summaryrefslogtreecommitdiffstats
path: root/vendor/github.com
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com')
-rw-r--r--vendor/github.com/NYTimes/gziphandler/gzip.go35
-rw-r--r--vendor/github.com/NYTimes/gziphandler/gzip_test.go49
-rw-r--r--vendor/github.com/armon/go-metrics/prometheus/prometheus.go96
-rw-r--r--vendor/github.com/armon/go-metrics/start.go2
-rw-r--r--vendor/github.com/avct/uasurfer/.gitignore56
-rw-r--r--vendor/github.com/avct/uasurfer/.travis.yml11
-rw-r--r--vendor/github.com/avct/uasurfer/LICENSE192
-rw-r--r--vendor/github.com/avct/uasurfer/README.md169
-rw-r--r--vendor/github.com/avct/uasurfer/browser.go192
-rw-r--r--vendor/github.com/avct/uasurfer/const_string.go49
-rw-r--r--vendor/github.com/avct/uasurfer/device.go60
-rw-r--r--vendor/github.com/avct/uasurfer/system.go332
-rw-r--r--vendor/github.com/avct/uasurfer/uasurfer.go227
-rw-r--r--vendor/github.com/avct/uasurfer/uasurfer_test.go1064
-rw-r--r--vendor/github.com/dgryski/dgoogauth/googauth_test.go8
-rw-r--r--vendor/github.com/go-ini/ini/file.go6
-rw-r--r--vendor/github.com/go-ini/ini/ini.go12
-rw-r--r--vendor/github.com/go-ini/ini/ini_test.go13
-rw-r--r--vendor/github.com/go-ini/ini/key.go26
-rw-r--r--vendor/github.com/go-ini/ini/key_test.go43
-rw-r--r--vendor/github.com/go-ini/ini/parser.go31
-rw-r--r--vendor/github.com/golang/protobuf/jsonpb/jsonpb.go3
-rw-r--r--vendor/github.com/golang/protobuf/jsonpb/jsonpb_test.go1
-rw-r--r--vendor/github.com/hashicorp/go-multierror/.travis.yml2
-rw-r--r--vendor/github.com/hashicorp/memberlist/memberlist.go4
-rw-r--r--vendor/github.com/hashicorp/memberlist/net.go2
-rw-r--r--vendor/github.com/hashicorp/memberlist/state.go14
-rw-r--r--vendor/github.com/hashicorp/memberlist/transport.go2
-rw-r--r--vendor/github.com/lib/pq/.travis.yml14
-rw-r--r--vendor/github.com/lib/pq/doc.go2
-rw-r--r--vendor/github.com/miekg/dns/.codecov.yml8
-rw-r--r--vendor/github.com/miekg/dns/Gopkg.lock21
-rw-r--r--vendor/github.com/miekg/dns/Gopkg.toml26
-rw-r--r--vendor/github.com/miekg/dns/Makefile.fuzz33
-rw-r--r--vendor/github.com/miekg/dns/Makefile.release52
-rw-r--r--vendor/github.com/miekg/dns/README.md5
-rw-r--r--vendor/github.com/miekg/dns/client.go19
-rw-r--r--vendor/github.com/miekg/dns/client_test.go10
-rw-r--r--vendor/github.com/miekg/dns/clientconfig.go6
-rw-r--r--vendor/github.com/miekg/dns/clientconfig_test.go54
-rw-r--r--vendor/github.com/miekg/dns/compress_generate.go3
-rw-r--r--vendor/github.com/miekg/dns/defaults.go7
-rw-r--r--vendor/github.com/miekg/dns/dns_test.go61
-rw-r--r--vendor/github.com/miekg/dns/dnssec.go80
-rw-r--r--vendor/github.com/miekg/dns/dnssec_keygen.go22
-rw-r--r--vendor/github.com/miekg/dns/dnssec_keyscan.go50
-rw-r--r--vendor/github.com/miekg/dns/dnssec_privkey.go8
-rw-r--r--vendor/github.com/miekg/dns/dnssec_test.go189
-rw-r--r--vendor/github.com/miekg/dns/doc.go2
-rw-r--r--vendor/github.com/miekg/dns/edns.go39
-rw-r--r--vendor/github.com/miekg/dns/fuzz.go23
-rw-r--r--vendor/github.com/miekg/dns/fuzz_test.go25
-rw-r--r--vendor/github.com/miekg/dns/idn/code_points.go2346
-rw-r--r--vendor/github.com/miekg/dns/idn/example_test.go18
-rw-r--r--vendor/github.com/miekg/dns/idn/punycode.go370
-rw-r--r--vendor/github.com/miekg/dns/idn/punycode_test.go116
-rw-r--r--vendor/github.com/miekg/dns/internal/socket/cmsghdr.go7
-rw-r--r--vendor/github.com/miekg/dns/internal/socket/controlmessage.go118
-rw-r--r--vendor/github.com/miekg/dns/internal/socket/controlmessage_test.go103
-rw-r--r--vendor/github.com/miekg/dns/internal/socket/socket.go4
-rw-r--r--vendor/github.com/miekg/dns/internal/socket/sys.go14
-rw-r--r--vendor/github.com/miekg/dns/leak_test.go71
-rw-r--r--vendor/github.com/miekg/dns/msg.go18
-rw-r--r--vendor/github.com/miekg/dns/msg_generate.go3
-rw-r--r--vendor/github.com/miekg/dns/msg_helpers.go5
-rw-r--r--vendor/github.com/miekg/dns/parse_test.go53
-rw-r--r--vendor/github.com/miekg/dns/sanitize.go2
-rw-r--r--vendor/github.com/miekg/dns/scan.go66
-rw-r--r--vendor/github.com/miekg/dns/scan_rr.go101
-rw-r--r--vendor/github.com/miekg/dns/scanner.go17
-rw-r--r--vendor/github.com/miekg/dns/server.go27
-rw-r--r--vendor/github.com/miekg/dns/server_test.go4
-rw-r--r--vendor/github.com/miekg/dns/types.go43
-rw-r--r--vendor/github.com/miekg/dns/types_generate.go6
-rw-r--r--vendor/github.com/miekg/dns/udp.go52
-rw-r--r--vendor/github.com/miekg/dns/udp_linux.go220
-rw-r--r--vendor/github.com/miekg/dns/udp_linux_test.go68
-rw-r--r--vendor/github.com/miekg/dns/udp_other.go17
-rw-r--r--vendor/github.com/miekg/dns/udp_test.go126
-rw-r--r--vendor/github.com/miekg/dns/udp_windows.go7
-rw-r--r--vendor/github.com/miekg/dns/update_test.go8
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/.gitattributes10
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/.gitignore2
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/AUTHORS3
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/CONTRIBUTING.md31
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/CONTRIBUTORS3
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/LICENSE27
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/PATENTS22
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/README.md21
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/acme.go1058
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/acme_test.go1352
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/autocert/autocert.go821
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/autocert/autocert_test.go606
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/autocert/cache.go130
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/autocert/cache_test.go58
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/autocert/example_test.go35
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/autocert/listener.go160
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/autocert/renewal.go124
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/autocert/renewal_test.go191
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/jws.go153
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/jws_test.go319
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/types.go329
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/types_test.go63
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bcrypt/base64.go35
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bcrypt/bcrypt.go295
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bcrypt/bcrypt_test.go243
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2b/blake2b.go207
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go43
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s762
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.go25
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.s290
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2b/blake2b_generic.go179
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2b/blake2b_ref.go11
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2b/blake2b_test.go798
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2b/blake2x.go177
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2b/register.go32
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2s/blake2s.go187
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2s/blake2s_386.go35
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2s/blake2s_386.s460
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2s/blake2s_amd64.go40
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2s/blake2s_amd64.s463
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2s/blake2s_generic.go174
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2s/blake2s_ref.go17
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2s/blake2s_test.go1002
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2s/blake2x.go178
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2s/register.go21
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blowfish/block.go159
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blowfish/blowfish_test.go274
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blowfish/cipher.go91
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blowfish/const.go199
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bn256/bn256.go404
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bn256/bn256_test.go304
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bn256/constants.go44
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bn256/curve.go278
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bn256/example_test.go43
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bn256/gfp12.go200
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bn256/gfp2.go219
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bn256/gfp6.go296
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bn256/optate.go395
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bn256/twist.go249
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/cast5/cast5.go526
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/cast5/cast5_test.go106
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go83
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go127
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.s2714
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go70
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_noasm.go15
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_test.go182
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_vectors_test.go332
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/chacha20poly1305/internal/chacha20/chacha_generic.go198
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/chacha20poly1305/internal/chacha20/chacha_test.go33
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/codereview.cfg1
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/cryptobyte/asn1.go732
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/cryptobyte/asn1/asn1.go46
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/cryptobyte/asn1_test.go300
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/cryptobyte/builder.go309
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/cryptobyte/cryptobyte_test.go428
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/cryptobyte/example_test.go154
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/cryptobyte/string.go167
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/curve25519/const_amd64.h8
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/curve25519/const_amd64.s20
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/curve25519/cswap_amd64.s65
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/curve25519/curve25519.go834
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/curve25519/curve25519_test.go39
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/curve25519/doc.go23
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/curve25519/freeze_amd64.s73
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/curve25519/ladderstep_amd64.s1377
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/curve25519/mont25519_amd64.go240
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/curve25519/mul_amd64.s169
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/curve25519/square_amd64.s132
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ed25519/ed25519.go181
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ed25519/ed25519_test.go183
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/const.go1422
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go1771
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ed25519/testdata/sign.input.gzbin0 -> 50330 bytes
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/hkdf/example_test.go61
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/hkdf/hkdf.go75
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/hkdf/hkdf_test.go370
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/md4/example_test.go20
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/md4/md4.go118
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/md4/md4_test.go71
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/md4/md4block.go89
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/nacl/auth/auth.go58
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/nacl/auth/auth_test.go172
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/nacl/auth/example_test.go36
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/nacl/box/box.go103
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/nacl/box/box_test.go78
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/nacl/box/example_test.go95
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/nacl/secretbox/example_test.go53
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/nacl/secretbox/secretbox.go166
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/nacl/secretbox/secretbox_test.go154
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ocsp/ocsp.go778
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ocsp/ocsp_test.go875
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/armor/armor.go219
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/armor/armor_test.go95
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/armor/encode.go160
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/canonical_text.go59
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/canonical_text_test.go52
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/clearsign/clearsign.go376
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/clearsign/clearsign_test.go210
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/elgamal/elgamal.go122
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/elgamal/elgamal_test.go49
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/errors/errors.go72
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/keys.go637
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/keys_test.go419
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/compressed.go123
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/compressed_test.go41
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/config.go91
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/encrypted_key.go199
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/encrypted_key_test.go146
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/literal.go89
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/ocfb.go143
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/ocfb_test.go46
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/one_pass_signature.go73
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/opaque.go162
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/opaque_test.go67
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/packet.go537
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/packet_test.go255
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/private_key.go380
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/private_key_test.go270
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/public_key.go748
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/public_key_test.go202
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/public_key_v3.go279
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/public_key_v3_test.go82
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/reader.go76
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/signature.go731
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/signature_test.go78
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/signature_v3.go146
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/signature_v3_test.go92
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted.go155
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted_test.go117
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go290
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted_test.go123
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/userattribute.go91
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/userattribute_test.go109
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/userid.go160
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/userid_test.go87
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/read.go442
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/read_test.go613
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/s2k/s2k.go273
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/s2k/s2k_test.go137
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/write.go378
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/write_test.go273
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/otr/libotr_test_helper.c197
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/otr/otr.go1415
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/otr/otr_test.go470
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/otr/smp.go572
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pbkdf2/pbkdf2.go77
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pbkdf2/pbkdf2_test.go157
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/bmp-string.go50
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/bmp-string_test.go63
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/crypto.go131
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/crypto_test.go125
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/errors.go23
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/internal/rc2/bench_test.go27
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/internal/rc2/rc2.go274
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/internal/rc2/rc2_test.go93
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/mac.go45
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/mac_test.go42
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/pbkdf.go170
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/pbkdf_test.go34
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/pkcs12.go346
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/pkcs12_test.go138
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/safebags.go57
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/poly1305/poly1305.go33
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/poly1305/poly1305_test.go159
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/poly1305/sum_amd64.go22
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/poly1305/sum_amd64.s125
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/poly1305/sum_arm.go22
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/poly1305/sum_arm.s427
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/poly1305/sum_ref.go141
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ripemd160/ripemd160.go120
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ripemd160/ripemd160_test.go64
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ripemd160/ripemd160block.go161
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/salsa20/salsa/hsalsa20.go144
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/salsa20/salsa/salsa2020_amd64.s889
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/salsa20/salsa/salsa208.go199
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.go24
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_ref.go234
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/salsa20/salsa/salsa_test.go54
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/salsa20/salsa20.go54
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/salsa20/salsa20_test.go139
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/scrypt/example_test.go26
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/scrypt/scrypt.go244
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/scrypt/scrypt_test.go162
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/doc.go66
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/hashes.go65
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/keccakf.go412
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/keccakf_amd64.go13
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/keccakf_amd64.s390
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/register.go18
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/sha3.go192
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/sha3_test.go311
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/shake.go60
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/testdata/keccakKats.json.deflatebin0 -> 521342 bytes
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/xor.go16
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/xor_generic.go28
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/xor_unaligned.go58
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/agent/client.go683
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/agent/client_test.go379
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/agent/example_test.go41
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/agent/forward.go103
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/agent/keyring.go215
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/agent/keyring_test.go76
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/agent/server.go523
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/agent/server_test.go259
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/agent/testdata_test.go64
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/benchmark_test.go122
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/buffer.go97
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/buffer_test.go87
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/certs.go519
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/certs_test.go222
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/channel.go633
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/cipher.go629
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/cipher_test.go129
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/client.go278
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/client_auth.go510
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/client_auth_test.go628
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/client_test.go119
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/common.go373
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/connection.go143
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/doc.go21
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/example_test.go320
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/handshake.go646
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/handshake_test.go559
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/kex.go540
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/kex_test.go50
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/keys.go1031
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/keys_test.go500
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts.go546
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts_test.go329
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/mac.go61
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/mempipe_test.go110
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/messages.go766
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/messages_test.go288
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/mux.go330
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/mux_test.go505
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/server.go580
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/session.go647
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/session_test.go774
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/streamlocal.go115
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/tcpip.go465
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/tcpip_test.go20
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/terminal/terminal.go951
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/terminal/terminal_test.go350
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/terminal/util.go116
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/terminal/util_bsd.go12
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/terminal/util_linux.go10
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/terminal/util_plan9.go58
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/terminal/util_solaris.go128
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/terminal/util_windows.go97
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/test/agent_unix_test.go59
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/test/banner_test.go33
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/test/cert_test.go77
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/test/dial_unix_test.go128
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/test/doc.go7
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/test/forward_unix_test.go194
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/test/session_test.go413
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/test/test_unix_test.go298
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/test/testdata_test.go64
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/testdata/doc.go8
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/testdata/keys.go177
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/testdata_test.go63
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/transport.go375
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/transport_test.go109
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/tea/cipher.go109
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/tea/tea_test.go93
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/twofish/twofish.go342
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/twofish/twofish_test.go129
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/xtea/block.go66
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/xtea/cipher.go82
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/xtea/xtea_test.go229
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/xts/xts.go137
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/xts/xts_test.go105
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/.gitattributes10
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/.gitignore2
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/AUTHORS3
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/CONTRIBUTING.md31
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/CONTRIBUTORS3
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/LICENSE27
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/PATENTS22
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/README.md16
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/asm.go41
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/constants.go218
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/doc.go82
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/instructions.go704
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/instructions_test.go525
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/setter.go10
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/testdata/all_instructions.bpf1
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/testdata/all_instructions.txt79
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/vm.go140
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/vm_aluop_test.go512
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/vm_bpf_test.go192
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/vm_extension_test.go49
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/vm_instructions.go174
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/vm_jump_test.go380
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/vm_load_test.go246
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/vm_ret_test.go115
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/vm_scratch_test.go247
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/vm_test.go144
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/codereview.cfg1
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/context/context.go56
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/context/context_test.go583
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go74
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/context/ctxhttp/ctxhttp_17_test.go29
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/context/ctxhttp/ctxhttp_pre17.go147
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/context/ctxhttp/ctxhttp_pre17_test.go79
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/context/ctxhttp/ctxhttp_test.go105
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/context/go17.go72
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/context/go19.go20
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/context/pre_go17.go300
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/context/pre_go19.go109
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/context/withtimeout_test.go31
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/dict/dict.go210
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/dns/dnsmessage/example_test.go132
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/dns/dnsmessage/message.go2001
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/dns/dnsmessage/message_test.go1141
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/atom/atom.go78
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/atom/atom_test.go109
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/atom/gen.go709
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/atom/table.go777
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/atom/table_test.go373
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/charset.go257
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/charset_test.go237
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/testdata/HTTP-charset.html48
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/testdata/HTTP-vs-UTF-8-BOM.html48
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/testdata/HTTP-vs-meta-charset.html49
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/testdata/HTTP-vs-meta-content.html49
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/testdata/No-encoding-declaration.html47
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/testdata/README9
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/testdata/UTF-16BE-BOM.htmlbin0 -> 2670 bytes
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/testdata/UTF-16LE-BOM.htmlbin0 -> 2682 bytes
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/testdata/UTF-8-BOM-vs-meta-charset.html49
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/testdata/UTF-8-BOM-vs-meta-content.html48
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/testdata/meta-charset-attribute.html48
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/testdata/meta-content-attribute.html48
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/const.go104
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/doc.go106
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/doctype.go156
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/entity.go2253
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/entity_test.go29
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/escape.go258
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/escape_test.go97
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/example_test.go40
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/foreign.go226
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/node.go193
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/node_test.go146
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/parse.go2094
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/parse_test.go388
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/render.go271
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/render_test.go156
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/go1.html2237
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/README28
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/adoption01.dat194
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/adoption02.dat31
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/comments01.dat135
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/doctype01.dat370
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/entities01.dat603
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/entities02.dat249
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/html5test-com.dat246
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/inbody01.dat43
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/isindex.dat40
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/pending-spec-changes-plain-text-unsafe.datbin0 -> 115 bytes
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/pending-spec-changes.dat52
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/plain-text-unsafe.datbin0 -> 4166 bytes
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/scriptdata01.dat308
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/scripted/adoption01.dat15
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/scripted/webkit01.dat28
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tables01.dat212
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests1.dat1952
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests10.dat799
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests11.dat482
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests12.dat62
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests14.dat74
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests15.dat208
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests16.dat2299
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests17.dat153
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests18.dat269
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests19.dat1237
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests2.dat763
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests20.dat455
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests21.dat221
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests22.dat157
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests23.dat155
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests24.dat79
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests25.dat219
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests26.dat313
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests3.dat305
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests4.dat59
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests5.dat191
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests6.dat663
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests7.dat390
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests8.dat148
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests9.dat457
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests_innerHTML_1.dat741
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tricky01.dat261
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/webkit01.dat610
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/webkit02.dat159
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/token.go1219
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/token_test.go748
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http/httpproxy/export_test.go7
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http/httpproxy/go19_test.go13
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http/httpproxy/proxy.go239
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http/httpproxy/proxy_test.go301
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/.gitignore2
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/Dockerfile51
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/Makefile3
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/README20
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/ciphers.go641
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/ciphers_test.go309
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/client_conn_pool.go256
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/configure_transport.go80
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/databuffer.go146
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/databuffer_test.go157
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/errors.go133
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/errors_test.go24
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/flow.go50
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/flow_test.go53
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/frame.go1579
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/frame_test.go1191
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/go16.go16
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/go17.go106
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/go17_not18.go36
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/go18.go56
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/go18_test.go79
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/go19.go16
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/go19_test.go59
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/gotrack.go170
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/gotrack_test.go33
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2demo/.gitignore5
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2demo/Makefile8
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2demo/README16
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2demo/h2demo.go538
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2demo/launch.go302
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2demo/rootCA.key27
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2demo/rootCA.pem26
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2demo/rootCA.srl1
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2demo/server.crt20
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2demo/server.key27
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2demo/tmpl.go1991
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2i/README.md97
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2i/h2i.go522
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/headermap.go78
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/hpack/encode.go240
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/hpack/encode_test.go386
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/hpack/hpack.go490
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/hpack/hpack_test.go722
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/hpack/huffman.go212
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/hpack/tables.go479
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/hpack/tables_test.go214
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/http2.go391
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/http2_test.go199
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/not_go16.go21
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/not_go17.go87
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/not_go18.go29
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/not_go19.go16
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/pipe.go163
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/pipe_test.go130
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/server.go2888
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/server_push_test.go521
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/server_test.go3725
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/testdata/draft-ietf-httpbis-http2.xml5021
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/transport.go2284
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/transport_test.go3847
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/write.go365
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/writesched.go242
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/writesched_priority.go452
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/writesched_priority_test.go541
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/writesched_random.go72
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/writesched_random_test.go44
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/writesched_test.go125
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/z_spec_test.go356
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/dstunreach.go41
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/echo.go45
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/endpoint.go113
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/example_test.go63
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/extension.go89
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/extension_test.go259
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/helper_posix.go75
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/interface.go236
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/ipv4.go61
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/ipv4_test.go83
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/ipv6.go23
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/listen_posix.go100
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/listen_stub.go33
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/message.go152
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/message_test.go134
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/messagebody.go41
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/mpls.go77
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/multipart.go109
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/multipart_test.go442
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/packettoobig.go43
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/paramprob.go63
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/ping_test.go200
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/sys_freebsd.go11
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/timeexceeded.go39
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/idna/example_test.go70
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/idna/idna.go732
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/idna/idna_test.go108
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/idna/punycode.go203
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/idna/punycode_test.go198
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/idna/tables.go4557
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/idna/trie.go72
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/idna/trieval.go119
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/iana/const.go180
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/iana/gen.go293
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/nettest/helper_bsd.go53
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/nettest/helper_nobsd.go15
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/nettest/helper_posix.go31
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/nettest/helper_stub.go32
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/nettest/helper_unix.go29
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/nettest/helper_windows.go42
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/nettest/interface.go94
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/nettest/rlimit.go11
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/nettest/stack.go147
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/cmsghdr.go11
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/cmsghdr_bsd.go13
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/cmsghdr_linux_32bit.go (renamed from vendor/github.com/miekg/dns/internal/socket/cmsghdr_linux_32bit.go)14
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/cmsghdr_linux_64bit.go (renamed from vendor/github.com/miekg/dns/internal/socket/cmsghdr_linux_64bit.go)14
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/cmsghdr_solaris_64bit.go14
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/cmsghdr_stub.go (renamed from vendor/github.com/miekg/dns/internal/socket/cmsghdr_other.go)6
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/defs_darwin.go44
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/defs_dragonfly.go44
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/defs_freebsd.go44
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/defs_linux.go49
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/defs_netbsd.go47
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/defs_openbsd.go44
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/defs_solaris.go44
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/error_unix.go31
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/error_windows.go26
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/iovec_32bit.go19
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/iovec_64bit.go19
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/iovec_solaris_64bit.go19
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/iovec_stub.go11
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/mmsghdr_stub.go21
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/mmsghdr_unix.go42
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/msghdr_bsd.go39
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/msghdr_bsdvar.go16
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/msghdr_linux.go36
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/msghdr_linux_32bit.go24
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/msghdr_linux_64bit.go24
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/msghdr_openbsd.go14
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/msghdr_solaris_64bit.go36
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/msghdr_stub.go14
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/rawconn.go66
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/rawconn_mmsg.go74
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/rawconn_msg.go77
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/rawconn_nommsg.go18
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/rawconn_nomsg.go18
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/rawconn_stub.go25
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/reflect.go62
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/socket.go285
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/socket_go1_9_test.go259
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/socket_test.go46
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys.go33
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_bsd.go17
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_bsdvar.go14
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_darwin.go7
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_dragonfly.go7
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux.go27
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_386.go55
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_386.s11
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_amd64.go10
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_arm.go10
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_arm64.go10
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_mips.go10
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_mips64.go10
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_mips64le.go10
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_mipsle.go10
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_ppc64.go10
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_ppc64le.go10
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_s390x.go55
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_s390x.s11
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_netbsd.go25
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_posix.go168
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_solaris.go71
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_solaris_amd64.s11
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_stub.go64
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_unix.go33
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_windows.go70
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_darwin_386.go59
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_darwin_amd64.go61
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_darwin_arm.go59
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_dragonfly_amd64.go61
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_freebsd_386.go59
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_freebsd_amd64.go61
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_freebsd_arm.go59
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_linux_386.go63
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_linux_amd64.go66
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_linux_arm.go63
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_linux_arm64.go66
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_linux_mips.go63
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_linux_mips64.go66
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_linux_mips64le.go66
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_linux_mipsle.go63
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_linux_ppc64.go66
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_linux_ppc64le.go66
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_linux_s390x.go66
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_netbsd_386.go65
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_netbsd_amd64.go68
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_netbsd_arm.go59
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_openbsd_386.go59
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_openbsd_amd64.go61
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_openbsd_arm.go59
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_solaris_amd64.go60
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/timeseries/timeseries.go525
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/timeseries/timeseries_test.go170
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/batch.go191
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/bpf_test.go93
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/control.go144
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/control_bsd.go40
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/control_pktinfo.go39
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/control_stub.go13
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/control_test.go21
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/control_unix.go73
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/control_windows.go16
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/defs_darwin.go77
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/defs_dragonfly.go38
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/defs_freebsd.go75
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/defs_linux.go122
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/defs_netbsd.go37
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/defs_openbsd.go37
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/defs_solaris.go84
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/dgramopt.go265
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/doc.go244
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/endpoint.go187
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/example_test.go224
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/gen.go199
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/genericopt.go57
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/header.go159
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/header_test.go228
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/helper.go63
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/iana.go34
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/icmp.go57
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/icmp_linux.go25
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/icmp_stub.go25
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/icmp_test.go95
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/multicast_test.go334
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/multicastlistener_test.go265
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/multicastsockopt_test.go195
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/packet.go69
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/packet_go1_8.go56
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/packet_go1_9.go67
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/payload.go23
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/payload_cmsg.go36
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/payload_cmsg_go1_8.go59
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/payload_cmsg_go1_9.go67
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/payload_nocmsg.go42
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/readwrite_go1_8_test.go248
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/readwrite_go1_9_test.go388
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/readwrite_test.go140
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sockopt.go44
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sockopt_posix.go71
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sockopt_stub.go42
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_asmreq.go119
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_asmreq_stub.go25
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_asmreqn.go42
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_asmreqn_stub.go21
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_bpf.go23
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_bpf_stub.go16
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_bsd.go37
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_darwin.go93
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_dragonfly.go35
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_freebsd.go76
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_linux.go59
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_solaris.go57
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_ssmreq.go54
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_ssmreq_stub.go21
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_stub.go13
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_windows.go67
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/unicast_test.go247
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/unicastsockopt_test.go148
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_darwin.go99
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_dragonfly.go31
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_freebsd_386.go93
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_freebsd_amd64.go95
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_freebsd_arm.go95
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_linux_386.go148
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_linux_amd64.go150
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_linux_arm.go148
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_linux_arm64.go150
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_linux_mips.go148
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_linux_mips64.go150
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_linux_mips64le.go150
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_linux_mipsle.go148
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_linux_ppc.go148
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_linux_ppc64.go150
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_linux_ppc64le.go150
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_linux_s390x.go150
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_netbsd.go30
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_openbsd.go30
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_solaris.go100
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/batch.go119
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/bpf_test.go96
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/control.go187
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/control_rfc2292_unix.go48
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/control_rfc3542_unix.go94
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/control_stub.go13
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/control_test.go21
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/control_unix.go55
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/control_windows.go16
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/defs_darwin.go112
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/defs_dragonfly.go84
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/defs_freebsd.go105
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/defs_linux.go147
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/defs_netbsd.go80
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/defs_openbsd.go89
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/defs_solaris.go114
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/dgramopt.go302
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/doc.go243
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/endpoint.go128
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/example_test.go216
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/gen.go199
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/genericopt.go58
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/header.go55
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/header_test.go55
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/helper.go57
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/iana.go82
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/icmp.go60
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/icmp_bsd.go29
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/icmp_linux.go27
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/icmp_solaris.go27
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/icmp_stub.go23
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/icmp_test.go96
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/icmp_windows.go22
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/mocktransponder_test.go32
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/multicast_test.go264
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/multicastlistener_test.go261
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/multicastsockopt_test.go157
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/payload.go23
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/payload_cmsg.go35
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/payload_cmsg_go1_8.go55
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/payload_cmsg_go1_9.go57
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/payload_nocmsg.go41
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/readwrite_go1_8_test.go242
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/readwrite_go1_9_test.go373
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/readwrite_test.go148
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sockopt.go43
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sockopt_posix.go87
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sockopt_stub.go46
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sockopt_test.go133
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_asmreq.go24
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_asmreq_stub.go17
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_bpf.go23
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_bpf_stub.go16
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_bsd.go57
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_darwin.go106
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_freebsd.go92
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_linux.go74
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_solaris.go74
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_ssmreq.go54
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_ssmreq_stub.go21
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_stub.go13
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_windows.go75
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/unicast_test.go184
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/unicastsockopt_test.go120
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_darwin.go131
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_dragonfly.go88
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_freebsd_386.go122
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_freebsd_amd64.go124
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_freebsd_arm.go124
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_linux_386.go170
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_linux_amd64.go172
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_linux_arm.go170
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_linux_arm64.go172
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_linux_mips.go170
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_linux_mips64.go172
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_linux_mips64le.go172
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_linux_mipsle.go170
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_linux_ppc.go170
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_linux_ppc64.go172
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_linux_ppc64le.go172
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_linux_s390x.go172
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_netbsd.go84
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_openbsd.go93
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_solaris.go131
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/lex/httplex/httplex.go351
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/lex/httplex/httplex_test.go119
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/lif/address.go105
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/lif/address_test.go123
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/lif/binary.go115
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/lif/defs_solaris.go90
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/lif/lif.go43
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/lif/link.go126
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/lif/link_test.go63
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/lif/sys.go21
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/lif/sys_solaris_amd64.s8
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/lif/syscall.go28
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/lif/zsys_solaris_amd64.go103
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/nettest/conntest.go456
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/nettest/conntest_go16.go24
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/nettest/conntest_go17.go24
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/nettest/conntest_test.go76
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/netutil/listen.go48
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/netutil/listen_test.go101
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/proxy/direct.go18
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/proxy/per_host.go140
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/proxy/per_host_test.go55
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/proxy/proxy.go134
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/proxy/proxy_test.go215
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/proxy/socks5.go214
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/publicsuffix/gen.go713
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/publicsuffix/list.go135
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/publicsuffix/list_test.go416
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/publicsuffix/table.go9419
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/publicsuffix/table_test.go16756
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/address.go425
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/address_darwin_test.go63
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/address_test.go103
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/binary.go90
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/defs_darwin.go114
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/defs_dragonfly.go113
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/defs_freebsd.go337
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/defs_netbsd.go112
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/defs_openbsd.go116
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/interface.go64
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/interface_announce.go32
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/interface_classic.go66
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/interface_freebsd.go78
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/interface_multicast.go30
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/interface_openbsd.go90
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/message.go72
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/message_darwin_test.go34
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/message_freebsd_test.go92
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/message_test.go239
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/route.go123
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/route_classic.go75
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/route_openbsd.go65
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/route_test.go390
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/sys.go39
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/sys_darwin.go87
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/sys_dragonfly.go76
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/sys_freebsd.go155
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/sys_netbsd.go71
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/sys_openbsd.go80
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/syscall.go28
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/zsys_darwin.go99
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/zsys_dragonfly.go98
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/zsys_freebsd_386.go126
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/zsys_freebsd_amd64.go123
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/zsys_freebsd_arm.go123
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/zsys_netbsd.go97
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/zsys_openbsd.go101
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/trace/events.go532
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/trace/histogram.go365
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/trace/histogram_test.go325
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/trace/trace.go1082
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/trace/trace_go16.go21
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/trace/trace_go17.go21
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/trace/trace_test.go178
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/file.go796
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/file_go1.6.go17
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/file_go1.7.go16
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/file_test.go1184
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/if.go173
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/if_test.go322
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/internal/xml/README11
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/internal/xml/atom_test.go56
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/internal/xml/example_test.go151
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/internal/xml/marshal.go1223
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/internal/xml/marshal_test.go1939
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/internal/xml/read.go692
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/internal/xml/read_test.go744
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/internal/xml/typeinfo.go371
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/internal/xml/xml.go1998
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/internal/xml/xml_test.go752
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/litmus_test_server.go94
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/lock.go445
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/lock_test.go731
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/prop.go418
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/prop_test.go613
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/webdav.go702
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/webdav_test.go344
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/xml.go519
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/xml_test.go906
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/websocket/client.go106
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/websocket/dial.go24
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/websocket/dial_test.go43
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/websocket/exampledial_test.go31
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/websocket/examplehandler_test.go26
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/websocket/hybi.go583
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/websocket/hybi_test.go608
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/websocket/server.go113
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/websocket/websocket.go448
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/websocket/websocket_test.go665
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/xsrftoken/xsrf.go94
-rw-r--r--vendor/github.com/miekg/dns/vendor/golang.org/x/net/xsrftoken/xsrf_test.go83
-rw-r--r--vendor/github.com/miekg/dns/version.go15
-rw-r--r--vendor/github.com/miekg/dns/version_test.go10
-rw-r--r--vendor/github.com/miekg/dns/xfr.go2
-rw-r--r--vendor/github.com/miekg/dns/xfr_test.go184
-rw-r--r--vendor/github.com/miekg/dns/zcompress.go3
-rw-r--r--vendor/github.com/miekg/dns/zmsg.go68
-rw-r--r--vendor/github.com/miekg/dns/ztypes.go23
-rw-r--r--vendor/github.com/mssola/user_agent/LICENSE2
-rw-r--r--vendor/github.com/mssola/user_agent/README.md2
-rw-r--r--vendor/github.com/mssola/user_agent/all_test.go9
-rw-r--r--vendor/github.com/mssola/user_agent/bot.go2
-rw-r--r--vendor/github.com/mssola/user_agent/browser.go2
-rw-r--r--vendor/github.com/mssola/user_agent/operating_systems.go4
-rw-r--r--vendor/github.com/mssola/user_agent/user_agent.go2
-rw-r--r--vendor/github.com/pelletier/go-toml/keysparsing.go62
-rw-r--r--vendor/github.com/pelletier/go-toml/lexer.go59
-rw-r--r--vendor/github.com/pelletier/go-toml/marshal.go40
-rw-r--r--vendor/github.com/pelletier/go-toml/marshal_test.go78
-rw-r--r--vendor/github.com/pelletier/go-toml/parser.go60
-rw-r--r--vendor/github.com/pelletier/go-toml/parser_test.go57
-rw-r--r--vendor/github.com/pelletier/go-toml/tomltree_create_test.go4
-rw-r--r--vendor/github.com/pelletier/go-toml/tomltree_write.go37
-rw-r--r--vendor/github.com/pkg/errors/README.md4
-rw-r--r--vendor/github.com/pkg/errors/stack.go3
-rw-r--r--vendor/github.com/prometheus/client_model/Makefile1
-rw-r--r--vendor/github.com/prometheus/common/config/http_config.go10
-rw-r--r--vendor/github.com/prometheus/common/config/http_config_test.go2
-rw-r--r--vendor/github.com/prometheus/common/model/time.go3
-rw-r--r--vendor/github.com/prometheus/common/model/time_test.go3
-rw-r--r--vendor/github.com/prometheus/procfs/.travis.yml8
-rw-r--r--vendor/github.com/prometheus/procfs/bcache/get.go8
-rw-r--r--vendor/github.com/prometheus/procfs/bcache/get_test.go20
-rw-r--r--vendor/github.com/prometheus/procfs/buddyinfo.go2
-rw-r--r--vendor/github.com/prometheus/procfs/fixtures/26231/net/dev4
l---------vendor/github.com/prometheus/procfs/fixtures/26231/ns/mnt1
l---------vendor/github.com/prometheus/procfs/fixtures/26231/ns/net1
-rw-r--r--vendor/github.com/prometheus/procfs/fixtures/net/dev6
-rw-r--r--vendor/github.com/prometheus/procfs/ipvs.go10
-rw-r--r--vendor/github.com/prometheus/procfs/net_dev.go203
-rw-r--r--vendor/github.com/prometheus/procfs/net_dev_test.go73
-rw-r--r--vendor/github.com/prometheus/procfs/proc_io.go5
-rw-r--r--vendor/github.com/prometheus/procfs/proc_ns.go55
-rw-r--r--vendor/github.com/prometheus/procfs/proc_ns_test.go31
-rw-r--r--vendor/github.com/rwcarlsen/goexif/README.md2
-rw-r--r--vendor/github.com/spf13/afero/copyOnWriteFs.go2
-rw-r--r--vendor/github.com/spf13/afero/copyOnWriteFs_test.go16
-rw-r--r--vendor/github.com/spf13/afero/mem/file.go3
-rw-r--r--vendor/github.com/spf13/afero/memmap_test.go30
-rw-r--r--vendor/github.com/spf13/cobra/README.md53
-rw-r--r--vendor/github.com/spf13/cobra/cobra.go3
-rw-r--r--vendor/github.com/spf13/cobra/cobra/cmd/add.go4
-rw-r--r--vendor/github.com/spf13/cobra/cobra/cmd/init.go14
-rw-r--r--vendor/github.com/spf13/cobra/cobra/cmd/testdata/root.go.golden12
-rw-r--r--vendor/github.com/spf13/cobra/cobra/cmd/testdata/test.go.golden2
-rw-r--r--vendor/github.com/spf13/cobra/command.go80
-rw-r--r--vendor/github.com/spf13/cobra/command_test.go61
-rw-r--r--vendor/github.com/spf13/cobra/doc/md_docs.go4
-rw-r--r--vendor/github.com/spf13/jwalterweatherman/README.md2
-rw-r--r--vendor/github.com/spf13/viper/.travis.yml5
-rw-r--r--vendor/github.com/spf13/viper/remote/remote.go5
-rw-r--r--vendor/github.com/spf13/viper/util.go62
-rw-r--r--vendor/github.com/spf13/viper/viper.go223
-rw-r--r--vendor/github.com/spf13/viper/viper_test.go187
-rw-r--r--vendor/github.com/xenolf/lego/.travis.yml4
-rw-r--r--vendor/github.com/xenolf/lego/acme/dns_challenge.go17
-rw-r--r--vendor/github.com/xenolf/lego/acme/dns_challenge_test.go7
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/azure/azure.go2
1054 files changed, 237350 insertions, 4097 deletions
diff --git a/vendor/github.com/NYTimes/gziphandler/gzip.go b/vendor/github.com/NYTimes/gziphandler/gzip.go
index 13ee34a42..b3cb8315b 100644
--- a/vendor/github.com/NYTimes/gziphandler/gzip.go
+++ b/vendor/github.com/NYTimes/gziphandler/gzip.go
@@ -82,7 +82,14 @@ type GzipResponseWriter struct {
buf []byte // Holds the first part of the write before reaching the minSize or the end of the write.
contentTypes []string // Only compress if the response is one of these content-types. All are accepted if empty.
- flushed bool // Indicate if the stream was already flushed
+}
+
+type GzipResponseWriterWithCloseNotify struct {
+ *GzipResponseWriter
+}
+
+func (w *GzipResponseWriterWithCloseNotify) CloseNotify() <-chan bool {
+ return w.ResponseWriter.(http.CloseNotifier).CloseNotify()
}
// Write appends data to the gzip writer.
@@ -170,8 +177,7 @@ func (w *GzipResponseWriter) init() {
func (w *GzipResponseWriter) Close() error {
if w.gw == nil {
// Gzip not trigged yet, write out regular response.
- // WriteHeader only if it wasn't already wrote by a Flush
- if !w.flushed && w.code != 0 {
+ if w.code != 0 {
w.ResponseWriter.WriteHeader(w.code)
}
if w.buf != nil {
@@ -194,16 +200,18 @@ func (w *GzipResponseWriter) Close() error {
// http.ResponseWriter if it is an http.Flusher. This makes GzipResponseWriter
// an http.Flusher.
func (w *GzipResponseWriter) Flush() {
- if w.gw != nil {
- w.gw.Flush()
+ if w.gw == nil {
+ // Only flush once startGzip has been called.
+ //
+ // Flush is thus a no-op until the written body
+ // exceeds minSize.
+ return
}
+ w.gw.Flush()
+
if fw, ok := w.ResponseWriter.(http.Flusher); ok {
- if !w.flushed && w.code != 0 {
- w.ResponseWriter.WriteHeader(w.code)
- }
fw.Flush()
- w.flushed = true
}
}
@@ -264,7 +272,6 @@ func GzipHandlerWithOpts(opts ...option) (func(http.Handler) http.Handler, error
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Add(vary, acceptEncoding)
-
if acceptsGzip(r) {
gw := &GzipResponseWriter{
ResponseWriter: w,
@@ -274,7 +281,13 @@ func GzipHandlerWithOpts(opts ...option) (func(http.Handler) http.Handler, error
}
defer gw.Close()
- h.ServeHTTP(gw, r)
+ if _, ok := w.(http.CloseNotifier); ok {
+ gwcn := GzipResponseWriterWithCloseNotify{gw}
+ h.ServeHTTP(gwcn, r)
+ } else {
+ h.ServeHTTP(gw, r)
+ }
+
} else {
h.ServeHTTP(w, r)
}
diff --git a/vendor/github.com/NYTimes/gziphandler/gzip_test.go b/vendor/github.com/NYTimes/gziphandler/gzip_test.go
index 7decfd17b..ec1543372 100644
--- a/vendor/github.com/NYTimes/gziphandler/gzip_test.go
+++ b/vendor/github.com/NYTimes/gziphandler/gzip_test.go
@@ -306,23 +306,58 @@ func TestStatusCodes(t *testing.T) {
}
}
-func TestStatusCodesFlushed(t *testing.T) {
+func TestFlushBeforeWrite(t *testing.T) {
+ b := []byte(testBody)
handler := GzipHandler(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
rw.WriteHeader(http.StatusNotFound)
rw.(http.Flusher).Flush()
- rw.Write([]byte("Not found"))
+ rw.Write(b)
}))
r := httptest.NewRequest(http.MethodGet, "/", nil)
- r.Header.Set(acceptEncoding, "gzip")
+ r.Header.Set("Accept-Encoding", "gzip")
w := httptest.NewRecorder()
handler.ServeHTTP(w, r)
- result := w.Result()
- if result.StatusCode != http.StatusNotFound {
- t.Errorf("StatusCode should have been 404 but was %d", result.StatusCode)
- }
+ res := w.Result()
+ assert.Equal(t, http.StatusNotFound, res.StatusCode)
+ assert.Equal(t, "gzip", res.Header.Get("Content-Encoding"))
+ assert.NotEqual(t, b, w.Body.Bytes())
}
+func TestImplementCloseNotifier(t *testing.T) {
+ GzipHandler(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request){
+ _, ok := rw.(http.CloseNotifier)
+ assert.True(t, ok, "response writer must implement http.CloseNotifier")
+ })).ServeHTTP(&mockRWCloseNotify{}, &http.Request{})
+}
+
+func TestNotImplementCloseNotifier(t *testing.T) {
+ GzipHandler(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request){
+ _, ok := rw.(http.CloseNotifier)
+ assert.False(t, ok, "response writer must not implement http.CloseNotifier")
+ })).ServeHTTP(httptest.NewRecorder(), &http.Request{})
+}
+
+
+type mockRWCloseNotify struct{}
+
+func (m *mockRWCloseNotify) CloseNotify() <-chan bool {
+ panic("implement me")
+}
+
+func (m *mockRWCloseNotify) Header() http.Header {
+ return http.Header{}
+}
+
+func (m *mockRWCloseNotify) Write([]byte) (int, error) {
+ panic("implement me")
+}
+
+func (m *mockRWCloseNotify) WriteHeader(int) {
+ panic("implement me")
+}
+
+
func TestIgnoreSubsequentWriteHeader(t *testing.T) {
handler := GzipHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(500)
diff --git a/vendor/github.com/armon/go-metrics/prometheus/prometheus.go b/vendor/github.com/armon/go-metrics/prometheus/prometheus.go
index a647e5965..a5b27d6d3 100644
--- a/vendor/github.com/armon/go-metrics/prometheus/prometheus.go
+++ b/vendor/github.com/armon/go-metrics/prometheus/prometheus.go
@@ -13,19 +13,91 @@ import (
"github.com/prometheus/client_golang/prometheus"
)
+var (
+ // DefaultPrometheusOpts is the default set of options used when creating a
+ // PrometheusSink.
+ DefaultPrometheusOpts = PrometheusOpts{
+ Expiration: 60 * time.Second,
+ }
+)
+
+// PrometheusOpts is used to configure the Prometheus Sink
+type PrometheusOpts struct {
+ // Expiration is the duration a metric is valid for, after which it will be
+ // untracked. If the value is zero, a metric is never expired.
+ Expiration time.Duration
+}
+
type PrometheusSink struct {
- mu sync.Mutex
- gauges map[string]prometheus.Gauge
- summaries map[string]prometheus.Summary
- counters map[string]prometheus.Counter
+ mu sync.Mutex
+ gauges map[string]prometheus.Gauge
+ summaries map[string]prometheus.Summary
+ counters map[string]prometheus.Counter
+ updates map[string]time.Time
+ expiration time.Duration
}
+// NewPrometheusSink creates a new PrometheusSink using the default options.
func NewPrometheusSink() (*PrometheusSink, error) {
- return &PrometheusSink{
- gauges: make(map[string]prometheus.Gauge),
- summaries: make(map[string]prometheus.Summary),
- counters: make(map[string]prometheus.Counter),
- }, nil
+ return NewPrometheusSinkFrom(DefaultPrometheusOpts)
+}
+
+// NewPrometheusSinkFrom creates a new PrometheusSink using the passed options.
+func NewPrometheusSinkFrom(opts PrometheusOpts) (*PrometheusSink, error) {
+ sink := &PrometheusSink{
+ gauges: make(map[string]prometheus.Gauge),
+ summaries: make(map[string]prometheus.Summary),
+ counters: make(map[string]prometheus.Counter),
+ updates: make(map[string]time.Time),
+ expiration: opts.Expiration,
+ }
+
+ return sink, prometheus.Register(sink)
+}
+
+// Describe is needed to meet the Collector interface.
+func (p *PrometheusSink) Describe(c chan<- *prometheus.Desc) {
+ // We must emit some description otherwise an error is returned. This
+ // description isn't shown to the user!
+ prometheus.NewGauge(prometheus.GaugeOpts{Name: "Dummy", Help: "Dummy"}).Describe(c)
+}
+
+// Collect meets the collection interface and allows us to enforce our expiration
+// logic to clean up ephemeral metrics if their value haven't been set for a
+// duration exceeding our allowed expiration time.
+func (p *PrometheusSink) Collect(c chan<- prometheus.Metric) {
+ p.mu.Lock()
+ defer p.mu.Unlock()
+
+ expire := p.expiration != 0
+ now := time.Now()
+ for k, v := range p.gauges {
+ last := p.updates[k]
+ if expire && last.Add(p.expiration).Before(now) {
+ delete(p.updates, k)
+ delete(p.gauges, k)
+ } else {
+ v.Collect(c)
+ }
+ }
+ for k, v := range p.summaries {
+ last := p.updates[k]
+ if expire && last.Add(p.expiration).Before(now) {
+ delete(p.updates, k)
+ delete(p.summaries, k)
+ } else {
+ v.Collect(c)
+ }
+ }
+ for k, v := range p.counters {
+ last := p.updates[k]
+ if expire && last.Add(p.expiration).Before(now) {
+ delete(p.updates, k)
+ delete(p.counters, k)
+ } else {
+ v.Collect(c)
+ }
+ }
}
var forbiddenChars = regexp.MustCompile("[ .=\\-]")
@@ -65,10 +137,10 @@ func (p *PrometheusSink) SetGaugeWithLabels(parts []string, val float32, labels
Help: key,
ConstLabels: prometheusLabels(labels),
})
- prometheus.MustRegister(g)
p.gauges[hash] = g
}
g.Set(float64(val))
+ p.updates[hash] = time.Now()
}
func (p *PrometheusSink) AddSample(parts []string, val float32) {
@@ -87,10 +159,10 @@ func (p *PrometheusSink) AddSampleWithLabels(parts []string, val float32, labels
MaxAge: 10 * time.Second,
ConstLabels: prometheusLabels(labels),
})
- prometheus.MustRegister(g)
p.summaries[hash] = g
}
g.Observe(float64(val))
+ p.updates[hash] = time.Now()
}
// EmitKey is not implemented. Prometheus doesn’t offer a type for which an
@@ -114,8 +186,8 @@ func (p *PrometheusSink) IncrCounterWithLabels(parts []string, val float32, labe
Help: key,
ConstLabels: prometheusLabels(labels),
})
- prometheus.MustRegister(g)
p.counters[hash] = g
}
g.Add(float64(val))
+ p.updates[hash] = time.Now()
}
diff --git a/vendor/github.com/armon/go-metrics/start.go b/vendor/github.com/armon/go-metrics/start.go
index 46f0c2eb2..dd41861c9 100644
--- a/vendor/github.com/armon/go-metrics/start.go
+++ b/vendor/github.com/armon/go-metrics/start.go
@@ -11,7 +11,7 @@ import (
// Config is used to configure metrics settings
type Config struct {
- ServiceName string // Prefixed with keys to seperate services
+ ServiceName string // Prefixed with keys to separate services
HostName string // Hostname to use. If not provided and EnableHostname, it will be os.Hostname
EnableHostname bool // Enable prefixing gauge values with hostname
EnableHostnameLabel bool // Enable adding hostname to labels
diff --git a/vendor/github.com/avct/uasurfer/.gitignore b/vendor/github.com/avct/uasurfer/.gitignore
new file mode 100644
index 000000000..35ba52a16
--- /dev/null
+++ b/vendor/github.com/avct/uasurfer/.gitignore
@@ -0,0 +1,56 @@
+# Compiled bin #
+###################
+
+
+# Compiled source #
+###################
+*.dll
+*.exe
+*.o
+*.so
+
+# Packages #
+############
+# it's better to unpack these files and commit the raw source
+# git has its own built in compression methods
+*.7z
+*.dmg
+*.gz
+*.iso
+*.jar
+*.rar
+*.tar
+*.zip
+
+# Configuration Files #
+#######################
+*.cfg
+
+# Logs and databases #
+######################
+*.log
+*.sql
+*.sqlite
+logs
+coverage.html
+coverage.out
+
+# Test Files #
+#######################
+*.test
+
+# OS generated files #
+######################
+.DS_Store
+.DS_Store?
+.Spotlight-V100
+.Trashes
+ehthumbs.db
+Thumbs.db
+
+# go.rice generated files
+*.rice-box.go
+
+# Dev Tools #
+######################
+.vagrant \ No newline at end of file
diff --git a/vendor/github.com/avct/uasurfer/.travis.yml b/vendor/github.com/avct/uasurfer/.travis.yml
new file mode 100644
index 000000000..77b64e6f2
--- /dev/null
+++ b/vendor/github.com/avct/uasurfer/.travis.yml
@@ -0,0 +1,11 @@
+sudo: false
+
+language: go
+
+go:
+ - 1.9.x
+ - 1.8.x
+ - 1.7.x
+
+script:
+ - go test
diff --git a/vendor/github.com/avct/uasurfer/LICENSE b/vendor/github.com/avct/uasurfer/LICENSE
new file mode 100644
index 000000000..a092343b2
--- /dev/null
+++ b/vendor/github.com/avct/uasurfer/LICENSE
@@ -0,0 +1,192 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ Copyright 2015 Avocet Systems Ltd.
+ http://avocet.io/opensource
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ Copyright 2015 Avocet Systems Ltd.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License. \ No newline at end of file
diff --git a/vendor/github.com/avct/uasurfer/README.md b/vendor/github.com/avct/uasurfer/README.md
new file mode 100644
index 000000000..2a4ab608d
--- /dev/null
+++ b/vendor/github.com/avct/uasurfer/README.md
@@ -0,0 +1,169 @@
+[![Build Status](https://travis-ci.org/avct/uasurfer.svg?branch=master)](https://travis-ci.org/avct/uasurfer) [![GoDoc](https://godoc.org/github.com/avct/uasurfer?status.svg)](https://godoc.org/github.com/avct/uasurfer) [![Go Report Card](https://goreportcard.com/badge/github.com/avct/uasurfer)](https://goreportcard.com/report/github.com/avct/uasurfer)
+
+# uasurfer
+
+![uasurfer-100px](https://cloud.githubusercontent.com/assets/597902/16172506/9debc136-357a-11e6-90fb-c7c46f50dff0.png)
+
+**User Agent Surfer** (uasurfer) is a lightweight Golang package that parses and abstracts [HTTP User-Agent strings](https://en.wikipedia.org/wiki/User_agent) with particular attention to device type.
+
+The following information is returned by uasurfer from a raw HTTP User-Agent string:
+
+| Name | Example | Coverage in 192,792 parses |
+|----------------|---------|--------------------------------|
+| Browser name | `chrome` | 99.85% |
+| Browser version | `53` | 99.17% |
+| Platform | `ipad` | 99.97% |
+| OS name | `ios` | 99.96% |
+| OS version | `10` | 98.81% |
+| Device type | `tablet` | 99.98% |
+
+Layout engine, browser language, and other esoteric attributes are not parsed.
+
+Coverage is estimated from a random sample of real UA strings collected across thousands of sources in US and EU mid-2016.
+
+## Usage
+
+### Parse(ua string) Function
+
+The `Parse()` function accepts a user agent `string` and returns UserAgent struct with named constants and integers for versions (minor, major and patch separately), and the full UA string that was parsed (lowercase). A string can be retrieved by adding `.String()` to a variable, such as `uasurfer.BrowserName.String()`.
+
+```
+// Define a user agent string
+myUA := "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36"
+
+// Parse() returns all attributes, including returning the full UA string last
+ua, uaString := uasurfer.Parse(myUA)
+```
+
+where example UserAgent is:
+```
+{
+ Browser {
+ BrowserName: BrowserChrome,
+ Version: {
+ Major: 45,
+ Minor: 0,
+ Patch: 2454,
+ },
+ },
+ OS {
+ Platform: PlatformMac,
+ Name: OSMacOSX,
+ Version: {
+ Major: 10,
+ Minor: 10,
+ Patch: 5,
+ },
+ },
+ DeviceType: DeviceComputer,
+}
+```
+
+**Usage note:** There are some OSes that do not return a version, see docs below. Linux is typically not reported with a specific Linux distro name or version.
+
+#### Browser Name
+* `BrowserChrome` - Google [Chrome](https://en.wikipedia.org/wiki/Google_Chrome), [Chromium](https://en.wikipedia.org/wiki/Chromium_(web_browser))
+* `BrowserSafari` - Apple [Safari](https://en.wikipedia.org/wiki/Safari_(web_browser)), Google Search ([GSA](https://itunes.apple.com/us/app/google/id284815942))
+* `BrowserIE` - Microsoft [Internet Explorer](https://en.wikipedia.org/wiki/Internet_Explorer), [Edge](https://en.wikipedia.org/wiki/Microsoft_Edge)
+* `BrowserFirefox` - Mozilla [Firefox](https://en.wikipedia.org/wiki/Firefox), GNU [IceCat](https://en.wikipedia.org/wiki/GNU_IceCat), [Iceweasel](https://en.wikipedia.org/wiki/Mozilla_Corporation_software_rebranded_by_the_Debian_project#Iceweasel), [Seamonkey](https://en.wikipedia.org/wiki/SeaMonkey)
+* `BrowserAndroid` - Android [WebView](https://developer.chrome.com/multidevice/webview/overview) (Android OS <4.4 only)
+* `BrowserOpera` - [Opera](https://en.wikipedia.org/wiki/Opera_(web_browser))
+* `BrowserUCBrowser` - [UC Browser](https://en.wikipedia.org/wiki/UC_Browser)
+* `BrowserSilk` - Amazon [Silk](https://en.wikipedia.org/wiki/Amazon_Silk)
+* `BrowserSpotify` - [Spotify](https://en.wikipedia.org/wiki/Spotify#Clients) desktop client
+* `BrowserBlackberry` - RIM [BlackBerry](https://en.wikipedia.org/wiki/BlackBerry)
+* `BrowserUnknown` - Unknown
+
+#### Browser Version
+
+Browser version returns an `unint8` of the major version attribute of the User-Agent String. For example Chrome 45.0.23423 would return `45`. The intention is to support math operators with versions, such as "do XYZ for Chrome version >23".
+
+Unknown version is returned as `0`.
+
+#### Platform
+* `PlatformWindows` - Microsoft Windows
+* `PlatformMac` - Apple Macintosh
+* `PlatformLinux` - Linux, including Android and other OSes
+* `PlatformiPad` - Apple iPad
+* `PlatformiPhone` - Apple iPhone
+* `PlatformBlackberry` - RIM Blackberry
+* `PlatformWindowsPhone` Microsoft Windows Phone & Mobile
+* `PlatformKindle` - Amazon Kindle & Kindle Fire
+* `PlatformPlaystation` - Sony Playstation, Vita, PSP
+* `PlatformXbox` - Microsoft Xbox - `PlatformXbox`
+* `PlatformNintendo` - Nintendo DS, Wii, etc.
+* `PlatformUnknown` - Unknown
+
+#### OS Name
+* `OSWindows`
+* `OSMacOSX` - includes "macOS Sierra"
+* `OSiOS`
+* `OSAndroid`
+* `OSChromeOS`
+* `OSWebOS`
+* `OSLinux`
+* `OSPlaystation`
+* `OSXbox`
+* `OSNintendo`
+* `OSUnknown`
+
+#### OS Version
+
+OS X major version is alway 10 with consecutive minor versions indicating release releases (10 - Yosemite, 11 - El Capitain, 12 Sierra, etc). Windows version is NT version. `Version{0, 0, 0}` indicated version is unknown or not evaluated.
+Versions can be compared using `Less` function: `if ver1.Less(ver2) {}`
+
+Here are some examples across the platform, os.name, and os.version:
+
+* For Windows XP (Windows NT 5.1), "`PlatformWindows`" is the platform, "`OSWindows`" is the name, and `{5, 1, 0}` the version.
+* For OS X 10.5.1, "`PlatformMac`" is the platform, "`OSMacOSX`" the name, and `{10, 5, 1}` the version.
+* For Android 5.1, "`PlatformLinux`" is the platform, "`OSAndroid`" is the name, and `{5, 1, 0}` the version.
+* For iOS 5.1, "`PlatformiPhone`" or "`PlatformiPad`" is the platform, "`OSiOS`" is the name, and `{5, 1, 0}` the version.
+
+###### Windows Version Guide
+
+* Windows 10 - `{10, 0, 0}`
+* Windows 8.1 - `{6, 3, 0}`
+* Windows 8 - `{6, 2, 0}`
+* Windows 7 - `{6, 1, 0}`
+* Windows Vista - `{6, 0, 0}`
+* Windows XP - `{5, 1, 0}` or `{5, 2, 0}`
+* Windows 2000 - `{5, 0, 0}`
+
+Windows 95, 98, and ME represent 0.01% of traffic worldwide and are not available through this package at this time.
+
+#### DeviceType
+DeviceType is typically quite accurate, though determining between phones and tablets on Android is not always possible due to how some vendors design their UA strings. A mobile Android device without tablet indicator defaults to being classified as a phone. DeviceTV supports major brands such as Philips, Sharp, Vizio and steaming boxes such as Apple, Google, Roku, Amazon.
+
+* `DeviceComputer`
+* `DevicePhone`
+* `DeviceTablet`
+* `DeviceTV`
+* `DeviceConsole`
+* `DeviceWearable`
+* `DeviceUnknown`
+
+## Example Combinations of Attributes
+* Surface RT -> `OSWindows8`, `DeviceTablet`, OSVersion >= `6`
+* Android Tablet -> `OSAndroid`, `DeviceTablet`
+* Microsoft Edge -> `BrowserIE`, BrowserVersion >= `12.0.0`
+
+## To do
+
+* Remove compiled regexp in favor of string.Contains wherever possible (lowers mem/alloc)
+* Better version support on Firefox derivatives (e.g. SeaMonkey)
+* Potential additional browser support:
+ * "NetFront" (1% share in India)
+ * "QQ Browser" (6.5% share in China)
+ * "Sogou Explorer" (5% share in China)
+ * "Maxthon" (1.5% share in China)
+ * "Nokia"
+* Potential additional OS support:
+ * "Nokia" (5% share in India)
+ * "Series 40" (5.5% share in India)
+ * Windows 2003 Server
+* iOS safari browser identification based on iOS version
+* Add android version to browser identification
+* old Macs
+ * "opera/9.64 (macintosh; ppc mac os x; u; en) presto/2.1.1"
+* old Windows
+ * "mozilla/5.0 (windows nt 4.0; wow64) applewebkit/537.36 (khtml, like gecko) chrome/37.0.2049.0 safari/537.36"
diff --git a/vendor/github.com/avct/uasurfer/browser.go b/vendor/github.com/avct/uasurfer/browser.go
new file mode 100644
index 000000000..e156818ab
--- /dev/null
+++ b/vendor/github.com/avct/uasurfer/browser.go
@@ -0,0 +1,192 @@
+package uasurfer
+
+import (
+ "strings"
+)
+
+// Browser struct contains the lowercase name of the browser, along
+// with its browser version number. Browser are grouped together without
+// consideration for device. For example, Chrome (Chrome/43.0) and Chrome for iOS
+// (CriOS/43.0) would both return as "chrome" (name) and 43.0 (version). Similarly
+// Internet Explorer 11 and Edge 12 would return as "ie" and "11" or "12", respectively.
+// type Browser struct {
+// Name BrowserName
+// Version struct {
+// Major int
+// Minor int
+// Patch int
+// }
+// }
+
+// Retrieve browser name from UA strings
+func (u *UserAgent) evalBrowserName(ua string) bool {
+ // Blackberry goes first because it reads as MSIE & Safari
+ if strings.Contains(ua, "blackberry") || strings.Contains(ua, "playbook") || strings.Contains(ua, "bb10") || strings.Contains(ua, "rim ") {
+ u.Browser.Name = BrowserBlackberry
+ return u.isBot()
+ }
+
+ if strings.Contains(ua, "applewebkit") {
+ switch {
+ case strings.Contains(ua, "opr/") || strings.Contains(ua, "opios/"):
+ u.Browser.Name = BrowserOpera
+
+ case strings.Contains(ua, "silk/"):
+ u.Browser.Name = BrowserSilk
+
+ case strings.Contains(ua, "edge/") || strings.Contains(ua, "iemobile/") || strings.Contains(ua, "msie "):
+ u.Browser.Name = BrowserIE
+
+ case strings.Contains(ua, "ucbrowser/") || strings.Contains(ua, "ucweb/"):
+ u.Browser.Name = BrowserUCBrowser
+
+ // Edge, Silk and other chrome-identifying browsers must evaluate before chrome, unless we want to add more overhead
+ case strings.Contains(ua, "chrome/") || strings.Contains(ua, "crios/") || strings.Contains(ua, "chromium/") || strings.Contains(ua, "crmo/"):
+ u.Browser.Name = BrowserChrome
+
+ case strings.Contains(ua, "android") && !strings.Contains(ua, "chrome/") && strings.Contains(ua, "version/") && !strings.Contains(ua, "like android"):
+ // Android WebView on Android >= 4.4 is purposefully being identified as Chrome above -- https://developer.chrome.com/multidevice/webview/overview
+ u.Browser.Name = BrowserAndroid
+
+ case strings.Contains(ua, "fxios"):
+ u.Browser.Name = BrowserFirefox
+
+ case strings.Contains(ua, " spotify/"):
+ u.Browser.Name = BrowserSpotify
+
+ // AppleBot uses webkit signature as well
+ case strings.Contains(ua, "applebot"):
+ u.Browser.Name = BrowserAppleBot
+
+ // presume it's safari unless an esoteric browser is being specified (webOSBrowser, SamsungBrowser, etc.)
+ case strings.Contains(ua, "like gecko") && strings.Contains(ua, "mozilla/") && strings.Contains(ua, "safari/") && !strings.Contains(ua, "linux") && !strings.Contains(ua, "android") && !strings.Contains(ua, "browser/") && !strings.Contains(ua, "os/"):
+ u.Browser.Name = BrowserSafari
+
+ // if we got this far and the device is iPhone or iPad, assume safari. Some agents don't actually contain the word "safari"
+ case strings.Contains(ua, "iphone") || strings.Contains(ua, "ipad"):
+ u.Browser.Name = BrowserSafari
+
+ // Google's search app on iPhone, leverages native Safari rather than Chrome
+ case strings.Contains(ua, " gsa/"):
+ u.Browser.Name = BrowserSafari
+
+ default:
+ goto notwebkit
+
+ }
+ return u.isBot()
+ }
+
+notwebkit:
+ switch {
+ case strings.Contains(ua, "msie") || strings.Contains(ua, "trident"):
+ u.Browser.Name = BrowserIE
+
+ case strings.Contains(ua, "gecko") && (strings.Contains(ua, "firefox") || strings.Contains(ua, "iceweasel") || strings.Contains(ua, "seamonkey") || strings.Contains(ua, "icecat")):
+ u.Browser.Name = BrowserFirefox
+
+ case strings.Contains(ua, "presto") || strings.Contains(ua, "opera"):
+ u.Browser.Name = BrowserOpera
+
+ case strings.Contains(ua, "ucbrowser"):
+ u.Browser.Name = BrowserUCBrowser
+
+ case strings.Contains(ua, "applebot"):
+ u.Browser.Name = BrowserAppleBot
+
+ case strings.Contains(ua, "baiduspider"):
+ u.Browser.Name = BrowserBaiduBot
+
+ case strings.Contains(ua, "adidxbot") || strings.Contains(ua, "bingbot") || strings.Contains(ua, "bingpreview"):
+ u.Browser.Name = BrowserBingBot
+
+ case strings.Contains(ua, "duckduckbot"):
+ u.Browser.Name = BrowserDuckDuckGoBot
+
+ case strings.Contains(ua, "facebot") || strings.Contains(ua, "facebookexternalhit"):
+ u.Browser.Name = BrowserFacebookBot
+
+ case strings.Contains(ua, "googlebot"):
+ u.Browser.Name = BrowserGoogleBot
+
+ case strings.Contains(ua, "linkedinbot"):
+ u.Browser.Name = BrowserLinkedInBot
+
+ case strings.Contains(ua, "msnbot"):
+ u.Browser.Name = BrowserMsnBot
+
+ case strings.Contains(ua, "pingdom.com_bot"):
+ u.Browser.Name = BrowserPingdomBot
+
+ case strings.Contains(ua, "twitterbot"):
+ u.Browser.Name = BrowserTwitterBot
+
+ case strings.Contains(ua, "yandex") || strings.Contains(ua, "yadirectfetcher"):
+ u.Browser.Name = BrowserYandexBot
+
+ case strings.Contains(ua, "yahoo"):
+ u.Browser.Name = BrowserYahooBot
+
+ case strings.Contains(ua, "phantomjs"):
+ u.Browser.Name = BrowserBot
+
+ default:
+ u.Browser.Name = BrowserUnknown
+
+ }
+
+ return u.isBot()
+}
+
+// Retrieve browser version
+// Methods used in order:
+// 1st: look for generic version/#
+// 2nd: look for browser-specific instructions (e.g. chrome/34)
+// 3rd: infer from OS (iOS only)
+func (u *UserAgent) evalBrowserVersion(ua string) {
+ // if there is a 'version/#' attribute with numeric version, use it -- except for Chrome since Android vendors sometimes hijack version/#
+ if u.Browser.Name != BrowserChrome && u.Browser.Version.findVersionNumber(ua, "version/") {
+ return
+ }
+
+ switch u.Browser.Name {
+ case BrowserChrome:
+ // match both chrome and crios
+ _ = u.Browser.Version.findVersionNumber(ua, "chrome/") || u.Browser.Version.findVersionNumber(ua, "crios/") || u.Browser.Version.findVersionNumber(ua, "crmo/")
+
+ case BrowserIE:
+ if u.Browser.Version.findVersionNumber(ua, "msie ") || u.Browser.Version.findVersionNumber(ua, "edge/") {
+ return
+ }
+
+ // get MSIE version from trident version https://en.wikipedia.org/wiki/Trident_(layout_engine)
+ if u.Browser.Version.findVersionNumber(ua, "trident/") {
+ // convert trident versions 3-7 to MSIE version
+ if (u.Browser.Version.Major >= 3) && (u.Browser.Version.Major <= 7) {
+ u.Browser.Version.Major += 4
+ }
+ }
+
+ case BrowserFirefox:
+ _ = u.Browser.Version.findVersionNumber(ua, "firefox/") || u.Browser.Version.findVersionNumber(ua, "fxios/")
+
+ case BrowserSafari: // executes typically if we're on iOS and not using a familiar browser
+ u.Browser.Version = u.OS.Version
+ // early Safari used a version number +1 to OS version
+ if (u.Browser.Version.Major <= 3) && (u.Browser.Version.Major >= 1) {
+ u.Browser.Version.Major++
+ }
+
+ case BrowserUCBrowser:
+ _ = u.Browser.Version.findVersionNumber(ua, "ucbrowser/")
+
+ case BrowserOpera:
+ _ = u.Browser.Version.findVersionNumber(ua, "opr/") || u.Browser.Version.findVersionNumber(ua, "opios/") || u.Browser.Version.findVersionNumber(ua, "opera/")
+
+ case BrowserSilk:
+ _ = u.Browser.Version.findVersionNumber(ua, "silk/")
+
+ case BrowserSpotify:
+ _ = u.Browser.Version.findVersionNumber(ua, "spotify/")
+ }
+}
diff --git a/vendor/github.com/avct/uasurfer/const_string.go b/vendor/github.com/avct/uasurfer/const_string.go
new file mode 100644
index 000000000..2fa21d86d
--- /dev/null
+++ b/vendor/github.com/avct/uasurfer/const_string.go
@@ -0,0 +1,49 @@
+// Code generated by "stringer -type=DeviceType,BrowserName,OSName,Platform -output=const_string.go"; DO NOT EDIT.
+
+package uasurfer
+
+import "fmt"
+
+const _DeviceType_name = "DeviceUnknownDeviceComputerDeviceTabletDevicePhoneDeviceConsoleDeviceWearableDeviceTV"
+
+var _DeviceType_index = [...]uint8{0, 13, 27, 39, 50, 63, 77, 85}
+
+func (i DeviceType) String() string {
+ if i < 0 || i >= DeviceType(len(_DeviceType_index)-1) {
+ return fmt.Sprintf("DeviceType(%d)", i)
+ }
+ return _DeviceType_name[_DeviceType_index[i]:_DeviceType_index[i+1]]
+}
+
+const _BrowserName_name = "BrowserUnknownBrowserChromeBrowserIEBrowserSafariBrowserFirefoxBrowserAndroidBrowserOperaBrowserBlackberryBrowserUCBrowserBrowserSilkBrowserNokiaBrowserNetFrontBrowserQQBrowserMaxthonBrowserSogouExplorerBrowserSpotifyBrowserBotBrowserAppleBotBrowserBaiduBotBrowserBingBotBrowserDuckDuckGoBotBrowserFacebookBotBrowserGoogleBotBrowserLinkedInBotBrowserMsnBotBrowserPingdomBotBrowserTwitterBotBrowserYandexBotBrowserYahooBot"
+
+var _BrowserName_index = [...]uint16{0, 14, 27, 36, 49, 63, 77, 89, 106, 122, 133, 145, 160, 169, 183, 203, 217, 227, 242, 257, 271, 291, 309, 325, 343, 356, 373, 390, 406, 421}
+
+func (i BrowserName) String() string {
+ if i < 0 || i >= BrowserName(len(_BrowserName_index)-1) {
+ return fmt.Sprintf("BrowserName(%d)", i)
+ }
+ return _BrowserName_name[_BrowserName_index[i]:_BrowserName_index[i+1]]
+}
+
+const _OSName_name = "OSUnknownOSWindowsPhoneOSWindowsOSMacOSXOSiOSOSAndroidOSBlackberryOSChromeOSOSKindleOSWebOSOSLinuxOSPlaystationOSXboxOSNintendoOSBot"
+
+var _OSName_index = [...]uint8{0, 9, 23, 32, 40, 45, 54, 66, 76, 84, 91, 98, 111, 117, 127, 132}
+
+func (i OSName) String() string {
+ if i < 0 || i >= OSName(len(_OSName_index)-1) {
+ return fmt.Sprintf("OSName(%d)", i)
+ }
+ return _OSName_name[_OSName_index[i]:_OSName_index[i+1]]
+}
+
+const _Platform_name = "PlatformUnknownPlatformWindowsPlatformMacPlatformLinuxPlatformiPadPlatformiPhonePlatformiPodPlatformBlackberryPlatformWindowsPhonePlatformPlaystationPlatformXboxPlatformNintendoPlatformBot"
+
+var _Platform_index = [...]uint8{0, 15, 30, 41, 54, 66, 80, 92, 110, 130, 149, 161, 177, 188}
+
+func (i Platform) String() string {
+ if i < 0 || i >= Platform(len(_Platform_index)-1) {
+ return fmt.Sprintf("Platform(%d)", i)
+ }
+ return _Platform_name[_Platform_index[i]:_Platform_index[i+1]]
+}
diff --git a/vendor/github.com/avct/uasurfer/device.go b/vendor/github.com/avct/uasurfer/device.go
new file mode 100644
index 000000000..70c00b112
--- /dev/null
+++ b/vendor/github.com/avct/uasurfer/device.go
@@ -0,0 +1,60 @@
+package uasurfer
+
+import (
+ "strings"
+)
+
+func (u *UserAgent) evalDevice(ua string) {
+ switch {
+
+ case u.OS.Platform == PlatformWindows || u.OS.Platform == PlatformMac || u.OS.Name == OSChromeOS:
+ if strings.Contains(ua, "mobile") || strings.Contains(ua, "touch") {
+ u.DeviceType = DeviceTablet // windows rt, linux haxor tablets
+ return
+ }
+ u.DeviceType = DeviceComputer
+
+ case u.OS.Platform == PlatformiPad || u.OS.Platform == PlatformiPod || strings.Contains(ua, "tablet") || strings.Contains(ua, "kindle/") || strings.Contains(ua, "playbook"):
+ u.DeviceType = DeviceTablet
+
+ case u.OS.Platform == PlatformiPhone || u.OS.Platform == PlatformBlackberry || strings.Contains(ua, "phone"):
+ u.DeviceType = DevicePhone
+
+ // long list of smarttv and tv dongle identifiers
+ case strings.Contains(ua, "tv") || strings.Contains(ua, "crkey") || strings.Contains(ua, "googletv") || strings.Contains(ua, "aftb") || strings.Contains(ua, "adt-") || strings.Contains(ua, "roku") || strings.Contains(ua, "viera") || strings.Contains(ua, "aquos") || strings.Contains(ua, "dtv") || strings.Contains(ua, "appletv") || strings.Contains(ua, "smarttv") || strings.Contains(ua, "tuner") || strings.Contains(ua, "smart-tv") || strings.Contains(ua, "hbbtv") || strings.Contains(ua, "netcast") || strings.Contains(ua, "vizio"):
+ u.DeviceType = DeviceTV
+
+ case u.OS.Name == OSAndroid:
+ // android phones report as "mobile", android tablets should not but often do -- http://android-developers.blogspot.com/2010/12/android-browser-user-agent-issues.html
+ if strings.Contains(ua, "mobile") {
+ u.DeviceType = DevicePhone
+ return
+ }
+
+ if strings.Contains(ua, "tablet") || strings.Contains(ua, "nexus 7") || strings.Contains(ua, "nexus 9") || strings.Contains(ua, "nexus 10") || strings.Contains(ua, "xoom") {
+ u.DeviceType = DeviceTablet
+ return
+ }
+
+ u.DeviceType = DevicePhone // default to phone
+
+ case u.OS.Platform == PlatformPlaystation || u.OS.Platform == PlatformXbox || u.OS.Platform == PlatformNintendo:
+ u.DeviceType = DeviceConsole
+
+ case strings.Contains(ua, "glass") || strings.Contains(ua, "watch") || strings.Contains(ua, "sm-v"):
+ u.DeviceType = DeviceWearable
+
+ // specifically above "mobile" string check as Kindle Fire tablets report as "mobile"
+ case u.Browser.Name == BrowserSilk || u.OS.Name == OSKindle && !strings.Contains(ua, "sd4930ur"):
+ u.DeviceType = DeviceTablet
+
+ case strings.Contains(ua, "mobile") || strings.Contains(ua, "touch") || strings.Contains(ua, " mobi") || strings.Contains(ua, "webos"): //anything "mobile"/"touch" that didn't get captured as tablet, console or wearable is presumed a phone
+ u.DeviceType = DevicePhone
+
+ case u.OS.Name == OSLinux: // linux goes last since it's in so many other device types (tvs, wearables, android-based stuff)
+ u.DeviceType = DeviceComputer
+
+ default:
+ u.DeviceType = DeviceUnknown
+ }
+}
diff --git a/vendor/github.com/avct/uasurfer/system.go b/vendor/github.com/avct/uasurfer/system.go
new file mode 100644
index 000000000..45a80409f
--- /dev/null
+++ b/vendor/github.com/avct/uasurfer/system.go
@@ -0,0 +1,332 @@
+package uasurfer
+
+import (
+ "regexp"
+ "strconv"
+ "strings"
+)
+
+var (
+ amazonFireFingerprint = regexp.MustCompile("\\s(k[a-z]{3,5}|sd\\d{4}ur)\\s") //tablet or phone
+)
+
+func (u *UserAgent) evalOS(ua string) bool {
+
+ s := strings.IndexRune(ua, '(')
+ e := strings.IndexRune(ua, ')')
+ if s > e {
+ s = 0
+ e = len(ua)
+ }
+ if e == -1 {
+ e = len(ua)
+ }
+
+ agentPlatform := ua[s+1 : e]
+ specsEnd := strings.Index(agentPlatform, ";")
+ var specs string
+ if specsEnd != -1 {
+ specs = agentPlatform[:specsEnd]
+ } else {
+ specs = agentPlatform
+ }
+
+ //strict OS & version identification
+ switch specs {
+ case "android":
+ u.evalLinux(ua, agentPlatform)
+
+ case "bb10", "playbook":
+ u.OS.Platform = PlatformBlackberry
+ u.OS.Name = OSBlackberry
+
+ case "x11", "linux":
+ u.evalLinux(ua, agentPlatform)
+
+ case "ipad", "iphone", "ipod touch", "ipod":
+ u.evaliOS(specs, agentPlatform)
+
+ case "macintosh":
+ u.evalMacintosh(ua)
+
+ default:
+ switch {
+ // Blackberry
+ case strings.Contains(ua, "blackberry") || strings.Contains(ua, "playbook"):
+ u.OS.Platform = PlatformBlackberry
+ u.OS.Name = OSBlackberry
+
+ // Windows Phone
+ case strings.Contains(agentPlatform, "windows phone "):
+ u.evalWindowsPhone(agentPlatform)
+
+ // Windows, Xbox
+ case strings.Contains(ua, "windows "):
+ u.evalWindows(ua)
+
+ // Kindle
+ case strings.Contains(ua, "kindle/") || amazonFireFingerprint.MatchString(agentPlatform):
+ u.OS.Platform = PlatformLinux
+ u.OS.Name = OSKindle
+
+ // Linux (broader attempt)
+ case strings.Contains(ua, "linux"):
+ u.evalLinux(ua, agentPlatform)
+
+ // WebOS (non-linux flagged)
+ case strings.Contains(ua, "webos") || strings.Contains(ua, "hpwos"):
+ u.OS.Platform = PlatformLinux
+ u.OS.Name = OSWebOS
+
+ // Nintendo
+ case strings.Contains(ua, "nintendo"):
+ u.OS.Platform = PlatformNintendo
+ u.OS.Name = OSNintendo
+
+ // Playstation
+ case strings.Contains(ua, "playstation") || strings.Contains(ua, "vita") || strings.Contains(ua, "psp"):
+ u.OS.Platform = PlatformPlaystation
+ u.OS.Name = OSPlaystation
+
+ // Android
+ case strings.Contains(ua, "android"):
+ u.evalLinux(ua, agentPlatform)
+
+ default:
+ u.OS.Platform = PlatformUnknown
+ u.OS.Name = OSUnknown
+ }
+ }
+
+ return u.isBot()
+}
+
+func (u *UserAgent) isBot() bool {
+
+ if u.OS.Platform == PlatformBot || u.OS.Name == OSBot {
+ u.DeviceType = DeviceComputer
+ return true
+ }
+
+ if u.Browser.Name >= BrowserBot && u.Browser.Name <= BrowserYahooBot {
+ u.OS.Platform = PlatformBot
+ u.OS.Name = OSBot
+ u.DeviceType = DeviceComputer
+ return true
+ }
+
+ return false
+}
+
+// evalLinux returns the `Platform`, `OSName` and Version of UAs with
+// 'linux' listed as their platform.
+func (u *UserAgent) evalLinux(ua string, agentPlatform string) {
+
+ switch {
+ // Kindle Fire
+ case strings.Contains(ua, "kindle") || amazonFireFingerprint.MatchString(agentPlatform):
+ // get the version of Android if available, though we don't call this OSAndroid
+ u.OS.Platform = PlatformLinux
+ u.OS.Name = OSKindle
+ u.OS.Version.findVersionNumber(agentPlatform, "android ")
+
+ // Android, Kindle Fire
+ case strings.Contains(ua, "android") || strings.Contains(ua, "googletv"):
+ // Android
+ u.OS.Platform = PlatformLinux
+ u.OS.Name = OSAndroid
+ u.OS.Version.findVersionNumber(agentPlatform, "android ")
+
+ // ChromeOS
+ case strings.Contains(ua, "cros"):
+ u.OS.Platform = PlatformLinux
+ u.OS.Name = OSChromeOS
+
+ // WebOS
+ case strings.Contains(ua, "webos") || strings.Contains(ua, "hpwos"):
+ u.OS.Platform = PlatformLinux
+ u.OS.Name = OSWebOS
+
+ // Linux, "Linux-like"
+ case strings.Contains(ua, "x11") || strings.Contains(ua, "bsd") || strings.Contains(ua, "suse") || strings.Contains(ua, "debian") || strings.Contains(ua, "ubuntu"):
+ u.OS.Platform = PlatformLinux
+ u.OS.Name = OSLinux
+
+ default:
+ u.OS.Platform = PlatformLinux
+ u.OS.Name = OSLinux
+ }
+}
+
+// evaliOS returns the `Platform`, `OSName` and Version of UAs with
+// 'ipad' or 'iphone' listed as their platform.
+func (u *UserAgent) evaliOS(uaPlatform string, agentPlatform string) {
+
+ switch uaPlatform {
+ // iPhone
+ case "iphone":
+ u.OS.Platform = PlatformiPhone
+ u.OS.Name = OSiOS
+ u.OS.getiOSVersion(agentPlatform)
+
+ // iPad
+ case "ipad":
+ u.OS.Platform = PlatformiPad
+ u.OS.Name = OSiOS
+ u.OS.getiOSVersion(agentPlatform)
+
+ // iPod
+ case "ipod touch", "ipod":
+ u.OS.Platform = PlatformiPod
+ u.OS.Name = OSiOS
+ u.OS.getiOSVersion(agentPlatform)
+
+ default:
+ u.OS.Platform = PlatformiPad
+ u.OS.Name = OSUnknown
+ }
+}
+
+func (u *UserAgent) evalWindowsPhone(agentPlatform string) {
+ u.OS.Platform = PlatformWindowsPhone
+
+ if u.OS.Version.findVersionNumber(agentPlatform, "windows phone os ") || u.OS.Version.findVersionNumber(agentPlatform, "windows phone ") {
+ u.OS.Name = OSWindowsPhone
+ } else {
+ u.OS.Name = OSUnknown
+ }
+}
+
+func (u *UserAgent) evalWindows(ua string) {
+
+ switch {
+ //Xbox -- it reads just like Windows
+ case strings.Contains(ua, "xbox"):
+ u.OS.Platform = PlatformXbox
+ u.OS.Name = OSXbox
+ if !u.OS.Version.findVersionNumber(ua, "windows nt ") {
+ u.OS.Version.Major = 6
+ u.OS.Version.Minor = 0
+ u.OS.Version.Patch = 0
+ }
+
+ // No windows version
+ case !strings.Contains(ua, "windows "):
+ u.OS.Platform = PlatformWindows
+ u.OS.Name = OSUnknown
+
+ case strings.Contains(ua, "windows nt ") && u.OS.Version.findVersionNumber(ua, "windows nt "):
+ u.OS.Platform = PlatformWindows
+ u.OS.Name = OSWindows
+
+ case strings.Contains(ua, "windows xp"):
+ u.OS.Platform = PlatformWindows
+ u.OS.Name = OSWindows
+ u.OS.Version.Major = 5
+ u.OS.Version.Minor = 1
+ u.OS.Version.Patch = 0
+
+ default:
+ u.OS.Platform = PlatformWindows
+ u.OS.Name = OSUnknown
+
+ }
+}
+
+func (u *UserAgent) evalMacintosh(uaPlatformGroup string) {
+ u.OS.Platform = PlatformMac
+ if i := strings.Index(uaPlatformGroup, "os x 10"); i != -1 {
+ u.OS.Name = OSMacOSX
+ u.OS.Version.parse(uaPlatformGroup[i+5:])
+
+ return
+ }
+ u.OS.Name = OSUnknown
+}
+
+func (v *Version) findVersionNumber(s string, m string) bool {
+ if ind := strings.Index(s, m); ind != -1 {
+ return v.parse(s[ind+len(m):])
+ }
+ return false
+}
+
+// getiOSVersion accepts the platform portion of a UA string and returns
+// a Version.
+func (o *OS) getiOSVersion(uaPlatformGroup string) {
+ if i := strings.Index(uaPlatformGroup, "cpu iphone os "); i != -1 {
+ o.Version.parse(uaPlatformGroup[i+14:])
+ return
+ }
+
+ if i := strings.Index(uaPlatformGroup, "cpu os "); i != -1 {
+ o.Version.parse(uaPlatformGroup[i+7:])
+ return
+ }
+
+ o.Version.parse(uaPlatformGroup)
+}
+
+// strToInt simply accepts a string and returns a `int`,
+// with '0' being default.
+func strToInt(str string) int {
+ i, _ := strconv.Atoi(str)
+ return i
+}
+
+// strToVer accepts a string and returns a Version,
+// with {0, 0, 0} being default.
+func (v *Version) parse(str string) bool {
+ if len(str) == 0 || str[0] < '0' || str[0] > '9' {
+ return false
+ }
+ for i := 0; i < 3; i++ {
+ empty := true
+ val := 0
+ l := len(str) - 1
+
+ for k, c := range str {
+ if c >= '0' && c <= '9' {
+ if empty {
+ val = int(c) - 48
+ empty = false
+ if k == l {
+ str = str[:0]
+ }
+ continue
+ }
+
+ if val == 0 {
+ if c == '0' {
+ if k == l {
+ str = str[:0]
+ }
+ continue
+ }
+ str = str[k:]
+ break
+ }
+
+ val = 10*val + int(c) - 48
+ if k == l {
+ str = str[:0]
+ }
+ continue
+ }
+ str = str[k+1:]
+ break
+ }
+
+ switch i {
+ case 0:
+ v.Major = val
+
+ case 1:
+ v.Minor = val
+
+ case 2:
+ v.Patch = val
+ }
+ }
+ return true
+}
diff --git a/vendor/github.com/avct/uasurfer/uasurfer.go b/vendor/github.com/avct/uasurfer/uasurfer.go
new file mode 100644
index 000000000..15aac6d40
--- /dev/null
+++ b/vendor/github.com/avct/uasurfer/uasurfer.go
@@ -0,0 +1,227 @@
+// Package uasurfer provides fast and reliable abstraction
+// of HTTP User-Agent strings. The philosophy is to identify
+// technologies that holds >1% market share, and to avoid
+// expending resources and accuracy on guessing at esoteric UA
+// strings.
+package uasurfer
+
+import "strings"
+
+//go:generate stringer -type=DeviceType,BrowserName,OSName,Platform -output=const_string.go
+
+// DeviceType (int) returns a constant.
+type DeviceType int
+
+// A complete list of supported devices in the
+// form of constants.
+const (
+ DeviceUnknown DeviceType = iota
+ DeviceComputer
+ DeviceTablet
+ DevicePhone
+ DeviceConsole
+ DeviceWearable
+ DeviceTV
+)
+
+// BrowserName (int) returns a constant.
+type BrowserName int
+
+// A complete list of supported web browsers in the
+// form of constants.
+const (
+ BrowserUnknown BrowserName = iota
+ BrowserChrome
+ BrowserIE
+ BrowserSafari
+ BrowserFirefox
+ BrowserAndroid
+ BrowserOpera
+ BrowserBlackberry
+ BrowserUCBrowser
+ BrowserSilk
+ BrowserNokia
+ BrowserNetFront
+ BrowserQQ
+ BrowserMaxthon
+ BrowserSogouExplorer
+ BrowserSpotify
+ BrowserBot // Bot list begins here
+ BrowserAppleBot
+ BrowserBaiduBot
+ BrowserBingBot
+ BrowserDuckDuckGoBot
+ BrowserFacebookBot
+ BrowserGoogleBot
+ BrowserLinkedInBot
+ BrowserMsnBot
+ BrowserPingdomBot
+ BrowserTwitterBot
+ BrowserYandexBot
+ BrowserYahooBot // Bot list ends here
+)
+
+// OSName (int) returns a constant.
+type OSName int
+
+// A complete list of supported OSes in the
+// form of constants. For handling particular versions
+// of operating systems (e.g. Windows 2000), see
+// the README.md file.
+const (
+ OSUnknown OSName = iota
+ OSWindowsPhone
+ OSWindows
+ OSMacOSX
+ OSiOS
+ OSAndroid
+ OSBlackberry
+ OSChromeOS
+ OSKindle
+ OSWebOS
+ OSLinux
+ OSPlaystation
+ OSXbox
+ OSNintendo
+ OSBot
+)
+
+// Platform (int) returns a constant.
+type Platform int
+
+// A complete list of supported platforms in the
+// form of constants. Many OSes report their
+// true platform, such as Android OS being Linux
+// platform.
+const (
+ PlatformUnknown Platform = iota
+ PlatformWindows
+ PlatformMac
+ PlatformLinux
+ PlatformiPad
+ PlatformiPhone
+ PlatformiPod
+ PlatformBlackberry
+ PlatformWindowsPhone
+ PlatformPlaystation
+ PlatformXbox
+ PlatformNintendo
+ PlatformBot
+)
+
+type Version struct {
+ Major int
+ Minor int
+ Patch int
+}
+
+func (v Version) Less(c Version) bool {
+ if v.Major < c.Major {
+ return true
+ }
+
+ if v.Major > c.Major {
+ return false
+ }
+
+ if v.Minor < c.Minor {
+ return true
+ }
+
+ if v.Minor > c.Minor {
+ return false
+ }
+
+ return v.Patch < c.Patch
+}
+
+type UserAgent struct {
+ Browser Browser
+ OS OS
+ DeviceType DeviceType
+}
+
+type Browser struct {
+ Name BrowserName
+ Version Version
+}
+
+type OS struct {
+ Platform Platform
+ Name OSName
+ Version Version
+}
+
+// Reset resets the UserAgent to it's zero value
+func (ua *UserAgent) Reset() {
+ ua.Browser = Browser{}
+ ua.OS = OS{}
+ ua.DeviceType = DeviceUnknown
+}
+
+// Parse accepts a raw user agent (string) and returns the UserAgent.
+func Parse(ua string) *UserAgent {
+ dest := new(UserAgent)
+ parse(ua, dest)
+ return dest
+}
+
+// ParseUserAgent is the same as Parse, but populates the supplied UserAgent.
+// It is the caller's responsibility to call Reset() on the UserAgent before
+// passing it to this function.
+func ParseUserAgent(ua string, dest *UserAgent) {
+ parse(ua, dest)
+}
+
+func parse(ua string, dest *UserAgent) {
+ ua = normalise(ua)
+ switch {
+ case len(ua) == 0:
+ dest.OS.Platform = PlatformUnknown
+ dest.OS.Name = OSUnknown
+ dest.Browser.Name = BrowserUnknown
+ dest.DeviceType = DeviceUnknown
+
+ // stop on on first case returning true
+ case dest.evalOS(ua):
+ case dest.evalBrowserName(ua):
+ default:
+ dest.evalBrowserVersion(ua)
+ dest.evalDevice(ua)
+ }
+}
+
+// normalise normalises the user supplied agent string so that
+// we can more easily parse it.
+func normalise(ua string) string {
+ if len(ua) <= 1024 {
+ var buf [1024]byte
+ ascii := copyLower(buf[:len(ua)], ua)
+ if !ascii {
+ // Fall back for non ascii characters
+ return strings.ToLower(ua)
+ }
+ return string(buf[:len(ua)])
+ }
+ // Fallback for unusually long strings
+ return strings.ToLower(ua)
+}
+
+// copyLower copies a lowercase version of s to b. It assumes s contains only single byte characters
+// and will panic if b is nil or is not long enough to contain all the bytes from s.
+// It returns early with false if any characters were non ascii.
+func copyLower(b []byte, s string) bool {
+ for j := 0; j < len(s); j++ {
+ c := s[j]
+ if c > 127 {
+ return false
+ }
+
+ if 'A' <= c && c <= 'Z' {
+ c += 'a' - 'A'
+ }
+
+ b[j] = c
+ }
+ return true
+}
diff --git a/vendor/github.com/avct/uasurfer/uasurfer_test.go b/vendor/github.com/avct/uasurfer/uasurfer_test.go
new file mode 100644
index 000000000..8668a159f
--- /dev/null
+++ b/vendor/github.com/avct/uasurfer/uasurfer_test.go
@@ -0,0 +1,1064 @@
+package uasurfer
+
+import "testing"
+
+var testUAVars = []struct {
+ UA string
+ UserAgent
+}{
+ // Empty
+ {"",
+ UserAgent{}},
+
+ // Single char
+ {"a",
+ UserAgent{}},
+
+ // Some random string
+ {"some random string",
+ UserAgent{}},
+
+ // Potentially malformed ua
+ {")(",
+ UserAgent{}},
+
+ // iPhone
+ {"Mozilla/5.0 (iPhone; CPU iPhone OS 7_0 like Mac OS X) AppleWebKit/546.10 (KHTML, like Gecko) Version/6.0 Mobile/7E18WD Safari/8536.25",
+ UserAgent{
+ Browser{BrowserSafari, Version{6, 0, 0}}, OS{PlatformiPhone, OSiOS, Version{7, 0, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (iPhone; CPU iPhone OS 8_0_2 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12A405 Safari/600.1.4",
+ UserAgent{
+ Browser{BrowserSafari, Version{8, 0, 0}}, OS{PlatformiPhone, OSiOS, Version{8, 0, 2}}, DevicePhone}},
+
+ // iPad
+ {"Mozilla/5.0(iPad; U; CPU iPhone OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B314 Safari/531.21.10",
+ UserAgent{
+ Browser{BrowserSafari, Version{4, 0, 4}}, OS{PlatformiPad, OSiOS, Version{3, 2, 0}}, DeviceTablet}},
+
+ {"Mozilla/5.0 (iPad; CPU OS 9_0 like Mac OS X) AppleWebKit/601.1.17 (KHTML, like Gecko) Version/8.0 Mobile/13A175 Safari/600.1.4",
+ UserAgent{
+ Browser{BrowserSafari, Version{8, 0, 0}}, OS{PlatformiPad, OSiOS, Version{9, 0, 0}}, DeviceTablet}},
+
+ {"Mozilla/5.0 (iPhone; CPU iPhone OS 10_0 like Mac OS X) AppleWebKit/602.1.32 (KHTML, like Gecko) Version/10.0 Mobile/14A5261v Safari/602.1",
+ UserAgent{
+ Browser{BrowserSafari, Version{10, 0, 0}}, OS{PlatformiPhone, OSiOS, Version{10, 0, 0}}, DevicePhone}},
+
+ // Chrome
+ {"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.130 Safari/537.36",
+ UserAgent{
+ Browser{BrowserChrome, Version{43, 0, 2357}}, OS{PlatformMac, OSMacOSX, Version{10, 10, 4}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_1_1 like Mac OS X; en) AppleWebKit/534.46.0 (KHTML, like Gecko) CriOS/19.0.1084.60 Mobile/9B206 Safari/534.48.3",
+ UserAgent{
+ Browser{BrowserChrome, Version{19, 0, 1084}}, OS{PlatformiPhone, OSiOS, Version{5, 1, 1}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; Android 6.0; Nexus 5X Build/MDB08L) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.76 Mobile Safari/537.36",
+ UserAgent{
+ Browser{BrowserChrome, Version{46, 0, 2490}}, OS{PlatformLinux, OSAndroid, Version{6, 0, 0}}, DevicePhone}},
+
+ // Chromium (Chrome)
+ {"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.19 (KHTML, like Gecko) Ubuntu/11.10 Chromium/18.0.1025.142 Chrome/18.0.1025.142 Safari/535.19",
+ UserAgent{
+ Browser{BrowserChrome, Version{18, 0, 1025}}, OS{PlatformLinux, OSLinux, Version{0, 0, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36",
+ UserAgent{
+ Browser{BrowserChrome, Version{45, 0, 2454}}, OS{PlatformMac, OSMacOSX, Version{10, 11, 0}}, DeviceComputer}},
+
+ //TODO: refactor "getVersion()" to handle this device/chrome version douchebaggery
+ // {"Mozilla/5.0 (Linux; Android 4.4.2; en-gb; SAMSUNG SM-G800F Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Version/1.6 Chrome/28.0.1500.94 Mobile Safari/537.36",
+ // UserAgent{
+ // Browser{BrowserChrome, Version{28,0,1500}, OS{PlatformLinux, OSAndroid, Version{4,4,2}}, DevicePhone}},
+
+ // Safari
+ {"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/600.7.12 (KHTML, like Gecko) Version/8.0.7 Safari/600.7.12",
+ UserAgent{
+ Browser{BrowserSafari, Version{8, 0, 7}}, OS{PlatformMac, OSMacOSX, Version{10, 10, 4}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_5; en-us) AppleWebKit/525.26.2 (KHTML, like Gecko) Version/3.2 Safari/525.26.12",
+ UserAgent{
+ Browser{BrowserSafari, Version{3, 2, 0}}, OS{PlatformMac, OSMacOSX, Version{10, 5, 5}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12) AppleWebKit/602.1.32 (KHTML, like Gecko) Version/10.0 Safari/602.1.32", // macOS Sierra dev beta
+ UserAgent{
+ Browser{BrowserSafari, Version{10, 0, 0}}, OS{PlatformMac, OSMacOSX, Version{10, 12, 0}}, DeviceComputer}},
+
+ // Firefox
+ {"Mozilla/5.0 (iPhone; CPU iPhone OS 8_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) FxiOS/1.0 Mobile/12F69 Safari/600.1.4",
+ UserAgent{
+ Browser{BrowserFirefox, Version{1, 0, 0}}, OS{PlatformiPhone, OSiOS, Version{8, 3, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Android 4.4; Tablet; rv:41.0) Gecko/41.0 Firefox/41.0",
+ UserAgent{
+ Browser{BrowserFirefox, Version{41, 0, 0}}, OS{PlatformLinux, OSAndroid, Version{4, 4, 0}}, DeviceTablet}},
+
+ {"Mozilla/5.0 (Android; Mobile; rv:40.0) Gecko/40.0 Firefox/40.0",
+ UserAgent{
+ Browser{BrowserFirefox, Version{40, 0, 0}}, OS{PlatformLinux, OSAndroid, Version{0, 0, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0",
+ UserAgent{
+ Browser{BrowserFirefox, Version{38, 0, 0}}, OS{PlatformLinux, OSLinux, Version{0, 0, 0}}, DeviceComputer}},
+
+ // Silk
+ {"Mozilla/5.0 (Linux; U; Android 4.4.3; de-de; KFTHWI Build/KTU84M) AppleWebKit/537.36 (KHTML, like Gecko) Silk/3.47 like Chrome/37.0.2026.117 Safari/537.36",
+ UserAgent{
+ Browser{BrowserSilk, Version{3, 47, 0}}, OS{PlatformLinux, OSKindle, Version{4, 4, 3}}, DeviceTablet}},
+
+ {"Mozilla/5.0 (Linux; U; en-us; KFJWI Build/IMM76D) AppleWebKit/535.19 (KHTML like Gecko) Silk/2.4 Safari/535.19 Silk-Acceleratedtrue",
+ UserAgent{
+ Browser{BrowserSilk, Version{2, 4, 0}}, OS{PlatformLinux, OSKindle, Version{0, 0, 0}}, DeviceTablet}},
+
+ // Opera
+ {"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36 OPR/18.0.1284.68",
+ UserAgent{
+ Browser{BrowserOpera, Version{18, 0, 1284}}, OS{PlatformWindows, OSWindows, Version{6, 1, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (iPhone; CPU iPhone OS 8_4 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) OPiOS/10.2.0.93022 Mobile/12H143 Safari/9537.53",
+ UserAgent{
+ Browser{BrowserOpera, Version{10, 2, 0}}, OS{PlatformiPhone, OSiOS, Version{8, 4, 0}}, DevicePhone}},
+
+ // Internet Explorer -- https://msdn.microsoft.com/en-us/library/hh869301(v=vs.85).aspx
+ {"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.123",
+ UserAgent{
+ Browser{BrowserIE, Version{12, 123, 0}}, OS{PlatformWindows, OSWindows, Version{10, 0, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)",
+ UserAgent{
+ Browser{BrowserIE, Version{10, 0, 0}}, OS{PlatformWindows, OSWindows, Version{6, 2, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Windows NT 6.3; Trident/7.0; .NET4.0E; .NET4.0C; rv:11.0) like Gecko",
+ UserAgent{
+ Browser{BrowserIE, Version{11, 0, 0}}, OS{PlatformWindows, OSWindows, Version{6, 3, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; DEVICE INFO) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Mobile Safari/537.36 Edge/12.123",
+ UserAgent{
+ Browser{BrowserIE, Version{12, 123, 0}}, OS{PlatformWindowsPhone, OSWindowsPhone, Version{10, 0, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Mobile; Windows Phone 8.1; Android 4.0; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 520) like iPhone OS 7_0_3 Mac OS X AppleWebKit/537 (KHTML, like Gecko) Mobile Safari/537",
+ UserAgent{
+ Browser{BrowserIE, Version{11, 0, 0}}, OS{PlatformWindowsPhone, OSWindowsPhone, Version{8, 1, 0}}, DevicePhone}},
+
+ {"Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; SV1; .NET CLR 1.1.4322; .NET CLR 1.0.3705; .NET CLR 2.0.50727)",
+ UserAgent{
+ Browser{BrowserIE, Version{5, 0, 1}}, OS{PlatformWindows, OSWindows, Version{5, 0, 0}}, DeviceComputer}},
+
+ {"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/4.0; GTB6.4; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; OfficeLiveConnector.1.3; OfficeLivePatch.0.0; .NET CLR 1.1.4322)",
+ UserAgent{
+ Browser{BrowserIE, Version{7, 0, 0}}, OS{PlatformWindows, OSWindows, Version{6, 1, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; ARM; Trident/6.0; Touch)", //Windows Surface RT tablet
+ UserAgent{
+ Browser{BrowserIE, Version{10, 0, 0}}, OS{PlatformWindows, OSWindows, Version{6, 2, 0}}, DeviceTablet}},
+
+ // UC Browser
+ {"Mozilla/5.0 (Linux; U; Android 2.3.4; en-US; MT11i Build/4.0.2.A.0.62) AppleWebKit/534.31 (KHTML, like Gecko) UCBrowser/9.0.1.275 U3/0.8.0 Mobile Safari/534.31",
+ UserAgent{
+ Browser{BrowserUCBrowser, Version{9, 0, 1}}, OS{PlatformLinux, OSAndroid, Version{2, 3, 4}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; U; Android 4.0.4; en-US; Micromax P255 Build/IMM76D) AppleWebKit/534.31 (KHTML, like Gecko) UCBrowser/9.2.0.308 U3/0.8.0 Mobile Safari/534.31",
+ UserAgent{
+ Browser{BrowserUCBrowser, Version{9, 2, 0}}, OS{PlatformLinux, OSAndroid, Version{4, 0, 4}}, DevicePhone}},
+
+ {"UCWEB/2.0 (Java; U; MIDP-2.0; en-US; MicromaxQ5) U2/1.0.0 UCBrowser/9.4.0.342 U2/1.0.0 Mobile",
+ UserAgent{
+ Browser{BrowserUCBrowser, Version{9, 4, 0}}, OS{PlatformUnknown, OSUnknown, Version{0, 0, 0}}, DevicePhone}},
+
+ // Nokia Browser
+ // {"Mozilla/5.0 (Series40; Nokia501/14.0.4/java_runtime_version=Nokia_Asha_1_2; Profile/MIDP-2.1 Configuration/CLDC-1.1) Gecko/20100401 S40OviBrowser/4.0.0.0.45",
+ // UserAgent{
+ // Browser{BrowserUnknown, Version{4,0,0}}, OS{PlatformUnknown, OSUnknown, Version{0,0,0}}, DevicePhone}},
+
+ // {"Mozilla/5.0 (Symbian/3; Series60/5.3 NokiaN8-00/111.040.1511; Profile/MIDP-2.1 Configuration/CLDC-1.1 ) AppleWebKit/535.1 (KHTML, like Gecko) NokiaBrowser/8.3.1.4 Mobile Safari/535.1",
+ // UserAgent{
+ // Browser{BrowserUnknown, Version{8,0,0}}, OS{PlatformUnknown, OSUnknown, Version{0,0,0}}, DevicePhone}},
+
+ // {"NokiaN97/21.1.107 (SymbianOS/9.4; Series60/5.0 Mozilla/5.0; Profile/MIDP-2.1 Configuration/CLDC-1.1) AppleWebkit/525 (KHTML, like Gecko) BrowserNG/7.1.4",
+ // BrowserUnknown, Version{7,0,0}}, OS{PlatformUnknown, OSUnknown, Version{0,0,0}}, DevicePhone}},
+
+ // ChromeOS
+ {"Mozilla/5.0 (X11; U; CrOS i686 9.10.0; en-US) AppleWebKit/532.5 (KHTML, like Gecko) Chrome/4.0.253.0 Safari/532.5",
+ UserAgent{
+ Browser{BrowserChrome, Version{4, 0, 253}}, OS{PlatformLinux, OSChromeOS, Version{0, 0, 0}}, DeviceComputer}},
+
+ // iPod, iPod Touch
+ {"mozilla/5.0 (ipod touch; cpu iphone os 9_3_3 like mac os x) applewebkit/601.1.46 (khtml, like gecko) version/9.0 mobile/13g34 safari/601.1",
+ UserAgent{
+ Browser{BrowserSafari, Version{9, 0, 0}}, OS{PlatformiPod, OSiOS, Version{9, 3, 3}}, DeviceTablet}},
+
+ {"mozilla/5.0 (ipod; cpu iphone os 6_1_6 like mac os x) applewebkit/536.26 (khtml, like gecko) version/6.0 mobile/10b500 safari/8536.25",
+ UserAgent{
+ Browser{BrowserSafari, Version{6, 0, 0}}, OS{PlatformiPod, OSiOS, Version{6, 1, 6}}, DeviceTablet}},
+
+ // WebOS
+ {"Mozilla/5.0 (hp-tablet; Linux; hpwOS/3.0.0; U; de-DE) AppleWebKit/534.6 (KHTML, like Gecko) wOSBrowser/233.70 Safari/534.6 TouchPad/1.0",
+ UserAgent{
+ Browser{BrowserUnknown, Version{0, 0, 0}}, OS{PlatformLinux, OSWebOS, Version{0, 0, 0}}, DeviceTablet}},
+
+ {"Mozilla/5.0 (webOS/1.4.1.1; U; en-US) AppleWebKit/532.2 (KHTML, like Gecko) Version/1.0 Safari/532.2 Pre/1.0",
+ UserAgent{
+ Browser{BrowserUnknown, Version{1, 0, 0}}, OS{PlatformLinux, OSWebOS, Version{0, 0, 0}}, DevicePhone}},
+
+ // Android WebView (Android <= 4.3)
+ {"Mozilla/5.0 (Linux; U; Android 2.2; en-us; DROID2 GLOBAL Build/S273) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",
+ UserAgent{
+ Browser{BrowserAndroid, Version{4, 0, 0}}, OS{PlatformLinux, OSAndroid, Version{2, 2, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; U; Android 4.0.3; de-ch; HTC Sensation Build/IML74K) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari53/4.30",
+ UserAgent{
+ Browser{BrowserAndroid, Version{4, 0, 0}}, OS{PlatformLinux, OSAndroid, Version{4, 0, 3}}, DevicePhone}},
+
+ // BlackBerry
+ {"Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML, like Gecko) Version/7.2.1.0 Safari/536.2+",
+ UserAgent{
+ Browser{BrowserBlackberry, Version{7, 2, 1}}, OS{PlatformBlackberry, OSBlackberry, Version{0, 0, 0}}, DeviceTablet}},
+
+ {"Mozilla/5.0 (BB10; Kbd) AppleWebKit/537.35+ (KHTML, like Gecko) Version/10.2.1.1925 Mobile Safari/537.35+",
+ UserAgent{
+ Browser{BrowserBlackberry, Version{10, 2, 1}}, OS{PlatformBlackberry, OSBlackberry, Version{0, 0, 0}}, DevicePhone}},
+
+ {"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) BlackBerry8703e/4.1.0 Profile/MIDP-2.0 Configuration/CLDC-1.1 VendorID/104",
+ UserAgent{
+ Browser{BrowserBlackberry, Version{0, 0, 0}}, OS{PlatformBlackberry, OSBlackberry, Version{0, 0, 0}}, DevicePhone}},
+
+ // Windows Phone
+ {"Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch; NOKIA; Lumia 625; ANZ941)",
+ UserAgent{
+ Browser{BrowserIE, Version{10, 0, 0}}, OS{PlatformWindowsPhone, OSWindowsPhone, Version{8, 0, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident/5.0; IEMobile/9.0; NOKIA; Lumia 900)",
+ UserAgent{
+ Browser{BrowserIE, Version{9, 0, 0}}, OS{PlatformWindowsPhone, OSWindowsPhone, Version{7, 5, 0}}, DevicePhone}},
+
+ // Kindle eReader
+ {"Mozilla/5.0 (Linux; U; en-US) AppleWebKit/528.5+ (KHTML, like Gecko, Safari/528.5+) Version/4.0 Kindle/3.0 (screen 600×800; rotate)",
+ UserAgent{
+ Browser{BrowserUnknown, Version{4, 0, 0}}, OS{PlatformLinux, OSKindle, Version{0, 0, 0}}, DeviceTablet}},
+
+ {"Mozilla/5.0 (X11; U; Linux armv7l like Android; en-us) AppleWebKit/531.2+ (KHTML, like Gecko) Version/5.0 Safari/533.2+ Kindle/3.0+",
+ UserAgent{
+ Browser{BrowserUnknown, Version{5, 0, 0}}, OS{PlatformLinux, OSKindle, Version{0, 0, 0}}, DeviceTablet}},
+
+ // Amazon Fire
+ {"Mozilla/5.0 (Linux; U; Android 4.4.3; de-de; KFTHWI Build/KTU84M) AppleWebKit/537.36 (KHTML, like Gecko) Silk/3.67 like Chrome/39.0.2171.93 Safari/537.36",
+ UserAgent{
+ Browser{BrowserSilk, Version{3, 67, 0}}, OS{PlatformLinux, OSKindle, Version{4, 4, 3}}, DeviceTablet}}, // Fire tablet
+
+ {"Mozilla/5.0 (Linux; U; Android 4.2.2; en­us; KFTHWI Build/JDQ39) AppleWebKit/537.36 (KHTML, like Gecko) Silk/3.22 like Chrome/34.0.1847.137 Mobile Safari/537.36",
+ UserAgent{
+ Browser{BrowserSilk, Version{3, 22, 0}}, OS{PlatformLinux, OSKindle, Version{4, 2, 2}}, DeviceTablet}}, // Fire tablet, but with "Mobile"
+
+ {"Mozilla/5.0 (Linux; Android 4.4.4; SD4930UR Build/KTU84P) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/34.0.0.0 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/35.0.0.48.273;]",
+ UserAgent{
+ Browser{BrowserChrome, Version{34, 0, 0}}, OS{PlatformLinux, OSKindle, Version{4, 4, 4}}, DevicePhone}}, // Facebook app on Fire Phone
+
+ {"mozilla/5.0 (linux; android 4.4.3; kfthwi build/ktu84m) applewebkit/537.36 (khtml, like gecko) version/4.0 chrome/34.0.0.0 safari/537.36 [pinterest/android]",
+ UserAgent{
+ Browser{BrowserChrome, Version{34, 0, 0}}, OS{PlatformLinux, OSKindle, Version{4, 4, 3}}, DeviceTablet}}, // Fire tablet running pinterest
+
+ // extra logic to identify phone when using silk has not been added
+ // {"Mozilla/5.0 (Linux; Android 4.4.4; SD4930UR Build/KTU84P) AppleWebKit/537.36 (KHTML, like Gecko) Silk/3.67 like Chrome/39.0.2171.93 Mobile Safari/537.36",
+ // UserAgent{
+ // Browser{BrowserSilk, Version{3,0,0}}, OS{PlatformLinux, OSKindle, Version{4,0,0}}, DevicePhone}}, // Silk on Fire Phone
+
+ // Nintendo
+ {"Opera/9.30 (Nintendo Wii; U; ; 2047-7; fr)",
+ UserAgent{
+ Browser{BrowserOpera, Version{9, 30, 0}}, OS{PlatformNintendo, OSNintendo, Version{0, 0, 0}}, DeviceConsole}},
+
+ {"Mozilla/5.0 (Nintendo WiiU) AppleWebKit/534.52 (KHTML, like Gecko) NX/2.1.0.8.21 NintendoBrowser/1.0.0.7494.US",
+ UserAgent{
+ Browser{BrowserUnknown, Version{0, 0, 0}}, OS{PlatformNintendo, OSNintendo, Version{0, 0, 0}}, DeviceConsole}},
+
+ // Xbox
+ {"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; Xbox)", //Xbox 360
+ UserAgent{
+ Browser{BrowserIE, Version{9, 0, 0}}, OS{PlatformXbox, OSXbox, Version{6, 1, 0}}, DeviceConsole}},
+
+ // Playstation
+ {"Mozilla/5.0 (PlayStation 4 4.50) AppleWebKit/601.2 (KHTML, like Gecko)",
+ UserAgent{
+ Browser{BrowserUnknown, Version{0, 0, 0}}, OS{PlatformPlaystation, OSPlaystation, Version{0, 0, 0}}, DeviceConsole}},
+
+ {"Mozilla/5.0 (Playstation Vita 1.61) AppleWebKit/531.22.8 (KHTML, like Gecko) Silk/3.2",
+ UserAgent{
+ Browser{BrowserSilk, Version{3, 2, 0}}, OS{PlatformPlaystation, OSPlaystation, Version{0, 0, 0}}, DeviceConsole}},
+
+ // Smart TVs and TV dongles
+ {"Mozilla/5.0 (CrKey armv7l 1.4.15250) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.0 Safari/537.36", // Chromecast
+ UserAgent{
+ Browser{BrowserChrome, Version{31, 0, 1650}}, OS{PlatformUnknown, OSUnknown, Version{0, 0, 0}}, DeviceTV}},
+
+ {"Mozilla/5.0 (Linux; GoogleTV 3.2; VAP430 Build/MASTER) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.77 Safari/534.24", // Google TV
+ UserAgent{
+ Browser{BrowserChrome, Version{11, 0, 696}}, OS{PlatformLinux, OSAndroid, Version{0, 0, 0}}, DeviceTV}},
+
+ {"Mozilla/5.0 (Linux; Android 5.0; ADT-1 Build/LPX13D) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.89 Mobile Safari/537.36", // Android TV
+ UserAgent{
+ Browser{BrowserChrome, Version{40, 0, 2214}}, OS{PlatformLinux, OSAndroid, Version{5, 0, 0}}, DeviceTV}},
+
+ {"Mozilla/5.0 (Linux; Android 4.2.2; AFTB Build/JDQ39) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.173 Mobile Safari/537.22", // Amazon Fire
+ UserAgent{
+ Browser{BrowserChrome, Version{25, 0, 1364}}, OS{PlatformLinux, OSAndroid, Version{4, 2, 2}}, DeviceTV}},
+
+ {"Mozilla/5.0 (Unknown; Linux armv7l) AppleWebKit/537.1+ (KHTML, like Gecko) Safari/537.1+ LG Browser/6.00.00(+mouse+3D+SCREEN+TUNER; LGE; GLOBAL-PLAT5; 03.07.01; 0x00000001;); LG NetCast.TV-2013/03.17.01 (LG, GLOBAL-PLAT4, wired)", // LG TV
+ UserAgent{
+ Browser{BrowserUnknown, Version{0, 0, 0}}, OS{PlatformLinux, OSLinux, Version{0, 0, 0}}, DeviceTV}},
+
+ {"Mozilla/5.0 (X11; FreeBSD; U; Viera; de-DE) AppleWebKit/537.11 (KHTML, like Gecko) Viera/3.10.0 Chrome/23.0.1271.97 Safari/537.11", // Panasonic Viera
+ UserAgent{
+ Browser{BrowserChrome, Version{23, 0, 1271}}, OS{PlatformLinux, OSLinux, Version{0, 0, 0}}, DeviceTV}},
+
+ // TODO: not catching "browser/" and reporting as safari -- ua string not being fully checked?
+ // {"Mozilla/5.0 (DTV) AppleWebKit/531.2+ (KHTML, like Gecko) Espial/6.1.5 AQUOSBrowser/2.0 (US01DTV;V;0001;0001)", // Sharp Aquos
+ // BrowserUnknown, Version{0,0,0}}, OS{PlatformUnknown, OSUnknown, Version{0,0,0}}, DeviceTV}},
+
+ {"Roku/DVP-5.2 (025.02E03197A)", // Roku
+ UserAgent{
+ Browser{BrowserUnknown, Version{0, 0, 0}}, OS{PlatformUnknown, OSUnknown, Version{0, 0, 0}}, DeviceTV}},
+
+ {"mozilla/5.0 (smart-tv; linux; tizen 2.3) applewebkit/538.1 (khtml, like gecko) samsungbrowser/1.0 tv safari/538.1", // Samsung SmartTV
+ UserAgent{
+ Browser{BrowserUnknown, Version{0, 0, 0}}, OS{PlatformLinux, OSLinux, Version{0, 0, 0}}, DeviceTV}},
+
+ {"mozilla/5.0 (linux; u) applewebkit/537.36 (khtml, like gecko) version/4.0 mobile safari/537.36 smarttv/6.0 (netcast)",
+ UserAgent{
+ Browser{BrowserUnknown, Version{4, 0, 0}}, OS{PlatformLinux, OSLinux, Version{0, 0, 0}}, DeviceTV}},
+
+ // Google search app (GSA) for iOS -- it's Safari in disguise as of v6
+ {"Mozilla/5.0 (iPad; CPU OS 8_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) GSA/6.0.51363 Mobile/12F69 Safari/600.1.4",
+ UserAgent{
+ Browser{BrowserSafari, Version{8, 3, 0}}, OS{PlatformiPad, OSiOS, Version{8, 3, 0}}, DeviceTablet}},
+
+ // Spotify (applicable for advertising applications)
+ {"Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Spotify/1.0.9.133 Safari/537.36",
+ UserAgent{
+ Browser{BrowserSpotify, Version{1, 0, 9}}, OS{PlatformWindows, OSWindows, Version{5, 1, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Spotify/1.0.9.133 Safari/537.36",
+ UserAgent{
+ Browser{BrowserSpotify, Version{1, 0, 9}}, OS{PlatformMac, OSMacOSX, Version{10, 10, 2}}, DeviceComputer}},
+
+ // Bots
+ {"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/600.2.5 (KHTML, like Gecko) Version/8.0.2 Safari/600.2.5 (Applebot/0.1; +http://www.apple.com/go/applebot)",
+ UserAgent{
+ Browser{BrowserAppleBot, Version{0, 0, 0}}, OS{PlatformBot, OSBot, Version{10, 10, 1}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)",
+ UserAgent{
+ Browser{BrowserBaiduBot, Version{0, 0, 0}}, OS{PlatformBot, OSBot, Version{0, 0, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)",
+ UserAgent{
+ Browser{BrowserBingBot, Version{0, 0, 0}}, OS{PlatformBot, OSBot, Version{0, 0, 0}}, DeviceComputer}},
+
+ {"DuckDuckBot/1.0; (+http://duckduckgo.com/duckduckbot.html)",
+ UserAgent{
+ Browser{BrowserDuckDuckGoBot, Version{0, 0, 0}}, OS{PlatformBot, OSBot, Version{0, 0, 0}}, DeviceComputer}},
+
+ {"facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)",
+ UserAgent{
+ Browser{BrowserFacebookBot, Version{0, 0, 0}}, OS{PlatformBot, OSBot, Version{0, 0, 0}}, DeviceComputer}},
+
+ {"Facebot/1.0",
+ UserAgent{
+ Browser{BrowserFacebookBot, Version{0, 0, 0}}, OS{PlatformBot, OSBot, Version{0, 0, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)",
+ UserAgent{
+ Browser{BrowserGoogleBot, Version{0, 0, 0}}, OS{PlatformBot, OSBot, Version{0, 0, 0}}, DeviceComputer}},
+
+ {"LinkedInBot/1.0 (compatible; Mozilla/5.0; Jakarta Commons-HttpClient/3.1 +http://www.linkedin.com)",
+ UserAgent{
+ Browser{BrowserLinkedInBot, Version{0, 0, 0}}, OS{PlatformBot, OSBot, Version{0, 0, 0}}, DeviceComputer}},
+
+ {"msnbot/2.0b (+http://search.msn.com/msnbot.htm)",
+ UserAgent{
+ Browser{BrowserMsnBot, Version{0, 0, 0}}, OS{PlatformBot, OSBot, Version{0, 0, 0}}, DeviceComputer}},
+
+ {"Pingdom.com_bot_version_1.4_(http://www.pingdom.com/)",
+ UserAgent{
+ Browser{BrowserPingdomBot, Version{0, 0, 0}}, OS{PlatformBot, OSBot, Version{0, 0, 0}}, DeviceComputer}},
+
+ {"Twitterbot/1.0",
+ UserAgent{
+ Browser{BrowserTwitterBot, Version{0, 0, 0}}, OS{PlatformBot, OSBot, Version{0, 0, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (compatible; YandexBot/3.0; +http://yandex.com/bots)",
+ UserAgent{
+ Browser{BrowserYandexBot, Version{0, 0, 0}}, OS{PlatformBot, OSBot, Version{0, 0, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (compatible; Yahoo! Slurp; http://help.yahoo.com/help/us/ysearch/slurp)",
+ UserAgent{
+ Browser{BrowserYahooBot, Version{0, 0, 0}}, OS{PlatformBot, OSBot, Version{0, 0, 0}}, DeviceComputer}},
+
+ // {"Mozilla/5.0 (iPhone; CPU iPhone OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)",
+ // BrowserBot, Version{0,0,0}}, OS{PlatformBot, OSBot, Version{6,0,0}}, DeviceComputer}},
+
+ {"mozilla/5.0 (unknown; linux x86_64) applewebkit/538.1 (khtml, like gecko) phantomjs/2.1.1 safari/538.1",
+ UserAgent{
+ Browser{BrowserBot, Version{0, 0, 0}}, OS{PlatformBot, OSBot, Version{0, 0, 0}}, DeviceComputer}},
+
+ // Unknown or partially handled
+ {"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.4; en-US; rv:1.9.1b3pre) Gecko/20090223 SeaMonkey/2.0a3", //Seamonkey (~FF)
+ UserAgent{
+ Browser{BrowserFirefox, Version{0, 0, 0}}, OS{PlatformMac, OSMacOSX, Version{10, 4, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en; rv:1.9.0.8pre) Gecko/2009022800 Camino/2.0b3pre", //Camino (~FF)
+ UserAgent{
+ Browser{BrowserUnknown, Version{0, 0, 0}}, OS{PlatformMac, OSMacOSX, Version{10, 5, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Mobile; rv:26.0) Gecko/26.0 Firefox/26.0", //firefox OS
+ UserAgent{
+ Browser{BrowserFirefox, Version{26, 0, 0}}, OS{PlatformUnknown, OSUnknown, Version{0, 0, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.45 Safari/535.19", //chrome for android having requested desktop site
+ UserAgent{
+ Browser{BrowserChrome, Version{18, 0, 1025}}, OS{PlatformLinux, OSLinux, Version{0, 0, 0}}, DeviceComputer}},
+
+ {"Opera/9.80 (S60; SymbOS; Opera Mobi/352; U; de) Presto/2.4.15 Version/10.00",
+ UserAgent{
+ Browser{BrowserOpera, Version{10, 0, 0}}, OS{PlatformUnknown, OSUnknown, Version{0, 0, 0}}, DevicePhone}},
+
+ // BrowserQQ
+ // {"Mozilla/5.0 (Windows NT 6.2; WOW64; Trident/7.0; Touch; .NET4.0E; .NET4.0C; .NET CLR 3.5.30729; .NET CLR 2.0.50727; .NET CLR 3.0.30729; InfoPath.3; Tablet PC 2.0; QQBrowser/7.6.21433.400; rv:11.0) like Gecko",
+ // UserAgent{
+ // Browser{BrowserQQ, Version{7,0,0}}, OS{PlatformWindows, OSWindows, Version{8,0,0}}, DeviceTablet}},
+
+ // {"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.124 Safari/537.36 QQBrowser/9.0.2191.400",
+ // UserAgent{
+ // Browser{BrowserQQ, Version{9,0,0}}, OS{PlatformWindows, OSWindows, Version{7,0,0}}, DeviceComputer}},
+
+ // ANDROID TESTS
+
+ {"Mozilla/5.0 (Linux; U; Android 1.0; en-us; dream) AppleWebKit/525.10+ (KHTML,like Gecko) Version/3.0.4 Mobile Safari/523.12.2",
+ UserAgent{
+ Browser{BrowserAndroid, Version{3, 0, 4}}, OS{PlatformLinux, OSAndroid, Version{1, 0, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; U; Android 1.0; en-us; generic) AppleWebKit/525.10 (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2",
+ UserAgent{
+ Browser{BrowserAndroid, Version{3, 0, 4}}, OS{PlatformLinux, OSAndroid, Version{1, 0, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; U; Android 1.0.3; de-de; A80KSC Build/ECLAIR) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17",
+ UserAgent{
+ Browser{BrowserAndroid, Version{4, 0, 0}}, OS{PlatformLinux, OSAndroid, Version{1, 0, 3}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; U; Android 1.5; en-gb; T-Mobile G1 Build/CRC1) AppleWebKit/528.5+ (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1",
+ UserAgent{
+ Browser{BrowserAndroid, Version{3, 1, 2}}, OS{PlatformLinux, OSAndroid, Version{1, 5, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; U; Android 1.5; es-; FBW1_4 Build/MASTER) AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2",
+ UserAgent{
+ Browser{BrowserAndroid, Version{3, 0, 4}}, OS{PlatformLinux, OSAndroid, Version{1, 5, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux U; Android 1.5 en-us hero) AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2",
+ UserAgent{
+ Browser{BrowserAndroid, Version{3, 0, 4}}, OS{PlatformLinux, OSAndroid, Version{1, 5, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; U; Android 1.5; en-us; Opus One Build/RBE.00.00) AppleWebKit/528.18.1 (KHTML, like Gecko) Version/3.1.1 Mobile Safari/525.20.1",
+ UserAgent{
+ Browser{BrowserAndroid, Version{3, 1, 1}}, OS{PlatformLinux, OSAndroid, Version{1, 5, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; U; Android 1.6; ar-us; SonyEricssonX10i Build/R2BA026) AppleWebKit/528.5+ (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1",
+ UserAgent{
+ Browser{BrowserAndroid, Version{3, 1, 2}}, OS{PlatformLinux, OSAndroid, Version{1, 6, 0}}, DevicePhone}},
+
+ // TODO: support names of Android OS?
+ //{"Mozilla/5.0 (Linux; U; Android Donut; de-de; HTC Tattoo 1.52.161.1 Build/Donut) AppleWebKit/528.5+ (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1",
+ // UserAgent{
+ // Browser{BrowserAndroid, Version{3, 1, 2}}, OS{PlatformLinux, OSAndroid, Version{1, 0, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; U; Android 1.6; en-gb; HTC Tattoo Build/DRC79) AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2",
+ UserAgent{
+ Browser{BrowserAndroid, Version{3, 0, 4}}, OS{PlatformLinux, OSAndroid, Version{1, 6, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; U; Android 1.6; ja-jp; Docomo HT-03A Build/DRD08) AppleWebKit/525.10 (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2",
+ UserAgent{
+ Browser{BrowserAndroid, Version{3, 0, 4}}, OS{PlatformLinux, OSAndroid, Version{1, 6, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; U; Android 2.1; en-us; Nexus One Build/ERD62) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17",
+ UserAgent{
+ Browser{BrowserAndroid, Version{4, 0, 0}}, OS{PlatformLinux, OSAndroid, Version{2, 1, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; U; Android 2.1-update1; en-au; HTC_Desire_A8183 V1.16.841.1 Build/ERE27) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17",
+ UserAgent{
+ Browser{BrowserAndroid, Version{4, 0, 0}}, OS{PlatformLinux, OSAndroid, Version{2, 1, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; U; Android 2.1; en-us; generic) AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2",
+ UserAgent{
+ Browser{BrowserAndroid, Version{3, 0, 4}}, OS{PlatformLinux, OSAndroid, Version{2, 1, 0}}, DevicePhone}},
+
+ // TODO support named versions of Android?
+ {"Mozilla/5.0 (Linux; U; Android Eclair; en-us; sholes) AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2",
+ UserAgent{
+ Browser{BrowserAndroid, Version{3, 0, 4}}, OS{PlatformLinux, OSAndroid, Version{0, 0, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; U; Android 2.2; en-sa; HTC_DesireHD_A9191 Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",
+ UserAgent{
+ Browser{BrowserAndroid, Version{4, 0, 0}}, OS{PlatformLinux, OSAndroid, Version{2, 2, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; U; Android 2.2.1; en-gb; HTC_DesireZ_A7272 Build/FRG83D) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",
+ UserAgent{
+ Browser{BrowserAndroid, Version{4, 0, 0}}, OS{PlatformLinux, OSAndroid, Version{2, 2, 1}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; U; Android 2.3.3; en-us; Sensation_4G Build/GRI40) AppleWebKit/533.1 (KHTML, like Gecko) Version/5.0 Safari/533.16",
+ UserAgent{
+ Browser{BrowserAndroid, Version{5, 0, 0}}, OS{PlatformLinux, OSAndroid, Version{2, 3, 3}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; U; Android 2.3.5; ko-kr; SHW-M250S Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",
+ UserAgent{
+ Browser{BrowserAndroid, Version{4, 0, 0}}, OS{PlatformLinux, OSAndroid, Version{2, 3, 5}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; U; Android 2.3.7; ja-jp; L-02D Build/GWK74) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",
+ UserAgent{
+ Browser{BrowserAndroid, Version{4, 0, 0}}, OS{PlatformLinux, OSAndroid, Version{2, 3, 7}}, DevicePhone}},
+
+ // TODO: is tablet, not phone
+ {"Mozilla/5.0 (Linux; U; Android 3.0; xx-xx; Transformer TF101 Build/HRI66) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13",
+ UserAgent{
+ Browser{BrowserAndroid, Version{4, 0, 0}}, OS{PlatformLinux, OSAndroid, Version{3, 0, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; U; Android 3.0; en-us; Xoom Build/HRI39) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13",
+ UserAgent{
+ Browser{BrowserAndroid, Version{4, 0, 0}}, OS{PlatformLinux, OSAndroid, Version{3, 0, 0}}, DeviceTablet}},
+
+ {"Mozilla/5.0 (Linux; U; Android 4.0.1; en-us; sdk Build/ICS_MR0) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30",
+ UserAgent{
+ Browser{BrowserAndroid, Version{4, 0, 0}}, OS{PlatformLinux, OSAndroid, Version{4, 0, 1}}, DevicePhone}},
+
+ // TODO support "android-" version prefix
+ // However, can't find reference to this naming scheme in real-world UA gathering
+ // {"Mozilla/5.0 (Linux; U; Android-4.0.3; en-us; Galaxy Nexus Build/IML74K) AppleWebKit/535.7 (KHTML, like Gecko) CrMo/16.0.912.75 Mobile Safari/535.7",
+ // UserAgent{
+ // Browser{BrowserChrome, Version{16,0,0}}, OS{PlatformLinux, OSAndroid, Version{4,0,0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; U; Android 4.1.1; en-us; Nexus S Build/JRO03E) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30",
+ UserAgent{
+ Browser{BrowserAndroid, Version{4, 0, 0}}, OS{PlatformLinux, OSAndroid, Version{4, 1, 1}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; U; Android 4.1; en-gb; Build/JRN84D) AppleWebKit/534.30 (KHTML like Gecko) Version/4.0 Mobile Safari/534.30",
+ UserAgent{
+ Browser{BrowserAndroid, Version{4, 0, 0}}, OS{PlatformLinux, OSAndroid, Version{4, 1, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; U; Android 4.1.1; el-gr; MB525 Build/JRO03H; CyanogenMod-10) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30",
+ UserAgent{
+ Browser{BrowserAndroid, Version{4, 0, 0}}, OS{PlatformLinux, OSAndroid, Version{4, 1, 1}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; U; Android 4.1.1; fr-fr; MB525 Build/JRO03H; CyanogenMod-10) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30",
+ UserAgent{
+ Browser{BrowserAndroid, Version{4, 0, 0}}, OS{PlatformLinux, OSAndroid, Version{4, 1, 1}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; U; Android 4.2; en-us; Nexus 10 Build/JVP15I) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30",
+ UserAgent{
+ Browser{BrowserAndroid, Version{4, 0, 0}}, OS{PlatformLinux, OSAndroid, Version{4, 2, 0}}, DeviceTablet}},
+
+ {"Mozilla/5.0 (Linux; U; Android 4.2; ro-ro; LT18i Build/4.1.B.0.431) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30",
+ UserAgent{
+ Browser{BrowserAndroid, Version{4, 0, 0}}, OS{PlatformLinux, OSAndroid, Version{4, 2, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; Android 4.3; Nexus 7 Build/JWR66D) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.111 Safari/537.36",
+ UserAgent{
+ Browser{BrowserChrome, Version{27, 0, 1453}}, OS{PlatformLinux, OSAndroid, Version{4, 3, 0}}, DeviceTablet}},
+
+ {"Mozilla/5.0 (Linux; Android 4.4; Nexus 7 Build/KOT24) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.105 Safari/537.36",
+ UserAgent{
+ Browser{BrowserChrome, Version{30, 0, 1599}}, OS{PlatformLinux, OSAndroid, Version{4, 4, 0}}, DeviceTablet}},
+
+ {"Mozilla/5.0 (Linux; Android 4.4; Nexus 4 Build/KRT16E) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.105 Mobile Safari",
+ UserAgent{
+ Browser{BrowserChrome, Version{30, 0, 1599}}, OS{PlatformLinux, OSAndroid, Version{4, 4, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; Android 6.0.1; SM-G930V Build/MMB29M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.98 Mobile Safari/537.36",
+ UserAgent{
+ Browser{BrowserChrome, Version{52, 0, 2743}}, OS{PlatformLinux, OSAndroid, Version{6, 0, 1}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; Android 7.0; Nexus 5X Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.98 Mobile Safari/537.36",
+ UserAgent{
+ Browser{BrowserChrome, Version{52, 0, 2743}}, OS{PlatformLinux, OSAndroid, Version{7, 0, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; Android 7.0; Nexus 6P Build/NRD90M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/52.0.2743.98 Mobile Safari/537.36",
+ UserAgent{
+ Browser{BrowserChrome, Version{52, 0, 2743}}, OS{PlatformLinux, OSAndroid, Version{7, 0, 0}}, DevicePhone}},
+
+ // BLACKBERRY TESTS
+
+ {"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) BlackBerry8703e/4.1.0 Profile/MIDP-2.0 Configuration/CLDC-1.1 VendorID/104",
+ UserAgent{
+ Browser{BrowserBlackberry, Version{0, 0, 0}}, OS{PlatformBlackberry, OSBlackberry, Version{0, 0, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (BB10; Touch) AppleWebKit/537.10+ (KHTML, like Gecko) Version/10.1.0.4633 Mobile Safari/537.10+",
+ UserAgent{
+ Browser{BrowserBlackberry, Version{10, 1, 0}}, OS{PlatformBlackberry, OSBlackberry, Version{0, 0, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (BB10; Kbd) AppleWebKit/537.35+ (KHTML, like Gecko) Version/10.2.1.1925 Mobile Safari/537.35+",
+ UserAgent{
+ Browser{BrowserBlackberry, Version{10, 2, 1}}, OS{PlatformBlackberry, OSBlackberry, Version{0, 0, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (PlayBook; U; RIM Tablet OS 1.0.0; en-US) AppleWebKit/534.11 (KHTML, like Gecko) Version/7.1.0.7 Safari/534.11",
+ UserAgent{
+ Browser{BrowserBlackberry, Version{7, 1, 0}}, OS{PlatformBlackberry, OSBlackberry, Version{0, 0, 0}}, DeviceTablet}},
+
+ {"Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML, like Gecko) Version/7.2.1.0 Safari/536.2+",
+ UserAgent{
+ Browser{BrowserBlackberry, Version{7, 2, 1}}, OS{PlatformBlackberry, OSBlackberry, Version{0, 0, 0}}, DeviceTablet}},
+
+ {"Mozilla/5.0 (X11; U; CrOS i686 9.10.0; en-US) AppleWebKit/532.5 (KHTML, like Gecko) Chrome/4.0.253.0 Safari/532.5",
+ UserAgent{
+ Browser{BrowserChrome, Version{4, 0, 253}}, OS{PlatformLinux, OSChromeOS, Version{0, 0, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (X11; CrOS armv7l 5500.100.6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.120 Safari/537.36",
+ UserAgent{
+ Browser{BrowserChrome, Version{34, 0, 1847}}, OS{PlatformLinux, OSChromeOS, Version{0, 0, 0}}, DeviceComputer}},
+
+ // {"Mozilla/5.0 (Mobile; rv:14.0) Gecko/14.0 Firefox/14.0",
+ // UserAgent{
+ // Browser{BrowserFirefox, 14, OSFirefoxOS, 14}, DevicePhone}},
+
+ // {"Mozilla/5.0 (Mobile; rv:17.0) Gecko/17.0 Firefox/17.0",
+ // UserAgent{
+ // Browser{BrowserFirefox, , OSFirefoxOS}, DevicePhone}},
+
+ // {"Mozilla/5.0 (Mobile; rv:18.1) Gecko/18.1 Firefox/18.1",
+ // UserAgent{
+ // Browser{BrowserFirefox, , OSFirefoxOS}, DevicePhone}},
+
+ // {"Mozilla/5.0 (Tablet; rv:18.1) Gecko/18.1 Firefox/18.1",
+ // UserAgent{
+ // Browser{BrowserFirefox, , OSFirefoxOS}, DevicePhone}},
+
+ // {"Mozilla/5.0 (Mobile; LG-D300; rv:18.1) Gecko/18.1 Firefox/18.1",
+ // UserAgent{
+ // Browser{BrowserFirefox, , OSFirefoxOS}, DevicePhone}},
+
+ {"Mozilla/5.0(iPad; U; CPU iPhone OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B314 Safari/531.21.10",
+ UserAgent{
+ Browser{BrowserSafari, Version{4, 0, 4}}, OS{PlatformiPad, OSiOS, Version{3, 2, 0}}, DeviceTablet}},
+
+ {"Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8A293 Safari/6531.22.7",
+ UserAgent{
+ Browser{BrowserSafari, Version{4, 0, 5}}, OS{PlatformiPhone, OSiOS, Version{4, 0, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (iPhone; CPU iPhone OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A334 Safari/7534.48.3",
+ UserAgent{
+ Browser{BrowserSafari, Version{5, 1, 0}}, OS{PlatformiPhone, OSiOS, Version{5, 0, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (iPad; CPU OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A334 Safari/7534.48.3",
+ UserAgent{
+ Browser{BrowserSafari, Version{5, 1, 0}}, OS{PlatformiPad, OSiOS, Version{5, 0, 0}}, DeviceTablet}},
+
+ {"Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5355d Safari/8536.25",
+ UserAgent{
+ Browser{BrowserSafari, Version{6, 0, 0}}, OS{PlatformiPad, OSiOS, Version{6, 0, 0}}, DeviceTablet}},
+
+ {"Mozilla/5.0 (iPhone; CPU iPhone OS 7_0 like Mac OS X) AppleWebKit/546.10 (KHTML, like Gecko) Version/6.0 Mobile/7E18WD Safari/8536.25",
+ UserAgent{
+ Browser{BrowserSafari, Version{6, 0, 0}}, OS{PlatformiPhone, OSiOS, Version{7, 0, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (iPad; CPU OS 7_0 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A465 Safari/9537.53",
+ UserAgent{
+ Browser{BrowserSafari, Version{7, 0, 0}}, OS{PlatformiPad, OSiOS, Version{7, 0, 0}}, DeviceTablet}},
+
+ {"Mozilla/5.0 (iPad; CPU OS 7_0_2 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A501 Safari/9537.53",
+ UserAgent{
+ Browser{BrowserSafari, Version{7, 0, 0}}, OS{PlatformiPad, OSiOS, Version{7, 0, 2}}, DeviceTablet}},
+
+ {"Mozilla/5.0 (iPhone; CPU iPhone OS 10_2_1 like Mac OS X) AppleWebKit/602.4.6 (KHTML, like Gecko) Mobile/14D27 [FBAN/FBIOS;FBAV/86.0.0.48.52;FBBV/53842252;FBDV/iPhone9,1;FBMD/iPhone;FBSN/iOS;FBSV/10.2.1;FBSS/2;FBCR/Verizon;FBID/phone;FBLC/en_US;FBOP/5;FBRV/0]",
+ UserAgent{
+ Browser{BrowserSafari, Version{10, 2, 1}}, OS{PlatformiPhone, OSiOS, Version{10, 2, 1}}, DevicePhone}},
+
+ // TODO handle default browser based on iOS version
+ // {"Mozilla/5.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/538.34.9 (KHTML, like Gecko) Mobile/12A4265u",
+ // UserAgent{
+ // Browser{BrowserSafari, Version{8,0,0}}, OS{PlatformiPhone, OSiOS, Version{8,0,0}}, DevicePhone}},
+
+ // TODO extrapolate browser from iOS version
+ // {"Mozilla/5.0 (iPad; CPU OS 8_0 like Mac OS X) AppleWebKit/538.34.9 (KHTML, like Gecko) Mobile/12A4265u",
+ // UserAgent{
+ // Browser{BrowserSafari, Version{8,0,0}}, OS{PlatformiPad, OSiOS, Version{8,0,0}}, DeviceTablet}},
+
+ {"Mozilla/5.0 (iPhone; CPU iPhone OS 8_0_2 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12A405 Safari/600.1.4",
+ UserAgent{
+ Browser{BrowserSafari, Version{8, 0, 0}}, OS{PlatformiPhone, OSiOS, Version{8, 0, 2}}, DevicePhone}},
+
+ {"Mozilla/5.0 (X11; U; Linux x86_64; en; rv:1.9.0.14) Gecko/20080528 Ubuntu/9.10 (karmic) Epiphany/2.22 Firefox/3.0",
+ UserAgent{
+ Browser{BrowserFirefox, Version{3, 0, 0}}, OS{PlatformLinux, OSLinux, Version{0, 0, 0}}, DeviceComputer}},
+
+ // Can't parse browser due to limitation of user agent library
+ {"Mozilla/5.0 (X11; U; Linux x86_64; zh-TW; rv:1.9.0.8) Gecko/2009032712 Ubuntu/8.04 (hardy) Firefox/3.0.8 GTB5",
+ UserAgent{
+ Browser{BrowserFirefox, Version{3, 0, 8}}, OS{PlatformLinux, OSLinux, Version{0, 0, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (compatible; Konqueror/3.5; Linux; x86_64) KHTML/3.5.5 (like Gecko) (Debian)",
+ UserAgent{
+ Browser{BrowserUnknown, Version{0, 0, 0}}, OS{PlatformLinux, OSLinux, Version{0, 0, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (X11; U; Linux i686; de; rv:1.9.1.5) Gecko/20091112 Iceweasel/3.5.5 (like Firefox/3.5.5; Debian-3.5.5-1)",
+ UserAgent{
+ Browser{BrowserFirefox, Version{3, 5, 5}}, OS{PlatformLinux, OSLinux, Version{0, 0, 0}}, DeviceComputer}},
+
+ // TODO consider bot?
+ // {"Miro/2.0.4 (http://www.getmiro.com/; Darwin 10.3.0 i386)",
+ // UserAgent{
+ // Browser{BrowserUnknown, Version{0,0,0}}, OS{PlatformMac, OSMacOSX, Version{3,0,0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.4; en-US; rv:1.9.1b3pre) Gecko/20090223 SeaMonkey/2.0a3",
+ UserAgent{
+ Browser{BrowserFirefox, Version{0, 0, 0}}, OS{PlatformMac, OSMacOSX, Version{10, 4, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_5; en-us) AppleWebKit/525.26.2 (KHTML, like Gecko) Version/3.2 Safari/525.26.12",
+ UserAgent{
+ Browser{BrowserSafari, Version{3, 2, 0}}, OS{PlatformMac, OSMacOSX, Version{10, 5, 5}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en; rv:1.9.0.8pre) Gecko/2009022800 Camino/2.0b3pre",
+ UserAgent{
+ Browser{BrowserUnknown, Version{0, 0, 0}}, OS{PlatformMac, OSMacOSX, Version{10, 5, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_2; en-US) AppleWebKit/533.1 (KHTML, like Gecko) Chrome/5.0.329.0 Safari/533.1",
+ UserAgent{
+ Browser{BrowserChrome, Version{5, 0, 329}}, OS{PlatformMac, OSMacOSX, Version{10, 6, 2}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 (.NET CLR 3.5.30729)",
+ UserAgent{
+ Browser{BrowserFirefox, Version{3, 5, 6}}, OS{PlatformMac, OSMacOSX, Version{10, 6, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/534.52.7 (KHTML, like Gecko) Version/5.1.2 Safari/534.52.7",
+ UserAgent{
+ Browser{BrowserSafari, Version{5, 1, 2}}, OS{PlatformMac, OSMacOSX, Version{10, 7, 2}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:9.0) Gecko/20111222 Thunderbird/9.0.1",
+ UserAgent{
+ Browser{BrowserUnknown, Version{0, 0, 0}}, OS{PlatformMac, OSMacOSX, Version{10, 7, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.75 Safari/535.7",
+ UserAgent{
+ Browser{BrowserChrome, Version{16, 0, 912}}, OS{PlatformMac, OSMacOSX, Version{10, 7, 2}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8) AppleWebKit/535.18.5 (KHTML, like Gecko) Version/5.2 Safari/535.18.5",
+ UserAgent{
+ Browser{BrowserSafari, Version{5, 2, 0}}, OS{PlatformMac, OSMacOSX, Version{10, 8, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_8; en-US) AppleWebKit/532.5 (KHTML, like Gecko) Chrome/4.0.249.0 Safari/532.5",
+ UserAgent{
+ Browser{BrowserChrome, Version{4, 0, 249}}, OS{PlatformMac, OSMacOSX, Version{10, 8, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9) AppleWebKit/537.35.1 (KHTML, like Gecko) Version/6.1 Safari/537.35.1",
+ UserAgent{
+ Browser{BrowserSafari, Version{6, 1, 0}}, OS{PlatformMac, OSMacOSX, Version{10, 9, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10) AppleWebKit/538.34.48 (KHTML, like Gecko) Version/8.0 Safari/538.35.8",
+ UserAgent{
+ Browser{BrowserSafari, Version{8, 0, 0}}, OS{PlatformMac, OSMacOSX, Version{10, 10, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10) AppleWebKit/538.32 (KHTML, like Gecko) Version/7.1 Safari/538.4",
+ UserAgent{
+ Browser{BrowserSafari, Version{7, 1, 0}}, OS{PlatformMac, OSMacOSX, Version{10, 10, 0}}, DeviceComputer}},
+
+ {"Opera/9.80 (S60; SymbOS; Opera Mobi/352; U; de) Presto/2.4.15 Version/10.00",
+ UserAgent{
+ Browser{BrowserOpera, Version{10, 0, 0}}, OS{PlatformUnknown, OSUnknown, Version{0, 0, 0}}, DevicePhone}},
+
+ {"Opera/9.80 (S60; SymbOS; Opera Mobi/352; U; de) Presto/2.4.15 Version/10.00",
+ UserAgent{
+ Browser{BrowserOpera, Version{10, 0, 0}}, OS{PlatformUnknown, OSUnknown, Version{0, 0, 0}}, DevicePhone}},
+
+ // TODO: support OneBrowser? https://play.google.com/store/apps/details?id=com.tencent.ibibo.mtt&hl=en_GB
+ // {"OneBrowser/3.1 (NokiaN70-1/5.0638.3.0.1)",
+ // UserAgent{
+ // Browser{BrowserUnknown, Version{0,0,0}}, OS{PlatformUnknown, OSUnknown, Version{0,0,0}}, DevicePhone}},
+
+ // WebOS reports itself as safari :(
+ {"Mozilla/5.0 (webOS/1.0; U; en-US) AppleWebKit/525.27.1 (KHTML, like Gecko) Version/1.0 Safari/525.27.1 Pre/1.0",
+ UserAgent{
+ Browser{BrowserUnknown, Version{1, 0, 0}}, OS{PlatformLinux, OSWebOS, Version{0, 0, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (webOS/1.4.1.1; U; en-US) AppleWebKit/532.2 (KHTML, like Gecko) Version/1.0 Safari/532.2 Pre/1.0",
+ UserAgent{
+ Browser{BrowserUnknown, Version{1, 0, 0}}, OS{PlatformLinux, OSWebOS, Version{0, 0, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (hp-tablet; Linux; hpwOS/3.0.0; U; de-DE) AppleWebKit/534.6 (KHTML, like Gecko) wOSBrowser/233.70 Safari/534.6 TouchPad/1.0",
+ UserAgent{
+ Browser{BrowserUnknown, Version{0, 0, 0}}, OS{PlatformLinux, OSWebOS, Version{0, 0, 0}}, DeviceTablet}},
+
+ {"Mozilla/5.0 (hp-tablet; Linux; hpwOS/3.0.2; U; en-US) AppleWebKit/534.6 (KHTML, like Gecko) wOSBrowser/234.40.1 Safari/534.6 TouchPad/1.0",
+ UserAgent{
+ Browser{BrowserUnknown, Version{0, 0, 0}}, OS{PlatformLinux, OSWebOS, Version{0, 0, 0}}, DeviceTablet}},
+
+ {"Opera/9.30 (Nintendo Wii; U; ; 2047-7; fr)",
+ UserAgent{
+ Browser{BrowserOpera, Version{9, 30, 0}}, OS{PlatformNintendo, OSNintendo, Version{0, 0, 0}}, DeviceConsole}},
+
+ {"Mozilla/5.0 (Nintendo WiiU) AppleWebKit/534.52 (KHTML, like Gecko) NX/2.1.0.8.21 NintendoBrowser/1.0.0.7494.US",
+ UserAgent{
+ Browser{BrowserUnknown, Version{0, 0, 0}}, OS{PlatformNintendo, OSNintendo, Version{0, 0, 0}}, DeviceConsole}},
+
+ {"Mozilla/5.0 (Nintendo WiiU) AppleWebKit/536.28 (KHTML, like Gecko) NX/3.0.3.12.6 NintendoBrowser/2.0.0.9362.US",
+ UserAgent{
+ Browser{BrowserUnknown, Version{0, 0, 0}}, OS{PlatformNintendo, OSNintendo, Version{0, 0, 0}}, DeviceConsole}},
+
+ // TODO fails to get opera first -- but is this a real UA string or an uncommon spoof?
+ // {"Mozilla/4.0 (compatible; MSIE 5.0; Windows 2000) Opera 6.0 [en]",
+ // BrowserIE, Version{5,0,0}}, OS{PlatformWindows, OSWindows, Version{4,0,0}}, DeviceComputer}},
+
+ {"Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; SV1; .NET CLR 1.1.4322; .NET CLR 1.0.3705; .NET CLR 2.0.50727)",
+ UserAgent{
+ Browser{BrowserIE, Version{5, 0, 1}}, OS{PlatformWindows, OSWindows, Version{5, 0, 0}}, DeviceComputer}},
+
+ {"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/4.0; GTB6.4; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; OfficeLiveConnector.1.3; OfficeLivePatch.0.0; .NET CLR 1.1.4322)",
+ UserAgent{
+ Browser{BrowserIE, Version{7, 0, 0}}, OS{PlatformWindows, OSWindows, Version{6, 1, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Windows; U; Windows NT 6.1; sk; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7",
+ UserAgent{
+ Browser{BrowserFirefox, Version{3, 5, 7}}, OS{PlatformWindows, OSWindows, Version{6, 1, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)",
+ UserAgent{
+ Browser{BrowserIE, Version{10, 0, 0}}, OS{PlatformWindows, OSWindows, Version{6, 2, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/536.5 (KHTML, like Gecko) YaBrowser/1.0.1084.5402 Chrome/19.0.1084.5402 Safari/536.5",
+ UserAgent{
+ Browser{BrowserChrome, Version{19, 0, 1084}}, OS{PlatformWindows, OSWindows, Version{6, 2, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.15 (KHTML, like Gecko) Chrome/24.0.1295.0 Safari/537.15",
+ UserAgent{
+ Browser{BrowserChrome, Version{24, 0, 1295}}, OS{PlatformWindows, OSWindows, Version{6, 2, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; Touch; rv:11.0) like Gecko",
+ UserAgent{
+ Browser{BrowserIE, Version{11, 0, 0}}, OS{PlatformWindows, OSWindows, Version{6, 3, 0}}, DeviceTablet}},
+
+ {"Mozilla/5.0 (IE 11.0; Windows NT 6.3; Trident/7.0; .NET4.0E; .NET4.0C; rv:11.0) like Gecko",
+ UserAgent{
+ Browser{BrowserIE, Version{11, 0, 0}}, OS{PlatformWindows, OSWindows, Version{6, 3, 0}}, DeviceComputer}},
+
+ // {"Mozilla/4.0 (compatible; MSIE 4.01; Windows 95)",
+ // UserAgent{
+ // Browser{BrowserIE, Version{5,0,0}}, OS{PlatformWindows, OSWindows95, Version{5,0,0}}, DeviceComputer}},
+
+ // {"Mozilla/4.0 (compatible; MSIE 5.0; Windows 95) Opera 6.02 [en]",
+ // UserAgent{
+ // Browser{BrowserIE, Version{5,0,0}}, OS{PlatformWindows, OSWindows95, Version{5,0,0}}, DeviceComputer}},
+
+ // {"Mozilla/4.0 (compatible; MSIE 6.0b; Windows 98; YComp 5.0.0.0)",
+ // UserAgent{
+ // Browser{BrowserIE, Version{6,0,0}}, OS{PlatformWindows, OSWindows98, Version{5,0,0}}, DeviceComputer}},
+
+ // {"Mozilla/4.0 (compatible; MSIE 4.01; Windows 98)",
+ // UserAgent{
+ // Browser{BrowserIE, Version{4,0,0}}, OS{PlatformWindows, OSWindows98, Version{5,0,0}}, DeviceComputer}},
+
+ // {"Mozilla/5.0 (Windows; U; Windows 98; en-US; rv:1.8.1.8pre) Gecko/20071019 Firefox/2.0.0.8 Navigator/9.0.0.1",
+ // UserAgent{
+ // Browser{BrowserFirefox, Version{2,0,0}}, OS{PlatformWindows, OSWindows98, Version{5,0,0}}, DeviceComputer}},
+
+ //Can't parse due to limitation of user agent library
+ // {"Mozilla/5.0 (Windows; U; Windows CE 5.1; rv:1.8.1a3) Gecko/20060610 Minimo/0.016",
+ // UserAgent{
+ // Browser{ BrowserUnknown, Version{0,0,0}}, OS{PlatformWindowsPhone, OSWindowsPhone, Version{0,0,0}}, DevicePhone}},
+
+ // {"Mozilla/4.0 (compatible; MSIE 4.01; Windows CE; 176x220)",
+ // UserAgent{
+ // Browser{BrowserIE, Version{4,0,0}}, OS{PlatformWindowsPhone, OSWindowsPhone, Version{0,0,0}}, DevicePhone}},
+
+ // Can't parse browser due to limitation of user agent library
+ // {"Mozilla/4.0 (compatible; MSIE 5.0; Windows ME) Opera 6.0 [de]",
+ // UserAgent{
+ // Browser{BrowserUnknown, OSWindowsME}, DeviceComputer}},
+
+ {"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; SLCC1; .NET CLR 2.0.50727; .NET CLR 1.1.4322; InfoPath.2; .NET CLR 3.5.21022; .NET CLR 3.5.30729; MS-RTC LM 8; OfficeLiveConnector.1.4; OfficeLivePatch.1.3; .NET CLR 3.0.30729)",
+ UserAgent{
+ Browser{BrowserIE, Version{8, 0, 0}}, OS{PlatformWindows, OSWindows, Version{6, 0, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Windows; U; Windows NT 5.1; cs; rv:1.9.1.8) Gecko/20100202 Firefox/3.5.8",
+ UserAgent{
+ Browser{BrowserFirefox, Version{3, 5, 8}}, OS{PlatformWindows, OSWindows, Version{5, 1, 0}}, DeviceComputer}},
+
+ {"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; )",
+ UserAgent{
+ Browser{BrowserIE, Version{7, 0, 0}}, OS{PlatformWindows, OSWindows, Version{5, 1, 0}}, DeviceComputer}},
+
+ // Can't parse due to limitation of user agent library
+ {"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Windows Phone 6.5.3.5)",
+ UserAgent{
+ Browser{BrowserIE, Version{6, 0, 0}}, OS{PlatformWindowsPhone, OSWindowsPhone, Version{6, 5, 3}}, DevicePhone}},
+
+ // desktop mode for Windows Phone 7
+ {"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; XBLWP7; ZuneWP7)",
+ UserAgent{
+ Browser{BrowserIE, Version{7, 0, 0}}, OS{PlatformWindows, OSWindows, Version{6, 1, 0}}, DeviceComputer}},
+
+ // mobile mode for Windows Phone 7
+ {"Mozilla/4.0 (compatible; MSIE 7.0; Windows Phone OS 7.0; Trident/3.1; IEMobile/7.0; HTC; T8788)",
+ UserAgent{
+ Browser{BrowserIE, Version{7, 0, 0}}, OS{PlatformWindowsPhone, OSWindowsPhone, Version{7, 0, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident/5.0; IEMobile/9.0)",
+ UserAgent{
+ Browser{BrowserIE, Version{9, 0, 0}}, OS{PlatformWindowsPhone, OSWindowsPhone, Version{7, 5, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch; NOKIA; Lumia 920)",
+ UserAgent{
+ Browser{BrowserIE, Version{10, 0, 0}}, OS{PlatformWindowsPhone, OSWindowsPhone, Version{8, 0, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Windows Phone 8.1; ARM; Trident/7.0; Touch IEMobile/11.0; HTC; Windows Phone 8S by HTC) like Gecko",
+ UserAgent{
+ Browser{BrowserIE, Version{11, 0, 0}}, OS{PlatformWindowsPhone, OSWindowsPhone, Version{8, 1, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Windows Phone 8.1; ARM; Trident/7.0; Touch IEMobile/11.0; NOKIA; 909) like Gecko",
+ UserAgent{
+ Browser{BrowserIE, Version{11, 0, 0}}, OS{PlatformWindowsPhone, OSWindowsPhone, Version{8, 1, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; Xbox)",
+ UserAgent{
+ Browser{BrowserIE, Version{9, 0, 0}}, OS{PlatformXbox, OSXbox, Version{6, 1, 0}}, DeviceConsole}},
+}
+
+func TestAgentSurfer(t *testing.T) {
+ for _, determined := range testUAVars {
+ t.Run("", func(t *testing.T) {
+ testFuncs := []func(string) *UserAgent{
+ Parse,
+ func(ua string) *UserAgent {
+ u := new(UserAgent)
+ ParseUserAgent(ua, u)
+ return u
+ },
+ }
+
+ for _, f := range testFuncs {
+ ua := f(determined.UA)
+
+ if ua.Browser.Name != determined.Browser.Name {
+ t.Errorf("browserName: got %v, wanted %v", ua.Browser.Name, determined.Browser.Name)
+ t.Logf("agent: %s", determined.UA)
+ }
+
+ if ua.Browser.Version != determined.Browser.Version {
+ t.Errorf("browser version: got %d, wanted %d", ua.Browser.Version, determined.Browser.Version)
+ t.Logf("agent: %s", determined.UA)
+ }
+
+ if ua.OS.Platform != determined.OS.Platform {
+ t.Errorf("platform: got %v, wanted %v", ua.OS.Platform, determined.OS.Platform)
+ t.Logf("agent: %s", determined.UA)
+ }
+
+ if ua.OS.Name != determined.OS.Name {
+ t.Errorf("os: got %s, wanted %s", ua.OS.Name, determined.OS.Name)
+ t.Logf("agent: %s", determined.UA)
+ }
+
+ if ua.OS.Version != determined.OS.Version {
+ t.Errorf("os version: got %d, wanted %d", ua.OS.Version, determined.OS.Version)
+ t.Logf("agent: %s", determined.UA)
+ }
+
+ if ua.DeviceType != determined.DeviceType {
+ t.Errorf("device type: got %v, wanted %v", ua.DeviceType, determined.DeviceType)
+ t.Logf("agent: %s", determined.UA)
+ }
+ }
+ })
+ }
+}
+
+func BenchmarkAgentSurfer(b *testing.B) {
+ num := len(testUAVars)
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ Parse(testUAVars[i%num].UA)
+ }
+}
+
+func BenchmarkAgentSurferReuse(b *testing.B) {
+ dest := new(UserAgent)
+ num := len(testUAVars)
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ dest.Reset()
+ ParseUserAgent(testUAVars[i%num].UA, dest)
+ }
+}
+
+func BenchmarkEvalSystem(b *testing.B) {
+ num := len(testUAVars)
+ v := UserAgent{}
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ v.evalOS(testUAVars[i%num].UA)
+ }
+}
+
+func BenchmarkEvalBrowserName(b *testing.B) {
+ num := len(testUAVars)
+ v := UserAgent{}
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ v.evalBrowserName(testUAVars[i%num].UA)
+ }
+}
+
+func BenchmarkEvalBrowserVersion(b *testing.B) {
+ num := len(testUAVars)
+ v := UserAgent{}
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ v.Browser.Name = testUAVars[i%num].Browser.Name
+ v.evalBrowserVersion(testUAVars[i%num].UA)
+ }
+}
+
+func BenchmarkEvalDevice(b *testing.B) {
+ num := len(testUAVars)
+ v := UserAgent{}
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ v.OS.Name = testUAVars[i%num].OS.Name
+ v.OS.Platform = testUAVars[i%num].OS.Platform
+ v.Browser.Name = testUAVars[i%num].Browser.Name
+ v.evalDevice(testUAVars[i%num].UA)
+ }
+}
+
+// Chrome for Mac
+func BenchmarkParseChromeMac(b *testing.B) {
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ Parse("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.130 Safari/537.36")
+ }
+}
+
+// Chrome for Windows
+func BenchmarkParseChromeWin(b *testing.B) {
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ Parse("Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.134 Safari/537.36")
+ }
+}
+
+// Chrome for Android
+func BenchmarkParseChromeAndroid(b *testing.B) {
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ Parse("Mozilla/5.0 (Linux; Android 4.4.2; GT-P5210 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.93 Safari/537.36")
+ }
+}
+
+// Safari for Mac
+func BenchmarkParseSafariMac(b *testing.B) {
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ Parse("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/600.7.12 (KHTML, like Gecko) Version/8.0.7 Safari/600.7.12")
+ }
+}
+
+// Safari for iPad
+func BenchmarkParseSafariiPad(b *testing.B) {
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ Parse("Mozilla/5.0 (iPad; CPU OS 8_1_2 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12B440 Safari/600.1.4")
+ }
+}
diff --git a/vendor/github.com/dgryski/dgoogauth/googauth_test.go b/vendor/github.com/dgryski/dgoogauth/googauth_test.go
index 031922c47..43f35d2c9 100644
--- a/vendor/github.com/dgryski/dgoogauth/googauth_test.go
+++ b/vendor/github.com/dgryski/dgoogauth/googauth_test.go
@@ -1,7 +1,7 @@
package dgoogauth
import (
- "strconv"
+ "fmt"
"testing"
"time"
)
@@ -199,11 +199,11 @@ func TestAuthenticate(t *testing.T) {
t0 = int64(time.Now().Unix() / 30)
}
c := ComputeCode(otpconf.Secret, t0)
+ code := fmt.Sprintf("%06d", c)
- invalid := c + 1
attempts = []attempt{
- {strconv.Itoa(invalid), false},
- {strconv.Itoa(c), true},
+ {code + "1", false},
+ {code, true},
}
for _, a := range attempts {
diff --git a/vendor/github.com/go-ini/ini/file.go b/vendor/github.com/go-ini/ini/file.go
index 93ac50836..ce26c3b31 100644
--- a/vendor/github.com/go-ini/ini/file.go
+++ b/vendor/github.com/go-ini/ini/file.go
@@ -345,6 +345,12 @@ func (f *File) writeToBuffer(indent string) (*bytes.Buffer, error) {
return nil, err
}
}
+
+ for _, val := range key.nestedValues {
+ if _, err := buf.WriteString(indent + " " + val + LineBreak); err != nil {
+ return nil, err
+ }
+ }
}
if PrettySection {
diff --git a/vendor/github.com/go-ini/ini/ini.go b/vendor/github.com/go-ini/ini/ini.go
index 508d60c19..535d3588a 100644
--- a/vendor/github.com/go-ini/ini/ini.go
+++ b/vendor/github.com/go-ini/ini/ini.go
@@ -32,7 +32,7 @@ const (
// Maximum allowed depth when recursively substituing variable names.
_DEPTH_VALUES = 99
- _VERSION = "1.30.3"
+ _VERSION = "1.32.0"
)
// Version returns current package version literal.
@@ -134,8 +134,16 @@ type LoadOptions struct {
AllowBooleanKeys bool
// AllowShadows indicates whether to keep track of keys with same name under same section.
AllowShadows bool
- // UnescapeValueDoubleQuotes indicates whether to unescape double quotes inside value to regular format when value is surrounded by double quotes, e.g. key="a \"value\"" => key=a "value"
+ // AllowNestedValues indicates whether to allow AWS-like nested values.
+ // Docs: http://docs.aws.amazon.com/cli/latest/topic/config-vars.html#nested-values
+ AllowNestedValues bool
+ // UnescapeValueDoubleQuotes indicates whether to unescape double quotes inside value to regular format
+ // when value is surrounded by double quotes, e.g. key="a \"value\"" => key=a "value"
UnescapeValueDoubleQuotes bool
+ // UnescapeValueCommentSymbols indicates to unescape comment symbols (\# and \;) inside value to regular format
+ // when value is NOT surrounded by any quotes.
+ // Note: UNSTABLE, behavior might change to only unescape inside double quotes but may noy necessary at all.
+ UnescapeValueCommentSymbols bool
// Some INI formats allow group blocks that store a block of raw content that doesn't otherwise
// conform to key/value pairs. Specify the names of those blocks here.
UnparseableSections []string
diff --git a/vendor/github.com/go-ini/ini/ini_test.go b/vendor/github.com/go-ini/ini/ini_test.go
index 7a1efe4ec..3e6992d3f 100644
--- a/vendor/github.com/go-ini/ini/ini_test.go
+++ b/vendor/github.com/go-ini/ini/ini_test.go
@@ -268,6 +268,19 @@ create_repo="创建了仓库 <a href=\"%s\">%s</a>"`))
})
})
+ Convey("Unescape comment symbols inside value", func() {
+ f, err := ini.LoadSources(ini.LoadOptions{
+ IgnoreInlineComment: true,
+ UnescapeValueCommentSymbols: true,
+ }, []byte(`
+key = test value <span style="color: %s\; background: %s">more text</span>
+`))
+ So(err, ShouldBeNil)
+ So(f, ShouldNotBeNil)
+
+ So(f.Section("").Key("key").String(), ShouldEqual, `test value <span style="color: %s; background: %s">more text</span>`)
+ })
+
Convey("Allow unparseable sections", func() {
f, err := ini.LoadSources(ini.LoadOptions{
Insensitive: true,
diff --git a/vendor/github.com/go-ini/ini/key.go b/vendor/github.com/go-ini/ini/key.go
index ab566c2c1..7c8566a1b 100644
--- a/vendor/github.com/go-ini/ini/key.go
+++ b/vendor/github.com/go-ini/ini/key.go
@@ -34,6 +34,8 @@ type Key struct {
isShadow bool
shadows []*Key
+
+ nestedValues []string
}
// newKey simply return a key object with given values.
@@ -66,6 +68,22 @@ func (k *Key) AddShadow(val string) error {
return k.addShadow(val)
}
+func (k *Key) addNestedValue(val string) error {
+ if k.isAutoIncrement || k.isBooleanType {
+ return errors.New("cannot add nested value to auto-increment or boolean key")
+ }
+
+ k.nestedValues = append(k.nestedValues, val)
+ return nil
+}
+
+func (k *Key) AddNestedValue(val string) error {
+ if !k.s.f.options.AllowNestedValues {
+ return errors.New("nested value is not allowed")
+ }
+ return k.addNestedValue(val)
+}
+
// ValueMapper represents a mapping function for values, e.g. os.ExpandEnv
type ValueMapper func(string) string
@@ -92,6 +110,12 @@ func (k *Key) ValueWithShadows() []string {
return vals
}
+// NestedValues returns nested values stored in the key.
+// It is possible returned value is nil if no nested values stored in the key.
+func (k *Key) NestedValues() []string {
+ return k.nestedValues
+}
+
// transformValue takes a raw value and transforms to its final string.
func (k *Key) transformValue(val string) string {
if k.s.f.ValueMapper != nil {
@@ -114,7 +138,7 @@ func (k *Key) transformValue(val string) string {
// Search in the same section.
nk, err := k.s.GetKey(noption)
- if err != nil {
+ if err != nil || k == nk {
// Search again in default section.
nk, _ = k.s.f.Section("").GetKey(noption)
}
diff --git a/vendor/github.com/go-ini/ini/key_test.go b/vendor/github.com/go-ini/ini/key_test.go
index 588efd429..a13ad95fa 100644
--- a/vendor/github.com/go-ini/ini/key_test.go
+++ b/vendor/github.com/go-ini/ini/key_test.go
@@ -15,6 +15,7 @@
package ini_test
import (
+ "bytes"
"fmt"
"strings"
"testing"
@@ -478,3 +479,45 @@ func TestKey_SetValue(t *testing.T) {
So(k.Value(), ShouldEqual, "ini.v1")
})
}
+
+func TestKey_NestedValues(t *testing.T) {
+ Convey("Read and write nested values", t, func() {
+ f, err := ini.LoadSources(ini.LoadOptions{
+ AllowNestedValues: true,
+ }, []byte(`
+aws_access_key_id = foo
+aws_secret_access_key = bar
+region = us-west-2
+s3 =
+ max_concurrent_requests=10
+ max_queue_size=1000`))
+ So(err, ShouldBeNil)
+ So(f, ShouldNotBeNil)
+
+ So(f.Section("").Key("s3").NestedValues(), ShouldResemble, []string{"max_concurrent_requests=10", "max_queue_size=1000"})
+
+ var buf bytes.Buffer
+ _, err = f.WriteTo(&buf)
+ So(err, ShouldBeNil)
+ So(buf.String(), ShouldEqual, `aws_access_key_id = foo
+aws_secret_access_key = bar
+region = us-west-2
+s3 =
+ max_concurrent_requests=10
+ max_queue_size=1000
+
+`)
+ })
+}
+
+func TestRecursiveValues(t *testing.T) {
+ Convey("Recursive values should not reflect on same key", t, func() {
+ f, err := ini.Load([]byte(`
+NAME = ini
+[package]
+NAME = %(NAME)s`))
+ So(err, ShouldBeNil)
+ So(f, ShouldNotBeNil)
+ So(f.Section("package").Key("NAME").String(), ShouldEqual, "ini")
+ })
+}
diff --git a/vendor/github.com/go-ini/ini/parser.go b/vendor/github.com/go-ini/ini/parser.go
index f8ac8026a..db3af8f00 100644
--- a/vendor/github.com/go-ini/ini/parser.go
+++ b/vendor/github.com/go-ini/ini/parser.go
@@ -193,7 +193,9 @@ func hasSurroundedQuote(in string, quote byte) bool {
strings.IndexByte(in[1:], quote) == len(in)-2
}
-func (p *parser) readValue(in []byte, ignoreContinuation, ignoreInlineComment, unescapeValueDoubleQuotes bool) (string, error) {
+func (p *parser) readValue(in []byte,
+ ignoreContinuation, ignoreInlineComment, unescapeValueDoubleQuotes, unescapeValueCommentSymbols bool) (string, error) {
+
line := strings.TrimLeftFunc(string(in), unicode.IsSpace)
if len(line) == 0 {
return "", nil
@@ -243,6 +245,13 @@ func (p *parser) readValue(in []byte, ignoreContinuation, ignoreInlineComment, u
if hasSurroundedQuote(line, '\'') ||
hasSurroundedQuote(line, '"') {
line = line[1 : len(line)-1]
+ } else if len(valQuote) == 0 && unescapeValueCommentSymbols {
+ if strings.Contains(line, `\;`) {
+ line = strings.Replace(line, `\;`, ";", -1)
+ }
+ if strings.Contains(line, `\#`) {
+ line = strings.Replace(line, `\#`, "#", -1)
+ }
}
return line, nil
}
@@ -261,6 +270,10 @@ func (f *File) parse(reader io.Reader) (err error) {
}
section, _ := f.NewSection(name)
+ // This "last" is not strictly equivalent to "previous one" if current key is not the first nested key
+ var isLastValueEmpty bool
+ var lastRegularKey *Key
+
var line []byte
var inUnparseableSection bool
for !p.isEOF {
@@ -269,6 +282,14 @@ func (f *File) parse(reader io.Reader) (err error) {
return err
}
+ if f.options.AllowNestedValues &&
+ isLastValueEmpty && len(line) > 0 {
+ if line[0] == ' ' || line[0] == '\t' {
+ lastRegularKey.addNestedValue(string(bytes.TrimSpace(line)))
+ continue
+ }
+ }
+
line = bytes.TrimLeftFunc(line, unicode.IsSpace)
if len(line) == 0 {
continue
@@ -333,7 +354,8 @@ func (f *File) parse(reader io.Reader) (err error) {
kname, err := p.readValue(line,
f.options.IgnoreContinuation,
f.options.IgnoreInlineComment,
- f.options.UnescapeValueDoubleQuotes)
+ f.options.UnescapeValueDoubleQuotes,
+ f.options.UnescapeValueCommentSymbols)
if err != nil {
return err
}
@@ -359,10 +381,12 @@ func (f *File) parse(reader io.Reader) (err error) {
value, err := p.readValue(line[offset:],
f.options.IgnoreContinuation,
f.options.IgnoreInlineComment,
- f.options.UnescapeValueDoubleQuotes)
+ f.options.UnescapeValueDoubleQuotes,
+ f.options.UnescapeValueCommentSymbols)
if err != nil {
return err
}
+ isLastValueEmpty = len(value) == 0
key, err := section.NewKey(kname, value)
if err != nil {
@@ -371,6 +395,7 @@ func (f *File) parse(reader io.Reader) (err error) {
key.isAutoIncrement = isAutoIncr
key.Comment = strings.TrimSpace(p.comment.String())
p.comment.Reset()
+ lastRegularKey = key
}
return nil
}
diff --git a/vendor/github.com/golang/protobuf/jsonpb/jsonpb.go b/vendor/github.com/golang/protobuf/jsonpb/jsonpb.go
index 110ae1384..dfdfc5b30 100644
--- a/vendor/github.com/golang/protobuf/jsonpb/jsonpb.go
+++ b/vendor/github.com/golang/protobuf/jsonpb/jsonpb.go
@@ -193,8 +193,7 @@ func (m *Marshaler) marshalObject(out *errWriter, v proto.Message, indent, typeU
// "Generated output always contains 3, 6, or 9 fractional digits,
// depending on required precision."
s, ns := s.Field(0).Int(), s.Field(1).Int()
- d := time.Duration(s)*time.Second + time.Duration(ns)*time.Nanosecond
- x := fmt.Sprintf("%.9f", d.Seconds())
+ x := fmt.Sprintf("%d.%09d", s, ns)
x = strings.TrimSuffix(x, "000")
x = strings.TrimSuffix(x, "000")
out.write(`"`)
diff --git a/vendor/github.com/golang/protobuf/jsonpb/jsonpb_test.go b/vendor/github.com/golang/protobuf/jsonpb/jsonpb_test.go
index 2428d0566..4fdbde15a 100644
--- a/vendor/github.com/golang/protobuf/jsonpb/jsonpb_test.go
+++ b/vendor/github.com/golang/protobuf/jsonpb/jsonpb_test.go
@@ -407,6 +407,7 @@ var marshalingTests = []struct {
{"Any with WKT", marshaler, anyWellKnown, anyWellKnownJSON},
{"Any with WKT and indent", marshalerAllOptions, anyWellKnown, anyWellKnownPrettyJSON},
{"Duration", marshaler, &pb.KnownTypes{Dur: &durpb.Duration{Seconds: 3}}, `{"dur":"3.000s"}`},
+ {"Duration", marshaler, &pb.KnownTypes{Dur: &durpb.Duration{Seconds: 100000000, Nanos: 1}}, `{"dur":"100000000.000000001s"}`},
{"Struct", marshaler, &pb.KnownTypes{St: &stpb.Struct{
Fields: map[string]*stpb.Value{
"one": {Kind: &stpb.Value_StringValue{"loneliest number"}},
diff --git a/vendor/github.com/hashicorp/go-multierror/.travis.yml b/vendor/github.com/hashicorp/go-multierror/.travis.yml
index 4b865d194..304a83595 100644
--- a/vendor/github.com/hashicorp/go-multierror/.travis.yml
+++ b/vendor/github.com/hashicorp/go-multierror/.travis.yml
@@ -3,7 +3,7 @@ sudo: false
language: go
go:
- - 1.6
+ - 1.x
branches:
only:
diff --git a/vendor/github.com/hashicorp/memberlist/memberlist.go b/vendor/github.com/hashicorp/memberlist/memberlist.go
index bdf333b43..e9084f9fd 100644
--- a/vendor/github.com/hashicorp/memberlist/memberlist.go
+++ b/vendor/github.com/hashicorp/memberlist/memberlist.go
@@ -639,7 +639,9 @@ func (m *Memberlist) Shutdown() error {
// Shut down the transport first, which should block until it's
// completely torn down. If we kill the memberlist-side handlers
// those I/O handlers might get stuck.
- m.transport.Shutdown()
+ if err := m.transport.Shutdown(); err != nil {
+ m.logger.Printf("[ERR] Failed to shutdown transport: %v", err)
+ }
// Now tear down everything else.
atomic.StoreInt32(&m.shutdown, 1)
diff --git a/vendor/github.com/hashicorp/memberlist/net.go b/vendor/github.com/hashicorp/memberlist/net.go
index 58e1fce20..a4330c4d2 100644
--- a/vendor/github.com/hashicorp/memberlist/net.go
+++ b/vendor/github.com/hashicorp/memberlist/net.go
@@ -1059,7 +1059,7 @@ func (m *Memberlist) readUserMsg(bufConn io.Reader, dec *codec.Decoder) error {
// operations, given the deadline. The bool return parameter is true if we
// we able to round trip a ping to the other node.
func (m *Memberlist) sendPingAndWaitForAck(addr string, ping ping, deadline time.Time) (bool, error) {
- conn, err := m.transport.DialTimeout(addr, m.config.TCPTimeout)
+ conn, err := m.transport.DialTimeout(addr, deadline.Sub(time.Now()))
if err != nil {
// If the node is actually dead we expect this to fail, so we
// shouldn't spam the logs with it. After this point, errors
diff --git a/vendor/github.com/hashicorp/memberlist/state.go b/vendor/github.com/hashicorp/memberlist/state.go
index 29fe5f1cf..f51692de0 100644
--- a/vendor/github.com/hashicorp/memberlist/state.go
+++ b/vendor/github.com/hashicorp/memberlist/state.go
@@ -251,10 +251,17 @@ func (m *Memberlist) probeNode(node *nodeState) {
nackCh := make(chan struct{}, m.config.IndirectChecks+1)
m.setProbeChannels(ping.SeqNo, ackCh, nackCh, probeInterval)
+ // Mark the sent time here, which should be after any pre-processing but
+ // before system calls to do the actual send. This probably over-reports
+ // a bit, but it's the best we can do. We had originally put this right
+ // after the I/O, but that would sometimes give negative RTT measurements
+ // which was not desirable.
+ sent := time.Now()
+
// Send a ping to the node. If this node looks like it's suspect or dead,
// also tack on a suspect message so that it has a chance to refute as
// soon as possible.
- deadline := time.Now().Add(probeInterval)
+ deadline := sent.Add(probeInterval)
addr := node.Address()
if node.State == stateAlive {
if err := m.encodeAndSendMsg(addr, pingMsg, &ping); err != nil {
@@ -284,11 +291,6 @@ func (m *Memberlist) probeNode(node *nodeState) {
}
}
- // Mark the sent time here, which should be after any pre-processing and
- // system calls to do the actual send. This probably under-reports a bit,
- // but it's the best we can do.
- sent := time.Now()
-
// Arrange for our self-awareness to get updated. At this point we've
// sent the ping, so any return statement means the probe succeeded
// which will improve our health until we get to the failure scenarios
diff --git a/vendor/github.com/hashicorp/memberlist/transport.go b/vendor/github.com/hashicorp/memberlist/transport.go
index ca0a66083..6ce55ea47 100644
--- a/vendor/github.com/hashicorp/memberlist/transport.go
+++ b/vendor/github.com/hashicorp/memberlist/transport.go
@@ -17,7 +17,7 @@ type Packet struct {
// Timestamp is the time when the packet was received. This should be
// taken as close as possible to the actual receipt time to help make an
- // accurate RTT measurements during probes.
+ // accurate RTT measurement during probes.
Timestamp time.Time
}
diff --git a/vendor/github.com/lib/pq/.travis.yml b/vendor/github.com/lib/pq/.travis.yml
index 01468f05c..4e34e8857 100644
--- a/vendor/github.com/lib/pq/.travis.yml
+++ b/vendor/github.com/lib/pq/.travis.yml
@@ -16,7 +16,7 @@ env:
- PQGOSSLTESTS=1
- PQSSLCERTTEST_PATH=$PWD/certs
- PGHOST=127.0.0.1
- - MEGACHECK_VERSION=2017.1
+ - MEGACHECK_VERSION=2017.2.1
matrix:
- PGVERSION=10
- PGVERSION=9.6
@@ -46,15 +46,13 @@ script:
- >
goimports -d -e $(find -name '*.go') | awk '{ print } END { exit NR == 0 ? 0 : 1 }'
- go vet ./...
- # For compatibility with Go 1.5, launch only if megacheck is present,
- # ignore SA1019 (deprecation warnings) in conn_test.go (we have to use the
- # deprecated driver.Execer and driver.Queryer interfaces) and S1024
- # (time.Until) everywhere.
+ # For compatibility with Go 1.5, launch only if megacheck is present.
- >
- which megacheck > /dev/null
- && megacheck -ignore 'github.com/lib/pq/conn_test.go:SA1019 github.com/lib/pq/*.go:S1024' ./...
+ which megacheck > /dev/null && megacheck -go 1.5 ./...
|| echo 'megacheck is not supported, skipping check'
# For compatibility with Go 1.5, launch only if golint is present.
- - which golint > /dev/null && golint ./... || echo 'golint is not supported, skipping check'
+ - >
+ which golint > /dev/null && golint ./...
+ || echo 'golint is not supported, skipping check'
- PQTEST_BINARY_PARAMETERS=no go test -race -v ./...
- PQTEST_BINARY_PARAMETERS=yes go test -race -v ./...
diff --git a/vendor/github.com/lib/pq/doc.go b/vendor/github.com/lib/pq/doc.go
index b2c3582c8..a1b029713 100644
--- a/vendor/github.com/lib/pq/doc.go
+++ b/vendor/github.com/lib/pq/doc.go
@@ -239,7 +239,7 @@ for more information). Note that the channel name will be truncated to 63
bytes by the PostgreSQL server.
You can find a complete, working example of Listener usage at
-http://godoc.org/github.com/lib/pq/examples/listen.
+http://godoc.org/github.com/lib/pq/example/listen.
*/
package pq
diff --git a/vendor/github.com/miekg/dns/.codecov.yml b/vendor/github.com/miekg/dns/.codecov.yml
new file mode 100644
index 000000000..f91e5c1fe
--- /dev/null
+++ b/vendor/github.com/miekg/dns/.codecov.yml
@@ -0,0 +1,8 @@
+coverage:
+ status:
+ project:
+ default:
+ target: 40%
+ threshold: null
+ patch: false
+ changes: false
diff --git a/vendor/github.com/miekg/dns/Gopkg.lock b/vendor/github.com/miekg/dns/Gopkg.lock
new file mode 100644
index 000000000..0c73a6444
--- /dev/null
+++ b/vendor/github.com/miekg/dns/Gopkg.lock
@@ -0,0 +1,21 @@
+# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
+
+
+[[projects]]
+ branch = "master"
+ name = "golang.org/x/crypto"
+ packages = ["ed25519","ed25519/internal/edwards25519"]
+ revision = "b080dc9a8c480b08e698fb1219160d598526310f"
+
+[[projects]]
+ branch = "master"
+ name = "golang.org/x/net"
+ packages = ["bpf","internal/iana","internal/socket","ipv4","ipv6"]
+ revision = "894f8ed5849b15b810ae41e9590a0d05395bba27"
+
+[solve-meta]
+ analyzer-name = "dep"
+ analyzer-version = 1
+ inputs-digest = "c4abc38abaeeeeb9be92455c9c02cae32841122b8982aaa067ef25bb8e86ff9d"
+ solver-name = "gps-cdcl"
+ solver-version = 1
diff --git a/vendor/github.com/miekg/dns/Gopkg.toml b/vendor/github.com/miekg/dns/Gopkg.toml
new file mode 100644
index 000000000..2f655b2c7
--- /dev/null
+++ b/vendor/github.com/miekg/dns/Gopkg.toml
@@ -0,0 +1,26 @@
+
+# Gopkg.toml example
+#
+# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
+# for detailed Gopkg.toml documentation.
+#
+# required = ["github.com/user/thing/cmd/thing"]
+# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
+#
+# [[constraint]]
+# name = "github.com/user/project"
+# version = "1.0.0"
+#
+# [[constraint]]
+# name = "github.com/user/project2"
+# branch = "dev"
+# source = "github.com/myfork/project2"
+#
+# [[override]]
+# name = "github.com/x/y"
+# version = "2.4.0"
+
+
+[[constraint]]
+ branch = "master"
+ name = "golang.org/x/crypto"
diff --git a/vendor/github.com/miekg/dns/Makefile.fuzz b/vendor/github.com/miekg/dns/Makefile.fuzz
new file mode 100644
index 000000000..dc158c4ac
--- /dev/null
+++ b/vendor/github.com/miekg/dns/Makefile.fuzz
@@ -0,0 +1,33 @@
+# Makefile for fuzzing
+#
+# Use go-fuzz and needs the tools installed.
+# See https://blog.cloudflare.com/dns-parser-meet-go-fuzzer/
+#
+# Installing go-fuzz:
+# $ make -f Makefile.fuzz get
+# Installs:
+# * github.com/dvyukov/go-fuzz/go-fuzz
+# * get github.com/dvyukov/go-fuzz/go-fuzz-build
+
+all: build
+
+.PHONY: build
+build:
+ go-fuzz-build -tags fuzz github.com/miekg/dns
+
+.PHONY: build-newrr
+build-newrr:
+ go-fuzz-build -func FuzzNewRR -tags fuzz github.com/miekg/dns
+
+.PHONY: fuzz
+fuzz:
+ go-fuzz -bin=dns-fuzz.zip -workdir=fuzz
+
+.PHONY: get
+get:
+ go get github.com/dvyukov/go-fuzz/go-fuzz
+ go get github.com/dvyukov/go-fuzz/go-fuzz-build
+
+.PHONY: clean
+clean:
+ rm *-fuzz.zip
diff --git a/vendor/github.com/miekg/dns/Makefile.release b/vendor/github.com/miekg/dns/Makefile.release
new file mode 100644
index 000000000..8fb748e8a
--- /dev/null
+++ b/vendor/github.com/miekg/dns/Makefile.release
@@ -0,0 +1,52 @@
+# Makefile for releasing.
+#
+# The release is controlled from version.go. The version found there is
+# used to tag the git repo, we're not building any artifects so there is nothing
+# to upload to github.
+#
+# * Up the version in version.go
+# * Run: make -f Makefile.release release
+# * will *commit* your change with 'Release $VERSION'
+# * push to github
+#
+
+define GO
+//+build ignore
+
+package main
+
+import (
+ "fmt"
+
+ "github.com/miekg/dns"
+)
+
+func main() {
+ fmt.Println(dns.Version.String())
+}
+endef
+
+$(file > version_release.go,$(GO))
+VERSION:=$(shell go run version_release.go)
+TAG="v$(VERSION)"
+
+all:
+ @echo Use the \'release\' target to start a release $(VERSION)
+ rm -f version_release.go
+
+.PHONY: release
+release: commit push
+ @echo Released $(VERSION)
+ rm -f version_release.go
+
+.PHONY: commit
+commit:
+ @echo Committing release $(VERSION)
+ git commit -am"Release $(VERSION)"
+ git tag $(TAG)
+
+.PHONY: push
+push:
+ @echo Pushing release $(VERSION) to master
+ git push --tags
+ git push
diff --git a/vendor/github.com/miekg/dns/README.md b/vendor/github.com/miekg/dns/README.md
index 94b54fe25..e6dbad25d 100644
--- a/vendor/github.com/miekg/dns/README.md
+++ b/vendor/github.com/miekg/dns/README.md
@@ -74,7 +74,7 @@ Send pull request if you want to be listed here.
* Parsing RRs ~ 100K RR/s, that's 5M records in about 50 seconds;
* Server side programming (mimicking the net/http package);
* Client side programming;
-* DNSSEC: signing, validating and key generation for DSA, RSA and ECDSA;
+* DNSSEC: signing, validating and key generation for DSA, RSA, ECDSA and Ed25519;
* EDNS0, NSID, Cookies;
* AXFR/IXFR;
* TSIG, SIG(0);
@@ -150,10 +150,13 @@ Example programs can be found in the `github.com/miekg/exdns` repository.
* 6975 - Algorithm Understanding in DNSSEC
* 7043 - EUI48/EUI64 records
* 7314 - DNS (EDNS) EXPIRE Option
+* 7477 - CSYNC RR
* 7828 - edns-tcp-keepalive EDNS0 Option
* 7553 - URI record
* 7858 - DNS over TLS: Initiation and Performance Considerations
+* 7871 - EDNS0 Client Subnet
* 7873 - Domain Name System (DNS) Cookies (draft-ietf-dnsop-cookies)
+* 8080 - EdDSA for DNSSEC
## Loosely based upon
diff --git a/vendor/github.com/miekg/dns/client.go b/vendor/github.com/miekg/dns/client.go
index 0914482ab..856b1698d 100644
--- a/vendor/github.com/miekg/dns/client.go
+++ b/vendor/github.com/miekg/dns/client.go
@@ -20,7 +20,7 @@ const tcpIdleTimeout time.Duration = 8 * time.Second
type Conn struct {
net.Conn // a net.Conn holding the connection
UDPSize uint16 // minimum receive buffer for UDP messages
- TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be fully qualified
+ TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2)
rtt time.Duration
t time.Time
tsigRequestMAC string
@@ -39,7 +39,7 @@ type Client struct {
DialTimeout time.Duration // net.DialTimeout, defaults to 2 seconds, or net.Dialer.Timeout if expiring earlier - overridden by Timeout when that value is non-zero
ReadTimeout time.Duration // net.Conn.SetReadTimeout value for connections, defaults to 2 seconds - overridden by Timeout when that value is non-zero
WriteTimeout time.Duration // net.Conn.SetWriteTimeout value for connections, defaults to 2 seconds - overridden by Timeout when that value is non-zero
- TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be fully qualified
+ TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2)
SingleInflight bool // if true suppress multiple outstanding queries for the same Qname, Qtype and Qclass
group singleflight
}
@@ -192,8 +192,10 @@ func (c *Client) exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err erro
}
// ReadMsg reads a message from the connection co.
-// If the received message contains a TSIG record the transaction
-// signature is verified.
+// If the received message contains a TSIG record the transaction signature
+// is verified. This method always tries to return the message, however if an
+// error is returned there are no guarantees that the returned message is a
+// valid representation of the packet read.
func (co *Conn) ReadMsg() (*Msg, error) {
p, err := co.ReadMsgHeader(nil)
if err != nil {
@@ -202,13 +204,10 @@ func (co *Conn) ReadMsg() (*Msg, error) {
m := new(Msg)
if err := m.Unpack(p); err != nil {
- // If ErrTruncated was returned, we still want to allow the user to use
+ // If an error was returned, we still want to allow the user to use
// the message, but naively they can just check err if they don't want
- // to use a truncated message
- if err == ErrTruncated {
- return m, err
- }
- return nil, err
+ // to use an erroneous message
+ return m, err
}
if t := m.IsTsig(); t != nil {
if _, ok := co.TsigSecret[t.Hdr.Name]; !ok {
diff --git a/vendor/github.com/miekg/dns/client_test.go b/vendor/github.com/miekg/dns/client_test.go
index ef977aefc..cc4198319 100644
--- a/vendor/github.com/miekg/dns/client_test.go
+++ b/vendor/github.com/miekg/dns/client_test.go
@@ -458,12 +458,12 @@ func TestTruncatedMsg(t *testing.T) {
t.Errorf("error should not be ErrTruncated from question cutoff unpack: %v", err)
}
- // Finally, if we only have the header, we should still return an error
+ // Finally, if we only have the header, we don't return an error.
buf1 = buf[:12]
r = new(Msg)
- if err = r.Unpack(buf1); err == nil || err != ErrTruncated {
- t.Errorf("error not ErrTruncated from header-only unpack: %v", err)
+ if err = r.Unpack(buf1); err != nil {
+ t.Errorf("from header-only unpack should not return an error: %v", err)
}
}
@@ -568,11 +568,11 @@ func TestConcurrentExchanges(t *testing.T) {
wg.Add(len(r))
for i := 0; i < len(r); i++ {
go func(i int) {
+ defer wg.Done()
r[i], _, _ = c.Exchange(m.Copy(), addrstr)
if r[i] == nil {
- t.Fatalf("response %d is nil", i)
+ t.Errorf("response %d is nil", i)
}
- wg.Done()
}(i)
}
select {
diff --git a/vendor/github.com/miekg/dns/clientconfig.go b/vendor/github.com/miekg/dns/clientconfig.go
index 6479fef93..a606ef696 100644
--- a/vendor/github.com/miekg/dns/clientconfig.go
+++ b/vendor/github.com/miekg/dns/clientconfig.go
@@ -79,8 +79,10 @@ func ClientConfigFromReader(resolvconf io.Reader) (*ClientConfig, error) {
switch {
case len(s) >= 6 && s[:6] == "ndots:":
n, _ := strconv.Atoi(s[6:])
- if n < 1 {
- n = 1
+ if n < 0 {
+ n = 0
+ } else if n > 15 {
+ n = 15
}
c.Ndots = n
case len(s) >= 8 && s[:8] == "timeout:":
diff --git a/vendor/github.com/miekg/dns/clientconfig_test.go b/vendor/github.com/miekg/dns/clientconfig_test.go
index 4c5d1fb60..5c10360d7 100644
--- a/vendor/github.com/miekg/dns/clientconfig_test.go
+++ b/vendor/github.com/miekg/dns/clientconfig_test.go
@@ -40,6 +40,28 @@ func testConfig(t *testing.T, data string) {
func TestNameserver(t *testing.T) { testConfig(t, normal) }
func TestMissingFinalNewLine(t *testing.T) { testConfig(t, missingNewline) }
+func TestNdots(t *testing.T) {
+ ndotsVariants := map[string]int{
+ "options ndots:0": 0,
+ "options ndots:1": 1,
+ "options ndots:15": 15,
+ "options ndots:16": 15,
+ "options ndots:-1": 0,
+ "": 1,
+ }
+
+ for data := range ndotsVariants {
+ cc, err := ClientConfigFromReader(strings.NewReader(data))
+ if err != nil {
+ t.Errorf("error parsing resolv.conf: %v", err)
+ }
+ if cc.Ndots != ndotsVariants[data] {
+ t.Errorf("Ndots not properly parsed: (Expected: %d / Was: %d)", ndotsVariants[data], cc.Ndots)
+ }
+ }
+
+}
+
func TestReadFromFile(t *testing.T) {
tempDir, err := ioutil.TempDir("", "")
if err != nil {
@@ -67,7 +89,7 @@ func TestReadFromFile(t *testing.T) {
}
}
-func TestNameList(t *testing.T) {
+func TestNameListNdots1(t *testing.T) {
cfg := ClientConfig{
Ndots: 1,
}
@@ -91,10 +113,18 @@ func TestNameList(t *testing.T) {
} else if names[1] != "miek.nl.test." {
t.Errorf("NameList didn't return search last: %v", names[1])
}
+}
+func TestNameListNdots2(t *testing.T) {
+ cfg := ClientConfig{
+ Ndots: 2,
+ }
- cfg.Ndots = 2
// Sent domain has less than NDots and search
- names = cfg.NameList("miek.nl")
+ cfg.Search = []string{
+ "test",
+ }
+ names := cfg.NameList("miek.nl")
+
if len(names) != 2 {
t.Errorf("NameList returned != 2 names: %v", names)
} else if names[0] != "miek.nl.test." {
@@ -103,3 +133,21 @@ func TestNameList(t *testing.T) {
t.Errorf("NameList didn't return sent domain last: %v", names[1])
}
}
+
+func TestNameListNdots0(t *testing.T) {
+ cfg := ClientConfig{
+ Ndots: 0,
+ }
+ cfg.Search = []string{
+ "test",
+ }
+ // Sent domain has less than NDots and search
+ names := cfg.NameList("miek")
+ if len(names) != 2 {
+ t.Errorf("NameList returned != 2 names: %v", names)
+ } else if names[0] != "miek." {
+ t.Errorf("NameList didn't return search first: %v", names[0])
+ } else if names[1] != "miek.test." {
+ t.Errorf("NameList didn't return sent domain last: %v", names[1])
+ }
+}
diff --git a/vendor/github.com/miekg/dns/compress_generate.go b/vendor/github.com/miekg/dns/compress_generate.go
index d2e5db26e..87fb36f68 100644
--- a/vendor/github.com/miekg/dns/compress_generate.go
+++ b/vendor/github.com/miekg/dns/compress_generate.go
@@ -18,8 +18,7 @@ import (
)
var packageHdr = `
-// *** DO NOT MODIFY ***
-// AUTOGENERATED BY go generate from compress_generate.go
+// Code generated by "go run compress_generate.go"; DO NOT EDIT.
package dns
diff --git a/vendor/github.com/miekg/dns/defaults.go b/vendor/github.com/miekg/dns/defaults.go
index c34890eec..14e18b0b3 100644
--- a/vendor/github.com/miekg/dns/defaults.go
+++ b/vendor/github.com/miekg/dns/defaults.go
@@ -273,8 +273,11 @@ func (t Type) String() string {
// String returns the string representation for the class c.
func (c Class) String() string {
- if c1, ok := ClassToString[uint16(c)]; ok {
- return c1
+ if s, ok := ClassToString[uint16(c)]; ok {
+ // Only emit mnemonics when they are unambiguous, specically ANY is in both.
+ if _, ok := StringToType[s]; !ok {
+ return s
+ }
}
return "CLASS" + strconv.Itoa(int(c))
}
diff --git a/vendor/github.com/miekg/dns/dns_test.go b/vendor/github.com/miekg/dns/dns_test.go
index 5835c13d5..feface4bf 100644
--- a/vendor/github.com/miekg/dns/dns_test.go
+++ b/vendor/github.com/miekg/dns/dns_test.go
@@ -1,6 +1,7 @@
package dns
import (
+ "bytes"
"encoding/hex"
"net"
"testing"
@@ -317,8 +318,9 @@ func TestNoRdataPack(t *testing.T) {
func TestNoRdataUnpack(t *testing.T) {
data := make([]byte, 1024)
for typ, fn := range TypeToRR {
- if typ == TypeSOA || typ == TypeTSIG {
+ if typ == TypeSOA || typ == TypeTSIG || typ == TypeTKEY {
// SOA, TSIG will not be seen (like this) in dyn. updates?
+ // TKEY requires length fields to be present for the Key and OtherData fields
continue
}
r := fn()
@@ -405,3 +407,60 @@ func TestMsgPackBuffer(t *testing.T) {
}
}
}
+
+// Make sure we can decode a TKEY packet from the string, modify the RR, and then pack it again.
+func TestTKEY(t *testing.T) {
+ // An example TKEY RR captured. There is no known accepted standard text format for a TKEY
+ // record so we do this from a hex string instead of from a text readable string.
+ tkeyStr := "0737362d6d732d370932322d3332633233332463303439663961662d633065612d313165372d363839362d6463333937396666656666640000f900ff0000000000d2086773732d747369670059fd01f359fe53730003000000b8a181b53081b2a0030a0100a10b06092a864882f712010202a2819d04819a60819706092a864886f71201020202006f8187308184a003020105a10302010fa2783076a003020112a26f046db29b1b1d2625da3b20b49dafef930dd1e9aad335e1c5f45dcd95e0005d67a1100f3e573d70506659dbed064553f1ab890f68f65ae10def0dad5b423b39f240ebe666f2886c5fe03819692d29182bbed87b83e1f9d16b7334ec16a3c4fc5ad4a990088e0be43f0c6957916f5fe60000"
+ tkeyBytes, err := hex.DecodeString(tkeyStr)
+ if err != nil {
+ t.Fatal("unable to decode TKEY string ", err)
+ }
+ // Decode the RR
+ rr, tkeyLen, unPackErr := UnpackRR(tkeyBytes, 0)
+ if unPackErr != nil {
+ t.Fatal("unable to decode TKEY RR", unPackErr)
+ }
+ // Make sure it's a TKEY record
+ if rr.Header().Rrtype != TypeTKEY {
+ t.Fatal("Unable to decode TKEY")
+ }
+ // Make sure we get back the same length
+ if rr.len() != len(tkeyBytes) {
+ t.Fatalf("Lengths don't match %d != %d", rr.len(), len(tkeyBytes))
+ }
+ // make space for it with some fudge room
+ msg := make([]byte, tkeyLen+1000)
+ offset, packErr := PackRR(rr, msg, 0, nil, false)
+ if packErr != nil {
+ t.Fatal("unable to pack TKEY RR", packErr)
+ }
+ if offset != len(tkeyBytes) {
+ t.Fatalf("mismatched TKEY RR size %d != %d", len(tkeyBytes), offset)
+ }
+ if bytes.Compare(tkeyBytes, msg[0:offset]) != 0 {
+ t.Fatal("mismatched TKEY data after rewriting bytes")
+ }
+ t.Logf("got TKEY of: " + rr.String())
+ // Now add some bytes to this and make sure we can encode OtherData properly
+ tkey := rr.(*TKEY)
+ tkey.OtherData = "abcd"
+ tkey.OtherLen = 2
+ offset, packErr = PackRR(tkey, msg, 0, nil, false)
+ if packErr != nil {
+ t.Fatal("unable to pack TKEY RR after modification", packErr)
+ }
+ if offset != (len(tkeyBytes) + 2) {
+ t.Fatalf("mismatched TKEY RR size %d != %d", offset, len(tkeyBytes)+2)
+ }
+ t.Logf("modified to TKEY of: " + rr.String())
+
+ // Make sure we can parse our string output
+ tkey.Hdr.Class = ClassINET // https://github.com/miekg/dns/issues/577
+ newRR, newError := NewRR(tkey.String())
+ if newError != nil {
+ t.Fatalf("unable to parse TKEY string: %s", newError)
+ }
+ t.Log("got reparsed TKEY of newRR: " + newRR.String())
+}
diff --git a/vendor/github.com/miekg/dns/dnssec.go b/vendor/github.com/miekg/dns/dnssec.go
index 3bd55388d..ac9fdd45e 100644
--- a/vendor/github.com/miekg/dns/dnssec.go
+++ b/vendor/github.com/miekg/dns/dnssec.go
@@ -19,6 +19,8 @@ import (
"sort"
"strings"
"time"
+
+ "golang.org/x/crypto/ed25519"
)
// DNSSEC encryption algorithm codes.
@@ -38,6 +40,8 @@ const (
ECCGOST
ECDSAP256SHA256
ECDSAP384SHA384
+ ED25519
+ ED448
INDIRECT uint8 = 252
PRIVATEDNS uint8 = 253 // Private (experimental keys)
PRIVATEOID uint8 = 254
@@ -56,6 +60,8 @@ var AlgorithmToString = map[uint8]string{
ECCGOST: "ECC-GOST",
ECDSAP256SHA256: "ECDSAP256SHA256",
ECDSAP384SHA384: "ECDSAP384SHA384",
+ ED25519: "ED25519",
+ ED448: "ED448",
INDIRECT: "INDIRECT",
PRIVATEDNS: "PRIVATEDNS",
PRIVATEOID: "PRIVATEOID",
@@ -73,6 +79,7 @@ var AlgorithmToHash = map[uint8]crypto.Hash{
ECDSAP256SHA256: crypto.SHA256,
ECDSAP384SHA384: crypto.SHA384,
RSASHA512: crypto.SHA512,
+ ED25519: crypto.Hash(0),
}
// DNSSEC hashing algorithm codes.
@@ -301,16 +308,32 @@ func (rr *RRSIG) Sign(k crypto.Signer, rrset []RR) error {
return ErrAlg
}
- h := hash.New()
- h.Write(signdata)
- h.Write(wire)
+ switch rr.Algorithm {
+ case ED25519:
+ // ed25519 signs the raw message and performs hashing internally.
+ // All other supported signature schemes operate over the pre-hashed
+ // message, and thus ed25519 must be handled separately here.
+ //
+ // The raw message is passed directly into sign and crypto.Hash(0) is
+ // used to signal to the crypto.Signer that the data has not been hashed.
+ signature, err := sign(k, append(signdata, wire...), crypto.Hash(0), rr.Algorithm)
+ if err != nil {
+ return err
+ }
- signature, err := sign(k, h.Sum(nil), hash, rr.Algorithm)
- if err != nil {
- return err
- }
+ rr.Signature = toBase64(signature)
+ default:
+ h := hash.New()
+ h.Write(signdata)
+ h.Write(wire)
+
+ signature, err := sign(k, h.Sum(nil), hash, rr.Algorithm)
+ if err != nil {
+ return err
+ }
- rr.Signature = toBase64(signature)
+ rr.Signature = toBase64(signature)
+ }
return nil
}
@@ -352,6 +375,9 @@ func sign(k crypto.Signer, hashed []byte, hash crypto.Hash, alg uint8) ([]byte,
// signature = append(signature, intToBytes(r1, 20)...)
// signature = append(signature, intToBytes(s1, 20)...)
// rr.Signature = signature
+
+ case ED25519:
+ return signature, nil
}
return nil, ErrAlg
@@ -456,6 +482,17 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
}
return ErrSig
+ case ED25519:
+ pubkey := k.publicKeyED25519()
+ if pubkey == nil {
+ return ErrKey
+ }
+
+ if ed25519.Verify(pubkey, append(signeddata, wire...), sigbuf) {
+ return nil
+ }
+ return ErrSig
+
default:
return ErrAlg
}
@@ -578,6 +615,17 @@ func (k *DNSKEY) publicKeyDSA() *dsa.PublicKey {
return pubkey
}
+func (k *DNSKEY) publicKeyED25519() ed25519.PublicKey {
+ keybuf, err := fromBase64([]byte(k.PublicKey))
+ if err != nil {
+ return nil
+ }
+ if len(keybuf) != ed25519.PublicKeySize {
+ return nil
+ }
+ return keybuf
+}
+
type wireSlice [][]byte
func (p wireSlice) Len() int { return len(p) }
@@ -615,6 +663,10 @@ func rawSignatureData(rrset []RR, s *RRSIG) (buf []byte, err error) {
switch x := r1.(type) {
case *NS:
x.Ns = strings.ToLower(x.Ns)
+ case *MD:
+ x.Md = strings.ToLower(x.Md)
+ case *MF:
+ x.Mf = strings.ToLower(x.Mf)
case *CNAME:
x.Target = strings.ToLower(x.Target)
case *SOA:
@@ -633,6 +685,18 @@ func rawSignatureData(rrset []RR, s *RRSIG) (buf []byte, err error) {
x.Email = strings.ToLower(x.Email)
case *MX:
x.Mx = strings.ToLower(x.Mx)
+ case *RP:
+ x.Mbox = strings.ToLower(x.Mbox)
+ x.Txt = strings.ToLower(x.Txt)
+ case *AFSDB:
+ x.Hostname = strings.ToLower(x.Hostname)
+ case *RT:
+ x.Host = strings.ToLower(x.Host)
+ case *SIG:
+ x.SignerName = strings.ToLower(x.SignerName)
+ case *PX:
+ x.Map822 = strings.ToLower(x.Map822)
+ x.Mapx400 = strings.ToLower(x.Mapx400)
case *NAPTR:
x.Replacement = strings.ToLower(x.Replacement)
case *KX:
diff --git a/vendor/github.com/miekg/dns/dnssec_keygen.go b/vendor/github.com/miekg/dns/dnssec_keygen.go
index 5e4b7741a..33e913ac5 100644
--- a/vendor/github.com/miekg/dns/dnssec_keygen.go
+++ b/vendor/github.com/miekg/dns/dnssec_keygen.go
@@ -8,6 +8,8 @@ import (
"crypto/rand"
"crypto/rsa"
"math/big"
+
+ "golang.org/x/crypto/ed25519"
)
// Generate generates a DNSKEY of the given bit size.
@@ -38,6 +40,10 @@ func (k *DNSKEY) Generate(bits int) (crypto.PrivateKey, error) {
if bits != 384 {
return nil, ErrKeySize
}
+ case ED25519:
+ if bits != 256 {
+ return nil, ErrKeySize
+ }
}
switch k.Algorithm {
@@ -75,6 +81,13 @@ func (k *DNSKEY) Generate(bits int) (crypto.PrivateKey, error) {
}
k.setPublicKeyECDSA(priv.PublicKey.X, priv.PublicKey.Y)
return priv, nil
+ case ED25519:
+ pub, priv, err := ed25519.GenerateKey(rand.Reader)
+ if err != nil {
+ return nil, err
+ }
+ k.setPublicKeyED25519(pub)
+ return priv, nil
default:
return nil, ErrAlg
}
@@ -117,6 +130,15 @@ func (k *DNSKEY) setPublicKeyDSA(_Q, _P, _G, _Y *big.Int) bool {
return true
}
+// Set the public key for Ed25519
+func (k *DNSKEY) setPublicKeyED25519(_K ed25519.PublicKey) bool {
+ if _K == nil {
+ return false
+ }
+ k.PublicKey = toBase64(_K)
+ return true
+}
+
// Set the public key (the values E and N) for RSA
// RFC 3110: Section 2. RSA Public KEY Resource Records
func exponentToBuf(_E int) []byte {
diff --git a/vendor/github.com/miekg/dns/dnssec_keyscan.go b/vendor/github.com/miekg/dns/dnssec_keyscan.go
index 4f8d830b8..e2d9d8f92 100644
--- a/vendor/github.com/miekg/dns/dnssec_keyscan.go
+++ b/vendor/github.com/miekg/dns/dnssec_keyscan.go
@@ -1,6 +1,7 @@
package dns
import (
+ "bytes"
"crypto"
"crypto/dsa"
"crypto/ecdsa"
@@ -9,6 +10,8 @@ import (
"math/big"
"strconv"
"strings"
+
+ "golang.org/x/crypto/ed25519"
)
// NewPrivateKey returns a PrivateKey by parsing the string s.
@@ -86,6 +89,8 @@ func (k *DNSKEY) ReadPrivateKey(q io.Reader, file string) (crypto.PrivateKey, er
}
priv.PublicKey = *pub
return priv, nil
+ case ED25519:
+ return readPrivateKeyED25519(m)
default:
return nil, ErrPrivKey
}
@@ -166,13 +171,56 @@ func readPrivateKeyECDSA(m map[string]string) (*ecdsa.PrivateKey, error) {
return p, nil
}
+func readPrivateKeyED25519(m map[string]string) (ed25519.PrivateKey, error) {
+ var p ed25519.PrivateKey
+ // TODO: validate that the required flags are present
+ for k, v := range m {
+ switch k {
+ case "privatekey":
+ p1, err := fromBase64([]byte(v))
+ if err != nil {
+ return nil, err
+ }
+ if len(p1) != 32 {
+ return nil, ErrPrivKey
+ }
+ // RFC 8080 and Golang's x/crypto/ed25519 differ as to how the
+ // private keys are represented. RFC 8080 specifies that private
+ // keys be stored solely as the seed value (p1 above) while the
+ // ed25519 package represents them as the seed value concatenated
+ // to the public key, which is derived from the seed value.
+ //
+ // ed25519.GenerateKey reads exactly 32 bytes from the passed in
+ // io.Reader and uses them as the seed. It also derives the
+ // public key and produces a compatible private key.
+ _, p, err = ed25519.GenerateKey(bytes.NewReader(p1))
+ if err != nil {
+ return nil, err
+ }
+ case "created", "publish", "activate":
+ /* not used in Go (yet) */
+ }
+ }
+ return p, nil
+}
+
// parseKey reads a private key from r. It returns a map[string]string,
// with the key-value pairs, or an error when the file is not correct.
func parseKey(r io.Reader, file string) (map[string]string, error) {
- s := scanInit(r)
+ s, cancel := scanInit(r)
m := make(map[string]string)
c := make(chan lex)
k := ""
+ defer func() {
+ cancel()
+ // zlexer can send up to two tokens, the next one and possibly 1 remainders.
+ // Do a non-blocking read.
+ _, ok := <-c
+ _, ok = <-c
+ if !ok {
+ // too bad
+ }
+ }()
// Start the lexer
go klexer(s, c)
for l := range c {
diff --git a/vendor/github.com/miekg/dns/dnssec_privkey.go b/vendor/github.com/miekg/dns/dnssec_privkey.go
index 56f3ea934..46f3215c8 100644
--- a/vendor/github.com/miekg/dns/dnssec_privkey.go
+++ b/vendor/github.com/miekg/dns/dnssec_privkey.go
@@ -7,6 +7,8 @@ import (
"crypto/rsa"
"math/big"
"strconv"
+
+ "golang.org/x/crypto/ed25519"
)
const format = "Private-key-format: v1.3\n"
@@ -79,6 +81,12 @@ func (r *DNSKEY) PrivateKeyString(p crypto.PrivateKey) string {
"Private_value(x): " + priv + "\n" +
"Public_value(y): " + pub + "\n"
+ case ed25519.PrivateKey:
+ private := toBase64(p[:32])
+ return format +
+ "Algorithm: " + algorithm + "\n" +
+ "PrivateKey: " + private + "\n"
+
default:
return ""
}
diff --git a/vendor/github.com/miekg/dns/dnssec_test.go b/vendor/github.com/miekg/dns/dnssec_test.go
index d5de439ba..7cf7c417a 100644
--- a/vendor/github.com/miekg/dns/dnssec_test.go
+++ b/vendor/github.com/miekg/dns/dnssec_test.go
@@ -8,6 +8,8 @@ import (
"strings"
"testing"
"time"
+
+ "golang.org/x/crypto/ed25519"
)
func getKey() *DNSKEY {
@@ -461,6 +463,55 @@ func TestSignVerifyECDSA2(t *testing.T) {
}
}
+func TestSignVerifyEd25519(t *testing.T) {
+ srv1, err := NewRR("srv.miek.nl. IN SRV 1000 800 0 web1.miek.nl.")
+ if err != nil {
+ t.Fatal(err)
+ }
+ srv := srv1.(*SRV)
+
+ // With this key
+ key := new(DNSKEY)
+ key.Hdr.Rrtype = TypeDNSKEY
+ key.Hdr.Name = "miek.nl."
+ key.Hdr.Class = ClassINET
+ key.Hdr.Ttl = 14400
+ key.Flags = 256
+ key.Protocol = 3
+ key.Algorithm = ED25519
+ privkey, err := key.Generate(256)
+ if err != nil {
+ t.Fatal("failure to generate key")
+ }
+
+ // Fill in the values of the Sig, before signing
+ sig := new(RRSIG)
+ sig.Hdr = RR_Header{"miek.nl.", TypeRRSIG, ClassINET, 14400, 0}
+ sig.TypeCovered = srv.Hdr.Rrtype
+ sig.Labels = uint8(CountLabel(srv.Hdr.Name)) // works for all 3
+ sig.OrigTtl = srv.Hdr.Ttl
+ sig.Expiration = 1296534305 // date -u '+%s' -d"2011-02-01 04:25:05"
+ sig.Inception = 1293942305 // date -u '+%s' -d"2011-01-02 04:25:05"
+ sig.KeyTag = key.KeyTag() // Get the keyfrom the Key
+ sig.SignerName = key.Hdr.Name
+ sig.Algorithm = ED25519
+
+ if sig.Sign(privkey.(ed25519.PrivateKey), []RR{srv}) != nil {
+ t.Fatal("failure to sign the record")
+ }
+
+ err = sig.Verify(key, []RR{srv})
+ if err != nil {
+ t.Logf("failure to validate:\n%s\n%s\n%s\n\n%s\n\n%v",
+ key.String(),
+ srv.String(),
+ sig.String(),
+ key.PrivateKeyString(privkey),
+ err,
+ )
+ }
+}
+
// Here the test vectors from the relevant RFCs are checked.
// rfc6605 6.1
func TestRFC6605P256(t *testing.T) {
@@ -590,6 +641,144 @@ PrivateKey: WURgWHCcYIYUPWgeLmiPY2DJJk02vgrmTfitxgqcL4vwW7BOrbawVmVe0d9V94SR`
}
}
+// rfc8080 6.1
+func TestRFC8080Ed25519Example1(t *testing.T) {
+ exDNSKEY := `example.com. 3600 IN DNSKEY 257 3 15 (
+ l02Woi0iS8Aa25FQkUd9RMzZHJpBoRQwAQEX1SxZJA4= )`
+ exPriv := `Private-key-format: v1.2
+Algorithm: 15 (ED25519)
+PrivateKey: ODIyNjAzODQ2MjgwODAxMjI2NDUxOTAyMDQxNDIyNjI=`
+ rrDNSKEY, err := NewRR(exDNSKEY)
+ if err != nil {
+ t.Fatal(err)
+ }
+ priv, err := rrDNSKEY.(*DNSKEY).NewPrivateKey(exPriv)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ exDS := `example.com. 3600 IN DS 3613 15 2 (
+ 3aa5ab37efce57f737fc1627013fee07bdf241bd10f3b1964ab55c78e79
+ a304b )`
+ rrDS, err := NewRR(exDS)
+ if err != nil {
+ t.Fatal(err)
+ }
+ ourDS := rrDNSKEY.(*DNSKEY).ToDS(SHA256)
+ if !reflect.DeepEqual(ourDS, rrDS.(*DS)) {
+ t.Fatalf("DS record differs:\n%v\n%v", ourDS, rrDS.(*DS))
+ }
+
+ exMX := `example.com. 3600 IN MX 10 mail.example.com.`
+ exRRSIG := `example.com. 3600 IN RRSIG MX 15 2 3600 (
+ 1440021600 1438207200 3613 example.com. (
+ oL9krJun7xfBOIWcGHi7mag5/hdZrKWw15jPGrHpjQeRAvTdszaPD+QLs3f
+ x8A4M3e23mRZ9VrbpMngwcrqNAg== ) )`
+ rrMX, err := NewRR(exMX)
+ if err != nil {
+ t.Fatal(err)
+ }
+ rrRRSIG, err := NewRR(exRRSIG)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err = rrRRSIG.(*RRSIG).Verify(rrDNSKEY.(*DNSKEY), []RR{rrMX}); err != nil {
+ t.Errorf("failure to validate the spec RRSIG: %v", err)
+ }
+
+ ourRRSIG := &RRSIG{
+ Hdr: RR_Header{
+ Ttl: rrMX.Header().Ttl,
+ },
+ KeyTag: rrDNSKEY.(*DNSKEY).KeyTag(),
+ SignerName: rrDNSKEY.(*DNSKEY).Hdr.Name,
+ Algorithm: rrDNSKEY.(*DNSKEY).Algorithm,
+ }
+ ourRRSIG.Expiration, _ = StringToTime("20150819220000")
+ ourRRSIG.Inception, _ = StringToTime("20150729220000")
+ err = ourRRSIG.Sign(priv.(ed25519.PrivateKey), []RR{rrMX})
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if err = ourRRSIG.Verify(rrDNSKEY.(*DNSKEY), []RR{rrMX}); err != nil {
+ t.Errorf("failure to validate our RRSIG: %v", err)
+ }
+
+ if !reflect.DeepEqual(ourRRSIG, rrRRSIG.(*RRSIG)) {
+ t.Fatalf("RRSIG record differs:\n%v\n%v", ourRRSIG, rrRRSIG.(*RRSIG))
+ }
+}
+
+// rfc8080 6.1
+func TestRFC8080Ed25519Example2(t *testing.T) {
+ exDNSKEY := `example.com. 3600 IN DNSKEY 257 3 15 (
+ zPnZ/QwEe7S8C5SPz2OfS5RR40ATk2/rYnE9xHIEijs= )`
+ exPriv := `Private-key-format: v1.2
+Algorithm: 15 (ED25519)
+PrivateKey: DSSF3o0s0f+ElWzj9E/Osxw8hLpk55chkmx0LYN5WiY=`
+ rrDNSKEY, err := NewRR(exDNSKEY)
+ if err != nil {
+ t.Fatal(err)
+ }
+ priv, err := rrDNSKEY.(*DNSKEY).NewPrivateKey(exPriv)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ exDS := `example.com. 3600 IN DS 35217 15 2 (
+ 401781b934e392de492ec77ae2e15d70f6575a1c0bc59c5275c04ebe80c
+ 6614c )`
+ rrDS, err := NewRR(exDS)
+ if err != nil {
+ t.Fatal(err)
+ }
+ ourDS := rrDNSKEY.(*DNSKEY).ToDS(SHA256)
+ if !reflect.DeepEqual(ourDS, rrDS.(*DS)) {
+ t.Fatalf("DS record differs:\n%v\n%v", ourDS, rrDS.(*DS))
+ }
+
+ exMX := `example.com. 3600 IN MX 10 mail.example.com.`
+ exRRSIG := `example.com. 3600 IN RRSIG MX 15 2 3600 (
+ 1440021600 1438207200 35217 example.com. (
+ zXQ0bkYgQTEFyfLyi9QoiY6D8ZdYo4wyUhVioYZXFdT410QPRITQSqJSnzQ
+ oSm5poJ7gD7AQR0O7KuI5k2pcBg== ) )`
+ rrMX, err := NewRR(exMX)
+ if err != nil {
+ t.Fatal(err)
+ }
+ rrRRSIG, err := NewRR(exRRSIG)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err = rrRRSIG.(*RRSIG).Verify(rrDNSKEY.(*DNSKEY), []RR{rrMX}); err != nil {
+ t.Errorf("failure to validate the spec RRSIG: %v", err)
+ }
+
+ ourRRSIG := &RRSIG{
+ Hdr: RR_Header{
+ Ttl: rrMX.Header().Ttl,
+ },
+ KeyTag: rrDNSKEY.(*DNSKEY).KeyTag(),
+ SignerName: rrDNSKEY.(*DNSKEY).Hdr.Name,
+ Algorithm: rrDNSKEY.(*DNSKEY).Algorithm,
+ }
+ ourRRSIG.Expiration, _ = StringToTime("20150819220000")
+ ourRRSIG.Inception, _ = StringToTime("20150729220000")
+ err = ourRRSIG.Sign(priv.(ed25519.PrivateKey), []RR{rrMX})
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if err = ourRRSIG.Verify(rrDNSKEY.(*DNSKEY), []RR{rrMX}); err != nil {
+ t.Errorf("failure to validate our RRSIG: %v", err)
+ }
+
+ if !reflect.DeepEqual(ourRRSIG, rrRRSIG.(*RRSIG)) {
+ t.Fatalf("RRSIG record differs:\n%v\n%v", ourRRSIG, rrRRSIG.(*RRSIG))
+ }
+}
+
func TestInvalidRRSet(t *testing.T) {
goodRecords := make([]RR, 2)
goodRecords[0] = &TXT{Hdr: RR_Header{Name: "name.cloudflare.com.", Rrtype: TypeTXT, Class: ClassINET, Ttl: 0}, Txt: []string{"Hello world"}}
diff --git a/vendor/github.com/miekg/dns/doc.go b/vendor/github.com/miekg/dns/doc.go
index 26e288dfe..1d8114744 100644
--- a/vendor/github.com/miekg/dns/doc.go
+++ b/vendor/github.com/miekg/dns/doc.go
@@ -63,7 +63,7 @@ class) is as easy as setting:
c.SingleInflight = true
-More advanced options are availabe using a net.Dialer and the corresponding API.
+More advanced options are available using a net.Dialer and the corresponding API.
For example it is possible to set a timeout, or to specify a source IP address
and port to use for the connection:
diff --git a/vendor/github.com/miekg/dns/edns.go b/vendor/github.com/miekg/dns/edns.go
index a6a36bdf2..6f9d2ea39 100644
--- a/vendor/github.com/miekg/dns/edns.go
+++ b/vendor/github.com/miekg/dns/edns.go
@@ -13,19 +13,18 @@ import (
const (
EDNS0LLQ = 0x1 // long lived queries: http://tools.ietf.org/html/draft-sekar-dns-llq-01
EDNS0UL = 0x2 // update lease draft: http://files.dns-sd.org/draft-sekar-dns-ul.txt
- EDNS0NSID = 0x3 // nsid (RFC5001)
+ EDNS0NSID = 0x3 // nsid (See RFC 5001)
EDNS0DAU = 0x5 // DNSSEC Algorithm Understood
EDNS0DHU = 0x6 // DS Hash Understood
EDNS0N3U = 0x7 // NSEC3 Hash Understood
- EDNS0SUBNET = 0x8 // client-subnet (RFC6891)
+ EDNS0SUBNET = 0x8 // client-subnet (See RFC 7871)
EDNS0EXPIRE = 0x9 // EDNS0 expire
EDNS0COOKIE = 0xa // EDNS0 Cookie
- EDNS0TCPKEEPALIVE = 0xb // EDNS0 tcp keep alive (RFC7828)
- EDNS0PADDING = 0xc // EDNS0 padding (RFC7830)
- EDNS0SUBNETDRAFT = 0x50fa // Don't use! Use EDNS0SUBNET
- EDNS0LOCALSTART = 0xFDE9 // Beginning of range reserved for local/experimental use (RFC6891)
- EDNS0LOCALEND = 0xFFFE // End of range reserved for local/experimental use (RFC6891)
- _DO = 1 << 15 // dnssec ok
+ EDNS0TCPKEEPALIVE = 0xb // EDNS0 tcp keep alive (See RFC 7828)
+ EDNS0PADDING = 0xc // EDNS0 padding (See RFC 7830)
+ EDNS0LOCALSTART = 0xFDE9 // Beginning of range reserved for local/experimental use (See RFC 6891)
+ EDNS0LOCALEND = 0xFFFE // End of range reserved for local/experimental use (See RFC 6891)
+ _DO = 1 << 15 // DNSSEC OK
)
// OPT is the EDNS0 RR appended to messages to convey extra (meta) information.
@@ -58,9 +57,6 @@ func (rr *OPT) String() string {
}
case *EDNS0_SUBNET:
s += "\n; SUBNET: " + o.String()
- if o.(*EDNS0_SUBNET).DraftOption {
- s += " (draft)"
- }
case *EDNS0_COOKIE:
s += "\n; COOKIE: " + o.String()
case *EDNS0_UL:
@@ -188,7 +184,7 @@ func (e *EDNS0_NSID) unpack(b []byte) error { e.Nsid = hex.EncodeToString(b); re
func (e *EDNS0_NSID) String() string { return string(e.Nsid) }
// EDNS0_SUBNET is the subnet option that is used to give the remote nameserver
-// an idea of where the client lives. It can then give back a different
+// an idea of where the client lives. See RFC 7871. It can then give back a different
// answer depending on the location or network topology.
// Basic use pattern for creating an subnet option:
//
@@ -204,26 +200,19 @@ func (e *EDNS0_NSID) String() string { return string(e.Nsid) }
// // e.Address = net.ParseIP("2001:7b8:32a::2") // for IPV6
// o.Option = append(o.Option, e)
//
-// Note: the spec (draft-ietf-dnsop-edns-client-subnet-00) has some insane logic
-// for which netmask applies to the address. This code will parse all the
-// available bits when unpacking (up to optlen). When packing it will apply
-// SourceNetmask. If you need more advanced logic, patches welcome and good luck.
+// This code will parse all the available bits when unpacking (up to optlen).
+// When packing it will apply SourceNetmask. If you need more advanced logic,
+// patches welcome and good luck.
type EDNS0_SUBNET struct {
Code uint16 // Always EDNS0SUBNET
Family uint16 // 1 for IP, 2 for IP6
SourceNetmask uint8
SourceScope uint8
Address net.IP
- DraftOption bool // Set to true if using the old (0x50fa) option code
}
// Option implements the EDNS0 interface.
-func (e *EDNS0_SUBNET) Option() uint16 {
- if e.DraftOption {
- return EDNS0SUBNETDRAFT
- }
- return EDNS0SUBNET
-}
+func (e *EDNS0_SUBNET) Option() uint16 { return EDNS0SUBNET }
func (e *EDNS0_SUBNET) pack() ([]byte, error) {
b := make([]byte, 4)
@@ -431,6 +420,7 @@ func (e *EDNS0_LLQ) String() string {
return s
}
+// EDNS0_DUA implements the EDNS0 "DNSSEC Algorithm Understood" option. See RFC 6975.
type EDNS0_DAU struct {
Code uint16 // Always EDNS0DAU
AlgCode []uint8
@@ -453,6 +443,7 @@ func (e *EDNS0_DAU) String() string {
return s
}
+// EDNS0_DHU implements the EDNS0 "DS Hash Understood" option. See RFC 6975.
type EDNS0_DHU struct {
Code uint16 // Always EDNS0DHU
AlgCode []uint8
@@ -475,6 +466,7 @@ func (e *EDNS0_DHU) String() string {
return s
}
+// EDNS0_N3U implements the EDNS0 "NSEC3 Hash Understood" option. See RFC 6975.
type EDNS0_N3U struct {
Code uint16 // Always EDNS0N3U
AlgCode []uint8
@@ -498,6 +490,7 @@ func (e *EDNS0_N3U) String() string {
return s
}
+// EDNS0_EXPIRE implementes the EDNS0 option as described in RFC 7314.
type EDNS0_EXPIRE struct {
Code uint16 // Always EDNS0EXPIRE
Expire uint32
diff --git a/vendor/github.com/miekg/dns/fuzz.go b/vendor/github.com/miekg/dns/fuzz.go
new file mode 100644
index 000000000..a8a09184d
--- /dev/null
+++ b/vendor/github.com/miekg/dns/fuzz.go
@@ -0,0 +1,23 @@
+// +build fuzz
+
+package dns
+
+func Fuzz(data []byte) int {
+ msg := new(Msg)
+
+ if err := msg.Unpack(data); err != nil {
+ return 0
+ }
+ if _, err := msg.Pack(); err != nil {
+ return 0
+ }
+
+ return 1
+}
+
+func FuzzNewRR(data []byte) int {
+ if _, err := NewRR(string(data)); err != nil {
+ return 0
+ }
+ return 1
+}
diff --git a/vendor/github.com/miekg/dns/fuzz_test.go b/vendor/github.com/miekg/dns/fuzz_test.go
deleted file mode 100644
index 255869730..000000000
--- a/vendor/github.com/miekg/dns/fuzz_test.go
+++ /dev/null
@@ -1,25 +0,0 @@
-package dns
-
-import "testing"
-
-func TestFuzzString(t *testing.T) {
- testcases := []string{"", " MINFO ", " RP ", " NSEC 0 0", " \" NSEC 0 0\"", " \" MINFO \"",
- ";a ", ";a����������",
- " NSAP O ", " NSAP N ",
- " TYPE4 TYPE6a789a3bc0045c8a5fb42c7d1bd998f5444 IN 9579b47d46817afbd17273e6",
- " TYPE45 3 3 4147994 TYPE\\(\\)\\)\\(\\)\\(\\(\\)\\(\\)\\)\\)\\(\\)\\(\\)\\(\\(\\R 948\"\")\\(\\)\\)\\)\\(\\ ",
- "$GENERATE 0-3 ${441189,5039418474430,o}",
- "$INCLUDE 00 TYPE00000000000n ",
- "$INCLUDE PE4 TYPE061463623/727071511 \\(\\)\\$GENERATE 6-462/0",
- }
- for i, tc := range testcases {
- rr, err := NewRR(tc)
- if err == nil {
- // rr can be nil because we can (for instance) just parse a comment
- if rr == nil {
- continue
- }
- t.Fatalf("parsed mailformed RR %d: %s", i, rr.String())
- }
- }
-}
diff --git a/vendor/github.com/miekg/dns/idn/code_points.go b/vendor/github.com/miekg/dns/idn/code_points.go
deleted file mode 100644
index 129c3742f..000000000
--- a/vendor/github.com/miekg/dns/idn/code_points.go
+++ /dev/null
@@ -1,2346 +0,0 @@
-package idn
-
-const (
- propertyUnknown property = iota // unknown character property
- propertyPVALID // allowed to be used in IDNs
- propertyCONTEXTJ // invisible or problematic characters (join controls)
- propertyCONTEXTO // invisible or problematic characters (others)
- propertyDISALLOWED // should not be included in IDNs
- propertyUNASSIGNED // code points that are not designated in the Unicode Standard
-)
-
-// property stores the property of a code point, as described in RFC 5892,
-// section 1
-type property int
-
-// codePoints list all code points in Unicode Character Database (UCD) Format
-// according to RFC 5892, appendix B.1. Thanks to libidn2 (GNU) -
-// http://www.gnu.org/software/libidn/libidn2/
-var codePoints = []struct {
- start rune
- end rune
- state property
-}{
- {0x0000, 0x002C, propertyDISALLOWED}, // <control>..COMMA
- {0x002D, 0x0, propertyPVALID}, // HYPHEN-MINUS
- {0x002E, 0x002F, propertyDISALLOWED}, // FULL STOP..SOLIDUS
- {0x0030, 0x0039, propertyPVALID}, // DIGIT ZERO..DIGIT NINE
- {0x003A, 0x0060, propertyDISALLOWED}, // COLON..GRAVE ACCENT
- {0x0041, 0x005A, propertyPVALID}, // LATIN CAPITAL LETTER A..LATIN CAPITAL LETTER Z
- {0x0061, 0x007A, propertyPVALID}, // LATIN SMALL LETTER A..LATIN SMALL LETTER Z
- {0x007B, 0x00B6, propertyDISALLOWED}, // LEFT CURLY BRACKET..PILCROW SIGN
- {0x00B7, 0x0, propertyCONTEXTO}, // MIDDLE DOT
- {0x00B8, 0x00DE, propertyDISALLOWED}, // CEDILLA..LATIN CAPITAL LETTER THORN
- {0x00DF, 0x00F6, propertyPVALID}, // LATIN SMALL LETTER SHARP S..LATIN SMALL LETT
- {0x00F7, 0x0, propertyDISALLOWED}, // DIVISION SIGN
- {0x00F8, 0x00FF, propertyPVALID}, // LATIN SMALL LETTER O WITH STROKE..LATIN SMAL
- {0x0100, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER A WITH MACRON
- {0x0101, 0x0, propertyPVALID}, // LATIN SMALL LETTER A WITH MACRON
- {0x0102, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER A WITH BREVE
- {0x0103, 0x0, propertyPVALID}, // LATIN SMALL LETTER A WITH BREVE
- {0x0104, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER A WITH OGONEK
- {0x0105, 0x0, propertyPVALID}, // LATIN SMALL LETTER A WITH OGONEK
- {0x0106, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER C WITH ACUTE
- {0x0107, 0x0, propertyPVALID}, // LATIN SMALL LETTER C WITH ACUTE
- {0x0108, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER C WITH CIRCUMFLEX
- {0x0109, 0x0, propertyPVALID}, // LATIN SMALL LETTER C WITH CIRCUMFLEX
- {0x010A, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER C WITH DOT ABOVE
- {0x010B, 0x0, propertyPVALID}, // LATIN SMALL LETTER C WITH DOT ABOVE
- {0x010C, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER C WITH CARON
- {0x010D, 0x0, propertyPVALID}, // LATIN SMALL LETTER C WITH CARON
- {0x010E, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER D WITH CARON
- {0x010F, 0x0, propertyPVALID}, // LATIN SMALL LETTER D WITH CARON
- {0x0110, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER D WITH STROKE
- {0x0111, 0x0, propertyPVALID}, // LATIN SMALL LETTER D WITH STROKE
- {0x0112, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER E WITH MACRON
- {0x0113, 0x0, propertyPVALID}, // LATIN SMALL LETTER E WITH MACRON
- {0x0114, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER E WITH BREVE
- {0x0115, 0x0, propertyPVALID}, // LATIN SMALL LETTER E WITH BREVE
- {0x0116, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER E WITH DOT ABOVE
- {0x0117, 0x0, propertyPVALID}, // LATIN SMALL LETTER E WITH DOT ABOVE
- {0x0118, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER E WITH OGONEK
- {0x0119, 0x0, propertyPVALID}, // LATIN SMALL LETTER E WITH OGONEK
- {0x011A, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER E WITH CARON
- {0x011B, 0x0, propertyPVALID}, // LATIN SMALL LETTER E WITH CARON
- {0x011C, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER G WITH CIRCUMFLEX
- {0x011D, 0x0, propertyPVALID}, // LATIN SMALL LETTER G WITH CIRCUMFLEX
- {0x011E, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER G WITH BREVE
- {0x011F, 0x0, propertyPVALID}, // LATIN SMALL LETTER G WITH BREVE
- {0x0120, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER G WITH DOT ABOVE
- {0x0121, 0x0, propertyPVALID}, // LATIN SMALL LETTER G WITH DOT ABOVE
- {0x0122, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER G WITH CEDILLA
- {0x0123, 0x0, propertyPVALID}, // LATIN SMALL LETTER G WITH CEDILLA
- {0x0124, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER H WITH CIRCUMFLEX
- {0x0125, 0x0, propertyPVALID}, // LATIN SMALL LETTER H WITH CIRCUMFLEX
- {0x0126, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER H WITH STROKE
- {0x0127, 0x0, propertyPVALID}, // LATIN SMALL LETTER H WITH STROKE
- {0x0128, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER I WITH TILDE
- {0x0129, 0x0, propertyPVALID}, // LATIN SMALL LETTER I WITH TILDE
- {0x012A, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER I WITH MACRON
- {0x012B, 0x0, propertyPVALID}, // LATIN SMALL LETTER I WITH MACRON
- {0x012C, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER I WITH BREVE
- {0x012D, 0x0, propertyPVALID}, // LATIN SMALL LETTER I WITH BREVE
- {0x012E, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER I WITH OGONEK
- {0x012F, 0x0, propertyPVALID}, // LATIN SMALL LETTER I WITH OGONEK
- {0x0130, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER I WITH DOT ABOVE
- {0x0131, 0x0, propertyPVALID}, // LATIN SMALL LETTER DOTLESS I
- {0x0132, 0x0134, propertyDISALLOWED}, // LATIN CAPITAL LIGATURE IJ..LATIN CAPITAL LET
- {0x0135, 0x0, propertyPVALID}, // LATIN SMALL LETTER J WITH CIRCUMFLEX
- {0x0136, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER K WITH CEDILLA
- {0x0137, 0x0138, propertyPVALID}, // LATIN SMALL LETTER K WITH CEDILLA..LATIN SMA
- {0x0139, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER L WITH ACUTE
- {0x013A, 0x0, propertyPVALID}, // LATIN SMALL LETTER L WITH ACUTE
- {0x013B, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER L WITH CEDILLA
- {0x013C, 0x0, propertyPVALID}, // LATIN SMALL LETTER L WITH CEDILLA
- {0x013D, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER L WITH CARON
- {0x013E, 0x0, propertyPVALID}, // LATIN SMALL LETTER L WITH CARON
- {0x013F, 0x0141, propertyDISALLOWED}, // LATIN CAPITAL LETTER L WITH MIDDLE DOT..LATI
- {0x0142, 0x0, propertyPVALID}, // LATIN SMALL LETTER L WITH STROKE
- {0x0143, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER N WITH ACUTE
- {0x0144, 0x0, propertyPVALID}, // LATIN SMALL LETTER N WITH ACUTE
- {0x0145, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER N WITH CEDILLA
- {0x0146, 0x0, propertyPVALID}, // LATIN SMALL LETTER N WITH CEDILLA
- {0x0147, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER N WITH CARON
- {0x0148, 0x0, propertyPVALID}, // LATIN SMALL LETTER N WITH CARON
- {0x0149, 0x014A, propertyDISALLOWED}, // LATIN SMALL LETTER N PRECEDED BY APOSTROPHE.
- {0x014B, 0x0, propertyPVALID}, // LATIN SMALL LETTER ENG
- {0x014C, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER O WITH MACRON
- {0x014D, 0x0, propertyPVALID}, // LATIN SMALL LETTER O WITH MACRON
- {0x014E, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER O WITH BREVE
- {0x014F, 0x0, propertyPVALID}, // LATIN SMALL LETTER O WITH BREVE
- {0x0150, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER O WITH DOUBLE ACUTE
- {0x0151, 0x0, propertyPVALID}, // LATIN SMALL LETTER O WITH DOUBLE ACUTE
- {0x0152, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LIGATURE OE
- {0x0153, 0x0, propertyPVALID}, // LATIN SMALL LIGATURE OE
- {0x0154, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER R WITH ACUTE
- {0x0155, 0x0, propertyPVALID}, // LATIN SMALL LETTER R WITH ACUTE
- {0x0156, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER R WITH CEDILLA
- {0x0157, 0x0, propertyPVALID}, // LATIN SMALL LETTER R WITH CEDILLA
- {0x0158, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER R WITH CARON
- {0x0159, 0x0, propertyPVALID}, // LATIN SMALL LETTER R WITH CARON
- {0x015A, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER S WITH ACUTE
- {0x015B, 0x0, propertyPVALID}, // LATIN SMALL LETTER S WITH ACUTE
- {0x015C, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER S WITH CIRCUMFLEX
- {0x015D, 0x0, propertyPVALID}, // LATIN SMALL LETTER S WITH CIRCUMFLEX
- {0x015E, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER S WITH CEDILLA
- {0x015F, 0x0, propertyPVALID}, // LATIN SMALL LETTER S WITH CEDILLA
- {0x0160, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER S WITH CARON
- {0x0161, 0x0, propertyPVALID}, // LATIN SMALL LETTER S WITH CARON
- {0x0162, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER T WITH CEDILLA
- {0x0163, 0x0, propertyPVALID}, // LATIN SMALL LETTER T WITH CEDILLA
- {0x0164, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER T WITH CARON
- {0x0165, 0x0, propertyPVALID}, // LATIN SMALL LETTER T WITH CARON
- {0x0166, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER T WITH STROKE
- {0x0167, 0x0, propertyPVALID}, // LATIN SMALL LETTER T WITH STROKE
- {0x0168, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER U WITH TILDE
- {0x0169, 0x0, propertyPVALID}, // LATIN SMALL LETTER U WITH TILDE
- {0x016A, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER U WITH MACRON
- {0x016B, 0x0, propertyPVALID}, // LATIN SMALL LETTER U WITH MACRON
- {0x016C, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER U WITH BREVE
- {0x016D, 0x0, propertyPVALID}, // LATIN SMALL LETTER U WITH BREVE
- {0x016E, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER U WITH RING ABOVE
- {0x016F, 0x0, propertyPVALID}, // LATIN SMALL LETTER U WITH RING ABOVE
- {0x0170, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER U WITH DOUBLE ACUTE
- {0x0171, 0x0, propertyPVALID}, // LATIN SMALL LETTER U WITH DOUBLE ACUTE
- {0x0172, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER U WITH OGONEK
- {0x0173, 0x0, propertyPVALID}, // LATIN SMALL LETTER U WITH OGONEK
- {0x0174, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER W WITH CIRCUMFLEX
- {0x0175, 0x0, propertyPVALID}, // LATIN SMALL LETTER W WITH CIRCUMFLEX
- {0x0176, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER Y WITH CIRCUMFLEX
- {0x0177, 0x0, propertyPVALID}, // LATIN SMALL LETTER Y WITH CIRCUMFLEX
- {0x0178, 0x0179, propertyDISALLOWED}, // LATIN CAPITAL LETTER Y WITH DIAERESIS..LATIN
- {0x017A, 0x0, propertyPVALID}, // LATIN SMALL LETTER Z WITH ACUTE
- {0x017B, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER Z WITH DOT ABOVE
- {0x017C, 0x0, propertyPVALID}, // LATIN SMALL LETTER Z WITH DOT ABOVE
- {0x017D, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER Z WITH CARON
- {0x017E, 0x0, propertyPVALID}, // LATIN SMALL LETTER Z WITH CARON
- {0x017F, 0x0, propertyDISALLOWED}, // LATIN SMALL LETTER LONG S
- {0x0180, 0x0, propertyPVALID}, // LATIN SMALL LETTER B WITH STROKE
- {0x0181, 0x0182, propertyDISALLOWED}, // LATIN CAPITAL LETTER B WITH HOOK..LATIN CAPI
- {0x0183, 0x0, propertyPVALID}, // LATIN SMALL LETTER B WITH TOPBAR
- {0x0184, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER TONE SIX
- {0x0185, 0x0, propertyPVALID}, // LATIN SMALL LETTER TONE SIX
- {0x0186, 0x0187, propertyDISALLOWED}, // LATIN CAPITAL LETTER OPEN O..LATIN CAPITAL L
- {0x0188, 0x0, propertyPVALID}, // LATIN SMALL LETTER C WITH HOOK
- {0x0189, 0x018B, propertyDISALLOWED}, // LATIN CAPITAL LETTER AFRICAN D..LATIN CAPITA
- {0x018C, 0x018D, propertyPVALID}, // LATIN SMALL LETTER D WITH TOPBAR..LATIN SMAL
- {0x018E, 0x0191, propertyDISALLOWED}, // LATIN CAPITAL LETTER REVERSED E..LATIN CAPIT
- {0x0192, 0x0, propertyPVALID}, // LATIN SMALL LETTER F WITH HOOK
- {0x0193, 0x0194, propertyDISALLOWED}, // LATIN CAPITAL LETTER G WITH HOOK..LATIN CAPI
- {0x0195, 0x0, propertyPVALID}, // LATIN SMALL LETTER HV
- {0x0196, 0x0198, propertyDISALLOWED}, // LATIN CAPITAL LETTER IOTA..LATIN CAPITAL LET
- {0x0199, 0x019B, propertyPVALID}, // LATIN SMALL LETTER K WITH HOOK..LATIN SMALL
- {0x019C, 0x019D, propertyDISALLOWED}, // LATIN CAPITAL LETTER TURNED M..LATIN CAPITAL
- {0x019E, 0x0, propertyPVALID}, // LATIN SMALL LETTER N WITH LONG RIGHT LEG
- {0x019F, 0x01A0, propertyDISALLOWED}, // LATIN CAPITAL LETTER O WITH MIDDLE TILDE..LA
- {0x01A1, 0x0, propertyPVALID}, // LATIN SMALL LETTER O WITH HORN
- {0x01A2, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER OI
- {0x01A3, 0x0, propertyPVALID}, // LATIN SMALL LETTER OI
- {0x01A4, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER P WITH HOOK
- {0x01A5, 0x0, propertyPVALID}, // LATIN SMALL LETTER P WITH HOOK
- {0x01A6, 0x01A7, propertyDISALLOWED}, // LATIN LETTER YR..LATIN CAPITAL LETTER TONE T
- {0x01A8, 0x0, propertyPVALID}, // LATIN SMALL LETTER TONE TWO
- {0x01A9, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER ESH
- {0x01AA, 0x01AB, propertyPVALID}, // LATIN LETTER REVERSED ESH LOOP..LATIN SMALL
- {0x01AC, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER T WITH HOOK
- {0x01AD, 0x0, propertyPVALID}, // LATIN SMALL LETTER T WITH HOOK
- {0x01AE, 0x01AF, propertyDISALLOWED}, // LATIN CAPITAL LETTER T WITH RETROFLEX HOOK..
- {0x01B0, 0x0, propertyPVALID}, // LATIN SMALL LETTER U WITH HORN
- {0x01B1, 0x01B3, propertyDISALLOWED}, // LATIN CAPITAL LETTER UPSILON..LATIN CAPITAL
- {0x01B4, 0x0, propertyPVALID}, // LATIN SMALL LETTER Y WITH HOOK
- {0x01B5, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER Z WITH STROKE
- {0x01B6, 0x0, propertyPVALID}, // LATIN SMALL LETTER Z WITH STROKE
- {0x01B7, 0x01B8, propertyDISALLOWED}, // LATIN CAPITAL LETTER EZH..LATIN CAPITAL LETT
- {0x01B9, 0x01BB, propertyPVALID}, // LATIN SMALL LETTER EZH REVERSED..LATIN LETTE
- {0x01BC, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER TONE FIVE
- {0x01BD, 0x01C3, propertyPVALID}, // LATIN SMALL LETTER TONE FIVE..LATIN LETTER R
- {0x01C4, 0x01CD, propertyDISALLOWED}, // LATIN CAPITAL LETTER DZ WITH CARON..LATIN CA
- {0x01CE, 0x0, propertyPVALID}, // LATIN SMALL LETTER A WITH CARON
- {0x01CF, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER I WITH CARON
- {0x01D0, 0x0, propertyPVALID}, // LATIN SMALL LETTER I WITH CARON
- {0x01D1, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER O WITH CARON
- {0x01D2, 0x0, propertyPVALID}, // LATIN SMALL LETTER O WITH CARON
- {0x01D3, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER U WITH CARON
- {0x01D4, 0x0, propertyPVALID}, // LATIN SMALL LETTER U WITH CARON
- {0x01D5, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER U WITH DIAERESIS AND MA
- {0x01D6, 0x0, propertyPVALID}, // LATIN SMALL LETTER U WITH DIAERESIS AND MACR
- {0x01D7, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER U WITH DIAERESIS AND AC
- {0x01D8, 0x0, propertyPVALID}, // LATIN SMALL LETTER U WITH DIAERESIS AND ACUT
- {0x01D9, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER U WITH DIAERESIS AND CA
- {0x01DA, 0x0, propertyPVALID}, // LATIN SMALL LETTER U WITH DIAERESIS AND CARO
- {0x01DB, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER U WITH DIAERESIS AND GR
- {0x01DC, 0x01DD, propertyPVALID}, // LATIN SMALL LETTER U WITH DIAERESIS AND GRAV
- {0x01DE, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER A WITH DIAERESIS AND MA
- {0x01DF, 0x0, propertyPVALID}, // LATIN SMALL LETTER A WITH DIAERESIS AND MACR
- {0x01E0, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER A WITH DOT ABOVE AND MA
- {0x01E1, 0x0, propertyPVALID}, // LATIN SMALL LETTER A WITH DOT ABOVE AND MACR
- {0x01E2, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER AE WITH MACRON
- {0x01E3, 0x0, propertyPVALID}, // LATIN SMALL LETTER AE WITH MACRON
- {0x01E4, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER G WITH STROKE
- {0x01E5, 0x0, propertyPVALID}, // LATIN SMALL LETTER G WITH STROKE
- {0x01E6, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER G WITH CARON
- {0x01E7, 0x0, propertyPVALID}, // LATIN SMALL LETTER G WITH CARON
- {0x01E8, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER K WITH CARON
- {0x01E9, 0x0, propertyPVALID}, // LATIN SMALL LETTER K WITH CARON
- {0x01EA, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER O WITH OGONEK
- {0x01EB, 0x0, propertyPVALID}, // LATIN SMALL LETTER O WITH OGONEK
- {0x01EC, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER O WITH OGONEK AND MACRO
- {0x01ED, 0x0, propertyPVALID}, // LATIN SMALL LETTER O WITH OGONEK AND MACRON
- {0x01EE, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER EZH WITH CARON
- {0x01EF, 0x01F0, propertyPVALID}, // LATIN SMALL LETTER EZH WITH CARON..LATIN SMA
- {0x01F1, 0x01F4, propertyDISALLOWED}, // LATIN CAPITAL LETTER DZ..LATIN CAPITAL LETTE
- {0x01F5, 0x0, propertyPVALID}, // LATIN SMALL LETTER G WITH ACUTE
- {0x01F6, 0x01F8, propertyDISALLOWED}, // LATIN CAPITAL LETTER HWAIR..LATIN CAPITAL LE
- {0x01F9, 0x0, propertyPVALID}, // LATIN SMALL LETTER N WITH GRAVE
- {0x01FA, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER A WITH RING ABOVE AND A
- {0x01FB, 0x0, propertyPVALID}, // LATIN SMALL LETTER A WITH RING ABOVE AND ACU
- {0x01FC, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER AE WITH ACUTE
- {0x01FD, 0x0, propertyPVALID}, // LATIN SMALL LETTER AE WITH ACUTE
- {0x01FE, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER O WITH STROKE AND ACUTE
- {0x01FF, 0x0, propertyPVALID}, // LATIN SMALL LETTER O WITH STROKE AND ACUTE
- {0x0200, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER A WITH DOUBLE GRAVE
- {0x0201, 0x0, propertyPVALID}, // LATIN SMALL LETTER A WITH DOUBLE GRAVE
- {0x0202, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER A WITH INVERTED BREVE
- {0x0203, 0x0, propertyPVALID}, // LATIN SMALL LETTER A WITH INVERTED BREVE
- {0x0204, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER E WITH DOUBLE GRAVE
- {0x0205, 0x0, propertyPVALID}, // LATIN SMALL LETTER E WITH DOUBLE GRAVE
- {0x0206, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER E WITH INVERTED BREVE
- {0x0207, 0x0, propertyPVALID}, // LATIN SMALL LETTER E WITH INVERTED BREVE
- {0x0208, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER I WITH DOUBLE GRAVE
- {0x0209, 0x0, propertyPVALID}, // LATIN SMALL LETTER I WITH DOUBLE GRAVE
- {0x020A, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER I WITH INVERTED BREVE
- {0x020B, 0x0, propertyPVALID}, // LATIN SMALL LETTER I WITH INVERTED BREVE
- {0x020C, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER O WITH DOUBLE GRAVE
- {0x020D, 0x0, propertyPVALID}, // LATIN SMALL LETTER O WITH DOUBLE GRAVE
- {0x020E, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER O WITH INVERTED BREVE
- {0x020F, 0x0, propertyPVALID}, // LATIN SMALL LETTER O WITH INVERTED BREVE
- {0x0210, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER R WITH DOUBLE GRAVE
- {0x0211, 0x0, propertyPVALID}, // LATIN SMALL LETTER R WITH DOUBLE GRAVE
- {0x0212, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER R WITH INVERTED BREVE
- {0x0213, 0x0, propertyPVALID}, // LATIN SMALL LETTER R WITH INVERTED BREVE
- {0x0214, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER U WITH DOUBLE GRAVE
- {0x0215, 0x0, propertyPVALID}, // LATIN SMALL LETTER U WITH DOUBLE GRAVE
- {0x0216, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER U WITH INVERTED BREVE
- {0x0217, 0x0, propertyPVALID}, // LATIN SMALL LETTER U WITH INVERTED BREVE
- {0x0218, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER S WITH COMMA BELOW
- {0x0219, 0x0, propertyPVALID}, // LATIN SMALL LETTER S WITH COMMA BELOW
- {0x021A, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER T WITH COMMA BELOW
- {0x021B, 0x0, propertyPVALID}, // LATIN SMALL LETTER T WITH COMMA BELOW
- {0x021C, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER YOGH
- {0x021D, 0x0, propertyPVALID}, // LATIN SMALL LETTER YOGH
- {0x021E, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER H WITH CARON
- {0x021F, 0x0, propertyPVALID}, // LATIN SMALL LETTER H WITH CARON
- {0x0220, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER N WITH LONG RIGHT LEG
- {0x0221, 0x0, propertyPVALID}, // LATIN SMALL LETTER D WITH CURL
- {0x0222, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER OU
- {0x0223, 0x0, propertyPVALID}, // LATIN SMALL LETTER OU
- {0x0224, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER Z WITH HOOK
- {0x0225, 0x0, propertyPVALID}, // LATIN SMALL LETTER Z WITH HOOK
- {0x0226, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER A WITH DOT ABOVE
- {0x0227, 0x0, propertyPVALID}, // LATIN SMALL LETTER A WITH DOT ABOVE
- {0x0228, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER E WITH CEDILLA
- {0x0229, 0x0, propertyPVALID}, // LATIN SMALL LETTER E WITH CEDILLA
- {0x022A, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER O WITH DIAERESIS AND MA
- {0x022B, 0x0, propertyPVALID}, // LATIN SMALL LETTER O WITH DIAERESIS AND MACR
- {0x022C, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER O WITH TILDE AND MACRON
- {0x022D, 0x0, propertyPVALID}, // LATIN SMALL LETTER O WITH TILDE AND MACRON
- {0x022E, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER O WITH DOT ABOVE
- {0x022F, 0x0, propertyPVALID}, // LATIN SMALL LETTER O WITH DOT ABOVE
- {0x0230, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER O WITH DOT ABOVE AND MA
- {0x0231, 0x0, propertyPVALID}, // LATIN SMALL LETTER O WITH DOT ABOVE AND MACR
- {0x0232, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER Y WITH MACRON
- {0x0233, 0x0239, propertyPVALID}, // LATIN SMALL LETTER Y WITH MACRON..LATIN SMAL
- {0x023A, 0x023B, propertyDISALLOWED}, // LATIN CAPITAL LETTER A WITH STROKE..LATIN CA
- {0x023C, 0x0, propertyPVALID}, // LATIN SMALL LETTER C WITH STROKE
- {0x023D, 0x023E, propertyDISALLOWED}, // LATIN CAPITAL LETTER L WITH BAR..LATIN CAPIT
- {0x023F, 0x0240, propertyPVALID}, // LATIN SMALL LETTER S WITH SWASH TAIL..LATIN
- {0x0241, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER GLOTTAL STOP
- {0x0242, 0x0, propertyPVALID}, // LATIN SMALL LETTER GLOTTAL STOP
- {0x0243, 0x0246, propertyDISALLOWED}, // LATIN CAPITAL LETTER B WITH STROKE..LATIN CA
- {0x0247, 0x0, propertyPVALID}, // LATIN SMALL LETTER E WITH STROKE
- {0x0248, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER J WITH STROKE
- {0x0249, 0x0, propertyPVALID}, // LATIN SMALL LETTER J WITH STROKE
- {0x024A, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER SMALL Q WITH HOOK TAIL
- {0x024B, 0x0, propertyPVALID}, // LATIN SMALL LETTER Q WITH HOOK TAIL
- {0x024C, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER R WITH STROKE
- {0x024D, 0x0, propertyPVALID}, // LATIN SMALL LETTER R WITH STROKE
- {0x024E, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER Y WITH STROKE
- {0x024F, 0x02AF, propertyPVALID}, // LATIN SMALL LETTER Y WITH STROKE..LATIN SMAL
- {0x02B0, 0x02B8, propertyDISALLOWED}, // MODIFIER LETTER SMALL H..MODIFIER LETTER SMA
- {0x02B9, 0x02C1, propertyPVALID}, // MODIFIER LETTER PRIME..MODIFIER LETTER REVER
- {0x02C2, 0x02C5, propertyDISALLOWED}, // MODIFIER LETTER LEFT ARROWHEAD..MODIFIER LET
- {0x02C6, 0x02D1, propertyPVALID}, // MODIFIER LETTER CIRCUMFLEX ACCENT..MODIFIER
- {0x02D2, 0x02EB, propertyDISALLOWED}, // MODIFIER LETTER CENTRED RIGHT HALF RING..MOD
- {0x02EC, 0x0, propertyPVALID}, // MODIFIER LETTER VOICING
- {0x02ED, 0x0, propertyDISALLOWED}, // MODIFIER LETTER UNASPIRATED
- {0x02EE, 0x0, propertyPVALID}, // MODIFIER LETTER DOUBLE APOSTROPHE
- {0x02EF, 0x02FF, propertyDISALLOWED}, // MODIFIER LETTER LOW DOWN ARROWHEAD..MODIFIER
- {0x0300, 0x033F, propertyPVALID}, // COMBINING GRAVE ACCENT..COMBINING DOUBLE OVE
- {0x0340, 0x0341, propertyDISALLOWED}, // COMBINING GRAVE TONE MARK..COMBINING ACUTE T
- {0x0342, 0x0, propertyPVALID}, // COMBINING GREEK PERISPOMENI
- {0x0343, 0x0345, propertyDISALLOWED}, // COMBINING GREEK KORONIS..COMBINING GREEK YPO
- {0x0346, 0x034E, propertyPVALID}, // COMBINING BRIDGE ABOVE..COMBINING UPWARDS AR
- {0x034F, 0x0, propertyDISALLOWED}, // COMBINING GRAPHEME JOINER
- {0x0350, 0x036F, propertyPVALID}, // COMBINING RIGHT ARROWHEAD ABOVE..COMBINING L
- {0x0370, 0x0, propertyDISALLOWED}, // GREEK CAPITAL LETTER HETA
- {0x0371, 0x0, propertyPVALID}, // GREEK SMALL LETTER HETA
- {0x0372, 0x0, propertyDISALLOWED}, // GREEK CAPITAL LETTER ARCHAIC SAMPI
- {0x0373, 0x0, propertyPVALID}, // GREEK SMALL LETTER ARCHAIC SAMPI
- {0x0374, 0x0, propertyDISALLOWED}, // GREEK NUMERAL SIGN
- {0x0375, 0x0, propertyCONTEXTO}, // GREEK LOWER NUMERAL SIGN
- {0x0376, 0x0, propertyDISALLOWED}, // GREEK CAPITAL LETTER PAMPHYLIAN DIGAMMA
- {0x0377, 0x0, propertyPVALID}, // GREEK SMALL LETTER PAMPHYLIAN DIGAMMA
- {0x0378, 0x0379, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x037A, 0x0, propertyDISALLOWED}, // GREEK YPOGEGRAMMENI
- {0x037B, 0x037D, propertyPVALID}, // GREEK SMALL REVERSED LUNATE SIGMA SYMBOL..GR
- {0x037E, 0x0, propertyDISALLOWED}, // GREEK QUESTION MARK
- {0x037F, 0x0383, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0384, 0x038A, propertyDISALLOWED}, // GREEK TONOS..GREEK CAPITAL LETTER IOTA WITH
- {0x038B, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x038C, 0x0, propertyDISALLOWED}, // GREEK CAPITAL LETTER OMICRON WITH TONOS
- {0x038D, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x038E, 0x038F, propertyDISALLOWED}, // GREEK CAPITAL LETTER UPSILON WITH TONOS..GRE
- {0x0390, 0x0, propertyPVALID}, // GREEK SMALL LETTER IOTA WITH DIALYTIKA AND T
- {0x0391, 0x03A1, propertyDISALLOWED}, // GREEK CAPITAL LETTER ALPHA..GREEK CAPITAL LE
- {0x03A2, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x03A3, 0x03AB, propertyDISALLOWED}, // GREEK CAPITAL LETTER SIGMA..GREEK CAPITAL LE
- {0x03AC, 0x03CE, propertyPVALID}, // GREEK SMALL LETTER ALPHA WITH TONOS..GREEK S
- {0x03CF, 0x03D6, propertyDISALLOWED}, // GREEK CAPITAL KAI SYMBOL..GREEK PI SYMBOL
- {0x03D7, 0x0, propertyPVALID}, // GREEK KAI SYMBOL
- {0x03D8, 0x0, propertyDISALLOWED}, // GREEK LETTER ARCHAIC KOPPA
- {0x03D9, 0x0, propertyPVALID}, // GREEK SMALL LETTER ARCHAIC KOPPA
- {0x03DA, 0x0, propertyDISALLOWED}, // GREEK LETTER STIGMA
- {0x03DB, 0x0, propertyPVALID}, // GREEK SMALL LETTER STIGMA
- {0x03DC, 0x0, propertyDISALLOWED}, // GREEK LETTER DIGAMMA
- {0x03DD, 0x0, propertyPVALID}, // GREEK SMALL LETTER DIGAMMA
- {0x03DE, 0x0, propertyDISALLOWED}, // GREEK LETTER KOPPA
- {0x03DF, 0x0, propertyPVALID}, // GREEK SMALL LETTER KOPPA
- {0x03E0, 0x0, propertyDISALLOWED}, // GREEK LETTER SAMPI
- {0x03E1, 0x0, propertyPVALID}, // GREEK SMALL LETTER SAMPI
- {0x03E2, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER SHEI
- {0x03E3, 0x0, propertyPVALID}, // COPTIC SMALL LETTER SHEI
- {0x03E4, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER FEI
- {0x03E5, 0x0, propertyPVALID}, // COPTIC SMALL LETTER FEI
- {0x03E6, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER KHEI
- {0x03E7, 0x0, propertyPVALID}, // COPTIC SMALL LETTER KHEI
- {0x03E8, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER HORI
- {0x03E9, 0x0, propertyPVALID}, // COPTIC SMALL LETTER HORI
- {0x03EA, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER GANGIA
- {0x03EB, 0x0, propertyPVALID}, // COPTIC SMALL LETTER GANGIA
- {0x03EC, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER SHIMA
- {0x03ED, 0x0, propertyPVALID}, // COPTIC SMALL LETTER SHIMA
- {0x03EE, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER DEI
- {0x03EF, 0x0, propertyPVALID}, // COPTIC SMALL LETTER DEI
- {0x03F0, 0x03F2, propertyDISALLOWED}, // GREEK KAPPA SYMBOL..GREEK LUNATE SIGMA SYMBO
- {0x03F3, 0x0, propertyPVALID}, // GREEK LETTER YOT
- {0x03F4, 0x03F7, propertyDISALLOWED}, // GREEK CAPITAL THETA SYMBOL..GREEK CAPITAL LE
- {0x03F8, 0x0, propertyPVALID}, // GREEK SMALL LETTER SHO
- {0x03F9, 0x03FA, propertyDISALLOWED}, // GREEK CAPITAL LUNATE SIGMA SYMBOL..GREEK CAP
- {0x03FB, 0x03FC, propertyPVALID}, // GREEK SMALL LETTER SAN..GREEK RHO WITH STROK
- {0x03FD, 0x042F, propertyDISALLOWED}, // GREEK CAPITAL REVERSED LUNATE SIGMA SYMBOL..
- {0x0430, 0x045F, propertyPVALID}, // CYRILLIC SMALL LETTER A..CYRILLIC SMALL LETT
- {0x0460, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER OMEGA
- {0x0461, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER OMEGA
- {0x0462, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER YAT
- {0x0463, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER YAT
- {0x0464, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER IOTIFIED E
- {0x0465, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER IOTIFIED E
- {0x0466, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER LITTLE YUS
- {0x0467, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER LITTLE YUS
- {0x0468, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER IOTIFIED LITTLE YUS
- {0x0469, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER IOTIFIED LITTLE YUS
- {0x046A, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER BIG YUS
- {0x046B, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER BIG YUS
- {0x046C, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER IOTIFIED BIG YUS
- {0x046D, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER IOTIFIED BIG YUS
- {0x046E, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER KSI
- {0x046F, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER KSI
- {0x0470, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER PSI
- {0x0471, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER PSI
- {0x0472, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER FITA
- {0x0473, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER FITA
- {0x0474, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER IZHITSA
- {0x0475, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER IZHITSA
- {0x0476, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER IZHITSA WITH DOUBLE
- {0x0477, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER IZHITSA WITH DOUBLE GR
- {0x0478, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER UK
- {0x0479, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER UK
- {0x047A, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER ROUND OMEGA
- {0x047B, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER ROUND OMEGA
- {0x047C, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER OMEGA WITH TITLO
- {0x047D, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER OMEGA WITH TITLO
- {0x047E, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER OT
- {0x047F, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER OT
- {0x0480, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER KOPPA
- {0x0481, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER KOPPA
- {0x0482, 0x0, propertyDISALLOWED}, // CYRILLIC THOUSANDS SIGN
- {0x0483, 0x0487, propertyPVALID}, // COMBINING CYRILLIC TITLO..COMBINING CYRILLIC
- {0x0488, 0x048A, propertyDISALLOWED}, // COMBINING CYRILLIC HUNDRED THOUSANDS SIGN..C
- {0x048B, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER SHORT I WITH TAIL
- {0x048C, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER SEMISOFT SIGN
- {0x048D, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER SEMISOFT SIGN
- {0x048E, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER ER WITH TICK
- {0x048F, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER ER WITH TICK
- {0x0490, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER GHE WITH UPTURN
- {0x0491, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER GHE WITH UPTURN
- {0x0492, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER GHE WITH STROKE
- {0x0493, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER GHE WITH STROKE
- {0x0494, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER GHE WITH MIDDLE HOOK
- {0x0495, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER GHE WITH MIDDLE HOOK
- {0x0496, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER ZHE WITH DESCENDER
- {0x0497, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER ZHE WITH DESCENDER
- {0x0498, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER ZE WITH DESCENDER
- {0x0499, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER ZE WITH DESCENDER
- {0x049A, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER KA WITH DESCENDER
- {0x049B, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER KA WITH DESCENDER
- {0x049C, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER KA WITH VERTICAL STR
- {0x049D, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER KA WITH VERTICAL STROK
- {0x049E, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER KA WITH STROKE
- {0x049F, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER KA WITH STROKE
- {0x04A0, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER BASHKIR KA
- {0x04A1, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER BASHKIR KA
- {0x04A2, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER EN WITH DESCENDER
- {0x04A3, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER EN WITH DESCENDER
- {0x04A4, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LIGATURE EN GHE
- {0x04A5, 0x0, propertyPVALID}, // CYRILLIC SMALL LIGATURE EN GHE
- {0x04A6, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER PE WITH MIDDLE HOOK
- {0x04A7, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER PE WITH MIDDLE HOOK
- {0x04A8, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER ABKHASIAN HA
- {0x04A9, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER ABKHASIAN HA
- {0x04AA, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER ES WITH DESCENDER
- {0x04AB, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER ES WITH DESCENDER
- {0x04AC, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER TE WITH DESCENDER
- {0x04AD, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER TE WITH DESCENDER
- {0x04AE, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER STRAIGHT U
- {0x04AF, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER STRAIGHT U
- {0x04B0, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER STRAIGHT U WITH STRO
- {0x04B1, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER STRAIGHT U WITH STROKE
- {0x04B2, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER HA WITH DESCENDER
- {0x04B3, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER HA WITH DESCENDER
- {0x04B4, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LIGATURE TE TSE
- {0x04B5, 0x0, propertyPVALID}, // CYRILLIC SMALL LIGATURE TE TSE
- {0x04B6, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER CHE WITH DESCENDER
- {0x04B7, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER CHE WITH DESCENDER
- {0x04B8, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER CHE WITH VERTICAL ST
- {0x04B9, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER CHE WITH VERTICAL STRO
- {0x04BA, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER SHHA
- {0x04BB, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER SHHA
- {0x04BC, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER ABKHASIAN CHE
- {0x04BD, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER ABKHASIAN CHE
- {0x04BE, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER ABKHASIAN CHE WITH D
- {0x04BF, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER ABKHASIAN CHE WITH DES
- {0x04C0, 0x04C1, propertyDISALLOWED}, // CYRILLIC LETTER PALOCHKA..CYRILLIC CAPITAL L
- {0x04C2, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER ZHE WITH BREVE
- {0x04C3, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER KA WITH HOOK
- {0x04C4, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER KA WITH HOOK
- {0x04C5, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER EL WITH TAIL
- {0x04C6, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER EL WITH TAIL
- {0x04C7, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER EN WITH HOOK
- {0x04C8, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER EN WITH HOOK
- {0x04C9, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER EN WITH TAIL
- {0x04CA, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER EN WITH TAIL
- {0x04CB, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER KHAKASSIAN CHE
- {0x04CC, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER KHAKASSIAN CHE
- {0x04CD, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER EM WITH TAIL
- {0x04CE, 0x04CF, propertyPVALID}, // CYRILLIC SMALL LETTER EM WITH TAIL..CYRILLIC
- {0x04D0, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER A WITH BREVE
- {0x04D1, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER A WITH BREVE
- {0x04D2, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER A WITH DIAERESIS
- {0x04D3, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER A WITH DIAERESIS
- {0x04D4, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LIGATURE A IE
- {0x04D5, 0x0, propertyPVALID}, // CYRILLIC SMALL LIGATURE A IE
- {0x04D6, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER IE WITH BREVE
- {0x04D7, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER IE WITH BREVE
- {0x04D8, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER SCHWA
- {0x04D9, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER SCHWA
- {0x04DA, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER SCHWA WITH DIAERESIS
- {0x04DB, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER SCHWA WITH DIAERESIS
- {0x04DC, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER ZHE WITH DIAERESIS
- {0x04DD, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER ZHE WITH DIAERESIS
- {0x04DE, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER ZE WITH DIAERESIS
- {0x04DF, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER ZE WITH DIAERESIS
- {0x04E0, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER ABKHASIAN DZE
- {0x04E1, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER ABKHASIAN DZE
- {0x04E2, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER I WITH MACRON
- {0x04E3, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER I WITH MACRON
- {0x04E4, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER I WITH DIAERESIS
- {0x04E5, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER I WITH DIAERESIS
- {0x04E6, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER O WITH DIAERESIS
- {0x04E7, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER O WITH DIAERESIS
- {0x04E8, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER BARRED O
- {0x04E9, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER BARRED O
- {0x04EA, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER BARRED O WITH DIAERE
- {0x04EB, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER BARRED O WITH DIAERESI
- {0x04EC, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER E WITH DIAERESIS
- {0x04ED, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER E WITH DIAERESIS
- {0x04EE, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER U WITH MACRON
- {0x04EF, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER U WITH MACRON
- {0x04F0, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER U WITH DIAERESIS
- {0x04F1, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER U WITH DIAERESIS
- {0x04F2, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER U WITH DOUBLE ACUTE
- {0x04F3, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER U WITH DOUBLE ACUTE
- {0x04F4, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER CHE WITH DIAERESIS
- {0x04F5, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER CHE WITH DIAERESIS
- {0x04F6, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER GHE WITH DESCENDER
- {0x04F7, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER GHE WITH DESCENDER
- {0x04F8, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER YERU WITH DIAERESIS
- {0x04F9, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER YERU WITH DIAERESIS
- {0x04FA, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER GHE WITH STROKE AND
- {0x04FB, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER GHE WITH STROKE AND HO
- {0x04FC, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER HA WITH HOOK
- {0x04FD, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER HA WITH HOOK
- {0x04FE, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER HA WITH STROKE
- {0x04FF, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER HA WITH STROKE
- {0x0500, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER KOMI DE
- {0x0501, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER KOMI DE
- {0x0502, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER KOMI DJE
- {0x0503, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER KOMI DJE
- {0x0504, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER KOMI ZJE
- {0x0505, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER KOMI ZJE
- {0x0506, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER KOMI DZJE
- {0x0507, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER KOMI DZJE
- {0x0508, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER KOMI LJE
- {0x0509, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER KOMI LJE
- {0x050A, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER KOMI NJE
- {0x050B, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER KOMI NJE
- {0x050C, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER KOMI SJE
- {0x050D, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER KOMI SJE
- {0x050E, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER KOMI TJE
- {0x050F, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER KOMI TJE
- {0x0510, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER REVERSED ZE
- {0x0511, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER REVERSED ZE
- {0x0512, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER EL WITH HOOK
- {0x0513, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER EL WITH HOOK
- {0x0514, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER LHA
- {0x0515, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER LHA
- {0x0516, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER RHA
- {0x0517, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER RHA
- {0x0518, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER YAE
- {0x0519, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER YAE
- {0x051A, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER QA
- {0x051B, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER QA
- {0x051C, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER WE
- {0x051D, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER WE
- {0x051E, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER ALEUT KA
- {0x051F, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER ALEUT KA
- {0x0520, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER EL WITH MIDDLE HOOK
- {0x0521, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER EL WITH MIDDLE HOOK
- {0x0522, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER EN WITH MIDDLE HOOK
- {0x0523, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER EN WITH MIDDLE HOOK
- {0x0524, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER PE WITH DESCENDER
- {0x0525, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER PE WITH DESCENDER
- {0x0526, 0x0530, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0531, 0x0556, propertyDISALLOWED}, // ARMENIAN CAPITAL LETTER AYB..ARMENIAN CAPITA
- {0x0557, 0x0558, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0559, 0x0, propertyPVALID}, // ARMENIAN MODIFIER LETTER LEFT HALF RING
- {0x055A, 0x055F, propertyDISALLOWED}, // ARMENIAN APOSTROPHE..ARMENIAN ABBREVIATION M
- {0x0560, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0561, 0x0586, propertyPVALID}, // ARMENIAN SMALL LETTER AYB..ARMENIAN SMALL LE
- {0x0587, 0x0, propertyDISALLOWED}, // ARMENIAN SMALL LIGATURE ECH YIWN
- {0x0588, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0589, 0x058A, propertyDISALLOWED}, // ARMENIAN FULL STOP..ARMENIAN HYPHEN
- {0x058B, 0x0590, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0591, 0x05BD, propertyPVALID}, // HEBREW ACCENT ETNAHTA..HEBREW POINT METEG
- {0x05BE, 0x0, propertyDISALLOWED}, // HEBREW PUNCTUATION MAQAF
- {0x05BF, 0x0, propertyPVALID}, // HEBREW POINT RAFE
- {0x05C0, 0x0, propertyDISALLOWED}, // HEBREW PUNCTUATION PASEQ
- {0x05C1, 0x05C2, propertyPVALID}, // HEBREW POINT SHIN DOT..HEBREW POINT SIN DOT
- {0x05C3, 0x0, propertyDISALLOWED}, // HEBREW PUNCTUATION SOF PASUQ
- {0x05C4, 0x05C5, propertyPVALID}, // HEBREW MARK UPPER DOT..HEBREW MARK LOWER DOT
- {0x05C6, 0x0, propertyDISALLOWED}, // HEBREW PUNCTUATION NUN HAFUKHA
- {0x05C7, 0x0, propertyPVALID}, // HEBREW POINT QAMATS QATAN
- {0x05C8, 0x05CF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x05D0, 0x05EA, propertyPVALID}, // HEBREW LETTER ALEF..HEBREW LETTER TAV
- {0x05EB, 0x05EF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x05F0, 0x05F2, propertyPVALID}, // HEBREW LIGATURE YIDDISH DOUBLE VAV..HEBREW L
- {0x05F3, 0x05F4, propertyCONTEXTO}, // HEBREW PUNCTUATION GERESH..HEBREW PUNCTUATIO
- {0x05F5, 0x05FF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0600, 0x0603, propertyDISALLOWED}, // ARABIC NUMBER SIGN..ARABIC SIGN SAFHA
- {0x0604, 0x0605, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0606, 0x060F, propertyDISALLOWED}, // ARABIC-INDIC CUBE ROOT..ARABIC SIGN MISRA
- {0x0610, 0x061A, propertyPVALID}, // ARABIC SIGN SALLALLAHOU ALAYHE WASSALLAM..AR
- {0x061B, 0x0, propertyDISALLOWED}, // ARABIC SEMICOLON
- {0x061C, 0x061D, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x061E, 0x061F, propertyDISALLOWED}, // ARABIC TRIPLE DOT PUNCTUATION MARK..ARABIC Q
- {0x0620, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0621, 0x063F, propertyPVALID}, // ARABIC LETTER HAMZA..ARABIC LETTER FARSI YEH
- {0x0640, 0x0, propertyDISALLOWED}, // ARABIC TATWEEL
- {0x0641, 0x065E, propertyPVALID}, // ARABIC LETTER FEH..ARABIC FATHA WITH TWO DOT
- {0x065F, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0660, 0x0669, propertyCONTEXTO}, // ARABIC-INDIC DIGIT ZERO..ARABIC-INDIC DIGIT
- {0x066A, 0x066D, propertyDISALLOWED}, // ARABIC PERCENT SIGN..ARABIC FIVE POINTED STA
- {0x066E, 0x0674, propertyPVALID}, // ARABIC LETTER DOTLESS BEH..ARABIC LETTER HIG
- {0x0675, 0x0678, propertyDISALLOWED}, // ARABIC LETTER HIGH HAMZA ALEF..ARABIC LETTER
- {0x0679, 0x06D3, propertyPVALID}, // ARABIC LETTER TTEH..ARABIC LETTER YEH BARREE
- {0x06D4, 0x0, propertyDISALLOWED}, // ARABIC FULL STOP
- {0x06D5, 0x06DC, propertyPVALID}, // ARABIC LETTER AE..ARABIC SMALL HIGH SEEN
- {0x06DD, 0x06DE, propertyDISALLOWED}, // ARABIC END OF AYAH..ARABIC START OF RUB EL H
- {0x06DF, 0x06E8, propertyPVALID}, // ARABIC SMALL HIGH ROUNDED ZERO..ARABIC SMALL
- {0x06E9, 0x0, propertyDISALLOWED}, // ARABIC PLACE OF SAJDAH
- {0x06EA, 0x06EF, propertyPVALID}, // ARABIC EMPTY CENTRE LOW STOP..ARABIC LETTER
- {0x06F0, 0x06F9, propertyCONTEXTO}, // EXTENDED ARABIC-INDIC DIGIT ZERO..EXTENDED A
- {0x06FA, 0x06FF, propertyPVALID}, // ARABIC LETTER SHEEN WITH DOT BELOW..ARABIC L
- {0x0700, 0x070D, propertyDISALLOWED}, // SYRIAC END OF PARAGRAPH..SYRIAC HARKLEAN AST
- {0x070E, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x070F, 0x0, propertyDISALLOWED}, // SYRIAC ABBREVIATION MARK
- {0x0710, 0x074A, propertyPVALID}, // SYRIAC LETTER ALAPH..SYRIAC BARREKH
- {0x074B, 0x074C, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x074D, 0x07B1, propertyPVALID}, // SYRIAC LETTER SOGDIAN ZHAIN..THAANA LETTER N
- {0x07B2, 0x07BF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x07C0, 0x07F5, propertyPVALID}, // NKO DIGIT ZERO..NKO LOW TONE APOSTROPHE
- {0x07F6, 0x07FA, propertyDISALLOWED}, // NKO SYMBOL OO DENNEN..NKO LAJANYALAN
- {0x07FB, 0x07FF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0800, 0x082D, propertyPVALID}, // SAMARITAN LETTER ALAF..SAMARITAN MARK NEQUDA
- {0x082E, 0x082F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0830, 0x083E, propertyDISALLOWED}, // SAMARITAN PUNCTUATION NEQUDAA..SAMARITAN PUN
- {0x083F, 0x08FF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0900, 0x0939, propertyPVALID}, // DEVANAGARI SIGN INVERTED CANDRABINDU..DEVANA
- {0x093A, 0x093B, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x093C, 0x094E, propertyPVALID}, // DEVANAGARI SIGN NUKTA..DEVANAGARI VOWEL SIGN
- {0x094F, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0950, 0x0955, propertyPVALID}, // DEVANAGARI OM..DEVANAGARI VOWEL SIGN CANDRA
- {0x0956, 0x0957, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0958, 0x095F, propertyDISALLOWED}, // DEVANAGARI LETTER QA..DEVANAGARI LETTER YYA
- {0x0960, 0x0963, propertyPVALID}, // DEVANAGARI LETTER VOCALIC RR..DEVANAGARI VOW
- {0x0964, 0x0965, propertyDISALLOWED}, // DEVANAGARI DANDA..DEVANAGARI DOUBLE DANDA
- {0x0966, 0x096F, propertyPVALID}, // DEVANAGARI DIGIT ZERO..DEVANAGARI DIGIT NINE
- {0x0970, 0x0, propertyDISALLOWED}, // DEVANAGARI ABBREVIATION SIGN
- {0x0971, 0x0972, propertyPVALID}, // DEVANAGARI SIGN HIGH SPACING DOT..DEVANAGARI
- {0x0973, 0x0978, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0979, 0x097F, propertyPVALID}, // DEVANAGARI LETTER ZHA..DEVANAGARI LETTER BBA
- {0x0980, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0981, 0x0983, propertyPVALID}, // BENGALI SIGN CANDRABINDU..BENGALI SIGN VISAR
- {0x0984, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0985, 0x098C, propertyPVALID}, // BENGALI LETTER A..BENGALI LETTER VOCALIC L
- {0x098D, 0x098E, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x098F, 0x0990, propertyPVALID}, // BENGALI LETTER E..BENGALI LETTER AI
- {0x0991, 0x0992, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0993, 0x09A8, propertyPVALID}, // BENGALI LETTER O..BENGALI LETTER NA
- {0x09A9, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x09AA, 0x09B0, propertyPVALID}, // BENGALI LETTER PA..BENGALI LETTER RA
- {0x09B1, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x09B2, 0x0, propertyPVALID}, // BENGALI LETTER LA
- {0x09B3, 0x09B5, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x09B6, 0x09B9, propertyPVALID}, // BENGALI LETTER SHA..BENGALI LETTER HA
- {0x09BA, 0x09BB, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x09BC, 0x09C4, propertyPVALID}, // BENGALI SIGN NUKTA..BENGALI VOWEL SIGN VOCAL
- {0x09C5, 0x09C6, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x09C7, 0x09C8, propertyPVALID}, // BENGALI VOWEL SIGN E..BENGALI VOWEL SIGN AI
- {0x09C9, 0x09CA, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x09CB, 0x09CE, propertyPVALID}, // BENGALI VOWEL SIGN O..BENGALI LETTER KHANDA
- {0x09CF, 0x09D6, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x09D7, 0x0, propertyPVALID}, // BENGALI AU LENGTH MARK
- {0x09D8, 0x09DB, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x09DC, 0x09DD, propertyDISALLOWED}, // BENGALI LETTER RRA..BENGALI LETTER RHA
- {0x09DE, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x09DF, 0x0, propertyDISALLOWED}, // BENGALI LETTER YYA
- {0x09E0, 0x09E3, propertyPVALID}, // BENGALI LETTER VOCALIC RR..BENGALI VOWEL SIG
- {0x09E4, 0x09E5, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x09E6, 0x09F1, propertyPVALID}, // BENGALI DIGIT ZERO..BENGALI LETTER RA WITH L
- {0x09F2, 0x09FB, propertyDISALLOWED}, // BENGALI RUPEE MARK..BENGALI GANDA MARK
- {0x09FC, 0x0A00, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0A01, 0x0A03, propertyPVALID}, // GURMUKHI SIGN ADAK BINDI..GURMUKHI SIGN VISA
- {0x0A04, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0A05, 0x0A0A, propertyPVALID}, // GURMUKHI LETTER A..GURMUKHI LETTER UU
- {0x0A0B, 0x0A0E, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0A0F, 0x0A10, propertyPVALID}, // GURMUKHI LETTER EE..GURMUKHI LETTER AI
- {0x0A11, 0x0A12, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0A13, 0x0A28, propertyPVALID}, // GURMUKHI LETTER OO..GURMUKHI LETTER NA
- {0x0A29, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0A2A, 0x0A30, propertyPVALID}, // GURMUKHI LETTER PA..GURMUKHI LETTER RA
- {0x0A31, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0A32, 0x0, propertyPVALID}, // GURMUKHI LETTER LA
- {0x0A33, 0x0, propertyDISALLOWED}, // GURMUKHI LETTER LLA
- {0x0A34, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0A35, 0x0, propertyPVALID}, // GURMUKHI LETTER VA
- {0x0A36, 0x0, propertyDISALLOWED}, // GURMUKHI LETTER SHA
- {0x0A37, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0A38, 0x0A39, propertyPVALID}, // GURMUKHI LETTER SA..GURMUKHI LETTER HA
- {0x0A3A, 0x0A3B, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0A3C, 0x0, propertyPVALID}, // GURMUKHI SIGN NUKTA
- {0x0A3D, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0A3E, 0x0A42, propertyPVALID}, // GURMUKHI VOWEL SIGN AA..GURMUKHI VOWEL SIGN
- {0x0A43, 0x0A46, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0A47, 0x0A48, propertyPVALID}, // GURMUKHI VOWEL SIGN EE..GURMUKHI VOWEL SIGN
- {0x0A49, 0x0A4A, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0A4B, 0x0A4D, propertyPVALID}, // GURMUKHI VOWEL SIGN OO..GURMUKHI SIGN VIRAMA
- {0x0A4E, 0x0A50, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0A51, 0x0, propertyPVALID}, // GURMUKHI SIGN UDAAT
- {0x0A52, 0x0A58, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0A59, 0x0A5B, propertyDISALLOWED}, // GURMUKHI LETTER KHHA..GURMUKHI LETTER ZA
- {0x0A5C, 0x0, propertyPVALID}, // GURMUKHI LETTER RRA
- {0x0A5D, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0A5E, 0x0, propertyDISALLOWED}, // GURMUKHI LETTER FA
- {0x0A5F, 0x0A65, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0A66, 0x0A75, propertyPVALID}, // GURMUKHI DIGIT ZERO..GURMUKHI SIGN YAKASH
- {0x0A76, 0x0A80, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0A81, 0x0A83, propertyPVALID}, // GUJARATI SIGN CANDRABINDU..GUJARATI SIGN VIS
- {0x0A84, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0A85, 0x0A8D, propertyPVALID}, // GUJARATI LETTER A..GUJARATI VOWEL CANDRA E
- {0x0A8E, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0A8F, 0x0A91, propertyPVALID}, // GUJARATI LETTER E..GUJARATI VOWEL CANDRA O
- {0x0A92, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0A93, 0x0AA8, propertyPVALID}, // GUJARATI LETTER O..GUJARATI LETTER NA
- {0x0AA9, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0AAA, 0x0AB0, propertyPVALID}, // GUJARATI LETTER PA..GUJARATI LETTER RA
- {0x0AB1, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0AB2, 0x0AB3, propertyPVALID}, // GUJARATI LETTER LA..GUJARATI LETTER LLA
- {0x0AB4, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0AB5, 0x0AB9, propertyPVALID}, // GUJARATI LETTER VA..GUJARATI LETTER HA
- {0x0ABA, 0x0ABB, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0ABC, 0x0AC5, propertyPVALID}, // GUJARATI SIGN NUKTA..GUJARATI VOWEL SIGN CAN
- {0x0AC6, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0AC7, 0x0AC9, propertyPVALID}, // GUJARATI VOWEL SIGN E..GUJARATI VOWEL SIGN C
- {0x0ACA, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0ACB, 0x0ACD, propertyPVALID}, // GUJARATI VOWEL SIGN O..GUJARATI SIGN VIRAMA
- {0x0ACE, 0x0ACF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0AD0, 0x0, propertyPVALID}, // GUJARATI OM
- {0x0AD1, 0x0ADF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0AE0, 0x0AE3, propertyPVALID}, // GUJARATI LETTER VOCALIC RR..GUJARATI VOWEL S
- {0x0AE4, 0x0AE5, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0AE6, 0x0AEF, propertyPVALID}, // GUJARATI DIGIT ZERO..GUJARATI DIGIT NINE
- {0x0AF0, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0AF1, 0x0, propertyDISALLOWED}, // GUJARATI RUPEE SIGN
- {0x0AF2, 0x0B00, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0B01, 0x0B03, propertyPVALID}, // ORIYA SIGN CANDRABINDU..ORIYA SIGN VISARGA
- {0x0B04, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0B05, 0x0B0C, propertyPVALID}, // ORIYA LETTER A..ORIYA LETTER VOCALIC L
- {0x0B0D, 0x0B0E, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0B0F, 0x0B10, propertyPVALID}, // ORIYA LETTER E..ORIYA LETTER AI
- {0x0B11, 0x0B12, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0B13, 0x0B28, propertyPVALID}, // ORIYA LETTER O..ORIYA LETTER NA
- {0x0B29, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0B2A, 0x0B30, propertyPVALID}, // ORIYA LETTER PA..ORIYA LETTER RA
- {0x0B31, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0B32, 0x0B33, propertyPVALID}, // ORIYA LETTER LA..ORIYA LETTER LLA
- {0x0B34, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0B35, 0x0B39, propertyPVALID}, // ORIYA LETTER VA..ORIYA LETTER HA
- {0x0B3A, 0x0B3B, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0B3C, 0x0B44, propertyPVALID}, // ORIYA SIGN NUKTA..ORIYA VOWEL SIGN VOCALIC R
- {0x0B45, 0x0B46, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0B47, 0x0B48, propertyPVALID}, // ORIYA VOWEL SIGN E..ORIYA VOWEL SIGN AI
- {0x0B49, 0x0B4A, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0B4B, 0x0B4D, propertyPVALID}, // ORIYA VOWEL SIGN O..ORIYA SIGN VIRAMA
- {0x0B4E, 0x0B55, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0B56, 0x0B57, propertyPVALID}, // ORIYA AI LENGTH MARK..ORIYA AU LENGTH MARK
- {0x0B58, 0x0B5B, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0B5C, 0x0B5D, propertyDISALLOWED}, // ORIYA LETTER RRA..ORIYA LETTER RHA
- {0x0B5E, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0B5F, 0x0B63, propertyPVALID}, // ORIYA LETTER YYA..ORIYA VOWEL SIGN VOCALIC L
- {0x0B64, 0x0B65, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0B66, 0x0B6F, propertyPVALID}, // ORIYA DIGIT ZERO..ORIYA DIGIT NINE
- {0x0B70, 0x0, propertyDISALLOWED}, // ORIYA ISSHAR
- {0x0B71, 0x0, propertyPVALID}, // ORIYA LETTER WA
- {0x0B72, 0x0B81, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0B82, 0x0B83, propertyPVALID}, // TAMIL SIGN ANUSVARA..TAMIL SIGN VISARGA
- {0x0B84, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0B85, 0x0B8A, propertyPVALID}, // TAMIL LETTER A..TAMIL LETTER UU
- {0x0B8B, 0x0B8D, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0B8E, 0x0B90, propertyPVALID}, // TAMIL LETTER E..TAMIL LETTER AI
- {0x0B91, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0B92, 0x0B95, propertyPVALID}, // TAMIL LETTER O..TAMIL LETTER KA
- {0x0B96, 0x0B98, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0B99, 0x0B9A, propertyPVALID}, // TAMIL LETTER NGA..TAMIL LETTER CA
- {0x0B9B, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0B9C, 0x0, propertyPVALID}, // TAMIL LETTER JA
- {0x0B9D, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0B9E, 0x0B9F, propertyPVALID}, // TAMIL LETTER NYA..TAMIL LETTER TTA
- {0x0BA0, 0x0BA2, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0BA3, 0x0BA4, propertyPVALID}, // TAMIL LETTER NNA..TAMIL LETTER TA
- {0x0BA5, 0x0BA7, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0BA8, 0x0BAA, propertyPVALID}, // TAMIL LETTER NA..TAMIL LETTER PA
- {0x0BAB, 0x0BAD, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0BAE, 0x0BB9, propertyPVALID}, // TAMIL LETTER MA..TAMIL LETTER HA
- {0x0BBA, 0x0BBD, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0BBE, 0x0BC2, propertyPVALID}, // TAMIL VOWEL SIGN AA..TAMIL VOWEL SIGN UU
- {0x0BC3, 0x0BC5, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0BC6, 0x0BC8, propertyPVALID}, // TAMIL VOWEL SIGN E..TAMIL VOWEL SIGN AI
- {0x0BC9, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0BCA, 0x0BCD, propertyPVALID}, // TAMIL VOWEL SIGN O..TAMIL SIGN VIRAMA
- {0x0BCE, 0x0BCF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0BD0, 0x0, propertyPVALID}, // TAMIL OM
- {0x0BD1, 0x0BD6, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0BD7, 0x0, propertyPVALID}, // TAMIL AU LENGTH MARK
- {0x0BD8, 0x0BE5, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0BE6, 0x0BEF, propertyPVALID}, // TAMIL DIGIT ZERO..TAMIL DIGIT NINE
- {0x0BF0, 0x0BFA, propertyDISALLOWED}, // TAMIL NUMBER TEN..TAMIL NUMBER SIGN
- {0x0BFB, 0x0C00, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0C01, 0x0C03, propertyPVALID}, // TELUGU SIGN CANDRABINDU..TELUGU SIGN VISARGA
- {0x0C04, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0C05, 0x0C0C, propertyPVALID}, // TELUGU LETTER A..TELUGU LETTER VOCALIC L
- {0x0C0D, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0C0E, 0x0C10, propertyPVALID}, // TELUGU LETTER E..TELUGU LETTER AI
- {0x0C11, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0C12, 0x0C28, propertyPVALID}, // TELUGU LETTER O..TELUGU LETTER NA
- {0x0C29, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0C2A, 0x0C33, propertyPVALID}, // TELUGU LETTER PA..TELUGU LETTER LLA
- {0x0C34, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0C35, 0x0C39, propertyPVALID}, // TELUGU LETTER VA..TELUGU LETTER HA
- {0x0C3A, 0x0C3C, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0C3D, 0x0C44, propertyPVALID}, // TELUGU SIGN AVAGRAHA..TELUGU VOWEL SIGN VOCA
- {0x0C45, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0C46, 0x0C48, propertyPVALID}, // TELUGU VOWEL SIGN E..TELUGU VOWEL SIGN AI
- {0x0C49, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0C4A, 0x0C4D, propertyPVALID}, // TELUGU VOWEL SIGN O..TELUGU SIGN VIRAMA
- {0x0C4E, 0x0C54, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0C55, 0x0C56, propertyPVALID}, // TELUGU LENGTH MARK..TELUGU AI LENGTH MARK
- {0x0C57, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0C58, 0x0C59, propertyPVALID}, // TELUGU LETTER TSA..TELUGU LETTER DZA
- {0x0C5A, 0x0C5F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0C60, 0x0C63, propertyPVALID}, // TELUGU LETTER VOCALIC RR..TELUGU VOWEL SIGN
- {0x0C64, 0x0C65, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0C66, 0x0C6F, propertyPVALID}, // TELUGU DIGIT ZERO..TELUGU DIGIT NINE
- {0x0C70, 0x0C77, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0C78, 0x0C7F, propertyDISALLOWED}, // TELUGU FRACTION DIGIT ZERO FOR ODD POWERS OF
- {0x0C80, 0x0C81, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0C82, 0x0C83, propertyPVALID}, // KANNADA SIGN ANUSVARA..KANNADA SIGN VISARGA
- {0x0C84, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0C85, 0x0C8C, propertyPVALID}, // KANNADA LETTER A..KANNADA LETTER VOCALIC L
- {0x0C8D, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0C8E, 0x0C90, propertyPVALID}, // KANNADA LETTER E..KANNADA LETTER AI
- {0x0C91, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0C92, 0x0CA8, propertyPVALID}, // KANNADA LETTER O..KANNADA LETTER NA
- {0x0CA9, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0CAA, 0x0CB3, propertyPVALID}, // KANNADA LETTER PA..KANNADA LETTER LLA
- {0x0CB4, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0CB5, 0x0CB9, propertyPVALID}, // KANNADA LETTER VA..KANNADA LETTER HA
- {0x0CBA, 0x0CBB, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0CBC, 0x0CC4, propertyPVALID}, // KANNADA SIGN NUKTA..KANNADA VOWEL SIGN VOCAL
- {0x0CC5, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0CC6, 0x0CC8, propertyPVALID}, // KANNADA VOWEL SIGN E..KANNADA VOWEL SIGN AI
- {0x0CC9, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0CCA, 0x0CCD, propertyPVALID}, // KANNADA VOWEL SIGN O..KANNADA SIGN VIRAMA
- {0x0CCE, 0x0CD4, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0CD5, 0x0CD6, propertyPVALID}, // KANNADA LENGTH MARK..KANNADA AI LENGTH MARK
- {0x0CD7, 0x0CDD, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0CDE, 0x0, propertyPVALID}, // KANNADA LETTER FA
- {0x0CDF, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0CE0, 0x0CE3, propertyPVALID}, // KANNADA LETTER VOCALIC RR..KANNADA VOWEL SIG
- {0x0CE4, 0x0CE5, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0CE6, 0x0CEF, propertyPVALID}, // KANNADA DIGIT ZERO..KANNADA DIGIT NINE
- {0x0CF0, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0CF1, 0x0CF2, propertyDISALLOWED}, // KANNADA SIGN JIHVAMULIYA..KANNADA SIGN UPADH
- {0x0CF3, 0x0D01, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0D02, 0x0D03, propertyPVALID}, // MALAYALAM SIGN ANUSVARA..MALAYALAM SIGN VISA
- {0x0D04, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0D05, 0x0D0C, propertyPVALID}, // MALAYALAM LETTER A..MALAYALAM LETTER VOCALIC
- {0x0D0D, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0D0E, 0x0D10, propertyPVALID}, // MALAYALAM LETTER E..MALAYALAM LETTER AI
- {0x0D11, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0D12, 0x0D28, propertyPVALID}, // MALAYALAM LETTER O..MALAYALAM LETTER NA
- {0x0D29, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0D2A, 0x0D39, propertyPVALID}, // MALAYALAM LETTER PA..MALAYALAM LETTER HA
- {0x0D3A, 0x0D3C, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0D3D, 0x0D44, propertyPVALID}, // MALAYALAM SIGN AVAGRAHA..MALAYALAM VOWEL SIG
- {0x0D45, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0D46, 0x0D48, propertyPVALID}, // MALAYALAM VOWEL SIGN E..MALAYALAM VOWEL SIGN
- {0x0D49, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0D4A, 0x0D4D, propertyPVALID}, // MALAYALAM VOWEL SIGN O..MALAYALAM SIGN VIRAM
- {0x0D4E, 0x0D56, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0D57, 0x0, propertyPVALID}, // MALAYALAM AU LENGTH MARK
- {0x0D58, 0x0D5F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0D60, 0x0D63, propertyPVALID}, // MALAYALAM LETTER VOCALIC RR..MALAYALAM VOWEL
- {0x0D64, 0x0D65, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0D66, 0x0D6F, propertyPVALID}, // MALAYALAM DIGIT ZERO..MALAYALAM DIGIT NINE
- {0x0D70, 0x0D75, propertyDISALLOWED}, // MALAYALAM NUMBER TEN..MALAYALAM FRACTION THR
- {0x0D76, 0x0D78, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0D79, 0x0, propertyDISALLOWED}, // MALAYALAM DATE MARK
- {0x0D7A, 0x0D7F, propertyPVALID}, // MALAYALAM LETTER CHILLU NN..MALAYALAM LETTER
- {0x0D80, 0x0D81, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0D82, 0x0D83, propertyPVALID}, // SINHALA SIGN ANUSVARAYA..SINHALA SIGN VISARG
- {0x0D84, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0D85, 0x0D96, propertyPVALID}, // SINHALA LETTER AYANNA..SINHALA LETTER AUYANN
- {0x0D97, 0x0D99, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0D9A, 0x0DB1, propertyPVALID}, // SINHALA LETTER ALPAPRAANA KAYANNA..SINHALA L
- {0x0DB2, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0DB3, 0x0DBB, propertyPVALID}, // SINHALA LETTER SANYAKA DAYANNA..SINHALA LETT
- {0x0DBC, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0DBD, 0x0, propertyPVALID}, // SINHALA LETTER DANTAJA LAYANNA
- {0x0DBE, 0x0DBF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0DC0, 0x0DC6, propertyPVALID}, // SINHALA LETTER VAYANNA..SINHALA LETTER FAYAN
- {0x0DC7, 0x0DC9, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0DCA, 0x0, propertyPVALID}, // SINHALA SIGN AL-LAKUNA
- {0x0DCB, 0x0DCE, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0DCF, 0x0DD4, propertyPVALID}, // SINHALA VOWEL SIGN AELA-PILLA..SINHALA VOWEL
- {0x0DD5, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0DD6, 0x0, propertyPVALID}, // SINHALA VOWEL SIGN DIGA PAA-PILLA
- {0x0DD7, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0DD8, 0x0DDF, propertyPVALID}, // SINHALA VOWEL SIGN GAETTA-PILLA..SINHALA VOW
- {0x0DE0, 0x0DF1, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0DF2, 0x0DF3, propertyPVALID}, // SINHALA VOWEL SIGN DIGA GAETTA-PILLA..SINHAL
- {0x0DF4, 0x0, propertyDISALLOWED}, // SINHALA PUNCTUATION KUNDDALIYA
- {0x0DF5, 0x0E00, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0E01, 0x0E32, propertyPVALID}, // THAI CHARACTER KO KAI..THAI CHARACTER SARA A
- {0x0E33, 0x0, propertyDISALLOWED}, // THAI CHARACTER SARA AM
- {0x0E34, 0x0E3A, propertyPVALID}, // THAI CHARACTER SARA I..THAI CHARACTER PHINTH
- {0x0E3B, 0x0E3E, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0E3F, 0x0, propertyDISALLOWED}, // THAI CURRENCY SYMBOL BAHT
- {0x0E40, 0x0E4E, propertyPVALID}, // THAI CHARACTER SARA E..THAI CHARACTER YAMAKK
- {0x0E4F, 0x0, propertyDISALLOWED}, // THAI CHARACTER FONGMAN
- {0x0E50, 0x0E59, propertyPVALID}, // THAI DIGIT ZERO..THAI DIGIT NINE
- {0x0E5A, 0x0E5B, propertyDISALLOWED}, // THAI CHARACTER ANGKHANKHU..THAI CHARACTER KH
- {0x0E5C, 0x0E80, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0E81, 0x0E82, propertyPVALID}, // LAO LETTER KO..LAO LETTER KHO SUNG
- {0x0E83, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0E84, 0x0, propertyPVALID}, // LAO LETTER KHO TAM
- {0x0E85, 0x0E86, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0E87, 0x0E88, propertyPVALID}, // LAO LETTER NGO..LAO LETTER CO
- {0x0E89, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0E8A, 0x0, propertyPVALID}, // LAO LETTER SO TAM
- {0x0E8B, 0x0E8C, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0E8D, 0x0, propertyPVALID}, // LAO LETTER NYO
- {0x0E8E, 0x0E93, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0E94, 0x0E97, propertyPVALID}, // LAO LETTER DO..LAO LETTER THO TAM
- {0x0E98, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0E99, 0x0E9F, propertyPVALID}, // LAO LETTER NO..LAO LETTER FO SUNG
- {0x0EA0, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0EA1, 0x0EA3, propertyPVALID}, // LAO LETTER MO..LAO LETTER LO LING
- {0x0EA4, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0EA5, 0x0, propertyPVALID}, // LAO LETTER LO LOOT
- {0x0EA6, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0EA7, 0x0, propertyPVALID}, // LAO LETTER WO
- {0x0EA8, 0x0EA9, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0EAA, 0x0EAB, propertyPVALID}, // LAO LETTER SO SUNG..LAO LETTER HO SUNG
- {0x0EAC, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0EAD, 0x0EB2, propertyPVALID}, // LAO LETTER O..LAO VOWEL SIGN AA
- {0x0EB3, 0x0, propertyDISALLOWED}, // LAO VOWEL SIGN AM
- {0x0EB4, 0x0EB9, propertyPVALID}, // LAO VOWEL SIGN I..LAO VOWEL SIGN UU
- {0x0EBA, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0EBB, 0x0EBD, propertyPVALID}, // LAO VOWEL SIGN MAI KON..LAO SEMIVOWEL SIGN N
- {0x0EBE, 0x0EBF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0EC0, 0x0EC4, propertyPVALID}, // LAO VOWEL SIGN E..LAO VOWEL SIGN AI
- {0x0EC5, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0EC6, 0x0, propertyPVALID}, // LAO KO LA
- {0x0EC7, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0EC8, 0x0ECD, propertyPVALID}, // LAO TONE MAI EK..LAO NIGGAHITA
- {0x0ECE, 0x0ECF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0ED0, 0x0ED9, propertyPVALID}, // LAO DIGIT ZERO..LAO DIGIT NINE
- {0x0EDA, 0x0EDB, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0EDC, 0x0EDD, propertyDISALLOWED}, // LAO HO NO..LAO HO MO
- {0x0EDE, 0x0EFF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0F00, 0x0, propertyPVALID}, // TIBETAN SYLLABLE OM
- {0x0F01, 0x0F0A, propertyDISALLOWED}, // TIBETAN MARK GTER YIG MGO TRUNCATED A..TIBET
- {0x0F0B, 0x0, propertyPVALID}, // TIBETAN MARK INTERSYLLABIC TSHEG
- {0x0F0C, 0x0F17, propertyDISALLOWED}, // TIBETAN MARK DELIMITER TSHEG BSTAR..TIBETAN
- {0x0F18, 0x0F19, propertyPVALID}, // TIBETAN ASTROLOGICAL SIGN -KHYUD PA..TIBETAN
- {0x0F1A, 0x0F1F, propertyDISALLOWED}, // TIBETAN SIGN RDEL DKAR GCIG..TIBETAN SIGN RD
- {0x0F20, 0x0F29, propertyPVALID}, // TIBETAN DIGIT ZERO..TIBETAN DIGIT NINE
- {0x0F2A, 0x0F34, propertyDISALLOWED}, // TIBETAN DIGIT HALF ONE..TIBETAN MARK BSDUS R
- {0x0F35, 0x0, propertyPVALID}, // TIBETAN MARK NGAS BZUNG NYI ZLA
- {0x0F36, 0x0, propertyDISALLOWED}, // TIBETAN MARK CARET -DZUD RTAGS BZHI MIG CAN
- {0x0F37, 0x0, propertyPVALID}, // TIBETAN MARK NGAS BZUNG SGOR RTAGS
- {0x0F38, 0x0, propertyDISALLOWED}, // TIBETAN MARK CHE MGO
- {0x0F39, 0x0, propertyPVALID}, // TIBETAN MARK TSA -PHRU
- {0x0F3A, 0x0F3D, propertyDISALLOWED}, // TIBETAN MARK GUG RTAGS GYON..TIBETAN MARK AN
- {0x0F3E, 0x0F42, propertyPVALID}, // TIBETAN SIGN YAR TSHES..TIBETAN LETTER GA
- {0x0F43, 0x0, propertyDISALLOWED}, // TIBETAN LETTER GHA
- {0x0F44, 0x0F47, propertyPVALID}, // TIBETAN LETTER NGA..TIBETAN LETTER JA
- {0x0F48, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0F49, 0x0F4C, propertyPVALID}, // TIBETAN LETTER NYA..TIBETAN LETTER DDA
- {0x0F4D, 0x0, propertyDISALLOWED}, // TIBETAN LETTER DDHA
- {0x0F4E, 0x0F51, propertyPVALID}, // TIBETAN LETTER NNA..TIBETAN LETTER DA
- {0x0F52, 0x0, propertyDISALLOWED}, // TIBETAN LETTER DHA
- {0x0F53, 0x0F56, propertyPVALID}, // TIBETAN LETTER NA..TIBETAN LETTER BA
- {0x0F57, 0x0, propertyDISALLOWED}, // TIBETAN LETTER BHA
- {0x0F58, 0x0F5B, propertyPVALID}, // TIBETAN LETTER MA..TIBETAN LETTER DZA
- {0x0F5C, 0x0, propertyDISALLOWED}, // TIBETAN LETTER DZHA
- {0x0F5D, 0x0F68, propertyPVALID}, // TIBETAN LETTER WA..TIBETAN LETTER A
- {0x0F69, 0x0, propertyDISALLOWED}, // TIBETAN LETTER KSSA
- {0x0F6A, 0x0F6C, propertyPVALID}, // TIBETAN LETTER FIXED-FORM RA..TIBETAN LETTER
- {0x0F6D, 0x0F70, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0F71, 0x0F72, propertyPVALID}, // TIBETAN VOWEL SIGN AA..TIBETAN VOWEL SIGN I
- {0x0F73, 0x0, propertyDISALLOWED}, // TIBETAN VOWEL SIGN II
- {0x0F74, 0x0, propertyPVALID}, // TIBETAN VOWEL SIGN U
- {0x0F75, 0x0F79, propertyDISALLOWED}, // TIBETAN VOWEL SIGN UU..TIBETAN VOWEL SIGN VO
- {0x0F7A, 0x0F80, propertyPVALID}, // TIBETAN VOWEL SIGN E..TIBETAN VOWEL SIGN REV
- {0x0F81, 0x0, propertyDISALLOWED}, // TIBETAN VOWEL SIGN REVERSED II
- {0x0F82, 0x0F84, propertyPVALID}, // TIBETAN SIGN NYI ZLA NAA DA..TIBETAN MARK HA
- {0x0F85, 0x0, propertyDISALLOWED}, // TIBETAN MARK PALUTA
- {0x0F86, 0x0F8B, propertyPVALID}, // TIBETAN SIGN LCI RTAGS..TIBETAN SIGN GRU MED
- {0x0F8C, 0x0F8F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x0F90, 0x0F92, propertyPVALID}, // TIBETAN SUBJOINED LETTER KA..TIBETAN SUBJOIN
- {0x0F93, 0x0, propertyDISALLOWED}, // TIBETAN SUBJOINED LETTER GHA
- {0x0F94, 0x0F97, propertyPVALID}, // TIBETAN SUBJOINED LETTER NGA..TIBETAN SUBJOI
- {0x0F98, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0F99, 0x0F9C, propertyPVALID}, // TIBETAN SUBJOINED LETTER NYA..TIBETAN SUBJOI
- {0x0F9D, 0x0, propertyDISALLOWED}, // TIBETAN SUBJOINED LETTER DDHA
- {0x0F9E, 0x0FA1, propertyPVALID}, // TIBETAN SUBJOINED LETTER NNA..TIBETAN SUBJOI
- {0x0FA2, 0x0, propertyDISALLOWED}, // TIBETAN SUBJOINED LETTER DHA
- {0x0FA3, 0x0FA6, propertyPVALID}, // TIBETAN SUBJOINED LETTER NA..TIBETAN SUBJOIN
- {0x0FA7, 0x0, propertyDISALLOWED}, // TIBETAN SUBJOINED LETTER BHA
- {0x0FA8, 0x0FAB, propertyPVALID}, // TIBETAN SUBJOINED LETTER MA..TIBETAN SUBJOIN
- {0x0FAC, 0x0, propertyDISALLOWED}, // TIBETAN SUBJOINED LETTER DZHA
- {0x0FAD, 0x0FB8, propertyPVALID}, // TIBETAN SUBJOINED LETTER WA..TIBETAN SUBJOIN
- {0x0FB9, 0x0, propertyDISALLOWED}, // TIBETAN SUBJOINED LETTER KSSA
- {0x0FBA, 0x0FBC, propertyPVALID}, // TIBETAN SUBJOINED LETTER FIXED-FORM WA..TIBE
- {0x0FBD, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0FBE, 0x0FC5, propertyDISALLOWED}, // TIBETAN KU RU KHA..TIBETAN SYMBOL RDO RJE
- {0x0FC6, 0x0, propertyPVALID}, // TIBETAN SYMBOL PADMA GDAN
- {0x0FC7, 0x0FCC, propertyDISALLOWED}, // TIBETAN SYMBOL RDO RJE RGYA GRAM..TIBETAN SY
- {0x0FCD, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x0FCE, 0x0FD8, propertyDISALLOWED}, // TIBETAN SIGN RDEL NAG RDEL DKAR..LEFT-FACING
- {0x0FD9, 0x0FFF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1000, 0x1049, propertyPVALID}, // MYANMAR LETTER KA..MYANMAR DIGIT NINE
- {0x104A, 0x104F, propertyDISALLOWED}, // MYANMAR SIGN LITTLE SECTION..MYANMAR SYMBOL
- {0x1050, 0x109D, propertyPVALID}, // MYANMAR LETTER SHA..MYANMAR VOWEL SIGN AITON
- {0x109E, 0x10C5, propertyDISALLOWED}, // MYANMAR SYMBOL SHAN ONE..GEORGIAN CAPITAL LE
- {0x10C6, 0x10CF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x10D0, 0x10FA, propertyPVALID}, // GEORGIAN LETTER AN..GEORGIAN LETTER AIN
- {0x10FB, 0x10FC, propertyDISALLOWED}, // GEORGIAN PARAGRAPH SEPARATOR..MODIFIER LETTE
- {0x10FD, 0x10FF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1100, 0x11FF, propertyDISALLOWED}, // HANGUL CHOSEONG KIYEOK..HANGUL JONGSEONG SSA
- {0x1200, 0x1248, propertyPVALID}, // ETHIOPIC SYLLABLE HA..ETHIOPIC SYLLABLE QWA
- {0x1249, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x124A, 0x124D, propertyPVALID}, // ETHIOPIC SYLLABLE QWI..ETHIOPIC SYLLABLE QWE
- {0x124E, 0x124F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1250, 0x1256, propertyPVALID}, // ETHIOPIC SYLLABLE QHA..ETHIOPIC SYLLABLE QHO
- {0x1257, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x1258, 0x0, propertyPVALID}, // ETHIOPIC SYLLABLE QHWA
- {0x1259, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x125A, 0x125D, propertyPVALID}, // ETHIOPIC SYLLABLE QHWI..ETHIOPIC SYLLABLE QH
- {0x125E, 0x125F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1260, 0x1288, propertyPVALID}, // ETHIOPIC SYLLABLE BA..ETHIOPIC SYLLABLE XWA
- {0x1289, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x128A, 0x128D, propertyPVALID}, // ETHIOPIC SYLLABLE XWI..ETHIOPIC SYLLABLE XWE
- {0x128E, 0x128F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1290, 0x12B0, propertyPVALID}, // ETHIOPIC SYLLABLE NA..ETHIOPIC SYLLABLE KWA
- {0x12B1, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x12B2, 0x12B5, propertyPVALID}, // ETHIOPIC SYLLABLE KWI..ETHIOPIC SYLLABLE KWE
- {0x12B6, 0x12B7, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x12B8, 0x12BE, propertyPVALID}, // ETHIOPIC SYLLABLE KXA..ETHIOPIC SYLLABLE KXO
- {0x12BF, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x12C0, 0x0, propertyPVALID}, // ETHIOPIC SYLLABLE KXWA
- {0x12C1, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x12C2, 0x12C5, propertyPVALID}, // ETHIOPIC SYLLABLE KXWI..ETHIOPIC SYLLABLE KX
- {0x12C6, 0x12C7, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x12C8, 0x12D6, propertyPVALID}, // ETHIOPIC SYLLABLE WA..ETHIOPIC SYLLABLE PHAR
- {0x12D7, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x12D8, 0x1310, propertyPVALID}, // ETHIOPIC SYLLABLE ZA..ETHIOPIC SYLLABLE GWA
- {0x1311, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x1312, 0x1315, propertyPVALID}, // ETHIOPIC SYLLABLE GWI..ETHIOPIC SYLLABLE GWE
- {0x1316, 0x1317, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1318, 0x135A, propertyPVALID}, // ETHIOPIC SYLLABLE GGA..ETHIOPIC SYLLABLE FYA
- {0x135B, 0x135E, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x135F, 0x0, propertyPVALID}, // ETHIOPIC COMBINING GEMINATION MARK
- {0x1360, 0x137C, propertyDISALLOWED}, // ETHIOPIC SECTION MARK..ETHIOPIC NUMBER TEN T
- {0x137D, 0x137F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1380, 0x138F, propertyPVALID}, // ETHIOPIC SYLLABLE SEBATBEIT MWA..ETHIOPIC SY
- {0x1390, 0x1399, propertyDISALLOWED}, // ETHIOPIC TONAL MARK YIZET..ETHIOPIC TONAL MA
- {0x139A, 0x139F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x13A0, 0x13F4, propertyPVALID}, // CHEROKEE LETTER A..CHEROKEE LETTER YV
- {0x13F5, 0x13FF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1400, 0x0, propertyDISALLOWED}, // CANADIAN SYLLABICS HYPHEN
- {0x1401, 0x166C, propertyPVALID}, // CANADIAN SYLLABICS E..CANADIAN SYLLABICS CAR
- {0x166D, 0x166E, propertyDISALLOWED}, // CANADIAN SYLLABICS CHI SIGN..CANADIAN SYLLAB
- {0x166F, 0x167F, propertyPVALID}, // CANADIAN SYLLABICS QAI..CANADIAN SYLLABICS B
- {0x1680, 0x0, propertyDISALLOWED}, // OGHAM SPACE MARK
- {0x1681, 0x169A, propertyPVALID}, // OGHAM LETTER BEITH..OGHAM LETTER PEITH
- {0x169B, 0x169C, propertyDISALLOWED}, // OGHAM FEATHER MARK..OGHAM REVERSED FEATHER M
- {0x169D, 0x169F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x16A0, 0x16EA, propertyPVALID}, // RUNIC LETTER FEHU FEOH FE F..RUNIC LETTER X
- {0x16EB, 0x16F0, propertyDISALLOWED}, // RUNIC SINGLE PUNCTUATION..RUNIC BELGTHOR SYM
- {0x16F1, 0x16FF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1700, 0x170C, propertyPVALID}, // TAGALOG LETTER A..TAGALOG LETTER YA
- {0x170D, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x170E, 0x1714, propertyPVALID}, // TAGALOG LETTER LA..TAGALOG SIGN VIRAMA
- {0x1715, 0x171F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1720, 0x1734, propertyPVALID}, // HANUNOO LETTER A..HANUNOO SIGN PAMUDPOD
- {0x1735, 0x1736, propertyDISALLOWED}, // PHILIPPINE SINGLE PUNCTUATION..PHILIPPINE DO
- {0x1737, 0x173F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1740, 0x1753, propertyPVALID}, // BUHID LETTER A..BUHID VOWEL SIGN U
- {0x1754, 0x175F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1760, 0x176C, propertyPVALID}, // TAGBANWA LETTER A..TAGBANWA LETTER YA
- {0x176D, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x176E, 0x1770, propertyPVALID}, // TAGBANWA LETTER LA..TAGBANWA LETTER SA
- {0x1771, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x1772, 0x1773, propertyPVALID}, // TAGBANWA VOWEL SIGN I..TAGBANWA VOWEL SIGN U
- {0x1774, 0x177F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1780, 0x17B3, propertyPVALID}, // KHMER LETTER KA..KHMER INDEPENDENT VOWEL QAU
- {0x17B4, 0x17B5, propertyDISALLOWED}, // KHMER VOWEL INHERENT AQ..KHMER VOWEL INHEREN
- {0x17B6, 0x17D3, propertyPVALID}, // KHMER VOWEL SIGN AA..KHMER SIGN BATHAMASAT
- {0x17D4, 0x17D6, propertyDISALLOWED}, // KHMER SIGN KHAN..KHMER SIGN CAMNUC PII KUUH
- {0x17D7, 0x0, propertyPVALID}, // KHMER SIGN LEK TOO
- {0x17D8, 0x17DB, propertyDISALLOWED}, // KHMER SIGN BEYYAL..KHMER CURRENCY SYMBOL RIE
- {0x17DC, 0x17DD, propertyPVALID}, // KHMER SIGN AVAKRAHASANYA..KHMER SIGN ATTHACA
- {0x17DE, 0x17DF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x17E0, 0x17E9, propertyPVALID}, // KHMER DIGIT ZERO..KHMER DIGIT NINE
- {0x17EA, 0x17EF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x17F0, 0x17F9, propertyDISALLOWED}, // KHMER SYMBOL LEK ATTAK SON..KHMER SYMBOL LEK
- {0x17FA, 0x17FF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1800, 0x180E, propertyDISALLOWED}, // MONGOLIAN BIRGA..MONGOLIAN VOWEL SEPARATOR
- {0x180F, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x1810, 0x1819, propertyPVALID}, // MONGOLIAN DIGIT ZERO..MONGOLIAN DIGIT NINE
- {0x181A, 0x181F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1820, 0x1877, propertyPVALID}, // MONGOLIAN LETTER A..MONGOLIAN LETTER MANCHU
- {0x1878, 0x187F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1880, 0x18AA, propertyPVALID}, // MONGOLIAN LETTER ALI GALI ANUSVARA ONE..MONG
- {0x18AB, 0x18AF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x18B0, 0x18F5, propertyPVALID}, // CANADIAN SYLLABICS OY..CANADIAN SYLLABICS CA
- {0x18F6, 0x18FF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1900, 0x191C, propertyPVALID}, // LIMBU VOWEL-CARRIER LETTER..LIMBU LETTER HA
- {0x191D, 0x191F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1920, 0x192B, propertyPVALID}, // LIMBU VOWEL SIGN A..LIMBU SUBJOINED LETTER W
- {0x192C, 0x192F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1930, 0x193B, propertyPVALID}, // LIMBU SMALL LETTER KA..LIMBU SIGN SA-I
- {0x193C, 0x193F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1940, 0x0, propertyDISALLOWED}, // LIMBU SIGN LOO
- {0x1941, 0x1943, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1944, 0x1945, propertyDISALLOWED}, // LIMBU EXCLAMATION MARK..LIMBU QUESTION MARK
- {0x1946, 0x196D, propertyPVALID}, // LIMBU DIGIT ZERO..TAI LE LETTER AI
- {0x196E, 0x196F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1970, 0x1974, propertyPVALID}, // TAI LE LETTER TONE-2..TAI LE LETTER TONE-6
- {0x1975, 0x197F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1980, 0x19AB, propertyPVALID}, // NEW TAI LUE LETTER HIGH QA..NEW TAI LUE LETT
- {0x19AC, 0x19AF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x19B0, 0x19C9, propertyPVALID}, // NEW TAI LUE VOWEL SIGN VOWEL SHORTENER..NEW
- {0x19CA, 0x19CF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x19D0, 0x19DA, propertyPVALID}, // NEW TAI LUE DIGIT ZERO..NEW TAI LUE THAM DIG
- {0x19DB, 0x19DD, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x19DE, 0x19FF, propertyDISALLOWED}, // NEW TAI LUE SIGN LAE..KHMER SYMBOL DAP-PRAM
- {0x1A00, 0x1A1B, propertyPVALID}, // BUGINESE LETTER KA..BUGINESE VOWEL SIGN AE
- {0x1A1C, 0x1A1D, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1A1E, 0x1A1F, propertyDISALLOWED}, // BUGINESE PALLAWA..BUGINESE END OF SECTION
- {0x1A20, 0x1A5E, propertyPVALID}, // TAI THAM LETTER HIGH KA..TAI THAM CONSONANT
- {0x1A5F, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x1A60, 0x1A7C, propertyPVALID}, // TAI THAM SIGN SAKOT..TAI THAM SIGN KHUEN-LUE
- {0x1A7D, 0x1A7E, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1A7F, 0x1A89, propertyPVALID}, // TAI THAM COMBINING CRYPTOGRAMMIC DOT..TAI TH
- {0x1A8A, 0x1A8F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1A90, 0x1A99, propertyPVALID}, // TAI THAM THAM DIGIT ZERO..TAI THAM THAM DIGI
- {0x1A9A, 0x1A9F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1AA0, 0x1AA6, propertyDISALLOWED}, // TAI THAM SIGN WIANG..TAI THAM SIGN REVERSED
- {0x1AA7, 0x0, propertyPVALID}, // TAI THAM SIGN MAI YAMOK
- {0x1AA8, 0x1AAD, propertyDISALLOWED}, // TAI THAM SIGN KAAN..TAI THAM SIGN CAANG
- {0x1AAE, 0x1AFF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1B00, 0x1B4B, propertyPVALID}, // BALINESE SIGN ULU RICEM..BALINESE LETTER ASY
- {0x1B4C, 0x1B4F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1B50, 0x1B59, propertyPVALID}, // BALINESE DIGIT ZERO..BALINESE DIGIT NINE
- {0x1B5A, 0x1B6A, propertyDISALLOWED}, // BALINESE PANTI..BALINESE MUSICAL SYMBOL DANG
- {0x1B6B, 0x1B73, propertyPVALID}, // BALINESE MUSICAL SYMBOL COMBINING TEGEH..BAL
- {0x1B74, 0x1B7C, propertyDISALLOWED}, // BALINESE MUSICAL SYMBOL RIGHT-HAND OPEN DUG.
- {0x1B7D, 0x1B7F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1B80, 0x1BAA, propertyPVALID}, // SUNDANESE SIGN PANYECEK..SUNDANESE SIGN PAMA
- {0x1BAB, 0x1BAD, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1BAE, 0x1BB9, propertyPVALID}, // SUNDANESE LETTER KHA..SUNDANESE DIGIT NINE
- {0x1BBA, 0x1BFF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1C00, 0x1C37, propertyPVALID}, // LEPCHA LETTER KA..LEPCHA SIGN NUKTA
- {0x1C38, 0x1C3A, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1C3B, 0x1C3F, propertyDISALLOWED}, // LEPCHA PUNCTUATION TA-ROL..LEPCHA PUNCTUATIO
- {0x1C40, 0x1C49, propertyPVALID}, // LEPCHA DIGIT ZERO..LEPCHA DIGIT NINE
- {0x1C4A, 0x1C4C, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1C4D, 0x1C7D, propertyPVALID}, // LEPCHA LETTER TTA..OL CHIKI AHAD
- {0x1C7E, 0x1C7F, propertyDISALLOWED}, // OL CHIKI PUNCTUATION MUCAAD..OL CHIKI PUNCTU
- {0x1C80, 0x1CCF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1CD0, 0x1CD2, propertyPVALID}, // VEDIC TONE KARSHANA..VEDIC TONE PRENKHA
- {0x1CD3, 0x0, propertyDISALLOWED}, // VEDIC SIGN NIHSHVASA
- {0x1CD4, 0x1CF2, propertyPVALID}, // VEDIC SIGN YAJURVEDIC MIDLINE SVARITA..VEDIC
- {0x1CF3, 0x1CFF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1D00, 0x1D2B, propertyPVALID}, // LATIN LETTER SMALL CAPITAL A..CYRILLIC LETTE
- {0x1D2C, 0x1D2E, propertyDISALLOWED}, // MODIFIER LETTER CAPITAL A..MODIFIER LETTER C
- {0x1D2F, 0x0, propertyPVALID}, // MODIFIER LETTER CAPITAL BARRED B
- {0x1D30, 0x1D3A, propertyDISALLOWED}, // MODIFIER LETTER CAPITAL D..MODIFIER LETTER C
- {0x1D3B, 0x0, propertyPVALID}, // MODIFIER LETTER CAPITAL REVERSED N
- {0x1D3C, 0x1D4D, propertyDISALLOWED}, // MODIFIER LETTER CAPITAL O..MODIFIER LETTER S
- {0x1D4E, 0x0, propertyPVALID}, // MODIFIER LETTER SMALL TURNED I
- {0x1D4F, 0x1D6A, propertyDISALLOWED}, // MODIFIER LETTER SMALL K..GREEK SUBSCRIPT SMA
- {0x1D6B, 0x1D77, propertyPVALID}, // LATIN SMALL LETTER UE..LATIN SMALL LETTER TU
- {0x1D78, 0x0, propertyDISALLOWED}, // MODIFIER LETTER CYRILLIC EN
- {0x1D79, 0x1D9A, propertyPVALID}, // LATIN SMALL LETTER INSULAR G..LATIN SMALL LE
- {0x1D9B, 0x1DBF, propertyDISALLOWED}, // MODIFIER LETTER SMALL TURNED ALPHA..MODIFIER
- {0x1DC0, 0x1DE6, propertyPVALID}, // COMBINING DOTTED GRAVE ACCENT..COMBINING LAT
- {0x1DE7, 0x1DFC, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1DFD, 0x1DFF, propertyPVALID}, // COMBINING ALMOST EQUAL TO BELOW..COMBINING R
- {0x1E00, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER A WITH RING BELOW
- {0x1E01, 0x0, propertyPVALID}, // LATIN SMALL LETTER A WITH RING BELOW
- {0x1E02, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER B WITH DOT ABOVE
- {0x1E03, 0x0, propertyPVALID}, // LATIN SMALL LETTER B WITH DOT ABOVE
- {0x1E04, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER B WITH DOT BELOW
- {0x1E05, 0x0, propertyPVALID}, // LATIN SMALL LETTER B WITH DOT BELOW
- {0x1E06, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER B WITH LINE BELOW
- {0x1E07, 0x0, propertyPVALID}, // LATIN SMALL LETTER B WITH LINE BELOW
- {0x1E08, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER C WITH CEDILLA AND ACUT
- {0x1E09, 0x0, propertyPVALID}, // LATIN SMALL LETTER C WITH CEDILLA AND ACUTE
- {0x1E0A, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER D WITH DOT ABOVE
- {0x1E0B, 0x0, propertyPVALID}, // LATIN SMALL LETTER D WITH DOT ABOVE
- {0x1E0C, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER D WITH DOT BELOW
- {0x1E0D, 0x0, propertyPVALID}, // LATIN SMALL LETTER D WITH DOT BELOW
- {0x1E0E, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER D WITH LINE BELOW
- {0x1E0F, 0x0, propertyPVALID}, // LATIN SMALL LETTER D WITH LINE BELOW
- {0x1E10, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER D WITH CEDILLA
- {0x1E11, 0x0, propertyPVALID}, // LATIN SMALL LETTER D WITH CEDILLA
- {0x1E12, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER D WITH CIRCUMFLEX BELOW
- {0x1E13, 0x0, propertyPVALID}, // LATIN SMALL LETTER D WITH CIRCUMFLEX BELOW
- {0x1E14, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER E WITH MACRON AND GRAVE
- {0x1E15, 0x0, propertyPVALID}, // LATIN SMALL LETTER E WITH MACRON AND GRAVE
- {0x1E16, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER E WITH MACRON AND ACUTE
- {0x1E17, 0x0, propertyPVALID}, // LATIN SMALL LETTER E WITH MACRON AND ACUTE
- {0x1E18, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER E WITH CIRCUMFLEX BELOW
- {0x1E19, 0x0, propertyPVALID}, // LATIN SMALL LETTER E WITH CIRCUMFLEX BELOW
- {0x1E1A, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER E WITH TILDE BELOW
- {0x1E1B, 0x0, propertyPVALID}, // LATIN SMALL LETTER E WITH TILDE BELOW
- {0x1E1C, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER E WITH CEDILLA AND BREV
- {0x1E1D, 0x0, propertyPVALID}, // LATIN SMALL LETTER E WITH CEDILLA AND BREVE
- {0x1E1E, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER F WITH DOT ABOVE
- {0x1E1F, 0x0, propertyPVALID}, // LATIN SMALL LETTER F WITH DOT ABOVE
- {0x1E20, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER G WITH MACRON
- {0x1E21, 0x0, propertyPVALID}, // LATIN SMALL LETTER G WITH MACRON
- {0x1E22, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER H WITH DOT ABOVE
- {0x1E23, 0x0, propertyPVALID}, // LATIN SMALL LETTER H WITH DOT ABOVE
- {0x1E24, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER H WITH DOT BELOW
- {0x1E25, 0x0, propertyPVALID}, // LATIN SMALL LETTER H WITH DOT BELOW
- {0x1E26, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER H WITH DIAERESIS
- {0x1E27, 0x0, propertyPVALID}, // LATIN SMALL LETTER H WITH DIAERESIS
- {0x1E28, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER H WITH CEDILLA
- {0x1E29, 0x0, propertyPVALID}, // LATIN SMALL LETTER H WITH CEDILLA
- {0x1E2A, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER H WITH BREVE BELOW
- {0x1E2B, 0x0, propertyPVALID}, // LATIN SMALL LETTER H WITH BREVE BELOW
- {0x1E2C, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER I WITH TILDE BELOW
- {0x1E2D, 0x0, propertyPVALID}, // LATIN SMALL LETTER I WITH TILDE BELOW
- {0x1E2E, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER I WITH DIAERESIS AND AC
- {0x1E2F, 0x0, propertyPVALID}, // LATIN SMALL LETTER I WITH DIAERESIS AND ACUT
- {0x1E30, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER K WITH ACUTE
- {0x1E31, 0x0, propertyPVALID}, // LATIN SMALL LETTER K WITH ACUTE
- {0x1E32, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER K WITH DOT BELOW
- {0x1E33, 0x0, propertyPVALID}, // LATIN SMALL LETTER K WITH DOT BELOW
- {0x1E34, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER K WITH LINE BELOW
- {0x1E35, 0x0, propertyPVALID}, // LATIN SMALL LETTER K WITH LINE BELOW
- {0x1E36, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER L WITH DOT BELOW
- {0x1E37, 0x0, propertyPVALID}, // LATIN SMALL LETTER L WITH DOT BELOW
- {0x1E38, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER L WITH DOT BELOW AND MA
- {0x1E39, 0x0, propertyPVALID}, // LATIN SMALL LETTER L WITH DOT BELOW AND MACR
- {0x1E3A, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER L WITH LINE BELOW
- {0x1E3B, 0x0, propertyPVALID}, // LATIN SMALL LETTER L WITH LINE BELOW
- {0x1E3C, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER L WITH CIRCUMFLEX BELOW
- {0x1E3D, 0x0, propertyPVALID}, // LATIN SMALL LETTER L WITH CIRCUMFLEX BELOW
- {0x1E3E, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER M WITH ACUTE
- {0x1E3F, 0x0, propertyPVALID}, // LATIN SMALL LETTER M WITH ACUTE
- {0x1E40, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER M WITH DOT ABOVE
- {0x1E41, 0x0, propertyPVALID}, // LATIN SMALL LETTER M WITH DOT ABOVE
- {0x1E42, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER M WITH DOT BELOW
- {0x1E43, 0x0, propertyPVALID}, // LATIN SMALL LETTER M WITH DOT BELOW
- {0x1E44, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER N WITH DOT ABOVE
- {0x1E45, 0x0, propertyPVALID}, // LATIN SMALL LETTER N WITH DOT ABOVE
- {0x1E46, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER N WITH DOT BELOW
- {0x1E47, 0x0, propertyPVALID}, // LATIN SMALL LETTER N WITH DOT BELOW
- {0x1E48, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER N WITH LINE BELOW
- {0x1E49, 0x0, propertyPVALID}, // LATIN SMALL LETTER N WITH LINE BELOW
- {0x1E4A, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER N WITH CIRCUMFLEX BELOW
- {0x1E4B, 0x0, propertyPVALID}, // LATIN SMALL LETTER N WITH CIRCUMFLEX BELOW
- {0x1E4C, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER O WITH TILDE AND ACUTE
- {0x1E4D, 0x0, propertyPVALID}, // LATIN SMALL LETTER O WITH TILDE AND ACUTE
- {0x1E4E, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER O WITH TILDE AND DIAERE
- {0x1E4F, 0x0, propertyPVALID}, // LATIN SMALL LETTER O WITH TILDE AND DIAERESI
- {0x1E50, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER O WITH MACRON AND GRAVE
- {0x1E51, 0x0, propertyPVALID}, // LATIN SMALL LETTER O WITH MACRON AND GRAVE
- {0x1E52, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER O WITH MACRON AND ACUTE
- {0x1E53, 0x0, propertyPVALID}, // LATIN SMALL LETTER O WITH MACRON AND ACUTE
- {0x1E54, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER P WITH ACUTE
- {0x1E55, 0x0, propertyPVALID}, // LATIN SMALL LETTER P WITH ACUTE
- {0x1E56, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER P WITH DOT ABOVE
- {0x1E57, 0x0, propertyPVALID}, // LATIN SMALL LETTER P WITH DOT ABOVE
- {0x1E58, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER R WITH DOT ABOVE
- {0x1E59, 0x0, propertyPVALID}, // LATIN SMALL LETTER R WITH DOT ABOVE
- {0x1E5A, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER R WITH DOT BELOW
- {0x1E5B, 0x0, propertyPVALID}, // LATIN SMALL LETTER R WITH DOT BELOW
- {0x1E5C, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER R WITH DOT BELOW AND MA
- {0x1E5D, 0x0, propertyPVALID}, // LATIN SMALL LETTER R WITH DOT BELOW AND MACR
- {0x1E5E, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER R WITH LINE BELOW
- {0x1E5F, 0x0, propertyPVALID}, // LATIN SMALL LETTER R WITH LINE BELOW
- {0x1E60, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER S WITH DOT ABOVE
- {0x1E61, 0x0, propertyPVALID}, // LATIN SMALL LETTER S WITH DOT ABOVE
- {0x1E62, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER S WITH DOT BELOW
- {0x1E63, 0x0, propertyPVALID}, // LATIN SMALL LETTER S WITH DOT BELOW
- {0x1E64, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER S WITH ACUTE AND DOT AB
- {0x1E65, 0x0, propertyPVALID}, // LATIN SMALL LETTER S WITH ACUTE AND DOT ABOV
- {0x1E66, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER S WITH CARON AND DOT AB
- {0x1E67, 0x0, propertyPVALID}, // LATIN SMALL LETTER S WITH CARON AND DOT ABOV
- {0x1E68, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER S WITH DOT BELOW AND DO
- {0x1E69, 0x0, propertyPVALID}, // LATIN SMALL LETTER S WITH DOT BELOW AND DOT
- {0x1E6A, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER T WITH DOT ABOVE
- {0x1E6B, 0x0, propertyPVALID}, // LATIN SMALL LETTER T WITH DOT ABOVE
- {0x1E6C, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER T WITH DOT BELOW
- {0x1E6D, 0x0, propertyPVALID}, // LATIN SMALL LETTER T WITH DOT BELOW
- {0x1E6E, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER T WITH LINE BELOW
- {0x1E6F, 0x0, propertyPVALID}, // LATIN SMALL LETTER T WITH LINE BELOW
- {0x1E70, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER T WITH CIRCUMFLEX BELOW
- {0x1E71, 0x0, propertyPVALID}, // LATIN SMALL LETTER T WITH CIRCUMFLEX BELOW
- {0x1E72, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER U WITH DIAERESIS BELOW
- {0x1E73, 0x0, propertyPVALID}, // LATIN SMALL LETTER U WITH DIAERESIS BELOW
- {0x1E74, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER U WITH TILDE BELOW
- {0x1E75, 0x0, propertyPVALID}, // LATIN SMALL LETTER U WITH TILDE BELOW
- {0x1E76, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER U WITH CIRCUMFLEX BELOW
- {0x1E77, 0x0, propertyPVALID}, // LATIN SMALL LETTER U WITH CIRCUMFLEX BELOW
- {0x1E78, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER U WITH TILDE AND ACUTE
- {0x1E79, 0x0, propertyPVALID}, // LATIN SMALL LETTER U WITH TILDE AND ACUTE
- {0x1E7A, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER U WITH MACRON AND DIAER
- {0x1E7B, 0x0, propertyPVALID}, // LATIN SMALL LETTER U WITH MACRON AND DIAERES
- {0x1E7C, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER V WITH TILDE
- {0x1E7D, 0x0, propertyPVALID}, // LATIN SMALL LETTER V WITH TILDE
- {0x1E7E, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER V WITH DOT BELOW
- {0x1E7F, 0x0, propertyPVALID}, // LATIN SMALL LETTER V WITH DOT BELOW
- {0x1E80, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER W WITH GRAVE
- {0x1E81, 0x0, propertyPVALID}, // LATIN SMALL LETTER W WITH GRAVE
- {0x1E82, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER W WITH ACUTE
- {0x1E83, 0x0, propertyPVALID}, // LATIN SMALL LETTER W WITH ACUTE
- {0x1E84, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER W WITH DIAERESIS
- {0x1E85, 0x0, propertyPVALID}, // LATIN SMALL LETTER W WITH DIAERESIS
- {0x1E86, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER W WITH DOT ABOVE
- {0x1E87, 0x0, propertyPVALID}, // LATIN SMALL LETTER W WITH DOT ABOVE
- {0x1E88, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER W WITH DOT BELOW
- {0x1E89, 0x0, propertyPVALID}, // LATIN SMALL LETTER W WITH DOT BELOW
- {0x1E8A, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER X WITH DOT ABOVE
- {0x1E8B, 0x0, propertyPVALID}, // LATIN SMALL LETTER X WITH DOT ABOVE
- {0x1E8C, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER X WITH DIAERESIS
- {0x1E8D, 0x0, propertyPVALID}, // LATIN SMALL LETTER X WITH DIAERESIS
- {0x1E8E, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER Y WITH DOT ABOVE
- {0x1E8F, 0x0, propertyPVALID}, // LATIN SMALL LETTER Y WITH DOT ABOVE
- {0x1E90, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER Z WITH CIRCUMFLEX
- {0x1E91, 0x0, propertyPVALID}, // LATIN SMALL LETTER Z WITH CIRCUMFLEX
- {0x1E92, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER Z WITH DOT BELOW
- {0x1E93, 0x0, propertyPVALID}, // LATIN SMALL LETTER Z WITH DOT BELOW
- {0x1E94, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER Z WITH LINE BELOW
- {0x1E95, 0x1E99, propertyPVALID}, // LATIN SMALL LETTER Z WITH LINE BELOW..LATIN
- {0x1E9A, 0x1E9B, propertyDISALLOWED}, // LATIN SMALL LETTER A WITH RIGHT HALF RING..L
- {0x1E9C, 0x1E9D, propertyPVALID}, // LATIN SMALL LETTER LONG S WITH DIAGONAL STRO
- {0x1E9E, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER SHARP S
- {0x1E9F, 0x0, propertyPVALID}, // LATIN SMALL LETTER DELTA
- {0x1EA0, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER A WITH DOT BELOW
- {0x1EA1, 0x0, propertyPVALID}, // LATIN SMALL LETTER A WITH DOT BELOW
- {0x1EA2, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER A WITH HOOK ABOVE
- {0x1EA3, 0x0, propertyPVALID}, // LATIN SMALL LETTER A WITH HOOK ABOVE
- {0x1EA4, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND A
- {0x1EA5, 0x0, propertyPVALID}, // LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACU
- {0x1EA6, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND G
- {0x1EA7, 0x0, propertyPVALID}, // LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRA
- {0x1EA8, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND H
- {0x1EA9, 0x0, propertyPVALID}, // LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOO
- {0x1EAA, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND T
- {0x1EAB, 0x0, propertyPVALID}, // LATIN SMALL LETTER A WITH CIRCUMFLEX AND TIL
- {0x1EAC, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND D
- {0x1EAD, 0x0, propertyPVALID}, // LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT
- {0x1EAE, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER A WITH BREVE AND ACUTE
- {0x1EAF, 0x0, propertyPVALID}, // LATIN SMALL LETTER A WITH BREVE AND ACUTE
- {0x1EB0, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER A WITH BREVE AND GRAVE
- {0x1EB1, 0x0, propertyPVALID}, // LATIN SMALL LETTER A WITH BREVE AND GRAVE
- {0x1EB2, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER A WITH BREVE AND HOOK A
- {0x1EB3, 0x0, propertyPVALID}, // LATIN SMALL LETTER A WITH BREVE AND HOOK ABO
- {0x1EB4, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER A WITH BREVE AND TILDE
- {0x1EB5, 0x0, propertyPVALID}, // LATIN SMALL LETTER A WITH BREVE AND TILDE
- {0x1EB6, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER A WITH BREVE AND DOT BE
- {0x1EB7, 0x0, propertyPVALID}, // LATIN SMALL LETTER A WITH BREVE AND DOT BELO
- {0x1EB8, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER E WITH DOT BELOW
- {0x1EB9, 0x0, propertyPVALID}, // LATIN SMALL LETTER E WITH DOT BELOW
- {0x1EBA, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER E WITH HOOK ABOVE
- {0x1EBB, 0x0, propertyPVALID}, // LATIN SMALL LETTER E WITH HOOK ABOVE
- {0x1EBC, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER E WITH TILDE
- {0x1EBD, 0x0, propertyPVALID}, // LATIN SMALL LETTER E WITH TILDE
- {0x1EBE, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND A
- {0x1EBF, 0x0, propertyPVALID}, // LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACU
- {0x1EC0, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND G
- {0x1EC1, 0x0, propertyPVALID}, // LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRA
- {0x1EC2, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND H
- {0x1EC3, 0x0, propertyPVALID}, // LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOO
- {0x1EC4, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND T
- {0x1EC5, 0x0, propertyPVALID}, // LATIN SMALL LETTER E WITH CIRCUMFLEX AND TIL
- {0x1EC6, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND D
- {0x1EC7, 0x0, propertyPVALID}, // LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT
- {0x1EC8, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER I WITH HOOK ABOVE
- {0x1EC9, 0x0, propertyPVALID}, // LATIN SMALL LETTER I WITH HOOK ABOVE
- {0x1ECA, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER I WITH DOT BELOW
- {0x1ECB, 0x0, propertyPVALID}, // LATIN SMALL LETTER I WITH DOT BELOW
- {0x1ECC, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER O WITH DOT BELOW
- {0x1ECD, 0x0, propertyPVALID}, // LATIN SMALL LETTER O WITH DOT BELOW
- {0x1ECE, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER O WITH HOOK ABOVE
- {0x1ECF, 0x0, propertyPVALID}, // LATIN SMALL LETTER O WITH HOOK ABOVE
- {0x1ED0, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND A
- {0x1ED1, 0x0, propertyPVALID}, // LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACU
- {0x1ED2, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND G
- {0x1ED3, 0x0, propertyPVALID}, // LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRA
- {0x1ED4, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND H
- {0x1ED5, 0x0, propertyPVALID}, // LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOO
- {0x1ED6, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND T
- {0x1ED7, 0x0, propertyPVALID}, // LATIN SMALL LETTER O WITH CIRCUMFLEX AND TIL
- {0x1ED8, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND D
- {0x1ED9, 0x0, propertyPVALID}, // LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT
- {0x1EDA, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER O WITH HORN AND ACUTE
- {0x1EDB, 0x0, propertyPVALID}, // LATIN SMALL LETTER O WITH HORN AND ACUTE
- {0x1EDC, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER O WITH HORN AND GRAVE
- {0x1EDD, 0x0, propertyPVALID}, // LATIN SMALL LETTER O WITH HORN AND GRAVE
- {0x1EDE, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER O WITH HORN AND HOOK AB
- {0x1EDF, 0x0, propertyPVALID}, // LATIN SMALL LETTER O WITH HORN AND HOOK ABOV
- {0x1EE0, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER O WITH HORN AND TILDE
- {0x1EE1, 0x0, propertyPVALID}, // LATIN SMALL LETTER O WITH HORN AND TILDE
- {0x1EE2, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER O WITH HORN AND DOT BEL
- {0x1EE3, 0x0, propertyPVALID}, // LATIN SMALL LETTER O WITH HORN AND DOT BELOW
- {0x1EE4, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER U WITH DOT BELOW
- {0x1EE5, 0x0, propertyPVALID}, // LATIN SMALL LETTER U WITH DOT BELOW
- {0x1EE6, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER U WITH HOOK ABOVE
- {0x1EE7, 0x0, propertyPVALID}, // LATIN SMALL LETTER U WITH HOOK ABOVE
- {0x1EE8, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER U WITH HORN AND ACUTE
- {0x1EE9, 0x0, propertyPVALID}, // LATIN SMALL LETTER U WITH HORN AND ACUTE
- {0x1EEA, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER U WITH HORN AND GRAVE
- {0x1EEB, 0x0, propertyPVALID}, // LATIN SMALL LETTER U WITH HORN AND GRAVE
- {0x1EEC, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER U WITH HORN AND HOOK AB
- {0x1EED, 0x0, propertyPVALID}, // LATIN SMALL LETTER U WITH HORN AND HOOK ABOV
- {0x1EEE, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER U WITH HORN AND TILDE
- {0x1EEF, 0x0, propertyPVALID}, // LATIN SMALL LETTER U WITH HORN AND TILDE
- {0x1EF0, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER U WITH HORN AND DOT BEL
- {0x1EF1, 0x0, propertyPVALID}, // LATIN SMALL LETTER U WITH HORN AND DOT BELOW
- {0x1EF2, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER Y WITH GRAVE
- {0x1EF3, 0x0, propertyPVALID}, // LATIN SMALL LETTER Y WITH GRAVE
- {0x1EF4, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER Y WITH DOT BELOW
- {0x1EF5, 0x0, propertyPVALID}, // LATIN SMALL LETTER Y WITH DOT BELOW
- {0x1EF6, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER Y WITH HOOK ABOVE
- {0x1EF7, 0x0, propertyPVALID}, // LATIN SMALL LETTER Y WITH HOOK ABOVE
- {0x1EF8, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER Y WITH TILDE
- {0x1EF9, 0x0, propertyPVALID}, // LATIN SMALL LETTER Y WITH TILDE
- {0x1EFA, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER MIDDLE-WELSH LL
- {0x1EFB, 0x0, propertyPVALID}, // LATIN SMALL LETTER MIDDLE-WELSH LL
- {0x1EFC, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER MIDDLE-WELSH V
- {0x1EFD, 0x0, propertyPVALID}, // LATIN SMALL LETTER MIDDLE-WELSH V
- {0x1EFE, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER Y WITH LOOP
- {0x1EFF, 0x1F07, propertyPVALID}, // LATIN SMALL LETTER Y WITH LOOP..GREEK SMALL
- {0x1F08, 0x1F0F, propertyDISALLOWED}, // GREEK CAPITAL LETTER ALPHA WITH PSILI..GREEK
- {0x1F10, 0x1F15, propertyPVALID}, // GREEK SMALL LETTER EPSILON WITH PSILI..GREEK
- {0x1F16, 0x1F17, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1F18, 0x1F1D, propertyDISALLOWED}, // GREEK CAPITAL LETTER EPSILON WITH PSILI..GRE
- {0x1F1E, 0x1F1F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1F20, 0x1F27, propertyPVALID}, // GREEK SMALL LETTER ETA WITH PSILI..GREEK SMA
- {0x1F28, 0x1F2F, propertyDISALLOWED}, // GREEK CAPITAL LETTER ETA WITH PSILI..GREEK C
- {0x1F30, 0x1F37, propertyPVALID}, // GREEK SMALL LETTER IOTA WITH PSILI..GREEK SM
- {0x1F38, 0x1F3F, propertyDISALLOWED}, // GREEK CAPITAL LETTER IOTA WITH PSILI..GREEK
- {0x1F40, 0x1F45, propertyPVALID}, // GREEK SMALL LETTER OMICRON WITH PSILI..GREEK
- {0x1F46, 0x1F47, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1F48, 0x1F4D, propertyDISALLOWED}, // GREEK CAPITAL LETTER OMICRON WITH PSILI..GRE
- {0x1F4E, 0x1F4F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1F50, 0x1F57, propertyPVALID}, // GREEK SMALL LETTER UPSILON WITH PSILI..GREEK
- {0x1F58, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x1F59, 0x0, propertyDISALLOWED}, // GREEK CAPITAL LETTER UPSILON WITH DASIA
- {0x1F5A, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x1F5B, 0x0, propertyDISALLOWED}, // GREEK CAPITAL LETTER UPSILON WITH DASIA AND
- {0x1F5C, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x1F5D, 0x0, propertyDISALLOWED}, // GREEK CAPITAL LETTER UPSILON WITH DASIA AND
- {0x1F5E, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x1F5F, 0x0, propertyDISALLOWED}, // GREEK CAPITAL LETTER UPSILON WITH DASIA AND
- {0x1F60, 0x1F67, propertyPVALID}, // GREEK SMALL LETTER OMEGA WITH PSILI..GREEK S
- {0x1F68, 0x1F6F, propertyDISALLOWED}, // GREEK CAPITAL LETTER OMEGA WITH PSILI..GREEK
- {0x1F70, 0x0, propertyPVALID}, // GREEK SMALL LETTER ALPHA WITH VARIA
- {0x1F71, 0x0, propertyDISALLOWED}, // GREEK SMALL LETTER ALPHA WITH OXIA
- {0x1F72, 0x0, propertyPVALID}, // GREEK SMALL LETTER EPSILON WITH VARIA
- {0x1F73, 0x0, propertyDISALLOWED}, // GREEK SMALL LETTER EPSILON WITH OXIA
- {0x1F74, 0x0, propertyPVALID}, // GREEK SMALL LETTER ETA WITH VARIA
- {0x1F75, 0x0, propertyDISALLOWED}, // GREEK SMALL LETTER ETA WITH OXIA
- {0x1F76, 0x0, propertyPVALID}, // GREEK SMALL LETTER IOTA WITH VARIA
- {0x1F77, 0x0, propertyDISALLOWED}, // GREEK SMALL LETTER IOTA WITH OXIA
- {0x1F78, 0x0, propertyPVALID}, // GREEK SMALL LETTER OMICRON WITH VARIA
- {0x1F79, 0x0, propertyDISALLOWED}, // GREEK SMALL LETTER OMICRON WITH OXIA
- {0x1F7A, 0x0, propertyPVALID}, // GREEK SMALL LETTER UPSILON WITH VARIA
- {0x1F7B, 0x0, propertyDISALLOWED}, // GREEK SMALL LETTER UPSILON WITH OXIA
- {0x1F7C, 0x0, propertyPVALID}, // GREEK SMALL LETTER OMEGA WITH VARIA
- {0x1F7D, 0x0, propertyDISALLOWED}, // GREEK SMALL LETTER OMEGA WITH OXIA
- {0x1F7E, 0x1F7F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1F80, 0x1FAF, propertyDISALLOWED}, // GREEK SMALL LETTER ALPHA WITH PSILI AND YPOG
- {0x1FB0, 0x1FB1, propertyPVALID}, // GREEK SMALL LETTER ALPHA WITH VRACHY..GREEK
- {0x1FB2, 0x1FB4, propertyDISALLOWED}, // GREEK SMALL LETTER ALPHA WITH VARIA AND YPOG
- {0x1FB5, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x1FB6, 0x0, propertyPVALID}, // GREEK SMALL LETTER ALPHA WITH PERISPOMENI
- {0x1FB7, 0x1FC4, propertyDISALLOWED}, // GREEK SMALL LETTER ALPHA WITH PERISPOMENI AN
- {0x1FC5, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x1FC6, 0x0, propertyPVALID}, // GREEK SMALL LETTER ETA WITH PERISPOMENI
- {0x1FC7, 0x1FCF, propertyDISALLOWED}, // GREEK SMALL LETTER ETA WITH PERISPOMENI AND
- {0x1FD0, 0x1FD2, propertyPVALID}, // GREEK SMALL LETTER IOTA WITH VRACHY..GREEK S
- {0x1FD3, 0x0, propertyDISALLOWED}, // GREEK SMALL LETTER IOTA WITH DIALYTIKA AND O
- {0x1FD4, 0x1FD5, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1FD6, 0x1FD7, propertyPVALID}, // GREEK SMALL LETTER IOTA WITH PERISPOMENI..GR
- {0x1FD8, 0x1FDB, propertyDISALLOWED}, // GREEK CAPITAL LETTER IOTA WITH VRACHY..GREEK
- {0x1FDC, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x1FDD, 0x1FDF, propertyDISALLOWED}, // GREEK DASIA AND VARIA..GREEK DASIA AND PERIS
- {0x1FE0, 0x1FE2, propertyPVALID}, // GREEK SMALL LETTER UPSILON WITH VRACHY..GREE
- {0x1FE3, 0x0, propertyDISALLOWED}, // GREEK SMALL LETTER UPSILON WITH DIALYTIKA AN
- {0x1FE4, 0x1FE7, propertyPVALID}, // GREEK SMALL LETTER RHO WITH PSILI..GREEK SMA
- {0x1FE8, 0x1FEF, propertyDISALLOWED}, // GREEK CAPITAL LETTER UPSILON WITH VRACHY..GR
- {0x1FF0, 0x1FF1, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1FF2, 0x1FF4, propertyDISALLOWED}, // GREEK SMALL LETTER OMEGA WITH VARIA AND YPOG
- {0x1FF5, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x1FF6, 0x0, propertyPVALID}, // GREEK SMALL LETTER OMEGA WITH PERISPOMENI
- {0x1FF7, 0x1FFE, propertyDISALLOWED}, // GREEK SMALL LETTER OMEGA WITH PERISPOMENI AN
- {0x1FFF, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x2000, 0x200B, propertyDISALLOWED}, // EN QUAD..ZERO WIDTH SPACE
- {0x200C, 0x200D, propertyCONTEXTJ}, // ZERO WIDTH NON-JOINER..ZERO WIDTH JOINER
- {0x200E, 0x2064, propertyDISALLOWED}, // LEFT-TO-RIGHT MARK..INVISIBLE PLUS
- {0x2065, 0x2069, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x206A, 0x2071, propertyDISALLOWED}, // INHIBIT SYMMETRIC SWAPPING..SUPERSCRIPT LATI
- {0x2072, 0x2073, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x2074, 0x208E, propertyDISALLOWED}, // SUPERSCRIPT FOUR..SUBSCRIPT RIGHT PARENTHESI
- {0x208F, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x2090, 0x2094, propertyDISALLOWED}, // LATIN SUBSCRIPT SMALL LETTER A..LATIN SUBSCR
- {0x2095, 0x209F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x20A0, 0x20B8, propertyDISALLOWED}, // EURO-CURRENCY SIGN..TENGE SIGN
- {0x20B9, 0x20CF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x20D0, 0x20F0, propertyDISALLOWED}, // COMBINING LEFT HARPOON ABOVE..COMBINING ASTE
- {0x20F1, 0x20FF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x2100, 0x214D, propertyDISALLOWED}, // ACCOUNT OF..AKTIESELSKAB
- {0x214E, 0x0, propertyPVALID}, // TURNED SMALL F
- {0x214F, 0x2183, propertyDISALLOWED}, // SYMBOL FOR SAMARITAN SOURCE..ROMAN NUMERAL R
- {0x2184, 0x0, propertyPVALID}, // LATIN SMALL LETTER REVERSED C
- {0x2185, 0x2189, propertyDISALLOWED}, // ROMAN NUMERAL SIX LATE FORM..VULGAR FRACTION
- {0x218A, 0x218F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x2190, 0x23E8, propertyDISALLOWED}, // LEFTWARDS ARROW..DECIMAL EXPONENT SYMBOL
- {0x23E9, 0x23FF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x2400, 0x2426, propertyDISALLOWED}, // SYMBOL FOR NULL..SYMBOL FOR SUBSTITUTE FORM
- {0x2427, 0x243F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x2440, 0x244A, propertyDISALLOWED}, // OCR HOOK..OCR DOUBLE BACKSLASH
- {0x244B, 0x245F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x2460, 0x26CD, propertyDISALLOWED}, // CIRCLED DIGIT ONE..DISABLED CAR
- {0x26CE, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x26CF, 0x26E1, propertyDISALLOWED}, // PICK..RESTRICTED LEFT ENTRY-2
- {0x26E2, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x26E3, 0x0, propertyDISALLOWED}, // HEAVY CIRCLE WITH STROKE AND TWO DOTS ABOVE
- {0x26E4, 0x26E7, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x26E8, 0x26FF, propertyDISALLOWED}, // BLACK CROSS ON SHIELD..WHITE FLAG WITH HORIZ
- {0x2700, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x2701, 0x2704, propertyDISALLOWED}, // UPPER BLADE SCISSORS..WHITE SCISSORS
- {0x2705, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x2706, 0x2709, propertyDISALLOWED}, // TELEPHONE LOCATION SIGN..ENVELOPE
- {0x270A, 0x270B, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x270C, 0x2727, propertyDISALLOWED}, // VICTORY HAND..WHITE FOUR POINTED STAR
- {0x2728, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x2729, 0x274B, propertyDISALLOWED}, // STRESS OUTLINED WHITE STAR..HEAVY EIGHT TEAR
- {0x274C, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x274D, 0x0, propertyDISALLOWED}, // SHADOWED WHITE CIRCLE
- {0x274E, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x274F, 0x2752, propertyDISALLOWED}, // LOWER RIGHT DROP-SHADOWED WHITE SQUARE..UPPE
- {0x2753, 0x2755, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x2756, 0x275E, propertyDISALLOWED}, // BLACK DIAMOND MINUS WHITE X..HEAVY DOUBLE CO
- {0x275F, 0x2760, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x2761, 0x2794, propertyDISALLOWED}, // CURVED STEM PARAGRAPH SIGN ORNAMENT..HEAVY W
- {0x2795, 0x2797, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x2798, 0x27AF, propertyDISALLOWED}, // HEAVY SOUTH EAST ARROW..NOTCHED LOWER RIGHT-
- {0x27B0, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x27B1, 0x27BE, propertyDISALLOWED}, // NOTCHED UPPER RIGHT-SHADOWED WHITE RIGHTWARD
- {0x27BF, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x27C0, 0x27CA, propertyDISALLOWED}, // THREE DIMENSIONAL ANGLE..VERTICAL BAR WITH H
- {0x27CB, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x27CC, 0x0, propertyDISALLOWED}, // LONG DIVISION
- {0x27CD, 0x27CF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x27D0, 0x2B4C, propertyDISALLOWED}, // WHITE DIAMOND WITH CENTRED DOT..RIGHTWARDS A
- {0x2B4D, 0x2B4F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x2B50, 0x2B59, propertyDISALLOWED}, // WHITE MEDIUM STAR..HEAVY CIRCLED SALTIRE
- {0x2B5A, 0x2BFF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x2C00, 0x2C2E, propertyDISALLOWED}, // GLAGOLITIC CAPITAL LETTER AZU..GLAGOLITIC CA
- {0x2C2F, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x2C30, 0x2C5E, propertyPVALID}, // GLAGOLITIC SMALL LETTER AZU..GLAGOLITIC SMAL
- {0x2C5F, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x2C60, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER L WITH DOUBLE BAR
- {0x2C61, 0x0, propertyPVALID}, // LATIN SMALL LETTER L WITH DOUBLE BAR
- {0x2C62, 0x2C64, propertyDISALLOWED}, // LATIN CAPITAL LETTER L WITH MIDDLE TILDE..LA
- {0x2C65, 0x2C66, propertyPVALID}, // LATIN SMALL LETTER A WITH STROKE..LATIN SMAL
- {0x2C67, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER H WITH DESCENDER
- {0x2C68, 0x0, propertyPVALID}, // LATIN SMALL LETTER H WITH DESCENDER
- {0x2C69, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER K WITH DESCENDER
- {0x2C6A, 0x0, propertyPVALID}, // LATIN SMALL LETTER K WITH DESCENDER
- {0x2C6B, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER Z WITH DESCENDER
- {0x2C6C, 0x0, propertyPVALID}, // LATIN SMALL LETTER Z WITH DESCENDER
- {0x2C6D, 0x2C70, propertyDISALLOWED}, // LATIN CAPITAL LETTER ALPHA..LATIN CAPITAL LE
- {0x2C71, 0x0, propertyPVALID}, // LATIN SMALL LETTER V WITH RIGHT HOOK
- {0x2C72, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER W WITH HOOK
- {0x2C73, 0x2C74, propertyPVALID}, // LATIN SMALL LETTER W WITH HOOK..LATIN SMALL
- {0x2C75, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER HALF H
- {0x2C76, 0x2C7B, propertyPVALID}, // LATIN SMALL LETTER HALF H..LATIN LETTER SMAL
- {0x2C7C, 0x2C80, propertyDISALLOWED}, // LATIN SUBSCRIPT SMALL LETTER J..COPTIC CAPIT
- {0x2C81, 0x0, propertyPVALID}, // COPTIC SMALL LETTER ALFA
- {0x2C82, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER VIDA
- {0x2C83, 0x0, propertyPVALID}, // COPTIC SMALL LETTER VIDA
- {0x2C84, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER GAMMA
- {0x2C85, 0x0, propertyPVALID}, // COPTIC SMALL LETTER GAMMA
- {0x2C86, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER DALDA
- {0x2C87, 0x0, propertyPVALID}, // COPTIC SMALL LETTER DALDA
- {0x2C88, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER EIE
- {0x2C89, 0x0, propertyPVALID}, // COPTIC SMALL LETTER EIE
- {0x2C8A, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER SOU
- {0x2C8B, 0x0, propertyPVALID}, // COPTIC SMALL LETTER SOU
- {0x2C8C, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER ZATA
- {0x2C8D, 0x0, propertyPVALID}, // COPTIC SMALL LETTER ZATA
- {0x2C8E, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER HATE
- {0x2C8F, 0x0, propertyPVALID}, // COPTIC SMALL LETTER HATE
- {0x2C90, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER THETHE
- {0x2C91, 0x0, propertyPVALID}, // COPTIC SMALL LETTER THETHE
- {0x2C92, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER IAUDA
- {0x2C93, 0x0, propertyPVALID}, // COPTIC SMALL LETTER IAUDA
- {0x2C94, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER KAPA
- {0x2C95, 0x0, propertyPVALID}, // COPTIC SMALL LETTER KAPA
- {0x2C96, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER LAULA
- {0x2C97, 0x0, propertyPVALID}, // COPTIC SMALL LETTER LAULA
- {0x2C98, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER MI
- {0x2C99, 0x0, propertyPVALID}, // COPTIC SMALL LETTER MI
- {0x2C9A, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER NI
- {0x2C9B, 0x0, propertyPVALID}, // COPTIC SMALL LETTER NI
- {0x2C9C, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER KSI
- {0x2C9D, 0x0, propertyPVALID}, // COPTIC SMALL LETTER KSI
- {0x2C9E, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER O
- {0x2C9F, 0x0, propertyPVALID}, // COPTIC SMALL LETTER O
- {0x2CA0, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER PI
- {0x2CA1, 0x0, propertyPVALID}, // COPTIC SMALL LETTER PI
- {0x2CA2, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER RO
- {0x2CA3, 0x0, propertyPVALID}, // COPTIC SMALL LETTER RO
- {0x2CA4, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER SIMA
- {0x2CA5, 0x0, propertyPVALID}, // COPTIC SMALL LETTER SIMA
- {0x2CA6, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER TAU
- {0x2CA7, 0x0, propertyPVALID}, // COPTIC SMALL LETTER TAU
- {0x2CA8, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER UA
- {0x2CA9, 0x0, propertyPVALID}, // COPTIC SMALL LETTER UA
- {0x2CAA, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER FI
- {0x2CAB, 0x0, propertyPVALID}, // COPTIC SMALL LETTER FI
- {0x2CAC, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER KHI
- {0x2CAD, 0x0, propertyPVALID}, // COPTIC SMALL LETTER KHI
- {0x2CAE, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER PSI
- {0x2CAF, 0x0, propertyPVALID}, // COPTIC SMALL LETTER PSI
- {0x2CB0, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER OOU
- {0x2CB1, 0x0, propertyPVALID}, // COPTIC SMALL LETTER OOU
- {0x2CB2, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER DIALECT-P ALEF
- {0x2CB3, 0x0, propertyPVALID}, // COPTIC SMALL LETTER DIALECT-P ALEF
- {0x2CB4, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER OLD COPTIC AIN
- {0x2CB5, 0x0, propertyPVALID}, // COPTIC SMALL LETTER OLD COPTIC AIN
- {0x2CB6, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER CRYPTOGRAMMIC EIE
- {0x2CB7, 0x0, propertyPVALID}, // COPTIC SMALL LETTER CRYPTOGRAMMIC EIE
- {0x2CB8, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER DIALECT-P KAPA
- {0x2CB9, 0x0, propertyPVALID}, // COPTIC SMALL LETTER DIALECT-P KAPA
- {0x2CBA, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER DIALECT-P NI
- {0x2CBB, 0x0, propertyPVALID}, // COPTIC SMALL LETTER DIALECT-P NI
- {0x2CBC, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER CRYPTOGRAMMIC NI
- {0x2CBD, 0x0, propertyPVALID}, // COPTIC SMALL LETTER CRYPTOGRAMMIC NI
- {0x2CBE, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER OLD COPTIC OOU
- {0x2CBF, 0x0, propertyPVALID}, // COPTIC SMALL LETTER OLD COPTIC OOU
- {0x2CC0, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER SAMPI
- {0x2CC1, 0x0, propertyPVALID}, // COPTIC SMALL LETTER SAMPI
- {0x2CC2, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER CROSSED SHEI
- {0x2CC3, 0x0, propertyPVALID}, // COPTIC SMALL LETTER CROSSED SHEI
- {0x2CC4, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER OLD COPTIC SHEI
- {0x2CC5, 0x0, propertyPVALID}, // COPTIC SMALL LETTER OLD COPTIC SHEI
- {0x2CC6, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER OLD COPTIC ESH
- {0x2CC7, 0x0, propertyPVALID}, // COPTIC SMALL LETTER OLD COPTIC ESH
- {0x2CC8, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER AKHMIMIC KHEI
- {0x2CC9, 0x0, propertyPVALID}, // COPTIC SMALL LETTER AKHMIMIC KHEI
- {0x2CCA, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER DIALECT-P HORI
- {0x2CCB, 0x0, propertyPVALID}, // COPTIC SMALL LETTER DIALECT-P HORI
- {0x2CCC, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER OLD COPTIC HORI
- {0x2CCD, 0x0, propertyPVALID}, // COPTIC SMALL LETTER OLD COPTIC HORI
- {0x2CCE, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER OLD COPTIC HA
- {0x2CCF, 0x0, propertyPVALID}, // COPTIC SMALL LETTER OLD COPTIC HA
- {0x2CD0, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER L-SHAPED HA
- {0x2CD1, 0x0, propertyPVALID}, // COPTIC SMALL LETTER L-SHAPED HA
- {0x2CD2, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER OLD COPTIC HEI
- {0x2CD3, 0x0, propertyPVALID}, // COPTIC SMALL LETTER OLD COPTIC HEI
- {0x2CD4, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER OLD COPTIC HAT
- {0x2CD5, 0x0, propertyPVALID}, // COPTIC SMALL LETTER OLD COPTIC HAT
- {0x2CD6, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER OLD COPTIC GANGIA
- {0x2CD7, 0x0, propertyPVALID}, // COPTIC SMALL LETTER OLD COPTIC GANGIA
- {0x2CD8, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER OLD COPTIC DJA
- {0x2CD9, 0x0, propertyPVALID}, // COPTIC SMALL LETTER OLD COPTIC DJA
- {0x2CDA, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER OLD COPTIC SHIMA
- {0x2CDB, 0x0, propertyPVALID}, // COPTIC SMALL LETTER OLD COPTIC SHIMA
- {0x2CDC, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER OLD NUBIAN SHIMA
- {0x2CDD, 0x0, propertyPVALID}, // COPTIC SMALL LETTER OLD NUBIAN SHIMA
- {0x2CDE, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER OLD NUBIAN NGI
- {0x2CDF, 0x0, propertyPVALID}, // COPTIC SMALL LETTER OLD NUBIAN NGI
- {0x2CE0, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER OLD NUBIAN NYI
- {0x2CE1, 0x0, propertyPVALID}, // COPTIC SMALL LETTER OLD NUBIAN NYI
- {0x2CE2, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER OLD NUBIAN WAU
- {0x2CE3, 0x2CE4, propertyPVALID}, // COPTIC SMALL LETTER OLD NUBIAN WAU..COPTIC S
- {0x2CE5, 0x2CEB, propertyDISALLOWED}, // COPTIC SYMBOL MI RO..COPTIC CAPITAL LETTER C
- {0x2CEC, 0x0, propertyPVALID}, // COPTIC SMALL LETTER CRYPTOGRAMMIC SHEI
- {0x2CED, 0x0, propertyDISALLOWED}, // COPTIC CAPITAL LETTER CRYPTOGRAMMIC GANGIA
- {0x2CEE, 0x2CF1, propertyPVALID}, // COPTIC SMALL LETTER CRYPTOGRAMMIC GANGIA..CO
- {0x2CF2, 0x2CF8, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x2CF9, 0x2CFF, propertyDISALLOWED}, // COPTIC OLD NUBIAN FULL STOP..COPTIC MORPHOLO
- {0x2D00, 0x2D25, propertyPVALID}, // GEORGIAN SMALL LETTER AN..GEORGIAN SMALL LET
- {0x2D26, 0x2D2F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x2D30, 0x2D65, propertyPVALID}, // TIFINAGH LETTER YA..TIFINAGH LETTER YAZZ
- {0x2D66, 0x2D6E, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x2D6F, 0x0, propertyDISALLOWED}, // TIFINAGH MODIFIER LETTER LABIALIZATION MARK
- {0x2D70, 0x2D7F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x2D80, 0x2D96, propertyPVALID}, // ETHIOPIC SYLLABLE LOA..ETHIOPIC SYLLABLE GGW
- {0x2D97, 0x2D9F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x2DA0, 0x2DA6, propertyPVALID}, // ETHIOPIC SYLLABLE SSA..ETHIOPIC SYLLABLE SSO
- {0x2DA7, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x2DA8, 0x2DAE, propertyPVALID}, // ETHIOPIC SYLLABLE CCA..ETHIOPIC SYLLABLE CCO
- {0x2DAF, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x2DB0, 0x2DB6, propertyPVALID}, // ETHIOPIC SYLLABLE ZZA..ETHIOPIC SYLLABLE ZZO
- {0x2DB7, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x2DB8, 0x2DBE, propertyPVALID}, // ETHIOPIC SYLLABLE CCHA..ETHIOPIC SYLLABLE CC
- {0x2DBF, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x2DC0, 0x2DC6, propertyPVALID}, // ETHIOPIC SYLLABLE QYA..ETHIOPIC SYLLABLE QYO
- {0x2DC7, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x2DC8, 0x2DCE, propertyPVALID}, // ETHIOPIC SYLLABLE KYA..ETHIOPIC SYLLABLE KYO
- {0x2DCF, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x2DD0, 0x2DD6, propertyPVALID}, // ETHIOPIC SYLLABLE XYA..ETHIOPIC SYLLABLE XYO
- {0x2DD7, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x2DD8, 0x2DDE, propertyPVALID}, // ETHIOPIC SYLLABLE GYA..ETHIOPIC SYLLABLE GYO
- {0x2DDF, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x2DE0, 0x2DFF, propertyPVALID}, // COMBINING CYRILLIC LETTER BE..COMBINING CYRI
- {0x2E00, 0x2E2E, propertyDISALLOWED}, // RIGHT ANGLE SUBSTITUTION MARKER..REVERSED QU
- {0x2E2F, 0x0, propertyPVALID}, // VERTICAL TILDE
- {0x2E30, 0x2E31, propertyDISALLOWED}, // RING POINT..WORD SEPARATOR MIDDLE DOT
- {0x2E32, 0x2E7F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x2E80, 0x2E99, propertyDISALLOWED}, // CJK RADICAL REPEAT..CJK RADICAL RAP
- {0x2E9A, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x2E9B, 0x2EF3, propertyDISALLOWED}, // CJK RADICAL CHOKE..CJK RADICAL C-SIMPLIFIED
- {0x2EF4, 0x2EFF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x2F00, 0x2FD5, propertyDISALLOWED}, // KANGXI RADICAL ONE..KANGXI RADICAL FLUTE
- {0x2FD6, 0x2FEF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x2FF0, 0x2FFB, propertyDISALLOWED}, // IDEOGRAPHIC DESCRIPTION CHARACTER LEFT TO RI
- {0x2FFC, 0x2FFF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x3000, 0x3004, propertyDISALLOWED}, // IDEOGRAPHIC SPACE..JAPANESE INDUSTRIAL STAND
- {0x3005, 0x3007, propertyPVALID}, // IDEOGRAPHIC ITERATION MARK..IDEOGRAPHIC NUMB
- {0x3008, 0x3029, propertyDISALLOWED}, // LEFT ANGLE BRACKET..HANGZHOU NUMERAL NINE
- {0x302A, 0x302D, propertyPVALID}, // IDEOGRAPHIC LEVEL TONE MARK..IDEOGRAPHIC ENT
- {0x302E, 0x303B, propertyDISALLOWED}, // HANGUL SINGLE DOT TONE MARK..VERTICAL IDEOGR
- {0x303C, 0x0, propertyPVALID}, // MASU MARK
- {0x303D, 0x303F, propertyDISALLOWED}, // PART ALTERNATION MARK..IDEOGRAPHIC HALF FILL
- {0x3040, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x3041, 0x3096, propertyPVALID}, // HIRAGANA LETTER SMALL A..HIRAGANA LETTER SMA
- {0x3097, 0x3098, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x3099, 0x309A, propertyPVALID}, // COMBINING KATAKANA-HIRAGANA VOICED SOUND MAR
- {0x309B, 0x309C, propertyDISALLOWED}, // KATAKANA-HIRAGANA VOICED SOUND MARK..KATAKAN
- {0x309D, 0x309E, propertyPVALID}, // HIRAGANA ITERATION MARK..HIRAGANA VOICED ITE
- {0x309F, 0x30A0, propertyDISALLOWED}, // HIRAGANA DIGRAPH YORI..KATAKANA-HIRAGANA DOU
- {0x30A1, 0x30FA, propertyPVALID}, // KATAKANA LETTER SMALL A..KATAKANA LETTER VO
- {0x30FB, 0x0, propertyCONTEXTO}, // KATAKANA MIDDLE DOT
- {0x30FC, 0x30FE, propertyPVALID}, // KATAKANA-HIRAGANA PROLONGED SOUND MARK..KATA
- {0x30FF, 0x0, propertyDISALLOWED}, // KATAKANA DIGRAPH KOTO
- {0x3100, 0x3104, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x3105, 0x312D, propertyPVALID}, // BOPOMOFO LETTER B..BOPOMOFO LETTER IH
- {0x312E, 0x3130, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x3131, 0x318E, propertyDISALLOWED}, // HANGUL LETTER KIYEOK..HANGUL LETTER ARAEAE
- {0x318F, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x3190, 0x319F, propertyDISALLOWED}, // IDEOGRAPHIC ANNOTATION LINKING MARK..IDEOGRA
- {0x31A0, 0x31B7, propertyPVALID}, // BOPOMOFO LETTER BU..BOPOMOFO FINAL LETTER H
- {0x31B8, 0x31BF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x31C0, 0x31E3, propertyDISALLOWED}, // CJK STROKE T..CJK STROKE Q
- {0x31E4, 0x31EF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x31F0, 0x31FF, propertyPVALID}, // KATAKANA LETTER SMALL KU..KATAKANA LETTER SM
- {0x3200, 0x321E, propertyDISALLOWED}, // PARENTHESIZED HANGUL KIYEOK..PARENTHESIZED K
- {0x321F, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x3220, 0x32FE, propertyDISALLOWED}, // PARENTHESIZED IDEOGRAPH ONE..CIRCLED KATAKAN
- {0x32FF, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x3300, 0x33FF, propertyDISALLOWED}, // SQUARE APAATO..SQUARE GAL
- {0x3400, 0x4DB5, propertyPVALID}, // <CJK Ideograph Extension A>..<CJK Ideograph
- {0x4DB6, 0x4DBF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x4DC0, 0x4DFF, propertyDISALLOWED}, // HEXAGRAM FOR THE CREATIVE HEAVEN..HEXAGRAM F
- {0x4E00, 0x9FCB, propertyPVALID}, // <CJK Ideograph>..<CJK Ideograph>
- {0x9FCC, 0x9FFF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xA000, 0xA48C, propertyPVALID}, // YI SYLLABLE IT..YI SYLLABLE YYR
- {0xA48D, 0xA48F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xA490, 0xA4C6, propertyDISALLOWED}, // YI RADICAL QOT..YI RADICAL KE
- {0xA4C7, 0xA4CF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xA4D0, 0xA4FD, propertyPVALID}, // LISU LETTER BA..LISU LETTER TONE MYA JEU
- {0xA4FE, 0xA4FF, propertyDISALLOWED}, // LISU PUNCTUATION COMMA..LISU PUNCTUATION FUL
- {0xA500, 0xA60C, propertyPVALID}, // VAI SYLLABLE EE..VAI SYLLABLE LENGTHENER
- {0xA60D, 0xA60F, propertyDISALLOWED}, // VAI COMMA..VAI QUESTION MARK
- {0xA610, 0xA62B, propertyPVALID}, // VAI SYLLABLE NDOLE FA..VAI SYLLABLE NDOLE DO
- {0xA62C, 0xA63F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xA640, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER ZEMLYA
- {0xA641, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER ZEMLYA
- {0xA642, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER DZELO
- {0xA643, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER DZELO
- {0xA644, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER REVERSED DZE
- {0xA645, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER REVERSED DZE
- {0xA646, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER IOTA
- {0xA647, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER IOTA
- {0xA648, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER DJERV
- {0xA649, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER DJERV
- {0xA64A, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER MONOGRAPH UK
- {0xA64B, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER MONOGRAPH UK
- {0xA64C, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER BROAD OMEGA
- {0xA64D, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER BROAD OMEGA
- {0xA64E, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER NEUTRAL YER
- {0xA64F, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER NEUTRAL YER
- {0xA650, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER YERU WITH BACK YER
- {0xA651, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER YERU WITH BACK YER
- {0xA652, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER IOTIFIED YAT
- {0xA653, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER IOTIFIED YAT
- {0xA654, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER REVERSED YU
- {0xA655, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER REVERSED YU
- {0xA656, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER IOTIFIED A
- {0xA657, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER IOTIFIED A
- {0xA658, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER CLOSED LITTLE YUS
- {0xA659, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER CLOSED LITTLE YUS
- {0xA65A, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER BLENDED YUS
- {0xA65B, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER BLENDED YUS
- {0xA65C, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER IOTIFIED CLOSED LITT
- {0xA65D, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER IOTIFIED CLOSED LITTLE
- {0xA65E, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER YN
- {0xA65F, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER YN
- {0xA660, 0xA661, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xA662, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER SOFT DE
- {0xA663, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER SOFT DE
- {0xA664, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER SOFT EL
- {0xA665, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER SOFT EL
- {0xA666, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER SOFT EM
- {0xA667, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER SOFT EM
- {0xA668, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER MONOCULAR O
- {0xA669, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER MONOCULAR O
- {0xA66A, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER BINOCULAR O
- {0xA66B, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER BINOCULAR O
- {0xA66C, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER DOUBLE MONOCULAR O
- {0xA66D, 0xA66F, propertyPVALID}, // CYRILLIC SMALL LETTER DOUBLE MONOCULAR O..CO
- {0xA670, 0xA673, propertyDISALLOWED}, // COMBINING CYRILLIC TEN MILLIONS SIGN..SLAVON
- {0xA674, 0xA67B, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xA67C, 0xA67D, propertyPVALID}, // COMBINING CYRILLIC KAVYKA..COMBINING CYRILLI
- {0xA67E, 0x0, propertyDISALLOWED}, // CYRILLIC KAVYKA
- {0xA67F, 0x0, propertyPVALID}, // CYRILLIC PAYEROK
- {0xA680, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER DWE
- {0xA681, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER DWE
- {0xA682, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER DZWE
- {0xA683, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER DZWE
- {0xA684, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER ZHWE
- {0xA685, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER ZHWE
- {0xA686, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER CCHE
- {0xA687, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER CCHE
- {0xA688, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER DZZE
- {0xA689, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER DZZE
- {0xA68A, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER TE WITH MIDDLE HOOK
- {0xA68B, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER TE WITH MIDDLE HOOK
- {0xA68C, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER TWE
- {0xA68D, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER TWE
- {0xA68E, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER TSWE
- {0xA68F, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER TSWE
- {0xA690, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER TSSE
- {0xA691, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER TSSE
- {0xA692, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER TCHE
- {0xA693, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER TCHE
- {0xA694, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER HWE
- {0xA695, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER HWE
- {0xA696, 0x0, propertyDISALLOWED}, // CYRILLIC CAPITAL LETTER SHWE
- {0xA697, 0x0, propertyPVALID}, // CYRILLIC SMALL LETTER SHWE
- {0xA698, 0xA69F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xA6A0, 0xA6E5, propertyPVALID}, // BAMUM LETTER A..BAMUM LETTER KI
- {0xA6E6, 0xA6EF, propertyDISALLOWED}, // BAMUM LETTER MO..BAMUM LETTER KOGHOM
- {0xA6F0, 0xA6F1, propertyPVALID}, // BAMUM COMBINING MARK KOQNDON..BAMUM COMBININ
- {0xA6F2, 0xA6F7, propertyDISALLOWED}, // BAMUM NJAEMLI..BAMUM QUESTION MARK
- {0xA6F8, 0xA6FF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xA700, 0xA716, propertyDISALLOWED}, // MODIFIER LETTER CHINESE TONE YIN PING..MODIF
- {0xA717, 0xA71F, propertyPVALID}, // MODIFIER LETTER DOT VERTICAL BAR..MODIFIER L
- {0xA720, 0xA722, propertyDISALLOWED}, // MODIFIER LETTER STRESS AND HIGH TONE..LATIN
- {0xA723, 0x0, propertyPVALID}, // LATIN SMALL LETTER EGYPTOLOGICAL ALEF
- {0xA724, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER EGYPTOLOGICAL AIN
- {0xA725, 0x0, propertyPVALID}, // LATIN SMALL LETTER EGYPTOLOGICAL AIN
- {0xA726, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER HENG
- {0xA727, 0x0, propertyPVALID}, // LATIN SMALL LETTER HENG
- {0xA728, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER TZ
- {0xA729, 0x0, propertyPVALID}, // LATIN SMALL LETTER TZ
- {0xA72A, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER TRESILLO
- {0xA72B, 0x0, propertyPVALID}, // LATIN SMALL LETTER TRESILLO
- {0xA72C, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER CUATRILLO
- {0xA72D, 0x0, propertyPVALID}, // LATIN SMALL LETTER CUATRILLO
- {0xA72E, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER CUATRILLO WITH COMMA
- {0xA72F, 0xA731, propertyPVALID}, // LATIN SMALL LETTER CUATRILLO WITH COMMA..LAT
- {0xA732, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER AA
- {0xA733, 0x0, propertyPVALID}, // LATIN SMALL LETTER AA
- {0xA734, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER AO
- {0xA735, 0x0, propertyPVALID}, // LATIN SMALL LETTER AO
- {0xA736, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER AU
- {0xA737, 0x0, propertyPVALID}, // LATIN SMALL LETTER AU
- {0xA738, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER AV
- {0xA739, 0x0, propertyPVALID}, // LATIN SMALL LETTER AV
- {0xA73A, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER AV WITH HORIZONTAL BAR
- {0xA73B, 0x0, propertyPVALID}, // LATIN SMALL LETTER AV WITH HORIZONTAL BAR
- {0xA73C, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER AY
- {0xA73D, 0x0, propertyPVALID}, // LATIN SMALL LETTER AY
- {0xA73E, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER REVERSED C WITH DOT
- {0xA73F, 0x0, propertyPVALID}, // LATIN SMALL LETTER REVERSED C WITH DOT
- {0xA740, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER K WITH STROKE
- {0xA741, 0x0, propertyPVALID}, // LATIN SMALL LETTER K WITH STROKE
- {0xA742, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER K WITH DIAGONAL STROKE
- {0xA743, 0x0, propertyPVALID}, // LATIN SMALL LETTER K WITH DIAGONAL STROKE
- {0xA744, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER K WITH STROKE AND DIAGO
- {0xA745, 0x0, propertyPVALID}, // LATIN SMALL LETTER K WITH STROKE AND DIAGONA
- {0xA746, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER BROKEN L
- {0xA747, 0x0, propertyPVALID}, // LATIN SMALL LETTER BROKEN L
- {0xA748, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER L WITH HIGH STROKE
- {0xA749, 0x0, propertyPVALID}, // LATIN SMALL LETTER L WITH HIGH STROKE
- {0xA74A, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER O WITH LONG STROKE OVER
- {0xA74B, 0x0, propertyPVALID}, // LATIN SMALL LETTER O WITH LONG STROKE OVERLA
- {0xA74C, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER O WITH LOOP
- {0xA74D, 0x0, propertyPVALID}, // LATIN SMALL LETTER O WITH LOOP
- {0xA74E, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER OO
- {0xA74F, 0x0, propertyPVALID}, // LATIN SMALL LETTER OO
- {0xA750, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER P WITH STROKE THROUGH D
- {0xA751, 0x0, propertyPVALID}, // LATIN SMALL LETTER P WITH STROKE THROUGH DES
- {0xA752, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER P WITH FLOURISH
- {0xA753, 0x0, propertyPVALID}, // LATIN SMALL LETTER P WITH FLOURISH
- {0xA754, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER P WITH SQUIRREL TAIL
- {0xA755, 0x0, propertyPVALID}, // LATIN SMALL LETTER P WITH SQUIRREL TAIL
- {0xA756, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER Q WITH STROKE THROUGH D
- {0xA757, 0x0, propertyPVALID}, // LATIN SMALL LETTER Q WITH STROKE THROUGH DES
- {0xA758, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER Q WITH DIAGONAL STROKE
- {0xA759, 0x0, propertyPVALID}, // LATIN SMALL LETTER Q WITH DIAGONAL STROKE
- {0xA75A, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER R ROTUNDA
- {0xA75B, 0x0, propertyPVALID}, // LATIN SMALL LETTER R ROTUNDA
- {0xA75C, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER RUM ROTUNDA
- {0xA75D, 0x0, propertyPVALID}, // LATIN SMALL LETTER RUM ROTUNDA
- {0xA75E, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER V WITH DIAGONAL STROKE
- {0xA75F, 0x0, propertyPVALID}, // LATIN SMALL LETTER V WITH DIAGONAL STROKE
- {0xA760, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER VY
- {0xA761, 0x0, propertyPVALID}, // LATIN SMALL LETTER VY
- {0xA762, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER VISIGOTHIC Z
- {0xA763, 0x0, propertyPVALID}, // LATIN SMALL LETTER VISIGOTHIC Z
- {0xA764, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER THORN WITH STROKE
- {0xA765, 0x0, propertyPVALID}, // LATIN SMALL LETTER THORN WITH STROKE
- {0xA766, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER THORN WITH STROKE THROU
- {0xA767, 0x0, propertyPVALID}, // LATIN SMALL LETTER THORN WITH STROKE THROUGH
- {0xA768, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER VEND
- {0xA769, 0x0, propertyPVALID}, // LATIN SMALL LETTER VEND
- {0xA76A, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER ET
- {0xA76B, 0x0, propertyPVALID}, // LATIN SMALL LETTER ET
- {0xA76C, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER IS
- {0xA76D, 0x0, propertyPVALID}, // LATIN SMALL LETTER IS
- {0xA76E, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER CON
- {0xA76F, 0x0, propertyPVALID}, // LATIN SMALL LETTER CON
- {0xA770, 0x0, propertyDISALLOWED}, // MODIFIER LETTER US
- {0xA771, 0xA778, propertyPVALID}, // LATIN SMALL LETTER DUM..LATIN SMALL LETTER U
- {0xA779, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER INSULAR D
- {0xA77A, 0x0, propertyPVALID}, // LATIN SMALL LETTER INSULAR D
- {0xA77B, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER INSULAR F
- {0xA77C, 0x0, propertyPVALID}, // LATIN SMALL LETTER INSULAR F
- {0xA77D, 0xA77E, propertyDISALLOWED}, // LATIN CAPITAL LETTER INSULAR G..LATIN CAPITA
- {0xA77F, 0x0, propertyPVALID}, // LATIN SMALL LETTER TURNED INSULAR G
- {0xA780, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER TURNED L
- {0xA781, 0x0, propertyPVALID}, // LATIN SMALL LETTER TURNED L
- {0xA782, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER INSULAR R
- {0xA783, 0x0, propertyPVALID}, // LATIN SMALL LETTER INSULAR R
- {0xA784, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER INSULAR S
- {0xA785, 0x0, propertyPVALID}, // LATIN SMALL LETTER INSULAR S
- {0xA786, 0x0, propertyDISALLOWED}, // LATIN CAPITAL LETTER INSULAR T
- {0xA787, 0xA788, propertyPVALID}, // LATIN SMALL LETTER INSULAR T..MODIFIER LETTE
- {0xA789, 0xA78B, propertyDISALLOWED}, // MODIFIER LETTER COLON..LATIN CAPITAL LETTER
- {0xA78C, 0x0, propertyPVALID}, // LATIN SMALL LETTER SALTILLO
- {0xA78D, 0xA7FA, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xA7FB, 0xA827, propertyPVALID}, // LATIN EPIGRAPHIC LETTER REVERSED F..SYLOTI N
- {0xA828, 0xA82B, propertyDISALLOWED}, // SYLOTI NAGRI POETRY MARK-1..SYLOTI NAGRI POE
- {0xA82C, 0xA82F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xA830, 0xA839, propertyDISALLOWED}, // NORTH INDIC FRACTION ONE QUARTER..NORTH INDI
- {0xA83A, 0xA83F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xA840, 0xA873, propertyPVALID}, // PHAGS-PA LETTER KA..PHAGS-PA LETTER CANDRABI
- {0xA874, 0xA877, propertyDISALLOWED}, // PHAGS-PA SINGLE HEAD MARK..PHAGS-PA MARK DOU
- {0xA878, 0xA87F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xA880, 0xA8C4, propertyPVALID}, // SAURASHTRA SIGN ANUSVARA..SAURASHTRA SIGN VI
- {0xA8C5, 0xA8CD, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xA8CE, 0xA8CF, propertyDISALLOWED}, // SAURASHTRA DANDA..SAURASHTRA DOUBLE DANDA
- {0xA8D0, 0xA8D9, propertyPVALID}, // SAURASHTRA DIGIT ZERO..SAURASHTRA DIGIT NINE
- {0xA8DA, 0xA8DF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xA8E0, 0xA8F7, propertyPVALID}, // COMBINING DEVANAGARI DIGIT ZERO..DEVANAGARI
- {0xA8F8, 0xA8FA, propertyDISALLOWED}, // DEVANAGARI SIGN PUSHPIKA..DEVANAGARI CARET
- {0xA8FB, 0x0, propertyPVALID}, // DEVANAGARI HEADSTROKE
- {0xA8FC, 0xA8FF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xA900, 0xA92D, propertyPVALID}, // KAYAH LI DIGIT ZERO..KAYAH LI TONE CALYA PLO
- {0xA92E, 0xA92F, propertyDISALLOWED}, // KAYAH LI SIGN CWI..KAYAH LI SIGN SHYA
- {0xA930, 0xA953, propertyPVALID}, // REJANG LETTER KA..REJANG VIRAMA
- {0xA954, 0xA95E, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xA95F, 0xA97C, propertyDISALLOWED}, // REJANG SECTION MARK..HANGUL CHOSEONG SSANGYE
- {0xA97D, 0xA97F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xA980, 0xA9C0, propertyPVALID}, // JAVANESE SIGN PANYANGGA..JAVANESE PANGKON
- {0xA9C1, 0xA9CD, propertyDISALLOWED}, // JAVANESE LEFT RERENGGAN..JAVANESE TURNED PAD
- {0xA9CE, 0x0, propertyUNASSIGNED}, // <reserved>
- {0xA9CF, 0xA9D9, propertyPVALID}, // JAVANESE PANGRANGKEP..JAVANESE DIGIT NINE
- {0xA9DA, 0xA9DD, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xA9DE, 0xA9DF, propertyDISALLOWED}, // JAVANESE PADA TIRTA TUMETES..JAVANESE PADA I
- {0xA9E0, 0xA9FF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xAA00, 0xAA36, propertyPVALID}, // CHAM LETTER A..CHAM CONSONANT SIGN WA
- {0xAA37, 0xAA3F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xAA40, 0xAA4D, propertyPVALID}, // CHAM LETTER FINAL K..CHAM CONSONANT SIGN FIN
- {0xAA4E, 0xAA4F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xAA50, 0xAA59, propertyPVALID}, // CHAM DIGIT ZERO..CHAM DIGIT NINE
- {0xAA5A, 0xAA5B, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xAA5C, 0xAA5F, propertyDISALLOWED}, // CHAM PUNCTUATION SPIRAL..CHAM PUNCTUATION TR
- {0xAA60, 0xAA76, propertyPVALID}, // MYANMAR LETTER KHAMTI GA..MYANMAR LOGOGRAM K
- {0xAA77, 0xAA79, propertyDISALLOWED}, // MYANMAR SYMBOL AITON EXCLAMATION..MYANMAR SY
- {0xAA7A, 0xAA7B, propertyPVALID}, // MYANMAR LETTER AITON RA..MYANMAR SIGN PAO KA
- {0xAA7C, 0xAA7F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xAA80, 0xAAC2, propertyPVALID}, // TAI VIET LETTER LOW KO..TAI VIET TONE MAI SO
- {0xAAC3, 0xAADA, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xAADB, 0xAADD, propertyPVALID}, // TAI VIET SYMBOL KON..TAI VIET SYMBOL SAM
- {0xAADE, 0xAADF, propertyDISALLOWED}, // TAI VIET SYMBOL HO HOI..TAI VIET SYMBOL KOI
- {0xAAE0, 0xABBF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xABC0, 0xABEA, propertyPVALID}, // MEETEI MAYEK LETTER KOK..MEETEI MAYEK VOWEL
- {0xABEB, 0x0, propertyDISALLOWED}, // MEETEI MAYEK CHEIKHEI
- {0xABEC, 0xABED, propertyPVALID}, // MEETEI MAYEK LUM IYEK..MEETEI MAYEK APUN IYE
- {0xABEE, 0xABEF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xABF0, 0xABF9, propertyPVALID}, // MEETEI MAYEK DIGIT ZERO..MEETEI MAYEK DIGIT
- {0xABFA, 0xABFF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xAC00, 0xD7A3, propertyPVALID}, // <Hangul Syllable>..<Hangul Syllable>
- {0xD7A4, 0xD7AF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xD7B0, 0xD7C6, propertyDISALLOWED}, // HANGUL JUNGSEONG O-YEO..HANGUL JUNGSEONG ARA
- {0xD7C7, 0xD7CA, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xD7CB, 0xD7FB, propertyDISALLOWED}, // HANGUL JONGSEONG NIEUN-RIEUL..HANGUL JONGSEO
- {0xD7FC, 0xD7FF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xD800, 0xFA0D, propertyDISALLOWED}, // <Non Private Use High Surrogate>..CJK COMPAT
- {0xFA0E, 0xFA0F, propertyPVALID}, // CJK COMPATIBILITY IDEOGRAPH-FA0E..CJK COMPAT
- {0xFA10, 0x0, propertyDISALLOWED}, // CJK COMPATIBILITY IDEOGRAPH-FA10
- {0xFA11, 0x0, propertyPVALID}, // CJK COMPATIBILITY IDEOGRAPH-FA11
- {0xFA12, 0x0, propertyDISALLOWED}, // CJK COMPATIBILITY IDEOGRAPH-FA12
- {0xFA13, 0xFA14, propertyPVALID}, // CJK COMPATIBILITY IDEOGRAPH-FA13..CJK COMPAT
- {0xFA15, 0xFA1E, propertyDISALLOWED}, // CJK COMPATIBILITY IDEOGRAPH-FA15..CJK COMPAT
- {0xFA1F, 0x0, propertyPVALID}, // CJK COMPATIBILITY IDEOGRAPH-FA1F
- {0xFA20, 0x0, propertyDISALLOWED}, // CJK COMPATIBILITY IDEOGRAPH-FA20
- {0xFA21, 0x0, propertyPVALID}, // CJK COMPATIBILITY IDEOGRAPH-FA21
- {0xFA22, 0x0, propertyDISALLOWED}, // CJK COMPATIBILITY IDEOGRAPH-FA22
- {0xFA23, 0xFA24, propertyPVALID}, // CJK COMPATIBILITY IDEOGRAPH-FA23..CJK COMPAT
- {0xFA25, 0xFA26, propertyDISALLOWED}, // CJK COMPATIBILITY IDEOGRAPH-FA25..CJK COMPAT
- {0xFA27, 0xFA29, propertyPVALID}, // CJK COMPATIBILITY IDEOGRAPH-FA27..CJK COMPAT
- {0xFA2A, 0xFA2D, propertyDISALLOWED}, // CJK COMPATIBILITY IDEOGRAPH-FA2A..CJK COMPAT
- {0xFA2E, 0xFA2F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xFA30, 0xFA6D, propertyDISALLOWED}, // CJK COMPATIBILITY IDEOGRAPH-FA30..CJK COMPAT
- {0xFA6E, 0xFA6F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xFA70, 0xFAD9, propertyDISALLOWED}, // CJK COMPATIBILITY IDEOGRAPH-FA70..CJK COMPAT
- {0xFADA, 0xFAFF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xFB00, 0xFB06, propertyDISALLOWED}, // LATIN SMALL LIGATURE FF..LATIN SMALL LIGATUR
- {0xFB07, 0xFB12, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xFB13, 0xFB17, propertyDISALLOWED}, // ARMENIAN SMALL LIGATURE MEN NOW..ARMENIAN SM
- {0xFB18, 0xFB1C, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xFB1D, 0x0, propertyDISALLOWED}, // HEBREW LETTER YOD WITH HIRIQ
- {0xFB1E, 0x0, propertyPVALID}, // HEBREW POINT JUDEO-SPANISH VARIKA
- {0xFB1F, 0xFB36, propertyDISALLOWED}, // HEBREW LIGATURE YIDDISH YOD YOD PATAH..HEBRE
- {0xFB37, 0x0, propertyUNASSIGNED}, // <reserved>
- {0xFB38, 0xFB3C, propertyDISALLOWED}, // HEBREW LETTER TET WITH DAGESH..HEBREW LETTER
- {0xFB3D, 0x0, propertyUNASSIGNED}, // <reserved>
- {0xFB3E, 0x0, propertyDISALLOWED}, // HEBREW LETTER MEM WITH DAGESH
- {0xFB3F, 0x0, propertyUNASSIGNED}, // <reserved>
- {0xFB40, 0xFB41, propertyDISALLOWED}, // HEBREW LETTER NUN WITH DAGESH..HEBREW LETTER
- {0xFB42, 0x0, propertyUNASSIGNED}, // <reserved>
- {0xFB43, 0xFB44, propertyDISALLOWED}, // HEBREW LETTER FINAL PE WITH DAGESH..HEBREW L
- {0xFB45, 0x0, propertyUNASSIGNED}, // <reserved>
- {0xFB46, 0xFBB1, propertyDISALLOWED}, // HEBREW LETTER TSADI WITH DAGESH..ARABIC LETT
- {0xFBB2, 0xFBD2, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xFBD3, 0xFD3F, propertyDISALLOWED}, // ARABIC LETTER NG ISOLATED FORM..ORNATE RIGHT
- {0xFD40, 0xFD4F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xFD50, 0xFD8F, propertyDISALLOWED}, // ARABIC LIGATURE TEH WITH JEEM WITH MEEM INIT
- {0xFD90, 0xFD91, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xFD92, 0xFDC7, propertyDISALLOWED}, // ARABIC LIGATURE MEEM WITH JEEM WITH KHAH INI
- {0xFDC8, 0xFDCF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xFDD0, 0xFDFD, propertyDISALLOWED}, // <noncharacter>..ARABIC LIGATURE BISMILLAH AR
- {0xFDFE, 0xFDFF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xFE00, 0xFE19, propertyDISALLOWED}, // VARIATION SELECTOR-1..PRESENTATION FORM FOR
- {0xFE1A, 0xFE1F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xFE20, 0xFE26, propertyPVALID}, // COMBINING LIGATURE LEFT HALF..COMBINING CONJ
- {0xFE27, 0xFE2F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xFE30, 0xFE52, propertyDISALLOWED}, // PRESENTATION FORM FOR VERTICAL TWO DOT LEADE
- {0xFE53, 0x0, propertyUNASSIGNED}, // <reserved>
- {0xFE54, 0xFE66, propertyDISALLOWED}, // SMALL SEMICOLON..SMALL EQUALS SIGN
- {0xFE67, 0x0, propertyUNASSIGNED}, // <reserved>
- {0xFE68, 0xFE6B, propertyDISALLOWED}, // SMALL REVERSE SOLIDUS..SMALL COMMERCIAL AT
- {0xFE6C, 0xFE6F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xFE70, 0xFE72, propertyDISALLOWED}, // ARABIC FATHATAN ISOLATED FORM..ARABIC DAMMAT
- {0xFE73, 0x0, propertyPVALID}, // ARABIC TAIL FRAGMENT
- {0xFE74, 0x0, propertyDISALLOWED}, // ARABIC KASRATAN ISOLATED FORM
- {0xFE75, 0x0, propertyUNASSIGNED}, // <reserved>
- {0xFE76, 0xFEFC, propertyDISALLOWED}, // ARABIC FATHA ISOLATED FORM..ARABIC LIGATURE
- {0xFEFD, 0xFEFE, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xFEFF, 0x0, propertyDISALLOWED}, // ZERO WIDTH NO-BREAK SPACE
- {0xFF00, 0x0, propertyUNASSIGNED}, // <reserved>
- {0xFF01, 0xFFBE, propertyDISALLOWED}, // FULLWIDTH EXCLAMATION MARK..HALFWIDTH HANGUL
- {0xFFBF, 0xFFC1, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xFFC2, 0xFFC7, propertyDISALLOWED}, // HALFWIDTH HANGUL LETTER A..HALFWIDTH HANGUL
- {0xFFC8, 0xFFC9, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xFFCA, 0xFFCF, propertyDISALLOWED}, // HALFWIDTH HANGUL LETTER YEO..HALFWIDTH HANGU
- {0xFFD0, 0xFFD1, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xFFD2, 0xFFD7, propertyDISALLOWED}, // HALFWIDTH HANGUL LETTER YO..HALFWIDTH HANGUL
- {0xFFD8, 0xFFD9, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xFFDA, 0xFFDC, propertyDISALLOWED}, // HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGUL
- {0xFFDD, 0xFFDF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xFFE0, 0xFFE6, propertyDISALLOWED}, // FULLWIDTH CENT SIGN..FULLWIDTH WON SIGN
- {0xFFE7, 0x0, propertyUNASSIGNED}, // <reserved>
- {0xFFE8, 0xFFEE, propertyDISALLOWED}, // HALFWIDTH FORMS LIGHT VERTICAL..HALFWIDTH WH
- {0xFFEF, 0xFFF8, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xFFF9, 0xFFFF, propertyDISALLOWED}, // INTERLINEAR ANNOTATION ANCHOR..<noncharacter
- {0x10000, 0x1000B, propertyPVALID}, // LINEAR B SYLLABLE B008 A..LINEAR B SYLLABLE
- {0x1000C, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x1000D, 0x10026, propertyPVALID}, // LINEAR B SYLLABLE B036 JO..LINEAR B SYLLABLE
- {0x10027, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x10028, 0x1003A, propertyPVALID}, // LINEAR B SYLLABLE B060 RA..LINEAR B SYLLABLE
- {0x1003B, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x1003C, 0x1003D, propertyPVALID}, // LINEAR B SYLLABLE B017 ZA..LINEAR B SYLLABLE
- {0x1003E, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x1003F, 0x1004D, propertyPVALID}, // LINEAR B SYLLABLE B020 ZO..LINEAR B SYLLABLE
- {0x1004E, 0x1004F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x10050, 0x1005D, propertyPVALID}, // LINEAR B SYMBOL B018..LINEAR B SYMBOL B089
- {0x1005E, 0x1007F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x10080, 0x100FA, propertyPVALID}, // LINEAR B IDEOGRAM B100 MAN..LINEAR B IDEOGRA
- {0x100FB, 0x100FF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x10100, 0x10102, propertyDISALLOWED}, // AEGEAN WORD SEPARATOR LINE..AEGEAN CHECK MAR
- {0x10103, 0x10106, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x10107, 0x10133, propertyDISALLOWED}, // AEGEAN NUMBER ONE..AEGEAN NUMBER NINETY THOU
- {0x10134, 0x10136, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x10137, 0x1018A, propertyDISALLOWED}, // AEGEAN WEIGHT BASE UNIT..GREEK ZERO SIGN
- {0x1018B, 0x1018F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x10190, 0x1019B, propertyDISALLOWED}, // ROMAN SEXTANS SIGN..ROMAN CENTURIAL SIGN
- {0x1019C, 0x101CF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x101D0, 0x101FC, propertyDISALLOWED}, // PHAISTOS DISC SIGN PEDESTRIAN..PHAISTOS DISC
- {0x101FD, 0x0, propertyPVALID}, // PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE
- {0x101FE, 0x1027F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x10280, 0x1029C, propertyPVALID}, // LYCIAN LETTER A..LYCIAN LETTER X
- {0x1029D, 0x1029F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x102A0, 0x102D0, propertyPVALID}, // CARIAN LETTER A..CARIAN LETTER UUU3
- {0x102D1, 0x102FF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x10300, 0x1031E, propertyPVALID}, // OLD ITALIC LETTER A..OLD ITALIC LETTER UU
- {0x1031F, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x10320, 0x10323, propertyDISALLOWED}, // OLD ITALIC NUMERAL ONE..OLD ITALIC NUMERAL F
- {0x10324, 0x1032F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x10330, 0x10340, propertyPVALID}, // GOTHIC LETTER AHSA..GOTHIC LETTER PAIRTHRA
- {0x10341, 0x0, propertyDISALLOWED}, // GOTHIC LETTER NINETY
- {0x10342, 0x10349, propertyPVALID}, // GOTHIC LETTER RAIDA..GOTHIC LETTER OTHAL
- {0x1034A, 0x0, propertyDISALLOWED}, // GOTHIC LETTER NINE HUNDRED
- {0x1034B, 0x1037F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x10380, 0x1039D, propertyPVALID}, // UGARITIC LETTER ALPA..UGARITIC LETTER SSU
- {0x1039E, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x1039F, 0x0, propertyDISALLOWED}, // UGARITIC WORD DIVIDER
- {0x103A0, 0x103C3, propertyPVALID}, // OLD PERSIAN SIGN A..OLD PERSIAN SIGN HA
- {0x103C4, 0x103C7, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x103C8, 0x103CF, propertyPVALID}, // OLD PERSIAN SIGN AURAMAZDAA..OLD PERSIAN SIG
- {0x103D0, 0x103D5, propertyDISALLOWED}, // OLD PERSIAN WORD DIVIDER..OLD PERSIAN NUMBER
- {0x103D6, 0x103FF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x10400, 0x10427, propertyDISALLOWED}, // DESERET CAPITAL LETTER LONG I..DESERET CAPIT
- {0x10428, 0x1049D, propertyPVALID}, // DESERET SMALL LETTER LONG I..OSMANYA LETTER
- {0x1049E, 0x1049F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x104A0, 0x104A9, propertyPVALID}, // OSMANYA DIGIT ZERO..OSMANYA DIGIT NINE
- {0x104AA, 0x107FF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x10800, 0x10805, propertyPVALID}, // CYPRIOT SYLLABLE A..CYPRIOT SYLLABLE JA
- {0x10806, 0x10807, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x10808, 0x0, propertyPVALID}, // CYPRIOT SYLLABLE JO
- {0x10809, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x1080A, 0x10835, propertyPVALID}, // CYPRIOT SYLLABLE KA..CYPRIOT SYLLABLE WO
- {0x10836, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x10837, 0x10838, propertyPVALID}, // CYPRIOT SYLLABLE XA..CYPRIOT SYLLABLE XE
- {0x10839, 0x1083B, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1083C, 0x0, propertyPVALID}, // CYPRIOT SYLLABLE ZA
- {0x1083D, 0x1083E, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1083F, 0x10855, propertyPVALID}, // CYPRIOT SYLLABLE ZO..IMPERIAL ARAMAIC LETTER
- {0x10856, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x10857, 0x1085F, propertyDISALLOWED}, // IMPERIAL ARAMAIC SECTION SIGN..IMPERIAL ARAM
- {0x10860, 0x108FF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x10900, 0x10915, propertyPVALID}, // PHOENICIAN LETTER ALF..PHOENICIAN LETTER TAU
- {0x10916, 0x1091B, propertyDISALLOWED}, // PHOENICIAN NUMBER ONE..PHOENICIAN NUMBER THR
- {0x1091C, 0x1091E, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1091F, 0x0, propertyDISALLOWED}, // PHOENICIAN WORD SEPARATOR
- {0x10920, 0x10939, propertyPVALID}, // LYDIAN LETTER A..LYDIAN LETTER C
- {0x1093A, 0x1093E, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1093F, 0x0, propertyDISALLOWED}, // LYDIAN TRIANGULAR MARK
- {0x10940, 0x109FF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x10A00, 0x10A03, propertyPVALID}, // KHAROSHTHI LETTER A..KHAROSHTHI VOWEL SIGN V
- {0x10A04, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x10A05, 0x10A06, propertyPVALID}, // KHAROSHTHI VOWEL SIGN E..KHAROSHTHI VOWEL SI
- {0x10A07, 0x10A0B, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x10A0C, 0x10A13, propertyPVALID}, // KHAROSHTHI VOWEL LENGTH MARK..KHAROSHTHI LET
- {0x10A14, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x10A15, 0x10A17, propertyPVALID}, // KHAROSHTHI LETTER CA..KHAROSHTHI LETTER JA
- {0x10A18, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x10A19, 0x10A33, propertyPVALID}, // KHAROSHTHI LETTER NYA..KHAROSHTHI LETTER TTT
- {0x10A34, 0x10A37, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x10A38, 0x10A3A, propertyPVALID}, // KHAROSHTHI SIGN BAR ABOVE..KHAROSHTHI SIGN D
- {0x10A3B, 0x10A3E, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x10A3F, 0x0, propertyPVALID}, // KHAROSHTHI VIRAMA
- {0x10A40, 0x10A47, propertyDISALLOWED}, // KHAROSHTHI DIGIT ONE..KHAROSHTHI NUMBER ONE
- {0x10A48, 0x10A4F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x10A50, 0x10A58, propertyDISALLOWED}, // KHAROSHTHI PUNCTUATION DOT..KHAROSHTHI PUNCT
- {0x10A59, 0x10A5F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x10A60, 0x10A7C, propertyPVALID}, // OLD SOUTH ARABIAN LETTER HE..OLD SOUTH ARABI
- {0x10A7D, 0x10A7F, propertyDISALLOWED}, // OLD SOUTH ARABIAN NUMBER ONE..OLD SOUTH ARAB
- {0x10A80, 0x10AFF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x10B00, 0x10B35, propertyPVALID}, // AVESTAN LETTER A..AVESTAN LETTER HE
- {0x10B36, 0x10B38, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x10B39, 0x10B3F, propertyDISALLOWED}, // AVESTAN ABBREVIATION MARK..LARGE ONE RING OV
- {0x10B40, 0x10B55, propertyPVALID}, // INSCRIPTIONAL PARTHIAN LETTER ALEPH..INSCRIP
- {0x10B56, 0x10B57, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x10B58, 0x10B5F, propertyDISALLOWED}, // INSCRIPTIONAL PARTHIAN NUMBER ONE..INSCRIPTI
- {0x10B60, 0x10B72, propertyPVALID}, // INSCRIPTIONAL PAHLAVI LETTER ALEPH..INSCRIPT
- {0x10B73, 0x10B77, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x10B78, 0x10B7F, propertyDISALLOWED}, // INSCRIPTIONAL PAHLAVI NUMBER ONE..INSCRIPTIO
- {0x10B80, 0x10BFF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x10C00, 0x10C48, propertyPVALID}, // OLD TURKIC LETTER ORKHON A..OLD TURKIC LETTE
- {0x10C49, 0x10E5F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x10E60, 0x10E7E, propertyDISALLOWED}, // RUMI DIGIT ONE..RUMI FRACTION TWO THIRDS
- {0x10E7F, 0x1107F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x11080, 0x110BA, propertyPVALID}, // KAITHI SIGN CANDRABINDU..KAITHI SIGN NUKTA
- {0x110BB, 0x110C1, propertyDISALLOWED}, // KAITHI ABBREVIATION SIGN..KAITHI DOUBLE DAND
- {0x110C2, 0x11FFF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x12000, 0x1236E, propertyPVALID}, // CUNEIFORM SIGN A..CUNEIFORM SIGN ZUM
- {0x1236F, 0x123FF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x12400, 0x12462, propertyDISALLOWED}, // CUNEIFORM NUMERIC SIGN TWO ASH..CUNEIFORM NU
- {0x12463, 0x1246F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x12470, 0x12473, propertyDISALLOWED}, // CUNEIFORM PUNCTUATION SIGN OLD ASSYRIAN WORD
- {0x12474, 0x12FFF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x13000, 0x1342E, propertyPVALID}, // EGYPTIAN HIEROGLYPH A001..EGYPTIAN HIEROGLYP
- {0x1342F, 0x1CFFF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1D000, 0x1D0F5, propertyDISALLOWED}, // BYZANTINE MUSICAL SYMBOL PSILI..BYZANTINE MU
- {0x1D0F6, 0x1D0FF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1D100, 0x1D126, propertyDISALLOWED}, // MUSICAL SYMBOL SINGLE BARLINE..MUSICAL SYMBO
- {0x1D127, 0x1D128, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1D129, 0x1D1DD, propertyDISALLOWED}, // MUSICAL SYMBOL MULTIPLE MEASURE REST..MUSICA
- {0x1D1DE, 0x1D1FF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1D200, 0x1D245, propertyDISALLOWED}, // GREEK VOCAL NOTATION SYMBOL-1..GREEK MUSICAL
- {0x1D246, 0x1D2FF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1D300, 0x1D356, propertyDISALLOWED}, // MONOGRAM FOR EARTH..TETRAGRAM FOR FOSTERING
- {0x1D357, 0x1D35F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1D360, 0x1D371, propertyDISALLOWED}, // COUNTING ROD UNIT DIGIT ONE..COUNTING ROD TE
- {0x1D372, 0x1D3FF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1D400, 0x1D454, propertyDISALLOWED}, // MATHEMATICAL BOLD CAPITAL A..MATHEMATICAL IT
- {0x1D455, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x1D456, 0x1D49C, propertyDISALLOWED}, // MATHEMATICAL ITALIC SMALL I..MATHEMATICAL SC
- {0x1D49D, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x1D49E, 0x1D49F, propertyDISALLOWED}, // MATHEMATICAL SCRIPT CAPITAL C..MATHEMATICAL
- {0x1D4A0, 0x1D4A1, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1D4A2, 0x0, propertyDISALLOWED}, // MATHEMATICAL SCRIPT CAPITAL G
- {0x1D4A3, 0x1D4A4, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1D4A5, 0x1D4A6, propertyDISALLOWED}, // MATHEMATICAL SCRIPT CAPITAL J..MATHEMATICAL
- {0x1D4A7, 0x1D4A8, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1D4A9, 0x1D4AC, propertyDISALLOWED}, // MATHEMATICAL SCRIPT CAPITAL N..MATHEMATICAL
- {0x1D4AD, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x1D4AE, 0x1D4B9, propertyDISALLOWED}, // MATHEMATICAL SCRIPT CAPITAL S..MATHEMATICAL
- {0x1D4BA, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x1D4BB, 0x0, propertyDISALLOWED}, // MATHEMATICAL SCRIPT SMALL F
- {0x1D4BC, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x1D4BD, 0x1D4C3, propertyDISALLOWED}, // MATHEMATICAL SCRIPT SMALL H..MATHEMATICAL SC
- {0x1D4C4, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x1D4C5, 0x1D505, propertyDISALLOWED}, // MATHEMATICAL SCRIPT SMALL P..MATHEMATICAL FR
- {0x1D506, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x1D507, 0x1D50A, propertyDISALLOWED}, // MATHEMATICAL FRAKTUR CAPITAL D..MATHEMATICAL
- {0x1D50B, 0x1D50C, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1D50D, 0x1D514, propertyDISALLOWED}, // MATHEMATICAL FRAKTUR CAPITAL J..MATHEMATICAL
- {0x1D515, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x1D516, 0x1D51C, propertyDISALLOWED}, // MATHEMATICAL FRAKTUR CAPITAL S..MATHEMATICAL
- {0x1D51D, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x1D51E, 0x1D539, propertyDISALLOWED}, // MATHEMATICAL FRAKTUR SMALL A..MATHEMATICAL D
- {0x1D53A, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x1D53B, 0x1D53E, propertyDISALLOWED}, // MATHEMATICAL DOUBLE-STRUCK CAPITAL D..MATHEM
- {0x1D53F, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x1D540, 0x1D544, propertyDISALLOWED}, // MATHEMATICAL DOUBLE-STRUCK CAPITAL I..MATHEM
- {0x1D545, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x1D546, 0x0, propertyDISALLOWED}, // MATHEMATICAL DOUBLE-STRUCK CAPITAL O
- {0x1D547, 0x1D549, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1D54A, 0x1D550, propertyDISALLOWED}, // MATHEMATICAL DOUBLE-STRUCK CAPITAL S..MATHEM
- {0x1D551, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x1D552, 0x1D6A5, propertyDISALLOWED}, // MATHEMATICAL DOUBLE-STRUCK SMALL A..MATHEMAT
- {0x1D6A6, 0x1D6A7, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1D6A8, 0x1D7CB, propertyDISALLOWED}, // MATHEMATICAL BOLD CAPITAL ALPHA..MATHEMATICA
- {0x1D7CC, 0x1D7CD, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1D7CE, 0x1D7FF, propertyDISALLOWED}, // MATHEMATICAL BOLD DIGIT ZERO..MATHEMATICAL M
- {0x1D800, 0x1EFFF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1F000, 0x1F02B, propertyDISALLOWED}, // MAHJONG TILE EAST WIND..MAHJONG TILE BACK
- {0x1F02C, 0x1F02F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1F030, 0x1F093, propertyDISALLOWED}, // DOMINO TILE HORIZONTAL BACK..DOMINO TILE VER
- {0x1F094, 0x1F0FF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1F100, 0x1F10A, propertyDISALLOWED}, // DIGIT ZERO FULL STOP..DIGIT NINE COMMA
- {0x1F10B, 0x1F10F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1F110, 0x1F12E, propertyDISALLOWED}, // PARENTHESIZED LATIN CAPITAL LETTER A..CIRCLE
- {0x1F12F, 0x1F130, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1F131, 0x0, propertyDISALLOWED}, // SQUARED LATIN CAPITAL LETTER B
- {0x1F132, 0x1F13C, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1F13D, 0x0, propertyDISALLOWED}, // SQUARED LATIN CAPITAL LETTER N
- {0x1F13E, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x1F13F, 0x0, propertyDISALLOWED}, // SQUARED LATIN CAPITAL LETTER P
- {0x1F140, 0x1F141, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1F142, 0x0, propertyDISALLOWED}, // SQUARED LATIN CAPITAL LETTER S
- {0x1F143, 0x1F145, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1F146, 0x0, propertyDISALLOWED}, // SQUARED LATIN CAPITAL LETTER W
- {0x1F147, 0x1F149, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1F14A, 0x1F14E, propertyDISALLOWED}, // SQUARED HV..SQUARED PPV
- {0x1F14F, 0x1F156, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1F157, 0x0, propertyDISALLOWED}, // NEGATIVE CIRCLED LATIN CAPITAL LETTER H
- {0x1F158, 0x1F15E, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1F15F, 0x0, propertyDISALLOWED}, // NEGATIVE CIRCLED LATIN CAPITAL LETTER P
- {0x1F160, 0x1F178, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1F179, 0x0, propertyDISALLOWED}, // NEGATIVE SQUARED LATIN CAPITAL LETTER J
- {0x1F17A, 0x0, propertyUNASSIGNED}, // <reserved>
- {0x1F17B, 0x1F17C, propertyDISALLOWED}, // NEGATIVE SQUARED LATIN CAPITAL LETTER L..NEG
- {0x1F17D, 0x1F17E, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1F17F, 0x0, propertyDISALLOWED}, // NEGATIVE SQUARED LATIN CAPITAL LETTER P
- {0x1F180, 0x1F189, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1F18A, 0x1F18D, propertyDISALLOWED}, // CROSSED NEGATIVE SQUARED LATIN CAPITAL LETTE
- {0x1F18E, 0x1F18F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1F190, 0x0, propertyDISALLOWED}, // SQUARE DJ
- {0x1F191, 0x1F1FF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1F200, 0x0, propertyDISALLOWED}, // SQUARE HIRAGANA HOKA
- {0x1F201, 0x1F20F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1F210, 0x1F231, propertyDISALLOWED}, // SQUARED CJK UNIFIED IDEOGRAPH-624B..SQUARED
- {0x1F232, 0x1F23F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1F240, 0x1F248, propertyDISALLOWED}, // TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRA
- {0x1F249, 0x1FFFD, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x1FFFE, 0x1FFFF, propertyDISALLOWED}, // <noncharacter>..<noncharacter>
- {0x20000, 0x2A6D6, propertyPVALID}, // <CJK Ideograph Extension B>..<CJK Ideograph
- {0x2A6D7, 0x2A6FF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x2A700, 0x2B734, propertyPVALID}, // <CJK Ideograph Extension C>..<CJK Ideograph
- {0x2B735, 0x2F7FF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x2F800, 0x2FA1D, propertyDISALLOWED}, // CJK COMPATIBILITY IDEOGRAPH-2F800..CJK COMPA
- {0x2FA1E, 0x2FFFD, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x2FFFE, 0x2FFFF, propertyDISALLOWED}, // <noncharacter>..<noncharacter>
- {0x30000, 0x3FFFD, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x3FFFE, 0x3FFFF, propertyDISALLOWED}, // <noncharacter>..<noncharacter>
- {0x40000, 0x4FFFD, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x4FFFE, 0x4FFFF, propertyDISALLOWED}, // <noncharacter>..<noncharacter>
- {0x50000, 0x5FFFD, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x5FFFE, 0x5FFFF, propertyDISALLOWED}, // <noncharacter>..<noncharacter>
- {0x60000, 0x6FFFD, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x6FFFE, 0x6FFFF, propertyDISALLOWED}, // <noncharacter>..<noncharacter>
- {0x70000, 0x7FFFD, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x7FFFE, 0x7FFFF, propertyDISALLOWED}, // <noncharacter>..<noncharacter>
- {0x80000, 0x8FFFD, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x8FFFE, 0x8FFFF, propertyDISALLOWED}, // <noncharacter>..<noncharacter>
- {0x90000, 0x9FFFD, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0x9FFFE, 0x9FFFF, propertyDISALLOWED}, // <noncharacter>..<noncharacter>
- {0xA0000, 0xAFFFD, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xAFFFE, 0xAFFFF, propertyDISALLOWED}, // <noncharacter>..<noncharacter>
- {0xB0000, 0xBFFFD, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xBFFFE, 0xBFFFF, propertyDISALLOWED}, // <noncharacter>..<noncharacter>
- {0xC0000, 0xCFFFD, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xCFFFE, 0xCFFFF, propertyDISALLOWED}, // <noncharacter>..<noncharacter>
- {0xD0000, 0xDFFFD, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xDFFFE, 0xDFFFF, propertyDISALLOWED}, // <noncharacter>..<noncharacter>
- {0xE0000, 0x0, propertyUNASSIGNED}, // <reserved>
- {0xE0001, 0x0, propertyDISALLOWED}, // LANGUAGE TAG
- {0xE0002, 0xE001F, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xE0020, 0xE007F, propertyDISALLOWED}, // TAG SPACE..CANCEL TAG
- {0xE0080, 0xE00FF, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xE0100, 0xE01EF, propertyDISALLOWED}, // VARIATION SELECTOR-17..VARIATION SELECTOR-25
- {0xE01F0, 0xEFFFD, propertyUNASSIGNED}, // <reserved>..<reserved>
- {0xEFFFE, 0x10FFFF, propertyDISALLOWED}, // <noncharacter>..<noncharacter>
-}
diff --git a/vendor/github.com/miekg/dns/idn/example_test.go b/vendor/github.com/miekg/dns/idn/example_test.go
deleted file mode 100644
index 8833cd91d..000000000
--- a/vendor/github.com/miekg/dns/idn/example_test.go
+++ /dev/null
@@ -1,18 +0,0 @@
-package idn_test
-
-import (
- "fmt"
- "github.com/miekg/dns/idn"
-)
-
-func ExampleToPunycode() {
- name := "インターネット.テスト"
- fmt.Printf("%s -> %s", name, idn.ToPunycode(name))
- // Output: インターネット.テスト -> xn--eckucmux0ukc.xn--zckzah
-}
-
-func ExampleFromPunycode() {
- name := "xn--mgbaja8a1hpac.xn--mgbachtv"
- fmt.Printf("%s -> %s", name, idn.FromPunycode(name))
- // Output: xn--mgbaja8a1hpac.xn--mgbachtv -> الانترنت.اختبار
-}
diff --git a/vendor/github.com/miekg/dns/idn/punycode.go b/vendor/github.com/miekg/dns/idn/punycode.go
deleted file mode 100644
index 1d03bf6ae..000000000
--- a/vendor/github.com/miekg/dns/idn/punycode.go
+++ /dev/null
@@ -1,370 +0,0 @@
-// Package idn implements encoding from and to punycode as speficied by RFC 3492.
-package idn
-
-import (
- "bytes"
- "strings"
- "unicode"
- "unicode/utf8"
-
- "github.com/miekg/dns"
-)
-
-// Implementation idea from RFC itself and from from IDNA::Punycode created by
-// Tatsuhiko Miyagawa <miyagawa@bulknews.net> and released under Perl Artistic
-// License in 2002.
-
-const (
- _MIN rune = 1
- _MAX rune = 26
- _SKEW rune = 38
- _BASE rune = 36
- _BIAS rune = 72
- _N rune = 128
- _DAMP rune = 700
-
- _DELIMITER = '-'
- _PREFIX = "xn--"
-)
-
-// ToPunycode converts unicode domain names to DNS-appropriate punycode names.
-// This function will return an empty string result for domain names with
-// invalid unicode strings. This function expects domain names in lowercase.
-func ToPunycode(s string) string {
- // Early check to see if encoding is needed.
- // This will prevent making heap allocations when not needed.
- if !needToPunycode(s) {
- return s
- }
-
- tokens := dns.SplitDomainName(s)
- switch {
- case s == "":
- return ""
- case tokens == nil: // s == .
- return "."
- case s[len(s)-1] == '.':
- tokens = append(tokens, "")
- }
-
- for i := range tokens {
- t := encode([]byte(tokens[i]))
- if t == nil {
- return ""
- }
- tokens[i] = string(t)
- }
- return strings.Join(tokens, ".")
-}
-
-// FromPunycode returns unicode domain name from provided punycode string.
-// This function expects punycode strings in lowercase.
-func FromPunycode(s string) string {
- // Early check to see if decoding is needed.
- // This will prevent making heap allocations when not needed.
- if !needFromPunycode(s) {
- return s
- }
-
- tokens := dns.SplitDomainName(s)
- switch {
- case s == "":
- return ""
- case tokens == nil: // s == .
- return "."
- case s[len(s)-1] == '.':
- tokens = append(tokens, "")
- }
- for i := range tokens {
- tokens[i] = string(decode([]byte(tokens[i])))
- }
- return strings.Join(tokens, ".")
-}
-
-// digitval converts single byte into meaningful value that's used to calculate decoded unicode character.
-const errdigit = 0xffff
-
-func digitval(code rune) rune {
- switch {
- case code >= 'A' && code <= 'Z':
- return code - 'A'
- case code >= 'a' && code <= 'z':
- return code - 'a'
- case code >= '0' && code <= '9':
- return code - '0' + 26
- }
- return errdigit
-}
-
-// lettercode finds BASE36 byte (a-z0-9) based on calculated number.
-func lettercode(digit rune) rune {
- switch {
- case digit >= 0 && digit <= 25:
- return digit + 'a'
- case digit >= 26 && digit <= 36:
- return digit - 26 + '0'
- }
- panic("dns: not reached")
-}
-
-// adapt calculates next bias to be used for next iteration delta.
-func adapt(delta rune, numpoints int, firsttime bool) rune {
- if firsttime {
- delta /= _DAMP
- } else {
- delta /= 2
- }
-
- var k rune
- for delta = delta + delta/rune(numpoints); delta > (_BASE-_MIN)*_MAX/2; k += _BASE {
- delta /= _BASE - _MIN
- }
-
- return k + ((_BASE-_MIN+1)*delta)/(delta+_SKEW)
-}
-
-// next finds minimal rune (one with lowest codepoint value) that should be equal or above boundary.
-func next(b []rune, boundary rune) rune {
- if len(b) == 0 {
- panic("dns: invalid set of runes to determine next one")
- }
- m := b[0]
- for _, x := range b[1:] {
- if x >= boundary && (m < boundary || x < m) {
- m = x
- }
- }
- return m
-}
-
-// preprune converts unicode rune to lower case. At this time it's not
-// supporting all things described in RFCs.
-func preprune(r rune) rune {
- if unicode.IsUpper(r) {
- r = unicode.ToLower(r)
- }
- return r
-}
-
-// tfunc is a function that helps calculate each character weight.
-func tfunc(k, bias rune) rune {
- switch {
- case k <= bias:
- return _MIN
- case k >= bias+_MAX:
- return _MAX
- }
- return k - bias
-}
-
-// needToPunycode returns true for strings that require punycode encoding
-// (contain unicode characters).
-func needToPunycode(s string) bool {
- // This function is very similar to bytes.Runes. We don't use bytes.Runes
- // because it makes a heap allocation that's not needed here.
- for i := 0; len(s) > 0; i++ {
- r, l := utf8.DecodeRuneInString(s)
- if r > 0x7f {
- return true
- }
- s = s[l:]
- }
- return false
-}
-
-// needFromPunycode returns true for strings that require punycode decoding.
-func needFromPunycode(s string) bool {
- if s == "." {
- return false
- }
-
- off := 0
- end := false
- pl := len(_PREFIX)
- sl := len(s)
-
- // If s starts with _PREFIX.
- if sl > pl && s[off:off+pl] == _PREFIX {
- return true
- }
-
- for {
- // Find the part after the next ".".
- off, end = dns.NextLabel(s, off)
- if end {
- return false
- }
- // If this parts starts with _PREFIX.
- if sl-off > pl && s[off:off+pl] == _PREFIX {
- return true
- }
- }
-}
-
-// encode transforms Unicode input bytes (that represent DNS label) into
-// punycode bytestream. This function would return nil if there's an invalid
-// character in the label.
-func encode(input []byte) []byte {
- n, bias := _N, _BIAS
-
- b := bytes.Runes(input)
- for i := range b {
- if !isValidRune(b[i]) {
- return nil
- }
-
- b[i] = preprune(b[i])
- }
-
- basic := make([]byte, 0, len(b))
- for _, ltr := range b {
- if ltr <= 0x7f {
- basic = append(basic, byte(ltr))
- }
- }
- basiclen := len(basic)
- fulllen := len(b)
- if basiclen == fulllen {
- return basic
- }
-
- var out bytes.Buffer
-
- out.WriteString(_PREFIX)
- if basiclen > 0 {
- out.Write(basic)
- out.WriteByte(_DELIMITER)
- }
-
- var (
- ltr, nextltr rune
- delta, q rune // delta calculation (see rfc)
- t, k, cp rune // weight and codepoint calculation
- )
-
- for h := basiclen; h < fulllen; n, delta = n+1, delta+1 {
- nextltr = next(b, n)
- delta, n = delta+(nextltr-n)*rune(h+1), nextltr
-
- for _, ltr = range b {
- if ltr < n {
- delta++
- }
- if ltr == n {
- q = delta
- for k = _BASE; ; k += _BASE {
- t = tfunc(k, bias)
- if q < t {
- break
- }
- cp = t + ((q - t) % (_BASE - t))
- out.WriteRune(lettercode(cp))
- q = (q - t) / (_BASE - t)
- }
-
- out.WriteRune(lettercode(q))
-
- bias = adapt(delta, h+1, h == basiclen)
- h, delta = h+1, 0
- }
- }
- }
- return out.Bytes()
-}
-
-// decode transforms punycode input bytes (that represent DNS label) into Unicode bytestream.
-func decode(b []byte) []byte {
- src := b // b would move and we need to keep it
-
- n, bias := _N, _BIAS
- if !bytes.HasPrefix(b, []byte(_PREFIX)) {
- return b
- }
- out := make([]rune, 0, len(b))
- b = b[len(_PREFIX):]
- for pos := len(b) - 1; pos >= 0; pos-- {
- // only last delimiter is our interest
- if b[pos] == _DELIMITER {
- out = append(out, bytes.Runes(b[:pos])...)
- b = b[pos+1:] // trim source string
- break
- }
- }
- if len(b) == 0 {
- return src
- }
- var (
- i, oldi, w rune
- ch byte
- t, digit rune
- ln int
- )
-
- for i = 0; len(b) > 0; i++ {
- oldi, w = i, 1
- for k := _BASE; len(b) > 0; k += _BASE {
- ch, b = b[0], b[1:]
- digit = digitval(rune(ch))
- if digit == errdigit {
- return src
- }
- i += digit * w
- if i < 0 {
- // safety check for rune overflow
- return src
- }
-
- t = tfunc(k, bias)
- if digit < t {
- break
- }
-
- w *= _BASE - t
- }
- ln = len(out) + 1
- bias = adapt(i-oldi, ln, oldi == 0)
- n += i / rune(ln)
- i = i % rune(ln)
- // insert
- out = append(out, 0)
- copy(out[i+1:], out[i:])
- out[i] = n
- }
-
- var ret bytes.Buffer
- for _, r := range out {
- ret.WriteRune(r)
- }
- return ret.Bytes()
-}
-
-// isValidRune checks if the character is valid. We will look for the
-// character property in the code points list. For now we aren't checking special
-// rules in case of contextual property
-func isValidRune(r rune) bool {
- return findProperty(r) == propertyPVALID
-}
-
-// findProperty will try to check the code point property of the given
-// character. It will use a binary search algorithm as we have a slice of
-// ordered ranges (average case performance O(log n))
-func findProperty(r rune) property {
- imin, imax := 0, len(codePoints)
-
- for imax >= imin {
- imid := (imin + imax) / 2
-
- codePoint := codePoints[imid]
- if (codePoint.start == r && codePoint.end == 0) || (codePoint.start <= r && codePoint.end >= r) {
- return codePoint.state
- }
-
- if (codePoint.end > 0 && codePoint.end < r) || (codePoint.end == 0 && codePoint.start < r) {
- imin = imid + 1
- } else {
- imax = imid - 1
- }
- }
-
- return propertyUnknown
-}
diff --git a/vendor/github.com/miekg/dns/idn/punycode_test.go b/vendor/github.com/miekg/dns/idn/punycode_test.go
deleted file mode 100644
index 9c9a15f0b..000000000
--- a/vendor/github.com/miekg/dns/idn/punycode_test.go
+++ /dev/null
@@ -1,116 +0,0 @@
-package idn
-
-import (
- "strings"
- "testing"
-)
-
-var testcases = [][2]string{
- {"", ""},
- {"a", "a"},
- {"a-b", "a-b"},
- {"a-b-c", "a-b-c"},
- {"abc", "abc"},
- {"я", "xn--41a"},
- {"zя", "xn--z-0ub"},
- {"яZ", "xn--z-zub"},
- {"а-я", "xn----7sb8g"},
- {"إختبار", "xn--kgbechtv"},
- {"آزمایشی", "xn--hgbk6aj7f53bba"},
- {"测试", "xn--0zwm56d"},
- {"測試", "xn--g6w251d"},
- {"испытание", "xn--80akhbyknj4f"},
- {"परीक्षा", "xn--11b5bs3a9aj6g"},
- {"δοκιμή", "xn--jxalpdlp"},
- {"테스트", "xn--9t4b11yi5a"},
- {"טעסט", "xn--deba0ad"},
- {"テスト", "xn--zckzah"},
- {"பரிட்சை", "xn--hlcj6aya9esc7a"},
- {"mamão-com-açúcar", "xn--mamo-com-acar-yeb1e6q"},
- {"σ", "xn--4xa"},
-}
-
-func TestEncodeDecodePunycode(t *testing.T) {
- for _, tst := range testcases {
- enc := encode([]byte(tst[0]))
- if string(enc) != tst[1] {
- t.Errorf("%s encodeded as %s but should be %s", tst[0], enc, tst[1])
- }
- dec := decode([]byte(tst[1]))
- if string(dec) != strings.ToLower(tst[0]) {
- t.Errorf("%s decoded as %s but should be %s", tst[1], dec, strings.ToLower(tst[0]))
- }
- }
-}
-
-func TestToFromPunycode(t *testing.T) {
- for _, tst := range testcases {
- // assert unicode.com == punycode.com
- full := ToPunycode(tst[0] + ".com")
- if full != tst[1]+".com" {
- t.Errorf("invalid result from string conversion to punycode, %s and should be %s.com", full, tst[1])
- }
- // assert punycode.punycode == unicode.unicode
- decoded := FromPunycode(tst[1] + "." + tst[1])
- if decoded != strings.ToLower(tst[0]+"."+tst[0]) {
- t.Errorf("invalid result from string conversion to punycode, %s and should be %s.%s", decoded, tst[0], tst[0])
- }
- }
-}
-
-func TestEncodeDecodeFinalPeriod(t *testing.T) {
- for _, tst := range testcases {
- // assert unicode.com. == punycode.com.
- full := ToPunycode(tst[0] + ".")
- if full != tst[1]+"." {
- t.Errorf("invalid result from string conversion to punycode when period added at the end, %#v and should be %#v", full, tst[1]+".")
- }
- // assert punycode.com. == unicode.com.
- decoded := FromPunycode(tst[1] + ".")
- if decoded != strings.ToLower(tst[0]+".") {
- t.Errorf("invalid result from string conversion to punycode when period added, %#v and should be %#v", decoded, tst[0]+".")
- }
- full = ToPunycode(tst[0])
- if full != tst[1] {
- t.Errorf("invalid result from string conversion to punycode when no period added at the end, %#v and should be %#v", full, tst[1]+".")
- }
- // assert punycode.com. == unicode.com.
- decoded = FromPunycode(tst[1])
- if decoded != strings.ToLower(tst[0]) {
- t.Errorf("invalid result from string conversion to punycode when no period added, %#v and should be %#v", decoded, tst[0]+".")
- }
- }
-}
-
-var invalidACEs = []string{
- "xn--*",
- "xn--",
- "xn---",
- "xn--a000000000",
-}
-
-func TestInvalidPunycode(t *testing.T) {
- for _, d := range invalidACEs {
- s := FromPunycode(d)
- if s != d {
- t.Errorf("Changed invalid name %s to %#v", d, s)
- }
- }
-}
-
-// You can verify the labels that are valid or not comparing to the Verisign
-// website: http://mct.verisign-grs.com/
-var invalidUnicodes = []string{
- "Σ",
- "ЯZ",
- "Испытание",
-}
-
-func TestInvalidUnicodes(t *testing.T) {
- for _, d := range invalidUnicodes {
- s := ToPunycode(d)
- if s != "" {
- t.Errorf("Changed invalid name %s to %#v", d, s)
- }
- }
-}
diff --git a/vendor/github.com/miekg/dns/internal/socket/cmsghdr.go b/vendor/github.com/miekg/dns/internal/socket/cmsghdr.go
deleted file mode 100644
index 62f2d2f74..000000000
--- a/vendor/github.com/miekg/dns/internal/socket/cmsghdr.go
+++ /dev/null
@@ -1,7 +0,0 @@
-// +build linux
-
-package socket
-
-func (h *cmsghdr) len() int { return int(h.Len) }
-func (h *cmsghdr) lvl() int { return int(h.Level) }
-func (h *cmsghdr) typ() int { return int(h.Type) }
diff --git a/vendor/github.com/miekg/dns/internal/socket/controlmessage.go b/vendor/github.com/miekg/dns/internal/socket/controlmessage.go
deleted file mode 100644
index 3176e9602..000000000
--- a/vendor/github.com/miekg/dns/internal/socket/controlmessage.go
+++ /dev/null
@@ -1,118 +0,0 @@
-package socket
-
-import (
- "errors"
- "unsafe"
-)
-
-func controlHeaderLen() int {
- return roundup(sizeofCmsghdr)
-}
-
-func controlMessageLen(dataLen int) int {
- return roundup(sizeofCmsghdr) + dataLen
-}
-
-// returns the whole length of control message.
-func ControlMessageSpace(dataLen int) int {
- return roundup(sizeofCmsghdr) + roundup(dataLen)
-}
-
-// A ControlMessage represents the head message in a stream of control
-// messages.
-//
-// A control message comprises of a header, data and a few padding
-// fields to conform to the interface to the kernel.
-//
-// See RFC 3542 for further information.
-type ControlMessage []byte
-
-// Data returns the data field of the control message at the head.
-func (m ControlMessage) Data(dataLen int) []byte {
- l := controlHeaderLen()
- if len(m) < l || len(m) < l+dataLen {
- return nil
- }
- return m[l : l+dataLen]
-}
-
-// ParseHeader parses and returns the header fields of the control
-// message at the head.
-func (m ControlMessage) ParseHeader() (lvl, typ, dataLen int, err error) {
- l := controlHeaderLen()
- if len(m) < l {
- return 0, 0, 0, errors.New("short message")
- }
- h := (*cmsghdr)(unsafe.Pointer(&m[0]))
- return h.lvl(), h.typ(), int(uint64(h.len()) - uint64(l)), nil
-}
-
-// Next returns the control message at the next.
-func (m ControlMessage) Next(dataLen int) ControlMessage {
- l := ControlMessageSpace(dataLen)
- if len(m) < l {
- return nil
- }
- return m[l:]
-}
-
-// MarshalHeader marshals the header fields of the control message at
-// the head.
-func (m ControlMessage) MarshalHeader(lvl, typ, dataLen int) error {
- if len(m) < controlHeaderLen() {
- return errors.New("short message")
- }
- h := (*cmsghdr)(unsafe.Pointer(&m[0]))
- h.set(controlMessageLen(dataLen), lvl, typ)
- return nil
-}
-
-// Marshal marshals the control message at the head, and returns the next
-// control message.
-func (m ControlMessage) Marshal(lvl, typ int, data []byte) (ControlMessage, error) {
- l := len(data)
- if len(m) < ControlMessageSpace(l) {
- return nil, errors.New("short message")
- }
- h := (*cmsghdr)(unsafe.Pointer(&m[0]))
- h.set(controlMessageLen(l), lvl, typ)
- if l > 0 {
- copy(m.Data(l), data)
- }
- return m.Next(l), nil
-}
-
-// Parse parses as a single or multiple control messages.
-func (m ControlMessage) Parse() ([]ControlMessage, error) {
- var ms []ControlMessage
- for len(m) >= controlHeaderLen() {
- h := (*cmsghdr)(unsafe.Pointer(&m[0]))
- l := h.len()
- if l <= 0 {
- return nil, errors.New("invalid header length")
- }
- if uint64(l) < uint64(controlHeaderLen()) {
- return nil, errors.New("invalid message length")
- }
- if uint64(l) > uint64(len(m)) {
- return nil, errors.New("short buffer")
- }
- ms = append(ms, ControlMessage(m[:l]))
- ll := l - controlHeaderLen()
- if len(m) >= ControlMessageSpace(ll) {
- m = m[ControlMessageSpace(ll):]
- } else {
- m = m[controlMessageLen(ll):]
- }
- }
- return ms, nil
-}
-
-// NewControlMessage returns a new stream of control messages.
-func NewControlMessage(dataLen []int) ControlMessage {
- var l int
- for i := range dataLen {
- l += ControlMessageSpace(dataLen[i])
- }
- return make([]byte, l)
-}
diff --git a/vendor/github.com/miekg/dns/internal/socket/controlmessage_test.go b/vendor/github.com/miekg/dns/internal/socket/controlmessage_test.go
deleted file mode 100644
index e9fff4d45..000000000
--- a/vendor/github.com/miekg/dns/internal/socket/controlmessage_test.go
+++ /dev/null
@@ -1,103 +0,0 @@
-// +build linux
-
-package socket
-
-import (
- "bytes"
- "testing"
-)
-
-type mockControl struct {
- Level int
- Type int
- Data []byte
-}
-
-func TestControlMessage(t *testing.T) {
- for _, tt := range []struct {
- cs []mockControl
- }{
- {
- []mockControl{
- {Level: 1, Type: 1},
- },
- },
- {
- []mockControl{
- {Level: 2, Type: 2, Data: []byte{0xfe}},
- },
- },
- {
- []mockControl{
- {Level: 3, Type: 3, Data: []byte{0xfe, 0xff, 0xff, 0xfe}},
- },
- },
- {
- []mockControl{
- {Level: 4, Type: 4, Data: []byte{0xfe, 0xff, 0xff, 0xfe, 0xfe, 0xff, 0xff, 0xfe}},
- },
- },
- {
- []mockControl{
- {Level: 4, Type: 4, Data: []byte{0xfe, 0xff, 0xff, 0xfe, 0xfe, 0xff, 0xff, 0xfe}},
- {Level: 2, Type: 2, Data: []byte{0xfe}},
- },
- },
- } {
- var w []byte
- var tailPadLen int
- mm := NewControlMessage([]int{0})
- for i, c := range tt.cs {
- m := NewControlMessage([]int{len(c.Data)})
- l := len(m) - len(mm)
- if i == len(tt.cs)-1 && l > len(c.Data) {
- tailPadLen = l - len(c.Data)
- }
- w = append(w, m...)
- }
-
- var err error
- ww := make([]byte, len(w))
- copy(ww, w)
- m := ControlMessage(ww)
- for _, c := range tt.cs {
- if err = m.MarshalHeader(c.Level, c.Type, len(c.Data)); err != nil {
- t.Fatalf("(%v).MarshalHeader() = %v", tt.cs, err)
- }
- copy(m.Data(len(c.Data)), c.Data)
- m = m.Next(len(c.Data))
- }
- m = ControlMessage(w)
- for _, c := range tt.cs {
- m, err = m.Marshal(c.Level, c.Type, c.Data)
- if err != nil {
- t.Fatalf("(%v).Marshal() = %v", tt.cs, err)
- }
- }
- if !bytes.Equal(ww, w) {
- t.Fatalf("got %#v; want %#v", ww, w)
- }
-
- ws := [][]byte{w}
- if tailPadLen > 0 {
- // Test a message with no tail padding.
- nopad := w[:len(w)-tailPadLen]
- ws = append(ws, [][]byte{nopad}...)
- }
- for _, w := range ws {
- ms, err := ControlMessage(w).Parse()
- if err != nil {
- t.Fatalf("(%v).Parse() = %v", tt.cs, err)
- }
- for i, m := range ms {
- lvl, typ, dataLen, err := m.ParseHeader()
- if err != nil {
- t.Fatalf("(%v).ParseHeader() = %v", tt.cs, err)
- }
- if lvl != tt.cs[i].Level || typ != tt.cs[i].Type || dataLen != len(tt.cs[i].Data) {
- t.Fatalf("%v: got %d, %d, %d; want %d, %d, %d", tt.cs[i], lvl, typ, dataLen, tt.cs[i].Level, tt.cs[i].Type, len(tt.cs[i].Data))
- }
- }
- }
- }
-}
diff --git a/vendor/github.com/miekg/dns/internal/socket/socket.go b/vendor/github.com/miekg/dns/internal/socket/socket.go
deleted file mode 100644
index edb58e29a..000000000
--- a/vendor/github.com/miekg/dns/internal/socket/socket.go
+++ /dev/null
@@ -1,4 +0,0 @@
-// Package socket contains ControlMessage parsing code from
-// golang.org/x/net/internal/socket. Instead of supporting all possible
-// architectures, we're only supporting linux 32/64 bit.
-package socket
diff --git a/vendor/github.com/miekg/dns/internal/socket/sys.go b/vendor/github.com/miekg/dns/internal/socket/sys.go
deleted file mode 100644
index 2f3f5cfed..000000000
--- a/vendor/github.com/miekg/dns/internal/socket/sys.go
+++ /dev/null
@@ -1,14 +0,0 @@
-package socket
-
-import "unsafe"
-
-var (
- kernelAlign = func() int {
- var p uintptr
- return int(unsafe.Sizeof(p))
- }()
-)
-
-func roundup(l int) int {
- return (l + kernelAlign - 1) & ^(kernelAlign - 1)
-}
diff --git a/vendor/github.com/miekg/dns/leak_test.go b/vendor/github.com/miekg/dns/leak_test.go
new file mode 100644
index 000000000..af37011d7
--- /dev/null
+++ b/vendor/github.com/miekg/dns/leak_test.go
@@ -0,0 +1,71 @@
+package dns
+
+import (
+ "fmt"
+ "os"
+ "runtime"
+ "sort"
+ "strings"
+ "testing"
+ "time"
+)
+
+// copied from net/http/main_test.go
+
+func interestingGoroutines() (gs []string) {
+ buf := make([]byte, 2<<20)
+ buf = buf[:runtime.Stack(buf, true)]
+ for _, g := range strings.Split(string(buf), "\n\n") {
+ sl := strings.SplitN(g, "\n", 2)
+ if len(sl) != 2 {
+ continue
+ }
+ stack := strings.TrimSpace(sl[1])
+ if stack == "" ||
+ strings.Contains(stack, "testing.(*M).before.func1") ||
+ strings.Contains(stack, "os/signal.signal_recv") ||
+ strings.Contains(stack, "created by net.startServer") ||
+ strings.Contains(stack, "created by testing.RunTests") ||
+ strings.Contains(stack, "closeWriteAndWait") ||
+ strings.Contains(stack, "testing.Main(") ||
+ strings.Contains(stack, "testing.(*T).Run(") ||
+ // These only show up with GOTRACEBACK=2; Issue 5005 (comment 28)
+ strings.Contains(stack, "runtime.goexit") ||
+ strings.Contains(stack, "created by runtime.gc") ||
+ strings.Contains(stack, "dns.interestingGoroutines") ||
+ strings.Contains(stack, "runtime.MHeap_Scavenger") {
+ continue
+ }
+ gs = append(gs, stack)
+ }
+ sort.Strings(gs)
+ return
+}
+
+func goroutineLeaked() error {
+ if testing.Short() {
+ // Don't worry about goroutine leaks in -short mode or in
+ // benchmark mode. Too distracting when there are false positives.
+ return nil
+ }
+
+ var stackCount map[string]int
+ for i := 0; i < 5; i++ {
+ n := 0
+ stackCount = make(map[string]int)
+ gs := interestingGoroutines()
+ for _, g := range gs {
+ stackCount[g]++
+ n++
+ }
+ if n == 0 {
+ return nil
+ }
+ // Wait for goroutines to schedule and die off:
+ time.Sleep(100 * time.Millisecond)
+ }
+ for stack, count := range stackCount {
+ fmt.Fprintf(os.Stderr, "%d instances of:\n%s\n", count, stack)
+ }
+ return fmt.Errorf("too many goroutines running after dns test(s)")
+}
diff --git a/vendor/github.com/miekg/dns/msg.go b/vendor/github.com/miekg/dns/msg.go
index afce17635..975dde781 100644
--- a/vendor/github.com/miekg/dns/msg.go
+++ b/vendor/github.com/miekg/dns/msg.go
@@ -612,8 +612,8 @@ func UnpackRR(msg []byte, off int) (rr RR, off1 int, err error) {
// If we cannot unpack the whole array, then it will return nil
func unpackRRslice(l int, msg []byte, off int) (dst1 []RR, off1 int, err error) {
var r RR
- // Optimistically make dst be the length that was sent
- dst := make([]RR, 0, l)
+ // Don't pre-allocate, l may be under attacker control
+ var dst []RR
for i := 0; i < l; i++ {
off1 := off
r, off, err = UnpackRR(msg, off)
@@ -811,13 +811,19 @@ func (dns *Msg) Unpack(msg []byte) (err error) {
dns.CheckingDisabled = (dh.Bits & _CD) != 0
dns.Rcode = int(dh.Bits & 0xF)
+ // If we are at the end of the message we should return *just* the
+ // header. This can still be useful to the caller. 9.9.9.9 sends these
+ // when responding with REFUSED for instance.
if off == len(msg) {
- return ErrTruncated
+ // reset sections before returning
+ dns.Question, dns.Answer, dns.Ns, dns.Extra = nil, nil, nil, nil
+ return nil
}
- // Optimistically use the count given to us in the header
- dns.Question = make([]Question, 0, int(dh.Qdcount))
-
+ // Qdcount, Ancount, Nscount, Arcount can't be trusted, as they are
+ // attacker controlled. This means we can't use them to pre-allocate
+ // slices.
+ dns.Question = nil
for i := 0; i < int(dh.Qdcount); i++ {
off1 := off
var q Question
diff --git a/vendor/github.com/miekg/dns/msg_generate.go b/vendor/github.com/miekg/dns/msg_generate.go
index 4d9f81d43..8ba609f72 100644
--- a/vendor/github.com/miekg/dns/msg_generate.go
+++ b/vendor/github.com/miekg/dns/msg_generate.go
@@ -18,8 +18,7 @@ import (
)
var packageHdr = `
-// *** DO NOT MODIFY ***
-// AUTOGENERATED BY go generate from msg_generate.go
+// Code generated by "go run msg_generate.go"; DO NOT EDIT.
package dns
diff --git a/vendor/github.com/miekg/dns/msg_helpers.go b/vendor/github.com/miekg/dns/msg_helpers.go
index 0ca12b048..946d5acbf 100644
--- a/vendor/github.com/miekg/dns/msg_helpers.go
+++ b/vendor/github.com/miekg/dns/msg_helpers.go
@@ -406,16 +406,13 @@ Option:
}
edns = append(edns, e)
off += int(optlen)
- case EDNS0SUBNET, EDNS0SUBNETDRAFT:
+ case EDNS0SUBNET:
e := new(EDNS0_SUBNET)
if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
return nil, len(msg), err
}
edns = append(edns, e)
off += int(optlen)
- if code == EDNS0SUBNETDRAFT {
- e.DraftOption = true
- }
case EDNS0COOKIE:
e := new(EDNS0_COOKIE)
if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
diff --git a/vendor/github.com/miekg/dns/parse_test.go b/vendor/github.com/miekg/dns/parse_test.go
index e7ffd4084..efdaf59af 100644
--- a/vendor/github.com/miekg/dns/parse_test.go
+++ b/vendor/github.com/miekg/dns/parse_test.go
@@ -145,7 +145,7 @@ func TestTXTEscapeParsing(t *testing.T) {
}
func GenerateDomain(r *rand.Rand, size int) []byte {
- dnLen := size % 70 // artificially limit size so there's less to intrepret if a failure occurs
+ dnLen := size % 70 // artificially limit size so there's less to interpret if a failure occurs
var dn []byte
done := false
for i := 0; i < dnLen && !done; {
@@ -203,7 +203,7 @@ func TestDomainQuick(t *testing.T) {
}
func GenerateTXT(r *rand.Rand, size int) []byte {
- rdLen := size % 300 // artificially limit size so there's less to intrepret if a failure occurs
+ rdLen := size % 300 // artificially limit size so there's less to interpret if a failure occurs
var rd []byte
for i := 0; i < rdLen; {
max := rdLen - 1
@@ -433,6 +433,7 @@ func TestParseClass(t *testing.T) {
// ClassANY can not occur in zone files
// "t.example.com. ANY A 127.0.0.1": "t.example.com. 3600 ANY A 127.0.0.1",
"t.example.com. NONE A 127.0.0.1": "t.example.com. 3600 NONE A 127.0.0.1",
+ "t.example.com. CLASS255 A 127.0.0.1": "t.example.com. 3600 CLASS255 A 127.0.0.1",
}
for i, o := range tests {
rr, err := NewRR(i)
@@ -1104,6 +1105,7 @@ func TestNewPrivateKey(t *testing.T) {
{RSASHA1, 1024},
{RSASHA256, 2048},
{DSA, 1024},
+ {ED25519, 256},
}
for _, algo := range algorithms {
@@ -1406,6 +1408,34 @@ func TestParseAVC(t *testing.T) {
}
}
+func TestParseCSYNC(t *testing.T) {
+ syncs := map[string]string{
+ `example.com. 3600 IN CSYNC 66 3 A NS AAAA`: `example.com. 3600 IN CSYNC 66 3 A NS AAAA`,
+ }
+ for s, o := range syncs {
+ rr, err := NewRR(s)
+ if err != nil {
+ t.Error("failed to parse RR: ", err)
+ continue
+ }
+ if rr.String() != o {
+ t.Errorf("`%s' should be equal to\n`%s', but is `%s'", s, o, rr.String())
+ }
+ }
+}
+
+func TestParseBadNAPTR(t *testing.T) {
+ // Should look like: mplus.ims.vodafone.com. 3600 IN NAPTR 10 100 "S" "SIP+D2U" "" _sip._udp.mplus.ims.vodafone.com.
+ naptr := `mplus.ims.vodafone.com. 3600 IN NAPTR 10 100 S SIP+D2U _sip._udp.mplus.ims.vodafone.com.`
+ _, err := NewRR(naptr) // parse fails, we should not have leaked a goroutine.
+ if err == nil {
+ t.Fatalf("parsing NAPTR should have failed: %s", naptr)
+ }
+ if err := goroutineLeaked(); err != nil {
+ t.Errorf("leaked goroutines: %s", err)
+ }
+}
+
func TestUnbalancedParens(t *testing.T) {
sig := `example.com. 3600 IN RRSIG MX 15 2 3600 (
1440021600 1438207200 3613 example.com. (
@@ -1413,6 +1443,23 @@ func TestUnbalancedParens(t *testing.T) {
x8A4M3e23mRZ9VrbpMngwcrqNAg== )`
_, err := NewRR(sig)
if err == nil {
- t.Fatalf("Failed to detect extra opening brace")
+ t.Fatalf("failed to detect extra opening brace")
+ }
+}
+
+func TestBad(t *testing.T) {
+ tests := []string{
+ `" TYPE257 9 1E12\x00\x105"`,
+ `" TYPE256 9 5"`,
+ `" TYPE257 0\"00000000000000400000000000000000000\x00\x10000000000000000000000000000000000 9 l\x16\x01\x005266"`,
+ }
+ for i := range tests {
+ s, err := strconv.Unquote(tests[i])
+ if err != nil {
+ t.Fatalf("failed to unquote: %q: %s", tests[i], err)
+ }
+ if _, err = NewRR(s); err == nil {
+ t.Errorf("correctly parsed %q", s)
+ }
}
}
diff --git a/vendor/github.com/miekg/dns/sanitize.go b/vendor/github.com/miekg/dns/sanitize.go
index b489f3f05..c415bdd6c 100644
--- a/vendor/github.com/miekg/dns/sanitize.go
+++ b/vendor/github.com/miekg/dns/sanitize.go
@@ -3,7 +3,7 @@ package dns
// Dedup removes identical RRs from rrs. It preserves the original ordering.
// The lowest TTL of any duplicates is used in the remaining one. Dedup modifies
// rrs.
-// m is used to store the RRs temporay. If it is nil a new map will be allocated.
+// m is used to store the RRs temporary. If it is nil a new map will be allocated.
func Dedup(rrs []RR, m map[string]RR) []RR {
if m == nil {
m = make(map[string]RR)
diff --git a/vendor/github.com/miekg/dns/scan.go b/vendor/github.com/miekg/dns/scan.go
index 243b9cf18..f9cd47401 100644
--- a/vendor/github.com/miekg/dns/scan.go
+++ b/vendor/github.com/miekg/dns/scan.go
@@ -1,23 +1,14 @@
package dns
import (
+ "fmt"
"io"
- "log"
"os"
+ "path/filepath"
"strconv"
"strings"
)
-type debugging bool
-
-const debug debugging = false
-
-func (d debugging) Printf(format string, args ...interface{}) {
- if d {
- log.Printf(format, args...)
- }
-}
-
const maxTok = 2048 // Largest token we can return.
const maxUint16 = 1<<16 - 1
@@ -127,7 +118,7 @@ func NewRR(s string) (RR, error) {
// See NewRR for more documentation.
func ReadRR(q io.Reader, filename string) (RR, error) {
defttl := &ttlState{defaultTtl, false}
- r := <-parseZoneHelper(q, ".", defttl, filename, 1)
+ r := <-parseZoneHelper(q, ".", filename, defttl, 1)
if r == nil {
return nil, nil
}
@@ -164,25 +155,37 @@ func ReadRR(q io.Reader, filename string) (RR, error) {
// The text "; this is comment" is returned in Token.Comment. Comments inside the
// RR are discarded. Comments on a line by themselves are discarded too.
func ParseZone(r io.Reader, origin, file string) chan *Token {
- return parseZoneHelper(r, origin, nil, file, 10000)
+ return parseZoneHelper(r, origin, file, nil, 10000)
}
-func parseZoneHelper(r io.Reader, origin string, defttl *ttlState, file string, chansize int) chan *Token {
+func parseZoneHelper(r io.Reader, origin, file string, defttl *ttlState, chansize int) chan *Token {
t := make(chan *Token, chansize)
- go parseZone(r, origin, defttl, file, t, 0)
+ go parseZone(r, origin, file, defttl, t, 0)
return t
}
-func parseZone(r io.Reader, origin string, defttl *ttlState, f string, t chan *Token, include int) {
+func parseZone(r io.Reader, origin, f string, defttl *ttlState, t chan *Token, include int) {
defer func() {
if include == 0 {
close(t)
}
}()
- s := scanInit(r)
+ s, cancel := scanInit(r)
c := make(chan lex)
// Start the lexer
go zlexer(s, c)
+
+ defer func() {
+ cancel()
+ // zlexer can send up to three tokens, the next one and possibly 2 remainders.
+ // Do a non-blocking read.
+ _, ok := <-c
+ _, ok = <-c
+ _, ok = <-c
+ if !ok {
+ // too bad
+ }
+ }()
// 6 possible beginnings of a line, _ is a space
// 0. zRRTYPE -> all omitted until the rrtype
// 1. zOwner _ zRrtype -> class/ttl omitted
@@ -296,16 +299,24 @@ func parseZone(r io.Reader, origin string, defttl *ttlState, f string, t chan *T
return
}
// Start with the new file
- r1, e1 := os.Open(l.token)
+ includePath := l.token
+ if !filepath.IsAbs(includePath) {
+ includePath = filepath.Join(filepath.Dir(f), includePath)
+ }
+ r1, e1 := os.Open(includePath)
if e1 != nil {
- t <- &Token{Error: &ParseError{f, "failed to open `" + l.token + "'", l}}
+ msg := fmt.Sprintf("failed to open `%s'", l.token)
+ if !filepath.IsAbs(l.token) {
+ msg += fmt.Sprintf(" as `%s'", includePath)
+ }
+ t <- &Token{Error: &ParseError{f, msg, l}}
return
}
if include+1 > 7 {
t <- &Token{Error: &ParseError{f, "too deeply nested $INCLUDE", l}}
return
}
- parseZone(r1, neworigin, defttl, l.token, t, include+1)
+ parseZone(r1, neworigin, includePath, defttl, t, include+1)
st = zExpectOwnerDir
case zExpectDirTTLBl:
if l.value != zBlank {
@@ -497,14 +508,12 @@ func zlexer(s *scan, c chan lex) {
if stri >= maxTok {
l.token = "token length insufficient for parsing"
l.err = true
- debug.Printf("[%+v]", l.token)
c <- l
return
}
if comi >= maxTok {
l.token = "comment length insufficient for parsing"
l.err = true
- debug.Printf("[%+v]", l.token)
c <- l
return
}
@@ -547,7 +556,6 @@ func zlexer(s *scan, c chan lex) {
case "$GENERATE":
l.value = zDirGenerate
}
- debug.Printf("[7 %+v]", l.token)
c <- l
} else {
l.value = zString
@@ -569,6 +577,7 @@ func zlexer(s *scan, c chan lex) {
return
}
l.value = zRrtpe
+ rrtype = true
l.torc = t
}
}
@@ -589,16 +598,14 @@ func zlexer(s *scan, c chan lex) {
}
}
}
- debug.Printf("[6 %+v]", l.token)
c <- l
}
stri = 0
- // I reverse space stuff here
+
if !space && !commt {
l.value = zBlank
l.token = " "
l.length = 1
- debug.Printf("[5 %+v]", l.token)
c <- l
}
owner = false
@@ -621,7 +628,6 @@ func zlexer(s *scan, c chan lex) {
l.token = string(str[:stri])
l.tokenUpper = strings.ToUpper(l.token)
l.length = stri
- debug.Printf("[4 %+v]", l.token)
c <- l
stri = 0
}
@@ -659,7 +665,6 @@ func zlexer(s *scan, c chan lex) {
l.tokenUpper = l.token
l.length = 1
l.comment = string(com[:comi])
- debug.Printf("[3 %+v %+v]", l.token, l.comment)
c <- l
l.comment = ""
comi = 0
@@ -685,14 +690,12 @@ func zlexer(s *scan, c chan lex) {
rrtype = true
}
}
- debug.Printf("[2 %+v]", l.token)
c <- l
}
l.value = zNewline
l.token = "\n"
l.tokenUpper = l.token
l.length = 1
- debug.Printf("[1 %+v]", l.token)
c <- l
stri = 0
commt = false
@@ -738,7 +741,6 @@ func zlexer(s *scan, c chan lex) {
l.tokenUpper = strings.ToUpper(l.token)
l.length = stri
- debug.Printf("[%+v]", l.token)
c <- l
stri = 0
}
@@ -774,7 +776,6 @@ func zlexer(s *scan, c chan lex) {
l.token = "extra closing brace"
l.tokenUpper = l.token
l.err = true
- debug.Printf("[%+v]", l.token)
c <- l
return
}
@@ -800,7 +801,6 @@ func zlexer(s *scan, c chan lex) {
l.tokenUpper = strings.ToUpper(l.token)
l.length = stri
l.value = zString
- debug.Printf("[%+v]", l.token)
c <- l
}
if brace != 0 {
diff --git a/vendor/github.com/miekg/dns/scan_rr.go b/vendor/github.com/miekg/dns/scan_rr.go
index c53ba1d5b..f4ccc8424 100644
--- a/vendor/github.com/miekg/dns/scan_rr.go
+++ b/vendor/github.com/miekg/dns/scan_rr.go
@@ -1024,6 +1024,56 @@ func setOPENPGPKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, strin
return rr, nil, c1
}
+func setCSYNC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(CSYNC)
+ rr.Hdr = h
+
+ l := <-c
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, l.comment
+ }
+ j, e := strconv.ParseUint(l.token, 10, 32)
+ if e != nil {
+ // Serial must be a number
+ return nil, &ParseError{f, "bad CSYNC serial", l}, ""
+ }
+ rr.Serial = uint32(j)
+
+ <-c // zBlank
+
+ l = <-c
+ j, e = strconv.ParseUint(l.token, 10, 16)
+ if e != nil {
+ // Serial must be a number
+ return nil, &ParseError{f, "bad CSYNC flags", l}, ""
+ }
+ rr.Flags = uint16(j)
+
+ rr.TypeBitMap = make([]uint16, 0)
+ var (
+ k uint16
+ ok bool
+ )
+ l = <-c
+ for l.value != zNewline && l.value != zEOF {
+ switch l.value {
+ case zBlank:
+ // Ok
+ case zString:
+ if k, ok = StringToType[l.tokenUpper]; !ok {
+ if k, ok = typeToInt(l.tokenUpper); !ok {
+ return nil, &ParseError{f, "bad CSYNC TypeBitMap", l}, ""
+ }
+ }
+ rr.TypeBitMap = append(rr.TypeBitMap, k)
+ default:
+ return nil, &ParseError{f, "bad CSYNC TypeBitMap", l}, ""
+ }
+ l = <-c
+ }
+ return rr, nil, l.comment
+}
+
func setSIG(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
r, e, s := setRRSIG(h, c, o, f)
if r != nil {
@@ -1797,7 +1847,7 @@ func setURI(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
if err != nil {
return nil, err, ""
}
- if len(s) > 1 {
+ if len(s) != 1 {
return nil, &ParseError{f, "bad URI Target", l}, ""
}
rr.Target = s[0]
@@ -2027,13 +2077,58 @@ func setCAA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
if e != nil {
return nil, e, ""
}
- if len(s) > 1 {
+ if len(s) != 1 {
return nil, &ParseError{f, "bad CAA Value", l}, ""
}
rr.Value = s[0]
return rr, nil, c1
}
+func setTKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(TKEY)
+ rr.Hdr = h
+
+ l := <-c
+
+ // Algorithm
+ if l.value != zString {
+ return nil, &ParseError{f, "bad TKEY algorithm", l}, ""
+ }
+ rr.Algorithm = l.token
+ <-c // zBlank
+
+ // Get the key length and key values
+ l = <-c
+ i, err := strconv.ParseUint(l.token, 10, 8)
+ if err != nil || l.err {
+ return nil, &ParseError{f, "bad TKEY key length", l}, ""
+ }
+ rr.KeySize = uint16(i)
+ <-c // zBlank
+ l = <-c
+ if l.value != zString {
+ return nil, &ParseError{f, "bad TKEY key", l}, ""
+ }
+ rr.Key = l.token
+ <-c // zBlank
+
+ // Get the otherdata length and string data
+ l = <-c
+ i, err = strconv.ParseUint(l.token, 10, 8)
+ if err != nil || l.err {
+ return nil, &ParseError{f, "bad TKEY otherdata length", l}, ""
+ }
+ rr.OtherLen = uint16(i)
+ <-c // zBlank
+ l = <-c
+ if l.value != zString {
+ return nil, &ParseError{f, "bad TKEY otherday", l}, ""
+ }
+ rr.OtherData = l.token
+
+ return rr, nil, ""
+}
+
var typeToparserFunc = map[uint16]parserFunc{
TypeAAAA: {setAAAA, false},
TypeAFSDB: {setAFSDB, false},
@@ -2043,6 +2138,7 @@ var typeToparserFunc = map[uint16]parserFunc{
TypeCDNSKEY: {setCDNSKEY, true},
TypeCERT: {setCERT, true},
TypeCNAME: {setCNAME, false},
+ TypeCSYNC: {setCSYNC, true},
TypeDHCID: {setDHCID, true},
TypeDLV: {setDLV, true},
TypeDNAME: {setDNAME, false},
@@ -2099,4 +2195,5 @@ var typeToparserFunc = map[uint16]parserFunc{
TypeUINFO: {setUINFO, true},
TypeURI: {setURI, true},
TypeX25: {setX25, false},
+ TypeTKEY: {setTKEY, true},
}
diff --git a/vendor/github.com/miekg/dns/scanner.go b/vendor/github.com/miekg/dns/scanner.go
index c29bc2f38..424e5af9f 100644
--- a/vendor/github.com/miekg/dns/scanner.go
+++ b/vendor/github.com/miekg/dns/scanner.go
@@ -4,6 +4,7 @@ package dns
import (
"bufio"
+ "context"
"io"
"text/scanner"
)
@@ -12,13 +13,18 @@ type scan struct {
src *bufio.Reader
position scanner.Position
eof bool // Have we just seen a eof
+ ctx context.Context
}
-func scanInit(r io.Reader) *scan {
+func scanInit(r io.Reader) (*scan, context.CancelFunc) {
s := new(scan)
s.src = bufio.NewReader(r)
s.position.Line = 1
- return s
+
+ ctx, cancel := context.WithCancel(context.Background())
+ s.ctx = ctx
+
+ return s, cancel
}
// tokenText returns the next byte from the input
@@ -27,6 +33,13 @@ func (s *scan) tokenText() (byte, error) {
if err != nil {
return c, err
}
+ select {
+ case <-s.ctx.Done():
+ return c, context.Canceled
+ default:
+ break
+ }
+
// delay the newline handling until the next token is delivered,
// fixes off-by-one errors when reporting a parse error.
if s.eof == true {
diff --git a/vendor/github.com/miekg/dns/server.go b/vendor/github.com/miekg/dns/server.go
index ee7e256fb..b6ce5b5f6 100644
--- a/vendor/github.com/miekg/dns/server.go
+++ b/vendor/github.com/miekg/dns/server.go
@@ -285,7 +285,7 @@ type Server struct {
WriteTimeout time.Duration
// TCP idle timeout for multiple queries, if nil, defaults to 8 * time.Second (RFC 5966).
IdleTimeout func() time.Duration
- // Secret(s) for Tsig map[<zonename>]<base64 secret>.
+ // Secret(s) for Tsig map[<zonename>]<base64 secret>. The zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2).
TsigSecret map[string]string
// Unsafe instructs the server to disregard any sanity checks and directly hand the message to
// the handler. It will specifically not check if the query has the QR bit not set.
@@ -460,6 +460,12 @@ func (srv *Server) serveTCP(l net.Listener) error {
// deadline is not used here
for {
rw, err := l.Accept()
+ srv.lock.RLock()
+ if !srv.started {
+ srv.lock.RUnlock()
+ return nil
+ }
+ srv.lock.RUnlock()
if err != nil {
if neterr, ok := err.(net.Error); ok && neterr.Temporary() {
continue
@@ -467,12 +473,6 @@ func (srv *Server) serveTCP(l net.Listener) error {
return err
}
m, err := reader.ReadTCP(rw, rtimeout)
- srv.lock.RLock()
- if !srv.started {
- srv.lock.RUnlock()
- return nil
- }
- srv.lock.RUnlock()
if err != nil {
continue
}
@@ -509,6 +509,12 @@ func (srv *Server) serveUDP(l *net.UDPConn) error {
}
srv.lock.RUnlock()
if err != nil {
+ if netErr, ok := err.(net.Error); ok && netErr.Temporary() {
+ continue
+ }
+ return err
+ }
+ if len(m) < headerSize {
continue
}
go srv.serve(s.RemoteAddr(), handler, m, l, s, nil)
@@ -626,11 +632,8 @@ func (srv *Server) readUDP(conn *net.UDPConn, timeout time.Duration) ([]byte, *S
conn.SetReadDeadline(time.Now().Add(timeout))
m := make([]byte, srv.UDPSize)
n, s, err := ReadFromSessionUDP(conn, m)
- if err != nil || n == 0 {
- if err != nil {
- return nil, nil, err
- }
- return nil, nil, ErrShortRead
+ if err != nil {
+ return nil, nil, err
}
m = m[:n]
return m, s, nil
diff --git a/vendor/github.com/miekg/dns/server_test.go b/vendor/github.com/miekg/dns/server_test.go
index 1a4b7ca0c..7693e761a 100644
--- a/vendor/github.com/miekg/dns/server_test.go
+++ b/vendor/github.com/miekg/dns/server_test.go
@@ -654,11 +654,11 @@ func TestServerStartStopRace(t *testing.T) {
s := &Server{}
s, _, _, err = RunLocalUDPServerWithFinChan(":0")
if err != nil {
- t.Fatalf("Could not start server: %s", err)
+ t.Fatalf("could not start server: %s", err)
}
go func() {
if err := s.Shutdown(); err != nil {
- t.Fatalf("Could not stop server: %s", err)
+ t.Fatalf("could not stop server: %s", err)
}
}()
}
diff --git a/vendor/github.com/miekg/dns/types.go b/vendor/github.com/miekg/dns/types.go
index deddb301b..a779ca8ab 100644
--- a/vendor/github.com/miekg/dns/types.go
+++ b/vendor/github.com/miekg/dns/types.go
@@ -78,6 +78,7 @@ const (
TypeCDS uint16 = 59
TypeCDNSKEY uint16 = 60
TypeOPENPGPKEY uint16 = 61
+ TypeCSYNC uint16 = 62
TypeSPF uint16 = 99
TypeUINFO uint16 = 100
TypeUID uint16 = 101
@@ -1012,14 +1013,18 @@ type TKEY struct {
Mode uint16
Error uint16
KeySize uint16
- Key string
+ Key string `dns:"size-hex:KeySize"`
OtherLen uint16
- OtherData string
+ OtherData string `dns:"size-hex:OtherLen"`
}
+// TKEY has no official presentation format, but this will suffice.
func (rr *TKEY) String() string {
- // It has no presentation format
- return ""
+ s := "\n;; TKEY PSEUDOSECTION:\n"
+ s += rr.Hdr.String() + " " + rr.Algorithm + " " +
+ strconv.Itoa(int(rr.KeySize)) + " " + rr.Key + " " +
+ strconv.Itoa(int(rr.OtherLen)) + " " + rr.OtherData
+ return s
}
// RFC3597 represents an unknown/generic RR. See RFC 3597.
@@ -1267,6 +1272,36 @@ type OPENPGPKEY struct {
func (rr *OPENPGPKEY) String() string { return rr.Hdr.String() + rr.PublicKey }
+// CSYNC RR. See RFC 7477.
+type CSYNC struct {
+ Hdr RR_Header
+ Serial uint32
+ Flags uint16
+ TypeBitMap []uint16 `dns:"nsec"`
+}
+
+func (rr *CSYNC) String() string {
+ s := rr.Hdr.String() + strconv.FormatInt(int64(rr.Serial), 10) + " " + strconv.Itoa(int(rr.Flags))
+
+ for i := 0; i < len(rr.TypeBitMap); i++ {
+ s += " " + Type(rr.TypeBitMap[i]).String()
+ }
+ return s
+}
+
+func (rr *CSYNC) len() int {
+ l := rr.Hdr.len() + 4 + 2
+ lastwindow := uint32(2 ^ 32 + 1)
+ for _, t := range rr.TypeBitMap {
+ window := t / 256
+ if uint32(window) != lastwindow {
+ l += 1 + 32
+ }
+ lastwindow = uint32(window)
+ }
+ return l
+}
+
// TimeToString translates the RRSIG's incep. and expir. times to the
// string representation used when printing the record.
// It takes serial arithmetic (RFC 1982) into account.
diff --git a/vendor/github.com/miekg/dns/types_generate.go b/vendor/github.com/miekg/dns/types_generate.go
index 3de021ca7..8703cce64 100644
--- a/vendor/github.com/miekg/dns/types_generate.go
+++ b/vendor/github.com/miekg/dns/types_generate.go
@@ -23,11 +23,11 @@ var skipLen = map[string]struct{}{
"NSEC": {},
"NSEC3": {},
"OPT": {},
+ "CSYNC": {},
}
var packageHdr = `
-// *** DO NOT MODIFY ***
-// AUTOGENERATED BY go generate from types_generate.go
+// Code generated by "go run types_generate.go"; DO NOT EDIT.
package dns
@@ -181,6 +181,8 @@ func main() {
fallthrough
case st.Tag(i) == `dns:"base64"`:
o("l += base64.StdEncoding.DecodedLen(len(rr.%s))\n")
+ case strings.HasPrefix(st.Tag(i), `dns:"size-hex:`): // this has an extra field where the length is stored
+ o("l += len(rr.%s)/2\n")
case strings.HasPrefix(st.Tag(i), `dns:"size-hex`):
fallthrough
case st.Tag(i) == `dns:"hex"`:
diff --git a/vendor/github.com/miekg/dns/udp.go b/vendor/github.com/miekg/dns/udp.go
index 12a209678..f3f31a7ac 100644
--- a/vendor/github.com/miekg/dns/udp.go
+++ b/vendor/github.com/miekg/dns/udp.go
@@ -4,6 +4,9 @@ package dns
import (
"net"
+
+ "golang.org/x/net/ipv4"
+ "golang.org/x/net/ipv6"
)
// SessionUDP holds the remote address and the associated
@@ -34,12 +37,53 @@ func WriteToSessionUDP(conn *net.UDPConn, b []byte, session *SessionUDP) (int, e
return n, err
}
+func setUDPSocketOptions(conn *net.UDPConn) error {
+ // Try setting the flags for both families and ignore the errors unless they
+ // both error.
+ err6 := ipv6.NewPacketConn(conn).SetControlMessage(ipv6.FlagDst|ipv6.FlagInterface, true)
+ err4 := ipv4.NewPacketConn(conn).SetControlMessage(ipv4.FlagDst|ipv4.FlagInterface, true)
+ if err6 != nil && err4 != nil {
+ return err4
+ }
+ return nil
+}
+
+// parseDstFromOOB takes oob data and returns the destination IP.
+func parseDstFromOOB(oob []byte) net.IP {
+ // Start with IPv6 and then fallback to IPv4
+ // TODO(fastest963): Figure out a way to prefer one or the other. Looking at
+ // the lvl of the header for a 0 or 41 isn't cross-platform.
+ var dst net.IP
+ cm6 := new(ipv6.ControlMessage)
+ if cm6.Parse(oob) == nil {
+ dst = cm6.Dst
+ }
+ if dst == nil {
+ cm4 := new(ipv4.ControlMessage)
+ if cm4.Parse(oob) == nil {
+ dst = cm4.Dst
+ }
+ }
+ return dst
+}
+
// correctSource takes oob data and returns new oob data with the Src equal to the Dst
func correctSource(oob []byte) []byte {
- dst, err := parseUDPSocketDst(oob)
- // If the destination could not be determined, ignore.
- if err != nil || dst == nil {
+ dst := parseDstFromOOB(oob)
+ if dst == nil {
return nil
}
- return marshalUDPSocketSrc(dst)
+ // If the dst is definitely an IPv6, then use ipv6's ControlMessage to
+ // respond otherwise use ipv4's because ipv6's marshal ignores ipv4
+ // addresses.
+ if dst.To4() == nil {
+ cm := new(ipv6.ControlMessage)
+ cm.Src = dst
+ oob = cm.Marshal()
+ } else {
+ cm := new(ipv4.ControlMessage)
+ cm.Src = dst
+ oob = cm.Marshal()
+ }
+ return oob
}
diff --git a/vendor/github.com/miekg/dns/udp_linux.go b/vendor/github.com/miekg/dns/udp_linux.go
deleted file mode 100644
index 13747ed34..000000000
--- a/vendor/github.com/miekg/dns/udp_linux.go
+++ /dev/null
@@ -1,220 +0,0 @@
-// +build linux,!appengine
-
-package dns
-
-// See:
-// * http://stackoverflow.com/questions/3062205/setting-the-source-ip-for-a-udp-socket and
-// * http://blog.powerdns.com/2012/10/08/on-binding-datagram-udp-sockets-to-the-any-addresses/
-//
-// Why do we need this: When listening on 0.0.0.0 with UDP so kernel decides what is the outgoing
-// interface, this might not always be the correct one. This code will make sure the egress
-// packet's interface matched the ingress' one.
-
-import (
- "net"
- "syscall"
- "unsafe"
-
- "github.com/miekg/dns/internal/socket"
-)
-
-const (
- sizeofInet6Pktinfo = 0x14
- sizeofInetPktinfo = 0xc
- protocolIP = 0
- protocolIPv6 = 41
-)
-
-type inetPktinfo struct {
- Ifindex int32
- Spec_dst [4]byte /* in_addr */
- Addr [4]byte /* in_addr */
-}
-
-type inet6Pktinfo struct {
- Addr [16]byte /* in6_addr */
- Ifindex int32
-}
-
-type inetControlMessage struct {
- Src net.IP // source address, specifying only
- Dst net.IP // destination address, receiving only
-}
-
-// setUDPSocketOptions sets the UDP socket options.
-// This function is implemented on a per platform basis. See udp_*.go for more details
-func setUDPSocketOptions(conn *net.UDPConn) error {
- sa, err := getUDPSocketName(conn)
- if err != nil {
- return err
- }
- switch sa.(type) {
- case *syscall.SockaddrInet6:
- v6only, err := getUDPSocketOptions6Only(conn)
- if err != nil {
- return err
- }
- setUDPSocketOptions6(conn)
- if !v6only {
- setUDPSocketOptions4(conn)
- }
- case *syscall.SockaddrInet4:
- setUDPSocketOptions4(conn)
- }
- return nil
-}
-
-// setUDPSocketOptions4 prepares the v4 socket for sessions.
-func setUDPSocketOptions4(conn *net.UDPConn) error {
- file, err := conn.File()
- if err != nil {
- return err
- }
- if err := syscall.SetsockoptInt(int(file.Fd()), syscall.IPPROTO_IP, syscall.IP_PKTINFO, 1); err != nil {
- file.Close()
- return err
- }
- // Calling File() above results in the connection becoming blocking, we must fix that.
- // See https://github.com/miekg/dns/issues/279
- err = syscall.SetNonblock(int(file.Fd()), true)
- if err != nil {
- file.Close()
- return err
- }
- file.Close()
- return nil
-}
-
-// setUDPSocketOptions6 prepares the v6 socket for sessions.
-func setUDPSocketOptions6(conn *net.UDPConn) error {
- file, err := conn.File()
- if err != nil {
- return err
- }
- if err := syscall.SetsockoptInt(int(file.Fd()), syscall.IPPROTO_IPV6, syscall.IPV6_RECVPKTINFO, 1); err != nil {
- file.Close()
- return err
- }
- err = syscall.SetNonblock(int(file.Fd()), true)
- if err != nil {
- file.Close()
- return err
- }
- file.Close()
- return nil
-}
-
-// getUDPSocketOption6Only return true if the socket is v6 only and false when it is v4/v6 combined
-// (dualstack).
-func getUDPSocketOptions6Only(conn *net.UDPConn) (bool, error) {
- file, err := conn.File()
- if err != nil {
- return false, err
- }
- // dual stack. See http://stackoverflow.com/questions/1618240/how-to-support-both-ipv4-and-ipv6-connections
- v6only, err := syscall.GetsockoptInt(int(file.Fd()), syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY)
- if err != nil {
- file.Close()
- return false, err
- }
- file.Close()
- return v6only == 1, nil
-}
-
-func getUDPSocketName(conn *net.UDPConn) (syscall.Sockaddr, error) {
- file, err := conn.File()
- if err != nil {
- return nil, err
- }
- defer file.Close()
- return syscall.Getsockname(int(file.Fd()))
-}
-
-// marshalInetPacketInfo marshals a ipv4 control message, returning
-// the byte slice for the next marshal, if any
-func marshalInetPacketInfo(b []byte, cm *inetControlMessage) []byte {
- m := socket.ControlMessage(b)
- m.MarshalHeader(protocolIP, syscall.IP_PKTINFO, sizeofInetPktinfo)
- if cm != nil {
- pi := (*inetPktinfo)(unsafe.Pointer(&m.Data(sizeofInetPktinfo)[0]))
- if ip := cm.Src.To4(); ip != nil {
- copy(pi.Spec_dst[:], ip)
- }
- }
- return m.Next(sizeofInetPktinfo)
-}
-
-// marshalInet6PacketInfo marshals a ipv6 control message, returning
-// the byte slice for the next marshal, if any
-func marshalInet6PacketInfo(b []byte, cm *inetControlMessage) []byte {
- m := socket.ControlMessage(b)
- m.MarshalHeader(protocolIPv6, syscall.IPV6_PKTINFO, sizeofInet6Pktinfo)
- if cm != nil {
- pi := (*inet6Pktinfo)(unsafe.Pointer(&m.Data(sizeofInet6Pktinfo)[0]))
- if ip := cm.Src.To16(); ip != nil && ip.To4() == nil {
- copy(pi.Addr[:], ip)
- }
- }
- return m.Next(sizeofInet6Pktinfo)
-}
-
-func parseInetPacketInfo(cm *inetControlMessage, b []byte) {
- pi := (*inetPktinfo)(unsafe.Pointer(&b[0]))
- if len(cm.Dst) < net.IPv4len {
- cm.Dst = make(net.IP, net.IPv4len)
- }
- copy(cm.Dst, pi.Addr[:])
-}
-
-func parseInet6PacketInfo(cm *inetControlMessage, b []byte) {
- pi := (*inet6Pktinfo)(unsafe.Pointer(&b[0]))
- if len(cm.Dst) < net.IPv6len {
- cm.Dst = make(net.IP, net.IPv6len)
- }
- copy(cm.Dst, pi.Addr[:])
-}
-
-// parseUDPSocketDst takes out-of-band data from ReadMsgUDP and parses it for
-// the Dst address
-func parseUDPSocketDst(oob []byte) (net.IP, error) {
- cm := new(inetControlMessage)
- ms, err := socket.ControlMessage(oob).Parse()
- if err != nil {
- return nil, err
- }
- for _, m := range ms {
- lvl, typ, l, err := m.ParseHeader()
- if err != nil {
- return nil, err
- }
- if lvl == protocolIPv6 { // IPv6
- if typ == syscall.IPV6_PKTINFO && l >= sizeofInet6Pktinfo {
- parseInet6PacketInfo(cm, m.Data(l))
- }
- } else if lvl == protocolIP { // IPv4
- if typ == syscall.IP_PKTINFO && l >= sizeofInetPktinfo {
- parseInetPacketInfo(cm, m.Data(l))
- }
- }
- }
- return cm.Dst, nil
-}
-
-// marshalUDPSocketSrc takes the given src address and returns out-of-band data
-// to give to WriteMsgUDP
-func marshalUDPSocketSrc(src net.IP) []byte {
- var oob []byte
- // If the dst is definitely an ipv6, then use ipv6 control to respond
- // otherwise use ipv4 because the ipv6 marshal ignores ipv4 messages.
- // See marshalInet6PacketInfo
- cm := new(inetControlMessage)
- cm.Src = src
- if src.To4() == nil {
- oob = make([]byte, socket.ControlMessageSpace(sizeofInet6Pktinfo))
- marshalInet6PacketInfo(oob, cm)
- } else {
- oob = make([]byte, socket.ControlMessageSpace(sizeofInetPktinfo))
- marshalInetPacketInfo(oob, cm)
- }
- return oob
-}
diff --git a/vendor/github.com/miekg/dns/udp_linux_test.go b/vendor/github.com/miekg/dns/udp_linux_test.go
deleted file mode 100644
index 14a8acefd..000000000
--- a/vendor/github.com/miekg/dns/udp_linux_test.go
+++ /dev/null
@@ -1,68 +0,0 @@
-// +build linux,!appengine
-
-package dns
-
-import (
- "bytes"
- "net"
- "testing"
-)
-
-func TestParseUDPSocketDst(t *testing.T) {
- // dst is :ffff:100.100.100.100
- oob := []byte{36, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 100, 100, 100, 100, 2, 0, 0, 0}
- dst, err := parseUDPSocketDst(oob)
- if err != nil {
- t.Fatalf("error parsing ipv6 oob: %v", err)
- }
- dst4 := dst.To4()
- if dst4 == nil {
- t.Errorf("failed to parse ipv4: %v", dst)
- } else if dst4.String() != "100.100.100.100" {
- t.Errorf("unexpected ipv4: %v", dst4)
- }
-
- // dst is 2001:db8::1
- oob = []byte{36, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 50, 0, 0, 0, 32, 1, 13, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}
- dst, err = parseUDPSocketDst(oob)
- if err != nil {
- t.Fatalf("error parsing ipv6 oob: %v", err)
- }
- dst6 := dst.To16()
- if dst6 == nil {
- t.Errorf("failed to parse ipv6: %v", dst)
- } else if dst6.String() != "2001:db8::1" {
- t.Errorf("unexpected ipv6: %v", dst4)
- }
-
- // dst is 100.100.100.100 but was received on 10.10.10.10
- oob = []byte{28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 2, 0, 0, 0, 10, 10, 10, 10, 100, 100, 100, 100, 0, 0, 0, 0}
- dst, err = parseUDPSocketDst(oob)
- if err != nil {
- t.Fatalf("error parsing ipv4 oob: %v", err)
- }
- dst4 = dst.To4()
- if dst4 == nil {
- t.Errorf("failed to parse ipv4: %v", dst)
- } else if dst4.String() != "100.100.100.100" {
- t.Errorf("unexpected ipv4: %v", dst4)
- }
-}
-
-func TestMarshalUDPSocketSrc(t *testing.T) {
- // src is 100.100.100.100
- exoob := []byte{28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 100, 100, 100, 100, 0, 0, 0, 0, 0, 0, 0, 0}
- oob := marshalUDPSocketSrc(net.ParseIP("100.100.100.100"))
- if !bytes.Equal(exoob, oob) {
- t.Errorf("expected ipv4 oob:\n%v", exoob)
- t.Errorf("actual ipv4 oob:\n%v", oob)
- }
-
- // src is 2001:db8::1
- exoob = []byte{36, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 50, 0, 0, 0, 32, 1, 13, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}
- oob = marshalUDPSocketSrc(net.ParseIP("2001:db8::1"))
- if !bytes.Equal(exoob, oob) {
- t.Errorf("expected ipv6 oob:\n%v", exoob)
- t.Errorf("actual ipv6 oob:\n%v", oob)
- }
-}
diff --git a/vendor/github.com/miekg/dns/udp_other.go b/vendor/github.com/miekg/dns/udp_other.go
deleted file mode 100644
index 531f4ebcc..000000000
--- a/vendor/github.com/miekg/dns/udp_other.go
+++ /dev/null
@@ -1,17 +0,0 @@
-// +build !linux appengine
-
-package dns
-
-import (
- "net"
-)
-
-// These do nothing. See udp_linux.go for an example of how to implement this.
-
-// We tried to adhire to some kind of naming scheme.
-func setUDPSocketOptions(conn *net.UDPConn) error { return nil }
-func setUDPSocketOptions4(conn *net.UDPConn) error { return nil }
-func setUDPSocketOptions6(conn *net.UDPConn) error { return nil }
-func getUDPSocketOptions6Only(conn *net.UDPConn) (bool, error) { return false, nil }
-func parseUDPSocketDst(oob []byte) (net.IP, error) { return nil, nil }
-func marshalUDPSocketSrc(src net.IP) []byte { return nil }
diff --git a/vendor/github.com/miekg/dns/udp_test.go b/vendor/github.com/miekg/dns/udp_test.go
new file mode 100644
index 000000000..2c145dbf6
--- /dev/null
+++ b/vendor/github.com/miekg/dns/udp_test.go
@@ -0,0 +1,126 @@
+// +build linux,!appengine
+
+package dns
+
+import (
+ "bytes"
+ "net"
+ "strings"
+ "testing"
+ "time"
+
+ "golang.org/x/net/ipv4"
+ "golang.org/x/net/ipv6"
+)
+
+func TestSetUDPSocketOptions(t *testing.T) {
+ // returns an error if we cannot resolve that address
+ testFamily := func(n, addr string) error {
+ a, err := net.ResolveUDPAddr(n, addr)
+ if err != nil {
+ return err
+ }
+ c, err := net.ListenUDP(n, a)
+ if err != nil {
+ return err
+ }
+ if err := setUDPSocketOptions(c); err != nil {
+ t.Fatalf("failed to set socket options: %v", err)
+ }
+ ch := make(chan *SessionUDP)
+ go func() {
+ // Set some deadline so this goroutine doesn't hang forever
+ c.SetReadDeadline(time.Now().Add(time.Minute))
+ b := make([]byte, 1)
+ _, sess, err := ReadFromSessionUDP(c, b)
+ if err != nil {
+ t.Fatalf("failed to read from conn: %v", err)
+ }
+ ch <- sess
+ }()
+
+ c2, err := net.Dial("udp", c.LocalAddr().String())
+ if err != nil {
+ t.Fatalf("failed to dial udp: %v", err)
+ }
+ if _, err := c2.Write([]byte{1}); err != nil {
+ t.Fatalf("failed to write to conn: %v", err)
+ }
+ sess := <-ch
+ if len(sess.context) == 0 {
+ t.Fatalf("empty session context: %v", sess)
+ }
+ ip := parseDstFromOOB(sess.context)
+ if ip == nil {
+ t.Fatalf("failed to parse dst: %v", sess)
+ }
+ if !strings.Contains(c.LocalAddr().String(), ip.String()) {
+ t.Fatalf("dst was different than listen addr: %v != %v", ip.String(), c.LocalAddr().String())
+ }
+ return nil
+ }
+
+ // we require that ipv4 be supported
+ if err := testFamily("udp4", "127.0.0.1:0"); err != nil {
+ t.Fatalf("failed to test socket options on IPv4: %v", err)
+ }
+ // IPv6 might not be supported so these will just log
+ if err := testFamily("udp6", "[::1]:0"); err != nil {
+ t.Logf("failed to test socket options on IPv6-only: %v", err)
+ }
+ if err := testFamily("udp", "[::1]:0"); err != nil {
+ t.Logf("failed to test socket options on IPv6/IPv4: %v", err)
+ }
+}
+
+func TestParseDstFromOOB(t *testing.T) {
+ // dst is :ffff:100.100.100.100
+ oob := []byte{36, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 100, 100, 100, 100, 2, 0, 0, 0}
+ dst := parseDstFromOOB(oob)
+ dst4 := dst.To4()
+ if dst4 == nil {
+ t.Errorf("failed to parse IPv4 in IPv6: %v", dst)
+ } else if dst4.String() != "100.100.100.100" {
+ t.Errorf("unexpected IPv4: %v", dst4)
+ }
+
+ // dst is 2001:db8::1
+ oob = []byte{36, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 50, 0, 0, 0, 32, 1, 13, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}
+ dst = parseDstFromOOB(oob)
+ dst6 := dst.To16()
+ if dst6 == nil {
+ t.Errorf("failed to parse IPv6: %v", dst)
+ } else if dst6.String() != "2001:db8::1" {
+ t.Errorf("unexpected IPv6: %v", dst4)
+ }
+
+ // dst is 100.100.100.100 but was received on 10.10.10.10
+ oob = []byte{28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 2, 0, 0, 0, 10, 10, 10, 10, 100, 100, 100, 100, 0, 0, 0, 0}
+ dst = parseDstFromOOB(oob)
+ dst4 = dst.To4()
+ if dst4 == nil {
+ t.Errorf("failed to parse IPv4: %v", dst)
+ } else if dst4.String() != "100.100.100.100" {
+ t.Errorf("unexpected IPv4: %v", dst4)
+ }
+}
+
+func TestCorrectSource(t *testing.T) {
+ // dst is :ffff:100.100.100.100 which should be counted as IPv4
+ oob := []byte{36, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 100, 100, 100, 100, 2, 0, 0, 0}
+ soob := correctSource(oob)
+ cm4 := new(ipv4.ControlMessage)
+ cm4.Src = net.ParseIP("100.100.100.100")
+ if !bytes.Equal(soob, cm4.Marshal()) {
+ t.Errorf("unexpected oob for ipv4 address: %v", soob)
+ }
+
+ // dst is 2001:db8::1
+ oob = []byte{36, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 50, 0, 0, 0, 32, 1, 13, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}
+ soob = correctSource(oob)
+ cm6 := new(ipv6.ControlMessage)
+ cm6.Src = net.ParseIP("2001:db8::1")
+ if !bytes.Equal(soob, cm6.Marshal()) {
+ t.Errorf("unexpected oob for IPv6 address: %v", soob)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/udp_windows.go b/vendor/github.com/miekg/dns/udp_windows.go
index 2ad4ede7f..6778c3c6c 100644
--- a/vendor/github.com/miekg/dns/udp_windows.go
+++ b/vendor/github.com/miekg/dns/udp_windows.go
@@ -14,6 +14,7 @@ func (s *SessionUDP) RemoteAddr() net.Addr { return s.raddr }
// ReadFromSessionUDP acts just like net.UDPConn.ReadFrom(), but returns a session object instead of a
// net.UDPAddr.
+// TODO(fastest963): Once go1.10 is released, use ReadMsgUDP.
func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) {
n, raddr, err := conn.ReadFrom(b)
if err != nil {
@@ -24,7 +25,13 @@ func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) {
}
// WriteToSessionUDP acts just like net.UDPConn.WriteTo(), but uses a *SessionUDP instead of a net.Addr.
+// TODO(fastest963): Once go1.10 is released, use WriteMsgUDP.
func WriteToSessionUDP(conn *net.UDPConn, b []byte, session *SessionUDP) (int, error) {
n, err := conn.WriteTo(b, session.raddr)
return n, err
}
+
+// TODO(fastest963): Once go1.10 is released and we can use *MsgUDP methods
+// use the standard method in udp.go for these.
+func setUDPSocketOptions(*net.UDPConn) error { return nil }
+func parseDstFromOOB([]byte, net.IP) net.IP { return nil }
diff --git a/vendor/github.com/miekg/dns/update_test.go b/vendor/github.com/miekg/dns/update_test.go
index 6813baa10..5dba413a4 100644
--- a/vendor/github.com/miekg/dns/update_test.go
+++ b/vendor/github.com/miekg/dns/update_test.go
@@ -119,15 +119,15 @@ func TestPreReqAndRemovals(t *testing.T) {
;example.org. IN SOA
;; ANSWER SECTION:
-name_used. 0 ANY ANY
+name_used. 0 CLASS255 ANY
name_not_used. 0 NONE ANY
-rrset_used1. 0 ANY A
+rrset_used1. 0 CLASS255 A
rrset_used2. 3600 IN A 127.0.0.1
rrset_not_used. 0 NONE A
;; AUTHORITY SECTION:
-remove1. 0 ANY ANY
-remove2. 0 ANY A
+remove1. 0 CLASS255 ANY
+remove2. 0 CLASS255 A
remove3. 0 NONE A 127.0.0.1
insert. 3600 IN A 127.0.0.1
`
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/.gitattributes b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/.gitattributes
new file mode 100644
index 000000000..d2f212e5d
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/.gitattributes
@@ -0,0 +1,10 @@
+# Treat all files in this repo as binary, with no git magic updating
+# line endings. Windows users contributing to Go will need to use a
+# modern version of git and editors capable of LF line endings.
+#
+# We'll prevent accidental CRLF line endings from entering the repo
+# via the git-review gofmt checks.
+#
+# See golang.org/issue/9281
+
+* -text
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/.gitignore b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/.gitignore
new file mode 100644
index 000000000..8339fd61d
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/.gitignore
@@ -0,0 +1,2 @@
+# Add no patterns to .hgignore except for files generated by the build.
+last-change
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/AUTHORS b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/AUTHORS
new file mode 100644
index 000000000..2b00ddba0
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/AUTHORS
@@ -0,0 +1,3 @@
+# This source code refers to The Go Authors for copyright purposes.
+# The master list of authors is in the main Go distribution,
+# visible at https://tip.golang.org/AUTHORS.
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/CONTRIBUTING.md b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/CONTRIBUTING.md
new file mode 100644
index 000000000..88dff59bc
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/CONTRIBUTING.md
@@ -0,0 +1,31 @@
+# Contributing to Go
+
+Go is an open source project.
+
+It is the work of hundreds of contributors. We appreciate your help!
+
+
+## Filing issues
+
+When [filing an issue](https://golang.org/issue/new), make sure to answer these five questions:
+
+1. What version of Go are you using (`go version`)?
+2. What operating system and processor architecture are you using?
+3. What did you do?
+4. What did you expect to see?
+5. What did you see instead?
+
+General questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker.
+The gophers there will answer or ask you to file an issue if you've tripped over a bug.
+
+## Contributing code
+
+Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html)
+before sending patches.
+
+**We do not accept GitHub pull requests**
+(we use [Gerrit](https://code.google.com/p/gerrit/) instead for code review).
+
+Unless otherwise noted, the Go source files are distributed under
+the BSD-style license found in the LICENSE file.
+
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/CONTRIBUTORS b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/CONTRIBUTORS
new file mode 100644
index 000000000..1fbd3e976
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/CONTRIBUTORS
@@ -0,0 +1,3 @@
+# This source code was written by the Go contributors.
+# The master list of contributors is in the main Go distribution,
+# visible at https://tip.golang.org/CONTRIBUTORS.
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/LICENSE b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/LICENSE
new file mode 100644
index 000000000..6a66aea5e
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2009 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/PATENTS b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/PATENTS
new file mode 100644
index 000000000..733099041
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/PATENTS
@@ -0,0 +1,22 @@
+Additional IP Rights Grant (Patents)
+
+"This implementation" means the copyrightable works distributed by
+Google as part of the Go project.
+
+Google hereby grants to You a perpetual, worldwide, non-exclusive,
+no-charge, royalty-free, irrevocable (except as stated in this section)
+patent license to make, have made, use, offer to sell, sell, import,
+transfer and otherwise run, modify and propagate the contents of this
+implementation of Go, where such license applies only to those patent
+claims, both currently owned or controlled by Google and acquired in
+the future, licensable by Google that are necessarily infringed by this
+implementation of Go. This grant does not include claims that would be
+infringed only as a consequence of further modification of this
+implementation. If you or your agent or exclusive licensee institute or
+order or agree to the institution of patent litigation against any
+entity (including a cross-claim or counterclaim in a lawsuit) alleging
+that this implementation of Go or any code incorporated within this
+implementation of Go constitutes direct or contributory patent
+infringement, or inducement of patent infringement, then any patent
+rights granted to you under this License for this implementation of Go
+shall terminate as of the date such litigation is filed.
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/README.md b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/README.md
new file mode 100644
index 000000000..c9d6fecd1
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/README.md
@@ -0,0 +1,21 @@
+# Go Cryptography
+
+This repository holds supplementary Go cryptography libraries.
+
+## Download/Install
+
+The easiest way to install is to run `go get -u golang.org/x/crypto/...`. You
+can also manually git clone the repository to `$GOPATH/src/golang.org/x/crypto`.
+
+## Report Issues / Send Patches
+
+This repository uses Gerrit for code changes. To learn how to submit changes to
+this repository, see https://golang.org/doc/contribute.html.
+
+The main issue tracker for the crypto repository is located at
+https://github.com/golang/go/issues. Prefix your issue with "x/crypto:" in the
+subject line, so it is easy to find.
+
+Note that contributions to the cryptography package receive additional scrutiny
+due to their sensitive nature. Patches may take longer than normal to receive
+feedback.
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/acme.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/acme.go
new file mode 100644
index 000000000..fa9c4b39e
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/acme.go
@@ -0,0 +1,1058 @@
+// Copyright 2015 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 acme provides an implementation of the
+// Automatic Certificate Management Environment (ACME) spec.
+// See https://tools.ietf.org/html/draft-ietf-acme-acme-02 for details.
+//
+// Most common scenarios will want to use autocert subdirectory instead,
+// which provides automatic access to certificates from Let's Encrypt
+// and any other ACME-based CA.
+//
+// This package is a work in progress and makes no API stability promises.
+package acme
+
+import (
+ "bytes"
+ "context"
+ "crypto"
+ "crypto/ecdsa"
+ "crypto/elliptic"
+ "crypto/rand"
+ "crypto/sha256"
+ "crypto/tls"
+ "crypto/x509"
+ "encoding/base64"
+ "encoding/hex"
+ "encoding/json"
+ "encoding/pem"
+ "errors"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "math/big"
+ "net/http"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+)
+
+// LetsEncryptURL is the Directory endpoint of Let's Encrypt CA.
+const LetsEncryptURL = "https://acme-v01.api.letsencrypt.org/directory"
+
+const (
+ maxChainLen = 5 // max depth and breadth of a certificate chain
+ maxCertSize = 1 << 20 // max size of a certificate, in bytes
+
+ // Max number of collected nonces kept in memory.
+ // Expect usual peak of 1 or 2.
+ maxNonces = 100
+)
+
+// Client is an ACME client.
+// The only required field is Key. An example of creating a client with a new key
+// is as follows:
+//
+// key, err := rsa.GenerateKey(rand.Reader, 2048)
+// if err != nil {
+// log.Fatal(err)
+// }
+// client := &Client{Key: key}
+//
+type Client struct {
+ // Key is the account key used to register with a CA and sign requests.
+ // Key.Public() must return a *rsa.PublicKey or *ecdsa.PublicKey.
+ Key crypto.Signer
+
+ // HTTPClient optionally specifies an HTTP client to use
+ // instead of http.DefaultClient.
+ HTTPClient *http.Client
+
+ // DirectoryURL points to the CA directory endpoint.
+ // If empty, LetsEncryptURL is used.
+ // Mutating this value after a successful call of Client's Discover method
+ // will have no effect.
+ DirectoryURL string
+
+ dirMu sync.Mutex // guards writes to dir
+ dir *Directory // cached result of Client's Discover method
+
+ noncesMu sync.Mutex
+ nonces map[string]struct{} // nonces collected from previous responses
+}
+
+// Discover performs ACME server discovery using c.DirectoryURL.
+//
+// It caches successful result. So, subsequent calls will not result in
+// a network round-trip. This also means mutating c.DirectoryURL after successful call
+// of this method will have no effect.
+func (c *Client) Discover(ctx context.Context) (Directory, error) {
+ c.dirMu.Lock()
+ defer c.dirMu.Unlock()
+ if c.dir != nil {
+ return *c.dir, nil
+ }
+
+ dirURL := c.DirectoryURL
+ if dirURL == "" {
+ dirURL = LetsEncryptURL
+ }
+ res, err := c.get(ctx, dirURL)
+ if err != nil {
+ return Directory{}, err
+ }
+ defer res.Body.Close()
+ c.addNonce(res.Header)
+ if res.StatusCode != http.StatusOK {
+ return Directory{}, responseError(res)
+ }
+
+ var v struct {
+ Reg string `json:"new-reg"`
+ Authz string `json:"new-authz"`
+ Cert string `json:"new-cert"`
+ Revoke string `json:"revoke-cert"`
+ Meta struct {
+ Terms string `json:"terms-of-service"`
+ Website string `json:"website"`
+ CAA []string `json:"caa-identities"`
+ }
+ }
+ if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
+ return Directory{}, err
+ }
+ c.dir = &Directory{
+ RegURL: v.Reg,
+ AuthzURL: v.Authz,
+ CertURL: v.Cert,
+ RevokeURL: v.Revoke,
+ Terms: v.Meta.Terms,
+ Website: v.Meta.Website,
+ CAA: v.Meta.CAA,
+ }
+ return *c.dir, nil
+}
+
+// CreateCert requests a new certificate using the Certificate Signing Request csr encoded in DER format.
+// The exp argument indicates the desired certificate validity duration. CA may issue a certificate
+// with a different duration.
+// If the bundle argument is true, the returned value will also contain the CA (issuer) certificate chain.
+//
+// In the case where CA server does not provide the issued certificate in the response,
+// CreateCert will poll certURL using c.FetchCert, which will result in additional round-trips.
+// In such a scenario, the caller can cancel the polling with ctx.
+//
+// CreateCert returns an error if the CA's response or chain was unreasonably large.
+// Callers are encouraged to parse the returned value to ensure the certificate is valid and has the expected features.
+func (c *Client) CreateCert(ctx context.Context, csr []byte, exp time.Duration, bundle bool) (der [][]byte, certURL string, err error) {
+ if _, err := c.Discover(ctx); err != nil {
+ return nil, "", err
+ }
+
+ req := struct {
+ Resource string `json:"resource"`
+ CSR string `json:"csr"`
+ NotBefore string `json:"notBefore,omitempty"`
+ NotAfter string `json:"notAfter,omitempty"`
+ }{
+ Resource: "new-cert",
+ CSR: base64.RawURLEncoding.EncodeToString(csr),
+ }
+ now := timeNow()
+ req.NotBefore = now.Format(time.RFC3339)
+ if exp > 0 {
+ req.NotAfter = now.Add(exp).Format(time.RFC3339)
+ }
+
+ res, err := c.retryPostJWS(ctx, c.Key, c.dir.CertURL, req)
+ if err != nil {
+ return nil, "", err
+ }
+ defer res.Body.Close()
+ if res.StatusCode != http.StatusCreated {
+ return nil, "", responseError(res)
+ }
+
+ curl := res.Header.Get("Location") // cert permanent URL
+ if res.ContentLength == 0 {
+ // no cert in the body; poll until we get it
+ cert, err := c.FetchCert(ctx, curl, bundle)
+ return cert, curl, err
+ }
+ // slurp issued cert and CA chain, if requested
+ cert, err := c.responseCert(ctx, res, bundle)
+ return cert, curl, err
+}
+
+// FetchCert retrieves already issued certificate from the given url, in DER format.
+// It retries the request until the certificate is successfully retrieved,
+// context is cancelled by the caller or an error response is received.
+//
+// The returned value will also contain the CA (issuer) certificate if the bundle argument is true.
+//
+// FetchCert returns an error if the CA's response or chain was unreasonably large.
+// Callers are encouraged to parse the returned value to ensure the certificate is valid
+// and has expected features.
+func (c *Client) FetchCert(ctx context.Context, url string, bundle bool) ([][]byte, error) {
+ for {
+ res, err := c.get(ctx, url)
+ if err != nil {
+ return nil, err
+ }
+ defer res.Body.Close()
+ if res.StatusCode == http.StatusOK {
+ return c.responseCert(ctx, res, bundle)
+ }
+ if res.StatusCode > 299 {
+ return nil, responseError(res)
+ }
+ d := retryAfter(res.Header.Get("Retry-After"), 3*time.Second)
+ select {
+ case <-time.After(d):
+ // retry
+ case <-ctx.Done():
+ return nil, ctx.Err()
+ }
+ }
+}
+
+// RevokeCert revokes a previously issued certificate cert, provided in DER format.
+//
+// The key argument, used to sign the request, must be authorized
+// to revoke the certificate. It's up to the CA to decide which keys are authorized.
+// For instance, the key pair of the certificate may be authorized.
+// If the key is nil, c.Key is used instead.
+func (c *Client) RevokeCert(ctx context.Context, key crypto.Signer, cert []byte, reason CRLReasonCode) error {
+ if _, err := c.Discover(ctx); err != nil {
+ return err
+ }
+
+ body := &struct {
+ Resource string `json:"resource"`
+ Cert string `json:"certificate"`
+ Reason int `json:"reason"`
+ }{
+ Resource: "revoke-cert",
+ Cert: base64.RawURLEncoding.EncodeToString(cert),
+ Reason: int(reason),
+ }
+ if key == nil {
+ key = c.Key
+ }
+ res, err := c.retryPostJWS(ctx, key, c.dir.RevokeURL, body)
+ if err != nil {
+ return err
+ }
+ defer res.Body.Close()
+ if res.StatusCode != http.StatusOK {
+ return responseError(res)
+ }
+ return nil
+}
+
+// AcceptTOS always returns true to indicate the acceptance of a CA's Terms of Service
+// during account registration. See Register method of Client for more details.
+func AcceptTOS(tosURL string) bool { return true }
+
+// Register creates a new account registration by following the "new-reg" flow.
+// It returns the registered account. The account is not modified.
+//
+// The registration may require the caller to agree to the CA's Terms of Service (TOS).
+// If so, and the account has not indicated the acceptance of the terms (see Account for details),
+// Register calls prompt with a TOS URL provided by the CA. Prompt should report
+// whether the caller agrees to the terms. To always accept the terms, the caller can use AcceptTOS.
+func (c *Client) Register(ctx context.Context, a *Account, prompt func(tosURL string) bool) (*Account, error) {
+ if _, err := c.Discover(ctx); err != nil {
+ return nil, err
+ }
+
+ var err error
+ if a, err = c.doReg(ctx, c.dir.RegURL, "new-reg", a); err != nil {
+ return nil, err
+ }
+ var accept bool
+ if a.CurrentTerms != "" && a.CurrentTerms != a.AgreedTerms {
+ accept = prompt(a.CurrentTerms)
+ }
+ if accept {
+ a.AgreedTerms = a.CurrentTerms
+ a, err = c.UpdateReg(ctx, a)
+ }
+ return a, err
+}
+
+// GetReg retrieves an existing registration.
+// The url argument is an Account URI.
+func (c *Client) GetReg(ctx context.Context, url string) (*Account, error) {
+ a, err := c.doReg(ctx, url, "reg", nil)
+ if err != nil {
+ return nil, err
+ }
+ a.URI = url
+ return a, nil
+}
+
+// UpdateReg updates an existing registration.
+// It returns an updated account copy. The provided account is not modified.
+func (c *Client) UpdateReg(ctx context.Context, a *Account) (*Account, error) {
+ uri := a.URI
+ a, err := c.doReg(ctx, uri, "reg", a)
+ if err != nil {
+ return nil, err
+ }
+ a.URI = uri
+ return a, nil
+}
+
+// Authorize performs the initial step in an authorization flow.
+// The caller will then need to choose from and perform a set of returned
+// challenges using c.Accept in order to successfully complete authorization.
+//
+// If an authorization has been previously granted, the CA may return
+// a valid authorization (Authorization.Status is StatusValid). If so, the caller
+// need not fulfill any challenge and can proceed to requesting a certificate.
+func (c *Client) Authorize(ctx context.Context, domain string) (*Authorization, error) {
+ if _, err := c.Discover(ctx); err != nil {
+ return nil, err
+ }
+
+ type authzID struct {
+ Type string `json:"type"`
+ Value string `json:"value"`
+ }
+ req := struct {
+ Resource string `json:"resource"`
+ Identifier authzID `json:"identifier"`
+ }{
+ Resource: "new-authz",
+ Identifier: authzID{Type: "dns", Value: domain},
+ }
+ res, err := c.retryPostJWS(ctx, c.Key, c.dir.AuthzURL, req)
+ if err != nil {
+ return nil, err
+ }
+ defer res.Body.Close()
+ if res.StatusCode != http.StatusCreated {
+ return nil, responseError(res)
+ }
+
+ var v wireAuthz
+ if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
+ return nil, fmt.Errorf("acme: invalid response: %v", err)
+ }
+ if v.Status != StatusPending && v.Status != StatusValid {
+ return nil, fmt.Errorf("acme: unexpected status: %s", v.Status)
+ }
+ return v.authorization(res.Header.Get("Location")), nil
+}
+
+// GetAuthorization retrieves an authorization identified by the given URL.
+//
+// If a caller needs to poll an authorization until its status is final,
+// see the WaitAuthorization method.
+func (c *Client) GetAuthorization(ctx context.Context, url string) (*Authorization, error) {
+ res, err := c.get(ctx, url)
+ if err != nil {
+ return nil, err
+ }
+ defer res.Body.Close()
+ if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusAccepted {
+ return nil, responseError(res)
+ }
+ var v wireAuthz
+ if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
+ return nil, fmt.Errorf("acme: invalid response: %v", err)
+ }
+ return v.authorization(url), nil
+}
+
+// RevokeAuthorization relinquishes an existing authorization identified
+// by the given URL.
+// The url argument is an Authorization.URI value.
+//
+// If successful, the caller will be required to obtain a new authorization
+// using the Authorize method before being able to request a new certificate
+// for the domain associated with the authorization.
+//
+// It does not revoke existing certificates.
+func (c *Client) RevokeAuthorization(ctx context.Context, url string) error {
+ req := struct {
+ Resource string `json:"resource"`
+ Status string `json:"status"`
+ Delete bool `json:"delete"`
+ }{
+ Resource: "authz",
+ Status: "deactivated",
+ Delete: true,
+ }
+ res, err := c.retryPostJWS(ctx, c.Key, url, req)
+ if err != nil {
+ return err
+ }
+ defer res.Body.Close()
+ if res.StatusCode != http.StatusOK {
+ return responseError(res)
+ }
+ return nil
+}
+
+// WaitAuthorization polls an authorization at the given URL
+// until it is in one of the final states, StatusValid or StatusInvalid,
+// or the context is done.
+//
+// It returns a non-nil Authorization only if its Status is StatusValid.
+// In all other cases WaitAuthorization returns an error.
+// If the Status is StatusInvalid, the returned error is of type *AuthorizationError.
+func (c *Client) WaitAuthorization(ctx context.Context, url string) (*Authorization, error) {
+ sleep := sleeper(ctx)
+ for {
+ res, err := c.get(ctx, url)
+ if err != nil {
+ return nil, err
+ }
+ retry := res.Header.Get("Retry-After")
+ if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusAccepted {
+ res.Body.Close()
+ if err := sleep(retry, 1); err != nil {
+ return nil, err
+ }
+ continue
+ }
+ var raw wireAuthz
+ err = json.NewDecoder(res.Body).Decode(&raw)
+ res.Body.Close()
+ if err != nil {
+ if err := sleep(retry, 0); err != nil {
+ return nil, err
+ }
+ continue
+ }
+ if raw.Status == StatusValid {
+ return raw.authorization(url), nil
+ }
+ if raw.Status == StatusInvalid {
+ return nil, raw.error(url)
+ }
+ if err := sleep(retry, 0); err != nil {
+ return nil, err
+ }
+ }
+}
+
+// GetChallenge retrieves the current status of an challenge.
+//
+// A client typically polls a challenge status using this method.
+func (c *Client) GetChallenge(ctx context.Context, url string) (*Challenge, error) {
+ res, err := c.get(ctx, url)
+ if err != nil {
+ return nil, err
+ }
+ defer res.Body.Close()
+ if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusAccepted {
+ return nil, responseError(res)
+ }
+ v := wireChallenge{URI: url}
+ if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
+ return nil, fmt.Errorf("acme: invalid response: %v", err)
+ }
+ return v.challenge(), nil
+}
+
+// Accept informs the server that the client accepts one of its challenges
+// previously obtained with c.Authorize.
+//
+// The server will then perform the validation asynchronously.
+func (c *Client) Accept(ctx context.Context, chal *Challenge) (*Challenge, error) {
+ auth, err := keyAuth(c.Key.Public(), chal.Token)
+ if err != nil {
+ return nil, err
+ }
+
+ req := struct {
+ Resource string `json:"resource"`
+ Type string `json:"type"`
+ Auth string `json:"keyAuthorization"`
+ }{
+ Resource: "challenge",
+ Type: chal.Type,
+ Auth: auth,
+ }
+ res, err := c.retryPostJWS(ctx, c.Key, chal.URI, req)
+ if err != nil {
+ return nil, err
+ }
+ defer res.Body.Close()
+ // Note: the protocol specifies 200 as the expected response code, but
+ // letsencrypt seems to be returning 202.
+ if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusAccepted {
+ return nil, responseError(res)
+ }
+
+ var v wireChallenge
+ if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
+ return nil, fmt.Errorf("acme: invalid response: %v", err)
+ }
+ return v.challenge(), nil
+}
+
+// DNS01ChallengeRecord returns a DNS record value for a dns-01 challenge response.
+// A TXT record containing the returned value must be provisioned under
+// "_acme-challenge" name of the domain being validated.
+//
+// The token argument is a Challenge.Token value.
+func (c *Client) DNS01ChallengeRecord(token string) (string, error) {
+ ka, err := keyAuth(c.Key.Public(), token)
+ if err != nil {
+ return "", err
+ }
+ b := sha256.Sum256([]byte(ka))
+ return base64.RawURLEncoding.EncodeToString(b[:]), nil
+}
+
+// HTTP01ChallengeResponse returns the response for an http-01 challenge.
+// Servers should respond with the value to HTTP requests at the URL path
+// provided by HTTP01ChallengePath to validate the challenge and prove control
+// over a domain name.
+//
+// The token argument is a Challenge.Token value.
+func (c *Client) HTTP01ChallengeResponse(token string) (string, error) {
+ return keyAuth(c.Key.Public(), token)
+}
+
+// HTTP01ChallengePath returns the URL path at which the response for an http-01 challenge
+// should be provided by the servers.
+// The response value can be obtained with HTTP01ChallengeResponse.
+//
+// The token argument is a Challenge.Token value.
+func (c *Client) HTTP01ChallengePath(token string) string {
+ return "/.well-known/acme-challenge/" + token
+}
+
+// TLSSNI01ChallengeCert creates a certificate for TLS-SNI-01 challenge response.
+// Servers can present the certificate to validate the challenge and prove control
+// over a domain name.
+//
+// The implementation is incomplete in that the returned value is a single certificate,
+// computed only for Z0 of the key authorization. ACME CAs are expected to update
+// their implementations to use the newer version, TLS-SNI-02.
+// For more details on TLS-SNI-01 see https://tools.ietf.org/html/draft-ietf-acme-acme-01#section-7.3.
+//
+// The token argument is a Challenge.Token value.
+// If a WithKey option is provided, its private part signs the returned cert,
+// and the public part is used to specify the signee.
+// If no WithKey option is provided, a new ECDSA key is generated using P-256 curve.
+//
+// The returned certificate is valid for the next 24 hours and must be presented only when
+// the server name of the client hello matches exactly the returned name value.
+func (c *Client) TLSSNI01ChallengeCert(token string, opt ...CertOption) (cert tls.Certificate, name string, err error) {
+ ka, err := keyAuth(c.Key.Public(), token)
+ if err != nil {
+ return tls.Certificate{}, "", err
+ }
+ b := sha256.Sum256([]byte(ka))
+ h := hex.EncodeToString(b[:])
+ name = fmt.Sprintf("%s.%s.acme.invalid", h[:32], h[32:])
+ cert, err = tlsChallengeCert([]string{name}, opt)
+ if err != nil {
+ return tls.Certificate{}, "", err
+ }
+ return cert, name, nil
+}
+
+// TLSSNI02ChallengeCert creates a certificate for TLS-SNI-02 challenge response.
+// Servers can present the certificate to validate the challenge and prove control
+// over a domain name. For more details on TLS-SNI-02 see
+// https://tools.ietf.org/html/draft-ietf-acme-acme-03#section-7.3.
+//
+// The token argument is a Challenge.Token value.
+// If a WithKey option is provided, its private part signs the returned cert,
+// and the public part is used to specify the signee.
+// If no WithKey option is provided, a new ECDSA key is generated using P-256 curve.
+//
+// The returned certificate is valid for the next 24 hours and must be presented only when
+// the server name in the client hello matches exactly the returned name value.
+func (c *Client) TLSSNI02ChallengeCert(token string, opt ...CertOption) (cert tls.Certificate, name string, err error) {
+ b := sha256.Sum256([]byte(token))
+ h := hex.EncodeToString(b[:])
+ sanA := fmt.Sprintf("%s.%s.token.acme.invalid", h[:32], h[32:])
+
+ ka, err := keyAuth(c.Key.Public(), token)
+ if err != nil {
+ return tls.Certificate{}, "", err
+ }
+ b = sha256.Sum256([]byte(ka))
+ h = hex.EncodeToString(b[:])
+ sanB := fmt.Sprintf("%s.%s.ka.acme.invalid", h[:32], h[32:])
+
+ cert, err = tlsChallengeCert([]string{sanA, sanB}, opt)
+ if err != nil {
+ return tls.Certificate{}, "", err
+ }
+ return cert, sanA, nil
+}
+
+// doReg sends all types of registration requests.
+// The type of request is identified by typ argument, which is a "resource"
+// in the ACME spec terms.
+//
+// A non-nil acct argument indicates whether the intention is to mutate data
+// of the Account. Only Contact and Agreement of its fields are used
+// in such cases.
+func (c *Client) doReg(ctx context.Context, url string, typ string, acct *Account) (*Account, error) {
+ req := struct {
+ Resource string `json:"resource"`
+ Contact []string `json:"contact,omitempty"`
+ Agreement string `json:"agreement,omitempty"`
+ }{
+ Resource: typ,
+ }
+ if acct != nil {
+ req.Contact = acct.Contact
+ req.Agreement = acct.AgreedTerms
+ }
+ res, err := c.retryPostJWS(ctx, c.Key, url, req)
+ if err != nil {
+ return nil, err
+ }
+ defer res.Body.Close()
+ if res.StatusCode < 200 || res.StatusCode > 299 {
+ return nil, responseError(res)
+ }
+
+ var v struct {
+ Contact []string
+ Agreement string
+ Authorizations string
+ Certificates string
+ }
+ if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
+ return nil, fmt.Errorf("acme: invalid response: %v", err)
+ }
+ var tos string
+ if v := linkHeader(res.Header, "terms-of-service"); len(v) > 0 {
+ tos = v[0]
+ }
+ var authz string
+ if v := linkHeader(res.Header, "next"); len(v) > 0 {
+ authz = v[0]
+ }
+ return &Account{
+ URI: res.Header.Get("Location"),
+ Contact: v.Contact,
+ AgreedTerms: v.Agreement,
+ CurrentTerms: tos,
+ Authz: authz,
+ Authorizations: v.Authorizations,
+ Certificates: v.Certificates,
+ }, nil
+}
+
+// retryPostJWS will retry calls to postJWS if there is a badNonce error,
+// clearing the stored nonces after each error.
+// If the response was 4XX-5XX, then responseError is called on the body,
+// the body is closed, and the error returned.
+func (c *Client) retryPostJWS(ctx context.Context, key crypto.Signer, url string, body interface{}) (*http.Response, error) {
+ sleep := sleeper(ctx)
+ for {
+ res, err := c.postJWS(ctx, key, url, body)
+ if err != nil {
+ return nil, err
+ }
+ // handle errors 4XX-5XX with responseError
+ if res.StatusCode >= 400 && res.StatusCode <= 599 {
+ err := responseError(res)
+ res.Body.Close()
+ // according to spec badNonce is urn:ietf:params:acme:error:badNonce
+ // however, acme servers in the wild return their version of the error
+ // https://tools.ietf.org/html/draft-ietf-acme-acme-02#section-5.4
+ if ae, ok := err.(*Error); ok && strings.HasSuffix(strings.ToLower(ae.ProblemType), ":badnonce") {
+ // clear any nonces that we might've stored that might now be
+ // considered bad
+ c.clearNonces()
+ retry := res.Header.Get("Retry-After")
+ if err := sleep(retry, 1); err != nil {
+ return nil, err
+ }
+ continue
+ }
+ return nil, err
+ }
+ return res, nil
+ }
+}
+
+// postJWS signs the body with the given key and POSTs it to the provided url.
+// The body argument must be JSON-serializable.
+func (c *Client) postJWS(ctx context.Context, key crypto.Signer, url string, body interface{}) (*http.Response, error) {
+ nonce, err := c.popNonce(ctx, url)
+ if err != nil {
+ return nil, err
+ }
+ b, err := jwsEncodeJSON(body, key, nonce)
+ if err != nil {
+ return nil, err
+ }
+ res, err := c.post(ctx, url, "application/jose+json", bytes.NewReader(b))
+ if err != nil {
+ return nil, err
+ }
+ c.addNonce(res.Header)
+ return res, nil
+}
+
+// popNonce returns a nonce value previously stored with c.addNonce
+// or fetches a fresh one from the given URL.
+func (c *Client) popNonce(ctx context.Context, url string) (string, error) {
+ c.noncesMu.Lock()
+ defer c.noncesMu.Unlock()
+ if len(c.nonces) == 0 {
+ return c.fetchNonce(ctx, url)
+ }
+ var nonce string
+ for nonce = range c.nonces {
+ delete(c.nonces, nonce)
+ break
+ }
+ return nonce, nil
+}
+
+// clearNonces clears any stored nonces
+func (c *Client) clearNonces() {
+ c.noncesMu.Lock()
+ defer c.noncesMu.Unlock()
+ c.nonces = make(map[string]struct{})
+}
+
+// addNonce stores a nonce value found in h (if any) for future use.
+func (c *Client) addNonce(h http.Header) {
+ v := nonceFromHeader(h)
+ if v == "" {
+ return
+ }
+ c.noncesMu.Lock()
+ defer c.noncesMu.Unlock()
+ if len(c.nonces) >= maxNonces {
+ return
+ }
+ if c.nonces == nil {
+ c.nonces = make(map[string]struct{})
+ }
+ c.nonces[v] = struct{}{}
+}
+
+func (c *Client) httpClient() *http.Client {
+ if c.HTTPClient != nil {
+ return c.HTTPClient
+ }
+ return http.DefaultClient
+}
+
+func (c *Client) get(ctx context.Context, urlStr string) (*http.Response, error) {
+ req, err := http.NewRequest("GET", urlStr, nil)
+ if err != nil {
+ return nil, err
+ }
+ return c.do(ctx, req)
+}
+
+func (c *Client) head(ctx context.Context, urlStr string) (*http.Response, error) {
+ req, err := http.NewRequest("HEAD", urlStr, nil)
+ if err != nil {
+ return nil, err
+ }
+ return c.do(ctx, req)
+}
+
+func (c *Client) post(ctx context.Context, urlStr, contentType string, body io.Reader) (*http.Response, error) {
+ req, err := http.NewRequest("POST", urlStr, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header.Set("Content-Type", contentType)
+ return c.do(ctx, req)
+}
+
+func (c *Client) do(ctx context.Context, req *http.Request) (*http.Response, error) {
+ res, err := c.httpClient().Do(req.WithContext(ctx))
+ if err != nil {
+ select {
+ case <-ctx.Done():
+ // Prefer the unadorned context error.
+ // (The acme package had tests assuming this, previously from ctxhttp's
+ // behavior, predating net/http supporting contexts natively)
+ // TODO(bradfitz): reconsider this in the future. But for now this
+ // requires no test updates.
+ return nil, ctx.Err()
+ default:
+ return nil, err
+ }
+ }
+ return res, nil
+}
+
+func (c *Client) fetchNonce(ctx context.Context, url string) (string, error) {
+ resp, err := c.head(ctx, url)
+ if err != nil {
+ return "", err
+ }
+ defer resp.Body.Close()
+ nonce := nonceFromHeader(resp.Header)
+ if nonce == "" {
+ if resp.StatusCode > 299 {
+ return "", responseError(resp)
+ }
+ return "", errors.New("acme: nonce not found")
+ }
+ return nonce, nil
+}
+
+func nonceFromHeader(h http.Header) string {
+ return h.Get("Replay-Nonce")
+}
+
+func (c *Client) responseCert(ctx context.Context, res *http.Response, bundle bool) ([][]byte, error) {
+ b, err := ioutil.ReadAll(io.LimitReader(res.Body, maxCertSize+1))
+ if err != nil {
+ return nil, fmt.Errorf("acme: response stream: %v", err)
+ }
+ if len(b) > maxCertSize {
+ return nil, errors.New("acme: certificate is too big")
+ }
+ cert := [][]byte{b}
+ if !bundle {
+ return cert, nil
+ }
+
+ // Append CA chain cert(s).
+ // At least one is required according to the spec:
+ // https://tools.ietf.org/html/draft-ietf-acme-acme-03#section-6.3.1
+ up := linkHeader(res.Header, "up")
+ if len(up) == 0 {
+ return nil, errors.New("acme: rel=up link not found")
+ }
+ if len(up) > maxChainLen {
+ return nil, errors.New("acme: rel=up link is too large")
+ }
+ for _, url := range up {
+ cc, err := c.chainCert(ctx, url, 0)
+ if err != nil {
+ return nil, err
+ }
+ cert = append(cert, cc...)
+ }
+ return cert, nil
+}
+
+// responseError creates an error of Error type from resp.
+func responseError(resp *http.Response) error {
+ // don't care if ReadAll returns an error:
+ // json.Unmarshal will fail in that case anyway
+ b, _ := ioutil.ReadAll(resp.Body)
+ e := &wireError{Status: resp.StatusCode}
+ if err := json.Unmarshal(b, e); err != nil {
+ // this is not a regular error response:
+ // populate detail with anything we received,
+ // e.Status will already contain HTTP response code value
+ e.Detail = string(b)
+ if e.Detail == "" {
+ e.Detail = resp.Status
+ }
+ }
+ return e.error(resp.Header)
+}
+
+// chainCert fetches CA certificate chain recursively by following "up" links.
+// Each recursive call increments the depth by 1, resulting in an error
+// if the recursion level reaches maxChainLen.
+//
+// First chainCert call starts with depth of 0.
+func (c *Client) chainCert(ctx context.Context, url string, depth int) ([][]byte, error) {
+ if depth >= maxChainLen {
+ return nil, errors.New("acme: certificate chain is too deep")
+ }
+
+ res, err := c.get(ctx, url)
+ if err != nil {
+ return nil, err
+ }
+ defer res.Body.Close()
+ if res.StatusCode != http.StatusOK {
+ return nil, responseError(res)
+ }
+ b, err := ioutil.ReadAll(io.LimitReader(res.Body, maxCertSize+1))
+ if err != nil {
+ return nil, err
+ }
+ if len(b) > maxCertSize {
+ return nil, errors.New("acme: certificate is too big")
+ }
+ chain := [][]byte{b}
+
+ uplink := linkHeader(res.Header, "up")
+ if len(uplink) > maxChainLen {
+ return nil, errors.New("acme: certificate chain is too large")
+ }
+ for _, up := range uplink {
+ cc, err := c.chainCert(ctx, up, depth+1)
+ if err != nil {
+ return nil, err
+ }
+ chain = append(chain, cc...)
+ }
+
+ return chain, nil
+}
+
+// linkHeader returns URI-Reference values of all Link headers
+// with relation-type rel.
+// See https://tools.ietf.org/html/rfc5988#section-5 for details.
+func linkHeader(h http.Header, rel string) []string {
+ var links []string
+ for _, v := range h["Link"] {
+ parts := strings.Split(v, ";")
+ for _, p := range parts {
+ p = strings.TrimSpace(p)
+ if !strings.HasPrefix(p, "rel=") {
+ continue
+ }
+ if v := strings.Trim(p[4:], `"`); v == rel {
+ links = append(links, strings.Trim(parts[0], "<>"))
+ }
+ }
+ }
+ return links
+}
+
+// sleeper returns a function that accepts the Retry-After HTTP header value
+// and an increment that's used with backoff to increasingly sleep on
+// consecutive calls until the context is done. If the Retry-After header
+// cannot be parsed, then backoff is used with a maximum sleep time of 10
+// seconds.
+func sleeper(ctx context.Context) func(ra string, inc int) error {
+ var count int
+ return func(ra string, inc int) error {
+ count += inc
+ d := backoff(count, 10*time.Second)
+ d = retryAfter(ra, d)
+ wakeup := time.NewTimer(d)
+ defer wakeup.Stop()
+ select {
+ case <-ctx.Done():
+ return ctx.Err()
+ case <-wakeup.C:
+ return nil
+ }
+ }
+}
+
+// retryAfter parses a Retry-After HTTP header value,
+// trying to convert v into an int (seconds) or use http.ParseTime otherwise.
+// It returns d if v cannot be parsed.
+func retryAfter(v string, d time.Duration) time.Duration {
+ if i, err := strconv.Atoi(v); err == nil {
+ return time.Duration(i) * time.Second
+ }
+ t, err := http.ParseTime(v)
+ if err != nil {
+ return d
+ }
+ return t.Sub(timeNow())
+}
+
+// backoff computes a duration after which an n+1 retry iteration should occur
+// using truncated exponential backoff algorithm.
+//
+// The n argument is always bounded between 0 and 30.
+// The max argument defines upper bound for the returned value.
+func backoff(n int, max time.Duration) time.Duration {
+ if n < 0 {
+ n = 0
+ }
+ if n > 30 {
+ n = 30
+ }
+ var d time.Duration
+ if x, err := rand.Int(rand.Reader, big.NewInt(1000)); err == nil {
+ d = time.Duration(x.Int64()) * time.Millisecond
+ }
+ d += time.Duration(1<<uint(n)) * time.Second
+ if d > max {
+ return max
+ }
+ return d
+}
+
+// keyAuth generates a key authorization string for a given token.
+func keyAuth(pub crypto.PublicKey, token string) (string, error) {
+ th, err := JWKThumbprint(pub)
+ if err != nil {
+ return "", err
+ }
+ return fmt.Sprintf("%s.%s", token, th), nil
+}
+
+// tlsChallengeCert creates a temporary certificate for TLS-SNI challenges
+// with the given SANs and auto-generated public/private key pair.
+// The Subject Common Name is set to the first SAN to aid debugging.
+// To create a cert with a custom key pair, specify WithKey option.
+func tlsChallengeCert(san []string, opt []CertOption) (tls.Certificate, error) {
+ var (
+ key crypto.Signer
+ tmpl *x509.Certificate
+ )
+ for _, o := range opt {
+ switch o := o.(type) {
+ case *certOptKey:
+ if key != nil {
+ return tls.Certificate{}, errors.New("acme: duplicate key option")
+ }
+ key = o.key
+ case *certOptTemplate:
+ var t = *(*x509.Certificate)(o) // shallow copy is ok
+ tmpl = &t
+ default:
+ // package's fault, if we let this happen:
+ panic(fmt.Sprintf("unsupported option type %T", o))
+ }
+ }
+ if key == nil {
+ var err error
+ if key, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader); err != nil {
+ return tls.Certificate{}, err
+ }
+ }
+ if tmpl == nil {
+ tmpl = &x509.Certificate{
+ SerialNumber: big.NewInt(1),
+ NotBefore: time.Now(),
+ NotAfter: time.Now().Add(24 * time.Hour),
+ BasicConstraintsValid: true,
+ KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
+ ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
+ }
+ }
+ tmpl.DNSNames = san
+ if len(san) > 0 {
+ tmpl.Subject.CommonName = san[0]
+ }
+
+ der, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, key.Public(), key)
+ if err != nil {
+ return tls.Certificate{}, err
+ }
+ return tls.Certificate{
+ Certificate: [][]byte{der},
+ PrivateKey: key,
+ }, nil
+}
+
+// encodePEM returns b encoded as PEM with block of type typ.
+func encodePEM(typ string, b []byte) []byte {
+ pb := &pem.Block{Type: typ, Bytes: b}
+ return pem.EncodeToMemory(pb)
+}
+
+// timeNow is useful for testing for fixed current time.
+var timeNow = time.Now
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/acme_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/acme_test.go
new file mode 100644
index 000000000..b44af5959
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/acme_test.go
@@ -0,0 +1,1352 @@
+// Copyright 2015 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 acme
+
+import (
+ "bytes"
+ "context"
+ "crypto/rand"
+ "crypto/rsa"
+ "crypto/tls"
+ "crypto/x509"
+ "crypto/x509/pkix"
+ "encoding/base64"
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "math/big"
+ "net/http"
+ "net/http/httptest"
+ "reflect"
+ "sort"
+ "strings"
+ "testing"
+ "time"
+)
+
+// Decodes a JWS-encoded request and unmarshals the decoded JSON into a provided
+// interface.
+func decodeJWSRequest(t *testing.T, v interface{}, r *http.Request) {
+ // Decode request
+ var req struct{ Payload string }
+ if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
+ t.Fatal(err)
+ }
+ payload, err := base64.RawURLEncoding.DecodeString(req.Payload)
+ if err != nil {
+ t.Fatal(err)
+ }
+ err = json.Unmarshal(payload, v)
+ if err != nil {
+ t.Fatal(err)
+ }
+}
+
+type jwsHead struct {
+ Alg string
+ Nonce string
+ JWK map[string]string `json:"jwk"`
+}
+
+func decodeJWSHead(r *http.Request) (*jwsHead, error) {
+ var req struct{ Protected string }
+ if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
+ return nil, err
+ }
+ b, err := base64.RawURLEncoding.DecodeString(req.Protected)
+ if err != nil {
+ return nil, err
+ }
+ var head jwsHead
+ if err := json.Unmarshal(b, &head); err != nil {
+ return nil, err
+ }
+ return &head, nil
+}
+
+func TestDiscover(t *testing.T) {
+ const (
+ reg = "https://example.com/acme/new-reg"
+ authz = "https://example.com/acme/new-authz"
+ cert = "https://example.com/acme/new-cert"
+ revoke = "https://example.com/acme/revoke-cert"
+ )
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ fmt.Fprintf(w, `{
+ "new-reg": %q,
+ "new-authz": %q,
+ "new-cert": %q,
+ "revoke-cert": %q
+ }`, reg, authz, cert, revoke)
+ }))
+ defer ts.Close()
+ c := Client{DirectoryURL: ts.URL}
+ dir, err := c.Discover(context.Background())
+ if err != nil {
+ t.Fatal(err)
+ }
+ if dir.RegURL != reg {
+ t.Errorf("dir.RegURL = %q; want %q", dir.RegURL, reg)
+ }
+ if dir.AuthzURL != authz {
+ t.Errorf("dir.AuthzURL = %q; want %q", dir.AuthzURL, authz)
+ }
+ if dir.CertURL != cert {
+ t.Errorf("dir.CertURL = %q; want %q", dir.CertURL, cert)
+ }
+ if dir.RevokeURL != revoke {
+ t.Errorf("dir.RevokeURL = %q; want %q", dir.RevokeURL, revoke)
+ }
+}
+
+func TestRegister(t *testing.T) {
+ contacts := []string{"mailto:admin@example.com"}
+
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if r.Method == "HEAD" {
+ w.Header().Set("Replay-Nonce", "test-nonce")
+ return
+ }
+ if r.Method != "POST" {
+ t.Errorf("r.Method = %q; want POST", r.Method)
+ }
+
+ var j struct {
+ Resource string
+ Contact []string
+ Agreement string
+ }
+ decodeJWSRequest(t, &j, r)
+
+ // Test request
+ if j.Resource != "new-reg" {
+ t.Errorf("j.Resource = %q; want new-reg", j.Resource)
+ }
+ if !reflect.DeepEqual(j.Contact, contacts) {
+ t.Errorf("j.Contact = %v; want %v", j.Contact, contacts)
+ }
+
+ w.Header().Set("Location", "https://ca.tld/acme/reg/1")
+ w.Header().Set("Link", `<https://ca.tld/acme/new-authz>;rel="next"`)
+ w.Header().Add("Link", `<https://ca.tld/acme/recover-reg>;rel="recover"`)
+ w.Header().Add("Link", `<https://ca.tld/acme/terms>;rel="terms-of-service"`)
+ w.WriteHeader(http.StatusCreated)
+ b, _ := json.Marshal(contacts)
+ fmt.Fprintf(w, `{"contact": %s}`, b)
+ }))
+ defer ts.Close()
+
+ prompt := func(url string) bool {
+ const terms = "https://ca.tld/acme/terms"
+ if url != terms {
+ t.Errorf("prompt url = %q; want %q", url, terms)
+ }
+ return false
+ }
+
+ c := Client{Key: testKeyEC, dir: &Directory{RegURL: ts.URL}}
+ a := &Account{Contact: contacts}
+ var err error
+ if a, err = c.Register(context.Background(), a, prompt); err != nil {
+ t.Fatal(err)
+ }
+ if a.URI != "https://ca.tld/acme/reg/1" {
+ t.Errorf("a.URI = %q; want https://ca.tld/acme/reg/1", a.URI)
+ }
+ if a.Authz != "https://ca.tld/acme/new-authz" {
+ t.Errorf("a.Authz = %q; want https://ca.tld/acme/new-authz", a.Authz)
+ }
+ if a.CurrentTerms != "https://ca.tld/acme/terms" {
+ t.Errorf("a.CurrentTerms = %q; want https://ca.tld/acme/terms", a.CurrentTerms)
+ }
+ if !reflect.DeepEqual(a.Contact, contacts) {
+ t.Errorf("a.Contact = %v; want %v", a.Contact, contacts)
+ }
+}
+
+func TestUpdateReg(t *testing.T) {
+ const terms = "https://ca.tld/acme/terms"
+ contacts := []string{"mailto:admin@example.com"}
+
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if r.Method == "HEAD" {
+ w.Header().Set("Replay-Nonce", "test-nonce")
+ return
+ }
+ if r.Method != "POST" {
+ t.Errorf("r.Method = %q; want POST", r.Method)
+ }
+
+ var j struct {
+ Resource string
+ Contact []string
+ Agreement string
+ }
+ decodeJWSRequest(t, &j, r)
+
+ // Test request
+ if j.Resource != "reg" {
+ t.Errorf("j.Resource = %q; want reg", j.Resource)
+ }
+ if j.Agreement != terms {
+ t.Errorf("j.Agreement = %q; want %q", j.Agreement, terms)
+ }
+ if !reflect.DeepEqual(j.Contact, contacts) {
+ t.Errorf("j.Contact = %v; want %v", j.Contact, contacts)
+ }
+
+ w.Header().Set("Link", `<https://ca.tld/acme/new-authz>;rel="next"`)
+ w.Header().Add("Link", `<https://ca.tld/acme/recover-reg>;rel="recover"`)
+ w.Header().Add("Link", fmt.Sprintf(`<%s>;rel="terms-of-service"`, terms))
+ w.WriteHeader(http.StatusOK)
+ b, _ := json.Marshal(contacts)
+ fmt.Fprintf(w, `{"contact":%s, "agreement":%q}`, b, terms)
+ }))
+ defer ts.Close()
+
+ c := Client{Key: testKeyEC}
+ a := &Account{URI: ts.URL, Contact: contacts, AgreedTerms: terms}
+ var err error
+ if a, err = c.UpdateReg(context.Background(), a); err != nil {
+ t.Fatal(err)
+ }
+ if a.Authz != "https://ca.tld/acme/new-authz" {
+ t.Errorf("a.Authz = %q; want https://ca.tld/acme/new-authz", a.Authz)
+ }
+ if a.AgreedTerms != terms {
+ t.Errorf("a.AgreedTerms = %q; want %q", a.AgreedTerms, terms)
+ }
+ if a.CurrentTerms != terms {
+ t.Errorf("a.CurrentTerms = %q; want %q", a.CurrentTerms, terms)
+ }
+ if a.URI != ts.URL {
+ t.Errorf("a.URI = %q; want %q", a.URI, ts.URL)
+ }
+}
+
+func TestGetReg(t *testing.T) {
+ const terms = "https://ca.tld/acme/terms"
+ const newTerms = "https://ca.tld/acme/new-terms"
+ contacts := []string{"mailto:admin@example.com"}
+
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if r.Method == "HEAD" {
+ w.Header().Set("Replay-Nonce", "test-nonce")
+ return
+ }
+ if r.Method != "POST" {
+ t.Errorf("r.Method = %q; want POST", r.Method)
+ }
+
+ var j struct {
+ Resource string
+ Contact []string
+ Agreement string
+ }
+ decodeJWSRequest(t, &j, r)
+
+ // Test request
+ if j.Resource != "reg" {
+ t.Errorf("j.Resource = %q; want reg", j.Resource)
+ }
+ if len(j.Contact) != 0 {
+ t.Errorf("j.Contact = %v", j.Contact)
+ }
+ if j.Agreement != "" {
+ t.Errorf("j.Agreement = %q", j.Agreement)
+ }
+
+ w.Header().Set("Link", `<https://ca.tld/acme/new-authz>;rel="next"`)
+ w.Header().Add("Link", `<https://ca.tld/acme/recover-reg>;rel="recover"`)
+ w.Header().Add("Link", fmt.Sprintf(`<%s>;rel="terms-of-service"`, newTerms))
+ w.WriteHeader(http.StatusOK)
+ b, _ := json.Marshal(contacts)
+ fmt.Fprintf(w, `{"contact":%s, "agreement":%q}`, b, terms)
+ }))
+ defer ts.Close()
+
+ c := Client{Key: testKeyEC}
+ a, err := c.GetReg(context.Background(), ts.URL)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if a.Authz != "https://ca.tld/acme/new-authz" {
+ t.Errorf("a.AuthzURL = %q; want https://ca.tld/acme/new-authz", a.Authz)
+ }
+ if a.AgreedTerms != terms {
+ t.Errorf("a.AgreedTerms = %q; want %q", a.AgreedTerms, terms)
+ }
+ if a.CurrentTerms != newTerms {
+ t.Errorf("a.CurrentTerms = %q; want %q", a.CurrentTerms, newTerms)
+ }
+ if a.URI != ts.URL {
+ t.Errorf("a.URI = %q; want %q", a.URI, ts.URL)
+ }
+}
+
+func TestAuthorize(t *testing.T) {
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if r.Method == "HEAD" {
+ w.Header().Set("Replay-Nonce", "test-nonce")
+ return
+ }
+ if r.Method != "POST" {
+ t.Errorf("r.Method = %q; want POST", r.Method)
+ }
+
+ var j struct {
+ Resource string
+ Identifier struct {
+ Type string
+ Value string
+ }
+ }
+ decodeJWSRequest(t, &j, r)
+
+ // Test request
+ if j.Resource != "new-authz" {
+ t.Errorf("j.Resource = %q; want new-authz", j.Resource)
+ }
+ if j.Identifier.Type != "dns" {
+ t.Errorf("j.Identifier.Type = %q; want dns", j.Identifier.Type)
+ }
+ if j.Identifier.Value != "example.com" {
+ t.Errorf("j.Identifier.Value = %q; want example.com", j.Identifier.Value)
+ }
+
+ w.Header().Set("Location", "https://ca.tld/acme/auth/1")
+ w.WriteHeader(http.StatusCreated)
+ fmt.Fprintf(w, `{
+ "identifier": {"type":"dns","value":"example.com"},
+ "status":"pending",
+ "challenges":[
+ {
+ "type":"http-01",
+ "status":"pending",
+ "uri":"https://ca.tld/acme/challenge/publickey/id1",
+ "token":"token1"
+ },
+ {
+ "type":"tls-sni-01",
+ "status":"pending",
+ "uri":"https://ca.tld/acme/challenge/publickey/id2",
+ "token":"token2"
+ }
+ ],
+ "combinations":[[0],[1]]}`)
+ }))
+ defer ts.Close()
+
+ cl := Client{Key: testKeyEC, dir: &Directory{AuthzURL: ts.URL}}
+ auth, err := cl.Authorize(context.Background(), "example.com")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if auth.URI != "https://ca.tld/acme/auth/1" {
+ t.Errorf("URI = %q; want https://ca.tld/acme/auth/1", auth.URI)
+ }
+ if auth.Status != "pending" {
+ t.Errorf("Status = %q; want pending", auth.Status)
+ }
+ if auth.Identifier.Type != "dns" {
+ t.Errorf("Identifier.Type = %q; want dns", auth.Identifier.Type)
+ }
+ if auth.Identifier.Value != "example.com" {
+ t.Errorf("Identifier.Value = %q; want example.com", auth.Identifier.Value)
+ }
+
+ if n := len(auth.Challenges); n != 2 {
+ t.Fatalf("len(auth.Challenges) = %d; want 2", n)
+ }
+
+ c := auth.Challenges[0]
+ if c.Type != "http-01" {
+ t.Errorf("c.Type = %q; want http-01", c.Type)
+ }
+ if c.URI != "https://ca.tld/acme/challenge/publickey/id1" {
+ t.Errorf("c.URI = %q; want https://ca.tld/acme/challenge/publickey/id1", c.URI)
+ }
+ if c.Token != "token1" {
+ t.Errorf("c.Token = %q; want token1", c.Token)
+ }
+
+ c = auth.Challenges[1]
+ if c.Type != "tls-sni-01" {
+ t.Errorf("c.Type = %q; want tls-sni-01", c.Type)
+ }
+ if c.URI != "https://ca.tld/acme/challenge/publickey/id2" {
+ t.Errorf("c.URI = %q; want https://ca.tld/acme/challenge/publickey/id2", c.URI)
+ }
+ if c.Token != "token2" {
+ t.Errorf("c.Token = %q; want token2", c.Token)
+ }
+
+ combs := [][]int{{0}, {1}}
+ if !reflect.DeepEqual(auth.Combinations, combs) {
+ t.Errorf("auth.Combinations: %+v\nwant: %+v\n", auth.Combinations, combs)
+ }
+}
+
+func TestAuthorizeValid(t *testing.T) {
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if r.Method == "HEAD" {
+ w.Header().Set("Replay-Nonce", "nonce")
+ return
+ }
+ w.WriteHeader(http.StatusCreated)
+ w.Write([]byte(`{"status":"valid"}`))
+ }))
+ defer ts.Close()
+ client := Client{Key: testKey, dir: &Directory{AuthzURL: ts.URL}}
+ _, err := client.Authorize(context.Background(), "example.com")
+ if err != nil {
+ t.Errorf("err = %v", err)
+ }
+}
+
+func TestGetAuthorization(t *testing.T) {
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if r.Method != "GET" {
+ t.Errorf("r.Method = %q; want GET", r.Method)
+ }
+
+ w.WriteHeader(http.StatusOK)
+ fmt.Fprintf(w, `{
+ "identifier": {"type":"dns","value":"example.com"},
+ "status":"pending",
+ "challenges":[
+ {
+ "type":"http-01",
+ "status":"pending",
+ "uri":"https://ca.tld/acme/challenge/publickey/id1",
+ "token":"token1"
+ },
+ {
+ "type":"tls-sni-01",
+ "status":"pending",
+ "uri":"https://ca.tld/acme/challenge/publickey/id2",
+ "token":"token2"
+ }
+ ],
+ "combinations":[[0],[1]]}`)
+ }))
+ defer ts.Close()
+
+ cl := Client{Key: testKeyEC}
+ auth, err := cl.GetAuthorization(context.Background(), ts.URL)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if auth.Status != "pending" {
+ t.Errorf("Status = %q; want pending", auth.Status)
+ }
+ if auth.Identifier.Type != "dns" {
+ t.Errorf("Identifier.Type = %q; want dns", auth.Identifier.Type)
+ }
+ if auth.Identifier.Value != "example.com" {
+ t.Errorf("Identifier.Value = %q; want example.com", auth.Identifier.Value)
+ }
+
+ if n := len(auth.Challenges); n != 2 {
+ t.Fatalf("len(set.Challenges) = %d; want 2", n)
+ }
+
+ c := auth.Challenges[0]
+ if c.Type != "http-01" {
+ t.Errorf("c.Type = %q; want http-01", c.Type)
+ }
+ if c.URI != "https://ca.tld/acme/challenge/publickey/id1" {
+ t.Errorf("c.URI = %q; want https://ca.tld/acme/challenge/publickey/id1", c.URI)
+ }
+ if c.Token != "token1" {
+ t.Errorf("c.Token = %q; want token1", c.Token)
+ }
+
+ c = auth.Challenges[1]
+ if c.Type != "tls-sni-01" {
+ t.Errorf("c.Type = %q; want tls-sni-01", c.Type)
+ }
+ if c.URI != "https://ca.tld/acme/challenge/publickey/id2" {
+ t.Errorf("c.URI = %q; want https://ca.tld/acme/challenge/publickey/id2", c.URI)
+ }
+ if c.Token != "token2" {
+ t.Errorf("c.Token = %q; want token2", c.Token)
+ }
+
+ combs := [][]int{{0}, {1}}
+ if !reflect.DeepEqual(auth.Combinations, combs) {
+ t.Errorf("auth.Combinations: %+v\nwant: %+v\n", auth.Combinations, combs)
+ }
+}
+
+func TestWaitAuthorization(t *testing.T) {
+ var count int
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ count++
+ w.Header().Set("Retry-After", "0")
+ if count > 1 {
+ fmt.Fprintf(w, `{"status":"valid"}`)
+ return
+ }
+ fmt.Fprintf(w, `{"status":"pending"}`)
+ }))
+ defer ts.Close()
+
+ type res struct {
+ authz *Authorization
+ err error
+ }
+ done := make(chan res)
+ defer close(done)
+ go func() {
+ var client Client
+ a, err := client.WaitAuthorization(context.Background(), ts.URL)
+ done <- res{a, err}
+ }()
+
+ select {
+ case <-time.After(5 * time.Second):
+ t.Fatal("WaitAuthz took too long to return")
+ case res := <-done:
+ if res.err != nil {
+ t.Fatalf("res.err = %v", res.err)
+ }
+ if res.authz == nil {
+ t.Fatal("res.authz is nil")
+ }
+ }
+}
+
+func TestWaitAuthorizationInvalid(t *testing.T) {
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ fmt.Fprintf(w, `{"status":"invalid"}`)
+ }))
+ defer ts.Close()
+
+ res := make(chan error)
+ defer close(res)
+ go func() {
+ var client Client
+ _, err := client.WaitAuthorization(context.Background(), ts.URL)
+ res <- err
+ }()
+
+ select {
+ case <-time.After(3 * time.Second):
+ t.Fatal("WaitAuthz took too long to return")
+ case err := <-res:
+ if err == nil {
+ t.Error("err is nil")
+ }
+ if _, ok := err.(*AuthorizationError); !ok {
+ t.Errorf("err is %T; want *AuthorizationError", err)
+ }
+ }
+}
+
+func TestWaitAuthorizationCancel(t *testing.T) {
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Retry-After", "60")
+ fmt.Fprintf(w, `{"status":"pending"}`)
+ }))
+ defer ts.Close()
+
+ res := make(chan error)
+ defer close(res)
+ go func() {
+ var client Client
+ ctx, cancel := context.WithTimeout(context.Background(), 200*time.Millisecond)
+ defer cancel()
+ _, err := client.WaitAuthorization(ctx, ts.URL)
+ res <- err
+ }()
+
+ select {
+ case <-time.After(time.Second):
+ t.Fatal("WaitAuthz took too long to return")
+ case err := <-res:
+ if err == nil {
+ t.Error("err is nil")
+ }
+ }
+}
+
+func TestRevokeAuthorization(t *testing.T) {
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if r.Method == "HEAD" {
+ w.Header().Set("Replay-Nonce", "nonce")
+ return
+ }
+ switch r.URL.Path {
+ case "/1":
+ var req struct {
+ Resource string
+ Status string
+ Delete bool
+ }
+ decodeJWSRequest(t, &req, r)
+ if req.Resource != "authz" {
+ t.Errorf("req.Resource = %q; want authz", req.Resource)
+ }
+ if req.Status != "deactivated" {
+ t.Errorf("req.Status = %q; want deactivated", req.Status)
+ }
+ if !req.Delete {
+ t.Errorf("req.Delete is false")
+ }
+ case "/2":
+ w.WriteHeader(http.StatusInternalServerError)
+ }
+ }))
+ defer ts.Close()
+ client := &Client{Key: testKey}
+ ctx := context.Background()
+ if err := client.RevokeAuthorization(ctx, ts.URL+"/1"); err != nil {
+ t.Errorf("err = %v", err)
+ }
+ if client.RevokeAuthorization(ctx, ts.URL+"/2") == nil {
+ t.Error("nil error")
+ }
+}
+
+func TestPollChallenge(t *testing.T) {
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if r.Method != "GET" {
+ t.Errorf("r.Method = %q; want GET", r.Method)
+ }
+
+ w.WriteHeader(http.StatusOK)
+ fmt.Fprintf(w, `{
+ "type":"http-01",
+ "status":"pending",
+ "uri":"https://ca.tld/acme/challenge/publickey/id1",
+ "token":"token1"}`)
+ }))
+ defer ts.Close()
+
+ cl := Client{Key: testKeyEC}
+ chall, err := cl.GetChallenge(context.Background(), ts.URL)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if chall.Status != "pending" {
+ t.Errorf("Status = %q; want pending", chall.Status)
+ }
+ if chall.Type != "http-01" {
+ t.Errorf("c.Type = %q; want http-01", chall.Type)
+ }
+ if chall.URI != "https://ca.tld/acme/challenge/publickey/id1" {
+ t.Errorf("c.URI = %q; want https://ca.tld/acme/challenge/publickey/id1", chall.URI)
+ }
+ if chall.Token != "token1" {
+ t.Errorf("c.Token = %q; want token1", chall.Token)
+ }
+}
+
+func TestAcceptChallenge(t *testing.T) {
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if r.Method == "HEAD" {
+ w.Header().Set("Replay-Nonce", "test-nonce")
+ return
+ }
+ if r.Method != "POST" {
+ t.Errorf("r.Method = %q; want POST", r.Method)
+ }
+
+ var j struct {
+ Resource string
+ Type string
+ Auth string `json:"keyAuthorization"`
+ }
+ decodeJWSRequest(t, &j, r)
+
+ // Test request
+ if j.Resource != "challenge" {
+ t.Errorf(`resource = %q; want "challenge"`, j.Resource)
+ }
+ if j.Type != "http-01" {
+ t.Errorf(`type = %q; want "http-01"`, j.Type)
+ }
+ keyAuth := "token1." + testKeyECThumbprint
+ if j.Auth != keyAuth {
+ t.Errorf(`keyAuthorization = %q; want %q`, j.Auth, keyAuth)
+ }
+
+ // Respond to request
+ w.WriteHeader(http.StatusAccepted)
+ fmt.Fprintf(w, `{
+ "type":"http-01",
+ "status":"pending",
+ "uri":"https://ca.tld/acme/challenge/publickey/id1",
+ "token":"token1",
+ "keyAuthorization":%q
+ }`, keyAuth)
+ }))
+ defer ts.Close()
+
+ cl := Client{Key: testKeyEC}
+ c, err := cl.Accept(context.Background(), &Challenge{
+ URI: ts.URL,
+ Token: "token1",
+ Type: "http-01",
+ })
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if c.Type != "http-01" {
+ t.Errorf("c.Type = %q; want http-01", c.Type)
+ }
+ if c.URI != "https://ca.tld/acme/challenge/publickey/id1" {
+ t.Errorf("c.URI = %q; want https://ca.tld/acme/challenge/publickey/id1", c.URI)
+ }
+ if c.Token != "token1" {
+ t.Errorf("c.Token = %q; want token1", c.Token)
+ }
+}
+
+func TestNewCert(t *testing.T) {
+ notBefore := time.Now()
+ notAfter := notBefore.AddDate(0, 2, 0)
+ timeNow = func() time.Time { return notBefore }
+
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if r.Method == "HEAD" {
+ w.Header().Set("Replay-Nonce", "test-nonce")
+ return
+ }
+ if r.Method != "POST" {
+ t.Errorf("r.Method = %q; want POST", r.Method)
+ }
+
+ var j struct {
+ Resource string `json:"resource"`
+ CSR string `json:"csr"`
+ NotBefore string `json:"notBefore,omitempty"`
+ NotAfter string `json:"notAfter,omitempty"`
+ }
+ decodeJWSRequest(t, &j, r)
+
+ // Test request
+ if j.Resource != "new-cert" {
+ t.Errorf(`resource = %q; want "new-cert"`, j.Resource)
+ }
+ if j.NotBefore != notBefore.Format(time.RFC3339) {
+ t.Errorf(`notBefore = %q; wanted %q`, j.NotBefore, notBefore.Format(time.RFC3339))
+ }
+ if j.NotAfter != notAfter.Format(time.RFC3339) {
+ t.Errorf(`notAfter = %q; wanted %q`, j.NotAfter, notAfter.Format(time.RFC3339))
+ }
+
+ // Respond to request
+ template := x509.Certificate{
+ SerialNumber: big.NewInt(int64(1)),
+ Subject: pkix.Name{
+ Organization: []string{"goacme"},
+ },
+ NotBefore: notBefore,
+ NotAfter: notAfter,
+
+ KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
+ ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
+ BasicConstraintsValid: true,
+ }
+
+ sampleCert, err := x509.CreateCertificate(rand.Reader, &template, &template, &testKeyEC.PublicKey, testKeyEC)
+ if err != nil {
+ t.Fatalf("Error creating certificate: %v", err)
+ }
+
+ w.Header().Set("Location", "https://ca.tld/acme/cert/1")
+ w.WriteHeader(http.StatusCreated)
+ w.Write(sampleCert)
+ }))
+ defer ts.Close()
+
+ csr := x509.CertificateRequest{
+ Version: 0,
+ Subject: pkix.Name{
+ CommonName: "example.com",
+ Organization: []string{"goacme"},
+ },
+ }
+ csrb, err := x509.CreateCertificateRequest(rand.Reader, &csr, testKeyEC)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ c := Client{Key: testKeyEC, dir: &Directory{CertURL: ts.URL}}
+ cert, certURL, err := c.CreateCert(context.Background(), csrb, notAfter.Sub(notBefore), false)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if cert == nil {
+ t.Errorf("cert is nil")
+ }
+ if certURL != "https://ca.tld/acme/cert/1" {
+ t.Errorf("certURL = %q; want https://ca.tld/acme/cert/1", certURL)
+ }
+}
+
+func TestFetchCert(t *testing.T) {
+ var count byte
+ var ts *httptest.Server
+ ts = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ count++
+ if count < 3 {
+ up := fmt.Sprintf("<%s>;rel=up", ts.URL)
+ w.Header().Set("Link", up)
+ }
+ w.Write([]byte{count})
+ }))
+ defer ts.Close()
+ res, err := (&Client{}).FetchCert(context.Background(), ts.URL, true)
+ if err != nil {
+ t.Fatalf("FetchCert: %v", err)
+ }
+ cert := [][]byte{{1}, {2}, {3}}
+ if !reflect.DeepEqual(res, cert) {
+ t.Errorf("res = %v; want %v", res, cert)
+ }
+}
+
+func TestFetchCertRetry(t *testing.T) {
+ var count int
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if count < 1 {
+ w.Header().Set("Retry-After", "0")
+ w.WriteHeader(http.StatusAccepted)
+ count++
+ return
+ }
+ w.Write([]byte{1})
+ }))
+ defer ts.Close()
+ res, err := (&Client{}).FetchCert(context.Background(), ts.URL, false)
+ if err != nil {
+ t.Fatalf("FetchCert: %v", err)
+ }
+ cert := [][]byte{{1}}
+ if !reflect.DeepEqual(res, cert) {
+ t.Errorf("res = %v; want %v", res, cert)
+ }
+}
+
+func TestFetchCertCancel(t *testing.T) {
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Retry-After", "0")
+ w.WriteHeader(http.StatusAccepted)
+ }))
+ defer ts.Close()
+ ctx, cancel := context.WithCancel(context.Background())
+ done := make(chan struct{})
+ var err error
+ go func() {
+ _, err = (&Client{}).FetchCert(ctx, ts.URL, false)
+ close(done)
+ }()
+ cancel()
+ <-done
+ if err != context.Canceled {
+ t.Errorf("err = %v; want %v", err, context.Canceled)
+ }
+}
+
+func TestFetchCertDepth(t *testing.T) {
+ var count byte
+ var ts *httptest.Server
+ ts = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ count++
+ if count > maxChainLen+1 {
+ t.Errorf("count = %d; want at most %d", count, maxChainLen+1)
+ w.WriteHeader(http.StatusInternalServerError)
+ }
+ w.Header().Set("Link", fmt.Sprintf("<%s>;rel=up", ts.URL))
+ w.Write([]byte{count})
+ }))
+ defer ts.Close()
+ _, err := (&Client{}).FetchCert(context.Background(), ts.URL, true)
+ if err == nil {
+ t.Errorf("err is nil")
+ }
+}
+
+func TestFetchCertBreadth(t *testing.T) {
+ var ts *httptest.Server
+ ts = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ for i := 0; i < maxChainLen+1; i++ {
+ w.Header().Add("Link", fmt.Sprintf("<%s>;rel=up", ts.URL))
+ }
+ w.Write([]byte{1})
+ }))
+ defer ts.Close()
+ _, err := (&Client{}).FetchCert(context.Background(), ts.URL, true)
+ if err == nil {
+ t.Errorf("err is nil")
+ }
+}
+
+func TestFetchCertSize(t *testing.T) {
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ b := bytes.Repeat([]byte{1}, maxCertSize+1)
+ w.Write(b)
+ }))
+ defer ts.Close()
+ _, err := (&Client{}).FetchCert(context.Background(), ts.URL, false)
+ if err == nil {
+ t.Errorf("err is nil")
+ }
+}
+
+func TestRevokeCert(t *testing.T) {
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if r.Method == "HEAD" {
+ w.Header().Set("Replay-Nonce", "nonce")
+ return
+ }
+
+ var req struct {
+ Resource string
+ Certificate string
+ Reason int
+ }
+ decodeJWSRequest(t, &req, r)
+ if req.Resource != "revoke-cert" {
+ t.Errorf("req.Resource = %q; want revoke-cert", req.Resource)
+ }
+ if req.Reason != 1 {
+ t.Errorf("req.Reason = %d; want 1", req.Reason)
+ }
+ // echo -n cert | base64 | tr -d '=' | tr '/+' '_-'
+ cert := "Y2VydA"
+ if req.Certificate != cert {
+ t.Errorf("req.Certificate = %q; want %q", req.Certificate, cert)
+ }
+ }))
+ defer ts.Close()
+ client := &Client{
+ Key: testKeyEC,
+ dir: &Directory{RevokeURL: ts.URL},
+ }
+ ctx := context.Background()
+ if err := client.RevokeCert(ctx, nil, []byte("cert"), CRLReasonKeyCompromise); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestNonce_add(t *testing.T) {
+ var c Client
+ c.addNonce(http.Header{"Replay-Nonce": {"nonce"}})
+ c.addNonce(http.Header{"Replay-Nonce": {}})
+ c.addNonce(http.Header{"Replay-Nonce": {"nonce"}})
+
+ nonces := map[string]struct{}{"nonce": struct{}{}}
+ if !reflect.DeepEqual(c.nonces, nonces) {
+ t.Errorf("c.nonces = %q; want %q", c.nonces, nonces)
+ }
+}
+
+func TestNonce_addMax(t *testing.T) {
+ c := &Client{nonces: make(map[string]struct{})}
+ for i := 0; i < maxNonces; i++ {
+ c.nonces[fmt.Sprintf("%d", i)] = struct{}{}
+ }
+ c.addNonce(http.Header{"Replay-Nonce": {"nonce"}})
+ if n := len(c.nonces); n != maxNonces {
+ t.Errorf("len(c.nonces) = %d; want %d", n, maxNonces)
+ }
+}
+
+func TestNonce_fetch(t *testing.T) {
+ tests := []struct {
+ code int
+ nonce string
+ }{
+ {http.StatusOK, "nonce1"},
+ {http.StatusBadRequest, "nonce2"},
+ {http.StatusOK, ""},
+ }
+ var i int
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if r.Method != "HEAD" {
+ t.Errorf("%d: r.Method = %q; want HEAD", i, r.Method)
+ }
+ w.Header().Set("Replay-Nonce", tests[i].nonce)
+ w.WriteHeader(tests[i].code)
+ }))
+ defer ts.Close()
+ for ; i < len(tests); i++ {
+ test := tests[i]
+ c := &Client{}
+ n, err := c.fetchNonce(context.Background(), ts.URL)
+ if n != test.nonce {
+ t.Errorf("%d: n=%q; want %q", i, n, test.nonce)
+ }
+ switch {
+ case err == nil && test.nonce == "":
+ t.Errorf("%d: n=%q, err=%v; want non-nil error", i, n, err)
+ case err != nil && test.nonce != "":
+ t.Errorf("%d: n=%q, err=%v; want %q", i, n, err, test.nonce)
+ }
+ }
+}
+
+func TestNonce_fetchError(t *testing.T) {
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.WriteHeader(http.StatusTooManyRequests)
+ }))
+ defer ts.Close()
+ c := &Client{}
+ _, err := c.fetchNonce(context.Background(), ts.URL)
+ e, ok := err.(*Error)
+ if !ok {
+ t.Fatalf("err is %T; want *Error", err)
+ }
+ if e.StatusCode != http.StatusTooManyRequests {
+ t.Errorf("e.StatusCode = %d; want %d", e.StatusCode, http.StatusTooManyRequests)
+ }
+}
+
+func TestNonce_postJWS(t *testing.T) {
+ var count int
+ seen := make(map[string]bool)
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ count++
+ w.Header().Set("Replay-Nonce", fmt.Sprintf("nonce%d", count))
+ if r.Method == "HEAD" {
+ // We expect the client do a HEAD request
+ // but only to fetch the first nonce.
+ return
+ }
+ // Make client.Authorize happy; we're not testing its result.
+ defer func() {
+ w.WriteHeader(http.StatusCreated)
+ w.Write([]byte(`{"status":"valid"}`))
+ }()
+
+ head, err := decodeJWSHead(r)
+ if err != nil {
+ t.Errorf("decodeJWSHead: %v", err)
+ return
+ }
+ if head.Nonce == "" {
+ t.Error("head.Nonce is empty")
+ return
+ }
+ if seen[head.Nonce] {
+ t.Errorf("nonce is already used: %q", head.Nonce)
+ }
+ seen[head.Nonce] = true
+ }))
+ defer ts.Close()
+
+ client := Client{Key: testKey, dir: &Directory{AuthzURL: ts.URL}}
+ if _, err := client.Authorize(context.Background(), "example.com"); err != nil {
+ t.Errorf("client.Authorize 1: %v", err)
+ }
+ // The second call should not generate another extra HEAD request.
+ if _, err := client.Authorize(context.Background(), "example.com"); err != nil {
+ t.Errorf("client.Authorize 2: %v", err)
+ }
+
+ if count != 3 {
+ t.Errorf("total requests count: %d; want 3", count)
+ }
+ if n := len(client.nonces); n != 1 {
+ t.Errorf("len(client.nonces) = %d; want 1", n)
+ }
+ for k := range seen {
+ if _, exist := client.nonces[k]; exist {
+ t.Errorf("used nonce %q in client.nonces", k)
+ }
+ }
+}
+
+func TestRetryPostJWS(t *testing.T) {
+ var count int
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ count++
+ w.Header().Set("Replay-Nonce", fmt.Sprintf("nonce%d", count))
+ if r.Method == "HEAD" {
+ // We expect the client to do 2 head requests to fetch
+ // nonces, one to start and another after getting badNonce
+ return
+ }
+
+ head, err := decodeJWSHead(r)
+ if err != nil {
+ t.Errorf("decodeJWSHead: %v", err)
+ } else if head.Nonce == "" {
+ t.Error("head.Nonce is empty")
+ } else if head.Nonce == "nonce1" {
+ // return a badNonce error to force the call to retry
+ w.WriteHeader(http.StatusBadRequest)
+ w.Write([]byte(`{"type":"urn:ietf:params:acme:error:badNonce"}`))
+ return
+ }
+ // Make client.Authorize happy; we're not testing its result.
+ w.WriteHeader(http.StatusCreated)
+ w.Write([]byte(`{"status":"valid"}`))
+ }))
+ defer ts.Close()
+
+ client := Client{Key: testKey, dir: &Directory{AuthzURL: ts.URL}}
+ // This call will fail with badNonce, causing a retry
+ if _, err := client.Authorize(context.Background(), "example.com"); err != nil {
+ t.Errorf("client.Authorize 1: %v", err)
+ }
+ if count != 4 {
+ t.Errorf("total requests count: %d; want 4", count)
+ }
+}
+
+func TestLinkHeader(t *testing.T) {
+ h := http.Header{"Link": {
+ `<https://example.com/acme/new-authz>;rel="next"`,
+ `<https://example.com/acme/recover-reg>; rel=recover`,
+ `<https://example.com/acme/terms>; foo=bar; rel="terms-of-service"`,
+ `<dup>;rel="next"`,
+ }}
+ tests := []struct {
+ rel string
+ out []string
+ }{
+ {"next", []string{"https://example.com/acme/new-authz", "dup"}},
+ {"recover", []string{"https://example.com/acme/recover-reg"}},
+ {"terms-of-service", []string{"https://example.com/acme/terms"}},
+ {"empty", nil},
+ }
+ for i, test := range tests {
+ if v := linkHeader(h, test.rel); !reflect.DeepEqual(v, test.out) {
+ t.Errorf("%d: linkHeader(%q): %v; want %v", i, test.rel, v, test.out)
+ }
+ }
+}
+
+func TestErrorResponse(t *testing.T) {
+ s := `{
+ "status": 400,
+ "type": "urn:acme:error:xxx",
+ "detail": "text"
+ }`
+ res := &http.Response{
+ StatusCode: 400,
+ Status: "400 Bad Request",
+ Body: ioutil.NopCloser(strings.NewReader(s)),
+ Header: http.Header{"X-Foo": {"bar"}},
+ }
+ err := responseError(res)
+ v, ok := err.(*Error)
+ if !ok {
+ t.Fatalf("err = %+v (%T); want *Error type", err, err)
+ }
+ if v.StatusCode != 400 {
+ t.Errorf("v.StatusCode = %v; want 400", v.StatusCode)
+ }
+ if v.ProblemType != "urn:acme:error:xxx" {
+ t.Errorf("v.ProblemType = %q; want urn:acme:error:xxx", v.ProblemType)
+ }
+ if v.Detail != "text" {
+ t.Errorf("v.Detail = %q; want text", v.Detail)
+ }
+ if !reflect.DeepEqual(v.Header, res.Header) {
+ t.Errorf("v.Header = %+v; want %+v", v.Header, res.Header)
+ }
+}
+
+func TestTLSSNI01ChallengeCert(t *testing.T) {
+ const (
+ token = "evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA"
+ // echo -n <token.testKeyECThumbprint> | shasum -a 256
+ san = "dbbd5eefe7b4d06eb9d1d9f5acb4c7cd.a27d320e4b30332f0b6cb441734ad7b0.acme.invalid"
+ )
+
+ client := &Client{Key: testKeyEC}
+ tlscert, name, err := client.TLSSNI01ChallengeCert(token)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if n := len(tlscert.Certificate); n != 1 {
+ t.Fatalf("len(tlscert.Certificate) = %d; want 1", n)
+ }
+ cert, err := x509.ParseCertificate(tlscert.Certificate[0])
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(cert.DNSNames) != 1 || cert.DNSNames[0] != san {
+ t.Fatalf("cert.DNSNames = %v; want %q", cert.DNSNames, san)
+ }
+ if cert.DNSNames[0] != name {
+ t.Errorf("cert.DNSNames[0] != name: %q vs %q", cert.DNSNames[0], name)
+ }
+ if cn := cert.Subject.CommonName; cn != san {
+ t.Errorf("cert.Subject.CommonName = %q; want %q", cn, san)
+ }
+}
+
+func TestTLSSNI02ChallengeCert(t *testing.T) {
+ const (
+ token = "evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA"
+ // echo -n evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA | shasum -a 256
+ sanA = "7ea0aaa69214e71e02cebb18bb867736.09b730209baabf60e43d4999979ff139.token.acme.invalid"
+ // echo -n <token.testKeyECThumbprint> | shasum -a 256
+ sanB = "dbbd5eefe7b4d06eb9d1d9f5acb4c7cd.a27d320e4b30332f0b6cb441734ad7b0.ka.acme.invalid"
+ )
+
+ client := &Client{Key: testKeyEC}
+ tlscert, name, err := client.TLSSNI02ChallengeCert(token)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if n := len(tlscert.Certificate); n != 1 {
+ t.Fatalf("len(tlscert.Certificate) = %d; want 1", n)
+ }
+ cert, err := x509.ParseCertificate(tlscert.Certificate[0])
+ if err != nil {
+ t.Fatal(err)
+ }
+ names := []string{sanA, sanB}
+ if !reflect.DeepEqual(cert.DNSNames, names) {
+ t.Fatalf("cert.DNSNames = %v;\nwant %v", cert.DNSNames, names)
+ }
+ sort.Strings(cert.DNSNames)
+ i := sort.SearchStrings(cert.DNSNames, name)
+ if i >= len(cert.DNSNames) || cert.DNSNames[i] != name {
+ t.Errorf("%v doesn't have %q", cert.DNSNames, name)
+ }
+ if cn := cert.Subject.CommonName; cn != sanA {
+ t.Errorf("CommonName = %q; want %q", cn, sanA)
+ }
+}
+
+func TestTLSChallengeCertOpt(t *testing.T) {
+ key, err := rsa.GenerateKey(rand.Reader, 512)
+ if err != nil {
+ t.Fatal(err)
+ }
+ tmpl := &x509.Certificate{
+ SerialNumber: big.NewInt(2),
+ Subject: pkix.Name{Organization: []string{"Test"}},
+ DNSNames: []string{"should-be-overwritten"},
+ }
+ opts := []CertOption{WithKey(key), WithTemplate(tmpl)}
+
+ client := &Client{Key: testKeyEC}
+ cert1, _, err := client.TLSSNI01ChallengeCert("token", opts...)
+ if err != nil {
+ t.Fatal(err)
+ }
+ cert2, _, err := client.TLSSNI02ChallengeCert("token", opts...)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ for i, tlscert := range []tls.Certificate{cert1, cert2} {
+ // verify generated cert private key
+ tlskey, ok := tlscert.PrivateKey.(*rsa.PrivateKey)
+ if !ok {
+ t.Errorf("%d: tlscert.PrivateKey is %T; want *rsa.PrivateKey", i, tlscert.PrivateKey)
+ continue
+ }
+ if tlskey.D.Cmp(key.D) != 0 {
+ t.Errorf("%d: tlskey.D = %v; want %v", i, tlskey.D, key.D)
+ }
+ // verify generated cert public key
+ x509Cert, err := x509.ParseCertificate(tlscert.Certificate[0])
+ if err != nil {
+ t.Errorf("%d: %v", i, err)
+ continue
+ }
+ tlspub, ok := x509Cert.PublicKey.(*rsa.PublicKey)
+ if !ok {
+ t.Errorf("%d: x509Cert.PublicKey is %T; want *rsa.PublicKey", i, x509Cert.PublicKey)
+ continue
+ }
+ if tlspub.N.Cmp(key.N) != 0 {
+ t.Errorf("%d: tlspub.N = %v; want %v", i, tlspub.N, key.N)
+ }
+ // verify template option
+ sn := big.NewInt(2)
+ if x509Cert.SerialNumber.Cmp(sn) != 0 {
+ t.Errorf("%d: SerialNumber = %v; want %v", i, x509Cert.SerialNumber, sn)
+ }
+ org := []string{"Test"}
+ if !reflect.DeepEqual(x509Cert.Subject.Organization, org) {
+ t.Errorf("%d: Subject.Organization = %+v; want %+v", i, x509Cert.Subject.Organization, org)
+ }
+ for _, v := range x509Cert.DNSNames {
+ if !strings.HasSuffix(v, ".acme.invalid") {
+ t.Errorf("%d: invalid DNSNames element: %q", i, v)
+ }
+ }
+ }
+}
+
+func TestHTTP01Challenge(t *testing.T) {
+ const (
+ token = "xxx"
+ // thumbprint is precomputed for testKeyEC in jws_test.go
+ value = token + "." + testKeyECThumbprint
+ urlpath = "/.well-known/acme-challenge/" + token
+ )
+ client := &Client{Key: testKeyEC}
+ val, err := client.HTTP01ChallengeResponse(token)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if val != value {
+ t.Errorf("val = %q; want %q", val, value)
+ }
+ if path := client.HTTP01ChallengePath(token); path != urlpath {
+ t.Errorf("path = %q; want %q", path, urlpath)
+ }
+}
+
+func TestDNS01ChallengeRecord(t *testing.T) {
+ // echo -n xxx.<testKeyECThumbprint> | \
+ // openssl dgst -binary -sha256 | \
+ // base64 | tr -d '=' | tr '/+' '_-'
+ const value = "8DERMexQ5VcdJ_prpPiA0mVdp7imgbCgjsG4SqqNMIo"
+
+ client := &Client{Key: testKeyEC}
+ val, err := client.DNS01ChallengeRecord("xxx")
+ if err != nil {
+ t.Fatal(err)
+ }
+ if val != value {
+ t.Errorf("val = %q; want %q", val, value)
+ }
+}
+
+func TestBackoff(t *testing.T) {
+ tt := []struct{ min, max time.Duration }{
+ {time.Second, 2 * time.Second},
+ {2 * time.Second, 3 * time.Second},
+ {4 * time.Second, 5 * time.Second},
+ {8 * time.Second, 9 * time.Second},
+ }
+ for i, test := range tt {
+ d := backoff(i, time.Minute)
+ if d < test.min || test.max < d {
+ t.Errorf("%d: d = %v; want between %v and %v", i, d, test.min, test.max)
+ }
+ }
+
+ min, max := time.Second, 2*time.Second
+ if d := backoff(-1, time.Minute); d < min || max < d {
+ t.Errorf("d = %v; want between %v and %v", d, min, max)
+ }
+
+ bound := 10 * time.Second
+ if d := backoff(100, bound); d != bound {
+ t.Errorf("d = %v; want %v", d, bound)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/autocert/autocert.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/autocert/autocert.go
new file mode 100644
index 000000000..94edba986
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/autocert/autocert.go
@@ -0,0 +1,821 @@
+// 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.
+
+// Package autocert provides automatic access to certificates from Let's Encrypt
+// and any other ACME-based CA.
+//
+// This package is a work in progress and makes no API stability promises.
+package autocert
+
+import (
+ "bytes"
+ "context"
+ "crypto"
+ "crypto/ecdsa"
+ "crypto/elliptic"
+ "crypto/rand"
+ "crypto/rsa"
+ "crypto/tls"
+ "crypto/x509"
+ "crypto/x509/pkix"
+ "encoding/pem"
+ "errors"
+ "fmt"
+ "io"
+ mathrand "math/rand"
+ "net/http"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+
+ "golang.org/x/crypto/acme"
+)
+
+// createCertRetryAfter is how much time to wait before removing a failed state
+// entry due to an unsuccessful createCert call.
+// This is a variable instead of a const for testing.
+// TODO: Consider making it configurable or an exp backoff?
+var createCertRetryAfter = time.Minute
+
+// pseudoRand is safe for concurrent use.
+var pseudoRand *lockedMathRand
+
+func init() {
+ src := mathrand.NewSource(timeNow().UnixNano())
+ pseudoRand = &lockedMathRand{rnd: mathrand.New(src)}
+}
+
+// AcceptTOS is a Manager.Prompt function that always returns true to
+// indicate acceptance of the CA's Terms of Service during account
+// registration.
+func AcceptTOS(tosURL string) bool { return true }
+
+// HostPolicy specifies which host names the Manager is allowed to respond to.
+// It returns a non-nil error if the host should be rejected.
+// The returned error is accessible via tls.Conn.Handshake and its callers.
+// See Manager's HostPolicy field and GetCertificate method docs for more details.
+type HostPolicy func(ctx context.Context, host string) error
+
+// HostWhitelist returns a policy where only the specified host names are allowed.
+// Only exact matches are currently supported. Subdomains, regexp or wildcard
+// will not match.
+func HostWhitelist(hosts ...string) HostPolicy {
+ whitelist := make(map[string]bool, len(hosts))
+ for _, h := range hosts {
+ whitelist[h] = true
+ }
+ return func(_ context.Context, host string) error {
+ if !whitelist[host] {
+ return errors.New("acme/autocert: host not configured")
+ }
+ return nil
+ }
+}
+
+// defaultHostPolicy is used when Manager.HostPolicy is not set.
+func defaultHostPolicy(context.Context, string) error {
+ return nil
+}
+
+// Manager is a stateful certificate manager built on top of acme.Client.
+// It obtains and refreshes certificates automatically,
+// as well as providing them to a TLS server via tls.Config.
+//
+// You must specify a cache implementation, such as DirCache,
+// to reuse obtained certificates across program restarts.
+// Otherwise your server is very likely to exceed the certificate
+// issuer's request rate limits.
+type Manager struct {
+ // Prompt specifies a callback function to conditionally accept a CA's Terms of Service (TOS).
+ // The registration may require the caller to agree to the CA's TOS.
+ // If so, Manager calls Prompt with a TOS URL provided by the CA. Prompt should report
+ // whether the caller agrees to the terms.
+ //
+ // To always accept the terms, the callers can use AcceptTOS.
+ Prompt func(tosURL string) bool
+
+ // Cache optionally stores and retrieves previously-obtained certificates.
+ // If nil, certs will only be cached for the lifetime of the Manager.
+ //
+ // Manager passes the Cache certificates data encoded in PEM, with private/public
+ // parts combined in a single Cache.Put call, private key first.
+ Cache Cache
+
+ // HostPolicy controls which domains the Manager will attempt
+ // to retrieve new certificates for. It does not affect cached certs.
+ //
+ // If non-nil, HostPolicy is called before requesting a new cert.
+ // If nil, all hosts are currently allowed. This is not recommended,
+ // as it opens a potential attack where clients connect to a server
+ // by IP address and pretend to be asking for an incorrect host name.
+ // Manager will attempt to obtain a certificate for that host, incorrectly,
+ // eventually reaching the CA's rate limit for certificate requests
+ // and making it impossible to obtain actual certificates.
+ //
+ // See GetCertificate for more details.
+ HostPolicy HostPolicy
+
+ // RenewBefore optionally specifies how early certificates should
+ // be renewed before they expire.
+ //
+ // If zero, they're renewed 30 days before expiration.
+ RenewBefore time.Duration
+
+ // Client is used to perform low-level operations, such as account registration
+ // and requesting new certificates.
+ // If Client is nil, a zero-value acme.Client is used with acme.LetsEncryptURL
+ // directory endpoint and a newly-generated ECDSA P-256 key.
+ //
+ // Mutating the field after the first call of GetCertificate method will have no effect.
+ Client *acme.Client
+
+ // Email optionally specifies a contact email address.
+ // This is used by CAs, such as Let's Encrypt, to notify about problems
+ // with issued certificates.
+ //
+ // If the Client's account key is already registered, Email is not used.
+ Email string
+
+ // ForceRSA makes the Manager generate certificates with 2048-bit RSA keys.
+ //
+ // If false, a default is used. Currently the default
+ // is EC-based keys using the P-256 curve.
+ ForceRSA bool
+
+ clientMu sync.Mutex
+ client *acme.Client // initialized by acmeClient method
+
+ stateMu sync.Mutex
+ state map[string]*certState // keyed by domain name
+
+ // tokenCert is keyed by token domain name, which matches server name
+ // of ClientHello. Keys always have ".acme.invalid" suffix.
+ tokenCertMu sync.RWMutex
+ tokenCert map[string]*tls.Certificate
+
+ // renewal tracks the set of domains currently running renewal timers.
+ // It is keyed by domain name.
+ renewalMu sync.Mutex
+ renewal map[string]*domainRenewal
+}
+
+// GetCertificate implements the tls.Config.GetCertificate hook.
+// It provides a TLS certificate for hello.ServerName host, including answering
+// *.acme.invalid (TLS-SNI) challenges. All other fields of hello are ignored.
+//
+// If m.HostPolicy is non-nil, GetCertificate calls the policy before requesting
+// a new cert. A non-nil error returned from m.HostPolicy halts TLS negotiation.
+// The error is propagated back to the caller of GetCertificate and is user-visible.
+// This does not affect cached certs. See HostPolicy field description for more details.
+func (m *Manager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate, error) {
+ if m.Prompt == nil {
+ return nil, errors.New("acme/autocert: Manager.Prompt not set")
+ }
+
+ name := hello.ServerName
+ if name == "" {
+ return nil, errors.New("acme/autocert: missing server name")
+ }
+ if !strings.Contains(strings.Trim(name, "."), ".") {
+ return nil, errors.New("acme/autocert: server name component count invalid")
+ }
+ if strings.ContainsAny(name, `/\`) {
+ return nil, errors.New("acme/autocert: server name contains invalid character")
+ }
+
+ ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
+ defer cancel()
+
+ // check whether this is a token cert requested for TLS-SNI challenge
+ if strings.HasSuffix(name, ".acme.invalid") {
+ m.tokenCertMu.RLock()
+ defer m.tokenCertMu.RUnlock()
+ if cert := m.tokenCert[name]; cert != nil {
+ return cert, nil
+ }
+ if cert, err := m.cacheGet(ctx, name); err == nil {
+ return cert, nil
+ }
+ // TODO: cache error results?
+ return nil, fmt.Errorf("acme/autocert: no token cert for %q", name)
+ }
+
+ // regular domain
+ name = strings.TrimSuffix(name, ".") // golang.org/issue/18114
+ cert, err := m.cert(ctx, name)
+ if err == nil {
+ return cert, nil
+ }
+ if err != ErrCacheMiss {
+ return nil, err
+ }
+
+ // first-time
+ if err := m.hostPolicy()(ctx, name); err != nil {
+ return nil, err
+ }
+ cert, err = m.createCert(ctx, name)
+ if err != nil {
+ return nil, err
+ }
+ m.cachePut(ctx, name, cert)
+ return cert, nil
+}
+
+// cert returns an existing certificate either from m.state or cache.
+// If a certificate is found in cache but not in m.state, the latter will be filled
+// with the cached value.
+func (m *Manager) cert(ctx context.Context, name string) (*tls.Certificate, error) {
+ m.stateMu.Lock()
+ if s, ok := m.state[name]; ok {
+ m.stateMu.Unlock()
+ s.RLock()
+ defer s.RUnlock()
+ return s.tlscert()
+ }
+ defer m.stateMu.Unlock()
+ cert, err := m.cacheGet(ctx, name)
+ if err != nil {
+ return nil, err
+ }
+ signer, ok := cert.PrivateKey.(crypto.Signer)
+ if !ok {
+ return nil, errors.New("acme/autocert: private key cannot sign")
+ }
+ if m.state == nil {
+ m.state = make(map[string]*certState)
+ }
+ s := &certState{
+ key: signer,
+ cert: cert.Certificate,
+ leaf: cert.Leaf,
+ }
+ m.state[name] = s
+ go m.renew(name, s.key, s.leaf.NotAfter)
+ return cert, nil
+}
+
+// cacheGet always returns a valid certificate, or an error otherwise.
+// If a cached certficate exists but is not valid, ErrCacheMiss is returned.
+func (m *Manager) cacheGet(ctx context.Context, domain string) (*tls.Certificate, error) {
+ if m.Cache == nil {
+ return nil, ErrCacheMiss
+ }
+ data, err := m.Cache.Get(ctx, domain)
+ if err != nil {
+ return nil, err
+ }
+
+ // private
+ priv, pub := pem.Decode(data)
+ if priv == nil || !strings.Contains(priv.Type, "PRIVATE") {
+ return nil, ErrCacheMiss
+ }
+ privKey, err := parsePrivateKey(priv.Bytes)
+ if err != nil {
+ return nil, err
+ }
+
+ // public
+ var pubDER [][]byte
+ for len(pub) > 0 {
+ var b *pem.Block
+ b, pub = pem.Decode(pub)
+ if b == nil {
+ break
+ }
+ pubDER = append(pubDER, b.Bytes)
+ }
+ if len(pub) > 0 {
+ // Leftover content not consumed by pem.Decode. Corrupt. Ignore.
+ return nil, ErrCacheMiss
+ }
+
+ // verify and create TLS cert
+ leaf, err := validCert(domain, pubDER, privKey)
+ if err != nil {
+ return nil, ErrCacheMiss
+ }
+ tlscert := &tls.Certificate{
+ Certificate: pubDER,
+ PrivateKey: privKey,
+ Leaf: leaf,
+ }
+ return tlscert, nil
+}
+
+func (m *Manager) cachePut(ctx context.Context, domain string, tlscert *tls.Certificate) error {
+ if m.Cache == nil {
+ return nil
+ }
+
+ // contains PEM-encoded data
+ var buf bytes.Buffer
+
+ // private
+ switch key := tlscert.PrivateKey.(type) {
+ case *ecdsa.PrivateKey:
+ if err := encodeECDSAKey(&buf, key); err != nil {
+ return err
+ }
+ case *rsa.PrivateKey:
+ b := x509.MarshalPKCS1PrivateKey(key)
+ pb := &pem.Block{Type: "RSA PRIVATE KEY", Bytes: b}
+ if err := pem.Encode(&buf, pb); err != nil {
+ return err
+ }
+ default:
+ return errors.New("acme/autocert: unknown private key type")
+ }
+
+ // public
+ for _, b := range tlscert.Certificate {
+ pb := &pem.Block{Type: "CERTIFICATE", Bytes: b}
+ if err := pem.Encode(&buf, pb); err != nil {
+ return err
+ }
+ }
+
+ return m.Cache.Put(ctx, domain, buf.Bytes())
+}
+
+func encodeECDSAKey(w io.Writer, key *ecdsa.PrivateKey) error {
+ b, err := x509.MarshalECPrivateKey(key)
+ if err != nil {
+ return err
+ }
+ pb := &pem.Block{Type: "EC PRIVATE KEY", Bytes: b}
+ return pem.Encode(w, pb)
+}
+
+// createCert starts the domain ownership verification and returns a certificate
+// for that domain upon success.
+//
+// If the domain is already being verified, it waits for the existing verification to complete.
+// Either way, createCert blocks for the duration of the whole process.
+func (m *Manager) createCert(ctx context.Context, domain string) (*tls.Certificate, error) {
+ // TODO: maybe rewrite this whole piece using sync.Once
+ state, err := m.certState(domain)
+ if err != nil {
+ return nil, err
+ }
+ // state may exist if another goroutine is already working on it
+ // in which case just wait for it to finish
+ if !state.locked {
+ state.RLock()
+ defer state.RUnlock()
+ return state.tlscert()
+ }
+
+ // We are the first; state is locked.
+ // Unblock the readers when domain ownership is verified
+ // and we got the cert or the process failed.
+ defer state.Unlock()
+ state.locked = false
+
+ der, leaf, err := m.authorizedCert(ctx, state.key, domain)
+ if err != nil {
+ // Remove the failed state after some time,
+ // making the manager call createCert again on the following TLS hello.
+ time.AfterFunc(createCertRetryAfter, func() {
+ defer testDidRemoveState(domain)
+ m.stateMu.Lock()
+ defer m.stateMu.Unlock()
+ // Verify the state hasn't changed and it's still invalid
+ // before deleting.
+ s, ok := m.state[domain]
+ if !ok {
+ return
+ }
+ if _, err := validCert(domain, s.cert, s.key); err == nil {
+ return
+ }
+ delete(m.state, domain)
+ })
+ return nil, err
+ }
+ state.cert = der
+ state.leaf = leaf
+ go m.renew(domain, state.key, state.leaf.NotAfter)
+ return state.tlscert()
+}
+
+// certState returns a new or existing certState.
+// If a new certState is returned, state.exist is false and the state is locked.
+// The returned error is non-nil only in the case where a new state could not be created.
+func (m *Manager) certState(domain string) (*certState, error) {
+ m.stateMu.Lock()
+ defer m.stateMu.Unlock()
+ if m.state == nil {
+ m.state = make(map[string]*certState)
+ }
+ // existing state
+ if state, ok := m.state[domain]; ok {
+ return state, nil
+ }
+
+ // new locked state
+ var (
+ err error
+ key crypto.Signer
+ )
+ if m.ForceRSA {
+ key, err = rsa.GenerateKey(rand.Reader, 2048)
+ } else {
+ key, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+ }
+ if err != nil {
+ return nil, err
+ }
+
+ state := &certState{
+ key: key,
+ locked: true,
+ }
+ state.Lock() // will be unlocked by m.certState caller
+ m.state[domain] = state
+ return state, nil
+}
+
+// authorizedCert starts the domain ownership verification process and requests a new cert upon success.
+// The key argument is the certificate private key.
+func (m *Manager) authorizedCert(ctx context.Context, key crypto.Signer, domain string) (der [][]byte, leaf *x509.Certificate, err error) {
+ if err := m.verify(ctx, domain); err != nil {
+ return nil, nil, err
+ }
+ client, err := m.acmeClient(ctx)
+ if err != nil {
+ return nil, nil, err
+ }
+ csr, err := certRequest(key, domain)
+ if err != nil {
+ return nil, nil, err
+ }
+ der, _, err = client.CreateCert(ctx, csr, 0, true)
+ if err != nil {
+ return nil, nil, err
+ }
+ leaf, err = validCert(domain, der, key)
+ if err != nil {
+ return nil, nil, err
+ }
+ return der, leaf, nil
+}
+
+// verify starts a new identifier (domain) authorization flow.
+// It prepares a challenge response and then blocks until the authorization
+// is marked as "completed" by the CA (either succeeded or failed).
+//
+// verify returns nil iff the verification was successful.
+func (m *Manager) verify(ctx context.Context, domain string) error {
+ client, err := m.acmeClient(ctx)
+ if err != nil {
+ return err
+ }
+
+ // start domain authorization and get the challenge
+ authz, err := client.Authorize(ctx, domain)
+ if err != nil {
+ return err
+ }
+ // maybe don't need to at all
+ if authz.Status == acme.StatusValid {
+ return nil
+ }
+
+ // pick a challenge: prefer tls-sni-02 over tls-sni-01
+ // TODO: consider authz.Combinations
+ var chal *acme.Challenge
+ for _, c := range authz.Challenges {
+ if c.Type == "tls-sni-02" {
+ chal = c
+ break
+ }
+ if c.Type == "tls-sni-01" {
+ chal = c
+ }
+ }
+ if chal == nil {
+ return errors.New("acme/autocert: no supported challenge type found")
+ }
+
+ // create a token cert for the challenge response
+ var (
+ cert tls.Certificate
+ name string
+ )
+ switch chal.Type {
+ case "tls-sni-01":
+ cert, name, err = client.TLSSNI01ChallengeCert(chal.Token)
+ case "tls-sni-02":
+ cert, name, err = client.TLSSNI02ChallengeCert(chal.Token)
+ default:
+ err = fmt.Errorf("acme/autocert: unknown challenge type %q", chal.Type)
+ }
+ if err != nil {
+ return err
+ }
+ m.putTokenCert(ctx, name, &cert)
+ defer func() {
+ // verification has ended at this point
+ // don't need token cert anymore
+ go m.deleteTokenCert(name)
+ }()
+
+ // ready to fulfill the challenge
+ if _, err := client.Accept(ctx, chal); err != nil {
+ return err
+ }
+ // wait for the CA to validate
+ _, err = client.WaitAuthorization(ctx, authz.URI)
+ return err
+}
+
+// putTokenCert stores the cert under the named key in both m.tokenCert map
+// and m.Cache.
+func (m *Manager) putTokenCert(ctx context.Context, name string, cert *tls.Certificate) {
+ m.tokenCertMu.Lock()
+ defer m.tokenCertMu.Unlock()
+ if m.tokenCert == nil {
+ m.tokenCert = make(map[string]*tls.Certificate)
+ }
+ m.tokenCert[name] = cert
+ m.cachePut(ctx, name, cert)
+}
+
+// deleteTokenCert removes the token certificate for the specified domain name
+// from both m.tokenCert map and m.Cache.
+func (m *Manager) deleteTokenCert(name string) {
+ m.tokenCertMu.Lock()
+ defer m.tokenCertMu.Unlock()
+ delete(m.tokenCert, name)
+ if m.Cache != nil {
+ m.Cache.Delete(context.Background(), name)
+ }
+}
+
+// renew starts a cert renewal timer loop, one per domain.
+//
+// The loop is scheduled in two cases:
+// - a cert was fetched from cache for the first time (wasn't in m.state)
+// - a new cert was created by m.createCert
+//
+// The key argument is a certificate private key.
+// The exp argument is the cert expiration time (NotAfter).
+func (m *Manager) renew(domain string, key crypto.Signer, exp time.Time) {
+ m.renewalMu.Lock()
+ defer m.renewalMu.Unlock()
+ if m.renewal[domain] != nil {
+ // another goroutine is already on it
+ return
+ }
+ if m.renewal == nil {
+ m.renewal = make(map[string]*domainRenewal)
+ }
+ dr := &domainRenewal{m: m, domain: domain, key: key}
+ m.renewal[domain] = dr
+ dr.start(exp)
+}
+
+// stopRenew stops all currently running cert renewal timers.
+// The timers are not restarted during the lifetime of the Manager.
+func (m *Manager) stopRenew() {
+ m.renewalMu.Lock()
+ defer m.renewalMu.Unlock()
+ for name, dr := range m.renewal {
+ delete(m.renewal, name)
+ dr.stop()
+ }
+}
+
+func (m *Manager) accountKey(ctx context.Context) (crypto.Signer, error) {
+ const keyName = "acme_account.key"
+
+ genKey := func() (*ecdsa.PrivateKey, error) {
+ return ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+ }
+
+ if m.Cache == nil {
+ return genKey()
+ }
+
+ data, err := m.Cache.Get(ctx, keyName)
+ if err == ErrCacheMiss {
+ key, err := genKey()
+ if err != nil {
+ return nil, err
+ }
+ var buf bytes.Buffer
+ if err := encodeECDSAKey(&buf, key); err != nil {
+ return nil, err
+ }
+ if err := m.Cache.Put(ctx, keyName, buf.Bytes()); err != nil {
+ return nil, err
+ }
+ return key, nil
+ }
+ if err != nil {
+ return nil, err
+ }
+
+ priv, _ := pem.Decode(data)
+ if priv == nil || !strings.Contains(priv.Type, "PRIVATE") {
+ return nil, errors.New("acme/autocert: invalid account key found in cache")
+ }
+ return parsePrivateKey(priv.Bytes)
+}
+
+func (m *Manager) acmeClient(ctx context.Context) (*acme.Client, error) {
+ m.clientMu.Lock()
+ defer m.clientMu.Unlock()
+ if m.client != nil {
+ return m.client, nil
+ }
+
+ client := m.Client
+ if client == nil {
+ client = &acme.Client{DirectoryURL: acme.LetsEncryptURL}
+ }
+ if client.Key == nil {
+ var err error
+ client.Key, err = m.accountKey(ctx)
+ if err != nil {
+ return nil, err
+ }
+ }
+ var contact []string
+ if m.Email != "" {
+ contact = []string{"mailto:" + m.Email}
+ }
+ a := &acme.Account{Contact: contact}
+ _, err := client.Register(ctx, a, m.Prompt)
+ if ae, ok := err.(*acme.Error); err == nil || ok && ae.StatusCode == http.StatusConflict {
+ // conflict indicates the key is already registered
+ m.client = client
+ err = nil
+ }
+ return m.client, err
+}
+
+func (m *Manager) hostPolicy() HostPolicy {
+ if m.HostPolicy != nil {
+ return m.HostPolicy
+ }
+ return defaultHostPolicy
+}
+
+func (m *Manager) renewBefore() time.Duration {
+ if m.RenewBefore > renewJitter {
+ return m.RenewBefore
+ }
+ return 720 * time.Hour // 30 days
+}
+
+// certState is ready when its mutex is unlocked for reading.
+type certState struct {
+ sync.RWMutex
+ locked bool // locked for read/write
+ key crypto.Signer // private key for cert
+ cert [][]byte // DER encoding
+ leaf *x509.Certificate // parsed cert[0]; always non-nil if cert != nil
+}
+
+// tlscert creates a tls.Certificate from s.key and s.cert.
+// Callers should wrap it in s.RLock() and s.RUnlock().
+func (s *certState) tlscert() (*tls.Certificate, error) {
+ if s.key == nil {
+ return nil, errors.New("acme/autocert: missing signer")
+ }
+ if len(s.cert) == 0 {
+ return nil, errors.New("acme/autocert: missing certificate")
+ }
+ return &tls.Certificate{
+ PrivateKey: s.key,
+ Certificate: s.cert,
+ Leaf: s.leaf,
+ }, nil
+}
+
+// certRequest creates a certificate request for the given common name cn
+// and optional SANs.
+func certRequest(key crypto.Signer, cn string, san ...string) ([]byte, error) {
+ req := &x509.CertificateRequest{
+ Subject: pkix.Name{CommonName: cn},
+ DNSNames: san,
+ }
+ return x509.CreateCertificateRequest(rand.Reader, req, key)
+}
+
+// Attempt to parse the given private key DER block. OpenSSL 0.9.8 generates
+// PKCS#1 private keys by default, while OpenSSL 1.0.0 generates PKCS#8 keys.
+// OpenSSL ecparam generates SEC1 EC private keys for ECDSA. We try all three.
+//
+// Inspired by parsePrivateKey in crypto/tls/tls.go.
+func parsePrivateKey(der []byte) (crypto.Signer, error) {
+ if key, err := x509.ParsePKCS1PrivateKey(der); err == nil {
+ return key, nil
+ }
+ if key, err := x509.ParsePKCS8PrivateKey(der); err == nil {
+ switch key := key.(type) {
+ case *rsa.PrivateKey:
+ return key, nil
+ case *ecdsa.PrivateKey:
+ return key, nil
+ default:
+ return nil, errors.New("acme/autocert: unknown private key type in PKCS#8 wrapping")
+ }
+ }
+ if key, err := x509.ParseECPrivateKey(der); err == nil {
+ return key, nil
+ }
+
+ return nil, errors.New("acme/autocert: failed to parse private key")
+}
+
+// validCert parses a cert chain provided as der argument and verifies the leaf, der[0],
+// corresponds to the private key, as well as the domain match and expiration dates.
+// It doesn't do any revocation checking.
+//
+// The returned value is the verified leaf cert.
+func validCert(domain string, der [][]byte, key crypto.Signer) (leaf *x509.Certificate, err error) {
+ // parse public part(s)
+ var n int
+ for _, b := range der {
+ n += len(b)
+ }
+ pub := make([]byte, n)
+ n = 0
+ for _, b := range der {
+ n += copy(pub[n:], b)
+ }
+ x509Cert, err := x509.ParseCertificates(pub)
+ if len(x509Cert) == 0 {
+ return nil, errors.New("acme/autocert: no public key found")
+ }
+ // verify the leaf is not expired and matches the domain name
+ leaf = x509Cert[0]
+ now := timeNow()
+ if now.Before(leaf.NotBefore) {
+ return nil, errors.New("acme/autocert: certificate is not valid yet")
+ }
+ if now.After(leaf.NotAfter) {
+ return nil, errors.New("acme/autocert: expired certificate")
+ }
+ if err := leaf.VerifyHostname(domain); err != nil {
+ return nil, err
+ }
+ // ensure the leaf corresponds to the private key
+ switch pub := leaf.PublicKey.(type) {
+ case *rsa.PublicKey:
+ prv, ok := key.(*rsa.PrivateKey)
+ if !ok {
+ return nil, errors.New("acme/autocert: private key type does not match public key type")
+ }
+ if pub.N.Cmp(prv.N) != 0 {
+ return nil, errors.New("acme/autocert: private key does not match public key")
+ }
+ case *ecdsa.PublicKey:
+ prv, ok := key.(*ecdsa.PrivateKey)
+ if !ok {
+ return nil, errors.New("acme/autocert: private key type does not match public key type")
+ }
+ if pub.X.Cmp(prv.X) != 0 || pub.Y.Cmp(prv.Y) != 0 {
+ return nil, errors.New("acme/autocert: private key does not match public key")
+ }
+ default:
+ return nil, errors.New("acme/autocert: unknown public key algorithm")
+ }
+ return leaf, nil
+}
+
+func retryAfter(v string) time.Duration {
+ if i, err := strconv.Atoi(v); err == nil {
+ return time.Duration(i) * time.Second
+ }
+ if t, err := http.ParseTime(v); err == nil {
+ return t.Sub(timeNow())
+ }
+ return time.Second
+}
+
+type lockedMathRand struct {
+ sync.Mutex
+ rnd *mathrand.Rand
+}
+
+func (r *lockedMathRand) int63n(max int64) int64 {
+ r.Lock()
+ n := r.rnd.Int63n(max)
+ r.Unlock()
+ return n
+}
+
+// For easier testing.
+var (
+ timeNow = time.Now
+
+ // Called when a state is removed.
+ testDidRemoveState = func(domain string) {}
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/autocert/autocert_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/autocert/autocert_test.go
new file mode 100644
index 000000000..43a62011a
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/autocert/autocert_test.go
@@ -0,0 +1,606 @@
+// 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.
+
+package autocert
+
+import (
+ "context"
+ "crypto"
+ "crypto/ecdsa"
+ "crypto/elliptic"
+ "crypto/rand"
+ "crypto/rsa"
+ "crypto/tls"
+ "crypto/x509"
+ "crypto/x509/pkix"
+ "encoding/base64"
+ "encoding/json"
+ "fmt"
+ "html/template"
+ "io"
+ "math/big"
+ "net/http"
+ "net/http/httptest"
+ "reflect"
+ "sync"
+ "testing"
+ "time"
+
+ "golang.org/x/crypto/acme"
+)
+
+var discoTmpl = template.Must(template.New("disco").Parse(`{
+ "new-reg": "{{.}}/new-reg",
+ "new-authz": "{{.}}/new-authz",
+ "new-cert": "{{.}}/new-cert"
+}`))
+
+var authzTmpl = template.Must(template.New("authz").Parse(`{
+ "status": "pending",
+ "challenges": [
+ {
+ "uri": "{{.}}/challenge/1",
+ "type": "tls-sni-01",
+ "token": "token-01"
+ },
+ {
+ "uri": "{{.}}/challenge/2",
+ "type": "tls-sni-02",
+ "token": "token-02"
+ }
+ ]
+}`))
+
+type memCache struct {
+ mu sync.Mutex
+ keyData map[string][]byte
+}
+
+func (m *memCache) Get(ctx context.Context, key string) ([]byte, error) {
+ m.mu.Lock()
+ defer m.mu.Unlock()
+
+ v, ok := m.keyData[key]
+ if !ok {
+ return nil, ErrCacheMiss
+ }
+ return v, nil
+}
+
+func (m *memCache) Put(ctx context.Context, key string, data []byte) error {
+ m.mu.Lock()
+ defer m.mu.Unlock()
+
+ m.keyData[key] = data
+ return nil
+}
+
+func (m *memCache) Delete(ctx context.Context, key string) error {
+ m.mu.Lock()
+ defer m.mu.Unlock()
+
+ delete(m.keyData, key)
+ return nil
+}
+
+func newMemCache() *memCache {
+ return &memCache{
+ keyData: make(map[string][]byte),
+ }
+}
+
+func dummyCert(pub interface{}, san ...string) ([]byte, error) {
+ return dateDummyCert(pub, time.Now(), time.Now().Add(90*24*time.Hour), san...)
+}
+
+func dateDummyCert(pub interface{}, start, end time.Time, san ...string) ([]byte, error) {
+ // use EC key to run faster on 386
+ key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+ if err != nil {
+ return nil, err
+ }
+ t := &x509.Certificate{
+ SerialNumber: big.NewInt(1),
+ NotBefore: start,
+ NotAfter: end,
+ BasicConstraintsValid: true,
+ KeyUsage: x509.KeyUsageKeyEncipherment,
+ DNSNames: san,
+ }
+ if pub == nil {
+ pub = &key.PublicKey
+ }
+ return x509.CreateCertificate(rand.Reader, t, t, pub, key)
+}
+
+func decodePayload(v interface{}, r io.Reader) error {
+ var req struct{ Payload string }
+ if err := json.NewDecoder(r).Decode(&req); err != nil {
+ return err
+ }
+ payload, err := base64.RawURLEncoding.DecodeString(req.Payload)
+ if err != nil {
+ return err
+ }
+ return json.Unmarshal(payload, v)
+}
+
+func TestGetCertificate(t *testing.T) {
+ man := &Manager{Prompt: AcceptTOS}
+ defer man.stopRenew()
+ hello := &tls.ClientHelloInfo{ServerName: "example.org"}
+ testGetCertificate(t, man, "example.org", hello)
+}
+
+func TestGetCertificate_trailingDot(t *testing.T) {
+ man := &Manager{Prompt: AcceptTOS}
+ defer man.stopRenew()
+ hello := &tls.ClientHelloInfo{ServerName: "example.org."}
+ testGetCertificate(t, man, "example.org", hello)
+}
+
+func TestGetCertificate_ForceRSA(t *testing.T) {
+ man := &Manager{
+ Prompt: AcceptTOS,
+ Cache: newMemCache(),
+ ForceRSA: true,
+ }
+ defer man.stopRenew()
+ hello := &tls.ClientHelloInfo{ServerName: "example.org"}
+ testGetCertificate(t, man, "example.org", hello)
+
+ cert, err := man.cacheGet(context.Background(), "example.org")
+ if err != nil {
+ t.Fatalf("man.cacheGet: %v", err)
+ }
+ if _, ok := cert.PrivateKey.(*rsa.PrivateKey); !ok {
+ t.Errorf("cert.PrivateKey is %T; want *rsa.PrivateKey", cert.PrivateKey)
+ }
+}
+
+func TestGetCertificate_nilPrompt(t *testing.T) {
+ man := &Manager{}
+ defer man.stopRenew()
+ url, finish := startACMEServerStub(t, man, "example.org")
+ defer finish()
+ key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+ if err != nil {
+ t.Fatal(err)
+ }
+ man.Client = &acme.Client{
+ Key: key,
+ DirectoryURL: url,
+ }
+ hello := &tls.ClientHelloInfo{ServerName: "example.org"}
+ if _, err := man.GetCertificate(hello); err == nil {
+ t.Error("got certificate for example.org; wanted error")
+ }
+}
+
+func TestGetCertificate_expiredCache(t *testing.T) {
+ // Make an expired cert and cache it.
+ pk, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+ if err != nil {
+ t.Fatal(err)
+ }
+ tmpl := &x509.Certificate{
+ SerialNumber: big.NewInt(1),
+ Subject: pkix.Name{CommonName: "example.org"},
+ NotAfter: time.Now(),
+ }
+ pub, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, &pk.PublicKey, pk)
+ if err != nil {
+ t.Fatal(err)
+ }
+ tlscert := &tls.Certificate{
+ Certificate: [][]byte{pub},
+ PrivateKey: pk,
+ }
+
+ man := &Manager{Prompt: AcceptTOS, Cache: newMemCache()}
+ defer man.stopRenew()
+ if err := man.cachePut(context.Background(), "example.org", tlscert); err != nil {
+ t.Fatalf("man.cachePut: %v", err)
+ }
+
+ // The expired cached cert should trigger a new cert issuance
+ // and return without an error.
+ hello := &tls.ClientHelloInfo{ServerName: "example.org"}
+ testGetCertificate(t, man, "example.org", hello)
+}
+
+func TestGetCertificate_failedAttempt(t *testing.T) {
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.WriteHeader(http.StatusBadRequest)
+ }))
+ defer ts.Close()
+
+ const example = "example.org"
+ d := createCertRetryAfter
+ f := testDidRemoveState
+ defer func() {
+ createCertRetryAfter = d
+ testDidRemoveState = f
+ }()
+ createCertRetryAfter = 0
+ done := make(chan struct{})
+ testDidRemoveState = func(domain string) {
+ if domain != example {
+ t.Errorf("testDidRemoveState: domain = %q; want %q", domain, example)
+ }
+ close(done)
+ }
+
+ key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+ if err != nil {
+ t.Fatal(err)
+ }
+ man := &Manager{
+ Prompt: AcceptTOS,
+ Client: &acme.Client{
+ Key: key,
+ DirectoryURL: ts.URL,
+ },
+ }
+ defer man.stopRenew()
+ hello := &tls.ClientHelloInfo{ServerName: example}
+ if _, err := man.GetCertificate(hello); err == nil {
+ t.Error("GetCertificate: err is nil")
+ }
+ select {
+ case <-time.After(5 * time.Second):
+ t.Errorf("took too long to remove the %q state", example)
+ case <-done:
+ man.stateMu.Lock()
+ defer man.stateMu.Unlock()
+ if v, exist := man.state[example]; exist {
+ t.Errorf("state exists for %q: %+v", example, v)
+ }
+ }
+}
+
+// startACMEServerStub runs an ACME server
+// The domain argument is the expected domain name of a certificate request.
+func startACMEServerStub(t *testing.T, man *Manager, domain string) (url string, finish func()) {
+ // echo token-02 | shasum -a 256
+ // then divide result in 2 parts separated by dot
+ tokenCertName := "4e8eb87631187e9ff2153b56b13a4dec.13a35d002e485d60ff37354b32f665d9.token.acme.invalid"
+ verifyTokenCert := func() {
+ hello := &tls.ClientHelloInfo{ServerName: tokenCertName}
+ _, err := man.GetCertificate(hello)
+ if err != nil {
+ t.Errorf("verifyTokenCert: GetCertificate(%q): %v", tokenCertName, err)
+ return
+ }
+ }
+
+ // ACME CA server stub
+ var ca *httptest.Server
+ ca = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Replay-Nonce", "nonce")
+ if r.Method == "HEAD" {
+ // a nonce request
+ return
+ }
+
+ switch r.URL.Path {
+ // discovery
+ case "/":
+ if err := discoTmpl.Execute(w, ca.URL); err != nil {
+ t.Errorf("discoTmpl: %v", err)
+ }
+ // client key registration
+ case "/new-reg":
+ w.Write([]byte("{}"))
+ // domain authorization
+ case "/new-authz":
+ w.Header().Set("Location", ca.URL+"/authz/1")
+ w.WriteHeader(http.StatusCreated)
+ if err := authzTmpl.Execute(w, ca.URL); err != nil {
+ t.Errorf("authzTmpl: %v", err)
+ }
+ // accept tls-sni-02 challenge
+ case "/challenge/2":
+ verifyTokenCert()
+ w.Write([]byte("{}"))
+ // authorization status
+ case "/authz/1":
+ w.Write([]byte(`{"status": "valid"}`))
+ // cert request
+ case "/new-cert":
+ var req struct {
+ CSR string `json:"csr"`
+ }
+ decodePayload(&req, r.Body)
+ b, _ := base64.RawURLEncoding.DecodeString(req.CSR)
+ csr, err := x509.ParseCertificateRequest(b)
+ if err != nil {
+ t.Errorf("new-cert: CSR: %v", err)
+ }
+ if csr.Subject.CommonName != domain {
+ t.Errorf("CommonName in CSR = %q; want %q", csr.Subject.CommonName, domain)
+ }
+ der, err := dummyCert(csr.PublicKey, domain)
+ if err != nil {
+ t.Errorf("new-cert: dummyCert: %v", err)
+ }
+ chainUp := fmt.Sprintf("<%s/ca-cert>; rel=up", ca.URL)
+ w.Header().Set("Link", chainUp)
+ w.WriteHeader(http.StatusCreated)
+ w.Write(der)
+ // CA chain cert
+ case "/ca-cert":
+ der, err := dummyCert(nil, "ca")
+ if err != nil {
+ t.Errorf("ca-cert: dummyCert: %v", err)
+ }
+ w.Write(der)
+ default:
+ t.Errorf("unrecognized r.URL.Path: %s", r.URL.Path)
+ }
+ }))
+ finish = func() {
+ ca.Close()
+
+ // make sure token cert was removed
+ cancel := make(chan struct{})
+ done := make(chan struct{})
+ go func() {
+ defer close(done)
+ tick := time.NewTicker(100 * time.Millisecond)
+ defer tick.Stop()
+ for {
+ hello := &tls.ClientHelloInfo{ServerName: tokenCertName}
+ if _, err := man.GetCertificate(hello); err != nil {
+ return
+ }
+ select {
+ case <-tick.C:
+ case <-cancel:
+ return
+ }
+ }
+ }()
+ select {
+ case <-done:
+ case <-time.After(5 * time.Second):
+ close(cancel)
+ t.Error("token cert was not removed")
+ <-done
+ }
+ }
+ return ca.URL, finish
+}
+
+// tests man.GetCertificate flow using the provided hello argument.
+// The domain argument is the expected domain name of a certificate request.
+func testGetCertificate(t *testing.T, man *Manager, domain string, hello *tls.ClientHelloInfo) {
+ url, finish := startACMEServerStub(t, man, domain)
+ defer finish()
+
+ // use EC key to run faster on 386
+ key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+ if err != nil {
+ t.Fatal(err)
+ }
+ man.Client = &acme.Client{
+ Key: key,
+ DirectoryURL: url,
+ }
+
+ // simulate tls.Config.GetCertificate
+ var tlscert *tls.Certificate
+ done := make(chan struct{})
+ go func() {
+ tlscert, err = man.GetCertificate(hello)
+ close(done)
+ }()
+ select {
+ case <-time.After(time.Minute):
+ t.Fatal("man.GetCertificate took too long to return")
+ case <-done:
+ }
+ if err != nil {
+ t.Fatalf("man.GetCertificate: %v", err)
+ }
+
+ // verify the tlscert is the same we responded with from the CA stub
+ if len(tlscert.Certificate) == 0 {
+ t.Fatal("len(tlscert.Certificate) is 0")
+ }
+ cert, err := x509.ParseCertificate(tlscert.Certificate[0])
+ if err != nil {
+ t.Fatalf("x509.ParseCertificate: %v", err)
+ }
+ if len(cert.DNSNames) == 0 || cert.DNSNames[0] != domain {
+ t.Errorf("cert.DNSNames = %v; want %q", cert.DNSNames, domain)
+ }
+
+}
+
+func TestAccountKeyCache(t *testing.T) {
+ m := Manager{Cache: newMemCache()}
+ ctx := context.Background()
+ k1, err := m.accountKey(ctx)
+ if err != nil {
+ t.Fatal(err)
+ }
+ k2, err := m.accountKey(ctx)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !reflect.DeepEqual(k1, k2) {
+ t.Errorf("account keys don't match: k1 = %#v; k2 = %#v", k1, k2)
+ }
+}
+
+func TestCache(t *testing.T) {
+ privKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+ if err != nil {
+ t.Fatal(err)
+ }
+ tmpl := &x509.Certificate{
+ SerialNumber: big.NewInt(1),
+ Subject: pkix.Name{CommonName: "example.org"},
+ NotAfter: time.Now().Add(time.Hour),
+ }
+ pub, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, &privKey.PublicKey, privKey)
+ if err != nil {
+ t.Fatal(err)
+ }
+ tlscert := &tls.Certificate{
+ Certificate: [][]byte{pub},
+ PrivateKey: privKey,
+ }
+
+ man := &Manager{Cache: newMemCache()}
+ defer man.stopRenew()
+ ctx := context.Background()
+ if err := man.cachePut(ctx, "example.org", tlscert); err != nil {
+ t.Fatalf("man.cachePut: %v", err)
+ }
+ res, err := man.cacheGet(ctx, "example.org")
+ if err != nil {
+ t.Fatalf("man.cacheGet: %v", err)
+ }
+ if res == nil {
+ t.Fatal("res is nil")
+ }
+}
+
+func TestHostWhitelist(t *testing.T) {
+ policy := HostWhitelist("example.com", "example.org", "*.example.net")
+ tt := []struct {
+ host string
+ allow bool
+ }{
+ {"example.com", true},
+ {"example.org", true},
+ {"one.example.com", false},
+ {"two.example.org", false},
+ {"three.example.net", false},
+ {"dummy", false},
+ }
+ for i, test := range tt {
+ err := policy(nil, test.host)
+ if err != nil && test.allow {
+ t.Errorf("%d: policy(%q): %v; want nil", i, test.host, err)
+ }
+ if err == nil && !test.allow {
+ t.Errorf("%d: policy(%q): nil; want an error", i, test.host)
+ }
+ }
+}
+
+func TestValidCert(t *testing.T) {
+ key1, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+ if err != nil {
+ t.Fatal(err)
+ }
+ key2, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+ if err != nil {
+ t.Fatal(err)
+ }
+ key3, err := rsa.GenerateKey(rand.Reader, 512)
+ if err != nil {
+ t.Fatal(err)
+ }
+ cert1, err := dummyCert(key1.Public(), "example.org")
+ if err != nil {
+ t.Fatal(err)
+ }
+ cert2, err := dummyCert(key2.Public(), "example.org")
+ if err != nil {
+ t.Fatal(err)
+ }
+ cert3, err := dummyCert(key3.Public(), "example.org")
+ if err != nil {
+ t.Fatal(err)
+ }
+ now := time.Now()
+ early, err := dateDummyCert(key1.Public(), now.Add(time.Hour), now.Add(2*time.Hour), "example.org")
+ if err != nil {
+ t.Fatal(err)
+ }
+ expired, err := dateDummyCert(key1.Public(), now.Add(-2*time.Hour), now.Add(-time.Hour), "example.org")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ tt := []struct {
+ domain string
+ key crypto.Signer
+ cert [][]byte
+ ok bool
+ }{
+ {"example.org", key1, [][]byte{cert1}, true},
+ {"example.org", key3, [][]byte{cert3}, true},
+ {"example.org", key1, [][]byte{cert1, cert2, cert3}, true},
+ {"example.org", key1, [][]byte{cert1, {1}}, false},
+ {"example.org", key1, [][]byte{{1}}, false},
+ {"example.org", key1, [][]byte{cert2}, false},
+ {"example.org", key2, [][]byte{cert1}, false},
+ {"example.org", key1, [][]byte{cert3}, false},
+ {"example.org", key3, [][]byte{cert1}, false},
+ {"example.net", key1, [][]byte{cert1}, false},
+ {"example.org", key1, [][]byte{early}, false},
+ {"example.org", key1, [][]byte{expired}, false},
+ }
+ for i, test := range tt {
+ leaf, err := validCert(test.domain, test.cert, test.key)
+ if err != nil && test.ok {
+ t.Errorf("%d: err = %v", i, err)
+ }
+ if err == nil && !test.ok {
+ t.Errorf("%d: err is nil", i)
+ }
+ if err == nil && test.ok && leaf == nil {
+ t.Errorf("%d: leaf is nil", i)
+ }
+ }
+}
+
+type cacheGetFunc func(ctx context.Context, key string) ([]byte, error)
+
+func (f cacheGetFunc) Get(ctx context.Context, key string) ([]byte, error) {
+ return f(ctx, key)
+}
+
+func (f cacheGetFunc) Put(ctx context.Context, key string, data []byte) error {
+ return fmt.Errorf("unsupported Put of %q = %q", key, data)
+}
+
+func (f cacheGetFunc) Delete(ctx context.Context, key string) error {
+ return fmt.Errorf("unsupported Delete of %q", key)
+}
+
+func TestManagerGetCertificateBogusSNI(t *testing.T) {
+ m := Manager{
+ Prompt: AcceptTOS,
+ Cache: cacheGetFunc(func(ctx context.Context, key string) ([]byte, error) {
+ return nil, fmt.Errorf("cache.Get of %s", key)
+ }),
+ }
+ tests := []struct {
+ name string
+ wantErr string
+ }{
+ {"foo.com", "cache.Get of foo.com"},
+ {"foo.com.", "cache.Get of foo.com"},
+ {`a\b.com`, "acme/autocert: server name contains invalid character"},
+ {`a/b.com`, "acme/autocert: server name contains invalid character"},
+ {"", "acme/autocert: missing server name"},
+ {"foo", "acme/autocert: server name component count invalid"},
+ {".foo", "acme/autocert: server name component count invalid"},
+ {"foo.", "acme/autocert: server name component count invalid"},
+ {"fo.o", "cache.Get of fo.o"},
+ }
+ for _, tt := range tests {
+ _, err := m.GetCertificate(&tls.ClientHelloInfo{ServerName: tt.name})
+ got := fmt.Sprint(err)
+ if got != tt.wantErr {
+ t.Errorf("GetCertificate(SNI = %q) = %q; want %q", tt.name, got, tt.wantErr)
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/autocert/cache.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/autocert/cache.go
new file mode 100644
index 000000000..61a5fd239
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/autocert/cache.go
@@ -0,0 +1,130 @@
+// 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.
+
+package autocert
+
+import (
+ "context"
+ "errors"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+)
+
+// ErrCacheMiss is returned when a certificate is not found in cache.
+var ErrCacheMiss = errors.New("acme/autocert: certificate cache miss")
+
+// Cache is used by Manager to store and retrieve previously obtained certificates
+// as opaque data.
+//
+// The key argument of the methods refers to a domain name but need not be an FQDN.
+// Cache implementations should not rely on the key naming pattern.
+type Cache interface {
+ // Get returns a certificate data for the specified key.
+ // If there's no such key, Get returns ErrCacheMiss.
+ Get(ctx context.Context, key string) ([]byte, error)
+
+ // Put stores the data in the cache under the specified key.
+ // Underlying implementations may use any data storage format,
+ // as long as the reverse operation, Get, results in the original data.
+ Put(ctx context.Context, key string, data []byte) error
+
+ // Delete removes a certificate data from the cache under the specified key.
+ // If there's no such key in the cache, Delete returns nil.
+ Delete(ctx context.Context, key string) error
+}
+
+// DirCache implements Cache using a directory on the local filesystem.
+// If the directory does not exist, it will be created with 0700 permissions.
+type DirCache string
+
+// Get reads a certificate data from the specified file name.
+func (d DirCache) Get(ctx context.Context, name string) ([]byte, error) {
+ name = filepath.Join(string(d), name)
+ var (
+ data []byte
+ err error
+ done = make(chan struct{})
+ )
+ go func() {
+ data, err = ioutil.ReadFile(name)
+ close(done)
+ }()
+ select {
+ case <-ctx.Done():
+ return nil, ctx.Err()
+ case <-done:
+ }
+ if os.IsNotExist(err) {
+ return nil, ErrCacheMiss
+ }
+ return data, err
+}
+
+// Put writes the certificate data to the specified file name.
+// The file will be created with 0600 permissions.
+func (d DirCache) Put(ctx context.Context, name string, data []byte) error {
+ if err := os.MkdirAll(string(d), 0700); err != nil {
+ return err
+ }
+
+ done := make(chan struct{})
+ var err error
+ go func() {
+ defer close(done)
+ var tmp string
+ if tmp, err = d.writeTempFile(name, data); err != nil {
+ return
+ }
+ select {
+ case <-ctx.Done():
+ // Don't overwrite the file if the context was canceled.
+ default:
+ newName := filepath.Join(string(d), name)
+ err = os.Rename(tmp, newName)
+ }
+ }()
+ select {
+ case <-ctx.Done():
+ return ctx.Err()
+ case <-done:
+ }
+ return err
+}
+
+// Delete removes the specified file name.
+func (d DirCache) Delete(ctx context.Context, name string) error {
+ name = filepath.Join(string(d), name)
+ var (
+ err error
+ done = make(chan struct{})
+ )
+ go func() {
+ err = os.Remove(name)
+ close(done)
+ }()
+ select {
+ case <-ctx.Done():
+ return ctx.Err()
+ case <-done:
+ }
+ if err != nil && !os.IsNotExist(err) {
+ return err
+ }
+ return nil
+}
+
+// writeTempFile writes b to a temporary file, closes the file and returns its path.
+func (d DirCache) writeTempFile(prefix string, b []byte) (string, error) {
+ // TempFile uses 0600 permissions
+ f, err := ioutil.TempFile(string(d), prefix)
+ if err != nil {
+ return "", err
+ }
+ if _, err := f.Write(b); err != nil {
+ f.Close()
+ return "", err
+ }
+ return f.Name(), f.Close()
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/autocert/cache_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/autocert/cache_test.go
new file mode 100644
index 000000000..653b05bed
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/autocert/cache_test.go
@@ -0,0 +1,58 @@
+// 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.
+
+package autocert
+
+import (
+ "context"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "reflect"
+ "testing"
+)
+
+// make sure DirCache satisfies Cache interface
+var _ Cache = DirCache("/")
+
+func TestDirCache(t *testing.T) {
+ dir, err := ioutil.TempDir("", "autocert")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.RemoveAll(dir)
+ dir = filepath.Join(dir, "certs") // a nonexistent dir
+ cache := DirCache(dir)
+ ctx := context.Background()
+
+ // test cache miss
+ if _, err := cache.Get(ctx, "nonexistent"); err != ErrCacheMiss {
+ t.Errorf("get: %v; want ErrCacheMiss", err)
+ }
+
+ // test put/get
+ b1 := []byte{1}
+ if err := cache.Put(ctx, "dummy", b1); err != nil {
+ t.Fatalf("put: %v", err)
+ }
+ b2, err := cache.Get(ctx, "dummy")
+ if err != nil {
+ t.Fatalf("get: %v", err)
+ }
+ if !reflect.DeepEqual(b1, b2) {
+ t.Errorf("b1 = %v; want %v", b1, b2)
+ }
+ name := filepath.Join(dir, "dummy")
+ if _, err := os.Stat(name); err != nil {
+ t.Error(err)
+ }
+
+ // test delete
+ if err := cache.Delete(ctx, "dummy"); err != nil {
+ t.Fatalf("delete: %v", err)
+ }
+ if _, err := cache.Get(ctx, "dummy"); err != ErrCacheMiss {
+ t.Errorf("get: %v; want ErrCacheMiss", err)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/autocert/example_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/autocert/example_test.go
new file mode 100644
index 000000000..71d61eb1c
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/autocert/example_test.go
@@ -0,0 +1,35 @@
+// 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 autocert_test
+
+import (
+ "crypto/tls"
+ "fmt"
+ "log"
+ "net/http"
+
+ "golang.org/x/crypto/acme/autocert"
+)
+
+func ExampleNewListener() {
+ mux := http.NewServeMux()
+ mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+ fmt.Fprintf(w, "Hello, TLS user! Your config: %+v", r.TLS)
+ })
+ log.Fatal(http.Serve(autocert.NewListener("example.com"), mux))
+}
+
+func ExampleManager() {
+ m := autocert.Manager{
+ Cache: autocert.DirCache("secret-dir"),
+ Prompt: autocert.AcceptTOS,
+ HostPolicy: autocert.HostWhitelist("example.org"),
+ }
+ s := &http.Server{
+ Addr: ":https",
+ TLSConfig: &tls.Config{GetCertificate: m.GetCertificate},
+ }
+ s.ListenAndServeTLS("", "")
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/autocert/listener.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/autocert/listener.go
new file mode 100644
index 000000000..d744df0ed
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/autocert/listener.go
@@ -0,0 +1,160 @@
+// 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 autocert
+
+import (
+ "crypto/tls"
+ "log"
+ "net"
+ "os"
+ "path/filepath"
+ "runtime"
+ "time"
+)
+
+// NewListener returns a net.Listener that listens on the standard TLS
+// port (443) on all interfaces and returns *tls.Conn connections with
+// LetsEncrypt certificates for the provided domain or domains.
+//
+// It enables one-line HTTPS servers:
+//
+// log.Fatal(http.Serve(autocert.NewListener("example.com"), handler))
+//
+// NewListener is a convenience function for a common configuration.
+// More complex or custom configurations can use the autocert.Manager
+// type instead.
+//
+// Use of this function implies acceptance of the LetsEncrypt Terms of
+// Service. If domains is not empty, the provided domains are passed
+// to HostWhitelist. If domains is empty, the listener will do
+// LetsEncrypt challenges for any requested domain, which is not
+// recommended.
+//
+// Certificates are cached in a "golang-autocert" directory under an
+// operating system-specific cache or temp directory. This may not
+// be suitable for servers spanning multiple machines.
+//
+// The returned listener uses a *tls.Config that enables HTTP/2, and
+// should only be used with servers that support HTTP/2.
+//
+// The returned Listener also enables TCP keep-alives on the accepted
+// connections. The returned *tls.Conn are returned before their TLS
+// handshake has completed.
+func NewListener(domains ...string) net.Listener {
+ m := &Manager{
+ Prompt: AcceptTOS,
+ }
+ if len(domains) > 0 {
+ m.HostPolicy = HostWhitelist(domains...)
+ }
+ dir := cacheDir()
+ if err := os.MkdirAll(dir, 0700); err != nil {
+ log.Printf("warning: autocert.NewListener not using a cache: %v", err)
+ } else {
+ m.Cache = DirCache(dir)
+ }
+ return m.Listener()
+}
+
+// Listener listens on the standard TLS port (443) on all interfaces
+// and returns a net.Listener returning *tls.Conn connections.
+//
+// The returned listener uses a *tls.Config that enables HTTP/2, and
+// should only be used with servers that support HTTP/2.
+//
+// The returned Listener also enables TCP keep-alives on the accepted
+// connections. The returned *tls.Conn are returned before their TLS
+// handshake has completed.
+//
+// Unlike NewListener, it is the caller's responsibility to initialize
+// the Manager m's Prompt, Cache, HostPolicy, and other desired options.
+func (m *Manager) Listener() net.Listener {
+ ln := &listener{
+ m: m,
+ conf: &tls.Config{
+ GetCertificate: m.GetCertificate, // bonus: panic on nil m
+ NextProtos: []string{"h2", "http/1.1"}, // Enable HTTP/2
+ },
+ }
+ ln.tcpListener, ln.tcpListenErr = net.Listen("tcp", ":443")
+ return ln
+}
+
+type listener struct {
+ m *Manager
+ conf *tls.Config
+
+ tcpListener net.Listener
+ tcpListenErr error
+}
+
+func (ln *listener) Accept() (net.Conn, error) {
+ if ln.tcpListenErr != nil {
+ return nil, ln.tcpListenErr
+ }
+ conn, err := ln.tcpListener.Accept()
+ if err != nil {
+ return nil, err
+ }
+ tcpConn := conn.(*net.TCPConn)
+
+ // Because Listener is a convenience function, help out with
+ // this too. This is not possible for the caller to set once
+ // we return a *tcp.Conn wrapping an inaccessible net.Conn.
+ // If callers don't want this, they can do things the manual
+ // way and tweak as needed. But this is what net/http does
+ // itself, so copy that. If net/http changes, we can change
+ // here too.
+ tcpConn.SetKeepAlive(true)
+ tcpConn.SetKeepAlivePeriod(3 * time.Minute)
+
+ return tls.Server(tcpConn, ln.conf), nil
+}
+
+func (ln *listener) Addr() net.Addr {
+ if ln.tcpListener != nil {
+ return ln.tcpListener.Addr()
+ }
+ // net.Listen failed. Return something non-nil in case callers
+ // call Addr before Accept:
+ return &net.TCPAddr{IP: net.IP{0, 0, 0, 0}, Port: 443}
+}
+
+func (ln *listener) Close() error {
+ if ln.tcpListenErr != nil {
+ return ln.tcpListenErr
+ }
+ return ln.tcpListener.Close()
+}
+
+func homeDir() string {
+ if runtime.GOOS == "windows" {
+ return os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
+ }
+ if h := os.Getenv("HOME"); h != "" {
+ return h
+ }
+ return "/"
+}
+
+func cacheDir() string {
+ const base = "golang-autocert"
+ switch runtime.GOOS {
+ case "darwin":
+ return filepath.Join(homeDir(), "Library", "Caches", base)
+ case "windows":
+ for _, ev := range []string{"APPDATA", "CSIDL_APPDATA", "TEMP", "TMP"} {
+ if v := os.Getenv(ev); v != "" {
+ return filepath.Join(v, base)
+ }
+ }
+ // Worst case:
+ return filepath.Join(homeDir(), base)
+ }
+ if xdg := os.Getenv("XDG_CACHE_HOME"); xdg != "" {
+ return filepath.Join(xdg, base)
+ }
+ return filepath.Join(homeDir(), ".cache", base)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/autocert/renewal.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/autocert/renewal.go
new file mode 100644
index 000000000..6c5da2bc8
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/autocert/renewal.go
@@ -0,0 +1,124 @@
+// 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.
+
+package autocert
+
+import (
+ "context"
+ "crypto"
+ "sync"
+ "time"
+)
+
+// renewJitter is the maximum deviation from Manager.RenewBefore.
+const renewJitter = time.Hour
+
+// domainRenewal tracks the state used by the periodic timers
+// renewing a single domain's cert.
+type domainRenewal struct {
+ m *Manager
+ domain string
+ key crypto.Signer
+
+ timerMu sync.Mutex
+ timer *time.Timer
+}
+
+// start starts a cert renewal timer at the time
+// defined by the certificate expiration time exp.
+//
+// If the timer is already started, calling start is a noop.
+func (dr *domainRenewal) start(exp time.Time) {
+ dr.timerMu.Lock()
+ defer dr.timerMu.Unlock()
+ if dr.timer != nil {
+ return
+ }
+ dr.timer = time.AfterFunc(dr.next(exp), dr.renew)
+}
+
+// stop stops the cert renewal timer.
+// If the timer is already stopped, calling stop is a noop.
+func (dr *domainRenewal) stop() {
+ dr.timerMu.Lock()
+ defer dr.timerMu.Unlock()
+ if dr.timer == nil {
+ return
+ }
+ dr.timer.Stop()
+ dr.timer = nil
+}
+
+// renew is called periodically by a timer.
+// The first renew call is kicked off by dr.start.
+func (dr *domainRenewal) renew() {
+ dr.timerMu.Lock()
+ defer dr.timerMu.Unlock()
+ if dr.timer == nil {
+ return
+ }
+
+ ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
+ defer cancel()
+ // TODO: rotate dr.key at some point?
+ next, err := dr.do(ctx)
+ if err != nil {
+ next = renewJitter / 2
+ next += time.Duration(pseudoRand.int63n(int64(next)))
+ }
+ dr.timer = time.AfterFunc(next, dr.renew)
+ testDidRenewLoop(next, err)
+}
+
+// do is similar to Manager.createCert but it doesn't lock a Manager.state item.
+// Instead, it requests a new certificate independently and, upon success,
+// replaces dr.m.state item with a new one and updates cache for the given domain.
+//
+// It may return immediately if the expiration date of the currently cached cert
+// is far enough in the future.
+//
+// The returned value is a time interval after which the renewal should occur again.
+func (dr *domainRenewal) do(ctx context.Context) (time.Duration, error) {
+ // a race is likely unavoidable in a distributed environment
+ // but we try nonetheless
+ if tlscert, err := dr.m.cacheGet(ctx, dr.domain); err == nil {
+ next := dr.next(tlscert.Leaf.NotAfter)
+ if next > dr.m.renewBefore()+renewJitter {
+ return next, nil
+ }
+ }
+
+ der, leaf, err := dr.m.authorizedCert(ctx, dr.key, dr.domain)
+ if err != nil {
+ return 0, err
+ }
+ state := &certState{
+ key: dr.key,
+ cert: der,
+ leaf: leaf,
+ }
+ tlscert, err := state.tlscert()
+ if err != nil {
+ return 0, err
+ }
+ dr.m.cachePut(ctx, dr.domain, tlscert)
+ dr.m.stateMu.Lock()
+ defer dr.m.stateMu.Unlock()
+ // m.state is guaranteed to be non-nil at this point
+ dr.m.state[dr.domain] = state
+ return dr.next(leaf.NotAfter), nil
+}
+
+func (dr *domainRenewal) next(expiry time.Time) time.Duration {
+ d := expiry.Sub(timeNow()) - dr.m.renewBefore()
+ // add a bit of randomness to renew deadline
+ n := pseudoRand.int63n(int64(renewJitter))
+ d -= time.Duration(n)
+ if d < 0 {
+ return 0
+ }
+ return d
+}
+
+var testDidRenewLoop = func(next time.Duration, err error) {}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/autocert/renewal_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/autocert/renewal_test.go
new file mode 100644
index 000000000..11d40ff5d
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/autocert/renewal_test.go
@@ -0,0 +1,191 @@
+// 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.
+
+package autocert
+
+import (
+ "context"
+ "crypto/ecdsa"
+ "crypto/elliptic"
+ "crypto/rand"
+ "crypto/tls"
+ "crypto/x509"
+ "encoding/base64"
+ "fmt"
+ "net/http"
+ "net/http/httptest"
+ "testing"
+ "time"
+
+ "golang.org/x/crypto/acme"
+)
+
+func TestRenewalNext(t *testing.T) {
+ now := time.Now()
+ timeNow = func() time.Time { return now }
+ defer func() { timeNow = time.Now }()
+
+ man := &Manager{RenewBefore: 7 * 24 * time.Hour}
+ defer man.stopRenew()
+ tt := []struct {
+ expiry time.Time
+ min, max time.Duration
+ }{
+ {now.Add(90 * 24 * time.Hour), 83*24*time.Hour - renewJitter, 83 * 24 * time.Hour},
+ {now.Add(time.Hour), 0, 1},
+ {now, 0, 1},
+ {now.Add(-time.Hour), 0, 1},
+ }
+
+ dr := &domainRenewal{m: man}
+ for i, test := range tt {
+ next := dr.next(test.expiry)
+ if next < test.min || test.max < next {
+ t.Errorf("%d: next = %v; want between %v and %v", i, next, test.min, test.max)
+ }
+ }
+}
+
+func TestRenewFromCache(t *testing.T) {
+ const domain = "example.org"
+
+ // ACME CA server stub
+ var ca *httptest.Server
+ ca = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Replay-Nonce", "nonce")
+ if r.Method == "HEAD" {
+ // a nonce request
+ return
+ }
+
+ switch r.URL.Path {
+ // discovery
+ case "/":
+ if err := discoTmpl.Execute(w, ca.URL); err != nil {
+ t.Fatalf("discoTmpl: %v", err)
+ }
+ // client key registration
+ case "/new-reg":
+ w.Write([]byte("{}"))
+ // domain authorization
+ case "/new-authz":
+ w.Header().Set("Location", ca.URL+"/authz/1")
+ w.WriteHeader(http.StatusCreated)
+ w.Write([]byte(`{"status": "valid"}`))
+ // cert request
+ case "/new-cert":
+ var req struct {
+ CSR string `json:"csr"`
+ }
+ decodePayload(&req, r.Body)
+ b, _ := base64.RawURLEncoding.DecodeString(req.CSR)
+ csr, err := x509.ParseCertificateRequest(b)
+ if err != nil {
+ t.Fatalf("new-cert: CSR: %v", err)
+ }
+ der, err := dummyCert(csr.PublicKey, domain)
+ if err != nil {
+ t.Fatalf("new-cert: dummyCert: %v", err)
+ }
+ chainUp := fmt.Sprintf("<%s/ca-cert>; rel=up", ca.URL)
+ w.Header().Set("Link", chainUp)
+ w.WriteHeader(http.StatusCreated)
+ w.Write(der)
+ // CA chain cert
+ case "/ca-cert":
+ der, err := dummyCert(nil, "ca")
+ if err != nil {
+ t.Fatalf("ca-cert: dummyCert: %v", err)
+ }
+ w.Write(der)
+ default:
+ t.Errorf("unrecognized r.URL.Path: %s", r.URL.Path)
+ }
+ }))
+ defer ca.Close()
+
+ // use EC key to run faster on 386
+ key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+ if err != nil {
+ t.Fatal(err)
+ }
+ man := &Manager{
+ Prompt: AcceptTOS,
+ Cache: newMemCache(),
+ RenewBefore: 24 * time.Hour,
+ Client: &acme.Client{
+ Key: key,
+ DirectoryURL: ca.URL,
+ },
+ }
+ defer man.stopRenew()
+
+ // cache an almost expired cert
+ now := time.Now()
+ cert, err := dateDummyCert(key.Public(), now.Add(-2*time.Hour), now.Add(time.Minute), domain)
+ if err != nil {
+ t.Fatal(err)
+ }
+ tlscert := &tls.Certificate{PrivateKey: key, Certificate: [][]byte{cert}}
+ if err := man.cachePut(context.Background(), domain, tlscert); err != nil {
+ t.Fatal(err)
+ }
+
+ // veriy the renewal happened
+ defer func() {
+ testDidRenewLoop = func(next time.Duration, err error) {}
+ }()
+ done := make(chan struct{})
+ testDidRenewLoop = func(next time.Duration, err error) {
+ defer close(done)
+ if err != nil {
+ t.Errorf("testDidRenewLoop: %v", err)
+ }
+ // Next should be about 90 days:
+ // dummyCert creates 90days expiry + account for man.RenewBefore.
+ // Previous expiration was within 1 min.
+ future := 88 * 24 * time.Hour
+ if next < future {
+ t.Errorf("testDidRenewLoop: next = %v; want >= %v", next, future)
+ }
+
+ // ensure the new cert is cached
+ after := time.Now().Add(future)
+ tlscert, err := man.cacheGet(context.Background(), domain)
+ if err != nil {
+ t.Fatalf("man.cacheGet: %v", err)
+ }
+ if !tlscert.Leaf.NotAfter.After(after) {
+ t.Errorf("cache leaf.NotAfter = %v; want > %v", tlscert.Leaf.NotAfter, after)
+ }
+
+ // verify the old cert is also replaced in memory
+ man.stateMu.Lock()
+ defer man.stateMu.Unlock()
+ s := man.state[domain]
+ if s == nil {
+ t.Fatalf("m.state[%q] is nil", domain)
+ }
+ tlscert, err = s.tlscert()
+ if err != nil {
+ t.Fatalf("s.tlscert: %v", err)
+ }
+ if !tlscert.Leaf.NotAfter.After(after) {
+ t.Errorf("state leaf.NotAfter = %v; want > %v", tlscert.Leaf.NotAfter, after)
+ }
+ }
+
+ // trigger renew
+ hello := &tls.ClientHelloInfo{ServerName: domain}
+ if _, err := man.GetCertificate(hello); err != nil {
+ t.Fatal(err)
+ }
+
+ // wait for renew loop
+ select {
+ case <-time.After(10 * time.Second):
+ t.Fatal("renew took too long to occur")
+ case <-done:
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/jws.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/jws.go
new file mode 100644
index 000000000..6cbca25de
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/jws.go
@@ -0,0 +1,153 @@
+// Copyright 2015 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 acme
+
+import (
+ "crypto"
+ "crypto/ecdsa"
+ "crypto/rand"
+ "crypto/rsa"
+ "crypto/sha256"
+ _ "crypto/sha512" // need for EC keys
+ "encoding/base64"
+ "encoding/json"
+ "fmt"
+ "math/big"
+)
+
+// jwsEncodeJSON signs claimset using provided key and a nonce.
+// The result is serialized in JSON format.
+// See https://tools.ietf.org/html/rfc7515#section-7.
+func jwsEncodeJSON(claimset interface{}, key crypto.Signer, nonce string) ([]byte, error) {
+ jwk, err := jwkEncode(key.Public())
+ if err != nil {
+ return nil, err
+ }
+ alg, sha := jwsHasher(key)
+ if alg == "" || !sha.Available() {
+ return nil, ErrUnsupportedKey
+ }
+ phead := fmt.Sprintf(`{"alg":%q,"jwk":%s,"nonce":%q}`, alg, jwk, nonce)
+ phead = base64.RawURLEncoding.EncodeToString([]byte(phead))
+ cs, err := json.Marshal(claimset)
+ if err != nil {
+ return nil, err
+ }
+ payload := base64.RawURLEncoding.EncodeToString(cs)
+ hash := sha.New()
+ hash.Write([]byte(phead + "." + payload))
+ sig, err := jwsSign(key, sha, hash.Sum(nil))
+ if err != nil {
+ return nil, err
+ }
+
+ enc := struct {
+ Protected string `json:"protected"`
+ Payload string `json:"payload"`
+ Sig string `json:"signature"`
+ }{
+ Protected: phead,
+ Payload: payload,
+ Sig: base64.RawURLEncoding.EncodeToString(sig),
+ }
+ return json.Marshal(&enc)
+}
+
+// jwkEncode encodes public part of an RSA or ECDSA key into a JWK.
+// The result is also suitable for creating a JWK thumbprint.
+// https://tools.ietf.org/html/rfc7517
+func jwkEncode(pub crypto.PublicKey) (string, error) {
+ switch pub := pub.(type) {
+ case *rsa.PublicKey:
+ // https://tools.ietf.org/html/rfc7518#section-6.3.1
+ n := pub.N
+ e := big.NewInt(int64(pub.E))
+ // Field order is important.
+ // See https://tools.ietf.org/html/rfc7638#section-3.3 for details.
+ return fmt.Sprintf(`{"e":"%s","kty":"RSA","n":"%s"}`,
+ base64.RawURLEncoding.EncodeToString(e.Bytes()),
+ base64.RawURLEncoding.EncodeToString(n.Bytes()),
+ ), nil
+ case *ecdsa.PublicKey:
+ // https://tools.ietf.org/html/rfc7518#section-6.2.1
+ p := pub.Curve.Params()
+ n := p.BitSize / 8
+ if p.BitSize%8 != 0 {
+ n++
+ }
+ x := pub.X.Bytes()
+ if n > len(x) {
+ x = append(make([]byte, n-len(x)), x...)
+ }
+ y := pub.Y.Bytes()
+ if n > len(y) {
+ y = append(make([]byte, n-len(y)), y...)
+ }
+ // Field order is important.
+ // See https://tools.ietf.org/html/rfc7638#section-3.3 for details.
+ return fmt.Sprintf(`{"crv":"%s","kty":"EC","x":"%s","y":"%s"}`,
+ p.Name,
+ base64.RawURLEncoding.EncodeToString(x),
+ base64.RawURLEncoding.EncodeToString(y),
+ ), nil
+ }
+ return "", ErrUnsupportedKey
+}
+
+// jwsSign signs the digest using the given key.
+// It returns ErrUnsupportedKey if the key type is unknown.
+// The hash is used only for RSA keys.
+func jwsSign(key crypto.Signer, hash crypto.Hash, digest []byte) ([]byte, error) {
+ switch key := key.(type) {
+ case *rsa.PrivateKey:
+ return key.Sign(rand.Reader, digest, hash)
+ case *ecdsa.PrivateKey:
+ r, s, err := ecdsa.Sign(rand.Reader, key, digest)
+ if err != nil {
+ return nil, err
+ }
+ rb, sb := r.Bytes(), s.Bytes()
+ size := key.Params().BitSize / 8
+ if size%8 > 0 {
+ size++
+ }
+ sig := make([]byte, size*2)
+ copy(sig[size-len(rb):], rb)
+ copy(sig[size*2-len(sb):], sb)
+ return sig, nil
+ }
+ return nil, ErrUnsupportedKey
+}
+
+// jwsHasher indicates suitable JWS algorithm name and a hash function
+// to use for signing a digest with the provided key.
+// It returns ("", 0) if the key is not supported.
+func jwsHasher(key crypto.Signer) (string, crypto.Hash) {
+ switch key := key.(type) {
+ case *rsa.PrivateKey:
+ return "RS256", crypto.SHA256
+ case *ecdsa.PrivateKey:
+ switch key.Params().Name {
+ case "P-256":
+ return "ES256", crypto.SHA256
+ case "P-384":
+ return "ES384", crypto.SHA384
+ case "P-521":
+ return "ES512", crypto.SHA512
+ }
+ }
+ return "", 0
+}
+
+// JWKThumbprint creates a JWK thumbprint out of pub
+// as specified in https://tools.ietf.org/html/rfc7638.
+func JWKThumbprint(pub crypto.PublicKey) (string, error) {
+ jwk, err := jwkEncode(pub)
+ if err != nil {
+ return "", err
+ }
+ b := sha256.Sum256([]byte(jwk))
+ return base64.RawURLEncoding.EncodeToString(b[:]), nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/jws_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/jws_test.go
new file mode 100644
index 000000000..0ff0fb5a3
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/jws_test.go
@@ -0,0 +1,319 @@
+// Copyright 2015 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 acme
+
+import (
+ "crypto/ecdsa"
+ "crypto/elliptic"
+ "crypto/rsa"
+ "crypto/x509"
+ "encoding/base64"
+ "encoding/json"
+ "encoding/pem"
+ "fmt"
+ "math/big"
+ "testing"
+)
+
+const (
+ testKeyPEM = `
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEA4xgZ3eRPkwoRvy7qeRUbmMDe0V+xH9eWLdu0iheeLlrmD2mq
+WXfP9IeSKApbn34g8TuAS9g5zhq8ELQ3kmjr+KV86GAMgI6VAcGlq3QrzpTCf/30
+Ab7+zawrfRaFONa1HwEzPY1KHnGVkxJc85gNkwYI9SY2RHXtvln3zs5wITNrdosq
+EXeaIkVYBEhbhNu54pp3kxo6TuWLi9e6pXeWetEwmlBwtWZlPoib2j3TxLBksKZf
+oyFyek380mHgJAumQ/I2fjj98/97mk3ihOY4AgVdCDj1z/GCoZkG5Rq7nbCGyosy
+KWyDX00Zs+nNqVhoLeIvXC4nnWdJMZ6rogxyQQIDAQABAoIBACIEZTOI1Kao9nmV
+9IeIsuaR1Y61b9neOF/MLmIVIZu+AAJFCMB4Iw11FV6sFodwpEyeZhx2WkpWVN+H
+r19eGiLX3zsL0DOdqBJoSIHDWCCMxgnYJ6nvS0nRxX3qVrBp8R2g12Ub+gNPbmFm
+ecf/eeERIVxfifd9VsyRu34eDEvcmKFuLYbElFcPh62xE3x12UZvV/sN7gXbawpP
+G+w255vbE5MoaKdnnO83cTFlcHvhn24M/78qP7Te5OAeelr1R89kYxQLpuGe4fbS
+zc6E3ym5Td6urDetGGrSY1Eu10/8sMusX+KNWkm+RsBRbkyKq72ks/qKpOxOa+c6
+9gm+Y8ECgYEA/iNUyg1ubRdH11p82l8KHtFC1DPE0V1gSZsX29TpM5jS4qv46K+s
+8Ym1zmrORM8x+cynfPx1VQZQ34EYeCMIX212ryJ+zDATl4NE0I4muMvSiH9vx6Xc
+7FmhNnaYzPsBL5Tm9nmtQuP09YEn8poiOJFiDs/4olnD5ogA5O4THGkCgYEA5MIL
+qWYBUuqbEWLRtMruUtpASclrBqNNsJEsMGbeqBJmoMxdHeSZckbLOrqm7GlMyNRJ
+Ne/5uWRGSzaMYuGmwsPpERzqEvYFnSrpjW5YtXZ+JtxFXNVfm9Z1gLLgvGpOUCIU
+RbpoDckDe1vgUuk3y5+DjZihs+rqIJ45XzXTzBkCgYBWuf3segruJZy5rEKhTv+o
+JqeUvRn0jNYYKFpLBeyTVBrbie6GkbUGNIWbrK05pC+c3K9nosvzuRUOQQL1tJbd
+4gA3oiD9U4bMFNr+BRTHyZ7OQBcIXdz3t1qhuHVKtnngIAN1p25uPlbRFUNpshnt
+jgeVoHlsBhApcs5DUc+pyQKBgDzeHPg/+g4z+nrPznjKnktRY1W+0El93kgi+J0Q
+YiJacxBKEGTJ1MKBb8X6sDurcRDm22wMpGfd9I5Cv2v4GsUsF7HD/cx5xdih+G73
+c4clNj/k0Ff5Nm1izPUno4C+0IOl7br39IPmfpSuR6wH/h6iHQDqIeybjxyKvT1G
+N0rRAoGBAKGD+4ZI/E1MoJ5CXB8cDDMHagbE3cq/DtmYzE2v1DFpQYu5I4PCm5c7
+EQeIP6dZtv8IMgtGIb91QX9pXvP0aznzQKwYIA8nZgoENCPfiMTPiEDT9e/0lObO
+9XWsXpbSTsRPj0sv1rB+UzBJ0PgjK4q2zOF0sNo7b1+6nlM3BWPx
+-----END RSA PRIVATE KEY-----
+`
+
+ // This thumbprint is for the testKey defined above.
+ testKeyThumbprint = "6nicxzh6WETQlrvdchkz-U3e3DOQZ4heJKU63rfqMqQ"
+
+ // openssl ecparam -name secp256k1 -genkey -noout
+ testKeyECPEM = `
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIK07hGLr0RwyUdYJ8wbIiBS55CjnkMD23DWr+ccnypWLoAoGCCqGSM49
+AwEHoUQDQgAE5lhEug5xK4xBDZ2nAbaxLtaLiv85bxJ7ePd1dkO23HThqIrvawF5
+QAaS/RNouybCiRhRjI3EaxLkQwgrCw0gqQ==
+-----END EC PRIVATE KEY-----
+`
+ // openssl ecparam -name secp384r1 -genkey -noout
+ testKeyEC384PEM = `
+-----BEGIN EC PRIVATE KEY-----
+MIGkAgEBBDAQ4lNtXRORWr1bgKR1CGysr9AJ9SyEk4jiVnlUWWUChmSNL+i9SLSD
+Oe/naPqXJ6CgBwYFK4EEACKhZANiAAQzKtj+Ms0vHoTX5dzv3/L5YMXOWuI5UKRj
+JigpahYCqXD2BA1j0E/2xt5vlPf+gm0PL+UHSQsCokGnIGuaHCsJAp3ry0gHQEke
+WYXapUUFdvaK1R2/2hn5O+eiQM8YzCg=
+-----END EC PRIVATE KEY-----
+`
+ // openssl ecparam -name secp521r1 -genkey -noout
+ testKeyEC512PEM = `
+-----BEGIN EC PRIVATE KEY-----
+MIHcAgEBBEIBSNZKFcWzXzB/aJClAb305ibalKgtDA7+70eEkdPt28/3LZMM935Z
+KqYHh/COcxuu3Kt8azRAUz3gyr4zZKhlKUSgBwYFK4EEACOhgYkDgYYABAHUNKbx
+7JwC7H6pa2sV0tERWhHhB3JmW+OP6SUgMWryvIKajlx73eS24dy4QPGrWO9/ABsD
+FqcRSkNVTXnIv6+0mAF25knqIBIg5Q8M9BnOu9GGAchcwt3O7RDHmqewnJJDrbjd
+GGnm6rb+NnWR9DIopM0nKNkToWoF/hzopxu4Ae/GsQ==
+-----END EC PRIVATE KEY-----
+`
+ // 1. openssl ec -in key.pem -noout -text
+ // 2. remove first byte, 04 (the header); the rest is X and Y
+ // 3. convert each with: echo <val> | xxd -r -p | base64 -w 100 | tr -d '=' | tr '/+' '_-'
+ testKeyECPubX = "5lhEug5xK4xBDZ2nAbaxLtaLiv85bxJ7ePd1dkO23HQ"
+ testKeyECPubY = "4aiK72sBeUAGkv0TaLsmwokYUYyNxGsS5EMIKwsNIKk"
+ testKeyEC384PubX = "MyrY_jLNLx6E1-Xc79_y-WDFzlriOVCkYyYoKWoWAqlw9gQNY9BP9sbeb5T3_oJt"
+ testKeyEC384PubY = "Dy_lB0kLAqJBpyBrmhwrCQKd68tIB0BJHlmF2qVFBXb2itUdv9oZ-TvnokDPGMwo"
+ testKeyEC512PubX = "AdQ0pvHsnALsfqlraxXS0RFaEeEHcmZb44_pJSAxavK8gpqOXHvd5Lbh3LhA8atY738AGwMWpxFKQ1VNeci_r7SY"
+ testKeyEC512PubY = "AXbmSeogEiDlDwz0Gc670YYByFzC3c7tEMeap7CckkOtuN0Yaebqtv42dZH0MiikzSco2ROhagX-HOinG7gB78ax"
+
+ // echo -n '{"crv":"P-256","kty":"EC","x":"<testKeyECPubX>","y":"<testKeyECPubY>"}' | \
+ // openssl dgst -binary -sha256 | base64 | tr -d '=' | tr '/+' '_-'
+ testKeyECThumbprint = "zedj-Bd1Zshp8KLePv2MB-lJ_Hagp7wAwdkA0NUTniU"
+)
+
+var (
+ testKey *rsa.PrivateKey
+ testKeyEC *ecdsa.PrivateKey
+ testKeyEC384 *ecdsa.PrivateKey
+ testKeyEC512 *ecdsa.PrivateKey
+)
+
+func init() {
+ testKey = parseRSA(testKeyPEM, "testKeyPEM")
+ testKeyEC = parseEC(testKeyECPEM, "testKeyECPEM")
+ testKeyEC384 = parseEC(testKeyEC384PEM, "testKeyEC384PEM")
+ testKeyEC512 = parseEC(testKeyEC512PEM, "testKeyEC512PEM")
+}
+
+func decodePEM(s, name string) []byte {
+ d, _ := pem.Decode([]byte(s))
+ if d == nil {
+ panic("no block found in " + name)
+ }
+ return d.Bytes
+}
+
+func parseRSA(s, name string) *rsa.PrivateKey {
+ b := decodePEM(s, name)
+ k, err := x509.ParsePKCS1PrivateKey(b)
+ if err != nil {
+ panic(fmt.Sprintf("%s: %v", name, err))
+ }
+ return k
+}
+
+func parseEC(s, name string) *ecdsa.PrivateKey {
+ b := decodePEM(s, name)
+ k, err := x509.ParseECPrivateKey(b)
+ if err != nil {
+ panic(fmt.Sprintf("%s: %v", name, err))
+ }
+ return k
+}
+
+func TestJWSEncodeJSON(t *testing.T) {
+ claims := struct{ Msg string }{"Hello JWS"}
+ // JWS signed with testKey and "nonce" as the nonce value
+ // JSON-serialized JWS fields are split for easier testing
+ const (
+ // {"alg":"RS256","jwk":{"e":"AQAB","kty":"RSA","n":"..."},"nonce":"nonce"}
+ protected = "eyJhbGciOiJSUzI1NiIsImp3ayI6eyJlIjoiQVFBQiIsImt0eSI6" +
+ "IlJTQSIsIm4iOiI0eGdaM2VSUGt3b1J2eTdxZVJVYm1NRGUwVi14" +
+ "SDllV0xkdTBpaGVlTGxybUQybXFXWGZQOUllU0tBcGJuMzRnOFR1" +
+ "QVM5ZzV6aHE4RUxRM2ttanItS1Y4NkdBTWdJNlZBY0dscTNRcnpw" +
+ "VENmXzMwQWI3LXphd3JmUmFGT05hMUh3RXpQWTFLSG5HVmt4SmM4" +
+ "NWdOa3dZSTlTWTJSSFh0dmxuM3pzNXdJVE5yZG9zcUVYZWFJa1ZZ" +
+ "QkVoYmhOdTU0cHAza3hvNlR1V0xpOWU2cFhlV2V0RXdtbEJ3dFda" +
+ "bFBvaWIyajNUeExCa3NLWmZveUZ5ZWszODBtSGdKQXVtUV9JMmZq" +
+ "ajk4Xzk3bWszaWhPWTRBZ1ZkQ0RqMXpfR0NvWmtHNVJxN25iQ0d5" +
+ "b3N5S1d5RFgwMFpzLW5OcVZob0xlSXZYQzRubldkSk1aNnJvZ3h5" +
+ "UVEifSwibm9uY2UiOiJub25jZSJ9"
+ // {"Msg":"Hello JWS"}
+ payload = "eyJNc2ciOiJIZWxsbyBKV1MifQ"
+ signature = "eAGUikStX_UxyiFhxSLMyuyBcIB80GeBkFROCpap2sW3EmkU_ggF" +
+ "knaQzxrTfItICSAXsCLIquZ5BbrSWA_4vdEYrwWtdUj7NqFKjHRa" +
+ "zpLHcoR7r1rEHvkoP1xj49lS5fc3Wjjq8JUhffkhGbWZ8ZVkgPdC" +
+ "4tMBWiQDoth-x8jELP_3LYOB_ScUXi2mETBawLgOT2K8rA0Vbbmx" +
+ "hWNlOWuUf-8hL5YX4IOEwsS8JK_TrTq5Zc9My0zHJmaieqDV0UlP" +
+ "k0onFjPFkGm7MrPSgd0MqRG-4vSAg2O4hDo7rKv4n8POjjXlNQvM" +
+ "9IPLr8qZ7usYBKhEGwX3yq_eicAwBw"
+ )
+
+ b, err := jwsEncodeJSON(claims, testKey, "nonce")
+ if err != nil {
+ t.Fatal(err)
+ }
+ var jws struct{ Protected, Payload, Signature string }
+ if err := json.Unmarshal(b, &jws); err != nil {
+ t.Fatal(err)
+ }
+ if jws.Protected != protected {
+ t.Errorf("protected:\n%s\nwant:\n%s", jws.Protected, protected)
+ }
+ if jws.Payload != payload {
+ t.Errorf("payload:\n%s\nwant:\n%s", jws.Payload, payload)
+ }
+ if jws.Signature != signature {
+ t.Errorf("signature:\n%s\nwant:\n%s", jws.Signature, signature)
+ }
+}
+
+func TestJWSEncodeJSONEC(t *testing.T) {
+ tt := []struct {
+ key *ecdsa.PrivateKey
+ x, y string
+ alg, crv string
+ }{
+ {testKeyEC, testKeyECPubX, testKeyECPubY, "ES256", "P-256"},
+ {testKeyEC384, testKeyEC384PubX, testKeyEC384PubY, "ES384", "P-384"},
+ {testKeyEC512, testKeyEC512PubX, testKeyEC512PubY, "ES512", "P-521"},
+ }
+ for i, test := range tt {
+ claims := struct{ Msg string }{"Hello JWS"}
+ b, err := jwsEncodeJSON(claims, test.key, "nonce")
+ if err != nil {
+ t.Errorf("%d: %v", i, err)
+ continue
+ }
+ var jws struct{ Protected, Payload, Signature string }
+ if err := json.Unmarshal(b, &jws); err != nil {
+ t.Errorf("%d: %v", i, err)
+ continue
+ }
+
+ b, err = base64.RawURLEncoding.DecodeString(jws.Protected)
+ if err != nil {
+ t.Errorf("%d: jws.Protected: %v", i, err)
+ }
+ var head struct {
+ Alg string
+ Nonce string
+ JWK struct {
+ Crv string
+ Kty string
+ X string
+ Y string
+ } `json:"jwk"`
+ }
+ if err := json.Unmarshal(b, &head); err != nil {
+ t.Errorf("%d: jws.Protected: %v", i, err)
+ }
+ if head.Alg != test.alg {
+ t.Errorf("%d: head.Alg = %q; want %q", i, head.Alg, test.alg)
+ }
+ if head.Nonce != "nonce" {
+ t.Errorf("%d: head.Nonce = %q; want nonce", i, head.Nonce)
+ }
+ if head.JWK.Crv != test.crv {
+ t.Errorf("%d: head.JWK.Crv = %q; want %q", i, head.JWK.Crv, test.crv)
+ }
+ if head.JWK.Kty != "EC" {
+ t.Errorf("%d: head.JWK.Kty = %q; want EC", i, head.JWK.Kty)
+ }
+ if head.JWK.X != test.x {
+ t.Errorf("%d: head.JWK.X = %q; want %q", i, head.JWK.X, test.x)
+ }
+ if head.JWK.Y != test.y {
+ t.Errorf("%d: head.JWK.Y = %q; want %q", i, head.JWK.Y, test.y)
+ }
+ }
+}
+
+func TestJWKThumbprintRSA(t *testing.T) {
+ // Key example from RFC 7638
+ const base64N = "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAt" +
+ "VT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn6" +
+ "4tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FD" +
+ "W2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n9" +
+ "1CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINH" +
+ "aQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw"
+ const base64E = "AQAB"
+ const expected = "NzbLsXh8uDCcd-6MNwXF4W_7noWXFZAfHkxZsRGC9Xs"
+
+ b, err := base64.RawURLEncoding.DecodeString(base64N)
+ if err != nil {
+ t.Fatalf("Error parsing example key N: %v", err)
+ }
+ n := new(big.Int).SetBytes(b)
+
+ b, err = base64.RawURLEncoding.DecodeString(base64E)
+ if err != nil {
+ t.Fatalf("Error parsing example key E: %v", err)
+ }
+ e := new(big.Int).SetBytes(b)
+
+ pub := &rsa.PublicKey{N: n, E: int(e.Uint64())}
+ th, err := JWKThumbprint(pub)
+ if err != nil {
+ t.Error(err)
+ }
+ if th != expected {
+ t.Errorf("thumbprint = %q; want %q", th, expected)
+ }
+}
+
+func TestJWKThumbprintEC(t *testing.T) {
+ // Key example from RFC 7520
+ // expected was computed with
+ // echo -n '{"crv":"P-521","kty":"EC","x":"<base64X>","y":"<base64Y>"}' | \
+ // openssl dgst -binary -sha256 | \
+ // base64 | \
+ // tr -d '=' | tr '/+' '_-'
+ const (
+ base64X = "AHKZLLOsCOzz5cY97ewNUajB957y-C-U88c3v13nmGZx6sYl_oJXu9A5RkT" +
+ "KqjqvjyekWF-7ytDyRXYgCF5cj0Kt"
+ base64Y = "AdymlHvOiLxXkEhayXQnNCvDX4h9htZaCJN34kfmC6pV5OhQHiraVySsUda" +
+ "QkAgDPrwQrJmbnX9cwlGfP-HqHZR1"
+ expected = "dHri3SADZkrush5HU_50AoRhcKFryN-PI6jPBtPL55M"
+ )
+
+ b, err := base64.RawURLEncoding.DecodeString(base64X)
+ if err != nil {
+ t.Fatalf("Error parsing example key X: %v", err)
+ }
+ x := new(big.Int).SetBytes(b)
+
+ b, err = base64.RawURLEncoding.DecodeString(base64Y)
+ if err != nil {
+ t.Fatalf("Error parsing example key Y: %v", err)
+ }
+ y := new(big.Int).SetBytes(b)
+
+ pub := &ecdsa.PublicKey{Curve: elliptic.P521(), X: x, Y: y}
+ th, err := JWKThumbprint(pub)
+ if err != nil {
+ t.Error(err)
+ }
+ if th != expected {
+ t.Errorf("thumbprint = %q; want %q", th, expected)
+ }
+}
+
+func TestJWKThumbprintErrUnsupportedKey(t *testing.T) {
+ _, err := JWKThumbprint(struct{}{})
+ if err != ErrUnsupportedKey {
+ t.Errorf("err = %q; want %q", err, ErrUnsupportedKey)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/types.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/types.go
new file mode 100644
index 000000000..3e199749e
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/types.go
@@ -0,0 +1,329 @@
+// 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.
+
+package acme
+
+import (
+ "crypto"
+ "crypto/x509"
+ "errors"
+ "fmt"
+ "net/http"
+ "strings"
+ "time"
+)
+
+// ACME server response statuses used to describe Authorization and Challenge states.
+const (
+ StatusUnknown = "unknown"
+ StatusPending = "pending"
+ StatusProcessing = "processing"
+ StatusValid = "valid"
+ StatusInvalid = "invalid"
+ StatusRevoked = "revoked"
+)
+
+// CRLReasonCode identifies the reason for a certificate revocation.
+type CRLReasonCode int
+
+// CRL reason codes as defined in RFC 5280.
+const (
+ CRLReasonUnspecified CRLReasonCode = 0
+ CRLReasonKeyCompromise CRLReasonCode = 1
+ CRLReasonCACompromise CRLReasonCode = 2
+ CRLReasonAffiliationChanged CRLReasonCode = 3
+ CRLReasonSuperseded CRLReasonCode = 4
+ CRLReasonCessationOfOperation CRLReasonCode = 5
+ CRLReasonCertificateHold CRLReasonCode = 6
+ CRLReasonRemoveFromCRL CRLReasonCode = 8
+ CRLReasonPrivilegeWithdrawn CRLReasonCode = 9
+ CRLReasonAACompromise CRLReasonCode = 10
+)
+
+// ErrUnsupportedKey is returned when an unsupported key type is encountered.
+var ErrUnsupportedKey = errors.New("acme: unknown key type; only RSA and ECDSA are supported")
+
+// Error is an ACME error, defined in Problem Details for HTTP APIs doc
+// http://tools.ietf.org/html/draft-ietf-appsawg-http-problem.
+type Error struct {
+ // StatusCode is The HTTP status code generated by the origin server.
+ StatusCode int
+ // ProblemType is a URI reference that identifies the problem type,
+ // typically in a "urn:acme:error:xxx" form.
+ ProblemType string
+ // Detail is a human-readable explanation specific to this occurrence of the problem.
+ Detail string
+ // Header is the original server error response headers.
+ // It may be nil.
+ Header http.Header
+}
+
+func (e *Error) Error() string {
+ return fmt.Sprintf("%d %s: %s", e.StatusCode, e.ProblemType, e.Detail)
+}
+
+// AuthorizationError indicates that an authorization for an identifier
+// did not succeed.
+// It contains all errors from Challenge items of the failed Authorization.
+type AuthorizationError struct {
+ // URI uniquely identifies the failed Authorization.
+ URI string
+
+ // Identifier is an AuthzID.Value of the failed Authorization.
+ Identifier string
+
+ // Errors is a collection of non-nil error values of Challenge items
+ // of the failed Authorization.
+ Errors []error
+}
+
+func (a *AuthorizationError) Error() string {
+ e := make([]string, len(a.Errors))
+ for i, err := range a.Errors {
+ e[i] = err.Error()
+ }
+ return fmt.Sprintf("acme: authorization error for %s: %s", a.Identifier, strings.Join(e, "; "))
+}
+
+// RateLimit reports whether err represents a rate limit error and
+// any Retry-After duration returned by the server.
+//
+// See the following for more details on rate limiting:
+// https://tools.ietf.org/html/draft-ietf-acme-acme-05#section-5.6
+func RateLimit(err error) (time.Duration, bool) {
+ e, ok := err.(*Error)
+ if !ok {
+ return 0, false
+ }
+ // Some CA implementations may return incorrect values.
+ // Use case-insensitive comparison.
+ if !strings.HasSuffix(strings.ToLower(e.ProblemType), ":ratelimited") {
+ return 0, false
+ }
+ if e.Header == nil {
+ return 0, true
+ }
+ return retryAfter(e.Header.Get("Retry-After"), 0), true
+}
+
+// Account is a user account. It is associated with a private key.
+type Account struct {
+ // URI is the account unique ID, which is also a URL used to retrieve
+ // account data from the CA.
+ URI string
+
+ // Contact is a slice of contact info used during registration.
+ Contact []string
+
+ // The terms user has agreed to.
+ // A value not matching CurrentTerms indicates that the user hasn't agreed
+ // to the actual Terms of Service of the CA.
+ AgreedTerms string
+
+ // Actual terms of a CA.
+ CurrentTerms string
+
+ // Authz is the authorization URL used to initiate a new authz flow.
+ Authz string
+
+ // Authorizations is a URI from which a list of authorizations
+ // granted to this account can be fetched via a GET request.
+ Authorizations string
+
+ // Certificates is a URI from which a list of certificates
+ // issued for this account can be fetched via a GET request.
+ Certificates string
+}
+
+// Directory is ACME server discovery data.
+type Directory struct {
+ // RegURL is an account endpoint URL, allowing for creating new
+ // and modifying existing accounts.
+ RegURL string
+
+ // AuthzURL is used to initiate Identifier Authorization flow.
+ AuthzURL string
+
+ // CertURL is a new certificate issuance endpoint URL.
+ CertURL string
+
+ // RevokeURL is used to initiate a certificate revocation flow.
+ RevokeURL string
+
+ // Term is a URI identifying the current terms of service.
+ Terms string
+
+ // Website is an HTTP or HTTPS URL locating a website
+ // providing more information about the ACME server.
+ Website string
+
+ // CAA consists of lowercase hostname elements, which the ACME server
+ // recognises as referring to itself for the purposes of CAA record validation
+ // as defined in RFC6844.
+ CAA []string
+}
+
+// Challenge encodes a returned CA challenge.
+// Its Error field may be non-nil if the challenge is part of an Authorization
+// with StatusInvalid.
+type Challenge struct {
+ // Type is the challenge type, e.g. "http-01", "tls-sni-02", "dns-01".
+ Type string
+
+ // URI is where a challenge response can be posted to.
+ URI string
+
+ // Token is a random value that uniquely identifies the challenge.
+ Token string
+
+ // Status identifies the status of this challenge.
+ Status string
+
+ // Error indicates the reason for an authorization failure
+ // when this challenge was used.
+ // The type of a non-nil value is *Error.
+ Error error
+}
+
+// Authorization encodes an authorization response.
+type Authorization struct {
+ // URI uniquely identifies a authorization.
+ URI string
+
+ // Status identifies the status of an authorization.
+ Status string
+
+ // Identifier is what the account is authorized to represent.
+ Identifier AuthzID
+
+ // Challenges that the client needs to fulfill in order to prove possession
+ // of the identifier (for pending authorizations).
+ // For final authorizations, the challenges that were used.
+ Challenges []*Challenge
+
+ // A collection of sets of challenges, each of which would be sufficient
+ // to prove possession of the identifier.
+ // Clients must complete a set of challenges that covers at least one set.
+ // Challenges are identified by their indices in the challenges array.
+ // If this field is empty, the client needs to complete all challenges.
+ Combinations [][]int
+}
+
+// AuthzID is an identifier that an account is authorized to represent.
+type AuthzID struct {
+ Type string // The type of identifier, e.g. "dns".
+ Value string // The identifier itself, e.g. "example.org".
+}
+
+// wireAuthz is ACME JSON representation of Authorization objects.
+type wireAuthz struct {
+ Status string
+ Challenges []wireChallenge
+ Combinations [][]int
+ Identifier struct {
+ Type string
+ Value string
+ }
+}
+
+func (z *wireAuthz) authorization(uri string) *Authorization {
+ a := &Authorization{
+ URI: uri,
+ Status: z.Status,
+ Identifier: AuthzID{Type: z.Identifier.Type, Value: z.Identifier.Value},
+ Combinations: z.Combinations, // shallow copy
+ Challenges: make([]*Challenge, len(z.Challenges)),
+ }
+ for i, v := range z.Challenges {
+ a.Challenges[i] = v.challenge()
+ }
+ return a
+}
+
+func (z *wireAuthz) error(uri string) *AuthorizationError {
+ err := &AuthorizationError{
+ URI: uri,
+ Identifier: z.Identifier.Value,
+ }
+ for _, raw := range z.Challenges {
+ if raw.Error != nil {
+ err.Errors = append(err.Errors, raw.Error.error(nil))
+ }
+ }
+ return err
+}
+
+// wireChallenge is ACME JSON challenge representation.
+type wireChallenge struct {
+ URI string `json:"uri"`
+ Type string
+ Token string
+ Status string
+ Error *wireError
+}
+
+func (c *wireChallenge) challenge() *Challenge {
+ v := &Challenge{
+ URI: c.URI,
+ Type: c.Type,
+ Token: c.Token,
+ Status: c.Status,
+ }
+ if v.Status == "" {
+ v.Status = StatusPending
+ }
+ if c.Error != nil {
+ v.Error = c.Error.error(nil)
+ }
+ return v
+}
+
+// wireError is a subset of fields of the Problem Details object
+// as described in https://tools.ietf.org/html/rfc7807#section-3.1.
+type wireError struct {
+ Status int
+ Type string
+ Detail string
+}
+
+func (e *wireError) error(h http.Header) *Error {
+ return &Error{
+ StatusCode: e.Status,
+ ProblemType: e.Type,
+ Detail: e.Detail,
+ Header: h,
+ }
+}
+
+// CertOption is an optional argument type for the TLSSNIxChallengeCert methods for
+// customizing a temporary certificate for TLS-SNI challenges.
+type CertOption interface {
+ privateCertOpt()
+}
+
+// WithKey creates an option holding a private/public key pair.
+// The private part signs a certificate, and the public part represents the signee.
+func WithKey(key crypto.Signer) CertOption {
+ return &certOptKey{key}
+}
+
+type certOptKey struct {
+ key crypto.Signer
+}
+
+func (*certOptKey) privateCertOpt() {}
+
+// WithTemplate creates an option for specifying a certificate template.
+// See x509.CreateCertificate for template usage details.
+//
+// In TLSSNIxChallengeCert methods, the template is also used as parent,
+// resulting in a self-signed certificate.
+// The DNSNames field of t is always overwritten for tls-sni challenge certs.
+func WithTemplate(t *x509.Certificate) CertOption {
+ return (*certOptTemplate)(t)
+}
+
+type certOptTemplate x509.Certificate
+
+func (*certOptTemplate) privateCertOpt() {}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/types_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/types_test.go
new file mode 100644
index 000000000..a7553e6b7
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/acme/types_test.go
@@ -0,0 +1,63 @@
+// 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 acme
+
+import (
+ "errors"
+ "net/http"
+ "testing"
+ "time"
+)
+
+func TestRateLimit(t *testing.T) {
+ now := time.Date(2017, 04, 27, 10, 0, 0, 0, time.UTC)
+ f := timeNow
+ defer func() { timeNow = f }()
+ timeNow = func() time.Time { return now }
+
+ h120, hTime := http.Header{}, http.Header{}
+ h120.Set("Retry-After", "120")
+ hTime.Set("Retry-After", "Tue Apr 27 11:00:00 2017")
+
+ err1 := &Error{
+ ProblemType: "urn:ietf:params:acme:error:nolimit",
+ Header: h120,
+ }
+ err2 := &Error{
+ ProblemType: "urn:ietf:params:acme:error:rateLimited",
+ Header: h120,
+ }
+ err3 := &Error{
+ ProblemType: "urn:ietf:params:acme:error:rateLimited",
+ Header: nil,
+ }
+ err4 := &Error{
+ ProblemType: "urn:ietf:params:acme:error:rateLimited",
+ Header: hTime,
+ }
+
+ tt := []struct {
+ err error
+ res time.Duration
+ ok bool
+ }{
+ {nil, 0, false},
+ {errors.New("dummy"), 0, false},
+ {err1, 0, false},
+ {err2, 2 * time.Minute, true},
+ {err3, 0, true},
+ {err4, time.Hour, true},
+ }
+ for i, test := range tt {
+ res, ok := RateLimit(test.err)
+ if ok != test.ok {
+ t.Errorf("%d: RateLimit(%+v): ok = %v; want %v", i, test.err, ok, test.ok)
+ continue
+ }
+ if res != test.res {
+ t.Errorf("%d: RateLimit(%+v) = %v; want %v", i, test.err, res, test.res)
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bcrypt/base64.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bcrypt/base64.go
new file mode 100644
index 000000000..fc3116090
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bcrypt/base64.go
@@ -0,0 +1,35 @@
+// Copyright 2011 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 bcrypt
+
+import "encoding/base64"
+
+const alphabet = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+
+var bcEncoding = base64.NewEncoding(alphabet)
+
+func base64Encode(src []byte) []byte {
+ n := bcEncoding.EncodedLen(len(src))
+ dst := make([]byte, n)
+ bcEncoding.Encode(dst, src)
+ for dst[n-1] == '=' {
+ n--
+ }
+ return dst[:n]
+}
+
+func base64Decode(src []byte) ([]byte, error) {
+ numOfEquals := 4 - (len(src) % 4)
+ for i := 0; i < numOfEquals; i++ {
+ src = append(src, '=')
+ }
+
+ dst := make([]byte, bcEncoding.DecodedLen(len(src)))
+ n, err := bcEncoding.Decode(dst, src)
+ if err != nil {
+ return nil, err
+ }
+ return dst[:n], nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bcrypt/bcrypt.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bcrypt/bcrypt.go
new file mode 100644
index 000000000..202fa8aff
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bcrypt/bcrypt.go
@@ -0,0 +1,295 @@
+// Copyright 2011 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 bcrypt implements Provos and Mazières's bcrypt adaptive hashing
+// algorithm. See http://www.usenix.org/event/usenix99/provos/provos.pdf
+package bcrypt // import "golang.org/x/crypto/bcrypt"
+
+// The code is a port of Provos and Mazières's C implementation.
+import (
+ "crypto/rand"
+ "crypto/subtle"
+ "errors"
+ "fmt"
+ "io"
+ "strconv"
+
+ "golang.org/x/crypto/blowfish"
+)
+
+const (
+ MinCost int = 4 // the minimum allowable cost as passed in to GenerateFromPassword
+ MaxCost int = 31 // the maximum allowable cost as passed in to GenerateFromPassword
+ DefaultCost int = 10 // the cost that will actually be set if a cost below MinCost is passed into GenerateFromPassword
+)
+
+// The error returned from CompareHashAndPassword when a password and hash do
+// not match.
+var ErrMismatchedHashAndPassword = errors.New("crypto/bcrypt: hashedPassword is not the hash of the given password")
+
+// The error returned from CompareHashAndPassword when a hash is too short to
+// be a bcrypt hash.
+var ErrHashTooShort = errors.New("crypto/bcrypt: hashedSecret too short to be a bcrypted password")
+
+// The error returned from CompareHashAndPassword when a hash was created with
+// a bcrypt algorithm newer than this implementation.
+type HashVersionTooNewError byte
+
+func (hv HashVersionTooNewError) Error() string {
+ return fmt.Sprintf("crypto/bcrypt: bcrypt algorithm version '%c' requested is newer than current version '%c'", byte(hv), majorVersion)
+}
+
+// The error returned from CompareHashAndPassword when a hash starts with something other than '$'
+type InvalidHashPrefixError byte
+
+func (ih InvalidHashPrefixError) Error() string {
+ return fmt.Sprintf("crypto/bcrypt: bcrypt hashes must start with '$', but hashedSecret started with '%c'", byte(ih))
+}
+
+type InvalidCostError int
+
+func (ic InvalidCostError) Error() string {
+ return fmt.Sprintf("crypto/bcrypt: cost %d is outside allowed range (%d,%d)", int(ic), int(MinCost), int(MaxCost))
+}
+
+const (
+ majorVersion = '2'
+ minorVersion = 'a'
+ maxSaltSize = 16
+ maxCryptedHashSize = 23
+ encodedSaltSize = 22
+ encodedHashSize = 31
+ minHashSize = 59
+)
+
+// magicCipherData is an IV for the 64 Blowfish encryption calls in
+// bcrypt(). It's the string "OrpheanBeholderScryDoubt" in big-endian bytes.
+var magicCipherData = []byte{
+ 0x4f, 0x72, 0x70, 0x68,
+ 0x65, 0x61, 0x6e, 0x42,
+ 0x65, 0x68, 0x6f, 0x6c,
+ 0x64, 0x65, 0x72, 0x53,
+ 0x63, 0x72, 0x79, 0x44,
+ 0x6f, 0x75, 0x62, 0x74,
+}
+
+type hashed struct {
+ hash []byte
+ salt []byte
+ cost int // allowed range is MinCost to MaxCost
+ major byte
+ minor byte
+}
+
+// GenerateFromPassword returns the bcrypt hash of the password at the given
+// cost. If the cost given is less than MinCost, the cost will be set to
+// DefaultCost, instead. Use CompareHashAndPassword, as defined in this package,
+// to compare the returned hashed password with its cleartext version.
+func GenerateFromPassword(password []byte, cost int) ([]byte, error) {
+ p, err := newFromPassword(password, cost)
+ if err != nil {
+ return nil, err
+ }
+ return p.Hash(), nil
+}
+
+// CompareHashAndPassword compares a bcrypt hashed password with its possible
+// plaintext equivalent. Returns nil on success, or an error on failure.
+func CompareHashAndPassword(hashedPassword, password []byte) error {
+ p, err := newFromHash(hashedPassword)
+ if err != nil {
+ return err
+ }
+
+ otherHash, err := bcrypt(password, p.cost, p.salt)
+ if err != nil {
+ return err
+ }
+
+ otherP := &hashed{otherHash, p.salt, p.cost, p.major, p.minor}
+ if subtle.ConstantTimeCompare(p.Hash(), otherP.Hash()) == 1 {
+ return nil
+ }
+
+ return ErrMismatchedHashAndPassword
+}
+
+// Cost returns the hashing cost used to create the given hashed
+// password. When, in the future, the hashing cost of a password system needs
+// to be increased in order to adjust for greater computational power, this
+// function allows one to establish which passwords need to be updated.
+func Cost(hashedPassword []byte) (int, error) {
+ p, err := newFromHash(hashedPassword)
+ if err != nil {
+ return 0, err
+ }
+ return p.cost, nil
+}
+
+func newFromPassword(password []byte, cost int) (*hashed, error) {
+ if cost < MinCost {
+ cost = DefaultCost
+ }
+ p := new(hashed)
+ p.major = majorVersion
+ p.minor = minorVersion
+
+ err := checkCost(cost)
+ if err != nil {
+ return nil, err
+ }
+ p.cost = cost
+
+ unencodedSalt := make([]byte, maxSaltSize)
+ _, err = io.ReadFull(rand.Reader, unencodedSalt)
+ if err != nil {
+ return nil, err
+ }
+
+ p.salt = base64Encode(unencodedSalt)
+ hash, err := bcrypt(password, p.cost, p.salt)
+ if err != nil {
+ return nil, err
+ }
+ p.hash = hash
+ return p, err
+}
+
+func newFromHash(hashedSecret []byte) (*hashed, error) {
+ if len(hashedSecret) < minHashSize {
+ return nil, ErrHashTooShort
+ }
+ p := new(hashed)
+ n, err := p.decodeVersion(hashedSecret)
+ if err != nil {
+ return nil, err
+ }
+ hashedSecret = hashedSecret[n:]
+ n, err = p.decodeCost(hashedSecret)
+ if err != nil {
+ return nil, err
+ }
+ hashedSecret = hashedSecret[n:]
+
+ // The "+2" is here because we'll have to append at most 2 '=' to the salt
+ // when base64 decoding it in expensiveBlowfishSetup().
+ p.salt = make([]byte, encodedSaltSize, encodedSaltSize+2)
+ copy(p.salt, hashedSecret[:encodedSaltSize])
+
+ hashedSecret = hashedSecret[encodedSaltSize:]
+ p.hash = make([]byte, len(hashedSecret))
+ copy(p.hash, hashedSecret)
+
+ return p, nil
+}
+
+func bcrypt(password []byte, cost int, salt []byte) ([]byte, error) {
+ cipherData := make([]byte, len(magicCipherData))
+ copy(cipherData, magicCipherData)
+
+ c, err := expensiveBlowfishSetup(password, uint32(cost), salt)
+ if err != nil {
+ return nil, err
+ }
+
+ for i := 0; i < 24; i += 8 {
+ for j := 0; j < 64; j++ {
+ c.Encrypt(cipherData[i:i+8], cipherData[i:i+8])
+ }
+ }
+
+ // Bug compatibility with C bcrypt implementations. We only encode 23 of
+ // the 24 bytes encrypted.
+ hsh := base64Encode(cipherData[:maxCryptedHashSize])
+ return hsh, nil
+}
+
+func expensiveBlowfishSetup(key []byte, cost uint32, salt []byte) (*blowfish.Cipher, error) {
+ csalt, err := base64Decode(salt)
+ if err != nil {
+ return nil, err
+ }
+
+ // Bug compatibility with C bcrypt implementations. They use the trailing
+ // NULL in the key string during expansion.
+ // We copy the key to prevent changing the underlying array.
+ ckey := append(key[:len(key):len(key)], 0)
+
+ c, err := blowfish.NewSaltedCipher(ckey, csalt)
+ if err != nil {
+ return nil, err
+ }
+
+ var i, rounds uint64
+ rounds = 1 << cost
+ for i = 0; i < rounds; i++ {
+ blowfish.ExpandKey(ckey, c)
+ blowfish.ExpandKey(csalt, c)
+ }
+
+ return c, nil
+}
+
+func (p *hashed) Hash() []byte {
+ arr := make([]byte, 60)
+ arr[0] = '$'
+ arr[1] = p.major
+ n := 2
+ if p.minor != 0 {
+ arr[2] = p.minor
+ n = 3
+ }
+ arr[n] = '$'
+ n += 1
+ copy(arr[n:], []byte(fmt.Sprintf("%02d", p.cost)))
+ n += 2
+ arr[n] = '$'
+ n += 1
+ copy(arr[n:], p.salt)
+ n += encodedSaltSize
+ copy(arr[n:], p.hash)
+ n += encodedHashSize
+ return arr[:n]
+}
+
+func (p *hashed) decodeVersion(sbytes []byte) (int, error) {
+ if sbytes[0] != '$' {
+ return -1, InvalidHashPrefixError(sbytes[0])
+ }
+ if sbytes[1] > majorVersion {
+ return -1, HashVersionTooNewError(sbytes[1])
+ }
+ p.major = sbytes[1]
+ n := 3
+ if sbytes[2] != '$' {
+ p.minor = sbytes[2]
+ n++
+ }
+ return n, nil
+}
+
+// sbytes should begin where decodeVersion left off.
+func (p *hashed) decodeCost(sbytes []byte) (int, error) {
+ cost, err := strconv.Atoi(string(sbytes[0:2]))
+ if err != nil {
+ return -1, err
+ }
+ err = checkCost(cost)
+ if err != nil {
+ return -1, err
+ }
+ p.cost = cost
+ return 3, nil
+}
+
+func (p *hashed) String() string {
+ return fmt.Sprintf("&{hash: %#v, salt: %#v, cost: %d, major: %c, minor: %c}", string(p.hash), p.salt, p.cost, p.major, p.minor)
+}
+
+func checkCost(cost int) error {
+ if cost < MinCost || cost > MaxCost {
+ return InvalidCostError(cost)
+ }
+ return nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bcrypt/bcrypt_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bcrypt/bcrypt_test.go
new file mode 100644
index 000000000..aecf759eb
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bcrypt/bcrypt_test.go
@@ -0,0 +1,243 @@
+// Copyright 2011 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 bcrypt
+
+import (
+ "bytes"
+ "fmt"
+ "testing"
+)
+
+func TestBcryptingIsEasy(t *testing.T) {
+ pass := []byte("mypassword")
+ hp, err := GenerateFromPassword(pass, 0)
+ if err != nil {
+ t.Fatalf("GenerateFromPassword error: %s", err)
+ }
+
+ if CompareHashAndPassword(hp, pass) != nil {
+ t.Errorf("%v should hash %s correctly", hp, pass)
+ }
+
+ notPass := "notthepass"
+ err = CompareHashAndPassword(hp, []byte(notPass))
+ if err != ErrMismatchedHashAndPassword {
+ t.Errorf("%v and %s should be mismatched", hp, notPass)
+ }
+}
+
+func TestBcryptingIsCorrect(t *testing.T) {
+ pass := []byte("allmine")
+ salt := []byte("XajjQvNhvvRt5GSeFk1xFe")
+ expectedHash := []byte("$2a$10$XajjQvNhvvRt5GSeFk1xFeyqRrsxkhBkUiQeg0dt.wU1qD4aFDcga")
+
+ hash, err := bcrypt(pass, 10, salt)
+ if err != nil {
+ t.Fatalf("bcrypt blew up: %v", err)
+ }
+ if !bytes.HasSuffix(expectedHash, hash) {
+ t.Errorf("%v should be the suffix of %v", hash, expectedHash)
+ }
+
+ h, err := newFromHash(expectedHash)
+ if err != nil {
+ t.Errorf("Unable to parse %s: %v", string(expectedHash), err)
+ }
+
+ // This is not the safe way to compare these hashes. We do this only for
+ // testing clarity. Use bcrypt.CompareHashAndPassword()
+ if err == nil && !bytes.Equal(expectedHash, h.Hash()) {
+ t.Errorf("Parsed hash %v should equal %v", h.Hash(), expectedHash)
+ }
+}
+
+func TestVeryShortPasswords(t *testing.T) {
+ key := []byte("k")
+ salt := []byte("XajjQvNhvvRt5GSeFk1xFe")
+ _, err := bcrypt(key, 10, salt)
+ if err != nil {
+ t.Errorf("One byte key resulted in error: %s", err)
+ }
+}
+
+func TestTooLongPasswordsWork(t *testing.T) {
+ salt := []byte("XajjQvNhvvRt5GSeFk1xFe")
+ // One byte over the usual 56 byte limit that blowfish has
+ tooLongPass := []byte("012345678901234567890123456789012345678901234567890123456")
+ tooLongExpected := []byte("$2a$10$XajjQvNhvvRt5GSeFk1xFe5l47dONXg781AmZtd869sO8zfsHuw7C")
+ hash, err := bcrypt(tooLongPass, 10, salt)
+ if err != nil {
+ t.Fatalf("bcrypt blew up on long password: %v", err)
+ }
+ if !bytes.HasSuffix(tooLongExpected, hash) {
+ t.Errorf("%v should be the suffix of %v", hash, tooLongExpected)
+ }
+}
+
+type InvalidHashTest struct {
+ err error
+ hash []byte
+}
+
+var invalidTests = []InvalidHashTest{
+ {ErrHashTooShort, []byte("$2a$10$fooo")},
+ {ErrHashTooShort, []byte("$2a")},
+ {HashVersionTooNewError('3'), []byte("$3a$10$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")},
+ {InvalidHashPrefixError('%'), []byte("%2a$10$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")},
+ {InvalidCostError(32), []byte("$2a$32$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")},
+}
+
+func TestInvalidHashErrors(t *testing.T) {
+ check := func(name string, expected, err error) {
+ if err == nil {
+ t.Errorf("%s: Should have returned an error", name)
+ }
+ if err != nil && err != expected {
+ t.Errorf("%s gave err %v but should have given %v", name, err, expected)
+ }
+ }
+ for _, iht := range invalidTests {
+ _, err := newFromHash(iht.hash)
+ check("newFromHash", iht.err, err)
+ err = CompareHashAndPassword(iht.hash, []byte("anything"))
+ check("CompareHashAndPassword", iht.err, err)
+ }
+}
+
+func TestUnpaddedBase64Encoding(t *testing.T) {
+ original := []byte{101, 201, 101, 75, 19, 227, 199, 20, 239, 236, 133, 32, 30, 109, 243, 30}
+ encodedOriginal := []byte("XajjQvNhvvRt5GSeFk1xFe")
+
+ encoded := base64Encode(original)
+
+ if !bytes.Equal(encodedOriginal, encoded) {
+ t.Errorf("Encoded %v should have equaled %v", encoded, encodedOriginal)
+ }
+
+ decoded, err := base64Decode(encodedOriginal)
+ if err != nil {
+ t.Fatalf("base64Decode blew up: %s", err)
+ }
+
+ if !bytes.Equal(decoded, original) {
+ t.Errorf("Decoded %v should have equaled %v", decoded, original)
+ }
+}
+
+func TestCost(t *testing.T) {
+ suffix := "XajjQvNhvvRt5GSeFk1xFe5l47dONXg781AmZtd869sO8zfsHuw7C"
+ for _, vers := range []string{"2a", "2"} {
+ for _, cost := range []int{4, 10} {
+ s := fmt.Sprintf("$%s$%02d$%s", vers, cost, suffix)
+ h := []byte(s)
+ actual, err := Cost(h)
+ if err != nil {
+ t.Errorf("Cost, error: %s", err)
+ continue
+ }
+ if actual != cost {
+ t.Errorf("Cost, expected: %d, actual: %d", cost, actual)
+ }
+ }
+ }
+ _, err := Cost([]byte("$a$a$" + suffix))
+ if err == nil {
+ t.Errorf("Cost, malformed but no error returned")
+ }
+}
+
+func TestCostValidationInHash(t *testing.T) {
+ if testing.Short() {
+ return
+ }
+
+ pass := []byte("mypassword")
+
+ for c := 0; c < MinCost; c++ {
+ p, _ := newFromPassword(pass, c)
+ if p.cost != DefaultCost {
+ t.Errorf("newFromPassword should default costs below %d to %d, but was %d", MinCost, DefaultCost, p.cost)
+ }
+ }
+
+ p, _ := newFromPassword(pass, 14)
+ if p.cost != 14 {
+ t.Errorf("newFromPassword should default cost to 14, but was %d", p.cost)
+ }
+
+ hp, _ := newFromHash(p.Hash())
+ if p.cost != hp.cost {
+ t.Errorf("newFromHash should maintain the cost at %d, but was %d", p.cost, hp.cost)
+ }
+
+ _, err := newFromPassword(pass, 32)
+ if err == nil {
+ t.Fatalf("newFromPassword: should return a cost error")
+ }
+ if err != InvalidCostError(32) {
+ t.Errorf("newFromPassword: should return cost error, got %#v", err)
+ }
+}
+
+func TestCostReturnsWithLeadingZeroes(t *testing.T) {
+ hp, _ := newFromPassword([]byte("abcdefgh"), 7)
+ cost := hp.Hash()[4:7]
+ expected := []byte("07$")
+
+ if !bytes.Equal(expected, cost) {
+ t.Errorf("single digit costs in hash should have leading zeros: was %v instead of %v", cost, expected)
+ }
+}
+
+func TestMinorNotRequired(t *testing.T) {
+ noMinorHash := []byte("$2$10$XajjQvNhvvRt5GSeFk1xFeyqRrsxkhBkUiQeg0dt.wU1qD4aFDcga")
+ h, err := newFromHash(noMinorHash)
+ if err != nil {
+ t.Fatalf("No minor hash blew up: %s", err)
+ }
+ if h.minor != 0 {
+ t.Errorf("Should leave minor version at 0, but was %d", h.minor)
+ }
+
+ if !bytes.Equal(noMinorHash, h.Hash()) {
+ t.Errorf("Should generate hash %v, but created %v", noMinorHash, h.Hash())
+ }
+}
+
+func BenchmarkEqual(b *testing.B) {
+ b.StopTimer()
+ passwd := []byte("somepasswordyoulike")
+ hash, _ := GenerateFromPassword(passwd, 10)
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ CompareHashAndPassword(hash, passwd)
+ }
+}
+
+func BenchmarkGeneration(b *testing.B) {
+ b.StopTimer()
+ passwd := []byte("mylongpassword1234")
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ GenerateFromPassword(passwd, 10)
+ }
+}
+
+// See Issue https://github.com/golang/go/issues/20425.
+func TestNoSideEffectsFromCompare(t *testing.T) {
+ source := []byte("passw0rd123456")
+ password := source[:len(source)-6]
+ token := source[len(source)-6:]
+ want := make([]byte, len(source))
+ copy(want, source)
+
+ wantHash := []byte("$2a$10$LK9XRuhNxHHCvjX3tdkRKei1QiCDUKrJRhZv7WWZPuQGRUM92rOUa")
+ _ = CompareHashAndPassword(wantHash, password)
+
+ got := bytes.Join([][]byte{password, token}, []byte(""))
+ if !bytes.Equal(got, want) {
+ t.Errorf("got=%q want=%q", got, want)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2b/blake2b.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2b/blake2b.go
new file mode 100644
index 000000000..7f0a86e44
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2b/blake2b.go
@@ -0,0 +1,207 @@
+// 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.
+
+// Package blake2b implements the BLAKE2b hash algorithm defined by RFC 7693
+// and the extendable output function (XOF) BLAKE2Xb.
+//
+// For a detailed specification of BLAKE2b see https://blake2.net/blake2.pdf
+// and for BLAKE2Xb see https://blake2.net/blake2x.pdf
+//
+// If you aren't sure which function you need, use BLAKE2b (Sum512 or New512).
+// If you need a secret-key MAC (message authentication code), use the New512
+// function with a non-nil key.
+//
+// BLAKE2X is a construction to compute hash values larger than 64 bytes. It
+// can produce hash values between 0 and 4 GiB.
+package blake2b
+
+import (
+ "encoding/binary"
+ "errors"
+ "hash"
+)
+
+const (
+ // The blocksize of BLAKE2b in bytes.
+ BlockSize = 128
+ // The hash size of BLAKE2b-512 in bytes.
+ Size = 64
+ // The hash size of BLAKE2b-384 in bytes.
+ Size384 = 48
+ // The hash size of BLAKE2b-256 in bytes.
+ Size256 = 32
+)
+
+var (
+ useAVX2 bool
+ useAVX bool
+ useSSE4 bool
+)
+
+var errKeySize = errors.New("blake2b: invalid key size")
+
+var iv = [8]uint64{
+ 0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1,
+ 0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179,
+}
+
+// Sum512 returns the BLAKE2b-512 checksum of the data.
+func Sum512(data []byte) [Size]byte {
+ var sum [Size]byte
+ checkSum(&sum, Size, data)
+ return sum
+}
+
+// Sum384 returns the BLAKE2b-384 checksum of the data.
+func Sum384(data []byte) [Size384]byte {
+ var sum [Size]byte
+ var sum384 [Size384]byte
+ checkSum(&sum, Size384, data)
+ copy(sum384[:], sum[:Size384])
+ return sum384
+}
+
+// Sum256 returns the BLAKE2b-256 checksum of the data.
+func Sum256(data []byte) [Size256]byte {
+ var sum [Size]byte
+ var sum256 [Size256]byte
+ checkSum(&sum, Size256, data)
+ copy(sum256[:], sum[:Size256])
+ return sum256
+}
+
+// New512 returns a new hash.Hash computing the BLAKE2b-512 checksum. A non-nil
+// key turns the hash into a MAC. The key must between zero and 64 bytes long.
+func New512(key []byte) (hash.Hash, error) { return newDigest(Size, key) }
+
+// New384 returns a new hash.Hash computing the BLAKE2b-384 checksum. A non-nil
+// key turns the hash into a MAC. The key must between zero and 64 bytes long.
+func New384(key []byte) (hash.Hash, error) { return newDigest(Size384, key) }
+
+// New256 returns a new hash.Hash computing the BLAKE2b-256 checksum. A non-nil
+// key turns the hash into a MAC. The key must between zero and 64 bytes long.
+func New256(key []byte) (hash.Hash, error) { return newDigest(Size256, key) }
+
+func newDigest(hashSize int, key []byte) (*digest, error) {
+ if len(key) > Size {
+ return nil, errKeySize
+ }
+ d := &digest{
+ size: hashSize,
+ keyLen: len(key),
+ }
+ copy(d.key[:], key)
+ d.Reset()
+ return d, nil
+}
+
+func checkSum(sum *[Size]byte, hashSize int, data []byte) {
+ h := iv
+ h[0] ^= uint64(hashSize) | (1 << 16) | (1 << 24)
+ var c [2]uint64
+
+ if length := len(data); length > BlockSize {
+ n := length &^ (BlockSize - 1)
+ if length == n {
+ n -= BlockSize
+ }
+ hashBlocks(&h, &c, 0, data[:n])
+ data = data[n:]
+ }
+
+ var block [BlockSize]byte
+ offset := copy(block[:], data)
+ remaining := uint64(BlockSize - offset)
+ if c[0] < remaining {
+ c[1]--
+ }
+ c[0] -= remaining
+
+ hashBlocks(&h, &c, 0xFFFFFFFFFFFFFFFF, block[:])
+
+ for i, v := range h[:(hashSize+7)/8] {
+ binary.LittleEndian.PutUint64(sum[8*i:], v)
+ }
+}
+
+type digest struct {
+ h [8]uint64
+ c [2]uint64
+ size int
+ block [BlockSize]byte
+ offset int
+
+ key [BlockSize]byte
+ keyLen int
+}
+
+func (d *digest) BlockSize() int { return BlockSize }
+
+func (d *digest) Size() int { return d.size }
+
+func (d *digest) Reset() {
+ d.h = iv
+ d.h[0] ^= uint64(d.size) | (uint64(d.keyLen) << 8) | (1 << 16) | (1 << 24)
+ d.offset, d.c[0], d.c[1] = 0, 0, 0
+ if d.keyLen > 0 {
+ d.block = d.key
+ d.offset = BlockSize
+ }
+}
+
+func (d *digest) Write(p []byte) (n int, err error) {
+ n = len(p)
+
+ if d.offset > 0 {
+ remaining := BlockSize - d.offset
+ if n <= remaining {
+ d.offset += copy(d.block[d.offset:], p)
+ return
+ }
+ copy(d.block[d.offset:], p[:remaining])
+ hashBlocks(&d.h, &d.c, 0, d.block[:])
+ d.offset = 0
+ p = p[remaining:]
+ }
+
+ if length := len(p); length > BlockSize {
+ nn := length &^ (BlockSize - 1)
+ if length == nn {
+ nn -= BlockSize
+ }
+ hashBlocks(&d.h, &d.c, 0, p[:nn])
+ p = p[nn:]
+ }
+
+ if len(p) > 0 {
+ d.offset += copy(d.block[:], p)
+ }
+
+ return
+}
+
+func (d *digest) Sum(sum []byte) []byte {
+ var hash [Size]byte
+ d.finalize(&hash)
+ return append(sum, hash[:d.size]...)
+}
+
+func (d *digest) finalize(hash *[Size]byte) {
+ var block [BlockSize]byte
+ copy(block[:], d.block[:d.offset])
+ remaining := uint64(BlockSize - d.offset)
+
+ c := d.c
+ if c[0] < remaining {
+ c[1]--
+ }
+ c[0] -= remaining
+
+ h := d.h
+ hashBlocks(&h, &c, 0xFFFFFFFFFFFFFFFF, block[:])
+
+ for i, v := range h {
+ binary.LittleEndian.PutUint64(hash[8*i:], v)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go
new file mode 100644
index 000000000..8c41cf6c7
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go
@@ -0,0 +1,43 @@
+// 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.
+
+// +build go1.7,amd64,!gccgo,!appengine
+
+package blake2b
+
+func init() {
+ useAVX2 = supportsAVX2()
+ useAVX = supportsAVX()
+ useSSE4 = supportsSSE4()
+}
+
+//go:noescape
+func supportsSSE4() bool
+
+//go:noescape
+func supportsAVX() bool
+
+//go:noescape
+func supportsAVX2() bool
+
+//go:noescape
+func hashBlocksAVX2(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte)
+
+//go:noescape
+func hashBlocksAVX(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte)
+
+//go:noescape
+func hashBlocksSSE4(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte)
+
+func hashBlocks(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) {
+ if useAVX2 {
+ hashBlocksAVX2(h, c, flag, blocks)
+ } else if useAVX {
+ hashBlocksAVX(h, c, flag, blocks)
+ } else if useSSE4 {
+ hashBlocksSSE4(h, c, flag, blocks)
+ } else {
+ hashBlocksGeneric(h, c, flag, blocks)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s
new file mode 100644
index 000000000..784bce6a9
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s
@@ -0,0 +1,762 @@
+// 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.
+
+// +build go1.7,amd64,!gccgo,!appengine
+
+#include "textflag.h"
+
+DATA ·AVX2_iv0<>+0x00(SB)/8, $0x6a09e667f3bcc908
+DATA ·AVX2_iv0<>+0x08(SB)/8, $0xbb67ae8584caa73b
+DATA ·AVX2_iv0<>+0x10(SB)/8, $0x3c6ef372fe94f82b
+DATA ·AVX2_iv0<>+0x18(SB)/8, $0xa54ff53a5f1d36f1
+GLOBL ·AVX2_iv0<>(SB), (NOPTR+RODATA), $32
+
+DATA ·AVX2_iv1<>+0x00(SB)/8, $0x510e527fade682d1
+DATA ·AVX2_iv1<>+0x08(SB)/8, $0x9b05688c2b3e6c1f
+DATA ·AVX2_iv1<>+0x10(SB)/8, $0x1f83d9abfb41bd6b
+DATA ·AVX2_iv1<>+0x18(SB)/8, $0x5be0cd19137e2179
+GLOBL ·AVX2_iv1<>(SB), (NOPTR+RODATA), $32
+
+DATA ·AVX2_c40<>+0x00(SB)/8, $0x0201000706050403
+DATA ·AVX2_c40<>+0x08(SB)/8, $0x0a09080f0e0d0c0b
+DATA ·AVX2_c40<>+0x10(SB)/8, $0x0201000706050403
+DATA ·AVX2_c40<>+0x18(SB)/8, $0x0a09080f0e0d0c0b
+GLOBL ·AVX2_c40<>(SB), (NOPTR+RODATA), $32
+
+DATA ·AVX2_c48<>+0x00(SB)/8, $0x0100070605040302
+DATA ·AVX2_c48<>+0x08(SB)/8, $0x09080f0e0d0c0b0a
+DATA ·AVX2_c48<>+0x10(SB)/8, $0x0100070605040302
+DATA ·AVX2_c48<>+0x18(SB)/8, $0x09080f0e0d0c0b0a
+GLOBL ·AVX2_c48<>(SB), (NOPTR+RODATA), $32
+
+DATA ·AVX_iv0<>+0x00(SB)/8, $0x6a09e667f3bcc908
+DATA ·AVX_iv0<>+0x08(SB)/8, $0xbb67ae8584caa73b
+GLOBL ·AVX_iv0<>(SB), (NOPTR+RODATA), $16
+
+DATA ·AVX_iv1<>+0x00(SB)/8, $0x3c6ef372fe94f82b
+DATA ·AVX_iv1<>+0x08(SB)/8, $0xa54ff53a5f1d36f1
+GLOBL ·AVX_iv1<>(SB), (NOPTR+RODATA), $16
+
+DATA ·AVX_iv2<>+0x00(SB)/8, $0x510e527fade682d1
+DATA ·AVX_iv2<>+0x08(SB)/8, $0x9b05688c2b3e6c1f
+GLOBL ·AVX_iv2<>(SB), (NOPTR+RODATA), $16
+
+DATA ·AVX_iv3<>+0x00(SB)/8, $0x1f83d9abfb41bd6b
+DATA ·AVX_iv3<>+0x08(SB)/8, $0x5be0cd19137e2179
+GLOBL ·AVX_iv3<>(SB), (NOPTR+RODATA), $16
+
+DATA ·AVX_c40<>+0x00(SB)/8, $0x0201000706050403
+DATA ·AVX_c40<>+0x08(SB)/8, $0x0a09080f0e0d0c0b
+GLOBL ·AVX_c40<>(SB), (NOPTR+RODATA), $16
+
+DATA ·AVX_c48<>+0x00(SB)/8, $0x0100070605040302
+DATA ·AVX_c48<>+0x08(SB)/8, $0x09080f0e0d0c0b0a
+GLOBL ·AVX_c48<>(SB), (NOPTR+RODATA), $16
+
+#define VPERMQ_0x39_Y1_Y1 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xc9; BYTE $0x39
+#define VPERMQ_0x93_Y1_Y1 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xc9; BYTE $0x93
+#define VPERMQ_0x4E_Y2_Y2 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xd2; BYTE $0x4e
+#define VPERMQ_0x93_Y3_Y3 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xdb; BYTE $0x93
+#define VPERMQ_0x39_Y3_Y3 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xdb; BYTE $0x39
+
+#define ROUND_AVX2(m0, m1, m2, m3, t, c40, c48) \
+ VPADDQ m0, Y0, Y0; \
+ VPADDQ Y1, Y0, Y0; \
+ VPXOR Y0, Y3, Y3; \
+ VPSHUFD $-79, Y3, Y3; \
+ VPADDQ Y3, Y2, Y2; \
+ VPXOR Y2, Y1, Y1; \
+ VPSHUFB c40, Y1, Y1; \
+ VPADDQ m1, Y0, Y0; \
+ VPADDQ Y1, Y0, Y0; \
+ VPXOR Y0, Y3, Y3; \
+ VPSHUFB c48, Y3, Y3; \
+ VPADDQ Y3, Y2, Y2; \
+ VPXOR Y2, Y1, Y1; \
+ VPADDQ Y1, Y1, t; \
+ VPSRLQ $63, Y1, Y1; \
+ VPXOR t, Y1, Y1; \
+ VPERMQ_0x39_Y1_Y1; \
+ VPERMQ_0x4E_Y2_Y2; \
+ VPERMQ_0x93_Y3_Y3; \
+ VPADDQ m2, Y0, Y0; \
+ VPADDQ Y1, Y0, Y0; \
+ VPXOR Y0, Y3, Y3; \
+ VPSHUFD $-79, Y3, Y3; \
+ VPADDQ Y3, Y2, Y2; \
+ VPXOR Y2, Y1, Y1; \
+ VPSHUFB c40, Y1, Y1; \
+ VPADDQ m3, Y0, Y0; \
+ VPADDQ Y1, Y0, Y0; \
+ VPXOR Y0, Y3, Y3; \
+ VPSHUFB c48, Y3, Y3; \
+ VPADDQ Y3, Y2, Y2; \
+ VPXOR Y2, Y1, Y1; \
+ VPADDQ Y1, Y1, t; \
+ VPSRLQ $63, Y1, Y1; \
+ VPXOR t, Y1, Y1; \
+ VPERMQ_0x39_Y3_Y3; \
+ VPERMQ_0x4E_Y2_Y2; \
+ VPERMQ_0x93_Y1_Y1
+
+#define VMOVQ_SI_X11_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x1E
+#define VMOVQ_SI_X12_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x26
+#define VMOVQ_SI_X13_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x2E
+#define VMOVQ_SI_X14_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x36
+#define VMOVQ_SI_X15_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x3E
+
+#define VMOVQ_SI_X11(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x5E; BYTE $n
+#define VMOVQ_SI_X12(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x66; BYTE $n
+#define VMOVQ_SI_X13(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x6E; BYTE $n
+#define VMOVQ_SI_X14(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x76; BYTE $n
+#define VMOVQ_SI_X15(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x7E; BYTE $n
+
+#define VPINSRQ_1_SI_X11_0 BYTE $0xC4; BYTE $0x63; BYTE $0xA1; BYTE $0x22; BYTE $0x1E; BYTE $0x01
+#define VPINSRQ_1_SI_X12_0 BYTE $0xC4; BYTE $0x63; BYTE $0x99; BYTE $0x22; BYTE $0x26; BYTE $0x01
+#define VPINSRQ_1_SI_X13_0 BYTE $0xC4; BYTE $0x63; BYTE $0x91; BYTE $0x22; BYTE $0x2E; BYTE $0x01
+#define VPINSRQ_1_SI_X14_0 BYTE $0xC4; BYTE $0x63; BYTE $0x89; BYTE $0x22; BYTE $0x36; BYTE $0x01
+#define VPINSRQ_1_SI_X15_0 BYTE $0xC4; BYTE $0x63; BYTE $0x81; BYTE $0x22; BYTE $0x3E; BYTE $0x01
+
+#define VPINSRQ_1_SI_X11(n) BYTE $0xC4; BYTE $0x63; BYTE $0xA1; BYTE $0x22; BYTE $0x5E; BYTE $n; BYTE $0x01
+#define VPINSRQ_1_SI_X12(n) BYTE $0xC4; BYTE $0x63; BYTE $0x99; BYTE $0x22; BYTE $0x66; BYTE $n; BYTE $0x01
+#define VPINSRQ_1_SI_X13(n) BYTE $0xC4; BYTE $0x63; BYTE $0x91; BYTE $0x22; BYTE $0x6E; BYTE $n; BYTE $0x01
+#define VPINSRQ_1_SI_X14(n) BYTE $0xC4; BYTE $0x63; BYTE $0x89; BYTE $0x22; BYTE $0x76; BYTE $n; BYTE $0x01
+#define VPINSRQ_1_SI_X15(n) BYTE $0xC4; BYTE $0x63; BYTE $0x81; BYTE $0x22; BYTE $0x7E; BYTE $n; BYTE $0x01
+
+#define VMOVQ_R8_X15 BYTE $0xC4; BYTE $0x41; BYTE $0xF9; BYTE $0x6E; BYTE $0xF8
+#define VPINSRQ_1_R9_X15 BYTE $0xC4; BYTE $0x43; BYTE $0x81; BYTE $0x22; BYTE $0xF9; BYTE $0x01
+
+// load msg: Y12 = (i0, i1, i2, i3)
+// i0, i1, i2, i3 must not be 0
+#define LOAD_MSG_AVX2_Y12(i0, i1, i2, i3) \
+ VMOVQ_SI_X12(i0*8); \
+ VMOVQ_SI_X11(i2*8); \
+ VPINSRQ_1_SI_X12(i1*8); \
+ VPINSRQ_1_SI_X11(i3*8); \
+ VINSERTI128 $1, X11, Y12, Y12
+
+// load msg: Y13 = (i0, i1, i2, i3)
+// i0, i1, i2, i3 must not be 0
+#define LOAD_MSG_AVX2_Y13(i0, i1, i2, i3) \
+ VMOVQ_SI_X13(i0*8); \
+ VMOVQ_SI_X11(i2*8); \
+ VPINSRQ_1_SI_X13(i1*8); \
+ VPINSRQ_1_SI_X11(i3*8); \
+ VINSERTI128 $1, X11, Y13, Y13
+
+// load msg: Y14 = (i0, i1, i2, i3)
+// i0, i1, i2, i3 must not be 0
+#define LOAD_MSG_AVX2_Y14(i0, i1, i2, i3) \
+ VMOVQ_SI_X14(i0*8); \
+ VMOVQ_SI_X11(i2*8); \
+ VPINSRQ_1_SI_X14(i1*8); \
+ VPINSRQ_1_SI_X11(i3*8); \
+ VINSERTI128 $1, X11, Y14, Y14
+
+// load msg: Y15 = (i0, i1, i2, i3)
+// i0, i1, i2, i3 must not be 0
+#define LOAD_MSG_AVX2_Y15(i0, i1, i2, i3) \
+ VMOVQ_SI_X15(i0*8); \
+ VMOVQ_SI_X11(i2*8); \
+ VPINSRQ_1_SI_X15(i1*8); \
+ VPINSRQ_1_SI_X11(i3*8); \
+ VINSERTI128 $1, X11, Y15, Y15
+
+#define LOAD_MSG_AVX2_0_2_4_6_1_3_5_7_8_10_12_14_9_11_13_15() \
+ VMOVQ_SI_X12_0; \
+ VMOVQ_SI_X11(4*8); \
+ VPINSRQ_1_SI_X12(2*8); \
+ VPINSRQ_1_SI_X11(6*8); \
+ VINSERTI128 $1, X11, Y12, Y12; \
+ LOAD_MSG_AVX2_Y13(1, 3, 5, 7); \
+ LOAD_MSG_AVX2_Y14(8, 10, 12, 14); \
+ LOAD_MSG_AVX2_Y15(9, 11, 13, 15)
+
+#define LOAD_MSG_AVX2_14_4_9_13_10_8_15_6_1_0_11_5_12_2_7_3() \
+ LOAD_MSG_AVX2_Y12(14, 4, 9, 13); \
+ LOAD_MSG_AVX2_Y13(10, 8, 15, 6); \
+ VMOVQ_SI_X11(11*8); \
+ VPSHUFD $0x4E, 0*8(SI), X14; \
+ VPINSRQ_1_SI_X11(5*8); \
+ VINSERTI128 $1, X11, Y14, Y14; \
+ LOAD_MSG_AVX2_Y15(12, 2, 7, 3)
+
+#define LOAD_MSG_AVX2_11_12_5_15_8_0_2_13_10_3_7_9_14_6_1_4() \
+ VMOVQ_SI_X11(5*8); \
+ VMOVDQU 11*8(SI), X12; \
+ VPINSRQ_1_SI_X11(15*8); \
+ VINSERTI128 $1, X11, Y12, Y12; \
+ VMOVQ_SI_X13(8*8); \
+ VMOVQ_SI_X11(2*8); \
+ VPINSRQ_1_SI_X13_0; \
+ VPINSRQ_1_SI_X11(13*8); \
+ VINSERTI128 $1, X11, Y13, Y13; \
+ LOAD_MSG_AVX2_Y14(10, 3, 7, 9); \
+ LOAD_MSG_AVX2_Y15(14, 6, 1, 4)
+
+#define LOAD_MSG_AVX2_7_3_13_11_9_1_12_14_2_5_4_15_6_10_0_8() \
+ LOAD_MSG_AVX2_Y12(7, 3, 13, 11); \
+ LOAD_MSG_AVX2_Y13(9, 1, 12, 14); \
+ LOAD_MSG_AVX2_Y14(2, 5, 4, 15); \
+ VMOVQ_SI_X15(6*8); \
+ VMOVQ_SI_X11_0; \
+ VPINSRQ_1_SI_X15(10*8); \
+ VPINSRQ_1_SI_X11(8*8); \
+ VINSERTI128 $1, X11, Y15, Y15
+
+#define LOAD_MSG_AVX2_9_5_2_10_0_7_4_15_14_11_6_3_1_12_8_13() \
+ LOAD_MSG_AVX2_Y12(9, 5, 2, 10); \
+ VMOVQ_SI_X13_0; \
+ VMOVQ_SI_X11(4*8); \
+ VPINSRQ_1_SI_X13(7*8); \
+ VPINSRQ_1_SI_X11(15*8); \
+ VINSERTI128 $1, X11, Y13, Y13; \
+ LOAD_MSG_AVX2_Y14(14, 11, 6, 3); \
+ LOAD_MSG_AVX2_Y15(1, 12, 8, 13)
+
+#define LOAD_MSG_AVX2_2_6_0_8_12_10_11_3_4_7_15_1_13_5_14_9() \
+ VMOVQ_SI_X12(2*8); \
+ VMOVQ_SI_X11_0; \
+ VPINSRQ_1_SI_X12(6*8); \
+ VPINSRQ_1_SI_X11(8*8); \
+ VINSERTI128 $1, X11, Y12, Y12; \
+ LOAD_MSG_AVX2_Y13(12, 10, 11, 3); \
+ LOAD_MSG_AVX2_Y14(4, 7, 15, 1); \
+ LOAD_MSG_AVX2_Y15(13, 5, 14, 9)
+
+#define LOAD_MSG_AVX2_12_1_14_4_5_15_13_10_0_6_9_8_7_3_2_11() \
+ LOAD_MSG_AVX2_Y12(12, 1, 14, 4); \
+ LOAD_MSG_AVX2_Y13(5, 15, 13, 10); \
+ VMOVQ_SI_X14_0; \
+ VPSHUFD $0x4E, 8*8(SI), X11; \
+ VPINSRQ_1_SI_X14(6*8); \
+ VINSERTI128 $1, X11, Y14, Y14; \
+ LOAD_MSG_AVX2_Y15(7, 3, 2, 11)
+
+#define LOAD_MSG_AVX2_13_7_12_3_11_14_1_9_5_15_8_2_0_4_6_10() \
+ LOAD_MSG_AVX2_Y12(13, 7, 12, 3); \
+ LOAD_MSG_AVX2_Y13(11, 14, 1, 9); \
+ LOAD_MSG_AVX2_Y14(5, 15, 8, 2); \
+ VMOVQ_SI_X15_0; \
+ VMOVQ_SI_X11(6*8); \
+ VPINSRQ_1_SI_X15(4*8); \
+ VPINSRQ_1_SI_X11(10*8); \
+ VINSERTI128 $1, X11, Y15, Y15
+
+#define LOAD_MSG_AVX2_6_14_11_0_15_9_3_8_12_13_1_10_2_7_4_5() \
+ VMOVQ_SI_X12(6*8); \
+ VMOVQ_SI_X11(11*8); \
+ VPINSRQ_1_SI_X12(14*8); \
+ VPINSRQ_1_SI_X11_0; \
+ VINSERTI128 $1, X11, Y12, Y12; \
+ LOAD_MSG_AVX2_Y13(15, 9, 3, 8); \
+ VMOVQ_SI_X11(1*8); \
+ VMOVDQU 12*8(SI), X14; \
+ VPINSRQ_1_SI_X11(10*8); \
+ VINSERTI128 $1, X11, Y14, Y14; \
+ VMOVQ_SI_X15(2*8); \
+ VMOVDQU 4*8(SI), X11; \
+ VPINSRQ_1_SI_X15(7*8); \
+ VINSERTI128 $1, X11, Y15, Y15
+
+#define LOAD_MSG_AVX2_10_8_7_1_2_4_6_5_15_9_3_13_11_14_12_0() \
+ LOAD_MSG_AVX2_Y12(10, 8, 7, 1); \
+ VMOVQ_SI_X13(2*8); \
+ VPSHUFD $0x4E, 5*8(SI), X11; \
+ VPINSRQ_1_SI_X13(4*8); \
+ VINSERTI128 $1, X11, Y13, Y13; \
+ LOAD_MSG_AVX2_Y14(15, 9, 3, 13); \
+ VMOVQ_SI_X15(11*8); \
+ VMOVQ_SI_X11(12*8); \
+ VPINSRQ_1_SI_X15(14*8); \
+ VPINSRQ_1_SI_X11_0; \
+ VINSERTI128 $1, X11, Y15, Y15
+
+// func hashBlocksAVX2(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte)
+TEXT ·hashBlocksAVX2(SB), 4, $320-48 // frame size = 288 + 32 byte alignment
+ MOVQ h+0(FP), AX
+ MOVQ c+8(FP), BX
+ MOVQ flag+16(FP), CX
+ MOVQ blocks_base+24(FP), SI
+ MOVQ blocks_len+32(FP), DI
+
+ MOVQ SP, DX
+ MOVQ SP, R9
+ ADDQ $31, R9
+ ANDQ $~31, R9
+ MOVQ R9, SP
+
+ MOVQ CX, 16(SP)
+ XORQ CX, CX
+ MOVQ CX, 24(SP)
+
+ VMOVDQU ·AVX2_c40<>(SB), Y4
+ VMOVDQU ·AVX2_c48<>(SB), Y5
+
+ VMOVDQU 0(AX), Y8
+ VMOVDQU 32(AX), Y9
+ VMOVDQU ·AVX2_iv0<>(SB), Y6
+ VMOVDQU ·AVX2_iv1<>(SB), Y7
+
+ MOVQ 0(BX), R8
+ MOVQ 8(BX), R9
+ MOVQ R9, 8(SP)
+
+loop:
+ ADDQ $128, R8
+ MOVQ R8, 0(SP)
+ CMPQ R8, $128
+ JGE noinc
+ INCQ R9
+ MOVQ R9, 8(SP)
+
+noinc:
+ VMOVDQA Y8, Y0
+ VMOVDQA Y9, Y1
+ VMOVDQA Y6, Y2
+ VPXOR 0(SP), Y7, Y3
+
+ LOAD_MSG_AVX2_0_2_4_6_1_3_5_7_8_10_12_14_9_11_13_15()
+ VMOVDQA Y12, 32(SP)
+ VMOVDQA Y13, 64(SP)
+ VMOVDQA Y14, 96(SP)
+ VMOVDQA Y15, 128(SP)
+ ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
+ LOAD_MSG_AVX2_14_4_9_13_10_8_15_6_1_0_11_5_12_2_7_3()
+ VMOVDQA Y12, 160(SP)
+ VMOVDQA Y13, 192(SP)
+ VMOVDQA Y14, 224(SP)
+ VMOVDQA Y15, 256(SP)
+
+ ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
+ LOAD_MSG_AVX2_11_12_5_15_8_0_2_13_10_3_7_9_14_6_1_4()
+ ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
+ LOAD_MSG_AVX2_7_3_13_11_9_1_12_14_2_5_4_15_6_10_0_8()
+ ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
+ LOAD_MSG_AVX2_9_5_2_10_0_7_4_15_14_11_6_3_1_12_8_13()
+ ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
+ LOAD_MSG_AVX2_2_6_0_8_12_10_11_3_4_7_15_1_13_5_14_9()
+ ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
+ LOAD_MSG_AVX2_12_1_14_4_5_15_13_10_0_6_9_8_7_3_2_11()
+ ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
+ LOAD_MSG_AVX2_13_7_12_3_11_14_1_9_5_15_8_2_0_4_6_10()
+ ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
+ LOAD_MSG_AVX2_6_14_11_0_15_9_3_8_12_13_1_10_2_7_4_5()
+ ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
+ LOAD_MSG_AVX2_10_8_7_1_2_4_6_5_15_9_3_13_11_14_12_0()
+ ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
+
+ ROUND_AVX2(32(SP), 64(SP), 96(SP), 128(SP), Y10, Y4, Y5)
+ ROUND_AVX2(160(SP), 192(SP), 224(SP), 256(SP), Y10, Y4, Y5)
+
+ VPXOR Y0, Y8, Y8
+ VPXOR Y1, Y9, Y9
+ VPXOR Y2, Y8, Y8
+ VPXOR Y3, Y9, Y9
+
+ LEAQ 128(SI), SI
+ SUBQ $128, DI
+ JNE loop
+
+ MOVQ R8, 0(BX)
+ MOVQ R9, 8(BX)
+
+ VMOVDQU Y8, 0(AX)
+ VMOVDQU Y9, 32(AX)
+ VZEROUPPER
+
+ MOVQ DX, SP
+ RET
+
+#define VPUNPCKLQDQ_X2_X2_X15 BYTE $0xC5; BYTE $0x69; BYTE $0x6C; BYTE $0xFA
+#define VPUNPCKLQDQ_X3_X3_X15 BYTE $0xC5; BYTE $0x61; BYTE $0x6C; BYTE $0xFB
+#define VPUNPCKLQDQ_X7_X7_X15 BYTE $0xC5; BYTE $0x41; BYTE $0x6C; BYTE $0xFF
+#define VPUNPCKLQDQ_X13_X13_X15 BYTE $0xC4; BYTE $0x41; BYTE $0x11; BYTE $0x6C; BYTE $0xFD
+#define VPUNPCKLQDQ_X14_X14_X15 BYTE $0xC4; BYTE $0x41; BYTE $0x09; BYTE $0x6C; BYTE $0xFE
+
+#define VPUNPCKHQDQ_X15_X2_X2 BYTE $0xC4; BYTE $0xC1; BYTE $0x69; BYTE $0x6D; BYTE $0xD7
+#define VPUNPCKHQDQ_X15_X3_X3 BYTE $0xC4; BYTE $0xC1; BYTE $0x61; BYTE $0x6D; BYTE $0xDF
+#define VPUNPCKHQDQ_X15_X6_X6 BYTE $0xC4; BYTE $0xC1; BYTE $0x49; BYTE $0x6D; BYTE $0xF7
+#define VPUNPCKHQDQ_X15_X7_X7 BYTE $0xC4; BYTE $0xC1; BYTE $0x41; BYTE $0x6D; BYTE $0xFF
+#define VPUNPCKHQDQ_X15_X3_X2 BYTE $0xC4; BYTE $0xC1; BYTE $0x61; BYTE $0x6D; BYTE $0xD7
+#define VPUNPCKHQDQ_X15_X7_X6 BYTE $0xC4; BYTE $0xC1; BYTE $0x41; BYTE $0x6D; BYTE $0xF7
+#define VPUNPCKHQDQ_X15_X13_X3 BYTE $0xC4; BYTE $0xC1; BYTE $0x11; BYTE $0x6D; BYTE $0xDF
+#define VPUNPCKHQDQ_X15_X13_X7 BYTE $0xC4; BYTE $0xC1; BYTE $0x11; BYTE $0x6D; BYTE $0xFF
+
+#define SHUFFLE_AVX() \
+ VMOVDQA X6, X13; \
+ VMOVDQA X2, X14; \
+ VMOVDQA X4, X6; \
+ VPUNPCKLQDQ_X13_X13_X15; \
+ VMOVDQA X5, X4; \
+ VMOVDQA X6, X5; \
+ VPUNPCKHQDQ_X15_X7_X6; \
+ VPUNPCKLQDQ_X7_X7_X15; \
+ VPUNPCKHQDQ_X15_X13_X7; \
+ VPUNPCKLQDQ_X3_X3_X15; \
+ VPUNPCKHQDQ_X15_X2_X2; \
+ VPUNPCKLQDQ_X14_X14_X15; \
+ VPUNPCKHQDQ_X15_X3_X3; \
+
+#define SHUFFLE_AVX_INV() \
+ VMOVDQA X2, X13; \
+ VMOVDQA X4, X14; \
+ VPUNPCKLQDQ_X2_X2_X15; \
+ VMOVDQA X5, X4; \
+ VPUNPCKHQDQ_X15_X3_X2; \
+ VMOVDQA X14, X5; \
+ VPUNPCKLQDQ_X3_X3_X15; \
+ VMOVDQA X6, X14; \
+ VPUNPCKHQDQ_X15_X13_X3; \
+ VPUNPCKLQDQ_X7_X7_X15; \
+ VPUNPCKHQDQ_X15_X6_X6; \
+ VPUNPCKLQDQ_X14_X14_X15; \
+ VPUNPCKHQDQ_X15_X7_X7; \
+
+#define HALF_ROUND_AVX(v0, v1, v2, v3, v4, v5, v6, v7, m0, m1, m2, m3, t0, c40, c48) \
+ VPADDQ m0, v0, v0; \
+ VPADDQ v2, v0, v0; \
+ VPADDQ m1, v1, v1; \
+ VPADDQ v3, v1, v1; \
+ VPXOR v0, v6, v6; \
+ VPXOR v1, v7, v7; \
+ VPSHUFD $-79, v6, v6; \
+ VPSHUFD $-79, v7, v7; \
+ VPADDQ v6, v4, v4; \
+ VPADDQ v7, v5, v5; \
+ VPXOR v4, v2, v2; \
+ VPXOR v5, v3, v3; \
+ VPSHUFB c40, v2, v2; \
+ VPSHUFB c40, v3, v3; \
+ VPADDQ m2, v0, v0; \
+ VPADDQ v2, v0, v0; \
+ VPADDQ m3, v1, v1; \
+ VPADDQ v3, v1, v1; \
+ VPXOR v0, v6, v6; \
+ VPXOR v1, v7, v7; \
+ VPSHUFB c48, v6, v6; \
+ VPSHUFB c48, v7, v7; \
+ VPADDQ v6, v4, v4; \
+ VPADDQ v7, v5, v5; \
+ VPXOR v4, v2, v2; \
+ VPXOR v5, v3, v3; \
+ VPADDQ v2, v2, t0; \
+ VPSRLQ $63, v2, v2; \
+ VPXOR t0, v2, v2; \
+ VPADDQ v3, v3, t0; \
+ VPSRLQ $63, v3, v3; \
+ VPXOR t0, v3, v3
+
+// load msg: X12 = (i0, i1), X13 = (i2, i3), X14 = (i4, i5), X15 = (i6, i7)
+// i0, i1, i2, i3, i4, i5, i6, i7 must not be 0
+#define LOAD_MSG_AVX(i0, i1, i2, i3, i4, i5, i6, i7) \
+ VMOVQ_SI_X12(i0*8); \
+ VMOVQ_SI_X13(i2*8); \
+ VMOVQ_SI_X14(i4*8); \
+ VMOVQ_SI_X15(i6*8); \
+ VPINSRQ_1_SI_X12(i1*8); \
+ VPINSRQ_1_SI_X13(i3*8); \
+ VPINSRQ_1_SI_X14(i5*8); \
+ VPINSRQ_1_SI_X15(i7*8)
+
+// load msg: X12 = (0, 2), X13 = (4, 6), X14 = (1, 3), X15 = (5, 7)
+#define LOAD_MSG_AVX_0_2_4_6_1_3_5_7() \
+ VMOVQ_SI_X12_0; \
+ VMOVQ_SI_X13(4*8); \
+ VMOVQ_SI_X14(1*8); \
+ VMOVQ_SI_X15(5*8); \
+ VPINSRQ_1_SI_X12(2*8); \
+ VPINSRQ_1_SI_X13(6*8); \
+ VPINSRQ_1_SI_X14(3*8); \
+ VPINSRQ_1_SI_X15(7*8)
+
+// load msg: X12 = (1, 0), X13 = (11, 5), X14 = (12, 2), X15 = (7, 3)
+#define LOAD_MSG_AVX_1_0_11_5_12_2_7_3() \
+ VPSHUFD $0x4E, 0*8(SI), X12; \
+ VMOVQ_SI_X13(11*8); \
+ VMOVQ_SI_X14(12*8); \
+ VMOVQ_SI_X15(7*8); \
+ VPINSRQ_1_SI_X13(5*8); \
+ VPINSRQ_1_SI_X14(2*8); \
+ VPINSRQ_1_SI_X15(3*8)
+
+// load msg: X12 = (11, 12), X13 = (5, 15), X14 = (8, 0), X15 = (2, 13)
+#define LOAD_MSG_AVX_11_12_5_15_8_0_2_13() \
+ VMOVDQU 11*8(SI), X12; \
+ VMOVQ_SI_X13(5*8); \
+ VMOVQ_SI_X14(8*8); \
+ VMOVQ_SI_X15(2*8); \
+ VPINSRQ_1_SI_X13(15*8); \
+ VPINSRQ_1_SI_X14_0; \
+ VPINSRQ_1_SI_X15(13*8)
+
+// load msg: X12 = (2, 5), X13 = (4, 15), X14 = (6, 10), X15 = (0, 8)
+#define LOAD_MSG_AVX_2_5_4_15_6_10_0_8() \
+ VMOVQ_SI_X12(2*8); \
+ VMOVQ_SI_X13(4*8); \
+ VMOVQ_SI_X14(6*8); \
+ VMOVQ_SI_X15_0; \
+ VPINSRQ_1_SI_X12(5*8); \
+ VPINSRQ_1_SI_X13(15*8); \
+ VPINSRQ_1_SI_X14(10*8); \
+ VPINSRQ_1_SI_X15(8*8)
+
+// load msg: X12 = (9, 5), X13 = (2, 10), X14 = (0, 7), X15 = (4, 15)
+#define LOAD_MSG_AVX_9_5_2_10_0_7_4_15() \
+ VMOVQ_SI_X12(9*8); \
+ VMOVQ_SI_X13(2*8); \
+ VMOVQ_SI_X14_0; \
+ VMOVQ_SI_X15(4*8); \
+ VPINSRQ_1_SI_X12(5*8); \
+ VPINSRQ_1_SI_X13(10*8); \
+ VPINSRQ_1_SI_X14(7*8); \
+ VPINSRQ_1_SI_X15(15*8)
+
+// load msg: X12 = (2, 6), X13 = (0, 8), X14 = (12, 10), X15 = (11, 3)
+#define LOAD_MSG_AVX_2_6_0_8_12_10_11_3() \
+ VMOVQ_SI_X12(2*8); \
+ VMOVQ_SI_X13_0; \
+ VMOVQ_SI_X14(12*8); \
+ VMOVQ_SI_X15(11*8); \
+ VPINSRQ_1_SI_X12(6*8); \
+ VPINSRQ_1_SI_X13(8*8); \
+ VPINSRQ_1_SI_X14(10*8); \
+ VPINSRQ_1_SI_X15(3*8)
+
+// load msg: X12 = (0, 6), X13 = (9, 8), X14 = (7, 3), X15 = (2, 11)
+#define LOAD_MSG_AVX_0_6_9_8_7_3_2_11() \
+ MOVQ 0*8(SI), X12; \
+ VPSHUFD $0x4E, 8*8(SI), X13; \
+ MOVQ 7*8(SI), X14; \
+ MOVQ 2*8(SI), X15; \
+ VPINSRQ_1_SI_X12(6*8); \
+ VPINSRQ_1_SI_X14(3*8); \
+ VPINSRQ_1_SI_X15(11*8)
+
+// load msg: X12 = (6, 14), X13 = (11, 0), X14 = (15, 9), X15 = (3, 8)
+#define LOAD_MSG_AVX_6_14_11_0_15_9_3_8() \
+ MOVQ 6*8(SI), X12; \
+ MOVQ 11*8(SI), X13; \
+ MOVQ 15*8(SI), X14; \
+ MOVQ 3*8(SI), X15; \
+ VPINSRQ_1_SI_X12(14*8); \
+ VPINSRQ_1_SI_X13_0; \
+ VPINSRQ_1_SI_X14(9*8); \
+ VPINSRQ_1_SI_X15(8*8)
+
+// load msg: X12 = (5, 15), X13 = (8, 2), X14 = (0, 4), X15 = (6, 10)
+#define LOAD_MSG_AVX_5_15_8_2_0_4_6_10() \
+ MOVQ 5*8(SI), X12; \
+ MOVQ 8*8(SI), X13; \
+ MOVQ 0*8(SI), X14; \
+ MOVQ 6*8(SI), X15; \
+ VPINSRQ_1_SI_X12(15*8); \
+ VPINSRQ_1_SI_X13(2*8); \
+ VPINSRQ_1_SI_X14(4*8); \
+ VPINSRQ_1_SI_X15(10*8)
+
+// load msg: X12 = (12, 13), X13 = (1, 10), X14 = (2, 7), X15 = (4, 5)
+#define LOAD_MSG_AVX_12_13_1_10_2_7_4_5() \
+ VMOVDQU 12*8(SI), X12; \
+ MOVQ 1*8(SI), X13; \
+ MOVQ 2*8(SI), X14; \
+ VPINSRQ_1_SI_X13(10*8); \
+ VPINSRQ_1_SI_X14(7*8); \
+ VMOVDQU 4*8(SI), X15
+
+// load msg: X12 = (15, 9), X13 = (3, 13), X14 = (11, 14), X15 = (12, 0)
+#define LOAD_MSG_AVX_15_9_3_13_11_14_12_0() \
+ MOVQ 15*8(SI), X12; \
+ MOVQ 3*8(SI), X13; \
+ MOVQ 11*8(SI), X14; \
+ MOVQ 12*8(SI), X15; \
+ VPINSRQ_1_SI_X12(9*8); \
+ VPINSRQ_1_SI_X13(13*8); \
+ VPINSRQ_1_SI_X14(14*8); \
+ VPINSRQ_1_SI_X15_0
+
+// func hashBlocksAVX(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte)
+TEXT ·hashBlocksAVX(SB), 4, $288-48 // frame size = 272 + 16 byte alignment
+ MOVQ h+0(FP), AX
+ MOVQ c+8(FP), BX
+ MOVQ flag+16(FP), CX
+ MOVQ blocks_base+24(FP), SI
+ MOVQ blocks_len+32(FP), DI
+
+ MOVQ SP, BP
+ MOVQ SP, R9
+ ADDQ $15, R9
+ ANDQ $~15, R9
+ MOVQ R9, SP
+
+ VMOVDQU ·AVX_c40<>(SB), X0
+ VMOVDQU ·AVX_c48<>(SB), X1
+ VMOVDQA X0, X8
+ VMOVDQA X1, X9
+
+ VMOVDQU ·AVX_iv3<>(SB), X0
+ VMOVDQA X0, 0(SP)
+ XORQ CX, 0(SP) // 0(SP) = ·AVX_iv3 ^ (CX || 0)
+
+ VMOVDQU 0(AX), X10
+ VMOVDQU 16(AX), X11
+ VMOVDQU 32(AX), X2
+ VMOVDQU 48(AX), X3
+
+ MOVQ 0(BX), R8
+ MOVQ 8(BX), R9
+
+loop:
+ ADDQ $128, R8
+ CMPQ R8, $128
+ JGE noinc
+ INCQ R9
+
+noinc:
+ VMOVQ_R8_X15
+ VPINSRQ_1_R9_X15
+
+ VMOVDQA X10, X0
+ VMOVDQA X11, X1
+ VMOVDQU ·AVX_iv0<>(SB), X4
+ VMOVDQU ·AVX_iv1<>(SB), X5
+ VMOVDQU ·AVX_iv2<>(SB), X6
+
+ VPXOR X15, X6, X6
+ VMOVDQA 0(SP), X7
+
+ LOAD_MSG_AVX_0_2_4_6_1_3_5_7()
+ VMOVDQA X12, 16(SP)
+ VMOVDQA X13, 32(SP)
+ VMOVDQA X14, 48(SP)
+ VMOVDQA X15, 64(SP)
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
+ SHUFFLE_AVX()
+ LOAD_MSG_AVX(8, 10, 12, 14, 9, 11, 13, 15)
+ VMOVDQA X12, 80(SP)
+ VMOVDQA X13, 96(SP)
+ VMOVDQA X14, 112(SP)
+ VMOVDQA X15, 128(SP)
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
+ SHUFFLE_AVX_INV()
+
+ LOAD_MSG_AVX(14, 4, 9, 13, 10, 8, 15, 6)
+ VMOVDQA X12, 144(SP)
+ VMOVDQA X13, 160(SP)
+ VMOVDQA X14, 176(SP)
+ VMOVDQA X15, 192(SP)
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
+ SHUFFLE_AVX()
+ LOAD_MSG_AVX_1_0_11_5_12_2_7_3()
+ VMOVDQA X12, 208(SP)
+ VMOVDQA X13, 224(SP)
+ VMOVDQA X14, 240(SP)
+ VMOVDQA X15, 256(SP)
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
+ SHUFFLE_AVX_INV()
+
+ LOAD_MSG_AVX_11_12_5_15_8_0_2_13()
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
+ SHUFFLE_AVX()
+ LOAD_MSG_AVX(10, 3, 7, 9, 14, 6, 1, 4)
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
+ SHUFFLE_AVX_INV()
+
+ LOAD_MSG_AVX(7, 3, 13, 11, 9, 1, 12, 14)
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
+ SHUFFLE_AVX()
+ LOAD_MSG_AVX_2_5_4_15_6_10_0_8()
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
+ SHUFFLE_AVX_INV()
+
+ LOAD_MSG_AVX_9_5_2_10_0_7_4_15()
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
+ SHUFFLE_AVX()
+ LOAD_MSG_AVX(14, 11, 6, 3, 1, 12, 8, 13)
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
+ SHUFFLE_AVX_INV()
+
+ LOAD_MSG_AVX_2_6_0_8_12_10_11_3()
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
+ SHUFFLE_AVX()
+ LOAD_MSG_AVX(4, 7, 15, 1, 13, 5, 14, 9)
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
+ SHUFFLE_AVX_INV()
+
+ LOAD_MSG_AVX(12, 1, 14, 4, 5, 15, 13, 10)
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
+ SHUFFLE_AVX()
+ LOAD_MSG_AVX_0_6_9_8_7_3_2_11()
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
+ SHUFFLE_AVX_INV()
+
+ LOAD_MSG_AVX(13, 7, 12, 3, 11, 14, 1, 9)
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
+ SHUFFLE_AVX()
+ LOAD_MSG_AVX_5_15_8_2_0_4_6_10()
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
+ SHUFFLE_AVX_INV()
+
+ LOAD_MSG_AVX_6_14_11_0_15_9_3_8()
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
+ SHUFFLE_AVX()
+ LOAD_MSG_AVX_12_13_1_10_2_7_4_5()
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
+ SHUFFLE_AVX_INV()
+
+ LOAD_MSG_AVX(10, 8, 7, 1, 2, 4, 6, 5)
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
+ SHUFFLE_AVX()
+ LOAD_MSG_AVX_15_9_3_13_11_14_12_0()
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
+ SHUFFLE_AVX_INV()
+
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 16(SP), 32(SP), 48(SP), 64(SP), X15, X8, X9)
+ SHUFFLE_AVX()
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 80(SP), 96(SP), 112(SP), 128(SP), X15, X8, X9)
+ SHUFFLE_AVX_INV()
+
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 144(SP), 160(SP), 176(SP), 192(SP), X15, X8, X9)
+ SHUFFLE_AVX()
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 208(SP), 224(SP), 240(SP), 256(SP), X15, X8, X9)
+ SHUFFLE_AVX_INV()
+
+ VMOVDQU 32(AX), X14
+ VMOVDQU 48(AX), X15
+ VPXOR X0, X10, X10
+ VPXOR X1, X11, X11
+ VPXOR X2, X14, X14
+ VPXOR X3, X15, X15
+ VPXOR X4, X10, X10
+ VPXOR X5, X11, X11
+ VPXOR X6, X14, X2
+ VPXOR X7, X15, X3
+ VMOVDQU X2, 32(AX)
+ VMOVDQU X3, 48(AX)
+
+ LEAQ 128(SI), SI
+ SUBQ $128, DI
+ JNE loop
+
+ VMOVDQU X10, 0(AX)
+ VMOVDQU X11, 16(AX)
+
+ MOVQ R8, 0(BX)
+ MOVQ R9, 8(BX)
+ VZEROUPPER
+
+ MOVQ BP, SP
+ RET
+
+// func supportsAVX2() bool
+TEXT ·supportsAVX2(SB), 4, $0-1
+ MOVQ runtime·support_avx2(SB), AX
+ MOVB AX, ret+0(FP)
+ RET
+
+// func supportsAVX() bool
+TEXT ·supportsAVX(SB), 4, $0-1
+ MOVQ runtime·support_avx(SB), AX
+ MOVB AX, ret+0(FP)
+ RET
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.go
new file mode 100644
index 000000000..2ab7c30fc
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.go
@@ -0,0 +1,25 @@
+// 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.
+
+// +build !go1.7,amd64,!gccgo,!appengine
+
+package blake2b
+
+func init() {
+ useSSE4 = supportsSSE4()
+}
+
+//go:noescape
+func supportsSSE4() bool
+
+//go:noescape
+func hashBlocksSSE4(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte)
+
+func hashBlocks(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) {
+ if useSSE4 {
+ hashBlocksSSE4(h, c, flag, blocks)
+ } else {
+ hashBlocksGeneric(h, c, flag, blocks)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.s b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.s
new file mode 100644
index 000000000..64530740b
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.s
@@ -0,0 +1,290 @@
+// 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.
+
+// +build amd64,!gccgo,!appengine
+
+#include "textflag.h"
+
+DATA ·iv0<>+0x00(SB)/8, $0x6a09e667f3bcc908
+DATA ·iv0<>+0x08(SB)/8, $0xbb67ae8584caa73b
+GLOBL ·iv0<>(SB), (NOPTR+RODATA), $16
+
+DATA ·iv1<>+0x00(SB)/8, $0x3c6ef372fe94f82b
+DATA ·iv1<>+0x08(SB)/8, $0xa54ff53a5f1d36f1
+GLOBL ·iv1<>(SB), (NOPTR+RODATA), $16
+
+DATA ·iv2<>+0x00(SB)/8, $0x510e527fade682d1
+DATA ·iv2<>+0x08(SB)/8, $0x9b05688c2b3e6c1f
+GLOBL ·iv2<>(SB), (NOPTR+RODATA), $16
+
+DATA ·iv3<>+0x00(SB)/8, $0x1f83d9abfb41bd6b
+DATA ·iv3<>+0x08(SB)/8, $0x5be0cd19137e2179
+GLOBL ·iv3<>(SB), (NOPTR+RODATA), $16
+
+DATA ·c40<>+0x00(SB)/8, $0x0201000706050403
+DATA ·c40<>+0x08(SB)/8, $0x0a09080f0e0d0c0b
+GLOBL ·c40<>(SB), (NOPTR+RODATA), $16
+
+DATA ·c48<>+0x00(SB)/8, $0x0100070605040302
+DATA ·c48<>+0x08(SB)/8, $0x09080f0e0d0c0b0a
+GLOBL ·c48<>(SB), (NOPTR+RODATA), $16
+
+#define SHUFFLE(v2, v3, v4, v5, v6, v7, t1, t2) \
+ MOVO v4, t1; \
+ MOVO v5, v4; \
+ MOVO t1, v5; \
+ MOVO v6, t1; \
+ PUNPCKLQDQ v6, t2; \
+ PUNPCKHQDQ v7, v6; \
+ PUNPCKHQDQ t2, v6; \
+ PUNPCKLQDQ v7, t2; \
+ MOVO t1, v7; \
+ MOVO v2, t1; \
+ PUNPCKHQDQ t2, v7; \
+ PUNPCKLQDQ v3, t2; \
+ PUNPCKHQDQ t2, v2; \
+ PUNPCKLQDQ t1, t2; \
+ PUNPCKHQDQ t2, v3
+
+#define SHUFFLE_INV(v2, v3, v4, v5, v6, v7, t1, t2) \
+ MOVO v4, t1; \
+ MOVO v5, v4; \
+ MOVO t1, v5; \
+ MOVO v2, t1; \
+ PUNPCKLQDQ v2, t2; \
+ PUNPCKHQDQ v3, v2; \
+ PUNPCKHQDQ t2, v2; \
+ PUNPCKLQDQ v3, t2; \
+ MOVO t1, v3; \
+ MOVO v6, t1; \
+ PUNPCKHQDQ t2, v3; \
+ PUNPCKLQDQ v7, t2; \
+ PUNPCKHQDQ t2, v6; \
+ PUNPCKLQDQ t1, t2; \
+ PUNPCKHQDQ t2, v7
+
+#define HALF_ROUND(v0, v1, v2, v3, v4, v5, v6, v7, m0, m1, m2, m3, t0, c40, c48) \
+ PADDQ m0, v0; \
+ PADDQ m1, v1; \
+ PADDQ v2, v0; \
+ PADDQ v3, v1; \
+ PXOR v0, v6; \
+ PXOR v1, v7; \
+ PSHUFD $0xB1, v6, v6; \
+ PSHUFD $0xB1, v7, v7; \
+ PADDQ v6, v4; \
+ PADDQ v7, v5; \
+ PXOR v4, v2; \
+ PXOR v5, v3; \
+ PSHUFB c40, v2; \
+ PSHUFB c40, v3; \
+ PADDQ m2, v0; \
+ PADDQ m3, v1; \
+ PADDQ v2, v0; \
+ PADDQ v3, v1; \
+ PXOR v0, v6; \
+ PXOR v1, v7; \
+ PSHUFB c48, v6; \
+ PSHUFB c48, v7; \
+ PADDQ v6, v4; \
+ PADDQ v7, v5; \
+ PXOR v4, v2; \
+ PXOR v5, v3; \
+ MOVOU v2, t0; \
+ PADDQ v2, t0; \
+ PSRLQ $63, v2; \
+ PXOR t0, v2; \
+ MOVOU v3, t0; \
+ PADDQ v3, t0; \
+ PSRLQ $63, v3; \
+ PXOR t0, v3
+
+#define LOAD_MSG(m0, m1, m2, m3, src, i0, i1, i2, i3, i4, i5, i6, i7) \
+ MOVQ i0*8(src), m0; \
+ PINSRQ $1, i1*8(src), m0; \
+ MOVQ i2*8(src), m1; \
+ PINSRQ $1, i3*8(src), m1; \
+ MOVQ i4*8(src), m2; \
+ PINSRQ $1, i5*8(src), m2; \
+ MOVQ i6*8(src), m3; \
+ PINSRQ $1, i7*8(src), m3
+
+// func hashBlocksSSE4(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte)
+TEXT ·hashBlocksSSE4(SB), 4, $288-48 // frame size = 272 + 16 byte alignment
+ MOVQ h+0(FP), AX
+ MOVQ c+8(FP), BX
+ MOVQ flag+16(FP), CX
+ MOVQ blocks_base+24(FP), SI
+ MOVQ blocks_len+32(FP), DI
+
+ MOVQ SP, BP
+ MOVQ SP, R9
+ ADDQ $15, R9
+ ANDQ $~15, R9
+ MOVQ R9, SP
+
+ MOVOU ·iv3<>(SB), X0
+ MOVO X0, 0(SP)
+ XORQ CX, 0(SP) // 0(SP) = ·iv3 ^ (CX || 0)
+
+ MOVOU ·c40<>(SB), X13
+ MOVOU ·c48<>(SB), X14
+
+ MOVOU 0(AX), X12
+ MOVOU 16(AX), X15
+
+ MOVQ 0(BX), R8
+ MOVQ 8(BX), R9
+
+loop:
+ ADDQ $128, R8
+ CMPQ R8, $128
+ JGE noinc
+ INCQ R9
+
+noinc:
+ MOVQ R8, X8
+ PINSRQ $1, R9, X8
+
+ MOVO X12, X0
+ MOVO X15, X1
+ MOVOU 32(AX), X2
+ MOVOU 48(AX), X3
+ MOVOU ·iv0<>(SB), X4
+ MOVOU ·iv1<>(SB), X5
+ MOVOU ·iv2<>(SB), X6
+
+ PXOR X8, X6
+ MOVO 0(SP), X7
+
+ LOAD_MSG(X8, X9, X10, X11, SI, 0, 2, 4, 6, 1, 3, 5, 7)
+ MOVO X8, 16(SP)
+ MOVO X9, 32(SP)
+ MOVO X10, 48(SP)
+ MOVO X11, 64(SP)
+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9)
+ LOAD_MSG(X8, X9, X10, X11, SI, 8, 10, 12, 14, 9, 11, 13, 15)
+ MOVO X8, 80(SP)
+ MOVO X9, 96(SP)
+ MOVO X10, 112(SP)
+ MOVO X11, 128(SP)
+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9)
+
+ LOAD_MSG(X8, X9, X10, X11, SI, 14, 4, 9, 13, 10, 8, 15, 6)
+ MOVO X8, 144(SP)
+ MOVO X9, 160(SP)
+ MOVO X10, 176(SP)
+ MOVO X11, 192(SP)
+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9)
+ LOAD_MSG(X8, X9, X10, X11, SI, 1, 0, 11, 5, 12, 2, 7, 3)
+ MOVO X8, 208(SP)
+ MOVO X9, 224(SP)
+ MOVO X10, 240(SP)
+ MOVO X11, 256(SP)
+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9)
+
+ LOAD_MSG(X8, X9, X10, X11, SI, 11, 12, 5, 15, 8, 0, 2, 13)
+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9)
+ LOAD_MSG(X8, X9, X10, X11, SI, 10, 3, 7, 9, 14, 6, 1, 4)
+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9)
+
+ LOAD_MSG(X8, X9, X10, X11, SI, 7, 3, 13, 11, 9, 1, 12, 14)
+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9)
+ LOAD_MSG(X8, X9, X10, X11, SI, 2, 5, 4, 15, 6, 10, 0, 8)
+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9)
+
+ LOAD_MSG(X8, X9, X10, X11, SI, 9, 5, 2, 10, 0, 7, 4, 15)
+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9)
+ LOAD_MSG(X8, X9, X10, X11, SI, 14, 11, 6, 3, 1, 12, 8, 13)
+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9)
+
+ LOAD_MSG(X8, X9, X10, X11, SI, 2, 6, 0, 8, 12, 10, 11, 3)
+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9)
+ LOAD_MSG(X8, X9, X10, X11, SI, 4, 7, 15, 1, 13, 5, 14, 9)
+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9)
+
+ LOAD_MSG(X8, X9, X10, X11, SI, 12, 1, 14, 4, 5, 15, 13, 10)
+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9)
+ LOAD_MSG(X8, X9, X10, X11, SI, 0, 6, 9, 8, 7, 3, 2, 11)
+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9)
+
+ LOAD_MSG(X8, X9, X10, X11, SI, 13, 7, 12, 3, 11, 14, 1, 9)
+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9)
+ LOAD_MSG(X8, X9, X10, X11, SI, 5, 15, 8, 2, 0, 4, 6, 10)
+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9)
+
+ LOAD_MSG(X8, X9, X10, X11, SI, 6, 14, 11, 0, 15, 9, 3, 8)
+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9)
+ LOAD_MSG(X8, X9, X10, X11, SI, 12, 13, 1, 10, 2, 7, 4, 5)
+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9)
+
+ LOAD_MSG(X8, X9, X10, X11, SI, 10, 8, 7, 1, 2, 4, 6, 5)
+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9)
+ LOAD_MSG(X8, X9, X10, X11, SI, 15, 9, 3, 13, 11, 14, 12, 0)
+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9)
+
+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, 16(SP), 32(SP), 48(SP), 64(SP), X11, X13, X14)
+ SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9)
+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, 80(SP), 96(SP), 112(SP), 128(SP), X11, X13, X14)
+ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9)
+
+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, 144(SP), 160(SP), 176(SP), 192(SP), X11, X13, X14)
+ SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9)
+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, 208(SP), 224(SP), 240(SP), 256(SP), X11, X13, X14)
+ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9)
+
+ MOVOU 32(AX), X10
+ MOVOU 48(AX), X11
+ PXOR X0, X12
+ PXOR X1, X15
+ PXOR X2, X10
+ PXOR X3, X11
+ PXOR X4, X12
+ PXOR X5, X15
+ PXOR X6, X10
+ PXOR X7, X11
+ MOVOU X10, 32(AX)
+ MOVOU X11, 48(AX)
+
+ LEAQ 128(SI), SI
+ SUBQ $128, DI
+ JNE loop
+
+ MOVOU X12, 0(AX)
+ MOVOU X15, 16(AX)
+
+ MOVQ R8, 0(BX)
+ MOVQ R9, 8(BX)
+
+ MOVQ BP, SP
+ RET
+
+// func supportsSSE4() bool
+TEXT ·supportsSSE4(SB), 4, $0-1
+ MOVL $1, AX
+ CPUID
+ SHRL $19, CX // Bit 19 indicates SSE4 support
+ ANDL $1, CX // CX != 0 if support SSE4
+ MOVB CX, ret+0(FP)
+ RET
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2b/blake2b_generic.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2b/blake2b_generic.go
new file mode 100644
index 000000000..4bd2abc91
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2b/blake2b_generic.go
@@ -0,0 +1,179 @@
+// 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.
+
+package blake2b
+
+import "encoding/binary"
+
+// the precomputed values for BLAKE2b
+// there are 12 16-byte arrays - one for each round
+// the entries are calculated from the sigma constants.
+var precomputed = [12][16]byte{
+ {0, 2, 4, 6, 1, 3, 5, 7, 8, 10, 12, 14, 9, 11, 13, 15},
+ {14, 4, 9, 13, 10, 8, 15, 6, 1, 0, 11, 5, 12, 2, 7, 3},
+ {11, 12, 5, 15, 8, 0, 2, 13, 10, 3, 7, 9, 14, 6, 1, 4},
+ {7, 3, 13, 11, 9, 1, 12, 14, 2, 5, 4, 15, 6, 10, 0, 8},
+ {9, 5, 2, 10, 0, 7, 4, 15, 14, 11, 6, 3, 1, 12, 8, 13},
+ {2, 6, 0, 8, 12, 10, 11, 3, 4, 7, 15, 1, 13, 5, 14, 9},
+ {12, 1, 14, 4, 5, 15, 13, 10, 0, 6, 9, 8, 7, 3, 2, 11},
+ {13, 7, 12, 3, 11, 14, 1, 9, 5, 15, 8, 2, 0, 4, 6, 10},
+ {6, 14, 11, 0, 15, 9, 3, 8, 12, 13, 1, 10, 2, 7, 4, 5},
+ {10, 8, 7, 1, 2, 4, 6, 5, 15, 9, 3, 13, 11, 14, 12, 0},
+ {0, 2, 4, 6, 1, 3, 5, 7, 8, 10, 12, 14, 9, 11, 13, 15}, // equal to the first
+ {14, 4, 9, 13, 10, 8, 15, 6, 1, 0, 11, 5, 12, 2, 7, 3}, // equal to the second
+}
+
+func hashBlocksGeneric(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) {
+ var m [16]uint64
+ c0, c1 := c[0], c[1]
+
+ for i := 0; i < len(blocks); {
+ c0 += BlockSize
+ if c0 < BlockSize {
+ c1++
+ }
+
+ v0, v1, v2, v3, v4, v5, v6, v7 := h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7]
+ v8, v9, v10, v11, v12, v13, v14, v15 := iv[0], iv[1], iv[2], iv[3], iv[4], iv[5], iv[6], iv[7]
+ v12 ^= c0
+ v13 ^= c1
+ v14 ^= flag
+
+ for j := range m {
+ m[j] = binary.LittleEndian.Uint64(blocks[i:])
+ i += 8
+ }
+
+ for j := range precomputed {
+ s := &(precomputed[j])
+
+ v0 += m[s[0]]
+ v0 += v4
+ v12 ^= v0
+ v12 = v12<<(64-32) | v12>>32
+ v8 += v12
+ v4 ^= v8
+ v4 = v4<<(64-24) | v4>>24
+ v1 += m[s[1]]
+ v1 += v5
+ v13 ^= v1
+ v13 = v13<<(64-32) | v13>>32
+ v9 += v13
+ v5 ^= v9
+ v5 = v5<<(64-24) | v5>>24
+ v2 += m[s[2]]
+ v2 += v6
+ v14 ^= v2
+ v14 = v14<<(64-32) | v14>>32
+ v10 += v14
+ v6 ^= v10
+ v6 = v6<<(64-24) | v6>>24
+ v3 += m[s[3]]
+ v3 += v7
+ v15 ^= v3
+ v15 = v15<<(64-32) | v15>>32
+ v11 += v15
+ v7 ^= v11
+ v7 = v7<<(64-24) | v7>>24
+
+ v0 += m[s[4]]
+ v0 += v4
+ v12 ^= v0
+ v12 = v12<<(64-16) | v12>>16
+ v8 += v12
+ v4 ^= v8
+ v4 = v4<<(64-63) | v4>>63
+ v1 += m[s[5]]
+ v1 += v5
+ v13 ^= v1
+ v13 = v13<<(64-16) | v13>>16
+ v9 += v13
+ v5 ^= v9
+ v5 = v5<<(64-63) | v5>>63
+ v2 += m[s[6]]
+ v2 += v6
+ v14 ^= v2
+ v14 = v14<<(64-16) | v14>>16
+ v10 += v14
+ v6 ^= v10
+ v6 = v6<<(64-63) | v6>>63
+ v3 += m[s[7]]
+ v3 += v7
+ v15 ^= v3
+ v15 = v15<<(64-16) | v15>>16
+ v11 += v15
+ v7 ^= v11
+ v7 = v7<<(64-63) | v7>>63
+
+ v0 += m[s[8]]
+ v0 += v5
+ v15 ^= v0
+ v15 = v15<<(64-32) | v15>>32
+ v10 += v15
+ v5 ^= v10
+ v5 = v5<<(64-24) | v5>>24
+ v1 += m[s[9]]
+ v1 += v6
+ v12 ^= v1
+ v12 = v12<<(64-32) | v12>>32
+ v11 += v12
+ v6 ^= v11
+ v6 = v6<<(64-24) | v6>>24
+ v2 += m[s[10]]
+ v2 += v7
+ v13 ^= v2
+ v13 = v13<<(64-32) | v13>>32
+ v8 += v13
+ v7 ^= v8
+ v7 = v7<<(64-24) | v7>>24
+ v3 += m[s[11]]
+ v3 += v4
+ v14 ^= v3
+ v14 = v14<<(64-32) | v14>>32
+ v9 += v14
+ v4 ^= v9
+ v4 = v4<<(64-24) | v4>>24
+
+ v0 += m[s[12]]
+ v0 += v5
+ v15 ^= v0
+ v15 = v15<<(64-16) | v15>>16
+ v10 += v15
+ v5 ^= v10
+ v5 = v5<<(64-63) | v5>>63
+ v1 += m[s[13]]
+ v1 += v6
+ v12 ^= v1
+ v12 = v12<<(64-16) | v12>>16
+ v11 += v12
+ v6 ^= v11
+ v6 = v6<<(64-63) | v6>>63
+ v2 += m[s[14]]
+ v2 += v7
+ v13 ^= v2
+ v13 = v13<<(64-16) | v13>>16
+ v8 += v13
+ v7 ^= v8
+ v7 = v7<<(64-63) | v7>>63
+ v3 += m[s[15]]
+ v3 += v4
+ v14 ^= v3
+ v14 = v14<<(64-16) | v14>>16
+ v9 += v14
+ v4 ^= v9
+ v4 = v4<<(64-63) | v4>>63
+
+ }
+
+ h[0] ^= v0 ^ v8
+ h[1] ^= v1 ^ v9
+ h[2] ^= v2 ^ v10
+ h[3] ^= v3 ^ v11
+ h[4] ^= v4 ^ v12
+ h[5] ^= v5 ^ v13
+ h[6] ^= v6 ^ v14
+ h[7] ^= v7 ^ v15
+ }
+ c[0], c[1] = c0, c1
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2b/blake2b_ref.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2b/blake2b_ref.go
new file mode 100644
index 000000000..da156a1ba
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2b/blake2b_ref.go
@@ -0,0 +1,11 @@
+// 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.
+
+// +build !amd64 appengine gccgo
+
+package blake2b
+
+func hashBlocks(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) {
+ hashBlocksGeneric(h, c, flag, blocks)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2b/blake2b_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2b/blake2b_test.go
new file mode 100644
index 000000000..5d68bbf60
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2b/blake2b_test.go
@@ -0,0 +1,798 @@
+// 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.
+
+package blake2b
+
+import (
+ "bytes"
+ "encoding/hex"
+ "fmt"
+ "hash"
+ "io"
+ "testing"
+)
+
+func fromHex(s string) []byte {
+ b, err := hex.DecodeString(s)
+ if err != nil {
+ panic(err)
+ }
+ return b
+}
+
+func TestHashes(t *testing.T) {
+ defer func(sse4, avx, avx2 bool) {
+ useSSE4, useAVX, useAVX2 = sse4, avx, avx2
+ }(useSSE4, useAVX, useAVX2)
+
+ if useAVX2 {
+ t.Log("AVX2 version")
+ testHashes(t)
+ useAVX2 = false
+ }
+ if useAVX {
+ t.Log("AVX version")
+ testHashes(t)
+ useAVX = false
+ }
+ if useSSE4 {
+ t.Log("SSE4 version")
+ testHashes(t)
+ useSSE4 = false
+ }
+ t.Log("generic version")
+ testHashes(t)
+}
+
+func TestHashes2X(t *testing.T) {
+ defer func(sse4, avx, avx2 bool) {
+ useSSE4, useAVX, useAVX2 = sse4, avx, avx2
+ }(useSSE4, useAVX, useAVX2)
+
+ if useAVX2 {
+ t.Log("AVX2 version")
+ testHashes2X(t)
+ useAVX2 = false
+ }
+ if useAVX {
+ t.Log("AVX version")
+ testHashes2X(t)
+ useAVX = false
+ }
+ if useSSE4 {
+ t.Log("SSE4 version")
+ testHashes2X(t)
+ useSSE4 = false
+ }
+ t.Log("generic version")
+ testHashes2X(t)
+}
+
+func testHashes(t *testing.T) {
+ key, _ := hex.DecodeString("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f")
+
+ input := make([]byte, 255)
+ for i := range input {
+ input[i] = byte(i)
+ }
+
+ for i, expectedHex := range hashes {
+ h, err := New512(key)
+ if err != nil {
+ t.Fatalf("#%d: error from New512: %v", i, err)
+ }
+
+ h.Write(input[:i])
+ sum := h.Sum(nil)
+
+ if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex {
+ t.Fatalf("#%d (single write): got %s, wanted %s", i, gotHex, expectedHex)
+ }
+
+ h.Reset()
+ for j := 0; j < i; j++ {
+ h.Write(input[j : j+1])
+ }
+
+ sum = h.Sum(sum[:0])
+ if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex {
+ t.Fatalf("#%d (byte-by-byte): got %s, wanted %s", i, gotHex, expectedHex)
+ }
+ }
+}
+
+func testHashes2X(t *testing.T) {
+ key, _ := hex.DecodeString("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f")
+
+ input := make([]byte, 256)
+ for i := range input {
+ input[i] = byte(i)
+ }
+
+ for i, expectedHex := range hashes2X {
+ length := uint32(len(expectedHex) / 2)
+ sum := make([]byte, int(length))
+
+ h, err := NewXOF(length, key)
+ if err != nil {
+ t.Fatalf("#%d: error from NewXOF: %v", i, err)
+ }
+
+ if _, err := h.Write(input); err != nil {
+ t.Fatalf("#%d (single write): error from Write: %v", i, err)
+ }
+ if _, err := h.Read(sum); err != nil {
+ t.Fatalf("#%d (single write): error from Read: %v", i, err)
+ }
+ if n, err := h.Read(sum); n != 0 || err != io.EOF {
+ t.Fatalf("#%d (single write): Read did not return (0, io.EOF) after exhaustion, got (%v, %v)", i, n, err)
+ }
+ if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex {
+ t.Fatalf("#%d (single write): got %s, wanted %s", i, gotHex, expectedHex)
+ }
+
+ h.Reset()
+ for j := 0; j < len(input); j++ {
+ h.Write(input[j : j+1])
+ }
+ for j := 0; j < len(sum); j++ {
+ h = h.Clone()
+ if _, err := h.Read(sum[j : j+1]); err != nil {
+ t.Fatalf("#%d (byte-by-byte) - Read %d: error from Read: %v", i, j, err)
+ }
+ }
+ if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex {
+ t.Fatalf("#%d (byte-by-byte): got %s, wanted %s", i, gotHex, expectedHex)
+ }
+ }
+
+ h, err := NewXOF(OutputLengthUnknown, key)
+ if err != nil {
+ t.Fatalf("#unknown length: error from NewXOF: %v", err)
+ }
+ if _, err := h.Write(input); err != nil {
+ t.Fatalf("#unknown length: error from Write: %v", err)
+ }
+
+ var result [64]byte
+ if n, err := h.Read(result[:]); err != nil {
+ t.Fatalf("#unknown length: error from Read: %v", err)
+ } else if n != len(result) {
+ t.Fatalf("#unknown length: Read returned %d bytes, want %d", n, len(result))
+ }
+
+ const expected = "3dbba8516da76bf7330055c66ea36cf1005e92714262b24d9710f51d9e126406e1bcd6497059f9331f1091c3634b695428d475ed432f987040575520a1c29f5e"
+ if fmt.Sprintf("%x", result) != expected {
+ t.Fatalf("#unknown length: bad result %x, wanted %s", result, expected)
+ }
+}
+
+func generateSequence(out []byte, seed uint32) {
+ a := 0xDEAD4BAD * seed // prime
+ b := uint32(1)
+
+ for i := range out { // fill the buf
+ a, b = b, a+b
+ out[i] = byte(b >> 24)
+ }
+}
+
+func computeMAC(msg []byte, hashSize int, key []byte) (sum []byte) {
+ var h hash.Hash
+ switch hashSize {
+ case Size:
+ h, _ = New512(key)
+ case Size384:
+ h, _ = New384(key)
+ case Size256:
+ h, _ = New256(key)
+ case 20:
+ h, _ = newDigest(20, key)
+ default:
+ panic("unexpected hashSize")
+ }
+
+ h.Write(msg)
+ return h.Sum(sum)
+}
+
+func computeHash(msg []byte, hashSize int) (sum []byte) {
+ switch hashSize {
+ case Size:
+ hash := Sum512(msg)
+ return hash[:]
+ case Size384:
+ hash := Sum384(msg)
+ return hash[:]
+ case Size256:
+ hash := Sum256(msg)
+ return hash[:]
+ case 20:
+ var hash [64]byte
+ checkSum(&hash, 20, msg)
+ return hash[:20]
+ default:
+ panic("unexpected hashSize")
+ }
+}
+
+// Test function from RFC 7693.
+func TestSelfTest(t *testing.T) {
+ hashLens := [4]int{20, 32, 48, 64}
+ msgLens := [6]int{0, 3, 128, 129, 255, 1024}
+
+ msg := make([]byte, 1024)
+ key := make([]byte, 64)
+
+ h, _ := New256(nil)
+ for _, hashSize := range hashLens {
+ for _, msgLength := range msgLens {
+ generateSequence(msg[:msgLength], uint32(msgLength)) // unkeyed hash
+
+ md := computeHash(msg[:msgLength], hashSize)
+ h.Write(md)
+
+ generateSequence(key[:], uint32(hashSize)) // keyed hash
+ md = computeMAC(msg[:msgLength], hashSize, key[:hashSize])
+ h.Write(md)
+ }
+ }
+
+ sum := h.Sum(nil)
+ expected := [32]byte{
+ 0xc2, 0x3a, 0x78, 0x00, 0xd9, 0x81, 0x23, 0xbd,
+ 0x10, 0xf5, 0x06, 0xc6, 0x1e, 0x29, 0xda, 0x56,
+ 0x03, 0xd7, 0x63, 0xb8, 0xbb, 0xad, 0x2e, 0x73,
+ 0x7f, 0x5e, 0x76, 0x5a, 0x7b, 0xcc, 0xd4, 0x75,
+ }
+ if !bytes.Equal(sum, expected[:]) {
+ t.Fatalf("got %x, wanted %x", sum, expected)
+ }
+}
+
+// Benchmarks
+
+func benchmarkSum(b *testing.B, size int) {
+ data := make([]byte, size)
+ b.SetBytes(int64(size))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ Sum512(data)
+ }
+}
+
+func benchmarkWrite(b *testing.B, size int) {
+ data := make([]byte, size)
+ h, _ := New512(nil)
+ b.SetBytes(int64(size))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ h.Write(data)
+ }
+}
+
+func BenchmarkWrite128(b *testing.B) { benchmarkWrite(b, 128) }
+func BenchmarkWrite1K(b *testing.B) { benchmarkWrite(b, 1024) }
+
+func BenchmarkSum128(b *testing.B) { benchmarkSum(b, 128) }
+func BenchmarkSum1K(b *testing.B) { benchmarkSum(b, 1024) }
+
+// These values were taken from https://blake2.net/blake2b-test.txt.
+var hashes = []string{
+ "10ebb67700b1868efb4417987acf4690ae9d972fb7a590c2f02871799aaa4786b5e996e8f0f4eb981fc214b005f42d2ff4233499391653df7aefcbc13fc51568",
+ "961f6dd1e4dd30f63901690c512e78e4b45e4742ed197c3c5e45c549fd25f2e4187b0bc9fe30492b16b0d0bc4ef9b0f34c7003fac09a5ef1532e69430234cebd",
+ "da2cfbe2d8409a0f38026113884f84b50156371ae304c4430173d08a99d9fb1b983164a3770706d537f49e0c916d9f32b95cc37a95b99d857436f0232c88a965",
+ "33d0825dddf7ada99b0e7e307104ad07ca9cfd9692214f1561356315e784f3e5a17e364ae9dbb14cb2036df932b77f4b292761365fb328de7afdc6d8998f5fc1",
+ "beaa5a3d08f3807143cf621d95cd690514d0b49efff9c91d24b59241ec0eefa5f60196d407048bba8d2146828ebcb0488d8842fd56bb4f6df8e19c4b4daab8ac",
+ "098084b51fd13deae5f4320de94a688ee07baea2800486689a8636117b46c1f4c1f6af7f74ae7c857600456a58a3af251dc4723a64cc7c0a5ab6d9cac91c20bb",
+ "6044540d560853eb1c57df0077dd381094781cdb9073e5b1b3d3f6c7829e12066bbaca96d989a690de72ca3133a83652ba284a6d62942b271ffa2620c9e75b1f",
+ "7a8cfe9b90f75f7ecb3acc053aaed6193112b6f6a4aeeb3f65d3de541942deb9e2228152a3c4bbbe72fc3b12629528cfbb09fe630f0474339f54abf453e2ed52",
+ "380beaf6ea7cc9365e270ef0e6f3a64fb902acae51dd5512f84259ad2c91f4bc4108db73192a5bbfb0cbcf71e46c3e21aee1c5e860dc96e8eb0b7b8426e6abe9",
+ "60fe3c4535e1b59d9a61ea8500bfac41a69dffb1ceadd9aca323e9a625b64da5763bad7226da02b9c8c4f1a5de140ac5a6c1124e4f718ce0b28ea47393aa6637",
+ "4fe181f54ad63a2983feaaf77d1e7235c2beb17fa328b6d9505bda327df19fc37f02c4b6f0368ce23147313a8e5738b5fa2a95b29de1c7f8264eb77b69f585cd",
+ "f228773ce3f3a42b5f144d63237a72d99693adb8837d0e112a8a0f8ffff2c362857ac49c11ec740d1500749dac9b1f4548108bf3155794dcc9e4082849e2b85b",
+ "962452a8455cc56c8511317e3b1f3b2c37df75f588e94325fdd77070359cf63a9ae6e930936fdf8e1e08ffca440cfb72c28f06d89a2151d1c46cd5b268ef8563",
+ "43d44bfa18768c59896bf7ed1765cb2d14af8c260266039099b25a603e4ddc5039d6ef3a91847d1088d401c0c7e847781a8a590d33a3c6cb4df0fab1c2f22355",
+ "dcffa9d58c2a4ca2cdbb0c7aa4c4c1d45165190089f4e983bb1c2cab4aaeff1fa2b5ee516fecd780540240bf37e56c8bcca7fab980e1e61c9400d8a9a5b14ac6",
+ "6fbf31b45ab0c0b8dad1c0f5f4061379912dde5aa922099a030b725c73346c524291adef89d2f6fd8dfcda6d07dad811a9314536c2915ed45da34947e83de34e",
+ "a0c65bddde8adef57282b04b11e7bc8aab105b99231b750c021f4a735cb1bcfab87553bba3abb0c3e64a0b6955285185a0bd35fb8cfde557329bebb1f629ee93",
+ "f99d815550558e81eca2f96718aed10d86f3f1cfb675cce06b0eff02f617c5a42c5aa760270f2679da2677c5aeb94f1142277f21c7f79f3c4f0cce4ed8ee62b1",
+ "95391da8fc7b917a2044b3d6f5374e1ca072b41454d572c7356c05fd4bc1e0f40b8bb8b4a9f6bce9be2c4623c399b0dca0dab05cb7281b71a21b0ebcd9e55670",
+ "04b9cd3d20d221c09ac86913d3dc63041989a9a1e694f1e639a3ba7e451840f750c2fc191d56ad61f2e7936bc0ac8e094b60caeed878c18799045402d61ceaf9",
+ "ec0e0ef707e4ed6c0c66f9e089e4954b058030d2dd86398fe84059631f9ee591d9d77375355149178c0cf8f8e7c49ed2a5e4f95488a2247067c208510fadc44c",
+ "9a37cce273b79c09913677510eaf7688e89b3314d3532fd2764c39de022a2945b5710d13517af8ddc0316624e73bec1ce67df15228302036f330ab0cb4d218dd",
+ "4cf9bb8fb3d4de8b38b2f262d3c40f46dfe747e8fc0a414c193d9fcf753106ce47a18f172f12e8a2f1c26726545358e5ee28c9e2213a8787aafbc516d2343152",
+ "64e0c63af9c808fd893137129867fd91939d53f2af04be4fa268006100069b2d69daa5c5d8ed7fddcb2a70eeecdf2b105dd46a1e3b7311728f639ab489326bc9",
+ "5e9c93158d659b2def06b0c3c7565045542662d6eee8a96a89b78ade09fe8b3dcc096d4fe48815d88d8f82620156602af541955e1f6ca30dce14e254c326b88f",
+ "7775dff889458dd11aef417276853e21335eb88e4dec9cfb4e9edb49820088551a2ca60339f12066101169f0dfe84b098fddb148d9da6b3d613df263889ad64b",
+ "f0d2805afbb91f743951351a6d024f9353a23c7ce1fc2b051b3a8b968c233f46f50f806ecb1568ffaa0b60661e334b21dde04f8fa155ac740eeb42e20b60d764",
+ "86a2af316e7d7754201b942e275364ac12ea8962ab5bd8d7fb276dc5fbffc8f9a28cae4e4867df6780d9b72524160927c855da5b6078e0b554aa91e31cb9ca1d",
+ "10bdf0caa0802705e706369baf8a3f79d72c0a03a80675a7bbb00be3a45e516424d1ee88efb56f6d5777545ae6e27765c3a8f5e493fc308915638933a1dfee55",
+ "b01781092b1748459e2e4ec178696627bf4ebafebba774ecf018b79a68aeb84917bf0b84bb79d17b743151144cd66b7b33a4b9e52c76c4e112050ff5385b7f0b",
+ "c6dbc61dec6eaeac81e3d5f755203c8e220551534a0b2fd105a91889945a638550204f44093dd998c076205dffad703a0e5cd3c7f438a7e634cd59fededb539e",
+ "eba51acffb4cea31db4b8d87e9bf7dd48fe97b0253ae67aa580f9ac4a9d941f2bea518ee286818cc9f633f2a3b9fb68e594b48cdd6d515bf1d52ba6c85a203a7",
+ "86221f3ada52037b72224f105d7999231c5e5534d03da9d9c0a12acb68460cd375daf8e24386286f9668f72326dbf99ba094392437d398e95bb8161d717f8991",
+ "5595e05c13a7ec4dc8f41fb70cb50a71bce17c024ff6de7af618d0cc4e9c32d9570d6d3ea45b86525491030c0d8f2b1836d5778c1ce735c17707df364d054347",
+ "ce0f4f6aca89590a37fe034dd74dd5fa65eb1cbd0a41508aaddc09351a3cea6d18cb2189c54b700c009f4cbf0521c7ea01be61c5ae09cb54f27bc1b44d658c82",
+ "7ee80b06a215a3bca970c77cda8761822bc103d44fa4b33f4d07dcb997e36d55298bceae12241b3fa07fa63be5576068da387b8d5859aeab701369848b176d42",
+ "940a84b6a84d109aab208c024c6ce9647676ba0aaa11f86dbb7018f9fd2220a6d901a9027f9abcf935372727cbf09ebd61a2a2eeb87653e8ecad1bab85dc8327",
+ "2020b78264a82d9f4151141adba8d44bf20c5ec062eee9b595a11f9e84901bf148f298e0c9f8777dcdbc7cc4670aac356cc2ad8ccb1629f16f6a76bcefbee760",
+ "d1b897b0e075ba68ab572adf9d9c436663e43eb3d8e62d92fc49c9be214e6f27873fe215a65170e6bea902408a25b49506f47babd07cecf7113ec10c5dd31252",
+ "b14d0c62abfa469a357177e594c10c194243ed2025ab8aa5ad2fa41ad318e0ff48cd5e60bec07b13634a711d2326e488a985f31e31153399e73088efc86a5c55",
+ "4169c5cc808d2697dc2a82430dc23e3cd356dc70a94566810502b8d655b39abf9e7f902fe717e0389219859e1945df1af6ada42e4ccda55a197b7100a30c30a1",
+ "258a4edb113d66c839c8b1c91f15f35ade609f11cd7f8681a4045b9fef7b0b24c82cda06a5f2067b368825e3914e53d6948ede92efd6e8387fa2e537239b5bee",
+ "79d2d8696d30f30fb34657761171a11e6c3f1e64cbe7bebee159cb95bfaf812b4f411e2f26d9c421dc2c284a3342d823ec293849e42d1e46b0a4ac1e3c86abaa",
+ "8b9436010dc5dee992ae38aea97f2cd63b946d94fedd2ec9671dcde3bd4ce9564d555c66c15bb2b900df72edb6b891ebcadfeff63c9ea4036a998be7973981e7",
+ "c8f68e696ed28242bf997f5b3b34959508e42d613810f1e2a435c96ed2ff560c7022f361a9234b9837feee90bf47922ee0fd5f8ddf823718d86d1e16c6090071",
+ "b02d3eee4860d5868b2c39ce39bfe81011290564dd678c85e8783f29302dfc1399ba95b6b53cd9ebbf400cca1db0ab67e19a325f2d115812d25d00978ad1bca4",
+ "7693ea73af3ac4dad21ca0d8da85b3118a7d1c6024cfaf557699868217bc0c2f44a199bc6c0edd519798ba05bd5b1b4484346a47c2cadf6bf30b785cc88b2baf",
+ "a0e5c1c0031c02e48b7f09a5e896ee9aef2f17fc9e18e997d7f6cac7ae316422c2b1e77984e5f3a73cb45deed5d3f84600105e6ee38f2d090c7d0442ea34c46d",
+ "41daa6adcfdb69f1440c37b596440165c15ada596813e2e22f060fcd551f24dee8e04ba6890387886ceec4a7a0d7fc6b44506392ec3822c0d8c1acfc7d5aebe8",
+ "14d4d40d5984d84c5cf7523b7798b254e275a3a8cc0a1bd06ebc0bee726856acc3cbf516ff667cda2058ad5c3412254460a82c92187041363cc77a4dc215e487",
+ "d0e7a1e2b9a447fee83e2277e9ff8010c2f375ae12fa7aaa8ca5a6317868a26a367a0b69fbc1cf32a55d34eb370663016f3d2110230eba754028a56f54acf57c",
+ "e771aa8db5a3e043e8178f39a0857ba04a3f18e4aa05743cf8d222b0b095825350ba422f63382a23d92e4149074e816a36c1cd28284d146267940b31f8818ea2",
+ "feb4fd6f9e87a56bef398b3284d2bda5b5b0e166583a66b61e538457ff0584872c21a32962b9928ffab58de4af2edd4e15d8b35570523207ff4e2a5aa7754caa",
+ "462f17bf005fb1c1b9e671779f665209ec2873e3e411f98dabf240a1d5ec3f95ce6796b6fc23fe171903b502023467dec7273ff74879b92967a2a43a5a183d33",
+ "d3338193b64553dbd38d144bea71c5915bb110e2d88180dbc5db364fd6171df317fc7268831b5aef75e4342b2fad8797ba39eddcef80e6ec08159350b1ad696d",
+ "e1590d585a3d39f7cb599abd479070966409a6846d4377acf4471d065d5db94129cc9be92573b05ed226be1e9b7cb0cabe87918589f80dadd4ef5ef25a93d28e",
+ "f8f3726ac5a26cc80132493a6fedcb0e60760c09cfc84cad178175986819665e76842d7b9fedf76dddebf5d3f56faaad4477587af21606d396ae570d8e719af2",
+ "30186055c07949948183c850e9a756cc09937e247d9d928e869e20bafc3cd9721719d34e04a0899b92c736084550186886efba2e790d8be6ebf040b209c439a4",
+ "f3c4276cb863637712c241c444c5cc1e3554e0fddb174d035819dd83eb700b4ce88df3ab3841ba02085e1a99b4e17310c5341075c0458ba376c95a6818fbb3e2",
+ "0aa007c4dd9d5832393040a1583c930bca7dc5e77ea53add7e2b3f7c8e231368043520d4a3ef53c969b6bbfd025946f632bd7f765d53c21003b8f983f75e2a6a",
+ "08e9464720533b23a04ec24f7ae8c103145f765387d738777d3d343477fd1c58db052142cab754ea674378e18766c53542f71970171cc4f81694246b717d7564",
+ "d37ff7ad297993e7ec21e0f1b4b5ae719cdc83c5db687527f27516cbffa822888a6810ee5c1ca7bfe3321119be1ab7bfa0a502671c8329494df7ad6f522d440f",
+ "dd9042f6e464dcf86b1262f6accfafbd8cfd902ed3ed89abf78ffa482dbdeeb6969842394c9a1168ae3d481a017842f660002d42447c6b22f7b72f21aae021c9",
+ "bd965bf31e87d70327536f2a341cebc4768eca275fa05ef98f7f1b71a0351298de006fba73fe6733ed01d75801b4a928e54231b38e38c562b2e33ea1284992fa",
+ "65676d800617972fbd87e4b9514e1c67402b7a331096d3bfac22f1abb95374abc942f16e9ab0ead33b87c91968a6e509e119ff07787b3ef483e1dcdccf6e3022",
+ "939fa189699c5d2c81ddd1ffc1fa207c970b6a3685bb29ce1d3e99d42f2f7442da53e95a72907314f4588399a3ff5b0a92beb3f6be2694f9f86ecf2952d5b41c",
+ "c516541701863f91005f314108ceece3c643e04fc8c42fd2ff556220e616aaa6a48aeb97a84bad74782e8dff96a1a2fa949339d722edcaa32b57067041df88cc",
+ "987fd6e0d6857c553eaebb3d34970a2c2f6e89a3548f492521722b80a1c21a153892346d2cba6444212d56da9a26e324dccbc0dcde85d4d2ee4399eec5a64e8f",
+ "ae56deb1c2328d9c4017706bce6e99d41349053ba9d336d677c4c27d9fd50ae6aee17e853154e1f4fe7672346da2eaa31eea53fcf24a22804f11d03da6abfc2b",
+ "49d6a608c9bde4491870498572ac31aac3fa40938b38a7818f72383eb040ad39532bc06571e13d767e6945ab77c0bdc3b0284253343f9f6c1244ebf2ff0df866",
+ "da582ad8c5370b4469af862aa6467a2293b2b28bd80ae0e91f425ad3d47249fdf98825cc86f14028c3308c9804c78bfeeeee461444ce243687e1a50522456a1d",
+ "d5266aa3331194aef852eed86d7b5b2633a0af1c735906f2e13279f14931a9fc3b0eac5ce9245273bd1aa92905abe16278ef7efd47694789a7283b77da3c70f8",
+ "2962734c28252186a9a1111c732ad4de4506d4b4480916303eb7991d659ccda07a9911914bc75c418ab7a4541757ad054796e26797feaf36e9f6ad43f14b35a4",
+ "e8b79ec5d06e111bdfafd71e9f5760f00ac8ac5d8bf768f9ff6f08b8f026096b1cc3a4c973333019f1e3553e77da3f98cb9f542e0a90e5f8a940cc58e59844b3",
+ "dfb320c44f9d41d1efdcc015f08dd5539e526e39c87d509ae6812a969e5431bf4fa7d91ffd03b981e0d544cf72d7b1c0374f8801482e6dea2ef903877eba675e",
+ "d88675118fdb55a5fb365ac2af1d217bf526ce1ee9c94b2f0090b2c58a06ca58187d7fe57c7bed9d26fca067b4110eefcd9a0a345de872abe20de368001b0745",
+ "b893f2fc41f7b0dd6e2f6aa2e0370c0cff7df09e3acfcc0e920b6e6fad0ef747c40668417d342b80d2351e8c175f20897a062e9765e6c67b539b6ba8b9170545",
+ "6c67ec5697accd235c59b486d7b70baeedcbd4aa64ebd4eef3c7eac189561a726250aec4d48cadcafbbe2ce3c16ce2d691a8cce06e8879556d4483ed7165c063",
+ "f1aa2b044f8f0c638a3f362e677b5d891d6fd2ab0765f6ee1e4987de057ead357883d9b405b9d609eea1b869d97fb16d9b51017c553f3b93c0a1e0f1296fedcd",
+ "cbaa259572d4aebfc1917acddc582b9f8dfaa928a198ca7acd0f2aa76a134a90252e6298a65b08186a350d5b7626699f8cb721a3ea5921b753ae3a2dce24ba3a",
+ "fa1549c9796cd4d303dcf452c1fbd5744fd9b9b47003d920b92de34839d07ef2a29ded68f6fc9e6c45e071a2e48bd50c5084e96b657dd0404045a1ddefe282ed",
+ "5cf2ac897ab444dcb5c8d87c495dbdb34e1838b6b629427caa51702ad0f9688525f13bec503a3c3a2c80a65e0b5715e8afab00ffa56ec455a49a1ad30aa24fcd",
+ "9aaf80207bace17bb7ab145757d5696bde32406ef22b44292ef65d4519c3bb2ad41a59b62cc3e94b6fa96d32a7faadae28af7d35097219aa3fd8cda31e40c275",
+ "af88b163402c86745cb650c2988fb95211b94b03ef290eed9662034241fd51cf398f8073e369354c43eae1052f9b63b08191caa138aa54fea889cc7024236897",
+ "48fa7d64e1ceee27b9864db5ada4b53d00c9bc7626555813d3cd6730ab3cc06ff342d727905e33171bde6e8476e77fb1720861e94b73a2c538d254746285f430",
+ "0e6fd97a85e904f87bfe85bbeb34f69e1f18105cf4ed4f87aec36c6e8b5f68bd2a6f3dc8a9ecb2b61db4eedb6b2ea10bf9cb0251fb0f8b344abf7f366b6de5ab",
+ "06622da5787176287fdc8fed440bad187d830099c94e6d04c8e9c954cda70c8bb9e1fc4a6d0baa831b9b78ef6648681a4867a11da93ee36e5e6a37d87fc63f6f",
+ "1da6772b58fabf9c61f68d412c82f182c0236d7d575ef0b58dd22458d643cd1dfc93b03871c316d8430d312995d4197f0874c99172ba004a01ee295abac24e46",
+ "3cd2d9320b7b1d5fb9aab951a76023fa667be14a9124e394513918a3f44096ae4904ba0ffc150b63bc7ab1eeb9a6e257e5c8f000a70394a5afd842715de15f29",
+ "04cdc14f7434e0b4be70cb41db4c779a88eaef6accebcb41f2d42fffe7f32a8e281b5c103a27021d0d08362250753cdf70292195a53a48728ceb5844c2d98bab",
+ "9071b7a8a075d0095b8fb3ae5113785735ab98e2b52faf91d5b89e44aac5b5d4ebbf91223b0ff4c71905da55342e64655d6ef8c89a4768c3f93a6dc0366b5bc8",
+ "ebb30240dd96c7bc8d0abe49aa4edcbb4afdc51ff9aaf720d3f9e7fbb0f9c6d6571350501769fc4ebd0b2141247ff400d4fd4be414edf37757bb90a32ac5c65a",
+ "8532c58bf3c8015d9d1cbe00eef1f5082f8f3632fbe9f1ed4f9dfb1fa79e8283066d77c44c4af943d76b300364aecbd0648c8a8939bd204123f4b56260422dec",
+ "fe9846d64f7c7708696f840e2d76cb4408b6595c2f81ec6a28a7f2f20cb88cfe6ac0b9e9b8244f08bd7095c350c1d0842f64fb01bb7f532dfcd47371b0aeeb79",
+ "28f17ea6fb6c42092dc264257e29746321fb5bdaea9873c2a7fa9d8f53818e899e161bc77dfe8090afd82bf2266c5c1bc930a8d1547624439e662ef695f26f24",
+ "ec6b7d7f030d4850acae3cb615c21dd25206d63e84d1db8d957370737ba0e98467ea0ce274c66199901eaec18a08525715f53bfdb0aacb613d342ebdceeddc3b",
+ "b403d3691c03b0d3418df327d5860d34bbfcc4519bfbce36bf33b208385fadb9186bc78a76c489d89fd57e7dc75412d23bcd1dae8470ce9274754bb8585b13c5",
+ "31fc79738b8772b3f55cd8178813b3b52d0db5a419d30ba9495c4b9da0219fac6df8e7c23a811551a62b827f256ecdb8124ac8a6792ccfecc3b3012722e94463",
+ "bb2039ec287091bcc9642fc90049e73732e02e577e2862b32216ae9bedcd730c4c284ef3968c368b7d37584f97bd4b4dc6ef6127acfe2e6ae2509124e66c8af4",
+ "f53d68d13f45edfcb9bd415e2831e938350d5380d3432278fc1c0c381fcb7c65c82dafe051d8c8b0d44e0974a0e59ec7bf7ed0459f86e96f329fc79752510fd3",
+ "8d568c7984f0ecdf7640fbc483b5d8c9f86634f6f43291841b309a350ab9c1137d24066b09da9944bac54d5bb6580d836047aac74ab724b887ebf93d4b32eca9",
+ "c0b65ce5a96ff774c456cac3b5f2c4cd359b4ff53ef93a3da0778be4900d1e8da1601e769e8f1b02d2a2f8c5b9fa10b44f1c186985468feeb008730283a6657d",
+ "4900bba6f5fb103ece8ec96ada13a5c3c85488e05551da6b6b33d988e611ec0fe2e3c2aa48ea6ae8986a3a231b223c5d27cec2eadde91ce07981ee652862d1e4",
+ "c7f5c37c7285f927f76443414d4357ff789647d7a005a5a787e03c346b57f49f21b64fa9cf4b7e45573e23049017567121a9c3d4b2b73ec5e9413577525db45a",
+ "ec7096330736fdb2d64b5653e7475da746c23a4613a82687a28062d3236364284ac01720ffb406cfe265c0df626a188c9e5963ace5d3d5bb363e32c38c2190a6",
+ "82e744c75f4649ec52b80771a77d475a3bc091989556960e276a5f9ead92a03f718742cdcfeaee5cb85c44af198adc43a4a428f5f0c2ddb0be36059f06d7df73",
+ "2834b7a7170f1f5b68559ab78c1050ec21c919740b784a9072f6e5d69f828d70c919c5039fb148e39e2c8a52118378b064ca8d5001cd10a5478387b966715ed6",
+ "16b4ada883f72f853bb7ef253efcab0c3e2161687ad61543a0d2824f91c1f81347d86be709b16996e17f2dd486927b0288ad38d13063c4a9672c39397d3789b6",
+ "78d048f3a69d8b54ae0ed63a573ae350d89f7c6cf1f3688930de899afa037697629b314e5cd303aa62feea72a25bf42b304b6c6bcb27fae21c16d925e1fbdac3",
+ "0f746a48749287ada77a82961f05a4da4abdb7d77b1220f836d09ec814359c0ec0239b8c7b9ff9e02f569d1b301ef67c4612d1de4f730f81c12c40cc063c5caa",
+ "f0fc859d3bd195fbdc2d591e4cdac15179ec0f1dc821c11df1f0c1d26e6260aaa65b79fafacafd7d3ad61e600f250905f5878c87452897647a35b995bcadc3a3",
+ "2620f687e8625f6a412460b42e2cef67634208ce10a0cbd4dff7044a41b7880077e9f8dc3b8d1216d3376a21e015b58fb279b521d83f9388c7382c8505590b9b",
+ "227e3aed8d2cb10b918fcb04f9de3e6d0a57e08476d93759cd7b2ed54a1cbf0239c528fb04bbf288253e601d3bc38b21794afef90b17094a182cac557745e75f",
+ "1a929901b09c25f27d6b35be7b2f1c4745131fdebca7f3e2451926720434e0db6e74fd693ad29b777dc3355c592a361c4873b01133a57c2e3b7075cbdb86f4fc",
+ "5fd7968bc2fe34f220b5e3dc5af9571742d73b7d60819f2888b629072b96a9d8ab2d91b82d0a9aaba61bbd39958132fcc4257023d1eca591b3054e2dc81c8200",
+ "dfcce8cf32870cc6a503eadafc87fd6f78918b9b4d0737db6810be996b5497e7e5cc80e312f61e71ff3e9624436073156403f735f56b0b01845c18f6caf772e6",
+ "02f7ef3a9ce0fff960f67032b296efca3061f4934d690749f2d01c35c81c14f39a67fa350bc8a0359bf1724bffc3bca6d7c7bba4791fd522a3ad353c02ec5aa8",
+ "64be5c6aba65d594844ae78bb022e5bebe127fd6b6ffa5a13703855ab63b624dcd1a363f99203f632ec386f3ea767fc992e8ed9686586aa27555a8599d5b808f",
+ "f78585505c4eaa54a8b5be70a61e735e0ff97af944ddb3001e35d86c4e2199d976104b6ae31750a36a726ed285064f5981b503889fef822fcdc2898dddb7889a",
+ "e4b5566033869572edfd87479a5bb73c80e8759b91232879d96b1dda36c012076ee5a2ed7ae2de63ef8406a06aea82c188031b560beafb583fb3de9e57952a7e",
+ "e1b3e7ed867f6c9484a2a97f7715f25e25294e992e41f6a7c161ffc2adc6daaeb7113102d5e6090287fe6ad94ce5d6b739c6ca240b05c76fb73f25dd024bf935",
+ "85fd085fdc12a080983df07bd7012b0d402a0f4043fcb2775adf0bad174f9b08d1676e476985785c0a5dcc41dbff6d95ef4d66a3fbdc4a74b82ba52da0512b74",
+ "aed8fa764b0fbff821e05233d2f7b0900ec44d826f95e93c343c1bc3ba5a24374b1d616e7e7aba453a0ada5e4fab5382409e0d42ce9c2bc7fb39a99c340c20f0",
+ "7ba3b2e297233522eeb343bd3ebcfd835a04007735e87f0ca300cbee6d416565162171581e4020ff4cf176450f1291ea2285cb9ebffe4c56660627685145051c",
+ "de748bcf89ec88084721e16b85f30adb1a6134d664b5843569babc5bbd1a15ca9b61803c901a4fef32965a1749c9f3a4e243e173939dc5a8dc495c671ab52145",
+ "aaf4d2bdf200a919706d9842dce16c98140d34bc433df320aba9bd429e549aa7a3397652a4d768277786cf993cde2338673ed2e6b66c961fefb82cd20c93338f",
+ "c408218968b788bf864f0997e6bc4c3dba68b276e2125a4843296052ff93bf5767b8cdce7131f0876430c1165fec6c4f47adaa4fd8bcfacef463b5d3d0fa61a0",
+ "76d2d819c92bce55fa8e092ab1bf9b9eab237a25267986cacf2b8ee14d214d730dc9a5aa2d7b596e86a1fd8fa0804c77402d2fcd45083688b218b1cdfa0dcbcb",
+ "72065ee4dd91c2d8509fa1fc28a37c7fc9fa7d5b3f8ad3d0d7a25626b57b1b44788d4caf806290425f9890a3a2a35a905ab4b37acfd0da6e4517b2525c9651e4",
+ "64475dfe7600d7171bea0b394e27c9b00d8e74dd1e416a79473682ad3dfdbb706631558055cfc8a40e07bd015a4540dcdea15883cbbf31412df1de1cd4152b91",
+ "12cd1674a4488a5d7c2b3160d2e2c4b58371bedad793418d6f19c6ee385d70b3e06739369d4df910edb0b0a54cbff43d54544cd37ab3a06cfa0a3ddac8b66c89",
+ "60756966479dedc6dd4bcff8ea7d1d4ce4d4af2e7b097e32e3763518441147cc12b3c0ee6d2ecabf1198cec92e86a3616fba4f4e872f5825330adbb4c1dee444",
+ "a7803bcb71bc1d0f4383dde1e0612e04f872b715ad30815c2249cf34abb8b024915cb2fc9f4e7cc4c8cfd45be2d5a91eab0941c7d270e2da4ca4a9f7ac68663a",
+ "b84ef6a7229a34a750d9a98ee2529871816b87fbe3bc45b45fa5ae82d5141540211165c3c5d7a7476ba5a4aa06d66476f0d9dc49a3f1ee72c3acabd498967414",
+ "fae4b6d8efc3f8c8e64d001dabec3a21f544e82714745251b2b4b393f2f43e0da3d403c64db95a2cb6e23ebb7b9e94cdd5ddac54f07c4a61bd3cb10aa6f93b49",
+ "34f7286605a122369540141ded79b8957255da2d4155abbf5a8dbb89c8eb7ede8eeef1daa46dc29d751d045dc3b1d658bb64b80ff8589eddb3824b13da235a6b",
+ "3b3b48434be27b9eababba43bf6b35f14b30f6a88dc2e750c358470d6b3aa3c18e47db4017fa55106d8252f016371a00f5f8b070b74ba5f23cffc5511c9f09f0",
+ "ba289ebd6562c48c3e10a8ad6ce02e73433d1e93d7c9279d4d60a7e879ee11f441a000f48ed9f7c4ed87a45136d7dccdca482109c78a51062b3ba4044ada2469",
+ "022939e2386c5a37049856c850a2bb10a13dfea4212b4c732a8840a9ffa5faf54875c5448816b2785a007da8a8d2bc7d71a54e4e6571f10b600cbdb25d13ede3",
+ "e6fec19d89ce8717b1a087024670fe026f6c7cbda11caef959bb2d351bf856f8055d1c0ebdaaa9d1b17886fc2c562b5e99642fc064710c0d3488a02b5ed7f6fd",
+ "94c96f02a8f576aca32ba61c2b206f907285d9299b83ac175c209a8d43d53bfe683dd1d83e7549cb906c28f59ab7c46f8751366a28c39dd5fe2693c9019666c8",
+ "31a0cd215ebd2cb61de5b9edc91e6195e31c59a5648d5c9f737e125b2605708f2e325ab3381c8dce1a3e958886f1ecdc60318f882cfe20a24191352e617b0f21",
+ "91ab504a522dce78779f4c6c6ba2e6b6db5565c76d3e7e7c920caf7f757ef9db7c8fcf10e57f03379ea9bf75eb59895d96e149800b6aae01db778bb90afbc989",
+ "d85cabc6bd5b1a01a5afd8c6734740da9fd1c1acc6db29bfc8a2e5b668b028b6b3154bfb8703fa3180251d589ad38040ceb707c4bad1b5343cb426b61eaa49c1",
+ "d62efbec2ca9c1f8bd66ce8b3f6a898cb3f7566ba6568c618ad1feb2b65b76c3ce1dd20f7395372faf28427f61c9278049cf0140df434f5633048c86b81e0399",
+ "7c8fdc6175439e2c3db15bafa7fb06143a6a23bc90f449e79deef73c3d492a671715c193b6fea9f036050b946069856b897e08c00768f5ee5ddcf70b7cd6d0e0",
+ "58602ee7468e6bc9df21bd51b23c005f72d6cb013f0a1b48cbec5eca299299f97f09f54a9a01483eaeb315a6478bad37ba47ca1347c7c8fc9e6695592c91d723",
+ "27f5b79ed256b050993d793496edf4807c1d85a7b0a67c9c4fa99860750b0ae66989670a8ffd7856d7ce411599e58c4d77b232a62bef64d15275be46a68235ff",
+ "3957a976b9f1887bf004a8dca942c92d2b37ea52600f25e0c9bc5707d0279c00c6e85a839b0d2d8eb59c51d94788ebe62474a791cadf52cccf20f5070b6573fc",
+ "eaa2376d55380bf772ecca9cb0aa4668c95c707162fa86d518c8ce0ca9bf7362b9f2a0adc3ff59922df921b94567e81e452f6c1a07fc817cebe99604b3505d38",
+ "c1e2c78b6b2734e2480ec550434cb5d613111adcc21d475545c3b1b7e6ff12444476e5c055132e2229dc0f807044bb919b1a5662dd38a9ee65e243a3911aed1a",
+ "8ab48713389dd0fcf9f965d3ce66b1e559a1f8c58741d67683cd971354f452e62d0207a65e436c5d5d8f8ee71c6abfe50e669004c302b31a7ea8311d4a916051",
+ "24ce0addaa4c65038bd1b1c0f1452a0b128777aabc94a29df2fd6c7e2f85f8ab9ac7eff516b0e0a825c84a24cfe492eaad0a6308e46dd42fe8333ab971bb30ca",
+ "5154f929ee03045b6b0c0004fa778edee1d139893267cc84825ad7b36c63de32798e4a166d24686561354f63b00709a1364b3c241de3febf0754045897467cd4",
+ "e74e907920fd87bd5ad636dd11085e50ee70459c443e1ce5809af2bc2eba39f9e6d7128e0e3712c316da06f4705d78a4838e28121d4344a2c79c5e0db307a677",
+ "bf91a22334bac20f3fd80663b3cd06c4e8802f30e6b59f90d3035cc9798a217ed5a31abbda7fa6842827bdf2a7a1c21f6fcfccbb54c6c52926f32da816269be1",
+ "d9d5c74be5121b0bd742f26bffb8c89f89171f3f934913492b0903c271bbe2b3395ef259669bef43b57f7fcc3027db01823f6baee66e4f9fead4d6726c741fce",
+ "50c8b8cf34cd879f80e2faab3230b0c0e1cc3e9dcadeb1b9d97ab923415dd9a1fe38addd5c11756c67990b256e95ad6d8f9fedce10bf1c90679cde0ecf1be347",
+ "0a386e7cd5dd9b77a035e09fe6fee2c8ce61b5383c87ea43205059c5e4cd4f4408319bb0a82360f6a58e6c9ce3f487c446063bf813bc6ba535e17fc1826cfc91",
+ "1f1459cb6b61cbac5f0efe8fc487538f42548987fcd56221cfa7beb22504769e792c45adfb1d6b3d60d7b749c8a75b0bdf14e8ea721b95dca538ca6e25711209",
+ "e58b3836b7d8fedbb50ca5725c6571e74c0785e97821dab8b6298c10e4c079d4a6cdf22f0fedb55032925c16748115f01a105e77e00cee3d07924dc0d8f90659",
+ "b929cc6505f020158672deda56d0db081a2ee34c00c1100029bdf8ea98034fa4bf3e8655ec697fe36f40553c5bb46801644a627d3342f4fc92b61f03290fb381",
+ "72d353994b49d3e03153929a1e4d4f188ee58ab9e72ee8e512f29bc773913819ce057ddd7002c0433ee0a16114e3d156dd2c4a7e80ee53378b8670f23e33ef56",
+ "c70ef9bfd775d408176737a0736d68517ce1aaad7e81a93c8c1ed967ea214f56c8a377b1763e676615b60f3988241eae6eab9685a5124929d28188f29eab06f7",
+ "c230f0802679cb33822ef8b3b21bf7a9a28942092901d7dac3760300831026cf354c9232df3e084d9903130c601f63c1f4a4a4b8106e468cd443bbe5a734f45f",
+ "6f43094cafb5ebf1f7a4937ec50f56a4c9da303cbb55ac1f27f1f1976cd96beda9464f0e7b9c54620b8a9fba983164b8be3578425a024f5fe199c36356b88972",
+ "3745273f4c38225db2337381871a0c6aafd3af9b018c88aa02025850a5dc3a42a1a3e03e56cbf1b0876d63a441f1d2856a39b8801eb5af325201c415d65e97fe",
+ "c50c44cca3ec3edaae779a7e179450ebdda2f97067c690aa6c5a4ac7c30139bb27c0df4db3220e63cb110d64f37ffe078db72653e2daacf93ae3f0a2d1a7eb2e",
+ "8aef263e385cbc61e19b28914243262af5afe8726af3ce39a79c27028cf3ecd3f8d2dfd9cfc9ad91b58f6f20778fd5f02894a3d91c7d57d1e4b866a7f364b6be",
+ "28696141de6e2d9bcb3235578a66166c1448d3e905a1b482d423be4bc5369bc8c74dae0acc9cc123e1d8ddce9f97917e8c019c552da32d39d2219b9abf0fa8c8",
+ "2fb9eb2085830181903a9dafe3db428ee15be7662224efd643371fb25646aee716e531eca69b2bdc8233f1a8081fa43da1500302975a77f42fa592136710e9dc",
+ "66f9a7143f7a3314a669bf2e24bbb35014261d639f495b6c9c1f104fe8e320aca60d4550d69d52edbd5a3cdeb4014ae65b1d87aa770b69ae5c15f4330b0b0ad8",
+ "f4c4dd1d594c3565e3e25ca43dad82f62abea4835ed4cd811bcd975e46279828d44d4c62c3679f1b7f7b9dd4571d7b49557347b8c5460cbdc1bef690fb2a08c0",
+ "8f1dc9649c3a84551f8f6e91cac68242a43b1f8f328ee92280257387fa7559aa6db12e4aeadc2d26099178749c6864b357f3f83b2fb3efa8d2a8db056bed6bcc",
+ "3139c1a7f97afd1675d460ebbc07f2728aa150df849624511ee04b743ba0a833092f18c12dc91b4dd243f333402f59fe28abdbbbae301e7b659c7a26d5c0f979",
+ "06f94a2996158a819fe34c40de3cf0379fd9fb85b3e363ba3926a0e7d960e3f4c2e0c70c7ce0ccb2a64fc29869f6e7ab12bd4d3f14fce943279027e785fb5c29",
+ "c29c399ef3eee8961e87565c1ce263925fc3d0ce267d13e48dd9e732ee67b0f69fad56401b0f10fcaac119201046cca28c5b14abdea3212ae65562f7f138db3d",
+ "4cec4c9df52eef05c3f6faaa9791bc7445937183224ecc37a1e58d0132d35617531d7e795f52af7b1eb9d147de1292d345fe341823f8e6bc1e5badca5c656108",
+ "898bfbae93b3e18d00697eab7d9704fa36ec339d076131cefdf30edbe8d9cc81c3a80b129659b163a323bab9793d4feed92d54dae966c77529764a09be88db45",
+ "ee9bd0469d3aaf4f14035be48a2c3b84d9b4b1fff1d945e1f1c1d38980a951be197b25fe22c731f20aeacc930ba9c4a1f4762227617ad350fdabb4e80273a0f4",
+ "3d4d3113300581cd96acbf091c3d0f3c310138cd6979e6026cde623e2dd1b24d4a8638bed1073344783ad0649cc6305ccec04beb49f31c633088a99b65130267",
+ "95c0591ad91f921ac7be6d9ce37e0663ed8011c1cfd6d0162a5572e94368bac02024485e6a39854aa46fe38e97d6c6b1947cd272d86b06bb5b2f78b9b68d559d",
+ "227b79ded368153bf46c0a3ca978bfdbef31f3024a5665842468490b0ff748ae04e7832ed4c9f49de9b1706709d623e5c8c15e3caecae8d5e433430ff72f20eb",
+ "5d34f3952f0105eef88ae8b64c6ce95ebfade0e02c69b08762a8712d2e4911ad3f941fc4034dc9b2e479fdbcd279b902faf5d838bb2e0c6495d372b5b7029813",
+ "7f939bf8353abce49e77f14f3750af20b7b03902e1a1e7fb6aaf76d0259cd401a83190f15640e74f3e6c5a90e839c7821f6474757f75c7bf9002084ddc7a62dc",
+ "062b61a2f9a33a71d7d0a06119644c70b0716a504de7e5e1be49bd7b86e7ed6817714f9f0fc313d06129597e9a2235ec8521de36f7290a90ccfc1ffa6d0aee29",
+ "f29e01eeae64311eb7f1c6422f946bf7bea36379523e7b2bbaba7d1d34a22d5ea5f1c5a09d5ce1fe682cced9a4798d1a05b46cd72dff5c1b355440b2a2d476bc",
+ "ec38cd3bbab3ef35d7cb6d5c914298351d8a9dc97fcee051a8a02f58e3ed6184d0b7810a5615411ab1b95209c3c810114fdeb22452084e77f3f847c6dbaafe16",
+ "c2aef5e0ca43e82641565b8cb943aa8ba53550caef793b6532fafad94b816082f0113a3ea2f63608ab40437ecc0f0229cb8fa224dcf1c478a67d9b64162b92d1",
+ "15f534efff7105cd1c254d074e27d5898b89313b7d366dc2d7d87113fa7d53aae13f6dba487ad8103d5e854c91fdb6e1e74b2ef6d1431769c30767dde067a35c",
+ "89acbca0b169897a0a2714c2df8c95b5b79cb69390142b7d6018bb3e3076b099b79a964152a9d912b1b86412b7e372e9cecad7f25d4cbab8a317be36492a67d7",
+ "e3c0739190ed849c9c962fd9dbb55e207e624fcac1eb417691515499eea8d8267b7e8f1287a63633af5011fde8c4ddf55bfdf722edf88831414f2cfaed59cb9a",
+ "8d6cf87c08380d2d1506eee46fd4222d21d8c04e585fbfd08269c98f702833a156326a0724656400ee09351d57b440175e2a5de93cc5f80db6daf83576cf75fa",
+ "da24bede383666d563eeed37f6319baf20d5c75d1635a6ba5ef4cfa1ac95487e96f8c08af600aab87c986ebad49fc70a58b4890b9c876e091016daf49e1d322e",
+ "f9d1d1b1e87ea7ae753a029750cc1cf3d0157d41805e245c5617bb934e732f0ae3180b78e05bfe76c7c3051e3e3ac78b9b50c05142657e1e03215d6ec7bfd0fc",
+ "11b7bc1668032048aa43343de476395e814bbbc223678db951a1b03a021efac948cfbe215f97fe9a72a2f6bc039e3956bfa417c1a9f10d6d7ba5d3d32ff323e5",
+ "b8d9000e4fc2b066edb91afee8e7eb0f24e3a201db8b6793c0608581e628ed0bcc4e5aa6787992a4bcc44e288093e63ee83abd0bc3ec6d0934a674a4da13838a",
+ "ce325e294f9b6719d6b61278276ae06a2564c03bb0b783fafe785bdf89c7d5acd83e78756d301b445699024eaeb77b54d477336ec2a4f332f2b3f88765ddb0c3",
+ "29acc30e9603ae2fccf90bf97e6cc463ebe28c1b2f9b4b765e70537c25c702a29dcbfbf14c99c54345ba2b51f17b77b5f15db92bbad8fa95c471f5d070a137cc",
+ "3379cbaae562a87b4c0425550ffdd6bfe1203f0d666cc7ea095be407a5dfe61ee91441cd5154b3e53b4f5fb31ad4c7a9ad5c7af4ae679aa51a54003a54ca6b2d",
+ "3095a349d245708c7cf550118703d7302c27b60af5d4e67fc978f8a4e60953c7a04f92fcf41aee64321ccb707a895851552b1e37b00bc5e6b72fa5bcef9e3fff",
+ "07262d738b09321f4dbccec4bb26f48cb0f0ed246ce0b31b9a6e7bc683049f1f3e5545f28ce932dd985c5ab0f43bd6de0770560af329065ed2e49d34624c2cbb",
+ "b6405eca8ee3316c87061cc6ec18dba53e6c250c63ba1f3bae9e55dd3498036af08cd272aa24d713c6020d77ab2f3919af1a32f307420618ab97e73953994fb4",
+ "7ee682f63148ee45f6e5315da81e5c6e557c2c34641fc509c7a5701088c38a74756168e2cd8d351e88fd1a451f360a01f5b2580f9b5a2e8cfc138f3dd59a3ffc",
+ "1d263c179d6b268f6fa016f3a4f29e943891125ed8593c81256059f5a7b44af2dcb2030d175c00e62ecaf7ee96682aa07ab20a611024a28532b1c25b86657902",
+ "106d132cbdb4cd2597812846e2bc1bf732fec5f0a5f65dbb39ec4e6dc64ab2ce6d24630d0f15a805c3540025d84afa98e36703c3dbee713e72dde8465bc1be7e",
+ "0e79968226650667a8d862ea8da4891af56a4e3a8b6d1750e394f0dea76d640d85077bcec2cc86886e506751b4f6a5838f7f0b5fef765d9dc90dcdcbaf079f08",
+ "521156a82ab0c4e566e5844d5e31ad9aaf144bbd5a464fdca34dbd5717e8ff711d3ffebbfa085d67fe996a34f6d3e4e60b1396bf4b1610c263bdbb834d560816",
+ "1aba88befc55bc25efbce02db8b9933e46f57661baeabeb21cc2574d2a518a3cba5dc5a38e49713440b25f9c744e75f6b85c9d8f4681f676160f6105357b8406",
+ "5a9949fcb2c473cda968ac1b5d08566dc2d816d960f57e63b898fa701cf8ebd3f59b124d95bfbbedc5f1cf0e17d5eaed0c02c50b69d8a402cabcca4433b51fd4",
+ "b0cead09807c672af2eb2b0f06dde46cf5370e15a4096b1a7d7cbb36ec31c205fbefca00b7a4162fa89fb4fb3eb78d79770c23f44e7206664ce3cd931c291e5d",
+ "bb6664931ec97044e45b2ae420ae1c551a8874bc937d08e969399c3964ebdba8346cdd5d09caafe4c28ba7ec788191ceca65ddd6f95f18583e040d0f30d0364d",
+ "65bc770a5faa3792369803683e844b0be7ee96f29f6d6a35568006bd5590f9a4ef639b7a8061c7b0424b66b60ac34af3119905f33a9d8c3ae18382ca9b689900",
+ "ea9b4dca333336aaf839a45c6eaa48b8cb4c7ddabffea4f643d6357ea6628a480a5b45f2b052c1b07d1fedca918b6f1139d80f74c24510dcbaa4be70eacc1b06",
+ "e6342fb4a780ad975d0e24bce149989b91d360557e87994f6b457b895575cc02d0c15bad3ce7577f4c63927ff13f3e381ff7e72bdbe745324844a9d27e3f1c01",
+ "3e209c9b33e8e461178ab46b1c64b49a07fb745f1c8bc95fbfb94c6b87c69516651b264ef980937fad41238b91ddc011a5dd777c7efd4494b4b6ecd3a9c22ac0",
+ "fd6a3d5b1875d80486d6e69694a56dbb04a99a4d051f15db2689776ba1c4882e6d462a603b7015dc9f4b7450f05394303b8652cfb404a266962c41bae6e18a94",
+ "951e27517e6bad9e4195fc8671dee3e7e9be69cee1422cb9fecfce0dba875f7b310b93ee3a3d558f941f635f668ff832d2c1d033c5e2f0997e4c66f147344e02",
+ "8eba2f874f1ae84041903c7c4253c82292530fc8509550bfdc34c95c7e2889d5650b0ad8cb988e5c4894cb87fbfbb19612ea93ccc4c5cad17158b9763464b492",
+ "16f712eaa1b7c6354719a8e7dbdfaf55e4063a4d277d947550019b38dfb564830911057d50506136e2394c3b28945cc964967d54e3000c2181626cfb9b73efd2",
+ "c39639e7d5c7fb8cdd0fd3e6a52096039437122f21c78f1679cea9d78a734c56ecbeb28654b4f18e342c331f6f7229ec4b4bc281b2d80a6eb50043f31796c88c",
+ "72d081af99f8a173dcc9a0ac4eb3557405639a29084b54a40172912a2f8a395129d5536f0918e902f9e8fa6000995f4168ddc5f893011be6a0dbc9b8a1a3f5bb",
+ "c11aa81e5efd24d5fc27ee586cfd8847fbb0e27601ccece5ecca0198e3c7765393bb74457c7e7a27eb9170350e1fb53857177506be3e762cc0f14d8c3afe9077",
+ "c28f2150b452e6c0c424bcde6f8d72007f9310fed7f2f87de0dbb64f4479d6c1441ba66f44b2accee61609177ed340128b407ecec7c64bbe50d63d22d8627727",
+ "f63d88122877ec30b8c8b00d22e89000a966426112bd44166e2f525b769ccbe9b286d437a0129130dde1a86c43e04bedb594e671d98283afe64ce331de9828fd",
+ "348b0532880b88a6614a8d7408c3f913357fbb60e995c60205be9139e74998aede7f4581e42f6b52698f7fa1219708c14498067fd1e09502de83a77dd281150c",
+ "5133dc8bef725359dff59792d85eaf75b7e1dcd1978b01c35b1b85fcebc63388ad99a17b6346a217dc1a9622ebd122ecf6913c4d31a6b52a695b86af00d741a0",
+ "2753c4c0e98ecad806e88780ec27fccd0f5c1ab547f9e4bf1659d192c23aa2cc971b58b6802580baef8adc3b776ef7086b2545c2987f348ee3719cdef258c403",
+ "b1663573ce4b9d8caefc865012f3e39714b9898a5da6ce17c25a6a47931a9ddb9bbe98adaa553beed436e89578455416c2a52a525cf2862b8d1d49a2531b7391",
+ "64f58bd6bfc856f5e873b2a2956ea0eda0d6db0da39c8c7fc67c9f9feefcff3072cdf9e6ea37f69a44f0c61aa0da3693c2db5b54960c0281a088151db42b11e8",
+ "0764c7be28125d9065c4b98a69d60aede703547c66a12e17e1c618994132f5ef82482c1e3fe3146cc65376cc109f0138ed9a80e49f1f3c7d610d2f2432f20605",
+ "f748784398a2ff03ebeb07e155e66116a839741a336e32da71ec696001f0ad1b25cd48c69cfca7265eca1dd71904a0ce748ac4124f3571076dfa7116a9cf00e9",
+ "3f0dbc0186bceb6b785ba78d2a2a013c910be157bdaffae81bb6663b1a73722f7f1228795f3ecada87cf6ef0078474af73f31eca0cc200ed975b6893f761cb6d",
+ "d4762cd4599876ca75b2b8fe249944dbd27ace741fdab93616cbc6e425460feb51d4e7adcc38180e7fc47c89024a7f56191adb878dfde4ead62223f5a2610efe",
+ "cd36b3d5b4c91b90fcbba79513cfee1907d8645a162afd0cd4cf4192d4a5f4c892183a8eacdb2b6b6a9d9aa8c11ac1b261b380dbee24ca468f1bfd043c58eefe",
+ "98593452281661a53c48a9d8cd790826c1a1ce567738053d0bee4a91a3d5bd92eefdbabebe3204f2031ca5f781bda99ef5d8ae56e5b04a9e1ecd21b0eb05d3e1",
+ "771f57dd2775ccdab55921d3e8e30ccf484d61fe1c1b9c2ae819d0fb2a12fab9be70c4a7a138da84e8280435daade5bbe66af0836a154f817fb17f3397e725a3",
+ "c60897c6f828e21f16fbb5f15b323f87b6c8955eabf1d38061f707f608abdd993fac3070633e286cf8339ce295dd352df4b4b40b2f29da1dd50b3a05d079e6bb",
+ "8210cd2c2d3b135c2cf07fa0d1433cd771f325d075c6469d9c7f1ba0943cd4ab09808cabf4acb9ce5bb88b498929b4b847f681ad2c490d042db2aec94214b06b",
+ "1d4edfffd8fd80f7e4107840fa3aa31e32598491e4af7013c197a65b7f36dd3ac4b478456111cd4309d9243510782fa31b7c4c95fa951520d020eb7e5c36e4ef",
+ "af8e6e91fab46ce4873e1a50a8ef448cc29121f7f74deef34a71ef89cc00d9274bc6c2454bbb3230d8b2ec94c62b1dec85f3593bfa30ea6f7a44d7c09465a253",
+ "29fd384ed4906f2d13aa9fe7af905990938bed807f1832454a372ab412eea1f5625a1fcc9ac8343b7c67c5aba6e0b1cc4644654913692c6b39eb9187ceacd3ec",
+ "a268c7885d9874a51c44dffed8ea53e94f78456e0b2ed99ff5a3924760813826d960a15edbedbb5de5226ba4b074e71b05c55b9756bb79e55c02754c2c7b6c8a",
+ "0cf8545488d56a86817cd7ecb10f7116b7ea530a45b6ea497b6c72c997e09e3d0da8698f46bb006fc977c2cd3d1177463ac9057fdd1662c85d0c126443c10473",
+ "b39614268fdd8781515e2cfebf89b4d5402bab10c226e6344e6b9ae000fb0d6c79cb2f3ec80e80eaeb1980d2f8698916bd2e9f747236655116649cd3ca23a837",
+ "74bef092fc6f1e5dba3663a3fb003b2a5ba257496536d99f62b9d73f8f9eb3ce9ff3eec709eb883655ec9eb896b9128f2afc89cf7d1ab58a72f4a3bf034d2b4a",
+ "3a988d38d75611f3ef38b8774980b33e573b6c57bee0469ba5eed9b44f29945e7347967fba2c162e1c3be7f310f2f75ee2381e7bfd6b3f0baea8d95dfb1dafb1",
+ "58aedfce6f67ddc85a28c992f1c0bd0969f041e66f1ee88020a125cbfcfebcd61709c9c4eba192c15e69f020d462486019fa8dea0cd7a42921a19d2fe546d43d",
+ "9347bd291473e6b4e368437b8e561e065f649a6d8ada479ad09b1999a8f26b91cf6120fd3bfe014e83f23acfa4c0ad7b3712b2c3c0733270663112ccd9285cd9",
+ "b32163e7c5dbb5f51fdc11d2eac875efbbcb7e7699090a7e7ff8a8d50795af5d74d9ff98543ef8cdf89ac13d0485278756e0ef00c817745661e1d59fe38e7537",
+ "1085d78307b1c4b008c57a2e7e5b234658a0a82e4ff1e4aaac72b312fda0fe27d233bc5b10e9cc17fdc7697b540c7d95eb215a19a1a0e20e1abfa126efd568c7",
+ "4e5c734c7dde011d83eac2b7347b373594f92d7091b9ca34cb9c6f39bdf5a8d2f134379e16d822f6522170ccf2ddd55c84b9e6c64fc927ac4cf8dfb2a17701f2",
+ "695d83bd990a1117b3d0ce06cc888027d12a054c2677fd82f0d4fbfc93575523e7991a5e35a3752e9b70ce62992e268a877744cdd435f5f130869c9a2074b338",
+ "a6213743568e3b3158b9184301f3690847554c68457cb40fc9a4b8cfd8d4a118c301a07737aeda0f929c68913c5f51c80394f53bff1c3e83b2e40ca97eba9e15",
+ "d444bfa2362a96df213d070e33fa841f51334e4e76866b8139e8af3bb3398be2dfaddcbc56b9146de9f68118dc5829e74b0c28d7711907b121f9161cb92b69a9",
+ "142709d62e28fcccd0af97fad0f8465b971e82201dc51070faa0372aa43e92484be1c1e73ba10906d5d1853db6a4106e0a7bf9800d373d6dee2d46d62ef2a461",
+}
+
+var hashes2X = []string{
+ "64",
+ "f457",
+ "e8c045",
+ "a74c6d0d",
+ "eb02ae482a",
+ "be65b981275e",
+ "8540ccd083a455",
+ "074a02fa58d7c7c0",
+ "da6da05e10db3022b6",
+ "542a5aae2f28f2c3b68c",
+ "ca3af2afc4afe891da78b1",
+ "e0f66b8dcebf4edc85f12c85",
+ "744224d383733b3fa2c53bfcf5",
+ "b09b653e85b72ef5cdf8fcfa95f3",
+ "dd51877f31f1cf7b9f68bbb09064a3",
+ "f5ebf68e7ebed6ad445ffc0c47e82650",
+ "ebdcfe03bcb7e21a9091202c5938c0a1bb",
+ "860fa5a72ff92efafc48a89df1632a4e2809",
+ "0d6d49daa26ae2818041108df3ce0a4db48c8d",
+ "e5d7e1bc5715f5ae991e4043e39533af5d53e47f",
+ "5232028a43b9d4dfa7f37439b49495926481ab8a29",
+ "c118803c922f9ae2397fb676a2ab7603dd9c29c21fe4",
+ "2af924f48b9bd7076bfd68794bba6402e2a7ae048de3ea",
+ "61255ac38231087c79ea1a0fa14538c26be1c851b6f318c0",
+ "f9712b8e42f0532162822f142cb946c40369f2f0e77b6b186e",
+ "76da0b89558df66f9b1e66a61d1e795b178ce77a359087793ff2",
+ "9036fd1eb32061bdecebc4a32aa524b343b8098a16768ee774d93c",
+ "f4ce5a05934e125d159678bea521f585574bcf9572629f155f63efcc",
+ "5e1c0d9fae56393445d3024d6b82692d1339f7b5936f68b062c691d3bf",
+ "538e35f3e11111d7c4bab69f83b30ade4f67addf1f45cdd2ac74bf299509",
+ "17572c4dcbb17faf8785f3bba9f6903895394352eae79b01ebd758377694cc",
+ "29f6bb55de7f8868e053176c878c9fe6c2055c4c5413b51ab0386c277fdbac75",
+ "bad026c8b2bd3d294907f2280a7145253ec2117d76e3800357be6d431b16366e41",
+ "386b7cb6e0fd4b27783125cbe80065af8eb9981fafc3ed18d8120863d972fa7427d9",
+ "06e8e6e26e756fff0b83b226dce974c21f970e44fb5b3e5bbada6e4b12f81cca666f48",
+ "2f9bd300244f5bc093ba6dcdb4a89fa29da22b1de9d2c9762af919b5fedf6998fbda305b",
+ "cf6bdcc46d788074511f9e8f0a4b86704365b2d3f98340b8db53920c385b959a38c8869ae7",
+ "1171e603e5cdeb4cda8fd7890222dd8390ede87b6f3284cac0f0d832d8250c9200715af7913d",
+ "bda7b2ad5d02bd35ffb009bdd72b7d7bc9c28b3a32f32b0ba31d6cbd3ee87c60b7b98c03404621",
+ "2001455324e748503aa08eff2fb2e52ae0170e81a6e9368ada054a36ca340fb779393fb045ac72b3",
+ "45f0761aefafbf87a68f9f1f801148d9bba52616ad5ee8e8ac9207e9846a782f487d5cca8b20355a18",
+ "3a7e05708be62f087f17b41ac9f20e4ef8115c5ab6d08e84d46af8c273fb46d3ce1aabebae5eea14e018",
+ "ea318da9d042ca337ccdfb2bee3e96ecb8f907876c8d143e8e44569178353c2e593e4a82c265931ba1dd79",
+ "e0f7c08f5bd712f87094b04528fadb283d83c9ceb82a3e39ec31c19a42a1a1c3bee5613b5640abe069b0d690",
+ "d35e63fb1f3f52ab8f7c6cd7c8247e9799042e53922fbaea808ab979fa0c096588cfea3009181d2f93002dfc11",
+ "b8b0ab69e3ae55a8699eb481dd665b6a2424c89bc6b7cca02d15fdf1b9854139cab49d34de498b50b2c7e8b910cf",
+ "fb65e3222a2950eae1701d4cdd4736266f65bf2c0d2e77968996eadb60ef74fb786f6234973a2524bdfe32d100aa0e",
+ "f28b4bb3a2e2c4d5c01a23ff134558559a2d3d704b75402983ee4e0f71d273ae056842c4153b18ee5c47e2bfa54313d4",
+ "7bb78794e58a53c3e4b1aeb161e756af051583d14e0a5a3205e094b7c9a8cf62d098fa9ea1db12f330a51ab9852c17f983",
+ "a879a8ebae4d0987789bcc58ec3448e35ba1fa1ee58c668d8295aba4eaeaf2762b053a677e25404f635a53037996974d418a",
+ "695865b353ec701ecc1cb38f3154489eed0d39829fc192bb68db286d20fa0a64235cde5639137819f7e99f86bd89afcef84a0f",
+ "a6ec25f369f71176952fb9b33305dc768589a6070463ee4c35996e1ced4964a865a5c3dc8f0d809eab71366450de702318e4834d",
+ "604749f7bfadb069a036409ffac5ba291fa05be8cba2f141554132f56d9bcb88d1ce12f2004cd3ade1aa66a26e6ef64e327514096d",
+ "daf9fa7dc2464a899533594e7916fc9bc585bd29dd60c930f3bfa78bc47f6c8439448043a45119fc9228c15bce5fd24f46baf9de736b",
+ "943ea5647a8666763084da6a6f15dcf0e8dc24f27fd0d9194805d25180fe3a6d98f4b2b5e0d6a04e9b41869817030f16ae975dd41fc35c",
+ "af4f73cbfc093760dfeb52d57ef45207bbd1a515f5523404e5d95a73c237d97ae65bd195b472de6d514c2c448b12fafc282166da132258e9",
+ "605f4ed72ed7f5046a342fe4cf6808100d4632e610d59f7ebb016e367d0ff0a95cf45b02c727ba71f147e95212f52046804d376c918cadd260",
+ "3750d8ab0a6b13f78e51d321dfd1aa801680e958de45b7b977d05732ee39f856b27cb2bcce8fbf3db6666d35e21244c2881fdcc27fbfea6b1672",
+ "8f1b929e80ab752b58abe9731b7b34eb61369536995abef1c0980d93903c1880da3637d367456895f0cb4769d6de3a979e38ed6f5f6ac4d48e9b32",
+ "d8469b7aa538b36cdc711a591d60dafecca22bd421973a70e2deef72f69d8014a6f0064eabfbebf5383cbb90f452c6e113d2110e4b1092c54a38b857",
+ "7d1f1ad2029f4880e1898af8289c23bc933a40863cc4ab697fead79c58b6b8e25b68cf5324579b0fe879fe7a12e6d03907f0140dfe7b29d33d6109ecf1",
+ "87a77aca6d551642288a0dff66078225ae39d288801607429d6725ca949eed7a6f199dd8a65523b4ee7cfa4187400e96597bfffc3e38ade0ae0ab88536a9",
+ "e101f43179d8e8546e5ce6a96d7556b7e6b9d4a7d00e7aade5579d085d527ce34a9329551ebcaf6ba946949bbe38e30a62ae344c1950b4bde55306b3bac432",
+ "4324561d76c370ef35ac36a4adf8f3773a50d86504bd284f71f7ce9e2bc4c1f1d34a7fb2d67561d101955d448b67577eb30dfee96a95c7f921ef53e20be8bc44",
+ "78f0ed6e220b3da3cc9381563b2f72c8dc830cb0f39a48c6ae479a6a78dcfa94002631dec467e9e9b47cc8f0887eb680e340aec3ec009d4a33d241533c76c8ca8c",
+ "9f6589c31a472e0a736f4eb22b6c70a9d332cc15304ccb66a6b97cd051b6ed82f8990e1d9bee2e4bb1c3c45e550ae0e7b96e93ae23f2fb8f63b309131e72b36cba6a",
+ "c138077ee4ed3d7ffa85ba851dfdf6e9843fc1dc00889d117237bfaad9aa757192f73556b959f98e6d24886ce48869f2a01a48c371785f12b6484eb2078f08c22066e1",
+ "f83e7c9e0954a500576ea1fc90a3db2cbd7994eaef647dab5b34e88ab9dc0b47addbc807b21c8e6dd3d0bd357f008471d4f3e0abb18450e1d4919e03a34545b9643f870e",
+ "3277a11f2628544fc66f50428f1ad56bcba6ee36ba2ca6ecdf7e255effc0c30235c039d13e01f04cf1efe95b5c2033ab72adda30994b62f2851d17c9920eadca9a251752dc",
+ "c2a834281a06fe7b730d3a03f90761daf02714c066e33fc07e1f59ac801ec2f4433486b5a2da8faa51a0cf3c34e29b2960cd0013378938dbd47c3a3d12d70db01d7d06c3e91e",
+ "47680182924a51cabe142a6175c9253e8ba7ea579ece8d9bcb78b1e9ca00db844fa08abcf41702bd758ee2c608d9612fed50e85854469cb4ef3038acf1e35b6ba4390561d8ae82",
+ "cec45830cd71869e83b109a99a3cd7d935f83a95de7c582f3adbd34e4938fa2f3f922f52f14f169c38cc6618d3f306a8a4d607b345b8a9c48017136fbf825aecf7b620e85f837fae",
+ "46fb53c70ab105079d5d78dc60eaa30d938f26e4d0b9df122e21ec85deda94744c1daf8038b8a6652d1ff3e7e15376f5abd30e564784a999f665078340d66b0e939e0c2ef03f9c08bb",
+ "7b0dcb52791a170cc52f2e8b95d8956f325c3751d3ef3b2b83b41d82d4496b46228a750d02b71a96012e56b0720949ca77dc68be9b1ef1ad6d6a5ceb86bf565cb972279039e209dddcdc",
+ "7153fd43e6b05f5e1a4401e0fef954a737ed142ec2f60bc4daeef9ce73ea1b40a0fcaf1a1e03a3513f930dd5335723632f59f7297fe3a98b68e125eadf478eb045ed9fc4ee566d13f537f5",
+ "c7f569c79c801dab50e9d9ca6542f25774b3841e49c83efe0b89109f569509ce7887bc0d2b57b50320eb81fab9017f16c4c870e59edb6c26620d93748500231d70a36f48a7c60747ca2d5986",
+ "0a81e0c547648595adca65623ce783411aac7f7d30c3ad269efafab288e7186f6895261972f5137877669c550f34f5128850ebb50e1884814ea1055ee29a866afd04b2087abed02d9592573428",
+ "6a7b6769e1f1c95314b0c7fe77013567891bd23416374f23e4f43e27bc4c55cfada13b53b1581948e07fb96a50676baa2756db0988077b0f27d36ac088e0ff0fe72eda1e8eb4b8facff3218d9af0",
+ "a399474595cb1ccab6107f18e80f03b1707745c7bf769fc9f260094dc9f8bc6fe09271cb0b131ebb2acd073de4a6521c8368e664278be86be216d1622393f23435fae4fbc6a2e7c961282a777c2d75",
+ "4f0fc590b2755a515ae6b46e9628092369d9c8e589e3239320639aa8f7aa44f8111c7c4b3fdbe6e55e036fbf5ebc9c0aa87a4e66851c11e86f6cbf0bd9eb1c98a378c7a7d3af900f55ee108b59bc9e5c",
+ "ed96a046f08dd675107331d267379c6fce3c352a9f8d7b243008a74cb4e9410836afaabe871dab6038ca94ce5f6d41fa922ce08aba58169f94cfc86d9f688f396abd24c11a6a9b0830572105a477c33e92",
+ "379955f539abf0eb2972ee99ed9546c4bbee363403991833005dc27904c271ef22a799bc32cb39f08d2e4ba6717d55153feb692d7c5efae70890bf29d96df02333c7b05ccc314e4835b018fec9141a82c745",
+ "e16cc8d41b96547ede0d0cf4d908c5fa393399daa4a9696e76a4c1f6a2a9fef70f17fb53551a8145ed88f18db8fe780a079d94732437023f7c1d1849ef69ad536a76204239e8ba5d97e507c36c7d042f87fe0e",
+ "a81de50750ece3f84536728f227208bf01ec5b7721579d007de72c88ee20663318332efe5bc7c09ad1fa8342be51f0609046ccf760a7957a7d8dc88941adb93666a4521ebe76618e5ddc2dd3261493d400b50073",
+ "b72c5fb7c7f60d243928fa41a2d711157b96aef290185c64b4de3dcfa3d644da67a8f37c2ac55caad79ec695a473e8b481f658c497edb8a191526592b11a412282d2a4010c90ef4647bd6ce745ebc9244a71d4876b",
+ "9550703877079c90e200e830f277b605624954c549e729c359ee01ee2b07741ecc4255cb37f96682dafcdbaade1063e2c5ccbd1918fb669926a67744101fb6de3ac016be4c74165a1e5a696b704ba2ebf4a953d44b95",
+ "a17eb44d4de502dc04a80d5a5e9507d17f27c96467f24c79b06bc98a4c410741d4ac2db98ec02c2a976d788531f1a4451b6c6204cef6dae1b6ebbcd0bde23e6fffb02754043c8fd3c783d90a670b16879ce68b5554fe1c",
+ "41d3ea1eaba5be4a206732dbb5b70b79b66a6e5908795ad4fb7cf9e67efb13f06fef8f90acb080ce082aadec6a1b543af759ab63fa6f1d3941186482b0c2b312f1151ea8386253a13ed3708093279b8eb04185636488b226",
+ "5e7cdd8373dc42a243c96013cd29df9283b5f28bb50453a903c85e2ce57f35861bf93f03029072b70dac0804e7d51fd0c578c8d9fa619f1e9ce3d8044f65d55634dba611280c1d5cfb59c836a595c803124f696b07ddfac718",
+ "26a14c4aa168907cb5de0d12a82e1373a128fb21f2ed11feba108b1bebce934ad63ed89f4ed7ea5e0bc8846e4fc10142f82de0bebd39d68f7874f615c3a9c896bab34190e85df05aaa316e14820b5e478d838fa89dfc94a7fc1e",
+ "0211dfc3c35881adc170e4ba6daab1b702dff88933db9a6829a76b8f4a7c2a6d658117132a974f0a0b3a38ceea1efc2488da21905345909e1d859921dc2b5054f09bce8eeb91fa2fc6d048ce00b9cd655e6aafbdaa3a2f19270a16",
+ "ddf015b01b68c4f5f72c3145d54049867d99ee6bef24282abf0eecdb506e295bacf8f23ffa65a4cd891f76a046b9dd82cae43a8d01e18a8dff3b50aeb92672be69d7c087ec1fa2d3b2a39196ea5b49b7baede37a586fea71aded587f",
+ "6ee721f71ca4dd5c9ce7873c5c04c6ce76a2c824b984251c15535afc96adc9a4d48ca314bfeb6b8ee65092f14cf2a7ca9614e1dcf24c2a7f0f0c11207d3d8aed4af92873b56e8b9ba2fbd659c3f4ca90fa24f113f74a37181bf0fdf758",
+ "689bd150e65ac123612524f720f54def78c095eaab8a87b8bcc72b443408e3227f5c8e2bd5af9bcac684d497bc3e41b7a022c28fb5458b95e8dfa2e8caccde0492936ff1902476bb7b4ef2125b19aca2cd3384d922d9f36dddbcd96ae0d6",
+ "3a3c0ef066fa4390ec76ad6be1dc9c31ddf45fef43fbfa1f49b439caa2eb9f3042253a9853e96a9cf86b4f873785a5d2c5d3b05f6501bc876e09031188e05f48937bf3c9b667d14800db62437590b84ce96aa70bb5141ee2ea41b55a6fd944",
+ "741ce384e5e0edaebb136701ce38b3d33215415197758ae81235307a4115777d4dab23891db530c6d28f63a957428391421f742789a0e04c99c828373d9903b64dd57f26b3a38b67df829ae243feef731ead0abfca049924667fdec49d40f665",
+ "a513f450d66cd5a48a115aee862c65b26e836f35a5eb6894a80519e2cd96cc4cad8ed7eb922b4fc9bbc55c973089d627b1da9c3a95f6c019ef1d47143cc545b15e4244424be28199c51a5efc7234dcd94e72d229897c392af85f523c2633427825",
+ "71f1554d2d49bb7bd9e62e71fa049fb54a2c097032f61ebda669b3e1d4593962e47fc62a0ab5d85706aebd6a2f9a192c88aa1ee2f6a46710cf4af6d3c25b7e68ad5c3db23ac009c8f13625ff85dc8e50a9a1b2682d3329330b973ec8cbb7bb73b2bd",
+ "167cc1067bc08a8d2c1a0c10041ebe1fc327b37043f6bd8f1c63569e9d36ded58519e66b162f34b6d8f1107ef1e3de199d97b36b44141a1fc4f49b883f40507ff11f909a017869dc8a2357fc7336ae68703d25f75710b0ff5f9765321c0fa53a51675c",
+ "cb859b35dc70e264efaad2a809fea1e71cd4a3f924be3b5a13f8687a1166b538c40b2ad51d5c3e47b0de482497382673140f547068ff0b3b0fb7501209e1bf36082509ae85f60bb98fd02ac50d883a1a8daa704952d83c1f6da60c9624bc7c99912930bf",
+ "afb1f0c6b7125b04fa2578dd40f60cb411b35ebc7026c702e25b3f0ae3d4695d44cfdf37cb755691dd9c365edadf21ee44245620e6a24d4c2497135b37cd7ac67e3bd0aaee9f63f107746f9b88859ea902bc7d6895406aa2161f480cad56327d0a5bba2836",
+ "13e9c0522587460d90c7cb354604de8f1bf850e75b4b176bda92862d35ec810861f7d5e7ff6ba9302f2c2c8642ff8b7776a2f53665790f570fcef3cac069a90d50db42227331c4affb33d6c040d75b9aeafc9086eb83ced38bb02c759e95ba08c92b17031288",
+ "0549812d62d3ed497307673a4806a21060987a4dbbf43d352b9b170a29240954cf04bc3e1e250476e6800b79e843a8bd8253b7d743de01ab336e978d4bea384eaff700ce020691647411b10a60acacb6f8837fb08ad666b8dcc9eaa87ccb42aef6914a3f3bc30a",
+ "3a263efbe1f2d463f20526e1d0fd735035fd3f808925f058b32c4d8788aeeab9b8ce233b3c34894731cd73361f465bd350395aebcabd2fb63010298ca025d849c1fa3cd573309b74d7f824bbfe383f09db24bcc565f636b877333206a6ad70815c3bef5574c5fc1c",
+ "3c6a7d8a84ef7e3eaa812fc1eb8e85105467230d2c9e4562edbfd808f4d1ac15d16b786cc6a02959c2bc17149c2ce74c6f85ee5ef22a8a96b9be1f197cffd214c1ab02a06a9227f37cd432579f8c28ff2b5ac91cca8ffe6240932739d56788c354e92c591e1dd76499",
+ "b571859294b02af17541a0b5e899a5f67d6f5e36d38255bc417486e69240db56b09cf2607fbf4f95d085a779358a8a8b41f36503438c1860c8f361ce0f2783a08b21bd7232b50ca6d35428335272a5c05b436b2631d8d5c84d60e8040083768ce56a250727fb0579dd5c",
+ "98ee1b7269d2a0dd490ca38d447279870ea55326571a1b430adbb2cf65c492131136f504145df3ab113a13abfb72c33663266b8bc9c458db4bf5d7ef03e1d3b8a99d5de0c024be8fabc8dc4f5dac82a0342d8ed65c329e7018d6997e69e29a01350516c86beaf153da65ac",
+ "41c5c95f088df320d35269e5bf86d10248f17aec6776f0fe653f1c356aae409788c938befeb67c86d1c8870e8099ca0ce61a80fbb5a6654c44529368f70fc9b9c2f912f5092047d0ffc339577d24142300e34948e086f62e23ecaca410d24f8a36b5c8c5a80e0926bc8aa16a",
+ "9f93c41f533b2a82a4df893c78faaaa793c1506974ba2a604cd33101713ca4adfd30819ffd8403402b8d40aff78106f3357f3e2c24312c0d3603a17184d7b999fc9908d14d50192aebabd90d05073da7af4be37dd3d81c90acc80e8333df546f17ab6874f1ec204392d1c0571e",
+ "3da5207245ac270a915fc91cdb314e5a2577c4f8e269c4e701f0d7493ba716de79935918b917a2bd5db98050dbd1eb3894b65fac5abf13e075abebc011e651c03cafb6127147771a5c8418223e1548137a89206635c26ca9c235ccc108dc25cf846e4732444bd0c2782b197b262b",
+ "96011af3965bb941dc8f749932ea484eccb9ba94e34b39f24c1e80410f96ce1d4f6e0aa5be606def4f54301e930493d4b55d484d93ab9dd4dc2c9cfb79345363af31ad42f4bd1aa6c77b8afc9f0d551bef7570b13b927afe3e7ac4de7603a0876d5edb1ad9be05e9ee8b53941e8f59",
+ "51dbbf2a7ca224e524e3454fe82ddc901fafd2120fa8603bc343f129484e9600f688586e040566de0351d1693829045232d04ff31aa6b80125c763faab2a9b233313d931903dcfaba490538b06e4688a35886dc24cdd32a13875e6acf45454a8eb8a315ab95e608ad8b6a49aef0e299a",
+ "5a6a422529e22104681e8b18d64bc0463a45df19ae2633751c7aae412c250f8fb2cd5e1270d3d0cf009c8aa69688ccd4e2b6536f5747a5bc479b20c135bf4e89d33a26118705a614c6be7ecfe766932471ad4ba01c4f045b1abb5070f90ec78439a27a1788db9327d1c32f939e5fb1d5ba",
+ "5d26c983642093cb12ff0afabd87b7c56e211d01844ad6da3f623b9f20a0c968034299f2a65e6673530c5980a532beb831c7d0697d12760445986681076dfb6fae5f3a4d8f17a0db5008ce8619f566d2cfe4cf2a6d6f9c3664e3a48564a351c0b3c945c5ee24587521e4112c57e318be1b6a",
+ "52641dbc6e36be4d905d8d60311e303e8e859cc47901ce30d6f67f152343e3c4030e3a33463793c19effd81fb7c4d631a9479a7505a983a052b1e948ce093b30efa595fab3a00f4cef9a2f664ceeb07ec61719212d58966bca9f00a7d7a8cb4024cf6476bab7fbccee5fd4e7c3f5e2b2975aa2",
+ "a34ce135b37bf3db1c4aaa4878b4499bd2ee17b85578fcaf605d41e1826b45fdaa1b083d8235dc642787f11469a5493e36806504fe2a2063905e821475e2d5ee217057950370492f5024995e77b82aa51b4f5bd8ea24dc71e0a8a640b0592c0d80c24a726169cf0a10b40944747113d03b52708c",
+ "46b3cdf4946e15a5334fc3244d6680f5fc132afa67bf43bfade23d0c9e0ec64e7dab76faaeca1870c05f96b7d019411d8b0873d9fed04fa5057c039d5949a4d592827f619471359d6171691cfa8a5d7cb07ef2804f6ccad4821c56d4988bea7765f660f09ef87405f0a80bcf8559efa111f2a0b419",
+ "8b9fc21691477f11252fca050b121c5334eb4280aa11659e267297de1fec2b2294c7ccee9b59a149b9930b08bd320d3943130930a7d931b71d2f10234f4480c67f1de883d9894ada5ed5071660e221d78ae402f1f05af47761e13fec979f2671e3c63fb0ae7aa1327cf9b8313adab90794a52686bbc4",
+ "cd6598924ce847de7ff45b20ac940aa6292a8a99b56a74eddc24f2cfb45797188614a21d4e8867e23ff75afd7cd324248d58fcf1ddc73fbd115dfa8c09e62022fab540a59f87c989c12a86ded05130939f00cd2f3b512963dfe0289f0e54acad881c1027d2a0292138fdee902d67d9669c0ca1034a9456",
+ "594e1cd7337248704e691854af0fdb021067ddf7832b049ba7b684438c32b029eded2df2c89a6ff5f2f2c311522ae2dc6db5a815afc60637b15ec24ef9541f1550409db2a006da3affffe548a1eaee7bd114e9b805d0756c8e90c4dc33cb05226bc2b393b18d953f8730d4c7ae693159cdba758ad28964e2",
+ "1f0d292453f04406ada8be4c161b82e3cdd69099a8637659e0ee40b8f6da46005cfc6085db9804852decfbe9f7b4dda019a7112612895a144ed430a960c8b2f5458d3d56b7f427cee6358915aee7146278aed2a0296cdd929e4d21ef95a3adf8b7a6beba673cdccdbdcfb2474711732d972ad054b2dc64f38d",
+ "b65a72d4e1f9f9f75911cc46ad0806b9b18c87d105332a3fe183f45f063a746c892dc6c4b9181b1485b3e3a2cc3b453eba2d4c39d6905a774ed3fb755468beb190925ecd8e57ecb0d985125741650c6b6a1b2a3a50e93e3892c21d47ed5884eed83aa94e1602288f2f49fe286624de9d01fcb54433a0dc4ad70b",
+ "705ce0ffa469250782aff725248fc88fe98eb76659e8407edc1c4842c9867d61fe64fb86f74e980598b92bc213d06f337bd5654fc28643c7ba769a4c31563427543c00808b627a19c90d86c322f33566ce020121cc322229c3337943d46f68ef939d613dcef0077269f88151d6398b6b009abb763410b154ad76a3",
+ "7fa881ce87498440ab6af13854f0d851a7e0404de33896999a9b3292a5d2f5b3ad033530c558168fe5d2fdb9b89a2354c46cf32a0e612afc6c6485d789511bfef26800c74bf1a4cfbe30bda310d5f6029c3dccdedb6149e4971274e276dccfabd63bc4b9955e8303feb57f8a688db55ecb4b33d1f9fe1b3a8ba7ac32",
+ "23a98f71c01c0408ae16843dc03be7db0aeaf055f951709d4e0dfdf64fffbffaf900ee592ee10929648e56f6c1e9f5be5793f7df66453eb56502c7c56c0f0c88da77abc8fa371e434104627ef7c663c49f40998dbad63fa6c7aa4fac17ae138d8bbe081f9bd168cd33c1fbc92fa35ed687679f48a64b87db1fe5bae675",
+ "7b8970b6a33237e5a7bcb39272703edb92285c55842b30b9a48834b1b507cc02a6764739f2f7ee6ae02a7b715a1c455e59e8c77a1ae98abb10161853f1234d20da99016588cd8602d6b7ec7e177d4011edfa61e6b3766a3c6f8d6e9eac893c568903eb6e6aba9c4725774f6b4343b7acaa6c031593a36eef6c72806ff309",
+ "f7f4d328ba108b7b1de4443e889a985ed52f485f3ca4e0c246aa5526590cbed344e9f4fe53e4eea0e761c82324649206ca8c2b45152157d4115e68c818644b03b65bb47ad79f94d37cb03c1d953b74c2b8adfa0e1c418bda9c518ddcd7050e0f149044740a2b16479413b63fc13c36144f80c73687513dca761ba8642a8ae0",
+ "2d7dc80c19a1d12d5fe3963569547a5d1d3e821e6f06c5d5e2c09401f946c9f7e13cd019f2f9a878b62dd850453b6294b99ccaa068e542993524b0f63832d48e865be31e8ec1ee103c718340c904b32efb69170b67f038d50a3252794b1b4076c0620621ab3d91215d55ffea99f23d54e161a90d8d4902fda5931d9f6a27146a",
+ "77dff4c7ad30c954338c4b23639dae4b275086cbe654d401a2343528065e4c9f1f2eca22aa025d49ca823e76fdbb35df78b1e5075ff2c82b680bca385c6d57f7ea7d1030bb392527b25dd73e9eeff97bea397cf3b9dda0c817a9c870ed12c006cc054968c64000e0da874e9b7d7d621b0679866912243ea096c7b38a1344e98f74",
+ "83bed0d556798f2b419f7056e6d3ffada06e939b95a688d0ec8c6ac5ea45ab73a4cf01043e0a170766e21395f27ab4b78c435f5f0dfe6e93ab80df38610e41158429ddf20296f53a06a017723359fe22dc08b5da33f0800a4fe50118e8d7eab2f83a85cd764bf8a166903bd0e9dcfeeceba44ff4ca4439846458d31ea2bb564645d1",
+ "ea12cf5a113543e39504123036f15a5bafa9c555562469f99cd29996a4dfaaab2a34b00557ccf15f37fc0cc1b3be427e725f2cd952e50af7970dda9200cd5ce252b1f29c40067fea3027ed686190803b59d834179d1b8f5b55abe55ad174b2a1188f7753ec0ae2fc01316e7d498b68ee3598a0e9baaaa664a60f7fb4f90edbed494ad7",
+ "55266358332d8d9e68bd13432088beadf95833aab67a0eb3b10650414255f299e2670c3e1a5b2976159a46c72a7ce57d59b7be14c15798e09ed50fa312a431b0264d7a1396aa6168bde897e208ece53d2cfc83786113b1e6eac5e9bb98984abb6c8d64eebb991903254abc650c999bb9958a5d7937434b869bc940e21b9dc1cc8982f2ba",
+ "4d6104ded730aefe02873f4c741232c8234a6d66d85393aff57fbf56ba6347666988dfc4d58f3cc895a0da598822edeee4533d24ec0ee292fd5e1ad04898ffbc1ff4bef14dec220babcb0f28fffe32a6e2c28aaaac16442bf4feb02917d18bb3a415d84fa9358d5a9852688d846c92271911f934181c30f82434d915f93f155a1ffbf0b125",
+ "eb5f579a4c476af554aac11e5719d378549497e613b35a929d6f36bb8831d7a466aa76de9be24ebb55543f1c13924f64cfd648a5b3fa90387315c16174dbf1e9a183c196d9bb8f84af65f1f8212429aadc11ef2426d07d4716062b85c8d5d2dff8e21b9e62b7fa7dbd57d72633054b464fb28583a56ca13ccc5ddc74dae942492f31731e7046",
+ "ebddec3dcaf18063e45a76ebeac39af85a1adc2818881ccce48c106288f5988365cca2b4b1d7f037322da46840f42bebdcbc7193838d426e101087d8cea03aaff743d573eb4f4e9a71a2c884390769a6503874125d194bee8d46a3a0d5e4fcf28ff8465887d8e9df771d70157e75df3642b331d2778ceb32ceba868640171ab7a5d22eede1ee44",
+ "26d87ec70b57691e3bb359633d3ddba17f029d62cdfe977f5fd42274d79b444a32494d1c01e9f72d03cce78c806df96e93ea78da3a054209924ed765edc4d570f66168dc25ee3114e4017e387440349c8f0a94804761c3055f88e4fda2a49b860b1486a9609095f6250f268b6a4d1aecc03a505632ebf0b9dc22d0755a736faf7ad7000858b5864b",
+ "3880f5cc2d08fa70ef44b1f263fcf534d062a298c1bd5ee2eee8c3265806c4ce50b004f3a1fc1fa5b024aaac7f528c023c8181f67c6e1c357425dc4d573bd46b93a542afa3a19bdb140a2ce666e1a01f5c4d2dcd681fa9f5839b797813c394738d5ee4971386c12c7c117d17c7bec324b760aa30cda9ab2aa850284ba6fa97946f710f02449d1883c6",
+ "3317d2f452105dd3f4a96f9257af8285a80be58066b50f6f54bd633749b49f6ab9d57d45652d2ae852a2f6940cd5ec3159dd7f333358b12f502325df38843508faf7e246352d201280babd90b14fbf7722641c3601d0e458474439973c611bb5502fd0eb3078f87124ca7e1a016fcb6cfeff65f6a565985aca7122cfa8c5a11da0cb47797c5132333179",
+ "f2c5c955d0224e784a46b9125f8fef8a5e1271e145eb08bbbd07ca8e1cfc848cef14fa3b36221ac62006403dbb7f7d77958ccc54a8566c837858b809f3e310ace8ca682515bc655d2a397cab238a663b464d511f02dc5d033dad4cb5e0e519e94a54b62a3896e460ec70e5716b5921bf8396aa86a60123e6287e34570bb01bdc602e113670bf498af2ff10",
+ "180e275205691a83630cf4b0c7b80e6df8fad6ef1c23ba8013d2f09aef7abade1827f23af230de90676240b4b3b0673f8afdea0327330055041741f65560d90348de696d34ca80dfe8afae582fe4879d4594b80e9408fb53e800e01ca58552b905c365e7f1416e51c080f517d6bbd30e64ae1535d59decdc76c6624d737868f49f2f719da39ba1344d59eab9",
+ "c517a84e4631a7f65ace170d1e5c2fdb259841535d88da323e68c0883e6af7b041cfe05908815a5a9d1b14fa712c2c16fadcf1ca54d3aa954d411240df331b2aebdfb65aced84d0b8aace56ec0aa7c13ec7d75ca883b6bcf6db74c9e98463c484a8262684f29910373430651f90ecffe18b072170e61ee58de20e2a6ff67b3ab00fccbb80af943f20b56b98107",
+ "d1a56a5ee990e02b84b5862fde62f69ec07567be2d7ccb769a461c4989d11fdda6c945d942fb8b2da795ed97e43a5b7dbdde7f8fd2ff7154544336d5c50fb7380341e660d4898c7fbc39b2b782f28defac6873523c7c1de8e52c65e4395c686ba483c35a220b0416d46357a063fa4c33fa9c52d5c207a1304ae141c791e62ba6a7374ed922b8dd94079b72b69302",
+ "4720b88d6bfb1ab43958e26827730d852d9ec30173ebd0fe0d273edcece2e788558984cd9306fe5978086a5cb6d37975755d2a3daeb16f99a8a11544b8247a8b7ed5587afc5bea1daf85dcea5703c5905cf56ae7cc76408ccabb8fcc25cacc5ff456db3f62fa559c45b9c71505eb5073df1f10fc4c9060843f0cd68bbb4e8edfb48d0fd81d9c21e53b28a2aae4f7ba",
+ "f4639b511db9e092823d47d2947efacbaae0e5b912dec3b284d2350b9262f3a51796a0cd9f8bc5a65879d6578ec24a060e293100c2e12ad82d5b2a0e9d22965858030e7cdf2ab3562bfa8ac084c6e8237aa22f54b94c4e92d69f22169ced6c85a293f5e16bfc326153bf629cdd6393675c6627cd949cd367eef02e0f54779f4d5210197698e4754a5fe490a3a7521c1c",
+ "3d9e7a860a718565e3670c29079ce80e381969fea91017cfd5952e0d8a4a79bb08e2cd1e26161f30ee03a24891d1bfa8c212861b51618d07429fb48000ff87ef09c6fca526567777e9c076d58a642d5c521b1caa5fb0fb3a4b8982dc14a444732b72b239b8f01fc8ba8ee86b3013b5d3e98a92b2aeaecd4879fca5d5e9e0bd880dbfffa6f96f94f3998812aac6a714f331",
+ "4d9bf551d7fd531e7482e2ec875c0651b0bcc6caa738f7497befd11e67ae0e036c9d7ae4301cc3c7906f0d0e1ed4738753f414f9b3cd9b8a71176e325c4c74ce020680ecbfb146889597f5b40487e93f974cd866817fb9fb24c7c7c16177e6e120bfe349e83aa82ba40e59e917565788658a2b254f25cf99bc65070b3794cea2259eb10e42bb54852cba3110baa773dcd70c",
+ "b91f65ab5bc059bfa5b43b6ebae243b1c46826f3da061338b5af02b2da76bb5ebad2b426de3c3134a633499c7c36a120369727cb48a0c6cbab0acecdda137057159aa117a5d687c4286868f561a272e0c18966b2fec3e55d75abea818ce2d339e26adc005c2658493fe06271ad0cc33fcb25065e6a2a286af45a518aee5e2532f81ec9256f93ff2d0d41c9b9a2efdb1a2af899",
+ "736f6e387acb9acbee026a6080f8a9eb8dbb5d7c54ac7053ce75dd184b2cb7b942e22a3497419ddb3a04cf9e4eb9340a1a6f9474c06ee1dcfc8513979fee1fc4768087617fd424f4d65f54782c787a1d2de6efc81534343e855f20b3f3589027a5436201eee747d45b9b8375e4294d72ab6a52e04dfbb2914db92ee58f134b026527ed52d4f794459e02a43a17b0d51ea69bd7f3",
+ "9242d3eb31d26d923b99d66954cfade94f25a18912e6356810b63b971ae74bb53bc58b3c01424208ea1e0b1499936daea27e63d904f9ed65fdf69de40780a3027b2e89d94bdf214f585472613ce328f628f4f0d56217dfb53db5f7a07f54c8d71db16e27de7cdb8d23988837b49b65c12f1771d979e8b192c9f4a16b8d9fba917bcf74ce5a82aac2075608ba6c2d485fa59864b9de",
+ "5da68704f4b592d41f08aca08f62d85e2e2466e5f3be010315d11d113db674c4b98764a509a2f5aacc7ae72c9deff2bcc42810b47f64d429b35745b9efff0b18c58653461e968aaa3c2c7fc455bc5771a8f10cd184be831040df767201ab8d32cb9a58c89afbebecb524502c9b940c1b838f8361bbcde90d272715017f67609ea39b20fac985332d82daaa023999e3f8bfa5f3758bb8",
+ "71ea2af9c8ac2e5ae44a176662882e01027ca3cdb41ec2c6785606a07d7231cd4a2bded7155c2feef3d44d8fd42afa73265cef826f6e03aa761c5c51d5b1f129ddc27503ff50d9c2d748322df4b13dd5cdc7d46381528ab22b79b0049011e4d2e57fe2735e0d58d8d56e92c75dbeac8c76c4239d7f3f24fb56697593b3e4afa6671d5bbc96c079a1c154fe20212ade67b05d49ceaa7a84",
+ "1d133170582fa4bff59a21953ebbc01bc202d43cd79c083d1f5c02fa15a43a0f519e36acb710bdabac880f04bc003800641c2487930de9c03c0e0deb347fa815efca0a38c6c5de694db698743bc955581f6a945deec4ae988ef7cdf40498b77796ddea3fae0ea844891ab751c7ee20917c5a4af53cd4ebd82170078f41ada2795e6eea17593fa90cbf5290a1095e299fc7f507f360f187cd",
+ "5ec4ac45d48fc15c72471d795066bdf8e99a483d5fdd599511b9cdc408de7c0616491b73924d0266da34a495331a935c4b8884f57d7ad8cce4cbe586875aa52482215ed39d7626cce55d50349c7767981c8bd6890f132a196184247343566fc972b86fe3c5369d6a6519e9f07942f0522b77ad01c751dcf7defe31e471a0ec00963765dd8518144a3b8c3c978ad108056516a25dbe3092e73c",
+ "0d5e74b78290c689f2b3cfea45fc9b6a84c822639cd438a7f05c07c374adced42cdc12d2a9233a4ffe80307efc1ac13cb04300e165f8d90dd01c0ea955e7657332c6e86ad6b43e78ba4c13c675aed83192d8427866fb6484e6a3071b2369a46fba9005f31232da7ffec7952f831aaaddf63e225263531c2cf387f8cc14fa856c8795137142c3a52ffa69b8e30ebc88ce3bbc227597bcc8dddd89",
+ "a0fe36f983259921dc2fa7d89002b3066241d63bfc2448caf7e10522a35562be0bfedc3dce49cfce2e614a04d4c64cfc0ab898873a7fc26928dc1927c009d12f6f9b7a278205d3d0057604f4ac746f8b9287c3bc6b929832bf253b6586192ac43fdd29ba585dbd9059aab9c6ff6000a7867c67fec1457b733f6b620881166b8fed92bc8d84f0426002e7be7fcd6ee0abf3755e2babfe5636ca0b37",
+ "1d29b6d8eca793bb801becf90b7d7de215b17618ec32340da4bac707cdbb58b951d5036ec02e105d83b5960e2a72002d19b7fa8e1128cc7c5049ed1f76b82a59eac6ed09e56eb73d9ade38a6739f0e07155afa6ec0d9f5cf13c4b30f5f9a465b162a9c3ba04b5a0b3363c2a63f13f2a3b57c590ec6aa7f64f4dcf7f1582d0ca157eb3b3e53b20e306b1f24e9bda87397d413f01b453ceffeca1fb1e7",
+ "6a2860c110cd0fc5a19bcaafcd30762ee10242d34739638e716bd89fd537ea4dc630e6f85d1bd88a25ad3892ca554c232c9830bd56980c9f08d378d28f7fa6fa7df4fcbf6ad98b1adfff3ec1f63310e50f920c99a5200b8e64c2c2ca249399a149942261f737d5d72da949e914c024d57c4b639cb89990fed2b38a37e5bcd24d17ca12dfcd36ce04691fd03c32f6ed5de2a2191ed7c826375ba81f78d0",
+ "7132aa291ddc9210c60dbe7eb3c19f9053f2dd74742cf57fdc5df98312adbf4710a73245de4a0c3b24e21ab8b466a77ae29d15500d5142555ef3088cbccbe685ed9119a10755148f0b9f0dbcf02b2b9bcadc8517c88346ea4e78285e9cbab122f824cc18faf53b742a87c008bb6aa47eed8e1c8709b8c2b9adb4cc4f07fb423e5830a8e503ab4f7945a2a02ab0a019b65d4fd71dc364d07bdc6e637990e3",
+ "3e664da330f2c6007bff0d5101d88288aaacd3c07913c09e871cce16e55a39fde1ce4db6b8379977c46cce08983ca686778afe0a77a41baf447854b9aa286c398c2b83c95a127b053101b6799c1638e5efd67273b2618df6ec0b96d8d040e8c1ee01a99b9b5c8fe63fea2f749e6c90d31f6fae4e1469ac09884c4fe1a8539acb313f42c941224a0e79c059e18affc2bcb6724975c436f7bf949ebdd8aef51c",
+ "7a6ea63a271eb49470f5ce77519ed61ae9b2f1be07a96855726bc3df1d0723af3a703fdfc2e739c9d31d25814daf661a23558b50982e66ee37ad880f5c8f11c8130fac8a5d0250583700d5a324894fae6d61993f6bf9327214f8674649f355b23fd634940b2c467973a839e659169c773119919f5b81ee171edb2e5f6940d7551f9e5a70625d9ea88711ad0ed8ab2da720ad358bef954456cb2d5636425717c2",
+ "c5106bbda114168c449172e49590c7eeb827fa4e1a2a7a87a3c1f721a9047d0c0a50fbf244731be1b7eb1a2ef30f5ae846a9f38f0df44f32af61b68dbdcd0226e741dfb6ef81a2503691af5e4b3171f48c59ba4ef91eba344b5b697f261df7bbbb734ca6e6daebaa4a179feb17002823281b8534d55a6531c59305f6e3fd3fa63b747bcf0deb654c392a02fe687a269effb1238f38bcaea6b208b221c45fe7fbe7",
+ "597716a5ebeebc4bf524c15518816f0b5dcda39cc833c3d66b6368ce39f3fd02ceba8d12072bfe6137c68d3acd50c849873150928b320b4fbc31c1456679ea1d0acaeeabf666d1f1bad3e6b9312c5cbdecf9b799d3e30b0316bed5f41245107b693366accc8b2bcef2a6be54209ffabc0bb6f93377abdcd57d1b25a89e046f16d8fd00f99d1c0cd247aafa72234386ae484510c084ee609f08aad32a005a0a5710cb",
+ "0771ffe789f4135704b6970b617bae41666bc9a6939d47bd04282e140d5a861c44cf05e0aa57190f5b02e298f1431265a365d29e3127d6fccd86ec0df600e26bcdda2d8f487d2e4b38fbb20f1667591f9b5730930788f2691b9ee1564829d1ada15fffc53e785e0c5e5dd11705a5a71e390ca66f4a592785be188fefe89b4bd085b2024b22a210cb7f4a71c2ad215f082ec63746c7367c22aedb5601f513d9f1ffc1f3",
+ "be6556c94313739c115895a7bad2b620c0708e24f0390daa55521c31d2c6782acf41156271238885c367a57c72b4fe999c160e804ad58d8e565edbce14a2dd90e443eb80626b3eab9d7ab75d6f8a062d7ca89b7af8eb292c98eaf87ad1dfd0db103d1bb6188bd7e7a63502153cf3ce23d43b60c5782602bac8ad92fb2324f5a79453898c5de18415639ecc5c7974d3077f76fc1df5b956723bb19a624d7ea3ec13ba3d86",
+ "4bc33729f14cd2f1dc2ff459abee8f6860dda1062845e4adab78b53c835d106bdfa35dd9e77219eaef403d4e80488ca6bd1c93dd76ef9d543fbb7c8904dccc5f71509a6214f73d0f4e467c3e038ea639b29e7fc442ee29f57117740576188ada15a739827c647a46b0271817ab235c023c30c90f2115e5c90cd8501e7b286962fc66ffc3fe7e8978746168314908a41998bd83a1eeffda9d714b864f4d490fdeb9c7a6edfa",
+ "ab12faea205b3d3a803cf6cb32b9698c32301a1e7f7c6c23a20174c95e98b7c3cfe93fffb3c970face8f5751312a261741141b948d777b8a2ea286fe69fc8ac84d34116a4674bb09a1a0b6af90a748e511749de4697908f4acb22be08e96ebc58ab1690acf73914286c198a2b57f1dd70ea8a52325d3045b8bdfe9a09792521526b7564a2a5fcd01e291f1f8894017ce7d3e8a5dba15332fb410fcfc8d62195a48a9e7c86fc4",
+ "7d421e59a567af70594757a49809a9c22e07fe14061090b9a041875bb77933deae36c823a9b47044fa0599187c75426b6b5ed94982ab1af7882d9e952eca399ee80a8903c4bc8ebe7a0fb035b6b26a2a013536e57fa9c94b16f8c2753c9dd79fb568f638966b06da81ce87cd77ac0793b7a36c45b8687c995bf4414d28289dbee977e77bf05d931b4feaa359a397ca41be529910077c8d498e0e8fb06e8e660cc6ebf07b77a02f",
+ "0c18ab727725d62fd3a2714b7185c09faca130438eff1675b38beca7f93a6962d7b98cb300ea33067a2035cdd694348784aa2eda2f16c731eca119a050d3b3ce7d5c0fd6c234354a1da98c0642451922f670984d035f8c6f35031d6188bbeb31a95e99e21b26f6eb5e2af3c7f8eea426357b3b5f83e0029f4c4732bca366c9aa625748297f039327c276cd8d9c9bf692a47af098aa50ca97b99961bef8bc2a7a802e0b8cfdb84319",
+ "92d5909d18a8b2b9971cd1627b461e98a74ba377186a6a9df5bd133635250b300abccb2254cacb775df6d99f7c7d0952653c28e6909b9f9a45adce691f7adc1afffcd9b06e49f775364cc2c62825b9c1a86089080e26b57e732aac98d80d009bfe50df01b95205aa07ed8ec5c873da3b92d00d53af825aa64b3c634c5ece40bff152c331222d3453fd92e0ca17cef19ecb96a6eed4961b627aca48b12fecd091754f770d52ba861546",
+ "802f22e4a388e874927fef24c797408254e03910bab5bf372320207f8067f2b1ea543917d4a27df89f5bf936ba12e04302bde23119533d0976beca9e20cc16b4dbf17a2ddc44b66aba76c61ad59d5e90de02a88327ead0a8b75463a1a68e307a6e2e53ecc1986274b9ee80bc9f3140671d5285bc5fb57b281042a8978a1175900c6073fd7bd740122956602c1aa773dd2896674d0a6beab24454b107f7c847acb31a0d332b4dfc5e3f2f",
+ "3844fe65db11c92fb90bf15e2e0cd216b5b5be91604baf3b84a0ca480e41ecfaca3709b32f8c6e8761406a635b88eec91e075c48799a16ca08f295d9766d74475c47f3f2a274eae8a6ee1d191a7f37ee413a4bf42cad52acd5564a651715ae42ac2cddd52f819c692ecdef52ecb763270322cdca7bd5aef71428fa73e844568b96b43c89bf1ed42a0abf209ffad0eeec286c6f141e8af073ba4adfbbdeda253752ae36c9957dfc905b4c49",
+ "329377f7bf3c8d74991a7d61b0cf39baff5d485d79751b0d5ad017d23bec570fb19810105bab79ab5acb102ab972165224d4ec888ec7de5148077fa9c1bb6820e0d91ae4e2591a21fec2f820606ce4bafc1e377f8dc3a5bd1a9e2772a57abccd0b757164d768872c91d02789545ab5b203f688d71dd08522a3fd2f5bcd7df507aebf1ca27ddff0a82afb7aa9c180008f49d1325adf97d047e77238fc75f56356de4e87d8c961575c9f6362c9",
+ "f7f269929b0d71ea8eef7120e55ccba691c582dd534692abef35c0fe9dec7dae973cd9702e5ad420d278fe0e653fdcb22fdcb63148109ec7e94f2d0750b28157dd1764376ae10fdb0a4aef3b304bd82793e0595f941226a2d72abbc929f53134dc495b0d65ced409914f94c2523f3dfbbdeeac84ae247ab5d1b9ea33dce1a808885a55be1f3683b46f4be73d9b62eec2585f690056858dfc427aabf591cd276724885bcd4c00b93bb51fb7484d",
+ "ac022309aa2c4d7fb628255b8b7fb4c3e3ae64b1cb65e0de711a6def1653d95d8088871cb8905fe8ae76423604988a8f77589f3f776dc1e4b30dbe9dd262b2187db02518a132d219bd1a06ebac13132b5164b6c420b37dd2ccee7d69b3b7fa12e54f0a53b853d490a68379ea1fa2d79762830ffb71bf86aab506b51f85c4b6a41b69325c7d0c7aa85b93b7144489d213e8f33dbb879fce22849865337b620b155cb2d2d36a68832889e30194d36d",
+ "d009c2b78a8f02e5e5dbb586ef71fc324b375092e15913ca1a5bfd22d516baadb96867bee3562e77c4a4852344a1a76c30728be5e22400b4cc41711f66754c246a520498d8c24f0205b9c873748dbeb67fe1ad099ad04cf89f4b517f0aa481136d9f6de2d727df01c6aa4099da59d4382b51e25fd47c33d9842c32b62331e50794bfe8b61b3ba9de1b8b704779c6d65edff3af00f121ab4a7ea384edabe47c6d0098a48991f387ca4444135ec59d46",
+ "c00bab36cce69899817d1425016d222d7303197ed3e3fdcac744705e7f178a1ac745968900f69299163e19b3161f3e0a4cc55aa2e4e71e0ee6ac427d1f4d14e063f68d303ddfbb18118335cfa7a6a90d99c38319ee76f7a884846a9e0b68030bf28e78bfbd56359b9368842814da42b04cb0e307d5d846dc22f049147bae31b9a956d17676a8cc348dafa3cabc2007a30e730e3894dddf9999fb8819086311f0703e141613ed6dcd7af8510e2dc435b0",
+ "c9789152a9fc29698d49ed95f09bd11b75f18a8c5615a73dbe54ae5e550027fd0ae6a8b60667040c1b12de3d1ee3f6bf061c78c951a3210effc912e19f482dd4de152063c588c44903bc11761706fd935afa040df085b08144d83d0dde32b46ab52f4fae98ac116c7ff11d7f553450c2e37b9c5f0b1dd9e0b8640a24cba6f2a5246c41f197f46e3dc8a29131c79bef3351c6e277a0a34442274d546ccd058891277473d668420f121750d19cd684267405",
+ "06a15a0731ce52557e368bcbaa11ef3399299e36fb9f2eda6e5726907c1d29c5c6fc581405ba48c7e2e522206a8f128d7c1c939d1132a00bd7d6366aa82724e968964eb2e373563f607dfa649590dcf5589114df69da5547fef8d1604cc4c6de1ed5783c8746918a4dd31168d6bc8784cd0c769206bd803d6ca8557b66748770402b075ef44b38157d4c0da7c6281725a2065d087b1f7b23455fa673bdeeba45b983311c44eabe9ef4b7bde3420ae9881863",
+ "d08aacef2d7a41aec09473bd8a44f628e15addb7b9e5b77a1e09c8ab4942f379a0bfcb324d580b774666f18ae78dd36710824ff12393f059068fe4b559c53662c2b0e6c69e23785c8f32554e837ec1714bee902e60737b639dd933af4f68cb9d7de77e1f3b28e5b122891afce62b79acd5b1ab4ba411662cc77d806449e69c5a45a143b742d98ac84a0826d68433b9b700ace6cd472ba2d58a90847f42ce9c43f38ffc017db4bf40450b2eee1f4594dc740c0f",
+ "6a6058b0a498b7ea76a93c646eb9b8629f0cba4a0c726420c5f67ba9b0412cade356abdf0a4fb94384bad32ce0d5dd9e23dcaae1d6f28ff8683616b30f1392890c67b3a2c04b360893b801f127e527e4da82e239f4c878da13f4a4f1c76db07190e77ec123995168102fb274434a2d1e12913b9b5cbab4aacaad2bd89d88b3ca2b8e60dacf7c22c9379097ff60880f552e320ca3b571994f52534470feee2b39e0dadb5cd88257a3e459a4cc6f12f17b8d54e1bb",
+ "adeced01fc5671531cbb45679f5ddd42b3a95151677b6125aaf6f5e8f82fbabaa5ecf7c3552c2458587224f0042870f178f5fca5465250e75d71352e652eeed23cdb7f915f5ebb44099b6db116ca1be45530ac8ed32b7f161d60ed4397ad3d7d649ae6bf75ca5bec891d8e595605be9764f3a03965e1fe0eaffbf212e3df4f0fa35e08ff9d0091e6d4ac4748edfe43b611085a6ffec163014655fdd839fd9e81b63b1fa8cae4ec335ec343289758e389a79ceedfae",
+ "d014592f3a83ba40af366f137c674724916c3cdd3f6cf9d4c5c7c8d6d51ebf26e315e2c12b3546be56fb52382904046ecbd2f5b883aa4ff473de6f0c26ab862c3fa34bf3d880cc1911ce39a4088c6617c179dc5faf68a2c488bbde12d67b50f73abcfab0e3b062e68c95363e11f5f1de8ec36ed01ea21442518089045df67d346135283ad5b3fff80cf57f20876849f6db9fa139728358415a90610f69ec720fc92d8234e3e122551e9df2c644c4a2c4e3734d07de8e",
+ "c0d0c37838873ba8757d6e41b409605043bc1635edcd731219587676d94217e9f0ab44b71de25000661ce7303b7015f45e6eaa7b7ebef92b8f4a34c902c908d2172185505fa33aca5a41be83079316cdfdd430fc2c45f505f85d867e6d516f7e1bf19c001d9f43018968aab65ec031b3801399231c83ec9e622dab5629922a6b424cab938c135ff7310501c2c02971bfd2f577e25904d1a618baf0859f77f4e8b1d0cde9544e95ec52ff710c0672fdb3d891feeea2b017",
+ "7022e7f00902219ba97baa0e940e8ac7727f58955aa068c29680fac4a16bcd812c03eeb5adbcfe867a7f7c6b5d89f4641adb9173b76a1a8438866f9b4f640ce2aedf5f1080c890bcf515b4be4e3e512352f1e5323c62ec46cb73f3d71be8235fee55a154763f7c3f9aeb61ffd28f4cd93d3310f608e2133586bf1ab3f102de96f64c68a4668de8acb2a76a7ce0cddddc8fa3df5e9d230823da16ed9ebb402d36e38e6e018795e5a71517ecab5f9ca472b9ced8ff69d2d195",
+ "acaf4baf3681ab865ab9abfae41697141ead9d5e98523c2e0e1eeb6373dd15405242a3393611e19b693cabaa4e45ac866cc66663a6e898dc73095a4132d43fb78ff7166724f06562fc6c546c78f2d5087467fcfb780478ec871ac38d9516c2f62bdb66c00218747e959b24f1f1795fafe39ee4109a1f84e3f82e96436a3f8e2c74ef1a665b0daaa459c7a80757b52c905e2fb4e30c4a3f882e87bce35d70e2925a1671205c28c89886a49e045e31434abaab4a7aed077ff22c",
+ "84cb6ec8a2da4f6c3b15edf77f9af9e44e13d67acc17b24bd4c7a33980f37050c0301ba3aa15ad92efe842cd3ebd3636cf945bb1f199fe0682037b9dacf86f162dadabfa625239c37f8b8db9901df0e618ff56fa62a57499f7ba83baebc085eaf3dda850835520344a67e09419368d81012168e5de5ea45158397af9a5c6a1657b26f319b66f816cd2c28996547d697e8df2bb163ccb9dda4d6691dffd102a13667ab9cde60ffbfb872187d9c425a7f67c1d9fffff9276ed0aeb",
+ "6a52c9bbbba454c14540b2be58230d78ecbeb391646a0c6fcce2f789086a78364b81ae85d5396d7cfa8b46bda41e3083ec5cf7b4c47dc601c8a697df52f557defca248506dbebab25657f5a561d09625b7f4b2f0119a12beeac087efc9d350a735c35d2431c1da7dda99befb17f41a3dc4da0f00bb95366be128538ce27763d81f832fe3c1d4efc07b5b08ad8dc9e65fb5e48546664e18cb2d3bb3fe1f56fa7aae718c5e3bbdeaf70e15023f6a25b72a2d177fcfd04211d40664fe",
+ "c3c4d3b31f1f5f9538923df3478c84fffaef411520a542da9a220ee4132eabb9d718b5076fb2f985485e8ba058330aed27ddfd3afa3db34aa60301088caec3d0053828c0c2bc87e2e61db5ea5a29f62fdad9c8b5fc5063ec4ee865e5b2e35fac0c7a835d5f57a1b1079833c25fc38fcb14311c54f8a3bd251bca19342d69e5785f9c2e43cf189d421c76c8e8db925d70fa0fae5ee3a28c4047c23a2b8a167ce53f35ced33bec822b88b06f41558c47d4fed1bfa3e21eb060df4d8ba1",
+ "8d55e92136992ba23856c1aea109766fc44772477efc932b3194af2265e433ed77d63b44d2a1cff2e8680eff120a430fe012f0f09c6201d546e13ad46fc4ce910eab27bb1569879abed2d9c37fae9f1267c2216ec5debcb20d4de58461a621e6ce8946899de81c0add44d35e27b7982a97f2a5e6314901caebe41dbba35f48bc9244ca6dca2bdde7306435892f287036df088633a070c2e385815ab3e2bfc1a47c05a5b9fe0e80dd6e38e4713a70c8f82bd32475eea8400c7bc67f59cf",
+ "5016284e20362610fa05ca9d789cad25f6d43263787e7e085476764ce4a8908ce99b262b375e9d106170b1bec1f473d5e777e0c1896533040e39c8c1465e07907ef5860e14e4d8310013e35f12090e0bfc687474b1f15f3dd2033a0edac5246102da4deec7e188c3517d84d9c2a0a4497a4c5f82a30f1ba009e45ee6eb3ab4368c720ea6feee428ffd2c4cc52debb8d634a64176572c72368f94a66689f23f8a01218f532117af5a8060d140e7ca435a92882fcb5630ebe14a4805f1dc83",
+ "05456ec59b8d41bbd736727976b96b38c43827f9e16169be673ff37870c2ecd5f0d1ea1a136be4cc7b047a02a4421d484fd2a12ece418e42ee391a13a0b1df5a0162b29ab70d3fe3e04ba6ab26b37d62b7cf05a5e2f033611bf970b8e1f30e198e483e740fa9618c1e8677e07b61296b94a9787a68fba622d7653b5568f4a8628025939b0f74389ea8fced6098c065bf2a869fd8e07d705eadb53006be2abb716a3114ceb0236d7e916f037cb954cf977720855d12be76d900ca124a2a66bb",
+ "eb6f60b83fcee77060ff346aaf6ec34d82a8af469947d3b5074cde8eb26566eb1fa039bcc707738df1e95869bd827c246e88436f0614d9834ead5392ef376105c4a9f370071cdeaaff6ca0f18b74c3a48d19a717253c49bd9009ccbfdd5728a08b7d112a2ed8dbafbbb46d7a75dc9a05e09bfde1a0a92d74a51887f9d123d7896e9f9d0057b660ed7d55454c069d3c5260411db4cdc67e7b74f680d7ac4b9dcc2f8baf72e15e6b3cafebcdf449a6436ed2c398b675f79c644747c57553bf7ea2",
+ "187a88e88514f6c4157c1ba40b442baae1ae563a6c989277443b12a219aa484cb9fa8adbb9a29d429f50155321b15664926317477079c7060dfdaa84c1d74bba78892c34e6f21ad35208d2ae622012401696bff5cd57b6485944b3db7b9071fa5f57fbfb1085d91bb9cff5808d662cdc6c8157249478262c44b7fbc397ed42a4977b202e817717bfccc9f0467294062313f7705251ed09573f16d23429361fada259dfb300369c4198f07341b38e84d02cdb74af5de6aab1fc2026208ea7c418c0",
+ "be31bc96606d0fab007e5caeded2f1c9f747c759777e9b6eef962bed49e45a1d4fc993e279d024915e600865ecb087b960584be18c41114d3c43f92169b9e0e1f85a0ebcd4e196376ccdc920e66103cd3b1c58407d0aafd0e003c4e341a1daddb9f4faba974362a32f35db83384b05ae8e3322d728893861afd8b1c940de5a17f691e763ce4969b6d94f67fb4a0235d100225bd8602f291388f0ca4a568748ad0d6040f1262eac2aede6cd27419bb78a394c1ffad72c262be8c3f9d9619d633e51d0",
+ "4d83d85ca838b4518588f2a90228a4dd18f14dd5b4c012d26298a97d848abbd825d221d02cceb6e8c701b4ad00e1dee4889b5c533e4bb60f1f41a4a61ee5478be2c1b1016c30345afd7a5253668260515e70751f22c8b4022d7fe4877d7bbce90b46531507dd3e89549e7fd58ea28f4cb23d33662bd003c1345ba94cc4b06867f778957901a8c441bee0f3b12e16463a51f7e50690356971dd73a686a49fda1eae46c9d54fba262811d698025d0ee053f1c58591c3bb3cbde69de0b31549ef5b69cf10",
+ "cdeb07d36dc5f9a1cd717a9e9cca37a2ce93caa298eee63571f7d6c5fde2a11c666cf53cf2dcb41ca2ea2319e7230ca68e38c647905928713a13982bf47fe33d7095ebd50b2df976208920a43eb2e29b942f32467403c45cea18bf44e0f6aeb155b48a8e5c471fec972a9d62f7ae093d2758f0aaec7ca50cb4725bfa219f1a3a46ad6bde7361f445f86b94d66b8ece080e56c510250693a5d0ea0ae87b4421860b853bcf0381eae4f1bf7c5c0472a93ad18407bc88475ab8560d344a921d3e86a02da397",
+ "a598fad52852c5d51ae3b10528fc1f722e21d44fbd42ae5acdf20e85a28532e646a223d27fd907bfd38eb8bb75175636892f8242877aab89e8c0824d368f3339ce7a82aa4e5af6db1f3b588a4d667a00f67bee37cfd2724dde06d2909fb9e58d892f4cfd2c4ca85acdf8256f5458b030a6bda151154ff2e6d7a8da90b54a2884c8a99fab5a4ac211ff23dc0975f4f592fd1b6b9dc7783bdcd2d4ca4e68d2902f2013e122cb62e2bff6b0a98ec55ba25837e21f1cfe67739b568d43e6413dab2bd1dc471e5a",
+ "17b68c74c9fe4926e8102070916a4e381b9fe25f5973c9bd4b04ce25749fc18931f37a65a356d3f5e5a1ef125d546f4f0ea797c15fb2efea6fbfcc5739c564693d47adeb12dcb3d98a2830719b13247792cb2491dca159a28138c6cff925aca42f4fdb02e73fbd508ec49b25c60703a7595a3e8f44b155b371d525e48e7e5dc84ac7b17c52bf5e526a67e7187234a2f19f57c548c70fc0b27183df73ffa53fa58b658034c896fa791ae9a7fd2620f5e46ce84c842a6e60e9324ae4db224ffc87d9617cb85ca2",
+ "b9e4267ea39e1de1fed0579f93bb351007c9f8fcdd811053fae33f09e2753d7428f04e1a9efcd45ea701a5d87a35b3afb2e6b65365dee6ead0bbb611b7797b212ac688653f542e604a39df277f12514ddfee3b4e27b98395c2cd97a203f1f1153c50327965770802ec2c9783edc428271762b275471e7ac65ac36523df28b0d7e6e6ccc7674268a132a63411fc82c0738dbb68af003b769a0bf9e6587b36476cb465350fee13f88ea355d47ffac7b0f964f4139db11b7642cb8d75fe1bc74d859b6d9e884f75ac",
+ "8ca704fe7208fe5f9c23110c0b3b4eee0ef632cae82bda68d8db2436ad409aa05cf159223586e1e6d8bdae9f316ea786809fbe7fe81ec61c61552d3a83cd6beaf652d1263862664df6aae321d0323440430f400f291c3efbe5d5c690b0cc6b0bf871b3933befb40bc870e2ee1ebb68025a2dcc11b68daadef6be29b5f21e440374301bde1e80dcfade4c9d681480e65ec494a6af48df232c3d51447b9d06be714949249c44c43cf73ed13ef0d533e770284e51369d94ae241a5fb2f163893071b2b4c118aeaf9eae",
+ "4fd8dd01012bb4df82bf42e0683f998e6f52dd9c5617bae33f867d6c0b69798cead8179346d70acc941abbbdd26e3229d5651361d2252c72ff22db2938d06ff6fc29a42fdf800ae967d06479bc7bbb8e71f40b1190a4b7189ffc9a7096cdb76d40aec424e1388e1eb7ef4ac3b34f3f089da8fda7d1927f5d775c0b2801d22dd1265c973158f640cec93edfed06dc80b20ef8c496b98289d54d46ccd205951cbb0f4e7daeb866b60bacb483411e4382b6f04d472843186bd0e31fbaa93e5c901ec028efafeb45fc551a",
+ "e9ee1b22b04b321a5fdd8301627011f583887d77560fb0f35552e207561f81e38ac58a0d0aeaf832d1ee72d913720d01f75574e9a321864fe95f4d0d8f0b8db97649a53e71e940aede5c40b4b9105daa42a6fb2811b61209247534cbaf830b07abe338d75d2f5f4eb1c3cf151e9edabe2c8d5f6fff08fac1495ef48160b100d30dcb0676700bcceb28723a29980ab0766a93abb8cb3d1963007db8458ed99b689d2a7c28c788743c80e8c1239b20982c81dadd0eed6740c65fbc4ef15c7b5569cb9fc997c6550a34b3b2",
+ "ec01e3a60964360f7f23ab0b22e021815765ad706f242265ebc19a2bb9e4eac94393952dcf61aae47682671a10f9165f0b20adf83a6706bfbdcf04c6faba6114653a35584267267873291c6fe7ff5f7695243143421509502c8875aafa9e9afe5be5ef2c851c7f35d69be5d3896000ccdbbfab5c238bb34d607cfe2d55d748880545b4aa7ca61137992925189025c62654b1f20d49c3ccd75aa73ce99cd7258dabedd6480a9f5185531fc0118beb68cc0a9cd182f6973287cf9252e12be5b619f15c25b65c71b7a316ebfd",
+ "db51a2f84704b78414093aa93708ec5e78573595c6e3a16c9e15744fa0f98ec78a1b3ed1e16f9717c01f6cab1bff0d56367ffc516c2e33261074935e0735ccf0d018744b4d28450f9a4db0dcf7ff504d3183aa967f76a507357948da9018fc38f150db53e2df6cea14466f03792f8bc11bdb5266dd6d508cde9e12ff04305c0295de29de19d491ad86e766774bb517e7e65befb1c5e2c267f013e235d8483e177214f89978b4cdc81aa7eff8b39f2825ad3a1b6ac1424e30edd49b067d770f16e74dd7a9c3af2ad74289a676",
+ "00e40f30ae3746edad0f5dd03d0e640933cf3d1694804c1e1ed6399ac36611d405196ee48f129344a8512feda16a354517871322bd5d9c6a1b592933eab531923efb393ffb23d9109cbe1075cebfa5fb917b40df028a621460ff6783c798792cb1d9635b5a6f84ec13918fa302924649b5c7fcb1f7007f0d2f06e9cfd7c27491e565a96c68a0c3644f92cd8f38857258c33801c5d537a83dfe583cba59d7eec7e394199c0a2660a62fabe3ed2099d57f315a6cd8de1a4ade29d977f15d65759cff433e5ac0c182aef3761163e1",
+ "3c5ea24d0d9b618294a263f062b2414a722be4eb10dfc346a6ec3b821d7396eba61cd6ef33618b04cd087a811f299d4606820227f16000d7c839062b96d3e3f59cd1a082448d13fc8f56b3fa7fb5f66d0350aa3b72dd7c165d590282f7da2e12cfe9e60e1796122bb8c2d40fdc2997af634b9c6b127a893dfb3467909378300db3da911be1d7b616bb8e0572433e65527e15d936500a2c60e9f9909dcf22ab5e4b6700f0238c205b4a813626fac3d945bab2637fb08203044a73d20c9a3fcf7c3fc4eb7807c3276dd5f73ce89597",
+ "9271aeeebfac46f4de85df78f1bfd36136aa8905e15835c9e1941176f71e3aa5b1b131843d40479735e23e182a2bd71f66f6149dccb7ed8c16469079dc8590bbf165374951785f4531f7e7361de62f936cfb23a2b5bdf186632e7042a0dd451fdc9b7208f923f3a5f250ae590ec348c63a16c3aacaf7379f53b5dd4152dcd40d23e683e2156e64c592ffc07e2cd6bbeebef4dd590b2f6b2bcbf08fcd111c079f5c4033adb6c17574f8756ecd87be27eff1d7c8e8d0324438d59ae171d5a17128fbcb5533d921bd044a2038a5046b33",
+ "4e3e533d5bcb15793d1b9d0468aaee801f32fdb486b11027183553a09ddbee8213924296f2815dc61577297459e834bf1c7a53f87d43782209e589b8295219ba7073a8fff18ad647fdb474fa39e1faa69911bf83438d5f64fe52f38ce6a991f25812c8f548de7bf2fdea7e9b4782beb4011d3567184c817521a2ba0ebad75b892f7f8e35d68b099827a1b08a84ec5e8125651d6f260295684d0ab1011a9209d2bdeb75128bf5364774d7df91e0746b7b08bda9185035f4f226e7d0a1946fcaa9c607a66b185d8546aac2800e85b74e67",
+ "b5d89fa2d94531093365d1259cc6fe8827fea48e6374c8b9a8c4d2209c280fa5c44958a1847222a692a59e6aa2696e6cdc8a543dd89b0ce03bc293b4e78d6ef48e1839694ccd5c65661143095c705b07e3ced84a0f5959114dd89deb956ab3fac8130eb4a878278205b801ae41a29e34146192308c4e759b374757b0c3b00319bce92a1b95a4d2ee179fd6714ff96155d26f693a5bc973f84ac8b3b91e3926276297532d98b46992a3f104c08100bf1671c43134bac280c617da711e90a0100137525375ebb12802a428885ae7fce6514a",
+ "40e3d8048fc10650cb8a7fc2e7113e26dec34f9ca2d5129cd10a8e8e44d113d61ee48c7d003e19fd307fc6debd70feb30243f298c510ccc4418355ce143066f067ad7c6de7288c3080e7ad46a23c8d34deb55a43e652fe90444ad3c57d3ec1e1c489d63ef915a24bc74a7925a0a7b1e1523f21ca8fee78df24e3d0a68d0013423db97c280799a0618229c0f2c167289a891e5c8d6661ab21285951c31710e3b5fe55f6347fe16d9b40507948a59252efeb616df83e5c098b07d0a7247cd371daff0e50491c582503fd89f79ba94d6af9ed76",
+ "1fa444de01dd3901e2b4684e3d7a799ffa02d85afd35fb30fe4c9d672837bee6dd8a3b8608b4bb5e589220ad5a854f46b46e41c6d57ad124a46beab4169ff69fee7e3838a6165e19dad8eb5d7bf53d4edd3cd2769daf219510a02fdd2afe0c0e1da3cd30fcd1aa88b68965586f07a25a1720fbd90a096ea30fc8e945e3637d7857c8a9c0ab4154ffb2000e57b5f9adfa4e4eaf8065bc3c2b2e75f495963325588785a6ce417dcddffd299873b15dcccca128d63cd4eeeadb64cda28099a9ad7c80d34844901f26b88b00b9aafeb2f90286d29d",
+ "fde0a0d9d813983bd1f55cf778a003a2023b34a555322ab280584537bc6bdd844d22a7d6066c18da83ec09f3d8d5a1aab4be0d5ce19b436052f6e259a4b49017a1f47f1fe2bf115d5bc8599fb216351c60dd6b1bedb2e6f4dcadf424b833501b6f099cbfad9e2290680fb69c25032b42a6274f7cb9b5c5950401354838a45f7cb77b95bf54718e2f3d3d9fb91eb2311903980277396398d9736d8e92fd838594ac8a537c6c529db5a8a4f89290e6ba6f20ac0e5ed6fef40901d0e0e8e3e502990811f9acaae555dd54eb1bcd96b513e2fe751bec",
+ "9f8e0caec87858599f5ab29bff86da78a841a918a023a111098687ecdf2747612d3f3809d9ca400b878bd4f92c43a1004f1c17c7f19a3cd1ce449bd2b23aff551623c37dd8c0be56bf3fd857b500c2b9f9ccea62481944090a3cf3b6ee81d9af8eeb60f65ef150f9fa4d3ed6ce4762d3d4f174ee8ccd460c25cafac0ea5ec8a6a4b2f9e8c0520cb7061155e532cb65f188b01e4b9086db951f504b060c296b326b3fc1c590498ecce594f828f4a10ea416675720ae505295d38a791bd0e93f428448a8f4c1fc0af53604a9e8255384d29ae5c334e2",
+ "33d1e683a4c97ee6bbaa5f9df1a88cb53b7f3c157b6045d70a56fda0ccbd3a1fa1f049cd564da072b53f415bf5fb843771c1d2551fd075d33377362b2f7c0645f9723123d11975991db8a2b518f02e2c7c30342a044754290bae2c77496d755e5981f12e6b0a0174280b958bf11ed628a9062775993ced04bf752ea8d165e3ac2177d7cd1b9371c44efa98f0b3e68602a839d384eec007979f46429dafb138cbc231ad928a9f65f7d66fac77416395e8f1debaaf76ec2e4e03e8674102cd26f614739f3ec9f949033df1fb97e87c2326d65aef94ed5f",
+ "180048f09d0b480887af7fd548a85abf605440c1ddde6afe4c30c30670233f7bf928f43b4681f59279ebbda5e8f8f2a1abefdee129e18ac60f9224e90b38b0aabd01308e0a27f41b6fb2ee07ee176ec9048c5fe33c3f7c791469c81f30e28170585b9f3e7e3c8c2e9d74370cb4518f13bf2dee048cbd98ffa32d85e43bcc64a626b40efb51ce712925fdd6fee006dc68b88004a81549d2121986dd1966084cd654a7c6686b3bae32afbd9625e09344e85cf9611ea08dfce835a2e5b3726e69ae8a76a97db60fcc539944ba4b1e8449e4d9802ae99fae86",
+ "13c0bc2f5eb887cd90eae426143764cf82b3545998c386007cca871890912217aa143ac4ed4ddb5a7495b704aa4de18419b8664b15bc26cfc6596a4d2ae408f98b47a566476d5802d594ba84c2f538def9d016661f6404bb2337a3932a24f6e30073a6c9c274b940c62c727242e24466084a3ea336365d71ea8fa6499c0ea8d59eea505f1126b99c795023c4963aa0d99323d0391e8701110edf551b2d3799e1063ca443f1add162156e445502ca1a052fe70c289838593b58839fc63de128a03e2bbf389e22ae0cf957fd03315ee407b096cc1cfd92dee6",
+ "6f1eb607d679efef065df08987a1174aab41bdac8aece7726dfa65805d6fff5b3d17a672d96b770dc32165f144f0f7324822a5c87563b7cd9e37a742ae83ef245d09006d91576f435a03476f509ea2936636232f66aa7f6cdf1ac187bbd1fcb8e20f8791866e60ed96c73374c12ac16795e999b891c64507d2dbd97e5fc29fac750ad27f2937cbcd29fdafccf27ab22453834d475f6186eaf975a36fad5c8bd61c21da554e1ded46c4c39765dcf5c8f5ccfb49b6a4dc562c919d0c7d8940ec536ab2448ec3c9a9c8b0e8fd4870cad9de2577c7b0c38563f355",
+ "dcdd993c94d3acbc555f464871a32c5da6f13b3d5bbc3e34429705e8ad2e76393fdd96a69a94acb652f5dc3c120d41187e9aa919669f727c4868013b0cb6acc165c1b7706c52248e15c3bf81eb6c147619467945c7c48fa14a73e7c3d5bec91706c567145342a026c9d97eff97ec672c5debb9df1a998083b0b0081d65c517b3e5634c95e347e781aa30ca1c8af815e2e494d844e847fdcb41622894a518dc36571123a40bfdbe8c4f4cff44d83c61dd9dcd24c464c53b395edb31efee9f3aa080e87cdc3d22d613ae84a53c9249c32c96f9a3bc4629bb126a70",
+ "49971f9823e63c3a72574d977953329e813b22a8387cd13f56d8ea77a5d1a8a20012632d1d8732bbcb9f756b9675aab5db927beacab7ca263e5718b8dfa7b2eed9a91bf5ed163b16139d45f7b8cc7e3f7bdda6202106f67dfb23b7c315ee3e17a09d466b1e6b13e7c7428184a979f5358667b4fa8bd40bcc8ea46058db44587a85377ac46bf155136c09ac58cb6c27f28e17028c91e7e8f74d5b500e56293b316974f02b9d9ea205d9b6ac4cfb74eb8eb0c944577fd2f41316368307beab3e327bf7dbaa0a4428836ec4e895dea635234abeaf113ceeadac33c7a3",
+ "c57a9cc958cee983599b04fe694f15fb470fcbc53e4bfcc00a27351b12d5d2434444253ad4184e87b81b738922ffd7ff1dc1e54f39c5518b49fb8fe50d63e3935f99e4bd125e8dc0ba8a17fd62de709339a43fabe15cf86d96a54010112170c340cfac4132182eed7301402bc7c8276089dec38488af145cb6222525894658f03501204b7a66aba0be1b557b28a2f652d66f7313ed825ecc4d8596c1be7420d4425b86a1a90a5b7f30d0f24e0d1aae0eb619ca457a71699e44be612a4011c597ee80b94d5507e429d7fc6af22579cd6ad642723b05ef169fade526fb",
+ "0568a672cd1ecbaa947045b712e2ac27995392fbef8f9488f79803cbee561c212287f080eca95adb5ba42739d78e3ba667f06045d87850d3a0499358649caa257ad29f1a9c511e7054db20554d15cbb55ff854afa45cae475c729cea72ede953522031865bc02b95589ed4d9841c552a8cc94904a93ed09ed77222f6c178195056be59bc4e96a815adf534e6b466fb47e262ff79c803c157a21b6e2269c2e0abeb494113cd868d8466e82d4b2f6a28b73645853d96bc9242515d803e33294848d3fe42fdff68da53c03491636beede47ff1399dd3d54a5e914d55d7adf",
+ "3f19f61a4cd085796731ac9f85a75a8bce77031932c31762d87d8b8d07b8bd19ff78d6b7d1bd1e87f3a4f41aad03b6c4d17a6cbc86be55f7c8b88ada047bb04f8d49f1c34bcf81cc0f3389ad01a758fc7eeb0072aa9ad1481992bfdde82e438e75590a4423832dfbe3756e2229ea873bc3606e6d72174cb2163bf40b5d49c81009dab85ecc03e311351bbf96e32c030a2b276a7698cb25bc2c967acb3213161a1fdde7d912cd6a804490f8056c47da1333f6e35c41e749c2c23919cb9af5eec5652e6e072b034fb1682e9aaa194a9c0bd456ea0b008d14dbce37967a7a8e",
+ "705f98f632d99d3651793825c38dc4deda56c59eac539da6a0159c83131cf8ab6f2ee0c3b74111fde351f7aa1a8c500a0cecab17c212d2c58ca09eae608c8eefc922b9902ef8d6832f799ba48c3c28aa702b3242107edeba01daafe424406a3822965056cfe8783455a671e93b1e2eae2321364f1871471c82124df33bc09e1b52882bd7e1c4c7d0b2f3dd4a28c2a002a43246768af0700f9659de99d62167be93177aabf19d678e79e9c726ac510d94e74873eda99620a3961930cd91937c88a06d8153d64fd60da7ca38cf26d1d4f04a0df273f52127c53fdc593f0f8df9",
+ "ea6f8e977c954657b45f25480ff42c36c7a10c77caa26eb1c907062e24fbca5aebc65cacca0de10abea8c78322f08672e13d8ac16996eca1aa17402eaea4c1cc6c800b22dc18cb8d620192d74bac02c07b5cfa61e513c7f28b7e29b9700e0e442720bf4c669d4995da19d19f841d9eb68cc74153592591e3bf059ef616b95305aa453b32fe99a91afb35bd482cf2b7aa42702837a53be3c38883d2963020e347556f841254ec6b85854485fe8c520b05f2ea67a9bf3981555c20991e2bacd4db5b418228b6002d8d41c025cb472bf5443aaa885974a408ea7f2e3f932c600deb",
+ "408190134ed06556811b1af808ab2d986aff152a28de2c41a2207c0ccc18125ac20f48384de89ea7c80cda1da14e60cc1599943646b4c0082bbcda2d9fa55a13e9df2934edf15eb4fd41f25fa3dd706ab6de522ed351b106321e494e7a27d5f7caf44ec6fadf1122d227eefc0f57aefc140d2c63d07dcbfd65790b1099745ed042cfd1548242076b98e616b76ff0d53db5179df8dd62c06a36a8b9e95a671e2a9b9dd3fb187a31ae5828d218ec5851913e0b52e2532bd4bf9e7b349f32de2b6d5d3cdf9f372d49617b6220c93c05962327e99a0480488443349f0fd54c1860f7c8",
+ "5f9e5c6f38573a85010a9d84d33f29c057003b2645e3ea6f72cbc7af95d197ce6a06b13fea81722853e6991791b8b15091cd066f5ed913592ed3d3af5370d39ba22beeb2a582a414b16824b77e194a094c2afdcc09aa73ce36f4943cca5ae32c5017dc398801dd92a47382d9327c9f6cffd38ca4167cd836f7855fc5ff048d8efba378cdde224905a0425e6b1de061fc951c5e624a5153b008ad41160a710b3ff2081748d5e02deb9f841f4fc6cf4a15153dd4fe874fd447482696283e79ee0e6bc8c1c0409baa5ab02c5209c319e3169b2476149c0c6e541c6197ca46e004eef533",
+ "218c6b3508aec69574f2b5039b30b942b72a8349d05f48ff945bbbe5c8957d5a6199492a6bf54bab821c9377e2edfa4c908384664d2c80112d5e805d66e0a551b941021be17dd20bd825bea9a3b6afb1b8c605805b3bda58750f03ea5c953a698494b425d8980c69f34d1c3f6b5866e8717031152a127215c256e08873c21b0f5cc85875d0f7c94601659150c04cd5fe5d381ba29983a2d94fcd3a65a94c53c7279cd000dddd4253d8cff8d7f6ace10247fe3bc30d63ba4bb54f557b3d22a3924369430d71ab37b701e9500bda70b5a643704858beed4726a889b6c9c91584194c68f1",
+ "dac26aa7273fc25d6e044c79fc2bfa46e59892a42bbca59a86826c91e76ab03e4bd9f7c0b5f08d1931d88b36ea77d94f7ba67cd4f1d3086e529427201119096ae066ae6f170940830ed7900de7bb9d66e09788287403a4ecc93c6da975d2fb08e918840a236c15f5d3a8f7375c2eeebbf6f01a6e7f29ca2b8d42df158414c320777433663c59fdcd1f39ca68e3473db721be7ce8c6dba5fddc024f94fedb286b0477581d451313ca8c737484daf60d67f9b2d56d4bcc271f7e9ae958c7f258efbc74d25753e0516f28282461941bf2dcc7dd8c7df6173b89760cefcac07190243ff863fb",
+ "c46e6512e6797cc7a54254a1b26b2de29aa83d6c4b1ea5a2786fbcec388270625b12635eae39e1fba013f8a65219421bca8b52a8ddfd431cda60299bdf160734d5a7450ec79620058522702174ae451b9bfa7c4a455fbbee3e1d048c7d4bac5131018228f137c8e130440c7059b4f15eaa34ce872a851a16ce86f982df78a00be4d564da2003a450ddee9ab43ea876b8b4b65c84f0b39265fd5456417afb5bc54997c986e66fc222f2123ba5e719c4d6b9a177b188277df384f1125821cf19d5248cef0be183ccdc84ac194506f740ed2188b2689ea4c9236a9e9e3a2fff85b6af4e9b49a3",
+ "1ccd4d278d67b65cf2564ecd4de1b55fe07adc80e1f735fe2f08ea53fd3977323689122c29c798957abaff6aba09bdcbf661d77f4dc8913ab1fe2bef38846166e3834785e7105d746484eff8c656af5d8c7854abc1c62b7fadb65521dc6f793d978bda9838eb3800417d32e8a24d8c8cb1d18a5de6ca79d9e1b0ff9aa25e6218fe944cf18666fecc1e31334b390260dbe0997539e1b02f6366b2aea4f4a21efe04f4b97568fcb39e59919d5ebac6543d5d0f48fc66b923c34aac377dc95c20329b837b6ed5e8d9a3d2089cd0d8f025658006ff41cbdaccca618822ca590ab155253f8bc1c7f5",
+ "9875209588395ee3c9fdd793fd48717cc84c8c3ea622b2ccc4a1be4448e6034b7810569855255031f10be5ffd714b05f9ce01972d712d40abf03d4d0ce175813a7a668f761324996093fc2aa5912f7fc2abdadd8775d2b4d9ad492216293381460ed8f6db3d641d1525f4242c348bbfe504c704f215dc461de51b5c75c1aae967936963848f16c673eca5e78dfd47eb19001d52d1bcf96c98956dad5ddf594a5da757e7ca35f2f69803b784e66ac5a58b75c228b8266ec592505e5d1ca87d81225738855f15bc0914677e81593fd409e77d159f8a908f67788de9eb06c5561547aada96c47c535",
+ "40c90e375e366f3756d89091eb3eed9fe0fbfc5638700af4617d358812bac53124a2205dd6756456787d49cd6a35e302479a0992288f47532e4ea7ab62fc5ad5adc690a5d9a446f7e035ad4641bd8dae83946aee3338ec984ccb5cc633e1409f2531eeffe05532a8b0062ba99454c9aeabf8ecb94db195af7032bfebc22912f49d39330add47ff8fa5720612d697f0b602738930e060a1bb214efc5e292224cf34e29deaea6b1b1ff847e94ecc997325ac38df61db45d82bf0e74a664d2fe085c20b04c39e90d6a170b68d2f1d373f00c731c524456ada73d659aaac9df3191a7a3865083343fc13",
+ "e8800d82e072210ca6d7fa2472028974780b76aad4bcb9ad362422dd05ae3232668251d164daa375a43b26a38cce28dbeb3dee1a4a579f70d0fe7febb29b5ece8aa836e050fb3d188c63aa9c3c0da6c717d86458a6096b5effceb964efdec7035960c09ccd10dea3c5f1c7f9f478d5887ebbe2e15c5ff85dbacbc444bb951c4eec7abecb89ed80187e409e2972ffe1a5f01562af109f2cf09471cf72cf83a3bb8f4e2ef38ed0e326b698296394e5b2718a5000c01425708e8ad0461e62462d8819c2377f13ab1be2c7c9f33dc06fe23cad27b87569f2ce2e56e4b2c60c7b1b3d370841d89ebdc1f192",
+ "796d6d1447d5b7e8c55cd8b2f8b7010db39f27565f907e3fc0e464ea2d4bb52b37f10e7c6dcfc59231b9cdee12c32aeb4adbc42b86e86eb6defb5b69e6ca75e1f4d0dae3e124e5a1b8b6697f7e10b0403f1f0a5ff848eef3752837a9ba17780f16a9a709188a8d5b89a2fa74adb2e651163b1c2b3d261e225c9158dcd9eb7ac3d6704cee290cdff6bcb3cb90cee030aa0d19d4693655c3c30ac6fc06d2ae37787c47126d57ed9a6bef5f8a6c56859aefc08755739a95aac57a4dd916a92ba9f3afbf969df8085949615033365c751a9a3e1a18cee98a69d22e64009bebf8307169b6c61de0617ecfafdf",
+ "4f9057183566153cf337b07c3f5556006de54c56b2a1e5326c07aaeabd1886ec6f1641358925db232b2f0dbf75229c796a7395b2f934c1f99090bec1123f3c841b1cb3c5b1ec42ed5408f2940f0c48a9470b852c46d6557853d459cecd2c32bbcd8ee21fa11e385eef0857cba4d8545a61b52a484cdd779db4739fbc7aa9860dcabe0488b98fa0b60c3f7d6153db279000a52ffb573dab37d2ab1896a90e5deb7ac6bbe56239085c325d83a917dc6e8a448425b718c2356b9f3066163555ec444f372e184e02c8c4c69b1c1c2ae2b51e45b98f73d933d18750968945ca85d6bbb22014b4c4015262e3c40d",
+ "79dcca7d8b81a61359e4aece21f3df7b99518ce70bd2f57a18bab5e7114af2add0a0cea7f319d69f231f060e0a539d9a23fb3e95451ce8c6340cfb09edf931df84203a39226dd9eb278f11b691ef612585b973daab373e65d11325898badf6732100371fd759960fa8fec373268421d28bffdb9b12a430b92fe4b07566ca0c89e616e49f8fc75ccd9cdc66db820d7c02e109aa5ed86b89770262918a518f90a2292f6b68d68ae03992e4259a17a23c84ec2a417f082b5abf3a26e44d2278ecb8ba9456965303a75f25394d1aaf5544590e74b14d8a4cc4050be2b0ebcfe4d2db6b12a02c68a3bcdda70301f3",
+ "848755dc31e25e9a42f9ec12d847d19f292c14c162c9aba49e972cb123b58b8e57bb263a923929833373858594ff52dbc298dbbc078599194e4c07b0e5fc1e10808bbacdb6e93c72b333685cf961f28eb0d5a395c63266b01f130d25db384b356e5da6d01042fc2359581b89c63b3bb2d1ce897fbc9e83fe85d9666cb60e6a8c657f70caad5387b8a045bf91095606802c8424ea8ac52ef29386dc46183378a5fcb2cb927428b8c070f1c42aafd3bc70ca25437807696a46873cfeb7b80ba2ebc3c4272443d445e46343a1465253a9eebd532a0d1d2c18264b91ff45159f245404ae9335f2af55c802772426b4",
+ "ecaa6e999ef355a0768730edb835db411829a3764f79d764bb5682af6d00f51b313e017b83fffe2e332cd4a3de0a81d6a52084d5748346a1f81eb9b183ff6d93d05edc00e938d001c90872dfe234e8dd085f639af168af4a07e18f1c56ca6c7c1addffc4a70eb4660666dda0321636c3f83479ad3b64e23d749620413a2ecdcc52ad4e6e63f2b817ce99c15b5d2da3792721d7158297cce65e0c04fe810d7e2434b969e4c7892b3840623e153576356e9a696fd9e7a801c25de621a7849da3f99158d3d09bf039f43c510c8ffb00fa3e9a3c12d2c8062dd25b8dabe53d8581e30427e81c3dfc2d455352487e1255",
+ "23a3fe80e3636313fdf922a1359514d9f31775e1adf24285e8001c04dbce866df055edf25b506e18953492a173ba5aa0c1ec758123406a97025ba9b6b7a97eb14734424d1a7841ec0eaeba0051d6e9734263bea1af9895a3b8c83d8c854da2ae7832bdd7c285b73f8113c3821cced38b3656b4e6369a9f8327cd368f04128f1d78b6b4260f55995277feffa15e34532cd0306c1f47354667c17018ee012a791af2dbbc7afc92c388008c601740cccbbe66f1eb06ea657e9d478066c2bd2093ab62cd94abadc002722f50968e8acf361658fc64f50685a5b1b004888b3b4f64a4ddb67bec7e4ac64c9ee8deeda896b9",
+ "758f3567cd992228386a1c01930f7c52a9dcce28fdc1aaa54b0fed97d9a54f1df805f31bac12d559e90a2063cd7df8311a148f6904f78c5440f75e49877c0c0855d59c7f7ee52837e6ef3e54a568a7b38a0d5b896e298c8e46a56d24d8cabda8aeff85a622a3e7c87483ba921f34156defd185f608e2241224286e38121a162c2ba7604f68484717196f6628861a948180e8f06c6cc1ec66d032cf8d16da039cd74277cde31e535bc1692a44046e16881c954af3cd91dc49b443a3680e4bc42a954a46ebd1368b1398edd7580f935514b15c7fbfa9b40048a35122283af731f5e460aa85b66e65f49a9d158699bd2870",
+ "fe511e86971cea2b6af91b2afa898d9b067fa71780790bb409189f5debe719f405e16acf7c4306a6e6ac5cd535290efe088943b9e6c5d25bfc508023c1b105d20d57252fee8cdbddb4d34a6ec2f72e8d55be55afcafd2e922ab8c31888bec4e816d04f0b2cd23df6e04720969c5152b3563c6da37e4608554cc7b8715bc10aba6a2e3b6fbcd35408df0dd73a9076bfad32b741fcdb0edfb563b3f753508b9b26f0a91673255f9bcda2b9a120f6bfa0632b6551ca517d846a747b66ebda1b2170891ece94c19ce8bf682cc94afdf0053fba4e4f0530935c07cdd6f879c999a8c4328ef6d3e0a37974a230ada83910604337",
+ "a6024f5b959698c0de45f4f29e1803f99dc8112989c536e5a1337e281bc856ff721e986de183d7b0ea9eb61166830ae5d6d6bc857dc833ff189b52889b8e2bd3f35b4937624d9b36dc5f19db44f0772508029784c7dac9568d28609058bc437e2f79f95b12307d8a8fb042d7fd6ee910a9e8df609ede3283f958ba918a9925a0b1d0f9f9f232062315f28a52cbd60e71c09d83e0f6600f508f0ae8ad7642c080ffc618fcd2314e26f67f1529342569f6df37017f7e3b2dac32ad88d56d175ab22205ee7e3ee94720d76933a21132e110fefbb0689a3adbaa4c685f43652136d09b3a359b5c671e38f11915cb5612db2ae294",
+ "af6de0e227bd78494acb559ddf34d8a7d55a03912384831be21c38376f39cda8a864aff7a48aed758f6bdf777779a669068a75ce82a06f6b3325c855ed83daf5513a078a61f7dc6c1622a633367e5f3a33e765c8ec5d8d54f48494006fdbf8922063e5340013e312871b7f8f8e5ea439c0d4cb78e2f19dd11f010729b692c65dd0d347f0ce53de9d849224666ea2f6487f1c6f953e8f9dbfd3d6de291c3e9d045e633cfd83c89d2f2327d0b2f31f72ac1604a3db1febc5f22cad08153278047210cc2894582c251a014c652e3951593e70e52a5d7451be8924b64f85c8247dab6268d24710b39fc1c07b4ac829fbda34ed79b5",
+ "d7314e8b1ff82100b8f5870da62b61c31ab37ace9e6a7b6f7d294571523783c1fdedcbc00dd487dd6f848c34aab493507d07071b5eb59d1a2346068c7f356755fbde3d2cab67514f8c3a12d6ff9f96a977a9ac9263491bd33122a904da5386b943d35a6ba383932df07f259b6b45f69e9b27b4ca124fb3ae143d709853eed86690bc2754d5f8865c355a44b5279d8eb31cdc00f7407fb5f5b34edc57fc7ace943565da2222dc80632ccf42f2f125ceb19714ea964c2e50603c9f8960c3f27c2ed0e18a559931c4352bd7422109a28c5e145003f55c9b7c664fdc985168868950396eaf6fefc7b73d815c1aca721d7c67da632925",
+ "2928b55c0e4d0f5cb4b60af59e9a702e3d616a8cf427c8bb03981fb8c29026d8f7d89161f36c11654f9a5e8ccb703595a58d671ecdc22c6a784abe363158682be4643002a7da5c9d268a30ea9a8d4cc24f562ab59f55c2b43af7dbcecc7e5ebe7494e82d74145a1e7d442125eb0431c5ea0939b27afa47f8ca97849f341f707660c7fbe49b7a0712fbcb6f7562ae2961425f27c7779c7534ecdeb8047ff3cb89a25159f3e1cefe42f9ef16426241f2c4d62c11d7ac43c4500dfcd184436bb4ef33260366f875230f26d81613c334dbda4736ba9d1d2966502914ec01bbe72d885606ec11da7a2cb01b29d35eebedbb0ecc73ed6c35",
+ "fd993f50e8a68c7b2c7f87511ce65b93c0aa94dcbdf2c9cca93816f0f3b2ab34c62c586fc507b4900a34cf9d0517e0fe10a89d154c5419c1f5e38de00e8834fe3dc1032abdeb10729a81655a69a12856a78ca6e12110580de879b086fd6608726541cfa9616326bdd36064bc0d1e5f9c93b41278bff6a13b2494b81e238c0c45aea1b07d855e8f3fe1478e373bd9d3957cf8a5e5b9003386793d994c7c575cff2322e2428cbbaa4f47560316ae3354a7478842ff7cc5dcbacb6e871e72b36f06d63a9aaeb9044cfb7974afdc238a5816f537dcf33ee40b4e1a5eb3cff2402b46d548264e133008d284f11b7e4e450bc3c5ff9f79b9c4",
+ "8df21892f5fc303b0de4adef1970186db6fe71bb3ea3094922e13afcfabf1d0be009f36d6f6310c5f9fda51f1a946507a055b645c296370440e5e83d8e906a2fb51f2b42de8856a81a4f28a73a8825c68ea08e5e366730bce8047011cb7d6d9be8c6f4211308fad21856284d5bc47d199988e0abf5badf8693ceeed0a2d98e8ae94b7775a42925edb1f697ffbd8e806af23145054a85e071819cca4cd48875290ca65e5ee72a9a54ff9f19c10ef4adaf8d04c9a9afcc73853fc128bbebc61f78702787c966ca6e1b1a0e4dab646acdfcd3c6bf3e5cfbec5ebe3e06c8abaa1de56e48421d87c46b5c78030afcafd91f27e7d7c85eb4872b",
+ "48ec6ec520f8e593d7b3f653eb15553de246723b81a6d0c3221aaa42a37420fba98a23796338dff5f845dce6d5a449be5ecc1887356619270461087e08d05fb60433a83d7bd00c002b09ea210b428965124b9b27d9105a71c826c1a2491cfd60e4cfa86c2da0c7100a8dc1c3f2f94b280d54e01e043acf0e966200d9fa8a41daf3b9382820786c75cadbb8841a1b2be5b6cbeb64878e4a231ae063a99b4e2308960ef0c8e2a16bb3545cc43bdf171493fb89a84f47e7973dc60cf75aeeca71e0a7ebe17d161d4fb9fe009941cc438f16a5bae6c99fcad08cac486eb2a48060b023d8730bf1d82fe60a2f036e6f52a5bff95f43bbe088933f",
+ "f4d84ed3e564c102600a795eaa9b1eaf4ad12f1a4deca1d042a0a2750ddf6201db03073d8bf553cb9dde48a1b0083827a609f7242b86584cc180964ae794b12ce55661e00e36a6ba4dbc389e6a5a85f1b45df9af7ead1b0a54db56e68639b9d438a91504e82c35d40c7bc7e048a53ac0b04accd0dadf4ac9884b0ca0e3cb5ba4336e3581be4c4760a553823ffa283a1120d4e145af56a59f2533903650f0b9e9ad9fe2e8a3c3c3dd03a1fcb709032c8835324839c735b0c051d0cbd8b5d867617c11023432e4bd275d3d0eb98a0b6cf58071a5b712922f2bc751ac7c2588c447444cde2f37a8ea5ec126425bf517e0d17c9e2999f52fee14b3",
+ "2ccea21bac9c2b70d3923309cbf2d7cb7abd1fcc8b8b002688870a80029c62397350c3c898194e5deea360bb963d26d485cb7963f8167586976ec0556950b2e86135f4a2800991ce8473bfd44a3c5e937a48b5e355ba5141bccf2131a83988d9d2a9e8e7635a956105b3512c05ef708139ced51d7a4e204c12d8a49a21e8dc6de2629a2fd092326885d9f218745fe09f6d91fb6afce250a30a63689534b6be1f26899ffa3767d835cf586aa47776700f94241bc999b1e3deefe188f37ff734f5f16ee6a00914323dc7b8a143c9137cdcc5cd08ae9566f04bb2941532674c97dff6ffa5ce3405ef8e5d27ec403114253dd6394c0167d72a0044c5",
+ "2b681c6398aee63bf862770341648bbcd31d7de7903c5903fe3d9469311320bb24d914f2af0cdca199c97214c7c679dc32a2800ba484a03c010ea6be3bb9f2c87e30a98b606050b8a3f297f12b8f92caaeceb3e844652115934874e0a1ab093a73d759b53f6a6c3096940dd22c2bb96ce6820a7b9c6d71a208de9892aa6a7209b0fff56a0cafea52b952cdd6f5752cff3309d448800b4e4c878aa595595b56b12b83fcd6ca89520c7da664e449d7b4438fc455888aad5de0fad9a06eed14afd3513b5ebbffe01775549b701181bd26370764f56eba52fdb24286ad1ac0f5418a7c429f7dfc7f3168437fa8eed7a2ed7c723a485e4c3ed14dea2e07",
+ "aadfd505a89f4aade2c3018258a7e039401b1fc6a7f3d87910dddbb880d372ec8a13c70d92245de5b8e5f9a285c33b99dc82fa2b22decee72b93a72211656ad7a52696c8e570f78be28c0e427a371dafde856e8d5ed24f83b0660b51e7fac05d93a8666dfde6def59af863f80f3e5f6801182c87422203df390dcb736b8f830052a8832eeeb0b4e27e732aaf793d166b5a3ec7745aeef3766937c2b75a276bddd145f6010c29d035e343e267cb2d828436876ec3a7ebe3b6347d4172f7a99d6821ce152e039e53deb33340b324c7f068ffb94b3cde35a8eaa12d15c3806a7ad0acec3e8c7078c1d32a28fd3eec9f32cb86e4c22166ff69e83785e851",
+ "1605b8cce529a9d6262fd4390d9e4ae5e14e0adc0ec89b028ef68dd0f373ea259aaa96f2967091dd0874c0105385e9e6da9ca68297c31afa44ef834535fb302ce5b4e49edacbbdf359fe1228a8172495b3e57014c27edd58b685110980056c50c398a64f4923f2d720b4df16d75cb36b4233660694182099c35028a972519c24764fc94e18e582b24deb3491535fc06b83837c7958522800e822201d694af0bd0aa3834e17d4b1ba36f470905ae5f8bbeeb6c4c8604d8af02baa347b07086d6989867ddd5e8e8ed7740c3469bfa2810519c55c6add1332c4c54ee9097961d6741cb12a09713a0d07645f784f42f5ad94b48b836b34263130b0483f15e3",
+ "ff9c6125b2f60bfd6c2427b279df070e430075096647599bdc68c531152c58e13858b82385d78c856092d6c74106e87ccf51ac7e673936332d9b223444eaa0e762ee258d8a733d3a515ec68ed73285e5ca183ae3278b4820b0ab2797feb1e7d8cc864df585dfb5ebe02a993325a9ad5e2d7d49d3132cf66013898351d044e0fe908ccdfeeebf651983601e3673a1f92d36510c0cc19b2e75856db8e4a41f92a51efa66d6cc22e414944c2c34a5a89ccde0be76f51410824e330d8e7c613194338c93732e8aea651fca18bcf1ac1824340c5553aff1e58d4ab8d7c8842b4712021e517cd6c140f6743c69c7bee05b10a8f24050a8caa4f96d1664909c5a06",
+ "6e85c2f8e1fdc3aaeb969da1258cb504bbf0070cd03d23b3fb5ee08feea5ee2e0ee1c71a5d0f4f701b351f4e4b4d74cb1e2ae6184814f77b62d2f08134b7236ebf6b67d8a6c9f01b4248b30667c555f5d8646dbfe291151b23c9c9857e33a4d5c847be29a5ee7b402e03bac02d1a4319acc0dd8f25e9c7a266f5e5c896cc11b5b238df96a0963ae806cb277abc515c298a3e61a3036b177acf87a56ca4478c4c6d0d468913de602ec891318bbaf52c97a77c35c5b7d164816cf24e4c4b0b5f45853882f716d61eb947a45ce2efa78f1c70a918512af1ad536cbe6148083385b34e207f5f690d7a954021e4b5f4258a385fd8a87809a481f34202af4caccb82",
+ "1e9b2c454e9de3a2d723d850331037dbf54133dbe27488ff757dd255833a27d8eb8a128ad12d0978b6884e25737086a704fb289aaaccf930d5b582ab4df1f55f0c429b6875edec3fe45464fa74164be056a55e243c4222c586bec5b18f39036aa903d98180f24f83d09a454dfa1e03a60e6a3ba4613e99c35f874d790174ee48a557f4f021ade4d1b278d7997ef094569b37b3db0505951e9ee8400adaea275c6db51b325ee730c69df97745b556ae41cd98741e28aa3a49544541eeb3da1b1e8fa4e8e9100d66dd0c7f5e2c271b1ecc077de79c462b9fe4c273543ecd82a5bea63c5acc01eca5fb780c7d7c8c9fe208ae8bd50cad1769693d92c6c8649d20d8",
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2b/blake2x.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2b/blake2x.go
new file mode 100644
index 000000000..c814496a7
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2b/blake2x.go
@@ -0,0 +1,177 @@
+// 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 blake2b
+
+import (
+ "encoding/binary"
+ "errors"
+ "io"
+)
+
+// XOF defines the interface to hash functions that
+// support arbitrary-length output.
+type XOF interface {
+ // Write absorbs more data into the hash's state. It panics if called
+ // after Read.
+ io.Writer
+
+ // Read reads more output from the hash. It returns io.EOF if the limit
+ // has been reached.
+ io.Reader
+
+ // Clone returns a copy of the XOF in its current state.
+ Clone() XOF
+
+ // Reset resets the XOF to its initial state.
+ Reset()
+}
+
+// OutputLengthUnknown can be used as the size argument to NewXOF to indicate
+// the the length of the output is not known in advance.
+const OutputLengthUnknown = 0
+
+// magicUnknownOutputLength is a magic value for the output size that indicates
+// an unknown number of output bytes.
+const magicUnknownOutputLength = (1 << 32) - 1
+
+// maxOutputLength is the absolute maximum number of bytes to produce when the
+// number of output bytes is unknown.
+const maxOutputLength = (1 << 32) * 64
+
+// NewXOF creates a new variable-output-length hash. The hash either produce a
+// known number of bytes (1 <= size < 2**32-1), or an unknown number of bytes
+// (size == OutputLengthUnknown). In the latter case, an absolute limit of
+// 256GiB applies.
+//
+// A non-nil key turns the hash into a MAC. The key must between
+// zero and 32 bytes long.
+func NewXOF(size uint32, key []byte) (XOF, error) {
+ if len(key) > Size {
+ return nil, errKeySize
+ }
+ if size == magicUnknownOutputLength {
+ // 2^32-1 indicates an unknown number of bytes and thus isn't a
+ // valid length.
+ return nil, errors.New("blake2b: XOF length too large")
+ }
+ if size == OutputLengthUnknown {
+ size = magicUnknownOutputLength
+ }
+ x := &xof{
+ d: digest{
+ size: Size,
+ keyLen: len(key),
+ },
+ length: size,
+ }
+ copy(x.d.key[:], key)
+ x.Reset()
+ return x, nil
+}
+
+type xof struct {
+ d digest
+ length uint32
+ remaining uint64
+ cfg, root, block [Size]byte
+ offset int
+ nodeOffset uint32
+ readMode bool
+}
+
+func (x *xof) Write(p []byte) (n int, err error) {
+ if x.readMode {
+ panic("blake2b: write to XOF after read")
+ }
+ return x.d.Write(p)
+}
+
+func (x *xof) Clone() XOF {
+ clone := *x
+ return &clone
+}
+
+func (x *xof) Reset() {
+ x.cfg[0] = byte(Size)
+ binary.LittleEndian.PutUint32(x.cfg[4:], uint32(Size)) // leaf length
+ binary.LittleEndian.PutUint32(x.cfg[12:], x.length) // XOF length
+ x.cfg[17] = byte(Size) // inner hash size
+
+ x.d.Reset()
+ x.d.h[1] ^= uint64(x.length) << 32
+
+ x.remaining = uint64(x.length)
+ if x.remaining == magicUnknownOutputLength {
+ x.remaining = maxOutputLength
+ }
+ x.offset, x.nodeOffset = 0, 0
+ x.readMode = false
+}
+
+func (x *xof) Read(p []byte) (n int, err error) {
+ if !x.readMode {
+ x.d.finalize(&x.root)
+ x.readMode = true
+ }
+
+ if x.remaining == 0 {
+ return 0, io.EOF
+ }
+
+ n = len(p)
+ if uint64(n) > x.remaining {
+ n = int(x.remaining)
+ p = p[:n]
+ }
+
+ if x.offset > 0 {
+ blockRemaining := Size - x.offset
+ if n < blockRemaining {
+ x.offset += copy(p, x.block[x.offset:])
+ x.remaining -= uint64(n)
+ return
+ }
+ copy(p, x.block[x.offset:])
+ p = p[blockRemaining:]
+ x.offset = 0
+ x.remaining -= uint64(blockRemaining)
+ }
+
+ for len(p) >= Size {
+ binary.LittleEndian.PutUint32(x.cfg[8:], x.nodeOffset)
+ x.nodeOffset++
+
+ x.d.initConfig(&x.cfg)
+ x.d.Write(x.root[:])
+ x.d.finalize(&x.block)
+
+ copy(p, x.block[:])
+ p = p[Size:]
+ x.remaining -= uint64(Size)
+ }
+
+ if todo := len(p); todo > 0 {
+ if x.remaining < uint64(Size) {
+ x.cfg[0] = byte(x.remaining)
+ }
+ binary.LittleEndian.PutUint32(x.cfg[8:], x.nodeOffset)
+ x.nodeOffset++
+
+ x.d.initConfig(&x.cfg)
+ x.d.Write(x.root[:])
+ x.d.finalize(&x.block)
+
+ x.offset = copy(p, x.block[:todo])
+ x.remaining -= uint64(todo)
+ }
+ return
+}
+
+func (d *digest) initConfig(cfg *[Size]byte) {
+ d.offset, d.c[0], d.c[1] = 0, 0, 0
+ for i := range d.h {
+ d.h[i] = iv[i] ^ binary.LittleEndian.Uint64(cfg[i*8:])
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2b/register.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2b/register.go
new file mode 100644
index 000000000..efd689af4
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2b/register.go
@@ -0,0 +1,32 @@
+// 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.
+
+// +build go1.9
+
+package blake2b
+
+import (
+ "crypto"
+ "hash"
+)
+
+func init() {
+ newHash256 := func() hash.Hash {
+ h, _ := New256(nil)
+ return h
+ }
+ newHash384 := func() hash.Hash {
+ h, _ := New384(nil)
+ return h
+ }
+
+ newHash512 := func() hash.Hash {
+ h, _ := New512(nil)
+ return h
+ }
+
+ crypto.RegisterHash(crypto.BLAKE2b_256, newHash256)
+ crypto.RegisterHash(crypto.BLAKE2b_384, newHash384)
+ crypto.RegisterHash(crypto.BLAKE2b_512, newHash512)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2s/blake2s.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2s/blake2s.go
new file mode 100644
index 000000000..ae0dc922b
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2s/blake2s.go
@@ -0,0 +1,187 @@
+// 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.
+
+// Package blake2s implements the BLAKE2s hash algorithm defined by RFC 7693
+// and the extendable output function (XOF) BLAKE2Xs.
+//
+// For a detailed specification of BLAKE2s see https://blake2.net/blake2.pdf
+// and for BLAKE2Xs see https://blake2.net/blake2x.pdf
+//
+// If you aren't sure which function you need, use BLAKE2s (Sum256 or New256).
+// If you need a secret-key MAC (message authentication code), use the New256
+// function with a non-nil key.
+//
+// BLAKE2X is a construction to compute hash values larger than 32 bytes. It
+// can produce hash values between 0 and 65535 bytes.
+package blake2s // import "golang.org/x/crypto/blake2s"
+
+import (
+ "encoding/binary"
+ "errors"
+ "hash"
+)
+
+const (
+ // The blocksize of BLAKE2s in bytes.
+ BlockSize = 64
+
+ // The hash size of BLAKE2s-256 in bytes.
+ Size = 32
+
+ // The hash size of BLAKE2s-128 in bytes.
+ Size128 = 16
+)
+
+var errKeySize = errors.New("blake2s: invalid key size")
+
+var iv = [8]uint32{
+ 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
+ 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
+}
+
+// Sum256 returns the BLAKE2s-256 checksum of the data.
+func Sum256(data []byte) [Size]byte {
+ var sum [Size]byte
+ checkSum(&sum, Size, data)
+ return sum
+}
+
+// New256 returns a new hash.Hash computing the BLAKE2s-256 checksum. A non-nil
+// key turns the hash into a MAC. The key must between zero and 32 bytes long.
+func New256(key []byte) (hash.Hash, error) { return newDigest(Size, key) }
+
+// New128 returns a new hash.Hash computing the BLAKE2s-128 checksum given a
+// non-empty key. Note that a 128-bit digest is too small to be secure as a
+// cryptographic hash and should only be used as a MAC, thus the key argument
+// is not optional.
+func New128(key []byte) (hash.Hash, error) {
+ if len(key) == 0 {
+ return nil, errors.New("blake2s: a key is required for a 128-bit hash")
+ }
+ return newDigest(Size128, key)
+}
+
+func newDigest(hashSize int, key []byte) (*digest, error) {
+ if len(key) > Size {
+ return nil, errKeySize
+ }
+ d := &digest{
+ size: hashSize,
+ keyLen: len(key),
+ }
+ copy(d.key[:], key)
+ d.Reset()
+ return d, nil
+}
+
+func checkSum(sum *[Size]byte, hashSize int, data []byte) {
+ var (
+ h [8]uint32
+ c [2]uint32
+ )
+
+ h = iv
+ h[0] ^= uint32(hashSize) | (1 << 16) | (1 << 24)
+
+ if length := len(data); length > BlockSize {
+ n := length &^ (BlockSize - 1)
+ if length == n {
+ n -= BlockSize
+ }
+ hashBlocks(&h, &c, 0, data[:n])
+ data = data[n:]
+ }
+
+ var block [BlockSize]byte
+ offset := copy(block[:], data)
+ remaining := uint32(BlockSize - offset)
+
+ if c[0] < remaining {
+ c[1]--
+ }
+ c[0] -= remaining
+
+ hashBlocks(&h, &c, 0xFFFFFFFF, block[:])
+
+ for i, v := range h {
+ binary.LittleEndian.PutUint32(sum[4*i:], v)
+ }
+}
+
+type digest struct {
+ h [8]uint32
+ c [2]uint32
+ size int
+ block [BlockSize]byte
+ offset int
+
+ key [BlockSize]byte
+ keyLen int
+}
+
+func (d *digest) BlockSize() int { return BlockSize }
+
+func (d *digest) Size() int { return d.size }
+
+func (d *digest) Reset() {
+ d.h = iv
+ d.h[0] ^= uint32(d.size) | (uint32(d.keyLen) << 8) | (1 << 16) | (1 << 24)
+ d.offset, d.c[0], d.c[1] = 0, 0, 0
+ if d.keyLen > 0 {
+ d.block = d.key
+ d.offset = BlockSize
+ }
+}
+
+func (d *digest) Write(p []byte) (n int, err error) {
+ n = len(p)
+
+ if d.offset > 0 {
+ remaining := BlockSize - d.offset
+ if n <= remaining {
+ d.offset += copy(d.block[d.offset:], p)
+ return
+ }
+ copy(d.block[d.offset:], p[:remaining])
+ hashBlocks(&d.h, &d.c, 0, d.block[:])
+ d.offset = 0
+ p = p[remaining:]
+ }
+
+ if length := len(p); length > BlockSize {
+ nn := length &^ (BlockSize - 1)
+ if length == nn {
+ nn -= BlockSize
+ }
+ hashBlocks(&d.h, &d.c, 0, p[:nn])
+ p = p[nn:]
+ }
+
+ d.offset += copy(d.block[:], p)
+ return
+}
+
+func (d *digest) Sum(sum []byte) []byte {
+ var hash [Size]byte
+ d.finalize(&hash)
+ return append(sum, hash[:d.size]...)
+}
+
+func (d *digest) finalize(hash *[Size]byte) {
+ var block [BlockSize]byte
+ h := d.h
+ c := d.c
+
+ copy(block[:], d.block[:d.offset])
+ remaining := uint32(BlockSize - d.offset)
+ if c[0] < remaining {
+ c[1]--
+ }
+ c[0] -= remaining
+
+ hashBlocks(&h, &c, 0xFFFFFFFF, block[:])
+ for i, v := range h {
+ binary.LittleEndian.PutUint32(hash[4*i:], v)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2s/blake2s_386.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2s/blake2s_386.go
new file mode 100644
index 000000000..45ae54614
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2s/blake2s_386.go
@@ -0,0 +1,35 @@
+// 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.
+
+// +build 386,!gccgo,!appengine
+
+package blake2s
+
+var (
+ useSSE4 = false
+ useSSSE3 = supportSSSE3()
+ useSSE2 = supportSSE2()
+)
+
+//go:noescape
+func supportSSE2() bool
+
+//go:noescape
+func supportSSSE3() bool
+
+//go:noescape
+func hashBlocksSSE2(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte)
+
+//go:noescape
+func hashBlocksSSSE3(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte)
+
+func hashBlocks(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) {
+ if useSSSE3 {
+ hashBlocksSSSE3(h, c, flag, blocks)
+ } else if useSSE2 {
+ hashBlocksSSE2(h, c, flag, blocks)
+ } else {
+ hashBlocksGeneric(h, c, flag, blocks)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2s/blake2s_386.s b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2s/blake2s_386.s
new file mode 100644
index 000000000..0bb65c70f
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2s/blake2s_386.s
@@ -0,0 +1,460 @@
+// 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.
+
+// +build 386,!gccgo,!appengine
+
+#include "textflag.h"
+
+DATA iv0<>+0x00(SB)/4, $0x6a09e667
+DATA iv0<>+0x04(SB)/4, $0xbb67ae85
+DATA iv0<>+0x08(SB)/4, $0x3c6ef372
+DATA iv0<>+0x0c(SB)/4, $0xa54ff53a
+GLOBL iv0<>(SB), (NOPTR+RODATA), $16
+
+DATA iv1<>+0x00(SB)/4, $0x510e527f
+DATA iv1<>+0x04(SB)/4, $0x9b05688c
+DATA iv1<>+0x08(SB)/4, $0x1f83d9ab
+DATA iv1<>+0x0c(SB)/4, $0x5be0cd19
+GLOBL iv1<>(SB), (NOPTR+RODATA), $16
+
+DATA rol16<>+0x00(SB)/8, $0x0504070601000302
+DATA rol16<>+0x08(SB)/8, $0x0D0C0F0E09080B0A
+GLOBL rol16<>(SB), (NOPTR+RODATA), $16
+
+DATA rol8<>+0x00(SB)/8, $0x0407060500030201
+DATA rol8<>+0x08(SB)/8, $0x0C0F0E0D080B0A09
+GLOBL rol8<>(SB), (NOPTR+RODATA), $16
+
+DATA counter<>+0x00(SB)/8, $0x40
+DATA counter<>+0x08(SB)/8, $0x0
+GLOBL counter<>(SB), (NOPTR+RODATA), $16
+
+#define ROTL_SSE2(n, t, v) \
+ MOVO v, t; \
+ PSLLL $n, t; \
+ PSRLL $(32-n), v; \
+ PXOR t, v
+
+#define ROTL_SSSE3(c, v) \
+ PSHUFB c, v
+
+#define ROUND_SSE2(v0, v1, v2, v3, m0, m1, m2, m3, t) \
+ PADDL m0, v0; \
+ PADDL v1, v0; \
+ PXOR v0, v3; \
+ ROTL_SSE2(16, t, v3); \
+ PADDL v3, v2; \
+ PXOR v2, v1; \
+ ROTL_SSE2(20, t, v1); \
+ PADDL m1, v0; \
+ PADDL v1, v0; \
+ PXOR v0, v3; \
+ ROTL_SSE2(24, t, v3); \
+ PADDL v3, v2; \
+ PXOR v2, v1; \
+ ROTL_SSE2(25, t, v1); \
+ PSHUFL $0x39, v1, v1; \
+ PSHUFL $0x4E, v2, v2; \
+ PSHUFL $0x93, v3, v3; \
+ PADDL m2, v0; \
+ PADDL v1, v0; \
+ PXOR v0, v3; \
+ ROTL_SSE2(16, t, v3); \
+ PADDL v3, v2; \
+ PXOR v2, v1; \
+ ROTL_SSE2(20, t, v1); \
+ PADDL m3, v0; \
+ PADDL v1, v0; \
+ PXOR v0, v3; \
+ ROTL_SSE2(24, t, v3); \
+ PADDL v3, v2; \
+ PXOR v2, v1; \
+ ROTL_SSE2(25, t, v1); \
+ PSHUFL $0x39, v3, v3; \
+ PSHUFL $0x4E, v2, v2; \
+ PSHUFL $0x93, v1, v1
+
+#define ROUND_SSSE3(v0, v1, v2, v3, m0, m1, m2, m3, t, c16, c8) \
+ PADDL m0, v0; \
+ PADDL v1, v0; \
+ PXOR v0, v3; \
+ ROTL_SSSE3(c16, v3); \
+ PADDL v3, v2; \
+ PXOR v2, v1; \
+ ROTL_SSE2(20, t, v1); \
+ PADDL m1, v0; \
+ PADDL v1, v0; \
+ PXOR v0, v3; \
+ ROTL_SSSE3(c8, v3); \
+ PADDL v3, v2; \
+ PXOR v2, v1; \
+ ROTL_SSE2(25, t, v1); \
+ PSHUFL $0x39, v1, v1; \
+ PSHUFL $0x4E, v2, v2; \
+ PSHUFL $0x93, v3, v3; \
+ PADDL m2, v0; \
+ PADDL v1, v0; \
+ PXOR v0, v3; \
+ ROTL_SSSE3(c16, v3); \
+ PADDL v3, v2; \
+ PXOR v2, v1; \
+ ROTL_SSE2(20, t, v1); \
+ PADDL m3, v0; \
+ PADDL v1, v0; \
+ PXOR v0, v3; \
+ ROTL_SSSE3(c8, v3); \
+ PADDL v3, v2; \
+ PXOR v2, v1; \
+ ROTL_SSE2(25, t, v1); \
+ PSHUFL $0x39, v3, v3; \
+ PSHUFL $0x4E, v2, v2; \
+ PSHUFL $0x93, v1, v1
+
+#define PRECOMPUTE(dst, off, src, t) \
+ MOVL 0*4(src), t; \
+ MOVL t, 0*4+off+0(dst); \
+ MOVL t, 9*4+off+64(dst); \
+ MOVL t, 5*4+off+128(dst); \
+ MOVL t, 14*4+off+192(dst); \
+ MOVL t, 4*4+off+256(dst); \
+ MOVL t, 2*4+off+320(dst); \
+ MOVL t, 8*4+off+384(dst); \
+ MOVL t, 12*4+off+448(dst); \
+ MOVL t, 3*4+off+512(dst); \
+ MOVL t, 15*4+off+576(dst); \
+ MOVL 1*4(src), t; \
+ MOVL t, 4*4+off+0(dst); \
+ MOVL t, 8*4+off+64(dst); \
+ MOVL t, 14*4+off+128(dst); \
+ MOVL t, 5*4+off+192(dst); \
+ MOVL t, 12*4+off+256(dst); \
+ MOVL t, 11*4+off+320(dst); \
+ MOVL t, 1*4+off+384(dst); \
+ MOVL t, 6*4+off+448(dst); \
+ MOVL t, 10*4+off+512(dst); \
+ MOVL t, 3*4+off+576(dst); \
+ MOVL 2*4(src), t; \
+ MOVL t, 1*4+off+0(dst); \
+ MOVL t, 13*4+off+64(dst); \
+ MOVL t, 6*4+off+128(dst); \
+ MOVL t, 8*4+off+192(dst); \
+ MOVL t, 2*4+off+256(dst); \
+ MOVL t, 0*4+off+320(dst); \
+ MOVL t, 14*4+off+384(dst); \
+ MOVL t, 11*4+off+448(dst); \
+ MOVL t, 12*4+off+512(dst); \
+ MOVL t, 4*4+off+576(dst); \
+ MOVL 3*4(src), t; \
+ MOVL t, 5*4+off+0(dst); \
+ MOVL t, 15*4+off+64(dst); \
+ MOVL t, 9*4+off+128(dst); \
+ MOVL t, 1*4+off+192(dst); \
+ MOVL t, 11*4+off+256(dst); \
+ MOVL t, 7*4+off+320(dst); \
+ MOVL t, 13*4+off+384(dst); \
+ MOVL t, 3*4+off+448(dst); \
+ MOVL t, 6*4+off+512(dst); \
+ MOVL t, 10*4+off+576(dst); \
+ MOVL 4*4(src), t; \
+ MOVL t, 2*4+off+0(dst); \
+ MOVL t, 1*4+off+64(dst); \
+ MOVL t, 15*4+off+128(dst); \
+ MOVL t, 10*4+off+192(dst); \
+ MOVL t, 6*4+off+256(dst); \
+ MOVL t, 8*4+off+320(dst); \
+ MOVL t, 3*4+off+384(dst); \
+ MOVL t, 13*4+off+448(dst); \
+ MOVL t, 14*4+off+512(dst); \
+ MOVL t, 5*4+off+576(dst); \
+ MOVL 5*4(src), t; \
+ MOVL t, 6*4+off+0(dst); \
+ MOVL t, 11*4+off+64(dst); \
+ MOVL t, 2*4+off+128(dst); \
+ MOVL t, 9*4+off+192(dst); \
+ MOVL t, 1*4+off+256(dst); \
+ MOVL t, 13*4+off+320(dst); \
+ MOVL t, 4*4+off+384(dst); \
+ MOVL t, 8*4+off+448(dst); \
+ MOVL t, 15*4+off+512(dst); \
+ MOVL t, 7*4+off+576(dst); \
+ MOVL 6*4(src), t; \
+ MOVL t, 3*4+off+0(dst); \
+ MOVL t, 7*4+off+64(dst); \
+ MOVL t, 13*4+off+128(dst); \
+ MOVL t, 12*4+off+192(dst); \
+ MOVL t, 10*4+off+256(dst); \
+ MOVL t, 1*4+off+320(dst); \
+ MOVL t, 9*4+off+384(dst); \
+ MOVL t, 14*4+off+448(dst); \
+ MOVL t, 0*4+off+512(dst); \
+ MOVL t, 6*4+off+576(dst); \
+ MOVL 7*4(src), t; \
+ MOVL t, 7*4+off+0(dst); \
+ MOVL t, 14*4+off+64(dst); \
+ MOVL t, 10*4+off+128(dst); \
+ MOVL t, 0*4+off+192(dst); \
+ MOVL t, 5*4+off+256(dst); \
+ MOVL t, 9*4+off+320(dst); \
+ MOVL t, 12*4+off+384(dst); \
+ MOVL t, 1*4+off+448(dst); \
+ MOVL t, 13*4+off+512(dst); \
+ MOVL t, 2*4+off+576(dst); \
+ MOVL 8*4(src), t; \
+ MOVL t, 8*4+off+0(dst); \
+ MOVL t, 5*4+off+64(dst); \
+ MOVL t, 4*4+off+128(dst); \
+ MOVL t, 15*4+off+192(dst); \
+ MOVL t, 14*4+off+256(dst); \
+ MOVL t, 3*4+off+320(dst); \
+ MOVL t, 11*4+off+384(dst); \
+ MOVL t, 10*4+off+448(dst); \
+ MOVL t, 7*4+off+512(dst); \
+ MOVL t, 1*4+off+576(dst); \
+ MOVL 9*4(src), t; \
+ MOVL t, 12*4+off+0(dst); \
+ MOVL t, 2*4+off+64(dst); \
+ MOVL t, 11*4+off+128(dst); \
+ MOVL t, 4*4+off+192(dst); \
+ MOVL t, 0*4+off+256(dst); \
+ MOVL t, 15*4+off+320(dst); \
+ MOVL t, 10*4+off+384(dst); \
+ MOVL t, 7*4+off+448(dst); \
+ MOVL t, 5*4+off+512(dst); \
+ MOVL t, 9*4+off+576(dst); \
+ MOVL 10*4(src), t; \
+ MOVL t, 9*4+off+0(dst); \
+ MOVL t, 4*4+off+64(dst); \
+ MOVL t, 8*4+off+128(dst); \
+ MOVL t, 13*4+off+192(dst); \
+ MOVL t, 3*4+off+256(dst); \
+ MOVL t, 5*4+off+320(dst); \
+ MOVL t, 7*4+off+384(dst); \
+ MOVL t, 15*4+off+448(dst); \
+ MOVL t, 11*4+off+512(dst); \
+ MOVL t, 0*4+off+576(dst); \
+ MOVL 11*4(src), t; \
+ MOVL t, 13*4+off+0(dst); \
+ MOVL t, 10*4+off+64(dst); \
+ MOVL t, 0*4+off+128(dst); \
+ MOVL t, 3*4+off+192(dst); \
+ MOVL t, 9*4+off+256(dst); \
+ MOVL t, 6*4+off+320(dst); \
+ MOVL t, 15*4+off+384(dst); \
+ MOVL t, 4*4+off+448(dst); \
+ MOVL t, 2*4+off+512(dst); \
+ MOVL t, 12*4+off+576(dst); \
+ MOVL 12*4(src), t; \
+ MOVL t, 10*4+off+0(dst); \
+ MOVL t, 12*4+off+64(dst); \
+ MOVL t, 1*4+off+128(dst); \
+ MOVL t, 6*4+off+192(dst); \
+ MOVL t, 13*4+off+256(dst); \
+ MOVL t, 4*4+off+320(dst); \
+ MOVL t, 0*4+off+384(dst); \
+ MOVL t, 2*4+off+448(dst); \
+ MOVL t, 8*4+off+512(dst); \
+ MOVL t, 14*4+off+576(dst); \
+ MOVL 13*4(src), t; \
+ MOVL t, 14*4+off+0(dst); \
+ MOVL t, 3*4+off+64(dst); \
+ MOVL t, 7*4+off+128(dst); \
+ MOVL t, 2*4+off+192(dst); \
+ MOVL t, 15*4+off+256(dst); \
+ MOVL t, 12*4+off+320(dst); \
+ MOVL t, 6*4+off+384(dst); \
+ MOVL t, 0*4+off+448(dst); \
+ MOVL t, 9*4+off+512(dst); \
+ MOVL t, 11*4+off+576(dst); \
+ MOVL 14*4(src), t; \
+ MOVL t, 11*4+off+0(dst); \
+ MOVL t, 0*4+off+64(dst); \
+ MOVL t, 12*4+off+128(dst); \
+ MOVL t, 7*4+off+192(dst); \
+ MOVL t, 8*4+off+256(dst); \
+ MOVL t, 14*4+off+320(dst); \
+ MOVL t, 2*4+off+384(dst); \
+ MOVL t, 5*4+off+448(dst); \
+ MOVL t, 1*4+off+512(dst); \
+ MOVL t, 13*4+off+576(dst); \
+ MOVL 15*4(src), t; \
+ MOVL t, 15*4+off+0(dst); \
+ MOVL t, 6*4+off+64(dst); \
+ MOVL t, 3*4+off+128(dst); \
+ MOVL t, 11*4+off+192(dst); \
+ MOVL t, 7*4+off+256(dst); \
+ MOVL t, 10*4+off+320(dst); \
+ MOVL t, 5*4+off+384(dst); \
+ MOVL t, 9*4+off+448(dst); \
+ MOVL t, 4*4+off+512(dst); \
+ MOVL t, 8*4+off+576(dst)
+
+// func hashBlocksSSE2(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte)
+TEXT ·hashBlocksSSE2(SB), 0, $672-24 // frame = 656 + 16 byte alignment
+ MOVL h+0(FP), AX
+ MOVL c+4(FP), BX
+ MOVL flag+8(FP), CX
+ MOVL blocks_base+12(FP), SI
+ MOVL blocks_len+16(FP), DX
+
+ MOVL SP, BP
+ MOVL SP, DI
+ ADDL $15, DI
+ ANDL $~15, DI
+ MOVL DI, SP
+
+ MOVL CX, 8(SP)
+ MOVL 0(BX), CX
+ MOVL CX, 0(SP)
+ MOVL 4(BX), CX
+ MOVL CX, 4(SP)
+ XORL CX, CX
+ MOVL CX, 12(SP)
+
+ MOVOU 0(AX), X0
+ MOVOU 16(AX), X1
+ MOVOU counter<>(SB), X2
+
+loop:
+ MOVO X0, X4
+ MOVO X1, X5
+ MOVOU iv0<>(SB), X6
+ MOVOU iv1<>(SB), X7
+
+ MOVO 0(SP), X3
+ PADDQ X2, X3
+ PXOR X3, X7
+ MOVO X3, 0(SP)
+
+ PRECOMPUTE(SP, 16, SI, CX)
+ ROUND_SSE2(X4, X5, X6, X7, 16(SP), 32(SP), 48(SP), 64(SP), X3)
+ ROUND_SSE2(X4, X5, X6, X7, 16+64(SP), 32+64(SP), 48+64(SP), 64+64(SP), X3)
+ ROUND_SSE2(X4, X5, X6, X7, 16+128(SP), 32+128(SP), 48+128(SP), 64+128(SP), X3)
+ ROUND_SSE2(X4, X5, X6, X7, 16+192(SP), 32+192(SP), 48+192(SP), 64+192(SP), X3)
+ ROUND_SSE2(X4, X5, X6, X7, 16+256(SP), 32+256(SP), 48+256(SP), 64+256(SP), X3)
+ ROUND_SSE2(X4, X5, X6, X7, 16+320(SP), 32+320(SP), 48+320(SP), 64+320(SP), X3)
+ ROUND_SSE2(X4, X5, X6, X7, 16+384(SP), 32+384(SP), 48+384(SP), 64+384(SP), X3)
+ ROUND_SSE2(X4, X5, X6, X7, 16+448(SP), 32+448(SP), 48+448(SP), 64+448(SP), X3)
+ ROUND_SSE2(X4, X5, X6, X7, 16+512(SP), 32+512(SP), 48+512(SP), 64+512(SP), X3)
+ ROUND_SSE2(X4, X5, X6, X7, 16+576(SP), 32+576(SP), 48+576(SP), 64+576(SP), X3)
+
+ PXOR X4, X0
+ PXOR X5, X1
+ PXOR X6, X0
+ PXOR X7, X1
+
+ LEAL 64(SI), SI
+ SUBL $64, DX
+ JNE loop
+
+ MOVL 0(SP), CX
+ MOVL CX, 0(BX)
+ MOVL 4(SP), CX
+ MOVL CX, 4(BX)
+
+ MOVOU X0, 0(AX)
+ MOVOU X1, 16(AX)
+
+ MOVL BP, SP
+ RET
+
+// func hashBlocksSSSE3(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte)
+TEXT ·hashBlocksSSSE3(SB), 0, $704-24 // frame = 688 + 16 byte alignment
+ MOVL h+0(FP), AX
+ MOVL c+4(FP), BX
+ MOVL flag+8(FP), CX
+ MOVL blocks_base+12(FP), SI
+ MOVL blocks_len+16(FP), DX
+
+ MOVL SP, BP
+ MOVL SP, DI
+ ADDL $15, DI
+ ANDL $~15, DI
+ MOVL DI, SP
+
+ MOVL CX, 8(SP)
+ MOVL 0(BX), CX
+ MOVL CX, 0(SP)
+ MOVL 4(BX), CX
+ MOVL CX, 4(SP)
+ XORL CX, CX
+ MOVL CX, 12(SP)
+
+ MOVOU 0(AX), X0
+ MOVOU 16(AX), X1
+ MOVOU counter<>(SB), X2
+
+loop:
+ MOVO X0, 656(SP)
+ MOVO X1, 672(SP)
+ MOVO X0, X4
+ MOVO X1, X5
+ MOVOU iv0<>(SB), X6
+ MOVOU iv1<>(SB), X7
+
+ MOVO 0(SP), X3
+ PADDQ X2, X3
+ PXOR X3, X7
+ MOVO X3, 0(SP)
+
+ MOVOU rol16<>(SB), X0
+ MOVOU rol8<>(SB), X1
+
+ PRECOMPUTE(SP, 16, SI, CX)
+ ROUND_SSSE3(X4, X5, X6, X7, 16(SP), 32(SP), 48(SP), 64(SP), X3, X0, X1)
+ ROUND_SSSE3(X4, X5, X6, X7, 16+64(SP), 32+64(SP), 48+64(SP), 64+64(SP), X3, X0, X1)
+ ROUND_SSSE3(X4, X5, X6, X7, 16+128(SP), 32+128(SP), 48+128(SP), 64+128(SP), X3, X0, X1)
+ ROUND_SSSE3(X4, X5, X6, X7, 16+192(SP), 32+192(SP), 48+192(SP), 64+192(SP), X3, X0, X1)
+ ROUND_SSSE3(X4, X5, X6, X7, 16+256(SP), 32+256(SP), 48+256(SP), 64+256(SP), X3, X0, X1)
+ ROUND_SSSE3(X4, X5, X6, X7, 16+320(SP), 32+320(SP), 48+320(SP), 64+320(SP), X3, X0, X1)
+ ROUND_SSSE3(X4, X5, X6, X7, 16+384(SP), 32+384(SP), 48+384(SP), 64+384(SP), X3, X0, X1)
+ ROUND_SSSE3(X4, X5, X6, X7, 16+448(SP), 32+448(SP), 48+448(SP), 64+448(SP), X3, X0, X1)
+ ROUND_SSSE3(X4, X5, X6, X7, 16+512(SP), 32+512(SP), 48+512(SP), 64+512(SP), X3, X0, X1)
+ ROUND_SSSE3(X4, X5, X6, X7, 16+576(SP), 32+576(SP), 48+576(SP), 64+576(SP), X3, X0, X1)
+
+ MOVO 656(SP), X0
+ MOVO 672(SP), X1
+ PXOR X4, X0
+ PXOR X5, X1
+ PXOR X6, X0
+ PXOR X7, X1
+
+ LEAL 64(SI), SI
+ SUBL $64, DX
+ JNE loop
+
+ MOVL 0(SP), CX
+ MOVL CX, 0(BX)
+ MOVL 4(SP), CX
+ MOVL CX, 4(BX)
+
+ MOVOU X0, 0(AX)
+ MOVOU X1, 16(AX)
+
+ MOVL BP, SP
+ RET
+
+// func supportSSSE3() bool
+TEXT ·supportSSSE3(SB), 4, $0-1
+ MOVL $1, AX
+ CPUID
+ MOVL CX, BX
+ ANDL $0x1, BX // supports SSE3
+ JZ FALSE
+ ANDL $0x200, CX // supports SSSE3
+ JZ FALSE
+ MOVB $1, ret+0(FP)
+ RET
+
+FALSE:
+ MOVB $0, ret+0(FP)
+ RET
+
+// func supportSSE2() bool
+TEXT ·supportSSE2(SB), 4, $0-1
+ MOVL $1, AX
+ CPUID
+ SHRL $26, DX
+ ANDL $1, DX // DX != 0 if support SSE2
+ MOVB DX, ret+0(FP)
+ RET
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2s/blake2s_amd64.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2s/blake2s_amd64.go
new file mode 100644
index 000000000..a925e6b20
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2s/blake2s_amd64.go
@@ -0,0 +1,40 @@
+// 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.
+
+// +build amd64,!gccgo,!appengine
+
+package blake2s
+
+var (
+ useSSE4 = supportSSE4()
+ useSSSE3 = supportSSSE3()
+ useSSE2 = true // Always available on amd64
+)
+
+//go:noescape
+func supportSSSE3() bool
+
+//go:noescape
+func supportSSE4() bool
+
+//go:noescape
+func hashBlocksSSE2(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte)
+
+//go:noescape
+func hashBlocksSSSE3(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte)
+
+//go:noescape
+func hashBlocksSSE4(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte)
+
+func hashBlocks(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) {
+ if useSSE4 {
+ hashBlocksSSE4(h, c, flag, blocks)
+ } else if useSSSE3 {
+ hashBlocksSSSE3(h, c, flag, blocks)
+ } else if useSSE2 {
+ hashBlocksSSE2(h, c, flag, blocks)
+ } else {
+ hashBlocksGeneric(h, c, flag, blocks)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2s/blake2s_amd64.s b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2s/blake2s_amd64.s
new file mode 100644
index 000000000..6cdf5a94c
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2s/blake2s_amd64.s
@@ -0,0 +1,463 @@
+// 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.
+
+// +build amd64,!gccgo,!appengine
+
+#include "textflag.h"
+
+DATA iv0<>+0x00(SB)/4, $0x6a09e667
+DATA iv0<>+0x04(SB)/4, $0xbb67ae85
+DATA iv0<>+0x08(SB)/4, $0x3c6ef372
+DATA iv0<>+0x0c(SB)/4, $0xa54ff53a
+GLOBL iv0<>(SB), (NOPTR+RODATA), $16
+
+DATA iv1<>+0x00(SB)/4, $0x510e527f
+DATA iv1<>+0x04(SB)/4, $0x9b05688c
+DATA iv1<>+0x08(SB)/4, $0x1f83d9ab
+DATA iv1<>+0x0c(SB)/4, $0x5be0cd19
+GLOBL iv1<>(SB), (NOPTR+RODATA), $16
+
+DATA rol16<>+0x00(SB)/8, $0x0504070601000302
+DATA rol16<>+0x08(SB)/8, $0x0D0C0F0E09080B0A
+GLOBL rol16<>(SB), (NOPTR+RODATA), $16
+
+DATA rol8<>+0x00(SB)/8, $0x0407060500030201
+DATA rol8<>+0x08(SB)/8, $0x0C0F0E0D080B0A09
+GLOBL rol8<>(SB), (NOPTR+RODATA), $16
+
+DATA counter<>+0x00(SB)/8, $0x40
+DATA counter<>+0x08(SB)/8, $0x0
+GLOBL counter<>(SB), (NOPTR+RODATA), $16
+
+#define ROTL_SSE2(n, t, v) \
+ MOVO v, t; \
+ PSLLL $n, t; \
+ PSRLL $(32-n), v; \
+ PXOR t, v
+
+#define ROTL_SSSE3(c, v) \
+ PSHUFB c, v
+
+#define ROUND_SSE2(v0, v1, v2, v3, m0, m1, m2, m3, t) \
+ PADDL m0, v0; \
+ PADDL v1, v0; \
+ PXOR v0, v3; \
+ ROTL_SSE2(16, t, v3); \
+ PADDL v3, v2; \
+ PXOR v2, v1; \
+ ROTL_SSE2(20, t, v1); \
+ PADDL m1, v0; \
+ PADDL v1, v0; \
+ PXOR v0, v3; \
+ ROTL_SSE2(24, t, v3); \
+ PADDL v3, v2; \
+ PXOR v2, v1; \
+ ROTL_SSE2(25, t, v1); \
+ PSHUFL $0x39, v1, v1; \
+ PSHUFL $0x4E, v2, v2; \
+ PSHUFL $0x93, v3, v3; \
+ PADDL m2, v0; \
+ PADDL v1, v0; \
+ PXOR v0, v3; \
+ ROTL_SSE2(16, t, v3); \
+ PADDL v3, v2; \
+ PXOR v2, v1; \
+ ROTL_SSE2(20, t, v1); \
+ PADDL m3, v0; \
+ PADDL v1, v0; \
+ PXOR v0, v3; \
+ ROTL_SSE2(24, t, v3); \
+ PADDL v3, v2; \
+ PXOR v2, v1; \
+ ROTL_SSE2(25, t, v1); \
+ PSHUFL $0x39, v3, v3; \
+ PSHUFL $0x4E, v2, v2; \
+ PSHUFL $0x93, v1, v1
+
+#define ROUND_SSSE3(v0, v1, v2, v3, m0, m1, m2, m3, t, c16, c8) \
+ PADDL m0, v0; \
+ PADDL v1, v0; \
+ PXOR v0, v3; \
+ ROTL_SSSE3(c16, v3); \
+ PADDL v3, v2; \
+ PXOR v2, v1; \
+ ROTL_SSE2(20, t, v1); \
+ PADDL m1, v0; \
+ PADDL v1, v0; \
+ PXOR v0, v3; \
+ ROTL_SSSE3(c8, v3); \
+ PADDL v3, v2; \
+ PXOR v2, v1; \
+ ROTL_SSE2(25, t, v1); \
+ PSHUFL $0x39, v1, v1; \
+ PSHUFL $0x4E, v2, v2; \
+ PSHUFL $0x93, v3, v3; \
+ PADDL m2, v0; \
+ PADDL v1, v0; \
+ PXOR v0, v3; \
+ ROTL_SSSE3(c16, v3); \
+ PADDL v3, v2; \
+ PXOR v2, v1; \
+ ROTL_SSE2(20, t, v1); \
+ PADDL m3, v0; \
+ PADDL v1, v0; \
+ PXOR v0, v3; \
+ ROTL_SSSE3(c8, v3); \
+ PADDL v3, v2; \
+ PXOR v2, v1; \
+ ROTL_SSE2(25, t, v1); \
+ PSHUFL $0x39, v3, v3; \
+ PSHUFL $0x4E, v2, v2; \
+ PSHUFL $0x93, v1, v1
+
+
+#define LOAD_MSG_SSE4(m0, m1, m2, m3, src, i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15) \
+ MOVL i0*4(src), m0; \
+ PINSRD $1, i1*4(src), m0; \
+ PINSRD $2, i2*4(src), m0; \
+ PINSRD $3, i3*4(src), m0; \
+ MOVL i4*4(src), m1; \
+ PINSRD $1, i5*4(src), m1; \
+ PINSRD $2, i6*4(src), m1; \
+ PINSRD $3, i7*4(src), m1; \
+ MOVL i8*4(src), m2; \
+ PINSRD $1, i9*4(src), m2; \
+ PINSRD $2, i10*4(src), m2; \
+ PINSRD $3, i11*4(src), m2; \
+ MOVL i12*4(src), m3; \
+ PINSRD $1, i13*4(src), m3; \
+ PINSRD $2, i14*4(src), m3; \
+ PINSRD $3, i15*4(src), m3
+
+#define PRECOMPUTE_MSG(dst, off, src, R8, R9, R10, R11, R12, R13, R14, R15) \
+ MOVQ 0*4(src), R8; \
+ MOVQ 2*4(src), R9; \
+ MOVQ 4*4(src), R10; \
+ MOVQ 6*4(src), R11; \
+ MOVQ 8*4(src), R12; \
+ MOVQ 10*4(src), R13; \
+ MOVQ 12*4(src), R14; \
+ MOVQ 14*4(src), R15; \
+ \
+ MOVL R8, 0*4+off+0(dst); \
+ MOVL R8, 9*4+off+64(dst); \
+ MOVL R8, 5*4+off+128(dst); \
+ MOVL R8, 14*4+off+192(dst); \
+ MOVL R8, 4*4+off+256(dst); \
+ MOVL R8, 2*4+off+320(dst); \
+ MOVL R8, 8*4+off+384(dst); \
+ MOVL R8, 12*4+off+448(dst); \
+ MOVL R8, 3*4+off+512(dst); \
+ MOVL R8, 15*4+off+576(dst); \
+ SHRQ $32, R8; \
+ MOVL R8, 4*4+off+0(dst); \
+ MOVL R8, 8*4+off+64(dst); \
+ MOVL R8, 14*4+off+128(dst); \
+ MOVL R8, 5*4+off+192(dst); \
+ MOVL R8, 12*4+off+256(dst); \
+ MOVL R8, 11*4+off+320(dst); \
+ MOVL R8, 1*4+off+384(dst); \
+ MOVL R8, 6*4+off+448(dst); \
+ MOVL R8, 10*4+off+512(dst); \
+ MOVL R8, 3*4+off+576(dst); \
+ \
+ MOVL R9, 1*4+off+0(dst); \
+ MOVL R9, 13*4+off+64(dst); \
+ MOVL R9, 6*4+off+128(dst); \
+ MOVL R9, 8*4+off+192(dst); \
+ MOVL R9, 2*4+off+256(dst); \
+ MOVL R9, 0*4+off+320(dst); \
+ MOVL R9, 14*4+off+384(dst); \
+ MOVL R9, 11*4+off+448(dst); \
+ MOVL R9, 12*4+off+512(dst); \
+ MOVL R9, 4*4+off+576(dst); \
+ SHRQ $32, R9; \
+ MOVL R9, 5*4+off+0(dst); \
+ MOVL R9, 15*4+off+64(dst); \
+ MOVL R9, 9*4+off+128(dst); \
+ MOVL R9, 1*4+off+192(dst); \
+ MOVL R9, 11*4+off+256(dst); \
+ MOVL R9, 7*4+off+320(dst); \
+ MOVL R9, 13*4+off+384(dst); \
+ MOVL R9, 3*4+off+448(dst); \
+ MOVL R9, 6*4+off+512(dst); \
+ MOVL R9, 10*4+off+576(dst); \
+ \
+ MOVL R10, 2*4+off+0(dst); \
+ MOVL R10, 1*4+off+64(dst); \
+ MOVL R10, 15*4+off+128(dst); \
+ MOVL R10, 10*4+off+192(dst); \
+ MOVL R10, 6*4+off+256(dst); \
+ MOVL R10, 8*4+off+320(dst); \
+ MOVL R10, 3*4+off+384(dst); \
+ MOVL R10, 13*4+off+448(dst); \
+ MOVL R10, 14*4+off+512(dst); \
+ MOVL R10, 5*4+off+576(dst); \
+ SHRQ $32, R10; \
+ MOVL R10, 6*4+off+0(dst); \
+ MOVL R10, 11*4+off+64(dst); \
+ MOVL R10, 2*4+off+128(dst); \
+ MOVL R10, 9*4+off+192(dst); \
+ MOVL R10, 1*4+off+256(dst); \
+ MOVL R10, 13*4+off+320(dst); \
+ MOVL R10, 4*4+off+384(dst); \
+ MOVL R10, 8*4+off+448(dst); \
+ MOVL R10, 15*4+off+512(dst); \
+ MOVL R10, 7*4+off+576(dst); \
+ \
+ MOVL R11, 3*4+off+0(dst); \
+ MOVL R11, 7*4+off+64(dst); \
+ MOVL R11, 13*4+off+128(dst); \
+ MOVL R11, 12*4+off+192(dst); \
+ MOVL R11, 10*4+off+256(dst); \
+ MOVL R11, 1*4+off+320(dst); \
+ MOVL R11, 9*4+off+384(dst); \
+ MOVL R11, 14*4+off+448(dst); \
+ MOVL R11, 0*4+off+512(dst); \
+ MOVL R11, 6*4+off+576(dst); \
+ SHRQ $32, R11; \
+ MOVL R11, 7*4+off+0(dst); \
+ MOVL R11, 14*4+off+64(dst); \
+ MOVL R11, 10*4+off+128(dst); \
+ MOVL R11, 0*4+off+192(dst); \
+ MOVL R11, 5*4+off+256(dst); \
+ MOVL R11, 9*4+off+320(dst); \
+ MOVL R11, 12*4+off+384(dst); \
+ MOVL R11, 1*4+off+448(dst); \
+ MOVL R11, 13*4+off+512(dst); \
+ MOVL R11, 2*4+off+576(dst); \
+ \
+ MOVL R12, 8*4+off+0(dst); \
+ MOVL R12, 5*4+off+64(dst); \
+ MOVL R12, 4*4+off+128(dst); \
+ MOVL R12, 15*4+off+192(dst); \
+ MOVL R12, 14*4+off+256(dst); \
+ MOVL R12, 3*4+off+320(dst); \
+ MOVL R12, 11*4+off+384(dst); \
+ MOVL R12, 10*4+off+448(dst); \
+ MOVL R12, 7*4+off+512(dst); \
+ MOVL R12, 1*4+off+576(dst); \
+ SHRQ $32, R12; \
+ MOVL R12, 12*4+off+0(dst); \
+ MOVL R12, 2*4+off+64(dst); \
+ MOVL R12, 11*4+off+128(dst); \
+ MOVL R12, 4*4+off+192(dst); \
+ MOVL R12, 0*4+off+256(dst); \
+ MOVL R12, 15*4+off+320(dst); \
+ MOVL R12, 10*4+off+384(dst); \
+ MOVL R12, 7*4+off+448(dst); \
+ MOVL R12, 5*4+off+512(dst); \
+ MOVL R12, 9*4+off+576(dst); \
+ \
+ MOVL R13, 9*4+off+0(dst); \
+ MOVL R13, 4*4+off+64(dst); \
+ MOVL R13, 8*4+off+128(dst); \
+ MOVL R13, 13*4+off+192(dst); \
+ MOVL R13, 3*4+off+256(dst); \
+ MOVL R13, 5*4+off+320(dst); \
+ MOVL R13, 7*4+off+384(dst); \
+ MOVL R13, 15*4+off+448(dst); \
+ MOVL R13, 11*4+off+512(dst); \
+ MOVL R13, 0*4+off+576(dst); \
+ SHRQ $32, R13; \
+ MOVL R13, 13*4+off+0(dst); \
+ MOVL R13, 10*4+off+64(dst); \
+ MOVL R13, 0*4+off+128(dst); \
+ MOVL R13, 3*4+off+192(dst); \
+ MOVL R13, 9*4+off+256(dst); \
+ MOVL R13, 6*4+off+320(dst); \
+ MOVL R13, 15*4+off+384(dst); \
+ MOVL R13, 4*4+off+448(dst); \
+ MOVL R13, 2*4+off+512(dst); \
+ MOVL R13, 12*4+off+576(dst); \
+ \
+ MOVL R14, 10*4+off+0(dst); \
+ MOVL R14, 12*4+off+64(dst); \
+ MOVL R14, 1*4+off+128(dst); \
+ MOVL R14, 6*4+off+192(dst); \
+ MOVL R14, 13*4+off+256(dst); \
+ MOVL R14, 4*4+off+320(dst); \
+ MOVL R14, 0*4+off+384(dst); \
+ MOVL R14, 2*4+off+448(dst); \
+ MOVL R14, 8*4+off+512(dst); \
+ MOVL R14, 14*4+off+576(dst); \
+ SHRQ $32, R14; \
+ MOVL R14, 14*4+off+0(dst); \
+ MOVL R14, 3*4+off+64(dst); \
+ MOVL R14, 7*4+off+128(dst); \
+ MOVL R14, 2*4+off+192(dst); \
+ MOVL R14, 15*4+off+256(dst); \
+ MOVL R14, 12*4+off+320(dst); \
+ MOVL R14, 6*4+off+384(dst); \
+ MOVL R14, 0*4+off+448(dst); \
+ MOVL R14, 9*4+off+512(dst); \
+ MOVL R14, 11*4+off+576(dst); \
+ \
+ MOVL R15, 11*4+off+0(dst); \
+ MOVL R15, 0*4+off+64(dst); \
+ MOVL R15, 12*4+off+128(dst); \
+ MOVL R15, 7*4+off+192(dst); \
+ MOVL R15, 8*4+off+256(dst); \
+ MOVL R15, 14*4+off+320(dst); \
+ MOVL R15, 2*4+off+384(dst); \
+ MOVL R15, 5*4+off+448(dst); \
+ MOVL R15, 1*4+off+512(dst); \
+ MOVL R15, 13*4+off+576(dst); \
+ SHRQ $32, R15; \
+ MOVL R15, 15*4+off+0(dst); \
+ MOVL R15, 6*4+off+64(dst); \
+ MOVL R15, 3*4+off+128(dst); \
+ MOVL R15, 11*4+off+192(dst); \
+ MOVL R15, 7*4+off+256(dst); \
+ MOVL R15, 10*4+off+320(dst); \
+ MOVL R15, 5*4+off+384(dst); \
+ MOVL R15, 9*4+off+448(dst); \
+ MOVL R15, 4*4+off+512(dst); \
+ MOVL R15, 8*4+off+576(dst)
+
+#define BLAKE2s_SSE2() \
+ PRECOMPUTE_MSG(SP, 16, SI, R8, R9, R10, R11, R12, R13, R14, R15); \
+ ROUND_SSE2(X4, X5, X6, X7, 16(SP), 32(SP), 48(SP), 64(SP), X8); \
+ ROUND_SSE2(X4, X5, X6, X7, 16+64(SP), 32+64(SP), 48+64(SP), 64+64(SP), X8); \
+ ROUND_SSE2(X4, X5, X6, X7, 16+128(SP), 32+128(SP), 48+128(SP), 64+128(SP), X8); \
+ ROUND_SSE2(X4, X5, X6, X7, 16+192(SP), 32+192(SP), 48+192(SP), 64+192(SP), X8); \
+ ROUND_SSE2(X4, X5, X6, X7, 16+256(SP), 32+256(SP), 48+256(SP), 64+256(SP), X8); \
+ ROUND_SSE2(X4, X5, X6, X7, 16+320(SP), 32+320(SP), 48+320(SP), 64+320(SP), X8); \
+ ROUND_SSE2(X4, X5, X6, X7, 16+384(SP), 32+384(SP), 48+384(SP), 64+384(SP), X8); \
+ ROUND_SSE2(X4, X5, X6, X7, 16+448(SP), 32+448(SP), 48+448(SP), 64+448(SP), X8); \
+ ROUND_SSE2(X4, X5, X6, X7, 16+512(SP), 32+512(SP), 48+512(SP), 64+512(SP), X8); \
+ ROUND_SSE2(X4, X5, X6, X7, 16+576(SP), 32+576(SP), 48+576(SP), 64+576(SP), X8)
+
+#define BLAKE2s_SSSE3() \
+ PRECOMPUTE_MSG(SP, 16, SI, R8, R9, R10, R11, R12, R13, R14, R15); \
+ ROUND_SSSE3(X4, X5, X6, X7, 16(SP), 32(SP), 48(SP), 64(SP), X8, X13, X14); \
+ ROUND_SSSE3(X4, X5, X6, X7, 16+64(SP), 32+64(SP), 48+64(SP), 64+64(SP), X8, X13, X14); \
+ ROUND_SSSE3(X4, X5, X6, X7, 16+128(SP), 32+128(SP), 48+128(SP), 64+128(SP), X8, X13, X14); \
+ ROUND_SSSE3(X4, X5, X6, X7, 16+192(SP), 32+192(SP), 48+192(SP), 64+192(SP), X8, X13, X14); \
+ ROUND_SSSE3(X4, X5, X6, X7, 16+256(SP), 32+256(SP), 48+256(SP), 64+256(SP), X8, X13, X14); \
+ ROUND_SSSE3(X4, X5, X6, X7, 16+320(SP), 32+320(SP), 48+320(SP), 64+320(SP), X8, X13, X14); \
+ ROUND_SSSE3(X4, X5, X6, X7, 16+384(SP), 32+384(SP), 48+384(SP), 64+384(SP), X8, X13, X14); \
+ ROUND_SSSE3(X4, X5, X6, X7, 16+448(SP), 32+448(SP), 48+448(SP), 64+448(SP), X8, X13, X14); \
+ ROUND_SSSE3(X4, X5, X6, X7, 16+512(SP), 32+512(SP), 48+512(SP), 64+512(SP), X8, X13, X14); \
+ ROUND_SSSE3(X4, X5, X6, X7, 16+576(SP), 32+576(SP), 48+576(SP), 64+576(SP), X8, X13, X14)
+
+#define BLAKE2s_SSE4() \
+ LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 0, 2, 4, 6, 1, 3, 5, 7, 8, 10, 12, 14, 9, 11, 13, 15); \
+ ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \
+ LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 14, 4, 9, 13, 10, 8, 15, 6, 1, 0, 11, 5, 12, 2, 7, 3); \
+ ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \
+ LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 11, 12, 5, 15, 8, 0, 2, 13, 10, 3, 7, 9, 14, 6, 1, 4); \
+ ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \
+ LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 7, 3, 13, 11, 9, 1, 12, 14, 2, 5, 4, 15, 6, 10, 0, 8); \
+ ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \
+ LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 9, 5, 2, 10, 0, 7, 4, 15, 14, 11, 6, 3, 1, 12, 8, 13); \
+ ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \
+ LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 2, 6, 0, 8, 12, 10, 11, 3, 4, 7, 15, 1, 13, 5, 14, 9); \
+ ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \
+ LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 12, 1, 14, 4, 5, 15, 13, 10, 0, 6, 9, 8, 7, 3, 2, 11); \
+ ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \
+ LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 13, 7, 12, 3, 11, 14, 1, 9, 5, 15, 8, 2, 0, 4, 6, 10); \
+ ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \
+ LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 6, 14, 11, 0, 15, 9, 3, 8, 12, 13, 1, 10, 2, 7, 4, 5); \
+ ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \
+ LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 10, 8, 7, 1, 2, 4, 6, 5, 15, 9, 3, 13, 11, 14, 12, 0); \
+ ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14)
+
+#define HASH_BLOCKS(h, c, flag, blocks_base, blocks_len, BLAKE2s_FUNC) \
+ MOVQ h, AX; \
+ MOVQ c, BX; \
+ MOVL flag, CX; \
+ MOVQ blocks_base, SI; \
+ MOVQ blocks_len, DX; \
+ \
+ MOVQ SP, BP; \
+ MOVQ SP, R9; \
+ ADDQ $15, R9; \
+ ANDQ $~15, R9; \
+ MOVQ R9, SP; \
+ \
+ MOVQ 0(BX), R9; \
+ MOVQ R9, 0(SP); \
+ XORQ R9, R9; \
+ MOVQ R9, 8(SP); \
+ MOVL CX, 8(SP); \
+ \
+ MOVOU 0(AX), X0; \
+ MOVOU 16(AX), X1; \
+ MOVOU iv0<>(SB), X2; \
+ MOVOU iv1<>(SB), X3 \
+ \
+ MOVOU counter<>(SB), X12; \
+ MOVOU rol16<>(SB), X13; \
+ MOVOU rol8<>(SB), X14; \
+ MOVO 0(SP), X15; \
+ \
+ loop: \
+ MOVO X0, X4; \
+ MOVO X1, X5; \
+ MOVO X2, X6; \
+ MOVO X3, X7; \
+ \
+ PADDQ X12, X15; \
+ PXOR X15, X7; \
+ \
+ BLAKE2s_FUNC(); \
+ \
+ PXOR X4, X0; \
+ PXOR X5, X1; \
+ PXOR X6, X0; \
+ PXOR X7, X1; \
+ \
+ LEAQ 64(SI), SI; \
+ SUBQ $64, DX; \
+ JNE loop; \
+ \
+ MOVO X15, 0(SP); \
+ MOVQ 0(SP), R9; \
+ MOVQ R9, 0(BX); \
+ \
+ MOVOU X0, 0(AX); \
+ MOVOU X1, 16(AX); \
+ \
+ MOVQ BP, SP
+
+// func hashBlocksSSE2(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte)
+TEXT ·hashBlocksSSE2(SB), 0, $672-48 // frame = 656 + 16 byte alignment
+ HASH_BLOCKS(h+0(FP), c+8(FP), flag+16(FP), blocks_base+24(FP), blocks_len+32(FP), BLAKE2s_SSE2)
+ RET
+
+// func hashBlocksSSSE3(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte)
+TEXT ·hashBlocksSSSE3(SB), 0, $672-48 // frame = 656 + 16 byte alignment
+ HASH_BLOCKS(h+0(FP), c+8(FP), flag+16(FP), blocks_base+24(FP), blocks_len+32(FP), BLAKE2s_SSSE3)
+ RET
+
+// func hashBlocksSSE4(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte)
+TEXT ·hashBlocksSSE4(SB), 0, $32-48 // frame = 16 + 16 byte alignment
+ HASH_BLOCKS(h+0(FP), c+8(FP), flag+16(FP), blocks_base+24(FP), blocks_len+32(FP), BLAKE2s_SSE4)
+ RET
+
+// func supportSSE4() bool
+TEXT ·supportSSE4(SB), 4, $0-1
+ MOVL $1, AX
+ CPUID
+ SHRL $19, CX // Bit 19 indicates SSE4.1.
+ ANDL $1, CX
+ MOVB CX, ret+0(FP)
+ RET
+
+// func supportSSSE3() bool
+TEXT ·supportSSSE3(SB), 4, $0-1
+ MOVL $1, AX
+ CPUID
+ MOVL CX, BX
+ ANDL $0x1, BX // Bit zero indicates SSE3 support.
+ JZ FALSE
+ ANDL $0x200, CX // Bit nine indicates SSSE3 support.
+ JZ FALSE
+ MOVB $1, ret+0(FP)
+ RET
+
+FALSE:
+ MOVB $0, ret+0(FP)
+ RET
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2s/blake2s_generic.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2s/blake2s_generic.go
new file mode 100644
index 000000000..f7e065378
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2s/blake2s_generic.go
@@ -0,0 +1,174 @@
+// 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.
+
+package blake2s
+
+// the precomputed values for BLAKE2s
+// there are 10 16-byte arrays - one for each round
+// the entries are calculated from the sigma constants.
+var precomputed = [10][16]byte{
+ {0, 2, 4, 6, 1, 3, 5, 7, 8, 10, 12, 14, 9, 11, 13, 15},
+ {14, 4, 9, 13, 10, 8, 15, 6, 1, 0, 11, 5, 12, 2, 7, 3},
+ {11, 12, 5, 15, 8, 0, 2, 13, 10, 3, 7, 9, 14, 6, 1, 4},
+ {7, 3, 13, 11, 9, 1, 12, 14, 2, 5, 4, 15, 6, 10, 0, 8},
+ {9, 5, 2, 10, 0, 7, 4, 15, 14, 11, 6, 3, 1, 12, 8, 13},
+ {2, 6, 0, 8, 12, 10, 11, 3, 4, 7, 15, 1, 13, 5, 14, 9},
+ {12, 1, 14, 4, 5, 15, 13, 10, 0, 6, 9, 8, 7, 3, 2, 11},
+ {13, 7, 12, 3, 11, 14, 1, 9, 5, 15, 8, 2, 0, 4, 6, 10},
+ {6, 14, 11, 0, 15, 9, 3, 8, 12, 13, 1, 10, 2, 7, 4, 5},
+ {10, 8, 7, 1, 2, 4, 6, 5, 15, 9, 3, 13, 11, 14, 12, 0},
+}
+
+func hashBlocksGeneric(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) {
+ var m [16]uint32
+ c0, c1 := c[0], c[1]
+
+ for i := 0; i < len(blocks); {
+ c0 += BlockSize
+ if c0 < BlockSize {
+ c1++
+ }
+
+ v0, v1, v2, v3, v4, v5, v6, v7 := h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7]
+ v8, v9, v10, v11, v12, v13, v14, v15 := iv[0], iv[1], iv[2], iv[3], iv[4], iv[5], iv[6], iv[7]
+ v12 ^= c0
+ v13 ^= c1
+ v14 ^= flag
+
+ for j := range m {
+ m[j] = uint32(blocks[i]) | uint32(blocks[i+1])<<8 | uint32(blocks[i+2])<<16 | uint32(blocks[i+3])<<24
+ i += 4
+ }
+
+ for k := range precomputed {
+ s := &(precomputed[k])
+
+ v0 += m[s[0]]
+ v0 += v4
+ v12 ^= v0
+ v12 = v12<<(32-16) | v12>>16
+ v8 += v12
+ v4 ^= v8
+ v4 = v4<<(32-12) | v4>>12
+ v1 += m[s[1]]
+ v1 += v5
+ v13 ^= v1
+ v13 = v13<<(32-16) | v13>>16
+ v9 += v13
+ v5 ^= v9
+ v5 = v5<<(32-12) | v5>>12
+ v2 += m[s[2]]
+ v2 += v6
+ v14 ^= v2
+ v14 = v14<<(32-16) | v14>>16
+ v10 += v14
+ v6 ^= v10
+ v6 = v6<<(32-12) | v6>>12
+ v3 += m[s[3]]
+ v3 += v7
+ v15 ^= v3
+ v15 = v15<<(32-16) | v15>>16
+ v11 += v15
+ v7 ^= v11
+ v7 = v7<<(32-12) | v7>>12
+
+ v0 += m[s[4]]
+ v0 += v4
+ v12 ^= v0
+ v12 = v12<<(32-8) | v12>>8
+ v8 += v12
+ v4 ^= v8
+ v4 = v4<<(32-7) | v4>>7
+ v1 += m[s[5]]
+ v1 += v5
+ v13 ^= v1
+ v13 = v13<<(32-8) | v13>>8
+ v9 += v13
+ v5 ^= v9
+ v5 = v5<<(32-7) | v5>>7
+ v2 += m[s[6]]
+ v2 += v6
+ v14 ^= v2
+ v14 = v14<<(32-8) | v14>>8
+ v10 += v14
+ v6 ^= v10
+ v6 = v6<<(32-7) | v6>>7
+ v3 += m[s[7]]
+ v3 += v7
+ v15 ^= v3
+ v15 = v15<<(32-8) | v15>>8
+ v11 += v15
+ v7 ^= v11
+ v7 = v7<<(32-7) | v7>>7
+
+ v0 += m[s[8]]
+ v0 += v5
+ v15 ^= v0
+ v15 = v15<<(32-16) | v15>>16
+ v10 += v15
+ v5 ^= v10
+ v5 = v5<<(32-12) | v5>>12
+ v1 += m[s[9]]
+ v1 += v6
+ v12 ^= v1
+ v12 = v12<<(32-16) | v12>>16
+ v11 += v12
+ v6 ^= v11
+ v6 = v6<<(32-12) | v6>>12
+ v2 += m[s[10]]
+ v2 += v7
+ v13 ^= v2
+ v13 = v13<<(32-16) | v13>>16
+ v8 += v13
+ v7 ^= v8
+ v7 = v7<<(32-12) | v7>>12
+ v3 += m[s[11]]
+ v3 += v4
+ v14 ^= v3
+ v14 = v14<<(32-16) | v14>>16
+ v9 += v14
+ v4 ^= v9
+ v4 = v4<<(32-12) | v4>>12
+
+ v0 += m[s[12]]
+ v0 += v5
+ v15 ^= v0
+ v15 = v15<<(32-8) | v15>>8
+ v10 += v15
+ v5 ^= v10
+ v5 = v5<<(32-7) | v5>>7
+ v1 += m[s[13]]
+ v1 += v6
+ v12 ^= v1
+ v12 = v12<<(32-8) | v12>>8
+ v11 += v12
+ v6 ^= v11
+ v6 = v6<<(32-7) | v6>>7
+ v2 += m[s[14]]
+ v2 += v7
+ v13 ^= v2
+ v13 = v13<<(32-8) | v13>>8
+ v8 += v13
+ v7 ^= v8
+ v7 = v7<<(32-7) | v7>>7
+ v3 += m[s[15]]
+ v3 += v4
+ v14 ^= v3
+ v14 = v14<<(32-8) | v14>>8
+ v9 += v14
+ v4 ^= v9
+ v4 = v4<<(32-7) | v4>>7
+ }
+
+ h[0] ^= v0 ^ v8
+ h[1] ^= v1 ^ v9
+ h[2] ^= v2 ^ v10
+ h[3] ^= v3 ^ v11
+ h[4] ^= v4 ^ v12
+ h[5] ^= v5 ^ v13
+ h[6] ^= v6 ^ v14
+ h[7] ^= v7 ^ v15
+ }
+ c[0], c[1] = c0, c1
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2s/blake2s_ref.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2s/blake2s_ref.go
new file mode 100644
index 000000000..a31127345
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2s/blake2s_ref.go
@@ -0,0 +1,17 @@
+// 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.
+
+// +build !amd64,!386 gccgo appengine
+
+package blake2s
+
+var (
+ useSSE4 = false
+ useSSSE3 = false
+ useSSE2 = false
+)
+
+func hashBlocks(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) {
+ hashBlocksGeneric(h, c, flag, blocks)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2s/blake2s_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2s/blake2s_test.go
new file mode 100644
index 000000000..cfeb18bb4
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2s/blake2s_test.go
@@ -0,0 +1,1002 @@
+// 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.
+
+package blake2s
+
+import (
+ "encoding/hex"
+ "fmt"
+ "testing"
+)
+
+func TestHashes(t *testing.T) {
+ defer func(sse2, ssse3, sse4 bool) {
+ useSSE2, useSSSE3, useSSE4 = sse2, ssse3, sse4
+ }(useSSE2, useSSSE3, useSSE4)
+
+ if useSSE4 {
+ t.Log("SSE4 version")
+ testHashes(t)
+ testHashes128(t)
+ useSSE4 = false
+ }
+ if useSSSE3 {
+ t.Log("SSSE3 version")
+ testHashes(t)
+ testHashes128(t)
+ useSSSE3 = false
+ }
+ if useSSE2 {
+ t.Log("SSE2 version")
+ testHashes(t)
+ testHashes128(t)
+ useSSE2 = false
+ }
+
+ t.Log("generic version")
+ testHashes(t)
+ testHashes128(t)
+}
+
+func TestHashes2X(t *testing.T) {
+ defer func(sse2, ssse3, sse4 bool) {
+ useSSE2, useSSSE3, useSSE4 = sse2, ssse3, sse4
+ }(useSSE2, useSSSE3, useSSE4)
+
+ if useSSE4 {
+ t.Log("SSE4 version")
+ testHashes2X(t)
+ useSSE4 = false
+ }
+ if useSSSE3 {
+ t.Log("SSSE3 version")
+ testHashes2X(t)
+ useSSSE3 = false
+ }
+ if useSSE2 {
+ t.Log("SSE2 version")
+ testHashes2X(t)
+ useSSE2 = false
+ }
+
+ t.Log("generic version")
+ testHashes2X(t)
+}
+
+func testHashes(t *testing.T) {
+ key, _ := hex.DecodeString("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f")
+
+ input := make([]byte, 255)
+ for i := range input {
+ input[i] = byte(i)
+ }
+
+ for i, expectedHex := range hashes {
+ h, err := New256(key)
+ if err != nil {
+ t.Fatalf("#%d: error from New256: %v", i, err)
+ }
+
+ h.Write(input[:i])
+ sum := h.Sum(nil)
+
+ if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex {
+ t.Fatalf("#%d (single write): got %s, wanted %s", i, gotHex, expectedHex)
+ }
+
+ h.Reset()
+ for j := 0; j < i; j++ {
+ h.Write(input[j : j+1])
+ }
+
+ sum = h.Sum(sum[:0])
+ if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex {
+ t.Fatalf("#%d (byte-by-byte): got %s, wanted %s", i, gotHex, expectedHex)
+ }
+ }
+}
+
+func testHashes128(t *testing.T) {
+ key, _ := hex.DecodeString("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f")
+
+ input := make([]byte, 255)
+ for i := range input {
+ input[i] = byte(i)
+ }
+
+ for i, expectedHex := range hashes128 {
+ h, err := New128(key)
+ if err != nil {
+ t.Fatalf("#%d: error from New128: %v", i, err)
+ }
+
+ h.Write(input[:i])
+ sum := h.Sum(nil)
+
+ if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex {
+ t.Fatalf("#%d (single write): got %s, wanted %s", i, gotHex, expectedHex)
+ }
+
+ h.Reset()
+ for j := 0; j < i; j++ {
+ h.Write(input[j : j+1])
+ }
+
+ sum = h.Sum(sum[:0])
+ if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex {
+ t.Fatalf("#%d (byte-by-byte): got %s, wanted %s", i, gotHex, expectedHex)
+ }
+ }
+}
+
+func testHashes2X(t *testing.T) {
+ key, _ := hex.DecodeString("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f")
+
+ input := make([]byte, 256)
+ for i := range input {
+ input[i] = byte(i)
+ }
+
+ for i, expectedHex := range hashes2X {
+ length := uint16(len(expectedHex) / 2)
+ sum := make([]byte, int(length))
+
+ h, err := NewXOF(length, key)
+ if err != nil {
+ t.Fatalf("#%d: error from NewXOF: %v", i, err)
+ }
+
+ if _, err := h.Write(input); err != nil {
+ t.Fatalf("#%d (single write): error from Write: %v", i, err)
+ }
+ if _, err := h.Read(sum); err != nil {
+ t.Fatalf("#%d (single write): error from Read: %v", i, err)
+ }
+
+ if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex {
+ t.Fatalf("#%d (single write): got %s, wanted %s", i, gotHex, expectedHex)
+ }
+
+ h.Reset()
+ for j := 0; j < len(input); j++ {
+ h.Write(input[j : j+1])
+ }
+ for j := 0; j < len(sum); j++ {
+ h = h.Clone()
+ if _, err := h.Read(sum[j : j+1]); err != nil {
+ t.Fatalf("#%d (byte-by-byte) - Read %d: error from Read: %v", i, j, err)
+ }
+ }
+ if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex {
+ t.Fatalf("#%d (byte-by-byte): got %s, wanted %s", i, gotHex, expectedHex)
+ }
+ }
+
+ h, err := NewXOF(OutputLengthUnknown, key)
+ if err != nil {
+ t.Fatalf("#unknown length: error from NewXOF: %v", err)
+ }
+ if _, err := h.Write(input); err != nil {
+ t.Fatalf("#unknown length: error from Write: %v", err)
+ }
+
+ var result [64]byte
+ if n, err := h.Read(result[:]); err != nil {
+ t.Fatalf("#unknown length: error from Read: %v", err)
+ } else if n != len(result) {
+ t.Fatalf("#unknown length: Read returned %d bytes, want %d", n, len(result))
+ }
+
+ const expected = "2a9a6977d915a2c4dd07dbcafe1918bf1682e56d9c8e567ecd19bfd7cd93528833c764d12b34a5e2a219c9fd463dab45e972c5574d73f45de5b2e23af72530d8"
+ if fmt.Sprintf("%x", result) != expected {
+ t.Fatalf("#unknown length: bad result %x, wanted %s", result, expected)
+ }
+}
+
+// Benchmarks
+
+func benchmarkSum(b *testing.B, size int) {
+ data := make([]byte, size)
+ b.SetBytes(int64(size))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ Sum256(data)
+ }
+}
+
+func benchmarkWrite(b *testing.B, size int) {
+ data := make([]byte, size)
+ h, _ := New256(nil)
+ b.SetBytes(int64(size))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ h.Write(data)
+ }
+}
+
+func BenchmarkWrite64(b *testing.B) { benchmarkWrite(b, 64) }
+func BenchmarkWrite1K(b *testing.B) { benchmarkWrite(b, 1024) }
+
+func BenchmarkSum64(b *testing.B) { benchmarkSum(b, 64) }
+func BenchmarkSum1K(b *testing.B) { benchmarkSum(b, 1024) }
+
+// hashes is taken from https://blake2.net/blake2s-test.txt
+var hashes = []string{
+ "48a8997da407876b3d79c0d92325ad3b89cbb754d86ab71aee047ad345fd2c49",
+ "40d15fee7c328830166ac3f918650f807e7e01e177258cdc0a39b11f598066f1",
+ "6bb71300644cd3991b26ccd4d274acd1adeab8b1d7914546c1198bbe9fc9d803",
+ "1d220dbe2ee134661fdf6d9e74b41704710556f2f6e5a091b227697445dbea6b",
+ "f6c3fbadb4cc687a0064a5be6e791bec63b868ad62fba61b3757ef9ca52e05b2",
+ "49c1f21188dfd769aea0e911dd6b41f14dab109d2b85977aa3088b5c707e8598",
+ "fdd8993dcd43f696d44f3cea0ff35345234ec8ee083eb3cada017c7f78c17143",
+ "e6c8125637438d0905b749f46560ac89fd471cf8692e28fab982f73f019b83a9",
+ "19fc8ca6979d60e6edd3b4541e2f967ced740df6ec1eaebbfe813832e96b2974",
+ "a6ad777ce881b52bb5a4421ab6cdd2dfba13e963652d4d6d122aee46548c14a7",
+ "f5c4b2ba1a00781b13aba0425242c69cb1552f3f71a9a3bb22b4a6b4277b46dd",
+ "e33c4c9bd0cc7e45c80e65c77fa5997fec7002738541509e68a9423891e822a3",
+ "fba16169b2c3ee105be6e1e650e5cbf40746b6753d036ab55179014ad7ef6651",
+ "f5c4bec6d62fc608bf41cc115f16d61c7efd3ff6c65692bbe0afffb1fede7475",
+ "a4862e76db847f05ba17ede5da4e7f91b5925cf1ad4ba12732c3995742a5cd6e",
+ "65f4b860cd15b38ef814a1a804314a55be953caa65fd758ad989ff34a41c1eea",
+ "19ba234f0a4f38637d1839f9d9f76ad91c8522307143c97d5f93f69274cec9a7",
+ "1a67186ca4a5cb8e65fca0e2ecbc5ddc14ae381bb8bffeb9e0a103449e3ef03c",
+ "afbea317b5a2e89c0bd90ccf5d7fd0ed57fe585e4be3271b0a6bf0f5786b0f26",
+ "f1b01558ce541262f5ec34299d6fb4090009e3434be2f49105cf46af4d2d4124",
+ "13a0a0c86335635eaa74ca2d5d488c797bbb4f47dc07105015ed6a1f3309efce",
+ "1580afeebebb346f94d59fe62da0b79237ead7b1491f5667a90e45edf6ca8b03",
+ "20be1a875b38c573dd7faaa0de489d655c11efb6a552698e07a2d331b5f655c3",
+ "be1fe3c4c04018c54c4a0f6b9a2ed3c53abe3a9f76b4d26de56fc9ae95059a99",
+ "e3e3ace537eb3edd8463d9ad3582e13cf86533ffde43d668dd2e93bbdbd7195a",
+ "110c50c0bf2c6e7aeb7e435d92d132ab6655168e78a2decdec3330777684d9c1",
+ "e9ba8f505c9c80c08666a701f3367e6cc665f34b22e73c3c0417eb1c2206082f",
+ "26cd66fca02379c76df12317052bcafd6cd8c3a7b890d805f36c49989782433a",
+ "213f3596d6e3a5d0e9932cd2159146015e2abc949f4729ee2632fe1edb78d337",
+ "1015d70108e03be1c702fe97253607d14aee591f2413ea6787427b6459ff219a",
+ "3ca989de10cfe609909472c8d35610805b2f977734cf652cc64b3bfc882d5d89",
+ "b6156f72d380ee9ea6acd190464f2307a5c179ef01fd71f99f2d0f7a57360aea",
+ "c03bc642b20959cbe133a0303e0c1abff3e31ec8e1a328ec8565c36decff5265",
+ "2c3e08176f760c6264c3a2cd66fec6c3d78de43fc192457b2a4a660a1e0eb22b",
+ "f738c02f3c1b190c512b1a32deabf353728e0e9ab034490e3c3409946a97aeec",
+ "8b1880df301cc963418811088964839287ff7fe31c49ea6ebd9e48bdeee497c5",
+ "1e75cb21c60989020375f1a7a242839f0b0b68973a4c2a05cf7555ed5aaec4c1",
+ "62bf8a9c32a5bccf290b6c474d75b2a2a4093f1a9e27139433a8f2b3bce7b8d7",
+ "166c8350d3173b5e702b783dfd33c66ee0432742e9b92b997fd23c60dc6756ca",
+ "044a14d822a90cacf2f5a101428adc8f4109386ccb158bf905c8618b8ee24ec3",
+ "387d397ea43a994be84d2d544afbe481a2000f55252696bba2c50c8ebd101347",
+ "56f8ccf1f86409b46ce36166ae9165138441577589db08cbc5f66ca29743b9fd",
+ "9706c092b04d91f53dff91fa37b7493d28b576b5d710469df79401662236fc03",
+ "877968686c068ce2f7e2adcff68bf8748edf3cf862cfb4d3947a3106958054e3",
+ "8817e5719879acf7024787eccdb271035566cfa333e049407c0178ccc57a5b9f",
+ "8938249e4b50cadaccdf5b18621326cbb15253e33a20f5636e995d72478de472",
+ "f164abba4963a44d107257e3232d90aca5e66a1408248c51741e991db5227756",
+ "d05563e2b1cba0c4a2a1e8bde3a1a0d9f5b40c85a070d6f5fb21066ead5d0601",
+ "03fbb16384f0a3866f4c3117877666efbf124597564b293d4aab0d269fabddfa",
+ "5fa8486ac0e52964d1881bbe338eb54be2f719549224892057b4da04ba8b3475",
+ "cdfabcee46911111236a31708b2539d71fc211d9b09c0d8530a11e1dbf6eed01",
+ "4f82de03b9504793b82a07a0bdcdff314d759e7b62d26b784946b0d36f916f52",
+ "259ec7f173bcc76a0994c967b4f5f024c56057fb79c965c4fae41875f06a0e4c",
+ "193cc8e7c3e08bb30f5437aa27ade1f142369b246a675b2383e6da9b49a9809e",
+ "5c10896f0e2856b2a2eee0fe4a2c1633565d18f0e93e1fab26c373e8f829654d",
+ "f16012d93f28851a1eb989f5d0b43f3f39ca73c9a62d5181bff237536bd348c3",
+ "2966b3cfae1e44ea996dc5d686cf25fa053fb6f67201b9e46eade85d0ad6b806",
+ "ddb8782485e900bc60bcf4c33a6fd585680cc683d516efa03eb9985fad8715fb",
+ "4c4d6e71aea05786413148fc7a786b0ecaf582cff1209f5a809fba8504ce662c",
+ "fb4c5e86d7b2229b99b8ba6d94c247ef964aa3a2bae8edc77569f28dbbff2d4e",
+ "e94f526de9019633ecd54ac6120f23958d7718f1e7717bf329211a4faeed4e6d",
+ "cbd6660a10db3f23f7a03d4b9d4044c7932b2801ac89d60bc9eb92d65a46c2a0",
+ "8818bbd3db4dc123b25cbba5f54c2bc4b3fcf9bf7d7a7709f4ae588b267c4ece",
+ "c65382513f07460da39833cb666c5ed82e61b9e998f4b0c4287cee56c3cc9bcd",
+ "8975b0577fd35566d750b362b0897a26c399136df07bababbde6203ff2954ed4",
+ "21fe0ceb0052be7fb0f004187cacd7de67fa6eb0938d927677f2398c132317a8",
+ "2ef73f3c26f12d93889f3c78b6a66c1d52b649dc9e856e2c172ea7c58ac2b5e3",
+ "388a3cd56d73867abb5f8401492b6e2681eb69851e767fd84210a56076fb3dd3",
+ "af533e022fc9439e4e3cb838ecd18692232adf6fe9839526d3c3dd1b71910b1a",
+ "751c09d41a9343882a81cd13ee40818d12eb44c6c7f40df16e4aea8fab91972a",
+ "5b73ddb68d9d2b0aa265a07988d6b88ae9aac582af83032f8a9b21a2e1b7bf18",
+ "3da29126c7c5d7f43e64242a79feaa4ef3459cdeccc898ed59a97f6ec93b9dab",
+ "566dc920293da5cb4fe0aa8abda8bbf56f552313bff19046641e3615c1e3ed3f",
+ "4115bea02f73f97f629e5c5590720c01e7e449ae2a6697d4d2783321303692f9",
+ "4ce08f4762468a7670012164878d68340c52a35e66c1884d5c864889abc96677",
+ "81ea0b7804124e0c22ea5fc71104a2afcb52a1fa816f3ecb7dcb5d9dea1786d0",
+ "fe362733b05f6bedaf9379d7f7936ede209b1f8323c3922549d9e73681b5db7b",
+ "eff37d30dfd20359be4e73fdf40d27734b3df90a97a55ed745297294ca85d09f",
+ "172ffc67153d12e0ca76a8b6cd5d4731885b39ce0cac93a8972a18006c8b8baf",
+ "c47957f1cc88e83ef9445839709a480a036bed5f88ac0fcc8e1e703ffaac132c",
+ "30f3548370cfdceda5c37b569b6175e799eef1a62aaa943245ae7669c227a7b5",
+ "c95dcb3cf1f27d0eef2f25d2413870904a877c4a56c2de1e83e2bc2ae2e46821",
+ "d5d0b5d705434cd46b185749f66bfb5836dcdf6ee549a2b7a4aee7f58007caaf",
+ "bbc124a712f15d07c300e05b668389a439c91777f721f8320c1c9078066d2c7e",
+ "a451b48c35a6c7854cfaae60262e76990816382ac0667e5a5c9e1b46c4342ddf",
+ "b0d150fb55e778d01147f0b5d89d99ecb20ff07e5e6760d6b645eb5b654c622b",
+ "34f737c0ab219951eee89a9f8dac299c9d4c38f33fa494c5c6eefc92b6db08bc",
+ "1a62cc3a00800dcbd99891080c1e098458193a8cc9f970ea99fbeff00318c289",
+ "cfce55ebafc840d7ae48281c7fd57ec8b482d4b704437495495ac414cf4a374b",
+ "6746facf71146d999dabd05d093ae586648d1ee28e72617b99d0f0086e1e45bf",
+ "571ced283b3f23b4e750bf12a2caf1781847bd890e43603cdc5976102b7bb11b",
+ "cfcb765b048e35022c5d089d26e85a36b005a2b80493d03a144e09f409b6afd1",
+ "4050c7a27705bb27f42089b299f3cbe5054ead68727e8ef9318ce6f25cd6f31d",
+ "184070bd5d265fbdc142cd1c5cd0d7e414e70369a266d627c8fba84fa5e84c34",
+ "9edda9a4443902a9588c0d0ccc62b930218479a6841e6fe7d43003f04b1fd643",
+ "e412feef7908324a6da1841629f35d3d358642019310ec57c614836b63d30763",
+ "1a2b8edff3f9acc1554fcbae3cf1d6298c6462e22e5eb0259684f835012bd13f",
+ "288c4ad9b9409762ea07c24a41f04f69a7d74bee2d95435374bde946d7241c7b",
+ "805691bb286748cfb591d3aebe7e6f4e4dc6e2808c65143cc004e4eb6fd09d43",
+ "d4ac8d3a0afc6cfa7b460ae3001baeb36dadb37da07d2e8ac91822df348aed3d",
+ "c376617014d20158bced3d3ba552b6eccf84e62aa3eb650e90029c84d13eea69",
+ "c41f09f43cecae7293d6007ca0a357087d5ae59be500c1cd5b289ee810c7b082",
+ "03d1ced1fba5c39155c44b7765cb760c78708dcfc80b0bd8ade3a56da8830b29",
+ "09bde6f152218dc92c41d7f45387e63e5869d807ec70b821405dbd884b7fcf4b",
+ "71c9036e18179b90b37d39e9f05eb89cc5fc341fd7c477d0d7493285faca08a4",
+ "5916833ebb05cd919ca7fe83b692d3205bef72392b2cf6bb0a6d43f994f95f11",
+ "f63aab3ec641b3b024964c2b437c04f6043c4c7e0279239995401958f86bbe54",
+ "f172b180bfb09740493120b6326cbdc561e477def9bbcfd28cc8c1c5e3379a31",
+ "cb9b89cc18381dd9141ade588654d4e6a231d5bf49d4d59ac27d869cbe100cf3",
+ "7bd8815046fdd810a923e1984aaebdcdf84d87c8992d68b5eeb460f93eb3c8d7",
+ "607be66862fd08ee5b19facac09dfdbcd40c312101d66e6ebd2b841f1b9a9325",
+ "9fe03bbe69ab1834f5219b0da88a08b30a66c5913f0151963c360560db0387b3",
+ "90a83585717b75f0e9b725e055eeeeb9e7a028ea7e6cbc07b20917ec0363e38c",
+ "336ea0530f4a7469126e0218587ebbde3358a0b31c29d200f7dc7eb15c6aadd8",
+ "a79e76dc0abca4396f0747cd7b748df913007626b1d659da0c1f78b9303d01a3",
+ "44e78a773756e0951519504d7038d28d0213a37e0ce375371757bc996311e3b8",
+ "77ac012a3f754dcfeab5eb996be9cd2d1f96111b6e49f3994df181f28569d825",
+ "ce5a10db6fccdaf140aaa4ded6250a9c06e9222bc9f9f3658a4aff935f2b9f3a",
+ "ecc203a7fe2be4abd55bb53e6e673572e0078da8cd375ef430cc97f9f80083af",
+ "14a5186de9d7a18b0412b8563e51cc5433840b4a129a8ff963b33a3c4afe8ebb",
+ "13f8ef95cb86e6a638931c8e107673eb76ba10d7c2cd70b9d9920bbeed929409",
+ "0b338f4ee12f2dfcb78713377941e0b0632152581d1332516e4a2cab1942cca4",
+ "eaab0ec37b3b8ab796e9f57238de14a264a076f3887d86e29bb5906db5a00e02",
+ "23cb68b8c0e6dc26dc27766ddc0a13a99438fd55617aa4095d8f969720c872df",
+ "091d8ee30d6f2968d46b687dd65292665742de0bb83dcc0004c72ce10007a549",
+ "7f507abc6d19ba00c065a876ec5657868882d18a221bc46c7a6912541f5bc7ba",
+ "a0607c24e14e8c223db0d70b4d30ee88014d603f437e9e02aa7dafa3cdfbad94",
+ "ddbfea75cc467882eb3483ce5e2e756a4f4701b76b445519e89f22d60fa86e06",
+ "0c311f38c35a4fb90d651c289d486856cd1413df9b0677f53ece2cd9e477c60a",
+ "46a73a8dd3e70f59d3942c01df599def783c9da82fd83222cd662b53dce7dbdf",
+ "ad038ff9b14de84a801e4e621ce5df029dd93520d0c2fa38bff176a8b1d1698c",
+ "ab70c5dfbd1ea817fed0cd067293abf319e5d7901c2141d5d99b23f03a38e748",
+ "1fffda67932b73c8ecaf009a3491a026953babfe1f663b0697c3c4ae8b2e7dcb",
+ "b0d2cc19472dd57f2b17efc03c8d58c2283dbb19da572f7755855aa9794317a0",
+ "a0d19a6ee33979c325510e276622df41f71583d07501b87071129a0ad94732a5",
+ "724642a7032d1062b89e52bea34b75df7d8fe772d9fe3c93ddf3c4545ab5a99b",
+ "ade5eaa7e61f672d587ea03dae7d7b55229c01d06bc0a5701436cbd18366a626",
+ "013b31ebd228fcdda51fabb03bb02d60ac20ca215aafa83bdd855e3755a35f0b",
+ "332ed40bb10dde3c954a75d7b8999d4b26a1c063c1dc6e32c1d91bab7bbb7d16",
+ "c7a197b3a05b566bcc9facd20e441d6f6c2860ac9651cd51d6b9d2cdeeea0390",
+ "bd9cf64ea8953c037108e6f654914f3958b68e29c16700dc184d94a21708ff60",
+ "8835b0ac021151df716474ce27ce4d3c15f0b2dab48003cf3f3efd0945106b9a",
+ "3bfefa3301aa55c080190cffda8eae51d9af488b4c1f24c3d9a75242fd8ea01d",
+ "08284d14993cd47d53ebaecf0df0478cc182c89c00e1859c84851686ddf2c1b7",
+ "1ed7ef9f04c2ac8db6a864db131087f27065098e69c3fe78718d9b947f4a39d0",
+ "c161f2dcd57e9c1439b31a9dd43d8f3d7dd8f0eb7cfac6fb25a0f28e306f0661",
+ "c01969ad34c52caf3dc4d80d19735c29731ac6e7a92085ab9250c48dea48a3fc",
+ "1720b3655619d2a52b3521ae0e49e345cb3389ebd6208acaf9f13fdacca8be49",
+ "756288361c83e24c617cf95c905b22d017cdc86f0bf1d658f4756c7379873b7f",
+ "e7d0eda3452693b752abcda1b55e276f82698f5f1605403eff830bea0071a394",
+ "2c82ecaa6b84803e044af63118afe544687cb6e6c7df49ed762dfd7c8693a1bc",
+ "6136cbf4b441056fa1e2722498125d6ded45e17b52143959c7f4d4e395218ac2",
+ "721d3245aafef27f6a624f47954b6c255079526ffa25e9ff77e5dcff473b1597",
+ "9dd2fbd8cef16c353c0ac21191d509eb28dd9e3e0d8cea5d26ca839393851c3a",
+ "b2394ceacdebf21bf9df2ced98e58f1c3a4bbbff660dd900f62202d6785cc46e",
+ "57089f222749ad7871765f062b114f43ba20ec56422a8b1e3f87192c0ea718c6",
+ "e49a9459961cd33cdf4aae1b1078a5dea7c040e0fea340c93a724872fc4af806",
+ "ede67f720effd2ca9c88994152d0201dee6b0a2d2c077aca6dae29f73f8b6309",
+ "e0f434bf22e3088039c21f719ffc67f0f2cb5e98a7a0194c76e96bf4e8e17e61",
+ "277c04e2853484a4eba910ad336d01b477b67cc200c59f3c8d77eef8494f29cd",
+ "156d5747d0c99c7f27097d7b7e002b2e185cb72d8dd7eb424a0321528161219f",
+ "20ddd1ed9b1ca803946d64a83ae4659da67fba7a1a3eddb1e103c0f5e03e3a2c",
+ "f0af604d3dabbf9a0f2a7d3dda6bd38bba72c6d09be494fcef713ff10189b6e6",
+ "9802bb87def4cc10c4a5fd49aa58dfe2f3fddb46b4708814ead81d23ba95139b",
+ "4f8ce1e51d2fe7f24043a904d898ebfc91975418753413aa099b795ecb35cedb",
+ "bddc6514d7ee6ace0a4ac1d0e068112288cbcf560454642705630177cba608bd",
+ "d635994f6291517b0281ffdd496afa862712e5b3c4e52e4cd5fdae8c0e72fb08",
+ "878d9ca600cf87e769cc305c1b35255186615a73a0da613b5f1c98dbf81283ea",
+ "a64ebe5dc185de9fdde7607b6998702eb23456184957307d2fa72e87a47702d6",
+ "ce50eab7b5eb52bdc9ad8e5a480ab780ca9320e44360b1fe37e03f2f7ad7de01",
+ "eeddb7c0db6e30abe66d79e327511e61fcebbc29f159b40a86b046ecf0513823",
+ "787fc93440c1ec96b5ad01c16cf77916a1405f9426356ec921d8dff3ea63b7e0",
+ "7f0d5eab47eefda696c0bf0fbf86ab216fce461e9303aba6ac374120e890e8df",
+ "b68004b42f14ad029f4c2e03b1d5eb76d57160e26476d21131bef20ada7d27f4",
+ "b0c4eb18ae250b51a41382ead92d0dc7455f9379fc9884428e4770608db0faec",
+ "f92b7a870c059f4d46464c824ec96355140bdce681322cc3a992ff103e3fea52",
+ "5364312614813398cc525d4c4e146edeb371265fba19133a2c3d2159298a1742",
+ "f6620e68d37fb2af5000fc28e23b832297ecd8bce99e8be4d04e85309e3d3374",
+ "5316a27969d7fe04ff27b283961bffc3bf5dfb32fb6a89d101c6c3b1937c2871",
+ "81d1664fdf3cb33c24eebac0bd64244b77c4abea90bbe8b5ee0b2aafcf2d6a53",
+ "345782f295b0880352e924a0467b5fbc3e8f3bfbc3c7e48b67091fb5e80a9442",
+ "794111ea6cd65e311f74ee41d476cb632ce1e4b051dc1d9e9d061a19e1d0bb49",
+ "2a85daf6138816b99bf8d08ba2114b7ab07975a78420c1a3b06a777c22dd8bcb",
+ "89b0d5f289ec16401a069a960d0b093e625da3cf41ee29b59b930c5820145455",
+ "d0fdcb543943fc27d20864f52181471b942cc77ca675bcb30df31d358ef7b1eb",
+ "b17ea8d77063c709d4dc6b879413c343e3790e9e62ca85b7900b086f6b75c672",
+ "e71a3e2c274db842d92114f217e2c0eac8b45093fdfd9df4ca7162394862d501",
+ "c0476759ab7aa333234f6b44f5fd858390ec23694c622cb986e769c78edd733e",
+ "9ab8eabb1416434d85391341d56993c55458167d4418b19a0f2ad8b79a83a75b",
+ "7992d0bbb15e23826f443e00505d68d3ed7372995a5c3e498654102fbcd0964e",
+ "c021b30085151435df33b007ccecc69df1269f39ba25092bed59d932ac0fdc28",
+ "91a25ec0ec0d9a567f89c4bfe1a65a0e432d07064b4190e27dfb81901fd3139b",
+ "5950d39a23e1545f301270aa1a12f2e6c453776e4d6355de425cc153f9818867",
+ "d79f14720c610af179a3765d4b7c0968f977962dbf655b521272b6f1e194488e",
+ "e9531bfc8b02995aeaa75ba27031fadbcbf4a0dab8961d9296cd7e84d25d6006",
+ "34e9c26a01d7f16181b454a9d1623c233cb99d31c694656e9413aca3e918692f",
+ "d9d7422f437bd439ddd4d883dae2a08350173414be78155133fff1964c3d7972",
+ "4aee0c7aaf075414ff1793ead7eaca601775c615dbd60b640b0a9f0ce505d435",
+ "6bfdd15459c83b99f096bfb49ee87b063d69c1974c6928acfcfb4099f8c4ef67",
+ "9fd1c408fd75c336193a2a14d94f6af5adf050b80387b4b010fb29f4cc72707c",
+ "13c88480a5d00d6c8c7ad2110d76a82d9b70f4fa6696d4e5dd42a066dcaf9920",
+ "820e725ee25fe8fd3a8d5abe4c46c3ba889de6fa9191aa22ba67d5705421542b",
+ "32d93a0eb02f42fbbcaf2bad0085b282e46046a4df7ad10657c9d6476375b93e",
+ "adc5187905b1669cd8ec9c721e1953786b9d89a9bae30780f1e1eab24a00523c",
+ "e90756ff7f9ad810b239a10ced2cf9b2284354c1f8c7e0accc2461dc796d6e89",
+ "1251f76e56978481875359801db589a0b22f86d8d634dc04506f322ed78f17e8",
+ "3afa899fd980e73ecb7f4d8b8f291dc9af796bc65d27f974c6f193c9191a09fd",
+ "aa305be26e5deddc3c1010cbc213f95f051c785c5b431e6a7cd048f161787528",
+ "8ea1884ff32e9d10f039b407d0d44e7e670abd884aeee0fb757ae94eaa97373d",
+ "d482b2155d4dec6b4736a1f1617b53aaa37310277d3fef0c37ad41768fc235b4",
+ "4d413971387e7a8898a8dc2a27500778539ea214a2dfe9b3d7e8ebdce5cf3db3",
+ "696e5d46e6c57e8796e4735d08916e0b7929b3cf298c296d22e9d3019653371c",
+ "1f5647c1d3b088228885865c8940908bf40d1a8272821973b160008e7a3ce2eb",
+ "b6e76c330f021a5bda65875010b0edf09126c0f510ea849048192003aef4c61c",
+ "3cd952a0beada41abb424ce47f94b42be64e1ffb0fd0782276807946d0d0bc55",
+ "98d92677439b41b7bb513312afb92bcc8ee968b2e3b238cecb9b0f34c9bb63d0",
+ "ecbca2cf08ae57d517ad16158a32bfa7dc0382eaeda128e91886734c24a0b29d",
+ "942cc7c0b52e2b16a4b89fa4fc7e0bf609e29a08c1a8543452b77c7bfd11bb28",
+ "8a065d8b61a0dffb170d5627735a76b0e9506037808cba16c345007c9f79cf8f",
+ "1b9fa19714659c78ff413871849215361029ac802b1cbcd54e408bd87287f81f",
+ "8dab071bcd6c7292a9ef727b4ae0d86713301da8618d9a48adce55f303a869a1",
+ "8253e3e7c7b684b9cb2beb014ce330ff3d99d17abbdbabe4f4d674ded53ffc6b",
+ "f195f321e9e3d6bd7d074504dd2ab0e6241f92e784b1aa271ff648b1cab6d7f6",
+ "27e4cc72090f241266476a7c09495f2db153d5bcbd761903ef79275ec56b2ed8",
+ "899c2405788e25b99a1846355e646d77cf400083415f7dc5afe69d6e17c00023",
+ "a59b78c4905744076bfee894de707d4f120b5c6893ea0400297d0bb834727632",
+ "59dc78b105649707a2bb4419c48f005400d3973de3736610230435b10424b24f",
+ "c0149d1d7e7a6353a6d906efe728f2f329fe14a4149a3ea77609bc42b975ddfa",
+ "a32f241474a6c16932e9243be0cf09bcdc7e0ca0e7a6a1b9b1a0f01e41502377",
+ "b239b2e4f81841361c1339f68e2c359f929af9ad9f34e01aab4631ad6d5500b0",
+ "85fb419c7002a3e0b4b6ea093b4c1ac6936645b65dac5ac15a8528b7b94c1754",
+ "9619720625f190b93a3fad186ab314189633c0d3a01e6f9bc8c4a8f82f383dbf",
+ "7d620d90fe69fa469a6538388970a1aa09bb48a2d59b347b97e8ce71f48c7f46",
+ "294383568596fb37c75bbacd979c5ff6f20a556bf8879cc72924855df9b8240e",
+ "16b18ab314359c2b833c1c6986d48c55a9fc97cde9a3c1f10a3177140f73f738",
+ "8cbbdd14bc33f04cf45813e4a153a273d36adad5ce71f499eeb87fb8ac63b729",
+ "69c9a498db174ecaefcc5a3ac9fdedf0f813a5bec727f1e775babdec7718816e",
+ "b462c3be40448f1d4f80626254e535b08bc9cdcff599a768578d4b2881a8e3f0",
+ "553e9d9c5f360ac0b74a7d44e5a391dad4ced03e0c24183b7e8ecabdf1715a64",
+ "7a7c55a56fa9ae51e655e01975d8a6ff4ae9e4b486fcbe4eac044588f245ebea",
+ "2afdf3c82abc4867f5de111286c2b3be7d6e48657ba923cfbf101a6dfcf9db9a",
+ "41037d2edcdce0c49b7fb4a6aa0999ca66976c7483afe631d4eda283144f6dfc",
+ "c4466f8497ca2eeb4583a0b08e9d9ac74395709fda109d24f2e4462196779c5d",
+ "75f609338aa67d969a2ae2a2362b2da9d77c695dfd1df7224a6901db932c3364",
+ "68606ceb989d5488fc7cf649f3d7c272ef055da1a93faecd55fe06f6967098ca",
+ "44346bdeb7e052f6255048f0d9b42c425bab9c3dd24168212c3ecf1ebf34e6ae",
+ "8e9cf6e1f366471f2ac7d2ee9b5e6266fda71f8f2e4109f2237ed5f8813fc718",
+ "84bbeb8406d250951f8c1b3e86a7c010082921833dfd9555a2f909b1086eb4b8",
+ "ee666f3eef0f7e2a9c222958c97eaf35f51ced393d714485ab09a069340fdf88",
+ "c153d34a65c47b4a62c5cacf24010975d0356b2f32c8f5da530d338816ad5de6",
+ "9fc5450109e1b779f6c7ae79d56c27635c8dd426c5a9d54e2578db989b8c3b4e",
+ "d12bf3732ef4af5c22fa90356af8fc50fcb40f8f2ea5c8594737a3b3d5abdbd7",
+ "11030b9289bba5af65260672ab6fee88b87420acef4a1789a2073b7ec2f2a09e",
+ "69cb192b8444005c8c0ceb12c846860768188cda0aec27a9c8a55cdee2123632",
+ "db444c15597b5f1a03d1f9edd16e4a9f43a667cc275175dfa2b704e3bb1a9b83",
+ "3fb735061abc519dfe979e54c1ee5bfad0a9d858b3315bad34bde999efd724dd",
+}
+
+var hashes128 = []string{
+ "9536f9b267655743dee97b8a670f9f53",
+ "13bacfb85b48a1223c595f8c1e7e82cb",
+ "d47a9b1645e2feae501cd5fe44ce6333",
+ "1e2a79436a7796a3e9826bfedf07659f",
+ "7640360ed3c4f3054dba79a21dda66b7",
+ "d1207ac2bf5ac84fc9ef016da5a46a86",
+ "3123987871e59305ece3125abfc0099a",
+ "cf9e072ad522f2cda2d825218086731c",
+ "95d22870392efe2846b12b6e8e84efbb",
+ "7d63c30e2d51333f245601b038c0b93b",
+ "ed608b98e13976bdf4bedc63fa35e443",
+ "ed704b5cd1abf8e0dd67a6ac667a3fa5",
+ "77dc70109827dc74c70fd26cba379ae5",
+ "d2bf34508b07825ee934f33958f4560e",
+ "a340baa7b8a93a6e658adef42e78eeb7",
+ "b85c5ceaecbe9a251eac76f6932ba395",
+ "246519722001f6e8e97a2183f5985e53",
+ "5bce5aa0b7c6cac2ecf6406183cd779a",
+ "13408f1647c02f6efd0047ad8344f695",
+ "a63970f196760aa36cb965ab62f0e0fa",
+ "bc26f48421dd99fd45e15e736d3e7dac",
+ "4c6f70f9e3237cde918afb52d26f1823",
+ "45ed610cfbc37db80c4bf0eef14ae8d6",
+ "87c4c150705ea5078209ec008200539c",
+ "54de21f5e0e6f2afe04daeb822b6931e",
+ "9732a04e505064e19de3d542e7e71631",
+ "d2bd27e95531d6957eef511c4ba64ad4",
+ "7a36c9f70dcc7c3063b547101a5f6c35",
+ "322007d1a44c4257bc7903b183305529",
+ "dbcc9a09f412290ca2e0d53dfd142ddb",
+ "df12ed43b8e53a56db20e0f83764002c",
+ "d114cc11e7d5b33a360c45f18d4c7c6e",
+ "c43b5e836af88620a8a71b1652cb8640",
+ "9491c653e8867ed73c1b4ac6b5a9bb4d",
+ "06d0e988df94ada6c6f9f36f588ab7c5",
+ "561efad2480e93262c8eeaa3677615c4",
+ "ba8ffc702e5adc93503045eca8702312",
+ "5782be6ccdc78c8425285e85de8ccdc6",
+ "aa1c4393e4c07b53ea6e2b5b1e970771",
+ "42a229dc50e52271c51e8666023ebc1e",
+ "53706110e919f84de7f8d6c7f0e7b831",
+ "fc5ac8ee39cc1dd1424391323e2901bd",
+ "bed27b62ff66cac2fbb68193c727106a",
+ "cd5e689b96d0b9ea7e08dac36f7b211e",
+ "0b4c7f604eba058d18e322c6e1baf173",
+ "eb838227fdfad09a27f0f8413120675d",
+ "3149cf9d19a7fd529e6154a8b4c3b3ad",
+ "ca1e20126df930fd5fb7afe4422191e5",
+ "b23398f910599f3c09b6549fa81bcb46",
+ "27fb17c11b34fa5d8b5afe5ee3321ead",
+ "0f665f5f04cf2d46b7fead1a1f328158",
+ "8f068be73b3681f99f3b282e3c02bba5",
+ "ba189bbd13808dcf4e002a4dd21660d5",
+ "2732dcd1b16668ae6ab6a61595d0d62a",
+ "d410ccdd059f0e02b472ec9ec54bdd3c",
+ "b2eaa07b055b3a03a399971327f7e8c2",
+ "2e8a225655e9f99b69c60dc8b4d8e566",
+ "4eb55416c853f2152e67f8a224133cec",
+ "49552403790d8de0505a8e317a443687",
+ "7f2747cd41f56942752e868212c7d5ac",
+ "02a28f10e193b430df7112d2d98cf759",
+ "d4213404a9f1cf759017747cf5958270",
+ "faa34884344f9c65e944882db8476d34",
+ "ece382a8bd5018f1de5da44b72cea75b",
+ "f1efa90d2547036841ecd3627fafbc36",
+ "811ff8686d23a435ecbd0bdafcd27b1b",
+ "b21beea9c7385f657a76558530438721",
+ "9cb969da4f1b4fc5b13bf78fe366f0c4",
+ "8850d16d7b614d3268ccfa009d33c7fc",
+ "aa98a2b6176ea86415b9aff3268c6f6d",
+ "ec3e1efa5ed195eff667e16b1af1e39e",
+ "e40787dca57411d2630db2de699beb08",
+ "554835890735babd06318de23d31e78a",
+ "493957feecddc302ee2bb2086b6ebfd3",
+ "f6069709ad5b0139163717e9ce1114ab",
+ "ba5ed386098da284484b211555505a01",
+ "9244c8dfad8cbb68c118fa51465b3ae4",
+ "51e309a5008eb1f5185e5cc007cfb36f",
+ "6ce9ff712121b4f6087955f4911eafd4",
+ "59b51d8dcda031218ccdd7c760828155",
+ "0012878767a3d4f1c8194458cf1f8832",
+ "82900708afd5b6582dc16f008c655edd",
+ "21302c7e39b5a4cdf1d6f86b4f00c9b4",
+ "e894c7431591eab8d1ce0fe2aa1f01df",
+ "b67e1c40ee9d988226d605621854d955",
+ "6237bdafa34137cbbec6be43ea9bd22c",
+ "4172a8e19b0dcb09b978bb9eff7af52b",
+ "5714abb55bd4448a5a6ad09fbd872fdf",
+ "7ce1700bef423e1f958a94a77a94d44a",
+ "3742ec50cded528527775833453e0b26",
+ "5d41b135724c7c9c689495324b162f18",
+ "85c523333c6442c202e9e6e0f1185f93",
+ "5c71f5222d40ff5d90e7570e71ab2d30",
+ "6e18912e83d012efb4c66250ced6f0d9",
+ "4add4448c2e35e0b138a0bac7b4b1775",
+ "c0376c6bc5e7b8b9d2108ec25d2aab53",
+ "f72261d5ed156765c977751c8a13fcc1",
+ "cff4156c48614b6ceed3dd6b9058f17e",
+ "36bfb513f76c15f514bcb593419835aa",
+ "166bf48c6bffaf8291e6fdf63854bef4",
+ "0b67d33f8b859c3157fbabd9e6e47ed0",
+ "e4da659ca76c88e73a9f9f10f3d51789",
+ "33c1ae2a86b3f51c0642e6ed5b5aa1f1",
+ "27469b56aca2334449c1cf4970dcd969",
+ "b7117b2e363378aa0901b0d6a9f6ddc0",
+ "a9578233b09e5cd5231943fdb12cd90d",
+ "486d7d75253598b716a068243c1c3e89",
+ "66f6b02d682b78ffdc85e9ec86852489",
+ "38a07b9a4b228fbcc305476e4d2e05d2",
+ "aedb61c7970e7d05bf9002dae3c6858c",
+ "c03ef441f7dd30fdb61ad2d4d8e4c7da",
+ "7f45cc1eea9a00cb6aeb2dd748361190",
+ "a59538b358459132e55160899e47bd65",
+ "137010fef72364411820c3fbed15c8df",
+ "d8362b93fc504500dbd33ac74e1b4d70",
+ "a7e49f12c8f47e3b29cf8c0889b0a9c8",
+ "072e94ffbfc684bd8ab2a1b9dade2fd5",
+ "5ab438584bd2229e452052e002631a5f",
+ "f233d14221097baef57d3ec205c9e086",
+ "3a95db000c4a8ff98dc5c89631a7f162",
+ "0544f18c2994ab4ddf1728f66041ff16",
+ "0bc02116c60a3cc331928d6c9d3ba37e",
+ "b189dca6cb5b813c74200834fba97f29",
+ "ac8aaab075b4a5bc24419da239212650",
+ "1e9f19323dc71c29ae99c479dc7e8df9",
+ "12d944c3fa7caa1b3d62adfc492274dd",
+ "b4c68f1fffe8f0030e9b18aad8c9dc96",
+ "25887fab1422700d7fa3edc0b20206e2",
+ "8c09f698d03eaf88abf69f8147865ef6",
+ "5c363ae42a5bec26fbc5e996428d9bd7",
+ "7fdfc2e854fbb3928150d5e3abcf56d6",
+ "f0c944023f714df115f9e4f25bcdb89b",
+ "6d19534b4c332741c8ddd79a9644de2d",
+ "32595eb23764fbfc2ee7822649f74a12",
+ "5a51391aab33c8d575019b6e76ae052a",
+ "98b861ce2c620f10f913af5d704a5afd",
+ "b7fe2fc8b77fb1ce434f8465c7ddf793",
+ "0e8406e0cf8e9cc840668ece2a0fc64e",
+ "b89922db99c58f6a128ccffe19b6ce60",
+ "e1be9af665f0932b77d7f5631a511db7",
+ "74b96f20f58de8dc9ff5e31f91828523",
+ "36a4cfef5a2a7d8548db6710e50b3009",
+ "007e95e8d3b91948a1dedb91f75de76b",
+ "a87a702ce08f5745edf765bfcd5fbe0d",
+ "847e69a388a749a9c507354d0dddfe09",
+ "07176eefbc107a78f058f3d424ca6a54",
+ "ad7e80682333b68296f6cb2b4a8e446d",
+ "53c4aba43896ae422e5de5b9edbd46bf",
+ "33bd6c20ca2a7ab916d6e98003c6c5f8",
+ "060d088ea94aa093f9981a79df1dfcc8",
+ "5617b214b9df08d4f11e58f5e76d9a56",
+ "ca3a60ee85bd971e1daf9f7db059d909",
+ "cd2b7754505d8c884eddf736f1ec613e",
+ "f496163b252f1439e7e113ba2ecabd8e",
+ "5719c7dcf9d9f756d6213354acb7d5cf",
+ "6f7dd40b245c54411e7a9be83ae5701c",
+ "c8994dd9fdeb077a45ea04a30358b637",
+ "4b1184f1e35458c1c747817d527a252f",
+ "fc7df674afeac7a3fd994183f4c67a74",
+ "4f68e05ce4dcc533acf9c7c01d95711e",
+ "d4ebc59e918400720035dfc88e0c486a",
+ "d3105dd6fa123e543b0b3a6e0eeaea9e",
+ "874196128ed443f5bdb2800ca048fcad",
+ "01645f134978dc8f9cf0abc93b53780e",
+ "5b8b64caa257873a0ffd47c981ef6c3f",
+ "4ee208fc50ba0a6e65c5b58cec44c923",
+ "53f409a52427b3b7ffabb057ca088428",
+ "c1d6cd616f5341a93d921e356e5887a9",
+ "e85c20fea67fa7320dc23379181183c8",
+ "7912b6409489df001b7372bc94aebde7",
+ "e559f761ec866a87f1f331767fafc60f",
+ "20a6f5a36bc37043d977ed7708465ef8",
+ "6a72f526965ab120826640dd784c6cc4",
+ "bf486d92ad68e87c613689dd370d001b",
+ "d339fd0eb35edf3abd6419c8d857acaf",
+ "9521cd7f32306d969ddabc4e6a617f52",
+ "a1cd9f3e81520842f3cf6cc301cb0021",
+ "18e879b6f154492d593edd3f4554e237",
+ "66e2329c1f5137589e051592587e521e",
+ "e899566dd6c3e82cbc83958e69feb590",
+ "8a4b41d7c47e4e80659d77b4e4bfc9ae",
+ "f1944f6fcfc17803405a1101998c57dd",
+ "f6bcec07567b4f72851b307139656b18",
+ "22e7bb256918fe9924dce9093e2d8a27",
+ "dd25b925815fe7b50b7079f5f65a3970",
+ "0457f10f299acf0c230dd4007612e58f",
+ "ecb420c19efd93814fae2964d69b54af",
+ "14eb47b06dff685d88751c6e32789db4",
+ "e8f072dbb50d1ab6654aa162604a892d",
+ "69cff9c62092332f03a166c7b0034469",
+ "d3619f98970b798ca32c6c14cd25af91",
+ "2246d423774ee9d51a551e89c0539d9e",
+ "75e5d1a1e374a04a699247dad827b6cf",
+ "6d087dd1d4cd15bf47db07c7a96b1db8",
+ "967e4c055ac51b4b2a3e506cebd5826f",
+ "7417aa79247e473401bfa92a25b62e2a",
+ "24f3f4956da34b5c533d9a551ccd7b16",
+ "0c40382de693a5304e2331eb951cc962",
+ "9436f949d51b347db5c8e6258dafaaac",
+ "d2084297fe84c4ba6e04e4fb73d734fe",
+ "42a6f8ff590af21b512e9e088257aa34",
+ "c484ad06b1cdb3a54f3f6464a7a2a6fd",
+ "1b8ac860f5ceb4365400a201ed2917aa",
+ "c43eadabbe7b7473f3f837fc52650f54",
+ "0e5d3205406126b1f838875deb150d6a",
+ "6bf4946f8ec8a9c417f50cd1e67565be",
+ "42f09a2522314799c95b3fc121a0e3e8",
+ "06b8f1487f691a3f7c3f74e133d55870",
+ "1a70a65fb4f314dcf6a31451a9d2704f",
+ "7d4acdd0823279fd28a1e48b49a04669",
+ "09545cc8822a5dfc93bbab708fd69174",
+ "efc063db625013a83c9a426d39a9bddb",
+ "213bbf89b3f5be0ffdb14854bbcb2588",
+ "b69624d89fe2774df9a6f43695d755d4",
+ "c0f9ff9ded82bd73c512e365a894774d",
+ "d1b68507ed89c17ead6f69012982db71",
+ "14cf16db04648978e35c44850855d1b0",
+ "9f254d4eccab74cd91d694df863650a8",
+ "8f8946e2967baa4a814d36ff01d20813",
+ "6b9dc4d24ecba166cb2915d7a6cba43b",
+ "eb35a80418a0042b850e294db7898d4d",
+ "f55f925d280c637d54055c9df088ef5f",
+ "f48427a04f67e33f3ba0a17f7c9704a7",
+ "4a9f5bfcc0321aea2eced896cee65894",
+ "8723a67d1a1df90f1cef96e6fe81e702",
+ "c166c343ee25998f80bad4067960d3fd",
+ "dab67288d16702e676a040fd42344d73",
+ "c8e9e0d80841eb2c116dd14c180e006c",
+ "92294f546bacf0dea9042c93ecba8b34",
+ "013705b1502b37369ad22fe8237d444e",
+ "9b97f8837d5f2ebab0768fc9a6446b93",
+ "7e7e5236b05ec35f89edf8bf655498e7",
+ "7be8f2362c174c776fb9432fe93bf259",
+ "2422e80420276d2df5702c6470879b01",
+ "df645795db778bcce23bbe819a76ba48",
+ "3f97a4ac87dfc58761cda1782d749074",
+ "50e3f45df21ebfa1b706b9c0a1c245a8",
+ "7879541c7ff612c7ddf17cb8f7260183",
+ "67f6542b903b7ba1945eba1a85ee6b1c",
+ "b34b73d36ab6234b8d3f5494d251138e",
+ "0aea139641fdba59ab1103479a96e05f",
+ "02776815a87b8ba878453666d42afe3c",
+ "5929ab0a90459ebac5a16e2fb37c847e",
+ "c244def5b20ce0468f2b5012d04ac7fd",
+ "12116add6fefce36ed8a0aeccce9b6d3",
+ "3cd743841e9d8b878f34d91b793b4fad",
+ "45e87510cf5705262185f46905fae35f",
+ "276047016b0bfb501b2d4fc748165793",
+ "ddd245df5a799417d350bd7f4e0b0b7e",
+ "d34d917a54a2983f3fdbc4b14caae382",
+ "7730fbc09d0c1fb1939a8fc436f6b995",
+ "eb4899ef257a1711cc9270a19702e5b5",
+ "8a30932014bce35bba620895d374df7a",
+ "1924aabf9c50aa00bee5e1f95b5d9e12",
+ "1758d6f8b982aec9fbe50f20e3082b46",
+ "cd075928ab7e6883e697fe7fd3ac43ee",
+}
+
+// hashes2X is taken from
+// https://github.com/BLAKE2/BLAKE2/blob/master/testvectors/blake2-kat.json
+var hashes2X = []string{
+ "0e",
+ "5196",
+ "ad6bad",
+ "d8e4b32f",
+ "8eb89056f3",
+ "410497c2ed72",
+ "f0de771b375c90",
+ "8662db8685033611",
+ "9ef9f1eed88a3f52ca",
+ "08225082df0d2b0a815e",
+ "0f6e84a17439f1bc97c299",
+ "895ec39c78d3556cefdbfabc",
+ "2b396b3fa90ab556079a79b44d",
+ "abae26501c4c1d6123c0f2289111",
+ "bca098df9099b3f785a37ba40fce5f",
+ "19b827f054b67a120f11efb0d690be70",
+ "b88d32a338fd60b58570fda228a121113b",
+ "3f30143af1cad33f9b794576e078cc79062e",
+ "ffddb58d9aa8d38086fcdae07e6653e8f31dfc",
+ "abb99c2e74a74556919040ca0cd857c95ec985e9",
+ "71f13f89af55ba936f8a7188ee93d2e8fb0cf2a720",
+ "99734fdf0eef4838a7515426f4c59b800854e2fcdc1c",
+ "579b1652aa1f5779d2b0e61868af856855020bdd44d7a7",
+ "1383d4ab4a6d8672b4075d421a159f69380ff47e4bb518d5",
+ "d3fa1412712dbbab71d4c6265dc1585c8dcc73380cf807f76a",
+ "1d57868a71e7245667780455d9aaa9e0683baf08fbaf946091c2",
+ "ef80418fe7049c6251ed7960a6b0e9def0da2749781994b24593a0",
+ "ef91cb81e4bfb50231e89475e251e2ef2fde59357551cd227588b63f",
+ "d7f398a5d21c3139cff0562a84f154b6953c7bc18a5f4b60491c196b6d",
+ "0a2abc6d38f30aef253579a4088c5b9aec64391f37d576eb06a300c193a5",
+ "02dd758fa23113a14fd94830e50e0f6b86faec4e551e808b0ca8d00fef2a15",
+ "a4fe2bd0f96a215fa7164ae1a405f4030a586c12b0c29806a099d7d7fdd8dd72",
+ "7dce710a20f42ab687ec6ea83b53faaa418229ce0d5a2ff2a5e66defb0b65c03c9",
+ "0320c40b5eea641d0bc25420b7545ac1d796b61563728a4dc451207f1addeedcf860",
+ "460539415f2baeb626fad748dee0eb3e9f27221661160e13edf39d1b5d476ee0672400",
+ "02de8ffa5b9c748164f99ed9d678b02e53f4ae88fb26c6d94a8cefc328725a692eae78c2",
+ "348a61a0136436136910262ad67ef20644b32c15456d5fad6b1679386d0bea87cc1a2e2b5e",
+ "24c32966c803434d48d2283482ee8f404f598cf7a17961748125d2ed1da987039b1ce00f2ba7",
+ "bd07cb16121d3b47adf03b96c41c947beadc01e40548e0d0773e61780d48d33a0e2a675ca681a6",
+ "a35844e34c20b4b9371b6c52fac412afe5d80a4c1e40aa3a0e5a729dc3d41c2c3719d096f616f0ba",
+ "6df1efbb4567747fe98d218935612f8835852dde2ce3dec767792d7f1d876cdae0056fef085245449d",
+ "48d6094af78bd38d8f4b39c54279b80ef617bc6ad21def0b2c62113b656c5d6a55aea2e3fde94a254b92",
+ "cd6e684759d2f19083164712c2aca0038442efb5b646594396b1fccdbd21203290f44cfdecca0373b3801b",
+ "155dfbf26103c8354362663677fa27d0e1ce3487a821a2a7171014c1bd5dd071f4974df272b1374765b8f2e1",
+ "15b11067f311efa4ee813dbca48d690dc92780656bc4d4c56510523190a240180867c829a8b8b9844175a8aa23",
+ "9bc27953a17fb84d5eabe95b4ea6bc03ea450274abccfb6f3938ded8560fb59662459a11a86b0e0f32fbea6bb1f8",
+ "03b78fb0b34fb8662accdf350a6be75ace9789653ee4375d351e871f6a98ac5e782ca4b4a717665d25e49a5ae25d81",
+ "687e9a6fda6e2ce0e40e4d30fef38c31e3513d2892bbe85c991fc3715947e42bc49bcd079a40ed061c2c3665efe555ab",
+ "f3886027d2049a8909e26545bd202d6a6fa2a6f815d31c7d520f705a81fa606dd695369c37aee4fa77dc645e9b05813ceb",
+ "e4a412ccd20b97797d91ccc286904fcd17c5afe8bed0618f1af333c052c473cd327637d951c32e4af047106036a3bc8c1c45",
+ "92f4b8c240a28b6238bc2eabadaf2ff3c4bfe0e6c61268ace6aebdeb0691450caea4287db8b329bde96af8cdb8a0fe2f57ef2d",
+ "e506834b3445e1a9a9b7bae844e91e0834512a06c0dc75fa4604e3b903c4e23616f2e0c78b5cc496660b4a13064bb1138edef4ff",
+ "27031955a40d8dbd1591f26e3c26e367a3c68f8204a396c6a4ba34b89672896d11276966a42bd516716f35ed63e442e116dbcf35da",
+ "646b1635c68d2328dddd5ac26eb9877c24c28390a45753a65044c3136ae2fe4fb40d09bf555271646d3dceb1ab1b7c8d8e421f553f94",
+ "f6171f8d833743bdee7cc8f8b29c38614e1d2d8d6a5fff68bec2c0f4dd463d7941ff5c368e2683d8f1dc97119bde2b73ca412718bc8cb1",
+ "45db1c478b040aa2e23fb4427017079810775c62abe737e82ec0ef8dcd0fc51f521f29fe6412fff7eac9beb7bcf75f483f3f8b971e42454b",
+ "500dab14687db3ca3dde9304af5f54194b37bdf475628af46b07bfbf6bc2b64ecef284b17f9d1d9be41794699bc0e76c2878b3a55730f7142d",
+ "31bba2efc7b3f415c3f031d4c06bb590ae40085ad157370af30238e03e25a359c9e133212ed34b7a006f839173b577e7015a87fdff2270fafddb",
+ "0600b3fb4b5e1ed0c8b2698ac1d9905e67e027390764821f963ad8d2b33cbc378b9c25c3ee422992d22b760222ed5697be0576d73938ae9d634ed7",
+ "4c0ca4f177d132594a4c613bad68da24c564efa3b4da0d0a903f26534a2e09f8d799d10e78f48ccdb0203954a36c5cf1bf24c076632c2b022b041200",
+ "97aacf2e1b013677b2e14084f097cb1e64d7b3fa36f097e189d86dc4a263bcc46817cd1ee6ff0c7ccd9acef63201cdc0e36254e19204a7388643bb571f",
+ "71fd6846ce7adb0843d6063546a16b79b54ad6c0f018a479a45817624fa221f63525084860559d1a0679c8d89a80701c62743ec2da8419d503f8f0cd7946",
+ "f73dfb046def3362d6de36077dae2cee2587fe95fe0800548bb7d99737897096ba59052e0dadcc1fb0ccb5535391875328637a0376a43a4d89366758dfe3e2",
+ "ec470d0aa932c78c5bcf86203ec0014314114765fa679c3daef214f883a17e1b4ca12f44433772a6e4ef685c904b2fc35586c6bd88f325b965968b06d808d73f",
+ "cf601753ffa09fe48a8a84c37769991e96290e200bbaf1910c57760f989bd0c72e6128e294528ee861ad7eee70d589de3cf4a0c35f7197e1925a64d0133628d87d",
+ "f15413f7d6fc54bb55829f698da92ee42fcf58dde1aa1bd07d438ecdc32ad6bf2bcdbecc99f18ed43e81b33065af5a4ca29960ae50553e610c0bbf4153d580e73dbb",
+ "84b1738adb9757fb9402ef7113581291136184d7ae35fe0b6a738da6acb0889d4d5bac7a957024e3709fa80c77d3859871ed1aa25cf488e438a2d24cfadce6008761dd",
+ "e02814bb81f250c1835a05108396b74c7878e737654bb83155e241774d04e639bbc571b413cd9349092f926c8a149a53cd33e9b63f370b6d460e504199d2e7d849db6cbe",
+ "aeee4a789956ec0913592c30ce4f9c544894da77ba447c84df3be2c869100e4df8f7e316445d844b31c3209abcc912f647735fd4a7136c2f35c6fda5b2e6708f5ca951b2b0",
+ "8cfd11ca385de3c843de84c830d59278fe79b70fb5ddbfbfc1ddefeb22c329ef2f607d1d1abbd1cd0d0cc7c5d3ed922add76aadca0d2f57b66cb16c582b6f18f60aee2f7509b",
+ "852e5ce2047d8d8b42b4c7e4987b95d23e8026a202d4567951bbbd23111e389fe33a736318546a914d2bddedfbf53846036ad9e35f29318b1f96e33eba08f071d6dc665149feb6",
+ "f225c23164979d0d13874a90ee291627e4f61a672a5578506fd3d65a12cb48a182f78350dc24c637b2f3950dc4882a5c1d5d5bad551c6f3e0093aa87e962bea51566af3791d52d65",
+ "5f33864d882455f8ef046aed64e2d1691e5c1555e333b0852750592e6f00d3b5ec941d0c00e99629612795d5870cf93c984b45e4464ba072a34903b400a42824ac13da28c7c1cb1959",
+ "7baaee7c3eb68c18c5ae1d45ba381803de34e36a52e2d7ccc9d48a297273c4d8644b473195bc23005f7a4f5ca790b1fa11f6a96e585e635513f11745dd97a69c1222204ab28d3c7735df",
+ "d0a2a3fc450ef9af7ae982041feb2842901026467d87839c33b4a9e081ea63d5be60ae99ca6e42393ded45255b8f42886f87ba0310572d9f0d8b5a07ff4b6bae1f30559a844983cc568560",
+ "3aa4164462b3e7044c35b08b047b924790f6d5c520b1df4305b5d41f4717e81f0cd4bccb9a5a6594773832b8707443adde4047caaed2293f92234df257df54ed275a9658fab483d0576d33a9",
+ "c8b4239fd7f1b893d978268f77f6505b5775d89090374322d40083b0f4c437423f670ca213f7fe05c61069725da2561646eefaea597ac48e293fbad44c2872046857e56d04a426a84008cefd71",
+ "f94839a7024c0a16971271b6727c081770110c957b1f2e03be03d2200b565cf8240f2873b0426042aaea996a1784fadb2b27f23bc1a521b4f7320dfbed86cd38d75141365ba9b443defc0a3b4078",
+ "8af934fdc8b3376ca09bdd89f9057ed38b656bff96a8f8a3038d456a265689ca32036670cb01469cc6e958cc4a46f1e80d700ae56659828a65c0456b8e55f28f255bc86ce48e44377bf1f9970b617d",
+ "ada572989e42f0e38c1f7c22b46bb52a84df8f7b3b773c9f17a5823e59a9725248d703efb4cb011abc9474e8e711666ed3cfa60db48480a8160615dfabad761bc0eb843d2e46299c59b61a15b4422fdf",
+ "b11f1ea52a7e4bd2a5cf1e234b7c9eb909fb45860080f0a6bdb5517a37b5b7cd90f3a9e2297f995e96c293189b807a7bf6e7633bebbc36674544db5f18dd33020aeaf50ee832efe4d3d053873fd31ce3b9",
+ "e54b006cd96c43d19787c1ab1e08ea0f8922bdb7142e748212e7912a1f2c0a4fad1b9f5209c30960b8b83ef4960e929b155a8a48c8fb7ce4326915950cede6b98a96b6f1ecb12715b713985dacd1c1180413",
+ "ee2c2f31a414ccd8f6a790f55e09155fd50aac2a878f9014f6c6035cae9186f90cdef0b7adf3e207c3d24ddfba8cd321b2e9228b02a1182b6973da6698071fce8cc0a23a7bf0d5aefd21ab1b8dc7818549bba3",
+ "6d6810793bad6c7efe8fd56cac04a0fb8717a44c09cbfaebce196a80ac318c79ca5c2db54fee8191ee2d305b690a92bd9e2c947a3c29342a93ac05796484638787a184e4525e82aeb9afa2f9480caebb91014c51",
+ "91e4694366cff84854872667fd168d2d42eca9070cdc92fca9936e8361e7266931f418450d098a42686241d08024dd72f0024d22ba644bd414245e78608942321ff61860ba1245f83c88592dc7995c49c0c53aa8a9",
+ "608aa620a5cf145f4477694407ccd8faa3182465b29ae98d96a42f7409434c21e4671bcae079f6871a09d8f2965e4926a9b08277d32f9dd6a474e3a9fb232f27fc4235df9c02abf67f7e540ca9ddc270ee91b23a5b57",
+ "c14f75e92f75f4356ab01c8792af13383e7fef2ffb3064de55e8da0a50511fea364ccd8140134872adccad197228319260a7b77b67a39677a0dcdcadfb750333ac8e032121e278bdcdbed5e452dae0416011186d9ebf29",
+ "03fcb9f6e1f058091b11351e775184ff2cd1f31ee846c6ea8efd49dd344f4af473f92eb44eba8a019776f77bb24e294aa9f962b39feecf7c59d46f1a606f89b1e81c2715ac9aa252e9ce941d091ffb99bb52404961794cf8",
+ "11e189b1d90fcfe8111c79c5351d826f5ec15a602af3b71d50bc7ed813f36c9a682520984ae911669d3c3036223a53176794c7e17929efab2b1c5b500f24f8c83d3db5d1029c5714c6fd34eb800a913985c218071677b9885c",
+ "69f8f5db3ab0321a708ab2f4234645dade6bfda495851dbe7257f2b72e3e8378b9fa8120bc836b737a675271e519b4712d2b56b359e0f2234ba7552dd4828b939e0542e729878ac1f81b6ce14cb573e76af3a6aa227f95b2350e",
+ "be734d78fae92cacb009cc400e023086bc3a3a10e8ca7cb4d553ea85314f51383660b8508e8477af60baf7e07c04cc9e094690ae12c73e5f089763201b4b48d664b94b4f5820bd1540f4a84100fdf8fce7f6466aa5d5c34fcbab45",
+ "d61b77032403f9b6ea5ad2b760eb0157545e37f1712ec44d7926ccf130e8fc0fe8e9b15570a6214c3899a074811486182b250dc97ebdd3b61403614d935cd0a61c0899f31b0e49b81c8a9a4fe8409822c470aacfde229d965dd62f51",
+ "c31bd548e36d5fae95ed8fa6e807642711c897f0fcc3b0d00bd317ed2bca73412064618c6a84a61c71bce3e963333b0266a5656571dcc4ba8a8c9d84af4bdb445c34a7aef445b15d77698e0b13c436c928cc7fa7acd5f68867e8132993",
+ "9903b8adab803d085b634bfae2e109dd247a7d6249f203403216d9f7410c36142df8fa56fb4d6f78136eef5817bad5ea3608439bb19336628c37d42db16ab2df8018b773baedafb77278a50926370b48bd81710203c7abc7b4043f9a1751",
+ "4dadaf0d6a96022c8ce40d48f460526d9956da33260e1770315ead420da75b122c762762aa3ddc1aef9070ff2298b2304cf90443318b17183b60778f3859b141053e5827decfff27ff106a48cfdb0371d0ef614fc7400e860b676df3176d1a",
+ "314dda800f2f494ca9c9678f178940d2284cb29c51cb01ca2019a9bede0cdc50f8ecf2a77e238b884867e78e691461a66100b38f374c4ccac80309641533a3217eca7e6b9a9af01c026201f0afaec5a61629a59eb530c3cb81934b0cb5b45eae",
+ "4658b7500951f75c84e4509d74047ca621009835c0152f03c9f96ca73beb29608c44390ba4473323e621284be872bdb72175628780113e470036265d11dfcb284ac04604e667f1e4c1d357a411d3100d4d9f84a14a6fabd1e3f4de0ac81af50179",
+ "491f877592837e7912f16b73ee1fb06f4633d854a5723e156978f48ec48fbd8b5e863c24d838ff95fa865155d07e5513df42c8bb7706f8e3806b705866475c0ac04bbe5aa4b91b7dc373e82153483b1b03304a1a791b058926c1becd069509cbf46e",
+ "231034720c719ab31f7c146a702a971f5943b70086b80a2a3eb928fa9380b7a1ad8773bfd0739142d2ad6e19819765ca54f92db5f16c1df5fa4b445c266215a92527bd4ef50ed277b9a21aee3fb7a8128c14ce084f53eac878a7a660b7c011eb1a33c5",
+ "3366860c77804fe0b4f368b02bb5b0d150821d957e3ba37842da9fc8d336e9d702c8446ecafbd19d79b868702f32405853bc17695873a7306e0ce4573cd9ac0b7fc7dd35534d7635198d152a1802f7d8d6a4bb07600fcdaacfaa1c3f40a09bc02e974c99",
+ "ccbbbe621f910a95835f5f8d74b21e13f8a4b03f72f91f37b5c7e995aa3cd5539508d5e234e77a4668a42c239b2d13ef0e55ecf85142055e3f8a7e46320e21324a6b88e6c823ac04b485125c2aa59b61476481208f92ea4dd330cb18777c1cf0df7cd07893",
+ "87faf0e49e7e5ab66ee3147921f8817867fe637d4ab694c33ee8009c759e7d707f44c69c1b9754e2b4f8f47b25f51cd01de7273f548f4952e8efc4d9044c6ea72d1d5857e0ffeb3f44b0c88cb67683401cfb2f1d17f0ca5696641bef28d7579f68d9d066d968",
+ "38c876a007ec727c92e2503990c4d9407cea2271026aee88cd7b16c4396f00cc4b760576adf2d683713a3f6063cc13ecd7e4f3b6148ad914ca89f34d1375aa4c8e2033f1315153189507bfd116b07fc4bc14f751bbbb0e752f621153ae8df4d68491a22430b309",
+ "87d636a33dbd9ad81ecd6f3569e418bf8a972f97c5644787b99c361195231a72455a121dd7b3254d6ff80101a0a1e2b1eb1ca4866bd23063fe007310c88c4a2ab3b49f14755cd0ee0e5ffa2fd0d2c0ea41d89e67a27a8f6c94b134ba8d361491b3c20bacac3d226b",
+ "b021af793badbb857f9a353e320450c44c1030fce3885e6b271bcc02e6af65fdc5be4dc483ff44bd5d539ed1e7eb7efe3001252e92a87df8227ace601047e101c871d29302b3cb6c6f4639078afc81c4c0f4c2e04688612ecf3f7be1d58ea92894a5dab49b949f2089",
+ "c5c1f2fbf2c8504a686b615278fc6221858d401b7fe790b75fb6bca6885cdd128e9142bf925471ee126f9e62d984de1c30c9c677eff5fdbd5eb0fa4ef3bff6a831056cea20fd61cf44d56ffc5bda0e8472ecdc67946d63c40db4ba882bc4dfa16d8ddac600570b9b6bf3",
+ "88f8cc0daeaeaea7ab0520a311dff91b1fd9a7a3ec778c333422c9f3eb0bc183acc80dfefb17a5ac5f95c490693c45666ec69234919b83244003191bad837aa2a237daeb427e07b9e7aa6ca94b1db03d54ee8f4fe8d0802cb14a6599005eb6326eefe5008d9098d40aa851",
+ "2eb6b1a58e7fe39ff915ac84c2f21a22432c4f0d260380a3f993310af048b11647f95d23adf8a746500833ee4e467fb52ea9f1039519fa58bcb0f1d0151558147b3c92b83730aba0e20eeeea2b75f3ff3ad79f2f8a46cbbadb114a52e32f018342aeeaf827e03ad6d583bbce",
+ "3ba7dcd16a98be1df6b904457709b906cbf8d39516ef107006c0bf363db79f91aaae033466624d30858e61c2c368599963e49f22446e4473aa0df06e9c734e183a941510d540536377072334910e9cef56bc66c12df310ecd4b9dc14207439c1da0ac08bdd9be9f2c840df207e",
+ "a34a7926324ea96867dac6f0dba51d753268e497b1c4f272918c7eb0e34120be65b7b5ba044d583141ec3ea16fcedae6197116b16562fb0706a89dc8efd3ba173ccd0fd7d84d480e0a3dda3b580c326aa1caca623879b0fb91e7d173998889da704eda6495023b5ad4c9ad406298",
+ "5ef97d80b90d5c716322d9ba645a0e1b7a403968258a7d43d310320f60f96235f50e9f22cac0ad239636521fa0607d2f471051b505b371d88778c46fe6787d47a91a5bec4e3900fe6ed22918226fc9fbb3f70ee733c369420612b76b5f55988d757c891d7005d17ee55783fe506202",
+ "140d2c08dae0553f6a49585fd5c217796279152b2e100ebde6812d6e5f6b862b2a3a484aed4d6226197e511be2d7f05f55a916e32534ddcb81bdcf499c3f44f526eb515cc3b6fa4c4039ad251253241f541558bba7413ca29318a414179048a054104e433c674ca2d4b3a4c181878727",
+ "29fdfc1e859b001ee104d107216b5299a792d26b2418e823e0381fa390380d654e4a0a0720ba5ff59b2ff22d8c4e013284f980911dcfec7f0dca2f89867f311ced1ac8a14d669ef1114504a5b7626f67b22ecd86469800f1575543b72ab1d4c5c10ee08f06159a4a3e1ae09937f12aa173",
+ "52dfb643832a598a10786a430fc484d6370a05356ee61c80a101dbbcfac75847fba78e27e537cc4eb918eb5ab40b968d0fb23506fee2ad37e12fb7534fb55a9e50902b69ceb78d51db449cbe2d1fc0a8c0022d8a82e2182b0a059035e5f6c4f4cc90278518e178becfbea814f317f9e7c051",
+ "d32f69c6a8ee00ca83b82eaf82e312fbb00d9b2f6202412a1ffc6890b4509bbbeda4c4a90e8f7bca37e7fd82bd23307e2342d27aa10039a83da55e84ce273822740510e4ec239d73c52b0cbc245ad523af961994f19db225212bf4cc160f68a84760233952a8e09f2c963be9bb1d71ca4bb265",
+ "d1e603a46aa49ee1a9ded63918f80feca5fc22fb45f659fd837ff79be5ad7faf0bbd9c4ba91628ee293b478a7e6a7bd433fa265c20e5941b9ea7edc906055ce9799cbb06d0b33ae7ed7f4b918cc082c3d4a1ac317a4acec175a73cc3eeb7cb97d96d24133a29c19375c57f3a4105519846dd14d4",
+ "b45ac88fac2e8d8f5a4a90930cd7523730733369af9e39bf1ffb833c01108952198301f4619f04b9c399fef04c214bad3358999967c474b67a7c06457a1d61f9466489ed5c0c64c6cdc83027386d6263491d18e81ae8d68ca4e396a71207adaaa60997d0dca867065e68852e6dba9669b62dc7672b",
+ "d5f2893edd67f8a4b5245a616039ffe459d50e3d103ad4675102028f2c497ea69bf52fa62cd9e84f30ae2ea40449302932bbb0a5e426a054f166fdbe92c744314cc0a0aa58bbc3a8739f7e099961219ec208a8d01c1ae8a2a2b06534bf822aaa00ca96218e430f0389c69c7f3fd195e128c38d484ff6",
+ "37279a76e79f33f8b52f29358841db9ec2e03cc86d09a335f5a35c0a31a1db3e9c4eb7b1d1b978332f47f8c3e5409d4e443e1d15342a316f442e3bfa151f6a0d216df2443d80cbcf12c101c51f2946d81161583218584640f4f9c10de3bb3f4772bd3a0f4a365f444777456b913592719818afb26472b6",
+ "a46d252a0addf504ad2541e7d992cbed58a22ea5679980fb0df072d37540a77dd0a1448bdb7f172da7da19d6e4180a29356ecb2a8b5199b59a24e7028bb4521f3281313d2c00da9e1d284972ab6527066e9d508d68094c6aa03537226ef19c28d47f91dddebfcc796ec4221642ddf9de5b80b3b90c22d9e7",
+ "060c18d8b57b5e6572dee194c69e265c2743a48d4185a802eaa8d4dbd4c66c9ff725c93667f1fb816418f18c5f9be55e38b7718a9250bc06284bd834c7bd6dfcd11a97c14779ac539629bcd6e15b5fca3466d14fe60d8671af0fb8b080218703bc1c21563b8f640fde0304a3f4aeb9ec0482f880b5be0daa74",
+ "8f2f42bc01acca20d36054ec81272da60580a9a5414697e0bdb4e44a4ab18b8e690c8056d32f6eaaf9ee08f3448f1f23b9844cf33fb4a93cba5e8157b00b2179d18b6aa7215ae4e9dc9ad52484ad4bfb3688fc80565ddb246dd6db8f0937e01b0d2f2e2a64ad87e03c2a4ad74af5ab97976379445b96404f1d71",
+ "ccb9e524051cca0578aa1cb437116a01c400338f371f9e57525214ad5143b9c3416897eae8e584ce79347297071f67041f921cbc381c2be0b310b8004d039c7cc08cb8ff30ef83c3db413f3fb9c799e31cd930f64da1592ec980cc19830b2a448594cb12a61fc7a229e9c59fe1d66179772865894afd068f0942e5",
+ "3eb5dc42172022ab7d0bc465a3c725b2d82ee8d9844b396913ceb8a885323dbbbf9ef4ed549724cc96d451ea1d1d44a8175a75f2a7d44bb8bfc2c2dffed00db0328cfde52bf9171f4025770abbe59b3aefd8151c480bafa09f613955fd571e5d8c0d4936c670d182cf119c068d420ded12af694d63cd5aef2f4f6f71",
+ "20ea77e58e41337ad63f149ed962a8210b6efa3747fe9bea317c4b48f9641f7145b7906ed020a7ae7d2ee59435392edc32aee7eff978a661375af723fbd440dd84e4a152f2e6ef66f4ab1046b22c77ac52717de721dfe39aa8ba8cd5da27baca00cc1fffe12c52382f0ee83ad1418f4c6a122effaf7471e1e125d7e7ba",
+ "95c662b835171fa23f948c3c3ed27bab9b3c367bbfe267fe65f8037a35b50cd7fc6030bfce4000425ef646c34793f0762635ae70487a0216ef7428da622be895d1b6040423246511c2370d6876a5c5d2df8bbd48fb14f787b632ad2c1f5a927fdf36bc493c1c8606accfa52de33258669f7d2d73c9c81119591c8ea2b0ef",
+ "f708a230675d83299cc43167a771602d52fa37cbc068ef9128ef60d186e5d98efb8c98798da619d2011bf4673214f4a4c82e4b11156f6292f6e676d5b84dc1b81e7cc811b0d37310ac58da1bfcb339f6ba689d80dd876b82d131e03f450c6c9f15c3a3b3d4db43c273c94ed1d1bd6d369c4d30256ff80ea626bda56a6b94ea",
+ "f8417766ce86b275f2b7fec49da832ab9bf9cb6fdfe1b916979ae5b69176d7e0293f8d34cb55cf2b4264a8d671370cb595c419c1a3ce5b8afa642208481333522005fbe48cdc700e47b29254b79f685e1e91e7e34121784f53bd6a7d9fb6369571bba992c54316a54e309bbc2d488e9f4233d51d72a0dd8845772377f2c0feb9",
+ "3479e04efa2318afc441931a7d0134abc2f04227239fa5a6ae40f25189da1f1f313732026631969d3761aea0c478528b129808955be429136eeff003779dd0b8757e3b802bdff0f5f957e19278eabad72764aa74d469231e935f4c80040462ab56094e4a69a82346b3aeb075e73a8e30318e46fdaec0a42f17ccf5b592fb800613",
+ "03df0e061fa2ae63b42f94a1ba387661760deaab3ec8ffabcaff20eeed8d0717d8d09a0eafd9bde04e97b9501ac0c6f4255331f787d16054873f0673a3b42ce23b75a3b38c1ebcc04306d086c57a79d6095d8ce78e082a66c9efca7c2650c1046c6e0bbce0b2cba27c3824333e50e046e2a7703d3328ab3b82c9d6a51bc99b9516ff",
+ "76b488b801932932beefffdd8c19cf5b4632306e69e37e6a837e9a20c8e073bcadd5640549faa4972ebd7ee55cb2425b74cb041a52dd401b1a531beb6dfb23c4cfe74bc84f034156c8f55050ca93236eb73c4e2595d9fbf93dc49e1ec9a31705359732dda73f737ec4274e5c82626dc4ec929e5e2c7a2f5f5fb666181922bd8be575e3",
+ "ff17f6ef13abc0426b03d309dc6e8eeb822300f7b87eff4f9c44140a424098fd2aef860e5646066d22f5e8ed1e82a459c9b9ad7b9d5978c29718e17bff4eeefd1a80ba48108b551e62cd8be919e29edea8fbd5a96dfc97d01058d226105cfcdec0fba5d70769039c77be10bd182bd67f431e4b48b3345f534f08a4beb49628515d3e0b67",
+ "95b9d7b5b88431445ec80df511d4d106db2da75a2ba201484f90699157e5954d31a19f34d8f11524c1dabd88b9c3adcdba0520b2bdc8485def670409d1cd3707ff5f3e9dffe1bca56a23f254bf24770e2e636755f215814c8e897a062fd84c9f3f3fd62d16c6672a2578db26f65851b2c9f50e0f42685733a12dd9828cee198eb7c835b066",
+ "010e2192db21f3d49f96ba542b9977588025d823fc941c1c02d982eae87fb58c200b70b88d41bbe8ab0b0e8d6e0f14f7da03fde25e10148887d698289d2f686fa1408501422e1250af6b63e8bb30aac23dcdec4bba9c517361dff6dff5e6c6d9adcf42e1606e451b0004de10d90f0aed30dd853a7143e9e3f9256a1e638793713013ebee79d5",
+ "02aaf6b569e8e5b703ff5f28ccb6b89bf879b7311ea7f1a25edd372db62de8e000219afc1ad67e7909cc2f7c714c6fc63ba341062cebf24780980899950afc35cef38086ee88991e3002ae17c07fd8a16a49a8a90fc5540be0956dff95390c3d37629949de99920d93096eb35cf0427f75a6561cf68326e129dbeffb8772bfdce245d320f922ae",
+ "70752b3f18713e2f533246a2a46e38a83cc36dfccec07c1030b5204cba4432700735a8cee538b078d281a2d0262110381c5815a112bb84404f55af91652bd17502dd75e4910e062943d8a736ae3eecdfdd8e3f83e0a5e2ddeeff0ccbdadaddc95391310fc657a59724f7e6560c37dc1d5bb5db40170190f04a274c864ade9687c0f6a2a48283177a",
+ "01f3c1333b44077c518cc594d0fb90c37651fb7b2442e71fc0a5611097f1cf7bcfaf11c8e0ac1b1cab54afba15bb9332df6bc64d8032368e3f686c8324b0114e0979dad78a5ccd3fff88bbe89eef89c4be586ca092addef552ed33224e85d8c2f4fba85ac7735f34b6aa5ae5299154f861a9fb83046b0e8fca4db32c1343e02676f283975f43c086cf",
+ "509283ebc99ff8d87902fa00e2d2a6fa239e335fb840dbd0fdbab6ed2d95e8275402523f7ce9a2fabd4b6c9b533288fbe914bde84365a204711d0977a7d698f4614385984dd4c137e4820035dd6737da364edff1bb62283e87a8c7ae8637314fe9b5777ec4ec21276dafedb2ad5ee1aa0ac99e34a6c01c055c8a239fd28681607f65143082cd4553c529",
+ "c17e417e876db4e123c631f7136b8a85bfd6ce66a69180d0cd5ecfd6f037bb1c7bd7908d51f2c485bf9e92c0e1799ee5f6ab834ee481f5eb1a8020205adb4d0f90126d4e7c2c859c5a5f644bdfa9c649ff4f168e834de6f9769429732099d46d0af506ab86c6fd92175159bbc05c75db8e1fa867e6030d64250008d64c857c47caec3dc8b2ffb384d0193e",
+ "950988fbe9d62a66f5f2c492bc8dc944a78eb3796ec37ba94b6a81a9d402ccad03cd8497fff74c5f4a03081c5fecec48574fecb21c1de261332c23108195d3f6a96ff8e433a1a30eda53dd5bb414973334f8cde5510ff759f7c17046cbb5acd8e8c4a6eecf2a9121ec3fc4b22c4daa72678194ce809024cd45c4ebb9ccdb6f854205cdb624f0787480d8034d",
+ "552a212c403b473741da8e9c7b916d5e5e9bcc9949021ae1ca1ed46b7d4a98addbb604d9fff56175b7e0367db26c9635fa7813653dc8d610befdd09ec41e99b192a716106f4299eec8b940863e5a59cf26cdc2cd0c3017f9b4f215812bed15f69e77edf672178e13c55580982f01fcc2fa131ec3d736a55d56504c545f4be50fee83f1263e4d3f3c877cc6242c",
+ "b00c4283dd3d9cd26e44bd97cede6c771cb14f2571b51cfdaae4309560ffd165da025a1bbd31096c3aa8286e2d6dcc3e681b8d01f2c5064ea26dfd0b5156b7a7f5d1e046c5bd1628f8fdae24b03bdf7cf7366900cc013a8cbed9d7f5937c914b08f8c27683b956e1279812d04288515333fc6aba3684dde2292951f0610649d90fe61606630fc6a4cd383649252c",
+ "f6e79457bb6d0884dd223be2cf5ae412a1ed425f1e4012f75951b096aea3b9f3581f9013bcae1aff2d3fc1e5c7e06f24af6d53c2c5c238b71c71cc670b05a7ee5204400026a5c4e5ddec3ad96771e49fae4b0f75ec58049ad9d972e5749a32d90f847f1ed2a1bab83db181e541cf5c8adb6b29ecc64dc25add491d408d3eb3ddcb013de7f5ffb6de9dd7ff300a5fc6",
+ "fe1d71e1d5efa3f712d23216ee8ee9139e66bd648b83efc02cdb4d45a28cf36759ff190a84d14d9471477abefb5aea4111110336143dd80cf81e02f268120cc07d746538f968e9876bff8358d390f5b8e7eafa61ecd236cedaf276bd61865fdd3424988201dcdeda2e3e0c33c9e3b3670125dd1049106cc6df5695fb2dca443233ff440f265bbff055483bac1e859b83",
+ "4c80163562872a965dedd8725652906156ada6e9d999027d96f49289edb92f9ef043e9d7c3377e091b27f85275499454af32317535997fb4aaeaf93565ad481ff7d45d2abddd4df4b60f71a6923ec30496c6ae534dc5427107ab4c5e656a322c7ab058d4c13ec0ebafa76576560697ac98f84aa4a554f98ec87134c0d7dca9184cf70412a324aac91823c0aca02537d197",
+ "fdd58c5ffe88665beb7073c8f4c22472f4bc9390cdd27a42622ca55978b000ab7579f795d4de0dfcaf521b8268980ef1d20277b07567985c0fd5030784ad6c32541ac24e99ab706105a2255fc32935c0fce6fdad9bb224d94ae4eae2a3ff08836618a3adf193630647bce1952b69da4de360f59da303519278bfd39b733cf66820a5e9e971b702f45998b69a0889f4bec8ec",
+ "ff38b15aba3794e2c81d88003e045ac6cbfc9f4833cdf896cefd8ac0c88674727ad9a9fcb9ef36574deea480e6f6e8691c8390ad73b8ea0eb3665c914b0d886546948e67d7987eea248b5feb52346ffdd965d5c835144c3bc63daf325e74b11267e32e58a914ae4521a668839d9445fececa49c5fba41f9e171698bbc7c6c97fa163a377a96456958d6e1d74f91ada56a30df8",
+ "f048c19328d60b4e59ed76940415b2c84c23883198bba5699efb0a1774ad5da6d15390c7b55d77d66f37448fe08107f42a5336408d5322f4b630e3275865fc66dccab39f6e13fabc133e5a441fe352d81c7cd9a25f145a6e2e2417d3b0bbc79eafcd7ad688c02011fd268dd44ac3f4f87b37a84a46fd9e9975962fba92c9a3486deb0c45f6a2e044df4bb79f0feeea432c5008b0",
+ "1b3e5fe6f113cce28a6f8d6f7809d3cec398cabffe9ff2ff10a7fec29a4ee4b54186063fd5307a2be393c9ecd75a37620bdb94c9c18da69b658579676ec90351d10dc33a7cb3b75798b1234f9f684d4a73a0fab2df3d5d6fdb1c1b1514d0935c1f2dd21486f91c2595b2f8f8a500ff443b9305270fb6f3da7961d9316d4ed6a135a31c4a3611d40e6585bbb34f498cd5b9a5d92676",
+ "740db337baa12b16897f17a85fa5685acc85e48338867f8ac9c0198dd650f5dfa7c17725c1262c72207e365c8aa45ffaab6470a0e5afefbfc3bb702a9766064f28cc8b796878dfdd3ca9d0216c14941438fc541fb5be0a13d29a996c5c985db4f630df067a5626db5dcd8df3a2bff17dc446e46e4079b8815da4318cb228c7722684e2a795a0ca56f500ea51951a6a385385d886f678",
+ "1465f2d578d167faa017fe8f763ce3cc8dc1e8371d774ed2a8803f12585296ee71a1f2253dd16b717a81f91f0f3641018a0111182b4e65d884b0a3d0292631ad807cdccc88bdeecb476e76f72b5246a630aff6e2401fa9570f85acb73ccb4e19ef04a932a03d7b7985dbe1e5bb410df517fe362321469e6f8b0e0cef6c31d7aa8ec06aa220620d66cc0e133fdee963589b12320fc9678e",
+ "80c051952fa6f3ef6af0f1759ec3e83c8eb91abee1de360bfa09e74b05af2475a0dbf8f9135aa25892919bbe0515898cfb6f88abc9e1891f2b2180bb97370f578973d55c13c35edb22ed80647c2a7e2884d1ccb2dc2f92d7b6ec5843ade13a608a31190ce965bde97161c4d4af1d91ca9962053f9aa51865bdf04fc23fa35a6fc3c8e888941263a26ed66c2dd0b29b2325dfbd1227c5091c",
+ "9c1e2a1aed6406052eed12b4495365f2f80e9c9645473f3549b607f20910bcd16dc3a4b173ac8d128129cdb7c76ebbc8e9a2a1ba0d822c66b367e790a69ac71f0a60ed4bff0e979148e3f3ee6607c76dbc572ee5ff17c27e4b52adebb4bedddff517f591a1977299c7cb01106f1453b098d29848ba3751c816215bb0d090c50f9e445b41b2c49d4eec83b92ce6c269ce835fd279e7cbbb5e47",
+ "466abda8944d0329d2975c0f2e2afc901f117887af301881f63b714f49a2f692fa63a8871fc0b301fe8573dc9b2689880cd8969e5072c57671e0633b041481dab25e65c9de404af033a11a8070c8ab70ca6d465318501afdd9940c7efbe1bb6d49581c222fad251dba4ee0a98efe22a3c4f74da05844523b30bbad6b080ac8df70a02da80bc9d477dfb869adb211e209a316d5dd1fd89a6b8f8e",
+ "0e89a873e07799ba9372fc95d483193bd91a1ee6cc186374b51c8e4d1f40dd3d30e08f7feecfffbea5395d480ee588a294b96304b04f1ee7bbf6200cc8876395d1db3ac813e1019bb68d27204e514fe4a61ad2cbd1782dca0e38b5538c5390bca626c5895b745cfca5dac636fd4f37fed9014ab46ae1156c7789bbcbb956ff7ee5ce9effa560731d26783dc6ae8bddd53a5d28133614d0ddeddd9c",
+ "fdde2b80bc7a577ef0a6c03e59512bd5b62c265d860b75416ef0ce374d544cbb4e3a5dbd31e3b43e82975090c28bc77d1bdec907aeceb5d1c8b71375b6d631b84a46153f5f1d195bfcb2af6f597a9cdc83782c5bbbb58c5188a87ebf375eee5212fa52523820a83106e8ecd52bedd60d95cd646159774389c07e1adcaa6b6f649408f33399ec6e507d61659696b3dd249996892d5986b654d94ff337",
+ "f5d7d66929afcdff04de30e83f248e69e89604daea782e1d82d8032e91a95c1d6fb2f5578f79b51be4397e4cd7cbc608ce143fdddbc6fb6c43ffdd394a7df0124353b919aeeac025f3eb11ff246c3b9657c1a947fc534ce48e18feffada8797037c6bc7e2d9a9e2e019fe65627b3feb28e446473e3bd413047a2587f0be6a103403cb3c33fdc212dca14d8e386aa511c22308e632f5f9528dbabaf2deb",
+ "332990a8dba55f977bc814436cf386ebbf10cb487a5f6ce83e13741bac670c6810284fbbe4e303547ef411e964fae82854e8c13cf56979b89ecfedd337aad78260060122d13dfbbf8497acb2066ed89e30a1d5c11008bd4d145b5ec353956310536304d8b8bba0793baec6d8f3ff49718a56e6694f8122078265cf5731d9ba61292c1219a1affb3679576d4998290aba3684a205c3469d40761a5c4e96b2",
+ "efbdff285027610f03182009c89b953f19721cfcdb8accd74bab6ec4bdf3f555ab902cb0dd91284269d140638aaabd211748aa4da3b18cddc653b57e461b9ad8491807c535c08fe97d89eb587c6af19ca152e72479626ab764e8b62da89fefc8354c75a44851f985746d78715a5a92798dac1a4222be27897b3f0aa63d596aa7378545f49b259aa8518c3def8a2ec8f7aa956c43668c8717052035a7c36b47",
+ "0eea9bb83bdc324fd21b03669aa922fbebc448e7d25e210294c07862cfa6e061731dfb67b4810633f4dbe2130d90fa1c65843af436e74219d213c4458dcac1c48ec4541fc6e3b7918ab2bc621aedda53658050900c3865ca57cd5dfa1d28576827401956d2dd8b861fa90ab11bb0b544ded9bd3d62e3278ed484e17db8f2d5dc5ea4d19a0e15134ba6986714c2b22c59c2f0e517b74eb92ce40d2f5b89e6d79f",
+ "25da9f90d2d3f81b420ea5b03be69df8ccf05f91cc46d9ace62c7f56ead9de4af576fbeee747b906aad69e59104523fe03e1a0a4d5d902352df18d18dc8225855c46fefeec9bd09c508c916995ed4161ee633f6e6291cb16e8cac7edcce213417d34a2c1edea84a0e613278b1e853e25fb4d66ff4c7ee4584e7f9b681c319c874d43502534e8c16a57b1ae7cc0723783807738a55b661e617ee285bdb8b845607f",
+ "a76b6f81372df09322098868d469fb3fb9beafc5edb32c674974ca7032966aaca5b5c9bffef87bfe626bd8e33d1c5f054f7d5acd3b91ff95324d1ae39eb905b9f2694fe5cb03486cee86d2f661a751b0e6c716a61d1d405494c2d4e32bf803803dc02dba2c06eecf6f97fb1f6c5fd10cfc4215c06d627c46b6a16da0854e4c7c873d50aa1bd396b35961b5fa31ac962575230c07c369f8fbc1ff2256b47383a3df2a",
+ "f9db613812f2259972d91b1598ffb166031b339913925ee385f03b3b35dc4b2f1ae78a3c3d99c6ff6a07be129ce1f4b8d994d24988d7fbd31f20535d36ab6bd0592cfb4f8c1ed9244c7fa8a3c46e91272a1a40c6cfcf261c5658476c59793bf1a3775086e41a0492f88a31e2d9d1ce75cf1c6b4b928b3545d838d1de6b61b735d921bcf72e4e0615e9ff969ef76b4b947026cb016e2660ba39b0c4c953369a52c210de",
+ "e601c7e75f80b10a2d15b06c521618ddc1836fe9b024458385c53cbfcedd79f3b4239598cd7b9f72c42dec0b29dda9d4fa842173558ed16c2c0969f7117157317b57266990855b9acbf510e76310ebe4b96c0de47d7f6b00bb88d06fad2c2f01610b9a686079f3ed84613ba477922502bc2305681cd8dd465e70e357534503b7cbc68070ad16d9c51de96ccf0aae1599299331c5655b801fd1dd48dddf6902d0e9579f0c",
+ "ee5ff4ca16d1bde59ffaf2d064eac9141c1d8f120ea2bda942b7956ba3effc5f1e725a3b40b0b9223a14d7a50df1681d14ca0e0eda7bb09c428fa3b2701f83a7a3e139485a118f6287d266dbc7fe68c87b35becabc7782537c79cb8165bdc40cc103d7b6d4b627fafa0e4113f92341ab90ceab594bfae20dadbfafd401684584598941f1ffb8e23dc8a04ecd15376cda6d849fe0dfd177538c62413622d172d9d46e05c450",
+ "1daca80db6ed9cb162ae24aae07c02f4126f07cd09ecee8e798fa1bc25c26c644333b63731b4ebc3f287f2318a820c32a3a55fc976576bc936f7384e2553d2891e3771ff24dd4c7f0256906460a8f12d30ed2b23583a0259cb00a9065a757d654d6e4603e7c7eb4a8426b527ae8a849d9350e9094b890367df3e8b23ad2df4d7dcce416bd8ea3badd037f53f7b07c02e5926515f196d62aeb9b8b14c863f067fc12c5dfc90db",
+ "27ff4e58a34ff1fcd66855d014ea17889a3cf0021a9fea3fabfd5b270ae770f40b5439e00c0d26bd9766f6fb0b4f23c5fcc195edf6d04bf708e5b0bced4f5c256e5ae47cc5651e51cd9fe9dc5d101439b9bc5cc24f76a8e8847c72686e2af1ce7098ad7bc104dad00c096a6d48b6453322e9cd6773fb91fb1eabd05dc5185a9aea07a2f64c6fea9897681b4428aaffe1fe5fd3e8ceb890b12169ec9d51eaabf0ca3d5ba415770d",
+ "75e2fb56327983b04f640717be8cba6fef3655b4d8e5539587d6478356ec397efaed818b8425d052778eb30ef0dee656c52c2aeab079ed496ae4441a365f2130432c87ba757e25b4511656ad15e2eff84d342331fd2814d1f1d11af65d98a424c115ba183437c0d0aa55f5c44b8685028a47d89d0d36a0f20aed510c366ab338f074a941b404fb349caaec821e0850a627777cc8f5abce6b509290027a2a28ff1db62a5ed2f95fc6",
+ "c6ae8b6a060917cd498aa7874ad44baff73efc89a023d9f3e9d12c03d0b7f5bcb5e24e1bc2ab2f2c67b9a9d36ff8beb51b5affd4a3510361001c80642955b22ea4bf28b81a5affe5ecdbabd8d17960a6af3825a4522fe76b3d720b5d06e66bff5379d7a8de1f5cc3e7bb75163a854d77d9b3949bf904b6c4e568682f0dab7f217f80da7303cfdc9a53c17b6b51d8ddff0ce49541e0c7d7b2eed82a9d6be4aec73274c30895f5f0f5fa",
+ "606c9a15a89cd66a00f26122e33ab0a08c4f73f073d843e0f6a4c1618271cfd64e52a055327deaaea8841bdd5b778ebbbd46fbc5f43362326208fdb0d0f93153c57072e2e84cecfe3b45accae7cf9dd1b3eaf9d8250d8174b3dade2256ecc8c3acc77f79d1bf9795a53c46c0f04196d8b492608a9f2a0f0b80294e2abe012dc01e60af94323c467f44c536bf375cddbb068c78432843703dd00544f4fff3eaa1a5a1467afaae7815f80d",
+ "88b383cb266937c4259fc65b9005a8c190ee6cc4b7d3575900e6f3f091d0a2cefa26e601259ffb3fd03083270eb63db1ffb8b4515ec454d12f0944f8f9f6869eedc2c5f1689766a748d74e79ad83ff6a1639aefdec6109342dead31e9cead50bcc00c5b2206e8aaa47fdd01397b141880490174141a1e6e19268378c1b54a84aba60ca711fd72f7df88e120dfea2caa140085a0cf73342f3c588b7edfb5b5e5ccabd68a32364746d92d536",
+ "dc0b293f1ba02a326743509f41efdfeeac1efc45137ac03e397a3273a1f586a0190cfb4ea96d6c13ca692a4de6de905c8338c3e29a04cbae76272f568b9d795cea5d758106b9d9cff6f80ef650d6b7c428ea3946c3acc594907fe4227ed68faf31f2f6775f1be5139dc0b4d73ed6308fa226b9077561c9e4c7a4df68cc6b819b0f463a11b9a09682ba99752c4db7aea9beac1d9279f2c2675d42b551d27aa2c1c34125e32f2f6f45c35bca45",
+ "5d801a7413311e1d1b19b3c321542b22e2a4ccbe340545d272abede9223741d9835a0fc80cc9da97a13f8bb4110eb4ad71093efba165b1edad0da01da89d86726e0d8e42ae003b4b50297d233c87da08406f0e7fc58ba6da5ee5ba3d2d7142cbe6632734eb2e7b7863c15cc82198ee8f9a0ae0b7f93bdbda1ed269b3824d5d3c8e78513815b17a4c0cc8c9706b9c77423a309ae3fd98e1e05cdbe9e2577834fd71f964301b10b66c316a2d8f2c",
+ "2fd32a2bc15a9e96a100624404fd0a4e54ba9f8c0543d8ccf7c5c2e35f5e8c3c11dfd497320aa903900a4ca55a2b323b3ac4a7cfcd01bf0b448db8829072bee6b77c3d7bec2e1d8b414d907288d4a804d2379546ef2e2dc628269589164b13fceb32dba6fd5d48a956ce0b5c3eb28d894a95af58bf52f0d6d6cbe51317152744b4ccfc918ed17fa6856478d580b389016b772e1d02e57d2217a204e25361d91d4845a3fa20fefe2c5004f1f89ff7",
+ "f537b437662759bef8bd64368536b9c64fffbddc5e2cbdad465c3966b7f2c4bc5b96767ef40a1c144a4f1cd49edc4cc5b57e7eb30d9b90108f6fd3c0dc8a8808b9e0bd13aa3d661c4863637c5e4ba286553694a60bef18801299ae349df53a355051dcc46a7d003c4aa613808f430e9db8ca7dfe0b3f0a4c5ab6eb306aeb53e11a01f910064fbe6ca78b2a94fac34a2602f73de3f275953e13ff5c6bb5c39b82321ead17ec0f8ecc479e6afbc926e1",
+ "1dd9fb7d5b5d5074971e69300720014deba6fbdb942bd29704cdfcd40fa5281d2a1b9f5b776183e03ff99c29587f10e8d325cb49c5c93e94f5132741b92c4086eec1374dea5c1e772cbb230c7b31f3e962eb572be810076bdb926b63732522cdf815c3ab99bbc164a1036aab103cac7b823dd21a911aec9bc794028f07b7f839bae0e68211286441f1c8d3a35b281fd321312577bbda04f643ecb2a74ec4527bb5148dbccbeba749f5ea19b6072366ba",
+ "5bd63737449de2d20ca63943953338ecf4cdd6cd0a726241adb04376385a809cc6ba0f3482a310746fbc2cd5eb214f03a14cdc548777fb0d048d659cd75a962e490c4fe47affc2430a34b10275e4c76752a115aae3a24d4fb4fad89ce4d79d65de10292f3490bfdaeabfae08ed51bda6ec8230e66cb07ddbeec26e3ef68dd71c852900659fcf0c963f4574ffe4626a33db9abf0873dde68b21138498b81e8cc44d354be4073615889a7ddff633b5447d38",
+ "a683ec8250506571f9c640fb1837e1ebb06f123e745f95e521e4ea7a0b2b08a514bbe5bdfd316903d1d6a05f5a143d94dab61d8a3a146ab40b2d6b72df2f0e945875a8aa7051ed115975f6f1567cfcbf04c5e11e3a7027b8e179ba00739181ba10b028e3df7259d0712f4a6cef96469ff737865b85fee2c2db02a6423e32505381e18a1e0b4ce3c7998b8d6b1b5e09c3a280b85486d0984c9e193b0ad2043c2bc4ad04f5b00a73956715937eebf6b3e27afc",
+ "4df9d160b8e81c42930c48956fcb46b20b6656ee30e5a51dd6317876dc33e0160d31280fc185e58479f994991d575a917073b4439919c9ac49b6a7c3f985211d084c82c9d5c5b9a2d29c5699a22e79de3958d7b0e856b9aa97493cd4563aaa04fa3977a9bb89e0bc06a82296bdc76d20c8d393770176d648712454305fdfcf4e117d05acb5a5b006a9f8d0dc66dca708c4e4103ca825d2331750685c44ce3d9b3e753455580f4d6ac4533edeeb02cebec7cc84",
+ "67bb59c3ef5ee8bc79b89a673e331e581215076cc36b68f517ca0a74f74efafe9dcc240e6d8ca4b21019c27d6c9289f4419b4f218eeb39eb741c5ebebfe0ed2f6faeec5e8c477acf71907990e8e288f4d4049111779b0635c7bbec16b76493f1c22f645745fdac2b383679fee573e4f47af45ee08d84f63a5ace4ee1c06fa41e2e6e14b7bc392e38426813087a3a461efc62ed1941dc8f1728a2bdc04fde72a0b786558783c84abd4bd100e4926979a0a5e707b1",
+ "d341147169d2937ff2373bd0a9aefa77968ec8f0d993c6f9881eb174a1911e05cdc45993cb86d149a754bbe321ae38363f9518c50dd3faf087ffeeeb6a058b226ccab7858c00ba6de0e8f4d034b1d27508da5cc473f3a413189ee6fd912d7750486912944d4dc34405ce5ccc3885fb0aabcb922bcfa9081d0ab84c288022bd501235a835eb2e1124ed1d48fd4f8682da8e7919321031326502273375625c4e3a7282b9f53452195e53c6b4b57cd5c66f621bed1814",
+ "27e7872a54dfff359ea7f0fca256983f7600236e716e111be15a1fe72eb66923ea60038ca2953b0286447dfe4fe853ca13c4d1ddc7a578f1fc5fc8598b05809ad0c64a4363c0228f8d15e28280837a16a5c4dadab681e28968ae17934639fbc124bc59212138e494eecad48f6546c38366f1b7b2a0f56f579f41fb3aef75dc5a0958b25deaa50cb7fd1c69816aa9a51874a98e57911a33daf773c6e6166cecfeec7a0cf54df01ab4b931984f54424e92e08cd92d5e43",
+ "13dcc9c2783b3fbf6711d02505b924e72ec6736131159017b966dda90986b97522bf52fd15fc0560ecb91e2175322334aaaa0097e1f3777c0be6d5d3de18ed6fa3444133486068a777443a8d0fa212ca46994944555c87ad1fb3a367db711c7ebd8f7a7a6dbb3a0207de85851d1b0ad2f4149bdd5a5ba0e1a81ff742df95edee850c0de20e90dd01753137cb8f2c64e5e4638ceb893a3879ae2c049aa5bce44d56bf3f325b6c5029b2b8e1b2da8de7d4e48ca7d8f6fbdc",
+ "9ca875115b109eab538d4ec7023600ad953cacdb49b5abe263e68b48eafac89a15e803e838d048d9625972f271cc8f36344bed7bab69abf0bf05979a4cfff273b82f9961626509765fcb4b4e7fa48212bcb3ab2b1f2dd5e2af768cba6300a813514dd13e4d269e3d36548af0cacdb18bb2439ec9459f6d847d39f5598304ec46a26d75de1f9f0c2a88db915bd26e45e1f1e68c5b5b50d1890e97a3803c36755f026863d14176b8b57f42e91d3ff37787f9b38e333e9f0433",
+ "ec006ac11e6d62b6d9b32ebe2e18c002353a9ffd5dfbc5161ab887770ddd9b8c0e19e5321e5bc105add22e473050b71f0399327c7eba1ef809f8667c1f4e2c7172e10e753705e9a083f5bce88d77521225ecd9e89f1e1caed367fb0275dc28f620fbd67e6b176c9ae5d2659e6ec662116c9f2bbca3a93043233a4861e0688db6dc1800f752c5d58aa5033c250c891d9126e534ed921a9026eb333333fa8292059b8b446f336ca6a0cb4c7946b6aea3831653122f154a4ea1d7",
+ "23deadc94481ce28188f3a0ca3e85431964cb31b60fabf381e6bd45ef0332bd4dde774b0281d317dc2e7d0c298fcf8625fa734126968df8b68ef8a35c325d84ba4fc53936ff3ffdd8838d2a8cabf8a9cac54aa444ed9875944e55994a22f7fa8538b1e983b57d9215fac5c0052029644044e790ce2f5044655608c1d7ad3bb862203ba3aba3b526606f273d342ed5721648e3f600942d3f7546f679161436389d879dd8094e1bd1b1e12cde15cd3cda4c30a40835665e4e5cf94",
+ "94701e06340114f9cf715a1fb659988d33db59e87bc4844b1500448960af757b5282f6d52967a6ae11aa4ecfc6818c962b084c811a57724f5d401191567f24ce917e4f8c3963474fdc9d2c8613c16f62446448b6da6eeae54d672825ed7606a90e4611d0e318ff00566862c955b636b5e81fec3362e8672ad2a6d222a515cf410482836deba092a51a4d464dfbbab35c50a33437ac16a88256e9e23ddd3c827cc58d3e5000ee90b12e4c5175c5733662d4848ae0d406c2f0a4f498",
+ "735b0758d5a331b2304f01081172eb95ae4115de651b1a6693c5b9543de33df25d9f421dbaeca033fc8bff57313b482778005aa9fdcbca65c643da2f3320e34197868eec3848ff3c70d7ac7d910fc332e9a359f892ae01641be253013b554a0d3f249b3586b1857e5a0f9482ebd91432a852b221f4287a6e81ed24e8064645d5b28ab9a13b26cc1420ce73dbc47b31acf8a871601022ce23bc443b1222ce9a037a2fe5226295feb4efd4fd671338f459ae146032697cf82fc55c8fbf",
+ "c48d94f14549352790079fee69e3e72ebaa380510e3581a0824066413e7044a36ad08affbf9b52b21963d2f8e092ff0ac1c973c423ade3ece5d3bca852b894675e8173290529226939c24109f50b8b0d5c9f762ff10388833d99bea99c5ef3ebb2a9d19d2231e67ca6c9056d8834730605897426cd069cbeb6a46b9f5332be73ab45c03fcc35c2d91f22bf3861b2b2549f9ec8798aeff83ceaf707325c77e7389b388de8dab7c7c63a4110ec156c5145e42203c4a8e3d071a7cb83b4cd",
+ "553e9e0de274167ecdd7b5fc85f9c0e665be7c22c93ddc6ec840ce171cf5d1d1a476743eb7ea0c9492eac5a4c9837c62a91dd1a6ea9e6fff1f1470b22cc62359474a6ba0b0334b2739528454470f4e14b9c4eeb6fd2cdd7e7c6f97668eebd1000bef4388015630a8332de7b17c2004060ecb11e58029b3f9575040a5dd4e294e7c78e4fc99e4390c56534a4e933d9a45460f62ffaaba25da293f7765cd7a4ce78c28a85013b893a0099c1c128b01ee66a76f051dc1409bf4176e5afec90e",
+ "dea8f97c66a3e375d0a3412105ed4f0784f3973ec8c57b4f553d3da40fd4cfd39761de563ec96a9178804641f7ebbee48caf9dec17a14bc8246618b22e683c0090259e3db19dc5b6175710df80cdc735a92a990a3cfb166461ae713adda7d9fa3c4cf9f409b1467f3cf85d2141ef3f119d1c53f23c0380b1ebd728d7e932c535965bca41a414b6ea5bf0f9a381e098d282a554a25ce41980d7c7be75ff5ce4b1e54cc61e683f1dd817b8e2c1a430d7f895e5e7af13912cc110f0bbb95372fb",
+ "9dfda2e2f732867e60ed2b5fa99ab88eb82dc7a54334d02031258beef75fa4bd6962a1083b9c29e4eeb3e5ab8065f3e2fc732675b8d7705c16cfb4ef7305eb58120f1af5ddc55872a2cbde3a48661a0598f48f63e2e9aadc603545e2b6001748e3af9e86e1830af7b84ffd3e8f16679213d37cac91f07af0af02b37f5ed946ef5c955b60d488acc6ae736b10459ca7dabeacd7dabcfd656511ac913174f6d99327be59befe3e463a49afbb5235f0ce2840588c6edfbaaba00a4211c0764dd638",
+ "ddcd23e8b9dc8889b8599c721e7f8ecc2cbdca03e5a8fd5105f7f2941daec4e2906c654210bdd478374ddee43ee749a920ee91872e057a1157d384dcd111266221b3c79774476b4862fe450704ff2c5353e9a936cac87c96515c28ed4c830335a55d084cb5873c5fd2dd907f3266d8eb7bf13b6dd7cd4966982a0949efd8e428dae13daee549e01cc3c226211d6307823f742c5ef2155601a4644c46eddd603d4abd959c6d242e427768df3b1e22d87971df58a1564b38311a897c85b497a72556",
+ "39016647acfbc63fe55a74598bc1956eaf4e0cb49d532c5d8323fc6a3f15a0231597f06eafd74ad245e672bf6b21e4da503cb5bf9d15e9038ef354b38807564d91f38b4258378ccd9b9420a1562d7136196822a1291c913d83c4cd99fd8d420990c72cdc47607124de21da8d9c7f472fdcc780379f186a04da93cd87628abf323c8dadcd7fb8fbade37d7d2b5c9f9fc524ff77494c98f42f2158a6f68c906105ca9e8bb2df463863cfc1e9008d8344f55c4e3203dde6699b59812d49ce1279fa1c86",
+ "02cff7567067cbca5911664c6bd7daaf484181edd2a771d0b64566c3ab08d382e83932cdd7b4dbf86c9cdd1a4c353a511e68afb6746a507a9cd385c198246f4543d606c6149a5384e4ff54c1b90d663dc7a4b91aeac3cf716db7ca6f9a1914e3a33efe82e7ccc4215999c0b012782402db4726db1d7d1c73571d45739aa6fcb5a20eeb54a84d5f99902a8d356cbf95f34c9c28c8f2badfbc08c69233514493c0c04963268c88bc54039ab2999c7b06cba405936dfc43b48cb53f62e18e7ff8ff3f6eb9",
+ "5764812ae6ab9491d8d295a0299228ec7146148ff373241a510faee7db7080706a8dada87938bf726c754e416c8c63c0ac617266a0a4863c2582412bf0f53b827e9a3465949a03dc2db3cb10b8c75e45cb9bf65410a0f6e6410b7f71f3a7e229e647cbbd5a54904bb96f8358adea1aaa0e845ac2838f6dd16936baa15a7c755af8029ef50aed3066d375d3265eaaa38822d11b173f4a1de39461d17d1629c8df7334d8da1b6401daaf7f34b2b48d6556ae99cd29ed1073926bcda867421832a4c36c7095",
+ "4df3043cf0f90462b37d9106e67366d112e4938c4f06abae97869531af89e9feebce0812dffe71a226de5dc36be652e26ef6a4be47d9b2db5cdd43809a565e4fc0988bfe82037c505dd276b757b785203249fd083fb474a25acccc9f38dc5164ff9097e05989aa6e280739a755231f93670e7226e22046914c155bf33d135b3f736ccca84cc47ae643215a054b54b7e13ffcd7ad73cced9279dc3210b80700fcc757acfb64c68e0bc4da05aac2b6a99d5582e79b303c88a7ac4dd8ed4289516bba0e243527",
+ "bf041a11622715426c3a755c637d5f478dd7da949e50f05377bf333f1c62c671ebdbf9467d37b780c25f7af9d453fc67fafb2f065a3f9f15d4c3561eeaa73fa6c813bf96dcf02430a2e6b65da8d174d2558110dc1208bdcb7898e2670894c0b9e2c894da3b130f57a90ec8ea1bffd27a37b4da4645c546b2b141db4e2c919154dac00e78dd3eb6e4445974e3bb07905982da35e4069ee8f8c5acd0efcfa5c981b4fd5d42da83c633e3e35ebdc959bd14c8bacb52212b4334f94aa64d2ee183861db35d2d8a94",
+ "a170ceda0613adc9c3a1e427f07beacf3b16ed69fb42b6bc09a38d803f632ad2929dba215b85683b74e2feb1d18fe17d0ea0db84d1be4e2e73476917a2a4cff51d6eca7c5e82232afde00dd2286a4c20eb09800b4d5d80e7ea35b6965b9792d99e399abda8cf32174ae2b7414b9bdb9d63e148f7357635a7310b130c939593cd3479164724011966c4232142df9966f09422f34f20b30af4b640a2c6d3dd985fe0ba3dfa9083cbb9b8dfe540ff9f6c608d18481213040768ef33300d773f9890c724ead320a1e7",
+ "929477e9c2d0bbad3429a0e0de776695255013108261dc6404cb09828770e274d8bb650a50e490dfe917fc2047b0f8ee72e105927d9fa70523c727778cbf6ae876d641ad562938c870d12f2e047bb78920739dba0c3f8ce1fb77589623a5f1625f5d6ab81940c7dfc3dc3a641d82b2813629bab8282999317d6b93842334f123fb4693a9c2c9d8ba9bfc746642dfbd045cd2021b272eab7358aa954d453da53fc5392dfa7eb881f6f53809b692d27f3366595ff403289efcc691e118b4744a1147071d8909bef1e8",
+ "3e98bb14fff5bdf7db38a3960dc55ca7d02333daed8712cca13dd5bffd114636559279db72554cc0a0ee1f7e15557d77cab0f2f1131f94fe698db81be38300a856a5eca85e5cf915fb7b6f38ccd2f27350e62cc30ce10ffe835118be3d435d2342ed3d06199b7e20c8e34d68902f0ab8745bd8b7d5b863d525c1f5906d2dca598db8a0f1e67736182cac15677579c58b8c670cae1be3e3c882153b2aa2988933e579ec2d6dbb00c671da64443dfc027dee6dfc3233c99758304570a982bf9b2eb59ccd70d0b54c4b54",
+ "aa12c7fa50ffdc2811c1872e4bee15f43e6909212385c872eb489f7e06dc1787043f56126f8373bdfa4b3f61405c73dd4dfd3f40aa5cd207e8520849c26f67716a46c0989a99efff42f24e0736e327af8e607c401a1bac77341e9a78c91e35d55b2457bdd5317a405a1fcf7a2a23de68ef92b65819e8aa3807c545361dfc9fe89125123492da958dc313cb5d03cb4b192c54ac6b27fcbc498652f5ed36b587bb74942b3ad453a8d79e5ddc06ebf806dad5046b73251064582ef5777dc530f8701701761884783fdf197f",
+ "83e615cf6e17a29e63945710b548a6d9935850eec69830841e26cb6071e908bf72c87cf079ffb34c5eb1a390def72d004a9488224a18e189aa1092a0f1135712834d257a53dc1d0e2c6417d8f472ff13b181910f4c93a307420d44beec8875d5219a3160b8e921434ddf3f71d68db1c1d5c39d68edb7a604792f8b4e31ecda7895c99fc7031a5b98a22009c1da005ac8fd2da0b5d742743f5712d12fd76d11a18e487776ce21ca0d6e5ab9ca6d8c394c321b91c14e291399a642721361811a73b7392e8603a3004e7060bf",
+ "ae1a8f7bfe4b1a0fa94708921dadb2c20b938239d7b9a2c7c598528f20f49764d322ebe85a5b2ea15563cf2f2304baf55d6607c52e2e1160859dcb7af6d7856899eada0e9128a180d3de6fed9334ba52b80c5c362d5591a0ec30f86d37a399927eb1c53076a12d26775522c511c83eb5b7abc2a00bd2dfd5627a8febba53d85f9b74c4b7f0c862ddb0d9298899b646b774d6cc23e4e23ab47174fccd34499253996d5e0917210e2f6daa1685f89f2f1fdfd5509ebc38191d539ecfb54ff0f5bbe6ef36ea35d425af6462f518",
+ "1d033e06be253ab800c8176d3a9650ab2a5bcaa03e11ea95fb9ab3834b41eb0d1b2bcecfe219364c3104ef65a8d692bd77c798548b7d9a8faf7f5172db24ec7c93006d6e9839368291b8277a82c034a3731f1b2e298d6e0282ec8a7902e4f844d132f1d261d171375c646065e201849f2df73e3748d853a3122c2206aac92fea448500c5418ecfb3d80e0e6c0d51f85831ce74f6c659cc291f5348a1ef8b949f1b2a753633e382f40c1bd1b2f44748ea61127b6f568255ae25e1da9f52c8c53cd62cd482788ae430388a92694c",
+ "104bc838b16a641749dcf73c57b207ea3bcc84381170e4ca362065a3d492e892b426a1f4fd82f69461d1ce1f3aaf8fc291ea30d6667e7e1aea4c44f7d52a5fa6d34709e6658483260ff5da76bfb74e7d194ad40dcac00daf0e45e74db4bc2248100a8b256b257278c3c98f1f2e3a80cdb812352aaf4155b3a4033999fb9fe7f506994fcf3a8db31e9e5ca8ef8c2e9c6326ca5b0803724ba641950eca877fe6ed6afc2e014651c56d0e6a61eaff7c5ed0b861d4bebe42904c0a568c26aa8abb2e97da2bfb40f14eafb6bf16cd208f",
+ "5b92e4a175437d0a53eb10de2c56401720b11715a034459ebf506c3fd6534b5e817a0f09deac4bcfd353301d8d031b1331582ac09189b48e6ccea444655866c4bbd123d45ebabb774f877cf12d33b84cfca4a6a94f3f98869fcf2bbb6cc1b964c2438c2f348bcdf9001dce60a4706d20c169a040baa61cbeb0b8e58d505e6e3739ab03e110ae7efdf91347474033defbd1e86af322ec6456d3394699ca7ca6a29a70d9b10a38fe666eab2858bfe12dacb31568549c826c15af5b6fddf779954351be1872f04e53db7b3b5fbf61fd18",
+ "401cc7bd9f8227efaed70dad83fc8db3bd38efc166f0f11ab142c565c68ba9db680423a3d698b6f3476ef440051fd20b93f6a2ed045825567df5a65e3f62e4442ec396ad260a16a13a1dee46c7e8d88bdd7edf223ab76a9a787c1f4fe9925c051a4ca0e77a0e78baa29f36d193c862fd3a60653f544ea9e3f75f2f553891be8c1fb882f6a6aad118f576f3c2793efc67221b37a45ab6137434f6228cb002fc137b91fb8572c757f00736879453d64a8a868c131810ffdad9e9d028d132157ecb1da675d54047d19b27d3258c9b1bca0a",
+ "c20cf0354982ca6a19d9a4dbf78f810934db2373941a12c263adefa61a5f385c859bc47028829c531dc25ccc0004c7510e707175a102ec3c4b4c933e3f52033e67476ff5f864c446c042a21e6037f7798363d20267891b965879fde80af6b59d77862e3a229af01b7ac78b578e94bd9f9b073c38a627c1864df0083aabb17024bdab6c3c0f0f73d31d59480523a2f23b78baa0385c15f290114305d7f98786b7dbc17a8c2aad97448e8ea389e68ef71091a6a9735ac12ca5497b9171da11a93c28d3273f58b74e2e46279d3ce9d0b20d19",
+ "e2365c2754073b511f16a1881ff8a537541ca7362ae7b84223d3c7d1d49d03a37d6d05dd2b819af9705c015dacc9dda83474eb14b7d5fce6e8a8f8c58e870149338d320e5ae476da6749af45e65ffed550d225a39dc74ffd93ba7da476985d6f44e90fc8e82454496260458431804d802fe804d825f611772f9710667377adfb1a11e4275bcecb42175c515f6a9439a359824f82cc9d480954364e6693099a821ace362e6c7ecbe68be8823bb5b49b4f23ad81b64139e3b63d9d4d298a842f013ef0d91ce7915ee8f816c70ba2aa3994216f",
+ "9c43944676fe859327096f82049cf69e48b98715878400fdf2805e0d5ee642e6cc9c43739f418b701348a033c5cb96bf8702fcd2fac9be58262a843c1e4155ed8a1724b6ebf7cce659d88a95a0c54deb2d7d9574a45219b6419ee173d1d8fad3ace47c962b349abe1048565df85bbd0eb9b11698258c23598023a00fdd26573e41951452027125c6e894a97736ecd63fd15b29a55d8dd9dab7e2e18f541a2e341890a61b7c896e7dc67aa82f3479dacd4a8ec7558d40c34d9ae4060e13718d676c2450258d83de8a86e012813693098c165b4e",
+ "1c707c29582d98a0e99639211102f3f041660ca03ad0939fe3855b8c1b22d6a9b8673c93e3eabc0ab231509b2b0d73c76a290a363943d12d2ff0ea30c6dd54eda753767effe04cabb4c3966388fa4c83a1906a0f48519a5fba9aeb585e0f8c45d6123a75ebe98fd1d0272f733a3925119481a321fe7509346c05128302851ba17a137f956f184e057a305e79a148727a5926de6854eb0314d5492fd735fa773d99ea34c95ca7546bd3a3aa8e66bcc6d860cec3d35d0e2165d5fbe8be99b6e7967df6693e5a6243e94c9c4a2528ae6305cbeca209",
+ "8f1e88103ffa378f062cade0ec509bec99a5c73fb273e79dbef24abf718ac26ac23dfd2b8932038ed3cb9637b71643c161142019f45b25b4fa4c52356737a27027e805ec635154327a66bfe64efc6285cca98c34edc7fb6c0766970a545342cf840aec0a5ba1dd3c6949be4fe97b0f8c8186de07536fd9074db34d09b2f08af9dcf9424d6edbf9cd044102c0e5dc35aff78c36d079dbd2c500e19c8c985ae2abaf6b2a20716bb719754a8840ce97632116c4d0b0e3c83ccca27f11c4204b76b5d6cfe6348a9615d8e4af53500dc4c2cabf12ec8c76",
+ "b9a0c28f1a6156992c103a84655fc6e654fa6e45e45819513afa797024717c00cc195994512fd53ecd1e12dac4d2448e0c40308382312084d2111f7db147b2e6589ce6d977f6115f629508167df8f45bac98abd49f6b272bcc4fd874dd5e29fb6daceb2d727a2a892194cfb9269eda00626ac89b4e74bd29b21e9f6ef18cb69889a02d4f0a06a2e5718899c1dc3b051c2cfa29653e782f87fefa478e6465bf5ff27f8b6abdb500077aac97100bd955ec535a587d66f23354be51cd8170289344bac9451f74e8aee3639f7c09981f4885e018912324d7",
+ "456844a34ae1074246f8f71eeef2010ec8733265bed7c1cc60043d770edfa320cbd4284a94be2574337e16d27f125074ebd7e99031f7abb4547b9540a7b0b5148ef501b550dd929f3dfe39ac65519f563e9254424aaafa05b1d37c16c771882e9e25d4906ac58603da749adf686932cd73d81e2658134fe69294c7a521d257eaf2110c667fc9d6f09b52d24b93910e532184eeb96eae9d9c9750ac3c39e79367431ac1af7011172d0a8be46a31010219a0310a733068c589bfc4748f3626aa4ff8d355cc893d05111c287c9992e95ad47481a6c42d6eca",
+ "c5c4b9900b9727bdc24baa544cad5faf8340be6b3759361f53889f71f5f4b224aa0090d875a00ea7116772117dbefc3a81c6950ca7ceeae71e4ba975c50d61fec82e6d9448d3a0dfd10bb087bdf0673e3e19fa2aaa7e97eebf71f11b86034fcf5a61240c71444ac3da15ef09b27b3523d37d309e8722380f835c1aee4a767bb027ec0674040853e5b53d6a31657f51acff6d2487860becd5ce695696cfe5937f4a0217b69e01cc6facc24dfe5f5230b8692a0b718e3b3c789d682db36101795a9a5f8bbb838c3679be72f7941a1db180135347d0a884ab7c",
+ "1781df2fedd2c39137854737d054cd3ed16b0ade411e41d97888ac900fdb46d9ae26b3d2dd07e118fd57eabd0dfd03a55793c76420666444865371adffc9b2f35068a0d70f9cfda1ac27ccb4beff4ffa5b8bb8bddac843386675c38a181fd0d935d6d51b25d78e7ff4ecef27a9853c0f0d2879c395ed1c4883987d123890d04f851c3e042e1164c68c0d503de16816f4b0e554236e5f4c339ea11d01ce652f6208f78f457a2417a97c0a6a240f443262def4b6763abf53e597bf1a28f907dc7cbdc751a234ea7d75710ad5ab0c37e8e9805102a375abd44011",
+ "8963552ad1e729ead07750df599d734157aaa4bcdcac17e8eb19b4f99cdb162686ff433137aa4e8a0cc8df0053999196262115aec326cf37567d9ba4760e0ad21d5763977f1ab9b35c0fc667890fa87fc946ceb776a811b5adc69446bfb8f5d9908029dc5aa38db816e4a4e8f98e5a48cf0a01627031c5bd1ced8bc1940dcafe4ae2f1199b186468eafc07e96a89d95dc18ef0fed3eda5b58ce58f221a47ba5311313cc680367eeb058fafc7bcadce5f520b6371489d9e529278ae6ee2650a85aed82896879038bbd9aa8d685fc9528943ccf2235cdf69a86464",
+ "23ceae3008085134433f5de4b47bafe0f443d443491e6cd47b216dd2dcc3da65239515a6e6b9beb9a939ae9f1f1f5e11f88326475e0962f319d9bf75ddfb4a46e7cc3f799d7547f3c0b2e089018b75787b82ea1a7295e7411f4852f94c94170e98bb0647923b8eb7d184038e56560da46085540cbfef82b6b577c445d038f6c93fbfdfc96ab3a0191d20a57b8610efb4cc45cd95198198e6f80ac46b0601511885f650eb00992605be903bcb46cd53c360c6f86e476c4c9ca4ad052eb572bbf26eb81dd9c73bcbec137aea6ee27aa97dadf7bef733fa1555019dab",
+ "c0fd31e82c996d7edef095cccfcf669accb85a483ea9c59f368cc980f73da7202a95c5156c34192ae4ebf773c1a683c079b17ac9d08b4265b4054fcddaf6666ca50f38f1a2ef2497459a68c06837363a526e850ecfbd223f55dba67db017eadb7a9139abb5bf3854834478b838aafa16c5ee90ea52fb2f7b8db2bcefb85b06fc455c2b6c27d0af9a49dbf2f313bf2599370637393e7972b31d8bf6759f3e6115c618e672831f84d76ba1879c754144e1df4d56b1e264b1797dcb8ab165040c8d20b931071081d7f74fbff590bdc8e888e71acc6a720270da8db7c821",
+ "936fdab91fba396e4a8754a97a04ba333daadc29885c9d0c8fea3387165278f4974e468fea57f2bfd8428c4d0f010833283db73735d39de0c0cb5898d0c06c0ecd05f61098935cb6130a8da60d1a6c2ecfe420f972263fff5a631b09e81c837183c5528bb1c740b36fc39cb082f3383c2b4afb25d04ad1d1f4af63dcf26a0bf5a647cd2e35a51cc119c4dc5031f5715b3bfa1f2b92de06bdac0d670fdd30980f32c51f3936b51e5db6b95a8d36279da5faa4c4e454f2b7e54e9f488071011c7f6f9b63da260a2e46d796d36c9a9dcae88085806a10a77bbb670d475778",
+ "a55fe162b287bd6eebd6cf7e7aeea8672322d924ae42c7404ff89aedb98943f3755d2889bca488cc7000e6e9b8e7a0ef289273cd29c44cc600e330d1775e3cb767f12150e1615dca8c3f67466463a3ca993a1b788cf67a7a35b95dfff954206eb5ea1e1bf7fb06482a551625b5c9fd9a86e8414c8cf79d3a14104a153cbe04aac5172aa4c4a89349f5856c4262dd1d7317a7544c9afbbed449e7dcc2b58d9df6c9c9ed3883e42e80f5c2433550f30e73c7bce0fccdd880adc19282a392dae26a0108e7faf168cfc15937aeb046d60712603286b8ddfb27916b79242d56f1",
+ "2bd6976592408cdbc4e41dcd3ecfbb786775ddedef914d9058e6753f839fdfe15b17d549dbc084aa6cdf3befa0158aa84c5d58c5876144fd7e6c41ab7d42419d0dd353732e0e6d3fafc4f5626c07433390a4fd467197e85b5de7e2cf1c26cc575356adedcc0740008523b503df12ff571387726c5ccb280376d19cbacb1d7ce7aab8b13292c6a8b8881e949cbf6d4610d16ebba1d46cdb8d0459596e0aa683d0307bd926e14de19b9bfeaefa29d91b82248604673a455520cbb64eef3f38cfad8e126a3b1cfa1aaba53a784c8ae0c50279c0ecdab54095d36f67ace9b8ebbb",
+ "71913ae2b1c8729ed6da003c24a1d4f96e28d7faf55ca14ee0b2865282b9b61103ce6ee0b00b00aacf2081adedea5616f9dfd22c6d6d4f5907bcc02eb33edf92de0bd479794f51246d9b612b4543f6ff633c4fc83bfa6144c9d26721cdc690a3d5a8db54d8bc7873bfd32924eeb502810732b5ac2f1852bb021c401d26c39aa3b7eb09083093a9e89bf889b53383b5af61110aca1b9fdf38908c7d5a184fc5f46b3423a66a2749feb8de2c541c563987278dbd0513d99b732411012b5b75e385510de5f6839c3797dc094c9501d5f0504b06b43efb6e746f2129ca189c1da424",
+ "9d048a83294de08d3063d2ee4b4f3106641d9b340a3785c076233686dd3382d9064a349c9eaa78028d35652078b583e3f708e036eb2ced3f7f0e936c0fd98f5d0f8aa91b8d9badef298bd0c06843831279e7c0c67ca7e572f552cfdd984c12e924c08c13aeec6f7e13d161785546ebfd794b5d6a92a4744e52c4cab1d0df93b9468be6e264e8cfcc488f9c3c1817cbe501f4b9cc5999483b7433aea777226b25273a6ef2331b5f3b6db8091591e8e276015da3ef78bb2ee0526ffe23def2d8d193cbe594e8ced1f3d216fcedae2a1eb288da82e34cf98aebc28def658ee0849ae7",
+ "3251c96cbf82ee2e5264528c0b6cdfc23d20e1eb2d6441b5d62f0fd24c692a0d45a8bc8aac32884b7141ac0f4f113ec9fc7f6b4db3d696374177f9a42d602ca471275b928f639105a55b846da9ac7274cc37de8c38541f6895f94d72a81e117844b46601c201f7189b935a96e42505f2098ac985d92dfe86349a706ef6325b3c2e4060ced3c453e68ed09e043bcc75846b80118dc53530248da250fb57922d0afa53a7b2c89161aa4fa372a46b2a8e1307741cecedf585d2f998a9d496763800b6965c38a5d8aa566c709f13699c8185ab4fd8fdc8b824f4dd6d1c255b4788f50574",
+ "2de31dbc8a012254586f3229d3524fc529554e98850d30acdfc11406bba6a142029126ac165ee90b2de7509fc3571a8ee12e16b05054eb8baea879d135b39627f0d8331be3e66bc720c2096ce74e437daebf3bc53d8f2ccc228c3256d3edb6e9ae7c354a0c9350e6d663a9a30630bf9da3d96b96608a2a171ae28105714058b6c4b38a36c56561c4612c32aad25c65b7fb6faa4e4ecd44ebf9b2fad42ff9a807cda2581614fd30d41a7436069399b8d4f062a37a5bd4066a93d541fa5797a7d3e7dc9c4c40f0bbf5256f71613240f9ef128b3423eacaf428ada06b6a531f835281e4f3",
+ "07dadee629a08223dcd7ec441287b4c5e26347451d9c003e3a8496b4ea313b51126283a6720d7851e24423d9c9c818b4601247178f38a61f45fd4c8596d79529d416834226666a2c8552bbc901cc5cc3406a18fc88077fea52e1b620748553052ab7788c0d025b095b736fbe714cb3a968ec16b5917652eba2d7cf32ef3140d6c27b25d053e9786d24cd09a5306a0ef55e46201faa6196a91084267d7a7b5ca57c2efdeb2cb97d682d2a191b915553c8933f1d1b7faf0b4a1d83ef611f1e44438bc1c3d860fbfd12b5f26e5a6889a31ce26ae6a55c7a563b5816d113423ef3f25fa9befc",
+ "1d94166bb387526d519c4ce150221954da8930f66765fe6a5504e30a69962d595cfdd07a82c003843598864261f053bdb6f5086d516c261e089caa89990f0967605768ae9200bdfe4dcd7b77a93265cb33d9851a2a1036113c732bf3f37534530641300f0620de5c16101e16f4baf39d9fcbfcb01c52afce0992c329d8dbb438c314eee995c5020611d6f889e06b8a032785cba9a415580dbf752b5e510523c89f478cc6f047bd926f51e4a965c9749d1e76379c0e7e5b56803893bafaa4d2892b4c52f143b2fa777cd1035ea418684b8019df084f9a3f1f768753096621f342895c510d01",
+ "fc0073f199ed8a1d6edc8e7bdf182670003108d82b283aba82326e856f8de378987a03d0fe8d2041440fd29d51c63796aab44090d2b14ee00859b3a08cbe88f724badcd3c401226c5db8b307b8deea5be305412b080e9f99cf79d6d08d3646f347a7afebb62912e3e246e2e726f9aec5c101d916e47f984507b1d65d313697256c77da7eca3bc5811c87bee02a2826cefff0d92bae989609aaf95d70561b40d98474c37277c884aed887a1606d206b11e8a8a71d1f1d19319557b57351228ff0404be700a6cc56c0a30f3d4b7a0a046463fdaf19e7d5f59e155f378e35baa33db1e881f2207f",
+ "f42a6a91278d6a076feba985b1cf4ce0af1fa9d6d039c136e8971e665ff088a10b6b9a379a6f5526fc5957773a0ccb8972a4a19be0745ac13937030a54b18dee4f4c5df47a58a33a7516b90e646e5da999166ab0e52f457f7c9b7e391836a687eaae37b377e59a4c995ab0c57162c307ab951a9ba6590f429cd27250e7010eb794ec1b1ec35f8aad189b2fd3e8aff24d93601d91a4884e6f84b02757ce7620a02901519fccfda52f68ad6df709d112a9c25d66bcbb9622806427ca8b8d346b6db05874bde800cde9cf17df4b05baab0f133febd1ebbb053b49c109a7f5b1f864a304d10288e2f0",
+ "bbcefaf4a0739509f8a2f831c954071aac52e60cfa882a867b8b910dcf7edf92e1c0692bb027bc378c460a01cb6ecc8f2a012dd84ee5a678cd497b1457b6d393421fbee98ff544fc7eba24cbc3aae506254d9a2d74dde74437ce4c8a69010718506bf4c5943342a942e5e2d3406a3016280b6e37954c5d5e763346251afb0b746cad68cac757f9df765e092518729cfb9a5e76300c124e708ca33591a369767ffb63933cb72fba67beb2223d98984d0b75eb5d1a38615913747b520b3d613c715c0c77d2987bb88f3c419bcc5d38573cf4a8a4f550b2d876f05ca252d88c70a561d869a5018b32f7",
+ "dc2437010cb05d9cab2af5c275e1d2acd627ce19fb86355df91fb8d059e60d591663c8eb077d48388c9a321057a98136f49f0098348d9f29d808936f98bb1787c7ac75fb14f6076dfd2de5b59b1fa4848cabaa9a99a091dc24b561911c392ecdbe53f4adae82b852d830adea3a10490c908e337ce0a6d12354ce05a37ad3a06696b66820af8a1f67e6287533fd6f38a5f6ad1c6b078c08baf2c37d2683af01e6a5b33796c8ae48935a888f9bd265f4f11a4e27c433b8b1c9afd140bcd21a07e24378ad6badde8e47c57e3340f49e2406e8d49afadd65eaaa4c3d078c27d7e42118cb86cd248100a356",
+ "6c290db326dd3152e6fa9b9c0cd7d49e50a0221b96e32f5f34a8cb7d0c2edd3e937a7d025d6999b7b468add4d6894d8f7aceaabc18f4d9c171f1fe95ea1ae8570382a8450fbc595d95b1f51d24e1abc2970b0e1d20ca40aa21bdfb3656adf2f19882eda606f5ef1c03174e1d94c8d12f0fee8dce6852f42a364eeafa27a7971d4379405db8e46baac4d685b969238e5df06292a6c790bf1994a051b038e1d8db91e1bc4804f32443781c34a552ed2e8100cea374e77af56ba0e11c45990d3ba68df9087b1f4968cbcbb1c42f99b7267c76af926ff3134e093df28fab039cad420c6b70f2d9b5e678c155",
+ "ac724a22ebabaedbbb052953e3c264a4b6440f313bad501cdc1484b64f33402a2230898776db5c818c28035ffae6ea24abd04b7159e42159833903a0c23a7c564f7645e49ddedb748fd9e51bd6cbf2eced98caaa35226970f003ce1fd260ac5795e096f1c04aebf8fd36e5e2adeea929b5e963a3cb71d6b55c85bb7d3a2b03a7e74b4416de8fa68950168d7c3ae8ed2e29bad1e8a182a7c5418e5d564373163778cd3c34e9d320eb1a60480a8f98b12e0026cbd7752e6079812e3767d9f55f3f10b8c214a6eceb2a58954091a06b33862af171a9b60bf2c6a44e8766e6c56e98092c56f2a8510f6d05c103",
+ "8c70114f7cffb375c2b9a06e27297a5c32418b2daf68af5bbedcc7106edbc070e764bf40c1f8eb15079e2ab77f898afff3490108ed9afb7ea9cb05df41d263be0e42d2321d3d2656622d7bd232bf68d37375fe7314b09cba66f19c8b59424198ee69e7a9f3de0ecce0685127807ce336fa479ccaf7aa1ebc4e406271ce6c4923ec36093516498cc227f9218869346c80ba5ae83e023aca0ae2bc86b5bf5d115a4616b6587cb869d92f8c780ab70d5766de07a204af5e1c8dbba622516d2e911b36c82e4687e4d258ea616c07f76ff0baa376c8d5975cffac0b25817f779ae3ce88b72eb47e378484ce999bf0",
+ "0733d59f041036398233fd47a84b93f6778ae5259ef5d62aa3b9faedec34c7edb570c18b2a5d2c4c55cf656d98a1ae396d45a3b746b7ad6f07312c3d05d1a50ffa90bcdcdba105e25b7b0c52664223f8c2476925d46dc6ea2406ded7d0b0b292f6656cebcc7616cfa4b82aec68b35d1da67f6ed2bf0171849d6bb65128d8a140ea5cf97f1003f8d7093bee077be78def4f7bd2caccbf0644f26b26285225142c40038484c3bb9ba9597744f4389e76dca3eb695c33ccc621cab1fb603cb3535a0ad318d220385d5e94f8674f3d55e97e097f8d5c049e911946afbfce783819951d65d6bff4567dc951390d1aaa",
+ "398ddbba3dcb5642c102efa841c1fcdaf067062e7eef8e2ee0cd73d7f77e57372d6ee1a9b7b6f86ad12d575001ae71f593449cb5a476c6bfeddaa2af0f9239c1d7effdedf66ceaf413707b5ab9661a7cc0ef8cfe4d1651579c4f0f64e2d12a52653c54f2dd60864e769eab8a627c89c56ee93365d031f0d2523cb95664b1575d51b122f33c9e94de75432a690658c977b68aa5b721a393f9b9b3b612c10e920a7d510c6d8460b35f8614c42f5d2c241a01b28105aa7c1b521ac63ebbedafac6d5a38c898e8590f918a1927bc53aecc2b1c8b18d7df9107c6997d9b3fa4b0bdb1c603da619d9e75670b97a5b40f06",
+ "ef07bbc7c4150dd47f8c69a7989948fe831dc798b0424dcd6551bfa8e88216095a7e5d720909bf3d23526b9ba464b66ff6b63a7337c31451ab9a15f04ead809a62bb52206237de77597a730106d02d227dd6099ea9ee2a92cdc446ac3b9d024e32255adb3e9b56b561c431e0b5a721f0336f19568a5335d0ebc6c73ed8ff2c15e219477d9e4b67f2928e251f8a61a2848857e037d010806c718ab062967fd8e85f3722252957923f5f9005aae47b4b1b3fa464e3ba9df573a56055f17e903126fbbcb6cb96de92fe617c97f84ef3ba0d8f2651dc4aa80c157f372ae1bc02e5067ad076f3fe48bb72c0f3c99273f82b",
+ "c7076986d2333f3a6752adf11f1a9e5c6bc4755f341073cc86a9c7519c8db029d5ae833fdf3fee826ff4692c57880c5074620ea97c00f1dde1e8a0f18501627984ded4d1b5c4af35be5cc1bcc868060a49a968dc0547acde490b4c68d79924a93a986aa0ad060c7de706e8a99ce8f84a4f8707b52a8ee122b763ba580d6b1f35f6af25094c69f49247da96c836991851ad36f60bf577863d7471608a012afa7a56656abeee7cd9b4f1f4d9d13a8526c0f33cd251caf7486639e787250390e7e488e9ec311fc3d847a7266cc59bcc2bc34192554aa57cf25db10ce04bdabef3fde6db85f55195ecc2ff892b2e268ebea6",
+ "01789f40d42d8d3e4a416fd9ae7de78c3a30507809eda200e1afaaf8d7020cd1fad18eba62d821946f220506cf105ff0e2069a771a2c233714afa6b2f695497e4b95c9693dbb93ec4c9a14720676aa87ee31dd34e4e081756477032b4a57b328285f2cdec1b269754c474936927e93acc26012aff1bb36f30c2402aca0a9b9ce9568f5000e2c934263933b436c94f8d6589c89db7edabc5d03a8fe795fe50c5166beab64ed7c22662b984ae2c66dbe4c090b0df603b27c759278f8d66859afea3f6a8f02c2c2a2202b9fc29132256f164b5050a803b43688dc4c9ba86374a3522afba5d1a19bb3820b883aebc267627095",
+ "2c61944bd6a50da00ebb951d2b67d79fc6b6fb5aca83b1de3dbd7690ab756bb1e1a21051ccf1e24136ac8ccb42a2ee10be94d2cb9289d5f52b6f90e9d07a3478f36a1eb7d08c3dec52ca154fd1427ba92a4ecbe73a71bceafbd26e9a39d50821e2876d3a0c0e6e373b9795dbf72ea29cc439ff42706be798c90d4617b39c90ec84bf9fb699dc8a9a34e25d81759d6c57df45efb1d0d68aa51278564b99633ed5dc464bb7d53c5c21f798f33bcd868657ecfe75a1ed8149d394b398969ef624831b30f1458465bfd2fdf3f284f2ffc54bf2817b5fab2e02056e864f78bb6fd870c64f3609dab218f25da8060f756e45121e79",
+ "942fa0c68cc72f69518a3a7aac0cde45bab0e928b5cb2bd24d049fc313f74b6afa87c4e34150484f3b5200163f8a6472d04777928ecc49319539fc17d71a38090f55a74f757fe45781a3c09f08dcd3dd4c73c8533a5e00cf8a86ebe77fe45be2848574f7c5d25e9a0632a60d2dd41febdbf987d2a0487e4a4ce6ed5f49f2d741a88ecac232b1498253fa4ee8147bbd0f600abdf295e81f7570015aac5fe6ca7bb4a99bb3fc54287106d7fc1132a574af49db82a7b9a5f33e193cde527ca2176c52cdab672165e0fe5720f71ada57ee90060aa069ae2a0bfe67c1b71b17c601c3c2224bf9891bc11ba216e3ebcb51fd95b8d7cb",
+ "0d68cfe9c087ec116fe7572042385159cc705960f842aabad1ed1387ec1697f4413a23c6090041328fedd4b626c6eeaac5b5a71acc1fd1bb8fbd228857ac5bd045c364be7a5a26338ff04c99c4c473cf445a891db6422d1bdef4533442df171643fc36a092fabb464298e4194c9e2950884de13d113ee24160a416404c16ddc5d2476cb3fb80da543e6ed9105f6003977acb34e1fdd2cbdf7a00d5ff84350b74ac231418c0d88269d02d824802791ff42a51cc835deb9869a6023f867f82ef6dc0bfb03e6dfa835646bb18a4074773486e308aa39e532aaea4e6fb35dcada7e060f8282c371ed26d22302323d4fd142a85534671",
+ "45e24b167a0bbef1bd8f79dd047763d0754f36a7b623f298059d177e8ac994945c37d2c4af06f01318960301595941124592f2995af1459d854339998d3ae17534df2d9793d6e203857d02c98a0cd88991e641b3e640090ba303f87b907dca8ca462fac19ad079b2c82ea5b521ab891b10138b083b3d9fa214a8fe60d1cb3599c5d199c61a2cfb7ee2f39e5a5abad5ac4998b707545f73e92128d21803420526d2598a53bb314adf29a0ef56b94bd2221601eb53ecb8540e8fffd38fba7bd827ef255e4ef55491475c0f383a241f81c72af4e1dbf2a65cd4d18a497615aa0de2791a3511a7977a8d4d41492bfa4085f2fd4e8f751d",
+ "1c1bb695ae90e6e33fc1e8b2a62ab98bf835ac7193440f2351c8cdd830472b637d2fd9c9013cb83caef506abc1c4f7567706db6046b1d184579c7a9223ab1b35e32898c70a3c27628123ffcfa518612f080a2c4a9f8e0a927a47dc98307d2b48de9d5dddcb5c82f0b0e4e610d44f1baa9bbbf7f5a727134680bb7d1327b73b52d8e5e36dbb53971e99e699d79f75a3fc01316bd7012947d119d6aeb7f75b8fbf0479c03002148553fa0da450fd59d4f1bebc252caa11ed9bec5b6ef54279b5f8382b61cffc67ec03f4baa7ea476c31364b86aa8ccad9fd0818717f0ced2dd49477874b4341c602d7a1beab860eb476c7e3ce597e6926",
+ "7a3cd9bb2277e2c7f1134fe7233f0f7883c2db9fba80aa5742b03041de0fe589d9e5ea84470dabf41bb66816f3e33ebf19a0ca5aba1004cf971249b258ff26a98dbd0c37ec6cd574854109433357720040bafed4531e0079186b1e853e0ced35d08d27f6d732ed6e2c6651b51cc15c420a24f2dc36c16ef4b3896df1bb03b3963f9aaeb02a48eac5772abd5948c2fd0db2bb74e3351e5eabd681c4f413655bd94dec96b1544c1d5d2d1df4bdc26020d25fe81d5238de824687a5505e1fbe08d11b3924b3ccc070fd225bf01eb79e3d21f7b62a836cd3bcc11c931669c37613470e356143df87c48848a829f5e018973a5db88eb6c60203",
+ "3f158afd0733fcc5dfe1efc2dd4eada732f942af734ee664955bb1ba613eafd0f349e7554a14d68200c62d8f2dca2ec8b81c8350735eaf437041f78b452598825b6899560963ade66a0fc74ad01f8343d1d19c7bb327a8dc14ffdb1c42fa72b2970d9155e2da6a2e6419d4117842d826ff38ffab9617307a0283d3ea28c8104ad9a6e087bb750ed1d10fd8f7100b1663682e979d80e43968c33d9eff66f4d1344e583ee521e78d0a2193c0577516b978339c143bfc689bc744bbc4a9163063de82c9706384b6b385e54666c86b34f23c1e25be293af06092ca31d857e11e5b2caf0d19dd3afbe85380878eda76d718b4bb869c67e044e242",
+ "a177af4387b9bfa3d59e97ee7b0ff5f4ae4a326fd9204c8d28831a67fcc385ee6c4828247b16d11aea9bb8cd9e6c4d2876c6b2fa6d5041ad39e1b04039071e29c4d86417e7eac4fc7d3823958a021823e2c880a757dfbcd0c8196371db5bbfac15e4d1a0596508b6d26f8c4a664924c95082d173f817995b44c4285d625d9b2f56c86632fe1295c5a8a7a3760028072bcb07bc245a705e7174d06b9d5c0c8ca495b9ac218f1921fa63f2db3fd148f07545366d008fb5aead7497d902b91fbaa39669929d4ae9d07df8557f1f0aed7b51252f10c6606e5ff3ede1327530ca356b4896ecf14bf7322d77fddfbe28d52f6de7f66eeb81704c87e2",
+ "01a15b9018e35cc342c926b01d03ad9db4993a6bf92e0555969fee90033f28f3ec234c1268b11b040dfa0770d4ceb39edfeb8ee6a589f4eebcc08d2d1b0a1a52953aa26eb44fdf4a2743c3dacb212a0c0f325572f645f53027b6f3c0c55abaeb1b0918c89bedcb5028f094d743ea354f8ff553c45f111a8fd5a14a4e5c835164747d302472e19a67da04b4c8e39756a9d248ce14d1ed43de75aca86850f2455eccd4639b2af035bb3f504cc9065d091c1c47e036083cb3fc50bf39292b11737c7ce0b49673ba93981de304dc65a671775b6ff927e3ff93850b214fffb5792105a4bdc81354d5b09e84afbdd1792b8fb4e9d0ae3dad2492b03282",
+ "24f07ae31279ceed18ec6d35990f21200934ad6b132c6c62e82fe92a40a0e60a5bed10720eff5a1f728971888682772b2d9060d4fee88f37d0824e7384dddcc549475f0e1a44eda4804778b62febe46e04657a20577ee70acb3425e334881eebd8ddf714ae8c527ea747e3367de384e595a43b299b6bb3f6b0a4716cf90038e0f75a47d5057d7fcc3c8a8f9224992c67f8ae0d3251ea09a24aed9ce57ab637f6b3cbb7083df62b6287f64d0877984c4249d113bdb2b07865082aa24cd7ec07061b17de320f51f29f25b82d7073d369cf2dbf96310c0c311997911b2cc02f606f9cd99663c57e78499192a2a78f9c9fa67013e0f9817287faa69b22",
+ "4aeb32bf9d050f10bea18d9f71b4afea7bd08550e574e7d50df234c7413668b297b6721d7a0f0bdcdcceb2f55adddea28cd59bd44be0c5ec067039e428706caae11f565d961ad6e7f4c51b0aed6d05cc5b8d826c4b9c39daefb6c7da46dce619a359dc9ce215a215218fa8d54ee0b4f301b6c201c7c2c5f7cb1c6e0cb76ba6c6e8f63ef7a5213d550b0d0857fa0ff9e3e38e497161617413ac066e2fa539520233193a5cb7baa0c2cb20b45e56bfed2c40a9544d1f230dd0cd6d4976e7cf51da8a13200c3957c0154c8237b2931ce19b824963ac576ea49b548cc6aa85c47796b470fb2c6308d88f390bb13607e294c84a838b2713b14ca6a5e8bcee",
+ "77e607478be5502432230c913d9ec82f967d87c0ee169a74076f989648853eca693277287f8a5b306bc94dfdbf64ca5cb5dfc0bc498589d51a691b8d57d4b0a9ee247d038fe1b5571183be3e75c37045bf1235863ff1b84b208c10e7f1a5ba54ff36af5b2870129867164d013e0a6d2cc067a3509bba2f46390302c80b651cf590ef69aad8effd94cab28a9b44be6a38b58cfc47c9c725d6fa467894163383b6873d10d263b1cbbad932ded59ab503920267ac026726f794a335a88f6ef564f8968c6fa6f5d3ea161eb6062ca349b9a0e4038273399cfa297a6b07ceda1ebaa99c9de2d935ee230a08c5a488ad46f3393243371d40916b8063cac9da63",
+ "50957c407519951bd32e45d21129d6b83436e520b0801ec8292d79a828106a41583a0d607f853dc4410e0a1427f7e873455a75df065cfc6eef970f7e49d123b346976460aadd91cf513c140c356442a84656904a8b1d708dc6089db371c36f4fe059c62302eaab3c06c0cb3b429961f899dcf99798464b8571a440cac7a52b495f32417af6bc8f58adc63647531f804b4e96273b29b42434c1236bde80ba3744fef7b1d11c2f9db332b35bc25123338ac9a0796aac213c9709b3c514ea7ecd80e22d3d8a74f28c8194418a6e1ff30714d0f5a61c068b73b2ba6cad14e05569b4a5a100da3f91429d6e3ffee10ceea057845ec6fc47a6c5125b22e598b2dc",
+ "f2273ec31e03cf42d9ca953f8b87e78c291cb538098e0f2436194b308ce30583f553fccb21ae6c2d58f3a5a2ca6037c1b8b7afb291009e4310a0c518e75314c5bb1e813bf521f56d0a4891d0772ad84f09a00634815029a3f9ad4e41eafb4a745e409ef3d4f0b1cf6232b70a5ce262b9432f096e834201a0992db5d09ffa5cbc5471460519a4bc7cdc33ae6dfe6ffc1e80ea5d29813136406499c3514186ced71854a340701519ef33b6c82ca67049ab58578ff49c4c4fbf7d97bfec2ecd8fbefec1b6d6467503fea9d26e134e8c35739a422647aaf4db29c9a32e3df36e5845791fdd75a70903e0ce808313a3327431b7772567f779bbaee2e134c109a387",
+ "5784e614d538f7f26c803191deb464a884817002988c36448dcbecfad1997fe51ab0b3853c51ed49ce9f4e477522fb3f32cc50515b753c18fb89a8d965afcf1ed5e099b22c4225732baeb986f5c5bc88e4582d27915e2a19126d3d4555fab4f6516a6a156dbfeed9e982fc589e33ce2b9e1ba2b416e11852ddeab93025974267ac82c84f071c3d07f215f47e3565fd1d962c76e0d635892ea71488273765887d31f250a26c4ddc377ed89b17326e259f6cc1de0e63158e83aebb7f5a7c08c63c767876c8203639958a407acca096d1f606c04b4f4b3fd771781a5901b1c3cee7c04c3b6870226eee309b74f51edbf70a3817cc8da87875301e04d0416a65dc5d",
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2s/blake2x.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2s/blake2x.go
new file mode 100644
index 000000000..eaff2a7f8
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2s/blake2x.go
@@ -0,0 +1,178 @@
+// 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 blake2s
+
+import (
+ "encoding/binary"
+ "errors"
+ "io"
+)
+
+// XOF defines the interface to hash functions that
+// support arbitrary-length output.
+type XOF interface {
+ // Write absorbs more data into the hash's state. It panics if called
+ // after Read.
+ io.Writer
+
+ // Read reads more output from the hash. It returns io.EOF if the limit
+ // has been reached.
+ io.Reader
+
+ // Clone returns a copy of the XOF in its current state.
+ Clone() XOF
+
+ // Reset resets the XOF to its initial state.
+ Reset()
+}
+
+// OutputLengthUnknown can be used as the size argument to NewXOF to indicate
+// the the length of the output is not known in advance.
+const OutputLengthUnknown = 0
+
+// magicUnknownOutputLength is a magic value for the output size that indicates
+// an unknown number of output bytes.
+const magicUnknownOutputLength = 65535
+
+// maxOutputLength is the absolute maximum number of bytes to produce when the
+// number of output bytes is unknown.
+const maxOutputLength = (1 << 32) * 32
+
+// NewXOF creates a new variable-output-length hash. The hash either produce a
+// known number of bytes (1 <= size < 65535), or an unknown number of bytes
+// (size == OutputLengthUnknown). In the latter case, an absolute limit of
+// 128GiB applies.
+//
+// A non-nil key turns the hash into a MAC. The key must between
+// zero and 32 bytes long.
+func NewXOF(size uint16, key []byte) (XOF, error) {
+ if len(key) > Size {
+ return nil, errKeySize
+ }
+ if size == magicUnknownOutputLength {
+ // 2^16-1 indicates an unknown number of bytes and thus isn't a
+ // valid length.
+ return nil, errors.New("blake2s: XOF length too large")
+ }
+ if size == OutputLengthUnknown {
+ size = magicUnknownOutputLength
+ }
+ x := &xof{
+ d: digest{
+ size: Size,
+ keyLen: len(key),
+ },
+ length: size,
+ }
+ copy(x.d.key[:], key)
+ x.Reset()
+ return x, nil
+}
+
+type xof struct {
+ d digest
+ length uint16
+ remaining uint64
+ cfg, root, block [Size]byte
+ offset int
+ nodeOffset uint32
+ readMode bool
+}
+
+func (x *xof) Write(p []byte) (n int, err error) {
+ if x.readMode {
+ panic("blake2s: write to XOF after read")
+ }
+ return x.d.Write(p)
+}
+
+func (x *xof) Clone() XOF {
+ clone := *x
+ return &clone
+}
+
+func (x *xof) Reset() {
+ x.cfg[0] = byte(Size)
+ binary.LittleEndian.PutUint32(x.cfg[4:], uint32(Size)) // leaf length
+ binary.LittleEndian.PutUint16(x.cfg[12:], x.length) // XOF length
+ x.cfg[15] = byte(Size) // inner hash size
+
+ x.d.Reset()
+ x.d.h[3] ^= uint32(x.length)
+
+ x.remaining = uint64(x.length)
+ if x.remaining == magicUnknownOutputLength {
+ x.remaining = maxOutputLength
+ }
+ x.offset, x.nodeOffset = 0, 0
+ x.readMode = false
+}
+
+func (x *xof) Read(p []byte) (n int, err error) {
+ if !x.readMode {
+ x.d.finalize(&x.root)
+ x.readMode = true
+ }
+
+ if x.remaining == 0 {
+ return 0, io.EOF
+ }
+
+ n = len(p)
+ if uint64(n) > x.remaining {
+ n = int(x.remaining)
+ p = p[:n]
+ }
+
+ if x.offset > 0 {
+ blockRemaining := Size - x.offset
+ if n < blockRemaining {
+ x.offset += copy(p, x.block[x.offset:])
+ x.remaining -= uint64(n)
+ return
+ }
+ copy(p, x.block[x.offset:])
+ p = p[blockRemaining:]
+ x.offset = 0
+ x.remaining -= uint64(blockRemaining)
+ }
+
+ for len(p) >= Size {
+ binary.LittleEndian.PutUint32(x.cfg[8:], x.nodeOffset)
+ x.nodeOffset++
+
+ x.d.initConfig(&x.cfg)
+ x.d.Write(x.root[:])
+ x.d.finalize(&x.block)
+
+ copy(p, x.block[:])
+ p = p[Size:]
+ x.remaining -= uint64(Size)
+ }
+
+ if todo := len(p); todo > 0 {
+ if x.remaining < uint64(Size) {
+ x.cfg[0] = byte(x.remaining)
+ }
+ binary.LittleEndian.PutUint32(x.cfg[8:], x.nodeOffset)
+ x.nodeOffset++
+
+ x.d.initConfig(&x.cfg)
+ x.d.Write(x.root[:])
+ x.d.finalize(&x.block)
+
+ x.offset = copy(p, x.block[:todo])
+ x.remaining -= uint64(todo)
+ }
+
+ return
+}
+
+func (d *digest) initConfig(cfg *[Size]byte) {
+ d.offset, d.c[0], d.c[1] = 0, 0, 0
+ for i := range d.h {
+ d.h[i] = iv[i] ^ binary.LittleEndian.Uint32(cfg[i*4:])
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2s/register.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2s/register.go
new file mode 100644
index 000000000..d277459a1
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blake2s/register.go
@@ -0,0 +1,21 @@
+// 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.
+
+// +build go1.9
+
+package blake2s
+
+import (
+ "crypto"
+ "hash"
+)
+
+func init() {
+ newHash256 := func() hash.Hash {
+ h, _ := New256(nil)
+ return h
+ }
+
+ crypto.RegisterHash(crypto.BLAKE2s_256, newHash256)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blowfish/block.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blowfish/block.go
new file mode 100644
index 000000000..9d80f1952
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blowfish/block.go
@@ -0,0 +1,159 @@
+// Copyright 2010 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 blowfish
+
+// getNextWord returns the next big-endian uint32 value from the byte slice
+// at the given position in a circular manner, updating the position.
+func getNextWord(b []byte, pos *int) uint32 {
+ var w uint32
+ j := *pos
+ for i := 0; i < 4; i++ {
+ w = w<<8 | uint32(b[j])
+ j++
+ if j >= len(b) {
+ j = 0
+ }
+ }
+ *pos = j
+ return w
+}
+
+// ExpandKey performs a key expansion on the given *Cipher. Specifically, it
+// performs the Blowfish algorithm's key schedule which sets up the *Cipher's
+// pi and substitution tables for calls to Encrypt. This is used, primarily,
+// by the bcrypt package to reuse the Blowfish key schedule during its
+// set up. It's unlikely that you need to use this directly.
+func ExpandKey(key []byte, c *Cipher) {
+ j := 0
+ for i := 0; i < 18; i++ {
+ // Using inlined getNextWord for performance.
+ var d uint32
+ for k := 0; k < 4; k++ {
+ d = d<<8 | uint32(key[j])
+ j++
+ if j >= len(key) {
+ j = 0
+ }
+ }
+ c.p[i] ^= d
+ }
+
+ var l, r uint32
+ for i := 0; i < 18; i += 2 {
+ l, r = encryptBlock(l, r, c)
+ c.p[i], c.p[i+1] = l, r
+ }
+
+ for i := 0; i < 256; i += 2 {
+ l, r = encryptBlock(l, r, c)
+ c.s0[i], c.s0[i+1] = l, r
+ }
+ for i := 0; i < 256; i += 2 {
+ l, r = encryptBlock(l, r, c)
+ c.s1[i], c.s1[i+1] = l, r
+ }
+ for i := 0; i < 256; i += 2 {
+ l, r = encryptBlock(l, r, c)
+ c.s2[i], c.s2[i+1] = l, r
+ }
+ for i := 0; i < 256; i += 2 {
+ l, r = encryptBlock(l, r, c)
+ c.s3[i], c.s3[i+1] = l, r
+ }
+}
+
+// This is similar to ExpandKey, but folds the salt during the key
+// schedule. While ExpandKey is essentially expandKeyWithSalt with an all-zero
+// salt passed in, reusing ExpandKey turns out to be a place of inefficiency
+// and specializing it here is useful.
+func expandKeyWithSalt(key []byte, salt []byte, c *Cipher) {
+ j := 0
+ for i := 0; i < 18; i++ {
+ c.p[i] ^= getNextWord(key, &j)
+ }
+
+ j = 0
+ var l, r uint32
+ for i := 0; i < 18; i += 2 {
+ l ^= getNextWord(salt, &j)
+ r ^= getNextWord(salt, &j)
+ l, r = encryptBlock(l, r, c)
+ c.p[i], c.p[i+1] = l, r
+ }
+
+ for i := 0; i < 256; i += 2 {
+ l ^= getNextWord(salt, &j)
+ r ^= getNextWord(salt, &j)
+ l, r = encryptBlock(l, r, c)
+ c.s0[i], c.s0[i+1] = l, r
+ }
+
+ for i := 0; i < 256; i += 2 {
+ l ^= getNextWord(salt, &j)
+ r ^= getNextWord(salt, &j)
+ l, r = encryptBlock(l, r, c)
+ c.s1[i], c.s1[i+1] = l, r
+ }
+
+ for i := 0; i < 256; i += 2 {
+ l ^= getNextWord(salt, &j)
+ r ^= getNextWord(salt, &j)
+ l, r = encryptBlock(l, r, c)
+ c.s2[i], c.s2[i+1] = l, r
+ }
+
+ for i := 0; i < 256; i += 2 {
+ l ^= getNextWord(salt, &j)
+ r ^= getNextWord(salt, &j)
+ l, r = encryptBlock(l, r, c)
+ c.s3[i], c.s3[i+1] = l, r
+ }
+}
+
+func encryptBlock(l, r uint32, c *Cipher) (uint32, uint32) {
+ xl, xr := l, r
+ xl ^= c.p[0]
+ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[1]
+ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[2]
+ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[3]
+ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[4]
+ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[5]
+ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[6]
+ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[7]
+ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[8]
+ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[9]
+ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[10]
+ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[11]
+ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[12]
+ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[13]
+ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[14]
+ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[15]
+ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[16]
+ xr ^= c.p[17]
+ return xr, xl
+}
+
+func decryptBlock(l, r uint32, c *Cipher) (uint32, uint32) {
+ xl, xr := l, r
+ xl ^= c.p[17]
+ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[16]
+ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[15]
+ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[14]
+ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[13]
+ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[12]
+ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[11]
+ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[10]
+ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[9]
+ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[8]
+ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[7]
+ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[6]
+ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[5]
+ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[4]
+ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[3]
+ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[2]
+ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[1]
+ xr ^= c.p[0]
+ return xr, xl
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blowfish/blowfish_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blowfish/blowfish_test.go
new file mode 100644
index 000000000..368ba872b
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blowfish/blowfish_test.go
@@ -0,0 +1,274 @@
+// Copyright 2010 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 blowfish
+
+import "testing"
+
+type CryptTest struct {
+ key []byte
+ in []byte
+ out []byte
+}
+
+// Test vector values are from https://www.schneier.com/code/vectors.txt.
+var encryptTests = []CryptTest{
+ {
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0x4E, 0xF9, 0x97, 0x45, 0x61, 0x98, 0xDD, 0x78}},
+ {
+ []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
+ []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
+ []byte{0x51, 0x86, 0x6F, 0xD5, 0xB8, 0x5E, 0xCB, 0x8A}},
+ {
+ []byte{0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
+ []byte{0x7D, 0x85, 0x6F, 0x9A, 0x61, 0x30, 0x63, 0xF2}},
+ {
+ []byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
+ []byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
+ []byte{0x24, 0x66, 0xDD, 0x87, 0x8B, 0x96, 0x3C, 0x9D}},
+
+ {
+ []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
+ []byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
+ []byte{0x61, 0xF9, 0xC3, 0x80, 0x22, 0x81, 0xB0, 0x96}},
+ {
+ []byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
+ []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
+ []byte{0x7D, 0x0C, 0xC6, 0x30, 0xAF, 0xDA, 0x1E, 0xC7}},
+ {
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0x4E, 0xF9, 0x97, 0x45, 0x61, 0x98, 0xDD, 0x78}},
+ {
+ []byte{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10},
+ []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
+ []byte{0x0A, 0xCE, 0xAB, 0x0F, 0xC6, 0xA0, 0xA2, 0x8D}},
+ {
+ []byte{0x7C, 0xA1, 0x10, 0x45, 0x4A, 0x1A, 0x6E, 0x57},
+ []byte{0x01, 0xA1, 0xD6, 0xD0, 0x39, 0x77, 0x67, 0x42},
+ []byte{0x59, 0xC6, 0x82, 0x45, 0xEB, 0x05, 0x28, 0x2B}},
+ {
+ []byte{0x01, 0x31, 0xD9, 0x61, 0x9D, 0xC1, 0x37, 0x6E},
+ []byte{0x5C, 0xD5, 0x4C, 0xA8, 0x3D, 0xEF, 0x57, 0xDA},
+ []byte{0xB1, 0xB8, 0xCC, 0x0B, 0x25, 0x0F, 0x09, 0xA0}},
+ {
+ []byte{0x07, 0xA1, 0x13, 0x3E, 0x4A, 0x0B, 0x26, 0x86},
+ []byte{0x02, 0x48, 0xD4, 0x38, 0x06, 0xF6, 0x71, 0x72},
+ []byte{0x17, 0x30, 0xE5, 0x77, 0x8B, 0xEA, 0x1D, 0xA4}},
+ {
+ []byte{0x38, 0x49, 0x67, 0x4C, 0x26, 0x02, 0x31, 0x9E},
+ []byte{0x51, 0x45, 0x4B, 0x58, 0x2D, 0xDF, 0x44, 0x0A},
+ []byte{0xA2, 0x5E, 0x78, 0x56, 0xCF, 0x26, 0x51, 0xEB}},
+ {
+ []byte{0x04, 0xB9, 0x15, 0xBA, 0x43, 0xFE, 0xB5, 0xB6},
+ []byte{0x42, 0xFD, 0x44, 0x30, 0x59, 0x57, 0x7F, 0xA2},
+ []byte{0x35, 0x38, 0x82, 0xB1, 0x09, 0xCE, 0x8F, 0x1A}},
+ {
+ []byte{0x01, 0x13, 0xB9, 0x70, 0xFD, 0x34, 0xF2, 0xCE},
+ []byte{0x05, 0x9B, 0x5E, 0x08, 0x51, 0xCF, 0x14, 0x3A},
+ []byte{0x48, 0xF4, 0xD0, 0x88, 0x4C, 0x37, 0x99, 0x18}},
+ {
+ []byte{0x01, 0x70, 0xF1, 0x75, 0x46, 0x8F, 0xB5, 0xE6},
+ []byte{0x07, 0x56, 0xD8, 0xE0, 0x77, 0x47, 0x61, 0xD2},
+ []byte{0x43, 0x21, 0x93, 0xB7, 0x89, 0x51, 0xFC, 0x98}},
+ {
+ []byte{0x43, 0x29, 0x7F, 0xAD, 0x38, 0xE3, 0x73, 0xFE},
+ []byte{0x76, 0x25, 0x14, 0xB8, 0x29, 0xBF, 0x48, 0x6A},
+ []byte{0x13, 0xF0, 0x41, 0x54, 0xD6, 0x9D, 0x1A, 0xE5}},
+ {
+ []byte{0x07, 0xA7, 0x13, 0x70, 0x45, 0xDA, 0x2A, 0x16},
+ []byte{0x3B, 0xDD, 0x11, 0x90, 0x49, 0x37, 0x28, 0x02},
+ []byte{0x2E, 0xED, 0xDA, 0x93, 0xFF, 0xD3, 0x9C, 0x79}},
+ {
+ []byte{0x04, 0x68, 0x91, 0x04, 0xC2, 0xFD, 0x3B, 0x2F},
+ []byte{0x26, 0x95, 0x5F, 0x68, 0x35, 0xAF, 0x60, 0x9A},
+ []byte{0xD8, 0x87, 0xE0, 0x39, 0x3C, 0x2D, 0xA6, 0xE3}},
+ {
+ []byte{0x37, 0xD0, 0x6B, 0xB5, 0x16, 0xCB, 0x75, 0x46},
+ []byte{0x16, 0x4D, 0x5E, 0x40, 0x4F, 0x27, 0x52, 0x32},
+ []byte{0x5F, 0x99, 0xD0, 0x4F, 0x5B, 0x16, 0x39, 0x69}},
+ {
+ []byte{0x1F, 0x08, 0x26, 0x0D, 0x1A, 0xC2, 0x46, 0x5E},
+ []byte{0x6B, 0x05, 0x6E, 0x18, 0x75, 0x9F, 0x5C, 0xCA},
+ []byte{0x4A, 0x05, 0x7A, 0x3B, 0x24, 0xD3, 0x97, 0x7B}},
+ {
+ []byte{0x58, 0x40, 0x23, 0x64, 0x1A, 0xBA, 0x61, 0x76},
+ []byte{0x00, 0x4B, 0xD6, 0xEF, 0x09, 0x17, 0x60, 0x62},
+ []byte{0x45, 0x20, 0x31, 0xC1, 0xE4, 0xFA, 0xDA, 0x8E}},
+ {
+ []byte{0x02, 0x58, 0x16, 0x16, 0x46, 0x29, 0xB0, 0x07},
+ []byte{0x48, 0x0D, 0x39, 0x00, 0x6E, 0xE7, 0x62, 0xF2},
+ []byte{0x75, 0x55, 0xAE, 0x39, 0xF5, 0x9B, 0x87, 0xBD}},
+ {
+ []byte{0x49, 0x79, 0x3E, 0xBC, 0x79, 0xB3, 0x25, 0x8F},
+ []byte{0x43, 0x75, 0x40, 0xC8, 0x69, 0x8F, 0x3C, 0xFA},
+ []byte{0x53, 0xC5, 0x5F, 0x9C, 0xB4, 0x9F, 0xC0, 0x19}},
+ {
+ []byte{0x4F, 0xB0, 0x5E, 0x15, 0x15, 0xAB, 0x73, 0xA7},
+ []byte{0x07, 0x2D, 0x43, 0xA0, 0x77, 0x07, 0x52, 0x92},
+ []byte{0x7A, 0x8E, 0x7B, 0xFA, 0x93, 0x7E, 0x89, 0xA3}},
+ {
+ []byte{0x49, 0xE9, 0x5D, 0x6D, 0x4C, 0xA2, 0x29, 0xBF},
+ []byte{0x02, 0xFE, 0x55, 0x77, 0x81, 0x17, 0xF1, 0x2A},
+ []byte{0xCF, 0x9C, 0x5D, 0x7A, 0x49, 0x86, 0xAD, 0xB5}},
+ {
+ []byte{0x01, 0x83, 0x10, 0xDC, 0x40, 0x9B, 0x26, 0xD6},
+ []byte{0x1D, 0x9D, 0x5C, 0x50, 0x18, 0xF7, 0x28, 0xC2},
+ []byte{0xD1, 0xAB, 0xB2, 0x90, 0x65, 0x8B, 0xC7, 0x78}},
+ {
+ []byte{0x1C, 0x58, 0x7F, 0x1C, 0x13, 0x92, 0x4F, 0xEF},
+ []byte{0x30, 0x55, 0x32, 0x28, 0x6D, 0x6F, 0x29, 0x5A},
+ []byte{0x55, 0xCB, 0x37, 0x74, 0xD1, 0x3E, 0xF2, 0x01}},
+ {
+ []byte{0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+ []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
+ []byte{0xFA, 0x34, 0xEC, 0x48, 0x47, 0xB2, 0x68, 0xB2}},
+ {
+ []byte{0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E},
+ []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
+ []byte{0xA7, 0x90, 0x79, 0x51, 0x08, 0xEA, 0x3C, 0xAE}},
+ {
+ []byte{0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE},
+ []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
+ []byte{0xC3, 0x9E, 0x07, 0x2D, 0x9F, 0xAC, 0x63, 0x1D}},
+ {
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
+ []byte{0x01, 0x49, 0x33, 0xE0, 0xCD, 0xAF, 0xF6, 0xE4}},
+ {
+ []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0xF2, 0x1E, 0x9A, 0x77, 0xB7, 0x1C, 0x49, 0xBC}},
+ {
+ []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0x24, 0x59, 0x46, 0x88, 0x57, 0x54, 0x36, 0x9A}},
+ {
+ []byte{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10},
+ []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
+ []byte{0x6B, 0x5C, 0x5A, 0x9C, 0x5D, 0x9E, 0x0A, 0x5A}},
+}
+
+func TestCipherEncrypt(t *testing.T) {
+ for i, tt := range encryptTests {
+ c, err := NewCipher(tt.key)
+ if err != nil {
+ t.Errorf("NewCipher(%d bytes) = %s", len(tt.key), err)
+ continue
+ }
+ ct := make([]byte, len(tt.out))
+ c.Encrypt(ct, tt.in)
+ for j, v := range ct {
+ if v != tt.out[j] {
+ t.Errorf("Cipher.Encrypt, test vector #%d: cipher-text[%d] = %#x, expected %#x", i, j, v, tt.out[j])
+ break
+ }
+ }
+ }
+}
+
+func TestCipherDecrypt(t *testing.T) {
+ for i, tt := range encryptTests {
+ c, err := NewCipher(tt.key)
+ if err != nil {
+ t.Errorf("NewCipher(%d bytes) = %s", len(tt.key), err)
+ continue
+ }
+ pt := make([]byte, len(tt.in))
+ c.Decrypt(pt, tt.out)
+ for j, v := range pt {
+ if v != tt.in[j] {
+ t.Errorf("Cipher.Decrypt, test vector #%d: plain-text[%d] = %#x, expected %#x", i, j, v, tt.in[j])
+ break
+ }
+ }
+ }
+}
+
+func TestSaltedCipherKeyLength(t *testing.T) {
+ if _, err := NewSaltedCipher(nil, []byte{'a'}); err != KeySizeError(0) {
+ t.Errorf("NewSaltedCipher with short key, gave error %#v, expected %#v", err, KeySizeError(0))
+ }
+
+ // A 57-byte key. One over the typical blowfish restriction.
+ key := []byte("012345678901234567890123456789012345678901234567890123456")
+ if _, err := NewSaltedCipher(key, []byte{'a'}); err != nil {
+ t.Errorf("NewSaltedCipher with long key, gave error %#v", err)
+ }
+}
+
+// Test vectors generated with Blowfish from OpenSSH.
+var saltedVectors = [][8]byte{
+ {0x0c, 0x82, 0x3b, 0x7b, 0x8d, 0x01, 0x4b, 0x7e},
+ {0xd1, 0xe1, 0x93, 0xf0, 0x70, 0xa6, 0xdb, 0x12},
+ {0xfc, 0x5e, 0xba, 0xde, 0xcb, 0xf8, 0x59, 0xad},
+ {0x8a, 0x0c, 0x76, 0xe7, 0xdd, 0x2c, 0xd3, 0xa8},
+ {0x2c, 0xcb, 0x7b, 0xee, 0xac, 0x7b, 0x7f, 0xf8},
+ {0xbb, 0xf6, 0x30, 0x6f, 0xe1, 0x5d, 0x62, 0xbf},
+ {0x97, 0x1e, 0xc1, 0x3d, 0x3d, 0xe0, 0x11, 0xe9},
+ {0x06, 0xd7, 0x4d, 0xb1, 0x80, 0xa3, 0xb1, 0x38},
+ {0x67, 0xa1, 0xa9, 0x75, 0x0e, 0x5b, 0xc6, 0xb4},
+ {0x51, 0x0f, 0x33, 0x0e, 0x4f, 0x67, 0xd2, 0x0c},
+ {0xf1, 0x73, 0x7e, 0xd8, 0x44, 0xea, 0xdb, 0xe5},
+ {0x14, 0x0e, 0x16, 0xce, 0x7f, 0x4a, 0x9c, 0x7b},
+ {0x4b, 0xfe, 0x43, 0xfd, 0xbf, 0x36, 0x04, 0x47},
+ {0xb1, 0xeb, 0x3e, 0x15, 0x36, 0xa7, 0xbb, 0xe2},
+ {0x6d, 0x0b, 0x41, 0xdd, 0x00, 0x98, 0x0b, 0x19},
+ {0xd3, 0xce, 0x45, 0xce, 0x1d, 0x56, 0xb7, 0xfc},
+ {0xd9, 0xf0, 0xfd, 0xda, 0xc0, 0x23, 0xb7, 0x93},
+ {0x4c, 0x6f, 0xa1, 0xe4, 0x0c, 0xa8, 0xca, 0x57},
+ {0xe6, 0x2f, 0x28, 0xa7, 0x0c, 0x94, 0x0d, 0x08},
+ {0x8f, 0xe3, 0xf0, 0xb6, 0x29, 0xe3, 0x44, 0x03},
+ {0xff, 0x98, 0xdd, 0x04, 0x45, 0xb4, 0x6d, 0x1f},
+ {0x9e, 0x45, 0x4d, 0x18, 0x40, 0x53, 0xdb, 0xef},
+ {0xb7, 0x3b, 0xef, 0x29, 0xbe, 0xa8, 0x13, 0x71},
+ {0x02, 0x54, 0x55, 0x41, 0x8e, 0x04, 0xfc, 0xad},
+ {0x6a, 0x0a, 0xee, 0x7c, 0x10, 0xd9, 0x19, 0xfe},
+ {0x0a, 0x22, 0xd9, 0x41, 0xcc, 0x23, 0x87, 0x13},
+ {0x6e, 0xff, 0x1f, 0xff, 0x36, 0x17, 0x9c, 0xbe},
+ {0x79, 0xad, 0xb7, 0x40, 0xf4, 0x9f, 0x51, 0xa6},
+ {0x97, 0x81, 0x99, 0xa4, 0xde, 0x9e, 0x9f, 0xb6},
+ {0x12, 0x19, 0x7a, 0x28, 0xd0, 0xdc, 0xcc, 0x92},
+ {0x81, 0xda, 0x60, 0x1e, 0x0e, 0xdd, 0x65, 0x56},
+ {0x7d, 0x76, 0x20, 0xb2, 0x73, 0xc9, 0x9e, 0xee},
+}
+
+func TestSaltedCipher(t *testing.T) {
+ var key, salt [32]byte
+ for i := range key {
+ key[i] = byte(i)
+ salt[i] = byte(i + 32)
+ }
+ for i, v := range saltedVectors {
+ c, err := NewSaltedCipher(key[:], salt[:i])
+ if err != nil {
+ t.Fatal(err)
+ }
+ var buf [8]byte
+ c.Encrypt(buf[:], buf[:])
+ if v != buf {
+ t.Errorf("%d: expected %x, got %x", i, v, buf)
+ }
+ }
+}
+
+func BenchmarkExpandKeyWithSalt(b *testing.B) {
+ key := make([]byte, 32)
+ salt := make([]byte, 16)
+ c, _ := NewCipher(key)
+ for i := 0; i < b.N; i++ {
+ expandKeyWithSalt(key, salt, c)
+ }
+}
+
+func BenchmarkExpandKey(b *testing.B) {
+ key := make([]byte, 32)
+ c, _ := NewCipher(key)
+ for i := 0; i < b.N; i++ {
+ ExpandKey(key, c)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blowfish/cipher.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blowfish/cipher.go
new file mode 100644
index 000000000..2641dadd6
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blowfish/cipher.go
@@ -0,0 +1,91 @@
+// Copyright 2010 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 blowfish implements Bruce Schneier's Blowfish encryption algorithm.
+package blowfish // import "golang.org/x/crypto/blowfish"
+
+// The code is a port of Bruce Schneier's C implementation.
+// See https://www.schneier.com/blowfish.html.
+
+import "strconv"
+
+// The Blowfish block size in bytes.
+const BlockSize = 8
+
+// A Cipher is an instance of Blowfish encryption using a particular key.
+type Cipher struct {
+ p [18]uint32
+ s0, s1, s2, s3 [256]uint32
+}
+
+type KeySizeError int
+
+func (k KeySizeError) Error() string {
+ return "crypto/blowfish: invalid key size " + strconv.Itoa(int(k))
+}
+
+// NewCipher creates and returns a Cipher.
+// The key argument should be the Blowfish key, from 1 to 56 bytes.
+func NewCipher(key []byte) (*Cipher, error) {
+ var result Cipher
+ if k := len(key); k < 1 || k > 56 {
+ return nil, KeySizeError(k)
+ }
+ initCipher(&result)
+ ExpandKey(key, &result)
+ return &result, nil
+}
+
+// NewSaltedCipher creates a returns a Cipher that folds a salt into its key
+// schedule. For most purposes, NewCipher, instead of NewSaltedCipher, is
+// sufficient and desirable. For bcrypt compatibility, the key can be over 56
+// bytes.
+func NewSaltedCipher(key, salt []byte) (*Cipher, error) {
+ if len(salt) == 0 {
+ return NewCipher(key)
+ }
+ var result Cipher
+ if k := len(key); k < 1 {
+ return nil, KeySizeError(k)
+ }
+ initCipher(&result)
+ expandKeyWithSalt(key, salt, &result)
+ return &result, nil
+}
+
+// BlockSize returns the Blowfish block size, 8 bytes.
+// It is necessary to satisfy the Block interface in the
+// package "crypto/cipher".
+func (c *Cipher) BlockSize() int { return BlockSize }
+
+// Encrypt encrypts the 8-byte buffer src using the key k
+// and stores the result in dst.
+// Note that for amounts of data larger than a block,
+// it is not safe to just call Encrypt on successive blocks;
+// instead, use an encryption mode like CBC (see crypto/cipher/cbc.go).
+func (c *Cipher) Encrypt(dst, src []byte) {
+ l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
+ r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
+ l, r = encryptBlock(l, r, c)
+ dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l)
+ dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r)
+}
+
+// Decrypt decrypts the 8-byte buffer src using the key k
+// and stores the result in dst.
+func (c *Cipher) Decrypt(dst, src []byte) {
+ l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
+ r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
+ l, r = decryptBlock(l, r, c)
+ dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l)
+ dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r)
+}
+
+func initCipher(c *Cipher) {
+ copy(c.p[0:], p[0:])
+ copy(c.s0[0:], s0[0:])
+ copy(c.s1[0:], s1[0:])
+ copy(c.s2[0:], s2[0:])
+ copy(c.s3[0:], s3[0:])
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blowfish/const.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blowfish/const.go
new file mode 100644
index 000000000..d04077595
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/blowfish/const.go
@@ -0,0 +1,199 @@
+// Copyright 2010 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.
+
+// The startup permutation array and substitution boxes.
+// They are the hexadecimal digits of PI; see:
+// https://www.schneier.com/code/constants.txt.
+
+package blowfish
+
+var s0 = [256]uint32{
+ 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96,
+ 0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
+ 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658,
+ 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
+ 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e,
+ 0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
+ 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6,
+ 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
+ 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c,
+ 0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
+ 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1,
+ 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
+ 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a,
+ 0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
+ 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176,
+ 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
+ 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706,
+ 0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
+ 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b,
+ 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
+ 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c,
+ 0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
+ 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a,
+ 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
+ 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760,
+ 0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
+ 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8,
+ 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
+ 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33,
+ 0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
+ 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0,
+ 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
+ 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777,
+ 0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
+ 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705,
+ 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
+ 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e,
+ 0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
+ 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9,
+ 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
+ 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f,
+ 0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
+ 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a,
+}
+
+var s1 = [256]uint32{
+ 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d,
+ 0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
+ 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65,
+ 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
+ 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9,
+ 0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
+ 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d,
+ 0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
+ 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc,
+ 0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
+ 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908,
+ 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
+ 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124,
+ 0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
+ 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908,
+ 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
+ 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b,
+ 0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
+ 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa,
+ 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
+ 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d,
+ 0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
+ 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5,
+ 0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
+ 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96,
+ 0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
+ 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca,
+ 0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
+ 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77,
+ 0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
+ 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054,
+ 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
+ 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea,
+ 0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
+ 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646,
+ 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
+ 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea,
+ 0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
+ 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e,
+ 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
+ 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd,
+ 0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
+ 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7,
+}
+
+var s2 = [256]uint32{
+ 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7,
+ 0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
+ 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af,
+ 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
+ 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4,
+ 0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
+ 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec,
+ 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
+ 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332,
+ 0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
+ 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58,
+ 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
+ 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22,
+ 0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
+ 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60,
+ 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
+ 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99,
+ 0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
+ 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74,
+ 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
+ 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3,
+ 0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
+ 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979,
+ 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
+ 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa,
+ 0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
+ 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086,
+ 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
+ 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24,
+ 0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
+ 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84,
+ 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
+ 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09,
+ 0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
+ 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe,
+ 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
+ 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0,
+ 0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
+ 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188,
+ 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
+ 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8,
+ 0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
+ 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0,
+}
+
+var s3 = [256]uint32{
+ 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742,
+ 0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
+ 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79,
+ 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
+ 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a,
+ 0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
+ 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1,
+ 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
+ 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797,
+ 0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
+ 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6,
+ 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
+ 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba,
+ 0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
+ 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5,
+ 0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
+ 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce,
+ 0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
+ 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd,
+ 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
+ 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb,
+ 0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
+ 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc,
+ 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
+ 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc,
+ 0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
+ 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a,
+ 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
+ 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a,
+ 0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
+ 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b,
+ 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
+ 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e,
+ 0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
+ 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623,
+ 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
+ 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a,
+ 0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
+ 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3,
+ 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
+ 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c,
+ 0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
+ 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6,
+}
+
+var p = [18]uint32{
+ 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0,
+ 0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
+ 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b,
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bn256/bn256.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bn256/bn256.go
new file mode 100644
index 000000000..014f8b355
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bn256/bn256.go
@@ -0,0 +1,404 @@
+// Copyright 2012 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 bn256 implements a particular bilinear group at the 128-bit security level.
+//
+// Bilinear groups are the basis of many of the new cryptographic protocols
+// that have been proposed over the past decade. They consist of a triplet of
+// groups (G₁, G₂ and GT) such that there exists a function e(g₁ˣ,g₂ʸ)=gTˣʸ
+// (where gₓ is a generator of the respective group). That function is called
+// a pairing function.
+//
+// This package specifically implements the Optimal Ate pairing over a 256-bit
+// Barreto-Naehrig curve as described in
+// http://cryptojedi.org/papers/dclxvi-20100714.pdf. Its output is compatible
+// with the implementation described in that paper.
+package bn256 // import "golang.org/x/crypto/bn256"
+
+import (
+ "crypto/rand"
+ "io"
+ "math/big"
+)
+
+// BUG(agl): this implementation is not constant time.
+// TODO(agl): keep GF(p²) elements in Mongomery form.
+
+// G1 is an abstract cyclic group. The zero value is suitable for use as the
+// output of an operation, but cannot be used as an input.
+type G1 struct {
+ p *curvePoint
+}
+
+// RandomG1 returns x and g₁ˣ where x is a random, non-zero number read from r.
+func RandomG1(r io.Reader) (*big.Int, *G1, error) {
+ var k *big.Int
+ var err error
+
+ for {
+ k, err = rand.Int(r, Order)
+ if err != nil {
+ return nil, nil, err
+ }
+ if k.Sign() > 0 {
+ break
+ }
+ }
+
+ return k, new(G1).ScalarBaseMult(k), nil
+}
+
+func (g *G1) String() string {
+ return "bn256.G1" + g.p.String()
+}
+
+// ScalarBaseMult sets e to g*k where g is the generator of the group and
+// then returns e.
+func (e *G1) ScalarBaseMult(k *big.Int) *G1 {
+ if e.p == nil {
+ e.p = newCurvePoint(nil)
+ }
+ e.p.Mul(curveGen, k, new(bnPool))
+ return e
+}
+
+// ScalarMult sets e to a*k and then returns e.
+func (e *G1) ScalarMult(a *G1, k *big.Int) *G1 {
+ if e.p == nil {
+ e.p = newCurvePoint(nil)
+ }
+ e.p.Mul(a.p, k, new(bnPool))
+ return e
+}
+
+// Add sets e to a+b and then returns e.
+// BUG(agl): this function is not complete: a==b fails.
+func (e *G1) Add(a, b *G1) *G1 {
+ if e.p == nil {
+ e.p = newCurvePoint(nil)
+ }
+ e.p.Add(a.p, b.p, new(bnPool))
+ return e
+}
+
+// Neg sets e to -a and then returns e.
+func (e *G1) Neg(a *G1) *G1 {
+ if e.p == nil {
+ e.p = newCurvePoint(nil)
+ }
+ e.p.Negative(a.p)
+ return e
+}
+
+// Marshal converts n to a byte slice.
+func (n *G1) Marshal() []byte {
+ n.p.MakeAffine(nil)
+
+ xBytes := new(big.Int).Mod(n.p.x, p).Bytes()
+ yBytes := new(big.Int).Mod(n.p.y, p).Bytes()
+
+ // Each value is a 256-bit number.
+ const numBytes = 256 / 8
+
+ ret := make([]byte, numBytes*2)
+ copy(ret[1*numBytes-len(xBytes):], xBytes)
+ copy(ret[2*numBytes-len(yBytes):], yBytes)
+
+ return ret
+}
+
+// Unmarshal sets e to the result of converting the output of Marshal back into
+// a group element and then returns e.
+func (e *G1) Unmarshal(m []byte) (*G1, bool) {
+ // Each value is a 256-bit number.
+ const numBytes = 256 / 8
+
+ if len(m) != 2*numBytes {
+ return nil, false
+ }
+
+ if e.p == nil {
+ e.p = newCurvePoint(nil)
+ }
+
+ e.p.x.SetBytes(m[0*numBytes : 1*numBytes])
+ e.p.y.SetBytes(m[1*numBytes : 2*numBytes])
+
+ if e.p.x.Sign() == 0 && e.p.y.Sign() == 0 {
+ // This is the point at infinity.
+ e.p.y.SetInt64(1)
+ e.p.z.SetInt64(0)
+ e.p.t.SetInt64(0)
+ } else {
+ e.p.z.SetInt64(1)
+ e.p.t.SetInt64(1)
+
+ if !e.p.IsOnCurve() {
+ return nil, false
+ }
+ }
+
+ return e, true
+}
+
+// G2 is an abstract cyclic group. The zero value is suitable for use as the
+// output of an operation, but cannot be used as an input.
+type G2 struct {
+ p *twistPoint
+}
+
+// RandomG1 returns x and g₂ˣ where x is a random, non-zero number read from r.
+func RandomG2(r io.Reader) (*big.Int, *G2, error) {
+ var k *big.Int
+ var err error
+
+ for {
+ k, err = rand.Int(r, Order)
+ if err != nil {
+ return nil, nil, err
+ }
+ if k.Sign() > 0 {
+ break
+ }
+ }
+
+ return k, new(G2).ScalarBaseMult(k), nil
+}
+
+func (g *G2) String() string {
+ return "bn256.G2" + g.p.String()
+}
+
+// ScalarBaseMult sets e to g*k where g is the generator of the group and
+// then returns out.
+func (e *G2) ScalarBaseMult(k *big.Int) *G2 {
+ if e.p == nil {
+ e.p = newTwistPoint(nil)
+ }
+ e.p.Mul(twistGen, k, new(bnPool))
+ return e
+}
+
+// ScalarMult sets e to a*k and then returns e.
+func (e *G2) ScalarMult(a *G2, k *big.Int) *G2 {
+ if e.p == nil {
+ e.p = newTwistPoint(nil)
+ }
+ e.p.Mul(a.p, k, new(bnPool))
+ return e
+}
+
+// Add sets e to a+b and then returns e.
+// BUG(agl): this function is not complete: a==b fails.
+func (e *G2) Add(a, b *G2) *G2 {
+ if e.p == nil {
+ e.p = newTwistPoint(nil)
+ }
+ e.p.Add(a.p, b.p, new(bnPool))
+ return e
+}
+
+// Marshal converts n into a byte slice.
+func (n *G2) Marshal() []byte {
+ n.p.MakeAffine(nil)
+
+ xxBytes := new(big.Int).Mod(n.p.x.x, p).Bytes()
+ xyBytes := new(big.Int).Mod(n.p.x.y, p).Bytes()
+ yxBytes := new(big.Int).Mod(n.p.y.x, p).Bytes()
+ yyBytes := new(big.Int).Mod(n.p.y.y, p).Bytes()
+
+ // Each value is a 256-bit number.
+ const numBytes = 256 / 8
+
+ ret := make([]byte, numBytes*4)
+ copy(ret[1*numBytes-len(xxBytes):], xxBytes)
+ copy(ret[2*numBytes-len(xyBytes):], xyBytes)
+ copy(ret[3*numBytes-len(yxBytes):], yxBytes)
+ copy(ret[4*numBytes-len(yyBytes):], yyBytes)
+
+ return ret
+}
+
+// Unmarshal sets e to the result of converting the output of Marshal back into
+// a group element and then returns e.
+func (e *G2) Unmarshal(m []byte) (*G2, bool) {
+ // Each value is a 256-bit number.
+ const numBytes = 256 / 8
+
+ if len(m) != 4*numBytes {
+ return nil, false
+ }
+
+ if e.p == nil {
+ e.p = newTwistPoint(nil)
+ }
+
+ e.p.x.x.SetBytes(m[0*numBytes : 1*numBytes])
+ e.p.x.y.SetBytes(m[1*numBytes : 2*numBytes])
+ e.p.y.x.SetBytes(m[2*numBytes : 3*numBytes])
+ e.p.y.y.SetBytes(m[3*numBytes : 4*numBytes])
+
+ if e.p.x.x.Sign() == 0 &&
+ e.p.x.y.Sign() == 0 &&
+ e.p.y.x.Sign() == 0 &&
+ e.p.y.y.Sign() == 0 {
+ // This is the point at infinity.
+ e.p.y.SetOne()
+ e.p.z.SetZero()
+ e.p.t.SetZero()
+ } else {
+ e.p.z.SetOne()
+ e.p.t.SetOne()
+
+ if !e.p.IsOnCurve() {
+ return nil, false
+ }
+ }
+
+ return e, true
+}
+
+// GT is an abstract cyclic group. The zero value is suitable for use as the
+// output of an operation, but cannot be used as an input.
+type GT struct {
+ p *gfP12
+}
+
+func (g *GT) String() string {
+ return "bn256.GT" + g.p.String()
+}
+
+// ScalarMult sets e to a*k and then returns e.
+func (e *GT) ScalarMult(a *GT, k *big.Int) *GT {
+ if e.p == nil {
+ e.p = newGFp12(nil)
+ }
+ e.p.Exp(a.p, k, new(bnPool))
+ return e
+}
+
+// Add sets e to a+b and then returns e.
+func (e *GT) Add(a, b *GT) *GT {
+ if e.p == nil {
+ e.p = newGFp12(nil)
+ }
+ e.p.Mul(a.p, b.p, new(bnPool))
+ return e
+}
+
+// Neg sets e to -a and then returns e.
+func (e *GT) Neg(a *GT) *GT {
+ if e.p == nil {
+ e.p = newGFp12(nil)
+ }
+ e.p.Invert(a.p, new(bnPool))
+ return e
+}
+
+// Marshal converts n into a byte slice.
+func (n *GT) Marshal() []byte {
+ n.p.Minimal()
+
+ xxxBytes := n.p.x.x.x.Bytes()
+ xxyBytes := n.p.x.x.y.Bytes()
+ xyxBytes := n.p.x.y.x.Bytes()
+ xyyBytes := n.p.x.y.y.Bytes()
+ xzxBytes := n.p.x.z.x.Bytes()
+ xzyBytes := n.p.x.z.y.Bytes()
+ yxxBytes := n.p.y.x.x.Bytes()
+ yxyBytes := n.p.y.x.y.Bytes()
+ yyxBytes := n.p.y.y.x.Bytes()
+ yyyBytes := n.p.y.y.y.Bytes()
+ yzxBytes := n.p.y.z.x.Bytes()
+ yzyBytes := n.p.y.z.y.Bytes()
+
+ // Each value is a 256-bit number.
+ const numBytes = 256 / 8
+
+ ret := make([]byte, numBytes*12)
+ copy(ret[1*numBytes-len(xxxBytes):], xxxBytes)
+ copy(ret[2*numBytes-len(xxyBytes):], xxyBytes)
+ copy(ret[3*numBytes-len(xyxBytes):], xyxBytes)
+ copy(ret[4*numBytes-len(xyyBytes):], xyyBytes)
+ copy(ret[5*numBytes-len(xzxBytes):], xzxBytes)
+ copy(ret[6*numBytes-len(xzyBytes):], xzyBytes)
+ copy(ret[7*numBytes-len(yxxBytes):], yxxBytes)
+ copy(ret[8*numBytes-len(yxyBytes):], yxyBytes)
+ copy(ret[9*numBytes-len(yyxBytes):], yyxBytes)
+ copy(ret[10*numBytes-len(yyyBytes):], yyyBytes)
+ copy(ret[11*numBytes-len(yzxBytes):], yzxBytes)
+ copy(ret[12*numBytes-len(yzyBytes):], yzyBytes)
+
+ return ret
+}
+
+// Unmarshal sets e to the result of converting the output of Marshal back into
+// a group element and then returns e.
+func (e *GT) Unmarshal(m []byte) (*GT, bool) {
+ // Each value is a 256-bit number.
+ const numBytes = 256 / 8
+
+ if len(m) != 12*numBytes {
+ return nil, false
+ }
+
+ if e.p == nil {
+ e.p = newGFp12(nil)
+ }
+
+ e.p.x.x.x.SetBytes(m[0*numBytes : 1*numBytes])
+ e.p.x.x.y.SetBytes(m[1*numBytes : 2*numBytes])
+ e.p.x.y.x.SetBytes(m[2*numBytes : 3*numBytes])
+ e.p.x.y.y.SetBytes(m[3*numBytes : 4*numBytes])
+ e.p.x.z.x.SetBytes(m[4*numBytes : 5*numBytes])
+ e.p.x.z.y.SetBytes(m[5*numBytes : 6*numBytes])
+ e.p.y.x.x.SetBytes(m[6*numBytes : 7*numBytes])
+ e.p.y.x.y.SetBytes(m[7*numBytes : 8*numBytes])
+ e.p.y.y.x.SetBytes(m[8*numBytes : 9*numBytes])
+ e.p.y.y.y.SetBytes(m[9*numBytes : 10*numBytes])
+ e.p.y.z.x.SetBytes(m[10*numBytes : 11*numBytes])
+ e.p.y.z.y.SetBytes(m[11*numBytes : 12*numBytes])
+
+ return e, true
+}
+
+// Pair calculates an Optimal Ate pairing.
+func Pair(g1 *G1, g2 *G2) *GT {
+ return &GT{optimalAte(g2.p, g1.p, new(bnPool))}
+}
+
+// bnPool implements a tiny cache of *big.Int objects that's used to reduce the
+// number of allocations made during processing.
+type bnPool struct {
+ bns []*big.Int
+ count int
+}
+
+func (pool *bnPool) Get() *big.Int {
+ if pool == nil {
+ return new(big.Int)
+ }
+
+ pool.count++
+ l := len(pool.bns)
+ if l == 0 {
+ return new(big.Int)
+ }
+
+ bn := pool.bns[l-1]
+ pool.bns = pool.bns[:l-1]
+ return bn
+}
+
+func (pool *bnPool) Put(bn *big.Int) {
+ if pool == nil {
+ return
+ }
+ pool.bns = append(pool.bns, bn)
+ pool.count--
+}
+
+func (pool *bnPool) Count() int {
+ return pool.count
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bn256/bn256_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bn256/bn256_test.go
new file mode 100644
index 000000000..1cec3884e
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bn256/bn256_test.go
@@ -0,0 +1,304 @@
+// Copyright 2012 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 bn256
+
+import (
+ "bytes"
+ "crypto/rand"
+ "math/big"
+ "testing"
+)
+
+func TestGFp2Invert(t *testing.T) {
+ pool := new(bnPool)
+
+ a := newGFp2(pool)
+ a.x.SetString("23423492374", 10)
+ a.y.SetString("12934872398472394827398470", 10)
+
+ inv := newGFp2(pool)
+ inv.Invert(a, pool)
+
+ b := newGFp2(pool).Mul(inv, a, pool)
+ if b.x.Int64() != 0 || b.y.Int64() != 1 {
+ t.Fatalf("bad result for a^-1*a: %s %s", b.x, b.y)
+ }
+
+ a.Put(pool)
+ b.Put(pool)
+ inv.Put(pool)
+
+ if c := pool.Count(); c > 0 {
+ t.Errorf("Pool count non-zero: %d\n", c)
+ }
+}
+
+func isZero(n *big.Int) bool {
+ return new(big.Int).Mod(n, p).Int64() == 0
+}
+
+func isOne(n *big.Int) bool {
+ return new(big.Int).Mod(n, p).Int64() == 1
+}
+
+func TestGFp6Invert(t *testing.T) {
+ pool := new(bnPool)
+
+ a := newGFp6(pool)
+ a.x.x.SetString("239487238491", 10)
+ a.x.y.SetString("2356249827341", 10)
+ a.y.x.SetString("082659782", 10)
+ a.y.y.SetString("182703523765", 10)
+ a.z.x.SetString("978236549263", 10)
+ a.z.y.SetString("64893242", 10)
+
+ inv := newGFp6(pool)
+ inv.Invert(a, pool)
+
+ b := newGFp6(pool).Mul(inv, a, pool)
+ if !isZero(b.x.x) ||
+ !isZero(b.x.y) ||
+ !isZero(b.y.x) ||
+ !isZero(b.y.y) ||
+ !isZero(b.z.x) ||
+ !isOne(b.z.y) {
+ t.Fatalf("bad result for a^-1*a: %s", b)
+ }
+
+ a.Put(pool)
+ b.Put(pool)
+ inv.Put(pool)
+
+ if c := pool.Count(); c > 0 {
+ t.Errorf("Pool count non-zero: %d\n", c)
+ }
+}
+
+func TestGFp12Invert(t *testing.T) {
+ pool := new(bnPool)
+
+ a := newGFp12(pool)
+ a.x.x.x.SetString("239846234862342323958623", 10)
+ a.x.x.y.SetString("2359862352529835623", 10)
+ a.x.y.x.SetString("928836523", 10)
+ a.x.y.y.SetString("9856234", 10)
+ a.x.z.x.SetString("235635286", 10)
+ a.x.z.y.SetString("5628392833", 10)
+ a.y.x.x.SetString("252936598265329856238956532167968", 10)
+ a.y.x.y.SetString("23596239865236954178968", 10)
+ a.y.y.x.SetString("95421692834", 10)
+ a.y.y.y.SetString("236548", 10)
+ a.y.z.x.SetString("924523", 10)
+ a.y.z.y.SetString("12954623", 10)
+
+ inv := newGFp12(pool)
+ inv.Invert(a, pool)
+
+ b := newGFp12(pool).Mul(inv, a, pool)
+ if !isZero(b.x.x.x) ||
+ !isZero(b.x.x.y) ||
+ !isZero(b.x.y.x) ||
+ !isZero(b.x.y.y) ||
+ !isZero(b.x.z.x) ||
+ !isZero(b.x.z.y) ||
+ !isZero(b.y.x.x) ||
+ !isZero(b.y.x.y) ||
+ !isZero(b.y.y.x) ||
+ !isZero(b.y.y.y) ||
+ !isZero(b.y.z.x) ||
+ !isOne(b.y.z.y) {
+ t.Fatalf("bad result for a^-1*a: %s", b)
+ }
+
+ a.Put(pool)
+ b.Put(pool)
+ inv.Put(pool)
+
+ if c := pool.Count(); c > 0 {
+ t.Errorf("Pool count non-zero: %d\n", c)
+ }
+}
+
+func TestCurveImpl(t *testing.T) {
+ pool := new(bnPool)
+
+ g := &curvePoint{
+ pool.Get().SetInt64(1),
+ pool.Get().SetInt64(-2),
+ pool.Get().SetInt64(1),
+ pool.Get().SetInt64(0),
+ }
+
+ x := pool.Get().SetInt64(32498273234)
+ X := newCurvePoint(pool).Mul(g, x, pool)
+
+ y := pool.Get().SetInt64(98732423523)
+ Y := newCurvePoint(pool).Mul(g, y, pool)
+
+ s1 := newCurvePoint(pool).Mul(X, y, pool).MakeAffine(pool)
+ s2 := newCurvePoint(pool).Mul(Y, x, pool).MakeAffine(pool)
+
+ if s1.x.Cmp(s2.x) != 0 ||
+ s2.x.Cmp(s1.x) != 0 {
+ t.Errorf("DH points don't match: (%s, %s) (%s, %s)", s1.x, s1.y, s2.x, s2.y)
+ }
+
+ pool.Put(x)
+ X.Put(pool)
+ pool.Put(y)
+ Y.Put(pool)
+ s1.Put(pool)
+ s2.Put(pool)
+ g.Put(pool)
+
+ if c := pool.Count(); c > 0 {
+ t.Errorf("Pool count non-zero: %d\n", c)
+ }
+}
+
+func TestOrderG1(t *testing.T) {
+ g := new(G1).ScalarBaseMult(Order)
+ if !g.p.IsInfinity() {
+ t.Error("G1 has incorrect order")
+ }
+
+ one := new(G1).ScalarBaseMult(new(big.Int).SetInt64(1))
+ g.Add(g, one)
+ g.p.MakeAffine(nil)
+ if g.p.x.Cmp(one.p.x) != 0 || g.p.y.Cmp(one.p.y) != 0 {
+ t.Errorf("1+0 != 1 in G1")
+ }
+}
+
+func TestOrderG2(t *testing.T) {
+ g := new(G2).ScalarBaseMult(Order)
+ if !g.p.IsInfinity() {
+ t.Error("G2 has incorrect order")
+ }
+
+ one := new(G2).ScalarBaseMult(new(big.Int).SetInt64(1))
+ g.Add(g, one)
+ g.p.MakeAffine(nil)
+ if g.p.x.x.Cmp(one.p.x.x) != 0 ||
+ g.p.x.y.Cmp(one.p.x.y) != 0 ||
+ g.p.y.x.Cmp(one.p.y.x) != 0 ||
+ g.p.y.y.Cmp(one.p.y.y) != 0 {
+ t.Errorf("1+0 != 1 in G2")
+ }
+}
+
+func TestOrderGT(t *testing.T) {
+ gt := Pair(&G1{curveGen}, &G2{twistGen})
+ g := new(GT).ScalarMult(gt, Order)
+ if !g.p.IsOne() {
+ t.Error("GT has incorrect order")
+ }
+}
+
+func TestBilinearity(t *testing.T) {
+ for i := 0; i < 2; i++ {
+ a, p1, _ := RandomG1(rand.Reader)
+ b, p2, _ := RandomG2(rand.Reader)
+ e1 := Pair(p1, p2)
+
+ e2 := Pair(&G1{curveGen}, &G2{twistGen})
+ e2.ScalarMult(e2, a)
+ e2.ScalarMult(e2, b)
+
+ minusE2 := new(GT).Neg(e2)
+ e1.Add(e1, minusE2)
+
+ if !e1.p.IsOne() {
+ t.Fatalf("bad pairing result: %s", e1)
+ }
+ }
+}
+
+func TestG1Marshal(t *testing.T) {
+ g := new(G1).ScalarBaseMult(new(big.Int).SetInt64(1))
+ form := g.Marshal()
+ _, ok := new(G1).Unmarshal(form)
+ if !ok {
+ t.Fatalf("failed to unmarshal")
+ }
+
+ g.ScalarBaseMult(Order)
+ form = g.Marshal()
+ g2, ok := new(G1).Unmarshal(form)
+ if !ok {
+ t.Fatalf("failed to unmarshal ∞")
+ }
+ if !g2.p.IsInfinity() {
+ t.Fatalf("∞ unmarshaled incorrectly")
+ }
+}
+
+func TestG2Marshal(t *testing.T) {
+ g := new(G2).ScalarBaseMult(new(big.Int).SetInt64(1))
+ form := g.Marshal()
+ _, ok := new(G2).Unmarshal(form)
+ if !ok {
+ t.Fatalf("failed to unmarshal")
+ }
+
+ g.ScalarBaseMult(Order)
+ form = g.Marshal()
+ g2, ok := new(G2).Unmarshal(form)
+ if !ok {
+ t.Fatalf("failed to unmarshal ∞")
+ }
+ if !g2.p.IsInfinity() {
+ t.Fatalf("∞ unmarshaled incorrectly")
+ }
+}
+
+func TestG1Identity(t *testing.T) {
+ g := new(G1).ScalarBaseMult(new(big.Int).SetInt64(0))
+ if !g.p.IsInfinity() {
+ t.Error("failure")
+ }
+}
+
+func TestG2Identity(t *testing.T) {
+ g := new(G2).ScalarBaseMult(new(big.Int).SetInt64(0))
+ if !g.p.IsInfinity() {
+ t.Error("failure")
+ }
+}
+
+func TestTripartiteDiffieHellman(t *testing.T) {
+ a, _ := rand.Int(rand.Reader, Order)
+ b, _ := rand.Int(rand.Reader, Order)
+ c, _ := rand.Int(rand.Reader, Order)
+
+ pa, _ := new(G1).Unmarshal(new(G1).ScalarBaseMult(a).Marshal())
+ qa, _ := new(G2).Unmarshal(new(G2).ScalarBaseMult(a).Marshal())
+ pb, _ := new(G1).Unmarshal(new(G1).ScalarBaseMult(b).Marshal())
+ qb, _ := new(G2).Unmarshal(new(G2).ScalarBaseMult(b).Marshal())
+ pc, _ := new(G1).Unmarshal(new(G1).ScalarBaseMult(c).Marshal())
+ qc, _ := new(G2).Unmarshal(new(G2).ScalarBaseMult(c).Marshal())
+
+ k1 := Pair(pb, qc)
+ k1.ScalarMult(k1, a)
+ k1Bytes := k1.Marshal()
+
+ k2 := Pair(pc, qa)
+ k2.ScalarMult(k2, b)
+ k2Bytes := k2.Marshal()
+
+ k3 := Pair(pa, qb)
+ k3.ScalarMult(k3, c)
+ k3Bytes := k3.Marshal()
+
+ if !bytes.Equal(k1Bytes, k2Bytes) || !bytes.Equal(k2Bytes, k3Bytes) {
+ t.Errorf("keys didn't agree")
+ }
+}
+
+func BenchmarkPairing(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ Pair(&G1{curveGen}, &G2{twistGen})
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bn256/constants.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bn256/constants.go
new file mode 100644
index 000000000..1ccefc498
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bn256/constants.go
@@ -0,0 +1,44 @@
+// Copyright 2012 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 bn256
+
+import (
+ "math/big"
+)
+
+func bigFromBase10(s string) *big.Int {
+ n, _ := new(big.Int).SetString(s, 10)
+ return n
+}
+
+// u is the BN parameter that determines the prime: 1868033³.
+var u = bigFromBase10("6518589491078791937")
+
+// p is a prime over which we form a basic field: 36u⁴+36u³+24u²+6u+1.
+var p = bigFromBase10("65000549695646603732796438742359905742825358107623003571877145026864184071783")
+
+// Order is the number of elements in both G₁ and G₂: 36u⁴+36u³+18u²+6u+1.
+var Order = bigFromBase10("65000549695646603732796438742359905742570406053903786389881062969044166799969")
+
+// xiToPMinus1Over6 is ξ^((p-1)/6) where ξ = i+3.
+var xiToPMinus1Over6 = &gfP2{bigFromBase10("8669379979083712429711189836753509758585994370025260553045152614783263110636"), bigFromBase10("19998038925833620163537568958541907098007303196759855091367510456613536016040")}
+
+// xiToPMinus1Over3 is ξ^((p-1)/3) where ξ = i+3.
+var xiToPMinus1Over3 = &gfP2{bigFromBase10("26098034838977895781559542626833399156321265654106457577426020397262786167059"), bigFromBase10("15931493369629630809226283458085260090334794394361662678240713231519278691715")}
+
+// xiToPMinus1Over2 is ξ^((p-1)/2) where ξ = i+3.
+var xiToPMinus1Over2 = &gfP2{bigFromBase10("50997318142241922852281555961173165965672272825141804376761836765206060036244"), bigFromBase10("38665955945962842195025998234511023902832543644254935982879660597356748036009")}
+
+// xiToPSquaredMinus1Over3 is ξ^((p²-1)/3) where ξ = i+3.
+var xiToPSquaredMinus1Over3 = bigFromBase10("65000549695646603727810655408050771481677621702948236658134783353303381437752")
+
+// xiTo2PSquaredMinus2Over3 is ξ^((2p²-2)/3) where ξ = i+3 (a cubic root of unity, mod p).
+var xiTo2PSquaredMinus2Over3 = bigFromBase10("4985783334309134261147736404674766913742361673560802634030")
+
+// xiToPSquaredMinus1Over6 is ξ^((1p²-1)/6) where ξ = i+3 (a cubic root of -1, mod p).
+var xiToPSquaredMinus1Over6 = bigFromBase10("65000549695646603727810655408050771481677621702948236658134783353303381437753")
+
+// xiTo2PMinus2Over3 is ξ^((2p-2)/3) where ξ = i+3.
+var xiTo2PMinus2Over3 = &gfP2{bigFromBase10("19885131339612776214803633203834694332692106372356013117629940868870585019582"), bigFromBase10("21645619881471562101905880913352894726728173167203616652430647841922248593627")}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bn256/curve.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bn256/curve.go
new file mode 100644
index 000000000..55b7063f1
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bn256/curve.go
@@ -0,0 +1,278 @@
+// Copyright 2012 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 bn256
+
+import (
+ "math/big"
+)
+
+// curvePoint implements the elliptic curve y²=x³+3. Points are kept in
+// Jacobian form and t=z² when valid. G₁ is the set of points of this curve on
+// GF(p).
+type curvePoint struct {
+ x, y, z, t *big.Int
+}
+
+var curveB = new(big.Int).SetInt64(3)
+
+// curveGen is the generator of G₁.
+var curveGen = &curvePoint{
+ new(big.Int).SetInt64(1),
+ new(big.Int).SetInt64(-2),
+ new(big.Int).SetInt64(1),
+ new(big.Int).SetInt64(1),
+}
+
+func newCurvePoint(pool *bnPool) *curvePoint {
+ return &curvePoint{
+ pool.Get(),
+ pool.Get(),
+ pool.Get(),
+ pool.Get(),
+ }
+}
+
+func (c *curvePoint) String() string {
+ c.MakeAffine(new(bnPool))
+ return "(" + c.x.String() + ", " + c.y.String() + ")"
+}
+
+func (c *curvePoint) Put(pool *bnPool) {
+ pool.Put(c.x)
+ pool.Put(c.y)
+ pool.Put(c.z)
+ pool.Put(c.t)
+}
+
+func (c *curvePoint) Set(a *curvePoint) {
+ c.x.Set(a.x)
+ c.y.Set(a.y)
+ c.z.Set(a.z)
+ c.t.Set(a.t)
+}
+
+// IsOnCurve returns true iff c is on the curve where c must be in affine form.
+func (c *curvePoint) IsOnCurve() bool {
+ yy := new(big.Int).Mul(c.y, c.y)
+ xxx := new(big.Int).Mul(c.x, c.x)
+ xxx.Mul(xxx, c.x)
+ yy.Sub(yy, xxx)
+ yy.Sub(yy, curveB)
+ if yy.Sign() < 0 || yy.Cmp(p) >= 0 {
+ yy.Mod(yy, p)
+ }
+ return yy.Sign() == 0
+}
+
+func (c *curvePoint) SetInfinity() {
+ c.z.SetInt64(0)
+}
+
+func (c *curvePoint) IsInfinity() bool {
+ return c.z.Sign() == 0
+}
+
+func (c *curvePoint) Add(a, b *curvePoint, pool *bnPool) {
+ if a.IsInfinity() {
+ c.Set(b)
+ return
+ }
+ if b.IsInfinity() {
+ c.Set(a)
+ return
+ }
+
+ // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3
+
+ // Normalize the points by replacing a = [x1:y1:z1] and b = [x2:y2:z2]
+ // by [u1:s1:z1·z2] and [u2:s2:z1·z2]
+ // where u1 = x1·z2², s1 = y1·z2³ and u1 = x2·z1², s2 = y2·z1³
+ z1z1 := pool.Get().Mul(a.z, a.z)
+ z1z1.Mod(z1z1, p)
+ z2z2 := pool.Get().Mul(b.z, b.z)
+ z2z2.Mod(z2z2, p)
+ u1 := pool.Get().Mul(a.x, z2z2)
+ u1.Mod(u1, p)
+ u2 := pool.Get().Mul(b.x, z1z1)
+ u2.Mod(u2, p)
+
+ t := pool.Get().Mul(b.z, z2z2)
+ t.Mod(t, p)
+ s1 := pool.Get().Mul(a.y, t)
+ s1.Mod(s1, p)
+
+ t.Mul(a.z, z1z1)
+ t.Mod(t, p)
+ s2 := pool.Get().Mul(b.y, t)
+ s2.Mod(s2, p)
+
+ // Compute x = (2h)²(s²-u1-u2)
+ // where s = (s2-s1)/(u2-u1) is the slope of the line through
+ // (u1,s1) and (u2,s2). The extra factor 2h = 2(u2-u1) comes from the value of z below.
+ // This is also:
+ // 4(s2-s1)² - 4h²(u1+u2) = 4(s2-s1)² - 4h³ - 4h²(2u1)
+ // = r² - j - 2v
+ // with the notations below.
+ h := pool.Get().Sub(u2, u1)
+ xEqual := h.Sign() == 0
+
+ t.Add(h, h)
+ // i = 4h²
+ i := pool.Get().Mul(t, t)
+ i.Mod(i, p)
+ // j = 4h³
+ j := pool.Get().Mul(h, i)
+ j.Mod(j, p)
+
+ t.Sub(s2, s1)
+ yEqual := t.Sign() == 0
+ if xEqual && yEqual {
+ c.Double(a, pool)
+ return
+ }
+ r := pool.Get().Add(t, t)
+
+ v := pool.Get().Mul(u1, i)
+ v.Mod(v, p)
+
+ // t4 = 4(s2-s1)²
+ t4 := pool.Get().Mul(r, r)
+ t4.Mod(t4, p)
+ t.Add(v, v)
+ t6 := pool.Get().Sub(t4, j)
+ c.x.Sub(t6, t)
+
+ // Set y = -(2h)³(s1 + s*(x/4h²-u1))
+ // This is also
+ // y = - 2·s1·j - (s2-s1)(2x - 2i·u1) = r(v-x) - 2·s1·j
+ t.Sub(v, c.x) // t7
+ t4.Mul(s1, j) // t8
+ t4.Mod(t4, p)
+ t6.Add(t4, t4) // t9
+ t4.Mul(r, t) // t10
+ t4.Mod(t4, p)
+ c.y.Sub(t4, t6)
+
+ // Set z = 2(u2-u1)·z1·z2 = 2h·z1·z2
+ t.Add(a.z, b.z) // t11
+ t4.Mul(t, t) // t12
+ t4.Mod(t4, p)
+ t.Sub(t4, z1z1) // t13
+ t4.Sub(t, z2z2) // t14
+ c.z.Mul(t4, h)
+ c.z.Mod(c.z, p)
+
+ pool.Put(z1z1)
+ pool.Put(z2z2)
+ pool.Put(u1)
+ pool.Put(u2)
+ pool.Put(t)
+ pool.Put(s1)
+ pool.Put(s2)
+ pool.Put(h)
+ pool.Put(i)
+ pool.Put(j)
+ pool.Put(r)
+ pool.Put(v)
+ pool.Put(t4)
+ pool.Put(t6)
+}
+
+func (c *curvePoint) Double(a *curvePoint, pool *bnPool) {
+ // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3
+ A := pool.Get().Mul(a.x, a.x)
+ A.Mod(A, p)
+ B := pool.Get().Mul(a.y, a.y)
+ B.Mod(B, p)
+ C := pool.Get().Mul(B, B)
+ C.Mod(C, p)
+
+ t := pool.Get().Add(a.x, B)
+ t2 := pool.Get().Mul(t, t)
+ t2.Mod(t2, p)
+ t.Sub(t2, A)
+ t2.Sub(t, C)
+ d := pool.Get().Add(t2, t2)
+ t.Add(A, A)
+ e := pool.Get().Add(t, A)
+ f := pool.Get().Mul(e, e)
+ f.Mod(f, p)
+
+ t.Add(d, d)
+ c.x.Sub(f, t)
+
+ t.Add(C, C)
+ t2.Add(t, t)
+ t.Add(t2, t2)
+ c.y.Sub(d, c.x)
+ t2.Mul(e, c.y)
+ t2.Mod(t2, p)
+ c.y.Sub(t2, t)
+
+ t.Mul(a.y, a.z)
+ t.Mod(t, p)
+ c.z.Add(t, t)
+
+ pool.Put(A)
+ pool.Put(B)
+ pool.Put(C)
+ pool.Put(t)
+ pool.Put(t2)
+ pool.Put(d)
+ pool.Put(e)
+ pool.Put(f)
+}
+
+func (c *curvePoint) Mul(a *curvePoint, scalar *big.Int, pool *bnPool) *curvePoint {
+ sum := newCurvePoint(pool)
+ sum.SetInfinity()
+ t := newCurvePoint(pool)
+
+ for i := scalar.BitLen(); i >= 0; i-- {
+ t.Double(sum, pool)
+ if scalar.Bit(i) != 0 {
+ sum.Add(t, a, pool)
+ } else {
+ sum.Set(t)
+ }
+ }
+
+ c.Set(sum)
+ sum.Put(pool)
+ t.Put(pool)
+ return c
+}
+
+func (c *curvePoint) MakeAffine(pool *bnPool) *curvePoint {
+ if words := c.z.Bits(); len(words) == 1 && words[0] == 1 {
+ return c
+ }
+
+ zInv := pool.Get().ModInverse(c.z, p)
+ t := pool.Get().Mul(c.y, zInv)
+ t.Mod(t, p)
+ zInv2 := pool.Get().Mul(zInv, zInv)
+ zInv2.Mod(zInv2, p)
+ c.y.Mul(t, zInv2)
+ c.y.Mod(c.y, p)
+ t.Mul(c.x, zInv2)
+ t.Mod(t, p)
+ c.x.Set(t)
+ c.z.SetInt64(1)
+ c.t.SetInt64(1)
+
+ pool.Put(zInv)
+ pool.Put(t)
+ pool.Put(zInv2)
+
+ return c
+}
+
+func (c *curvePoint) Negative(a *curvePoint) {
+ c.x.Set(a.x)
+ c.y.Neg(a.y)
+ c.z.Set(a.z)
+ c.t.SetInt64(0)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bn256/example_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bn256/example_test.go
new file mode 100644
index 000000000..b2d19807a
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bn256/example_test.go
@@ -0,0 +1,43 @@
+// Copyright 2012 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 bn256
+
+import (
+ "crypto/rand"
+)
+
+func ExamplePair() {
+ // This implements the tripartite Diffie-Hellman algorithm from "A One
+ // Round Protocol for Tripartite Diffie-Hellman", A. Joux.
+ // http://www.springerlink.com/content/cddc57yyva0hburb/fulltext.pdf
+
+ // Each of three parties, a, b and c, generate a private value.
+ a, _ := rand.Int(rand.Reader, Order)
+ b, _ := rand.Int(rand.Reader, Order)
+ c, _ := rand.Int(rand.Reader, Order)
+
+ // Then each party calculates g₁ and g₂ times their private value.
+ pa := new(G1).ScalarBaseMult(a)
+ qa := new(G2).ScalarBaseMult(a)
+
+ pb := new(G1).ScalarBaseMult(b)
+ qb := new(G2).ScalarBaseMult(b)
+
+ pc := new(G1).ScalarBaseMult(c)
+ qc := new(G2).ScalarBaseMult(c)
+
+ // Now each party exchanges its public values with the other two and
+ // all parties can calculate the shared key.
+ k1 := Pair(pb, qc)
+ k1.ScalarMult(k1, a)
+
+ k2 := Pair(pc, qa)
+ k2.ScalarMult(k2, b)
+
+ k3 := Pair(pa, qb)
+ k3.ScalarMult(k3, c)
+
+ // k1, k2 and k3 will all be equal.
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bn256/gfp12.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bn256/gfp12.go
new file mode 100644
index 000000000..f084eddf2
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bn256/gfp12.go
@@ -0,0 +1,200 @@
+// Copyright 2012 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 bn256
+
+// For details of the algorithms used, see "Multiplication and Squaring on
+// Pairing-Friendly Fields, Devegili et al.
+// http://eprint.iacr.org/2006/471.pdf.
+
+import (
+ "math/big"
+)
+
+// gfP12 implements the field of size p¹² as a quadratic extension of gfP6
+// where ω²=τ.
+type gfP12 struct {
+ x, y *gfP6 // value is xω + y
+}
+
+func newGFp12(pool *bnPool) *gfP12 {
+ return &gfP12{newGFp6(pool), newGFp6(pool)}
+}
+
+func (e *gfP12) String() string {
+ return "(" + e.x.String() + "," + e.y.String() + ")"
+}
+
+func (e *gfP12) Put(pool *bnPool) {
+ e.x.Put(pool)
+ e.y.Put(pool)
+}
+
+func (e *gfP12) Set(a *gfP12) *gfP12 {
+ e.x.Set(a.x)
+ e.y.Set(a.y)
+ return e
+}
+
+func (e *gfP12) SetZero() *gfP12 {
+ e.x.SetZero()
+ e.y.SetZero()
+ return e
+}
+
+func (e *gfP12) SetOne() *gfP12 {
+ e.x.SetZero()
+ e.y.SetOne()
+ return e
+}
+
+func (e *gfP12) Minimal() {
+ e.x.Minimal()
+ e.y.Minimal()
+}
+
+func (e *gfP12) IsZero() bool {
+ e.Minimal()
+ return e.x.IsZero() && e.y.IsZero()
+}
+
+func (e *gfP12) IsOne() bool {
+ e.Minimal()
+ return e.x.IsZero() && e.y.IsOne()
+}
+
+func (e *gfP12) Conjugate(a *gfP12) *gfP12 {
+ e.x.Negative(a.x)
+ e.y.Set(a.y)
+ return a
+}
+
+func (e *gfP12) Negative(a *gfP12) *gfP12 {
+ e.x.Negative(a.x)
+ e.y.Negative(a.y)
+ return e
+}
+
+// Frobenius computes (xω+y)^p = x^p ω·ξ^((p-1)/6) + y^p
+func (e *gfP12) Frobenius(a *gfP12, pool *bnPool) *gfP12 {
+ e.x.Frobenius(a.x, pool)
+ e.y.Frobenius(a.y, pool)
+ e.x.MulScalar(e.x, xiToPMinus1Over6, pool)
+ return e
+}
+
+// FrobeniusP2 computes (xω+y)^p² = x^p² ω·ξ^((p²-1)/6) + y^p²
+func (e *gfP12) FrobeniusP2(a *gfP12, pool *bnPool) *gfP12 {
+ e.x.FrobeniusP2(a.x)
+ e.x.MulGFP(e.x, xiToPSquaredMinus1Over6)
+ e.y.FrobeniusP2(a.y)
+ return e
+}
+
+func (e *gfP12) Add(a, b *gfP12) *gfP12 {
+ e.x.Add(a.x, b.x)
+ e.y.Add(a.y, b.y)
+ return e
+}
+
+func (e *gfP12) Sub(a, b *gfP12) *gfP12 {
+ e.x.Sub(a.x, b.x)
+ e.y.Sub(a.y, b.y)
+ return e
+}
+
+func (e *gfP12) Mul(a, b *gfP12, pool *bnPool) *gfP12 {
+ tx := newGFp6(pool)
+ tx.Mul(a.x, b.y, pool)
+ t := newGFp6(pool)
+ t.Mul(b.x, a.y, pool)
+ tx.Add(tx, t)
+
+ ty := newGFp6(pool)
+ ty.Mul(a.y, b.y, pool)
+ t.Mul(a.x, b.x, pool)
+ t.MulTau(t, pool)
+ e.y.Add(ty, t)
+ e.x.Set(tx)
+
+ tx.Put(pool)
+ ty.Put(pool)
+ t.Put(pool)
+ return e
+}
+
+func (e *gfP12) MulScalar(a *gfP12, b *gfP6, pool *bnPool) *gfP12 {
+ e.x.Mul(e.x, b, pool)
+ e.y.Mul(e.y, b, pool)
+ return e
+}
+
+func (c *gfP12) Exp(a *gfP12, power *big.Int, pool *bnPool) *gfP12 {
+ sum := newGFp12(pool)
+ sum.SetOne()
+ t := newGFp12(pool)
+
+ for i := power.BitLen() - 1; i >= 0; i-- {
+ t.Square(sum, pool)
+ if power.Bit(i) != 0 {
+ sum.Mul(t, a, pool)
+ } else {
+ sum.Set(t)
+ }
+ }
+
+ c.Set(sum)
+
+ sum.Put(pool)
+ t.Put(pool)
+
+ return c
+}
+
+func (e *gfP12) Square(a *gfP12, pool *bnPool) *gfP12 {
+ // Complex squaring algorithm
+ v0 := newGFp6(pool)
+ v0.Mul(a.x, a.y, pool)
+
+ t := newGFp6(pool)
+ t.MulTau(a.x, pool)
+ t.Add(a.y, t)
+ ty := newGFp6(pool)
+ ty.Add(a.x, a.y)
+ ty.Mul(ty, t, pool)
+ ty.Sub(ty, v0)
+ t.MulTau(v0, pool)
+ ty.Sub(ty, t)
+
+ e.y.Set(ty)
+ e.x.Double(v0)
+
+ v0.Put(pool)
+ t.Put(pool)
+ ty.Put(pool)
+
+ return e
+}
+
+func (e *gfP12) Invert(a *gfP12, pool *bnPool) *gfP12 {
+ // See "Implementing cryptographic pairings", M. Scott, section 3.2.
+ // ftp://136.206.11.249/pub/crypto/pairings.pdf
+ t1 := newGFp6(pool)
+ t2 := newGFp6(pool)
+
+ t1.Square(a.x, pool)
+ t2.Square(a.y, pool)
+ t1.MulTau(t1, pool)
+ t1.Sub(t2, t1)
+ t2.Invert(t1, pool)
+
+ e.x.Negative(a.x)
+ e.y.Set(a.y)
+ e.MulScalar(e, t2, pool)
+
+ t1.Put(pool)
+ t2.Put(pool)
+
+ return e
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bn256/gfp2.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bn256/gfp2.go
new file mode 100644
index 000000000..97f3f1f3f
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bn256/gfp2.go
@@ -0,0 +1,219 @@
+// Copyright 2012 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 bn256
+
+// For details of the algorithms used, see "Multiplication and Squaring on
+// Pairing-Friendly Fields, Devegili et al.
+// http://eprint.iacr.org/2006/471.pdf.
+
+import (
+ "math/big"
+)
+
+// gfP2 implements a field of size p² as a quadratic extension of the base
+// field where i²=-1.
+type gfP2 struct {
+ x, y *big.Int // value is xi+y.
+}
+
+func newGFp2(pool *bnPool) *gfP2 {
+ return &gfP2{pool.Get(), pool.Get()}
+}
+
+func (e *gfP2) String() string {
+ x := new(big.Int).Mod(e.x, p)
+ y := new(big.Int).Mod(e.y, p)
+ return "(" + x.String() + "," + y.String() + ")"
+}
+
+func (e *gfP2) Put(pool *bnPool) {
+ pool.Put(e.x)
+ pool.Put(e.y)
+}
+
+func (e *gfP2) Set(a *gfP2) *gfP2 {
+ e.x.Set(a.x)
+ e.y.Set(a.y)
+ return e
+}
+
+func (e *gfP2) SetZero() *gfP2 {
+ e.x.SetInt64(0)
+ e.y.SetInt64(0)
+ return e
+}
+
+func (e *gfP2) SetOne() *gfP2 {
+ e.x.SetInt64(0)
+ e.y.SetInt64(1)
+ return e
+}
+
+func (e *gfP2) Minimal() {
+ if e.x.Sign() < 0 || e.x.Cmp(p) >= 0 {
+ e.x.Mod(e.x, p)
+ }
+ if e.y.Sign() < 0 || e.y.Cmp(p) >= 0 {
+ e.y.Mod(e.y, p)
+ }
+}
+
+func (e *gfP2) IsZero() bool {
+ return e.x.Sign() == 0 && e.y.Sign() == 0
+}
+
+func (e *gfP2) IsOne() bool {
+ if e.x.Sign() != 0 {
+ return false
+ }
+ words := e.y.Bits()
+ return len(words) == 1 && words[0] == 1
+}
+
+func (e *gfP2) Conjugate(a *gfP2) *gfP2 {
+ e.y.Set(a.y)
+ e.x.Neg(a.x)
+ return e
+}
+
+func (e *gfP2) Negative(a *gfP2) *gfP2 {
+ e.x.Neg(a.x)
+ e.y.Neg(a.y)
+ return e
+}
+
+func (e *gfP2) Add(a, b *gfP2) *gfP2 {
+ e.x.Add(a.x, b.x)
+ e.y.Add(a.y, b.y)
+ return e
+}
+
+func (e *gfP2) Sub(a, b *gfP2) *gfP2 {
+ e.x.Sub(a.x, b.x)
+ e.y.Sub(a.y, b.y)
+ return e
+}
+
+func (e *gfP2) Double(a *gfP2) *gfP2 {
+ e.x.Lsh(a.x, 1)
+ e.y.Lsh(a.y, 1)
+ return e
+}
+
+func (c *gfP2) Exp(a *gfP2, power *big.Int, pool *bnPool) *gfP2 {
+ sum := newGFp2(pool)
+ sum.SetOne()
+ t := newGFp2(pool)
+
+ for i := power.BitLen() - 1; i >= 0; i-- {
+ t.Square(sum, pool)
+ if power.Bit(i) != 0 {
+ sum.Mul(t, a, pool)
+ } else {
+ sum.Set(t)
+ }
+ }
+
+ c.Set(sum)
+
+ sum.Put(pool)
+ t.Put(pool)
+
+ return c
+}
+
+// See "Multiplication and Squaring in Pairing-Friendly Fields",
+// http://eprint.iacr.org/2006/471.pdf
+func (e *gfP2) Mul(a, b *gfP2, pool *bnPool) *gfP2 {
+ tx := pool.Get().Mul(a.x, b.y)
+ t := pool.Get().Mul(b.x, a.y)
+ tx.Add(tx, t)
+ tx.Mod(tx, p)
+
+ ty := pool.Get().Mul(a.y, b.y)
+ t.Mul(a.x, b.x)
+ ty.Sub(ty, t)
+ e.y.Mod(ty, p)
+ e.x.Set(tx)
+
+ pool.Put(tx)
+ pool.Put(ty)
+ pool.Put(t)
+
+ return e
+}
+
+func (e *gfP2) MulScalar(a *gfP2, b *big.Int) *gfP2 {
+ e.x.Mul(a.x, b)
+ e.y.Mul(a.y, b)
+ return e
+}
+
+// MulXi sets e=ξa where ξ=i+3 and then returns e.
+func (e *gfP2) MulXi(a *gfP2, pool *bnPool) *gfP2 {
+ // (xi+y)(i+3) = (3x+y)i+(3y-x)
+ tx := pool.Get().Lsh(a.x, 1)
+ tx.Add(tx, a.x)
+ tx.Add(tx, a.y)
+
+ ty := pool.Get().Lsh(a.y, 1)
+ ty.Add(ty, a.y)
+ ty.Sub(ty, a.x)
+
+ e.x.Set(tx)
+ e.y.Set(ty)
+
+ pool.Put(tx)
+ pool.Put(ty)
+
+ return e
+}
+
+func (e *gfP2) Square(a *gfP2, pool *bnPool) *gfP2 {
+ // Complex squaring algorithm:
+ // (xi+b)² = (x+y)(y-x) + 2*i*x*y
+ t1 := pool.Get().Sub(a.y, a.x)
+ t2 := pool.Get().Add(a.x, a.y)
+ ty := pool.Get().Mul(t1, t2)
+ ty.Mod(ty, p)
+
+ t1.Mul(a.x, a.y)
+ t1.Lsh(t1, 1)
+
+ e.x.Mod(t1, p)
+ e.y.Set(ty)
+
+ pool.Put(t1)
+ pool.Put(t2)
+ pool.Put(ty)
+
+ return e
+}
+
+func (e *gfP2) Invert(a *gfP2, pool *bnPool) *gfP2 {
+ // See "Implementing cryptographic pairings", M. Scott, section 3.2.
+ // ftp://136.206.11.249/pub/crypto/pairings.pdf
+ t := pool.Get()
+ t.Mul(a.y, a.y)
+ t2 := pool.Get()
+ t2.Mul(a.x, a.x)
+ t.Add(t, t2)
+
+ inv := pool.Get()
+ inv.ModInverse(t, p)
+
+ e.x.Neg(a.x)
+ e.x.Mul(e.x, inv)
+ e.x.Mod(e.x, p)
+
+ e.y.Mul(a.y, inv)
+ e.y.Mod(e.y, p)
+
+ pool.Put(t)
+ pool.Put(t2)
+ pool.Put(inv)
+
+ return e
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bn256/gfp6.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bn256/gfp6.go
new file mode 100644
index 000000000..f98ae782c
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bn256/gfp6.go
@@ -0,0 +1,296 @@
+// Copyright 2012 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 bn256
+
+// For details of the algorithms used, see "Multiplication and Squaring on
+// Pairing-Friendly Fields, Devegili et al.
+// http://eprint.iacr.org/2006/471.pdf.
+
+import (
+ "math/big"
+)
+
+// gfP6 implements the field of size p⁶ as a cubic extension of gfP2 where τ³=ξ
+// and ξ=i+3.
+type gfP6 struct {
+ x, y, z *gfP2 // value is xτ² + yτ + z
+}
+
+func newGFp6(pool *bnPool) *gfP6 {
+ return &gfP6{newGFp2(pool), newGFp2(pool), newGFp2(pool)}
+}
+
+func (e *gfP6) String() string {
+ return "(" + e.x.String() + "," + e.y.String() + "," + e.z.String() + ")"
+}
+
+func (e *gfP6) Put(pool *bnPool) {
+ e.x.Put(pool)
+ e.y.Put(pool)
+ e.z.Put(pool)
+}
+
+func (e *gfP6) Set(a *gfP6) *gfP6 {
+ e.x.Set(a.x)
+ e.y.Set(a.y)
+ e.z.Set(a.z)
+ return e
+}
+
+func (e *gfP6) SetZero() *gfP6 {
+ e.x.SetZero()
+ e.y.SetZero()
+ e.z.SetZero()
+ return e
+}
+
+func (e *gfP6) SetOne() *gfP6 {
+ e.x.SetZero()
+ e.y.SetZero()
+ e.z.SetOne()
+ return e
+}
+
+func (e *gfP6) Minimal() {
+ e.x.Minimal()
+ e.y.Minimal()
+ e.z.Minimal()
+}
+
+func (e *gfP6) IsZero() bool {
+ return e.x.IsZero() && e.y.IsZero() && e.z.IsZero()
+}
+
+func (e *gfP6) IsOne() bool {
+ return e.x.IsZero() && e.y.IsZero() && e.z.IsOne()
+}
+
+func (e *gfP6) Negative(a *gfP6) *gfP6 {
+ e.x.Negative(a.x)
+ e.y.Negative(a.y)
+ e.z.Negative(a.z)
+ return e
+}
+
+func (e *gfP6) Frobenius(a *gfP6, pool *bnPool) *gfP6 {
+ e.x.Conjugate(a.x)
+ e.y.Conjugate(a.y)
+ e.z.Conjugate(a.z)
+
+ e.x.Mul(e.x, xiTo2PMinus2Over3, pool)
+ e.y.Mul(e.y, xiToPMinus1Over3, pool)
+ return e
+}
+
+// FrobeniusP2 computes (xτ²+yτ+z)^(p²) = xτ^(2p²) + yτ^(p²) + z
+func (e *gfP6) FrobeniusP2(a *gfP6) *gfP6 {
+ // τ^(2p²) = τ²τ^(2p²-2) = τ²ξ^((2p²-2)/3)
+ e.x.MulScalar(a.x, xiTo2PSquaredMinus2Over3)
+ // τ^(p²) = ττ^(p²-1) = τξ^((p²-1)/3)
+ e.y.MulScalar(a.y, xiToPSquaredMinus1Over3)
+ e.z.Set(a.z)
+ return e
+}
+
+func (e *gfP6) Add(a, b *gfP6) *gfP6 {
+ e.x.Add(a.x, b.x)
+ e.y.Add(a.y, b.y)
+ e.z.Add(a.z, b.z)
+ return e
+}
+
+func (e *gfP6) Sub(a, b *gfP6) *gfP6 {
+ e.x.Sub(a.x, b.x)
+ e.y.Sub(a.y, b.y)
+ e.z.Sub(a.z, b.z)
+ return e
+}
+
+func (e *gfP6) Double(a *gfP6) *gfP6 {
+ e.x.Double(a.x)
+ e.y.Double(a.y)
+ e.z.Double(a.z)
+ return e
+}
+
+func (e *gfP6) Mul(a, b *gfP6, pool *bnPool) *gfP6 {
+ // "Multiplication and Squaring on Pairing-Friendly Fields"
+ // Section 4, Karatsuba method.
+ // http://eprint.iacr.org/2006/471.pdf
+
+ v0 := newGFp2(pool)
+ v0.Mul(a.z, b.z, pool)
+ v1 := newGFp2(pool)
+ v1.Mul(a.y, b.y, pool)
+ v2 := newGFp2(pool)
+ v2.Mul(a.x, b.x, pool)
+
+ t0 := newGFp2(pool)
+ t0.Add(a.x, a.y)
+ t1 := newGFp2(pool)
+ t1.Add(b.x, b.y)
+ tz := newGFp2(pool)
+ tz.Mul(t0, t1, pool)
+
+ tz.Sub(tz, v1)
+ tz.Sub(tz, v2)
+ tz.MulXi(tz, pool)
+ tz.Add(tz, v0)
+
+ t0.Add(a.y, a.z)
+ t1.Add(b.y, b.z)
+ ty := newGFp2(pool)
+ ty.Mul(t0, t1, pool)
+ ty.Sub(ty, v0)
+ ty.Sub(ty, v1)
+ t0.MulXi(v2, pool)
+ ty.Add(ty, t0)
+
+ t0.Add(a.x, a.z)
+ t1.Add(b.x, b.z)
+ tx := newGFp2(pool)
+ tx.Mul(t0, t1, pool)
+ tx.Sub(tx, v0)
+ tx.Add(tx, v1)
+ tx.Sub(tx, v2)
+
+ e.x.Set(tx)
+ e.y.Set(ty)
+ e.z.Set(tz)
+
+ t0.Put(pool)
+ t1.Put(pool)
+ tx.Put(pool)
+ ty.Put(pool)
+ tz.Put(pool)
+ v0.Put(pool)
+ v1.Put(pool)
+ v2.Put(pool)
+ return e
+}
+
+func (e *gfP6) MulScalar(a *gfP6, b *gfP2, pool *bnPool) *gfP6 {
+ e.x.Mul(a.x, b, pool)
+ e.y.Mul(a.y, b, pool)
+ e.z.Mul(a.z, b, pool)
+ return e
+}
+
+func (e *gfP6) MulGFP(a *gfP6, b *big.Int) *gfP6 {
+ e.x.MulScalar(a.x, b)
+ e.y.MulScalar(a.y, b)
+ e.z.MulScalar(a.z, b)
+ return e
+}
+
+// MulTau computes τ·(aτ²+bτ+c) = bτ²+cτ+aξ
+func (e *gfP6) MulTau(a *gfP6, pool *bnPool) {
+ tz := newGFp2(pool)
+ tz.MulXi(a.x, pool)
+ ty := newGFp2(pool)
+ ty.Set(a.y)
+ e.y.Set(a.z)
+ e.x.Set(ty)
+ e.z.Set(tz)
+ tz.Put(pool)
+ ty.Put(pool)
+}
+
+func (e *gfP6) Square(a *gfP6, pool *bnPool) *gfP6 {
+ v0 := newGFp2(pool).Square(a.z, pool)
+ v1 := newGFp2(pool).Square(a.y, pool)
+ v2 := newGFp2(pool).Square(a.x, pool)
+
+ c0 := newGFp2(pool).Add(a.x, a.y)
+ c0.Square(c0, pool)
+ c0.Sub(c0, v1)
+ c0.Sub(c0, v2)
+ c0.MulXi(c0, pool)
+ c0.Add(c0, v0)
+
+ c1 := newGFp2(pool).Add(a.y, a.z)
+ c1.Square(c1, pool)
+ c1.Sub(c1, v0)
+ c1.Sub(c1, v1)
+ xiV2 := newGFp2(pool).MulXi(v2, pool)
+ c1.Add(c1, xiV2)
+
+ c2 := newGFp2(pool).Add(a.x, a.z)
+ c2.Square(c2, pool)
+ c2.Sub(c2, v0)
+ c2.Add(c2, v1)
+ c2.Sub(c2, v2)
+
+ e.x.Set(c2)
+ e.y.Set(c1)
+ e.z.Set(c0)
+
+ v0.Put(pool)
+ v1.Put(pool)
+ v2.Put(pool)
+ c0.Put(pool)
+ c1.Put(pool)
+ c2.Put(pool)
+ xiV2.Put(pool)
+
+ return e
+}
+
+func (e *gfP6) Invert(a *gfP6, pool *bnPool) *gfP6 {
+ // See "Implementing cryptographic pairings", M. Scott, section 3.2.
+ // ftp://136.206.11.249/pub/crypto/pairings.pdf
+
+ // Here we can give a short explanation of how it works: let j be a cubic root of
+ // unity in GF(p²) so that 1+j+j²=0.
+ // Then (xτ² + yτ + z)(xj²τ² + yjτ + z)(xjτ² + yj²τ + z)
+ // = (xτ² + yτ + z)(Cτ²+Bτ+A)
+ // = (x³ξ²+y³ξ+z³-3ξxyz) = F is an element of the base field (the norm).
+ //
+ // On the other hand (xj²τ² + yjτ + z)(xjτ² + yj²τ + z)
+ // = τ²(y²-ξxz) + τ(ξx²-yz) + (z²-ξxy)
+ //
+ // So that's why A = (z²-ξxy), B = (ξx²-yz), C = (y²-ξxz)
+ t1 := newGFp2(pool)
+
+ A := newGFp2(pool)
+ A.Square(a.z, pool)
+ t1.Mul(a.x, a.y, pool)
+ t1.MulXi(t1, pool)
+ A.Sub(A, t1)
+
+ B := newGFp2(pool)
+ B.Square(a.x, pool)
+ B.MulXi(B, pool)
+ t1.Mul(a.y, a.z, pool)
+ B.Sub(B, t1)
+
+ C := newGFp2(pool)
+ C.Square(a.y, pool)
+ t1.Mul(a.x, a.z, pool)
+ C.Sub(C, t1)
+
+ F := newGFp2(pool)
+ F.Mul(C, a.y, pool)
+ F.MulXi(F, pool)
+ t1.Mul(A, a.z, pool)
+ F.Add(F, t1)
+ t1.Mul(B, a.x, pool)
+ t1.MulXi(t1, pool)
+ F.Add(F, t1)
+
+ F.Invert(F, pool)
+
+ e.x.Mul(C, F, pool)
+ e.y.Mul(B, F, pool)
+ e.z.Mul(A, F, pool)
+
+ t1.Put(pool)
+ A.Put(pool)
+ B.Put(pool)
+ C.Put(pool)
+ F.Put(pool)
+
+ return e
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bn256/optate.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bn256/optate.go
new file mode 100644
index 000000000..7ae0746eb
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bn256/optate.go
@@ -0,0 +1,395 @@
+// Copyright 2012 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 bn256
+
+func lineFunctionAdd(r, p *twistPoint, q *curvePoint, r2 *gfP2, pool *bnPool) (a, b, c *gfP2, rOut *twistPoint) {
+ // See the mixed addition algorithm from "Faster Computation of the
+ // Tate Pairing", http://arxiv.org/pdf/0904.0854v3.pdf
+
+ B := newGFp2(pool).Mul(p.x, r.t, pool)
+
+ D := newGFp2(pool).Add(p.y, r.z)
+ D.Square(D, pool)
+ D.Sub(D, r2)
+ D.Sub(D, r.t)
+ D.Mul(D, r.t, pool)
+
+ H := newGFp2(pool).Sub(B, r.x)
+ I := newGFp2(pool).Square(H, pool)
+
+ E := newGFp2(pool).Add(I, I)
+ E.Add(E, E)
+
+ J := newGFp2(pool).Mul(H, E, pool)
+
+ L1 := newGFp2(pool).Sub(D, r.y)
+ L1.Sub(L1, r.y)
+
+ V := newGFp2(pool).Mul(r.x, E, pool)
+
+ rOut = newTwistPoint(pool)
+ rOut.x.Square(L1, pool)
+ rOut.x.Sub(rOut.x, J)
+ rOut.x.Sub(rOut.x, V)
+ rOut.x.Sub(rOut.x, V)
+
+ rOut.z.Add(r.z, H)
+ rOut.z.Square(rOut.z, pool)
+ rOut.z.Sub(rOut.z, r.t)
+ rOut.z.Sub(rOut.z, I)
+
+ t := newGFp2(pool).Sub(V, rOut.x)
+ t.Mul(t, L1, pool)
+ t2 := newGFp2(pool).Mul(r.y, J, pool)
+ t2.Add(t2, t2)
+ rOut.y.Sub(t, t2)
+
+ rOut.t.Square(rOut.z, pool)
+
+ t.Add(p.y, rOut.z)
+ t.Square(t, pool)
+ t.Sub(t, r2)
+ t.Sub(t, rOut.t)
+
+ t2.Mul(L1, p.x, pool)
+ t2.Add(t2, t2)
+ a = newGFp2(pool)
+ a.Sub(t2, t)
+
+ c = newGFp2(pool)
+ c.MulScalar(rOut.z, q.y)
+ c.Add(c, c)
+
+ b = newGFp2(pool)
+ b.SetZero()
+ b.Sub(b, L1)
+ b.MulScalar(b, q.x)
+ b.Add(b, b)
+
+ B.Put(pool)
+ D.Put(pool)
+ H.Put(pool)
+ I.Put(pool)
+ E.Put(pool)
+ J.Put(pool)
+ L1.Put(pool)
+ V.Put(pool)
+ t.Put(pool)
+ t2.Put(pool)
+
+ return
+}
+
+func lineFunctionDouble(r *twistPoint, q *curvePoint, pool *bnPool) (a, b, c *gfP2, rOut *twistPoint) {
+ // See the doubling algorithm for a=0 from "Faster Computation of the
+ // Tate Pairing", http://arxiv.org/pdf/0904.0854v3.pdf
+
+ A := newGFp2(pool).Square(r.x, pool)
+ B := newGFp2(pool).Square(r.y, pool)
+ C := newGFp2(pool).Square(B, pool)
+
+ D := newGFp2(pool).Add(r.x, B)
+ D.Square(D, pool)
+ D.Sub(D, A)
+ D.Sub(D, C)
+ D.Add(D, D)
+
+ E := newGFp2(pool).Add(A, A)
+ E.Add(E, A)
+
+ G := newGFp2(pool).Square(E, pool)
+
+ rOut = newTwistPoint(pool)
+ rOut.x.Sub(G, D)
+ rOut.x.Sub(rOut.x, D)
+
+ rOut.z.Add(r.y, r.z)
+ rOut.z.Square(rOut.z, pool)
+ rOut.z.Sub(rOut.z, B)
+ rOut.z.Sub(rOut.z, r.t)
+
+ rOut.y.Sub(D, rOut.x)
+ rOut.y.Mul(rOut.y, E, pool)
+ t := newGFp2(pool).Add(C, C)
+ t.Add(t, t)
+ t.Add(t, t)
+ rOut.y.Sub(rOut.y, t)
+
+ rOut.t.Square(rOut.z, pool)
+
+ t.Mul(E, r.t, pool)
+ t.Add(t, t)
+ b = newGFp2(pool)
+ b.SetZero()
+ b.Sub(b, t)
+ b.MulScalar(b, q.x)
+
+ a = newGFp2(pool)
+ a.Add(r.x, E)
+ a.Square(a, pool)
+ a.Sub(a, A)
+ a.Sub(a, G)
+ t.Add(B, B)
+ t.Add(t, t)
+ a.Sub(a, t)
+
+ c = newGFp2(pool)
+ c.Mul(rOut.z, r.t, pool)
+ c.Add(c, c)
+ c.MulScalar(c, q.y)
+
+ A.Put(pool)
+ B.Put(pool)
+ C.Put(pool)
+ D.Put(pool)
+ E.Put(pool)
+ G.Put(pool)
+ t.Put(pool)
+
+ return
+}
+
+func mulLine(ret *gfP12, a, b, c *gfP2, pool *bnPool) {
+ a2 := newGFp6(pool)
+ a2.x.SetZero()
+ a2.y.Set(a)
+ a2.z.Set(b)
+ a2.Mul(a2, ret.x, pool)
+ t3 := newGFp6(pool).MulScalar(ret.y, c, pool)
+
+ t := newGFp2(pool)
+ t.Add(b, c)
+ t2 := newGFp6(pool)
+ t2.x.SetZero()
+ t2.y.Set(a)
+ t2.z.Set(t)
+ ret.x.Add(ret.x, ret.y)
+
+ ret.y.Set(t3)
+
+ ret.x.Mul(ret.x, t2, pool)
+ ret.x.Sub(ret.x, a2)
+ ret.x.Sub(ret.x, ret.y)
+ a2.MulTau(a2, pool)
+ ret.y.Add(ret.y, a2)
+
+ a2.Put(pool)
+ t3.Put(pool)
+ t2.Put(pool)
+ t.Put(pool)
+}
+
+// sixuPlus2NAF is 6u+2 in non-adjacent form.
+var sixuPlus2NAF = []int8{0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, -1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, -1, 0, 1, 0, 0, 0, 1, 0, -1, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 1}
+
+// miller implements the Miller loop for calculating the Optimal Ate pairing.
+// See algorithm 1 from http://cryptojedi.org/papers/dclxvi-20100714.pdf
+func miller(q *twistPoint, p *curvePoint, pool *bnPool) *gfP12 {
+ ret := newGFp12(pool)
+ ret.SetOne()
+
+ aAffine := newTwistPoint(pool)
+ aAffine.Set(q)
+ aAffine.MakeAffine(pool)
+
+ bAffine := newCurvePoint(pool)
+ bAffine.Set(p)
+ bAffine.MakeAffine(pool)
+
+ minusA := newTwistPoint(pool)
+ minusA.Negative(aAffine, pool)
+
+ r := newTwistPoint(pool)
+ r.Set(aAffine)
+
+ r2 := newGFp2(pool)
+ r2.Square(aAffine.y, pool)
+
+ for i := len(sixuPlus2NAF) - 1; i > 0; i-- {
+ a, b, c, newR := lineFunctionDouble(r, bAffine, pool)
+ if i != len(sixuPlus2NAF)-1 {
+ ret.Square(ret, pool)
+ }
+
+ mulLine(ret, a, b, c, pool)
+ a.Put(pool)
+ b.Put(pool)
+ c.Put(pool)
+ r.Put(pool)
+ r = newR
+
+ switch sixuPlus2NAF[i-1] {
+ case 1:
+ a, b, c, newR = lineFunctionAdd(r, aAffine, bAffine, r2, pool)
+ case -1:
+ a, b, c, newR = lineFunctionAdd(r, minusA, bAffine, r2, pool)
+ default:
+ continue
+ }
+
+ mulLine(ret, a, b, c, pool)
+ a.Put(pool)
+ b.Put(pool)
+ c.Put(pool)
+ r.Put(pool)
+ r = newR
+ }
+
+ // In order to calculate Q1 we have to convert q from the sextic twist
+ // to the full GF(p^12) group, apply the Frobenius there, and convert
+ // back.
+ //
+ // The twist isomorphism is (x', y') -> (xω², yω³). If we consider just
+ // x for a moment, then after applying the Frobenius, we have x̄ω^(2p)
+ // where x̄ is the conjugate of x. If we are going to apply the inverse
+ // isomorphism we need a value with a single coefficient of ω² so we
+ // rewrite this as x̄ω^(2p-2)ω². ξ⁶ = ω and, due to the construction of
+ // p, 2p-2 is a multiple of six. Therefore we can rewrite as
+ // x̄ξ^((p-1)/3)ω² and applying the inverse isomorphism eliminates the
+ // ω².
+ //
+ // A similar argument can be made for the y value.
+
+ q1 := newTwistPoint(pool)
+ q1.x.Conjugate(aAffine.x)
+ q1.x.Mul(q1.x, xiToPMinus1Over3, pool)
+ q1.y.Conjugate(aAffine.y)
+ q1.y.Mul(q1.y, xiToPMinus1Over2, pool)
+ q1.z.SetOne()
+ q1.t.SetOne()
+
+ // For Q2 we are applying the p² Frobenius. The two conjugations cancel
+ // out and we are left only with the factors from the isomorphism. In
+ // the case of x, we end up with a pure number which is why
+ // xiToPSquaredMinus1Over3 is ∈ GF(p). With y we get a factor of -1. We
+ // ignore this to end up with -Q2.
+
+ minusQ2 := newTwistPoint(pool)
+ minusQ2.x.MulScalar(aAffine.x, xiToPSquaredMinus1Over3)
+ minusQ2.y.Set(aAffine.y)
+ minusQ2.z.SetOne()
+ minusQ2.t.SetOne()
+
+ r2.Square(q1.y, pool)
+ a, b, c, newR := lineFunctionAdd(r, q1, bAffine, r2, pool)
+ mulLine(ret, a, b, c, pool)
+ a.Put(pool)
+ b.Put(pool)
+ c.Put(pool)
+ r.Put(pool)
+ r = newR
+
+ r2.Square(minusQ2.y, pool)
+ a, b, c, newR = lineFunctionAdd(r, minusQ2, bAffine, r2, pool)
+ mulLine(ret, a, b, c, pool)
+ a.Put(pool)
+ b.Put(pool)
+ c.Put(pool)
+ r.Put(pool)
+ r = newR
+
+ aAffine.Put(pool)
+ bAffine.Put(pool)
+ minusA.Put(pool)
+ r.Put(pool)
+ r2.Put(pool)
+
+ return ret
+}
+
+// finalExponentiation computes the (p¹²-1)/Order-th power of an element of
+// GF(p¹²) to obtain an element of GT (steps 13-15 of algorithm 1 from
+// http://cryptojedi.org/papers/dclxvi-20100714.pdf)
+func finalExponentiation(in *gfP12, pool *bnPool) *gfP12 {
+ t1 := newGFp12(pool)
+
+ // This is the p^6-Frobenius
+ t1.x.Negative(in.x)
+ t1.y.Set(in.y)
+
+ inv := newGFp12(pool)
+ inv.Invert(in, pool)
+ t1.Mul(t1, inv, pool)
+
+ t2 := newGFp12(pool).FrobeniusP2(t1, pool)
+ t1.Mul(t1, t2, pool)
+
+ fp := newGFp12(pool).Frobenius(t1, pool)
+ fp2 := newGFp12(pool).FrobeniusP2(t1, pool)
+ fp3 := newGFp12(pool).Frobenius(fp2, pool)
+
+ fu, fu2, fu3 := newGFp12(pool), newGFp12(pool), newGFp12(pool)
+ fu.Exp(t1, u, pool)
+ fu2.Exp(fu, u, pool)
+ fu3.Exp(fu2, u, pool)
+
+ y3 := newGFp12(pool).Frobenius(fu, pool)
+ fu2p := newGFp12(pool).Frobenius(fu2, pool)
+ fu3p := newGFp12(pool).Frobenius(fu3, pool)
+ y2 := newGFp12(pool).FrobeniusP2(fu2, pool)
+
+ y0 := newGFp12(pool)
+ y0.Mul(fp, fp2, pool)
+ y0.Mul(y0, fp3, pool)
+
+ y1, y4, y5 := newGFp12(pool), newGFp12(pool), newGFp12(pool)
+ y1.Conjugate(t1)
+ y5.Conjugate(fu2)
+ y3.Conjugate(y3)
+ y4.Mul(fu, fu2p, pool)
+ y4.Conjugate(y4)
+
+ y6 := newGFp12(pool)
+ y6.Mul(fu3, fu3p, pool)
+ y6.Conjugate(y6)
+
+ t0 := newGFp12(pool)
+ t0.Square(y6, pool)
+ t0.Mul(t0, y4, pool)
+ t0.Mul(t0, y5, pool)
+ t1.Mul(y3, y5, pool)
+ t1.Mul(t1, t0, pool)
+ t0.Mul(t0, y2, pool)
+ t1.Square(t1, pool)
+ t1.Mul(t1, t0, pool)
+ t1.Square(t1, pool)
+ t0.Mul(t1, y1, pool)
+ t1.Mul(t1, y0, pool)
+ t0.Square(t0, pool)
+ t0.Mul(t0, t1, pool)
+
+ inv.Put(pool)
+ t1.Put(pool)
+ t2.Put(pool)
+ fp.Put(pool)
+ fp2.Put(pool)
+ fp3.Put(pool)
+ fu.Put(pool)
+ fu2.Put(pool)
+ fu3.Put(pool)
+ fu2p.Put(pool)
+ fu3p.Put(pool)
+ y0.Put(pool)
+ y1.Put(pool)
+ y2.Put(pool)
+ y3.Put(pool)
+ y4.Put(pool)
+ y5.Put(pool)
+ y6.Put(pool)
+
+ return t0
+}
+
+func optimalAte(a *twistPoint, b *curvePoint, pool *bnPool) *gfP12 {
+ e := miller(a, b, pool)
+ ret := finalExponentiation(e, pool)
+ e.Put(pool)
+
+ if a.IsInfinity() || b.IsInfinity() {
+ ret.SetOne()
+ }
+
+ return ret
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bn256/twist.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bn256/twist.go
new file mode 100644
index 000000000..4f8b3fede
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/bn256/twist.go
@@ -0,0 +1,249 @@
+// Copyright 2012 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 bn256
+
+import (
+ "math/big"
+)
+
+// twistPoint implements the elliptic curve y²=x³+3/ξ over GF(p²). Points are
+// kept in Jacobian form and t=z² when valid. The group G₂ is the set of
+// n-torsion points of this curve over GF(p²) (where n = Order)
+type twistPoint struct {
+ x, y, z, t *gfP2
+}
+
+var twistB = &gfP2{
+ bigFromBase10("6500054969564660373279643874235990574282535810762300357187714502686418407178"),
+ bigFromBase10("45500384786952622612957507119651934019977750675336102500314001518804928850249"),
+}
+
+// twistGen is the generator of group G₂.
+var twistGen = &twistPoint{
+ &gfP2{
+ bigFromBase10("21167961636542580255011770066570541300993051739349375019639421053990175267184"),
+ bigFromBase10("64746500191241794695844075326670126197795977525365406531717464316923369116492"),
+ },
+ &gfP2{
+ bigFromBase10("20666913350058776956210519119118544732556678129809273996262322366050359951122"),
+ bigFromBase10("17778617556404439934652658462602675281523610326338642107814333856843981424549"),
+ },
+ &gfP2{
+ bigFromBase10("0"),
+ bigFromBase10("1"),
+ },
+ &gfP2{
+ bigFromBase10("0"),
+ bigFromBase10("1"),
+ },
+}
+
+func newTwistPoint(pool *bnPool) *twistPoint {
+ return &twistPoint{
+ newGFp2(pool),
+ newGFp2(pool),
+ newGFp2(pool),
+ newGFp2(pool),
+ }
+}
+
+func (c *twistPoint) String() string {
+ return "(" + c.x.String() + ", " + c.y.String() + ", " + c.z.String() + ")"
+}
+
+func (c *twistPoint) Put(pool *bnPool) {
+ c.x.Put(pool)
+ c.y.Put(pool)
+ c.z.Put(pool)
+ c.t.Put(pool)
+}
+
+func (c *twistPoint) Set(a *twistPoint) {
+ c.x.Set(a.x)
+ c.y.Set(a.y)
+ c.z.Set(a.z)
+ c.t.Set(a.t)
+}
+
+// IsOnCurve returns true iff c is on the curve where c must be in affine form.
+func (c *twistPoint) IsOnCurve() bool {
+ pool := new(bnPool)
+ yy := newGFp2(pool).Square(c.y, pool)
+ xxx := newGFp2(pool).Square(c.x, pool)
+ xxx.Mul(xxx, c.x, pool)
+ yy.Sub(yy, xxx)
+ yy.Sub(yy, twistB)
+ yy.Minimal()
+ return yy.x.Sign() == 0 && yy.y.Sign() == 0
+}
+
+func (c *twistPoint) SetInfinity() {
+ c.z.SetZero()
+}
+
+func (c *twistPoint) IsInfinity() bool {
+ return c.z.IsZero()
+}
+
+func (c *twistPoint) Add(a, b *twistPoint, pool *bnPool) {
+ // For additional comments, see the same function in curve.go.
+
+ if a.IsInfinity() {
+ c.Set(b)
+ return
+ }
+ if b.IsInfinity() {
+ c.Set(a)
+ return
+ }
+
+ // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3
+ z1z1 := newGFp2(pool).Square(a.z, pool)
+ z2z2 := newGFp2(pool).Square(b.z, pool)
+ u1 := newGFp2(pool).Mul(a.x, z2z2, pool)
+ u2 := newGFp2(pool).Mul(b.x, z1z1, pool)
+
+ t := newGFp2(pool).Mul(b.z, z2z2, pool)
+ s1 := newGFp2(pool).Mul(a.y, t, pool)
+
+ t.Mul(a.z, z1z1, pool)
+ s2 := newGFp2(pool).Mul(b.y, t, pool)
+
+ h := newGFp2(pool).Sub(u2, u1)
+ xEqual := h.IsZero()
+
+ t.Add(h, h)
+ i := newGFp2(pool).Square(t, pool)
+ j := newGFp2(pool).Mul(h, i, pool)
+
+ t.Sub(s2, s1)
+ yEqual := t.IsZero()
+ if xEqual && yEqual {
+ c.Double(a, pool)
+ return
+ }
+ r := newGFp2(pool).Add(t, t)
+
+ v := newGFp2(pool).Mul(u1, i, pool)
+
+ t4 := newGFp2(pool).Square(r, pool)
+ t.Add(v, v)
+ t6 := newGFp2(pool).Sub(t4, j)
+ c.x.Sub(t6, t)
+
+ t.Sub(v, c.x) // t7
+ t4.Mul(s1, j, pool) // t8
+ t6.Add(t4, t4) // t9
+ t4.Mul(r, t, pool) // t10
+ c.y.Sub(t4, t6)
+
+ t.Add(a.z, b.z) // t11
+ t4.Square(t, pool) // t12
+ t.Sub(t4, z1z1) // t13
+ t4.Sub(t, z2z2) // t14
+ c.z.Mul(t4, h, pool)
+
+ z1z1.Put(pool)
+ z2z2.Put(pool)
+ u1.Put(pool)
+ u2.Put(pool)
+ t.Put(pool)
+ s1.Put(pool)
+ s2.Put(pool)
+ h.Put(pool)
+ i.Put(pool)
+ j.Put(pool)
+ r.Put(pool)
+ v.Put(pool)
+ t4.Put(pool)
+ t6.Put(pool)
+}
+
+func (c *twistPoint) Double(a *twistPoint, pool *bnPool) {
+ // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3
+ A := newGFp2(pool).Square(a.x, pool)
+ B := newGFp2(pool).Square(a.y, pool)
+ C := newGFp2(pool).Square(B, pool)
+
+ t := newGFp2(pool).Add(a.x, B)
+ t2 := newGFp2(pool).Square(t, pool)
+ t.Sub(t2, A)
+ t2.Sub(t, C)
+ d := newGFp2(pool).Add(t2, t2)
+ t.Add(A, A)
+ e := newGFp2(pool).Add(t, A)
+ f := newGFp2(pool).Square(e, pool)
+
+ t.Add(d, d)
+ c.x.Sub(f, t)
+
+ t.Add(C, C)
+ t2.Add(t, t)
+ t.Add(t2, t2)
+ c.y.Sub(d, c.x)
+ t2.Mul(e, c.y, pool)
+ c.y.Sub(t2, t)
+
+ t.Mul(a.y, a.z, pool)
+ c.z.Add(t, t)
+
+ A.Put(pool)
+ B.Put(pool)
+ C.Put(pool)
+ t.Put(pool)
+ t2.Put(pool)
+ d.Put(pool)
+ e.Put(pool)
+ f.Put(pool)
+}
+
+func (c *twistPoint) Mul(a *twistPoint, scalar *big.Int, pool *bnPool) *twistPoint {
+ sum := newTwistPoint(pool)
+ sum.SetInfinity()
+ t := newTwistPoint(pool)
+
+ for i := scalar.BitLen(); i >= 0; i-- {
+ t.Double(sum, pool)
+ if scalar.Bit(i) != 0 {
+ sum.Add(t, a, pool)
+ } else {
+ sum.Set(t)
+ }
+ }
+
+ c.Set(sum)
+ sum.Put(pool)
+ t.Put(pool)
+ return c
+}
+
+func (c *twistPoint) MakeAffine(pool *bnPool) *twistPoint {
+ if c.z.IsOne() {
+ return c
+ }
+
+ zInv := newGFp2(pool).Invert(c.z, pool)
+ t := newGFp2(pool).Mul(c.y, zInv, pool)
+ zInv2 := newGFp2(pool).Square(zInv, pool)
+ c.y.Mul(t, zInv2, pool)
+ t.Mul(c.x, zInv2, pool)
+ c.x.Set(t)
+ c.z.SetOne()
+ c.t.SetOne()
+
+ zInv.Put(pool)
+ t.Put(pool)
+ zInv2.Put(pool)
+
+ return c
+}
+
+func (c *twistPoint) Negative(a *twistPoint, pool *bnPool) {
+ c.x.Set(a.x)
+ c.y.SetZero()
+ c.y.Sub(c.y, a.y)
+ c.z.Set(a.z)
+ c.t.SetZero()
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/cast5/cast5.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/cast5/cast5.go
new file mode 100644
index 000000000..0b4af37bd
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/cast5/cast5.go
@@ -0,0 +1,526 @@
+// Copyright 2010 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 cast5 implements CAST5, as defined in RFC 2144. CAST5 is a common
+// OpenPGP cipher.
+package cast5 // import "golang.org/x/crypto/cast5"
+
+import "errors"
+
+const BlockSize = 8
+const KeySize = 16
+
+type Cipher struct {
+ masking [16]uint32
+ rotate [16]uint8
+}
+
+func NewCipher(key []byte) (c *Cipher, err error) {
+ if len(key) != KeySize {
+ return nil, errors.New("CAST5: keys must be 16 bytes")
+ }
+
+ c = new(Cipher)
+ c.keySchedule(key)
+ return
+}
+
+func (c *Cipher) BlockSize() int {
+ return BlockSize
+}
+
+func (c *Cipher) Encrypt(dst, src []byte) {
+ l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
+ r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
+
+ l, r = r, l^f1(r, c.masking[0], c.rotate[0])
+ l, r = r, l^f2(r, c.masking[1], c.rotate[1])
+ l, r = r, l^f3(r, c.masking[2], c.rotate[2])
+ l, r = r, l^f1(r, c.masking[3], c.rotate[3])
+
+ l, r = r, l^f2(r, c.masking[4], c.rotate[4])
+ l, r = r, l^f3(r, c.masking[5], c.rotate[5])
+ l, r = r, l^f1(r, c.masking[6], c.rotate[6])
+ l, r = r, l^f2(r, c.masking[7], c.rotate[7])
+
+ l, r = r, l^f3(r, c.masking[8], c.rotate[8])
+ l, r = r, l^f1(r, c.masking[9], c.rotate[9])
+ l, r = r, l^f2(r, c.masking[10], c.rotate[10])
+ l, r = r, l^f3(r, c.masking[11], c.rotate[11])
+
+ l, r = r, l^f1(r, c.masking[12], c.rotate[12])
+ l, r = r, l^f2(r, c.masking[13], c.rotate[13])
+ l, r = r, l^f3(r, c.masking[14], c.rotate[14])
+ l, r = r, l^f1(r, c.masking[15], c.rotate[15])
+
+ dst[0] = uint8(r >> 24)
+ dst[1] = uint8(r >> 16)
+ dst[2] = uint8(r >> 8)
+ dst[3] = uint8(r)
+ dst[4] = uint8(l >> 24)
+ dst[5] = uint8(l >> 16)
+ dst[6] = uint8(l >> 8)
+ dst[7] = uint8(l)
+}
+
+func (c *Cipher) Decrypt(dst, src []byte) {
+ l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
+ r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
+
+ l, r = r, l^f1(r, c.masking[15], c.rotate[15])
+ l, r = r, l^f3(r, c.masking[14], c.rotate[14])
+ l, r = r, l^f2(r, c.masking[13], c.rotate[13])
+ l, r = r, l^f1(r, c.masking[12], c.rotate[12])
+
+ l, r = r, l^f3(r, c.masking[11], c.rotate[11])
+ l, r = r, l^f2(r, c.masking[10], c.rotate[10])
+ l, r = r, l^f1(r, c.masking[9], c.rotate[9])
+ l, r = r, l^f3(r, c.masking[8], c.rotate[8])
+
+ l, r = r, l^f2(r, c.masking[7], c.rotate[7])
+ l, r = r, l^f1(r, c.masking[6], c.rotate[6])
+ l, r = r, l^f3(r, c.masking[5], c.rotate[5])
+ l, r = r, l^f2(r, c.masking[4], c.rotate[4])
+
+ l, r = r, l^f1(r, c.masking[3], c.rotate[3])
+ l, r = r, l^f3(r, c.masking[2], c.rotate[2])
+ l, r = r, l^f2(r, c.masking[1], c.rotate[1])
+ l, r = r, l^f1(r, c.masking[0], c.rotate[0])
+
+ dst[0] = uint8(r >> 24)
+ dst[1] = uint8(r >> 16)
+ dst[2] = uint8(r >> 8)
+ dst[3] = uint8(r)
+ dst[4] = uint8(l >> 24)
+ dst[5] = uint8(l >> 16)
+ dst[6] = uint8(l >> 8)
+ dst[7] = uint8(l)
+}
+
+type keyScheduleA [4][7]uint8
+type keyScheduleB [4][5]uint8
+
+// keyScheduleRound contains the magic values for a round of the key schedule.
+// The keyScheduleA deals with the lines like:
+// z0z1z2z3 = x0x1x2x3 ^ S5[xD] ^ S6[xF] ^ S7[xC] ^ S8[xE] ^ S7[x8]
+// Conceptually, both x and z are in the same array, x first. The first
+// element describes which word of this array gets written to and the
+// second, which word gets read. So, for the line above, it's "4, 0", because
+// it's writing to the first word of z, which, being after x, is word 4, and
+// reading from the first word of x: word 0.
+//
+// Next are the indexes into the S-boxes. Now the array is treated as bytes. So
+// "xD" is 0xd. The first byte of z is written as "16 + 0", just to be clear
+// that it's z that we're indexing.
+//
+// keyScheduleB deals with lines like:
+// K1 = S5[z8] ^ S6[z9] ^ S7[z7] ^ S8[z6] ^ S5[z2]
+// "K1" is ignored because key words are always written in order. So the five
+// elements are the S-box indexes. They use the same form as in keyScheduleA,
+// above.
+
+type keyScheduleRound struct{}
+type keySchedule []keyScheduleRound
+
+var schedule = []struct {
+ a keyScheduleA
+ b keyScheduleB
+}{
+ {
+ keyScheduleA{
+ {4, 0, 0xd, 0xf, 0xc, 0xe, 0x8},
+ {5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa},
+ {6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9},
+ {7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb},
+ },
+ keyScheduleB{
+ {16 + 8, 16 + 9, 16 + 7, 16 + 6, 16 + 2},
+ {16 + 0xa, 16 + 0xb, 16 + 5, 16 + 4, 16 + 6},
+ {16 + 0xc, 16 + 0xd, 16 + 3, 16 + 2, 16 + 9},
+ {16 + 0xe, 16 + 0xf, 16 + 1, 16 + 0, 16 + 0xc},
+ },
+ },
+ {
+ keyScheduleA{
+ {0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0},
+ {1, 4, 0, 2, 1, 3, 16 + 2},
+ {2, 5, 7, 6, 5, 4, 16 + 1},
+ {3, 7, 0xa, 9, 0xb, 8, 16 + 3},
+ },
+ keyScheduleB{
+ {3, 2, 0xc, 0xd, 8},
+ {1, 0, 0xe, 0xf, 0xd},
+ {7, 6, 8, 9, 3},
+ {5, 4, 0xa, 0xb, 7},
+ },
+ },
+ {
+ keyScheduleA{
+ {4, 0, 0xd, 0xf, 0xc, 0xe, 8},
+ {5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa},
+ {6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9},
+ {7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb},
+ },
+ keyScheduleB{
+ {16 + 3, 16 + 2, 16 + 0xc, 16 + 0xd, 16 + 9},
+ {16 + 1, 16 + 0, 16 + 0xe, 16 + 0xf, 16 + 0xc},
+ {16 + 7, 16 + 6, 16 + 8, 16 + 9, 16 + 2},
+ {16 + 5, 16 + 4, 16 + 0xa, 16 + 0xb, 16 + 6},
+ },
+ },
+ {
+ keyScheduleA{
+ {0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0},
+ {1, 4, 0, 2, 1, 3, 16 + 2},
+ {2, 5, 7, 6, 5, 4, 16 + 1},
+ {3, 7, 0xa, 9, 0xb, 8, 16 + 3},
+ },
+ keyScheduleB{
+ {8, 9, 7, 6, 3},
+ {0xa, 0xb, 5, 4, 7},
+ {0xc, 0xd, 3, 2, 8},
+ {0xe, 0xf, 1, 0, 0xd},
+ },
+ },
+}
+
+func (c *Cipher) keySchedule(in []byte) {
+ var t [8]uint32
+ var k [32]uint32
+
+ for i := 0; i < 4; i++ {
+ j := i * 4
+ t[i] = uint32(in[j])<<24 | uint32(in[j+1])<<16 | uint32(in[j+2])<<8 | uint32(in[j+3])
+ }
+
+ x := []byte{6, 7, 4, 5}
+ ki := 0
+
+ for half := 0; half < 2; half++ {
+ for _, round := range schedule {
+ for j := 0; j < 4; j++ {
+ var a [7]uint8
+ copy(a[:], round.a[j][:])
+ w := t[a[1]]
+ w ^= sBox[4][(t[a[2]>>2]>>(24-8*(a[2]&3)))&0xff]
+ w ^= sBox[5][(t[a[3]>>2]>>(24-8*(a[3]&3)))&0xff]
+ w ^= sBox[6][(t[a[4]>>2]>>(24-8*(a[4]&3)))&0xff]
+ w ^= sBox[7][(t[a[5]>>2]>>(24-8*(a[5]&3)))&0xff]
+ w ^= sBox[x[j]][(t[a[6]>>2]>>(24-8*(a[6]&3)))&0xff]
+ t[a[0]] = w
+ }
+
+ for j := 0; j < 4; j++ {
+ var b [5]uint8
+ copy(b[:], round.b[j][:])
+ w := sBox[4][(t[b[0]>>2]>>(24-8*(b[0]&3)))&0xff]
+ w ^= sBox[5][(t[b[1]>>2]>>(24-8*(b[1]&3)))&0xff]
+ w ^= sBox[6][(t[b[2]>>2]>>(24-8*(b[2]&3)))&0xff]
+ w ^= sBox[7][(t[b[3]>>2]>>(24-8*(b[3]&3)))&0xff]
+ w ^= sBox[4+j][(t[b[4]>>2]>>(24-8*(b[4]&3)))&0xff]
+ k[ki] = w
+ ki++
+ }
+ }
+ }
+
+ for i := 0; i < 16; i++ {
+ c.masking[i] = k[i]
+ c.rotate[i] = uint8(k[16+i] & 0x1f)
+ }
+}
+
+// These are the three 'f' functions. See RFC 2144, section 2.2.
+func f1(d, m uint32, r uint8) uint32 {
+ t := m + d
+ I := (t << r) | (t >> (32 - r))
+ return ((sBox[0][I>>24] ^ sBox[1][(I>>16)&0xff]) - sBox[2][(I>>8)&0xff]) + sBox[3][I&0xff]
+}
+
+func f2(d, m uint32, r uint8) uint32 {
+ t := m ^ d
+ I := (t << r) | (t >> (32 - r))
+ return ((sBox[0][I>>24] - sBox[1][(I>>16)&0xff]) + sBox[2][(I>>8)&0xff]) ^ sBox[3][I&0xff]
+}
+
+func f3(d, m uint32, r uint8) uint32 {
+ t := m - d
+ I := (t << r) | (t >> (32 - r))
+ return ((sBox[0][I>>24] + sBox[1][(I>>16)&0xff]) ^ sBox[2][(I>>8)&0xff]) - sBox[3][I&0xff]
+}
+
+var sBox = [8][256]uint32{
+ {
+ 0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949,
+ 0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e,
+ 0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d,
+ 0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0,
+ 0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7,
+ 0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935,
+ 0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d,
+ 0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50,
+ 0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe,
+ 0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3,
+ 0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167,
+ 0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291,
+ 0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779,
+ 0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2,
+ 0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511,
+ 0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d,
+ 0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5,
+ 0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324,
+ 0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c,
+ 0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc,
+ 0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d,
+ 0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96,
+ 0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a,
+ 0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d,
+ 0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd,
+ 0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6,
+ 0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9,
+ 0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872,
+ 0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c,
+ 0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e,
+ 0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9,
+ 0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf,
+ },
+ {
+ 0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651,
+ 0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3,
+ 0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb,
+ 0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806,
+ 0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b,
+ 0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359,
+ 0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b,
+ 0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c,
+ 0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34,
+ 0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb,
+ 0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd,
+ 0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860,
+ 0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b,
+ 0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304,
+ 0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b,
+ 0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf,
+ 0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c,
+ 0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13,
+ 0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f,
+ 0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6,
+ 0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6,
+ 0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58,
+ 0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906,
+ 0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d,
+ 0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6,
+ 0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4,
+ 0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6,
+ 0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f,
+ 0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249,
+ 0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa,
+ 0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9,
+ 0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1,
+ },
+ {
+ 0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90,
+ 0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5,
+ 0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e,
+ 0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240,
+ 0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5,
+ 0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b,
+ 0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71,
+ 0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04,
+ 0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82,
+ 0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15,
+ 0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2,
+ 0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176,
+ 0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148,
+ 0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc,
+ 0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341,
+ 0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e,
+ 0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51,
+ 0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f,
+ 0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a,
+ 0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b,
+ 0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b,
+ 0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5,
+ 0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45,
+ 0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536,
+ 0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc,
+ 0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0,
+ 0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69,
+ 0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2,
+ 0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49,
+ 0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d,
+ 0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a,
+ 0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783,
+ },
+ {
+ 0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1,
+ 0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf,
+ 0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15,
+ 0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121,
+ 0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25,
+ 0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5,
+ 0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb,
+ 0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5,
+ 0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d,
+ 0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6,
+ 0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23,
+ 0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003,
+ 0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6,
+ 0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119,
+ 0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24,
+ 0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a,
+ 0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79,
+ 0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df,
+ 0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26,
+ 0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab,
+ 0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7,
+ 0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417,
+ 0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2,
+ 0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2,
+ 0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a,
+ 0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919,
+ 0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef,
+ 0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876,
+ 0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab,
+ 0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04,
+ 0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282,
+ 0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2,
+ },
+ {
+ 0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f,
+ 0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a,
+ 0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff,
+ 0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02,
+ 0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a,
+ 0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7,
+ 0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9,
+ 0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981,
+ 0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774,
+ 0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655,
+ 0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2,
+ 0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910,
+ 0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1,
+ 0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da,
+ 0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049,
+ 0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f,
+ 0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba,
+ 0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be,
+ 0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3,
+ 0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840,
+ 0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4,
+ 0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2,
+ 0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7,
+ 0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5,
+ 0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e,
+ 0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e,
+ 0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801,
+ 0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad,
+ 0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0,
+ 0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20,
+ 0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8,
+ 0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4,
+ },
+ {
+ 0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac,
+ 0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138,
+ 0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367,
+ 0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98,
+ 0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072,
+ 0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3,
+ 0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd,
+ 0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8,
+ 0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9,
+ 0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54,
+ 0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387,
+ 0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc,
+ 0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf,
+ 0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf,
+ 0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f,
+ 0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289,
+ 0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950,
+ 0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f,
+ 0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b,
+ 0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be,
+ 0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13,
+ 0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976,
+ 0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0,
+ 0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891,
+ 0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da,
+ 0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc,
+ 0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084,
+ 0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25,
+ 0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121,
+ 0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5,
+ 0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd,
+ 0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f,
+ },
+ {
+ 0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f,
+ 0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de,
+ 0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43,
+ 0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19,
+ 0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2,
+ 0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516,
+ 0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88,
+ 0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816,
+ 0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756,
+ 0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a,
+ 0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264,
+ 0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688,
+ 0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28,
+ 0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3,
+ 0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7,
+ 0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06,
+ 0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033,
+ 0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a,
+ 0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566,
+ 0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509,
+ 0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962,
+ 0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e,
+ 0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c,
+ 0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c,
+ 0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285,
+ 0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301,
+ 0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be,
+ 0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767,
+ 0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647,
+ 0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914,
+ 0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c,
+ 0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3,
+ },
+ {
+ 0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5,
+ 0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc,
+ 0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd,
+ 0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d,
+ 0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2,
+ 0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862,
+ 0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc,
+ 0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c,
+ 0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e,
+ 0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039,
+ 0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8,
+ 0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42,
+ 0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5,
+ 0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472,
+ 0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225,
+ 0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c,
+ 0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb,
+ 0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054,
+ 0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70,
+ 0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc,
+ 0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c,
+ 0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3,
+ 0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4,
+ 0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101,
+ 0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f,
+ 0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e,
+ 0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a,
+ 0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c,
+ 0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384,
+ 0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c,
+ 0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82,
+ 0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e,
+ },
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/cast5/cast5_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/cast5/cast5_test.go
new file mode 100644
index 000000000..778b272a6
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/cast5/cast5_test.go
@@ -0,0 +1,106 @@
+// Copyright 2010 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 cast5
+
+import (
+ "bytes"
+ "encoding/hex"
+ "testing"
+)
+
+// This test vector is taken from RFC 2144, App B.1.
+// Since the other two test vectors are for reduced-round variants, we can't
+// use them.
+var basicTests = []struct {
+ key, plainText, cipherText string
+}{
+ {
+ "0123456712345678234567893456789a",
+ "0123456789abcdef",
+ "238b4fe5847e44b2",
+ },
+}
+
+func TestBasic(t *testing.T) {
+ for i, test := range basicTests {
+ key, _ := hex.DecodeString(test.key)
+ plainText, _ := hex.DecodeString(test.plainText)
+ expected, _ := hex.DecodeString(test.cipherText)
+
+ c, err := NewCipher(key)
+ if err != nil {
+ t.Errorf("#%d: failed to create Cipher: %s", i, err)
+ continue
+ }
+ var cipherText [BlockSize]byte
+ c.Encrypt(cipherText[:], plainText)
+ if !bytes.Equal(cipherText[:], expected) {
+ t.Errorf("#%d: got:%x want:%x", i, cipherText, expected)
+ }
+
+ var plainTextAgain [BlockSize]byte
+ c.Decrypt(plainTextAgain[:], cipherText[:])
+ if !bytes.Equal(plainTextAgain[:], plainText) {
+ t.Errorf("#%d: got:%x want:%x", i, plainTextAgain, plainText)
+ }
+ }
+}
+
+// TestFull performs the test specified in RFC 2144, App B.2.
+// However, due to the length of time taken, it's disabled here and a more
+// limited version is included, below.
+func TestFull(t *testing.T) {
+ if testing.Short() {
+ // This is too slow for normal testing
+ return
+ }
+
+ a, b := iterate(1000000)
+
+ const expectedA = "eea9d0a249fd3ba6b3436fb89d6dca92"
+ const expectedB = "b2c95eb00c31ad7180ac05b8e83d696e"
+
+ if hex.EncodeToString(a) != expectedA {
+ t.Errorf("a: got:%x want:%s", a, expectedA)
+ }
+ if hex.EncodeToString(b) != expectedB {
+ t.Errorf("b: got:%x want:%s", b, expectedB)
+ }
+}
+
+func iterate(iterations int) ([]byte, []byte) {
+ const initValueHex = "0123456712345678234567893456789a"
+
+ initValue, _ := hex.DecodeString(initValueHex)
+
+ var a, b [16]byte
+ copy(a[:], initValue)
+ copy(b[:], initValue)
+
+ for i := 0; i < iterations; i++ {
+ c, _ := NewCipher(b[:])
+ c.Encrypt(a[:8], a[:8])
+ c.Encrypt(a[8:], a[8:])
+ c, _ = NewCipher(a[:])
+ c.Encrypt(b[:8], b[:8])
+ c.Encrypt(b[8:], b[8:])
+ }
+
+ return a[:], b[:]
+}
+
+func TestLimited(t *testing.T) {
+ a, b := iterate(1000)
+
+ const expectedA = "23f73b14b02a2ad7dfb9f2c35644798d"
+ const expectedB = "e5bf37eff14c456a40b21ce369370a9f"
+
+ if hex.EncodeToString(a) != expectedA {
+ t.Errorf("a: got:%x want:%s", a, expectedA)
+ }
+ if hex.EncodeToString(b) != expectedB {
+ t.Errorf("b: got:%x want:%s", b, expectedB)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go
new file mode 100644
index 000000000..3f0dcb9d8
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go
@@ -0,0 +1,83 @@
+// 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.
+
+// Package chacha20poly1305 implements the ChaCha20-Poly1305 AEAD as specified in RFC 7539.
+package chacha20poly1305 // import "golang.org/x/crypto/chacha20poly1305"
+
+import (
+ "crypto/cipher"
+ "errors"
+)
+
+const (
+ // KeySize is the size of the key used by this AEAD, in bytes.
+ KeySize = 32
+ // NonceSize is the size of the nonce used with this AEAD, in bytes.
+ NonceSize = 12
+)
+
+type chacha20poly1305 struct {
+ key [32]byte
+}
+
+// New returns a ChaCha20-Poly1305 AEAD that uses the given, 256-bit key.
+func New(key []byte) (cipher.AEAD, error) {
+ if len(key) != KeySize {
+ return nil, errors.New("chacha20poly1305: bad key length")
+ }
+ ret := new(chacha20poly1305)
+ copy(ret.key[:], key)
+ return ret, nil
+}
+
+func (c *chacha20poly1305) NonceSize() int {
+ return NonceSize
+}
+
+func (c *chacha20poly1305) Overhead() int {
+ return 16
+}
+
+func (c *chacha20poly1305) Seal(dst, nonce, plaintext, additionalData []byte) []byte {
+ if len(nonce) != NonceSize {
+ panic("chacha20poly1305: bad nonce length passed to Seal")
+ }
+
+ if uint64(len(plaintext)) > (1<<38)-64 {
+ panic("chacha20poly1305: plaintext too large")
+ }
+
+ return c.seal(dst, nonce, plaintext, additionalData)
+}
+
+var errOpen = errors.New("chacha20poly1305: message authentication failed")
+
+func (c *chacha20poly1305) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
+ if len(nonce) != NonceSize {
+ panic("chacha20poly1305: bad nonce length passed to Open")
+ }
+ if len(ciphertext) < 16 {
+ return nil, errOpen
+ }
+ if uint64(len(ciphertext)) > (1<<38)-48 {
+ panic("chacha20poly1305: ciphertext too large")
+ }
+
+ return c.open(dst, nonce, ciphertext, additionalData)
+}
+
+// sliceForAppend takes a slice and a requested number of bytes. It returns a
+// slice with the contents of the given slice followed by that many bytes and a
+// second slice that aliases into it and contains only the extra bytes. If the
+// original slice has sufficient capacity then no allocation is performed.
+func sliceForAppend(in []byte, n int) (head, tail []byte) {
+ if total := len(in) + n; cap(in) >= total {
+ head = in[:total]
+ } else {
+ head = make([]byte, total)
+ copy(head, in)
+ }
+ tail = head[len(in):]
+ return
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go
new file mode 100644
index 000000000..7cd7ad834
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go
@@ -0,0 +1,127 @@
+// 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.
+
+// +build go1.7,amd64,!gccgo,!appengine
+
+package chacha20poly1305
+
+import "encoding/binary"
+
+//go:noescape
+func chacha20Poly1305Open(dst []byte, key []uint32, src, ad []byte) bool
+
+//go:noescape
+func chacha20Poly1305Seal(dst []byte, key []uint32, src, ad []byte)
+
+// cpuid is implemented in chacha20poly1305_amd64.s.
+func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32)
+
+// xgetbv with ecx = 0 is implemented in chacha20poly1305_amd64.s.
+func xgetbv() (eax, edx uint32)
+
+var (
+ useASM bool
+ useAVX2 bool
+)
+
+func init() {
+ detectCPUFeatures()
+}
+
+// detectCPUFeatures is used to detect if cpu instructions
+// used by the functions implemented in assembler in
+// chacha20poly1305_amd64.s are supported.
+func detectCPUFeatures() {
+ maxID, _, _, _ := cpuid(0, 0)
+ if maxID < 1 {
+ return
+ }
+
+ _, _, ecx1, _ := cpuid(1, 0)
+
+ haveSSSE3 := isSet(9, ecx1)
+ useASM = haveSSSE3
+
+ haveOSXSAVE := isSet(27, ecx1)
+
+ osSupportsAVX := false
+ // For XGETBV, OSXSAVE bit is required and sufficient.
+ if haveOSXSAVE {
+ eax, _ := xgetbv()
+ // Check if XMM and YMM registers have OS support.
+ osSupportsAVX = isSet(1, eax) && isSet(2, eax)
+ }
+ haveAVX := isSet(28, ecx1) && osSupportsAVX
+
+ if maxID < 7 {
+ return
+ }
+
+ _, ebx7, _, _ := cpuid(7, 0)
+ haveAVX2 := isSet(5, ebx7) && haveAVX
+ haveBMI2 := isSet(8, ebx7)
+
+ useAVX2 = haveAVX2 && haveBMI2
+}
+
+// isSet checks if bit at bitpos is set in value.
+func isSet(bitpos uint, value uint32) bool {
+ return value&(1<<bitpos) != 0
+}
+
+// setupState writes a ChaCha20 input matrix to state. See
+// https://tools.ietf.org/html/rfc7539#section-2.3.
+func setupState(state *[16]uint32, key *[32]byte, nonce []byte) {
+ state[0] = 0x61707865
+ state[1] = 0x3320646e
+ state[2] = 0x79622d32
+ state[3] = 0x6b206574
+
+ state[4] = binary.LittleEndian.Uint32(key[:4])
+ state[5] = binary.LittleEndian.Uint32(key[4:8])
+ state[6] = binary.LittleEndian.Uint32(key[8:12])
+ state[7] = binary.LittleEndian.Uint32(key[12:16])
+ state[8] = binary.LittleEndian.Uint32(key[16:20])
+ state[9] = binary.LittleEndian.Uint32(key[20:24])
+ state[10] = binary.LittleEndian.Uint32(key[24:28])
+ state[11] = binary.LittleEndian.Uint32(key[28:32])
+
+ state[12] = 0
+ state[13] = binary.LittleEndian.Uint32(nonce[:4])
+ state[14] = binary.LittleEndian.Uint32(nonce[4:8])
+ state[15] = binary.LittleEndian.Uint32(nonce[8:12])
+}
+
+func (c *chacha20poly1305) seal(dst, nonce, plaintext, additionalData []byte) []byte {
+ if !useASM {
+ return c.sealGeneric(dst, nonce, plaintext, additionalData)
+ }
+
+ var state [16]uint32
+ setupState(&state, &c.key, nonce)
+
+ ret, out := sliceForAppend(dst, len(plaintext)+16)
+ chacha20Poly1305Seal(out[:], state[:], plaintext, additionalData)
+ return ret
+}
+
+func (c *chacha20poly1305) open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
+ if !useASM {
+ return c.openGeneric(dst, nonce, ciphertext, additionalData)
+ }
+
+ var state [16]uint32
+ setupState(&state, &c.key, nonce)
+
+ ciphertext = ciphertext[:len(ciphertext)-16]
+ ret, out := sliceForAppend(dst, len(ciphertext))
+ if !chacha20Poly1305Open(out, state[:], ciphertext, additionalData) {
+ for i := range out {
+ out[i] = 0
+ }
+ return nil, errOpen
+ }
+
+ return ret, nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.s b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.s
new file mode 100644
index 000000000..1c57e3894
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.s
@@ -0,0 +1,2714 @@
+// 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.
+
+// This file was originally from https://golang.org/cl/24717 by Vlad Krasnov of CloudFlare.
+
+// +build go1.7,amd64,!gccgo,!appengine
+
+#include "textflag.h"
+// General register allocation
+#define oup DI
+#define inp SI
+#define inl BX
+#define adp CX // free to reuse, after we hash the additional data
+#define keyp R8 // free to reuse, when we copy the key to stack
+#define itr2 R9 // general iterator
+#define itr1 CX // general iterator
+#define acc0 R10
+#define acc1 R11
+#define acc2 R12
+#define t0 R13
+#define t1 R14
+#define t2 R15
+#define t3 R8
+// Register and stack allocation for the SSE code
+#define rStore (0*16)(BP)
+#define sStore (1*16)(BP)
+#define state1Store (2*16)(BP)
+#define state2Store (3*16)(BP)
+#define tmpStore (4*16)(BP)
+#define ctr0Store (5*16)(BP)
+#define ctr1Store (6*16)(BP)
+#define ctr2Store (7*16)(BP)
+#define ctr3Store (8*16)(BP)
+#define A0 X0
+#define A1 X1
+#define A2 X2
+#define B0 X3
+#define B1 X4
+#define B2 X5
+#define C0 X6
+#define C1 X7
+#define C2 X8
+#define D0 X9
+#define D1 X10
+#define D2 X11
+#define T0 X12
+#define T1 X13
+#define T2 X14
+#define T3 X15
+#define A3 T0
+#define B3 T1
+#define C3 T2
+#define D3 T3
+// Register and stack allocation for the AVX2 code
+#define rsStoreAVX2 (0*32)(BP)
+#define state1StoreAVX2 (1*32)(BP)
+#define state2StoreAVX2 (2*32)(BP)
+#define ctr0StoreAVX2 (3*32)(BP)
+#define ctr1StoreAVX2 (4*32)(BP)
+#define ctr2StoreAVX2 (5*32)(BP)
+#define ctr3StoreAVX2 (6*32)(BP)
+#define tmpStoreAVX2 (7*32)(BP) // 256 bytes on stack
+#define AA0 Y0
+#define AA1 Y5
+#define AA2 Y6
+#define AA3 Y7
+#define BB0 Y14
+#define BB1 Y9
+#define BB2 Y10
+#define BB3 Y11
+#define CC0 Y12
+#define CC1 Y13
+#define CC2 Y8
+#define CC3 Y15
+#define DD0 Y4
+#define DD1 Y1
+#define DD2 Y2
+#define DD3 Y3
+#define TT0 DD3
+#define TT1 AA3
+#define TT2 BB3
+#define TT3 CC3
+// ChaCha20 constants
+DATA ·chacha20Constants<>+0x00(SB)/4, $0x61707865
+DATA ·chacha20Constants<>+0x04(SB)/4, $0x3320646e
+DATA ·chacha20Constants<>+0x08(SB)/4, $0x79622d32
+DATA ·chacha20Constants<>+0x0c(SB)/4, $0x6b206574
+DATA ·chacha20Constants<>+0x10(SB)/4, $0x61707865
+DATA ·chacha20Constants<>+0x14(SB)/4, $0x3320646e
+DATA ·chacha20Constants<>+0x18(SB)/4, $0x79622d32
+DATA ·chacha20Constants<>+0x1c(SB)/4, $0x6b206574
+// <<< 16 with PSHUFB
+DATA ·rol16<>+0x00(SB)/8, $0x0504070601000302
+DATA ·rol16<>+0x08(SB)/8, $0x0D0C0F0E09080B0A
+DATA ·rol16<>+0x10(SB)/8, $0x0504070601000302
+DATA ·rol16<>+0x18(SB)/8, $0x0D0C0F0E09080B0A
+// <<< 8 with PSHUFB
+DATA ·rol8<>+0x00(SB)/8, $0x0605040702010003
+DATA ·rol8<>+0x08(SB)/8, $0x0E0D0C0F0A09080B
+DATA ·rol8<>+0x10(SB)/8, $0x0605040702010003
+DATA ·rol8<>+0x18(SB)/8, $0x0E0D0C0F0A09080B
+
+DATA ·avx2InitMask<>+0x00(SB)/8, $0x0
+DATA ·avx2InitMask<>+0x08(SB)/8, $0x0
+DATA ·avx2InitMask<>+0x10(SB)/8, $0x1
+DATA ·avx2InitMask<>+0x18(SB)/8, $0x0
+
+DATA ·avx2IncMask<>+0x00(SB)/8, $0x2
+DATA ·avx2IncMask<>+0x08(SB)/8, $0x0
+DATA ·avx2IncMask<>+0x10(SB)/8, $0x2
+DATA ·avx2IncMask<>+0x18(SB)/8, $0x0
+// Poly1305 key clamp
+DATA ·polyClampMask<>+0x00(SB)/8, $0x0FFFFFFC0FFFFFFF
+DATA ·polyClampMask<>+0x08(SB)/8, $0x0FFFFFFC0FFFFFFC
+DATA ·polyClampMask<>+0x10(SB)/8, $0xFFFFFFFFFFFFFFFF
+DATA ·polyClampMask<>+0x18(SB)/8, $0xFFFFFFFFFFFFFFFF
+
+DATA ·sseIncMask<>+0x00(SB)/8, $0x1
+DATA ·sseIncMask<>+0x08(SB)/8, $0x0
+// To load/store the last < 16 bytes in a buffer
+DATA ·andMask<>+0x00(SB)/8, $0x00000000000000ff
+DATA ·andMask<>+0x08(SB)/8, $0x0000000000000000
+DATA ·andMask<>+0x10(SB)/8, $0x000000000000ffff
+DATA ·andMask<>+0x18(SB)/8, $0x0000000000000000
+DATA ·andMask<>+0x20(SB)/8, $0x0000000000ffffff
+DATA ·andMask<>+0x28(SB)/8, $0x0000000000000000
+DATA ·andMask<>+0x30(SB)/8, $0x00000000ffffffff
+DATA ·andMask<>+0x38(SB)/8, $0x0000000000000000
+DATA ·andMask<>+0x40(SB)/8, $0x000000ffffffffff
+DATA ·andMask<>+0x48(SB)/8, $0x0000000000000000
+DATA ·andMask<>+0x50(SB)/8, $0x0000ffffffffffff
+DATA ·andMask<>+0x58(SB)/8, $0x0000000000000000
+DATA ·andMask<>+0x60(SB)/8, $0x00ffffffffffffff
+DATA ·andMask<>+0x68(SB)/8, $0x0000000000000000
+DATA ·andMask<>+0x70(SB)/8, $0xffffffffffffffff
+DATA ·andMask<>+0x78(SB)/8, $0x0000000000000000
+DATA ·andMask<>+0x80(SB)/8, $0xffffffffffffffff
+DATA ·andMask<>+0x88(SB)/8, $0x00000000000000ff
+DATA ·andMask<>+0x90(SB)/8, $0xffffffffffffffff
+DATA ·andMask<>+0x98(SB)/8, $0x000000000000ffff
+DATA ·andMask<>+0xa0(SB)/8, $0xffffffffffffffff
+DATA ·andMask<>+0xa8(SB)/8, $0x0000000000ffffff
+DATA ·andMask<>+0xb0(SB)/8, $0xffffffffffffffff
+DATA ·andMask<>+0xb8(SB)/8, $0x00000000ffffffff
+DATA ·andMask<>+0xc0(SB)/8, $0xffffffffffffffff
+DATA ·andMask<>+0xc8(SB)/8, $0x000000ffffffffff
+DATA ·andMask<>+0xd0(SB)/8, $0xffffffffffffffff
+DATA ·andMask<>+0xd8(SB)/8, $0x0000ffffffffffff
+DATA ·andMask<>+0xe0(SB)/8, $0xffffffffffffffff
+DATA ·andMask<>+0xe8(SB)/8, $0x00ffffffffffffff
+
+GLOBL ·chacha20Constants<>(SB), (NOPTR+RODATA), $32
+GLOBL ·rol16<>(SB), (NOPTR+RODATA), $32
+GLOBL ·rol8<>(SB), (NOPTR+RODATA), $32
+GLOBL ·sseIncMask<>(SB), (NOPTR+RODATA), $16
+GLOBL ·avx2IncMask<>(SB), (NOPTR+RODATA), $32
+GLOBL ·avx2InitMask<>(SB), (NOPTR+RODATA), $32
+GLOBL ·polyClampMask<>(SB), (NOPTR+RODATA), $32
+GLOBL ·andMask<>(SB), (NOPTR+RODATA), $240
+// No PALIGNR in Go ASM yet (but VPALIGNR is present).
+#define shiftB0Left BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xdb; BYTE $0x04 // PALIGNR $4, X3, X3
+#define shiftB1Left BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xe4; BYTE $0x04 // PALIGNR $4, X4, X4
+#define shiftB2Left BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xed; BYTE $0x04 // PALIGNR $4, X5, X5
+#define shiftB3Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xed; BYTE $0x04 // PALIGNR $4, X13, X13
+#define shiftC0Left BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xf6; BYTE $0x08 // PALIGNR $8, X6, X6
+#define shiftC1Left BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xff; BYTE $0x08 // PALIGNR $8, X7, X7
+#define shiftC2Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xc0; BYTE $0x08 // PALIGNR $8, X8, X8
+#define shiftC3Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xf6; BYTE $0x08 // PALIGNR $8, X14, X14
+#define shiftD0Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xc9; BYTE $0x0c // PALIGNR $12, X9, X9
+#define shiftD1Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xd2; BYTE $0x0c // PALIGNR $12, X10, X10
+#define shiftD2Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xdb; BYTE $0x0c // PALIGNR $12, X11, X11
+#define shiftD3Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xff; BYTE $0x0c // PALIGNR $12, X15, X15
+#define shiftB0Right BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xdb; BYTE $0x0c // PALIGNR $12, X3, X3
+#define shiftB1Right BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xe4; BYTE $0x0c // PALIGNR $12, X4, X4
+#define shiftB2Right BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xed; BYTE $0x0c // PALIGNR $12, X5, X5
+#define shiftB3Right BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xed; BYTE $0x0c // PALIGNR $12, X13, X13
+#define shiftC0Right shiftC0Left
+#define shiftC1Right shiftC1Left
+#define shiftC2Right shiftC2Left
+#define shiftC3Right shiftC3Left
+#define shiftD0Right BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xc9; BYTE $0x04 // PALIGNR $4, X9, X9
+#define shiftD1Right BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xd2; BYTE $0x04 // PALIGNR $4, X10, X10
+#define shiftD2Right BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xdb; BYTE $0x04 // PALIGNR $4, X11, X11
+#define shiftD3Right BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xff; BYTE $0x04 // PALIGNR $4, X15, X15
+// Some macros
+#define chachaQR(A, B, C, D, T) \
+ PADDD B, A; PXOR A, D; PSHUFB ·rol16<>(SB), D \
+ PADDD D, C; PXOR C, B; MOVO B, T; PSLLL $12, T; PSRLL $20, B; PXOR T, B \
+ PADDD B, A; PXOR A, D; PSHUFB ·rol8<>(SB), D \
+ PADDD D, C; PXOR C, B; MOVO B, T; PSLLL $7, T; PSRLL $25, B; PXOR T, B
+
+#define chachaQR_AVX2(A, B, C, D, T) \
+ VPADDD B, A, A; VPXOR A, D, D; VPSHUFB ·rol16<>(SB), D, D \
+ VPADDD D, C, C; VPXOR C, B, B; VPSLLD $12, B, T; VPSRLD $20, B, B; VPXOR T, B, B \
+ VPADDD B, A, A; VPXOR A, D, D; VPSHUFB ·rol8<>(SB), D, D \
+ VPADDD D, C, C; VPXOR C, B, B; VPSLLD $7, B, T; VPSRLD $25, B, B; VPXOR T, B, B
+
+#define polyAdd(S) ADDQ S, acc0; ADCQ 8+S, acc1; ADCQ $1, acc2
+#define polyMulStage1 MOVQ (0*8)(BP), AX; MOVQ AX, t2; MULQ acc0; MOVQ AX, t0; MOVQ DX, t1; MOVQ (0*8)(BP), AX; MULQ acc1; IMULQ acc2, t2; ADDQ AX, t1; ADCQ DX, t2
+#define polyMulStage2 MOVQ (1*8)(BP), AX; MOVQ AX, t3; MULQ acc0; ADDQ AX, t1; ADCQ $0, DX; MOVQ DX, acc0; MOVQ (1*8)(BP), AX; MULQ acc1; ADDQ AX, t2; ADCQ $0, DX
+#define polyMulStage3 IMULQ acc2, t3; ADDQ acc0, t2; ADCQ DX, t3
+#define polyMulReduceStage MOVQ t0, acc0; MOVQ t1, acc1; MOVQ t2, acc2; ANDQ $3, acc2; MOVQ t2, t0; ANDQ $-4, t0; MOVQ t3, t1; SHRQ $2, t2:t3; SHRQ $2, t3; ADDQ t0, acc0; ADCQ t1, acc1; ADCQ $0, acc2; ADDQ t2, acc0; ADCQ t3, acc1; ADCQ $0, acc2
+
+#define polyMulStage1_AVX2 MOVQ (0*8)(BP), DX; MOVQ DX, t2; MULXQ acc0, t0, t1; IMULQ acc2, t2; MULXQ acc1, AX, DX; ADDQ AX, t1; ADCQ DX, t2
+#define polyMulStage2_AVX2 MOVQ (1*8)(BP), DX; MULXQ acc0, acc0, AX; ADDQ acc0, t1; MULXQ acc1, acc1, t3; ADCQ acc1, t2; ADCQ $0, t3
+#define polyMulStage3_AVX2 IMULQ acc2, DX; ADDQ AX, t2; ADCQ DX, t3
+
+#define polyMul polyMulStage1; polyMulStage2; polyMulStage3; polyMulReduceStage
+#define polyMulAVX2 polyMulStage1_AVX2; polyMulStage2_AVX2; polyMulStage3_AVX2; polyMulReduceStage
+// ----------------------------------------------------------------------------
+TEXT polyHashADInternal<>(SB), NOSPLIT, $0
+ // adp points to beginning of additional data
+ // itr2 holds ad length
+ XORQ acc0, acc0
+ XORQ acc1, acc1
+ XORQ acc2, acc2
+ CMPQ itr2, $13
+ JNE hashADLoop
+
+openFastTLSAD:
+ // Special treatment for the TLS case of 13 bytes
+ MOVQ (adp), acc0
+ MOVQ 5(adp), acc1
+ SHRQ $24, acc1
+ MOVQ $1, acc2
+ polyMul
+ RET
+
+hashADLoop:
+ // Hash in 16 byte chunks
+ CMPQ itr2, $16
+ JB hashADTail
+ polyAdd(0(adp))
+ LEAQ (1*16)(adp), adp
+ SUBQ $16, itr2
+ polyMul
+ JMP hashADLoop
+
+hashADTail:
+ CMPQ itr2, $0
+ JE hashADDone
+
+ // Hash last < 16 byte tail
+ XORQ t0, t0
+ XORQ t1, t1
+ XORQ t2, t2
+ ADDQ itr2, adp
+
+hashADTailLoop:
+ SHLQ $8, t1:t0
+ SHLQ $8, t0
+ MOVB -1(adp), t2
+ XORQ t2, t0
+ DECQ adp
+ DECQ itr2
+ JNE hashADTailLoop
+
+hashADTailFinish:
+ ADDQ t0, acc0; ADCQ t1, acc1; ADCQ $1, acc2
+ polyMul
+
+ // Finished AD
+hashADDone:
+ RET
+
+// ----------------------------------------------------------------------------
+// func chacha20Poly1305Open(dst, key, src, ad []byte) bool
+TEXT ·chacha20Poly1305Open(SB), 0, $288-97
+ // For aligned stack access
+ MOVQ SP, BP
+ ADDQ $32, BP
+ ANDQ $-32, BP
+ MOVQ dst+0(FP), oup
+ MOVQ key+24(FP), keyp
+ MOVQ src+48(FP), inp
+ MOVQ src_len+56(FP), inl
+ MOVQ ad+72(FP), adp
+
+ // Check for AVX2 support
+ CMPB ·useAVX2(SB), $1
+ JE chacha20Poly1305Open_AVX2
+
+ // Special optimization, for very short buffers
+ CMPQ inl, $128
+ JBE openSSE128 // About 16% faster
+
+ // For long buffers, prepare the poly key first
+ MOVOU ·chacha20Constants<>(SB), A0
+ MOVOU (1*16)(keyp), B0
+ MOVOU (2*16)(keyp), C0
+ MOVOU (3*16)(keyp), D0
+ MOVO D0, T1
+
+ // Store state on stack for future use
+ MOVO B0, state1Store
+ MOVO C0, state2Store
+ MOVO D0, ctr3Store
+ MOVQ $10, itr2
+
+openSSEPreparePolyKey:
+ chachaQR(A0, B0, C0, D0, T0)
+ shiftB0Left; shiftC0Left; shiftD0Left
+ chachaQR(A0, B0, C0, D0, T0)
+ shiftB0Right; shiftC0Right; shiftD0Right
+ DECQ itr2
+ JNE openSSEPreparePolyKey
+
+ // A0|B0 hold the Poly1305 32-byte key, C0,D0 can be discarded
+ PADDL ·chacha20Constants<>(SB), A0; PADDL state1Store, B0
+
+ // Clamp and store the key
+ PAND ·polyClampMask<>(SB), A0
+ MOVO A0, rStore; MOVO B0, sStore
+
+ // Hash AAD
+ MOVQ ad_len+80(FP), itr2
+ CALL polyHashADInternal<>(SB)
+
+openSSEMainLoop:
+ CMPQ inl, $256
+ JB openSSEMainLoopDone
+
+ // Load state, increment counter blocks
+ MOVO ·chacha20Constants<>(SB), A0; MOVO state1Store, B0; MOVO state2Store, C0; MOVO ctr3Store, D0; PADDL ·sseIncMask<>(SB), D0
+ MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL ·sseIncMask<>(SB), D1
+ MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL ·sseIncMask<>(SB), D2
+ MOVO A2, A3; MOVO B2, B3; MOVO C2, C3; MOVO D2, D3; PADDL ·sseIncMask<>(SB), D3
+
+ // Store counters
+ MOVO D0, ctr0Store; MOVO D1, ctr1Store; MOVO D2, ctr2Store; MOVO D3, ctr3Store
+
+ // There are 10 ChaCha20 iterations of 2QR each, so for 6 iterations we hash 2 blocks, and for the remaining 4 only 1 block - for a total of 16
+ MOVQ $4, itr1
+ MOVQ inp, itr2
+
+openSSEInternalLoop:
+ MOVO C3, tmpStore
+ chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3)
+ MOVO tmpStore, C3
+ MOVO C1, tmpStore
+ chachaQR(A3, B3, C3, D3, C1)
+ MOVO tmpStore, C1
+ polyAdd(0(itr2))
+ shiftB0Left; shiftB1Left; shiftB2Left; shiftB3Left
+ shiftC0Left; shiftC1Left; shiftC2Left; shiftC3Left
+ shiftD0Left; shiftD1Left; shiftD2Left; shiftD3Left
+ polyMulStage1
+ polyMulStage2
+ LEAQ (2*8)(itr2), itr2
+ MOVO C3, tmpStore
+ chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3)
+ MOVO tmpStore, C3
+ MOVO C1, tmpStore
+ polyMulStage3
+ chachaQR(A3, B3, C3, D3, C1)
+ MOVO tmpStore, C1
+ polyMulReduceStage
+ shiftB0Right; shiftB1Right; shiftB2Right; shiftB3Right
+ shiftC0Right; shiftC1Right; shiftC2Right; shiftC3Right
+ shiftD0Right; shiftD1Right; shiftD2Right; shiftD3Right
+ DECQ itr1
+ JGE openSSEInternalLoop
+
+ polyAdd(0(itr2))
+ polyMul
+ LEAQ (2*8)(itr2), itr2
+
+ CMPQ itr1, $-6
+ JG openSSEInternalLoop
+
+ // Add in the state
+ PADDD ·chacha20Constants<>(SB), A0; PADDD ·chacha20Constants<>(SB), A1; PADDD ·chacha20Constants<>(SB), A2; PADDD ·chacha20Constants<>(SB), A3
+ PADDD state1Store, B0; PADDD state1Store, B1; PADDD state1Store, B2; PADDD state1Store, B3
+ PADDD state2Store, C0; PADDD state2Store, C1; PADDD state2Store, C2; PADDD state2Store, C3
+ PADDD ctr0Store, D0; PADDD ctr1Store, D1; PADDD ctr2Store, D2; PADDD ctr3Store, D3
+
+ // Load - xor - store
+ MOVO D3, tmpStore
+ MOVOU (0*16)(inp), D3; PXOR D3, A0; MOVOU A0, (0*16)(oup)
+ MOVOU (1*16)(inp), D3; PXOR D3, B0; MOVOU B0, (1*16)(oup)
+ MOVOU (2*16)(inp), D3; PXOR D3, C0; MOVOU C0, (2*16)(oup)
+ MOVOU (3*16)(inp), D3; PXOR D3, D0; MOVOU D0, (3*16)(oup)
+ MOVOU (4*16)(inp), D0; PXOR D0, A1; MOVOU A1, (4*16)(oup)
+ MOVOU (5*16)(inp), D0; PXOR D0, B1; MOVOU B1, (5*16)(oup)
+ MOVOU (6*16)(inp), D0; PXOR D0, C1; MOVOU C1, (6*16)(oup)
+ MOVOU (7*16)(inp), D0; PXOR D0, D1; MOVOU D1, (7*16)(oup)
+ MOVOU (8*16)(inp), D0; PXOR D0, A2; MOVOU A2, (8*16)(oup)
+ MOVOU (9*16)(inp), D0; PXOR D0, B2; MOVOU B2, (9*16)(oup)
+ MOVOU (10*16)(inp), D0; PXOR D0, C2; MOVOU C2, (10*16)(oup)
+ MOVOU (11*16)(inp), D0; PXOR D0, D2; MOVOU D2, (11*16)(oup)
+ MOVOU (12*16)(inp), D0; PXOR D0, A3; MOVOU A3, (12*16)(oup)
+ MOVOU (13*16)(inp), D0; PXOR D0, B3; MOVOU B3, (13*16)(oup)
+ MOVOU (14*16)(inp), D0; PXOR D0, C3; MOVOU C3, (14*16)(oup)
+ MOVOU (15*16)(inp), D0; PXOR tmpStore, D0; MOVOU D0, (15*16)(oup)
+ LEAQ 256(inp), inp
+ LEAQ 256(oup), oup
+ SUBQ $256, inl
+ JMP openSSEMainLoop
+
+openSSEMainLoopDone:
+ // Handle the various tail sizes efficiently
+ TESTQ inl, inl
+ JE openSSEFinalize
+ CMPQ inl, $64
+ JBE openSSETail64
+ CMPQ inl, $128
+ JBE openSSETail128
+ CMPQ inl, $192
+ JBE openSSETail192
+ JMP openSSETail256
+
+openSSEFinalize:
+ // Hash in the PT, AAD lengths
+ ADDQ ad_len+80(FP), acc0; ADCQ src_len+56(FP), acc1; ADCQ $1, acc2
+ polyMul
+
+ // Final reduce
+ MOVQ acc0, t0
+ MOVQ acc1, t1
+ MOVQ acc2, t2
+ SUBQ $-5, acc0
+ SBBQ $-1, acc1
+ SBBQ $3, acc2
+ CMOVQCS t0, acc0
+ CMOVQCS t1, acc1
+ CMOVQCS t2, acc2
+
+ // Add in the "s" part of the key
+ ADDQ 0+sStore, acc0
+ ADCQ 8+sStore, acc1
+
+ // Finally, constant time compare to the tag at the end of the message
+ XORQ AX, AX
+ MOVQ $1, DX
+ XORQ (0*8)(inp), acc0
+ XORQ (1*8)(inp), acc1
+ ORQ acc1, acc0
+ CMOVQEQ DX, AX
+
+ // Return true iff tags are equal
+ MOVB AX, ret+96(FP)
+ RET
+
+// ----------------------------------------------------------------------------
+// Special optimization for buffers smaller than 129 bytes
+openSSE128:
+ // For up to 128 bytes of ciphertext and 64 bytes for the poly key, we require to process three blocks
+ MOVOU ·chacha20Constants<>(SB), A0; MOVOU (1*16)(keyp), B0; MOVOU (2*16)(keyp), C0; MOVOU (3*16)(keyp), D0
+ MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL ·sseIncMask<>(SB), D1
+ MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL ·sseIncMask<>(SB), D2
+ MOVO B0, T1; MOVO C0, T2; MOVO D1, T3
+ MOVQ $10, itr2
+
+openSSE128InnerCipherLoop:
+ chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0)
+ shiftB0Left; shiftB1Left; shiftB2Left
+ shiftC0Left; shiftC1Left; shiftC2Left
+ shiftD0Left; shiftD1Left; shiftD2Left
+ chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0)
+ shiftB0Right; shiftB1Right; shiftB2Right
+ shiftC0Right; shiftC1Right; shiftC2Right
+ shiftD0Right; shiftD1Right; shiftD2Right
+ DECQ itr2
+ JNE openSSE128InnerCipherLoop
+
+ // A0|B0 hold the Poly1305 32-byte key, C0,D0 can be discarded
+ PADDL ·chacha20Constants<>(SB), A0; PADDL ·chacha20Constants<>(SB), A1; PADDL ·chacha20Constants<>(SB), A2
+ PADDL T1, B0; PADDL T1, B1; PADDL T1, B2
+ PADDL T2, C1; PADDL T2, C2
+ PADDL T3, D1; PADDL ·sseIncMask<>(SB), T3; PADDL T3, D2
+
+ // Clamp and store the key
+ PAND ·polyClampMask<>(SB), A0
+ MOVOU A0, rStore; MOVOU B0, sStore
+
+ // Hash
+ MOVQ ad_len+80(FP), itr2
+ CALL polyHashADInternal<>(SB)
+
+openSSE128Open:
+ CMPQ inl, $16
+ JB openSSETail16
+ SUBQ $16, inl
+
+ // Load for hashing
+ polyAdd(0(inp))
+
+ // Load for decryption
+ MOVOU (inp), T0; PXOR T0, A1; MOVOU A1, (oup)
+ LEAQ (1*16)(inp), inp
+ LEAQ (1*16)(oup), oup
+ polyMul
+
+ // Shift the stream "left"
+ MOVO B1, A1
+ MOVO C1, B1
+ MOVO D1, C1
+ MOVO A2, D1
+ MOVO B2, A2
+ MOVO C2, B2
+ MOVO D2, C2
+ JMP openSSE128Open
+
+openSSETail16:
+ TESTQ inl, inl
+ JE openSSEFinalize
+
+ // We can safely load the CT from the end, because it is padded with the MAC
+ MOVQ inl, itr2
+ SHLQ $4, itr2
+ LEAQ ·andMask<>(SB), t0
+ MOVOU (inp), T0
+ ADDQ inl, inp
+ PAND -16(t0)(itr2*1), T0
+ MOVO T0, 0+tmpStore
+ MOVQ T0, t0
+ MOVQ 8+tmpStore, t1
+ PXOR A1, T0
+
+ // We can only store one byte at a time, since plaintext can be shorter than 16 bytes
+openSSETail16Store:
+ MOVQ T0, t3
+ MOVB t3, (oup)
+ PSRLDQ $1, T0
+ INCQ oup
+ DECQ inl
+ JNE openSSETail16Store
+ ADDQ t0, acc0; ADCQ t1, acc1; ADCQ $1, acc2
+ polyMul
+ JMP openSSEFinalize
+
+// ----------------------------------------------------------------------------
+// Special optimization for the last 64 bytes of ciphertext
+openSSETail64:
+ // Need to decrypt up to 64 bytes - prepare single block
+ MOVO ·chacha20Constants<>(SB), A0; MOVO state1Store, B0; MOVO state2Store, C0; MOVO ctr3Store, D0; PADDL ·sseIncMask<>(SB), D0; MOVO D0, ctr0Store
+ XORQ itr2, itr2
+ MOVQ inl, itr1
+ CMPQ itr1, $16
+ JB openSSETail64LoopB
+
+openSSETail64LoopA:
+ // Perform ChaCha rounds, while hashing the remaining input
+ polyAdd(0(inp)(itr2*1))
+ polyMul
+ SUBQ $16, itr1
+
+openSSETail64LoopB:
+ ADDQ $16, itr2
+ chachaQR(A0, B0, C0, D0, T0)
+ shiftB0Left; shiftC0Left; shiftD0Left
+ chachaQR(A0, B0, C0, D0, T0)
+ shiftB0Right; shiftC0Right; shiftD0Right
+
+ CMPQ itr1, $16
+ JAE openSSETail64LoopA
+
+ CMPQ itr2, $160
+ JNE openSSETail64LoopB
+
+ PADDL ·chacha20Constants<>(SB), A0; PADDL state1Store, B0; PADDL state2Store, C0; PADDL ctr0Store, D0
+
+openSSETail64DecLoop:
+ CMPQ inl, $16
+ JB openSSETail64DecLoopDone
+ SUBQ $16, inl
+ MOVOU (inp), T0
+ PXOR T0, A0
+ MOVOU A0, (oup)
+ LEAQ 16(inp), inp
+ LEAQ 16(oup), oup
+ MOVO B0, A0
+ MOVO C0, B0
+ MOVO D0, C0
+ JMP openSSETail64DecLoop
+
+openSSETail64DecLoopDone:
+ MOVO A0, A1
+ JMP openSSETail16
+
+// ----------------------------------------------------------------------------
+// Special optimization for the last 128 bytes of ciphertext
+openSSETail128:
+ // Need to decrypt up to 128 bytes - prepare two blocks
+ MOVO ·chacha20Constants<>(SB), A1; MOVO state1Store, B1; MOVO state2Store, C1; MOVO ctr3Store, D1; PADDL ·sseIncMask<>(SB), D1; MOVO D1, ctr0Store
+ MOVO A1, A0; MOVO B1, B0; MOVO C1, C0; MOVO D1, D0; PADDL ·sseIncMask<>(SB), D0; MOVO D0, ctr1Store
+ XORQ itr2, itr2
+ MOVQ inl, itr1
+ ANDQ $-16, itr1
+
+openSSETail128LoopA:
+ // Perform ChaCha rounds, while hashing the remaining input
+ polyAdd(0(inp)(itr2*1))
+ polyMul
+
+openSSETail128LoopB:
+ ADDQ $16, itr2
+ chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0)
+ shiftB0Left; shiftC0Left; shiftD0Left
+ shiftB1Left; shiftC1Left; shiftD1Left
+ chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0)
+ shiftB0Right; shiftC0Right; shiftD0Right
+ shiftB1Right; shiftC1Right; shiftD1Right
+
+ CMPQ itr2, itr1
+ JB openSSETail128LoopA
+
+ CMPQ itr2, $160
+ JNE openSSETail128LoopB
+
+ PADDL ·chacha20Constants<>(SB), A0; PADDL ·chacha20Constants<>(SB), A1
+ PADDL state1Store, B0; PADDL state1Store, B1
+ PADDL state2Store, C0; PADDL state2Store, C1
+ PADDL ctr1Store, D0; PADDL ctr0Store, D1
+
+ MOVOU (0*16)(inp), T0; MOVOU (1*16)(inp), T1; MOVOU (2*16)(inp), T2; MOVOU (3*16)(inp), T3
+ PXOR T0, A1; PXOR T1, B1; PXOR T2, C1; PXOR T3, D1
+ MOVOU A1, (0*16)(oup); MOVOU B1, (1*16)(oup); MOVOU C1, (2*16)(oup); MOVOU D1, (3*16)(oup)
+
+ SUBQ $64, inl
+ LEAQ 64(inp), inp
+ LEAQ 64(oup), oup
+ JMP openSSETail64DecLoop
+
+// ----------------------------------------------------------------------------
+// Special optimization for the last 192 bytes of ciphertext
+openSSETail192:
+ // Need to decrypt up to 192 bytes - prepare three blocks
+ MOVO ·chacha20Constants<>(SB), A2; MOVO state1Store, B2; MOVO state2Store, C2; MOVO ctr3Store, D2; PADDL ·sseIncMask<>(SB), D2; MOVO D2, ctr0Store
+ MOVO A2, A1; MOVO B2, B1; MOVO C2, C1; MOVO D2, D1; PADDL ·sseIncMask<>(SB), D1; MOVO D1, ctr1Store
+ MOVO A1, A0; MOVO B1, B0; MOVO C1, C0; MOVO D1, D0; PADDL ·sseIncMask<>(SB), D0; MOVO D0, ctr2Store
+
+ MOVQ inl, itr1
+ MOVQ $160, itr2
+ CMPQ itr1, $160
+ CMOVQGT itr2, itr1
+ ANDQ $-16, itr1
+ XORQ itr2, itr2
+
+openSSLTail192LoopA:
+ // Perform ChaCha rounds, while hashing the remaining input
+ polyAdd(0(inp)(itr2*1))
+ polyMul
+
+openSSLTail192LoopB:
+ ADDQ $16, itr2
+ chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0)
+ shiftB0Left; shiftC0Left; shiftD0Left
+ shiftB1Left; shiftC1Left; shiftD1Left
+ shiftB2Left; shiftC2Left; shiftD2Left
+
+ chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0)
+ shiftB0Right; shiftC0Right; shiftD0Right
+ shiftB1Right; shiftC1Right; shiftD1Right
+ shiftB2Right; shiftC2Right; shiftD2Right
+
+ CMPQ itr2, itr1
+ JB openSSLTail192LoopA
+
+ CMPQ itr2, $160
+ JNE openSSLTail192LoopB
+
+ CMPQ inl, $176
+ JB openSSLTail192Store
+
+ polyAdd(160(inp))
+ polyMul
+
+ CMPQ inl, $192
+ JB openSSLTail192Store
+
+ polyAdd(176(inp))
+ polyMul
+
+openSSLTail192Store:
+ PADDL ·chacha20Constants<>(SB), A0; PADDL ·chacha20Constants<>(SB), A1; PADDL ·chacha20Constants<>(SB), A2
+ PADDL state1Store, B0; PADDL state1Store, B1; PADDL state1Store, B2
+ PADDL state2Store, C0; PADDL state2Store, C1; PADDL state2Store, C2
+ PADDL ctr2Store, D0; PADDL ctr1Store, D1; PADDL ctr0Store, D2
+
+ MOVOU (0*16)(inp), T0; MOVOU (1*16)(inp), T1; MOVOU (2*16)(inp), T2; MOVOU (3*16)(inp), T3
+ PXOR T0, A2; PXOR T1, B2; PXOR T2, C2; PXOR T3, D2
+ MOVOU A2, (0*16)(oup); MOVOU B2, (1*16)(oup); MOVOU C2, (2*16)(oup); MOVOU D2, (3*16)(oup)
+
+ MOVOU (4*16)(inp), T0; MOVOU (5*16)(inp), T1; MOVOU (6*16)(inp), T2; MOVOU (7*16)(inp), T3
+ PXOR T0, A1; PXOR T1, B1; PXOR T2, C1; PXOR T3, D1
+ MOVOU A1, (4*16)(oup); MOVOU B1, (5*16)(oup); MOVOU C1, (6*16)(oup); MOVOU D1, (7*16)(oup)
+
+ SUBQ $128, inl
+ LEAQ 128(inp), inp
+ LEAQ 128(oup), oup
+ JMP openSSETail64DecLoop
+
+// ----------------------------------------------------------------------------
+// Special optimization for the last 256 bytes of ciphertext
+openSSETail256:
+ // Need to decrypt up to 256 bytes - prepare four blocks
+ MOVO ·chacha20Constants<>(SB), A0; MOVO state1Store, B0; MOVO state2Store, C0; MOVO ctr3Store, D0; PADDL ·sseIncMask<>(SB), D0
+ MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL ·sseIncMask<>(SB), D1
+ MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL ·sseIncMask<>(SB), D2
+ MOVO A2, A3; MOVO B2, B3; MOVO C2, C3; MOVO D2, D3; PADDL ·sseIncMask<>(SB), D3
+
+ // Store counters
+ MOVO D0, ctr0Store; MOVO D1, ctr1Store; MOVO D2, ctr2Store; MOVO D3, ctr3Store
+ XORQ itr2, itr2
+
+openSSETail256Loop:
+ // This loop inteleaves 8 ChaCha quarter rounds with 1 poly multiplication
+ polyAdd(0(inp)(itr2*1))
+ MOVO C3, tmpStore
+ chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3)
+ MOVO tmpStore, C3
+ MOVO C1, tmpStore
+ chachaQR(A3, B3, C3, D3, C1)
+ MOVO tmpStore, C1
+ shiftB0Left; shiftB1Left; shiftB2Left; shiftB3Left
+ shiftC0Left; shiftC1Left; shiftC2Left; shiftC3Left
+ shiftD0Left; shiftD1Left; shiftD2Left; shiftD3Left
+ polyMulStage1
+ polyMulStage2
+ MOVO C3, tmpStore
+ chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3)
+ MOVO tmpStore, C3
+ MOVO C1, tmpStore
+ chachaQR(A3, B3, C3, D3, C1)
+ MOVO tmpStore, C1
+ polyMulStage3
+ polyMulReduceStage
+ shiftB0Right; shiftB1Right; shiftB2Right; shiftB3Right
+ shiftC0Right; shiftC1Right; shiftC2Right; shiftC3Right
+ shiftD0Right; shiftD1Right; shiftD2Right; shiftD3Right
+ ADDQ $2*8, itr2
+ CMPQ itr2, $160
+ JB openSSETail256Loop
+ MOVQ inl, itr1
+ ANDQ $-16, itr1
+
+openSSETail256HashLoop:
+ polyAdd(0(inp)(itr2*1))
+ polyMul
+ ADDQ $2*8, itr2
+ CMPQ itr2, itr1
+ JB openSSETail256HashLoop
+
+ // Add in the state
+ PADDD ·chacha20Constants<>(SB), A0; PADDD ·chacha20Constants<>(SB), A1; PADDD ·chacha20Constants<>(SB), A2; PADDD ·chacha20Constants<>(SB), A3
+ PADDD state1Store, B0; PADDD state1Store, B1; PADDD state1Store, B2; PADDD state1Store, B3
+ PADDD state2Store, C0; PADDD state2Store, C1; PADDD state2Store, C2; PADDD state2Store, C3
+ PADDD ctr0Store, D0; PADDD ctr1Store, D1; PADDD ctr2Store, D2; PADDD ctr3Store, D3
+ MOVO D3, tmpStore
+
+ // Load - xor - store
+ MOVOU (0*16)(inp), D3; PXOR D3, A0
+ MOVOU (1*16)(inp), D3; PXOR D3, B0
+ MOVOU (2*16)(inp), D3; PXOR D3, C0
+ MOVOU (3*16)(inp), D3; PXOR D3, D0
+ MOVOU A0, (0*16)(oup)
+ MOVOU B0, (1*16)(oup)
+ MOVOU C0, (2*16)(oup)
+ MOVOU D0, (3*16)(oup)
+ MOVOU (4*16)(inp), A0; MOVOU (5*16)(inp), B0; MOVOU (6*16)(inp), C0; MOVOU (7*16)(inp), D0
+ PXOR A0, A1; PXOR B0, B1; PXOR C0, C1; PXOR D0, D1
+ MOVOU A1, (4*16)(oup); MOVOU B1, (5*16)(oup); MOVOU C1, (6*16)(oup); MOVOU D1, (7*16)(oup)
+ MOVOU (8*16)(inp), A0; MOVOU (9*16)(inp), B0; MOVOU (10*16)(inp), C0; MOVOU (11*16)(inp), D0
+ PXOR A0, A2; PXOR B0, B2; PXOR C0, C2; PXOR D0, D2
+ MOVOU A2, (8*16)(oup); MOVOU B2, (9*16)(oup); MOVOU C2, (10*16)(oup); MOVOU D2, (11*16)(oup)
+ LEAQ 192(inp), inp
+ LEAQ 192(oup), oup
+ SUBQ $192, inl
+ MOVO A3, A0
+ MOVO B3, B0
+ MOVO C3, C0
+ MOVO tmpStore, D0
+
+ JMP openSSETail64DecLoop
+
+// ----------------------------------------------------------------------------
+// ------------------------- AVX2 Code ----------------------------------------
+chacha20Poly1305Open_AVX2:
+ VZEROUPPER
+ VMOVDQU ·chacha20Constants<>(SB), AA0
+ BYTE $0xc4; BYTE $0x42; BYTE $0x7d; BYTE $0x5a; BYTE $0x70; BYTE $0x10 // broadcasti128 16(r8), ymm14
+ BYTE $0xc4; BYTE $0x42; BYTE $0x7d; BYTE $0x5a; BYTE $0x60; BYTE $0x20 // broadcasti128 32(r8), ymm12
+ BYTE $0xc4; BYTE $0xc2; BYTE $0x7d; BYTE $0x5a; BYTE $0x60; BYTE $0x30 // broadcasti128 48(r8), ymm4
+ VPADDD ·avx2InitMask<>(SB), DD0, DD0
+
+ // Special optimization, for very short buffers
+ CMPQ inl, $192
+ JBE openAVX2192
+ CMPQ inl, $320
+ JBE openAVX2320
+
+ // For the general key prepare the key first - as a byproduct we have 64 bytes of cipher stream
+ VMOVDQA BB0, state1StoreAVX2
+ VMOVDQA CC0, state2StoreAVX2
+ VMOVDQA DD0, ctr3StoreAVX2
+ MOVQ $10, itr2
+
+openAVX2PreparePolyKey:
+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0)
+ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $12, DD0, DD0, DD0
+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0)
+ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $4, DD0, DD0, DD0
+ DECQ itr2
+ JNE openAVX2PreparePolyKey
+
+ VPADDD ·chacha20Constants<>(SB), AA0, AA0
+ VPADDD state1StoreAVX2, BB0, BB0
+ VPADDD state2StoreAVX2, CC0, CC0
+ VPADDD ctr3StoreAVX2, DD0, DD0
+
+ VPERM2I128 $0x02, AA0, BB0, TT0
+
+ // Clamp and store poly key
+ VPAND ·polyClampMask<>(SB), TT0, TT0
+ VMOVDQA TT0, rsStoreAVX2
+
+ // Stream for the first 64 bytes
+ VPERM2I128 $0x13, AA0, BB0, AA0
+ VPERM2I128 $0x13, CC0, DD0, BB0
+
+ // Hash AD + first 64 bytes
+ MOVQ ad_len+80(FP), itr2
+ CALL polyHashADInternal<>(SB)
+ XORQ itr1, itr1
+
+openAVX2InitialHash64:
+ polyAdd(0(inp)(itr1*1))
+ polyMulAVX2
+ ADDQ $16, itr1
+ CMPQ itr1, $64
+ JNE openAVX2InitialHash64
+
+ // Decrypt the first 64 bytes
+ VPXOR (0*32)(inp), AA0, AA0
+ VPXOR (1*32)(inp), BB0, BB0
+ VMOVDQU AA0, (0*32)(oup)
+ VMOVDQU BB0, (1*32)(oup)
+ LEAQ (2*32)(inp), inp
+ LEAQ (2*32)(oup), oup
+ SUBQ $64, inl
+
+openAVX2MainLoop:
+ CMPQ inl, $512
+ JB openAVX2MainLoopDone
+
+ // Load state, increment counter blocks, store the incremented counters
+ VMOVDQU ·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2; VMOVDQA AA0, AA3
+ VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2; VMOVDQA BB0, BB3
+ VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2; VMOVDQA CC0, CC3
+ VMOVDQA ctr3StoreAVX2, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD1; VPADDD ·avx2IncMask<>(SB), DD1, DD2; VPADDD ·avx2IncMask<>(SB), DD2, DD3
+ VMOVDQA DD0, ctr0StoreAVX2; VMOVDQA DD1, ctr1StoreAVX2; VMOVDQA DD2, ctr2StoreAVX2; VMOVDQA DD3, ctr3StoreAVX2
+ XORQ itr1, itr1
+
+openAVX2InternalLoop:
+ // Lets just say this spaghetti loop interleaves 2 quarter rounds with 3 poly multiplications
+ // Effectively per 512 bytes of stream we hash 480 bytes of ciphertext
+ polyAdd(0*8(inp)(itr1*1))
+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3
+ polyMulStage1_AVX2
+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3
+ VPSHUFB ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3
+ polyMulStage2_AVX2
+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3
+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3
+ polyMulStage3_AVX2
+ VMOVDQA CC3, tmpStoreAVX2
+ VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0
+ VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1
+ VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2
+ VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3
+ VMOVDQA tmpStoreAVX2, CC3
+ polyMulReduceStage
+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3
+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3
+ VPSHUFB ·rol8<>(SB), DD0, DD0; VPSHUFB ·rol8<>(SB), DD1, DD1; VPSHUFB ·rol8<>(SB), DD2, DD2; VPSHUFB ·rol8<>(SB), DD3, DD3
+ polyAdd(2*8(inp)(itr1*1))
+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3
+ polyMulStage1_AVX2
+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3
+ VMOVDQA CC3, tmpStoreAVX2
+ VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0
+ VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1
+ VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2
+ VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3
+ VMOVDQA tmpStoreAVX2, CC3
+ polyMulStage2_AVX2
+ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2; VPALIGNR $4, BB3, BB3, BB3
+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3
+ VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2; VPALIGNR $12, DD3, DD3, DD3
+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3
+ polyMulStage3_AVX2
+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3
+ VPSHUFB ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3
+ polyMulReduceStage
+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3
+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3
+ polyAdd(4*8(inp)(itr1*1))
+ LEAQ (6*8)(itr1), itr1
+ VMOVDQA CC3, tmpStoreAVX2
+ VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0
+ VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1
+ VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2
+ VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3
+ VMOVDQA tmpStoreAVX2, CC3
+ polyMulStage1_AVX2
+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3
+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3
+ polyMulStage2_AVX2
+ VPSHUFB ·rol8<>(SB), DD0, DD0; VPSHUFB ·rol8<>(SB), DD1, DD1; VPSHUFB ·rol8<>(SB), DD2, DD2; VPSHUFB ·rol8<>(SB), DD3, DD3
+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3
+ polyMulStage3_AVX2
+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3
+ VMOVDQA CC3, tmpStoreAVX2
+ VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0
+ VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1
+ VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2
+ VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3
+ VMOVDQA tmpStoreAVX2, CC3
+ polyMulReduceStage
+ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2; VPALIGNR $12, BB3, BB3, BB3
+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3
+ VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2; VPALIGNR $4, DD3, DD3, DD3
+ CMPQ itr1, $480
+ JNE openAVX2InternalLoop
+
+ VPADDD ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1; VPADDD ·chacha20Constants<>(SB), AA2, AA2; VPADDD ·chacha20Constants<>(SB), AA3, AA3
+ VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2; VPADDD state1StoreAVX2, BB3, BB3
+ VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2; VPADDD state2StoreAVX2, CC3, CC3
+ VPADDD ctr0StoreAVX2, DD0, DD0; VPADDD ctr1StoreAVX2, DD1, DD1; VPADDD ctr2StoreAVX2, DD2, DD2; VPADDD ctr3StoreAVX2, DD3, DD3
+ VMOVDQA CC3, tmpStoreAVX2
+
+ // We only hashed 480 of the 512 bytes available - hash the remaining 32 here
+ polyAdd(480(inp))
+ polyMulAVX2
+ VPERM2I128 $0x02, AA0, BB0, CC3; VPERM2I128 $0x13, AA0, BB0, BB0; VPERM2I128 $0x02, CC0, DD0, AA0; VPERM2I128 $0x13, CC0, DD0, CC0
+ VPXOR (0*32)(inp), CC3, CC3; VPXOR (1*32)(inp), AA0, AA0; VPXOR (2*32)(inp), BB0, BB0; VPXOR (3*32)(inp), CC0, CC0
+ VMOVDQU CC3, (0*32)(oup); VMOVDQU AA0, (1*32)(oup); VMOVDQU BB0, (2*32)(oup); VMOVDQU CC0, (3*32)(oup)
+ VPERM2I128 $0x02, AA1, BB1, AA0; VPERM2I128 $0x02, CC1, DD1, BB0; VPERM2I128 $0x13, AA1, BB1, CC0; VPERM2I128 $0x13, CC1, DD1, DD0
+ VPXOR (4*32)(inp), AA0, AA0; VPXOR (5*32)(inp), BB0, BB0; VPXOR (6*32)(inp), CC0, CC0; VPXOR (7*32)(inp), DD0, DD0
+ VMOVDQU AA0, (4*32)(oup); VMOVDQU BB0, (5*32)(oup); VMOVDQU CC0, (6*32)(oup); VMOVDQU DD0, (7*32)(oup)
+
+ // and here
+ polyAdd(496(inp))
+ polyMulAVX2
+ VPERM2I128 $0x02, AA2, BB2, AA0; VPERM2I128 $0x02, CC2, DD2, BB0; VPERM2I128 $0x13, AA2, BB2, CC0; VPERM2I128 $0x13, CC2, DD2, DD0
+ VPXOR (8*32)(inp), AA0, AA0; VPXOR (9*32)(inp), BB0, BB0; VPXOR (10*32)(inp), CC0, CC0; VPXOR (11*32)(inp), DD0, DD0
+ VMOVDQU AA0, (8*32)(oup); VMOVDQU BB0, (9*32)(oup); VMOVDQU CC0, (10*32)(oup); VMOVDQU DD0, (11*32)(oup)
+ VPERM2I128 $0x02, AA3, BB3, AA0; VPERM2I128 $0x02, tmpStoreAVX2, DD3, BB0; VPERM2I128 $0x13, AA3, BB3, CC0; VPERM2I128 $0x13, tmpStoreAVX2, DD3, DD0
+ VPXOR (12*32)(inp), AA0, AA0; VPXOR (13*32)(inp), BB0, BB0; VPXOR (14*32)(inp), CC0, CC0; VPXOR (15*32)(inp), DD0, DD0
+ VMOVDQU AA0, (12*32)(oup); VMOVDQU BB0, (13*32)(oup); VMOVDQU CC0, (14*32)(oup); VMOVDQU DD0, (15*32)(oup)
+ LEAQ (32*16)(inp), inp
+ LEAQ (32*16)(oup), oup
+ SUBQ $(32*16), inl
+ JMP openAVX2MainLoop
+
+openAVX2MainLoopDone:
+ // Handle the various tail sizes efficiently
+ TESTQ inl, inl
+ JE openSSEFinalize
+ CMPQ inl, $128
+ JBE openAVX2Tail128
+ CMPQ inl, $256
+ JBE openAVX2Tail256
+ CMPQ inl, $384
+ JBE openAVX2Tail384
+ JMP openAVX2Tail512
+
+// ----------------------------------------------------------------------------
+// Special optimization for buffers smaller than 193 bytes
+openAVX2192:
+ // For up to 192 bytes of ciphertext and 64 bytes for the poly key, we process four blocks
+ VMOVDQA AA0, AA1
+ VMOVDQA BB0, BB1
+ VMOVDQA CC0, CC1
+ VPADDD ·avx2IncMask<>(SB), DD0, DD1
+ VMOVDQA AA0, AA2
+ VMOVDQA BB0, BB2
+ VMOVDQA CC0, CC2
+ VMOVDQA DD0, DD2
+ VMOVDQA DD1, TT3
+ MOVQ $10, itr2
+
+openAVX2192InnerCipherLoop:
+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0)
+ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1
+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1
+ VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1
+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0)
+ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1
+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1
+ VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1
+ DECQ itr2
+ JNE openAVX2192InnerCipherLoop
+ VPADDD AA2, AA0, AA0; VPADDD AA2, AA1, AA1
+ VPADDD BB2, BB0, BB0; VPADDD BB2, BB1, BB1
+ VPADDD CC2, CC0, CC0; VPADDD CC2, CC1, CC1
+ VPADDD DD2, DD0, DD0; VPADDD TT3, DD1, DD1
+ VPERM2I128 $0x02, AA0, BB0, TT0
+
+ // Clamp and store poly key
+ VPAND ·polyClampMask<>(SB), TT0, TT0
+ VMOVDQA TT0, rsStoreAVX2
+
+ // Stream for up to 192 bytes
+ VPERM2I128 $0x13, AA0, BB0, AA0
+ VPERM2I128 $0x13, CC0, DD0, BB0
+ VPERM2I128 $0x02, AA1, BB1, CC0
+ VPERM2I128 $0x02, CC1, DD1, DD0
+ VPERM2I128 $0x13, AA1, BB1, AA1
+ VPERM2I128 $0x13, CC1, DD1, BB1
+
+openAVX2ShortOpen:
+ // Hash
+ MOVQ ad_len+80(FP), itr2
+ CALL polyHashADInternal<>(SB)
+
+openAVX2ShortOpenLoop:
+ CMPQ inl, $32
+ JB openAVX2ShortTail32
+ SUBQ $32, inl
+
+ // Load for hashing
+ polyAdd(0*8(inp))
+ polyMulAVX2
+ polyAdd(2*8(inp))
+ polyMulAVX2
+
+ // Load for decryption
+ VPXOR (inp), AA0, AA0
+ VMOVDQU AA0, (oup)
+ LEAQ (1*32)(inp), inp
+ LEAQ (1*32)(oup), oup
+
+ // Shift stream left
+ VMOVDQA BB0, AA0
+ VMOVDQA CC0, BB0
+ VMOVDQA DD0, CC0
+ VMOVDQA AA1, DD0
+ VMOVDQA BB1, AA1
+ VMOVDQA CC1, BB1
+ VMOVDQA DD1, CC1
+ VMOVDQA AA2, DD1
+ VMOVDQA BB2, AA2
+ JMP openAVX2ShortOpenLoop
+
+openAVX2ShortTail32:
+ CMPQ inl, $16
+ VMOVDQA A0, A1
+ JB openAVX2ShortDone
+
+ SUBQ $16, inl
+
+ // Load for hashing
+ polyAdd(0*8(inp))
+ polyMulAVX2
+
+ // Load for decryption
+ VPXOR (inp), A0, T0
+ VMOVDQU T0, (oup)
+ LEAQ (1*16)(inp), inp
+ LEAQ (1*16)(oup), oup
+ VPERM2I128 $0x11, AA0, AA0, AA0
+ VMOVDQA A0, A1
+
+openAVX2ShortDone:
+ VZEROUPPER
+ JMP openSSETail16
+
+// ----------------------------------------------------------------------------
+// Special optimization for buffers smaller than 321 bytes
+openAVX2320:
+ // For up to 320 bytes of ciphertext and 64 bytes for the poly key, we process six blocks
+ VMOVDQA AA0, AA1; VMOVDQA BB0, BB1; VMOVDQA CC0, CC1; VPADDD ·avx2IncMask<>(SB), DD0, DD1
+ VMOVDQA AA0, AA2; VMOVDQA BB0, BB2; VMOVDQA CC0, CC2; VPADDD ·avx2IncMask<>(SB), DD1, DD2
+ VMOVDQA BB0, TT1; VMOVDQA CC0, TT2; VMOVDQA DD0, TT3
+ MOVQ $10, itr2
+
+openAVX2320InnerCipherLoop:
+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0)
+ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2
+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2
+ VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2
+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0)
+ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2
+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2
+ VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2
+ DECQ itr2
+ JNE openAVX2320InnerCipherLoop
+
+ VMOVDQA ·chacha20Constants<>(SB), TT0
+ VPADDD TT0, AA0, AA0; VPADDD TT0, AA1, AA1; VPADDD TT0, AA2, AA2
+ VPADDD TT1, BB0, BB0; VPADDD TT1, BB1, BB1; VPADDD TT1, BB2, BB2
+ VPADDD TT2, CC0, CC0; VPADDD TT2, CC1, CC1; VPADDD TT2, CC2, CC2
+ VMOVDQA ·avx2IncMask<>(SB), TT0
+ VPADDD TT3, DD0, DD0; VPADDD TT0, TT3, TT3
+ VPADDD TT3, DD1, DD1; VPADDD TT0, TT3, TT3
+ VPADDD TT3, DD2, DD2
+
+ // Clamp and store poly key
+ VPERM2I128 $0x02, AA0, BB0, TT0
+ VPAND ·polyClampMask<>(SB), TT0, TT0
+ VMOVDQA TT0, rsStoreAVX2
+
+ // Stream for up to 320 bytes
+ VPERM2I128 $0x13, AA0, BB0, AA0
+ VPERM2I128 $0x13, CC0, DD0, BB0
+ VPERM2I128 $0x02, AA1, BB1, CC0
+ VPERM2I128 $0x02, CC1, DD1, DD0
+ VPERM2I128 $0x13, AA1, BB1, AA1
+ VPERM2I128 $0x13, CC1, DD1, BB1
+ VPERM2I128 $0x02, AA2, BB2, CC1
+ VPERM2I128 $0x02, CC2, DD2, DD1
+ VPERM2I128 $0x13, AA2, BB2, AA2
+ VPERM2I128 $0x13, CC2, DD2, BB2
+ JMP openAVX2ShortOpen
+
+// ----------------------------------------------------------------------------
+// Special optimization for the last 128 bytes of ciphertext
+openAVX2Tail128:
+ // Need to decrypt up to 128 bytes - prepare two blocks
+ VMOVDQA ·chacha20Constants<>(SB), AA1
+ VMOVDQA state1StoreAVX2, BB1
+ VMOVDQA state2StoreAVX2, CC1
+ VMOVDQA ctr3StoreAVX2, DD1
+ VPADDD ·avx2IncMask<>(SB), DD1, DD1
+ VMOVDQA DD1, DD0
+
+ XORQ itr2, itr2
+ MOVQ inl, itr1
+ ANDQ $-16, itr1
+ TESTQ itr1, itr1
+ JE openAVX2Tail128LoopB
+
+openAVX2Tail128LoopA:
+ // Perform ChaCha rounds, while hashing the remaining input
+ polyAdd(0(inp)(itr2*1))
+ polyMulAVX2
+
+openAVX2Tail128LoopB:
+ ADDQ $16, itr2
+ chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0)
+ VPALIGNR $4, BB1, BB1, BB1
+ VPALIGNR $8, CC1, CC1, CC1
+ VPALIGNR $12, DD1, DD1, DD1
+ chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0)
+ VPALIGNR $12, BB1, BB1, BB1
+ VPALIGNR $8, CC1, CC1, CC1
+ VPALIGNR $4, DD1, DD1, DD1
+ CMPQ itr2, itr1
+ JB openAVX2Tail128LoopA
+ CMPQ itr2, $160
+ JNE openAVX2Tail128LoopB
+
+ VPADDD ·chacha20Constants<>(SB), AA1, AA1
+ VPADDD state1StoreAVX2, BB1, BB1
+ VPADDD state2StoreAVX2, CC1, CC1
+ VPADDD DD0, DD1, DD1
+ VPERM2I128 $0x02, AA1, BB1, AA0; VPERM2I128 $0x02, CC1, DD1, BB0; VPERM2I128 $0x13, AA1, BB1, CC0; VPERM2I128 $0x13, CC1, DD1, DD0
+
+openAVX2TailLoop:
+ CMPQ inl, $32
+ JB openAVX2Tail
+ SUBQ $32, inl
+
+ // Load for decryption
+ VPXOR (inp), AA0, AA0
+ VMOVDQU AA0, (oup)
+ LEAQ (1*32)(inp), inp
+ LEAQ (1*32)(oup), oup
+ VMOVDQA BB0, AA0
+ VMOVDQA CC0, BB0
+ VMOVDQA DD0, CC0
+ JMP openAVX2TailLoop
+
+openAVX2Tail:
+ CMPQ inl, $16
+ VMOVDQA A0, A1
+ JB openAVX2TailDone
+ SUBQ $16, inl
+
+ // Load for decryption
+ VPXOR (inp), A0, T0
+ VMOVDQU T0, (oup)
+ LEAQ (1*16)(inp), inp
+ LEAQ (1*16)(oup), oup
+ VPERM2I128 $0x11, AA0, AA0, AA0
+ VMOVDQA A0, A1
+
+openAVX2TailDone:
+ VZEROUPPER
+ JMP openSSETail16
+
+// ----------------------------------------------------------------------------
+// Special optimization for the last 256 bytes of ciphertext
+openAVX2Tail256:
+ // Need to decrypt up to 256 bytes - prepare four blocks
+ VMOVDQA ·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1
+ VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1
+ VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1
+ VMOVDQA ctr3StoreAVX2, DD0
+ VPADDD ·avx2IncMask<>(SB), DD0, DD0
+ VPADDD ·avx2IncMask<>(SB), DD0, DD1
+ VMOVDQA DD0, TT1
+ VMOVDQA DD1, TT2
+
+ // Compute the number of iterations that will hash data
+ MOVQ inl, tmpStoreAVX2
+ MOVQ inl, itr1
+ SUBQ $128, itr1
+ SHRQ $4, itr1
+ MOVQ $10, itr2
+ CMPQ itr1, $10
+ CMOVQGT itr2, itr1
+ MOVQ inp, inl
+ XORQ itr2, itr2
+
+openAVX2Tail256LoopA:
+ polyAdd(0(inl))
+ polyMulAVX2
+ LEAQ 16(inl), inl
+
+ // Perform ChaCha rounds, while hashing the remaining input
+openAVX2Tail256LoopB:
+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0)
+ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1
+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1
+ VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1
+ INCQ itr2
+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0)
+ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1
+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1
+ VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1
+ CMPQ itr2, itr1
+ JB openAVX2Tail256LoopA
+
+ CMPQ itr2, $10
+ JNE openAVX2Tail256LoopB
+
+ MOVQ inl, itr2
+ SUBQ inp, inl
+ MOVQ inl, itr1
+ MOVQ tmpStoreAVX2, inl
+
+ // Hash the remainder of data (if any)
+openAVX2Tail256Hash:
+ ADDQ $16, itr1
+ CMPQ itr1, inl
+ JGT openAVX2Tail256HashEnd
+ polyAdd (0(itr2))
+ polyMulAVX2
+ LEAQ 16(itr2), itr2
+ JMP openAVX2Tail256Hash
+
+// Store 128 bytes safely, then go to store loop
+openAVX2Tail256HashEnd:
+ VPADDD ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1
+ VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1
+ VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1
+ VPADDD TT1, DD0, DD0; VPADDD TT2, DD1, DD1
+ VPERM2I128 $0x02, AA0, BB0, AA2; VPERM2I128 $0x02, CC0, DD0, BB2; VPERM2I128 $0x13, AA0, BB0, CC2; VPERM2I128 $0x13, CC0, DD0, DD2
+ VPERM2I128 $0x02, AA1, BB1, AA0; VPERM2I128 $0x02, CC1, DD1, BB0; VPERM2I128 $0x13, AA1, BB1, CC0; VPERM2I128 $0x13, CC1, DD1, DD0
+
+ VPXOR (0*32)(inp), AA2, AA2; VPXOR (1*32)(inp), BB2, BB2; VPXOR (2*32)(inp), CC2, CC2; VPXOR (3*32)(inp), DD2, DD2
+ VMOVDQU AA2, (0*32)(oup); VMOVDQU BB2, (1*32)(oup); VMOVDQU CC2, (2*32)(oup); VMOVDQU DD2, (3*32)(oup)
+ LEAQ (4*32)(inp), inp
+ LEAQ (4*32)(oup), oup
+ SUBQ $4*32, inl
+
+ JMP openAVX2TailLoop
+
+// ----------------------------------------------------------------------------
+// Special optimization for the last 384 bytes of ciphertext
+openAVX2Tail384:
+ // Need to decrypt up to 384 bytes - prepare six blocks
+ VMOVDQA ·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2
+ VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2
+ VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2
+ VMOVDQA ctr3StoreAVX2, DD0
+ VPADDD ·avx2IncMask<>(SB), DD0, DD0
+ VPADDD ·avx2IncMask<>(SB), DD0, DD1
+ VPADDD ·avx2IncMask<>(SB), DD1, DD2
+ VMOVDQA DD0, ctr0StoreAVX2
+ VMOVDQA DD1, ctr1StoreAVX2
+ VMOVDQA DD2, ctr2StoreAVX2
+
+ // Compute the number of iterations that will hash two blocks of data
+ MOVQ inl, tmpStoreAVX2
+ MOVQ inl, itr1
+ SUBQ $256, itr1
+ SHRQ $4, itr1
+ ADDQ $6, itr1
+ MOVQ $10, itr2
+ CMPQ itr1, $10
+ CMOVQGT itr2, itr1
+ MOVQ inp, inl
+ XORQ itr2, itr2
+
+ // Perform ChaCha rounds, while hashing the remaining input
+openAVX2Tail384LoopB:
+ polyAdd(0(inl))
+ polyMulAVX2
+ LEAQ 16(inl), inl
+
+openAVX2Tail384LoopA:
+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0)
+ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2
+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2
+ VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2
+ polyAdd(0(inl))
+ polyMulAVX2
+ LEAQ 16(inl), inl
+ INCQ itr2
+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0)
+ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2
+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2
+ VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2
+
+ CMPQ itr2, itr1
+ JB openAVX2Tail384LoopB
+
+ CMPQ itr2, $10
+ JNE openAVX2Tail384LoopA
+
+ MOVQ inl, itr2
+ SUBQ inp, inl
+ MOVQ inl, itr1
+ MOVQ tmpStoreAVX2, inl
+
+openAVX2Tail384Hash:
+ ADDQ $16, itr1
+ CMPQ itr1, inl
+ JGT openAVX2Tail384HashEnd
+ polyAdd(0(itr2))
+ polyMulAVX2
+ LEAQ 16(itr2), itr2
+ JMP openAVX2Tail384Hash
+
+// Store 256 bytes safely, then go to store loop
+openAVX2Tail384HashEnd:
+ VPADDD ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1; VPADDD ·chacha20Constants<>(SB), AA2, AA2
+ VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2
+ VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2
+ VPADDD ctr0StoreAVX2, DD0, DD0; VPADDD ctr1StoreAVX2, DD1, DD1; VPADDD ctr2StoreAVX2, DD2, DD2
+ VPERM2I128 $0x02, AA0, BB0, TT0; VPERM2I128 $0x02, CC0, DD0, TT1; VPERM2I128 $0x13, AA0, BB0, TT2; VPERM2I128 $0x13, CC0, DD0, TT3
+ VPXOR (0*32)(inp), TT0, TT0; VPXOR (1*32)(inp), TT1, TT1; VPXOR (2*32)(inp), TT2, TT2; VPXOR (3*32)(inp), TT3, TT3
+ VMOVDQU TT0, (0*32)(oup); VMOVDQU TT1, (1*32)(oup); VMOVDQU TT2, (2*32)(oup); VMOVDQU TT3, (3*32)(oup)
+ VPERM2I128 $0x02, AA1, BB1, TT0; VPERM2I128 $0x02, CC1, DD1, TT1; VPERM2I128 $0x13, AA1, BB1, TT2; VPERM2I128 $0x13, CC1, DD1, TT3
+ VPXOR (4*32)(inp), TT0, TT0; VPXOR (5*32)(inp), TT1, TT1; VPXOR (6*32)(inp), TT2, TT2; VPXOR (7*32)(inp), TT3, TT3
+ VMOVDQU TT0, (4*32)(oup); VMOVDQU TT1, (5*32)(oup); VMOVDQU TT2, (6*32)(oup); VMOVDQU TT3, (7*32)(oup)
+ VPERM2I128 $0x02, AA2, BB2, AA0; VPERM2I128 $0x02, CC2, DD2, BB0; VPERM2I128 $0x13, AA2, BB2, CC0; VPERM2I128 $0x13, CC2, DD2, DD0
+ LEAQ (8*32)(inp), inp
+ LEAQ (8*32)(oup), oup
+ SUBQ $8*32, inl
+ JMP openAVX2TailLoop
+
+// ----------------------------------------------------------------------------
+// Special optimization for the last 512 bytes of ciphertext
+openAVX2Tail512:
+ VMOVDQU ·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2; VMOVDQA AA0, AA3
+ VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2; VMOVDQA BB0, BB3
+ VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2; VMOVDQA CC0, CC3
+ VMOVDQA ctr3StoreAVX2, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD1; VPADDD ·avx2IncMask<>(SB), DD1, DD2; VPADDD ·avx2IncMask<>(SB), DD2, DD3
+ VMOVDQA DD0, ctr0StoreAVX2; VMOVDQA DD1, ctr1StoreAVX2; VMOVDQA DD2, ctr2StoreAVX2; VMOVDQA DD3, ctr3StoreAVX2
+ XORQ itr1, itr1
+ MOVQ inp, itr2
+
+openAVX2Tail512LoopB:
+ polyAdd(0(itr2))
+ polyMulAVX2
+ LEAQ (2*8)(itr2), itr2
+
+openAVX2Tail512LoopA:
+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3
+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3
+ VPSHUFB ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3
+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3
+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3
+ VMOVDQA CC3, tmpStoreAVX2
+ VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0
+ VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1
+ VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2
+ VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3
+ VMOVDQA tmpStoreAVX2, CC3
+ polyAdd(0*8(itr2))
+ polyMulAVX2
+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3
+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3
+ VPSHUFB ·rol8<>(SB), DD0, DD0; VPSHUFB ·rol8<>(SB), DD1, DD1; VPSHUFB ·rol8<>(SB), DD2, DD2; VPSHUFB ·rol8<>(SB), DD3, DD3
+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3
+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3
+ VMOVDQA CC3, tmpStoreAVX2
+ VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0
+ VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1
+ VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2
+ VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3
+ VMOVDQA tmpStoreAVX2, CC3
+ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2; VPALIGNR $4, BB3, BB3, BB3
+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3
+ VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2; VPALIGNR $12, DD3, DD3, DD3
+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3
+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3
+ VPSHUFB ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3
+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3
+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3
+ polyAdd(2*8(itr2))
+ polyMulAVX2
+ LEAQ (4*8)(itr2), itr2
+ VMOVDQA CC3, tmpStoreAVX2
+ VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0
+ VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1
+ VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2
+ VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3
+ VMOVDQA tmpStoreAVX2, CC3
+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3
+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3
+ VPSHUFB ·rol8<>(SB), DD0, DD0; VPSHUFB ·rol8<>(SB), DD1, DD1; VPSHUFB ·rol8<>(SB), DD2, DD2; VPSHUFB ·rol8<>(SB), DD3, DD3
+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3
+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3
+ VMOVDQA CC3, tmpStoreAVX2
+ VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0
+ VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1
+ VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2
+ VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3
+ VMOVDQA tmpStoreAVX2, CC3
+ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2; VPALIGNR $12, BB3, BB3, BB3
+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3
+ VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2; VPALIGNR $4, DD3, DD3, DD3
+ INCQ itr1
+ CMPQ itr1, $4
+ JLT openAVX2Tail512LoopB
+
+ CMPQ itr1, $10
+ JNE openAVX2Tail512LoopA
+
+ MOVQ inl, itr1
+ SUBQ $384, itr1
+ ANDQ $-16, itr1
+
+openAVX2Tail512HashLoop:
+ TESTQ itr1, itr1
+ JE openAVX2Tail512HashEnd
+ polyAdd(0(itr2))
+ polyMulAVX2
+ LEAQ 16(itr2), itr2
+ SUBQ $16, itr1
+ JMP openAVX2Tail512HashLoop
+
+openAVX2Tail512HashEnd:
+ VPADDD ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1; VPADDD ·chacha20Constants<>(SB), AA2, AA2; VPADDD ·chacha20Constants<>(SB), AA3, AA3
+ VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2; VPADDD state1StoreAVX2, BB3, BB3
+ VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2; VPADDD state2StoreAVX2, CC3, CC3
+ VPADDD ctr0StoreAVX2, DD0, DD0; VPADDD ctr1StoreAVX2, DD1, DD1; VPADDD ctr2StoreAVX2, DD2, DD2; VPADDD ctr3StoreAVX2, DD3, DD3
+ VMOVDQA CC3, tmpStoreAVX2
+ VPERM2I128 $0x02, AA0, BB0, CC3; VPERM2I128 $0x13, AA0, BB0, BB0; VPERM2I128 $0x02, CC0, DD0, AA0; VPERM2I128 $0x13, CC0, DD0, CC0
+ VPXOR (0*32)(inp), CC3, CC3; VPXOR (1*32)(inp), AA0, AA0; VPXOR (2*32)(inp), BB0, BB0; VPXOR (3*32)(inp), CC0, CC0
+ VMOVDQU CC3, (0*32)(oup); VMOVDQU AA0, (1*32)(oup); VMOVDQU BB0, (2*32)(oup); VMOVDQU CC0, (3*32)(oup)
+ VPERM2I128 $0x02, AA1, BB1, AA0; VPERM2I128 $0x02, CC1, DD1, BB0; VPERM2I128 $0x13, AA1, BB1, CC0; VPERM2I128 $0x13, CC1, DD1, DD0
+ VPXOR (4*32)(inp), AA0, AA0; VPXOR (5*32)(inp), BB0, BB0; VPXOR (6*32)(inp), CC0, CC0; VPXOR (7*32)(inp), DD0, DD0
+ VMOVDQU AA0, (4*32)(oup); VMOVDQU BB0, (5*32)(oup); VMOVDQU CC0, (6*32)(oup); VMOVDQU DD0, (7*32)(oup)
+ VPERM2I128 $0x02, AA2, BB2, AA0; VPERM2I128 $0x02, CC2, DD2, BB0; VPERM2I128 $0x13, AA2, BB2, CC0; VPERM2I128 $0x13, CC2, DD2, DD0
+ VPXOR (8*32)(inp), AA0, AA0; VPXOR (9*32)(inp), BB0, BB0; VPXOR (10*32)(inp), CC0, CC0; VPXOR (11*32)(inp), DD0, DD0
+ VMOVDQU AA0, (8*32)(oup); VMOVDQU BB0, (9*32)(oup); VMOVDQU CC0, (10*32)(oup); VMOVDQU DD0, (11*32)(oup)
+ VPERM2I128 $0x02, AA3, BB3, AA0; VPERM2I128 $0x02, tmpStoreAVX2, DD3, BB0; VPERM2I128 $0x13, AA3, BB3, CC0; VPERM2I128 $0x13, tmpStoreAVX2, DD3, DD0
+
+ LEAQ (12*32)(inp), inp
+ LEAQ (12*32)(oup), oup
+ SUBQ $12*32, inl
+
+ JMP openAVX2TailLoop
+
+// ----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
+// func chacha20Poly1305Seal(dst, key, src, ad []byte)
+TEXT ·chacha20Poly1305Seal(SB), 0, $288-96
+ // For aligned stack access
+ MOVQ SP, BP
+ ADDQ $32, BP
+ ANDQ $-32, BP
+ MOVQ dst+0(FP), oup
+ MOVQ key+24(FP), keyp
+ MOVQ src+48(FP), inp
+ MOVQ src_len+56(FP), inl
+ MOVQ ad+72(FP), adp
+
+ CMPB ·useAVX2(SB), $1
+ JE chacha20Poly1305Seal_AVX2
+
+ // Special optimization, for very short buffers
+ CMPQ inl, $128
+ JBE sealSSE128 // About 15% faster
+
+ // In the seal case - prepare the poly key + 3 blocks of stream in the first iteration
+ MOVOU ·chacha20Constants<>(SB), A0
+ MOVOU (1*16)(keyp), B0
+ MOVOU (2*16)(keyp), C0
+ MOVOU (3*16)(keyp), D0
+
+ // Store state on stack for future use
+ MOVO B0, state1Store
+ MOVO C0, state2Store
+
+ // Load state, increment counter blocks
+ MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL ·sseIncMask<>(SB), D1
+ MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL ·sseIncMask<>(SB), D2
+ MOVO A2, A3; MOVO B2, B3; MOVO C2, C3; MOVO D2, D3; PADDL ·sseIncMask<>(SB), D3
+
+ // Store counters
+ MOVO D0, ctr0Store; MOVO D1, ctr1Store; MOVO D2, ctr2Store; MOVO D3, ctr3Store
+ MOVQ $10, itr2
+
+sealSSEIntroLoop:
+ MOVO C3, tmpStore
+ chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3)
+ MOVO tmpStore, C3
+ MOVO C1, tmpStore
+ chachaQR(A3, B3, C3, D3, C1)
+ MOVO tmpStore, C1
+ shiftB0Left; shiftB1Left; shiftB2Left; shiftB3Left
+ shiftC0Left; shiftC1Left; shiftC2Left; shiftC3Left
+ shiftD0Left; shiftD1Left; shiftD2Left; shiftD3Left
+
+ MOVO C3, tmpStore
+ chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3)
+ MOVO tmpStore, C3
+ MOVO C1, tmpStore
+ chachaQR(A3, B3, C3, D3, C1)
+ MOVO tmpStore, C1
+ shiftB0Right; shiftB1Right; shiftB2Right; shiftB3Right
+ shiftC0Right; shiftC1Right; shiftC2Right; shiftC3Right
+ shiftD0Right; shiftD1Right; shiftD2Right; shiftD3Right
+ DECQ itr2
+ JNE sealSSEIntroLoop
+
+ // Add in the state
+ PADDD ·chacha20Constants<>(SB), A0; PADDD ·chacha20Constants<>(SB), A1; PADDD ·chacha20Constants<>(SB), A2; PADDD ·chacha20Constants<>(SB), A3
+ PADDD state1Store, B0; PADDD state1Store, B1; PADDD state1Store, B2; PADDD state1Store, B3
+ PADDD state2Store, C1; PADDD state2Store, C2; PADDD state2Store, C3
+ PADDD ctr1Store, D1; PADDD ctr2Store, D2; PADDD ctr3Store, D3
+
+ // Clamp and store the key
+ PAND ·polyClampMask<>(SB), A0
+ MOVO A0, rStore
+ MOVO B0, sStore
+
+ // Hash AAD
+ MOVQ ad_len+80(FP), itr2
+ CALL polyHashADInternal<>(SB)
+
+ MOVOU (0*16)(inp), A0; MOVOU (1*16)(inp), B0; MOVOU (2*16)(inp), C0; MOVOU (3*16)(inp), D0
+ PXOR A0, A1; PXOR B0, B1; PXOR C0, C1; PXOR D0, D1
+ MOVOU A1, (0*16)(oup); MOVOU B1, (1*16)(oup); MOVOU C1, (2*16)(oup); MOVOU D1, (3*16)(oup)
+ MOVOU (4*16)(inp), A0; MOVOU (5*16)(inp), B0; MOVOU (6*16)(inp), C0; MOVOU (7*16)(inp), D0
+ PXOR A0, A2; PXOR B0, B2; PXOR C0, C2; PXOR D0, D2
+ MOVOU A2, (4*16)(oup); MOVOU B2, (5*16)(oup); MOVOU C2, (6*16)(oup); MOVOU D2, (7*16)(oup)
+
+ MOVQ $128, itr1
+ SUBQ $128, inl
+ LEAQ 128(inp), inp
+
+ MOVO A3, A1; MOVO B3, B1; MOVO C3, C1; MOVO D3, D1
+
+ CMPQ inl, $64
+ JBE sealSSE128SealHash
+
+ MOVOU (0*16)(inp), A0; MOVOU (1*16)(inp), B0; MOVOU (2*16)(inp), C0; MOVOU (3*16)(inp), D0
+ PXOR A0, A3; PXOR B0, B3; PXOR C0, C3; PXOR D0, D3
+ MOVOU A3, (8*16)(oup); MOVOU B3, (9*16)(oup); MOVOU C3, (10*16)(oup); MOVOU D3, (11*16)(oup)
+
+ ADDQ $64, itr1
+ SUBQ $64, inl
+ LEAQ 64(inp), inp
+
+ MOVQ $2, itr1
+ MOVQ $8, itr2
+
+ CMPQ inl, $64
+ JBE sealSSETail64
+ CMPQ inl, $128
+ JBE sealSSETail128
+ CMPQ inl, $192
+ JBE sealSSETail192
+
+sealSSEMainLoop:
+ // Load state, increment counter blocks
+ MOVO ·chacha20Constants<>(SB), A0; MOVO state1Store, B0; MOVO state2Store, C0; MOVO ctr3Store, D0; PADDL ·sseIncMask<>(SB), D0
+ MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL ·sseIncMask<>(SB), D1
+ MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL ·sseIncMask<>(SB), D2
+ MOVO A2, A3; MOVO B2, B3; MOVO C2, C3; MOVO D2, D3; PADDL ·sseIncMask<>(SB), D3
+
+ // Store counters
+ MOVO D0, ctr0Store; MOVO D1, ctr1Store; MOVO D2, ctr2Store; MOVO D3, ctr3Store
+
+sealSSEInnerLoop:
+ MOVO C3, tmpStore
+ chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3)
+ MOVO tmpStore, C3
+ MOVO C1, tmpStore
+ chachaQR(A3, B3, C3, D3, C1)
+ MOVO tmpStore, C1
+ polyAdd(0(oup))
+ shiftB0Left; shiftB1Left; shiftB2Left; shiftB3Left
+ shiftC0Left; shiftC1Left; shiftC2Left; shiftC3Left
+ shiftD0Left; shiftD1Left; shiftD2Left; shiftD3Left
+ polyMulStage1
+ polyMulStage2
+ LEAQ (2*8)(oup), oup
+ MOVO C3, tmpStore
+ chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3)
+ MOVO tmpStore, C3
+ MOVO C1, tmpStore
+ polyMulStage3
+ chachaQR(A3, B3, C3, D3, C1)
+ MOVO tmpStore, C1
+ polyMulReduceStage
+ shiftB0Right; shiftB1Right; shiftB2Right; shiftB3Right
+ shiftC0Right; shiftC1Right; shiftC2Right; shiftC3Right
+ shiftD0Right; shiftD1Right; shiftD2Right; shiftD3Right
+ DECQ itr2
+ JGE sealSSEInnerLoop
+ polyAdd(0(oup))
+ polyMul
+ LEAQ (2*8)(oup), oup
+ DECQ itr1
+ JG sealSSEInnerLoop
+
+ // Add in the state
+ PADDD ·chacha20Constants<>(SB), A0; PADDD ·chacha20Constants<>(SB), A1; PADDD ·chacha20Constants<>(SB), A2; PADDD ·chacha20Constants<>(SB), A3
+ PADDD state1Store, B0; PADDD state1Store, B1; PADDD state1Store, B2; PADDD state1Store, B3
+ PADDD state2Store, C0; PADDD state2Store, C1; PADDD state2Store, C2; PADDD state2Store, C3
+ PADDD ctr0Store, D0; PADDD ctr1Store, D1; PADDD ctr2Store, D2; PADDD ctr3Store, D3
+ MOVO D3, tmpStore
+
+ // Load - xor - store
+ MOVOU (0*16)(inp), D3; PXOR D3, A0
+ MOVOU (1*16)(inp), D3; PXOR D3, B0
+ MOVOU (2*16)(inp), D3; PXOR D3, C0
+ MOVOU (3*16)(inp), D3; PXOR D3, D0
+ MOVOU A0, (0*16)(oup)
+ MOVOU B0, (1*16)(oup)
+ MOVOU C0, (2*16)(oup)
+ MOVOU D0, (3*16)(oup)
+ MOVO tmpStore, D3
+
+ MOVOU (4*16)(inp), A0; MOVOU (5*16)(inp), B0; MOVOU (6*16)(inp), C0; MOVOU (7*16)(inp), D0
+ PXOR A0, A1; PXOR B0, B1; PXOR C0, C1; PXOR D0, D1
+ MOVOU A1, (4*16)(oup); MOVOU B1, (5*16)(oup); MOVOU C1, (6*16)(oup); MOVOU D1, (7*16)(oup)
+ MOVOU (8*16)(inp), A0; MOVOU (9*16)(inp), B0; MOVOU (10*16)(inp), C0; MOVOU (11*16)(inp), D0
+ PXOR A0, A2; PXOR B0, B2; PXOR C0, C2; PXOR D0, D2
+ MOVOU A2, (8*16)(oup); MOVOU B2, (9*16)(oup); MOVOU C2, (10*16)(oup); MOVOU D2, (11*16)(oup)
+ ADDQ $192, inp
+ MOVQ $192, itr1
+ SUBQ $192, inl
+ MOVO A3, A1
+ MOVO B3, B1
+ MOVO C3, C1
+ MOVO D3, D1
+ CMPQ inl, $64
+ JBE sealSSE128SealHash
+ MOVOU (0*16)(inp), A0; MOVOU (1*16)(inp), B0; MOVOU (2*16)(inp), C0; MOVOU (3*16)(inp), D0
+ PXOR A0, A3; PXOR B0, B3; PXOR C0, C3; PXOR D0, D3
+ MOVOU A3, (12*16)(oup); MOVOU B3, (13*16)(oup); MOVOU C3, (14*16)(oup); MOVOU D3, (15*16)(oup)
+ LEAQ 64(inp), inp
+ SUBQ $64, inl
+ MOVQ $6, itr1
+ MOVQ $4, itr2
+ CMPQ inl, $192
+ JG sealSSEMainLoop
+
+ MOVQ inl, itr1
+ TESTQ inl, inl
+ JE sealSSE128SealHash
+ MOVQ $6, itr1
+ CMPQ inl, $64
+ JBE sealSSETail64
+ CMPQ inl, $128
+ JBE sealSSETail128
+ JMP sealSSETail192
+
+// ----------------------------------------------------------------------------
+// Special optimization for the last 64 bytes of plaintext
+sealSSETail64:
+ // Need to encrypt up to 64 bytes - prepare single block, hash 192 or 256 bytes
+ MOVO ·chacha20Constants<>(SB), A1
+ MOVO state1Store, B1
+ MOVO state2Store, C1
+ MOVO ctr3Store, D1
+ PADDL ·sseIncMask<>(SB), D1
+ MOVO D1, ctr0Store
+
+sealSSETail64LoopA:
+ // Perform ChaCha rounds, while hashing the previously encrypted ciphertext
+ polyAdd(0(oup))
+ polyMul
+ LEAQ 16(oup), oup
+
+sealSSETail64LoopB:
+ chachaQR(A1, B1, C1, D1, T1)
+ shiftB1Left; shiftC1Left; shiftD1Left
+ chachaQR(A1, B1, C1, D1, T1)
+ shiftB1Right; shiftC1Right; shiftD1Right
+ polyAdd(0(oup))
+ polyMul
+ LEAQ 16(oup), oup
+
+ DECQ itr1
+ JG sealSSETail64LoopA
+
+ DECQ itr2
+ JGE sealSSETail64LoopB
+ PADDL ·chacha20Constants<>(SB), A1
+ PADDL state1Store, B1
+ PADDL state2Store, C1
+ PADDL ctr0Store, D1
+
+ JMP sealSSE128Seal
+
+// ----------------------------------------------------------------------------
+// Special optimization for the last 128 bytes of plaintext
+sealSSETail128:
+ // Need to encrypt up to 128 bytes - prepare two blocks, hash 192 or 256 bytes
+ MOVO ·chacha20Constants<>(SB), A0; MOVO state1Store, B0; MOVO state2Store, C0; MOVO ctr3Store, D0; PADDL ·sseIncMask<>(SB), D0; MOVO D0, ctr0Store
+ MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL ·sseIncMask<>(SB), D1; MOVO D1, ctr1Store
+
+sealSSETail128LoopA:
+ // Perform ChaCha rounds, while hashing the previously encrypted ciphertext
+ polyAdd(0(oup))
+ polyMul
+ LEAQ 16(oup), oup
+
+sealSSETail128LoopB:
+ chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0)
+ shiftB0Left; shiftC0Left; shiftD0Left
+ shiftB1Left; shiftC1Left; shiftD1Left
+ polyAdd(0(oup))
+ polyMul
+ LEAQ 16(oup), oup
+ chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0)
+ shiftB0Right; shiftC0Right; shiftD0Right
+ shiftB1Right; shiftC1Right; shiftD1Right
+
+ DECQ itr1
+ JG sealSSETail128LoopA
+
+ DECQ itr2
+ JGE sealSSETail128LoopB
+
+ PADDL ·chacha20Constants<>(SB), A0; PADDL ·chacha20Constants<>(SB), A1
+ PADDL state1Store, B0; PADDL state1Store, B1
+ PADDL state2Store, C0; PADDL state2Store, C1
+ PADDL ctr0Store, D0; PADDL ctr1Store, D1
+
+ MOVOU (0*16)(inp), T0; MOVOU (1*16)(inp), T1; MOVOU (2*16)(inp), T2; MOVOU (3*16)(inp), T3
+ PXOR T0, A0; PXOR T1, B0; PXOR T2, C0; PXOR T3, D0
+ MOVOU A0, (0*16)(oup); MOVOU B0, (1*16)(oup); MOVOU C0, (2*16)(oup); MOVOU D0, (3*16)(oup)
+
+ MOVQ $64, itr1
+ LEAQ 64(inp), inp
+ SUBQ $64, inl
+
+ JMP sealSSE128SealHash
+
+// ----------------------------------------------------------------------------
+// Special optimization for the last 192 bytes of plaintext
+sealSSETail192:
+ // Need to encrypt up to 192 bytes - prepare three blocks, hash 192 or 256 bytes
+ MOVO ·chacha20Constants<>(SB), A0; MOVO state1Store, B0; MOVO state2Store, C0; MOVO ctr3Store, D0; PADDL ·sseIncMask<>(SB), D0; MOVO D0, ctr0Store
+ MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL ·sseIncMask<>(SB), D1; MOVO D1, ctr1Store
+ MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL ·sseIncMask<>(SB), D2; MOVO D2, ctr2Store
+
+sealSSETail192LoopA:
+ // Perform ChaCha rounds, while hashing the previously encrypted ciphertext
+ polyAdd(0(oup))
+ polyMul
+ LEAQ 16(oup), oup
+
+sealSSETail192LoopB:
+ chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0)
+ shiftB0Left; shiftC0Left; shiftD0Left
+ shiftB1Left; shiftC1Left; shiftD1Left
+ shiftB2Left; shiftC2Left; shiftD2Left
+
+ polyAdd(0(oup))
+ polyMul
+ LEAQ 16(oup), oup
+
+ chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0)
+ shiftB0Right; shiftC0Right; shiftD0Right
+ shiftB1Right; shiftC1Right; shiftD1Right
+ shiftB2Right; shiftC2Right; shiftD2Right
+
+ DECQ itr1
+ JG sealSSETail192LoopA
+
+ DECQ itr2
+ JGE sealSSETail192LoopB
+
+ PADDL ·chacha20Constants<>(SB), A0; PADDL ·chacha20Constants<>(SB), A1; PADDL ·chacha20Constants<>(SB), A2
+ PADDL state1Store, B0; PADDL state1Store, B1; PADDL state1Store, B2
+ PADDL state2Store, C0; PADDL state2Store, C1; PADDL state2Store, C2
+ PADDL ctr0Store, D0; PADDL ctr1Store, D1; PADDL ctr2Store, D2
+
+ MOVOU (0*16)(inp), T0; MOVOU (1*16)(inp), T1; MOVOU (2*16)(inp), T2; MOVOU (3*16)(inp), T3
+ PXOR T0, A0; PXOR T1, B0; PXOR T2, C0; PXOR T3, D0
+ MOVOU A0, (0*16)(oup); MOVOU B0, (1*16)(oup); MOVOU C0, (2*16)(oup); MOVOU D0, (3*16)(oup)
+ MOVOU (4*16)(inp), T0; MOVOU (5*16)(inp), T1; MOVOU (6*16)(inp), T2; MOVOU (7*16)(inp), T3
+ PXOR T0, A1; PXOR T1, B1; PXOR T2, C1; PXOR T3, D1
+ MOVOU A1, (4*16)(oup); MOVOU B1, (5*16)(oup); MOVOU C1, (6*16)(oup); MOVOU D1, (7*16)(oup)
+
+ MOVO A2, A1
+ MOVO B2, B1
+ MOVO C2, C1
+ MOVO D2, D1
+ MOVQ $128, itr1
+ LEAQ 128(inp), inp
+ SUBQ $128, inl
+
+ JMP sealSSE128SealHash
+
+// ----------------------------------------------------------------------------
+// Special seal optimization for buffers smaller than 129 bytes
+sealSSE128:
+ // For up to 128 bytes of ciphertext and 64 bytes for the poly key, we require to process three blocks
+ MOVOU ·chacha20Constants<>(SB), A0; MOVOU (1*16)(keyp), B0; MOVOU (2*16)(keyp), C0; MOVOU (3*16)(keyp), D0
+ MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL ·sseIncMask<>(SB), D1
+ MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL ·sseIncMask<>(SB), D2
+ MOVO B0, T1; MOVO C0, T2; MOVO D1, T3
+ MOVQ $10, itr2
+
+sealSSE128InnerCipherLoop:
+ chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0)
+ shiftB0Left; shiftB1Left; shiftB2Left
+ shiftC0Left; shiftC1Left; shiftC2Left
+ shiftD0Left; shiftD1Left; shiftD2Left
+ chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0)
+ shiftB0Right; shiftB1Right; shiftB2Right
+ shiftC0Right; shiftC1Right; shiftC2Right
+ shiftD0Right; shiftD1Right; shiftD2Right
+ DECQ itr2
+ JNE sealSSE128InnerCipherLoop
+
+ // A0|B0 hold the Poly1305 32-byte key, C0,D0 can be discarded
+ PADDL ·chacha20Constants<>(SB), A0; PADDL ·chacha20Constants<>(SB), A1; PADDL ·chacha20Constants<>(SB), A2
+ PADDL T1, B0; PADDL T1, B1; PADDL T1, B2
+ PADDL T2, C1; PADDL T2, C2
+ PADDL T3, D1; PADDL ·sseIncMask<>(SB), T3; PADDL T3, D2
+ PAND ·polyClampMask<>(SB), A0
+ MOVOU A0, rStore
+ MOVOU B0, sStore
+
+ // Hash
+ MOVQ ad_len+80(FP), itr2
+ CALL polyHashADInternal<>(SB)
+ XORQ itr1, itr1
+
+sealSSE128SealHash:
+ // itr1 holds the number of bytes encrypted but not yet hashed
+ CMPQ itr1, $16
+ JB sealSSE128Seal
+ polyAdd(0(oup))
+ polyMul
+
+ SUBQ $16, itr1
+ ADDQ $16, oup
+
+ JMP sealSSE128SealHash
+
+sealSSE128Seal:
+ CMPQ inl, $16
+ JB sealSSETail
+ SUBQ $16, inl
+
+ // Load for decryption
+ MOVOU (inp), T0
+ PXOR T0, A1
+ MOVOU A1, (oup)
+ LEAQ (1*16)(inp), inp
+ LEAQ (1*16)(oup), oup
+
+ // Extract for hashing
+ MOVQ A1, t0
+ PSRLDQ $8, A1
+ MOVQ A1, t1
+ ADDQ t0, acc0; ADCQ t1, acc1; ADCQ $1, acc2
+ polyMul
+
+ // Shift the stream "left"
+ MOVO B1, A1
+ MOVO C1, B1
+ MOVO D1, C1
+ MOVO A2, D1
+ MOVO B2, A2
+ MOVO C2, B2
+ MOVO D2, C2
+ JMP sealSSE128Seal
+
+sealSSETail:
+ TESTQ inl, inl
+ JE sealSSEFinalize
+
+ // We can only load the PT one byte at a time to avoid read after end of buffer
+ MOVQ inl, itr2
+ SHLQ $4, itr2
+ LEAQ ·andMask<>(SB), t0
+ MOVQ inl, itr1
+ LEAQ -1(inp)(inl*1), inp
+ XORQ t2, t2
+ XORQ t3, t3
+ XORQ AX, AX
+
+sealSSETailLoadLoop:
+ SHLQ $8, t2, t3
+ SHLQ $8, t2
+ MOVB (inp), AX
+ XORQ AX, t2
+ LEAQ -1(inp), inp
+ DECQ itr1
+ JNE sealSSETailLoadLoop
+ MOVQ t2, 0+tmpStore
+ MOVQ t3, 8+tmpStore
+ PXOR 0+tmpStore, A1
+ MOVOU A1, (oup)
+ MOVOU -16(t0)(itr2*1), T0
+ PAND T0, A1
+ MOVQ A1, t0
+ PSRLDQ $8, A1
+ MOVQ A1, t1
+ ADDQ t0, acc0; ADCQ t1, acc1; ADCQ $1, acc2
+ polyMul
+
+ ADDQ inl, oup
+
+sealSSEFinalize:
+ // Hash in the buffer lengths
+ ADDQ ad_len+80(FP), acc0
+ ADCQ src_len+56(FP), acc1
+ ADCQ $1, acc2
+ polyMul
+
+ // Final reduce
+ MOVQ acc0, t0
+ MOVQ acc1, t1
+ MOVQ acc2, t2
+ SUBQ $-5, acc0
+ SBBQ $-1, acc1
+ SBBQ $3, acc2
+ CMOVQCS t0, acc0
+ CMOVQCS t1, acc1
+ CMOVQCS t2, acc2
+
+ // Add in the "s" part of the key
+ ADDQ 0+sStore, acc0
+ ADCQ 8+sStore, acc1
+
+ // Finally store the tag at the end of the message
+ MOVQ acc0, (0*8)(oup)
+ MOVQ acc1, (1*8)(oup)
+ RET
+
+// ----------------------------------------------------------------------------
+// ------------------------- AVX2 Code ----------------------------------------
+chacha20Poly1305Seal_AVX2:
+ VZEROUPPER
+ VMOVDQU ·chacha20Constants<>(SB), AA0
+ BYTE $0xc4; BYTE $0x42; BYTE $0x7d; BYTE $0x5a; BYTE $0x70; BYTE $0x10 // broadcasti128 16(r8), ymm14
+ BYTE $0xc4; BYTE $0x42; BYTE $0x7d; BYTE $0x5a; BYTE $0x60; BYTE $0x20 // broadcasti128 32(r8), ymm12
+ BYTE $0xc4; BYTE $0xc2; BYTE $0x7d; BYTE $0x5a; BYTE $0x60; BYTE $0x30 // broadcasti128 48(r8), ymm4
+ VPADDD ·avx2InitMask<>(SB), DD0, DD0
+
+ // Special optimizations, for very short buffers
+ CMPQ inl, $192
+ JBE seal192AVX2 // 33% faster
+ CMPQ inl, $320
+ JBE seal320AVX2 // 17% faster
+
+ // For the general key prepare the key first - as a byproduct we have 64 bytes of cipher stream
+ VMOVDQA AA0, AA1; VMOVDQA AA0, AA2; VMOVDQA AA0, AA3
+ VMOVDQA BB0, BB1; VMOVDQA BB0, BB2; VMOVDQA BB0, BB3; VMOVDQA BB0, state1StoreAVX2
+ VMOVDQA CC0, CC1; VMOVDQA CC0, CC2; VMOVDQA CC0, CC3; VMOVDQA CC0, state2StoreAVX2
+ VPADDD ·avx2IncMask<>(SB), DD0, DD1; VMOVDQA DD0, ctr0StoreAVX2
+ VPADDD ·avx2IncMask<>(SB), DD1, DD2; VMOVDQA DD1, ctr1StoreAVX2
+ VPADDD ·avx2IncMask<>(SB), DD2, DD3; VMOVDQA DD2, ctr2StoreAVX2
+ VMOVDQA DD3, ctr3StoreAVX2
+ MOVQ $10, itr2
+
+sealAVX2IntroLoop:
+ VMOVDQA CC3, tmpStoreAVX2
+ chachaQR_AVX2(AA0, BB0, CC0, DD0, CC3); chachaQR_AVX2(AA1, BB1, CC1, DD1, CC3); chachaQR_AVX2(AA2, BB2, CC2, DD2, CC3)
+ VMOVDQA tmpStoreAVX2, CC3
+ VMOVDQA CC1, tmpStoreAVX2
+ chachaQR_AVX2(AA3, BB3, CC3, DD3, CC1)
+ VMOVDQA tmpStoreAVX2, CC1
+
+ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $12, DD0, DD0, DD0
+ VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $12, DD1, DD1, DD1
+ VPALIGNR $4, BB2, BB2, BB2; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $12, DD2, DD2, DD2
+ VPALIGNR $4, BB3, BB3, BB3; VPALIGNR $8, CC3, CC3, CC3; VPALIGNR $12, DD3, DD3, DD3
+
+ VMOVDQA CC3, tmpStoreAVX2
+ chachaQR_AVX2(AA0, BB0, CC0, DD0, CC3); chachaQR_AVX2(AA1, BB1, CC1, DD1, CC3); chachaQR_AVX2(AA2, BB2, CC2, DD2, CC3)
+ VMOVDQA tmpStoreAVX2, CC3
+ VMOVDQA CC1, tmpStoreAVX2
+ chachaQR_AVX2(AA3, BB3, CC3, DD3, CC1)
+ VMOVDQA tmpStoreAVX2, CC1
+
+ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $4, DD0, DD0, DD0
+ VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $4, DD1, DD1, DD1
+ VPALIGNR $12, BB2, BB2, BB2; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $4, DD2, DD2, DD2
+ VPALIGNR $12, BB3, BB3, BB3; VPALIGNR $8, CC3, CC3, CC3; VPALIGNR $4, DD3, DD3, DD3
+ DECQ itr2
+ JNE sealAVX2IntroLoop
+
+ VPADDD ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1; VPADDD ·chacha20Constants<>(SB), AA2, AA2; VPADDD ·chacha20Constants<>(SB), AA3, AA3
+ VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2; VPADDD state1StoreAVX2, BB3, BB3
+ VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2; VPADDD state2StoreAVX2, CC3, CC3
+ VPADDD ctr0StoreAVX2, DD0, DD0; VPADDD ctr1StoreAVX2, DD1, DD1; VPADDD ctr2StoreAVX2, DD2, DD2; VPADDD ctr3StoreAVX2, DD3, DD3
+
+ VPERM2I128 $0x13, CC0, DD0, CC0 // Stream bytes 96 - 127
+ VPERM2I128 $0x02, AA0, BB0, DD0 // The Poly1305 key
+ VPERM2I128 $0x13, AA0, BB0, AA0 // Stream bytes 64 - 95
+
+ // Clamp and store poly key
+ VPAND ·polyClampMask<>(SB), DD0, DD0
+ VMOVDQA DD0, rsStoreAVX2
+
+ // Hash AD
+ MOVQ ad_len+80(FP), itr2
+ CALL polyHashADInternal<>(SB)
+
+ // Can store at least 320 bytes
+ VPXOR (0*32)(inp), AA0, AA0
+ VPXOR (1*32)(inp), CC0, CC0
+ VMOVDQU AA0, (0*32)(oup)
+ VMOVDQU CC0, (1*32)(oup)
+
+ VPERM2I128 $0x02, AA1, BB1, AA0; VPERM2I128 $0x02, CC1, DD1, BB0; VPERM2I128 $0x13, AA1, BB1, CC0; VPERM2I128 $0x13, CC1, DD1, DD0
+ VPXOR (2*32)(inp), AA0, AA0; VPXOR (3*32)(inp), BB0, BB0; VPXOR (4*32)(inp), CC0, CC0; VPXOR (5*32)(inp), DD0, DD0
+ VMOVDQU AA0, (2*32)(oup); VMOVDQU BB0, (3*32)(oup); VMOVDQU CC0, (4*32)(oup); VMOVDQU DD0, (5*32)(oup)
+ VPERM2I128 $0x02, AA2, BB2, AA0; VPERM2I128 $0x02, CC2, DD2, BB0; VPERM2I128 $0x13, AA2, BB2, CC0; VPERM2I128 $0x13, CC2, DD2, DD0
+ VPXOR (6*32)(inp), AA0, AA0; VPXOR (7*32)(inp), BB0, BB0; VPXOR (8*32)(inp), CC0, CC0; VPXOR (9*32)(inp), DD0, DD0
+ VMOVDQU AA0, (6*32)(oup); VMOVDQU BB0, (7*32)(oup); VMOVDQU CC0, (8*32)(oup); VMOVDQU DD0, (9*32)(oup)
+
+ MOVQ $320, itr1
+ SUBQ $320, inl
+ LEAQ 320(inp), inp
+
+ VPERM2I128 $0x02, AA3, BB3, AA0; VPERM2I128 $0x02, CC3, DD3, BB0; VPERM2I128 $0x13, AA3, BB3, CC0; VPERM2I128 $0x13, CC3, DD3, DD0
+ CMPQ inl, $128
+ JBE sealAVX2SealHash
+
+ VPXOR (0*32)(inp), AA0, AA0; VPXOR (1*32)(inp), BB0, BB0; VPXOR (2*32)(inp), CC0, CC0; VPXOR (3*32)(inp), DD0, DD0
+ VMOVDQU AA0, (10*32)(oup); VMOVDQU BB0, (11*32)(oup); VMOVDQU CC0, (12*32)(oup); VMOVDQU DD0, (13*32)(oup)
+ SUBQ $128, inl
+ LEAQ 128(inp), inp
+
+ MOVQ $8, itr1
+ MOVQ $2, itr2
+
+ CMPQ inl, $128
+ JBE sealAVX2Tail128
+ CMPQ inl, $256
+ JBE sealAVX2Tail256
+ CMPQ inl, $384
+ JBE sealAVX2Tail384
+ CMPQ inl, $512
+ JBE sealAVX2Tail512
+
+ // We have 448 bytes to hash, but main loop hashes 512 bytes at a time - perform some rounds, before the main loop
+ VMOVDQA ·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2; VMOVDQA AA0, AA3
+ VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2; VMOVDQA BB0, BB3
+ VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2; VMOVDQA CC0, CC3
+ VMOVDQA ctr3StoreAVX2, DD0
+ VPADDD ·avx2IncMask<>(SB), DD0, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD1; VPADDD ·avx2IncMask<>(SB), DD1, DD2; VPADDD ·avx2IncMask<>(SB), DD2, DD3
+ VMOVDQA DD0, ctr0StoreAVX2; VMOVDQA DD1, ctr1StoreAVX2; VMOVDQA DD2, ctr2StoreAVX2; VMOVDQA DD3, ctr3StoreAVX2
+
+ VMOVDQA CC3, tmpStoreAVX2
+ chachaQR_AVX2(AA0, BB0, CC0, DD0, CC3); chachaQR_AVX2(AA1, BB1, CC1, DD1, CC3); chachaQR_AVX2(AA2, BB2, CC2, DD2, CC3)
+ VMOVDQA tmpStoreAVX2, CC3
+ VMOVDQA CC1, tmpStoreAVX2
+ chachaQR_AVX2(AA3, BB3, CC3, DD3, CC1)
+ VMOVDQA tmpStoreAVX2, CC1
+
+ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $12, DD0, DD0, DD0
+ VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $12, DD1, DD1, DD1
+ VPALIGNR $4, BB2, BB2, BB2; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $12, DD2, DD2, DD2
+ VPALIGNR $4, BB3, BB3, BB3; VPALIGNR $8, CC3, CC3, CC3; VPALIGNR $12, DD3, DD3, DD3
+
+ VMOVDQA CC3, tmpStoreAVX2
+ chachaQR_AVX2(AA0, BB0, CC0, DD0, CC3); chachaQR_AVX2(AA1, BB1, CC1, DD1, CC3); chachaQR_AVX2(AA2, BB2, CC2, DD2, CC3)
+ VMOVDQA tmpStoreAVX2, CC3
+ VMOVDQA CC1, tmpStoreAVX2
+ chachaQR_AVX2(AA3, BB3, CC3, DD3, CC1)
+ VMOVDQA tmpStoreAVX2, CC1
+
+ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $4, DD0, DD0, DD0
+ VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $4, DD1, DD1, DD1
+ VPALIGNR $12, BB2, BB2, BB2; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $4, DD2, DD2, DD2
+ VPALIGNR $12, BB3, BB3, BB3; VPALIGNR $8, CC3, CC3, CC3; VPALIGNR $4, DD3, DD3, DD3
+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3
+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3
+ VPSHUFB ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3
+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3
+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3
+ VMOVDQA CC3, tmpStoreAVX2
+ VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0
+ VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1
+ VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2
+ VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3
+ VMOVDQA tmpStoreAVX2, CC3
+
+ SUBQ $16, oup // Adjust the pointer
+ MOVQ $9, itr1
+ JMP sealAVX2InternalLoopStart
+
+sealAVX2MainLoop:
+ // Load state, increment counter blocks, store the incremented counters
+ VMOVDQU ·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2; VMOVDQA AA0, AA3
+ VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2; VMOVDQA BB0, BB3
+ VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2; VMOVDQA CC0, CC3
+ VMOVDQA ctr3StoreAVX2, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD1; VPADDD ·avx2IncMask<>(SB), DD1, DD2; VPADDD ·avx2IncMask<>(SB), DD2, DD3
+ VMOVDQA DD0, ctr0StoreAVX2; VMOVDQA DD1, ctr1StoreAVX2; VMOVDQA DD2, ctr2StoreAVX2; VMOVDQA DD3, ctr3StoreAVX2
+ MOVQ $10, itr1
+
+sealAVX2InternalLoop:
+ polyAdd(0*8(oup))
+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3
+ polyMulStage1_AVX2
+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3
+ VPSHUFB ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3
+ polyMulStage2_AVX2
+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3
+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3
+ polyMulStage3_AVX2
+ VMOVDQA CC3, tmpStoreAVX2
+ VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0
+ VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1
+ VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2
+ VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3
+ VMOVDQA tmpStoreAVX2, CC3
+ polyMulReduceStage
+
+sealAVX2InternalLoopStart:
+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3
+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3
+ VPSHUFB ·rol8<>(SB), DD0, DD0; VPSHUFB ·rol8<>(SB), DD1, DD1; VPSHUFB ·rol8<>(SB), DD2, DD2; VPSHUFB ·rol8<>(SB), DD3, DD3
+ polyAdd(2*8(oup))
+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3
+ polyMulStage1_AVX2
+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3
+ VMOVDQA CC3, tmpStoreAVX2
+ VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0
+ VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1
+ VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2
+ VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3
+ VMOVDQA tmpStoreAVX2, CC3
+ polyMulStage2_AVX2
+ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2; VPALIGNR $4, BB3, BB3, BB3
+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3
+ VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2; VPALIGNR $12, DD3, DD3, DD3
+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3
+ polyMulStage3_AVX2
+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3
+ VPSHUFB ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3
+ polyMulReduceStage
+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3
+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3
+ polyAdd(4*8(oup))
+ LEAQ (6*8)(oup), oup
+ VMOVDQA CC3, tmpStoreAVX2
+ VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0
+ VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1
+ VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2
+ VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3
+ VMOVDQA tmpStoreAVX2, CC3
+ polyMulStage1_AVX2
+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3
+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3
+ polyMulStage2_AVX2
+ VPSHUFB ·rol8<>(SB), DD0, DD0; VPSHUFB ·rol8<>(SB), DD1, DD1; VPSHUFB ·rol8<>(SB), DD2, DD2; VPSHUFB ·rol8<>(SB), DD3, DD3
+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3
+ polyMulStage3_AVX2
+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3
+ VMOVDQA CC3, tmpStoreAVX2
+ VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0
+ VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1
+ VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2
+ VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3
+ VMOVDQA tmpStoreAVX2, CC3
+ polyMulReduceStage
+ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2; VPALIGNR $12, BB3, BB3, BB3
+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3
+ VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2; VPALIGNR $4, DD3, DD3, DD3
+ DECQ itr1
+ JNE sealAVX2InternalLoop
+
+ VPADDD ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1; VPADDD ·chacha20Constants<>(SB), AA2, AA2; VPADDD ·chacha20Constants<>(SB), AA3, AA3
+ VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2; VPADDD state1StoreAVX2, BB3, BB3
+ VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2; VPADDD state2StoreAVX2, CC3, CC3
+ VPADDD ctr0StoreAVX2, DD0, DD0; VPADDD ctr1StoreAVX2, DD1, DD1; VPADDD ctr2StoreAVX2, DD2, DD2; VPADDD ctr3StoreAVX2, DD3, DD3
+ VMOVDQA CC3, tmpStoreAVX2
+
+ // We only hashed 480 of the 512 bytes available - hash the remaining 32 here
+ polyAdd(0*8(oup))
+ polyMulAVX2
+ LEAQ (4*8)(oup), oup
+ VPERM2I128 $0x02, AA0, BB0, CC3; VPERM2I128 $0x13, AA0, BB0, BB0; VPERM2I128 $0x02, CC0, DD0, AA0; VPERM2I128 $0x13, CC0, DD0, CC0
+ VPXOR (0*32)(inp), CC3, CC3; VPXOR (1*32)(inp), AA0, AA0; VPXOR (2*32)(inp), BB0, BB0; VPXOR (3*32)(inp), CC0, CC0
+ VMOVDQU CC3, (0*32)(oup); VMOVDQU AA0, (1*32)(oup); VMOVDQU BB0, (2*32)(oup); VMOVDQU CC0, (3*32)(oup)
+ VPERM2I128 $0x02, AA1, BB1, AA0; VPERM2I128 $0x02, CC1, DD1, BB0; VPERM2I128 $0x13, AA1, BB1, CC0; VPERM2I128 $0x13, CC1, DD1, DD0
+ VPXOR (4*32)(inp), AA0, AA0; VPXOR (5*32)(inp), BB0, BB0; VPXOR (6*32)(inp), CC0, CC0; VPXOR (7*32)(inp), DD0, DD0
+ VMOVDQU AA0, (4*32)(oup); VMOVDQU BB0, (5*32)(oup); VMOVDQU CC0, (6*32)(oup); VMOVDQU DD0, (7*32)(oup)
+
+ // and here
+ polyAdd(-2*8(oup))
+ polyMulAVX2
+ VPERM2I128 $0x02, AA2, BB2, AA0; VPERM2I128 $0x02, CC2, DD2, BB0; VPERM2I128 $0x13, AA2, BB2, CC0; VPERM2I128 $0x13, CC2, DD2, DD0
+ VPXOR (8*32)(inp), AA0, AA0; VPXOR (9*32)(inp), BB0, BB0; VPXOR (10*32)(inp), CC0, CC0; VPXOR (11*32)(inp), DD0, DD0
+ VMOVDQU AA0, (8*32)(oup); VMOVDQU BB0, (9*32)(oup); VMOVDQU CC0, (10*32)(oup); VMOVDQU DD0, (11*32)(oup)
+ VPERM2I128 $0x02, AA3, BB3, AA0; VPERM2I128 $0x02, tmpStoreAVX2, DD3, BB0; VPERM2I128 $0x13, AA3, BB3, CC0; VPERM2I128 $0x13, tmpStoreAVX2, DD3, DD0
+ VPXOR (12*32)(inp), AA0, AA0; VPXOR (13*32)(inp), BB0, BB0; VPXOR (14*32)(inp), CC0, CC0; VPXOR (15*32)(inp), DD0, DD0
+ VMOVDQU AA0, (12*32)(oup); VMOVDQU BB0, (13*32)(oup); VMOVDQU CC0, (14*32)(oup); VMOVDQU DD0, (15*32)(oup)
+ LEAQ (32*16)(inp), inp
+ SUBQ $(32*16), inl
+ CMPQ inl, $512
+ JG sealAVX2MainLoop
+
+ // Tail can only hash 480 bytes
+ polyAdd(0*8(oup))
+ polyMulAVX2
+ polyAdd(2*8(oup))
+ polyMulAVX2
+ LEAQ 32(oup), oup
+
+ MOVQ $10, itr1
+ MOVQ $0, itr2
+ CMPQ inl, $128
+ JBE sealAVX2Tail128
+ CMPQ inl, $256
+ JBE sealAVX2Tail256
+ CMPQ inl, $384
+ JBE sealAVX2Tail384
+ JMP sealAVX2Tail512
+
+// ----------------------------------------------------------------------------
+// Special optimization for buffers smaller than 193 bytes
+seal192AVX2:
+ // For up to 192 bytes of ciphertext and 64 bytes for the poly key, we process four blocks
+ VMOVDQA AA0, AA1
+ VMOVDQA BB0, BB1
+ VMOVDQA CC0, CC1
+ VPADDD ·avx2IncMask<>(SB), DD0, DD1
+ VMOVDQA AA0, AA2
+ VMOVDQA BB0, BB2
+ VMOVDQA CC0, CC2
+ VMOVDQA DD0, DD2
+ VMOVDQA DD1, TT3
+ MOVQ $10, itr2
+
+sealAVX2192InnerCipherLoop:
+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0)
+ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1
+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1
+ VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1
+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0)
+ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1
+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1
+ VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1
+ DECQ itr2
+ JNE sealAVX2192InnerCipherLoop
+ VPADDD AA2, AA0, AA0; VPADDD AA2, AA1, AA1
+ VPADDD BB2, BB0, BB0; VPADDD BB2, BB1, BB1
+ VPADDD CC2, CC0, CC0; VPADDD CC2, CC1, CC1
+ VPADDD DD2, DD0, DD0; VPADDD TT3, DD1, DD1
+ VPERM2I128 $0x02, AA0, BB0, TT0
+
+ // Clamp and store poly key
+ VPAND ·polyClampMask<>(SB), TT0, TT0
+ VMOVDQA TT0, rsStoreAVX2
+
+ // Stream for up to 192 bytes
+ VPERM2I128 $0x13, AA0, BB0, AA0
+ VPERM2I128 $0x13, CC0, DD0, BB0
+ VPERM2I128 $0x02, AA1, BB1, CC0
+ VPERM2I128 $0x02, CC1, DD1, DD0
+ VPERM2I128 $0x13, AA1, BB1, AA1
+ VPERM2I128 $0x13, CC1, DD1, BB1
+
+sealAVX2ShortSeal:
+ // Hash aad
+ MOVQ ad_len+80(FP), itr2
+ CALL polyHashADInternal<>(SB)
+ XORQ itr1, itr1
+
+sealAVX2SealHash:
+ // itr1 holds the number of bytes encrypted but not yet hashed
+ CMPQ itr1, $16
+ JB sealAVX2ShortSealLoop
+ polyAdd(0(oup))
+ polyMul
+ SUBQ $16, itr1
+ ADDQ $16, oup
+ JMP sealAVX2SealHash
+
+sealAVX2ShortSealLoop:
+ CMPQ inl, $32
+ JB sealAVX2ShortTail32
+ SUBQ $32, inl
+
+ // Load for encryption
+ VPXOR (inp), AA0, AA0
+ VMOVDQU AA0, (oup)
+ LEAQ (1*32)(inp), inp
+
+ // Now can hash
+ polyAdd(0*8(oup))
+ polyMulAVX2
+ polyAdd(2*8(oup))
+ polyMulAVX2
+ LEAQ (1*32)(oup), oup
+
+ // Shift stream left
+ VMOVDQA BB0, AA0
+ VMOVDQA CC0, BB0
+ VMOVDQA DD0, CC0
+ VMOVDQA AA1, DD0
+ VMOVDQA BB1, AA1
+ VMOVDQA CC1, BB1
+ VMOVDQA DD1, CC1
+ VMOVDQA AA2, DD1
+ VMOVDQA BB2, AA2
+ JMP sealAVX2ShortSealLoop
+
+sealAVX2ShortTail32:
+ CMPQ inl, $16
+ VMOVDQA A0, A1
+ JB sealAVX2ShortDone
+
+ SUBQ $16, inl
+
+ // Load for encryption
+ VPXOR (inp), A0, T0
+ VMOVDQU T0, (oup)
+ LEAQ (1*16)(inp), inp
+
+ // Hash
+ polyAdd(0*8(oup))
+ polyMulAVX2
+ LEAQ (1*16)(oup), oup
+ VPERM2I128 $0x11, AA0, AA0, AA0
+ VMOVDQA A0, A1
+
+sealAVX2ShortDone:
+ VZEROUPPER
+ JMP sealSSETail
+
+// ----------------------------------------------------------------------------
+// Special optimization for buffers smaller than 321 bytes
+seal320AVX2:
+ // For up to 320 bytes of ciphertext and 64 bytes for the poly key, we process six blocks
+ VMOVDQA AA0, AA1; VMOVDQA BB0, BB1; VMOVDQA CC0, CC1; VPADDD ·avx2IncMask<>(SB), DD0, DD1
+ VMOVDQA AA0, AA2; VMOVDQA BB0, BB2; VMOVDQA CC0, CC2; VPADDD ·avx2IncMask<>(SB), DD1, DD2
+ VMOVDQA BB0, TT1; VMOVDQA CC0, TT2; VMOVDQA DD0, TT3
+ MOVQ $10, itr2
+
+sealAVX2320InnerCipherLoop:
+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0)
+ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2
+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2
+ VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2
+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0)
+ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2
+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2
+ VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2
+ DECQ itr2
+ JNE sealAVX2320InnerCipherLoop
+
+ VMOVDQA ·chacha20Constants<>(SB), TT0
+ VPADDD TT0, AA0, AA0; VPADDD TT0, AA1, AA1; VPADDD TT0, AA2, AA2
+ VPADDD TT1, BB0, BB0; VPADDD TT1, BB1, BB1; VPADDD TT1, BB2, BB2
+ VPADDD TT2, CC0, CC0; VPADDD TT2, CC1, CC1; VPADDD TT2, CC2, CC2
+ VMOVDQA ·avx2IncMask<>(SB), TT0
+ VPADDD TT3, DD0, DD0; VPADDD TT0, TT3, TT3
+ VPADDD TT3, DD1, DD1; VPADDD TT0, TT3, TT3
+ VPADDD TT3, DD2, DD2
+
+ // Clamp and store poly key
+ VPERM2I128 $0x02, AA0, BB0, TT0
+ VPAND ·polyClampMask<>(SB), TT0, TT0
+ VMOVDQA TT0, rsStoreAVX2
+
+ // Stream for up to 320 bytes
+ VPERM2I128 $0x13, AA0, BB0, AA0
+ VPERM2I128 $0x13, CC0, DD0, BB0
+ VPERM2I128 $0x02, AA1, BB1, CC0
+ VPERM2I128 $0x02, CC1, DD1, DD0
+ VPERM2I128 $0x13, AA1, BB1, AA1
+ VPERM2I128 $0x13, CC1, DD1, BB1
+ VPERM2I128 $0x02, AA2, BB2, CC1
+ VPERM2I128 $0x02, CC2, DD2, DD1
+ VPERM2I128 $0x13, AA2, BB2, AA2
+ VPERM2I128 $0x13, CC2, DD2, BB2
+ JMP sealAVX2ShortSeal
+
+// ----------------------------------------------------------------------------
+// Special optimization for the last 128 bytes of ciphertext
+sealAVX2Tail128:
+ // Need to decrypt up to 128 bytes - prepare two blocks
+ // If we got here after the main loop - there are 512 encrypted bytes waiting to be hashed
+ // If we got here before the main loop - there are 448 encrpyred bytes waiting to be hashed
+ VMOVDQA ·chacha20Constants<>(SB), AA0
+ VMOVDQA state1StoreAVX2, BB0
+ VMOVDQA state2StoreAVX2, CC0
+ VMOVDQA ctr3StoreAVX2, DD0
+ VPADDD ·avx2IncMask<>(SB), DD0, DD0
+ VMOVDQA DD0, DD1
+
+sealAVX2Tail128LoopA:
+ polyAdd(0(oup))
+ polyMul
+ LEAQ 16(oup), oup
+
+sealAVX2Tail128LoopB:
+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0)
+ polyAdd(0(oup))
+ polyMul
+ VPALIGNR $4, BB0, BB0, BB0
+ VPALIGNR $8, CC0, CC0, CC0
+ VPALIGNR $12, DD0, DD0, DD0
+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0)
+ polyAdd(16(oup))
+ polyMul
+ LEAQ 32(oup), oup
+ VPALIGNR $12, BB0, BB0, BB0
+ VPALIGNR $8, CC0, CC0, CC0
+ VPALIGNR $4, DD0, DD0, DD0
+ DECQ itr1
+ JG sealAVX2Tail128LoopA
+ DECQ itr2
+ JGE sealAVX2Tail128LoopB
+
+ VPADDD ·chacha20Constants<>(SB), AA0, AA1
+ VPADDD state1StoreAVX2, BB0, BB1
+ VPADDD state2StoreAVX2, CC0, CC1
+ VPADDD DD1, DD0, DD1
+
+ VPERM2I128 $0x02, AA1, BB1, AA0
+ VPERM2I128 $0x02, CC1, DD1, BB0
+ VPERM2I128 $0x13, AA1, BB1, CC0
+ VPERM2I128 $0x13, CC1, DD1, DD0
+ JMP sealAVX2ShortSealLoop
+
+// ----------------------------------------------------------------------------
+// Special optimization for the last 256 bytes of ciphertext
+sealAVX2Tail256:
+ // Need to decrypt up to 256 bytes - prepare two blocks
+ // If we got here after the main loop - there are 512 encrypted bytes waiting to be hashed
+ // If we got here before the main loop - there are 448 encrpyred bytes waiting to be hashed
+ VMOVDQA ·chacha20Constants<>(SB), AA0; VMOVDQA ·chacha20Constants<>(SB), AA1
+ VMOVDQA state1StoreAVX2, BB0; VMOVDQA state1StoreAVX2, BB1
+ VMOVDQA state2StoreAVX2, CC0; VMOVDQA state2StoreAVX2, CC1
+ VMOVDQA ctr3StoreAVX2, DD0
+ VPADDD ·avx2IncMask<>(SB), DD0, DD0
+ VPADDD ·avx2IncMask<>(SB), DD0, DD1
+ VMOVDQA DD0, TT1
+ VMOVDQA DD1, TT2
+
+sealAVX2Tail256LoopA:
+ polyAdd(0(oup))
+ polyMul
+ LEAQ 16(oup), oup
+
+sealAVX2Tail256LoopB:
+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0)
+ polyAdd(0(oup))
+ polyMul
+ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1
+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1
+ VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1
+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0)
+ polyAdd(16(oup))
+ polyMul
+ LEAQ 32(oup), oup
+ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1
+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1
+ VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1
+ DECQ itr1
+ JG sealAVX2Tail256LoopA
+ DECQ itr2
+ JGE sealAVX2Tail256LoopB
+
+ VPADDD ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1
+ VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1
+ VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1
+ VPADDD TT1, DD0, DD0; VPADDD TT2, DD1, DD1
+ VPERM2I128 $0x02, AA0, BB0, TT0
+ VPERM2I128 $0x02, CC0, DD0, TT1
+ VPERM2I128 $0x13, AA0, BB0, TT2
+ VPERM2I128 $0x13, CC0, DD0, TT3
+ VPXOR (0*32)(inp), TT0, TT0; VPXOR (1*32)(inp), TT1, TT1; VPXOR (2*32)(inp), TT2, TT2; VPXOR (3*32)(inp), TT3, TT3
+ VMOVDQU TT0, (0*32)(oup); VMOVDQU TT1, (1*32)(oup); VMOVDQU TT2, (2*32)(oup); VMOVDQU TT3, (3*32)(oup)
+ MOVQ $128, itr1
+ LEAQ 128(inp), inp
+ SUBQ $128, inl
+ VPERM2I128 $0x02, AA1, BB1, AA0
+ VPERM2I128 $0x02, CC1, DD1, BB0
+ VPERM2I128 $0x13, AA1, BB1, CC0
+ VPERM2I128 $0x13, CC1, DD1, DD0
+
+ JMP sealAVX2SealHash
+
+// ----------------------------------------------------------------------------
+// Special optimization for the last 384 bytes of ciphertext
+sealAVX2Tail384:
+ // Need to decrypt up to 384 bytes - prepare two blocks
+ // If we got here after the main loop - there are 512 encrypted bytes waiting to be hashed
+ // If we got here before the main loop - there are 448 encrpyred bytes waiting to be hashed
+ VMOVDQA ·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2
+ VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2
+ VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2
+ VMOVDQA ctr3StoreAVX2, DD0
+ VPADDD ·avx2IncMask<>(SB), DD0, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD1; VPADDD ·avx2IncMask<>(SB), DD1, DD2
+ VMOVDQA DD0, TT1; VMOVDQA DD1, TT2; VMOVDQA DD2, TT3
+
+sealAVX2Tail384LoopA:
+ polyAdd(0(oup))
+ polyMul
+ LEAQ 16(oup), oup
+
+sealAVX2Tail384LoopB:
+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0)
+ polyAdd(0(oup))
+ polyMul
+ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2
+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2
+ VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2
+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0)
+ polyAdd(16(oup))
+ polyMul
+ LEAQ 32(oup), oup
+ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2
+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2
+ VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2
+ DECQ itr1
+ JG sealAVX2Tail384LoopA
+ DECQ itr2
+ JGE sealAVX2Tail384LoopB
+
+ VPADDD ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1; VPADDD ·chacha20Constants<>(SB), AA2, AA2
+ VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2
+ VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2
+ VPADDD TT1, DD0, DD0; VPADDD TT2, DD1, DD1; VPADDD TT3, DD2, DD2
+ VPERM2I128 $0x02, AA0, BB0, TT0
+ VPERM2I128 $0x02, CC0, DD0, TT1
+ VPERM2I128 $0x13, AA0, BB0, TT2
+ VPERM2I128 $0x13, CC0, DD0, TT3
+ VPXOR (0*32)(inp), TT0, TT0; VPXOR (1*32)(inp), TT1, TT1; VPXOR (2*32)(inp), TT2, TT2; VPXOR (3*32)(inp), TT3, TT3
+ VMOVDQU TT0, (0*32)(oup); VMOVDQU TT1, (1*32)(oup); VMOVDQU TT2, (2*32)(oup); VMOVDQU TT3, (3*32)(oup)
+ VPERM2I128 $0x02, AA1, BB1, TT0
+ VPERM2I128 $0x02, CC1, DD1, TT1
+ VPERM2I128 $0x13, AA1, BB1, TT2
+ VPERM2I128 $0x13, CC1, DD1, TT3
+ VPXOR (4*32)(inp), TT0, TT0; VPXOR (5*32)(inp), TT1, TT1; VPXOR (6*32)(inp), TT2, TT2; VPXOR (7*32)(inp), TT3, TT3
+ VMOVDQU TT0, (4*32)(oup); VMOVDQU TT1, (5*32)(oup); VMOVDQU TT2, (6*32)(oup); VMOVDQU TT3, (7*32)(oup)
+ MOVQ $256, itr1
+ LEAQ 256(inp), inp
+ SUBQ $256, inl
+ VPERM2I128 $0x02, AA2, BB2, AA0
+ VPERM2I128 $0x02, CC2, DD2, BB0
+ VPERM2I128 $0x13, AA2, BB2, CC0
+ VPERM2I128 $0x13, CC2, DD2, DD0
+
+ JMP sealAVX2SealHash
+
+// ----------------------------------------------------------------------------
+// Special optimization for the last 512 bytes of ciphertext
+sealAVX2Tail512:
+ // Need to decrypt up to 512 bytes - prepare two blocks
+ // If we got here after the main loop - there are 512 encrypted bytes waiting to be hashed
+ // If we got here before the main loop - there are 448 encrpyred bytes waiting to be hashed
+ VMOVDQA ·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2; VMOVDQA AA0, AA3
+ VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2; VMOVDQA BB0, BB3
+ VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2; VMOVDQA CC0, CC3
+ VMOVDQA ctr3StoreAVX2, DD0
+ VPADDD ·avx2IncMask<>(SB), DD0, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD1; VPADDD ·avx2IncMask<>(SB), DD1, DD2; VPADDD ·avx2IncMask<>(SB), DD2, DD3
+ VMOVDQA DD0, ctr0StoreAVX2; VMOVDQA DD1, ctr1StoreAVX2; VMOVDQA DD2, ctr2StoreAVX2; VMOVDQA DD3, ctr3StoreAVX2
+
+sealAVX2Tail512LoopA:
+ polyAdd(0(oup))
+ polyMul
+ LEAQ 16(oup), oup
+
+sealAVX2Tail512LoopB:
+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3
+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3
+ VPSHUFB ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3
+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3
+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3
+ VMOVDQA CC3, tmpStoreAVX2
+ VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0
+ VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1
+ VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2
+ VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3
+ VMOVDQA tmpStoreAVX2, CC3
+ polyAdd(0*8(oup))
+ polyMulAVX2
+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3
+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3
+ VPSHUFB ·rol8<>(SB), DD0, DD0; VPSHUFB ·rol8<>(SB), DD1, DD1; VPSHUFB ·rol8<>(SB), DD2, DD2; VPSHUFB ·rol8<>(SB), DD3, DD3
+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3
+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3
+ VMOVDQA CC3, tmpStoreAVX2
+ VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0
+ VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1
+ VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2
+ VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3
+ VMOVDQA tmpStoreAVX2, CC3
+ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2; VPALIGNR $4, BB3, BB3, BB3
+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3
+ VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2; VPALIGNR $12, DD3, DD3, DD3
+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3
+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3
+ VPSHUFB ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3
+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3
+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3
+ polyAdd(2*8(oup))
+ polyMulAVX2
+ LEAQ (4*8)(oup), oup
+ VMOVDQA CC3, tmpStoreAVX2
+ VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0
+ VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1
+ VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2
+ VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3
+ VMOVDQA tmpStoreAVX2, CC3
+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3
+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3
+ VPSHUFB ·rol8<>(SB), DD0, DD0; VPSHUFB ·rol8<>(SB), DD1, DD1; VPSHUFB ·rol8<>(SB), DD2, DD2; VPSHUFB ·rol8<>(SB), DD3, DD3
+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3
+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3
+ VMOVDQA CC3, tmpStoreAVX2
+ VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0
+ VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1
+ VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2
+ VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3
+ VMOVDQA tmpStoreAVX2, CC3
+ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2; VPALIGNR $12, BB3, BB3, BB3
+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3
+ VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2; VPALIGNR $4, DD3, DD3, DD3
+
+ DECQ itr1
+ JG sealAVX2Tail512LoopA
+ DECQ itr2
+ JGE sealAVX2Tail512LoopB
+
+ VPADDD ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1; VPADDD ·chacha20Constants<>(SB), AA2, AA2; VPADDD ·chacha20Constants<>(SB), AA3, AA3
+ VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2; VPADDD state1StoreAVX2, BB3, BB3
+ VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2; VPADDD state2StoreAVX2, CC3, CC3
+ VPADDD ctr0StoreAVX2, DD0, DD0; VPADDD ctr1StoreAVX2, DD1, DD1; VPADDD ctr2StoreAVX2, DD2, DD2; VPADDD ctr3StoreAVX2, DD3, DD3
+ VMOVDQA CC3, tmpStoreAVX2
+ VPERM2I128 $0x02, AA0, BB0, CC3
+ VPXOR (0*32)(inp), CC3, CC3
+ VMOVDQU CC3, (0*32)(oup)
+ VPERM2I128 $0x02, CC0, DD0, CC3
+ VPXOR (1*32)(inp), CC3, CC3
+ VMOVDQU CC3, (1*32)(oup)
+ VPERM2I128 $0x13, AA0, BB0, CC3
+ VPXOR (2*32)(inp), CC3, CC3
+ VMOVDQU CC3, (2*32)(oup)
+ VPERM2I128 $0x13, CC0, DD0, CC3
+ VPXOR (3*32)(inp), CC3, CC3
+ VMOVDQU CC3, (3*32)(oup)
+
+ VPERM2I128 $0x02, AA1, BB1, AA0
+ VPERM2I128 $0x02, CC1, DD1, BB0
+ VPERM2I128 $0x13, AA1, BB1, CC0
+ VPERM2I128 $0x13, CC1, DD1, DD0
+ VPXOR (4*32)(inp), AA0, AA0; VPXOR (5*32)(inp), BB0, BB0; VPXOR (6*32)(inp), CC0, CC0; VPXOR (7*32)(inp), DD0, DD0
+ VMOVDQU AA0, (4*32)(oup); VMOVDQU BB0, (5*32)(oup); VMOVDQU CC0, (6*32)(oup); VMOVDQU DD0, (7*32)(oup)
+
+ VPERM2I128 $0x02, AA2, BB2, AA0
+ VPERM2I128 $0x02, CC2, DD2, BB0
+ VPERM2I128 $0x13, AA2, BB2, CC0
+ VPERM2I128 $0x13, CC2, DD2, DD0
+ VPXOR (8*32)(inp), AA0, AA0; VPXOR (9*32)(inp), BB0, BB0; VPXOR (10*32)(inp), CC0, CC0; VPXOR (11*32)(inp), DD0, DD0
+ VMOVDQU AA0, (8*32)(oup); VMOVDQU BB0, (9*32)(oup); VMOVDQU CC0, (10*32)(oup); VMOVDQU DD0, (11*32)(oup)
+
+ MOVQ $384, itr1
+ LEAQ 384(inp), inp
+ SUBQ $384, inl
+ VPERM2I128 $0x02, AA3, BB3, AA0
+ VPERM2I128 $0x02, tmpStoreAVX2, DD3, BB0
+ VPERM2I128 $0x13, AA3, BB3, CC0
+ VPERM2I128 $0x13, tmpStoreAVX2, DD3, DD0
+
+ JMP sealAVX2SealHash
+
+// func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32)
+TEXT ·cpuid(SB), NOSPLIT, $0-24
+ MOVL eaxArg+0(FP), AX
+ MOVL ecxArg+4(FP), CX
+ CPUID
+ MOVL AX, eax+8(FP)
+ MOVL BX, ebx+12(FP)
+ MOVL CX, ecx+16(FP)
+ MOVL DX, edx+20(FP)
+ RET
+
+// func xgetbv() (eax, edx uint32)
+TEXT ·xgetbv(SB),NOSPLIT,$0-8
+ MOVL $0, CX
+ XGETBV
+ MOVL AX, eax+0(FP)
+ MOVL DX, edx+4(FP)
+ RET
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go
new file mode 100644
index 000000000..f7e4bfb1c
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go
@@ -0,0 +1,70 @@
+// 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.
+
+package chacha20poly1305
+
+import (
+ "encoding/binary"
+
+ "golang.org/x/crypto/chacha20poly1305/internal/chacha20"
+ "golang.org/x/crypto/poly1305"
+)
+
+func roundTo16(n int) int {
+ return 16 * ((n + 15) / 16)
+}
+
+func (c *chacha20poly1305) sealGeneric(dst, nonce, plaintext, additionalData []byte) []byte {
+ var counter [16]byte
+ copy(counter[4:], nonce)
+
+ var polyKey [32]byte
+ chacha20.XORKeyStream(polyKey[:], polyKey[:], &counter, &c.key)
+
+ ret, out := sliceForAppend(dst, len(plaintext)+poly1305.TagSize)
+ counter[0] = 1
+ chacha20.XORKeyStream(out, plaintext, &counter, &c.key)
+
+ polyInput := make([]byte, roundTo16(len(additionalData))+roundTo16(len(plaintext))+8+8)
+ copy(polyInput, additionalData)
+ copy(polyInput[roundTo16(len(additionalData)):], out[:len(plaintext)])
+ binary.LittleEndian.PutUint64(polyInput[len(polyInput)-16:], uint64(len(additionalData)))
+ binary.LittleEndian.PutUint64(polyInput[len(polyInput)-8:], uint64(len(plaintext)))
+
+ var tag [poly1305.TagSize]byte
+ poly1305.Sum(&tag, polyInput, &polyKey)
+ copy(out[len(plaintext):], tag[:])
+
+ return ret
+}
+
+func (c *chacha20poly1305) openGeneric(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
+ var tag [poly1305.TagSize]byte
+ copy(tag[:], ciphertext[len(ciphertext)-16:])
+ ciphertext = ciphertext[:len(ciphertext)-16]
+
+ var counter [16]byte
+ copy(counter[4:], nonce)
+
+ var polyKey [32]byte
+ chacha20.XORKeyStream(polyKey[:], polyKey[:], &counter, &c.key)
+
+ polyInput := make([]byte, roundTo16(len(additionalData))+roundTo16(len(ciphertext))+8+8)
+ copy(polyInput, additionalData)
+ copy(polyInput[roundTo16(len(additionalData)):], ciphertext)
+ binary.LittleEndian.PutUint64(polyInput[len(polyInput)-16:], uint64(len(additionalData)))
+ binary.LittleEndian.PutUint64(polyInput[len(polyInput)-8:], uint64(len(ciphertext)))
+
+ ret, out := sliceForAppend(dst, len(ciphertext))
+ if !poly1305.Verify(&tag, polyInput, &polyKey) {
+ for i := range out {
+ out[i] = 0
+ }
+ return nil, errOpen
+ }
+
+ counter[0] = 1
+ chacha20.XORKeyStream(out, ciphertext, &counter, &c.key)
+ return ret, nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_noasm.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_noasm.go
new file mode 100644
index 000000000..4c2eb703c
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_noasm.go
@@ -0,0 +1,15 @@
+// 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.
+
+// +build !amd64 !go1.7 gccgo appengine
+
+package chacha20poly1305
+
+func (c *chacha20poly1305) seal(dst, nonce, plaintext, additionalData []byte) []byte {
+ return c.sealGeneric(dst, nonce, plaintext, additionalData)
+}
+
+func (c *chacha20poly1305) open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
+ return c.openGeneric(dst, nonce, ciphertext, additionalData)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_test.go
new file mode 100644
index 000000000..78f981a74
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_test.go
@@ -0,0 +1,182 @@
+// 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.
+
+package chacha20poly1305
+
+import (
+ "bytes"
+ cr "crypto/rand"
+ "encoding/hex"
+ mr "math/rand"
+ "testing"
+)
+
+func TestVectors(t *testing.T) {
+ for i, test := range chacha20Poly1305Tests {
+ key, _ := hex.DecodeString(test.key)
+ nonce, _ := hex.DecodeString(test.nonce)
+ ad, _ := hex.DecodeString(test.aad)
+ plaintext, _ := hex.DecodeString(test.plaintext)
+
+ aead, err := New(key)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ ct := aead.Seal(nil, nonce, plaintext, ad)
+ if ctHex := hex.EncodeToString(ct); ctHex != test.out {
+ t.Errorf("#%d: got %s, want %s", i, ctHex, test.out)
+ continue
+ }
+
+ plaintext2, err := aead.Open(nil, nonce, ct, ad)
+ if err != nil {
+ t.Errorf("#%d: Open failed", i)
+ continue
+ }
+
+ if !bytes.Equal(plaintext, plaintext2) {
+ t.Errorf("#%d: plaintext's don't match: got %x vs %x", i, plaintext2, plaintext)
+ continue
+ }
+
+ if len(ad) > 0 {
+ alterAdIdx := mr.Intn(len(ad))
+ ad[alterAdIdx] ^= 0x80
+ if _, err := aead.Open(nil, nonce, ct, ad); err == nil {
+ t.Errorf("#%d: Open was successful after altering additional data", i)
+ }
+ ad[alterAdIdx] ^= 0x80
+ }
+
+ alterNonceIdx := mr.Intn(aead.NonceSize())
+ nonce[alterNonceIdx] ^= 0x80
+ if _, err := aead.Open(nil, nonce, ct, ad); err == nil {
+ t.Errorf("#%d: Open was successful after altering nonce", i)
+ }
+ nonce[alterNonceIdx] ^= 0x80
+
+ alterCtIdx := mr.Intn(len(ct))
+ ct[alterCtIdx] ^= 0x80
+ if _, err := aead.Open(nil, nonce, ct, ad); err == nil {
+ t.Errorf("#%d: Open was successful after altering ciphertext", i)
+ }
+ ct[alterCtIdx] ^= 0x80
+ }
+}
+
+func TestRandom(t *testing.T) {
+ // Some random tests to verify Open(Seal) == Plaintext
+ for i := 0; i < 256; i++ {
+ var nonce [12]byte
+ var key [32]byte
+
+ al := mr.Intn(128)
+ pl := mr.Intn(16384)
+ ad := make([]byte, al)
+ plaintext := make([]byte, pl)
+ cr.Read(key[:])
+ cr.Read(nonce[:])
+ cr.Read(ad)
+ cr.Read(plaintext)
+
+ aead, err := New(key[:])
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ ct := aead.Seal(nil, nonce[:], plaintext, ad)
+
+ plaintext2, err := aead.Open(nil, nonce[:], ct, ad)
+ if err != nil {
+ t.Errorf("Random #%d: Open failed", i)
+ continue
+ }
+
+ if !bytes.Equal(plaintext, plaintext2) {
+ t.Errorf("Random #%d: plaintext's don't match: got %x vs %x", i, plaintext2, plaintext)
+ continue
+ }
+
+ if len(ad) > 0 {
+ alterAdIdx := mr.Intn(len(ad))
+ ad[alterAdIdx] ^= 0x80
+ if _, err := aead.Open(nil, nonce[:], ct, ad); err == nil {
+ t.Errorf("Random #%d: Open was successful after altering additional data", i)
+ }
+ ad[alterAdIdx] ^= 0x80
+ }
+
+ alterNonceIdx := mr.Intn(aead.NonceSize())
+ nonce[alterNonceIdx] ^= 0x80
+ if _, err := aead.Open(nil, nonce[:], ct, ad); err == nil {
+ t.Errorf("Random #%d: Open was successful after altering nonce", i)
+ }
+ nonce[alterNonceIdx] ^= 0x80
+
+ alterCtIdx := mr.Intn(len(ct))
+ ct[alterCtIdx] ^= 0x80
+ if _, err := aead.Open(nil, nonce[:], ct, ad); err == nil {
+ t.Errorf("Random #%d: Open was successful after altering ciphertext", i)
+ }
+ ct[alterCtIdx] ^= 0x80
+ }
+}
+
+func benchamarkChaCha20Poly1305Seal(b *testing.B, buf []byte) {
+ b.SetBytes(int64(len(buf)))
+
+ var key [32]byte
+ var nonce [12]byte
+ var ad [13]byte
+ var out []byte
+
+ aead, _ := New(key[:])
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ out = aead.Seal(out[:0], nonce[:], buf[:], ad[:])
+ }
+}
+
+func benchamarkChaCha20Poly1305Open(b *testing.B, buf []byte) {
+ b.SetBytes(int64(len(buf)))
+
+ var key [32]byte
+ var nonce [12]byte
+ var ad [13]byte
+ var ct []byte
+ var out []byte
+
+ aead, _ := New(key[:])
+ ct = aead.Seal(ct[:0], nonce[:], buf[:], ad[:])
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ out, _ = aead.Open(out[:0], nonce[:], ct[:], ad[:])
+ }
+}
+
+func BenchmarkChacha20Poly1305Open_64(b *testing.B) {
+ benchamarkChaCha20Poly1305Open(b, make([]byte, 64))
+}
+
+func BenchmarkChacha20Poly1305Seal_64(b *testing.B) {
+ benchamarkChaCha20Poly1305Seal(b, make([]byte, 64))
+}
+
+func BenchmarkChacha20Poly1305Open_1350(b *testing.B) {
+ benchamarkChaCha20Poly1305Open(b, make([]byte, 1350))
+}
+
+func BenchmarkChacha20Poly1305Seal_1350(b *testing.B) {
+ benchamarkChaCha20Poly1305Seal(b, make([]byte, 1350))
+}
+
+func BenchmarkChacha20Poly1305Open_8K(b *testing.B) {
+ benchamarkChaCha20Poly1305Open(b, make([]byte, 8*1024))
+}
+
+func BenchmarkChacha20Poly1305Seal_8K(b *testing.B) {
+ benchamarkChaCha20Poly1305Seal(b, make([]byte, 8*1024))
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_vectors_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_vectors_test.go
new file mode 100644
index 000000000..49f0da6b7
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_vectors_test.go
@@ -0,0 +1,332 @@
+// 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.
+
+package chacha20poly1305
+
+var chacha20Poly1305Tests = []struct {
+ plaintext, aad, key, nonce, out string
+}{
+ {
+ "4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e20776f756c642062652069742e",
+ "50515253c0c1c2c3c4c5c6c7",
+ "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f",
+ "070000004041424344454647",
+ "d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b61161ae10b594f09e26a7e902ecbd0600691",
+ },
+ {
+ "1400000cebccee3bf561b292340fec60",
+ "00000000000000001603030010",
+ "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e",
+ "129039b5572e8a7a8131f76a",
+ "2b487a2941bc07f3cc76d1a531662588ee7c2598e59778c24d5b27559a80d163",
+ },
+ {
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000000000000000000000000",
+ "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e",
+ "129039b5572e8a7a8131f76a",
+ "3f487a25aa70e9c8391763370569c9e83b7650dd1921c8b78869f241f25d2096c910b180930c5b8747fd90959fe8ca2dcadb4fa50fa1439f916b2301e1cc0810d6725775d3ab86721700f96e22709b0a7a8bef32627dd929b2dd3ba15772b669062bb558bc92e6c241a1d60d9f0035e80c335f854815fe1138ab8af653eab3e122135feeec7dfaba1cc24af82a2b7acccdd824899a7e03cc29c25be8a4f56a66673845b93bae1556f09dafc89a0d22af207718e2a6bb022e9d917597295992ea3b750cc0e7a7c3d33b23c5a8aeab45f5bb542f6c9e6c1747ae5a344aff483ba38577ad534b33b3abc7d284776ea33ed488c2a2475648a4fcda561745ea7787ed60f2368deb27c75adce6ff9b6cc6de1f5e72a741e2d59f64751b3ae482d714e0c90e83c671ff98ed611823afb39e6e5019a6ba548a2a72e829c7b7b4a101ac9deb90a25d3e0c50d22e1fc26c7c02296fa13c6d9c14767f68aaf46450a8d0fd5feb60d9d73c6e68623425b4984a79d619dd6bf896459aa77a681ec9c1a97f645e121f47779b051f8948a817f84d1f55da170d5bbbaf2f64e18b97ed3fd822db2819f523314f1e5ac72e8f69bbe6c87c22daddb0e1ac6790f8534071de2f258064b99789bfb165b065b8fe96f9127cd7dca9f7cb0368420f1e802faa3ca23792f2a5b93773dd405e71c320b211b54f7a26626b03c060e1ab87f32ac588abfa056ce090bd7c69913a700c80f325bfe824fa",
+ },
+ {
+ "0967de57eefe1aaa999b9b746d88a1a248000d8734e0e938c6aa87",
+ "e4f0a3a4f90a8250f8806aa319053e8d73c62f150e2f239563037e9cc92823ad18c65111d0d462c954cc6c6ed2aafb45702a5a7e597d13bd8091594ab97cf7d1",
+ "f2db28620582e05f00f31c808475ca3df1c20e340bf14828352499466d79295f",
+ "4349e2131d44dc711148dfe3",
+ "bd06cc144fdc0d8b735fa4452eabbf78fd4ad2966ea41a84f68da40ca2da439777bc2ba6c4ec2de0d003eb",
+ },
+ {
+ "c4c920fb52a56fe66eaa8aa3fa187c543e3db8e5c8094c4313dc4ed35dfc5821c5791d171e8cfe8d37883031a0ad",
+ "85deea3dc4",
+ "05ff881d1e151bab4ca3db7d44880222733fe62686f71ce1e4610f2ea19599a7",
+ "b34710f65aed442e4a40866b",
+ "b154452fb7e85d175dd0b0db08591565c5587a725cf22386922f5d27a01015aba778975510b38754b2182e24352f019b7ad493e1ed255906715644aec6e0",
+ },
+ {
+ "c4b337df5e83823900c6c202e93541cf5bc8c677a9aad8b8d87a4d7221e294e595cbc4f34e462d4e0def50f62491c57f598cf60236cfba0f4908816aea154f80e013732e59a07c668fcc5cb35d2232b7ae29b9e4f874f3417c74ab6689fae6690d5a9766fa13cd8adf293d3d4b70f4f999adde9121d1d29d467d04cf77ea398444d0ea3fe4b7c9c3e106002c76f4260fa204a0c3d5",
+ "72611bef65eb664f24ea94f4d5d3d88c9c9c6da29c9a1991c02833c4c9f6993b57b5",
+ "dd0f2d4bb1c9e5ca5aa5f38d69bc8402f7dbb7229857b4a41b3044d481b7655e",
+ "2bbca0910cc47ca0b8517391",
+ "83aa28d6d98901e2981d21d3758ae4db8cce07fe08d82ca6f036a68daa88a7dda56eeb38040c942bdda0fd2d369eec44bd070e2c9314992f68dc16989a6ac0c3912c378cf3254f4bae74a66b075e828df6f855c0d8a827ffed3c03582c12a9112eeb7be43dfe8bd78beb2d1e56678b99a0372531727cb7f2b98d2f917ec10de93fe86267100c20356e80528c5066688c8b7acba76e591449952343f663993d5b642e59eb0f",
+ },
+ {
+ "a9775b8e42b63335439cf1c79fe8a3560b3baebfdfc9ef239d70da02cea0947817f00659a63a8ee9d67fb1756854cc738f7a326e432191e1916be35f0b78d72268de7c0e180af7ee8aa864f2fc30658baa97f9edb88ace49f5b2a8002a8023925e9fa076a997643340c8253cf88ac8a221c190d94c5e224110cb423a4b65cca9046c1fad0483e1444c0680449148e7b20a778c56d5ae97e679d920c43eed6d42598cf05d10d1a15cd722a0686a871b74fea7cad45562bacf3bda937ac701bc218dac7e9d7d20f955429abdac21d821207febf4d54daea4898837035038bf71c66cef63e90f5d3e51f7fcfe18d41f38540a2c2958dacde16304e4b33da324030f1366f923c337",
+ "74ba3372d308910b5c9c3885f41252d57556",
+ "9cf77bd06a4ed8fb59349791b98ba40b6019611942f5768e8be2ee88477149e3",
+ "b928935c4c966c60fd6583c0",
+ "ec7fd64fd75b254961a2b7fc942470d8620f439258b871d0d00f58028b5e0bee5e139e8108ac439391465d6658f559b1df57aa21cf826ede1a28bc11af885e13eebfc009870928fae8abfdd943a60c54fca93f0502dc23d29c2fd5340f9bc0e6ef2a18b66ef627af95f796d5bbca50de22c8ec802da9397089b25c6ba5262468e3977b45dc112e51896c70731b0a52d7efec7c93b41995823436bf4b0c477ae79684407c9831b487928b2b8303caca752b3edf1f0598e15831155462706f94ef3fa3a9e5f937f37085afa9b4bbf939d275796a61b78f70597acfd25cd87f967021cd99328fc371b5eb5739869520657b30e4a5b0db7c8715cbe275dee78e719b357d3a9731f9eaba95986479bb2004a77822fc115a3d",
+ },
+ {
+ "b3d3128bce6bbf66fd78f1a18352bae56bfcdae18b65c379ee0aeb37ee54fba1270d2df578ec5b75654d16e89fd1cd0acda7ec580dafd2fbbabd32a8112d49383a762db2638928c8d63eb0750f7e7fdd256b35321b072dd5c45f7dd58cc60dc63d3b79a0c4a1689adf180fef968eccbcfa01ee15091ceacd7b67a3082db0ce6aeb470aafe87249c88b58b721e783dde184ccf68de8e05b6347fe6b74ae3adf9a81e9496a5c9332e7ebe908d26ce6b3f0b2a97e9a89d9fdd0d7694585a3241f240d698e69fcc050e7a959ba153f6d06f117848ba05d887134f1b6b994dad9b9e74247513e08a125b1fadfc7394dcd2a6451b504ae3e75e22f2b9bc405747dedb6c43ef4ccdf1a7edaf9451346123eaa63f3af113124f361508e255503a242b96680ae3360c8b13ac1f64d08088bb26b7f617cb0866f11d6fd362b00d86eba3fee68724e302388f119d6f92161ac8ce00d08919377a26974d99575b1032ff0f1976240c785c8b89e9eb2bf005e4be06b5371ffca14683fedfdb49e00e38ff27af1324177faf91599abd5990920797574eb743effdc7decda318ada1419cc8e0bfecf82f9c99792746c2b",
+ "7e8da4f3018f673f8e43bd7a1dee05f8031ec49129c361abbc2a434e9eaf791c3c1d0f3dad767d3bba3ab6d728bbcf2bd994bd03571eae1348f161e6a1da03ddf7121ba4",
+ "7ee32dd501dce849cd492f6e23324c1a4567bfceff9f11d1352bcb8615f1b093",
+ "8998e043d2961afa51ea262a",
+ "ba85e72af18cb5ba85a4a0d6c28b4ac1e5509a3a2fdb0e3255cbc559df5e6a661fc560c756a0264dd99b72c61c51a4b7ad56ca4c8ccb7e8edfc48ff3cceac5d1e8ac5fc87096adc4d0e9a27492857b17604c3a694cfe0e70b22df106c8f3c61f840bcd634964cdb571840e125e381e7dd3a0d97972e965f16f775fa4ce555124318290bf508beb7bd77e633042deb0e863631478fc3dc9122862b3c31264471bcce54e0b74040c8bafd481cf798f332e8940f1134d3027d6f28e771d15e154fc89c6c25fe18a5d312807cc2e623bb1bbb4f0b6ec71d009407eb54bb0759f03682f65d0da8812f84d8e97483f6a8d76a8417efcd9526444abba24288647609791578887ef49780b0b89f51b072cae81c5b5014463da3633dda105b82add0f9c2f065dca46eedd2928be2570493c79a996fa78ea6aec0996497fe2dc444432ade4eaa662ee2255f0f4b92d593288a8e3ffe7a15a10e9d33b0203af23f4c9fd2cfcb6160db63b52810869ff1e65423dbe2c4415884b9f8dec3c968e14cd74f323c89053a96111bc9ce59ec483832c49c53a648e5f0f797f53642ac60170c94b473f1f2e7d8a38e46460b81219b52081263027f74cbf63a75af3a7",
+ },
+ {
+ "68d5ba501e87994ef6bc8042d7c5a99693a835a4796ad044f0e536a0790a7ee1e03832fec0cb4cb688cdf85f92a1f526492acac2949a0684803c24f947a3da27db0c259bd87251603f49bfd1eab4f733dec2f5725cfcf6dc381ad57fbdb0a699bccc34943e86f47dcfb34eba6746ed4508e3b764dfad4117c8169785c63d1e8309531747d90cc4a8bf13622759506c613324c512d10629991dc01fe3fe3d6607907e4f698a1312492674707fc4dde0f701a609d2ac336cc9f38badf1c813f9599148c21b5bd4658249d5010db2e205b3880e863441f2fe357dab2645be1f9e5067616bc335d0457ea6468c5828910cb09f92e5e184e316018e3c464c5ce59cc34608867bd8cbfa7e1286d73a17e3ebb675d097f9b3adfa41ea408d46252a096b3290e70a5be1896d6760a87e439334b863ccb11679ab5763ebe4a9110eb37c4043634b9e44d40cab34b42977475e2faa2ae0c0a38b170776fbb0870a63044aa6679545ac6951579d0581144cdf43f60923b6acaecdb325c864acd2c7b01d6e18b2b3c41c041bb9099cce557b114b84350131e3cee4089648b5691065867e7d38314154355d0e3ef9dc9375eddef922df2a06ad0f0e4357c3ac672932e5a66b16e8bf4b45cd893ea91cb397faadb9d9d7bf86e6ceca3e9176a5baa98b6114a149d3ed8ea176cc4a9380e18d2d9b67045aedeb28b729ba2ece74d759d5ebfb1ebee8ac5f5e79aaf1f98b7f2626e62a81d315a98b3e",
+ "63b90dd89066ad7b61cc39497899a8f14399eace1810f5fe3b76d2501f5d8f83169c5ba602082164d45aad4df3553e36ef29050739fa067470d8c58f3554124bf06df1f27612564a6c04976059d69648ff9b50389556ad052e729563c6a7",
+ "7d5c4314a542aff57a454b274a7999dfdc5f878a159c29be27dabdfcf7c06975",
+ "aeb6159fa88bb1ffd51d036d",
+ "7597f7f44191e815a409754db7fea688e0105c987fa065e621823ea6dea617aed613092ad566c487cfa1a93f556615d2a575fb30ac34b11e19cd908d74545906f929dc9e59f6f1e1e6eaaabe182748ef87057ef7820ffcf254c40237d3ea9ff004472db783ed54b5a294a46cf90519bf89367b04fc01ce544c5bcdd3197eb1237923ce2c0c99921ca959c53b54176d292e97f6d9696ded6054711721aebda543e3e077c90e6f216cdc275b86d45603521c5aab24f08fd06833b0743c388382f941e19e0283ac7c4ef22383e1b9b08572882769c1382bab9ad127e7f3e09b5330b82d3e0c7d6f0df46edc93265999eef8e7afa0cb1db77df7accf5bff8631a320d146a5c751a637a80f627b0c9a41b44f09212f38c154226de02f4906ef34139bbeacc3f06739c8540e37334392d38ba1cbf4bc7debe77c09b35d2200216db15ed4389f43bfd8ae9bf76fd8243c3d869546e16b8e44a6cd1edbd2c58ef890b5a84cda889131e5cd9402ca4d8271052c6b4fe3f2dff54fb77bcb575c315b9109f90b14bc8e109919808a581c1809e2a188d29fd34ce639088a6683f641925f5b4b3529baa34e080bb47fb7ad9b43d0d67c9e6ae7cacb50527fa74e56d0c8b20149f5d332d686d48ebbe634c2b5d35fc84c69a5bcc93b93dedcf9fdf19a1fb9b75f6df9692d16f6c3490377a06294499e4b8ebeaa0cfd840bfa05fde21c0b5e94d13063b3f5da7b537caefe89069cfa9de9eb8f06e4d30125de64716f821bcc8279c0c7ea2e",
+ },
+ {
+ "89c1ee38b6697d0190c87a2aa756892ee09fca095df1e31aeedbda5750f604d9b8f2116e5b8f70ec57ea16fe419f2d213ef72b9be90eb5d7e98f2e398632123e2524ac80b31c6c0a07820848223569602d94fc16a3b1ed8c411bc6c74ed80573fcb1f3afce60b9d5e2c21d04f78665241b613abe12274a5343101a91e91f04e5d1f7959f574e743a10913e0817a32c320467f0178e3b6ad14b856234a4661a755eaf14b5fd88ef0e192e1631d14263d6a954ed388f5709dadc6c0f81d229f630d80be6d593d5e3ad03f9ded53c41abe595981d24ef27ffcc930e4d653743960f4e7ce4e251c88f55c16d2afdaed5e3446d00685c276728ba757520acb9b6bb0732a0e9836878d829e5022794d70ad8440a40a132a8c9ec1d3f0ccaf8c285fff425e9788d6150b74753dedb2ae8b36ff2f310249bd911b9181d8310e00810d42ef94cbb5a9d72a1f0507c1a382f892b23994fbe7360778b7efa9c5e03ac3231a57fecff1c5fa10caf1d26e84db0137049622ebcc3a64841a0e49fa390d1d43550c1346c20d578cff39fb7404fcab0982dde55f0849d312581d0c811a19d46f25e7a5e7e50d74d43760583c5cf335dfc11b2ec964f1dbbd0ed83e18f2027817ea2dffcf2b64a352c4fb8f11eeb4f1bfc01079251254d2112d103a1f12a2270cc026cbeb8b6f3e505abd62496253f93274625786b73997e449c1f35c742a593441252fcc845e1cef1b8f287dd311a0477407ce3b31661f7b2802c79c2d20d06e45f03aca4e47a959c6c1d7a9d377e1577fbf82a115921c3d94e3d9c204aa204a9a5b04d8a2be3269700a035371f4aaf1a42d92b9bfbee74492b106975b36d1e581d6ce2484f09e04fa91586c85f35e2a10f0d3c0afcb05327c1bc9d7429bbcc4627af8f76b86fc561844c2ae3810c84901ac09a1670ed3d31a9daa5d296",
+ "7219bd21a834d917f93a9b45647ec77102578bc2f2a132dfde6489b9095b4f7b740c9c1c4075333ab0ce7f14",
+ "a7f849b054982cc8a4c8e5e53e181feee79e0233e58882839892134ad582da7c",
+ "4c46854e9e101090b1436f90",
+ "ab2e189baf60886bed88eb751bf3560a8bd3cdb6ee621d8c18b5fb3aa418f350048ecf359a7d542daf7090ec8688c3b0fe85914aa49d83be4ae3396f7bdc48051afae6a97fca7b42c0bf612a42d3c79ef6aadceb57f5cfe8d67f89d49add0ea1ffd423da058297239e72a85fa6cd1d82e243a503b1b0e12d7510a9ee98d7921dae2754d7581e52acb8ab9e7f9df3c73410789115cef6ce7c937a5441ad4edf2b7a8c0c6d152d5a5909c4ce839d59594a6163364038c4c71a1507389717f61e2bda1ea66a83ef477762e7834ebcfaa8f2ee61ced1605ba1380108236e1763bf40af5259da07dd3e3d0fb2801868c2e7c839e318678687cbe33384e2ef5750a0a0e2d2e19e869a4277e32a315ed4de79357f6a12a8a25d5b18291316d9bf40dad2d05d1b523ade76650669c700a1c2965f4e51337aa5d45ec7b4981072779401d6d30ed69034053334bccb18425ac68460becf2aeccc75aacd3d6709f07ee10366ed848c8a54904af4ea71fc2117de133f01e1cc031f2a4d0779b997b82682433ee615202d5dfffba6c916f11a00551d56ffde8c36b303263e14adaf45b6eab0bedf344e5214ce52f071d2f40154d788c6870020791a03d2fd4ec5879d9026241954ed45cfddef4937ea3d0d45647f252be31411237983a1be340fc65ebab9a5620abb0e8d475af4e89e842e895eda0cbd283bb5d0bf20236c62d956de733d60ebceb42fc0c9adbf9b69f8d66551b0aca0e260625ad41cad75d752a234af7caf7902c2c5b62f04b6a8e019a6179d44feeb2ad5859ef1c45371e66f1af1fe0de63997266c290e27f0dd62185c53f81e0a50c296a51ace7c90d9cf0dda8b2d7e72a347f64c44262e2a544d1acc7bb05734dc1783bbc1903279092fe7fe434610aa95fc2ce5fc5ee45858f5e8337d8fcb0a468464becb1cef6b7e5ea48ba383ad8a406df9c581f1cac057d8711fcb",
+ },
+ {
+ "2dcfbb59975f217c445f95634d7c0250afe7d8316a70c47dba99ff94167ab74349729ce1d2bd5d161df27a6a6e7cba1e63924fcd03134abdad4952c3c409060d7ca2ee4e5f4c647c3edee7ad5aa1cbbd341a8a372ed4f4db1e469ee250a4efcc46de1aa52a7e22685d0915b7aae075defbff1529d40a04f250a2d4a046c36c8ca18631cb055334625c4919072a8ee5258efb4e6205525455f428f63aeb62c68de9f758ee4b8c50a7d669ae00f89425868f73e894c53ce9b964dff34f42b9dc2bb03519fbc169a397d25197cae5bc50742f3808f474f2add8d1a0281359043e0a395705fbc0a89293fa2a5ddfe6ae5416e65c0a5b4eb83320585b33b26072bc99c9c1948a6a271d64517a433728974d0ff4586a42109d6268f9961a5908d6f2d198875b02ae7866fff3a9361b41842a35dc9477ec32da542b706f8478457649ddfda5dfab1d45aa10efe12c3065566541ebdc2d1db6814826f0cc9e3642e813408df3ebaa3896bb2777e757dc3dbc1d28994a454fcb8d76bc5914f29cfc05dc89f8c734315def58d4d6b0b0136ccd3c05178155e30fcb9f68df9104dc96e0658fa899c0058818da5ec88a723558ae3a6f2f8f523e5af1a73a82ab16198c7ba8341568399d8013fc499e6e7ef61cb8654b48b88aa2a931dc2cdcf245686eed9c8355d620d5e91c1e878a9c7da655e3f29d9b7c3f44ad1c70890eb5f27ca28efff76420cd4e3cebd5c788536ddd365f7ad1dbb91588d58612e43b0460de9260d5f780a245bc8e1a83166df1f3a3506d742c268ab4fc10c6e04bca40295da0ff5420a199dd2fb36045215138c4a2a539ceccc382c8d349a81e13e848708947c4a9e85d861811e75d323896f6da3b2fa807f22bcfc57477e487602cf8e973bc925b1a19732b00d15d38675313a283bbaa75e6793b5af11fe2514bda3abe96cc19b0e58ddbe55e381ec58c31670fec1184d38bbf2d7cde0fcd29e907e780d30130b98e0c9eec44bcb1d0ed18dfda2a64adb523da3102eafe2bd3051353d8148491a290308ed4ec3fa5da5784b481e861360c3b670e256539f96a4c4c4360d0d40260049035f1cfdacb275e7fa847e0df531b466141ac9a3a16e7865947572e4ab732daec23aac6eed1256d796c4d58bf699f20aa4bbae461a16abbe9c1e9",
+ "33791b0d653fb72c2d88519b02bde85a7c51f99cfb4456dfa6f84a61e10b4a14846521",
+ "a0a7b73ca2fc9282a28acc036bd74d7f5cb2a146577a5c29dbc3963fe7ebfd87",
+ "eaa4d916d261676d632455be",
+ "c9a631de470fd04dcbf8ea9f4d8ac37c3988878b6381707ac2c91d3720edbb31576ba90731f433a5e13582aca2b3c76ae75ca8881a463ecfa789910d3a776a9ad4800521c6baa120b2f1afd10f32ef8da63f5b69f5e5fd88ee84bf66b0666b15d05c4050f5358a050b9d5cf1503719f56cd48ceba78f29efe2ae8092e37f5134df526831532f86ccb9339637e2c9e9b9036f83cc058fda23e826a188456e7fd3f4ee20f4e4a3221883fe3232b49db607b90a8956133ab95051c9ec33a908ea7e81a1bfa7bd06c09f0143d07bb23a3feeac7f0d7720269c93e2df19d03605828c8713b84d183c9a50954c12fe3b047511ad15ef03a63355520cbd224d06a34de67a671368e6a8f9feeefe48fc273764a8c69c00314e5d693f159cb5270544f3c4e1760b0529e3303ab308e9a6d03835a3a42aef2df5f7643696f707a574d1dcc676aeecdd9947ebe8c13bcf15d30b2d10d2cd95445a307c1d22d39450615ad38f9302c6eb9dc05764b0503d6a7eaff9feb94834853b47bc25660207be3e7c0e27cb3127b5402cb016396e5ff07ddc3df29861dd68a17f53bf660b23352b739d6da72381b8d19a9fc95da7efb79330a2b360dce4309860af429e3fd10cab235c4acc1d80d9e20d67019375bd161ab65648400f308815afe63cfc717f7d0eea150e687caac25b6603287d44dca4a7cc2f67c3bdd54450bd3170340253b03ba054ec003070eddf9c14fb9dc595e228e4968524900cb5d85af6d1e658a42d744e0e7eb6995023823a8dc33528c6715b2e1aa607782c8e1ddddad72026d657bf122ece8685f6e92236e809139325e4a3c069facf94c10b7896995bba01eb22c7b3a87ea2114a7649d7ed3e83d223e5e785c66a75119beab0968d3eaf0cbcc2d7ede95d024041e6db39a880ce3e19efea32fb89a40a2aae22f407e5fd615e51e48dbd50a8b4ec27ce95e2ba1928bf699d0418705482ed0ed7acc858dfbd690403c74667a88dd5221bb79940c6c4a268379c10343aaefb635982c14f33ad83d47ced9682961540bd4f75804d3d48ba8aa67fb2e3a1db83fbcbe57fec9e4ffb1b575e947f8bd8263c680357960e3a39382974774b5a013f2f8514b3c63c21dbfd314fd5d927d82ba616d76629ac018879f54ff84b5808e94af4fcfe1cf8845b65208ca5510b5b593ce6c109611652cd",
+ },
+ {
+ "c335b055b752e083554b5aa2cbb6556cfcace658d5c11b6b000256fd89e9b24c1e62a2d5b582580acdb2ad9869020465aeeabe83acd9eeacdc44aa652d5cb24bbe542073d6787ea32b2b3c942d40f9db2bb75ed7914c836d902dd2be89840948d82abbaea23952cd648e6191ce5b6cf912cad0a3165410a781e3650b676e5340980eee3b484008acce6a3e9dc5aa96d775677b8bbb8b323c6e9747d6069a169ea904d9f145e29d134cdbb0118647e8fbae638669efb9a55d50ed33568749f5304ece2193b0bfa6fc9a570d209ef61b4c59a2b5485b5aa6ab47d902cf23f7ff71c5210476e0aa727a01809b9f76b6ebcf58a018b3fbbe5f42976111ba58112b1d322f9312da068cdb86277bfcde66cb3607e3ea02a1494439aa56f302671f1f994eb3ab28b937043f5f7f3b3de50673ecea5dee8ba633c45089b852f0d772892525344ede6b521dcad15807b65e7ba348d891d47fc498cf4d50223d2794c64db9fa9b9766edb430be0c38746ab317b38ba9870a6d1fdabb70fcf89790bfe449b97fe01f6c94502aa0889f0a3bb6bdc65f44d1cd64ab88d4a7806b373f5080f9cf60183cf4686694f0059e2bbc5cf21ba0c3e8046e70d815f1444c3094cc29632c429f20aa06b49b0b52c6c7aeb8e34f7bcb53e93c2cfe2d704a5d0416876742c90762730d160e1869d5e0178dc366098ebaf2cae6f1f7563b555a52dcc194a5c8f718d50d27ee76fcce8e8991f4921fae85ea9476e1eab1364403120698b7ce8fd0a49cf79213f360a17cf1950f104494fad80adcc3bb1207bf250d57dcdce6ac8082a312959672361363cc227310b66ee8c04aab7b5cb33a81c0915e9c770a1cfaae2e8f44a0c65703927977a22fe58aef2f366b8be9a50da9376b46ae7562a82391386831febf359039ac326891bc58c0f2c34bdb6858859fc3cb4e392df65cbe2ec4f02c8425bcbdd1ee2562ab7d229d406d79a9c6fe4889c996c2f68d1fb5bbe3a5e867caa4249b934afd3ec71fdb088c54b15252f9dc1b909e121dbdc7d8a16cc00836652dd1f877ce363eed11467966f7ccb8f1a8d48146e69e04ad76a51937ad4f9cda209451eeca90dbdbd65441ce20fabfc8ce400fb4de136154b87a8b65c92740e9bb91d78521b261f806a2c6279c85ef6ac5fe1ea3117ff7c9f9832fc2aa6fab660082eb22344c1a3befe0628b6551f62a5014cd6194c42b8d475a50f2c9fb58c97e43ebb29005ed7fe54f0a4aa10074f1154152a9067d364dd7863fa082976a00db55b26b5ba0ea40eff48b90",
+ "f5ff810a41d4b34751e9942970d4c9f26b33f24689a4b1e4449b243490afc485af468ff01a42376b2bcb949b9f5e8d0b917f511a",
+ "a74271c184a82cb074c14b131fd91eb05870cb7c73c9e511ec8140bfe2f34089",
+ "2403fe689e239c2ed261b381",
+ "af9be893d5fd23aab42e6a2e59a8e7cb13d4f543db02af87cb0802bc1af7c717cd0093cc8244994cf21189146922b69927ffd5745e57118bea07a6afe7c21d952c13ab636b3c2e461dc9ffb3ae701175360156338be94b1fa7115799831019455cfaf5114010fe45f8fb9c77ec50fe06f2c5a32423edccb3b2210ee1200a78e1a3130c567542377827586ca8cf0c14c19fa1449a2cce9c039bb441b04e9c0a3f9a743b31c828032174fcdb7c894349aa68f5adf97dfe9294d24e6b5fed95eb994397883f58487bf5c57b0aea5268be7cee9efeab370f89805ebe5373ab2e93658fc078955ccf68b554dd5605005751ee8531c35ca5336a5d0ce273370c0dc9307779b86e96d2d1daf2620d67d43e1fb7800ccf250ca3c02eb74047c1d2a2bc7f29fff8320301694b80d0fd975f834337d00d5f0e4215044d52aa4ca21e6a9d7e03f186d7cdd5c48e3765dc926fb0a46bb0f05c50d9f69c9c507527a60366b7dc251aae1d6bb0d9c73735dcfab959f6fd4382fe2a1f6ad07affb0601bb9040f81b55a48f6a6c5f8ac4a2acc2b0c9a6c439198f7926460695fa11e0b0b017e39de5cf0d5d5f84d972b5eee7b5d1e0343b5485cd84b92ad892e5b23f3e803f5b363f2398c11c15be9f13e59922b0d49902dc8483fb142850b4226da2fb84e9b434a34f6bb67f575a9e57fde3354bc3077a876e260311bb2481bb139aa9af55df5074749fe532d7b8a554218a90cc7e7ac69db280bae5d55a174dfc8d325b9909a8da1016d4e162fe5ba70cf8726cdf291f5e47083d9929cd5e32021cbfd982fd0975f6f9baf4322b553cb3174b11c007559879f308419ff9e4e18eee8d3640cec8aea082b90f69cf3c7676c28af0265c24c91cd58a06513198892ce6ce1ab3ee9ac0a2e937b973a9cac06a039a54f8d994c13d42c59187f677352e5feb32a417aebec4d852b2595e7e67450e06dbd183279e3b63022a3813b37257b085bf8454d6890875a2950d20210a8df4f9da746722f62687e92f0e9efc3e5d526d65ccfbcc042fcac7964dbe147932c73924bdcdf62f9eae58d29e8567ffed90048bcf0566b952e986efeae4c477944af18bd243c3eccf8d88c06d07279adad037450cb8547a8aa0a74223f4851747c803cb21a2dd027e7080aed75038cdcecbc4639d87763cdd41829a1b72cedf0d722b180d0d492a5740ea7607b95f3201df352fb1ab28149124d2df5d5ec106867897b537302c3431402348f94d28eebc701ae1b49d10adedea38f1654fbc48885e59e6e6dfd413c6b5a97d8c35dfb07a6cdefe317bf61cf91",
+ },
+ {
+ "4aba5a776ace38b6e2578f0007e770d264e39c49f588ca3547ad2888365e3a811994f8836330394587c8458eb0b6611499fd5d8e8527c3cdd4ec550b4a8f8c632384e786b420cb3be911c999c72aad60270aefad31b27a069ecf11e95e9d4c81213308d554d3103de4d9d6ab04830c2b8dfbd8bead52c44c21d5357f72810193b5096809dc7846c1521c6c569f78812c735aea21acaf6dce84a24df7234e8ad857f3e1346b27f5bd436113e2da950e4deff96e9ba8db692c7db723a105ae795da15b910c8286cac6e7dda8c172b70f61b07dfd58596684d61da8772356f180f74c1103ce97cd947eab3d401df44f7fa4cc7cfc25e280fc002873237e64a375b0b4797f4b4613c9f150090f44588ee8250ae44aec6546ec8dba0f0c1eb281cf66fa4eb141617b32b28441f6ddcfdf02d9c34cc62893b2b64dc2c26b74433adb3e888c7fea07b19c8cf39269c2716b9c35b7625d4a141397d6d5034b193d2657c6b2d6b0ba874c467adeaf3d501ad985d13be21c4ff6b326cbb671e4f4973bba49116a0399b6491394f850e4122969e4644c00b442b3da0d6a4bf25ee22d182b3f822fd83878ebcc713cb183651a67ca66677ea81b58b685a3a8e385d5fbb0147ddfecb558d881c914324c794db443b31bc15c361912bbbcba9e418f99f2a416d190cb29684df27c7f3ff6ccf339800efbdc4514ee00d1a89f12373804db4fd66c1affd467f251e73147b3248033327b0f7790fd7861a51773dd4f78b89e4e24b94df9203f4a077091bb9411eec78dfe3e1dfbb67ea1cdf17e1d6936bbb75b74055495449e9cb52f5749404610cd444fea3f0568e0d35a5ef0c395ab7bf0208044b5c4e2517911a9c351efd31f33220972287253fbccb1eb8f46960a36b68a7a6b4f5cbdc86d668bbf555fde8881e7faa9594da425ff8fb54526bf7cdc4af64899530561c06bed7fc04c5d48cd4542779e901bc48fab79d4d13850ad8247f51b9afa7d5a656ada25b6376d837cb0fa1b4016dfcfc158a39290f43f133b352ed52fab2f951509bacb41284fbdd849d8185fb7e7200f8ab2a07ef2b3b927e18e568dbeeba2c7a66e08cebdc6a6069ebe6656a586652f3905ae2bb867529af6a827b494c97b3a378408f44aaefbe86c613e11e7a44020a9ee4b62569dfc4c462300daec7b1424ff1c1849ca1332367470475c14877cbe76c820cc651c18ab3f18852b93994f93b568dc7f7b0eb5f07ffc4c9384c851fa9071c6f68ddea1ccf627f889c0471c76aff9f52b07ab1b86a7671a2b2f6b25c0ddebb66ac95737bf7e2f493f7665b5265eaa5166556cecfdd3062802724ec24f3978b903d0f0c24e1f0b8d967142bccfed0d354279223f4c28684e9ab611e9ef89a3f25993b5a8b3c0354931780501651236a78b58e7d7814f251b053605f4c0a8e7193b9cc1ee5cf7378e6f3c8fd44ec57bd91e62b09fb1d6bab60cbfabcc6792e6a32ea7918a9ec9180d05a7e1546d5d2d8bbfde2a71b4e427c0a4d28d0b6473ae",
+ "921a401db90935c60edda8624a0590d5c46eff3522e35de2872f6f9394e24126fd8143b68a797c995624fba0298b75eef974",
+ "6a4d35ae03bf277f587da4541dcddf92bbd906dff45d5ff23c0f60ae53b062be",
+ "231b5780fedfb06d724450b3",
+ "ba40968282d98849b19d867f8b564ea5a81d657516099362926bca4cb6e9ae02719d10c8061f53008c727a0eeea5e1e36c9e55c117e9434e213316c96840231a1e356b254a9981d4a6ca3c66cfc61018bcaade1a4486506559e6aa3a86bac980d391d835fd5ded98d10f1394d84bf1bbf2cd3397890d704154802f7864ecc753db782fd3d19213ae65ace4770e1bacf32d61c6730aa5adcab4d7e2e437888c11c29abba4890a17a00f67a53b660becd94092df0598df5ac57326f6860593a519e28bd4a39f6481e1a4748881fd5f0456a3cd9f28d1d1e78dc64030cbd8fdb2c5abdab3f13d6ccccd187e71e989f8c486929efcdbf2a763effa95af62db5cef95e9081b818275c69267022fda4b7fdb8c650b491a785b03d4d0186625962b6326ec3f4e176373da4dc1f83a14815adf82c6bffa7c6967d77528d0249754bb4d17656bc4a89449b16152a4a1aea7eb0054a8892f271138971507d2f3b237ba5b620f444544e4a8c2b1ab4f9168762c27478c9f776c47ee2e9ff05bfa35ed127f0cabe7cc053640bb8aa01f8359b74bf89ef43ca94c48fcd201eae39d1835957eeccd6b3a852f4e1bbfef9a469f42c764481ff8408fe5871afeeae7676b58f4202199aad50a596626dff97c8e60d750cc59da9f595ce12ce9afdce14481cb1e39994de8fe4cce07845110d6703dc59d34734e93e9e57e1c52d61f44143a2d290220a4bad5098d098ee65ea4b6757d8a9bf5485aa3d697a7826d4a285186f5da10eff707566c23c6a15033365bcb498c44487c72d96402d1834753fdbf86770239761f03e0dc8963766441da99c0813e4f1df5a1d018c8799861a396562eb24ce305ca15f4022d83ea3c56b68d9a7ceac4742ec0ce50f4d36273df26005ec2b051fa071b319be2d8a5ed26eb75bc1ea83761b8454db234d15d84d6706cd178981c1f156e6d28f774aee3e9a4fade022e71b52b50aa532b8bc7fe464f22d6eb169c69671875d614e987658820c2f584a4fea3008afdcbb646dba3d69020fbf503f121be3480344db23efdda0d255aa058c3ff66abd3a5fe35db977521608bba7eddae72ae801f4fbb12a1de4133039e046ceb8db87e465e5ede1d79a08c857d59076d7ff858942c31e15cbbdae6fc15c3f9545a0825d6ff8583c0aba8a7d143d27b93f6caefb98c0d83bd8715abcab2a49087f55a9daf9090eacdf45be08ad80b5df5070e1719f68c4cc8f8711083f0f7823a09ec092f22df95fe9e95114fdf82a3f6eed0bfc9c0aa65222609442776154a474dbc9e662cd5dce66846572e52417ee5d7eb59287d07ef60a9537fe1f85c7fa74fe84dea0da235ac7574335e6649b54a6bd33397df4bf4a7976c4ab868aa702766d2bc8d2c82c2d1c2653fc8428b8d1e61852ac185a3a0b416dbcf8eb54c44967ff43c44f2b32c6d4a9dbf2c2f3a587b430aef50f0375cdb4c1b319ac9aca486d9bb321141b065f52f7b6decaf1985531ca7bbc3772a561eb1efb8a6297075920bc432131a5b211bf25e35fa31e12833bc77a9de14c7",
+ },
+ {
+ "6c0056937faf1023032df1e2bfacbbc58bb022eba25ffa020d4eb26f0caf0678af5d0b2f0c1b520f4843f107f0adcc7b5dee66ff4d61025bafb4cabb64d133132e3e423a599549a1d83aa8c8e774444462aa44b00b460bbafad5755ea6a872d4e6b40e3f4957e0229288ea79fc2ebe5fd9020fe4481a9f42ef14a196bd136aa3c779e311d0c333624c1ddc484c9aa7259cb609e4d0a826c0bdc7567adac01da23900b30ac4e66c100348584fe200747eb67e6287268947e3509d5d2b5d7bcd977b80a13f660d4f6956a8b938a82db75eab19e5d2a22cb5f3c9131e278eebbe096b5f49d16c983ac240f3fbe821b247cccb2c9e6e59546122677f49f56a07fed56647a6d3e0e09520d49009f54250c10e7c607cd5b4ddf81b5c4110c6490e9baf56418236211856f5a85feaebafacf92c0c7501c052f9dbae3beb7484f90f334f50b68571cedc67763b5161ebfd5a1709cf18c92112a4cf4d8f43d1895204d8a2ba5e14883a7bff75cc6060cabb77d38a909daca2417befd1bfc05a11c432b47f90c807ca4306400f67a0d92218adaca84a584a8bd4395c93f9b6a4bde9583c79204444634a8473b1244cd33cf980e443d82ecfac672b3f60e2e41ecb3c5a445d9e88c0e90c339a31806e6d79ee52bdc6808c73e8b7b24899966664d3c1a9305f31f0483e24e36fa451dc1d3f2eda05af6678971e2bdfb7c1461c9407c5c466f6b5af34d992a37de3809a22ae75275ddba0f4f9cbd4b18c1acd212192e587889a36bd73c860f0abe08bcd8f00f5ecdb95e1d560b586eccf530df0e5f3776d8dae2a01768bf1226b7ceffa7ce4e75879c82dd97db3c64c06d33cebc6b35854618355d80e46fa79c3e9743fce5b974723c421a077e7ec7dba286881dbc1d53d442a1552700fcb33f83f73c69a0a0ebdcf2f5d461649c4d0712c514ded268a31509f83c1ae4ff4a68e676d29727be641aa4487c08d4b90ff78e24c6508d69759751a1a23690ec9f8763621e8b107295b4bb01bd9fcacd8748e24d996fa70ef6f8b0992f4185bec8e920d7643159f9f604fba394b6611bff435998b2f097a9e948430899c8c752a1e83a061983f00f88ebb32da214399167932a1a83c1b47d09f77593b03cf6521520583ea4483e2d33e14ad60584676d1791779b532c085d238df0d3bae735d0078e0eabd63cc90a2e13d023983780afc8f83b1c14437937c16a1b7c41414c48cf4ae49587ad9fa5b16fc949a749e96032248c4667f58e295f999590dae1d99a2cbe3fa45bcf4a1d3f0356d64d40367f64b2c5cca843e5f7dd7b88a85d52328a00622e6c317879607bc036c9006d38652ffe21c83207c00f8348a7d0aaea5aab4c89077df170de6d41052641726eb6925cd85a9ee01a9e636346340e209ea96d17b0eb0921b96662ce9cb430fb6ac348331dd7133875769bbbba99dc49333950e4145a15ddb0789c4d2ccd38878080ca9e57ddc6cd5452790eec45482f8e990392e319609391fce0beba19463a9a00d8f1de9fbf22f23821de7d69fdfbf3019ed61aff79acfc5a6ba663a1e10da2b9ff7149aea43bd6c61a543008402309df0924de72c1cacd2d6120cf422e61fc1de345cc8771934d8be77d9437a09e06a9b2d51c849fd9a200fa714328d34f36b684f33df6968b827df916a599a4bc3367814fec21198e2213ff653cd2a463892966c72ffd42a26b3bb91",
+ "0d55dcd08b54e58916f622f81761ef6a2e19b167ac47d3",
+ "e42e1d6d44138f3d2bf12c951f454686f18d590fd30057405b5a3dc2b317fa97",
+ "1e46a7486c5a03fd6758d938",
+ "fd3c1fac10cc82e49235fd57f5aea0ee7a7bd6d539b138d4b3fb623aee591615c1a61228ef9673113a3a90a3687a12d4c6367d5f7bc67d422fdc4106455084d79c2c42c5e86368dd164bcbce7925bfffe7d96c13a2f49aac8e9d1ada3554e3fdc21aab00455a0f33b0c1fdea91b3588e7ad301bfccf9940027332fbdf966463491f7a33c093e0a13831ea9d2183294f89f414cf7b5876af04fa68d594430194429df74fa5915394427259e832bc545c13400aef6cf16620d48280798a6e49773c9316d79fa1dc758e54cde2e2cdb856092d83f4e9b698385cb976fd6cc2538abe055273a5b34a784182ea5e7d3ac9019a05de5e5afe4308a7ed2d363cd50ed6a52df1c616e4a82f607ced768445d13ae4884f2ae1f9fd8313924e8a1a8a23905c92eb231f638dfa6f4cb27bbb9844e05afbbe2ca4d1a3b3a5b371bf33c9ab6f82a7387d61cf8bf662097624145a983839b0cb9f4bd07556800b4054fb3d0bac94f44bcc9b4ac49c39f5571fac4e02ff09f08b3ed5add4bf8bba934e9feb773c0590b45c45fa036382f3fe9782ad19107d4630321e414b7b442b64f18fdd5219039e5740f34b3ce8925d1afe8a39e35ce8db086060bab63b9720700499f82db19a62897c6d845389461260303f9cf2bc7235a898b4620c2191ef05604a5c8c783d58009533a86b27c12b0772635d34ac53993ccf174c9087073e5e69b26c0c3d9f768507ac4d4e2af847b65e3a6e1b7a6dafb0aefc190871cdae6c60f0b1d6137c351d4cb211870791cf4cb8af2ea446f6401eb9ec8a5bcebccce898d1dfb13454df6b35b81ed6d7637e6e261e004080c60944f3a08e8e5fc7e2e4939e7c2607c8cf07d1d10883ba3ad43e2611826f245df571857ae0a7a867df9659f2082c19f94ce400132e48c7f8de2b102c7f83ba5cd1e785597a0ba0d73bb81bba0c00300d4bcd6ec25fb73105a46122873bfa729c0979d8d314ab7ea52391aabab513dbfd1cf01c2990c0a3612f4511c2bcf0f5a07e659a881a7f99c3f1fc4a46e66904427fe26a4a80a904c047d090c861a075c0ae4e29bfbc18b9620aaa42237f4c6fa76ee7491ee638ab5f1cf0b440759828e1ec519679efc776eb1468999a00f667e87199ad6891e98b95fb682e02517b024a6bb803ed23c944010cb7bad0733eccc12d6ab6030c6e88d510ce92e2f98fdcfaa1e37e41fbfb4e99589c0e8efbefd40473db42b3a73b57b22a2f8c9bdaab16831f1b117dd83a77dd01ee8d0c2e92203adb670f4fd65e618823ad196220d70e014c1aafd8863797c61c16382c2600062683ed3a180c70891717c52da15191b02f25d1715ebf33a5e6037092421989c942082f4b836423cc3e976c9bcda185de36f06265dfc250a27d2de0bc48c73b3bff704f3b386f962522f572108458bdb283c6ab3fd33b3ac13a406268fd5d97e17db9c0f780b4b2a8f761d15a4d8b3a0cd73357ecf4d26a6492ee069f19325823ef50bcb2f73326719a57b67eeef506fe8915a1b1ba1a637592268257b91e9c7c5d33cdd947967efc1952005d82ccef9a3ad7ef8ffbb6b658983d64c51242ba53f8f8963245b87a25aa9324c527e53f8c11d55f30aab598401589acd13f090541b3b057b162190f27910718b02a6b8ddbb8ca6cf40bf0d2848f4b76341bd5e78f476862bcdbe2d1bac84c0566fb45b21388221ecd8483d99fe603646b1a9f38a49230cf4dbe5d7883d73eece01bf",
+ },
+ {
+ "04892b94c65685f2eba438322b29bf8439938590d3e0eb10a29e279d356cb439f6dfcdbc3552af21f7e753221012a649a52bda780bc589ae63b04b981dffd113df9fcf14f17e35e865880a769bb1bf40dc99b9e85e4296c1f2e1590fe02b22bfcaf2d4bb7009a4d692ae4c2d5f0b6d3ca526240368bac55b9b1e6a7b498d3b137f0fcfef1873c5aa2111d7811d45bdc26be1c5d49b8a2f36a999b1f226ec06a5fbd59514485abe696c96ea89dba74b4688101a239b495944e30b3609f73caff3114407599ec5c30a5bad933655de7dddef97018ae15acec46504cd5d417c5052c057ac5f1c6f69781cfdae71db2b4fcac35054a4aa22681027356d68b2bdba721466d130d53ba8f23857631382b2de450232e9ad5551bd7c872ae439e79eabfb057d2bdab8d4ccf02b3003ade2e1f3e514dc92692e4fe5b579c9ee6067995b6c168647ce5a13be8543c23326a3260bb7029d2030ec05e565ced3c5366d20a283a6e95201fd108640d2b96676df712de20e4e12fa53f85f22cb24583844fabcebe40eece11e7221f12c88670bf994ed08e2000236f86258c386b0fccbaab8b68ec6a26fe41491d540193c4c12d1391ab3391de9317f41f505f1f1d09ca9862a6f289a533d2b297d4465c956360371ea3c8ed36e0d1563120654e3a2fd69cd6c9267bfcf92e84cd64e162c84199d6e552b42c33857264b5d7a2e007797cde32934a3f8c68b459cd95bc85e7466ccc9910e8dca65b315c32e43c3a5da908904c42cfc8ab74126919ceeef1054bbdae6ca67b02f1ac5f24808b5eee24577e609a3e3935a24b9ebc1a8dad1fc96abe26012928f2d5782755f3763427dda28867d0b1ad830d3c3f17b9ec278346e5a9480ed23ad44a523a4dd86e65a610ee0de1afab64ace7a3b4918fdc14c6b1ce0ec0903994da9bcf18643d7e0a4e6c08200bb394a89b385d2cb829417eeb0f7dab9fa7306a330f82973cf0917b5ca99b585d2ff0e8584e050077467f5245ecfdd5942e4fc72dc26e5ab2ffc61f996167e68168cee9a6d3ea1e1a696060465e35da8c75a1aa380004faffcb0a992c627fbdcb4e97721271802cdaf08d214ec2fbcb389d75709d7a6b9d35662661c8961f93d4a705e7188613f3769114c55400809cadf60d3b6068c8a5ceef078785171b59be1140c6a754ba1de5ced349df63d67d59d3a8ca3c716ffb506772d57e9e3f2caf7fe346c4ad64aa6c37e43b9bbaa8f58e51bfbac31fa6137728f8e5b728025697e5ad5c8301f6ff39eb2ad595d3cb24257adee88a84fbf1ade4d7550cd9ab94bf48e1424ae83184c35c5a5920157d45805c2e0ad129fc7f0ec3c41b9d6fa04cb8918ef379b0783d1cc2863cd80382585fa05320ca4f9fd90353e490b384ed6c166c6f802cd7bd39aa43667246e8da96992db7537d472c709b01114e95febaac5b1a3c77e1e9a18c2d180e63f0d8fa89f6a1ed63e909e4741af5c2a0e47d4d3f8779b7696358f58060f3f461cceeebb390c92779d30bfdedf1b08ed62dcc05a545bd0ea915f42976e81dd8a50cc4689d8d8007508bf53e7da5bd43c3894968cf0677681c6b818353af6bf8ac205139add1310e5d363ccadbfa0eaf735808325e7f9a6aeb1bee3ebb4a27576a88811859c216b6f84371c43d8063a0d87bd326eb6d81c6896ff534ba2c9c14a51d2cfedf33a5c787279bb4a7ff65706b389756a6191d2f791254233ee047d40d64c2dca878a42f903fd4382f39a89a723fe11848fe37b2008be53f7c2d037981d6462a4eea49df1a2e074957afd3c9dfb4d218a309cab395afe301ccf",
+ "67b5eccb1790babc2dab5e0d1ff3871c3024177d45a2ae",
+ "259603e1c3af3fd0ce3257eb627b02e0c0a48ea2f175de3d8c36570a445e5369",
+ "e14de73c4b17581a7e0d0649",
+ "33522e67ef932da5fa8abe628b51f3abd5049951dbc982ea95b7769652d4830c588fa45e3fcff094c8602b9008d7b2f9bf6c1c4a8cfb515401c7c44a7ec42ccb967722a710199e121a41160b1ec581507e9bd2e2e506b10c4b5a8d6977435aa08e27504957cd49e756e1574c4ccbbdde937de35128b7ee3455d2e665c596c2e97c253c94e405f85eb5de84874c099b4a97eb8f492d28f2e4bc64b228dd5984e76ca08376d7f1355ba8e0fa60fca96635075417d8b436278e0fb91e3bfc7d61ca8c7407086933c061b2d318f46f352099e1d317d6c44098539d1d2c1b7894db668e7a82ff991864fae236570cc420a4229883f1e2242d05aa07e175bc6abe11cc643cf1786a4456a2de8c066fb1a70fe387f149ffbe8cca7b110e256fd0c09b1d3bd7381cfa82fa700c8db1e79809ccf75ea52d0b349264557046e8703a191ddaace00ccfc513db5e78810eaac0a99d7bb1a5725e722d4e595216a0e12f3a7aab2e623ea9e1dad06169914bcd51b643016fea7dc3f2743b1e65877f1fd5581bee5ef206d86494a587ec8462a170746fcedb2c9f99090674ee687382711b4610ddac599732453dc063518aa36f5b4129098fb9fddc02eb8f8cfc2fdf0d904ef4d6d06014f977b29d0e9aab4044ce9c662a18b1a8db1ceea97854e90704430fe9b1046b221b27ac79054fcc68c3abd6fab7da66e255ff0cbd0506c852e961e619615c944cd9a05c25abb63742f5da7bd9939feb0f2f2208c8ce82f551a9d4d70e935dad018e3e4e6998e39670221601c3e34716ba75eb4e2fdf53c4d471c444330514986de45cf44d77f793c17e36a271fc65e6bf08943aef4c66547dc310c7a430e3fe7a54898de48f69f282f52bbdc4daabdb325cec7ab66fce1aea4e2fd932dc1a316c821f5220ea437447feae2fa478adade7cd515a27d8c132d0299b3ca1bc8516c9d9e7c65c38c238c69f03e104eb42a29cacc8d79b808ea6fb233a5056201e3697f81a2d49ccd8b8efd1ab0fd407c16a210767d1d3ca798ee53a4bbf1ce5090d321b1a64fc2c5f013c23829f5b0d2737936ca71595a1d02711c8a7b0e74654e5d76376ae26977dd49c68e3c0a7b36e047d44be42d732c31f681bd7b1b4b339f004ecd847960377acd005debfab13d0fb88355025877630aff753a7cfddf6851e8bcc8ec37b8f9149830f47e6b601098b2ba19a4c0808e31e8927b2525cb82bfddc9b4bcba2b46bbe768ee278fb89010243d16f9679f5ba4f13cfe76b5beb16c7b28daf99b0873098115c2233ee3402ac0f6c899a2cfcc83b2ccc06676999ad48017c4ace507080a26501993327ebdcbd1e2eaaaa99f4998b716cd9e36eb26b4573a03fd1d18047198fdf675ef4f979864ac85d230a011c69d8b6c45e9efbdc2a03f195c9731b4cefa60208ba845c0978e73d082bf6d6a513b93dc805a4f5973f4158f60a200167ca88704a15ac5ab1f38ed455a426f7c6a96b6bfea2ebc1ae1247cfe5ff29ee81bdbcb53b03b89568bae9a6f311d2b20e31c2d91bd18fd93a37be266d0de8015d52e325f78356dea0b77cc76f28e0f06e4ec705d1328340013a77b0b6196f44b7712fff4ae0ac7f6afab9456a95012b7c6d387285487476d189977e28f6c9d1a3f736320d61302c2d627d5a7ac8cde4988056b55eeba27efe7e640f94c115762ad5849423ae138c76f15b47bd2a2bde2c492489b7980aaf1c4e32a155f858d7be4fcd0f8a18e7b5d97c5a08d7885d6d56222ef49542c7f80498a14a8eed1c092543aac3439966d5b5d0cb9e602f4fd795c09d652b64f9ab67e38f48c88d18e30a9774f37e9c77b7a94cc7310d",
+ },
+ {
+ "4ab8068988d4bbe0bf1e5bc2fe1c668cbe58019c958dd2ec97164aea7f3f41c9f747527f1c0e5fdb2cbb9d2ad704b6955cb731f14403dddb1a28c5996707635e4eb5dd6ac33d46eff8e319cfe7cf6443869534ca9812a5b23a6b4ca172afffc064dc2b28197117115431e03c00447f87d9b45172c6f724006270a1d41fa094847cbfac9630c3a785f488c1f5cc407ca6f4cd18bac43cba26ad5bfaccfb8f50784efc0e7fc0b504b43dc5a90a0525b0faf3c8b4b7046fdeb1cad87ec667ce3eb6cb4c358b01393f3ffee949030ef9fd01c1b2b9c5219777eb6ff5b1d7c3ef8d8e3bc2193dfb597cf942c5fc50befa527fac0b44cda2bbb811b06ae87459750295371cd232754e2bb7132807d1225950ce64949b0650531800bd0074177677acad937ee008cc0bbfdf33c6b0552000238494be8be412a3e5cfa359e619d092c76310a76bdcb22abbe6f16b3b116b5f95001d20e42fc3c9ff6723e580f378475788eec265a1ed2087de8cc2eff72184f73fa5dc6e68a56dcfc85350bccb97135386d5b827c2d9aea065708f5c921454d1b9303f21d5adf19e00415acbd86d1e5e42d78505b033a515a435713649c50702f54623cbf31469f355c3be2e30dd8c72b4127764451d79e952ea1f9bb0269da56dc07060d5d9542a9c1258ccefe53fa3f7b6073cd38026256b45c01b6c5dc0d91e3139f30a8d1da7a076738f5bb23352693a8e3cbbb46226fa22416680013f9e3278913d06aee4a62457357f0a68d173a360af5e1411840e34c574b4c6b352f92ce33632911ad8b6710d357b7607ee19679e777baffb8ae3c0fe9786b2e97fdeccb5105ecfe81441f549bc6b50ab84b749fb33f8f6bddcb6bb733d6d5dbc4b29725b8741439b8239e53fa435ea29ed3324202b1bdd07d1987b0e06d8cb51013dad897ef02401290940ce3f2af72c5d1b4c8836299008c10b16c7e3e119e41ec66d9db6929ee09bdeaeda08a50665c052edf77b7dff3d8815046bf71d5015e3bdb29a4f507aeb2e28c536cdcc9b8d1e89849a0683d78f99dbfa90f94aa5dc08587657a8f042d718080de5d4a973f232f78c387b63c7143fc2a4380c491414a18b6c4a7bae2194b62e798ad7ec7d09e409425f6d0973accb17e4d860f8ec0283584cff076d93bd9b0c4873f9c57cddcebe3c3bc8afe793c6cb6b26c4582847b07446b7e1d9757de6bdf0df826cbc502bf88cf3a773866d3ff293034abc4afa3091b2126a278f50e47f2f66ebebb616e342098ab690f7f5828bf8cc4742c677d378893e9f188e8397bee983a9a0998de2a31798330f8db59a8581e1c847589bc0e2d95ffa68e39226cc15cf6cae5c4f5174e7848375391dfabafec202565ec2383721339f04c5c5d1da953d88f18cda65745ee8e99805e35203a6545a0416923b38c5db3c8aa00d64354bed27d7c78c4b257534bd7a18107ebe64d8c27b6afdb330d8efba79fd1fae480cd51fd3626bf8d79fb651b7c6cf752aa737a5123558420d48fc86451b358d270aacfa6c17f343b7a9956e6f64e4990c1b3f1e5097605edf5ce4247819b19f245e9a90758dd42c36699ba5cd7f3ed99a7df7eb155749f4b42d192c47cacb6b2865fb9ef2cfca283865cd06e40cdf7f89d76a9e2eb393e2e0ac0e2776da929f3f8e3d325d075a966d289c51347bd0bd523a5c81edef63ce9b72f5114c88b08b16edbd73f518096240a5b37421843173be8df4ac7c587a17ca6f2916f7d9a10dc75f81bc778a1eb730d12b51555cc414eab9c066113a7edba9a7f1a18092ae47f12f0368ba211feaf34a3b48a7ff5c91b81cf7c95675a4001c95a19d284fe4197fe8823909a123fcec5e45935da12416be1bdf14918414ad19b54a41052f5b8417ddbd207ee01d6a3e62fd9b0321b1c13d91d6ce15ea7b2ea0c670a5f5cb290ca8e62c26c6499104ab8e9fafb05170ede246bbf7313625d1fc9576f1609ffd08852a2f4b73c04f1f4eeecefe3f3eeb2185a618b6dd3e87d9d3fdcb349cc83c21f26b6c662bbb857aa95378e991640a160a23cce76153c134508c68ec54a5",
+ "0d471079ad3c3432b6de852ec71692d12d9df4f984554d458a9dd1f28a2697976da8111ae4454c9a23d1c8eae75bbc14f8b00e7c065bc290f8938282b91a1a26c22b40a6708c40945d087e45633a595beb67d8f1c29a81",
+ "f3dac58738ce057d3140d68d2b3e651c00ff9dbb2ca0f913be50219dd36f23c6",
+ "bb2d033de71d570ddf824e85",
+ "238c4e6be84bfb151557327095c88f6dc2889bce2d6f0329e0c42a5cd7554ab16c8b5a4db26eab30f519c24766b1085e11d40823053ca77adfe2af387b4dcde12bc38502229510606ff086265f45b1087375dc4a022eb0b641101c74ad566ab6f230133b7aa61861aa8202b67beddc30dda506691a42032357010d45adc7ee633b536a2fefb3b2143837bb46db04f66a6e2bc628d6041b3d306ff78e96205ab66847036efa1fb6e6a387cf8d5a105738be7163df9da0db48e3d8fd6a786f0f887968e180ad6888e110fb3d7919c42a7f8c92491d795c813f30ea645fafcddf877f5035f133f864fd0ba1415b3d698f2349ebe03d9e76610355e7fc23221c5c72b1b2628a40b14badf93288fc4abeaff5306d274f21938650ab236a39496d3f8a6e9086eac058e365d4335b51eafac813f9175bb7bebb75605909ec3fde6515694e119f7b6e96aa1d6d6454c3a7dddeacc83bf0c1f5f6c2a9dd2f460f3e5b074a33b8d7904e6988ae43a22a87f0933f812e45c4c518bf83e606bad4c3c55422ab2207e9d3cfcbc5819049f55e35b9663273d9d3a6f8a897fa38b0dca77eb6c344290cc007b68d913187f2cd480a40262623a4e95d90d5701ac2b9d858d70a27f0672f919c2ded1fb89134ac9a8ba6ac62931c832372abb70e811dc50cce264ece65e87338231f18ac007c5f68f3b1c5904ffbb2e1dc361d53914917770d66afe28c547d8cd5896d892cbdadc34cd6af348c93bdb8b072f38b085361e62ded7a38b4368824c759ec7d2cf4caddb9191e5deedc8b8388bc4ba2c0672321bcda3a7343c9ea71ef03750912f35624d81da5fa8a6ee676c4efd99d0c7258b844ded7b35d8c8233a316b508d79c7c0b3edabad5db9543615179b1c111bfd78b79327ac5b4155336d670baa592d441c810cb1b7c07f3d35473a45b57e780b7d997782aeecfc0363976fb608d6967844ed00b63ba75996054d090aeb605c195b1ff86f9d9ab5892d27632cbb59c06b3ccd69d33ed5dea9398f00b7c6404fcfe2fcb5924e4cb75cbcae0a1b084ea8b15eaa5847431e9ab70e4afe15b4c82239f6165e243e3b76d6c91d23b16edecad8bcb16898641f8e323671452034a8ec9b42b29cec0db210bad0444f1c5bf3505cc41d514d5a270d556f0a34333bd06cd6509ba253a6ba7a6db8f1a60c99f0c3d566a038a72f1271a178cc3ff890b0df1e7438c0c1a12d9873643e2d7bfeb92379545de50834abe2a345faf7ca49beeab87ee516dd8598b71196b8cdb15e7200cb5bd814338babd74c565faaf33d9a8ed4209b417345a1ae611880ea22ab2e894d5d14a28fe3835d3b2718125f0e6daabd85327455646290ceab89e579ed5e1d72a0172e4a6d8da70290b5022c941f3866f96cc4218de5d2622d13af6dab15760a1ec5d10918267f9585284058aba611ba07b1d5711cef505869831699bedc2b190fe1d578814065c91d87a8c8dc9b0d4dae0c80cd241f0bda3a6d5e714c894b7a48b1e5eed4555f103eb03c9db30efcb855df422d7451a6d70f28174c7ebff536dd2cd2891f6c3f264d632ca924c4e0d84b37cf8e06e6f2e29efac6cf008cc27f062441278dbc9f09cf44987e0e9ca088a48437b0b89efb9cf00d3d0c5fb449fd4b64e21dc48cf300c2d80a502cb583219f1881e78e647783d91dd2f3b389a1594eefd8ea07d4786f983d13e33cf7a34e4c9a0ec4b791f1666a4eef4e63bde7a241f49b5cf615888bd8130743bc8a6d502bfc73ab64d1184ead9a611832b7e24483a1a0fc475d9ff6166b86a18a3dc96910ff182cf326456c4461ce8acb3467f801890eaf1ce0b24791da9c650876e718c0bf43c475174f9712dd4a228695e8f8b2b23fc4a06358b4a6a8e1afa87a0280c3e098f218f7a6d6bd716f8c105a7eb799ba0220837fa5a96c8a22a826a6f7ea9d7216a24acbc7b0133210cc17c8190507badb421bc54997ff9340cdc1ee415126ac46a4fec9fee12d40f06300f7e397b228250f36d6f0d2ddad5fe1898ea690e4c7cc3a116a70bfaf6d2dc996753fffae40ba5280b8356b7ab4ffbc914ec74eaa070581fdd1d9e5aa2",
+ },
+ {
+ "4d81b652fee892d575bd13dad913d976cf0517c819d5183a72eba995b1f27efe743451721ce34791a15a6b7a6e44f13d4a080563dd1d9d4f0946e5ba3863b9ac970a1fb4ed66458ec1b1092ff5fa6c3f0271a2df8e3f2e97851352be760b6a0e1589c202f00791b1b89ae0ae944ced96bd90754bcfa3e355b735132d407d3b5507fd57f705e8a8bd82886b16d459ac91e921dcb8c5bf0d7cf420a9349ee589a5e2e19ce7c944a54ccc1062a0690f3152300d0bf5cd1871c1391bf6d7007f7ce26018ca2a5c6f76287fd8c8e9e7f93b1806460dd35f7f95989a8b6f9a0aeb7c6b0346955fb50b8735e34f1ecb4859e34ea0f022ff6fb797094206a34cf120b7f4664c531c57da513b296f0671c8e9bf68d9e1674998fe52da04f627f516dee97c2b3c988216e9bd3f58c3b021ac70898651f1cfeaef21c4f417ebe92dcad3aaf50f4277262c356584f816a5a5862f2bd720fac10f1b86033371ed603bc00a30cf4da8f579dd5bfdd571a37af7d2a5cef29f9001bb1605ee87f24ec3b259f381a69b771f78d21c4e43bfc83a916e08830d9885c8ae8ab6367c05f92e5eecaf0488262300f83f4e3bff177590857e149216995bc52311fb9f16f4cd74e07c7868a39b699bdbb7d7dace4c6a53ca7ee6e11741a63a52a1d96995a6dd752356dec6f14761ccfe38a6cd8511204f8f0630a747d6e19a77bb030c61e0828436604a28a7acf4a5e49b7269ac93b93b99e9e2e1c0c47b377f7e44e05ec6659526afbdcd5bb172404ce5a9f8786234114c16f20cda6d4359eb873a4a4d9fdf734e9c40aa4db3ea9a98939210f6c62142dd144eb78191116d194bb766ea96da38321ae27fcdcc196560ac75567297984fabe6072c771899906350f74de6d18518eb6898b934b11e945d94ead02b821fd6682602e03e9c70a1ec67eed33874eb24dc83dd1035fba5928f8f62ba1282907aa8935ae72fcb881b3277ee6bebda8fc75d6cd792677c25f70c87b11e094298b2d5f39904be211ff0980e5b83e8ea4a455622d8be9efdb5aa8466c88ea861407d54d98112faa10293af5e16974861dc9f83b45d21b112cc367894c421f5049e49dd205bd7c15e6a70bc810704e2e3a3659800864912527f8be743acdc474a26246a81fc2bdf669b9be7a2a0c986432e1e44b5675607e7e1ee2a8dcb72d8f1964272926e52f909ede0ac8daa32d1d850158db76b959e4d83c9da4e3bb23fd1f5b26463045d6cf13d187fe74a50c09a654d52d0e2f01d66b9f8b4f4aaf4c69fa62a02aa876f9bc4871aacd26a6c6ccfb9bea09cafbd0268b5b65d60aa23ff504d02fad4719698f8b044ca1bb037ea6af58a06a448080dfdbe6a5d698d5db9da5fb4aed04a46c8fa8b93153bca00a5bf8aab64d2b371d072db2ddb688a9442e948f0b99236828dc115a2fddfa2a29e2d4e02ff0173cf734efd4eb687e3f8712be82abe1fac4be0c1eddda090803fbdce41bccfb58c43038991ba1074b281a09bac5eba58a99a1a9678ba26f8f9e3c63ba095f02cd8f3b56aadc5de60477efbf3dcb54b854f651cc72042bf19268554c61b44f2f338a75de56c3c45b3ba40a697f5f21c4557380c777bcc91a151e5676c2a59606200bd476cf98d20b4cdc64bc3b8670810a014871be018bc32fe239e287cfe8a7cbcd1e8b55e08692ccfb4ef871cf797bc0b1fd7ec37931e35b6bc5d32bbe7ae77b9962c179f96436e4a32f566298d2235acf921e38c3f1942fb7674b65e222d17b95a2e58f072c63aa4bba1ce48c303f4bd24d84963f18c5e670015c52342dcdc9c0b348c7dfac721b568effe2bf2f2e816ca3279bbbed823beede8e12fc5bdccd0f1584deb1f6ea1875e9fb350919b675ccde0178bb83a4aa5232bd5e8e9a1b8daf905c6197367a0d106532297ef89f3bc690b48224592c768bd9c50a63d0881370d475081aef052b444744b33fd3fef674a37898fc950f887ed482d2a51ae615ef5b1dfa3a23257e6a6a319a4e2080b2c4094bb09e4b390d1fcbefc4d6c5dab620f8b05b1bd5d976300b007e2b8120ef8a6c9028b7d925c795058c6bdb6711fc5fc2476b9810d1d81bd24637537716edd3b7068b802c531531df710d3682f9865530e1ed51b3b56d860ba4e972bbc74662cdd1e2ea24f81bf469193afc02b14143a32e9556e3f2ecef97c65",
+ "2538d98b64b6aa9258f9141840a5abef66d6037a10356366a3a294719c10d6c148b04cac66f63ebff052d730f8821f5e5822d869573bcffbdd636c7973433abbf38767597da5186df8ef9df071bc4ecade2633366102313e659db8d8e0f293d379fa2df79f456497",
+ "a5049b0aa153e282457555bf6f82b60fc81aa6fd1c2ea3db031478ffb74b5b5d",
+ "350287a6bed5709dfba3d35c",
+ "849670914f5fe318eb01e8849e536374ec11e813acdbbe6a5e82a506f6aef4f916a3a7fb2e41db3adf990175e21f2386d1805af9bbc32a6ac156b13b1a9505958f68599019c4b7297314229c467114754277b10e9f49a4d12837ef24184629c8902ebe2a23f740dc826b01f8963d47100bf617b314835e436104eb207fa9a1079b8feba06d9369b9aa8222d38d87096b73678bc5db9a1add59394530e678b6ec93a80efc6e8320f2909e3e891306d69b016ade0d30cde64c2c903b401f9d01a29b5cb8619dc68ad6c21900b365a6b657f7d9ca4c145fe598a94eeea741e20a9329996b17aba5d7115c93623f2f5d6927068d0f190b49eb885429d771bbbb3980e9293e4d664a71c3cb629d869dc97e58fc3d328331b11df19a38d61e1705ec4c3d779168abe049e9d675337ff658e00d2d610c8f227d1341d1c41f1c01d8b5d83c4b1b30ae4318da9822f46402ee8cd5cfe9f3f22d90a5ec2d0aaa0baa85e10f5295cc6005c5a0887287b0c867a23da1a4c2196f91fe0bd4f0db1ab324c26fe6088d7583f3cd052b7f6fca38e8b21f98fd07fe78b7657da1f586f1fbd3d2b4079e20f21dccc0d269d53a29deb7c7fb63cc291d1d2c50ff163e08ce612310d3bd622f2416e193078ce4e1463f8a3490578af96ca98e665468281f1af9117a2ed23367df19b570885de9d6594f09aaba4090bdd1079720b08d54311793c97bbe14433b031c865b059cb4f75db74779b82c4f83eb4bd829c62eab995027b548063d7cab7d1a6f9642da6cf7181c0ac71594b97fc2c84b1768f81eb287091f63c76623c61e7ba90c922c74d46b9ae5d8094d9752bc1e8020a82601c356a201e0473d540053c707a88f4baad37826152dd245c4cee6b0019583c61e4327fdf6bdcae53584cdba8a503b835bfb5df9d649705fcc1f09376eec96c3da1e105accc1cbc21d90f527041a9beb85f8cbb1ee8db798838bb45374b741618f83b5d0801a3af2f640abdbe74ec3dc15d6711b4c1480aa8d6084defba82ed221ba359c9744705c4feee0955c27ef468cbb816694516f73fb541e0ad4ccf99ec8b67ef090505d1f7c4c3a8ed7e291c820261f12d92bbc6609da6c275349819848c9112826674f243acb9a29ab73f17c8f8af12c7437c11972c824f00db7ad284e51b9b508a925f0664bb259b4443d56463bffc9e5d845c9b9f79b24c1f457088fadd281f48238866e0b92d6253638eb188bbaa8bf6a81d2b1087904974752697cffb00b4ba05e5b7b842a3d2c0a743e4bd691625788fbe9df14600643b1d161bb2916176b6ee40aee38dbb594ec2735d41369ed3a0c6dd9073f1eb51d1b77eb9a967b53670a8ed755f3b2b73a6cb50a9e1ea7549346646dbe4b801c8aa642779d8761b6c2d2e1a9995e758ab92f07c4eb4a23c042171a4b354f434ced5f6d9ccd26cd6c2506e5023dc076ced15566fdabc7364f4a8594cd6ec404e1a9470f52a83052390e4f7789ade9179b069d9f84ca2c7ac9eea51035db817845aded7405bee90cbe92364c8c7cf8a366cbebd7a972438f2a9881395a8610a2cd0c06c46b60cdae5b1f473f4fd6ec48479cf35101656f05485198a470cd36af22838e7ba3e28863cd8ba7bbba7e3c2625c1106a6be44c9e3d9b9938679b26f0713c62c3757a2dc8b2d9eed5e652220a7711cd220bc91a9afd7c940dd8be71616ebb8b2cb0686dfa161c6ef56994a3cafaec5e79bd0a2531fd1c1a42771acb101a38988bcba51ad85bffcd8c67aebec5b37d526b29f7b9d31388e1e7ad7154f8e65516f0d80a30b88c2b868be2541d19ea1d2bcbadd30e2fbb1b4678bfef7f200e0f8309ac0701000c52ebbcd6fa00cb85c8d3ea9c5aceeb3adcf3773cfb3bfc9ac764d031d7c63ab888e9b03eb9fa74554dab4719d426d0875a508c8c86b22cabfeeb70b0f1461db4e5f639d2a2d28a089dbcc48e3f34394ff1acb887b89f75d3236c8143bb9b06273c3878744340ea1858a9f383f8bbdc259250e23a3c3992bf8b7ca7e1a66913547710402bb538a8866772d11cf4214060ed091d403e1c9ca3af75859259f88656a1cfecfdb49d57c193e60a2223627c681a2fbc7390140aeddc19df035a5207adde4f5736bc542bfdc943ae8b094f4a8701618688fadc2284fb423f602c41ad8ee11e5d9fdfa67fb7dc7d4dce7847d4875b3af667168ebb6082f6911c95",
+ },
+ {
+ "67f0494a728fbfc84e2f4a043e121ee40f3b12b31616c78e157ed970db28674318b08d8b3f4c538d7b9d91b9b0b09ebfebb07201c6398fdbb8684c9390b3d6a8636333a3b086302b24c2e5d47283935d33065efa3fedd5f755218be5d4618d38c5c1db75470ba06bcd853f3f08d39c3cd9fa3618e70b103c2d9b2101fcaf39c1701436b720d723ed5c622d6535c9a10ec4d727abe237e80fd20911ceb84a90285fc6e07f9d036cfa65995f9b6300a927d7d0d2b907bac9d9c4daa87c2438a583fe85029c886f96ed08f5886bf53292cc0265850a1f4ee3e3288b604dc305d0c28ad35e1242f4ff4ae988b6deba48aabcad2fc6cd7eaab0a63510f3f915c4bb9f9719b1d90db123f639d9d4f3227eafcfad769c2b204dd2555dc54e738909122022c4f92f751d25aef6f9a1187750e825c68450e6d1223c2fe88aa27194b492b6788be6eda80b9b9f053cb77c8d9fa15324f23af5147624fc00c66e947b004bf38b31e1343c7cd341b98abe462a5f994e51d343664968624a2ed0dea9d0299d5c5a7e9097fa63d8b3ed96f917f693654766a9adb01110fa3fe0d8e9b102860d5c049df3fe00ccb2ed62ab05583e6aa0a5134d55245d4f643e274def29d3fc86d79979d599458786a8338b0071f6a01609ee6b2e4bba9289e2df780bb27491890d0b5ea650e62df819b8f98aae99a1b8870ce6d3c7785ca957d5b4094946925751f0fda1d62a9aefe3937a912c1b49b4272f87eea7e397feb84c0702929959e38a568460811e5064b1caf5dee53f920c6e19fb16fc9214b5de1cb770b510533f66d8a0e7f6f04ba8ba41869f8018abee31a6042d3919e217359988eaa9db2a10b3caf7aaba43527484d81304f0bef22165f74e9e1031b545ca3d2f74195984cc237b76ddbec85142a06446902339b1883000264031db85fb19b46f320ef3fe316f750f2d3d6070dec5b66ee8ef20701f20965f5171e44c8a99bcbca7afbbd81e30e74c6d48bc4b0d72baf562da6581fafbe14b6cc597f75e53b305036ede219ec56d0c0d29571a9c110ffeeb747fe56f6030dc26c8d3841b868a1ef56840932dad9f3bd7f75573086571f4d9f0d949510a2577d2f8fbed7e850c73ed4c071bf9a656d09dab43a610b49aeaa57333f67d586d4f50683dceee4942db9549f68eef4c5f8df8a2330857cdf2fc4025f2be7d5f0dcdc74a9cb593de91282787b716d416a3ccb8d6d40fa3c70be4ecfda26a5caf3724fad3d98db16ab6d8f26defc68392923b69664b0c2d56f01a549284b042bbd43c8faec940187f190aec08d06f9a62ab03c9f610f64c0010a0939451d5502511dfd3da1fec5a38f64640c7b6db2961def257eee9a3eff944828e9557deba68bd8e42dc7a9c1570e35537993061fa0f5351fd3cf4ec36386ec4cdc5a2882d5f16703b900c5000efa63888d69982e5ecd3e329c8cf5f003e23ce03c55631246ca15ffcadb0fc9d5634252ccda812ba7bf5e343c44244026512062a68374ed4d8add0855dcc22b30148e0cef0f2886be76bafabadf3ae1205b43c6deb8a41c338114895dd6b49deb329ada31b350e02a1bdad4eb05b61b50f9d22fa2863bd607406f552713e302467ddc78213d584b4933202438d63f99d011b97297f5589f35b7e45ccbd76f02453b7a7668c2b1a1f5d1d63eb805c8881771faaf67433eacfb22f9b6fa58b93f9423a5fcf667aeec39751ae17ad36992556431bca77059a29353598dac12bd3036633d2ccadc18f44123e5bc074f4e5ca380095af062fd83b647015259be929011cfbcdc9bc5d0dcf9b688f0f5d74da95746f447a9e1cb5028ccb2827b45129d04cf6990953a6d8ee0e67fe6bdbd8004f4744cae5607fe7ec4a0f14fe603dcead3367b6870d8e751cf57387d04b881f92cce9772d695f19b36e2db2cf6a807c9ee83225f5c09a11b50e99855921a4eced8e631af7c234aa31615c00ccdd7c6ac5ae8fba6e29cc233765a891864c7d73dae08ed1a3c27cd423d8d4efb550597afee8356c12018f496637daec83575f5e38ed2fdbafabafd38483c239d31cb4d104e93d16eacc6050033a3c86929be4ca8914a538bf540b43d7ce7daaea317bee1ab80504846554879f900d312bf2fbb406a0edc5f4f809cbc68675b0b7f09fd1a8a4d52c0929b3a8b9c1dae4b3d599b976867e6a7e8736450dabf5c49c949544386a71419324ea4ce5c4319899ca510f50d07ace57b013655b0929f79dbf3cd629ad17bdd10109b7c53a4f5f04a16e5471e823c898362df43f57ebdd1627b33fd4cafca6cc065d9140acf0454d5f99be47bc87e0f3b4d4320bbf0f21e7c261bb8d5d615963beeaa46bdbe9b83a8277813ffe6132b23564bef5",
+ "74dfdc364097c39ef91c01b707a522e28edb1c11529d5050ff820234e6c0295aa00591e09d547e9671804d7825705ab44b76c59d1315ed1297ef477db070d85076693013bdafa92e2ff6a654660008b176cd4e8ae23b9c792be3f7db54cf2bca385bddf50a8624397cca8ee3cb96944164e3cb461e68",
+ "b3b5ccd7ef49a27d2c6d13c0ae77a37abec2e27e0b2d3530cdbb7f36792a7d2c",
+ "c0494bb7249f864f69beab46",
+ "ed8d6e964bcde1df68e7f362243073941fd68ac77929c8e480c89f519f748b3dc337b1af6231632c975167a8425b174b42c2c60dfc0ec85a0a212bf5c9aada818a83f9664c8712d96de1036b5e5d8c8298786b753638de3a8da958549f16eb9c723355cdf7b999aac464ec39df7d6c1607e81b88b63043d1c847dab618f1b19336911b4b0145c2a694e61db71e021282006d48e37f10f3b6314dd012a07618228532c28ca84a936e0eff83723d117b2f2db857d14af5bbd5948a0e53018b31e57cc2a81f36aa013a844990753ccb347fe98fab294cbd252a8b8f7246276275d2780511fd3cb7baa2fd1548184f968c422230f7ad73ae9dde91295f79f6b799e7d234dfd6573fee6d6ae748b0a8cd7ed4862ebd957390826f276c2afb01fbb4b64b61a1bfc138508efd630e77580867bdc1e96a48a694cf0db6c2a11f05dd0bc8769e7200bb0749f5798b6f3559de55d0c281eb5df22b731fbbc109da9c68f209b888e61240c4c0ca006d105c0a7f43144021547d3316e5a99f6c429f9ea2f17d77dc68bc9d5125b6260f79bc8b3b8061972e6757d87b6544f21645c0b4debe5224f7c48142c09f35b8e144c0c1e6521f04c170519ff744d61abd59a56d25a26c5ed5972191b25e78e2140f3ce68fe17be9e59a79f6c69619a79b83614c670c7736d19c27fd22515fb5b896a6418cc0b4850e85c07b38b995cffafd9f69763cbbcfa9d1bbea6868244a66a5cc82e815fae09f5775d28437634926d571c2b0d200855e09cbdc67d10f85bd4cc334ded4c83aeea57f8e373a950f135997666b653e8de47a3bc0059525720045996bff500a47baeec97808fe971d7693dfde339e8beca3598fbc053121536c30d0af10f8f5d8e5eeaaaa9586d7abb563fd69e88351f93bcc46520f6d97c1a49ba9f8f6a25cdcfc11b2a722910aabe7435ac8f0dcda9f824fdde80850f21a2d4bcbfd2e9fcbd14dec05c117a9796db49e2f0dc55e74c7f0f615bd049fa7d0bfcf197dcda3ef3de90762e6f6f9f8a8936bd04fcf2a97cf18ecc8f2f118ffbf02b67f252097e4289d02f264161f6f90f79e1e1ef8414b01a9e1a77b88c039ad6eda6df1e28fcfe9370f0d574aa9e857dcebb19eb7ce8af9b19b4481c9fb3e1f0db3b02af483f737ce3ea824b2165e7c0fca8585383d4b0a16eab2c7e3ee5c038f939a97bc8e1c093cc5372ee45d81836c988f3ab3e6ee0e5f9549e4b7bc381a2afac2074cf75ed56b0e757e7966cb253d549fb0902da98294c6dd4de3c2e166b7e45098d2729b1393deb68471d4d3218dea3dfd0183b654ae4092a79357945eea4b28cfd06b40d30d1b4b8f19827895f6f908f0fe511f74ec84cbab2483ca4bdfc6ef50178eabad79b18b58529c9328c13c52c2869858cc20ec36ef7717e1c743d13f9607bbdb0b701d9df6aca7366814e883d23e51ee5b0f20ef70e2c4134ab037d213315fddc89009260981329a1872e541767adbd5ee9501e7df4ef0cdfae9769961f8716ee7dfbab0ec89b3f62e987387d5842e124a69b07245d359052ada50cfd67472d27ce2c4eacb5421b62dd7331da54ebf0989803797f4c8c781d0e2e6477b421c7d5cefc8146aacc0012af3f1f7cd71ce2b1045d86bf48c9a13fe469a1865294e160b4975023d0eb24ed26837afefc250a914f86f8b1f5d67d65e9737e841519148d4dd5dbf2b5a8b073861288ec9793d4b113d71c01727f67d791852fc3946dc912d60fc66bffccf4c45d859eed9f0bfc7f89086df5d5cd830ac919aa7cdb4504018052d67f6a3ca012ed69187cd5fbe91875cfade381bff1e804ba59cd59f0f75cb46dcfba234ab9832c3fb9aa8dde19fc1fb30677ac1793a38d94aefd9ffcd4e777e9e4f6d49e0cdac6c16a36bc2f3ed8e23b80350e3be6d866aaafbc8cbf7c69fe44c2aa80651164803150c23ebe262aa669c77ca94d215895d2ee9c3e325a0bf2c61e419a41e0f7b1ba8ee0508307d49301abccd5b74c054b6c7bd1aa67cffeafee033761d8226d9dbd7214b130a867764062cf4da685deefa23693b8549d5ef5e53df85c19bfb3c43c6bd073e7a836f849587a4747e1a9a3c7194f6d5472d2e3e4c81784a3061fc9bd3b94862c4784974d859134369486f2651f1db94f511c6f59f41da0d75307191602730b88e4e6101fc8d392c87687f3be454dd92fb8ec380715bcd88aadb63717cbce4db91a36821a572c363759d8d0a2ab007e5981b78731dfdea20d900b14f0c5ee6a4a9b532ed2134e6edb4dc267f001cb88dbe43aac4aad453b839d035697df7de98ca7a9ee7601228a79004b89796e9ab971aeb8e62c789bb21f38b77b492c57db402bf6a42ad0cee169e9251d865ea3e5f79b1801ef1e53797aa6c7060d6f9486081",
+ },
+ {
+ "04cf92a64cbe135f7fc1d7223b95e41d13f04b482018039f4e7ccacba8aa15ac79a752c5666524e527fb076290ec80a3dccbebfce3ee9b316a65fd130f12bf88b9124d1f7772049e6d0c01fef881a1d44c8dd02f7b6b60e6d15df9e06fb86929cab64842284de09659e19451623525aec2f5dd3e603e24319b1d120bd57b34a0317ce25ac9c2f022a4847306b998b57c8d92baeed0de1f6cfb3177d0acab70de275238f1152813b9ac87bf651f74e1ad079b9bd779ba4374ecba459865b5768d08ae7e1dd691d6821895e8380ac9e5116580e8de3a2c5326e698bf4c4d35d955e45772bae8483d01de2539e8ee1ef9539ee132d80d85fff41dbe406af319c0d7703292587bcf5959f49241e2b03a364e1b682729ed261d0ae45d74d77634afe667413ee210983b042a7ce6dbb61c29d18450fa7176177b5a74f032ea24e1d08b220f6d32a7a836d1241cacda39d6acbd26a62f9dbeaaf7329a291dbf0aed4a2cfcb85ea360947585b1215feaf70ba71eb2d6bb7081b2a21bdcbfdae6ad2513a9dd714d3d06c2c2b7e322a1db2d48f9df1fb44fa066f2bb42b196295ebb3c0898ad55d5b317986afaba0bd5e754cec773821613e908ce2bba6454181f9020b73e758df18c255c87df675cc6bb2b8d2eada44196ac10c26674167f94a79f4be515d8d6a1fd3228dc9a85a355b030845dd4c5f481d5b6e74acc66de730629581b022fbcff61e5dcfb6a7f511aafd577849a6b057021ecbaee53986159c1ba74c3e930c34a159f467f1e9799cd6c1151067c56769e43308c96c8edef8aa7634d909310dba9af2128cdb8c29b24d3ec2a4f43a1ed86d1791c9a670b240e6e719f01827aaa319bd3ff53959a776886a1b7c942a54f141e6bae8576d294e44333e6c5ad90f74863f69bf890126016b318e0f6bd2f0adb9bb861118af5f6cd28dc93d56c8a1dd080b8c810ca29267d410673fe367dd9d1353ae2bf2fd88d57b4202c21aa49f12a01b93acbe260492367bc219d3afb6e6f35502f6529bcbcdddce9fe8632efb034a9eaff8b4a48afb105d04e3fcbbcae010ddd6636992213750b12fb3e01ab72aa957136e0bae591bfb5e0fe819cac82a98ae8df230af399160594540640c6b1d537e7b5f1cc47b08127ae02c35b846de56c4c08773fa18d4436e14b76a7fc4bdee301d0af4880306f2f33328ab79f6f24ec779b2b1928704f09bbc5b0b7108e9a115e4959df79c80eacfb98649a0788867e23b2974b22e654ddab0494bc922ecdf17727d0f0efde9dea7601857d890bfbacbd93f7df794bbc254f50e1e17eaed2f5d5a2e6c58083aff68434730d406fb9fd02b0dd7bfb99a04aea812b6830fe5e05a044ca21c77a174bae8b58eefa11ecfcc1c977bc6218064c9931b5c92f13cfd05799f11e130869c293c1b08dd29c899365014fc8195514b286c97cb6dc4b8633e47751f87fbaba137b6aa04d072ae06c2b2f34448449f60b1272c1efbd4722a2be749a3d2e5450aabef1f7c51bd8324607668a8caf8097c2f358b1b09fd3525d47ec9a7640eb20ffdc17c4f7eff63df75dc7830c471ace3a727feb11533d6e9a2a08106af33069cf482ec63724032e81cab18e12cb5c4c3ddc374e2f75bcc99fc5da09b80a738852a14e8ac552b8471c6ad52e35317b730db2c13c277e06c643e0d0fbea43833de4d2c7a9247ff040e9c56f1ff7ea92049c5341c4d1478a14275a10119d934e8165152b89951bca7ee1399dd8232fdcbf831d8354640e698b68799d060ceb877201b2fb96cec514affeb28721e163e1648164b9e5722271db9b0ee1a7f96819fa1b1590e9daa598d9571ffa3882db9d034056e9b2785a8d13686eba61d7d45cf2e9ecdbc391739ce89297211472be18b21401658c5bf29fc3615924382d802a166d05dafe7876e70a0d081e80c63632da379766928a0555eb5e7a238cfa4da267527c66caf34dd40055f2801b29b3f5604a5bf3d46048bfbec2e24abd2fed2481698a4b5cd71f5d2c12dd473b903c9bdb978eaff7d76fb69951005681ed7b0257054eb3dd6d10097fee51ba7e8d565925e4091cbb78d255c9d3ab4ac0264d172c9bcb0908db1288c9634248f198a1167daa323822058decd83936985f83b08b1e7b942756a7af200af168fb8a091107b4443fd649cdc22106f9b9657c69f19be485c23b2c715b3762c332eccc44f380883357d10019f20612ab6b8f155c2af9e2ec340e5d8f45bf5278ac1fbc9f9f44d2f615d21007d822b244b1c7a0dbc182c7f5912485d6e4d74e90f60a2f964e028c63d49c6aadbf1df170e4914ca514139ba538207b1cf7caaceed4db8423dd1086b2adf15f6c0e50dcf2e12898f53c339a745316904ae03c38b417bcd7f5cd5ea77a4f06e65d56c24f37ebe72d271ac79b6ddd2bb8bd67f0727ead49737aa71af4f620da53769ca3ae878adbaea5a249128074ca3ddbbbaf5a68f9cde2a0e8d69708b0ea7f4c8d2dd4180882bdaacccf2a409a681c551776bd10439fb12b7548342532b371c0e045d8e8c895929464bdd4fe25f0533c66104daaaffed52446094978bcbb389c",
+ "001084c8a5175c0ad43108f9215c35886c82321c800740c6118a3fcd45776a4588ee0e2d056a37d99b40d2bd9c0845088a77240b7e65d18fef105d3488c77910b5873dbbf275948db5",
+ "d614d2e671066e387f7eee07bca9f9313d86e6a4d1371360900d670e11ecf1e7",
+ "674a516f8f59f9067e0485e3",
+ "1ee376e9e3c89b2147bcf75480ff0dec1d0e8cd45ba812f34c84124871d484b4ca87bfc8cf99f85ad452c482933801426e2737a97468809fa36caebebe8eed07a626b3bc3614ef1ceb54f9221ecb16f413f0bd9ed4b3010c40632f05223484af7bf5948c2fb8a3d2ce04c53e3f2682494f3969a0f8eb738cf93c0141799c9e6b68924433f0326991e19626bb19e6fbb5dd46baf39f92e830f9b1ff465a007f031891fb1f1799cc122d3ae7a55624356b5297bd5d948d9ff2e414cd8adf00a53524df43f398938d33c93b2c06bcde2679566c0a7b0177b4a873f35874739d550712d5cfe3d25c19292ba97c01d84224738bb25546e5c252fe5e5f260ca881aaf176a271a6fca2edbb2cf23ae6d4c56c20daadadb8205c2e33881867cd67ae6e59132edccc3601f014b744ff8eb6aef5e09b358607695d3af42ab8fa30e9fdf99ce54427ba9da3699de19f7a8f9be368df47ff0607601a91e7a5fa6e72be50bb32b825427cdeda3972a18a23af290986cde14f5fb9cbddad336f5efcd2d7a0cf3d5b23e54b702352fd5ee52d7e3479441497d56e17d5868574c56cfc421ee47bb00e9c75b84262a1b9e2cbfcccfed9c4c386ef0d2c1be9a7b7556909b5d72a38b7258acdd624de2396c75386e077c34f005f92a2203c82d1072c8998f03b1df22de832ac733977705453b1d72336b8d371cf1ed3923f462ecd22075de5df68c83ab1e6648ede7fd5ee5794a744abcb32af73bcb182cf97d36f37c15535c4107b7c8f2321f9fe0e2b6ccbe74204df3d748c05bc1e0e2c55ae1aee2d4aa4a52e98ca7229d6d06576196ac8e4b14a9ce807075cdc876aaf904c9962741efa8c6caf41e6b87b2ecd6636e2e58f3ecf576e5d8b895162545e618960ff6e336ff17eacd5a1eb335001633fa78c41ed05466d904ef9b81b643a043298c0e291a085e4e67da72e329adfccc407f800709865147db49cbdf4232073b7bc7ad89b3dd901d927ee08ae6497e0f2f9d052ca8d7444d2e2ae2197f930a7b1c8af38d8739ad298464169823684612cb628c484f710cf9c552551b6837b575a43275100bf800b7a3d777adc44d07f67cee5000422b9049dcfbedfccded0f2aa4d189621579b01e3fdaedc4d772dcc593316ca85e7aa248d219dac21c561d318a4936ac0d3bd5c75311486c174e0e2182affdf69bdd6a086534e4a602efba2b9363beeb5346539b45336cbaf479da6b15b226a9ac026482216dedb84ae3443b306820d9f05f78dca7090d727c7481d82c6e5df80e189e24e46f5758e453e542bd91a58eb51a89e07c50afb543c6b998704432e863dc4c0d0236e0672835a7b0b64e14f5ced2904e54da4287597f920bb4d542c35d3b0271cf0eec055656d523d7d2cbd667445d3e8634854f8616b7d7a7f3e14fd32651e9df40e1daedfdff1371f16d5549ed5646adf2d417e4b3a4d145bbe0974ab388c2716861a08296b862e4fd035163281457877eff89dadb160eb2b780414435784804bf4fd36602699d8c2f6a8cbcb509198c38e2df2edaae7bd7c93313ca98a9c2d24419a12ce35b0b3d68c18840e3ff8739d70969927c7db9a6569787bdedf5c99948a9e79b2302a83a71159f4c789b3b3f05f1e574f8a24c899ae3457f8e73f9bd86976fbddd83b1af337eb8da4c0dbac3792921597e18a2fd3a0ac89a270794529d370d36bb6dc7452e754e903781cbf57c8646b92d5d02842e7df229b3d721f9b981f9d61a48f00e53948a5dbc4f739849609d94aba3e3f5f8163d40321576cb8eb8e89953b608a01184d41aafc13f40c47b12240e3ad49413473c26b6843f4514be221c2af632d1a54cba230457f23f00b2608485c381ae03b389ad0a1671fb416de4659cc7f7a9c4b6d9807789c307d061fcf613b96a2d79e5e3e20b863c8b1b75f35c982b40ac8dcb7d2712ef7df94901facef783e8015a9a48574aa6f0cfb0bf6c1a3409028f8d62137c347f5a35ad6a3cd60d71aeb29bae56bb4590f69226fb4e08fab7a9f41e58f4d5784540a70e7a97720c549c8440b089eabd0eb3e4d37a2e54b1160572ce568f4256dd244decec31fec555017ebf488e878945383750eff26a8a1cca73e7d6f52d8cb229d5603360a3bffec23029ee34145c4aade82d486758e0aea9e1b7bf0b4bfbd4fcc96aab66a27fb463b48c6a6c5c5a60253e2fbc5716ef55629277a5f3b89c300e21bf1226241ce0d587fe3f5b11e47f35614169dcfaa375ee1aa589be33a4363765368f5666d155cf72e851d426fa67b982aac4dbbc29356d71deb0715b34e00b9fd8876bbb09ca0701b15615f05cc45e128b3864b26003e6ffe801c4e27402f37b8997e0c29ebc273dc03358cd22fdb68d9cd3b56ff8248a727c2d4ac65acda4d0e0f511bc07ab06cefcf444f1002c151b953d7f7b19695668a86683497c2a2d2e69f19a4997148d2e8d158da859c8f44437d9ce9db92f84a88e89cbffc74c0ef4295088e2543a4f7c6ae9c908bd987bcfd7a074f83ffaf3888bd7f430dc5a5bb70d223c21b1bcd8bff2103408460df864dcc168486f6a66d67ded366c6e10f50bcddada93627cda711764a57ec36035ebc",
+ },
+ {
+ "ce72c93caa49bb9850774149a87fcf8e23a0c53701554468645554553d54190bc6e247712b02097b794bc421ca94afed34742435ca689d2ebef183fb469c060c7f4d7daa508726c9d2eaeb9c7e9a89b30faee8d9168607d4778acfbd27d5caa623475073ce763ca061273cdfc2c692d1747baa8a01b15f783b2e36620400082747599a16cfd6b630fef310c0b9a2912d1d3bb71eec16972745cd8a49cd927014eb0a2abbe0e1ebded4fb9e8d9e2fbabb6a71da5688717ecd3e08160b9a861f86904a41702b2c4fff28ed8cc61d468187b75bde3fcc5c0c0a642215fea83584387fc5a9aaf2f8a91ae535e0027b618a32bd687289c47e9428a1a92649deab825d702b076223b07c08e55c0b60be95937bfd0504c18398e924420f6e20baf07e2b1b858d3e360a461b66517c24e60f9fe314a4a4973c8dbc7e9d2a9f571a1d8235a21073d81ab9f4800b70a5f17f44d593e8792a2507e6a3a41042fb2a5f7e5f028ed2daa88cce28973ecd88bd125d50fad77b1fde61c38272057d9c65fbfc6789ce41315a105af14e277a0c39d75c34aed7538c39160eab1c8c47818743e8111229426c399c5e88c4d894fdaff0315ec885ea019bf9acb785f3380c37201d494a60b583fc130bc0eb9fbe9b90eff95874e35910dc05c761f8006e2f208b786aeb2eeee841f9a82d9966c82956c181caa4dada81dfa2e2d7a25007c2dc7f2dc7ad1bafef14581cadbee4d614a557df4931b9ca105bade8fdfdefc0d96eeda11c08500b1ca827ca670ba07bb0f85af92914c43a6f71226d6e112d487f1ae99b2239a63ee2cd0849d8a9c488a11f82ca334604a2b7260f25373c6db75656527890f9b772c6bfbb9f687f27099ea9d4d1efd874a6ff83cc36c039ed1690408f20394692ff054d9e6eccc6776b6f4b3c5f24b0052334d159f40b470a9b8799bbc0df4dbfe59a5e536624cad193160ef23abef85df2c9b6e6d4fdf16f848a2a446a77044f1162a278866c491982570cbc16041908cdd0efa2cde011526a3c96d4b39a23c5fcc53d8232869cb4dea871f4ac8afc795aeb1b28cb2d7a3669100a1cab2ee1a7f31e2a25a5c6da836e4b771ad57393305faf582adcd26045e26b618d9943358c615fb206258c8993d700adac7440dcd3ef34fdcb065e10e9c9727662b5abee160aa01d2f2ca6c203a76fb01bb08cee9fc1eb6bc7497bb012ed2774a2d263b9dd03d60c307ccf33233ee33eee702c8e3118f9f86174a97462d0e804a24bbd7f4f938c7f105bb23399967288069e1637b60f2f1883d88ce5a874ea4bc0a7ca0f3b568e4bb1407e4bd6f0d3dc8fe91345f8435d7b1be961c45e4b0f1ef2d92d2d30bb78e1fbf72cd2e7ffae76e8c2bce005195c2003bde46108f37ffacdac28fd67a0de62970b347f0ae3f5f3a5b1d3aacb2fcaceecaf2ff4a2aeef6f5a176cc1b74b234f5658ce603bc353e075278a4056540e43033d37a6eb2615453d8206f5cd294423811283bcd5d79c4afe268a547b98977ed5cf24c0f53a0533bc0b2889356cacb67e2f7353060f9e04362859b1c1f02f96bf5457b58e5ce84a6810d39d7c7f53faaec64db5d6ebb90c1412bdd503ec6bc240c277ce1f5f18876feb24eb6a77e5193e33ce141e8720329add079dc9735f0a35d7d85436f1dba6dcff9147777760b5aa2ec9c8b5e9fb4fc602ec8f754c99ab2372ff5963dbff3fda91865108e606b214cf7acab875197e78060eed52a798751998ce7c73cebc4d5f429f6729a5193d7593072d0921ac8127ba6e796107ee7b9fbcf7128ab35fe9f6fe501fa4695c19fd64460685f287acacf5250efc13899bcf80ad5a340d432a0b9449affda5c8fa090f008e01873aae7d5fbc7972451542c5c29cf9cfdf23db736c8a7112536b1b626caa63f3e4117044cdeab612fff8d8c194d19174f56ce761f6587349c48fab30390f231d209461ee7e18007d10d83ea5aacf199f3b00003259747b1d03274d3c3670595604bb4482d345ffe31d3e88c70da16649a2677bfbdbf618de1d651a53d573aada2eee5c01335ce5519a6d18a70f7ff0b1e66bacc162c49f7f29b9d3fe2c7dd85b6b355c9f9141f02baf08d2be87c36f6d2e1b2e90dfcd100886e306b360df0ecb146a6aa5ac5ad05b63a219ea65885894a386248254348ada17908d776f9b438306ad28b208f80d6b9b265500aead945134b9d388ed5d6205edf07c5d8bbfe0916d0943750150e09c76359d24e3317517ea489fd8a501dd93f159f07d19d00e86d952fbdba2db771910143df346b30a30fba908a1abe5349c3f241958f428dece7ad9a91cb42035c43573b87b26c2ab216cb4c21799f6b3d81acd300ff50edd6fe7868b9ba6c160db3418565ada027b46b63e5d4f3411284fde585ed3673b424ec1cdea678e4a43c262991c3c9b988351d6e0a10af1c959cf21b7a288f2e4d7b3b2c11b400b5e036df71fa993b72ce48d0d8598fe4ef1ce70a970f89b55cf4f07906a479bc84a08bf6ab25221de37afebbc47ea0b38b87be128737d7d43cc84d336cc6ffe1677bd802910a2084751f30398dd0ed09589b2befd2f3b40fbc013318c822fa2faec2323fcc52b43161f47aefc557e92df3050dc5f8b1c5a4b2f8bd7b2ba7aaca79dcfa362fbe7781a2e261683a4a862d5f83e34845a8fcf8a1aa73cd521e87cbeb71f20b20698cc34bee3b8628b1a3784596c",
+ "08b3fbd73d157e79ea9f61665d19867dcb8c1598c1d37b793606936d8aecd992a0d46addeae857d488b83be5d1c1639d4d78350e4cb08782b61bef4107c9d3a79d3d85",
+ "a56f38b4bbe83b3d9e562cdf5ef5b30593f08a1a166676c4fb0d5861654e640b",
+ "8726dc5cae9497936658f603",
+ "88420357d1ad70e7c7bfd55b3cfd4bf06cd4e9b4ed5cba681045199a06985956d35fe86b28b9a4599964930d05d230a23c55a6a152f67082a453fc31f68489df05c553f9ae5cdb3f611445db384d79af865e52440a876fc4153d896b7a2318dbc2a4495ecdbb2e9dc68022326d35289e82aa55197aedc266dd91ba3018c7b474ba22b4e773773f3e9890ea84bc16a6b235e4bb69e785c40c1adc15b0e0ef03aa147b0d14e62341e27398b84a53f72c9199cc1c94cbcad2bd31aa69c96b06d01775b8c0f80278a43f526664bdd430164863c9c9140ad87798a5b8f38dfe90d37f54d1137709d5311136b728e6c799da244294daa4c8b44bfb0acc603a16c088a081129a0d2cff55ce1c4ccb486fa0ecc3098ef2196f47c49f9d253112bd5746fd99df5d2be577617dc2519c0ad04ee49ee1d7be3d50492017108fffc9a414ea227af39fe49fb2c895fcf00d927bf4a2d78c466fd44df4768e6775d39fa5c834b60979ca27ee9f00faf37a090838f56275a894ddadd265a8d2de74265e4d8d286639ce8f01eccd4f551cf6b4429eae3f08902b6ce6ef422cf91ce8946d9403fe8064784895b62a7f5df76ea294132c59da6b9f53d4195c1e9000bec499c14cf8bad460aebb024a76ac50616f0dcda71c0f56dd3239b11764f3ed6ed06c049b2ad673e4beea391dbb854fde1f01b1900858b9809259f3906b34f95a1c6ce8d24fdf0cf7c2ab7bde2202a7f1482baa6e51caaccef9f541c377da620bfbc63955cae0e6644ec8ed6878f704f1dea30d6b50d4291892bad19b0234582d50c6cc0b4165322cff24a9dc2ce1be35be0fdb3bb7abb777ff0b2f4cf16277388af5a89220d59f1f45ee9cc2a0fd7af9aa8e9e8d548fd65be4e47e7f8ef58f7701f93a42e7ff78f70e807fb63513157fcba96ad9731b2e8f80da85ef407d5c368ad16f0657620bfc122ba1b10d7ac2bf46d8133a9c6fec1fe04882f3d5765da8f825e1984a4313f72b67d806ed45c000dd3ddedd524d474b9b5788547d0712e8edb4c6c586d0cdf8f2384f1e093a7f6dffea6e79df9cb9398f5d0b9a7cbd63d489430fbfa397a0d03ef916b7702f33a54ebab84a7055b7ec6179b0ab7722f03e126ed343b1cdf2af3763df7e3a070162535514b01ad86c6cb051859aba1cc4766b12c8cd57b73fdd3c65af6961c45395aa7b885dd59e115db885f644e1c94bfa26b3804f767601c86e2c7dcecd4daa59955e6a40991a4b4701e63fc82b46dc0ccf59af40a8583171375551c868436ede535705f2e6380c5899cddfcaf9e94314794bab98846cd5ba9e9afbdbe1ea7fec5e22e7b2aae59fa598f4d6c0cc6f936a616e11bf01a2acc891cbfa2bc53c511a8a3a3da2e3aa5907d123ab2a4a3c0009fdb5235a3c33718fe4c504e1539abac6370e06150c402b5fc2f8c32608db4ce2eca9d1e4b96371ee195f6cd632f5b972385f9d5d357b87c78cb4e2c27aa9851534de14de923543f5fd9d55e34d6e8b7e1f3f2735df80046de01f79d0321066f9bbd76299c7386d285f7bf4ac15e033e89a040710c90f87aacc09fb8159f93c8b4860247eef079e32d05707e88aac734a2eadaa853f528d9986e0af3435b5c5f44ddfdab9b0c9ab3eea97676e920f80d1794740067f9b229fb018c804e595aa997533a5e967cb79ee58eea18995a90ac08333f1c69600b17ef4f454f540dbfa8b502457761bc4daa876d9053ae1f55001b6916ce559dc6268d01841255990e56614e6f4ee4ce04472dff0657360d75da4e83a71c852a2585110e53137e91bd89d64d99b5614ab2a5691c876f15d9931b092fc6729c0732db5cc40f966fe440ff99d7d05b24a872f552c27fb0cf2af443340b153214b407fb9ca3750d9c157aa75763b0b7600959663889d00f392d6ebc12835bd2f03ad802a21d0228f1d2e9731d0f0051eb2d5369ab790d1134c38e28d2bc2d5d57d6d897244742c176559961a1e40c84ee5c8225c8d72b92352a011e3785c262aac115cafccc2fe1b5e81a677a0220f207ebadd786b93f58e40eb6ade68ddda5b66c5f0f6b4b95cdb8241156110ba3303beb79acbd54423315768bb43b4fe8c4a465e50c4e63bce272c4d731ea4c797e14b2de31ce4264e2479179b906f67af4a23c56e817abafedc2c7a65aa45f0c89fcd0baba60561a8d013e2d5e0bdf9fbcc1346d3edb20e6e9f9c410982e1ac43039ad8fd0ebd453a6788376951fc20374b59946a6803498929d9fdf2e0f5e58c441329a79d1232e957b3a9ed17231c663b4819dcb6b4e33d205edaeb7d7ec466930bd84a064b40aa67fd76f6ca005408062b45b5aed6f8161836c7160a8c8313dc9aa1c6d42c2c16972a1065e41aea9c58db7916e1670cb42a8b54d85498561b4401761506860b19b446655f8988101fb4c45067e30edc3f00df8d88ee34111dd6626d605d993ff207be09704fd8dc242ce514bae77cecd20f10d4a38435a3f5e545882fdc224586a04ca6a162e118d23716240fa67892b78faf98a17916471f7f121fb9f85497a0b34bf5aaa4ee1ed8a4681bec55d1b4973d4368600115bea70f20a37c9e942b87f6cd1e2ab70fd401e703e3c8334c75fc338508e06d6370779578fbe737a75954b4701bfd92028ec32d3d7ae606caaf9f049d9774f70efa707c1c1174d9fcb5b0a0ae2a961c6f58e48ba82c2db14ebbbdc24288e42879f547b855c86dea9a3b9877e4b105515bd78cc43465",
+ },
+ {
+ "bf7884fab52251e202afd7b5b46aa53f85bca5fb80a009d8016e276579e401385d853312a884f4aa33cc5fe7360426bbc0ccb7416cc0196e2e40d3a825d5e0825a1394029789acca550bb28b10d847d0a4fe1111be2b7fec6b5294902775128288a784203031ea853c9c104c75571d19552e2a1359a900c5fc9455230968a5920f2ab23f5b9cc49739d4e4ae2c01c7812ff295899b954e9729a3bb330b60c51a8a7759e5131d7d4cf261fa1e62c29f91b4341a4fc968e7f30ca2261702eb328d628b7275a9efc29b50bcb9b27e5844328d5e8256c76949d30b6fea0d5a1c9abca80d3251fcf4ec4db0a5ff2ffd43618aa2e3e1694c2a3c579a2665f443ffb1eb0ce33c09d7285687cd55b6ca9918553bfb36a44860e09ffa0604ef4904a034108370195a986fe165c598305eb08599abbb3df31b1d93162397056d9ba5a1ac2812c582aa356310fafb4058abc5f157802e4a9b4bddb16e75b6db105b7dbc838f820539b76949b1648909104efa67ce28b16a738f1be104d2bd142d3ad1b1c953b6020a1f4cbb84d5c49424befbf2e6ac5c593b783a3f4af75477312528fa78dffd82fe493d821e011642bf1135a5be91fef909383953308dcb61b2f35c2ad259acd1a2e953c0ea6a03a97b384e39c94c33d3846c26b4f9f116abe572d5b7cb81886d6adc2d544630fdc1684bfb32972e051b9a2bd0931de63e025813b923944290fe1ebd5264ee4f25569a2088314e8d4ce8b91c7bd602b9d85acc917d60d30d5ef1cbb055b9ff7b0f999b98caea2517d2de334eb436078c90d41e0e34f11b93e3e643389f43b3afdc4f47a7396cbe0b4bf159ff27618cb835aac6699be1fc7ec840b767836a165fb95d06f2cac4fe15b65714ddb8a095ed4a5b57e63d536405931b6c168683763fe07c32aa4130bff787d4d440746a2dbfc584a502d809076b257482abf7f8ead7741c82b54c41acd41581148aeb4149b0c6eeb39ef7ba091c2e8bc72583b2fdf8ce7fad1bc05aefd6db0360c644a9760a9729a88ee4b2ab123d7238c12435b9f3b4660e74c0fd4a9b00aa614453d84fea01f779e5a924f8e79630a8bb6561ae19c7bc8d88b9d823b98285fdd65d4cc05e443944ed5d3cd4f46c7cafd1dd5deaa519772dd24f508bd2d588a832d5689119a2d506ff11dbf37d57a24e35ff38da18af07eaff5775d12dfe795fd3e1f0ec83c5f283d6cd76532519a15a18d93431893b1b88929159bf8fd21f62b30f4e37d540baab0e30ff3349a08d627ac19303fcae8b8e3fe44eceb66d30697c7ea051bf5afdcd8bfc00d49c8d36164ec9194a78a4d8b78826863e93b6a810354861f4a35ec12e5ac102f74e390d9c0227e67acbbe3254e5b892786e3a88a383ea9726485854a319569a678fa70392cee90c9aa83eee8df6800565bb8e083e78a064c0f8b863120efd799ea57d3073663c0d0e7bfb9b717ca1d6372fdf75a77fd9677791cb899fc8033d6d806de1e6aaeef525ea909666316d9d604c1207cbeb6f427c3acc1b02cf59704fc65135703f2a9529bb2c8fec992c4de53e54b029c3f2a5fdbec1008d1a70dce0c11251003ce62af712b9e4abe631902485404e4933f346f1b4467fceb65baf776d0078aae6a2a1f95b85a441b635663c75b485a8a7cb9a5c12192ac874d940e2d9b88cc05a2db9b5b35df769925da508112ab0b8f64a1408633fd0d81810baf2c846b222736bd826c8cf905b2c35633d6013f5565e0a5ec1492e99613f53530799052a0d70023339d1c394fdf9f73a590a2faf68390d2a823bc3e47a173782b03dacbdadaef1e67fb47a7cad71b6067ce5b5e41fc20ea1fed28578e9bdfa99faa657a754488ed3fc084faa7a05b0f6eb66da0a28e9ab26bb319fa4ee993de840948f94dc1d68d926b783a0bd3396a89970b2c2595de8148e87b87c21f664618af4f567115d403715c3d7d2f66d7a90de2c5237893a4c18c20494e3faf94485ed39ecfe972c36acef0d7ee57bf8755924c790ad02dcc5c4e15aa7db53eb6040244c3ebb7874676782e54dfdddc256018ae6af8cc37450a4cef77f21e2e061062ca0c2a514290c960f5993ec1ce9eea6d09d3293118237e079b6015b966361c3032368174d74ae5cce4148ea2b3690fbd3c28ee544c5c5bd7bc618122979d52c9d3d44eab1f2467f338e695ec5f95998bbe77dffac42bc2809d43a324e0f5feb4ca3d5fd951b7dc8a9e6276ee080079b68849b14c7573cd02c76027a856165d1043acf99554c62fe32896d120974ae71f84986bfa0c28fcc399246bef3ab90f8e55f913aabf339dd7ca6f0861a9ef712e77dd28740615479f39a37e746c7df2b267066d1649fafe0459f665f3d5e7124db43ab1ba5ff94989acc7fe0935e0bbacf718b33103a1355d97ab416d8263ab369e6cf0ee563a77f2f265fc3856b7d54dc0887ed439a421c14f733ec1d6da086536f9539d23cb8026218c5e783423b5f4ac24c8d5d8faa7186dd5ea34afe299e6dbed73ffa8f415da706442a48808a9342d6209f65ca11eba76f8ef26db890da76671971f65bce9e6112c8aa92523dd5295d748e28857acff408c161c0513b37b855a8afb0764d118815bb1b68f8f09156641f7eea994ddea20f4062607b9919d041c880b71592402a4d5b92464b239caf431a99dc67787e76b8e1d7337af004bcb88473cd16b3f7640e8aaa59ad4609f060a2cdc71a4b3ed22c1506a7050a63bd8ed68aa58a8109980bb3f2b9f9fba9599d7620b8c25e8aee739095789af83529cfbfce5941d7f14c8ae30583deafdc7c25fc34e75bbed6ce4f6b47e9647c12333ce08c7db77dc94161cfc43f7ea0bba39def8bf8ae61c6fdcc0de6308af963c6d9ef43916d0cd2cedb970d5937c9fdd4b888cc66e99363b5a04ae62a4349f01c3933ada64080741b1781754e4a722303faef69e382cd9823177e4d5ac83e76017124a7b1a41bcdbb9c4209e7b42c",
+ "eaae1c53919e2029c137a80f91704d0871be2c1870d0333d8bcf7f94",
+ "4c434cddb399e52457113cc7e16f046c3f8301f5b6c296979f8a091a9ea557ea",
+ "b633c1a0e1ddf4727b149b3d",
+ "f1de487001a580cee6edadb1ef6b700c861a70c6ef16274447b8c61bb10d2d1efbf104d5f7d7172c6a5cf9c06d886165a2919ee9418e2e8f803d47832dae5ef232ee300d1f973a6298c22d777a1b16264353cc731a7a683cfe31e0abc704460788c555c0c24f281b81d7761235a955c736f17f213a896b40a034609ca8456ec3cf5906d01121b7580ce19d89347b6a59c81add318df487b2442a7a8b5e30df78467abbf46bcd5ee5b994a39ca5bd8846caba6f02f4f1335b73d4e20be0b6ad85966f86d1bb857713ebf947ae936782f1f4929498bbd66bdd5ad6fa252364a5a6b46180e93b54cc321b3cf63cf23d55392475c6b8c8c9dc707924b55544151c7c55ae0bf391f793e52bed70829fcd32b2926600f65be0943d6a9a96547675426b0dca9cc7b0f5dbc9d5439d0281014c6c159d055d6bd89d67828ba7fd2a0570ba82996037f7dcce297fe6518331270f6fd5ee63d406cc5081472bc5f2298a9208dba9398ccf807ce9af982885897715b3c5742456f756d79c70434a9baf7b4b6664c9d9f5696c5256b74099e593f97a2d4a469cb3430d0c3eb06083398cabd58af598945a85c9235a3fdd9ba7686e54d0de9afb594b1bb030be8e6bb839f6b45699dbcd2f771db64b0c62bbf6c8672fb412d60c00b3d87f82ffff6512e8308877573323c5a2d6a216ce3e2ce07c9763835ae59d44d7958fd873e3995b62b1b347e489ce86e023ae27a6cb03ddec27a38fb233499a714acd89232a91d38abce30299f38f437f7a46df647f2be862c1e7bcc1e4263c2147b13ee5b345b7fcb973f3ac71db8bc12309f67ddb62659bd73fbd20664eadcd23a79233386aeec1a6fcc8c592053954ee53826cb9b6bba22400648887311cdfa5414c96d5956fe193a3729be1434d923a3f9849f6c419f77ea05fb72f3c4f75ccec03b7f7aef8c8e55c8c5480ee505ae1a7594e6a911dfbc39dbb0ae8656f5972eb644c64203a920fe0078f3d050cc5666ed9747c23df7853d6913005d0156e741a5ead3bb1b22e5bd802c303a73a961f0b60d0fa698041c22577b44eba5d6071de4b545d9f5de24944c151de6a189bfdc223e0507c74ff929f06a2e7497e8c63073294b4aba110a006a6e9510a9617405d9ee711831e085940006761822672549d1d1c70e50002c2227f6f304b9a7f11dc05751be2dfd297087044d2e20ecfa0c091478d62c1bf5f0aacd25bb0384853762a51144b77d30418b633c4c10a6eda7b2eac46905641da0b685f85349749a91cdbaa4027fc50eb97a7dea9e8cbb5b5f386ace0363803ba579cd16ef80dc40ba1044b4ecd0e81e382635d7855e2341b18e0ca705ff46990282fe25093a248ca04a1fff64ebee25065350ea4b9e5990da4dd2e28688ab08b6d6fcb54d70f6d74fd7e5e05d21c12f5b140839aa966aea9ee094a923ee5ec704b5b709ff009c20ed89a75468c48b505d07c7a5ba1ad54ed610886c9d84468eaa598c71b017578404c909dbca431703e0cb1cfb975a696a1677bc015a75db007eccdcb21b9e5e119c48f148c2cffcf29e245e52156ba5ba0a8b0031570e4cbe7b3ac4646353594f0c4a9424c9d97845c5e1a4b4016df9be8df3013e5269484cf32258849afbdd733189ea11783f0f64d3aba9b4f48818011e868cc03ecaa44ff0ab83ed12981a6df445294ff672f3a16d6e0d19b90007d4646e967e0fb1763b3c879f548e1103a75c94f3a7f72be78555eafc086c1c58d1761aac60b843704f234c55b951a1303a12705f2120f784c2bc1494432a94c835d908f0edd5cbb169afd2d38087ca5bc5e5df9c3bd970dd2da4fb2a00933538148ebf669a20b5beef0402e53dbfc3a0f289b33b41ca27eb2f036a22f0d02e0617bd01e8c74be264515c9b46b9ab6fc67403a35837844580794088a9d3c14ad9309435daa0396f48017be524856ab6c191350529962ead64bab33171a01bb3c144b23bed406cb05102c693ce5df36eb541c47e871acf56f2b47de687eb9b3511ae83d06b1f69fbcef3225c3469c304741437fcd0ff4ae3484c117f51d24b6ae1363beb7d85d9b61e01e3dee901b90f2d3272eedb384ddb4d3b9594b9c0926595e500f8ce2e5cd407bd7a4e2c8e6f4315bf693e8c961ba5b8a6c7f5030c68a6b995e9d3f9eaee9eebc9d679eaf72a5f1cb6b2fc66edc7dffa2370dd778ea7ff446121999afba7bb35ceabf626c6269bc466d65f7f812c663bcb2fd87d3e09ab7d71e727f66d20ec48a5d2bf0aaf0aca05d1546d6e974f90df85c1393e3d45731f71ec7b5cb6cfb4e5c29976ead6944a99df2045056e198b19905362d4e9b765adb65eb089233a8b3777352665489c9456cceed593c6590d9f3cc4024d0bb92e1a0dc619bf8ae65be77456c18f8171e4d2d846073cf5c57ba93adbc0db9799e3d98934aa6899372acfa4d7d2ea32e20164b79c71d7bd33c94f9a781a25cbcafe563462eeacaec0e8d9d6c0199de85558a3a05d1ee3483351915d8a4e65ca0ab129a2386a9e26aff9b912c588babbcf25f8c467145061b9b8fbbff19d8c6ded8527d457be7c926c8f490bbcd627b3002044b7729a52e94147f95772591616f6074047e758597f410b3100f9efafaa4137dedfd0edfa85b0927804f0b4fcea1a174622116222004d42b36c2c73d04781f2f49d080f351e57154a3980005bcfb0ea34288e2fafec5bfd01e1f7901b3efc71ae58bf8df4cd7c045856103b77bd78073f0174aaaef4a3c0e8b5b46dc92db55478f012dc1b7d513e215e735573257f105d2390b5366f49b61809033c13ed4e1ebe19ab89313c947f2585f0788a0c5de90b41ad0dbbfc604a0d414d0e5390a0f3c9616cfce4097e38e05888b8bc6e55e40368bacdba7e5b76f4bd8fe619746155c30b38807a1ad325b00ecc3dbcf23014e79f1c39af7cdd0dc7ea58ce733e6611b7eae069deb047aeadfc21960e614db19d2e7e0905a9873268b9a24f856c28059321a742cd6cb3d1527",
+ },
+ {
+ "c89c3cadc094bffd5ba06c600dabe30ea19ad037316fc13b895fe0e14ac8841264c1bf25557e22b01f8e102c3af43adb8e0a12bf79d3fa0232dae37ca3688e07294e2c7ecc4e2eebdd3f17173351f2c15b0480d4d77bd70955ba86f82214004b622cc92f7bf81a5837326f6a83612bdf65abb33c268a457c45cb7467e074b342a17c711c748c74abbee31541444020a9ecd4e5125e2a8ea3f6030bd677be18183a8a34af16a85ad48b7015cfb036789c0a5daf68883d0c7e401754b8d56cd00ff605be0cad19e03989f608392c81d636de859e66c2aae403c138bb96a58ba69b9064a83e7d8877067e7f40aa0016e0df9b7f455d292a60eb621b8107a727a3378c4b7509d3ec10526c50fc6c66dd4b015c915e85bbbf701ddaf2258119c8b9a5132eafe61bbf38870f35f375123f766ed0d4f38b9364a86e56cdef6f95a815a8d7c48ff283c77992fc6c070eab7d7c7b517006e5d4af532a7c429912ebaebac27249b4f5112d870d998e1c450b98c05d08c742dc769506f2d7a004c24ebf84c10838b619653e27ffcc4344d8db0435e4cb77c0410cc734e36738a6b5f72a7600632d19c86b40c737830b0f5f104443dbbb031dc7ca51ab318951e7817b5d81de8a9aa7f5db6e2d5e7a3cbd8a8100653c048204ced3af005d00e7de7b445f5acff901c4d46ff133e92ef073aff1d9ebf55befc32f9ec38c9eaa6a1aefc974bec2758297e474cacea2ba4151ab1a3ca0762c64a5ca273169d29b83c164f77f266c01bd5075871e17426068ed7aa58ef0d1f2959b19c604eb6187acc57e2becea2da93ba23159ba73b9226034c7ee2498e0ba34fa8038e5e2c092a73ebd9329ea3d648d6ebd47e1776941ab3130cfc91089fd0a0a36f0ecf68293343f275d2a64c1b7d27ffeb3f667f4a19824706235fa5f3f04952ff08bb183c0f1aa1d1b0edfd2e05ed093543788f5d0ac6532e15f912163275053b202d772f381900e906fe070cdb00421e78c16b7387be91adb7b3b3ea28b92548d69c780ea578e7ac66eeb931eefb4067bcabdb345a7cd2022085fc494f118215adfa2443630bffc9faa8fbd9943c3140d81c7532895734a9dd20e31c326531d06f5623c252139c4cbc882640c457819c63f6ceed4e03872b246a3766df69373ebf5af1116e8d5e1b15745bd9dbdd663fd4352d1238a43d5d1e74b3edddfb1c9d460daeb49afccfa0712b7a4cf8d07ccd0599ef3e4e1c9b5c814f3a6f3a46fc80449b34df87f47ff91fea3618cab2d5c04cb50e8ad199d752d901b21348ae939d39c86cc1bcecbadcc6f0e581a3bb51e070507b41ea4294b35456c69cf55a2a3f1296f0df73abac3a9c81cc303d1e20ad6e9bef48de83fc22dac2cfc01ce9ff3f70e00ee49bab2f282ceb6859f989075814e690e36a8d16354fd6056cbff49c30e49b1570363498531ff0ad0979a4518e9ae271f57f883abf5e301c0e24a83f09335479698911bca90269a28c0e040a98e67c9e55f4c91542f921511dd980270cd490766da22306b48ca9309aad3b2393b7b1e9ac7afeff64204081f9c0a8f6a5396d02eb9009901ca2c0a75ffbdae3a38ccd5007cc4f6bec8fedd64086cce5c039e8abc9e23bd694fc8de4e858c89bd585ebdd422b492eab26f4ebbdc1d17dfbba19b5ac458c31320a161a52dea638548205a6ad4ec54875ca34238c059177bfab2d5be0a98d12b3932d0661d33ec655446d0283224af8ec7f1c6874add03448fd8029a71d3c5aa06951123c9fd881d435845757df50444e6cacc31a8cf7537a778d1184b96c3512cd474f5d1fd1214555789d24c8d173358e36400b2d937595109729d9f35eecb0963c0da60d2eeb52a778876059fa95d820d5d34e7948d389dffd53d34c4083d27c917879b053cc57dc43c8263e5dfe5f33c19dad0a7126ea6e8abdbacb318d37c305a183596ddb25b1934beff13a4f24fbdcc2064de8e0bc639e672ecfe45692e9f8164365e1691784b4f775ef369aeb135ce15135c20da95064c810592ea33316b9767caaef842f948b9573b2205ec57d3026a2f2244c42991462e233061549cf9bc66a7b4a8a0fc61f73883fd24dad02644004989c4721a0aa03d3b0191d7fa4d3da102e541fe463936c9365ba30681e706ca70cb3c8ad5dcc710de59e7d8a6247aa809bba74ff4dd182a38bb31baa337841302c19ed89d65e87bbed05465f4ce0dfe89b44d7e9266a8ca21d984c41109d813ca76eb67dbd4e39aa437ff98050c968ec1e40c534ab51d6b8ea2309fab08b3757e9edc5972bff316f6f2affbff458ac0299613734b30dfdad20f797d172cf295cbcfee3d8ee25485d40380d3480a9372a1a6e5ecd7c4c6a9d34027ea6c197f37e86e757750c9fc24cc7cf814878b8628326c140930dbb2041bd9ee87f36ebfdbdc34522cfd4e50c9cb48dd52d4647a06d08e0f0069c104849bf30c8e61cb693dffbc69fc0ab9c5d502a227d606a1dcd630ebd799acdb1e47ce2ad52ff53f6cf4fbd5f0058fb5db915702675ea44334d42e0b6ddae78b22b5b5f7e5aa36519e31278e37b64312479b14aef9b8f12d8c1f39faf920851bd53b13bae5490c847b3312b2e956c430f1d8deea91cf171dee5017e7709d0346d81600bd5f0c41da3f548c28aa50589b293685ba059cd7f3edefdb5d8cdea364f4a42153b0632ef0b7ba18610b71fc34a781eead1dc5a00ab47b6840590ba44dafc6a16029cf50e089684194d93dc881beb62edb7ccee6304a4e71a35915f109db92690461b9e4ea21257ffb62477c20feaafc7a78e2aac2301b66893157920ce9fb114ab4f534d61bb3d17dfb4d9ef9f79a736f7c1d32ac3998356aefc876d8c38722787d564e980a1f15056cb3fe634d71d2c98e0475c79cab318b73a863362f85aeacdcfc44e61b5aeb870de9ea5b5abd24e8c19ab05e45e1e9b8894deeb9d29d65ae99aa94b5047f3c1168276cc2e491aba52b5b03703ced28c63a167f0cb3e4bb4d8e4f0292cf3ea4376510fa49a1a5efcc00f23c3cdf6402197b81262e66e17bf4307d87ffbc2b37213b316bddd65aa9d64ce6122c4a1545c5966bf4fc4c6ff17ded787ca9a3b3cadee435bbba8f6590dc4ba30895b84d5b4eb94f4b05be3c",
+ "82abb4ff5457b21f359754f151e456e2c0a185c8363d15918bcee0d6d49f12564ac655",
+ "b63b577e719494032062e3f63682098dcdcfe26cedea2a40893c847a331e4ce9",
+ "9f1d08be539f1244f0f69ad2",
+ "88dcdb0309f8c4a96ad5560f8210eda1f5afb31b85b7a8b15525777748967d4ed77c063f65d64ef19b31044f2adc690f5e457faa1abe2e127b38c626eaa94053c9ae1b6b4d0db1f02c8404b50f58210cc9fcc6fa4ecc615631da631031cd6253b4a13a3e88295ffdc775fd4bdf29655d9780dbe02b0a82aad4c4088e90b51f170909c0f98ff93ca3926067ec94be05841603db4f913b7025a9ee34b8d8bc629ed827a2a9857e0814d36b83cba21e670f8f94ceb4be5757e0b8782895b5d8605868e4f584b5bb6a5f3a94edd9b23fc2b6fa06914aec970c260fc370aa245ca68888c90c43eecb68474c9e45c53a7da055f5bfe39b56769fa56264dc8bf4c1616e30262bd501ff9fc5cd78f73ad89e093feba0393a11c6b2cbca765ba025c40dd0417dfa644fce96db5a0362235ad37a317145e7b5f3c7213c7fb3c393be57a1cb55035f06da1f0bf665653c5fe8a0f3ca67dbcbfc59852694d34819d0978cd09b508d103017168f6848258493be737cc24c2112f2afeabf41038bea1f74bc8656d9910b77d33cc691a0d9b12f7c518ecef93423cb4871949a518d2f06e5427823324275b97110f8f88b0d14788741e617f4b194e679a1627da50376a08d4f23b005c0446b46d4f534ed85e4692e7946ec818437089425ee30e47de995e8774b61003801de67939d9fed7bf0cdaf625798d0d0d04a61a2482217b890168e36f20cf1d6b81f9daf1a49a781567c4363ac2f3ebf0252d5adfbed17f98cc264ed2765aa279b7437410ee8b4cf42932e5055f4884deefd2a979ab1328f97cb750b3b7e4615b9c1c61659c90a5ff6d1c736e785587ec85040fb2c6decf789c2707974bfcbd0c7f699627b31e0762321d55bcc6acf1aabbd44abd7766d397bfbb68c424b311611d9eeb6598ca3126f569f688455da8d5ab86eb01f9c96186858c4b5e447aa2b9ca11aa5453f731beed4e09f95bb7376e200212e2f03551b8b09a19d6910f25898d692bc20bf6ed3ac9a0276db560de5c9e264f4db8fec6577042fbbd4510bb7070086508ac451a1fda26582c259412fbf1bd60cd5e921160c2604fde559b5ed4df52b805010b225f999450adadc6e108b70f169a3d8da6efbe1cce1c4908b004e928e3cdfdd0b4c5f742fd72a11c9585aa3517486201b6d9a98739b77970a88072750d29d005a291546f13b576b4249d71f04a9abf8f653ca206d98f738af2a1203bf0975f0a40138df054ee834ab73a3b1d7036567369a7ae15f808904e08adfc84b34a0e1356009d8a82e51c3e8f2170908179bfe47be8ad819cb12e85b6b76bba7c9b9398dfc00f550e32c171b4d5f2d9676063efee0b0b49660c10260ce052dd00addc3359e35c25dc33066d4b05bec7d93f71e0ad7d5ab83d844c7f33137894327f464260688ea4ce9847046e7dd0bfa48d4e15277a9586b4742daf0c5ecc59aceea6867068b03c20aad38d04a814472287d809a9285cd4dcdbf68f3f4ffb794701f4c265b2dff4aee55c9815938689162e08309df150538e60dccc03d495adcc560fb831444b922a6375845cef5dec56eff2910b5bde5f25f0e550ab5a13205de91d20896fe04a8ecc2c83d1371cf381424f8c43d2a5ced374878405f52bb92f4fa3c15d29ec151508488f9b4e42527921e245a8ee4b5d6ee95797f6ec4374d79acd7b467454a1d7eda05a8ae104534b23c46b27581abed6afc3ca555202dda94fc2b93501fe78867730a84f6f726dfd7364bc240b65d6c3022a04e09c89e36a809fbf244cc5522315110e9e33c8a4e1f1396e3e51fcdd53d9ae94fe7bf6c6ccef0ce02048a11441de3c25aa9787c577501977e486f8dfaa4c81e3183e648311148ce5cf3de56878847a9d14c0645777022c158670377dd9553eb63eb17e19ebb06202be8fd9bc2b24878cc86f9938e5996751ad9ca04b636497199f7f27dfa0f5ba2a01c3a491bec6dc5113d127f6aae38fa07ce7539a0c1817f7f0de0da538f4d85ffa394784a42eb50994e28530e3997e3345db28bafbb836fa463d34146d9f46d8d2b28b3954b9bc7f84046828e9b55e2fd663e562aa95caa97873f48f0a003d2251fb3ddbce0b6072fc17e0d3f99b655b8f41e8e6986ef7526544222e2d402489eabed4c219540605b9f5dd321ad902708601e85bc874c11efedd072aab7e10272c87b08b9457223de9fbc3abc2d1346656a524e9c67d79d4053c4257e886d6b430f5b7f57b2e5e92ae69273c1705a3074d5066def69fadea1af8fa9b3bf4890f9cda4b1833e5ed27f22bc4fe4cf452880c7b53320bc7cb748c0af6e7550ffa84e4714ec18d208131ae9e3edc6cd6fa2c60ab8ebc1ee56eafc01fbfba061e55014b9711eb58fdd01f8936d29dd081565de0b175b02989c5ff374e6f58c3383e9bc00d8a93903e6a221c7475e15aaef77594849af877f3807a76e03bdd54ff0b192bf34385d24d858d6f454810ee48141d73e3acf1aa3d19cd4c723a634cd8e25b4fb604c744e408dfd82961e46e8444f001d0991af24b3b6ec57ba41fb45122afc73ec6b25f501f1abd46181247945729337bf5083e5821968502a5a696043ee696c290095feac000957f968ac61ccb572ab2f37008830ab9a81d02456190af99873450b52df1888c3d8b6b13df65a9bb36a4b6d0538a0f179daebca2bed6f94b4670560fc5471c3770f2d004b6a138b8243068d754fd246e9881242638c6675f1611f237146f6e0f72ff2fba96f479fe0a662a81f40928f5400a0bbfb5ed07a87f457d5febdbdd6f323e2a59f749e6fc8a51d08b023734c762a91cc517401be57ffdf6a52b9174ea153abf2190ae2642955c3c02b4a15d72456c9d2f323de6fabbf56dfa3b566f1aa688c86b662bd34cf2511cc4a30621b6f1f1ac382bc1c4fa4c0d4d5a30ae90a5e54a9fb4afc1475e7c612eeb7f0e09e894c2004cd04126df9359d525d7f090e4b531916207c38c3512341c84218c86fc50061043ba1b89ddfb21cd756b391cb53e8c1cd55352be05efe562669e3986c022e30c79a97bdf087889a392e6da0d72cc7ea208aaf23408df23f3a9ea9bf9a935e49c9994a37a5dd0faf1267d5f7db47cf64ae1d3ec166466b2f882eb21698aa375cb50146c0e660e9bbb38d7bbc1c1c6d8333f7031d6a",
+ },
+ {
+ "68ca38fccd585eb14f953358220027046c14ef965478d3d8f206f63fef4fe3571a1b53e774b298c347cc1b69cc426d39575ccfabd5a284c7a87a0698cae9efe40543cb79f5643c3c3057a5fc991235f06f059c44a7200b509a12e864fbd748001a14790f78b54ba80cf0a4a603da9672df32b68652c1d6edd3be51cf969acfb0ae49c026fe0bce0bfc72b1ff4c47712b7a27b2cce888b9bc470b8bdda55a8d53a34d79a25947ad55b95e5406a5c5311fece3ecd46ca590b3b01b9055761da8196b21bbc468681922c66d286c32598b1e3d77f2a91d835ccd9eec231409cb2e74ede9385552517718be9f84f0f9100e368701dfa4843b7222279537306065a54d4edda3a02f1ab9edba3ddeb34dece9d5edc8797103eb942a80cb5ae130ff2e7eddd11f0cecd8f9a615d75963c44238b10ab1230d9db7371d8291feb2912d306efe4f7aea2773903d4be9a00f2bd8c03589e342269a79441c0b42ce9c6fff0a6e4e845876f7e9b342d25351fe2b1233b4f576db90ef1facfa617b96d17aa03fc824973e1c80f15e5344b0516fc28424b7faff47ea1ef4e47f6f7b50e91b8fb14027f05ca7e1bafa266a4b952cd0b9e4cab82bb4d61f99568e14a6772f36296f5d19cb04fa86ff20f04ab61d1a6f01e5282c99fe4c3254da46fb5276317be58e94b1928e3791af27dc6544f6d445dbfc7275fbbea74f98ee4aea647b654909f9fa9c88312d3759099c9d0070e3db6d55506813f8b7abe602964a7dfb9387f58e237dbf50b4185a50b65ac099352dee8695017e4dac644f42aecc3e415333cf76b08fc764a721b45d7b74f6b0a2e43637e5b4849218d3d4c6a01208f345d76af56631590e520d6bcd82627d2446b45b2c68e0be81b3924753a54f47ea27b1e08de2399b34470701c9697eedaf3248db9b28991cdc2c632fd1b376bbda279b6709d5033d1c0a3ee573bdd222ef1afe8a4397a61fc30a4e94bdc55097ecebfef6c00133dc0b72c17e2f93a11eae9fa9f1364f10fa595e8e1623dead10caac068aad3967b9ab2837dabcd8f96a77a25baef16ba84bc93661ed150ffddfbb0369683cd021e8f959c2b531bb1fa95d7a574fe5ff9aae35fb9b4a0a9829c59b932ed8634fc05ca88211da3e30839baadaea8fd9843e0e80d9598a7282500d157ee579cda5d57628e7506617d301c2adec5186708f94f069ed7bdb70cbe88549cefe1673d48c9bbbdc01d2af03945cefe6e25f757750de64cbb9d496a25adf7058f5e32c827fe75e80ba0e834e6a72344dd2aac4228828ed42fd83e4576254af5737dcd9b6c338377d46baccb02d00fdffaac12133ea0e75e791593ef3aded4ae4c9249b8d5cd20aa28cd652b9d750b88111d9b4fbe729e27882206b2f0eb614d7daaf6436816fd80d452ac71c7a7f9e8c595287407c6ab9fe8a242e98da4270b4f1d4ea7243c27f89ed46a567c643f31f967b5f12e518106f3d3e08178078cc714cb6e39079631966a9becd6f02c18e983ceeaa2106ba9043f9985b791027eb5dddceed563106bcdbc48a4ac64bd95e87c708a8cdc33811bcd16c35e193203e70ef2bc7203183fbf60d46bc581f1bdfe62387b3e6c0c4a29130d872c3f8b134e7dcfb080e7e03048c49c0e468dbc44eff4b02e50bc6889cf7600fba58c0ee409ce948aa684baef4956fd8fd4a9c4c49e84e2ff314b7900b179fc66f5fb4affb9ef7a6064354fad8c3d2d50e6f2157576f864a843dda8f547955c4d80a73d4a86b7aaeaecea886927a5ba0e97df740ec7e8b70bb650010df55d4b75f478b07b205b560d45de666d84206c1bffd02ab7b8d1c37f21c47d1711b89d16214d8151a8e75eeeb5c54c39e5a855d578708d314240a064051d8b26c6183ce755be38fe9597dd5b5d198532b1db083a4b856b8dd60bf1db197cf1df852eb6daecffd97287a6cdd4c05307722e0fac798507f75b03e9361d5627ecdb56a3b633938fa61b2673efe6c6e768e4e7055e6c1d55c7113efd3e95151b606bbf169f4296455dccb93da370150c54fc11b3682f092f30381c6ecd218a3d9d39442c8bea61d9a71b174a8b2c56e028689380879cafb7c4bc2691dda0cf6ada039755edf93f851446df9f63267f8b8f030c069fabbe6457d4f63575b5905fb927a5a720d52c351bfbc48f12440a91471697e6b2564b1a2b314fa0e6dff090079637287b635d875f120671561102ad27aa83d9f0cee41bf023bcd703ad670b43ae23bf01713650834cc1e95dd486757f0a4f6fc9337bb95738805ad5e756198579c886eb0ee77e4ba957997dde0eecd84e4c9171c84ad8f0cb23c6a289e037f3a8beeea7965ce34fa47cbd727baa4ac9e6dc3baf17049fd2386674b246aca5ef6b8496f1d17a3175f6fee86299232c7fff682f066cbed895155d475bf9fd4b5571d257534c88c93377b1a600d4c280d42aafda975eb32c740073cffa610b5fd2dda7262a2fff5da7a0f3a875c62949e0c9247827d7a49bd8185bc27967124c34b9725ee961bc8102a029786652c2571be6cf33be63cf867c2b48e5826b31b714a415fe05c27f0862a870d8fb33200719ef4ac8530a4ecf2597b4a7f2e66f078a7505803774889a1cf963083c831f46725a1ec5545d8489e53921d81f80ef99f5e51a2d5992c7769c2a7ec8bd8e0f2fd81de53c7b69b650a2d838b269185c5efd668c470943bd956e3c5e1bba5d3b927b10cee68a75372d4d6fdfa6782c05659281bc9bc56a2123967f4f50cc7ae3379ba21e1617553354b5030b3d3f0092c1824f5d47b97e6b4fedaa90aa2573e1b115ffc72d44fa8209fd8d372c8dc9ee00193b47c2a9a302875da331731713243d02eb5a57d5dc51c35988ffd742ddd75c191f1eb2c2214a1fc47b82db8ea708818262d9583f2b1b98a40b6ff6e94742f25661a51882ef28475aab12d9422b6ac48e341cbd6f38460333b5fa1cfd4d0f43aeb46c21938468fe3f7bc771972246156652d2c58b18c8cecec2dbbc0feb0fae9f6bc022e029111f94e8913c0ad741612a1426b53cff73fbb24fb7b22ab750ba1310ecf339fe12ced6a3fae17b4c429550794a8d68be891b0e30cd28e81de2fb2ecfee58bdf11794951276005eb8a5af21e03c8aaeb595ace652c5ce60a8b98f6897d82698ffbb2e02213e50d9d3f00bb42c8652d22bffb87ec576ef6e206ed6c846fd5136a87f38c9ad899371799f35a6258878418830b04da79fabd80e7290456fe17c0850a4c20e2e657f97f4a53e1a3db65bb5e71bf38eab9f56aa11e6ef71c85b8a28f04c271",
+ "ea196b6a64be4b0799b1c2f72281300c3a2577db44e5d3606b8b02fa8fc46c7aded7e442",
+ "7c86a2c06b7520d60023d18fe73d09c514ed07a91d50d8fd5bff00e7550faed1",
+ "952f492fe00b26028c560fc6",
+ "b3f3294815ce461c8843172efe93f73a8254e58a0e71953e35c15aa89a7bd9dfee967853dcbfba73d3b87fa60449cbcabf13b1206d0cb27d2c3fedcfa695b6d41efda37bb6db35449bd470a23787619ee48f981d3f0b1c8e121725b2289b6d67858a4f9ab41683bdaec8a913ca2cc292a9640efe50fb85a1d1f7b286f45d4448f85b3242f45ab44e3281d759db24dfabbae4259f127d6546ecb914d7e93e2c19230c67fba8a6cba6069023ff7ea3d8a170289c2b4391bb97a7b899228d032b36186dfbb29ae8f0e6c06d753f4c6b21982d49ee682bef50a5c2c8434510c5fa2b9c0349592f33f8d7ad6f7243d42b292aee6d210c61e3f898875b91a17a89148275031b74cb34e628d7b701775dbfcf87c79ab279a73dad14d8eed365eb9f29a007b7d2ccc07ceb8cdcdaece67fa0166e135c9a4b939426882eeca98ab887ed2e4888bbebd5afc9f2da3e9162527262b0fa85903246bc8b80df3060c890ebaa516781a2b2a138b98001287e12a9c68471912dd297bc0beadccdc31a27b7c726baf31510cd355a28e4ef786b30084af66ef135909795aa73814cbbc6552270d5e11d46e9497ba30d6d8cecf343d16e7e3357bc9bbfbc7c1dcaa5fafd8a9b07056129da02e6228886463474c5af1d670bc14cf2868b816cc71578ad807a37477341c8192bfc2e8b1f7bfd58827e041f70384f92bb4c6acc415dde5099a1c2b27b709f9e53d1dab07c87a042ca4af7a2a6ee57b37bf2bb42259d372ecfeaf1dc55ac3a9f211f16fef3b2d5f11dc19fd1f425c14779580b2501ec6e0a84220e7e12baf9e0fee3e8cf499a7fba6721a746f598f04ee8ab4df31fb8fa5ce2d2419d5551155c009f2780cdd225ec2c19f94fb9c8b785ad4574b4da766eabfa696a1994e64a2518d1bcade6390cc683a6e80cf8b163c3e58cfa1134ee743079347f08a89c81478668df32ce9cdd7b853db5cf7af13436f3bbb11bcfa8f6b6d727a1df84f99fb3a5c248b8fd5baf669b68fd9af45298030f3251bf0351fa9b58b0b9fba53ecfd838300790ebd689744c1b7b333fbed76c8fb96fc669ecc6695ff5bf8379dd2a3c270af858cc60894be8922d69fb9707bd2a7825f2eec4a5056e5e91714f4dcfa86974259fcbfd5f20d55923a0a9936fb20e5ae9670e2019336e15f530c0be449fe355a7a02c0938d60720d5b8f4f59d2e4213ad5251c6058312b43d47c44ffc8946a98797f5ace279d3e126da63633c0eff1c412febdd47817aaee466c639e43637c1e179f606780ab490d3f0b3c2d79709f1262305fc87c02f68da2dc32f8c544e7b358c3a5d2c27986a19d13fe736c60a3524e94caa55e853eedeece985d16bfa6c487bed6583436cf82077fcdcf90a05f49db50588f46550f7a0c3a1cfca902d66d25dba8d2c53bb5557cc1d87c8a407898b3c30c4f0852df92d839859c191228d0a47324ea9ec2e0ae84513cbe4ff4aff85e77b8587f1044bcb9775099ebc2f28fbcd1cad58a8ce1f072f2228f559fbfdd8405d86f8262c27c3d95e01016b343c6a4e59dec81b59bb6e3c6109a4cffffa85e9752ed2149b5624417c0dfd1a27bd2630bf59814f15820c43bfa317be59ef6f433c95e8be154a8ae94765bcedadebb717f0d8c24e01e1952bd104ba9620f067554ae0faeb78f13c622c45d97b2b5774a3e30cb07f2cf0e8b19d1266d8a8861f3772305e24ec5c9cb714806c7d705a3bed6385f8be4e12562e17ec3df01afb4ef6f7427c48a1bc0e64fc65eb1c3d3ff2d6687e4c275a019f5ab5c63bbe47e3680fb1802d5835c4d494f0f394de1ae47f81eef005127d0971c4589c456ae6a69855f35635c28b590c1b93f155fabcab59b6c7cd8ea1c4ed1f67093aa782c54329cdcf9bf84a40400de707b894587d6e08cf7fd72fa45b6709a26e97ff5ec1269b8042358f872a79e8c2db1c7ebffac014d6b6f71b0c1c1945ddedaf5b6911668059b61b55eea4737aa307c829309c9ea548fba2bede023849bd61b5a467cd1ab1c61205ce64301e2531e5d58d03c74ecdafe1f5b74627be8716cad0d0a0be60984c9f9dfeae24a6c4949170ce2f589326e0a76c447a578ea3a5e4bd9f18884f18843eb1a78aa2fae06a7569a97551b227c34d429c8e1c8c5417ced93c30dcc607cb32a365d87328aaecb4ce57ab8e74f0d9099e267cfb747a3bca9f76b5f6dfb543bc4b5c06c3646062ec14f511058eb2939601913f8a0f1785249cb72b0bb1c12a9508b23caf490537eec53f614f3e06592eb61f75c1cecfa514cf7b500b0375095d5db74556220131390b77d0db72711c0c7229a5769b1d2b3f5105f3a4370beb1cacbd93ce32f89f1fc833c7949211dd204616c013a3399a22f5325f1a00008f4c8ee7dc5bd7476848721fef843123a6213cb0c0b6ae84233ed01a77a115d06e08990b8e60cfa4f41dbc9505cfae76463278b6c6b5ac7c3b83284caaba4a6a1d739c392528ff5b06bc3b82e98060e3001279a44aabaacc661fb14e7581d1235940cbe067c6b386da09454e0467c785ed0b65d41ff4cf36ba5f63d3ff2b45c11c6c22d3ea8ebbf1d52d770e0ebf2ba0c67c7d3641c145cab474a88119335990137fa82a340c2cc8c453752a3aa801127a47aeefe66d1af1a26ee1cd0e6d935bd548f6ce33a9c204be02ba08f9fa03c685665375db7c0c656ddf3e441ddd96b0d2018beff5086cc63339f26bc8332a5e6a1422bfedb69187a3443c23b630a28b02f8075faf3ff2fbeef6cdf02ba4af47a765003de2254b69f487bb5d038759a33ce6885611198b81b0b6fc5d7a531a7a90dbc3556aa758db1657698cb3698b8207b1c1b589efe5d52790667ac483dde9543953c6392d5eb8afdafa205d325e314f810e9c7722cbf5bb76fd6502733149bf21c60717ff5bc366b85ee9f206bb1f330ea72f61a9766090eabde747b1eb9c046cc8713d5a4f8d4b7dcd7c61f2496c5b467608cd9260382b8f11b04c318a5ebb6411a4c7fa060e08c295c6062ac644bd3d10bcbfcfe2e3748eba66f65d904ff21147faa8475f508f21238d42f62b697249b9fceb905127f7684c8130cb8663f09cd25ea038078e1980237389337d1446c3a77bce41b37b50b9c3a020526e7b7b3bef370cd7af71b225700627060eb65693899d277ed130ec5ed9eee75d4886f31aa93bbf302e0c69c9c4499396b43dceb67c02fafaff8b56698308393a03f60babde883f00de2c66831f024fafaf98b2fcf37a9ce01d4f34e95c9408395716dcf83fe86c7a0f5e3e6741c3b63b6ebe9964f1d5005eeb732ce66402007beb3e6a087053",
+ },
+ {
+ "9100c5b2d7c5d5a854bce55e82f94b89a268da7b66357a661dcf75cba10a1b320ae0e4e1a5b989f9766e57f867a3810a0b5b857191ffd7aece4c796f5694a2617486421940cc12b63a6aaea20d2fac188b318a1c3061cafeae436e04d710654b96a864d674768caee03a50ed6afc06f52d90115df1db5c9f1ecaa4f5da094070b1a447251ad3d4fb0e24e87821ee6d4e7e7eac7059080f77d2b36cacbdac1c6e5063946a376865458c4ebdad3c2afcbba8a82b01b03a7882eee42eab904a19e0aead4ae515b02aa2fee74f3a114bf5b9f320baa35b3225491653f4a69e0d864cbbd031d0805b727e42c2b9530dae0c01cfc6a42af8ca730e1d67b4bb743a072f0a38008b937209d534c2284271344340fae76af2b1dd00cf44b48ab8ee92e8f9cae8845e5a8d338f505cd1c19014018bfb6b7dad487e7c8c32064421982c1a63149ec16f2bf4fe7b50cf3ce1e33d6cdea8e98bf067077c9a0ec1bba6edd5090273ca719ebf6f1a0f3e56f021945cff3c468b2dad92a947a06a024758d7505a4a1bcbe9da3a03e97859da99ed36982a7c23572ab60071566b749dc34bee1d9609e87fe32282cc9adba633c9ddcbf359ef4a83a54af5fbb5699978b487954a907dc9739f4b3f3927e66cf0c338e31c272da0cc7795c72dfe60a5b2e73bfd77b8c6ea58122a913910fe29d3360cef5d398f29b024f0dd225183d538bed2b076989aceaac460e3d45e0ca7941897f151261a024b0adf6d5b62429420144497adde6557a3c53b7723471fb760b6a8b1dcc2b327cd939528f5d7bc16ec00ad99df12f082d82bf9fb7318b3d3ce5b84ab1e38d2ebcb6713c03fd0d62bd083c4af96b4316ee02b6953431c261278aabd96e28f81adf7946e3664446135c825e45ed916ccb941350c84523296cadd5360bfe3e16dda75db10da1f710fe796f3456f0911294a4735cf9968656345b9c3049ca47176194c86f36cf702538df699fcffaa254af15b198ac37eed0837b00cd3547e496ecacf6136c6648a535a235059cd75a3bfd0bc49933b379b72e7a8463c268faaf05f0b27256fb179c9d4c923a13ec6600f83aaa2bee13e30c8e676040c06aefc65ba238a29d403f3a8cc164a0bdcaa1a5f54bc1d35fa4efee0c402eccab1e92f6b0cba94e1bd87898a9dd3957a7eafd9d26bf70866450646090833d4b91c032428bdb9097b409305de669a58e44931b7b428bf1a6dc56177cd944b87b04eabd80c64e287a5758c83db26dbc06f0c772335363ea2fb9f19c833644fe3b3fbbbbf5f9d460412d287eef862ae676f258aa45bc8465667601e9ac46e7d77693936c8d67ccde94e54d746b785ad26aa38ca0500105b6870790235e780ac50b9e3198f5fe678ae3a4ff4f1d4a2177edae183daf2de42625845973fc544907e27a90d868f8634c9d529bbaacbd228a5b4ac7fa68ac208e207a022cce4b24a0b5b5791eaddc6b3b3ef6e5dba41855ff531de9bbca0a39ea743c0732772bd32cd15c4b7f28a6ba579d902331a88920fb970aa75114e14b891d42cb947e9eb14feafccf1393796b21099e52b21773adae8e550f93364b1c438dd7d7fc76994c51860b652974d04a7e6ead207610de149f231422595f4e9ced1674d98d0e15ee841143ad8613f804729524e8a5f30d451611676f70a60c5dcc7127497f4d27f35e7ba0e48f98e9022e0deac400e809170970867a1682c7d2f3ef2c632c44568abff76f4f804841ae462c7247147b6e1debe48802674fd55b2ef1be5b4604d5f60c35358c7d773ab3a3ad0ab81868c6044d4e06a48ddbffacddadf813a2ce09aef34f3b60b666245a032f021b87c81fc506166983f25930cff728d399f6dd48ea1c745ad2da7f2cdd9e3ee915f708db0d1f3481018db1c174ea950ed17247bb8ebc065186758e5403bd4d19a445e4a15519326696e4280bcecd1a903f525bbe1e521f94d79df8db4b35f4ef7bd990c0f2c32789a75f95761ca0064bf251fa00b409a58b979e56d2c44bc2302552f118162891bd78272384c739c0c98bbaca3fc46fbb5bfe123eb25df0e27343e38b5a0c2d0774443af91b64b9d4e0649f20290edb84fcedb3bf4ba491bee8754a32716739e5ab64deb6c9888bb9fd2ada1629a59b16934ec5dee3678dcbdcc7fe5e2f3833da9d1281669b1d108837eaae5180396813883de26b957037623825b0675df431fb06b35191c06229f84cc849ccf1b1e079efc2e575331cd77b3297d2908c048b82b7dd14883f3e707bf6ca38f87c19625bec47c11f54988a97205d27ac51a32f19704391af72021b78cc4461386dc3844a1b45596fede3f70e311eba92b1d9ac221d3dc19f3fdd080c2169348f2cc8c9380e12a7ebf69efa37bda4ca6f7e66919b94532ac43022c0518c04d0a8cd99e0cbac88b7a317a1dac5469534b4fbc64080196b44498e149b0a196bb2d6f59392a21c4a4523ec1ff922a52de790e42810fd9355471169d22b734dde4a3361ecd57e271a92132a8b35cfa91d508d45618ad8c6c1ea209405a3d1d3ee1535caeaa3f20546052fc13aff7a584ff79db1726678344098d8563caa2a2abf6fe5aa03d7af49dccf1b17be85600e7cfdbfff54282394b0fbeafda615185574fdff78d59ec2a26dddba1c531a1ac007cabf5be2e2f0a3dedb9174e0a9da5597c9de6d68911fc66ec9d2b1e3fd71ebb83147ab14384ee303d067f47a324a01fc187f54a98f1b0848fdba2ceb3c18936d503e71887d548c4dbc70b7eecac9ead3393f8cb85a84f1484f2e237b36b6d886f54a0f629e8bb05b0c6839c722149a5b541703aeac04e6eb230a5659b12ed0a668d018f75bc94258218c1f5390b9aee4c0b2836cb76a47da649e2425bcf4cc15c4d51d109e5f78cfdb88137c31b2510264e46f1c4eb6e6b3450ad901ff9517b47a24d508844dc85fc5dbcc079e2d09f301691f401ff5f36500cc66f0617eb4dba389d427c7ac778d78438506608f0961f818a2080ea56d0f61c40fc342b49ee63e730df61f757387b9089e1987977b7fa02d87aec2e4be24b8bdf7fb6286d190f9df870944fa910df32f178ab692fa56b071f57366a3981f51800ab416dc4500abcc19e0c6aaeeb9ca063470993ec749a0bcbd07604516b1d51175ebedbaec8986f67a4d9158f75b5f3bcbe86a83220b4fdf12a0242951f94ac7d52882b1b209b82c4749753ea4d46a60bcc4f3eed033bde2d3d20c25cb46fd907f7052217a0a4db143b2efe8875a59441f4d22ef70d0c244b2de6a7e15581e84c860a6326ae3e3aea6d3972e2de0623d2d852c9e65eed318bd3d86d29595575df60d9050e1740f884796b6657718a294adcf2303adf61c6b23933db93885172e82a78f741b8efc6315a2c88ccb6b11692a346cd82a79334e0c610734e61e6378b5e2ecc161d924778bfcf4475805a0823a0d5a54768d9272ee99b7c4a81b3d5dfe1a2f5ff34",
+ "3c77f30bbb698b1571aeb54653fcae2c23dc16be58603f0c361eedd813ec0c4f63005a1e69e533da93e820e6e4ce1308aa29c60289060ebf24fc9738e8a4874ca4e26a0dc79ee75b8607416bd554737f",
+ "0223c0a6052bb3cdc99a284fa169ba76be2df53b677642a606090a9267a60769",
+ "7d3981073f90c6648c5e9c74",
+ "61ec5230306b70113f67b340575b77ef76d521ff75b754d551e4177591a02351ad382b2a4067f2b3af7e8e15431c7133e98be9d8293d17ef40161dbad9a4f1a4f30cdd557bb9a8b03b5f1b277c850e23ecfa0fc2ab1102e4b1d5e836a606883c3d43527fc3aa26955964b144a9a56cafa7b174d72a0635b80e7b4f871ead3838a955a14c4b8c5c3c66fd86a5e4ff10dfaa92105378bbc5f76ad29727e5bc4779ba3e6dc19bf45020f6ce4dfb3400df05cac51577d58eec21b22839b8f055226b204e641783bb3305b4461172f1c1d48eec56fe6f82aae564ac6688d7b0994747d9b23a24418e69f8a4fc548f854f86baacbdec78b7597b138c453349034c8cad2ff272781e0e6799ef2f8addaf18528736aef21ef8c2d213161e36b2c7815fcfc40747626e0165684e46a9a2275c533d548e52a9952a556168195d602ead86f6bd699e97ca59f4cb2050ff148f5bdfec358dc4542ff2f700db9861dfe5ba377ec7fdc0fcb2501e72fe6873c7cc76b95b4f300857f76e6e6e370119f403b556115b19fee7009f4f6675ad2d174f44002e35ddc360f309f20a3a1dbf39d90d7e5fa2106c53afb0bf445e4cede59cb50b8a7a2c0961d00b2c251f2d815309f74a46a424838ee87f1229273ff3b66dfb79e3b1ce11bd60e061e60e3f37bd7ac896b618cd78388590f44b1a276b965a4b95f2e3a7a175b30fb45dc7a71d4b3a1a33e98af30dbb46a217c50046ac21b8bbe9537c02f05a5780c8a5d796bd6424fd9e9f3ed5932069bc050bf4a1898a0ef0ca756aa2e2269b709cc92e0c5192ab49d692143388ede2bde4923c85eae8f59db5c7711dabeb33743c692be6dfebd815456958b5e1384a109f891f433e7b4a1031d4f30478b05766dd97eb964a28f2f7b55aa6c27c7f4ebf4d47ee8709bf99915426b3896412a855798e392e111789213af537cff7a976b4509e0eb6ffbb8e886a3596a242d16d95109b0ff562c624e06636a3611f804f9b2e252afe8a4e5e868b48e9e734f688f2da2012d7fdfe2d3aca75fd74730a85aae90353417fd52b92d28a5098b6af358a096b859859916bcd5a8f779676c6e04ea461fe62872050af92d08cdf1124bde1e889ace3c923457ecfe0a635ec757907a131ad7c2ca3f60e1317880f843c5e63f4ba59ab2882a492dd1e070b070af6f60e18cca29541206a7b267c3f75a5327fd9b8ffc9b36b57b73b36e586541d15c85253e17a2581e8f8a1518f275cc79afcf2b5c88a16e9bf553e757df089b5db90a9dcdc1867b788fe75abb5161dd7ee1cf37d3f0faa793ddb1bbf1eca13f4220ea63af8ef7c0e7144d999ba1c5a983e74d48cef708c1d28d3c0a168ab87d0ef70f381693f0d438ce013ffa2cba65a8cf6b498a7120209564535b7372690329cdbd74eaa76765962720f06aae58338a10064ad80f5a67395db2c31d36b1f5eb777306395f192599d2f737327afdcd9f14b3f24155a3f974915d3302427494fad756703b13afcd1764ef9735e7dbff920f1253cb668e9f40632aea1e0b4620db162138e4a97e6f0729b14be4a7c3256250d5e7423ba1238c704503c51cfc9cb68db7001b2f597a15e77138beea02e11e0bb98a72f2a77b7260e9172fe7e60483114ddd836addd966b69570db5eb26a0cfc4f8a8b80d26357ed51a70165bc0dd11ad7467688025bdb532e7222ea12f23c44d08d111b0ad4acb2f5b3d6b45c387d541ffc84466ed57acacefb1436ef00bcb5b6211dfd0650113ac369b9f3e4891acb2693c377467b1e9c949cc0ea6c4a72ef9292964275ed397cd2b1ed25fe1aa8f47e90cde362392da5e53893eef6e4f61decae1a75e3b726f0596f09c3cba62aa08bea89984b484d5768296a5afa8b0759dceba530a169d22b81979212b3343db35ce4e4766dd251ea6a47f5033cc090d6577efbed441bb4f8944937e812f12ef17ede76df621bd4cfa31567ade18b74583a2b783279150d584ca13c0d4784b70156afdf9be8ae96666b82def888465cd3df349de427d5f5b3572e4f963d33f968e6780e381ca196bc04a6664fe93fdc8558b21b84130dfa2a646950eb2e927885925af46d7a28d1507bcc3c02ba98318bfebe5b9eea1bd47935ad869eb701cbc35a9aef5efad88ff54eb350a34ccef2e159de8e16135b81105bf799fbd86aa11653b5ef93a1ab1c367231d61b42b8bdb4f04d8d05396d53247d51890be9b56c51cb19eec0fd1e6b8cdc98376b6c6b30963ac7ab02656ff94dec0e3a0eb3f3ffb8bebd99d5889df98e6c77093c370373dd5f17871fb334c7eb12c6ca22deb75bdac9eaf24281c965dffe03da9c940e13fb382fb6be332797813710a7cd2e7720f5b9e53fc0d98fcceeea4a8e9f787e670d60bfc4a849f34571e5d09b9e9c28cdf2b2d888eca9bb31ea8b9239bd19dca86880ad3e12b1583acc3a6d1f0a438ce3b5a337487279dc4ead1b214272d455e6a2c8cce4ae3bb29abfdbe77a67ababeaff5dd9c96b17f589cd4615c0209eba5e4b1c7167b4b739ca4b9957185961529d1082226f85068890c94aa1f1c244259ef7b120e40114926a49c4412b67b4caef1ff3ce6f3aea3c6107b830cd34df9f4d73d7d978b6b9d5c481e9d76e83d649e742b098334838fe50d80975fb567642d3b72c461ef3072ebb1d03c0099e97575bae6a12cd2352d9d296351df6965d736d7568c2911394a73d199743526ba54dd62c56c598f4e78495c0172739274c0b8c96755e489765723a24a8704093a94544f6c8764dcd1ce6b4bf2917cfad27d85e4442b4e5bd577ea1a88c2b79d61cc1be01ee9028235b36444483b4e45da1087bf6d45ca540620de5aacc644a0d5c4b807b582c7b058e140eebca539947502bf73c9abc81a0e3a618b39d3a38c4ff7f94767fd7e6b9eb61e629806bc3d183bdade7e369d180dd2f57fef677e22ce41be7224f11723a85a3f1d14d7b72dc98ccb2816b77e625ce3db3e2c5753af8b079e0d63939079a01910ee4699cb405d4d9c60e4ac86a7fda3a4c9c290662afbdb7678c3a84c87ff83470fa8a416511a06d3216a1445699d7ad7e6980491fd596d39762d576b08fcbf0825243c1fc01ec8300780857c429c607113160a8354f6699b368a87983464472a5754fd58943fca6f6779764fbe6cbb510d5280292df02c4a7ed9acec8c95ad67ebcda71d0f519ac18db9b43b28244cd34fe02c5d694df57410eb54c5e1ca0f8501e7776a811d7ee81eb9d8c80b2ca50a012b5eecd5428af965b217e7fdac80be88a01f76d473105b027eb557a523f13c55e1670ff34627667649573e0f19dda41c525a8c96c2866a88bd73e66c786767e1657960f6676d8a22be1c6024158a0f0e4ec761148b5a3d8ea481d8fed94855be82479ba23213190054f937838f0e35e00aa74c89b294c29ea25ad7e96b4b6fa952ea8f1cbe5397b7c86d0b74ccc25e22c88736b045fe86110bffa0679f28a1f27162b51410498cb7",
+ },
+ {
+ "0fcff2c29cbb5cc40bfd2ec573ecf368275ade6a00e5730b77dab17e437b46524b3814e7f470acff6ddac4e0c6b748ed112657120bca1d83a4ce01e74a473995804d7c74bd28732a02370ac8ef52b600790d1284d82f077cfe096448509dddd0eb5944a882b7d384efdd4dde3003dea910f12de82035651e3ec9668e66435f519da3fa1f5bcda34aaaf028daf3068304f7b1ec18e65136241a9db281e011d27db5cc9c1099405a4430821e2488a228805314983966ce5d806b0f014c21d4c9d6a066e63aa6407ed6c29cfa4a3e22ca913762ca9d31271d9c371fe858f3b22e931814cdbe544b9416e88f6026b12bb8e88d8285beaaa35be1c24339b5f567480d7b16cbcf6160e549ef4570a0702889feaa0ebc54b11735735b6e2850d5715e5087291fe8890432784aa219bacaa2b874b075c9628cfed5e76dfe38426f9693f6bfb2de49b710c101b2dabb7c7c74f12de9ba8f75b8645d25629568d12bfbc7eaada63364b6f56569cf21e54c95d6797e9008f3496c506ecfe5d6a010d168fb7f0e2ee3c423492df36a133fffe9b87d7ac070c32cc131fba6089cb7d904b25812e03cd6048504f7ef1736ee00ee6b7aaedb3dda9c6fd6437772fa5076aca9888ce55e906a62875979bd477aabb2f4598d32342aa10a6d187c6768f213117a9ff6d830603bb7b9b475002e20b2237a4055ae6af6b8d70e343e76265188a0f07e7820dfb3d898684d99966d4bb9e78b0e95f5044dcc12810a89a75b11474c8fc06c6e734407db91a072ffeb2be6773a7c6c3ec939514b43daf29feb3aeb7afa57e96d9cf0492d90bb2c7be613f2208f5f5f5898b0a3db8a967a75d065efcabdd83759c88086583bb3d422c6c6425525a1adbd515199dbe71350b77940813618b88fe139153974c80d968ed4d9e3f97a91b7cce250a7c963f880dc38011250b9a131f2b76b677f78fd0e4cd6f1465182fd1d644dc42db0bcad8df4ae9f456841765af8e1c1775abf85a69577ece6f9e9035e36c88be784397479e713be4f5434aa4c166bc4702a4916c0c003a6baecaa182372a30af6dc7e6fc4912d13e662bd327829f6e85340fe130001babaee64d211d6761bcc52993c162a692a10cbe7434310392b64792a777a2b31341995072a6b7d4538cfde74e609dd1019a9f75cec0896186c0f42e3896d15be87aac5b11642f74e11d5c2f7de9f07f848ff543507ea4d73fa8f5683fc6b41831606352c482c7a5a013c51e0db59d824582c595f17a6d2113528943194d6b5aadcead62516507f178cd0f76729cf8b81fce4e0138ab224bfdbb8f16f8ea6196b90ef90a63f0fbdcbdfb5320984be8a80a26b932d1db7ecf870dd67fe838069136ff9b9ae087779e82cacf1b06a7b310ce6c439047c26fcec0364ea87e4549a544d540256cb7c3ef7282fa792aad89e919dd89519fe910501f5ef88da43232e917730e742ac2539d454e066feb9058f56dd246fdbb674dcab636585a788b338ffe41f4190447a65985acb9613d02669ad4ad888004c65acb0ca315752e58f51c9ae9259f20cbe8a668a207a5a46e30891bc909108f53db8bf6f0f11549e621d4cf4763e0035c867bfe9e1192fc421c080b25289a78f4167fe517852efdb6f3ccfe67ad01b4337da2c18f35bdc151c5dc76ee66efd27d5fc784e4e6829bea4f8a41ec8bf61ff998d178ce9f4a10551687337d7705eac6cd7fabb3f2379e31c1d01e4dc63e475f0fb01d9efa3de400b5177e2c2d68f2ead89e9ecad62cfc97fd0ad5b3391d0248dd2fd7c75dcbd802d3463ef0af21eb77b07a3286a72f1e9439f457630159abde7983a5c74f7dda12b40913632afedadb691d62003c70a46664fbd976457544cef8ea863858505b1c596e7f745d4a5fb657b1c694226afa9756c40d9c49425b323ce17a8531c5919b24010f715b5f27a300ee37334931ca9ff5c83c3f0a87713768ebccaaa15e35c56f3536ba945e5d954c94c885c68325bc4b51fb55d96c8d424849ece9a812af0747d5b1dc240f71609439f65acd1c17086e025e376eeb79a7255680cd692fc4b0f5768d1985fe8a1a387074f58c8bfdea8e5c11ed379b845ce2052a5b24ef0c1a658923eb87adf5b01e6aa59ae6937564ef97421722c67404cb9e5fe07d5bfad2e52ebe6cccb41ceb1eb2760545fb6a3582bc4ca572b0aa4e4f0a2ecc56299f3b485d980501a4e010576615ad518fd2d43c1f79aed013ed1f1e1bdb74357aaf7dc84772c9ec62da43c8ffe11a7fb3eeabc3584a936c37b28a438dfe78f89de6b0d5597ac1bc55057544e68fb49a6e505db69af122c2a3ad06219b7f2a2955db0ebf55c06baac5e0efac609436dee484857f75a8421945484ad0c7650a1d3008cc85c938208f19002b7994524878d6ddf85c763a65cb72a09c3a059657459f13cb584bfbd754fbf2de904517092be4f1786b2bde26ae8eb2d884592fc9e84395408f8117e47d1ab30d5fca167bbf07e41a33c230d240e3aac53cda9f251e24659da57d721288252fe7ff3653ae3e47b86209e9344accef0009b99f2ec7b3845558f1d77b89fc9b61ebc1b589fffd3261f71b9631e87541e22ed100e694854bed771358f10fe452fba61875a605b8080cc39e3eac13708e32518f28e60464c38b782c7c7800df63b6e7e95ced9154ea54e32900f6998f38eb1e51c112b6949e2eb11a96b1ea0a68c1e3b5af750a99c9fdb2cae44c5a1d37686ef87b158d19343e23daf00dd558cfb91e6f2e18f8e806abb2faf80d082f657717d08ca4e9c0d30d9bc30b612bcb1a3a3a3843231059dec344c6c04ce625b3fe064092e00175fd9d38f8fe54c4088efe30d211412be01460a6d4ad8d0a618b00a21de0a383de30ccd72f119b27a08958729a999e8aadff21829cbe8cfe398d90476e33db4c64981383a9aeab4a27f3bcb29d4b3d3b3a6ebdd71d3ac546b8658e269959630de176819b153cd53d2091efbddd2cf9178ba6ee98e1a3df9a095db0a2b713a0988a22239f5f08cc8f9abc3d67d9267f54dd5dedbf01bd490b0b09adb21d4e5aa7707e36cf77034f01bf8c7988a2e8dd7046bb2f486878436371f1258f3f7026afee6d7f6560be67103ad098edc9665e00118d4879f58bdd677cf2e6bc631d5c517acbb6db8a1debb4fe7492b7daf0b7ec7df056637c23caf926a1a589bef1db29cd81f547afd0fc9e459f46108ffdfcfdee43515a771c439dbde9177ceaf296a8749be0146cdca2b26be8c2ebd6cfd9b5032b1f7a375307f54c2f622711f8cf8684afaaf17c4da3e83666c40d26adc239c8d1a40024bbf560db5787ed404763d4e70ec6635c6a4b82c10f8ff7ad42217613c57648716ba94cb33129f3789dc86f9c8ec2e8e90e6bba0dfba1bb3dc3215188979a09f33346a6647099ed0e624c9ae10f83da0def840bdb25b718e8d86a616ff46b5327b1f99c22937920f5b5bbd6b53fa0b32f24befa4a7603234e6d94be51f00189a20b15c49e8ee58434a15ae9d10b9cf0204bfa7ab1fd9e006b22bebd22b036c4bb4c9949cb7ecdf01028d9f12466e144b2dbbf64d95d65347013e192d428678f64f0d9306f97208fb00a70d4615229143dd8890725ee3ba6021d38d6359055aa812edaf",
+ "0c5fb7075f5e15a6733737b614bf46871e29417e4b140bae6e10081623f5c52f557c36b4da4b5a4e82920497514b1e6f745fedbf73f86ee10976f82c6cbd5bc13a917514ddd062",
+ "e70954c812cac03e367e99f7b82a6dcc073d2f679f965d524872756ee58654cc",
+ "5f6267f6b3b21423267310e6",
+ "c53868c0fdc14e891ae1bc257fbb13be210a5d9cdbd9d18fe1b474f9a1929dbba3f25222d8fe8c1be3eef22352100064b922fd9642ad128a202b6382ae0a67c8affb0c5bfa1a80e55c1084cc372485243df872d677a80a3ef1ca3589908bca621f6f50133eb762cb9c05775d13db7dd3eb65ffd3eef96e8dd42928facc68390f6bbc50b17e1ef5ea6310d8756dd177be2cceb63a97bcceaa046794915589ca022d90756b02c22e8634c0ed44192abc3b8b1e2814c855ab27aaae3bdd801a73e6209fdd559ceb59a94fd98a66d12a31a643ca2f4b07ed910bc390f77ab89395d5cd1d783d8940dad4447f0452991b209cfcd998b0c814cebd08f9ff15052818bab0bf51c3b72ac1020d3b0974fbdf4ff941b1ab9c01f284fe82f2fd89c0aeb4b9fbb0a74ece08b3debc7b65e7263e2922fd4aba15ae3cba7885d04127c8e06a67f244e7aa4556f8694a5db6653f6e48d6de54f9e4024d25d3236d4f933205b6a358aa1506f832ef7d556c6a1bfe4aabfce51f3b5ac64bf6ab1e665bddb12fe13db9f07a55db3da3886df36ddb89f3a4939b1e9e5b701301570e3d01c0b947f498dcc6af438cc15e6038cb78a78986da0316cab67bca3e28c95e6b7e6b36cae9202cf4a77a0e15d3c3291d267aeee172dd587a944719b9fbe077603b4d39d4302b9a6415aa07af309a5e1cf7a9379552becdb4bc6a0b5c85d2e63bb141c405afc58a8b2b4188b3883a24eedf98dd50fc54725c440ccdb03514a6f37cab49296b6826b6bc7d7ad8cac0a3425eeb6866d94119acdad468cefe162a29e8831c77aa83321e8ae3e20e968cfe51dbf2b63f4e26c61536e6be4f63d61bbd06af38023b15f4fccb8ae0356d924dbf646bff69d1ac0d6e1c7f40b12d6d16e52d1c15958add5708bd38c514e47fe623a67c9ec211cd625b398fa7fd67a23e6e9f65d42dda2bae94524372fbc1a7e0ab3f1c451c126135536e73c573749aa60177dfb68843752b010e2cb9c1afaf51c94a48cf8ac7aab3fb200aaebcedefc6cccb581848da0121af92d9f4be002f0c2beffdfa65c36bec80e7f62d7009b1eb719d24b96e97059e6b50a52662c2c833738849f342391514349305228b29bfa9c7cf2a931558ca8e704c600148a28bd871465b23af499c11784aa45acd051f276d82789c58b14f12619372be4bc3a285f6cee21d65648d18e61752d6e7957736d3385f8ad36702c451c61ed475997d6d9f11c8be5257d8febce329aa701028aa2b5644b8515a95b5e866780e32754ac2e6f2e31b2c04a4ad35cbcbc25b23e9bf49cb1a5d877ca30880741757c29303af8676546760016f1538991b37cf0cd24ad3b1d877e5e1bd083e4b990af6ff5c0b28e530db3f463d21e76c928c8e1ffaa6c045937ea171a9071827a173e231f50e95430ae4895932c88ce048058ce6d0a50ca5c1842506158e98bb2912a61c7991a2256c97cb9050a4bb3ca32594622756291340561e9e584dd2e096263b6ff8eb898ae86f5f24500320d2d0ebb30d84cb4ef876a877dad23a611b39bf0cba5e22f2850e11c298fa23fed40691b83acc87136f8fa540b1dc40d1b0d0bd489ee9dad785c121955a094a2c6bd3353e142c04f7b88b2eb3305fd00d5eddb391b73fa2b16a6357aaa2abf2059ec979bd3ce06d5fff1c325bbe5c833a101615750613047d8155ac0c3a0734cc6aaeae7cb65d7501cb95f9d6d1161d09c961c0681547faf7983ed2efaf4e0fbb87a06169ecff1d0ee540a9223a73f75584441d4669cac09c2dbdb8aa2aed74eb9a2870f2021eb16e5f5c3e79a24d7110af4bece22a1086d27642550cadfa4f0e03f2c032a2745e1c9277a4f67fa4dc74ba056110fed3a63f643567d079c9430b8d5b3bf57a9b3f02d486d870229fee5462043b6bda8d265c745ddc1b8952bf91828d6db2edcfca7051e74df9dd456dca5e04ba469b9ff6a8130aab3903c05659b8f31cf4ba4c22511493a36541ff9d88c708dfb714d52a3c0356543e6efad37530b598bb63c3724772907abe4cad39c896c62daf5b30cd7d37eb36a7be2494353028c76e8d148b018c7bb755c45d2a33f61944071bae8316881e9aa37e4ec2374aac4f8436ed3c7db2092326538f07fc6644e0239899e3335f73c1e3c4602b12d19d7b639d4968974b6b2703ec1add8cd930cbafff4158f68f06aaac83bb4a2e31466e2ddc247ad71c5f4c49af7defd1394e21819cc24c78380caefb2ce87c0d1050680313037def12ca21cf67bb6692d6e4a9e90a9c9a0b7118ac300c6c6f636337aa25bc59cf1d9749dc183803cc0ccd1ff53210352795c6edb49ff1e5e8ebaee7b3eda6e3c0c340fa60594115e37fab60133b8a3b39d2e63db0bc6a03973e236fca801553912f93feafd8b96766049dd2066f3c5ac9222121ee9d36cbcd8f713adc8779949941f8a8dcc92ade62e46e9f1b292d5f7eced14c3bff50a811cb762ced1f103652773ef946e18569eb5892626627e085d4ffb3102c1586ddf88acbaeed903b22d3e7ccd8b8ddcdfddb872403240bc8e0e46a068f55bbddaf90fffb9a914187aac2ceedf21fefa1fe32fc7bdbb9fd76dcda1fca7b39107d308d11a118e47499dc4092ef0cd28d0d9af84440f095b4feb7adcba198894cd89a324c60ed0b996c520d4b33391bbbef1997256af7ba7ec1069244359066af81543ca23105742fee3480f890373d3205236bed566cd22a62bf69f8c0f27b714f84a203bca1605865e2cc2f9211389e0df7a4b3aab9d10826639357efe1f5fe64a1bd6d06d0b5605658c4d2d12e1bec77e70ea393b0a09043dd7d6684bd53f4c883f2f6928d99ba91873d063d43600f9105d503b11d8dc2b05e34b4fcf18e78b2b6c97d3b2c9249a2f6566ddab2a8a67fed6c9f8af2f4ef98dd579f2d4fb572e178489c503df5d5f03bee9920db347a6e734ed72ec7233387f1579c13725599a33a90915ddf03725dce20fd3806abc1029a20732380596057830ed63b6edcaa4d4418871bbfd58de1d1f2800588ed207f2016e11abd1baf1895f6096e2c75cc5916836a9ddc09cab4c28e53fadbd7d3080088131cc270095315b61011b0cea5b4d64b647bbcea54d20be1eec0992c72fc9c9771cae19191cf6a6f1840acec1deff605626d0a0d79ea8fe0af63ea75e80f8141fa8d7ca6f4c99dc7e78aeacc67762ed0134f1a0b053debfb9ccb145800b9818c2deb46f7124e8655f37c3291af107ed75384afcedb44518ca14cdea341c9657ec638531011cb957ed6b3434b736ae8c8199684cc58862638c5f6c07e1cbe8ae68c5582b1697ca9dbdd01e97023138a9173d6b1294cd99514a28102e6912b1c87ef22cdc611133bcc111e95c355a26b20a3d6f0ead66e932c5e1229b0fc17a7d6f78134c69beb362ca75017b1bf1105ac8970fad48acb8313cb3ff10e9d72c4ff11f95c2dab59575525c98653a9c7d31585a3742267c062d6ffc7a4303a3e81a45bf39e1ce2097623bba70f216aa612c64ba06ed6d596ad6abbdde69d56ab45e25ebcd4e485824449550232be26f987c14008f67c9db9d0f709f567fa44502b9e0839457e5f0aadec0395bf5c38ed8de7529708e58c0a895198fc8b2570fb6e68547630ca7f313526d392ac4776be973205f971854c300454d5",
+ },
+ {
+ "95a17355dfa9d378a18ba20e58aa4b8711ea1d6e3c65e0b2d3c6382892c7d02768437d47ed50bf8edc619c340be7bb1cd1d88b0d3d6bbf1031f738c4be09eb264c686d39b92cc7958e63c9994a84b61b5c412999ace8a9dee0e2a29eeb8dc537f63271af5f3844ed9c0d86e6913c02ed7d2b862a132f08f311aa92fc3757342d89a5dce8dd20d5792d5c60be9862ab168d3140a061489472f2266f297da357064833ef2554c49f8120ff40b961ebcfee1d0f8e7e5722f049485f72c502c9cc4afdbb70517f0fd2a00e12596ffe285d1b37eb998e0e89d756e9491ceb13e83610a3a66122b533c2c3461b3244438f5f7a7af8088881dfdf6a29fb563ce38c4c8632ada8e7e06baa2686dc6aca6bc944e5c14d6e432c4dad554803912b8fddb1c18a59a86bc452914b2efc1599c5597f87a6edcad33a7728827bbaad0a975ecc22b7748d7cc71ec7f51adc8fe0350e67dcfb31af35a8d7b72391642e29c2fa4b796ed8f535f6bc2b1198baf1cec858aac38959f83130af55c21383ebd57d364eeb0e442104004c1599060667ce5e1191e76a89199a386e5c4bf147206e7d6e598bb27a90b3c6a54cccacb39a0ac42bf22eb40bc8ec7925376a6c57d8eac6317578ac052b72ab773f572ad961ee05531cb95ee5a6d70add4176351960fb4bd673f7db9f698616a8dd41823f2f87924c40f131e6c83bc40ab1f92312f46ee86765c306cf4a1d77275ef9668d80f9d9c1ea0aa7b2456bbcf764e009584ef1c0b4b4c683fee3fa2641f48ccf7485a8356fb3dd22f848deefadbef8050de9c5c19e8c449c6f3ec2b1324f80a7d428dc44dbb966d40244c3af03bcb410a57ad1430615e07553a22686f1a62dc6cf090aaac3707ec5b44274b7fe28c7a3a298e7a8adc71e016944875bebb421babd2b64809be3454f25b90723e2cec68467ad2d14744b15de8f9c397a505a340e85998e207cd46fa18d76c46f458af4ac3821c0ac6cd68afb72c376c31daad1a2435fc2bf333260c1a82430edaf2499e7455a93b1301eada2e12365ffcd36a1119664d0c996318a3e55bb2c04dfc5eb251f7fd64f9d83f27ea6577d748e1f85248355ed19867857dc3383e01249cc37684b0eb8e891aa663801e4ac8f0331b38686a19f0d19f6e94c7ac95ec395962be0a4e3c8358d2f6d8f13191e164ad29cd1733bde8c31c7d8ab90366e26cc9a06707dcfa60bfe139a112db827778ac348fdfe26892fed61db7e9849a464e3aad561797b6c778e0688bbbeaf3349727b4670a2d0a08f317b0dc9c4b12ea85c0309d57e754d0c7bd5c83985fb82f776c968189908a8ca83b5944767c2efc3c5f898436de54fe8bb17224012a437896d9fa106a749d12aff657266276129ec5ac12fc7a77eb06296d2a2a876d931e479d3ea201cbb4b1b20bd81471eaa33786c624013e1f07577c2171f38f0511c6924078a40c2d55ce392dd2ab0885e29f4c06907a1597c181b933853838970edad7777ed394c491cde27478eafa5b7a36520aa0779261f94b957e83ce058298dcfa07b08ecc425caeb6c599a11103d7631e77daa0d9d3fc6f42703d57f2c624ecddd56b9a27b848de7dd28f8ed656f1e4decc95a8908217e2f2453ae50b5fc1d9352d735ce5bc2b538eaae25501d449d090df793151811443c64f28d19eeaaac4081e10edca4c4148e723ade8f7e7b988b732ba08b3ce4c8a0d655bac4ff66048148135decd7727a49ac59d82ad470b5479c55d3d8399b790ff033d3ef99d770e1eacecdc140480aeca1e2167553cbbdef2090c7592b40681b733b0a0d127beefd49bcbe8904c975a5ab8b1afe56d7ed7667b5cf92f537ad6972b876843364817c20400524097ac9b405e4b35bbba0d12355a0b54bd763b4491b2acd4e8e4fcaaf8fcfd398499d4c4e81ffa93ca07a5ff51a1540f178f43a931e07e1ad56ab5ce57a2f7dc3ccca114dc9ba8a6934e95f4efe9f3f76947909b280ea5fd795bbbc0feb3ad2b704e305cd9d8f37d178961f77355eedc9d7f77c58e1db2f7797eb8682255939293c3ef7dacd2eab46c4cbbdf929aac301a13f59831a88fab173803399d96dc216abb9f079e79bbfab667ca590266891c8a7ea4bc1724573e5c5a67e9f1341b5bffaa538e240f78da7733237999ac86141b2ac0324f17609b71c885630c90befc3b027a5f01e33979165ce2a00968c414838446c2aba76e1d7fe3707c742f68af21d30e23b637accc848f6c8df820a27bb4e94e5090ac6e008fde7cf3fdd5931fa891335ec8d01b5d6f77db57a87dc35d6701adf7ae0bf82dda6511c83ab4d7d3460b221eeb3d6c4aa537924db5559b1c6739040534fc330f5144c78bf99f5f4faa715e85aebac043e2529197a82ca40f65a8149a9447a9e58c61618600b0c5ab221420c0cee114a133a648dbc2eceb2894ffc329376d1eb3ce7039cf30ff6a53038b23c26c38739fdebc7b919956ca2e468d577dea6621a8d66b78075ad26a6e6d8e20c9b694698540d516ea2bd108625e5fd038b5f1e19c5d5993b82bfe16897c375322dbbca81c81cef6ad900f0ffe5ed02714c208a12f5234d78e32ee07af155ad1e1077a0d8938f426d8f326c751f6ee66c8f707e8493cbfc76f9ddf1ea329e094315a91ba9385e16c890823db0f0231c7f939a042665009d5edd8e48102c515341fa6eea33cc00fb5d82380d735b29f2eec3f61428f7b186d43fcee46b2037ad1aa6974d729848cf1a80dc8ddb0580c9c876def06d8f7642cf45263a655ee77f047fcd76171546319622bf71283f3bf0b519e123a85765779c8bb201e99981ed184e642f63aa61f9cc206bf45fa6e514bfc637671d9cdfba2891bb112a3cff438a6372ee0dd3e7d9f352ce52f8b367b7799e1f963bfe50638f0c74b94873fcd3d66fc1e342a8bd36fb8b88f33eefabb78eca4dc9c89e2c57aaa010f2140dc5ea7c86cebe2f8bf42a167d1d546cc80bfa9258c35af6efb1a090c293a4cf588e4bdf5c090ee7fe38fd7b5551e71e5ce2b0b5a50bab95bc4c257edfc94d37579816b4a2249ba05c991bb2ea02d047e480fc8a8ba71f48f344c6d20d140a64ac20184e45b4eea14d0953370c237ef0a47a7a2f22997715dd3ee8ea52f24ffe12674d571b3bf968454ca051701e411499bc43bb55bbd033f9b81d4baa6c49bdd49614efd20d58175af868ca16a9deaf65216abbdc3beed5f30b209e786a5b4c006f3bd27d93e9d78b51a1a2fb7f5160a0bc1b7df70952ea1573888ddde3d9dd5314b0d0a899a733eb48d5e6c7274667e362e4da6b37c480aa4d0d8730e66483fb1453a3aefad69942ac7f09d3c571b6275590938c541336a121bdd20722550236a9a5e4a37c7de628fceffbc260b1e9b6417c4295907937b13609b8585ebb8f076073abdcf19104ed80ffafe1b09997f115d987a552be5689c70fe125ca702d2ae4d807d5690bc2e90b72cabb0b61ad203b34c68df21c16b92bf8def5680b204ce327214c32e4363d5600f96162a6819dda472acc6441858f396385a16fa5ee52cc0f9ffef3d53c49d535aa37db2cd4b573ff81d74006677969ec1ad891082b5d18ca5b0b9f975574ccffaca72b805c9f7fdd76bfe3dd384dc953255a5b50b7731a137fb9aad42e77d3da1eff5a7b9eda5814993cf2d289bb25ae1680ffcdf419e073d38b4701021adb2019359bb70ff4cca930be7bb979a0678f20665d14803d8753c8ce54cae92feb026486ba747a861daa449863bd38cb4d5831aa6db1e7f404b0c3587aac8765aeecec686066ee7d11321574f04d3f3da571e71222ce07277eca7ff97607",
+ "5e24f34a8d53b17bd0c2aee5369e3276dbd7e7c2ea0990f1300fbbb00831b76655aab1e2fd625ecd",
+ "c1d796f1e651a1ee825855d80206baff6818cc8c247ee6ce62b7531e6e9ac32f",
+ "240cb25aaae4d085bbb747a5",
+ "319e968ad291ea5d4a057c38f7afa4ddb9c9565962fa1a7b231e397a268ad8e0c5030a2df09dc4f99402ddf2e0d06e753bf55e1b318b3e5ff0108de2328d3b8d53e23e08bf7d84d59fededd60d47bbb52736b0491f82c616eb5f779c496abd6499555035e4513c8613e7204e6bff8d06dfecd9ce38c6b83efd8d0e41f84f7cfc9ae07113237987a4b2eaa87f7e0a310155e282e57858244e9071712fa026cb781e5a4bfe6fa1bc480e534096394459a3d1354e2d9a54aac6926a60b388410fd0b53f7a3a9116292f37406369c22ea674418c4deeead171e00f74f5cabae5d24a0686a4bcd8ba99aea613a23edd0a019a319daa3779c212fbdca9d772fc3fe612cf178c2aca2aeaf6bce2433494027a474eff699bba95fc7dcf79ca1d77b1e097439a9050a5cc78e0b78bf2e7f50f959ea2986a59be3880519cd84d0a673acb0432feb1945c603e70748445c74600ccfec60efcf9e4d02a7df5f967de4b473f63b0b0499ff4ba350ec1182f3a0ac17ef9ae28945fc9bc714c49909a7c1e2f311aa6ad7652e22e1f48bb51cf53814a2125152813752d86c7f9468a991d0ac84b1a2f3969b8081c228b7f5760718036e26a10e211ff04ea323acdaaddf9b06a08c92ed663d0fdf13fa601cda45c416c2d3803dd9b5ca29cba57e59cf4ad93176c65c64507b1995d638541c90b381ff758833a2ad67b0de44c280fdfd82b3c6d4353ae30b33768863cd3169a2032f26e37ddd57e7da1673cfc7375bf6e6792495a2b434155d684f2a6f2b919f944469d47be5aa7da74eed69d871e6f65c3ae08904a9ad042ba39905188f0b9158fd14094bd6a408fba6ef57566d69eccda86bb54cd3ca7381f51bffeaf8bcc1ae8df91d22c359888e21b70f640d6f3726a34e6100ee269124747f0ca05110f63deee07e3628bd6aacf926036ccec02c0b6bd7259db52ea8b7a686b36ba1d0296c85e43e25d72ce46c66a1e646301dafd2f4c502281e6f949011cea69459c026c65bd130d6ef06be17b23a9c9a84746e39d017b144135025ac527c1e653f233770cd68e9f232c3b623ceda836843b3e9ea313cc6a57d28ce71ccfb7265ce73b06bce1447220645e6f66caeb06b55129b97c8dd8db54c94d771504d24cedc86a8ec706a9f7dcbbcd7fc7cf38005b2913b1cfb77370bd23183ac7b5ca5135a2738cc91d05b2b22640469e3daeb6a7b0f14fc6652563663520f7754aba624a35e5d24529a6ee9f5ef0d019d83c04f5a93a38b68cbce0cecd42a11aae305475806326aebb4f673791f50c9f90894add51a0fd7c02807efd8c1bd21fa717a860e224bc9fa3f40975fd8d558e4844a09f8920256528450d77e546604e2ce2d38efadaf39a0ea3ea12156174aa8a20481e6c1190e448564675f9ca60bcef37cacec5aa218122e7bd25b571ff10f54979d62018b779a2a3d5d7d6cd56ae31efef2c844ba50ff9da88eba7a8e0d9fc5388a805ba4ad35eaa4798e395d2fe112083cce2f11cc850d25ca5c6e60a9996cee4789ca99d519daedb62f4fb1e535b742a35d71d7390117e93821ff18948a78c1fcdcb90a5f1211327d7ee0663ef16ff446e0e22d8cb7b2d3d05469b1c02864f4a87e2d9715f60c9e7be841e308d0a5f6c50161a4a0464aebafb88e0d2df8cefcead93c9623106d5518a9852f320235594be10c45bc0cf06c9daa007100ff97959357f9be8e49c870d0a11c884213e266c35e9131439fb3654fd5f1abd1e778ccb02b8c262753a22653a09272a0c33b6b2683c9045e8f967af756b98dc1797ff605c64ac5bda8252e9ebfe0e4d8d7ca754fcca5e3de3c4b63678da095281d76d60fa12ff4ca818825f346b9c4e426cee16db5818d78a527a901cd088bc2983f9b83430b50683018996996717a1738439680b68e3f61cbdcd0f0e1a6b436af8fa05d3ce2228054e319bad1dc6ac970c75313c552fc1136fabc302fcd1d09ef1b9138d18133a772cbd9cb197ff58c6e898f9e83e4e27206f3b15b6bf2778aaf9fb38e0d50152f8dbf5763816132a04b4b2e9639584b3dc8ea6d95ade024f9497944200ab0aeab206ef099859b9240aaa15f737c1e0fe6d015d04f47261ade4928e3c2ca21d1f5ab4a3f571f2ed92ebeeebf2493e6e39f0063ba931e165384ee1b5081f5f8d26ec24716757037f5158d35effbe67009080ad7b0381292a513f312eb28328cf5ff47a6599e36c14277c3eb5053c5aca530ff5954c21c03fb3fd5fc0facdac36dd819b0495fde421411e0440991da0cc4a20d294446115c0b79045037fbfacfeac574da3bf192fec4bf38c27cef71d03787430223b6069ba6d9273ec8679736a832277c657862ca791b559a5054ee8c7c07618083f75480c8aa01cb086c7317315911802e6cefb15bbe20494b14d97e3a885806db775c216dc15949e3b724f7cbb30bd2c46bd5a2fd6132352c2b21cc2b47891dd9794975f70a6fa7a0791ee761ccf4c263f27f64790826c1aa656c39483e029baef0855935e7e6c133a4035a3699925fbde131ca62948879373346af35bd7fa52b8d6c3338f213bbd9c79977c0d710028d1d386df614c5faf4a1f8fe5506a9af7059370893ff6d07d91383baba67a617b5d829e0e2eb20e541ed5c34be7ef0eaf6c6f6f52d7ca01933a2a4e8de46e422dc95161ba8ad354f6bc7c8e4cf8ab5e08607530147fcd7c9481afc621c5a3230a05e2c4db79db9e1e73f43556a8e8f0dff7ffe420282212f23d4c5f6f8d2febe129b9fe5ba7ddf27f72ae898a4eba270b5d2bb3b6b06e38c546ba80a9b2bc46097d0b47db5ae72485ef2c6419e856c33c2d66a861b9d474699e730eb8a8992e3ea9c1ed74316687d5d9fc611189eba2aa31af5ba8e81179866dc016bda977c59c595e40001c8ab3a4a44cec00ff84c6dbd9ad4be30bcc080e69b9398089d6ea464a70f536ace3b447693301c94850606d0de1299770b5f45e6d28f8ab83e3ffe52178522eb91fdaa9e4a696674ba0f52ee18e960b04415782f018d67479081b1bf9b4c9b90de026cbb66bf7d9d12cddccdd9b2c8ee2f010892571c6f0c0feac9555c71bf61f9cd69553cf7fc2be8d058e0c3430e134adb1ba28985fdc4f0cf71bd3cd09f5f82f303cded0de62f98404477bdd0a846c6c51e3e82ebf72f475afc8e6388aec57206018ba2528ede194345cc1ee95cb2023793f692f708aac3c9e8a682af36b078f5d6c7a3ed07475e9fe73b95d1eee048ab898edfee3fac4beda45f03eeb64b2128f6df9453ed77c6010e13c0270c068f704f49e62fb7410be90ffee47584ca2efc5287dae1f63bcc1819e7548eb9f0d8a3182f9ed00da3817255a2ff735876b75cd21cb25e86aa4b2893f9e5089dfac76194563f9a14335dd37ef06a501c89623caaf6feb4afb792092dfed515ba7518e278c341834a9dd17b50a0fc860b62ec621b69408cb3fbf7d4ab88a3e367fda84c82357376fa9b1161b739361c313b99dcbf4122f3870c8175093298cf432174217398928983ab6cea4759f18e7a21d71fe1b0f3cda05d241e12db0818b8763bd23d958d6e52981ce8d84cd6d82640d2000874a53c0bd14949ec99e48ce6c954ef0d08e6e319de5ebf7e142f25c0f50ff13f6acecde6a270c8d8de05ef4c310ce9e92f40f6f2b77d6e7aa3f056d4a20f7faa7cd0b93d82e3972343a50a26ff462caada10621bc953b73913944246d2a4da25fa52cc6ee1293c436ab9031ee2dc79cce39f139f44d473c236731257c6f65ca4d383e39cf8d33923afea3c80244021d36e0ed43230c44e7d1a1297d35464861f9149d869f26cc51879027169803e43c898d1b4a2a2480197500",
+ },
+ {
+ "2158abc2472e1b9c061da2c01d0ad9e996fd687cccca331fe8a2baacd12c06f284b1b5cbdfd067e5ed09a60a137ff4a97c5c26482659680ffb22bbcd4ec1bfd272749e52440537320fdd3c225c30ccd98cf221b34b89c247ab7d14f93ed3ccb0486a028c6f3abe7e17fba1742b6d4db85f6e6baaf82df1a3aa059de8d9699821d39bad42d56cc1ec67626092cfad4a2e1cb5d814e2cab78ccf5474a8bd0dc990a877d37de394694af6cadcc57727f393dccba7bf955f4b65b3c00d71cdd701754ed4f231685b7b5e2557239d7e16305be2d81a773765dcea25ea5bf2c15d670f3159409ab5bbf8da121c779132a8ec1480068cb76b68a19152fd83135aeb228b446225f91d1ed4303a4bc16cf3ad8173b30d2a1e75ccafc8c933db231efeae6260d45c7ef230ae2c7b6f986f1c19e2cf260ded9cd99d64a2d03fc5ee3d73509e47ac1c39dcca655839fec75517a9243eb611da8fae3e317e7df66cbb6abd59b16975eb463f509e784e65cd660ef1a4c5027e54b1bc862f397c9cf4e6594d98c2c2830801d3a679220b46881a372cdf3aaa33eb66b91a9f36b6941c0fe1b4d2a437daa50b811f2d8c65b5a69de185d78bb9c2f172dc90a89324c5a2067974aab14f4fbcd06ee95cd49e03717f88480a410afbb4e68b5c79b0211cb69b90604cdfaf08af1ef10cf28f0f630e97ab18d9b5138d9b9ee9154e0b3104a6c164f2a114fa5032eb5c247a6b87880332a0dce7b36982515297a05dc8a4038a09f52b1def7b4fdad8735443fadc462c7c22132f8b9581de2d213bf5c53f7fce34aaeb24263afefead5341a72f88d3acaae6db367c5c14a97d4f9e438e1e11c3c8fde7ee37e5ece5382e8c68b660146046ef96c24caa6bc9fa0a0c88281e4bf01b32df5218cb3750f9c4b8af24cc106abca62d085198d14ba2ded3cafc1fbb17519a696965a1ba5f65720e893f1ef3fbc5200316b9d4615bb23426ae53e1c5a57b2f0ee0d0c83f353b4ebe7a6cb17531d278478b4ca8e6ffdd0cad30ed73d568a2e44972ac88a7e7d665614316d674e84ebc739b645a9a4166477254ba47bc5c2b05ced88e75bf64da21a7f1f71cd946d84de13ca77b7e0dc2f0617d371ed96323a83bb11dfa16f81bbde913d9c259b10f3aeeb6b56cc4775c25f49343cef667763118932c2e8b47ec745ac537b37746ed65fda2d1c11a2de60ec02adcb79152e8a9e614d8715cc4e6b6891d6a0063576560fa3621146308222432ffdbc351c36c37d844a934088fea92ac54920facf870a62e91ba9299dcb6cbdb918e2d54fb642c3f0d60489c4bda489f6c584b64c8f19359ab25f388dbbe636c4d90c048f5ed87024dcf9f98a9e738163f837a07750d61203254a80d120c795f9c3aa791272f9474fe330da81a45be5ac838613d46c25e781606862912ff88af393040605fd4d55d07e2052227c37ceffcdd2d42a08bbab69140dfa4406853799893daf768af546f915a91b81d0da719ebd45b8b5f1641f15621959689e810217bea18e3996c532ac6e4e2e4f289fddd5e5968bd6fa9aec5ca435c532b6c74a7568c8aeff9dd19bfc2fba3b484a191e2faf9a069a24e2e6d928ac0bdf635644cc1ef3bbacc547a8e4f1d42d4bed3b6b8cc56216fa550dc37da9cf4d1d1591d9348594d14adc7a3fde5e5d1a3b9875c85de7df483cdd0baa86dae793e0796d14fef1f649de6079acbec6b6fa5f2cb2bd0481f5316f00dbe5dbc379bc3cd6d13bd8c775a727ef43e6a5fad1051783b22c05a75d64a8394a73fcb430299b015563c8cb0ae0aa4ec750399855411c076d21aeca8656f3d0cae084fb0a1ffc6f73b52a7ea5d4bd6d24e7057a3811719533105fc967439a32241f2d3e3f299da2deb821748cdee1a1c5e71bfdf88d833bade2f505268f375a9e6488cd8e16705cce91d15b60b2fd269a19148296a7be348aa349a12270fbc0d5748e538afeb0598081a4f1349217ceab3c4141d40f765ea2bfffd530fb9606601469fb131a44939be984c07bac8f26d8c068accfdefb729eeb47cfd6ddc646e22031f53a7698c6501d86cbba05e282d64b2f962a1b08b9064078dd1e3f14006f45f599bc8e600cabe6d855fcbae8c3060859202361d929a241f6c0711ac0d050b67a1d44da19e0b0e236adad1f60a327c9c34b2b9c64cdde5b8e4f664f2fc70599d44a63ee2b14d051c27d71231098ecd3d4086038d63e84547dfaa39db1a92785e38b640ea0345062a1c185b25a72862e7ae6574114eba592d6492087e2580dc5d361c473a614d647e66c0a30de806f4976b69a8b92301e68794ee05b96ee116a5fd5edf5eab43dc1103801eec861383f17c2bab9f2d9126c1802b7aee0c909309ee72679ab644abb9c4caa54add283b5954e6f881781e42f849bce6554c7a5e3becc5d5a209805ccd4a0117272a53807e3978ffb19641a9dffd9034490a9284f658599961daf52f24f6464c2099cc9ed3459d84dbde2ebbdbbeef25c882a9beda03573bdd4c6a0143b14d634a1a021d5f9fa23a7ed0f5598ee57e56672814412b6c7c08b8e709fb98575fe2716100d000a20a7e7200d800e556564c7e6a8da9d609b18ff0bb8a8812e96b834a6b534b0d5dc97f5da17f42f8d58e763f1b201625d1a5158c2f9e9e190921637474ae81d278002f197f7211540088931ca8a941794e56067ef4a497fdc6fa713aa9f20c21f23c3a71ae4cc5aed459ca7c020bf55162fbcf56a066546660c5a009b8ad2aaae9651c97b1e145853a10013d1bf68e7df25dd492c328f823ed982da54557502ebc6cc56d4d0bf2881bf3c536ea53b4dcb0886e73b066969dfec343441b9372d7ff38454c4337d45e2b999415ec48f19cd05f0f80c5a61ec369610784f47a5cf3b2a13ff5d8145303ade7189a300936006846812dec9ff15500f8daf47236e724d72619af3a6cb3e854cb8284d5b8843dfe056beaa45c40a4541a98c7507feb27a605d6e07189c8c5554a492a03ce6701d3d2ec782e2c1c8346b54a963435bdda3a93bbac1d837172cebb9cd18903d25cd6bed404eaf18730a6d1c6da0783b5411770ed34f35fa6c11a4292a34565ff1b23d4200ec5a73e6b7905458088fac19f6aafd35e0e791f28bbb2cb0117ca1c3a9e3c4863e487ce5d8c14dd140e9eb4794d87d75b01f683bca84ebdbf19dafab716421bfac9e95755fd346a0cd31e8520a55c7ca652ff63fb4e20ba67fab41e11f7390bc02363162097802c6a9eb18b430d07ea60064d5b546d15bb68cada79c113848136e797577f1783e9b53574f9427be3a28230fdd69d139205dd6c7e9e7f031fb6eab70d69ce905384c5c77d084360aac590a89b2dbb2d339899b13619b455cf9f0cdc08db6c5b5f3223dc3a663ce42bcc8cc6f947f42cdf8dde15a6926b753177513a52be95b1f0b88d2a1ec90e49959b108fe204bbc29199d7382c42ad5dbaff970cbd2dbeade54bd70415e54daa805d396361f525f38efc2bba3fd818f9d7af0594dcc341c20f18c624fe13ce7e7108e1d2fd06c58b03f04642c95e3ba00d4035ea0476ac138f72378d85050bf60dedc90af38e96f67fdc38483a73e847b41d31b894ddcb234f02b0d507bbcb15a8941f9c23b592a291cbeacb3ed213f2f044aa842275a7717757467f121294bba6b357c969e96bfab455c6f328d9e5181d909c3f0543b17d9af7fcac099067b043be79aca8e5a75c3a6d4f6246357a63c516a3ca595447f34b43a055d3070517c67ec36e636aca9ed71a001d4f7b81149124deeb7826dec3697e183d861d544c9c17baff82849d599e9e77ed19f801aa1ce095940674576ff270ac788d00c429187e299a03c6f3a1646a8f7d6290287e70bd1276316ae624da929c67936191abdfba45e2803884e5a3136205a38a841448968a7900709dda033a42969bd3417a8d865d0dbee1f261f4556797dfebab278136a182a63e5ca9789e3f1371808efe06eb0cc5ccfe26c0538d573378035afa39fb7cdf3ad889b277c8c6e84954e74f3ff3140bf13bcb45c822784125d23b5eceb73e",
+ "088fc7ba068f80efd8d4d62813c93c1eba77e9ff400c7781314abc901873ce200295da09245bf8fd2fce254397616151d94b511957c89a881256182ac9e64acb7b25d4a080cc9daf9ac2f231235483fc9fd415f69caf7eaf0597",
+ "78d5f86b071bbf8a185e5e2d54faddd2a9e26983b1e7a74be0f0b979b9f4af31",
+ "d9ce7d249af9496e99c93b36",
+ "ad542824b49fc520f0b7ff8ce2bff8b3d47baacb4a1c95ed56a306483aac551fffba48e8a8f5e4cc536e9266182f6811d070fb9282f5c542cefb4993ccc7044b42cfd6fc71793dc8dd2de23c630f9ceaeddba45efed9d7fca25fcb07d193c000822478b19c2ee9fb31760cfe01475ba8a003db469d1130318a79345a29d054a9f9412dca1edf6d8f1498af5bb6fdbbd3d5f9a244ff176f62742c53779291ef6294df6540d841f4ee8c7c58fc8497ba74d9cf7947add5373427d81ae928305b93dd26cfc65e63b0ed0812ce759511bfbb10aca98f2abdbc9055c4e5ab82637f6a965bb74f592bdf11118b8eb79d50331e76cb4d10c6b4428cd4ec2ef4cb727bdba2b5375f5184d77772d0f9fd3a3c579a4a548b9c2dadc22c805ae959617af49a514b43f47af834313ed2e4d1fcec2c4b9ea87f328fa3d23129a36e6c54bcd08f7e30645de86e98ebb11bcaf99543503eb1e024bc9fd51fe6bd5e6d749033f2452cdf28b3d0f8a304111bdd26dbde641c02fcb15dc21b1a9baac5e86d35b4126ed1cc8a2c3c2a5b94c99fb9b2008daf1a0c090633bf9e31326428c75a50e821b1e72a6504c9d7bcfcaabecd929163d365832e8971f5efebff99ee3f5b95f957e8904d05b410936d8a81c60b4947f8605c58e5b727d491995c76fbe06e556c8ab5cc661a0c09ebc98d61010050f68b31fbe1f9de8f6481b2704204b0164d8433ba4dc1076908c782826e9b555e8d608463581099a466f92bfd6ac9796eacc0ab771a3f11d03806b0f33ec04c69cef6b87d58c11acb5d1374450ce61ba159456b915043c5c17cb03f0ba66d027105bb6fff41e6422f13e2a466f073358bf68149a3b577cfba7ea08b42f83fbc5a2aff17c5ee7dbdac3ff97389f5b8d1f3750e5c9be651209eeb9574127ea81bd7619da16d1cfab85754883543f6474c8c0cc9d5b80e34bf8262d2b4798f9917bcab4b880339397907a5bafe7d149247fd735523df3cbb17ae5e298846ad3bfb7d4f902aa549b7667d3ea945b002e7b209bc83842a7b120d6d27ce80631404371f31d1f61efc5423e1822032a1cbf4fa1a6b6fe79934a202d5add8c6e3595e49be3dd9553a569521c50e9653bc684ef2b73c3526ff7a0843fcac9cc9ecf46e63df5b9328a54c576bd299a366bbdc0f83a9de67b03f1da16244bd6d52e7e4b52c4ed693827735554b05b3a260cd01a41d7c944d0b7b58ae4b0eb052da34bc22b779d7ad46f90f3d4049c097e0adeaf71bbb30ed24b32ff5c7a65177db77492c2571e9cd99f15e613797e319ea7377038d53b28a4cd66a697e5e8f84cf16bd0f0430b34826114b4e1d1ebaaf2939dff7f9f4ce7c0861e51701c42d9cc9e871018b447ccaf4e402e3d63be164dcdf6799314a389ada8bf5e51a35148acf627e51481b9b0e4bec09c9e6d59229721b151fa9adf8323001fcf33afbc9a949643172f39b0d10ef57b37973683fdd9b9eb46e63054fd05ffbef889ff8fc8f251b0ab41fb00757ec1964ef373fceb8f6d148a7f7c89944b3cfc240d091601b23046188ba70a7cdf7b6f96eb93dcd3d24d4aebdc4a29a749bfe3cf5f6e1a025b62982ce188e6b57245d829c9fc1dcaaa5309a8b9557b8824a78eceef6e977721de4065b474ae008642b974001a5565ef5fe4250194e8b861cc45a8691c461817f10b646fb526bf0fe7790bb0db29d1356e8c7a197ec78df8310431d632a032b5490c2a458eb8d4327a9679d7e8ef8739797b0e820e2c567ce3562592e862a1dfcecd50bf77fcfcd00518db65ee0effb9eb3655d5d401a4a47808faa596d17b316f828cbbc14a7e018a0593da9320140a752f3824b5fcb66aa4c3cb94366ee8b821b09e7bea2c04ece15e8a7be1f58463b525e8cfcfc3fdd395ec5b0575094313557e632d0a65e3099e3c653111a5fb4f0eb2aa710229fc055a2bfd8a7147cbecc10823f1244fbb6894af1408ff9047d6483ef83573b5421b9798ee387dc38f166b11de6c33e9785e9b3d9d28bc24c37890e4f8f8ff24cca298b44d6fb1c6aad28cc634a67dd427205285521a172c2a4884ac5b038e261e38faf0086a02aa29195713cea335c47d03d67fa0dec7a8cb21db741519f5f0ba0143f14d71e33d82c75d6a19b3f7a42e6c16d762354daa2670ffa55bd400637de9cddf9e7964a03b4c8956f36bf54d89cf16de23e8c52957b52eb4572a11d1398be72bdb129e2c1abb58c65cc291bb7b0d2dc326c6125a441863a6c92de0f47a355222d58bf10af0d297a86a98b4e933a8f844fc7f1bbc8ba77919dfc50c41219e3db309b92ba056349faa758daf360b8ac05e43fc2069cd46e63fec399cd7764b111467fc65407ac06f5f84a3179930f6215ac5ec906146c19e0d3e162e77a2bca3582128284282b251cdcac03ecc204266ac3a9cfe8d8854008baf89c0ea0096a400d6a0d2f7c681c99462cf0105f7a3dde690ece0438fbb820b9c73c6cdf6208c336831101b904526cf8ac331d879d71615d8b1f750ac7f0ec692d97a5e21e17e194a98c10172b5c4bc1049a8743188ae7c4d70384a7e68c1353aab7882bb91aa383821046ed0ebabb4b2dd126ccb935f48646b299095cdb71ecd5cc402e4635a3f7a3c8a6f54f4076ba028dedb402bcc92f5668dec3d91dda7319f58382017e306237e42480ee2c1f5930564cf16fdf37a3434585336b8e4535bba87311cd47722b9da727250560624a5dde48a2090ee44592d2fc06edda634b600fad9f843c6b2eaa0697b42858afee8191dd2a31e5685bd104188e2ccb057dd0a8d4d1205d7c846f5b8ec0f06bff61c7f47ac4da30e1bc80a4e95af79b14a83e9af2e0f195cb92d14f752a5f12ff90a05765be453075d799694848fcddb07859336ec101c8052bdc273d4abc313cfb351b543fa340dcd01bf32fea59881ddb8f33c6023ccea70532814ce4a2d0c66c846347b86c29dfc34f6fa4db298911d4367c59939020a3d078194e6a3a3c5126c24ed182398468e77fd61a5b1271f5cb2a97868876954c3f7179d6a045f4bd770f681cd82216cd2b1ceeb4e724b3fddeb74481e662fbd7f5dd45bed6d4f89d21b8dd9c1009ad2b0b16954e97993ab8f3fdd9d61f8db102a945591b4552f419971a9e46a792dd8392c8d9502767c82d9b4f69e66071eb579859e9ca070cad5fe3b7fcb77b8474926ea991ce7ad201421f8a79c051b762a066027ab2b9595a1c97ad57f3149f5872ed4d8e99195d47bd3c03bbee590a50a99d8048e912aaeed797977b52f0240a6cf2c865b108456881adbfda60cf701454da17bae879cf098df808f34e50bccaada2d3edeb1aa73cfe3c512d814eb33897b6ff9d67d3d682517cc333c3c2552adc99860b1f0d1076390de9f84fcc9e802581f77e14f5254da01831c70cb8581630dadb44209377d90447a1a21cc8a2d6d897db62d8420afbcc6ed85ce42f3281255bd43e0afd3e86b27d3b957104ef54959282b0e1b381a26f16057246704c7888126055af5a1f494540f01897e8781e1a5c0193b7bef4b5588d0e9b9c8de74dcdb63f03f7b15cf48fbb71c7c3bbe9329e3d326988bad7d0cb85537c1e0b3cd88f37a3c7765f548f99e495ddc29daed8c7f15dadf2e5b79def91dbbea277c51a5da250e66c305604bcce4789ca2df9a10614d72824ba8e4f179f35ccae7119fd962cce13b282f0f970ca6c4776374c4bc438f0de98aa04fb3cf23d2c6800a4a666c15bd20c486e88e688ff9e5fce906b4ae96ec7c3388d7567ce6c8bc61f6d2373b93f9ddbb02b384084b3f28f54c9ddda232d3084daa5fac5ca356ac0059f2fd3fde5d6a9516d0954653b699aa986f70733538e19721daa41329abb95058450e602eb5726ad5a8b81aa474650659c6f7f6f53f8a6e635bf35f4b1191e0dbefad3be756c6141c7d55f007f4fd131e5d5eaa120ba31cc32b8d4c69d4fa784fe0af7dc272898789c774e7995cb252eb6c8e8053c9e7adb59c27f675952d161dba78bdfb15859fdfe4fe4a44c01efd394bf51d43c600aa9a527d9c490971e188e28b980e77a9c6ea0a4ef6bd38d11b47f5745ecdb",
+ },
+ {
+ "9cd1c25b5bdab9b9080db3e5e05dc749e0783087c310777d89307138613bdffe0ca259677c13208420d4690031314a11a97a986d8b0fea143f5b4da0972c9ea3cef80b4b0b2bcf2bff392c306a764113f0d9807be86a9027c6ddc85d096600d85e0b236937f295362bc1679537a8a9278229a36a9433925a105ab719c0b7f11fc31488fa071d3032de97c81540713dc29ae02c2e13be8823183f3cd9f72ef8ba4280b4499ee47c7c7c4492bcb5cf7e4fafaa7ec26906e58146215a3d4f52f792d3abdb718f57ed0b9b7fc7504e45a0fdf01ebf5924a4da6ac635a715879ea75a4983cbd9dab9e47638acc687f16684e184443aa9e81513ae4abbc4d1596b2ca3eef77cc9b0603fe90c0570fe6cf4dff0381a99212fadcf7968934ac1ff7664ed6ee0b61e41f5074dfb774b676c2b57a445f1c5749e95ed062837c727ae2c151c0ccb3a4dc1429bbcb9e62325117aca566b8fca0924b70f4defd7749d0389b90f55f35d1635f8d2efdef514f06fde46db6e11e492c8f4dfb7cb5454cedd0ddd32013a4836321a25110f3a017f18475a86583e192132f8d8fd4c2dcb2a3aa95c3be3a57216bf9727cfd1284eea6fa870c8e689e91982c116ceeee2f8298b55646efad684b96eab883fd3d629437e9a0b6523f47ea5b59474a4766ccd01c13170bb08f47576a0fdb573d4dfb65279c1b79cb535426bcab60f4022dc42e40db29f15a6148b461241bae62070389932f035e7257752ef2d6130503d72344b24d360cae8ec11fa2dcbe04d3b18e66d081b552e93a71dc0094d1046bf4491e318f2ae00debffa0b8ada58c5f23e33fb598829ec2f46ad3894bd7f530210371a02e51ae0a414eb2eee43f3e08126dbdbae04c7de4b7416df32953234a6694ea84e6889f27c74206ab8144a393a2614e92adcc77550dd54827387b619f004c13f6c4a31e8bf525277669db0a0c3c589eda15063f12eb774a13e2aba2f2f7b6e9bc69f8485f1d6fc5773acf83671812412d28704003e78a17da25bacd1d61a6d9cb9f121abc71d023bcafa713b7c954e4e1c524e5bcaefd86c4a843e209eabbd579cde0263fc059ec6ff10017ba54fc9c2a1171d6b06f5d85079167117c12e6e5d0c71c008765fce756fd0f1141fbad6c1d2f32cd8e80429611a9a78dbc8e738d458f9ddce58ab43c77b34db9befb25cc1a588998e8dc2efa75c6883244fbbf9a7b4d6750c81b8d3fdedaf98dc61f49d067c369409f984b155ec347a3bef73e2a44957b0ca0f84c7fc335fd89453759ad0ac2fd9a5b38afa9fbe74daaee7bc52301302fb2286c21fb922f74d756de84519171fbecaa9b869682d431614ff6845126a4034f10253aa244bf89ab8e0dfd1f7fe8fc1a8472a10746d26896c8ece7ef80eb2e910069435518ccf096caeda63ad692455b04e6525bb8bae27197ca5118a57fb9a5d8fcfae1b9eb7874d91eafafa0e4fab5cb4d0173f7e3e58fae369843a641e98f3ee460e8cfe95d98f7fd38a8d2235e9d6050015833e6d7d21d7015c3b1ff42f0d3a3d9a38d373c8524752e06987c9408cca550f08c38c2a9a8d86d5ac7a04bab44254ed15c7b5670e0747788e11b81adb0d29e3d0b50d6a429340ee0d44a8c286fcaf9bc46403d26b4a4af95b021336103c1ae0f1274b33bb8b21c8cfca8a56c639f18a9df45d083fa7019aaa14d1ba50eb9a4112e574cd70969640602096265a87b1f77c0e00bbb501555f1626196611b4a824991cf10ab2874a12a8e0390267eaf9e3f8f99eadfbf40d111a26772cda1f50743c417eeec9c80171a83a730f246cf31c6691c96185d672a0fde9ccd7091c4b455dc93326913497396e0a4992773caeddcd783e534eb0f34b99bf23a2db6ee738381b5fc94ff603be014c507888ff55557793a8c5439b11dc5a347f35a2666eda81cda4d1c3a78fc4f3df3c7bde91d05524791b67142c446f60c3a4022912ddabdf817ca3280b671beaa496c935661e5adf39c1f4650563c5c807c8f21aa59df926199c4e2404690ea8ffd7dd65f637452ff93995fe9c5ac7a322b9bdc756b7ed6f533b9357a4a1ffa379dd096f144e9e0d87330c238ed3c6b08c8478e23b65518ea1e4e64585e5e9fec2f26dd7400ce4c73ff0eacdc3b07e4f34f6316f5b82fefc66e442ecc92bea8c1d58635d644724a3380e71fbbeef4bf3e57c6240ff603d65447f510eaa3c9ac794fd24f844489b7c560c7814fbc307e03f6a213eca5ea40fddf51d8731b74ec5b472bdf8ba59751065ed2461b02c41ef96622e60c0d26f9dc78c24f94372bef7e47cf09ed565ae3a52d39b02ffddf1953f1ff500f1659db9f1c2b23534702c19ec1cb7c18166fcd33997d53874c7cdb4e6c2b4d82751911913434e48b37a61a0971861187e5decb7f5c1ef6988bc1d6f7fd147a623d8bf361b0d7ece88df6e1ff8d037762d232e22e51d8c6ddaa9dc597b23ff9efbbfd416cc53e5543253732a23aba151cecf73b3ecff21c6a9fd1f24211fc21cde9633aae918ff1c6b72468f1de7e0ecb6539fa353c069fcbe8920dfa8e2fb86782e3062462f7eb2a2c441bfac21ab62744b05c70b6fc3c9f8e3a8a0c5a4263ed256a019861ecb28e20ce78e2d93f1a1def669e9652cb35d105bfdd5ff2313d27ab3eb00d1b628b4c20f42efa23390802af96a8f261ded3678ea0b780e1f4a88d23588a4ebb058adbf9a9c62ce2ce2f8264c874c697482e25f8d5a6daca4f57fd97d23c42d7b71ec150d4ee33931db5f7d63abe7d72dc936bb23a367c798e6a01509644284d52f9ae27d7d1bae597b2cbc26139354dcca0fff6d76c6065d661b66ca5eeb9f8d85810a029cb95b17e5173ef8ab92d475a1d3e21799e874ff04dbc962c668ef4be9f94d85b2a99d97c0db8f6b6d63e00e36c325cfab9aceaf7597113bff0086e8fad36eac7c0b443de6d3a8533789616d4c863df7200ba795a3b8d0a2b9568bb32af95fa604a3e3ea778c3dae159e1b612458584564ffda07b8aba9710134242b2d83d23127b51b9e41584c56f667b71bc01060240f3a2bc7e5d438e7095c1236e0e468079a83a5dbdcf132d258e9ed18f94d3c098867d06d3c09544565677b454be34ce567f1c143e2f3153bdc0353d65090dfd8f7af4633b89a781e01f4634dd7b0323ea1f38184e697bfc39a1299eaa278c39a2709cde0a346fea53a61f211112450b318d137fe68f6c102085aedabd2b045fab912da5c58d8019239f3a44b18f4fe30c5352e2e2bf030334a1dde1dcd23178636f1e38ec9e42102d8c54df0b94b207e804eacab3edddf89fabda6c8e1bd4e17ae31a57716c679ee8bc7de4412fec3934c6f3e8b4c1d1447dbba0fbc775dd3258f789ca53f1593cadc710fef6fd282bb41c0468ede5ad5b914e4758b4148b0d0c04c75ff6208ca3e79d92de8abafa4ec70ea7a4e454f0759337ce575c4954584e2bb8444c34e823d27b025d25fc9becfb4391df9882452bca0373164cd76e9af316df3f5bb7532e22557b485217254d5ab72ce349620f03758219b259784d4c9f1c7beac3cf08e624742e768b53b3d60ad0b94442c847b84a516a93d9b7d068c44c43980b4c7e2fb0ac964bf05a11fb2adb4f6d938715dde88061b238321afc7e5e84799b02a94baf3f879f89a98ab474ca12085137d639b837ebe069f6dcd8456141d063eb1c032aa392a44d1d58b1e77aba38a280625ab84e3b123507ea7a692c4acd1756c031fa52d637703ee957a993804c13e296cc20c1de55c9b8c032e50afffc51c02e5c12f48383237cdacd005b09243d9fe05e51cea42b77645e5c6f4e48c10e671d216b90a48f0d8f5c1dda553217f5126646d11a62587eb0a4ee0efdaf0d54bc2eb04cd34f5a529b682ce09a34d5acab2c8db58ed6244f7b024e68a14bcd5d7a7daa4dbcf490485cbd38e6f20e839d2b0142b9d766f9527937bb1a737877edf6122ba306bbfb5379243a6b22bdf85dcf3b079691f0e90b28a4259c1c9d8a02afa5b5a661a0f9dac52435e7d22e3591593d37eb2e10f646b51be2d1a96cd4490289ef642ad93eeffd64d7cf830d60dc4a98c768a9bdbf6ec9923062ff04abf19e8b65b95494a9420971018c7e6268b8fb2021a4ddd103976333fa52389643c711a980664e29a8479aa9c4091c2cc2074ce3ac1ab4afa217d39c6a1",
+ "c22add33457539a957d32dd07ec9110f8cdd2f00ab6ac256b4bc7732f63dd3b867b0ecac262555",
+ "e71f9a3dd457b4064df1d9055889f105af175a2d10dd7b8729da0d0116c2d9fd",
+ "7df9824e774c5f86d83cb5d8",
+ "689683c9e7aa9c48b9fda0cfffea0458ea0c3dedccd21efeb06126f1194780917c9f4f2f44b1daceec3f6b1f75506f4169bdacf12c1f65958784851056fe0b4b42a22aeb043ab35ca73747346ac58c550324c4b849a404c94b8860967b6fc58aff25dad0556f1952c045b91f56ec8eebf6f552c18b2a0641c037e6c6538b289601e1fd5a7bbe7b6e0b224124fec341bf77615183abafb52b3e30082a0abfc2cf224324338c132426011d9f800b382e6b834896ea48a8247f149d92ded7e69c7800096076cd2a729a1fe41c70dafb1f855ffa2ffc27b93e2f5f6827ade7118af60730033675d84de9cde6c260d3d615a945dfe0ed25f33b6cbd2c0e204ee919219d85c7536f4700f06fa61937f8dbbe9bda88db1f4ba8a8d195cd385eec62edd9ce673880800be9aa4430e5c10a5908f6dd349af70f32b32d8db38a7d73821af47b993b622bf168565082d07e88fc48231a440469adeca59263302438ece96d89de11cf8057454d1bfe8e4e36965a4d82618834a0847af39dd8776866d9558a5cff79a1cc9d1e3c22e050677e54ead68b3cf0094daa01330d41bb66708a8bbb8a196fae5c77dc6774629d38905e81d97c5b16d755182f687a8046e55d148419cf9c12139fee50c0533b0f04a805723ce1ea5595fca5b668e58f6b3b396f438308372489b640317cfa3a79392cf6d1afdd8c3359557a83790021a4eb418fa189ad15ba9be0f74182ac76076f102ec171117a3d16ca20b4d200e03e54f1f0ee6308e463a148c0c85aac3ccbe5781cf45b53a313f7c9975a45d1853ed9104a860c08634a8211b87500b5ffa3d8d9d56f22256d485b9b45b24d3873159adb8ae25966cc40f164f342519e88d1ead1e711e1b2bbd4be64c7e83f056f797c2d3a5cf7c5025f92be5637fa7738a1bbba55f761dcd1451ce4b1e85a6628b629a2f7917a86363b01516472c0f8614abe2ad1c9d5501b2a44a68e3eeeb34a64541125bf49138bcd15b7c82dfd40708414b85107d8b982c4f99783a03c707a37787a91a7198063f0e8a2d52dca61755105faaa09c063c7a0849570cba1aa7ddb3600eeba602c7e7c9b90ed00ec731d4d1d8e4bb42f9e9db21616c4aca48dc27b939428834404331288f03c2b5e887103c51748d0257519c3988f6492eb70cabbc2dd8a8a910d737a678d0970ec48bef3b81673bd10b687b37e11d49e7cf90c03c54826ecd833bfd9dbb8174274dd45b139d08371d5d248ee33298193194734c5863adf4bca92bc282bae2f47da5201fc240dd0710a22a8d922faf92c2071a7eede7ee17232d3b6ee5f3ebb1a8b230600b243c860968ab427a5f540912e5e7bfa0271201f288727f2bd5173539d5318e5c1c0a71cba4d9501b91c3bffa7bb61b3713f1751efe94a66e17d2b42da51d13c3df40f4db988dace42a6a1b9d138c4f590b7227990711afbf8f56fa63f2800cc019bbd4a7b3a0983c9b9e5f77562dcad6de96e3b2eb85cd99d28a021a10d6734400a91369236b48ed68528afc68f247d45c79318fc5d634ecb0f3ef8536d8ec2e877adc3308be906c5b96777d0e05970023e5c5dffed12310cc97249e4b95e32451c9acca8394fde699deda57e938bed7167e62e2cb62357f82fbe821ee73b4e09c6e2f512515412c2f27805762a8493e74a3d30bb409e499002a97354381318af28311ce484bdf7c39db53f08f73ca5793945e13fc8c66d503fa95506b37ce134ce2945d75b424ca6367ef4ed47b9cb8ba7de80e773279bf23ac888eb105385ea958b1b49b27c8db6b1e14a5c8ed5d28808a7d0b6bff1a58f24f9c57fd8b8f477a9d1365f89c698b8ba923896181299d474b93e05d3c915b10a69e61910761a6d8644933c593661b0828afeca590ca18e702322d9140d98fcf836c2f7a4f72b59eb529823a52ab05d919c3eee4db2cae1067213c5070450a160fd52fa44bc9bacc5c136701cd7adb1faf484da376477da08f6a4dcaa37af47c7b026c2da9d5fd0b30741357104cb2bc0d3cebd132b5fc7c873ebeceec5492aecab95ab393f35b93b923d2ca071e6bd8522c3ad8598a05e96646504f1620c045aa5734d665acbdda0ef73612be4ca4d95ba069041e042497f7b10445869989ce30f55206a1feb4e64890b7d1f7e9df2e88a352674a52ae4267c06592d425ed1d88101cf94588135892218ac11f3976ab2b47a27f02eb887696c94b13d48b4370eb11222274b5513a0fef905c66d0c1893832ffdb9b333178b65338fd8b81094d8f86f2e4e96a47e72032cd6fd47af87eec295c6e980f595b57f79abeb4654c4039fa03ade732b1e579551898b801ecd6e0fb1c5fd198335834b51673d074a8222640d2a969998f5b878bf897fdcf3426c4e24a7c599e5567643fa79ea5d20e7de581a873ee0181e3632a4e304f9dae09a81f882d4061ec17e588793b160c93a926874d5a8b78727f88de9bc125589a9562db5bb1c01012bbea1b2eeab68877871ce83455db43cc48455effbc71c436aebe362af22c6a319d134f65681c4d0d51f9aa42fb20f48ae3f7065664aeff5d8349624a5d79eb0bef3cbb2a1244ee445f560a6bf7a796b2c950a37dfb85ed5be11e8e305e835c9e077e676aa5ce23edb1f74806278548e3fa35059abc2f032289f9bd76043c8dd1352b6131cf34f66bcd0e7f1d13081f5b08ed0c69136f3b7ad8e05e9fe99a9b73624095f96740c1f40074e5d92ffeccdc0f15502082fdfcfc97a800be511c22b875f2832b2b891cb1aad2a17c7bd0be4427a4549404172f7c14d5e425e14498237c26a7813cd8612d048703cb180f1a6194f688b4644304950b078692faec7a2a5c5bbc482f3a7e8ef2825c4c19032a7a79a2908ca9774c6403e6b15625c485f2dd078902aff769dfee2dca9373704bf63ad981b51f61253910fd48c49ef10e3938f35ca8dd491a8e569baef675df30367b093f1088ebe8f876191dc32055481d074e5e47a4bd728efaea9fee3e83d8556255ffb2fa08194bdc66897d97d1557186d5f873169461494a83368ed8065b9a033fa4c2f07f7c60f945b60479e3c89233d58f674c0c6fa5918150bae0c6de2b65a09ccd490e2ad8571745bc37e70982411af667f3e8e9b9f7f75d863e5fef05c1f0d2acc7c86585a83ee32e0a64a9e67e75b80def5bfeb7cffe6e6822efa7a9cf049689b58336b081c039696e0fd3b2a2a6b0d177c9b3f8fe5cbb1c69ea93c1235b2c5b6934f603127eeafc4ed0728161612acdb2ba894a5ac376c4ef1fa8d49b4722379e5cb39752837395c413dd29a2a88c03849b6fb2221fd85ba6d5a50ba7ee9c09ecc5e6dc66afdaa1b021282cadc68f19529eadab809341187d57cfdfe01d0798ab8a94277b9b868612e575bd98f70de80ebe5f57637c511800373262eb5ac3836b03808ca5d5f732f286a5f18a7b7fb8cd8f60e4debe54731c9c524b84694c5469975443964ed28ccff2f4e8e0cf4c60c1c8a092e986cf12fa90a994e4f26ac89fabe8a0d1e27fdc00f1d3d3fdb73bb76809f93ea113e336cb0a5438147e454e262fbb7d656aa1be1288839bc342b48ba7d0e72c85a2e24be1a97dfb2db85b5d850481e62f3b11a28c6407686e73d550b9f1d0f010602e82af26813d2484a8db2da0814782c8404b2865abfbe3c98a07ffb37eea6de7992cad73a9b81ae96a9acb13ba213eb4111d868cc73b0432d2b6c2d7e0e0ca7ccbdce86d01576e1136871a07c76498eae53fb7ebf2e85fb8561d10dfba740400ef4495ece7eb33ce3bce26344eddd88cf1ed8028ec5fe8e71edda54dbdae08f50f8df6295f6d7ef1163f62262a200456a7777d0565d7f5832fcc7ac144b5c3e0ce3e5c9b7f880a54ed5e80662e96b356ff58f2e372b1dc0d73cb8b96c72caa9e5dd312841a8be23f838bc706d893e1a8a48b2c069874c293c41d00226f73f987aec8686046ac4c0c972c991c38b98cabce30e7255dbf16039b95dc7d103fde630b03441b15bd2c214763fece9d6778d1c6354d2c9478c226175c02cb006006715fffc879a6a2b4111f6234ee330d6c84d453c9ffac08efda1f380110a8ef8c2fe44e2ed644cc3e0146b4d02f76586fbb6d69b827be38b9add444e2bac4d7165007cdbf2ea8c4b967fc1bb70c68b229f19bc3f79cb13ee6265264885f04c09a96583f331ed46de3e5dcaf08313ba6053f3d0c1916a0f",
+ },
+ {
+ "3ab6cbeebc18df951d371e0f3cce2697fb367476bd9d50ca9e668c77636eeb9d24b68be0ce6a75eca194fbde6221755d57e9d3148623de24896a9becd98789fd3d14de0c7e53f81fe7f3fd491472a66b5b797fe19c5d0525c7a111a0289a9e65ae7c712ccf694cb75c490070bca7db17205af9bdb7fee27f9ff41fc78ebd2d3d399e690908b5c064ffc0d5bb67b0d2880bcb45c2ca2741691b6131aa1e5ee758fc50610406216905e13ec049ee92d1f95e16bc283dfd91595ec2037d20ead51d3a362140578a4538c80581b79852b0f6686c1ea66aafffc872024592ec1aaf2650d167a75bace024b261db4ab48b401cf85ec2620dc12a7fc37012af8ac1d6db923d82eee962129bc4ede578782594708357d29118fd10dc6d228bf7e461d2769e556488b776237b6309f3dc2e884cb2df1f43f71c53d389765f805ac053d05fa835e75fab0adb0f13ceeb425637f43556372d728a00fb005f7c5a20cf2b7f776066d60b70b11a848005c6d63dba0c93f139067b39017c997dd6b94c0138c3619e9a6d0e4b8792cb8d58a2ca12ae5d03e7637f2065fbb9e2d1722fd3aaf234488ca157d829e9a3b642458054f3dd58da41d7fba6d2b488a327b776d1aaab1a364c710e755ab22b9cf7abf1eb8949c5ca20c070f275f8959cb00c6d5ab7879003f89f795351a4ef4850e033d929f9a349b9133b2e0bd1cabbdd381594bfa697b845100b96b5fade05db12de040b814ec49489f39f5abd5b37f570cbb516636d5b7378f12872d02d4de20b52ed8ca0b12029a4c084621bbb578b870ca2ea79fd5df1ef8664bfb3b1a1bf038e4ba33f6ccde42c5146470c9dd293aa747d2372db1561617920142ac1d32e4f1fd18e8b9e72b7efb8fefc56d08f00450d23b7e8381849b1385ddcf9310a4850dbd6db7a4992690190655760f557a5027b5ceab3743365ac9041a5c14bed1126c4eca00d7e0a0e0e6f666f64bd1466387150ece5835192149237d5dd25e703e9d3a4f652ae04601d6acf8228e4e86055394c3abc9dccd02f04a60c298d101260b408b2620c137f77e2019fc6eaff1b234c56dfe922b0192656254fe3356143e969f64b7609cbedebcc8cb2b68bcdd9d723b9c14669da6cbfffbca2351de51e87db6afde435ead0017682b8014f91d9734a9ab9b374257273e114a8fffac786d53183ba666d8a67e30c1fe45bb1bdcefb5787afcbad213f8e36e78d30ae1305df96bf450349ade655cccbb17d887f79e00728abb449ea427fd2d0af80e3b5607a74a57dbe5264131f2fc49cb74415974b3d43ff872d4106ff11b680f56be06fdf85ec9dd850b1f77f759337b9a9ce04e611036d3f45743e562abe4b959eba7424a712fcf7c3f3773886aef22f7cf6168efa83cd3ff70b9521cae1b6689b2b8c423d883a007bb138025f2a31db2147691bcb365ac242efe40cd09a746cc501ae0289e80205993b07f86538d486803da14b74fb0db6ebf1c2bb8c36275137d654c1be56c65891cd50f705247d85621fd0d61ade8c05cf4ec15b84e8adbcbe017d7d5743d5e91025e0154a5d9bac7c6b8297490e9c195c5d74e046219c042219817a5c56636c7c4382c6a01d721d88f4b4d20250eb5eae5f3ef481dbf8a3f47a1d51d080bd4cc33f12645c8481e57835b77a85a2d83301172782f22026e69a43376ac4f5b78734c9eb914e6c76c6a12d4127cf195ad030825322a279093cbc40a680355d086a27f3fb7560713b019e7c286d96833dc60590e9a709f2e3c632894668e74ed20e42cd83a23ebea3dc3bcc49d14f8697541780fb2072dee6a5672d0d4e7bdf5cbdacdf5fea9e03c6d9cf0faa1e954172acc26dcd344bb3d9b2e0e6015cc55d19713d795bdb7c21b44b305e69c69fdb7261483f9693f36f45d356462f1ba4498de1c2e8bc3e0a70893acef2006dcd73cf15b265a8a5d4ed792a34a846d8f1d3b9b3bb75f1c5e57a00b36c00203973ef4e2654f6cb29e4445318ed99f0de6ca992281e83ed03feedb66aeed6a461c6f2871ae95343cd9797e58430d5639d7ef5c59c78b29f76a055e18e2b85eff177770c60ca4f2d61e612e617e749b4653e7901b62ba02dcbf50e59219349120ac01e6b8a6e98eb54abd16b921a1ff85898f90fc49a3c8f8f4ae9b0dd32c3e7f2e1527c4feb67a496390f28532f20acc71abb8bb4f71b434104f41e36b705289858a4e8430b8cd9449b0198ca2244923cff1df0f63833373c275572de5a9a77b23e5ff54aebce8e86d02651f26ae32e69001e5f3951967579ebe8574682cef8c12dee0b18bc999f8cc0f07e2ad3ac94d3caf30c1c8a8295756aecbbecbbb4ade8a2b8015e52a0eb1290693c6316d036e0c443fc4ec591c32f7e7f1b3933c921d5812233d3c21ee5528822b59ef2ec7eb62f7b04f40cc8238a473ec37a07e54f8907825ccaa1421c2964d2c756be450dedc011e1cdd9045720421b9a4a00e9d3076c2fd10d71ee36d5c0fd2c7e42396b034a4cd0245027449242dfdc42c8af4a34df1b4150097726c9745247b78bb2bad5fe8af94eb13ee1f41dbd36e56d801a4c9c5b9ca5d3c26f4714b6fe9f69b87567426eb6f4ac97e8c9541eafc19fc90d3b24aae0f76c4f3f81063d206ff695d638048c2cb023147a78332939d2f2470d16f1ed0e5d3d4dde438affb2809488b99815e54938fac3b02deceaffde310cf422f9027f364f5e79da5d2b5af1b4138ac9f9d301f396b220829c1f60cd2b54ef24576e5ba6ccd4802900db1bb4eea57de7787eda0e30fa90cc19f099444488699bf7c442c398c2ed989d084c8cadc97325484e337848c34562b3dea6f7670f935ed3d5216c970e04351651c1c31a34e862821bdbcbde202d91fed38965e31cc3b6f1e52288f327bd0a787ecd92b3b6f535d1d000b0f02d41ee01ca54e4e6179ad7fcbd60f0e41dfa5c9cc7ee4f7de3844fb385ffa3b24092b30be697f1fd32c9faef29ead346e42fe2ab1d312901b678b43b7758edb7eaa1c2d038b4cd6a7dc759a6b12cec955bcf4179006a7ab6e22ef15986df107080d340b8870e2304d57caa87a9961c04655d7d66c7f71ca9260e02aced131d6de65d256d6b487141c51bc86eb1e4721742f07d09e799b30da7b5ba94c8d701ae34271ba06f8ce134a7a9a2598d1570cf05edd9ec868cfa2e41b4c20a8bc4b8bfebd45f5a60408f08e931617746d1464bbe1f3844ab3272ede635f771f9af30e483903ee4d0cdecbaff4d31451e7791dc97c92042fb932fe1c82652c1d682a55912e33de3b1299db076cef594458670dc4f911f4a244e2bec757dad4b0052a41235e2f5e60b929682608c16a61287826218a1ac3cf0d8286555d5b0552754685c365d4342f0d9c45065daf6786179da791a86b50a5edd6fb4b21f09d9747136aacf79ecbf52b00fb88b0630ec7f0a6699901ba4eff913a3ab33ac85a71ebb51ed343eac86eebb3e79c16e664078ccda09e77ef8e0919b8cc447116b65ccbd5200fbfe86e9bac5637b33c9bcac9596b57c14ad5da548e96a8ffad5f5c69247c68d464c770011da7b45a337f138cda6b4e15311879bfaf12af4c61fba596780e6adcd5dadde372823da6014122dbac70f0dd896a8d387d3c74df282a659028d06cfeab3ae22dcd1fc3ce60f69a0d678aeae0e5681952949e31ccb8975cd167c9d012f4b230b1c1f47022eb1a3042951b338a734cdd17db0ed483a621650deb3510efe74191a94611dc212c0c73b117a73b8ae41892cf176742bd98a7cb73dcdc53b42df56d640739852335f8d44d901fc884286b433fc285fd5b3db8df0a8522cea3182c071f559c328b8516c9252681a94eecec7ebf626c0a9014d9aaaa0c694d14855433dae06656657d1f8a939123d28e00513d72bd3802d211ad7c1e06b9228c0d5656edccad5339bcdddd5e01afdc01f10974be3187804324fc513ba583b7b2da1e9096bbe3d078c1adc6c34d92c54e9c49fccdc17d10e66962120ee5d9b1cfe852569436270cf7c4c3bb12568050e2ca4db08bbac16214238413195dd4d936272fca5d56d7551b9b002df1807ed44abc84c66746387b79bc9e830a635c308a7bfad7c2c22cee6d3d0c5ebd8b230837b7ceaefdf71a67a3a8eaae0c36de86b2d96e759b8b53f8b8604775eb7a7e13223cb21033dc87d775628581a954085c2d66c1c8f225b1aa86091061738e7495cb36a5ff032dc678904bfa39a00285cd6947865b6d4805e3411644b4a4c94a6fffe05ef31e156bae6165d801685dcec195552d029d22e5de393a82ddf3cd3de3ad8cd6bba2325a03982204f07fc3c21518ef17a601fd743b27f7191bb446ff61d3c61d7608777990997e911932532e5b3235f13423756f5b6c786720cf6682932c90092",
+ "50772c5a0e156ba13a9d86edc0e600021d56f7d31e7e452a74ad53a6775339c7ca6521d87a8c79b42900a1e9e6a1ec03f7e3d615611c3fd5c9927c40e5b508af1a298794b60148df01e9c9e78ab5ea8198c097fadcd6cfa6694be64e00eefe1a1885aece86f6ad87df766e692b58ebc41982bef5",
+ "93a2561a9904a1787a10e2a668cd6a814f2877a7b512698e94796805875c8d1a",
+ "588d9bc1d98210d9700ef488",
+ "165d8c9eabcd5e93e6eff7be122c8c242e1a7f284790c93324f924efabcec4a4ce48262011b7360c2833143d645ff295453853c92f0c48c6dfc2af7ec58d9bec0d13239c7e5593cdb39d49376c6341263df80c0ed2ed79fe9899d0c07de93f6ea95a5dfd307e49bdb5672b158a4df623ee86d54cd1a0fa9a60ce39d1f5f4b6b0ce9daf2a61a907cff3bdd3f29156ac439638e0910d728843ae17ea7368814ad7734732e7c023d4954e1cd5fd19fc9b76e9bb84b61dd4371478917757b14b366b4bfab4eab0d9de746088ad43d8742e2b9e58faff15c2eff084df5f4316111d5dd7d23cc0b1ee1000253f26cd260aa636f03f64a8342e531ca1515b3beecc3ee07a29184988325322d5c09754c278231f92c0d980adc919d4fccf4a1da1d37f1ddb58ca997d6d700946199fa007c43853b6caf5f8049233584087fb23c3952414ac487e452f0c3898486d04e5b008b843122501f9c8a294da9159a04119ad5c8e9f5c211411e34559d3a7bcf2ac10e0174f94f3f2968c80ebdf4498de172884dbdad0acc3a887f9bfe896a6004d54cc424567d53f1198ba33c56aa460edc6af0e437b34322c1144854bafb2434f00703c1992dbad0ceaa0616aec60a380676ca11558cece57a936959d6c2ffe0647eeffd37524fbafa9691f31499701b202d9dc9980e79ea517089eced779aa45b522c9ad193e63ea8b64e8a942f630d44370f23b7e9acfedac51dd9f139f8806b09a8fbbabc76fec3c3721fad5087a6d41f93973af8d787d8bc74a3122d99ea14e2f30a3c90be4b695c8b269784eefafa52d6a79e785eb47a23d72f037ca572b7029d2f37baabce57658119fb02c5b659e3aadfe0052f1cc3c0afc6fe4624533d9700388713945c20c1d175da53738fc73f48fe57fef8305e796b474b6f8d3fc5040042373a13384237d95bb045ce0c20934a964a8372acedfd6e559aa84180a86311a3996cc17bf7f73e5d85d4db2529989e5836edad490aaa5f56d17326825aa20608fd209903335de4b36b79f68b6a52194f6ea8ce42570533df650e65b50c367f69b9f08c32b3ce3e75318106b8b2c6b6d09369c781fbf2aaa35053af215b621f833814ec4778ac683de0dc22c418b077a917a6e405ccbde9f72ed523aa696be1a6f247b096b9235217bcf19b88d43178cce5a7d82335fccb4c079e00280bfd272b9f16ffefa7fea38d09dfb2e4874553b135052595812aed3fa15096abf1eebf9abd598289e0d156974de4c2654c60825d42b662ca7439816d9d3a0255f40a4965504f643f029da535d4b109e8658ec570e99859382ca0ede0b0495d508c63c7f1eff3f648c60e9b773590cc663a751178ba7603a11985ff519056661b9460c1aabc30e83bb0073a927682a06d1b8050c345f7920c1a37546d79587fae2a92c803a986248f90547f0b6c0ad0552d8260d2a0dc3cc76d092ab76b8c12f05dcf141167a6ea300bc23227933396ef6fe9d51a1ba5a754485950f06cfa6964db2d0fd1d4393cc36f0592fca25ac1a6aacda2a32f548ed20287e3d291661848a62d41504e4fcb1cd1785617fa5786712b3005f1a1041733df6cf838ea3ea0b93685889bc6b2857d80a9bc0e7a66f7fb3d805770402f049889311fc112dccc72a25bd127777fd87bf5ab56d39bfe6be2b45a8301c2f324dcc50b27540200d522c24941701f7293b8877ac84cf35638507c7d912a3a94e4384b68c507412df65d0c4ca8ec2da704bd4483eb2e0d13b68c0c2b68c106a55b9710ad0a1436d655a3cf3c419d5e6f027ddf5dcfc896a5b316a7dae9290a7bf81aed539a647c8c98e24e7ed6a4f7f00a11134ca715e5826625c250500f8f16b40de048b095b5dd08268407f58a91c86c36ca5a2bf4f8fc682adf1bf601da24414c74956e1a8fd2888b5260e980c32f6678a4dc4ff73220c22593d23144b84c2ff56920342248876d15ea54fc100c09a81b802dd15f030bda9aa08727ea49e34f0ca8693e0a06d0af06ea7ceddbf0584adfdebeb20510bbac683451d9f84cf0f4e85c34d979e550e07e7f414d6f1011cb3dc28d0df6d4aac113f2d5b04e4486ee2cdcd4157dafcbbd55e8330a7176d1b231d9f47a63da9ee30fec6cc2c5aba3a8c6154f79997af89d972743255355647235ee939f4f305ec655271e0cd562ff6f401b86dd5826c769298445108ad0d9e13c504551f74c507436911331db60ef0ea99dc259b13cfcb0596fa9b3c95cd7fc3b1611e3b012b6719afbcee7548939676dffc372276aecd08e6a14251407cf995266545427d49ae5ab245cd5d534c52542fc71b3973f0b766f3d234c8baaec8b74eaa8ba90abe160b4504769d02e08d7af4e7ecc167780c619cefa58865169b674b2b1e10d82f6560ba0be41a781f4afa46bd722566d941a8e6f87e4a5c03d89685a22a3470354f2922e2915f9d46288a5e8896ed13617dce694a595e379f25fe621dde8ba73d865976950954e5bd07db147a0fb74f87cb06aba49b073942b82fab33a878651df73df2721ef800b658bdc6c359d396f684598e93f38e79639b8736b02dfcc124fb9fc199c35f2fa1d0dc39939c57286e58a7deed7b6c76e02b99a14d9bbf11f65d8eb7fa096fe4baf0f78cb34736499a0ca550f10d7edc8909dc34b039e3abdf1aa67a51d37a2eaf4c07022897d4d8355d3325bcf392d91d02d462488ead90b366e9645b956c3802e4249d34b5b2b2484a1dec15a9477821df6bef5e1626ec5ee9832fc3bd0b63a3c4100d32fac3e9085f0b5ba43123f54beaa7ccbe6ba68231649f35a28acfcbbf97dea2d6cfd96025032b3950ec8437108d0f07baf1bc89e3afbc2cdbb5031d3cd9e20b19018adda466382059229e4c8c54b455eda4280bde43b36afa96e146e408c7104523d5f565d22ef86d4c7cbf9c6e0d0b30e37b37feb9332939c642eacfe19d0dae1259d3267635051ea5f9b518dd74786e45fb8bdf72cbe3753bd50bea2a961b49cc0e2d589e77fd25ebd962463fc728b1d288c38a79a182b124d345872afbcfe792d259e7e5334311244edc75d05f9a12eadb61fd3ff79fe8c097eb01a4ac1f0c339d3be74be3d96b0b6a15e8868d043a0f2007ee8aa51756d78b7a78ad90fd9a26afbcb51fdc20ed7a3947f715c833e363bb87504d8efc9f8b93a993e2e26430f79f3cce203b09093c9b456b1967212eb0db4f7688d4dccd4a523866f75c9d9e7ce07825ae34399c5607a60b771866a647b6d5e1e20795ca906e451f367d8c40ffe79a2cecfe7aa47a402f8d49be9084661c96ebb11f1b48e7e8abd2978ee626f962e98f99db4eb3c6a52aa2bb2e62194120ce1e773b9db784e8c9b5adcfb70e3bd5717293eebf014e9872c5c1bdf3fb296cb88eab5e97a5ac320092033b49f37d840dac23021c19ab2a89190f3c8dde927f6e6b41874bf71ba7747a616682bd5b3f17a1dad40f4993a1b186ce4f44afb4e36af7715450bac62cb1527eb8db1d87bbc4d9c99415d16660e48efd911e02f5777a77e72733af3c3f5315dd0c785d5212b79c46c3bccd74582c57cfac0d50fc0c85370476913f9d8e8e10d0f6602f2271994972de49ab1a91728713c3cfcedb0e61c270b5fb331a980965bcfe10b41251a0f7915d5943f49fb139626f1c424524f2fba3a407e77dd7513669894fd09fff4185fbb997b4e4677f6ea0b52892f013f1691bdb38eee9307a565e396bab484d91cea9268f49aed29e319b0add900b6a75f7461db5486aaf5366f98df05674361308931de753c70777de73337a996f6d4b0e06d63a69849ba7533bb0e446f062edbd6250e61a49f4120f84efc1cf74c1bd30cc61a2d719fa76991dab119fc814a7c56f48bd584c7935679c53bb0ac78905b5d961fcd89a4b567d17a5182651cb07146aa9a94972ce613e8ff9c878a8433c0244052f09980a52d800e97ba65e8ac186862def58c72b9feec91266e26aa5075b3337c7bb8716b3acafe666ffe2df32b78f9995661d3ba28f8a8780436aae1da2a3e6a0a16dc562b8d5df6f68391aab73a10508e0f55208f974a0505f0fc0d8a55049a7b631fc94fab91459ae1f199527362695b41972e50faee34c5cca9e35e8682099f5e9652f88cfe9fa990ff2154c89c1c2a4ed6bb8a889fecfdf048ee0aae7798c55d6cdfd062cbca97ca289578c832d658ceaf26faba54c9c3ee9eb5bac80698c1441b9cba287f749a5e30d5cc715a01c89353ceab0974ae77fecc1d2dfb31a5101783cbc002c73cd155dfd14685c2f9acc170dc437c649b6b4720b676848a7f9b56cc4787eabe72f6e3f2aed776f9bb1432fba93a63bfa44fbcfcb6eaa9ef4b79b32bdbd68cddbb9897cf5a02c6f99fc765790092edf0d5bca7c55cf232a03fbb6f3eae09b12e09a9b49a538e0589394700d16ebd3",
+ },
+ {
+ "3497e8d61062e6f2084ebf72d00e9a47b550591edeee9746f31ea28039a1646d384c4348af293ab778f92a4807c48fbd14e8dbf3d67339c991dc4aca7dae38b5fb7bfeaaa538611d328b653950f4f664dcd257b345917cd66dc6a1ea75d99f70549d1af9d67b1608077b41576f38bb4c0a13ff4fa47b251142c6fbb79f9a27f43841ed0ebc0416c37f571aef8fd63b99e93ae88db50e9ef7d499ae7433d5686b165579d3598f96d9e7b1c876870310703df8fdf2069beadb34984f676eb7d3840c4c5766dcee3fc39f0739260a499647429339482e232362bc72c92a299cae36e9069cc5f4db8893e2c1b9ec0b4f334de26c951090b9724c2b3b7655d8248bc12a27861e020eb1e4cf6ad0dab903279b6fbdabff761d4ba159c1f631e681f210a8782faa86e08e554b5e30046157a0d1144bd08a691c2cc2dd22f3c3a4e5d44c5d03f7e3e385382ee4683345c0d316d41ee75f87038b49e0ad3ca45121789e7e7b95615e1a9a8dfe02c044c2935a97b141f639448182252ebfc980e0411e5fbcb3c01acd5aa7cc5d67101ffa6ab6acacace5f02d67155c26dedc071ffa66dbad26f67a819d46de0556fdffc1b4ab6d60905d8ef873ea1e51c62571c08b4c6db242e733e02e11e5840ee445c290b2232010b118839b37d4615c4521e8928e9ad475cdb4a3de9928ec7e6daf0e20d22e308347b31e7e877fdacda0c25f2e5c33a329e84707816ff4ffdca30dfc753c2cf883df16016795db34359e9363fac60624ae4d2b30bc1f2f99c23d953779c22ffca145fd08dad83c0f76cf727196799544c6c07483e0a41ca2e1b1da5a730956154f531d292b5a39a229ab13bf24a804eb68786e481c8aebfd3bc557afceadc41d00e1472c3b80ce652be1245089283bf1a1a93abd3325bb6eea121db8c0e1d6c0c31decfe9dba63c89b881824b0531651fc500f2f75ca9e5fdcbb179c9ded5d600a495ea704c2709f4a88c4fadcda4cd82a5b089f25a6fe0161159efe03fb5e0d44bdb5487f25e8c9adacc389860f62b06a6a4f8f104d9171622f70652ace736e8b28b70a4d9fd3fa4b9784d1a6e6811150d0a0601d31d17f6041e58a1058f99b80b0a6cd4f79c79a104b6bb731ecc881bc68e1d99ab358faf43d8504957ea0152e46e27dbfaa17d0f58287276e4fa82ab78a03513d5b4c3199d1362e4fd6447d1c26fadbd011abc69332ed0181952b391f2e8a5c89d68e22a7c451f69a9573b6bb6d918c7e3d52116f3f12f1d43d2af46bb450f58bde1732a268293cfd9cf2b90a844588c1979a30d6ac21aaea4b9e5500ef4a8bcd62bd70cae6acc8839f818d23c615e45daf14335c36dd46817c9b816be60c3848caa812b055da33f45bc01721d6fb7e850fb1e1458f27c70bc34876a955aef11f5703cfacde03a039c3b75b99b2d91fc18b00071a28ce25eb169b946b49858aa0885a4c665deca020a3fbba55d4d9175fd91e7901ec9eec0239806e8305f8238e5270f4af5c94d0008f8a5564636cc33c8a3d3e76db2a7915abe798b0dfbb3e322b33e188c7b188573bddbb9e4a7edbd4bb194b9743c4aceeab449f8affddbc2b109eb3d84f3b2f8b18ea2962680437241d82bb6146674ff1abee7baacc38d5dcd688b425c3e3b0dccdda3e36de755afcf7155d3d7cac2e279baad167e2a743b82ff8ddf3db8ecfa9680ddf468339427a4e9fb8ca4ce6f1e790c24e7269912a9989088c65965b0efe68ed44eb26876674261e3e72042f5995f1a7075b3932f4c23a8027d0db35ce4322122f489995bcc0b3fa32b7298c4c1b3354766c866a2fc0ea5690c58c5e08ae7037f70accb3ca7faefc37d78883f2bcd768285dd2571dbcaead813a0b8ae87cc1df868e93500d414c4418d5c80b919f73b9fd46111a02bfc884f9d30ee14fcfc1d55d54256b9572afad4777b8d8172c911472a22e7461f6f85aca063c19d6fdef3351149ee6864e93cdc54ca5dc7837f0ead91f5e3b155795df5dd1f933cee8671ffc05058353995019e5f6f55d2de6470605a5411afcd7fa5aa8f38d77dbf496d7fa9c5a4d35ab661aa15c77ce42bed44763166160ed5bba954e470c293ca301363f5b837406ea8ea746057588c34acf266030864d8c40e2da88ef04c49205fad1607d456767d30eadd884359bce04c12e35487bc1885d9b104c9fd4dea4ceaf054cf46cb3c77a619ffe963acc9bfcfad0447591ccd32cdd1fccb1fe7080ad75cca2e17f695ce0095a774327123f21e2839773506a9f2d896bde87dc5e35512ad733aa408f8a49e9018d1013cc32f550c968a03308cdbc73ab444f0a79a13450d4de906369da4c6a675d7e338f738358dc238be4f047579c8ba7a60448da541cb9e57f22bfcb8c26280a59b77edd0f5a009a3ef1e2958d6d3c3372840dc6a0c6ab1fe86aeb7590137feacbfdc7da57c77595b8572b45c4677836ec86fd8c4ca8ac351397aaa3aa298d752754507e1cc514d41c3f1ae0a692179218141f65bccb9acf6244730c6d00829455d21371972745b3665f930cf2aa9f0abebe6f7b89094aeb4dbdf7bbbe794f134b6284e289c995ef2929fc1bd39b259259950de29e57cdec15c4a7d33ef6e689596a6ce23301d25c2ace77fe699d90c2329da4d0f471bc093563dc735ac2fdb32c6995606a67bc953534939ed1236003c004d3b47590beabf39a1e4d5d1b00898496e9effda68433da17d1ab3a32aefa3681aeac116c5705077552649153ed15e9d704e67d8819579feb02d91db0d3533182ff43ee5648f5cc9a595ded4772d61e77bd9bffd6f29fc1f478dea44c32d5ce3118bc8860b254fb0bb1e85223bf709a7c0b9a52fd3914f1b1f295fd246bcb568388dee43a32df45e3c798068608a102143b5511746903255b98238003eed68776b46bb0e64af6c9118ecf9896709aaaabefbc1f58bf45b45768345b560ae2cdbe4d7da497736da8013c4098addb4258cafe7823bdbdd715250b707b155248d39fc6773639e4de3b201fd3cdfa1526c4149ee7d15bbee680c956fbdea844b1470a287d430c5c7e2d7b51fa756720397bbe214c19df3399a989958732d93979e361f7266e53a59bcef695435db67cd8749d258e7d582726e1bcad1395e68d7848849fb6d74451a53ae6e8989c64701102959f7fedc6a5cf8352e218396f9181f33037ca74886fae6e57460bbcb71cbe4cbb3d3a81e2090434eb1d6d5baeee4ede251952ad88001ce047279cfe435a4afe97847f798d84ad79a11bd44f09222d2f3b7fdcc47ff8a4c61f40c4629a0f603193e0aa2164579a05726e547c9081abcc0087907f8034469f740a020e19623fad42e9cea64068abb3d6ff2f6680da328061c200e1f646816a5083786ae5b71728a0e5cee14d7a942379c389fa9dbc7afe7e7ae075c061df11e4587bc90f92f1b077c091c43a25e7b3e870ad852c2883aba2632063c4ff74a857ef7267816317f823a8bc5dcda311b513be3a40e6bdeb89210bece50a608e624f00c9d063e0c8878884e45527f50a3ab4447a9a01652322700f087b6f96ddbe96a68ef98656800eda6563015a6d3c0eb1b6a9b21cccd58cdcdd074b73e40a098a980210ef831ec9e881cb42ee07519fbdfa52d9c62766a2046dee7752f880dc9082ed7f050b49ed8d14307b1b811bd87b6db2419418e49885d20fd7ca8fb45a11a1da17ac2304393734b552b5d02a303ddc72d1f456697a287851f207054c18a6262f5349348c806841d21e11fd4e4ed9c01fce1688483e009930079f7d2045a34f98ed83256dec66400a783d58c61619e6e42f6e2c6e6fc69e76651b96aabfe643ac69681955ce595f4696b80dadd1f3910061be6ed0840d47e928dd93e7c3d6932d3ead820d06e2539d9a604a6b53db6bb599da851de7cc060faa9af76d708a9aaf371dbc3eff0fdb99702504c3006f789a49feb730cabe40745837e2c8c17c77f999333798431231b337357637a5efd1eeed891fb7475f2c9f960e67578adf50241287bc5599ee08d0237f08c86ed9b75b62d612a9353e48cb4cb022d78f73fba1fab7f794a5ff64c97e6c91ec464847a81e5a5253989a1ee54a41bcd9b4b77bae6e72421471a7ddf0136edc59b72402d57e542916ee47fb3988b7123c6e8debddff2df171d4ce61e83c3d41f36143c9df97f2f68639f1bfc2a9d1fe175fe9f45e17e5cfebb330d3f06e15e3cf58acaff09ea576d896359a3f06985765824bc499319384e4c458d4326db801c564b0b503552bdbec60752b670d82cc8fce9028ff24ade3e805b81a72701b37d4ccedd72118b20d792739e035bbacc4893ded88619a6c499f246311947e48684a35406c4ef279c71ab2a74f6e5313f7900080f19aec3a39109d4aa41c930c66c84cd2163f4cdd59fe84a86cd8bb6468bce45a56d09490e032da844e6d90b436dd874c1cd32a75d1ae1d3e86d8a2ef948649eb56dd7b360f55ba5dc34a12f9279945436c6fb83d1ed57ba4ae1d9342a3dc2df9baa82fc9fee927c13439ba5bd2ff9f3e6f577b8d2df731db14c51db8a14bb15bf3e125f1ca4cb2fe856c5a576cf995db5010687d0799581c5e76d400c1855bb46680a631cc582f51c589a831",
+ "823d0cd34e7450550da9716c1f456ce0cbc79431483a6214939266581b0e899e4c95719a09c1ef166a618289a6ee6971b6fea3fe380512cb977823b387ac51d341c26d4a835c61eebde37764d2e1d588df7886177e98e3151106c898b3196bf4dbd83f5f",
+ "a4639c22fc7f370d8500a53819102df5e86c541c0ca10e8f6564e50b90c28f34",
+ "34a04df283c45655a52bdd84",
+ "cd8d1b2e5f65ddb3c0da8f12096134da22ad4d541444964077610aafc1f77f8da5ffc75bee807541cb6eb0526e78d57fd88fa9d9608914cf391ae7ccb8eedb0aa711889f9b6192601163b271c90df5d69fef487b6c05a24fc667469cf16cbd5afd58fc830119fc9f61b26dd50a96ed84c96825a615a3aee84ea4c950152323b20884346b25c9e2a6be3a93505ba059fbb114c224bed8f05f54eab76b2c9c23a0fd942eef9696ff67484b542c8347f1b1fd7df7242872b3528c9e45030447b2bc85eaf191963291e4223b75778335e5f1256618ff87bbd68b5a9e5cbd2ca1dc8aff4625c834edf8fb0d879b1f75ba9b85895a6bb4d7569a41bb3be6cdd020065bcc69b44a8fa335d9418ea2d090d8061e042e8e1a6ac03a6d5525079f14274079734ed42c5c9ab9986f0fee6bc9ee6c485e233e9b4d6de70664902529a135a5675ae129353eb2c00b73f226e84fe8c594272d6eceaca28b6da30492c92074250ec80beddb7208f9b5418944305b0864009b3bbb3dfbfb4cc2bba3313f8f7c6c19860f1dc0f5d7aa06e3b551adfc63dddac980a79d72bd2225d54a87a93717291c7b78bdfc5521f7f3239d5564fe9c9559dfefe76b77efc2e75991f31a0134529a6611ab9ef076491f2d2d81ffc5774ba8f8009dd7e5881e09ddf5116fcb5a44e576aef6cea91ebf52c56c742049639392cfb8b280dc2229252e04d8d394ffafa539290acdd8118656e7e1a4f7bfc0bb689448379e8cedff7590a09a3f5a29bf819fd87297b96ca07431a29a07ae126eb9d65e21824c16707db89868e127f17614a536de6ed268b1600a8b02aac2bca54a09b7cccf8e184448df334f95b9f0221187d56da7bd422f09b4d94228098b563df53414a5a86728962a2ea63023d8c3f03847b36db7cd189ccfef3e623b14842b8cccb18b4f80f01b32a4cec48f3009b98ffa25dbad76089c8700e90848da74aeca81d01f4dab2b7e844a3e48bef21f33c92734b821ab382bdf6d0b1048a9866e676b78ac9398678ff626d5c173a15a0a7514b2544405dd54eccaa2791605c87d7117bc9f8c0ad84623a9d3a2b1733304b492d4dec38f7981db9361b03a2837a95fe937976c7f4341a802dbf583366fbe368a3af3f92618046bb55696cf7af1f465a5a57ec5908621f431ffc762f35abe892f772a60a3f75ad8401321f67981e90083fdd1cce40903ce56a629120d6e13c8871523c4d848664331966298c8b31a5bc8174a8c14f61cbe98ae7ee3e90bc832b04318864d19a9b8b6d49a260f42bb120cef9afbe704faecf0f428d917ead9f020f5e9d772bc8f29600f8a7623d8971c1e3c5f1a3b094191e497bd70f85de124137cc4b9fe0617cb73cd44b89aada072625e25976e7aaa5a8fe9d9e3f32db47d1565aaef0e84d256bfce6aedfa1a2dce5a94976a2bb9a0da95941fb7ed444990b0e0e87627e35f3235a998019650a5e5cae804ecab8cf729a5c712f1e7d17486082dd50cbeb2ee1b0be6a7bf08a66ab3cf1fe9f49c7083f5b8ad183f32fb35fb8a41230e4041bcf0e5ef54bc3d21ecc1fceb08d95d745a997e8f2fc3c0f6b1b6c1c02e03ff02ae0d879d13eedd42d9f9949ca7ebb785764162ceb6c6f9944dcb3927b2f4eab23ab566b2b2bcc0c7d77b82579e88203602264064ce98b5b1ed992c1bb13edce579ae7f5e11697b493749f308b33e47512533350df5c07c3dadff656197884f359cdfcb736d29231aea1524b56e06c92f5a98ea663543f67e44003f5b41907a951dd792468c84c5e0e1b46149a5c9751295e153990b78c0cc712889a21b299b0315150dc50aa3b4f7fb0079ddd39d263a754b1dcc595c76ea9fea6c120384afb38d4bd40491c4689b1afc9dd096dd0327c84802bda6bb6b7a8830bc6c06b308ae9665a8666a5551ec954eb72adb827ef38f036c51698a28c92dc1c9e25c267532da2c04c1bf27f5b683ac750c3ef53a8460dc186331549bf82868f9327422c09afe1cd15e161bc41a70cab2f973efcfc8f01a380b86a432e1ae540e09d404d93d22a20dd5f685a52f0acb863dadea236288b1714700f23d1c19e40e219e8ed21f6a393e541abba850ffbbd4030e5f6567b7202fb66d86cc2a0beabd495814f6a50690e8d74cb8b093e4d43261fff80e7a67ca06dfe808899cbef84c09ece01414baac740cbe4c656b17991868e2a136f4785a0de311aeb18cc95ed33fbece22aaed8cc1e47f58cf6c09a6f92c96f37d2d2485b369093506f5e9f8534f8569655277d0399ddd3d33861bd40c71ac53a44d1981cd744d79202322d47a0228356c0e27efa2ff1009cf2a416fb6e8844eb76b8077a4a3961ff193e1c95b222e72688ba48be82ec5da498e58861ea613782ed1ab50a95b5cc236834af98e61528ab18453c20ff978551b81e1bcc0ff4b7092bdd9ab0b946b7324b7361ef05e1f7d7f6a336281b4bb2c671a95a6ab84be6bef1b9c8c3d2536edb8d79b40637e16d7281ec5243016232d7c9fc07ed9dfcf555055d8ae65f12ad150da81f62f2e1e82b3adacf6d623ee4759ad61a09038905bcf1dbbab671dd28fc1d10a0b7eaaef73a5862ab449bd84c8698d061e79fbe52a86739ba945a01353e0f3916667bd7b4356cc65451c7003927f2aa738d98245760550156dda529be741ce3ae1afdea0de35ada26ac241fcb5d518e6ee7f9930baf88bacf8bdaccbecfdb920f3b26285439912a8902ae029b07f28c1dbcfde780cd2bee6c6e5f4520c5c7ff3ab5448ec86cfb270c39586f80041f3764b5dc77dc5ced0695c89671cf90ed34c4067b4bd938b1493c7902dd94be824810a00bbde4915d138fcc7584790bb0b6682fc0799cd415441ac90c1caa008c7fde3ab4a3aae478c64991ebe07e6c4587d3046c9ebb8e125e795f0be9266bcee5a4e4355a2830c5b34e583b0355b34b89c08011db6f6b8371de003074704e8cdda37ce42c7e395b6a37bae3dfbe67bcfd1f125c9a262d56883ddc028773988270aa30c6dd326cbffee589f38286533e1d5c9486011170be591beab5e0ce98837cf91f0a58d69d872e364aa88daf9cfa71bad167129420282d99ed5884a1276dfffb2c4100c74a8b863b063c07937f2e9c12523deac4ea16178863d975e3a5be5efb5ffbea994d07f7ddc5326bed1f5c9415c1d4ee1667e3a581499bb573595158636ad94d84f7c6e4b8efc2b141f2bfab7932a050fd88a8c7b21877cddd488543db5b11138cc808e1248b6e2ef492faa8a32f9d93e3c060b5cec10f03794248f9662ed8c283a8e0eb493824e2750ec75b3b1292d80ce002083a3c64cc487afc31b20f84a778f386b012ef7bef46e638d0f1cd75487ea46e05621d608482637b3e642a9a2c5371bead4386eff968b3e007fc263086d8a930dc76a8431a4e6907ae35c7b3291075d1c723f02e4895714803c0e97d65b04c0f27d01d5d68001bdb3bbd44dfee1eff1754fe8c182cd9bc6ee273beb2a444ca1766f747d86f36cd8cef6eb1dafe0c38b9327a8cac6e83e076099188f02721cc4de3d940c3ef19d9b067be07b890c798a79ee8c44d96c5e05ee5d5202d941a674378386233a83bc85134dc8c46a7531b2b952fb277d8089cfb13e882bcf7545f0605271fe38bf4754f98dfa13fe6b635a62bcf962553882a8f28a9a5fc0b3f85509b702d4a7555d40c4f7d10fbe80d48b4826995fda7d15f14aa9b95fc6526101cf09c97fd74baca6bd26b4fce8a57b0726e0f68118969ec067e9ca39b2ba59fb0d78eb5cec5b872613b1b76763b3217d859bd6d991bbb5448bd4e49dd6597ddec9e46afb3f71d254aba828c91de51904139ab19138e36e6996a207da80323d96077c97a3e8994296376d4dcb602f1e77371efe8b020b7b6f6f7bd2bd733ad9c06c45b77a2893d73b4a8a57707969af74ba06b2fe7d4079bcad1cfeb3689ab95c8b1215fe0a855eb431f67df4ea589dadbf055086924e42cb142c9031e25b81e8e1167a54008ba1ad7fec6794f203b27f3092dd72bb766c9653a72b2e25c965f53487cf3baf74eb7742702380303af8c0a61cca3eec78d4b709e35e2cc5bd586263d9f56fc12454547bc6165e3f070ce7b2bcace5c8cbf52f987568dd90237cf190dabd4ee7a80494692a5379b013611f4eebeef8e1ab9a9c5ba61926095545e19c3dd61b7b404230729aff7d82b6bbbed6b4a926f6e49189e3bccb578fcb3537951fe9c78ac842350ddd80133275ac0bce3a669183776fee8288f874d29190b452d65bb7d8edfedc6fa0ae147102b92041af6dd8a566932e016763b60a5b9b1e3667f228cab075f966d1c525ac19d12046c6409345799adfd7154b6d8b51eeb1eab3a132ac6a2e08acd1a34bbbbdd019195af9f8a93c6ed5463765173e669cb0d42b6cffee1a4b45987853d43c02f920819f45a4fe0905d8c65aca182b4bf56fa0dc51cb53c642fef003d92c13ef4bc1bac571cbe2ba3673a49694f6311b7dfc17a4069759177930b179748d4403c7259e10a5d221cd0a6b745966e598f894e607b779dd5289fbdae0b4348141ad373a62c76aa454b35b39a7be875598bb30007fc300606ee2537cfcd7c22b6149880fb3cd8eb53054d698a0d20f26a5c3ce468255737a68706784",
+ },
+ {
+ "5622aa8d2f308dd468a7e4959ccc01f0e80d91f79df65b8201eb44911f6abc758c6703bb97908fff377395d33f96c328a4541f414b7ac34c6607dd85729afbfe01feba988e4997c6bd2c99fcc35d2467b143a8fcbe6b49247226a9e4c0a4e3c1a29d5931e6f1f7a31d90a0e0edc4479f08ef9bc65ae4eacd0b93b1cb38948dda31e60b18d702bbf5935bd580201d1f280cbbee679fd834aa6be576a37a037eabe989c3c18c7fb61fda8b9ffaa8bf22b57a101c19e850c454353af7af3d755b26ff1ee78b9d9daa78294972d108958682a5a29c8ef260e2289ad9d7d74f32fd4e51e5d9ee828366abccd97dd56e035713a6f3a1985383c0ed5d98c4accac2fa1ba7d30a295670d5224952f7b7554fcbfb426c9496f054834dec48f9b70af3d2b1c6dcda1c4daf3e9601364e57851952c785e65d753be1c22729bbde33aeb1e4748dbe90da6ecf716f05bfc68ad819515dffafd33a909562b95140ecfff1d0747f8e0459fcd3ca6cd8893262614bb4bf4b639285f327e7ac782898781968ec98f6f0f2f3c4bc5f9c4691ffa7ddb3662816f8ad092095b598bd4d10d6b5fc6fabed619eb11dfd4d638f4c0b6cff7194156a411e8ad6d3229320336ad52fd9811c3a1fcd571d1bbbac67c6186737ac7ca1ed9b2bc46e4e578f81c164b09ae5cdd4059a2c22b5e7ce1dade684e49200867f9bb1430aff9b99805cfd31f7e3fecbe898f70a4eded86b8bbeef7050eff6cf8ba71395a7ae2e270a2b58010e56cdf6efc4003da3d8a82e96979ee68694b6113cc9a6e377d40a810063830eb95005a81405e5b7de8de67424845bab1911bc55da6338513742d237a555465fa54b07ba50ed712e7a57a39fdcfe4af50f064ae969823aa1c40cd86a621ec90769d0c1babd33e8388a8bd76689215b9827a5819127bb32ecc80a562a291f3192eff34cad2635e5b0c0bc174add72e2041864953f1fc72be7d28111fba0438d9036da3d5c0f220ccfde2319bb96fcbfae6055ed7f1c1967ee9a78e93bbb77cbf151084d602a5a2f087d49c3134582c1a5d7af24f4c88be26204cc9dbf4368b19470fef49a5823a2d66c65e9b1e8ab56bf5a7bb3220696840a6222caa58a7b39fb792d95d25038a8bd9d916e853cc5459640f8b8468e3d51f05f1b95e996cee40ffb7ae14cb289094f1b77d5573c1aee7c12a6c3a1e31491422f272cc5f510d4f18ab63d3c3f468c5abd61b2fa7ba0768d46392e2a4dc06c7ce79841dca916cd33cc0a700b50fc660e5d1808d8b87e65feb89428055495823b2dc317d6d9e50aa5ef7ab14076174ed32f56abe7d410e58ca40e92f8a31433d0d74ba7b130b1561f2b075fa11ead744d031f34d82f1a64d428f6cccb0a009be24b42937bf3e99a1ef1fabf0fa7335dab52918382abe756d3de229ee8223aca6d7c5de87047838e387d4e472481a4cfd4365256e13aacb518ce5300f18dcb5e0a28477a6fca08a74756ef6bd8933bacc98d02abc7ae60df7cb3e06d41abcc4bd313c543ddcdea2424d98ffc6dcaa83658aae11f5841ffd4f5df42368a0e815d2146a0fe138b223764b133d17cdb08d485e9f3dd2bf2b220d1f4565b02d7b9231d592130e4436849f49b1a70772244fc0c38da372a8c57fc80ad57828410a5a16ac6d14e093997fdd5b26e4cd4b248e0ea221715ae6e112e1b68b09f795540e31b1231244bc922207b906c4f42b5302dd7474286b653b4d1bb657134bab117d6c349fa0f121c2f8dac9cdcef510c1c28545eae0ab163db6cc84ca182feb858c10153d0136f00a01c9c7d0bed892715dd85c4e73627c3a2ef0f43710dfccacffd1d9f118c9fb1a83b2eb328b8da3e955f027d95294038184f7b895d77532c7570cb86fd6b37a5a66659cf1e330db3930f302838706050c0dcd91d532d49c89d144e9a7f864026ec99f50acc02bd5f11ee88495ee8991ec4723b189f84e03d992fd718b5173ea1b033ab7d3568dc4656648fb54d28d3119b0f293a930a772c394f45ee66838f17b73a94eca27033f9d5c2ae22eb813386905dc024673850a087958eed191d04d05798bcf909eff2deb2a0009d223323b290e3d6f71b2797a2bc2590d54294a5992d629336518514032614a04847c3fad8a7d1cfc2f86765b48cf58acf892f68b691fbece38100e6a71487ef5c4ae934f1ba03b4b26a1967f70ef1c697202e4eb22a3a95ab3b7b524f0241ab4d2adf3ee5e3f2974d0bfe4419ef0ab11039ffc26339570e74d260c4d5a16f22cb4f60b03253487f5e46c47836ce29460728086a615f78d631d89a06790928455889f58adc3d0a3a84ceb2ba9cdb00a403080e6567873b985fd59fd9dec71e375013c12c51cb67d599198f36f58fdaf897e85dfe6f9896cf6d35a84cfdc6834dd9447a2a10e1ffa9fa8edfef1db9e8b4a245b211de49e04b7e88977b4e1ac9285f43526f2452181ee0f80efeb1f6b2533b656519ae45652ccefca81c17714476b497e5d8e9fdf6c9f504c7a7fa7afa36df5f4f8da5b4b973b1618fc8d2d43e866b235e5420551d1659e5bd545fb78a3e17d9cbbc8e842f3fe6be07b892453ffd689d5188f26f9e4c545ba0b3132af12a03bce6914015d026d3d7df661c1e6384bbb50dae24abfa78079a2b1ac41c44c7d82a59183f293f12011e781d3cdca2f791afa5b55a9f2d6139587bfd74bfc54ce91e642847a33b48c1b366fd8f08f520b79ad5113a0273735aee71ceae361a97547fc09b22fbe4e4ae4ae13e52d65e0971341aab368d1e917c8f5f2ac57ac119f981b51b7c99ff2be3e16935b7c73e28fb58d332e6f2c36281228c479c4d6095cf15b14baeb0769191dfc649a70471a25d45d4433797a5b8ba31ff567e60ec4d759d99244d0fb5dfef7c2896809938ddde0d2015a4c5ce5ef6cdb5752da1c2a33e5bc78b6b7c6a5af892f0792c28560a357720da3cee3833bbeda8e98e6a8cccc6535831cfc28bc8557b4181a3978bd90eabb34b99eb7e55d9263e6790ca34561d8c87ec4e12b4a38df524318db00a9b5bbde6f5a8644a818a88e91b521d716fa9f95bf70b109b9905bfca926fd42ecb9114c039790abb0392a41ee4c190536a89ae6194befc2dc4bcf7562bcb84f65c99b69612c0511552f53436b6c489204d3881e1f67e0fba3a061165d2955c2e2e12c440d31556250a8a5cc04ee5e09b1d627c14e08bce1a92df7f6475db92a3ee57e4c16c3ae677c44237122818ad457a29595ab528744707f3ab7ccf3d20bd94047e013e647802a7af14cfc7c11441ea6e9b9f960fe69d03911ad2cf3a8f633e0d647c71dc7e188c92e75353fc953d6a30dd0040c39d4355b71524f1a4872fb1ecab22c8293b54bb22a80e1e3d4c886d2988adec26f041dd0565cfa9edfe5ad9aa7da1d3b8f68fda9e9df9dbe98148120af6ff30e6400deca6dc9593dbf06c856d0d582503e7ffa185f87c6e7ac58184bb80b4a1c0c18d669e23f9791365fe807356a5763ea418c39d94311759b29b14324fb6f3104359ae66532779b825f92b7c9ea2ba43ba7de04eaef7a86192bc93e17286f1b6e0a01c33c796ebed8f17692eb9237173a051c14e4869afda2643bb98c9ac4ea94c6bdc1401c80190df6abe988d2f0b2d80cc7bc8362ba25c6e5df4370a43e156aebd6aaf856b3f64d5fefc622d078faed40b760a361966a4765adb809dbcd74b7a41faffad3a64823860e5656874133c7f8a46b5a3ac591906359aa4f171ef6bb2ea6b5f24cfe25c2fc7c1973bd5d3bb5f197002c5ca1bccffb570f0265f5cd949c7386d961ac9c5e18b5d1d6030d8bf4a48c10f12dcdb11924b02b8ab5e91f425ca62bbe42b80c6b6dde3160ebbd55803966716734327058e29bd39874f2eac199067fdbbe8c372c5a688d3615e2b65f4937b67d6a26c64cc2a9e5379cc00925c678f174f538915f912e85b7014c064a73bcc7ddd38e1a9627ffddb4bfd6da764fdbfb45048c9495ab1a4cac5642f6c9ffbe97d33cb26964a23719620df3d85dcfc392c4502759fb31a6a797e99e51e94cf9bc79ac15de4e5cf7a05aeb88a8ab4c3b6f9c52b99794503f2c49cd7e230a67df7403e552523249f29d257b35c0c7712053c3d9eb583a1a7473d7f296d25a66566e4ba8b08de2a31b082e40c8e5b1e93985b324dded3f52511744e7e99f4e3ffd99d8ae17bb5122b37f637c5525558eab18a378f5e2cb56fa003ed3af8d139d16ec4b2ea79c415b0ba4d750ca2cdf653582ee3b65a9825fb9b123593e36e645232163cabda515b959ed0a1419e9894f6c677ac200fd11babe3503ec7bfa319f1b9559d94a6f82945c9ca8667621a5d28920949a1da644cbdb58b84742e9d65e7f2027b99fba4dec46f642bd17e88fa109143b26ba7fe285c89add0b74a369f3d381ad633bfb4f72e1822ff96aaf9a73b3c59a6e457cf40e17c1198c64737037f52d9b3118daa3fa5cd3e3c7738e3b3743c595893289974a4aa0d6bf1446e70964823a7d5cee67b9b25b7125d9ac5d1d61f2a6947c3deec6deb575e2fc5cec60df26de3c0545e5b79156dd6af33a78552d1ee9994cc8501b7dc5fe7a22eadaf201a92e06ef03be705a8bdb4db65392d3628c7cbf44cccac292c93cb5a407a7a5a0d5ac9fd95b0033d6eb719d3f14609190dd40d5aa1b983cd4c4e278cc8a1e7d5fbb0d39060d6cdce8de6a17e2dab973a7fa594205e17edab6514372eb51e03b0ced6402fac0efd3af49fb8214a505cc9f5f0ea5308d7fe6dec369ba154",
+ "9f522375925222a04f5c95ee14b6386412025903ecad0bc3ab78afe1145136b3a3592835ab4ad6faa66be9",
+ "d1ba82b3ced3e9817642aaacedf482e79bedd0560ef2754215ee792514bbf8e6",
+ "bb21211f342379370f2642d3",
+ "1a6683805d3f478ca1c1512b9846468378f83be27393db63956e151ec408368b47334afe610249182f54c4d0a01b704db2aa90a9755b8feb67ef9301f0715d7d6bdfa5cc4497cef1142a43eeb42f7c413e8f489af30d742a706d05a40a0c4a5991f9e2cc5d9fbca6ad3767682e20c146ac35aef38dfb2a77388b738fa022158d5c802e5f0761096bb45b50815ebf09172759521b5c5d459703ebe9ff669ee4d14a86e5d0650b597f4a082ba0aef366a924ea378b91c3262d99f48189eea19c76c0f644079f8415c11033cf24d30d6c149ab13ca5c29deafdc816e457257361c1af4b915da312d2e6c7fc712faa27be3e67c893f9005a0e2c28369991c1dab22d38961d1abd6d94c4d549cf491aa1f8d522be3ffa6d214825a5fde3c94c4e35c29b8d05b2627eb12c9d94f450a85eec6bc963a279a37c2344ca36eb604c4bd11c2bf2ecc0dc16c2c365bbbcad3541bd54f8d0bdbb3ca4a087b62fc19fcc1c13984eab807d2a6a1386643d90d412d027bcd0a638765498cdbb1f4cc1b91b69bd241eab3645f225ece85a56e5008d6094041f8cca6b9a0ae3b15585de6fe0695d79d348f8619431ece40e736957a7627224fe92bbe30df5124f476d97e36b5b08b3787e8e00f0c10013068eb156f82f3494a35d6edd5f7048d1e91954f1013ede22eca8b4ba41699ee08decedde87139180a567c6d169b672af0f12aa09ce20e9cac4e78b8067d31ba4f63606c00d1d787b868cf7643fbb170f8074667c9f7584d36af80b4e6557724013618c28d0dd40bfe9d4b25761b3c99558af528c2d290d04b09821bd7f992c044dd61dde9395bd0c9ddec6d0bf6e044ddf0b4b2d6753f5acf2e9c904caa4e9f310578527b85e6738803758da646919989f735b09c9a5744e63fed2c3982e59fd29d2baeb9771316bf8d29213a4956b66c78d5654436ffdd82d0d572530fd09507b988d13fd743f35333237681f8abbb301a8ea870159f802a57760659094d0e4902036c5a62c563f1fc86c4238e1ce89f5176ecaea194ca112fbdeefbef4fa7c203678cafd34486fe58b2af04f84a1cb620c6e123bfd96301e0a5e5e5abcc95d28b852d0cee2f51faa73e42f22fc335f50de4c3812ee14038633a195083f3944284c1086c34995832c3cceb7d385b4ce86af10685c16005495121105272d1d739c584a07ec7801c3667bb280987a8aa41f9537e9d1812a5dba5b385a0b71d2e9573c6f3e9ebf0bf7267528946a6aa6f43efce908d32525cdc3b825bb11c7239f1de412704d24c17455b9382fd6a873180f0d5d44dc449320973d5cd0d4e67e83946b6ef47e5fc3dabadd80751f1421404e56b1bce748b7bde63c6975ca81f3eaf52586a55242c9745dee3f7c796d4508e818eaa4fa50490c1a79624561b98d2e1139a328806414c905372356a22393ea0da51c83957029edd8c2dfcf46d9564264d74c1c0497034ec018b1dd4c14acebc34b6d2c1a616937c37b8b4a0ee5dcdf787a0de1173798ab929b72e0fa83a6c9b9a99d8024328d9c236a8f57550a4f83e8071eac76adb55939f85f5b5f514174b670a3e8dc2b54656f6201940a81fe4953d2680ae4ec58635ba74d15efab3e06dca6ac269711ef2d4dd49f731e24a92a3b935ebbb3fe8d001cd4062669ae4baa62c2947033afcfaca227d88a11769f87456d5cd1bb6606891e71d63aff9cd5a7d23263a78768ac2ac54ece1441fd37d096cd27e916e68891137fc3cca427febd1947cfb4d7ccfad75b2ec5e809c132111eadf25a73043d68333139bd2435de9941bbc61c5c509897cfc19a21645019eaaccb6d06371e3d0570c09c7556e41a727e44d9bd672fccd1f89cc7d58761c16df8fb75fb8a1dde2caaf088f02dad91b6489114398740e6798f3ea8c7b0cfd974e160a0106d703d9589ab09aae79108e3212f19cb950ea9c0798a1532bc2a065d5900a12054395c0545b0878ac0b1d461f553dccfc2a22bf254ced88dcb538e3889549960b77ba6237ab1458e158f4f46606372e797ec9d9ecc6534acaa1218e7540eef11030bb9c3e5a7816f3b33a590d970619bdd2dc04d5c6f4ec38b7cb4d525234b836eab57f65dd045e02367eede9049e219b8712b8d6fe178080c5f77b821f1a475259ae571a5578eb3b48863162d45486f71a28ecbcedb35b320e5b6401f9e7870aa5418449bf47502626e1f42abf481b48d5a6819c640bfdb64f873d583fc4e40187940a6c3373ea7b47195270a8657898f55568985018abcea9bce1c155d95b426f91a734b2a14ec2c7ca2011a4d30019fd9b3ef63a804e9c30c3de2651c4213e90285a4ba100b31ee402e8a7f23cf9d4dba003bbf982526bc63be5af102dca34e7d362d6fbf6f56046160d7af33b364f2a86074d1c0fdd54aae89b19480efde2a9caef9de7c0f9491e1cf43a48752cef405a0ff16b0fc67bbe433a3c1b9661406c3726092efdc076febd60c436476f24dab1b0b8f8893986d951ed72282990e8b1526f4dcf539b22c01c6a7eb5577cd540a16a81296ebeeb7ddda72e60fcf2840c5b42c5cba30eaea5402f267d1d04bc80da5ef0dd2bf3c7a2be986507617c9bdbc96c6273a0c9e586a0c48c98b4552113149c6f79557fc8ace0b1a512fec3aa09ef191f95c2163113ac5cdd940f0c2120509bc53c3ea493c54703effb902ef752c830c61e85636ca95429bf16937bf6786b3eae1b277bf08dcd69f521a0078d633beb33c9aa0cb33b238e1021ca67df122a403a3698452740bdcac81d22ccfe4ab5f835d1961708d1faf6d40f115f16c6094ea37a7ff15e0534f62c19a6f4ded0967be337cdbdd2a7c58ba16ba2e4c3686e9d075c6fa7d29b2a0335ab4940d2a95c4500295f4db84ae65e46c54b7300909cc5411c725a31fd962d239aa0e2007c285586b4c778e2ac7afec42cd8409a63d7cd9c677031f43f4aaf04258dcf1270c02a4764177aa66db2d8f860eeb1fd06d0b27587537410bcb641f90aaa7bfc6f12bd143f66e7c933a0f3ce6b5048913e1b2d79eaa6c19e7255d5eabd24d5f12426339541a22d600cdfd1781a1a3894740887840aa82e5a461fc324285b0223ac9b95c3eb88160353f168b3d4ae8a2e87b7715b5fd2671f66e6eaaf9365b3d9e3acd9a749faefba6009783771177aa4dc91f72fed7a5bf6b1b7738b84ac0a07b4a5a3f0a9134a39e1e7e3e2f9a92d5644295f31c5a356092bf07c709b4c34305ebf50e857a4f593dd1cce0439d3fd125c1ede1a48f583bbbe0eec7058345129ef78868a96f8a76ba7fbfd1c5eebf75f3e0eeeb9db87474b96f321b87fffc02433513fb467fb74e2fc8feb498d51530c753e9a173e95e0edc5ba9802641a45db281b2e2d87d409057b4fb1925e834e90fa5619ae3a9237d5b104e7ac67c2bdc31001eedb4ec7064b2f72e0379bf8780f67ec4b195db014a2d130e77b1778efe3dc703f1310a566a6d3b5c9b12b1d4e25815493ed1510a516a31ced3b64ca49a783ad63ea71a57290727fa31386d2fbfe41f12d36a618c6c28d8f10405eb3e0a33e8ac2e4133ba75c688c8c9a2bb33c8fa032eaf3ea0d2c27bf89269c4aec55f8232b292e7fa9fc24527184f19187d9d8a3f52335e2feb5dc6d997b9b773a79a31db832b752e5738963ee5d61a1b426414975693f986e165e52d46cb059fdd4f48f008e96d4c1a48306b7c002fd0c861721656074cf11173ca65cbdb694c79f58a3f3365e872b24670b691682c10261eb1ffb2b65da031d070e31542f49704b77970a78bcfb4c4ca517b4c966a4e8e27664704f633e90cb7d7917dc1d3a8b8b7fcf59ea3a8a81305761923cb182cebdd59255803a14ca8a75fd007670d79a25eacda1138d67a0fd1da981529dbf182fc4d7a700ba498e4476a1d415381c9e2ffa3bd46201cf2e454c4aaedbbe3893bb4121a6de02cbecc1f319155eb8c99d1030103bb6194bee51e74fa01f28dbe16092955b9599d5c1f1c3f356e26d48fcad7c4cdf0eef25c25273dd62171785c9d2c5a01b1f3da9b4786b1b399d890e2049b73c12de2fb7177f2bc3d9c645398111ebcfd83b73119897bb994f998f4a6fae1b3d6361e171059dba0bf9de9af7a5a1b21641790baf82a36278945d649cf5d310f3792fdefe8c58986a48118fd94647b786e47733ae703701e18992bc1b143b1da6110a98030bb9895c14d7b8eae1a155a550e219a5b6301b6d26d7956ecfe4c7023eec1ff62538b3606ebc7906a1243bf8357f593b6cfff32e3fc6b51f6a0ffaecb658d526f7a5e9faa6294e4808b779f4832318cc184e49e8957b72bea0d67366e040cf76a85889fc6b04e84afab0d02947d0d83e0de19f12966fa8372f6e82ff402bd7a69195eb1a7864a3375aa9e23736fa4d4b0224647e416474c01f72b7d4af240d7f43395b5b04c8fdef1165ce1d56ee8ba0e350e6ada893e0594facbfb5f0d8829ae203929525951584c21371b86deb0f76ef5daad5e847135a6488b35ea33e3a165fea502975d6421d4567a229bf3ce94605885453610eb9c82f9ea743bee9e14776bc3076a29af268cc72d9092a492d9ff08c345dc2eb2f8003b561d9912ae1198c58107f8b37a08b35075af9863110e6770425e9d59c2dfff9d9942c8bc3bf7904c2a952bcd573706caf1ee14420564ffc433c0f5871c4bda916f2530ac75819ade49fa1de21edacbbf6b7075dba21a84989411c566b7c356b81803c7215ab0f326a6b8910dbc62c1bee3af51f105fcdebc0dbc56a50b22cf81eda563bf8c2eff98b476e8",
+ },
+ {
+ "99444e82c6c4c47070b164f298ffdf6955ee5bcb3070b9aa95ce658db4db084d2056cfe61a93568b44ba7ddcba5d450f4ba0da7b119425a6628b3416663c638692326cacc5c237097db5e537122b465dcb21d8dcb5fe831789b72deff3907685c2e23187a56990221e755930a09f8d6cc065487563cb8cec82b9dc754952fa0b342c92d99522fbb39854e338f470a4b4d5ed2a39b8b6253b7001b0b953abc588d757616c7a5d1f12b1024aa572ef5a47dc8480943aa6cfaaa78064fb2b29830280e46efa418d0cf38f57980146f2482276c9b6b16f865b1606bf1131e894336979a163ba2e70adbdc746be0d38062fafcfe5603e6bbb55717b66a263fbd5cc7476302ea4a0dc6167221f745a26a309f5886934f4258965a0ef0803eaddd05e54008df8a0695a078b797be59f1eef95a658c99a7d52001d4108212ce5f18a39f1173291808c980b0513f1a531e03ad7380372b65572d3967af4c25fe54d99d664cb67e557fff05c12e10143c13b1bfa3e8db093ff832a7978ecd85d3971349e3c9b83939b73f0ad55f1f1162d0c106b99c0ff98442911bc15e9194f5b4ded97e9702b84e31b31380c224f392e5fa5c720a45f64cd7020e25a3931b5871e4c708e77f4729225aa9f48f9d876597d3e79219dddee0efdd16836021dbd21692dafe121217347cc128fc5eb051e6843978ae17478ef714957a84c74656ddd931cbeb43e32fb0a448acf2f90ee98d38522b4fa9aa36be4fa13306e799d4c0cb90ac0f73cbc018146d1b0d6bf48aa446a5e3e0502aae9fcbd196b36b6b7426fc10367febf687f05392fdcf878863de2e47be7e625d0e3e3e94e199f055c0fc65f76c41ede43231873ff10eb854dcd6ac9b550ee8533d16f81eb0e86471d4da69311c47255e78ac8e79ab36ce880d6b135279fbb5a712adc5c3862a356af49e9c10d5b16f4e5dedb80914868111e194745b802a0292c7c8564de28ba8e71a44f7eff6573e5434e65d496cde5b5e62cfa9e2e9ac85a164dbff5767983e71dd2661d37d9027a27674ebe3433731a606db88e0880e91ecea8134421962b3f68915c9f6a5e1992c56750f99bc313fb30cb89384c72571a1a6a5e3c01897b691bd70985352217fa8a67f3252a06205bd1a9931d1cea3736559572561fedbf3ac4c8bff9ebd7f3753ee69a69ecbac4be6357db7f4213b697a828edc716ac01da75c1d46098c7d5d6ae6f3f9a2903588c5b340c9d47c234efea21b700cdb8db4279afa2117677e824e627bf0f2b179c864ba823926a57825478395545f130886bdf2a7c55a2647a888c3998b750343d9cdc602e46b7b09a2fe9ef74db1ffc46fe27c254c927ce51b307e96a571da7f3f907223fbed2daedbcc96197e95edde7859f3b4ec6099f791089e368a68a5ba0917ddf4f50b93c0c839ea36cfc8053811f8fcfe6986e5fa9f743119ecd6c3e5fea1dae3ad7eb465a89e9c68569190688a8d56e4143ceea3b11fbd9de67173d5134ec8b0bd7d16560ba2be52345ebacedc01a2e03e8183ef91317d87b2e15cc6301586ed829d438e4ff1d074408b332c8ce60ccb6790ab08c228807509dd4b39f2c227755f6b039f5cd413ad6f46c9ec2cc6a79457529d297b1d9e74ead9bedd9bd652fb31568a8e2a9e2b89e4e57601bc1d960360232cdb30cb502b950ef930d54c2c0692a684cd44b0472995bd2b41dac1553ae47216253d6640d2653a033a862f3118c5b5d60a662d240bda5f4da51092eff514f61a425c5b14b19517ec1b371d240cc30a0739273b34f18a72a69b1586802a7caa6cc8f5817a8a995695d063c9dd26c3d45feb0f84dc8a0773151cf9a537664f942f351599cfbee0558f441f5c7ad320cabe305f9aba570ddf6407749b6db42f9ce94526a8f4170e735b1dcfc5f0e090af10e039db3747aa9b4f1f26acc34639ac8b60557f7753e2c261a29852932901a4093b7f307319cbb228e26eec289898b3f8ee236032163293b8caf64be3f7ffed236f1da688d958a1bbb79dd45026884904bbb936c1ebca7aa6b0c68aa8b667dc1575729e4ecb4ffa82ddced2f4571bf902c52fc4a0ea3f47aaf5c243ac2a1fc19f825fde5d9fc8d06d97a351eebf4ae1846aa62554d57cffdb3f3377695338f8d598d723289ff3962796e8065632e7da9d8dffe2636cd23eac15a60568eefe3e77c561906555268cfc1e9342417b1cdf090cc16c79939b15a9311b0210094087dea22833f74eb0e35d44259ecf327dc84f3f24b8c2bfce7be0d97e00d2be88a150a0d557ff963b4cda60eb99935951d288768b4b2649b717133517f5e3909744417c9c3102c77ddd285976cba2c89e2b4f297665632d7c8652847c4625038a6670169772de0550066ec6c2018f503cce79a333ecc0a0632334df6959d2e3b052fa47c5c84d15ceabdc80bd6be0ea2a5a8d5e374e0e9a613369ca8d4cae3d9f98755560b27b2f6e47b01ba390f5ddeb732c22b12abd225e26ecdb639b08f3237e488430b3b39f0b63aaaef4907cd003a8f2b4c3bfd721d6c3fd3a5f062d72746606a529ba34251ddec4026f40d262e9d527ad84fecf5bb2cc8601c2a38437098aec2335104842ff1c455e5d17c136ece8d461d7a3bd9a60339c22d71059e09b3603c0565c0345684893b56054ec4d3db0bf15546cafb4a03bd7775c3157e7676bb7bdb7baf3100396c563eba1a12952503eb6ccde6b6d0a42d456743c4ddb97f5994fa08c5fa41315080eb6b928090956bfc6252b232f6e0785d233c3adcbb9370b59c35b0dd66005d516befd1fc843df8e68fab19858b91e2aecd1c8a88b0fa3d4c2fed2995ee87e65976b755fbf44ee183f9fa08848bea325807bce0b7b61e03e50b2c7af9b360532a17a8250cf6068fef0198738c82a5e58961c54017e343fcef7076e823d63b4deee472fada7989ca7a213d06a4e3eb2d44b16e5c94b1588321cf6c45a5a792938b058d667e1730f8386dfedc50ea0a959b78f12f2949b34b181f90bec622515227dfb8a5f6e89d2e559c0ba686153b218d2c50b67503018e22914ce9b49d3bdb7cf38172db1ea130baacd640c111614e3db204b3b50641d8978dc14b2afc27a7efa819cac6bafa8166d1c127e2237520d57ad38a80146217a12363cb1f8a720e328cd8f846d379ada43bd4865e4aa633c479bd448d205b2e43befa63486c717af84a733f1dececc127c047850aeeb8ce677612f5966e23d92c1d3c758aaeef82f862c1154fadd6766e1dfc780bb447732a5968c0c78b9af4a9d669338458b57cbb77910a24678092857c0b903152035bab6b1c73f7b667a08cd0d31128888de3ff1fed24866eb60beac19c1b139f77bf0b9332024999a2d56975e691fd7475fd93622119d0d725bb99c1d6ac604d6b6be09d6d29360fff9f84e5318259a67fec08a006d9772b9410ec6abd4cb828b898c625c2fc35c19cb9a6cd3b0073baec7b5af254d21de8e209539f560bc80ea38e33658a68262622cdf35dcd6618b9e272ac3644c91f27d372c6297d8e37201c6a86a7d3accdf579c15246276a0009ddac4021755f4848d10f714e9da86eba13f461e6a12edb1aef2d6117986120750d609682bfdfcb90ee3cde8be54d45f841a6dee2d5b9fdc4e65edb7ebffcf3cc5c8a4e1c6919ac57568be23bd8283319ce11fca3caf968b057432f163f22e29cac30b8154a646ca0ef4fdbc7770ee1451fdde9e9d651992d94c843d4eb2570975528ad9f8c193f7c681a43df28242547010e30d75fca04f39247c77d6c3715c25fc261ecdba16844bbab23e4d0482bd1565ca9b526ada9b8f5703661a84b23070d85f3e8265b2ce10750c5d798f1a8ef4d51a473ff4d2bf4be615566ac796db9fe61a224bcce05c31ecb9ab7bc43a609944a7c9398a7875609ddbcb556296f548a117847df7d0afe48a5b504e85b0d7ca589103d3197933a744fefca795e1e036f964a4f14554d5cfa0261e25d6e5e02f86e402906d3637a2352459cb1639f20faea6f0e3fbc6a39becb1b1b3a791e32e85e5bee31be685410adf0c11190e20b7a5119b90e83f2cc4f0de8898606bb6e64165c95d4c5eae472daa6836a888ee4d9a79de72b8fb47a9c9c0323a2be9106d4ee9ba8b3858c256032a9caba37af94df4c7b0adc2f8478cb879b6d452d73191b0fc1ce944df3f4809cbf3ad46eceb3ba4abd9679410f45c8aab20dd72626f235e7c0c934b4beb4507def24ebbdd7a507943c81d54bc69df578aacd9ed0bfd3b7809dec345ba084d88fa9c34d80685415a4d5eaef9b88e51432b2b2037186baf123a6257e47aa56d6531923d38178e8264dd315e95bfafd8dacaf901e354b0f58f135d638df2c0f32453205c7aaeeedf8c102e11cfddea9a98d3ac7c385d71b760cf2afeb1ebe1d64f0222b9b101893d11a74ed175297c1dfd188a2565fbecc6bb07b56ce3973322a965dc5a675587890cc65a71efc68fdcdf1a023505ef0bc0e6b12dca5860fcf1c6c94c2e2ec3a72b8a019d69c82d36a73738dc3d17d7fdfe992bc8e18cb5d3437f1f619dd318b95d1a56b6d273ed79ab2655d83e2dd63cb6f1f5987eab6bb21a7b13b84e2c619b36b842192c3f82c755d8af840675b0bd67a655d641b1886c3c9c147ac87615ff3e58085a879b21dd63c1616a3712279ec87d650a2eed665b797ad631f0ec312f343979cbc49b99385cfa92841cba12d52777df565545a1deb07800a15431c0987b4a543fd5ed6832e80ab6f4b4d9c9ec419932a6ded4759f5c7630a0b80139234b8d53117acb4452c60b477ad50157169a89bd796e2308baa9395b513a94747611c7978c82dbdf48d716c3ac181ac2b2a4702c02a324bd4c5e089d989d020ebec9963b5c721a95492158f54973b7fc1828181acb3cc8078ac095136d97221c60b847bd2a52427383ab68cd1f10b92738c13203fdfa0b78baa09c1837be2498667c459",
+ "0ce980442336d0f427db869a6799baa6785b5e030567c588e2a7d2680e96c11b7f415fa27730969e0b1c3973b5f3192d4e773153def6dcc09dae29ac44eac7c42c2666a356fd4262197bd5cf6eeefcbd662d104423ec05c19a2e6ddf1834a3445a09e8b1062a1320a5e8ef13d6ebd03c19e1813ccd86fd68b46a",
+ "1ac8a509db7bf4acb80d8d394a5abf47c273b2093f50f35049e749f3e16cb0fb",
+ "47cc9eea11f9f3f9aafa23bd",
+ "088888333340b3a057b05491fb2402301c8654948aa6d5ee1ec75eb045858c22056fef0873d6675f897126052923a47a30675b266ffb6181cbd29ce2da3720e36a227e4c6e53328d789913c0d9cd149a6e49293996b1be7d6c513b24d876445a950e723ade3efc36907c840b9b8cfdb1503811b4044d931a0009b381fd60a5bf1e73d16348cb57eea672709875fb9d56908dbc729d5d7d322a17a41d0f62c9af9a013ab1e19fb7b6c6e7fa0c0b18bec5e3d3e92546c77e3753193389e5fcdb6a6a1896cba461343e71ef7a156b136b27ae6f45be9368301cfade203e9b53824d70f07de9abfea1968b8ff8489b9804422ba05ac3c3adf23ba0848817fa51febab5e9b5500100310479e710b663f064c1ef101c9a5320367cd8bc6e52081a32f070e7d3fd6f4210cdffdb9fcab1de4af5b06a7c6d191dcc12b25b3053e58952bfd1f723afbf570796946c1df9579ad14ea9c8c30389c1de4d1e845c764fec5eb8faaf4c558c5eb5113018c6a21ef653ac7d7f5b6c7e1a8fd48c6f423e9913436202da176a86731287db7331db055508acc94168888040ee37b3c119c8a0d88360241d68745825fe480324a944d56e7cd0375d4d33a5fe7a3863c2aaa899b2d24f65b70bd804039116fe959c32442c9f0b5470463523eb4336985b71125fe5235cbca0c88a6f92416d038e144de5ff8ef6ca749a9e239f02db505bff8e16fad1cba8b1500445f067a674142b6413e9dc0f432242d8301879bfc11fa86d1ac9992ab12319fea8b703e10a13bfd4b017496222be26b56af3ef67610f904f0ca8a3e7cc249ca8122735a542b289f13922904ff23dd197f8883c7ac77150d7331316ef94e0cf13b6ad95070420513599100b0a6d117640b781c622ed7ef7ead29476b3c835bd9dbda2203930bcee7ac01c3b9c89da405ee436ee652ddcc3e96c7f1a94e200eec9a4a226f3cf7ae5725068916e73b61149497d11dd85157f895669f51978d1bea8fd2afabb18d082365daba2682ef623109988b7d0e27ae57bc14d86603f93b5ac040ae52d8db404ee27e6c34cd4246f40eccf9d3f8637a4615a4006918b01d34709bcbebd02ea72958d54db3e87d69e6d783de2f1841029d6975eb11f9b076c247108797d5368c656f888092b82aa81aa26e164e038b359bd68801c22fc107e4083a9d85fc254b002ece9d4545310b0cb22ec1af04a7ee31d210ede4b605dbdbcb70e4301989422ef46edf63f9c96de9cb3f70638b51df5c0abe79b7af8cd97148f2b7bf394bea0f7bbbf6925f83b901b87a6079f2c3b38a98fe1a86dc7f48bf97553701834f557451df4b41e7db984a34432823585380b45c1b84813d6aa21107cae252923fb4673cf660a541e65610ac0127d238285f53bf329b62169f3e42d5efe268dea62578e97da59a58a1314a1bd46cf7a7cae772814130b51411082e30062fdbda1c9e14d6b2bfff89d0379d32461f3b8e833b105f6a89532ae748b5fb43f283fc86450404e8befb8442b65e338aa0408303a70e9c27a1d923d9f2a06e7c6159c50bf2e3ba5b035420ecbd9d0b5fae478eb1ab72fa714f99d00188bb10e60380fa3a3a318c2d359ea3805c2fa0dde17ee52a504f70d6b466bd38d1dd4196be336a9ab4a9e573d1bc6404018a119f688c1dc2a8ed1433e8a8ebf455ce3808c245f0220f0c12d28c771757763bd111ab829294e2429a6f7a59858dfa1fe0b806e986d40aaff934589fefd75ab91097a979f26bc9352267efb2d82c4738e4e6c451b0d5adc398f546c646b9e6b8fc84e91651a1252d5b805a857c7798d102d1e6f90749252bc53588348ecec0897c79f514442fe3b27608c95d0cba999a7e0fbd7f601689b4dc63ecb9ff553ff12eca3e9b26e3eccbde28770bb6aff7c864ad6be77fc09f81f90df6efd0c4025d0916ab5197ab846dfe6121c462761d9cc87112ebbca197b0a222fd34a15b824b7eda06a56a6ffda760fae5f0b527e2798f01e205a3f47947a4bd190f6abfb1dab2e3a53131af95d593bb57e4f4af506440cf20636d9fccc449d9565bf43dec8b6877337ca5a43900c1dc600c877b290342914e909aad8c5f0755bc25652781535c057ed5ab2ff8ad4322a8edf3fc1b5311dae6361a7395919725f4cd87ce0ccba37c64eb3618f9c5a53644ada569b90cd07184fc048f1b589eb29852909e75e7116ef96a268ea85c2bd257cefdde9222d7eda875a2a3abcd3a02a1fb470ba967b20beb54914b8b0c6ed464ba978088d7f8b30d098966b0bde82a8f1210f5d0c3405c9bc73f703134d0b6ee13326f65fa0b8154f4e30808997d4afbd060285942ca1dededc3410a099881492b5730ab7bdc2a4cfd0068f67766d60b5d4945f121459d2083334ac878d067bef644b9ee427bbbd6c9351d7b019bfc051c05ac301ff3792a1c687546dbf6a07a0cf56717374bfa1191c22b7753f6ae02392f8aac9207d1ad0fcd57c5c8b35817574b7dd90a00cab75f508f8a234eabce6618305f94746cb6a8573389d336bb67e1b0d2b6e9bd3959ef344e1eb245b522c35222813b8c6e82df48987436b5592025e9786ca63b6d1a064223bfacf59ada713c2a3116611393aa8446ea79b3cb21e96d13b659ada2d6524686fd46ec66c1b4d8f5ae7831840c9e3db64d528f83a1cef1e0a586a783f8306cb261ed9c2905493e74d35883fcb39cfc5745c282104cc3ce804999231d13e1bc6f2c022f05999fb57575bbdaf00d7a990e17dd2f8b9dfe66a637b42f58ee49ba60f2dd9718d09d7025b6061b2087bc35f0a8c884f5b67a5e18c2b4e857d3b48b79dc7cab6b72f572d22987566238a7153ed6264578424f1ce091fd05b7f14563fe12c76104d3373367af3ed3aca694a21127b5912c0b7eb1ddf9d4a9f03f660d49f7a7f0fb42797fd112414c3eba2b75a04282dcb9645191fd3dbe376e7f60ab40bb7ca1e991053a1912854a68d7dcf854201d1f2c26c6cfaea32e29d80847e6288274713d2ca973b91dab97884326b280c6f06c65b8fd25d314be29139961051a1d8699467d02b67991baabc9b05629660c243ca3b0477362d5e6bf9eaa33beeb52cf399846c77fcae11a89cbfdb2058e443ddd44fe202a3ba5c2efce937d78b9639781b8b2b99077b433189cf3b0733ed73b59bb194c9a98c5aa0cba6e71d1c5522f193defb9e31fd2cd60f22bedaf7008c2fb0b55a8dd52731dfa2bc69b40f835ae95db040cda6a4a1588a5ba4769edfeb7369c1e9a3b1cda293255b4942881d94d771b7b82460004875e71be64c582f2830c5e80dd6de421a311c5852f4912bea1451b0328d01c7029867cf9af99284cdfc1e1f0aa0d8c19ba9bc035dc270b45724247137da5d3fc4daa09e7014fe1439889968eb23fe124f067825d5f7b304f17a983580e009e0e51630ea0006dbc74a30b512cd9eb4d0b315a0ffdbfb581609ea9661b0007cd234ce43c17c92269a7519bfe99c2ca94b5cd3e7654946e67b37d4270a369266db6804336a446022677a024d44cc02cb04108292dc12f790578a0d61cb6fada738902eed3afdf1850bafcb279f18b5798d7466752c6368a594533baff5dbd17974638ecc41753b184845206c79bbab84dfef148eb7f1390f8cb7346a14c88caf540c241cad11ce8869be3bec85d029ef490fc5edacf94fa962be39a33c8efefcbb6b43960d5bc35f8fb72038af3801466aed141b50e9ac7dcf1921f7a6abaf320ff02ac34bbfac265e05e27495e6e027e673a48a874e6f0c33827a050fa21c2efa789c1e3df2ecda95fc52ca7be35dbf17ff6c73f37cb236e5131542e002913d177ffb21ac450e2542e24b894650007c36c52d90f83731009a7c3239ccf11829cf0fb6510d9924e927f14d6a06f8dc772fc9b028a8bbd2d3388985f3e2609abbd08434c46642b97240c9380a831bbafdc5db77be63a1400cc9a4f7362a689b07a77162022c6ba7a1bb9f0446a0b6b460ebdd9111132694fa5f1b29da39be66c5179849ae9720b2da0a012d4bdfd1b18b8fbef0d5c32b92c351dcf2c599f069c3b53f622fc8e904f27584b2d97d43f779abcde6dc1413c0a677dd187b28cfbcf7fa6316f0967b53977432d45944ce8ebd2e265c0bf6b2870c75ae808fed52aa35421ef55667ecd6f9d279c9b91c9314bd9411bce267d6ad52b1d910b3e65147c3eb6021a0af98707408e66bb11ca5abf5e34b2bc85b144fd06ea56f5d7f8939fe0cfa4862e7f306de069cf85f4aa7aa97c6848594f5a6dbcc718d2af77497f4b9d5ffa217fc301127071e9bc9c2c9222ba90e286506e384f321e622f05d81c114953d0f7e9626b74f4a6bea8cfb86ceb4575e5cf4fb84e9efac8291d1f4153ad3cd9a34ce0ffcfbe30b6829c0f986a4f85d63b602ab99ff3934b1e0c46e55d56eb479b79ca0729beb59aed783e9a3ccd55db8d884733dbd93f9fd7a7209fb92fcc49826b2d4356ca676f01b0981637897b3d2f90f37bfd73b214a398a8e4e2f9e5abec01d8192ca690191255dd8304a2d95a69331288bce00385f462e942f4d694dc3560a263c8ac2b5cd1d2c63b90ec67c32eaf5bd947bd8ac730da9c09ebc6888b0b4f3bead157aa9d31c2802df8ff0e4d69b7abfed6f184bf35a16ffb5677ddfc4682322128932d57fe4c32f21e190e1147d8e673ae407b1dbbca31331310b299e9f3db08ebfd2dad3158562c2e47addcbcc831cef0194ac8ba9778d0103c2955c886d439967bf788eae688f2a7459b0ef3bd16808e8d768b8962a24588d918ceb2cd1cd611b504019f65216beca212f44600cb7fac77216b7645c49f18064a3acdc01399315084dc9ea151ee28534fb31628d190bc540ac6b6aba572ba51aee89544015e6fbca2b3c2330f2ac1f68849e99e1a1f7f523599eaee22720392ea52259e26f1101614d4edae481b3783af4e99082d75dcca549049290731bbadd1ec0a93789ad5c9afe8bae44e35b3e59e562362964",
+ },
+ {
+ "0410d1f8bc890649c250a3819766f4496f339a6384e34acdd72b3a87266edd2a7eae223a372883f978277a108d6e59fca1f35f25d7a9f3aed42d35fa9b12241ac04754f76fd8f0e8ff6af88cd851887a45e89f1c9192ca66bfff605b128575d2ccc9ca3ba1ba23a0251b2cfd6db577b29d17ce2ea998946997f5c4a97a397c46024681a400a54425c071232d269adfc3b1adf15b4586c4dd7b8886f5c1023bc348bc674961ac6e221d914f432c2f06dddcf738227dfcfff88485ed45882809d0e57019461c88683919b87c45e78223c37a5be5f758e4f0dc6add22f2062bc2eb9bdc31b8649af17d526ec339f0e6fc6a41e26299c65276302f982235c3e5205ec1521625ec08a23e766577664b73d18d5533261c859c4cb4346feaf7540a56155c6c3a4874dc86ea42fd518d71221ac65541e2dadd2f8e129e7809f2835f07dfcc4128401dae2b5fac7ced1d9e07e3f348c6cd26f55b3893d4418557a18c366dcd5eadea0dd84ab95437d6f23eb9e5877fb2ad740ee507e2268c39c7186f34e5cee2d0dbba1a940f516a018f23e716a399c317a7a81f89cfabc296c432cba900ad79db67936f76e4d97874fc5f8a9ff84eb7a0f6d629c581ec5c451e27ef1ed468f93bfc68b2e0412a543d89dfdd812d9421236a4be9eb374531556c207340886c7b84d42d651557b952e0982f62c5c383e92dced21905174a5a836acdc3f2393e770d6cdc22c39575a42ea406f36889dc9558aeae5dc5f8b84862850b55bf4accccb6a8ef793d641d6b08235f70ad3b0605eab462afad1af80fa003645f4d302b03d81a7d167e9a8187bee0f76b1cfd7006b2d2b55fedad6e8db1d3ecfe031702dc327ff2b0197337d7542f42702cb276de852b3d72d9acff8a7feb8882028a5e340950e523c41cfa184b3d8878effe56742994e60240e58cbfd01541d39fa007a9f0ecccb409c6cc540354ccf35223677cb74e7ef7330bb60420f7d7bf97de6888cb343cd4fb0928fe5df5f1b018592ccfa7aac6dab57cded573b5950b94fd935f32cf332dd85b2b36501de6687612371dbcfdf77279d647ed8bdcf81fda8b7e0c5ab139330d64695d814fc6f761fd141dfb0c8f74e2d7616db3598d8de40b993fbdd272ca37db27b82aedb08bebc4a8e6d0385ab20fbc20c215ad50fab8e93975bcab3ff38667abb0545b3b3f20e325f01b80a32a3cc3ed51703d4b2826849ee22fddd5b544816599dca0d8fc84feed9f7e90caba53b70bc3f457eb1adb89fd0b67d2c0ab53264430c61d2c4a1b19ea99a9b453fc6b5ebf5fb5ab799134769c9b495c479c828bcc49a8f993c3127d5cbc31afb89c0e78fbc323755457ebf0f3344d3ad1cfc59d186e96ac31a9298e655b3d1df74b95f30fb868631053540388a13d597002f689708d35a2365e309bb96db8b1b94ea4c8060c2b165f7f19e72056409159371ac9c44f6bfaad9b9567094d18c29bbc8aa2c8b5b82735d20f55284fe68186004b4a4fb644fd52d9645b277c1dc238a764005c1d2791ef36e71786cd990ccee4571d9a9b1aec757e479cfa645e320bc33268e05af9cf90e0e616ae7f237c637a99fe15b4ea8a3232262d96855fa248920a28ec03f77ce4dd93925db60ec030a7be455ba9d08edbf6bb717b1a13c3ac1deb9821e21505c0a8971d5ea5dd8e4c9cd3a845a336209af191150ba5d9b8c2c450e3a765e8670d7f846b2461f971fdcd1942704f620a40f4204b99f9035bbd543f64b927cbc7a74f32cbb12c3caef955f169a45374e4479430e08d333c4a877baf41a27a0849ca3a157b6651295fa71ac94b6e3d30b5d160965e93d2a81b4d575cefd264399c9e4e17059f4064465b2d92c96ac27e3b221499b5e642d033992c236b905c072faa1e34495f9890bac6228330e4016c061605bbfc478c30e1b8534c49af54785972aca2d144328b0a540e3b3810a73e26acfa22f48652d53ea521875475ffade8ab50b9f08245fad753350f63dc4e898948ac7dcefe520ca47394f8e993a6d13ff68a2f78cf294f235f5f863bad10c4f5bc41c3ba93cf5e076357f0f7fdc136f34b656b1b8ebb3eed1ac429c7d4edbc902f7f4bc24ea9c9b200b9a9fd7adff0c6445ce1d2171fc031e3e9f8b8d6b448053393c8813d91333d4bdc3bc5bb2b8bff876cd29e8b92cf6f7bc727517b6f57ae031f3040b0637dfb40b8c1fbe44cfb6bb9cd0a445fd9b3daa1da2b1c4a82cb4da1fb8d525e0a4d9ec30e9aa75b951214621c58c1f60c9b97e6c6b330497e7dea790a3cd8158a76d898107ff3a5910707ae60c8a46c633b522aee83736d005de60b9abe202435f8bc4577b0eb08b7f2b617bb5a831e95d6488459bbf15919d764b39684d7cb7c9310f343fbfcfbeeb212a90d96c7a26c1026c5cb171ee4ef839785076e5084026077455c73404a2653f333e9bad555cafc1a9613387a02bb1287c380d7478238bec8943208de585bd18b448b6099565cb3ec70ec6672a778fa6af9d1b17b0970439da24c7bfaa74c85ecd8e5852e42391ab2258024ccf91e37f2f0e86df958b197fafd12f4a45f7990375f1665a14f7f5374ff7740f89677ea8660587fb80916b30629a7aa88213bbf80512421a0a37414a2eb549b81cc85072cdd87e4e69d97ecc63f974e60d20de0233101c3d475d777602b12e2f797e9237570085b0e9f48d4dedf233eb1301ed4621f9736946eadf599bfd79157c0b4cc31bc273f5c6f133a4e3679ff6797d3c9b76aff4bd8ad40726c1703c3d8b78f0974b748d0265b0a75928374f91b48c2d2b2c11d8b6e5efddb75009e4db72e562be59efb0bfa06808c89f585a43d4776ef08947a77f277526777f0b52f1e0b5a03aa560fa45c8f30e584b58ac1fc00b104942b7b86a3cdee1abea349dcaea4e058faeffc567e2c3b03e1c5c4ddc675e25aa15de1442bcf5ee972a8c5204ca5794694759c13a2d716839dda61635043bdf1a09e35cb6d93b4df3b7a00871f79cdb4ee69c79041dd14deb7754107b8fef8589d2d240ac1d8eafc52ea847263512651bbede2fccaf6da816b1b892319817bb6af9fc17078ab6cca95f03cf8426249fd4f2bf91921d39b8cee24af07a52bbe54ca7fc4422a310dbf2149b763ac0060fb2c59154d2cb0da1ad4892279b4e0ce7f5f92c189c3ce48e518ff48c4ffa9bf2b02d4792f84534958dc6bd2914ba010aa32d133f6a07bdbb87a237c7acc3ba5cf101efe947147ed4eb3bfdffe5fefa991c0dc8760586218d286944c52d0f221e0101f74826761d01a20af187f9ec1115e9e98bff6fbd7c8816c15d33c07f51c171490997bf269951218ae92b66fa3150d3bd40336abccb717e18b53e8806fff94009910f202a5041b5396d1c339e6d075bad4ab66a0637d81eed1696e4068024001123204b8371f0bcdf0ce07d79f7c917327f7138a75947846fde68665e9c767fbf96bb3308abffe7a8d05512c81e39fa8dab2334f46ab9543921ca97be31076dc7b2a0d05e90b7f7610d1a391b442398ef56cde3b18737faa8f282572389b4fb3c55cb8ae6737257708c808bc0a414bffae293bc69cba702ce2959e1a30edcdf64985a4b0bcc927c5912f819c71cc9b1ff5d6e5929055be72ea5c8c1a4a591093deb5449b7e6b60109be1ac0cae472ba31e1035ae65f3214f50ad699a077a2de52f7180addde0bd78c2698470b1af13cfbf497d243c9e738c4cdc265356543885c5b933a299f01a5b5a9ecb0b4ddfda0c28573064f6a3f142801795d66bcd5c31868fd3207fee7bd98c47e4da26bee64e1617b20cbaa34e3abbe31126b06d5737fc2b577b19d255a519397f3ff8668d0e7d401a37e368729e4b83c5fbf01c32ec478967605cbc0675f685b5eeeb42fc688216a0667e1204c995c9c485e6f7712d80d88edc9594528b1907790549756dcc8b0d32091f36d2b4009639e68daa130e83a1ea18353ca34f431c548d91c1591ccf8b25eec1f7a3c18ddca71b87bb290a5c13229250c5e193e1352072f6798ec504b3b4c6aa578737332f52baea7bc4468fe6d8dfabb9728cee93fee50c8caa113f5ed7e9b55e21e98d73a377ef68be7e4e965dfa50cf863e6285236f11ce80512c573ae2b55bcb43cf6ebabed6783c250f991f5f68a59dcb2ac13a3c8fba8dbb11c79dc6236809f2d7c4b0ad3cecd24b85f1aaed9748b8c109f2fd98ac8a53bd52f18475598d67305117de8e03b0d988a2847539cc2efad520f86dcd82c08ad4b10e490b9cb03bedc7197bcaca55526cd9c8a5a5f69f7a1697e7e31aa76eee597c386418e89f06b0b9817a83d6cdefaf9594548b33cea1cbb585e55df3d3b66f0b1a88f4b98ea4720f1ef5e6ebe4958078ea0bacb8ad776e325ccb252f81943b9b1c2f54aad3c7baf1bca0dda1355d191f69c5d8163c464898116dc89201032d1e3281c8054882f60522d3a65831bf779a854fb0c195f85aa66522386625658457e74d5c2fcf5234f226da4a579ac1f11f11a1e0a6993a4dfe5c856481ebe9d8d2363401058736f7ad104104aa03f5c91496aaba2fe4072d418d91c2787a9b4ab0cf4bb65681ad0392ef073cf2fc060692b0c0c194c8eed5558098cdfa3317ab02626159e40e5c76fd64b2ef60b8f5f368b6b4fd7ea3d2d3236aa01d9db7c8a01929f9fd38557335b926251ade1a0d47d0c1444e6416218781c1a51e786dbe9297b78fcf0d0304c62929e00744ed4e14af926313a9849b2a464048bead075044bee013cbe318920c4172138560629a0ff4fd229d81bdc7c7fd1086ab17d6efd5b603a1991b33a55ca5b9e2051b7c140f7937adfaf474c2f284489d9b1e8c71d58f126eaa451407eacde9f0e86504f7de3ba4d830199a229de2bf39014baad6dbbc448501588ceb2575db0ddae005b81ba9914bc22b6d600e2c990f7843e553ff29d8008265eba7dac7b5b5a7ba6dc263fe0e262a7b8638a81f4720622c7361554b61d7b04c7f8b133440baeead7d51ac8b77d606fd0eae1c55ce7e8141dfd68d40ae3d8d2dc8a061085b4fb6d8a06263183869154618329be6b01c2890f2b5d0a0f25dcdbbfe2ec3597d79311edb943613fd4b59157df4fc2e1024be03d98ea3cbec7186ea9f4a431dc3743b9f0871b205bc0c1b3a001768",
+ "113b261414b4b7dfa028668ac8b0cde5734120124991c54f4dd16a87d181efe2bc15f6d0caaeaf6ad615f59ec5c2833904a34b4d34109c82e10609b387f995430e8c13d83ac34310d838af9efa32d7fed6224c0a33",
+ "cd762390b93369f1e207eb15deeaeb0036f5331e82480d180f84a76c3e44550b",
+ "e88c14ef96c7768f5dba9de9",
+ "8d6aaa27892a76fb05a2e96cef9a9b4b7ae0670a12cff95f7b076372456889fbd3b9b4fb5fd98b3bd85b247f15009be2f4e7a0329dd118b6872199b314e159618ede0381dd97db28743461ace1a694c0383d8458150a501d6c45f4b50d5b1bd47e61a51f9ed4929bf2e564f201ed0e6825170027d93e482c1ce268459d2f81cab41f0e7ff281430c16b34a29b5c76630dba72ab9e751bae41122b26121d91f2af271a23e818263f46e05fdd52f319d58330bcabf66637a368c0a8aeeb20cad1916d966e5e0b0de74cc67ebe57e3d1fe01e9743d42a931cb4b98bb762ea43ab937d1e5c42eb08fd56e70e911bdcc1ca4ca0604a329c5364b262ce2de282b4732ea657b89300cc7b7127ba4a2d08c13f581f024fd093ac09c2bc245be60c80e102405597fa8082f4d28cc954a93217edffaba3d2a397bb59ee89c8cc0f33eded78f21183bd1acdce64a923dd609a0620d2911f61e81fb2c8ccad8ad9d81157223253a121ea2bc60d6a3670c563fe06bd75688572b3be83cd31dfeac6b17cf8455267b481219c42034b2252977f32b8e6588fb05166498fa37d17c2b002a655b5711bbc21175348225fdcca041b1f97fae48fb1e222c5bb46b5202191c00666b7e1b2d84aca3edbee7a97dc0f6d1330e929226f8a76c155e973c1ab62c867e1f87be37788754e51825ba31af9f4722b5782ef782fbb70c391a664f252d14e49a805e94790135ff6bd881a687f98b42da96fd34bf240eae4914488af739ec15f13f048a7eb5fa94af14e8b6ac5fae714cbef6268b114813ca2a3920a7a9d5eb506a2ca211758de292047eefdb5a97e18530dcd8410495fc42abed91b1204d9b8ba9d6aed11d2d0fa0d931d46f93f2c1a560ef9f5f7cee1497be770d3cb07c534215cec12c1458bb57aab4d95cf4a15a5e3a3bf8e650206d5cac4af3193d169f1a57638d9a50f6b7c6985d42f7138b9226451670d7359351c2affbca65680557693d03458341198b8e13d0ea6abb7496edea3cd4dee2eb93695e668c7c0901c6809b8ef434e88b85a8b22cab6508b9560fae62900056b7c5c29a8c899bed45a2b5159a1d4929476ef350101317f77f02d48a039cf4cf01c56319cbba16fe908c49ed6f3face88867c0ad3703452baa7b86fe58a00ab8f740b4e8055164b0385dd3fa44502ffbb99cdd843bc3287ea468aafe4cc298a3fc180f284dbf78aa09e0a2f7d8593356eab016ad8dc505420edd376b66598a3d0aaa848fd68c4e07419b8b50e40febe2b6b17ad07726fae1f87e86abd01490a0ce24fb57b533c765504ee0a9ca154187bcf5e6828e3addc7597532643cfd992558d63b1acd00e7aa41b9765094217480c08c43f4f0b3f0127120699b7f2a5ac07c655b6143e467777cdad4bc21d4b57da4d8f9b9a7e4523d8c6fba3614b7f7281e80ff0f9004577adcff1b79fe443c80ca9655ecc102d5df6aab2ff6c3401f344b77666c59ac7d5b92bf4f1e2322f74b75e6ef2bf43ad9e018f164ae76a91451e5221bdf5b65a4fbbaa8dc31e6063b451edbbf4965307f8e65bfae87b15f2453083bea8484017228a9cdc6edab1a28834eed8ce07430f776b916b3bdd2340798955ce9ffcf114c3f6a88bcc4c7b6f2e3842426488c340d00f2c4d2d6fd3b6263dcf7a57f5cea6c77efba7013297bd3320accf033acc0833aaa8e8f95cecba469704214f54a1ed581349878a591f9993371f1daf92e55b2a4faf8f952cf785c687a59b3c258daef1b6d7bf9f904123c7384a859933c3ac31e33edf648a1be4d6264ffade860915bd118f0b9aaec2eb8e16b2015fc25e68caac77a3accea53b9b178f6cf48d15029fac12963b4277df037b7a494cb29b1d9e6d2148531a1f7360519cba5657c080254f130a1cc3ccaadb4298d7ea0223897e63d798b4f4909577cf9b491a82de0275a246bb1211bc4144574c8ef176b382262c0e087975cbef33cc616d32e0131a9efdbe8ad3d9cb5f935d3f4f409852acca22ae2a6e7450e9a426ec3b9183f93b4b7f89d850e1c7053c661936e0cde23e831a261b319b430da45772f0fc0113679d06f025983bbf37ecfba35eeca28de5ff4815a490570491266e92faaf8d0ad4ac8df106faff8fe3c8d050ae9dfc03a01ad177c21d7b653509a80369a668a97eaa532dc9867c32aebaf89ed36586e1ebbe1045347766a354a86ec1e8b2f30c8fdfbb6c5d549e7a84db81b73fb828499c5c4be0d4b2b7ffb197133a0ee18abb5a4e371be0ec0a6535507029316f8decde30833ca47493ffcab781d028edfb91c138609baf1054ad52a5d8ccb98b3ca5b138f253d99bd556afd80f71b39f36e0d96fba4e0cbdb18926894968aa825392f12d98b6497ff85a0e4a91c97f37ba1dcad30fe688b54008b925805104a61dc22b712685202ecdb073fad9b10b5b9ee2ff781f23fd41ecdec87f85b369a304b85bd2af126d08f79d8a9e2bff0b18607a95c4efe35941c5493c94e3f2f3902e79f4cfe84c138b83c7f32d7c5a125b28c6107921e8ac92f1af7da015b46a2f9169369cede770292eee8a5f40d080ea1c267c33cb7d4187093d486dc3911bb2d6cae036cb508e81ca783ab5e95cec751e39f3038003081a252eefa7cd913baf136d4e27076251da9cbf0c7d2586fe02b62ec786790ef08fb3ff3d79bd06868eb1abd9875920e14fccf6dc144e898f578b7295fb5f4e84cbf683722ce3597aafe3195e194736fc317ed03ebbb00d956ce89f7a41a334020e1a88da355d3b47d5bd3965a290f6fbf5dfdc8c8e6347b4eb85151e53a960311582235f3b546ca80a670dcb628fef572dfae0c101bc08c80f78d5630a793bdfe402592c316227f2333b386839a67e6ee8d9396fabc9648ea656a407670efaf80966034958f4a70fe7b920c79dea3d5a0ff05f3ed0516537d51a686efcb258520936fdd415345251c9ac1143a41be295cf12da5d4319e78e1c57ce20507490e5213ca7be92afca8ec8b6a07b33571afe6940daa2afb0dd4dcc1c329474ff8e13d740488e5ced552074fff695a04fc1b70755245895a1e9c387fd9514261dbb0f600ae03f4896e795d1e72f421d8572543243d662f6811eb9402b6a3b8dbb0f32de95bb1ac01b1287663d3b6a3f52339a4f6b27789e15519b2b59f2f4fc8fd33ad1a6e4d02cf0ddf8499f45746da424ee78e72847e3cd3833551b6e6fd6b1aa98c688252b57a1d97660ff006ea1b970a0b8fc7d2e313ffd0b0b85299ded47b60cd2fe9bdd7ebace4b0c1072cdf67231a475045990b35ec761e1dc1dfbd0c402296566eb4b9462979d33c9d652a9295ae70943f38adb212b48bd8ebe82722b1712ab6a3be6060297e2aa54e7d0158e4aba6975237e7c7a1e22b29560b8d262125ff2a6e5c1332acd0f6b5ba15b4a82d3631891a01530321830aa8f2e8ab6b41bc5b5356957a4d0c3bc3eab04df7700305a95d0f9cd18d486c675c963876b25b1a0f78e245deb40dedd14dafdaa9d614fb06eb2538c5411e13be116c76fbd3377ff212eb07c5c035612e4cd7a1de2ceafe95832eff88a9bdb3595cc19287fa40b8d244afe9bd24dca40db49893602a59640d7a1b8e7475825b09cb0cee111864deba9d3d1beac03664279910accb9fac534ef099e398d7f6e3235cef7685fd1ae46e47da093135741894273c0c3486197c26057044b10faa57244721328b47e611633d16d3e4776d90309d68ce4a60d3ecda26c9f39c1c6da67ff79fde4977efc5653d79ad86c3b53090003bb72e78aeedcf4c8107185d9aa65221df4e2104640a1a083845c01000370371fea2a6bc8ae43fbe290949da4e559d3867c16df16b143fdc807616f51ebce8d05bb03c2b0bd587b95e3f6a15d907aa9a5b11622ddf4c81ff9fda4bb49d3e9577551bae649cf64ac0cfd646b02f6f16cdefde09a55e77afd16c74e8a3d777d80b7cc42c51f618a3c467968631119f11ca4385f0f5713e37ab1133b692de475db1d44fbfe9d274b9a09e673dac88aea74ba88cde8db3c831e9b5a0f1e40261281e5aea9d4dfd48c5d9e173f4d9cd56fe7fd610909c838bcbe1d6c729e151ecb4caef511a36a14b03cca7ec5d0feacb4647ea5212a11d18cbcbedf78443127680ac0b1bb65120b4197570288226830e2a92b380e32387bbcd3be2c77d6c7722054d849be9de459cc1832ec3ac8e7f60fba9c81cf5fbad37d228eba137a23227d56cd24970340f2b7599aada9d2424cdba8b50c2b97244dc83f7391e2ceba5bc0a11ba547c142126c791265b33a3db6238321a5f3273ffb01e42adee17b898153e41818b91413ec4f6386ab3dd48db875afe659db9eac94d16f850ac179d087d93784d607349e8711f5f96fd514e8d096de8b4a74122ba914520e93a11fa4adf006700e122e2531e1f39340cccbab4862708d69c117d3efbebabc14a0231916ae1ee8285727c9fc980051360346d53dfc76aa5a11fb1fc8f36f95f741e913bd2cd1031e508b320abd2d3a62baa400dc439969eb44e6abf8223b29d4025c3d1ca08d2dbdbbf9927c625270543e8c0cb5ac5bb5d504d224e66a1895719e4f975d819a95e54cecfa59ec8e385aaacbb023772fdddbe093afaf5a75e63a62d51926254e5b47da1e9b05851196644b9180734d05810dcf3502747c4ece652b67674c02aae74f20d07de2ad5993b3a68d10207eab6be5be34e52ada655aa96c1d82df9b24c2acec35e8f0bec9131c20d0ad8936880af87215611b80d07d7a741a12d8145bd05066c6ac171afd8684b92f72237bb0e4ca4aec1ec280e39f36928852d5d8d02fe463acbad8ecefc103083fd4298f399bb254e7bfa166638460b760ccf2b0f5fec0e3875206bdc8ce096274643824acfad71ba06441c74788356caebdd2208f6f077b056fa9d85aa4357e93bf064a776f5f3b0f288d0afdc51558c8f25cbee17247364c2bb24637dd69017f92bbb43024d9c773439626a02bd0cd44136a642c9c5ae593f32eada790c31a6704030f2e07f1173cbc0dabc410bf9864214c298a6283b3631acbf94b8371681ba81eed1aa81ccf258252d7f90fe733ac770b9744d0170cb554b39e6c72e05919cc237f8f4d7f3545f4d2732f4c9473c77401dcba04c0fd33efc73219f31c08dfab26abee9a7cd4ad3584730768fae899fc",
+ },
+ {
+ "9c73ac05648e0c50a3ea3a8eea70841e8e06669c1e7520c5e25e093769c4b005375c0a9cea16ec8e00261ceb96a00924a66fc0c4e4e089c63e93fea857aead8e0ab82af4ce1682cf3c9fbad23fc3f7e632b7aa169834ddd6c7db7e1e892cac93e4d787b2ed0a812aa93bfce8fef3ce30ab794743ad241974ff989288c43e1ba815a25a03acdc2d5517293e161d0c46c8858d0b32b124a6b0bc3838807753288cf6838fa25fbcf876e6368c0342d3cbc860d6fa12faa1c2b7d9fb37504e60dd44e36ce74229dfb80f1545125718dd1f78b31a8aadbb4d6494489ce596fcc2dbdf2ec22157a1d966b61e780d36552daf084739b602861a96ceb67b65b23d40916c02b2c3a38c2a59aaa266e1f8939000dac9b6dc50d1731e87ee833a2cc3cb98c57e5b680a85c1b428289520bb252096efd7723fa8e55d2fd4e16900a435986ab3f3d2bd799471a1bc07c1772ce10d1bb8805a6065b8903999f9393d2ed1a7e1c57a9e3e0e10dfca17a04143814f5f3acfb99a34712a6e0a24a7485279ef343e69d27c77e25b41f9fb833d7cd29cb6a15551d5c77b43d19feb19f2640926a272f81eeadb792bd474ae11f080ada72103f8f7ca733a9b1325b50589be2b2b3023491afec246d336f4e4277592ce9695c68d5f39c8fa4cedaf51776d7ca29ea0ecb89eaefe71e5f3560c68e8dafe7da08cdcd954d626418677b8f3f45b9194474a32f548a4da3bfae6a3e2c0a25f602e3b3a821160c397d77c8bcbd71c5f1e669213af36eeea30d48e12953071f55eac2fe0bd8fa355671fe032f6fc9214632428125a16fc8aea8a9c7fba0d7518b9a4f876349ccb9bbbabcdb2a85fc60b83ee1ddd041967efa4036e5e10e377c9886f40bc0b0b57c7b724795f843f6a072e87e532a04c21445090a360731a2afb896ab795750e5c2c33d58bb714f5be427ca3751df09661402604a09a1eca95a8344d3daa5b99d68e6e6245825704c5d4a73af197d052d7f75778917542261d77735a21cff3f75d6159a3e4b1a7a9854ee376e6b3c8bdaa1f353b957862b2efd50d10a40007026261a546124cef979ad20d8085d53e30f5736b8aebcd3cdaa349ea474af249ac53eef2653ae1fcd5b3095538de9368d307d45df2a19acd44e3b78c2da9d5d9fcc4cb61feac5dd35f66299845bc0018c3d476b6761083baf33a4621e41cfae0e0c642de729fb2d206db6a4b976a635b3fd911b5e9946fddceb6feb2d2f893b2bed590317442037a1d6dc5b5d72910160221cbecb53bc983f1c736c3bfc9757e9e05af1248b28d651f521af67b2a0d7e4bd86a0013338404fabac7b9833c372142e6338a98c0efb7130aae8e34bb0c80937680a7a904aba3be735d41af9462f17b967b13566bcb697579f8a9340429c77baa6e24ae1ac86d8d25ae3cb9112e34a7a948fd141367898c5f33c0635c87de06f603b510cb229df0d0d9a9e107de88b12686c539ed4fc54c8285afde0c8ee502919a125cbcaf4c8c89f56e90d3f641f97c07326956f7b5d87c65b689f39b8b84359ee0f14d2c7ed621ec67f5e2a8ee5faf21c805187edd95e3941ed62fa95a65473a569566d46b87c0d27ca37b6b022a8cca30a4480d392ba15701d1015b3648958cddfb614983211bffc4966ac6c1f691f19bd9fed405a02c06712d62a775f73353f3949c76b6b7757a4ee0410fd6d20071abfe46b09e72b70f9f19b61410ea67037e037934bbefaf09cff018a5c218176d165d1eb5cfd5c46eee7b82fe65ea02e3ed7b18a86ac7b139b7c9df79e1f6e6f85304ad22d97190c7ec12c651fcc835ea434d92ae1444e7cb0dc644efbc2ae70f2f94310805c1d0f2d49643d05e78baa1c54d4fd99137a49efde88dba1374c94208fb4a0ebc1a0090b043610ebc1bb08168ff5bf936ff9834e825eefb9ab73da2b287b06fa2b0ff52f46061b07c1131e4108cde478c767b749b696f3520acd8d3338842d53941282da289dd1e9a0e02aa9be0f127566c9bf2d50a27f6b6ffc9e9880bbfc14ce7eeee70cb0c0ad90fb474efa69b46123638e8405fdef65fa7e0e7b29fa8fe8696edf661f9003a08b4aff85a4a3e6d817655c1d533b834da981b8c37c38abd5977b3ba71b3f57967a471c2eeaf2f6f258431fbb7e92f91814b1db80ea775681f282290db170942bb7b04aa2a331950b74a4b6e337affb4c51c6cd4c4e13ce3095e73e4767c2731f72bdb225ff572163fbd8573378427fda194d165750d487f6bbb63e1378a132fb6ee5115e3c32b2380b096b735bdb4d651853bc7928346fe3ea9df7534f2a4eae1f5ffc4b82ae738db7df0103ba4e68c2a2153bca499bae2439a57778cfc616df16032aa8a19e26597d275d2775b5ea17cb25d204b18028eb25a053e5666ac47c6def151f7d4b68ea62c601d87bfbe04711c24bc34274be6815024d7b7d01e7dae10cea6e485348ab195a83854663cc5826181b688cc9c091dc1e0d491fe51400e20e6f2a51a7d56af258e038bcbc80e2c4ac4b41661bd33229d07b39b59f3aa79d99c1ef41974a33e02a7cacd6fd8f9b99cadd0fd6a031f070bd3a364c64ddda0e9fb94036f374171de0b3f4ee3380780e6d77d50db9d58e670fb4a364827d631226a3491a27602808141ce657ad6e560ad62b088ff086e6f03b8a64bdf7c7d01e7b19289279509a9d6d80e50aef3b05b5561e4556952c46d0b6ab8eae735eccee77e570e1360b7ea38c53ae6b8eb420e4c2663b57827228392db6e79105a47f7d89e06ecfebdd63783101d3bfb5f494785acfdfed41f8166faefdf0b49260222c4080ec2c6e4f949f41784f076ce37fc7a34fa4e547bb44e6b9359b4b95cd67d64e4402ac83973bd50f8adc7c6e4c34019bd8f6d3843bba3d7155890712e0ed5134e00db877398d86b459f312a6272431f01b057446bfb1b8053acf181bac79408c7708f3a0867a64e06d7786849bb874a6bdf8fd6daaa572d5648ae100f4318d6b3a811bb0fb709168e817ed83c0622a7e5b17ebf5cd5ecb21d9ac32ddddb039083144c93cb55a95ad72732132d54bb120639d1620ebd142b58d75835b35cc6367012c93c6772963e9ac852c71c0dda2246ab845469997fc170d8f62334bc5aa4ce23e036967674303ec6f75bd3d17d197d026de69beda70bc59d2ff95a899d28ac7e5e42f4d37233996a8e6d3b0b86b80df49ea8e145b4a6e3e39f3d6c3c6518bac45baf97cde23037709d737b242b8918ca31f90fe59ff2c83e2f347a954d3559a8e4f075c620ad36be20b1e24b3afa156cf3255192171ad0474e4adc9b7f35436325b92945665f038611e5d14bdfe7b7d20c09642323346a717f460dfe7b5062a0098be66febe9f5fccfc747aeaeff81ba08e5dd2b1a489c998ea9970afaf9aa03859073707a686c492fb3f7ddb27897ba5e75e578bd82114b2ba85525a2002927909c970a04035334b64b1169c3a923211e0999db8baa26b6537cdcf57c051c0ca1b317a5b66ad96cb5ebd57994f99ab202348d8ddeb343312f1f26ab2442b8c5f5cf6bab394418ef2fed68c3e60275e836027515b6b946e5d86d91fdaf49c2a5182d5051726840a156a8653cabda25e1dd9af693533d782caa09295952ebfe6a194fbc8bb7fc2c0da5914a506c6f31490928dc5d6554890f5eb268b09d671bb6b6d7416dd36e7b78ffc5c86b34fab43d22909a87e5239643d5fef373650e291be56b89b9d90431d8c9fa44fdf4f83a1689d59d6ef833b1ce31a44197b36ab298d53b51ae3f8387087dcb0571c340874c1524ba0d576bdb88101c1fc387d25b5c0dad0b4d309255ad5d5b1e209ba56db0c927bd209399a8a3b5c8663c9ac199a76ea4f49e364a4b93a569b3400e20f0d748adf7db46a07efc68e43802a5d1a914759eb2abe8fe3e8d67f2cd7612bd4d5a6a4535b1e5b3ad4d97e54f3db7f8512c9603d87e01160b6908d8df1b952c750071abb1565e5ea3f643f233faeb84278187ff0089150bf21ee4d13979fdae796f592ac5b88869aecc5be1c64665edc8ececc87502d36720b73859313607aaa561d56a195dd3c7292fa8f0750ddd3df9ca056fccd9d6ec900f45c1454c6ceaad4154c69e288dc85735b8cc42950a3c5f0fab2be8811779905c3ad5a9a6bf56e7141d863caa4e93e0065f229b695efb790926618b3eda1b9a15f143bbb09aa3c4b72900617793417df364185cc213d5cc3a375778117212266356e214f085d8a7aed908256c4aa25faebabc70ce913c08c89380da06920069e8e27dd867567f152f883a9bd2dcfb8097b7f065482d6d11c0edebc67feb3068cead403503c04b324885ce1a62c99af9808a5ec8b7cbd978b8c43e37b06e9f7e1ce0b31fa0fe52e8842002e6e99cdf69263d31de080b56c0cf94f77f0397fd1f77b13e17af90ff33b00119999df802c33534a13d3ff7fd0e8cf58e8f8c8bae033cec1aec7d191f2d1a39c7b731c97a67fd1ca43c13a24b9f97d92e2364dc26a1c9408d4659ac7373e53a2a1704a47e01c0223ed4c489735b62a27ec67ea46747e4f48d3da101b0863bda9d3f7f1b413f3e7f130208875e6a29dc30a78198ef658c7ca32d7d53b4b92e51f8ad6d39ecabb800adc0870b2ab0e85b5769f346ce7fc371ad40c561f9f3b2f2a01f2b8ccae48c78a41383cfc36b2a1bd41d61a39c24144965d9aa5ecc5d506c7c7cf9476085bf049942d35caefd77821ad925b7fd3a006213abc1e008114c848d45cbedcb8af264cdc5c07bc338fddd1123940e5d95717040325048439dccd1e298bead22b011ef76d26a390a68161b8bab29e8409a5880cca9c8104694e1282c9fd64f50e73ec6b9a9ffc31115de9cc0088400a2dc806f85487fcbdd60f409ffca584fb197156b40142e512a0dedea1571ebb74d6b26d3b4a59e9105929a055cf3540e8a6a79ca7ea71ba8b40893c9797e81c6e9a7999d4d382e52cac95727bcac354616ae1094552b3d0a33d0d3ac4e547237fc0cd54944039b0eccf335889f6aceb518de496e0986783c564be8a4a05bdc9c67b1e5abb480b98173ef091259d8c772b611e0c09758fceea3e59243406edfa71fc452d4450b55b8fa5ecb543692c6eda3a6ad3bfea929a18ebbe5ce2ac4754989c71dced37286cdd1512107e4e7f4878da1c28b4beb2dd9a712a8d1d61d1a5fe5382db8aab4857b05a783e98e77711c1933a7641fd43dc6e6e597bd03b11ce8e94aa094fe250f03cc92ed5b0a5e7723911e87b0f3c476d9aa0d96adbfb395a8fd353cfb5a4cfe27deeb82e849f90bdb17928b0a5702e4010f7aaece2d43772a78b325d2ff24f9de0f7bc65974d2348c64",
+ "bf96bbc17abcd1f56a9f22ad164d25ca72f8c996f1a7a66d6effe140336da4f20460b47e1c8573872496343be35a055552ceec437692b0e4919224c4ffc8b603286a8245eff5cc148b004f6e5a54c4ac22b0f09842a07cd332a09732694d3591b8b7d6a7ada2bb38a30aa7fd5e6baa811b9a195d3a96306d",
+ "aa2f714d3a184a9883f4199e8e33fbc9c92b36fff2d59f07a9d0d335d7476e81",
+ "36c79f9f14d431cc8c077439",
+ "873d0617c986dc9d83e9cdfc50b1f916626a9d9e1c595dc7ccd99d1e993d25d89b04a893c89e205952eef8f1733054bbb55fa5e1b07135787d4fcfae226737b50cafa2c11276e8708451be9b4d7f662e98ef6b705c5c4fc64588728eab1dfee22a0a92bae61828a7394977b0ae8a3b6d0126a23583fec025becf0a72a28891391ac1495732a7a4a1d43a63ed8eb37b280b6d886096fbc4f77aadbc5e441e996334d0e10cd7f3dbba9bb7efb147297986509a07735385c681e0543186dc166291edc3b4664f5c8ffb0965c85bc30ff5e7769a69609c69ebb68f35d104bafe3dbd3e2a40e13865f19bca3612e48592aa930eaee29440b4ebc1c0a59f1c54519857c929709b086bfddd6d4a30940b592be48e0067976099efe71f45f956182dbb300e8076e1207baa32d59c1afef7f34171bd66099d2d7f07b39d16d0f8b085185bf2554c6ad66bcd656f07979e8f19575a116f5c4fb9700ec3b46a3254f28afa1ed51348c1af6dba26fd398098a76d7bfa2ff195eebab41330ef290bf75205a2ee570a2fa46bbaa74aa6ba68a0e63e2731dc1974eb44794f3c89ba58cf96f7a070fcca678185711d97cd9d7d8202351ed589e0b05a7a190e60ae4aa109254a7bcf7013f8addd07a64145e21226795ff7c7b1c225f40ed7c3552da8eb18b9bc9bc70c2e7ecb10c8b20c54f04b6e27b5044a7a67b558407eb330f2083444375c022565c45fe817dc00c7d24c23db320d15949b0b64fbbaedd310e73e423fcebe6e1e98a5cd232d97e6466642e5e3b23f06525ac1cdf8688650cd366b1b7ba2a9033e62d836b14bb73717757b76b9673671bd3d3b2a56628f5a309f3b86ad32abac0590c50f7c5a22e0a920d88dc9fbcb3add08b900a2a2fae4178aa100a0e645ab428e0e79bd90baf4af2755e48262b64838a6fbc21226e323c0a1ba5703e30738fc7b5a7df9eabec6199df5ff6ad58f9df5a734ccd6509e53ecb3de1c881732e26e52ab848a0335b04b25f2254aaf8c130c78b0c9a40b60d402673ac7ec7311d0b00c45bd176bc73ad81c2478611804f59e3c145110aacce922e473ef346f8acaabdbb9f313dd3f8d0a937d0c048e5af789e2e09a816146f9ea28170909caf2572a2f6e2d0d511242909de2815e9ec586b2d12183ddbeb7dd70f32424097e2ec28b4ba62cf78f547e2057a4c050cccdf6b582172343742ec8c85e2847efb1595bccf89ece3b3ebba824d2f097b1987ec26c6e5710544739d54a714060fa91b7995cff0161415eaf55758078772c0271d9d282354e47a25b673eb11497a6ed8db82267d65ad47412300ed525af96f943c5336b1de88676dc346e7339230032463d305b0442f934018bdf0242768511d20474c6ecc82fd752c0c0ca5cee1f3e06e679fa5835540f97870d47ccc6bab233290be7a3bbd4a73f1dc7682049bf7b3cbfb6687479c18d246e3c07161df5c889ee95d39cccd989625a8c9e80f951f8b1832f6378e05daa8566477d7fe547e49ae6e822a68de4df9fc4d6500d5219c3d3bd8887bd7f695151ba378da17c2e750399f7482973510a386721c59683a86003edb9f0ce1ea89bd7bb8a25c222df7ebedcc1b56c8ce18f367b2cae720e0591b477f6ffb498c3d7ce59cabb1b01d7cba84d7180b4b2a165d4b889a6ac361720e768f2913aa50b0b5c88e55c35bb4df4fbc4460338809605f1fd445a2bcd97ec1d2f269b5e779a18c8f215bbc5555c745424484ee5436119eb8754f5e9e91f51fe715353596baa1fbb0a690e99691636e6027cbd4b7be752bc278661e2677070ddc12dccc262d3dd47160345de51359ee8dcf2f61044f95dfdaf323881b2bbff68af6572348f786f6e52d1309cff871ad58148307d7eaedc93ef037922b6092ac62171433adc4934884efdee3052ebd60ee115f76f9dbd0eab7c4c0a77b4ce8078209d23d81d957335f331965b556ebd54732327b5aacc899f9ed0edacad9eb98cb845867f249efb0e1a5fa2483227f78decbf7f1f32d060ab0c01eb985d83920b2cc24b5f9a0d5d869e980129d3b78277fb87e5cda61e340a729d86b6617b8828dffc7c37d4c38080ef3515c2784935973dd184e0a8160f84bb78bcd8a5e691760be4a4d41ed6512ee436ce24650c0e17e7d74b5e01cc39b21e21514a84db262d673f24a82cfd5dfe2a162976171c538b24af16429bf8ed5fa8e37f89ec6e7d63ea1d83ac1087cf89e8f43161f225108889e922493d973e36b510074533cb1cb22174d21c4076959e4191a5df880a8b868b95a9cb5151a7ad47375fcd87725660cc0b59c88ceb86984941268493c49b8aa2baa8c531ecf497853ffc3d26b926a379e72188e246d42073041fbca453bd558f328881c8f8d9e099e898a912530c4be499f2b32229c359ea10e0befe6d94cba5ddafe51d164898166e890b22fd1eebd5724451511dce1f8f7431d712a3f1e50fa5f609da686253311af255b84b2106b09b803e94b51729cfa0826869945d46b9606547e7e33fd9961cf15b400d0f5e01d8fd4d92a83ae526934059d4514b9e0005317a70466aa0b6086d5fcfed201d958a0de55fd23f0919ea29b8aa02440031a9fc206b9feef362a73430a4204869354ec81b6fff92eca97e7f1bb12d25228eae466b8137b4806895ce34b57dc14bdcd107fe160776b0e5daab150ba06976eb884eaa574da393af4de355381c7caa4f611a2ee70a0c78df93a4276f55e6281997b4aeb36888a6d9638cc95444047e5202f41f8bdd787f1ff44a648cc7d39f05e49e5d6989fedb194c526780709763da81a780db0d1534a466cce57e11dd3a4c0e273d9873af1040d52a90e20101e1f80ef296d45769d204cd5417a84e022b6b336675d36d9cbdb16b0cbb08f5e240012967c8067c92f97f981cd19d449084400d76adfb7c610abb73bf21e161db04debe6665fca79d71c8cc50adc3ecf0e52d07773478ca97b8e9821a5704dc58acc647a5bc618d2b681f17942c46c266c73ec211ca403a7d47e42e12c775b370cd500d70a4aac7124f5f6d2d4ca78e1c17a96426c326bb60379ceb0c84a86200f3b450e5e9aaa11f45440f5260eee7675a8b9c47fbc58cf18a651a1dc7b39a911442504f12c103054bb50f15381e512dc6e3af7b414b3db26fe767d83a2a53d7181fec8f6b196c7874befd6628b31797ee3c9260c7b7853b137893e36696e2a47277add98462ea9a0edeb7d2d3c0f2805fd7db64c2c7eff353ff2b36f4de862a42779ffd4dbe77b6a79bc9f4ea3e909474ead915fa3fa990bc82b83a670b163e79300b627fb91c4502e96bb9dde00f716ae6ad14dac647c9f7c2e5b2e505708b5fee996b8e9113a8f4f2caaf414061ee72e76b8bf47ec4f781bd7c589adebc2c267448247e30d659998d8037783494a1fdadcc819d7ad7ea2674f75e10639c3d3055046a00814ddda0e463185454a4455d60b9780250183d591c3db6f27373cd2ce4f02f206ae10a8c32d71226e7cb8d5b05909445977164983c0073434d6c0f2bb62bda66a16792d6e53a49ccb5ac3e285a6baba935f30e9d1ddb812a018ce04f29e2009ad678ba72b6a7112d6e7cfcd3ee7b058ec954a6fd7fd01018a6eba6209687c3130de58147b07bcfa02ec1caf30b59daf87db4618b4a5fad34cbc8014a7529b9458e05eccb9a77ef1621aa95513c6fa4003b0877ffa6d48805e7867dcf53447caf348228ce926233f65d553146584d6ff3dc3ed3296db9bfe69dec6a07add13037b3aade118b2ac3c52350b9691a6cb32356ad93377059fb8ceab68de38d96876d6d383db01f3cf620e47cbfd471bf6dd1f601210482f7c3bdd4c3bd37dd0a7507e1f0fe515151634813dd4ecefe97b52eda28e7a7129993b0af311abd3a07bc463f3cbbcb4fb0eb265a5835663fdbab0d8b8b5a73837ac98ced6582348fdeb41ac8ea9e36f9818ab9c0a41bac1389a6b518ea17df043dd50550f32471645791bf59855ed695b84919aa5cb688e569122786660f06e3a919ef9cf18c355bb397b86710c367362cddb0239aa1d32d489328e4bf92b3abdc3d0dacd76ef1a1efa28fdb848e708aed6780e2d8efb19a2e26fea56b4440dc3eafd796896d73fd150bbd967871f5e6ee5db58995f2f85cc2a15077d7d472bec2e30430af6891193ef03dfc7761e2b3b3b54a72d4f1084a8fc541526fdeb0633dcba14e9485b43065aee8750397ea88d9ff13417149e0fa145be666e6f4afdabe7ad8e4864e777c20ee7a2842db44dedee22f3ce2f97d72919b9ff6059352083be816a7515c48c5140a99af8e81b9e18b10074dc73dab55fae66261421629c8e323d8134f08beefbda555660a51e4b55a9ba4573bdf0396cc413145a941c4175aa672586f7676027f9fe211db87fe07a23962f5b1ad8f566f0d5b13c5146457276f307a02e1e13d00c5032a06d225248215e4bc4be1b672f1eaff16ca95da42513fc4315c7a6663f9101aba80224acbf0c87fd3a2ee9dedd1808c1247c5bebf3cb8d77377a508ddb484ed91203a438ef5ed3ca14e087102bc5f3828d8c3437ecf5c92eeec0331ed93ae33520740abae9b7bfc45f097da70adbb9b9b879e46a7d655dbf75d89773f737b66fd8a8c13506cff7b44bd85dee279ea7053f3ed8447fe79c400cf23726fae800449d27af5e342ecf776378e2eb449a3af27a40fe4a9806487b81c942bfe1a4b0fc146c971a13f83669e0189e337cc9fa2024864436189a9165ade6b864698ecb797ea05fed0d60f0ab4b92cbae36c72ccb5aa45337cc02dd086afed9e5522ecdb75ccf389fcd63c5a4abbf60908e39cb3268c76a08687588be67a856a841eeaaee8ed016f6640ef0f5acce12ab8bb58dda380696e3fb22d0bae0788c4fb79d00cfa5ae3e479dcf7d08b45f4592c2d2a7f8081d5a9398659613ba4932ebfd7382d516b2648ec4ff4477648069b9b2e4decc89547c16ab82a0ad9cf293fee5adb17cea4c95ab7b8e386dcae6acac63ad0d1d13656dfd97d5623dbe45230de597751321bbe5a03c879c303fd7a0d837d48141decb6df4f0865717628c85dbfda29df9a8a69b2c956c75fc66e45c08960c23bbbc706e48395057f989dfe675305067b3ed8d046db339e504d5b2bc978ab4dc261d8afb325c5e794ec79d63d8db53f9dd24b623fbcc202679fae8f7d39f7f7e0667b142c714b6a723996e5254ad2ebafd63c3577f8909981ce6b3eb1a6ad67a4e93c45ac3b34587d153ec5ab67a2697a9741610d5a176cb9b5856bdccb98f69421061c84811dd6660495d9f30548efaa69e36ead246d997c95bad0ca3fdc1a08b4be31b12daf211d3e29d585cdac48af8f2268ec304bb35d",
+ },
+ {
+ "ceb1f819497c0d631a9c9616655f419b5e3470fd3b19cd0e4fa556bd26cd9df57e960ec7121b2a2cb7c0421c1f84b77eb8277bf341490190ee574d1424eb09a281176a933394bfea5502077486bef23ee66e3127b732b7a58a04b9aeefc35170dabb030d4fc3f8a4c5ff194bbd0b89a379baca30ec81d576868f25755276e62c31e93a80ac322571313ebcee494592c3ff5cf3ecdec962645887d9aafdbfd62ea910af5542d4c7731283625bc9f41ec85012b42edb1792339e6cdd9c2bb3cad4c4792a064df17a5f74dcbb3dd0d90620ebba4fc6d1e1f9704dd60c798ad64d4e5077549d68cefdddaab81a7a91209b7ddbea43accb3d1c191328929dffdfeb4f5740ecbf0ee99cb9a1b73333d7ceb0b2b8f35f84307b9d44a42fe1a30ecdf2650dde251bc8c1d46978089c50d64c028f40611370ddb0b481df9624ed63165370f4788bbc396026b268c2023e0f04cd4f66e0bf439074c46f0ae85d6dfeb0ddf22868af61c8d5133097156fa61a3cf5801db5c3ad29871d336f7aa06d2a7d5f52e50eb3aee3c7de7bdc4d21f68a1776a7cc3954f5c071282febc89c1545fc672a0a1bd8eee2b769be048ab58ea12b356d658a6225fb8a55e752f1fc97ed64c2f87f9ae661514f1f56d9d4e47b001ae865a44b8a9fd5df8628d183bfbee781b6661c9cc76debe6c3c5bba840bbc228206673aa05498a8c715b0f3019f6b2d05cce6c233b5809ff1dc4a75d7f69859fcff94ad442d460b32f6fe348659518c16385e49fddee9efab2455732aedcd17dd51b5117efb2ca1e21ae6787437f48a7042d46e11be4dbcd2932ffd70fd154e4eca5fcdc57c6fa79746100b8e1485fe575a5c79089a25eb2d55d89e42eddc81b82c4f7da8bf153ff5353b7349b161911bbe0a14483fff6585d7f3c8b5c04a6dfc99db9548f0c53e25f0b16fa212f0bdd10ad2193ac18eb09972795f42b3bd3f4d98c4868989c4af7a760f1c88ffda59faac73256df1d607644f56a70303d6409c9ad716149bb58f01b4ab8ab475e4af1257d47049aa77adf9ce54fcd22b3d6ec60484da903a6991ff052ca37b01428d5916fd92c17530bb3385a805b0d57476e9f9417a23ab1c12a038b61b3a0898831f9615d10b468c3edc24448d09b8f3e3a2355dc5e069e880929eabcc97344fb6ca5587c5ac1404783848f531f1e915941e7359fedd328f7fd12b3c685f8c1f29d1a6ef7dbae3e5e32cdb251eb43aa2d2ae0cc18b3f40fb006c2778cba387e5852ec4f2d9b8e8ccd5b3e1f4781c974aca940c45d35d30d3b9584c750bd45a80f32f73dcd85c99ae107b92888839c342cdcf88911cb974d611b14b1d85a59e88c502559d6eef3b7f5addf7d307bb25c57aae669767db6d798ca887124e159b0317e09076cfdbe61aa9ddeda189036703b1cd9b1998f88325910a37ef1fc2e227a382ae635e847df8625b99eb6ef0ef10ce7a2a5762ad7d03a7a4e2b767c4df0b477d6e9601dc8e6438184f97193ea7d7a8c22f1b6fac1f0740f1beb8b68db40e0b22940cff2261273aa0be43df561b88184a9377e6a27f27942dd04abb9448b6b6ecb3a60f14dd39b58b8d94e1991cf9d3a071ba42e0e1d71eb211ca466a70fd4724a34639707feefbfd73dd9680d76a214924642a063b38b85cf30eb763fbfe889f34b20fa4a10ba214d938a5a092c6e9b73b13bd664c75b34f746aa360593c0f8dee0f328f0ad4a3e40d498490007e573b8204a1ce7a550deecfb15f18ed5ea6cb5dd95a68adfe4cab37c13b383f8273b1971580016a8df02a3f4f431c9de9e7ebb33244512080fc5852278081b9f4434109c3427441329e8071d19d0fbb74fb6ea73fbfc7c0ac1012d3a0948d94d7ceae9b0112ec43a16cb582f9c53e7eb0ad15e05ceda108fdb3dc9e585a332018d1cb19e4a75d86041308fdd8476c88e4826931601a3a5dce06fc16512f4669f10183d5a8d15bace4649abcac07358089aeb1e9b8fc3776f3239d5442d3be33d532097e13651af7c9a5b465ace9e626889800318447b8876b45dbbe1989e1eecbfb5cdf5067c71a0d7b7fba6555d0edede12f7228d7f9841dc532274f24060b1f52da6fbaa179b81ce962723f43601d248f8f4d5778c1653e038c8d27828836d562968004003810e9aa9318edf3260272b54fca2e012f6c04abe92c2e6152f3c3e973c7e9abe8c3467bdc246f0226d1b7669bd577bb317c571aa8758bfb694fe4dd17ce78f091cf6c6de3cb601a9d177128fce8d42e652b490d90c4f8fa04ddc71cac300d3dff699be3250bfdb2136edb0057af3ebcca77ba5b3ca34531810c5e2d4c5b5b3bc4e71ee9e30cac067b7706c326357fe0ad2a4bd9cd811b4e9d696bd9b4b70579ae246381210f879c769e5f9cc3cf8d70e9c94ab74a55f5d7bf61a17418b6edb6db4147fc40cf98c75de85421b7d192919add48e5334ebce2a06e56b915447fe085b7dcd677659dd55de1f705c389975e56e0338a2ef07ccf5ec3786407e8449d9011641786f1ecd4d3d3da975d61f5a442293e6119ab20686ea8cc7681010421226838a95a157e2de948c536aabadafcd4095dfda48e5613272289a8238dc945e5f1ef30075d5de096131740cdf23da1fb8b9fa009e5b321083cd93bba9271909460c09bbe1e8c54319394ff85c291814e21215816d4791f01424abbe4cc4c792d0d04db1b812f4d24b44caa76de2bc50f4d1d1611862512d87fcebd3c0b2659082b2423bc5360d107ad7b8e8ba7438ae4509105d6b618af25e75c51e272aafaaddf1e5a227f2b2a2c96a8a83dec23223cb428136a30b290181ee20a819cf52f6c03798e7294a89f3b5137693d5a8b7a0ea38d78e43008fc4eeaf6d077ebffd3ef7952620e0af1395c38a289832df391d1710ab5b103a1ffeea8c06684c03a74399cd63797c770e3f0136d8331611502d21fb883136a82f2034358880392fc3d2fc274b799e59b89f8f90d2a5a123d3c21e5bf3540323743858fdb8912c7c6329a3aea241075ae097ebb23c8cd50f4ff46b42486e65bda6beba5f4fe6dbb30f7e61b1bf690c9f00f7513c83274cd21bb71563257a20cc38da2b88c1063bd0849c8243058ee205853342085a8edb7545f0d96a6af936a3d4612b95676665eb02e72e0875100dfa444f039eddde1422ceed8d38e6c3dbba25064f8c6cb5786f9ca67712b7840cfbd40f99b1edadd4bb9a61f48124cf3b49d68bd642404eb1dcf428eeabadfba6810a4032f8ed06b38867a7098c7744d54dcfab8f0ff941ecee69da9916d54097e080cad86dd08bf53833fec4aa4399f7124586223ec70e2c31e8c647be06df9e86a976f37901e9b134e775de2a0fd53d545c5f92236dbf5455859c138b7bb1112427049d29ed4f5dd5c43cffd3113c276d9bba910879e55efe817189fc239a204a9ebe738c0dd161d10d60a51e9dcc8c38861d41ff029ffd841086803320a17ebf5ff14b6cc2ac3dcf0ce2eea9af7ae23597233599c2321dd2b99e06d93f84989e75e30a388f47079c2af545d96f270e064a43a00c76bddf2f5be5089a69a138de844216148a1eb0b413f58d831d9b8967df297455e7538442388cdda12d157fb25896c6e2b47696c76b234a88bed4f09dfd64f2e4b77627ef03049030190fe271a5a853591ee9218a0c6b12cb3f02683d665b211dd1480cd44c9c0566ace7d751902babae14cc3821374bec774d54b4b4afd5d1811ede556a7a5ad02642a878d2d32380e7efb9082604f49d51495105f827d77945b5cfaf2f2980566b28ce3dfbf1bee2e077eb067bdfa4cc28f5d2211ca99a615e69118d9391e3feb9b13cb4a2fa9682718189ec612db889228aaa3f3345a091aeb11f41420240fbb47caf567646d9e7c762d3288f8bb2b1165cf049a191db5042fa9185fcd180b04d3007c376e0aa3d427d66d10918821f74736816044366463df7cb3ac94cea167cf1daf2d1842f130295e40bad672a22da9238ded69e241395f04d5e3c3875b8294faafbd3d90ed56ff3e01c5a0a3e349d761273143686aa26d408620c7d1a35ccc430a09e3f750d3256298c6068c0fdded270f308f79d2fcba591d723ac0cef703d8f0e7c051bae5b453abbadfab98bcc297ed4201b03ebc195c2e441cfd3b10c63c08868db36c320707ecd6a37593661d70a81f30e6db4a32f98e4fe6b950ace55923631c8f95138781fa2af78d8104fe39242f1fff6942e8e782dfa0d37c863caff9492f8e5cb70046d207c4630cc29c20e1ac105aef093261d8d335456961e552ab14d107cbe14e9de912f0e5d58d16b729270208204469f917af4e710123c3bc38a4b3f485f2926f058344db105b9239829441a2d8ababf04aea615c0e350846d9bc3b5faecdbeb450f38f615f119ad1b5dc748e88107ec2fae01f0915174feec37b3e7248ed2699d0a5fb2fc785f17d6275fbea867aad815acc8a6fd3ca4ea7357d197e5a30082ad5f35a9d894c0aebb206c6487163c9cc20442c040e6aab33d7b4b221e4ba4cbabd975836e353129559d8ddcb3c97876cdba360da0e0c1dd5b0cff7957a444027db985ebefb6154453a221076c997d3954b347f49308d2ee14d1676b75ab6ef365f3de54aaf398fd96b9040253813ba734829bc78a6db59e3f1c0ab4c878a72d6b8681157919130fd3171126994dcdcdcf68955ad64af8156702c92f7a715ce6f7ddfb70f60e80c92691efbfdebc8cae252108fb6c0010d303d9027d4a5e63413b5fb2316d32fb93c3ea52a2a7df50cc0058c76c58d73f5bb041d9fb9f3c3cda9bee0c0920079ce4f1ef8698ced664ce2e2b3b86027ae2b3bcbbae5bf7ea3693d9429cf94938dd3a2763d3f53937c46763ffee6579d018358bc69182b1c7158a09b18352ea618c11c45f07fe97cb65faca535f43237879ae3e0a31efd14679daf8fd2ce25eb8f32218fa20afc586a98fd908d3fd804cabbf56dcae272328011b252dfd83e5f0a5fdebc6acb04c5540255e1322de5fce9db5aa4cdccd74dde8990ae51cefd6c1edc1879971d3efb1f94dc41b2b23e9c9d89415b46189914a229b2f3e8b05ff78c68711385a00e9534dae6f79d15842aaec575e4ee0f098028bc74016cd3f8e93c6a0cb21a0b574ee63e367343ca9de28003d76e02d0ee2b8d622cfa3615d3628fd02499eb7bd8c1aa1f34edd9c2d059c6a7c7c978a5e4f60801e03e17c3a09793c5217f310a30db1965b8e328893cef20f4a899aa8d9fa28f7fe0a733813ed7466046776a874273ecfb57158483f4a588ad4f232adec5ba4ea651822780596de09fd54b1717bf04130619979a0e3d12ab7c35d64afb8099a1d21bc952653742f50c8e1c244d10374329cedd27fbefd37815a9b3112a4cb2fc587c4ebda381b2b01fced45cdf0b9ff8ca7d10b65ce42e728de183a82e369486a2e3345664e70674a5dac174d6616d90de8e472b62759df057119875483cfbfb103041751747f9cd12bb31e91caf79eb2db1168026a4707dc618f30",
+ "e45eef9561f3acb3672b4f38570256e8cc4d877e2998e72b022e33de8fc20f7320fe0882f2b53559e084923786e8205336a7d15f3fb88a41e7bd20767f2feaa02df2221fa7577988db0bbf61f3dfb429868688c53e130725d0279c505686f083",
+ "475a44cde0cc931edf9a44b0c1e0001766f09ade023dfe6b59a6af800e549b55",
+ "7812a320691ca8442767a51a",
+ "eaa577bd67fe79ce4586f43355c94528e306c1678946e4f7a907d2a8ee7f4281270502522119a8b09b6f05d864921cb515fddf6a1000fc2f67b52d0627998591e2acf5b6faf71c278e5754b2703662ce670dd049da8d6e280c2b84d6a9b29ce28980563c40e03381a49c54608b72faec9b272ef05cfa41957d9eaf3e944b22610c725d8efea90aaac6e782848d368ffc08784d7fe37ea1effbbbb34952def29fc511fb10a1282bb0b6334328e4d00529a44de3259b522553a07d524dc75f431cc9670127c15670c0df419826617cfb5ebdd8788d5f528a9eb1e61324eac5c1746f339aae2e2e2fae598642a389da671482128acf2d69814258d83de98f186468136868b729aa5f0874fef2ff2575a1f87439d64e049e4d0637e9c99ecb7275417af654541306615f30b75a6caaa563e4790dfb28fe9f0e7881ea2d885eefdba99efa7f878925ce7d33e86d888154a1b03189429fe20af8fa3a68d65ced9b690a709031121425cfcd7e1890ed9614f9dc3ecbd0e38c6c84e453e3204978ddc1ef8d7fc6cae28c61a472d8e089e23209f0c36e80c994af771e6505e72ba90e5543f6bad6dcd31fdd468b13533a0254e44797825764ac1f63747d8d6ca019ff16fa732068ee94be382c46b168050ba725379df31a98ab81ec8eb266a3c3f2e1cd95e5f12b3bc79b8b435e4d94098c6184631cec57e9d8913458889223a2a4541f34d2f9df380f34c3e541fc587f0a6cf08c82e99476060eb84709a292f4c7a8551bda3a9eb6735787dbb9d7f1e83937c2e0e49f2cf6e0ab0ad84c40fbafc3c7e61886a8629bea816972fa0afd0f617b6340b1af19e341875e97565c8eb0b25fcf68696ee674d2abdc29396bfd0f282543d2b72a239c6470f76d3b5bff6d1d064e6e2d06f9deef2aae8a259c034373efc820f9a2fdbce36cc27f35dd6386de3b49509d0c305757257f8674d958c580a09e768c0f6ef237416fd53c31511badb2e7cdfee636508482f01899e72052b46b5d844799cf94708520178cfec2b61c8980fa7dfaad8915b0b75ce6eb57ed4a01edcb4a35c1dfcdf8d60f3191bbcdfd522a0e321ea41c2cd87a303522d0f98b82dcbe53232ecbf0e2528de7e1be75569584bf2ec574687fde67ffe9827ebbe78f2e5bc4fb368f3c9b0f588c97f7a139bd82fe86eb605b8e29cee75d07b510da1b24fd62cd2fb366f1621e7dbf268b15937f7f7ea4acf6e615775a32c90733769996dd2c5aebe08ecba73e0bc4781d33971992b2764c1b08aa972859cb61b003406479423254a01ea85a348ef249d408157cc0962d1e24cd9c426e6e6a3784dec6fe935be1f6730b01e8683d97e21d8774b2e2655f85db7149e930a44524d4f86004cd687d8a528b6ceadd890707458cab62809110ee28f61a7277ed79dc41e573fd4a59fabf15393ed4c21bf4d5138ac843e80bbf5e1c39ac2d7f2147f35996eb51a9e835db63faaa196b8aef1823ad72523fbfcb35b5560582a48a25ab770e7528e4b3ef291e6f62f5fac916e2162b3b56304287e46839858daf322b0de083d1691d6bda44d66d085ef0d0ad364eebacdd0a43a4456035e58910d0b2dacce45b1c0beabc784f3620a3e4390c345df6117b86d4fc386523b7ceeaecc21233a2865ec6b63bffba6689fb3323402119db8f0665a4730b2e26ca6411db04f1bcc78ce6272159ed2665a286f1ad7758d6d90090a6fd320e697dafbdfef575077e282b825bd64a4dbcf92d1fc0c6f795154e8466ee4b318f2d44b6f81c52523ab68ff8367e01090c2623e00b4008e784049df873a35c29e0abcfae7acbf27236adba0b913d19a15b4af4996669aba4c656c317084347ca962ac8df15cd2f849f522016eb92de4de62944b917d88200ef9aa2def0d13e5f4ae09d2eb4a2d0800af1d704cb01975f6d59768a2b50e39e78116147fd6dcdfbc08354c1b4033bf6772fa127856a4072556a9f07bd7516d01ef41bcb519005c0a3b2a04400427ec033f1b52fe5fdc1aed8e2521fd0fff663e203defc39d7546281a98a502b8a470af16cc62a6581c9985d7ca516864b799fcc55a803ce80711484f6b81591d2402bb1499c95dfb1dee9846679c22853be87c84b4547138dc4fd46b4e79ad12773a5392540a595954112f0cb1d9be4d4eb3aaa4286b6c01520558d58587d9d7f0df3a0282011ce01c9c17111d10ad61b3675b1826c1ad37fc562bdde951b43f890555d6f74ac4fbdb9abbe8bc1e80bb6d52c13de8960a3ff8f65201265e82981dbe39e0d65cf3f1fb6c56e11f9786210383d0150a5e0cbbdb52ca8b2bc45c12fb572657380df369082685b3de9847d5014beaeef815d63e203cc911061eb53d89a312d187f9f02760bfa71083fb643f5d8c324c410070b7ebde250a185e7359837899bb1568a43fa3418f39c12feb03b148b924bfb98b99352b1fbad3f07ac8e4302f85d1fe9ee4bf7507972670ff8beca105cdeb037f1cc4f944d6ca869d0281653de5ee93a7362420fdba8b01a375ff08fe27873655953ec1c00f53613c6ab8b244e2fc1b6babdca5311428d06f57aa4882dc870165deff75ba877dd2a04d1799f26ebfac97a1be53a83ab77dbc2cd4aa45bd779f61b1283eae1a1866ec8a9c150dd0a4deceb2ddea1bc0f4206cd435600a8f190b999b952337d9eb2bdeb3aba2cb2e7000319056629dc1f00901f0880278509417223a3ea0919fcdcf12bff0771c7cc725bdca292068478ccb2e1f35ae8964e0601789a73e7e7c1769ba53f865910fc3d0085c922d7f7849d27b6e7503d521371351f9d7dfd5afc5df0effdf6ac49617fa228501ad72154a73e07781dc4b07765dbfa721d95cf1dc41e161cbd34fc7883a25e3ba6b03e504b2c3b98c8b12ff629b965c2aefc26d74faff7f784baf09c3fc38c487a9d1f5818261162f97e9dff70cf42eb5dbcd7bebb66d68f26d917ddf2a3efc0db1e3372b170b4cd18da507e44c467943f73648dba74db1053b53f989e481c3054bac22c6342fca2c26d30a859a1312e9c353bf921f68136de2b1589747bc765153927c31ebe749dcdff98b5da84c4b66085451b4c87fe1ba2142f98636bcb268c33f7b8c2b96a6525298814578377aa189dd73d5bb27ec5cd2110d8751c18a3110273df2595d4c3a00809bdeda70d86c4a8169b7010c9cdeabfbc3dd3266518226d0ade9bcc4825f18198c854de329fb8fe456dd3bf35d89bd9d2384f3f3282f6872351a18a2f852bf173ea4426de6d01b3ef4b4685aa82df7dc45b99617a8b8c8a0c65a2237b3eaae8267e1f6c453f485432529d973924a080f6a1cc2cc18f804f53209383ce3601ad9361afc331707be1c88b4370404cb7fe0bc538df04adc5c8d9ced94b4c474b19619a53dca3fddb434cac09ce10c0293fea04e8e1b19fd3ff3d174baa988d91cb604fadc59ac0b61f4f87bfd07eee20f7f3ffd96766dd6f3555cd48da7ecd71d2fef34ab082678bfc4dd007669b3fc7a937a5a46269baa7e4e4e43eff1b2b847ea70b6c6c23905d6fb2fbccd944251087ac00c35c2eedba30641797d36ef9d3cb1afc0e3e8930f5b605a847ee77106995bd44047294d04350194369c5a7bf246d1108e1d18d9a638be0c051f695ce86579db613cd8922e86c683c91800b9a34fe6339e0dd79472daa662f78f04f0151a3acd18f11faa4e1216222843b521fb998c8490ab8bab27fde36395b456501307d07b484b453b189fa339282a634af30fea99c9af8f877e61871fe743238b2cee6cb69dbd17d574b5106ebe4b0fde4ef42fab469a5ba7d62c23b67d857f1af6ac981c320db70cdbb6be41bbca60bb7a159ee1c85cb82e0a220064359c06c660b75de6b49839eea68c80283b75d9d627aa4500c0c0f21edafe4a2cf7ee079d5310479da06ba58b142614fe69cb236c51447d63db31cdff91485b46325c26d40dc6d608d46a5e2fb01df06064a022ddf6d5cce0147d5b2a5aba5f9fadc5e778010a924e00a13e21daeea2cd330f45536ef4f42c2e77be00bb53b3f9a93d3eb327dbf30baccee5d26849cfad654ff3ef2b035b78dd3ef42de3302e5514551a968a205b823dffb040ac9452ae3efb43219b02436d0761ca11470405510e534d56caeaacc40eaf9c47a39475adad266f5ddc813e71223800dd46fa7c02b078353f870049806ed7ba57b40b7c3c6272296667500c4b97dd2d7026698b6bc4985bc01be99e0097013a2632c71740888ffaf902a02bf644b38cf9a42528880d9dd142de967cc2ad3e1f1737f0cb8dc5c59c252496e8cfe4e53c82f4a28d9ba2bfa62b6415ba3e5e09040d7f3e3abfeba53e46575e8817ac5eca806ec8a84c7cf77c9fa86c9dd2940f5b96b25a92d4a8f894d4717c8f80a62a35a51d8511f1e822fd79e6fc27cc3f3097d9e3272447de6f223971657ded9e660ee4f8836359742ce7616fd0ca2de6656c71b212b34b8edc71ff36bc84ac4af58eb1adcba4b2c0cb31468dbd2c2b7ee6752981ee1d152c4e4a9b25b2ce87796820def34b662381806d2e4fc77f0b69d7a87de43d94d62a6a6526a7f8c588392890e96f9c51bb58b4f438eb5d197477ce9b160d1c898c89ab408b3c1d648be93b531a5bb4988592c5a8999ae3acbe586d947fe6dd507cddb92dff4974ae17ab99aad5aec9d07b96bd29489876f51afa67570e86b69321d9e565d86001514638403f86666dbf93f18e0a62bf65db333bb85a3ae12d8411aa3c2a423a29bacbbfeebb8a5bafd90436bfded16f992232360211086a3084d9fd1980dd96631820a2cf25c3ac5c19d164cf5ab9a852399491962100ca4fd640146b7ea5460b4fb9e46bf8d23d508a4eeb8a3e9fad8249ece3648c2ec7705a7414eb8e8d602549204cb437f589161fe40de1447d14efa4d738b775d0333526c845cef5ffcbaf5c957df1d8022176b56eeb198e7ad2dfc3d7ea46b125ed432cd04c77efc011a2dad8573345080d7c3cdf5cc160fbc86c4ee1959ee1b8258056b0f3d9343c22dbb2f7858c5f162f08cffdca1acc866aa68e5f1c00b74f66544e8a61e429335adf6f73e32fa87e48e1adf15bb6c7aeacc93713dbc31cdccc9b0e52f922842679494039c395cc1d95eb97ae4df3bb8aba9a2584d97a236f87cb22f00c0a078b045044a5c456e22b2b94a76a559de2672c880660f9785b76bcc2aaed780e05212415c6e73880ca110654ed155a1004af45d5f15ae8e5bfd4817440c5d3d5589eea2c6c344ca0d85d91460638b37f877ea4cbbed35ea75678ef2335a5922cc8541987cc256c8f58045028d33a1c4899cc32265c619ac782ff998a478996be6a0c5b102a664831b395a884f18e77885d860d6b236c52a8066d2ced25432bce79a31b23117f405ef4ebdf3517de98d288f8c3baf04b63b6817c46c14b646308e9f97170b7dbbf9d1a36480338d8eb7466df56feb6baef42cba75512954fd7e33961d247b7393726e46c6e94e156d5776a89ad3e288554470ca0bc4cf4d2d2b0c01ae4fcafcb65ccd6ead03df1d4d6577bb",
+ },
+ {
+ "228eabb5ad8b4ff13b10d13b27372bc2152dff149859ba47d9c89b741d4a5340d8fff5858a4576c55547007d7e2b3f94583ea8f0976237712bd2e5481c3988f5387e7ac2c3f18718388795b7b2d44b0a13f3faaa55311b800301c9203a511572cf8f349280bbabb9424070f415bbfe28aef8d20329ee842cef4d4c299e619b6ef1cf00718aab2accec9ac00155be2903b6fb07dfe98b0bd8d8580176b99ce4aa6be51cf59046c17ce1817d363fa63af5a241d48bcce064a438651af102ff9c6de4b86374fe24f1dfa66e16e51550dbb791af425d8fa601c70c1bb90e1a557bfe0dde730b0364eba9d2018ee751699ee219e13fa8874070935b29a1767e1d748bfbe796fe4b81a71e823605d39fa4b5b885f4610c34d1a090fa4106785e7a035a629958ad1b00cb9d36d171d575268efa1bef064fc0a6dfbae8e532466035a0c2cef96fe9f93b872f0cf804811e927b39818189412868fb104e2d56ae62f77031f0df1ae91aa11826991ca7b8af22f130a47a72cce36ddc319b32dffd294f2e192e490249ea1a6f8437173ce6392d16dda888a98bf685bc91b89b8ee1eabdfb1806fd61f018d1744fe8b03521de4bff86d4a811ca2ecd5be668e9c752a6c26aacc0cc9dd89d112785c25ca6a0a7a5267b4e37457c04a0626c8a29be30ec28ddacf47a84918bab164d07bdedae62132ab04a6f2c4e108eba9ab878caa4a1a7509521d427ad7f3dfa86fae8345dfb5e0d46ce3a94dec84f7880c7422468ea74fe0b4825b8c762b34d5d9b82ba96e0c7dcae01718ccac0044a87476ff031e3ee3c2c13f5f375a841d243c38cd9a354b6525527de1fe7e36a6e2ad95e5bbc4c97e85f8cdcd5341da777e03451838807d5dd2eb4fd15976783c140e21cfc2eb3e58e40c16374de0aecbe3e3d41c64417a472cba18762080a2348ec3f441bf229a932ea0ca7c816938655d0c81b14dfbf86aa600d0c68172fb0046ef51f601ec89309d43ad1eacd583f9d205bb1ff1a37a97b44b5e35be4945f52897eb2a74645b01a7f82054cda44e9fa9f9af9bad1a235155718713bacd08d354f3fdd95858db0040fb551e9f93ae399d5dc53a67e88bcd5a02d104dfd9d824cdd5fe262ed9266fc47b7e640f2c9d9c7a62c6d24b429fa55560aa254a824a0858482e771144d6d5b05539cf71d75bec3a22be75655e1ababec4dff9472a019f6220067374dd49252282e4945a407084633ef9c88d14833bd95335107d36afdf56a642cb739bf0a61ed53a6915baed78e9d74166ebc492b517c7c594fe6564550bb7108f43012551e65fbafc0a9874e46fb64b5b7aee0082a5d617a43b8bf9473309c6761aebc7f13b72ed460b522a6b0875b67353c705f99d1d9dc899870fcc90c632aba1fa9ced6d7a2368dc4dd3d4b38a5807415e00de6b9ea70525a6c1b67d04521efeeefc6c591fc5256d990a1123522864a029430bb7ea00dd80d283fdd6d61cc5b509221e28f73386803d97a38fb0182fd95b3b91353c6eb60ef2b3d5c8c0ab8dc9cd9be2b4cf69450d00e88cb0f0bc9a4be82b71148a37237ceaf945ab94c365625f58171eb15c1bb244a87335550d813d28f241a3296520046e65aff3291555786d7c871ec8a2d10d4b44429041c3cd6ab60f0def742de3d28393c5aca92b150697ac15504ee66d8a2aa01a6c63d7c719d6d4f94af2ed1d8670e3231a0e481095e425e6231c43ad36e3b7a3478f6a61563f5aa13237beb8a891dbb29013c325f7f91c1b055fb83c436fdf8aef49ec457946e6ab7e955427373fd9c743acfd4b9609569b591ec79c7ea7276de103a35a4a8a05c91f59e04689ba1ddd570b18ed046f785d7e4ff9fce7115ac814fe126f781828877208ddfbb2ebc919e6d1f6eb417f38bfbf22ac9633f75e58e560b85d88d0e4fad9b2e68c9ebf9675819d50c30c8982bbbc2f41e02690390bf0e16979b24e648bf15b18800aaef58c3c465f38cfd1e47bf1266c17b69523b7868d2138cb95c4bce0dd3ceb7c2267b868b6e12888d5a489fc0091b295b56a1c328b54fe1119aaf1e6d7dd52fa450b52fbfc8b84c2200ebe209060b655cad288562786673121691809366af37b76567762d1fc24f1fad3128b43c8d10e9b6954b2efcbe40124fc0a5b670dd6dd544e30263a551825282aa06be3817a8eeacf31ca8b25cba011d60b78d3d2462810764e4acb566ff371005f5481c9d36c991527143af2c44cc8cfc59c920bb4a281f2ed4d494d30ba4d900edf59e23be2f763072255cb6f1e8b24ab1d305fbfb2429cff8bda303617c034e71a17230d0e860420dbcf9fea4ab48557e4d50797179496936ec6c97686fe6d9115809e14069244d251d4bc9c8931e47e06ec051e709ba1df526b55d959b37a6f3408833aaac80cfc9cb99915eb7d83e26998f0da2492b986fe0f5047b2cab6e6d33a117df21e6a8ec7f394a3712885dab176a4d6095e5cf75dbd3f0077e5e74b1ff8b902072380cf172562884de852ff5f07c55856224fb3df8eb44764ab9284944b86ab6f176a863cdd0e7ab5616a14692f6cbf41bc63113b27689fc2fb145736aaf2a5b26d2bef3a2a59ef8bb3f3e4d360a4251d0736482e9ed7e189fc48c0973b6649988228c2ac72b23826a61cfa06b11f13c8555be6e433d87e20113eb74c94f0e51719a7b38c59eba300089d06b9bc2a72017668e5aa3153ca4282718f1762642e7c1be1f865cd9b65c6387c8fe496f1e60d5acbb78c2f71cea1f35dc955b1e7d1cdc9ca339765995d9e05dd729cdf58aa2a1451b633c374e5b6c2af1c8486ee4250a875e80e1f359c15130eb1e2575c0c7badb2af61378527fa24347ebb12c10bbb36e3c94619556b2c641d0ebb691b2706cdd667f55b8fff8fb46e3ac72f3682661a4bac2391075ff5145eb07d69d77437adec2d096c1c89208ab3e7a9ea6a0ff4a5bc1846b3683bd7c6ec4520c3c95861a5856b0191e4221c9819c67273c66729728f6035e79c0dae8842df4c0c27ada1ad18b34efcd55b94ef120762e87e8c5afdec80d5788e83f0d1533cdd7aea8f27f33266e007b274f6d48c59bcfad607e8b298be2b17322be88558c60033452826778f167f318b660607bfb2f285cadb385399636acb8f5350d819511b5e7931c5f8483529d3ab3fdb5ae2dde0ada918f1327c6c0dfbbf5ed3c8afef171910dd0169022b3cad5b08084dd5e8eb8ef1ecb17e48bf69f80e3db0ae1cc7b73d94b89696e3c3443ecb4c7ca12568201744d1858d90ff759f2d264d49edf47772bd0e0990c14dcf8c8a4c2dafa44dc6e92f4c66b03bdc4f68f28ca2d0811a433e184cced99a8e5614ca83c46ec18b47e0c7ae91037ae06c6d6d0f3dee19711c21cddafb5869416d23c5219296acda7774891877f3f8d46155d39f43ed10500ede3afa26943b83b800b54a9752250ec6ae173e920002f365d692a9b3a2f9b27124ac97b8e81b70e8c0bb7022d07ee97e962810962b03fc019695b5399f77aab414327cfc5dedd51e99453179c42ae85a42f8e06e0cec6f937224dd019c77c5a0ba32ad08107216a9c758138b730bd5b5f4b613f192839514a8621634d9dbd5840e728c1ef4a2c8bbfadc376dd80d13dcb327ce55ab536a43b570789f5c5e135ac0af79b54232613d0e989ae695aeb358c671ae71d508b58a793e19c58c3d204cdc9a021ecc634bcb0bd6a1917554ea3bd688adab8163260a914fc01d7ce05a497a5c5836cf9401cb6aa35cd008470bdecfb97a511c905badd01bbb4d0c05867661debd2162beeccd52399d5a70a929405293916f33ed0d03f8b850f4bdd77b1fb6283118d71de629577383c81cad086f4099ce7476cb787f73c96431a0df4156f7826fce9045f7e7c97bbfd618b845595203cdc8df4638430fac74a07bc5f773486731d8ad29c06695704cbe2882077a85d543551b7ba81b181ccb93d2b3071b1a38f3c762b42df8246aa64cecbdc772830ac79e766fa99e8c65225f28297a32526df9b51227bd368253737f013ae18435a912bc18cc4a95216ce449865e8bd8bc759dce9d4af52f9e789eafa37023e91946952202dfb7243cab7db2f9f98bb66f19750c547a2bf2e2ba92862ab66f33fcf465ffc41d23f0b891a3b28b3f68ea48dde6ad4802902abd22b0d7d9101bd61471c5d88ee9d9477b7cf9f6ac52e0f520c79278da22938745446f1e647ae478ecba416b941aa31f979d0633efe72910bebb8988de1d0013616f31c5da163eb6c07022649ac57422627a5642618f53103adc9918f9992c5b085e10d2744f9934bfbb994a710d6cd387c325e94278f97d5582864f1bb29a1400aaf674ea8fb99a3b42e4ac50418fd804a5b1471eaac4642d4aa338fd3d5d0dd84372b2c32c5cfe7f319acf731a9787b048cedee3833300dde639cb1386c8fbca4bae8d67fb7bd72d1696a0212e27e166e6b04a79e34b47c98502ed0bdbd8d61777537f72df569fe5ed30071b57e8724e98ccb88c07f0458cf32298cefb6ed672b255e581ac756789b57e950d57174bffd3f47bdbe4b168e7e3f1a6df508d4202d327947facfbf9526a9e5fc1a5abb179902d4584deae6cb2900391e080d3f3540b87c3a873ccfaee5b4aaff0e6516a867ea00b4d5e680fee6b91defc65c240614a1409bdd0f49c2c4f3c1d258d77abfc17a749660f49547adb236730e5a7a22fbbabdd8ca079a8efa5b605332db12f455868ab67a1ffd27d1339bdf8d150189cfbf6199c6fc27c05788138a63267eb8ac086e27286b4ef99ee9d92cfedab5ce9916675f128f206a1733f47a597232067aa12da20c7b9cab6575d7634f8c31e9a29948b528681f3f9c13b9f585ebfbff8c28a299a43e4409b31b6c02a79eeb493734fe5f9c1d9e3830572eb54229b5cf525768f695acff48c76b4a6e0936b7406ab69f06d33d3f04946db9d7966ea6e8c50ede5abadda28149edef5223a6938d5c32933070d234043feddbd65c81be218f9d7c497a1ecac30bb9162e60a9bbbcdb4fec4b212050610e2b376aadf58b3c9207860d2650d0310ae6606a8f1b266b6a13b68c3306ed413224abdf19371bac3ea1b964f28996fc70f666ff118c6a7c9f2108d327f5145919c03832f754de35f5979ae72130e39126499037d6fbb3751cbb4843b05d9dc91dd5fc1429da491f72e3069313ea243933b47109af247fcbe0c70f9024ac5a41815655ab309fcaa282d03596ba59cfee0e40f7bd657689453e98d562442fa4c585f970b6983a581b0b8eb1c5e780b3f5c1abb326213c6b5fd440c2187066ddf55f4eabf88804139392c45979440c6f05b7222bd95e963832d7fa4a4760273cc075e8b8feeccb917e8feaf7d3f766d9ae880487e69bc01872ba62b91b8af5dbffdd93fdc95e8f47ed793fc070a5991f2e9ea61439662dab218f643c1959171937aa160008a548f51f87b58f2c4fae5aed556f26bb9cd1dc2b3518458e2f5ec5d974c6e11a0ed639958cc8c1db771cc8cc8bee8727bf6452f47c9782acf548856a0e67841c3dbdb1c98572a4fc8e6cc8195a504019b4930d302a90dc20d8628ae6c90e0206cbb3d05025744db4e115cd3b650e5519a1624acbf226ebca8875b05183b2584e65289f8b9cec3f7d010cb9671a0e80bb70ca8763f1722d79e8decb6b9023baf64b5981e745c06546cc1e",
+ "ade72c2ea29cf829ffe99c2d63840b2eef9b51a9919c02128347d2e88e9f063b86326928cf6252ce4beefbae7206dc61a22d0b33c90d464d551835e3b73c1e3d6e88663deab80c35a607e4180ec079b0ee84e3b7922904e7423acaf976e837",
+ "43348cf32211d7daa300de8a4218543c8e3c7373ad10950765c39760f80b733c",
+ "e4709d225a552e90fb357413",
+ "562050bfb40451f27b1181c389508550a0f46b53d14ca73143da9dae3d3d2b466e9618db39e3219675d2b6eadded7dd9c741d7c9bf3c5619a521189607acbcf6b3964d469d966fa134444aa06d80749c873f0f976e0c5efc5be8d00a2729f03eda6a7b8630575df8b3a19388ff88daf0d00bb3e7c35a525ded90a4511ce815fe6c8904406cf72d7bfa14ca533566f7b54268835285c5402e22a63f98b5d90c86dae0a76d65eacc1ba85b3f5a1499d5f3432dd5455fab9e8bfbd266e99283c2bddf9b556410956b2f061603d1fc91194766f90da841699ba7da3d53ed5abdd8e98034f8fe734446d92b458a731aa4c578552ec1ac5d1baaccc4153a67b48a290602d5f955d61a08436b27cfb0786a80afef76e1266310a42d90feeb3bcc40ae5c4506432dcc92f7e5758ceaf277255401f5c5f4b10df93a249e38edd9effe7bacdf7fecc451d3b2cea77c9bab0403450c41929775b8c0ace46f6928f4d9cf3adf86832d298ea32b236d3201464e2ff506ef01da0e1e389e26e2b3ddc553b369b48d1aa5dd43edd5cab065e276aeff72a4c43206063fc7eea3bcc783ba2221f5b615a7a43a75cecda6bca5aa159e9208bf66af61e2e465c2daee630c4c62077ea6ef0e8b4b4e272d4e93a5f5284f9da463e1a60f815a8a31698ecdc09dff2b62f00e37aea5fd4b07a110cef27e12466c1814d3b10017cb9b8e12f2f38f10cbe31296de2570d5662b16639fcdc05db81e0d48178d055ef873501148d00903ec771400fa4873c5579dc3265028f531538f6dab1e5607a15c8b90cbfa4835107cba6f453bbdc71d08c7e423f58b44be38a9c8a610469f2551ee6177edf639cde35fe8e02f76b7ed106d691a876a4fda3b42d8ace3e0d3d4e026206c5d7d4d56fdda9dcd30fd7b74217fab3c617903f1aeffb8363443ed128af94c391810e327704d6f655e57dece97658d41e074029823850ddf7c5937af41c64465046d8544bba65c691ac69121bd272107f7eef8cfdb6a25da5da16d1033cede09129d51f6abfe63905a6fba9a64d7832fa35825447150595a60163af848eea878fb31a5fb97b1859efbfcc8586eebce8cfe64386461a9b88aa5efc1db43c64dfd5d4a45aa74803fd178f9e16a3f59acfb6e13a564d645cedd73890d0a82fb6dffeef527694a7cf2a89aed9750c3675a67505bff77de8d046087bd39a85c90aedb085e99baf04c7e3bf92e350b332da1b8af85550a00d68904ca426da61add864496d6ff442bb0b848e9aa463bb0c2085cff1a83a47d6f702bd184cfb5c139752754c8978d27b58d364bd88722b9097ee3a6ae28eabb14ca7c31e40461101e92448dbbc63b55cfe56efd078d0058c5e6146c73bcd949c4b3ec9f881b9a5f7b41ca83301261e0c674f2d35d96761baa00ce0675c082bf73dc52dc726a3e605067569a372d2bb47fc8fe1e74f00078ce6f352a6d9d97fd2834670ba3a45aa6751eafc7ed6694e1e07542860c8ea516f296ee901a3ee16b00b40419c74bf6db12c7230325e85a918f412bc2f6469c1a13a5aa77f028e327749efd05b91053f49d9f1edf49aa552c58c68257233a168db60ac55b4086ddaea275b078869cda7b69493c4b371b4e9c8361357a7ac7d3d3bbb464c960addfa8df2b208b21b090d540c440241598212d33273203d484e0930e22469c2a8e866579a4a2b3db8f8344dbf8baa1b97be0c4d976f6aaf14cc09ec52630139b894b2b6f4dad3a205a7b286253f1522b1d6e43bfa37beaf06f831c6f0945cefb2593b9b298da13b0d910582086c5d7e256ed4067bfb476dbe01bcddb437d46ba716d6ace2ff9912c8e460ad33ab3d8f97b7b08dd4ba9e01968d1949ff85b4b9d5b8da291fc0f90ab1eab1d246f67d76092b7a37528ceb388dd76f8a8f0aabb7490f02a2c8bc6498cb26350d859c466dd611bf0ceb81a8b7899c67742c22697ccee21c4963acb003d15c1a2078112bab05595917584e417db3872a0ff0a29138bbca7314449b19827525340370d7e48fdf9f7c6b4a280e78d00775a291081a5e78e7a00ff915015dd5af5f0a45690baba8b1b503bf85f326c23136f4424be4a559aed03fbc81400ac27a33dadb2155d1704950d98043dcd86df1eee78f3f266c4d14deb8126708f74b59aa15e8b497c6a52924a473f999aaf0abd3d148fee8503a1568efec7bfb0bd463402f563e4019cc9c9e1eb498aa54dcb659f43b86df0a34de4e51ec558bbbade3d69511d3fea2baf44f67e85ada7398d7f72ecadcd9e981f82b0743ed74bd33088ba4cbc85b0c99dc5382c599706dd2d51aa9f470c25a98e7e8248dec216a155495630662bf6ba0b7a4baa2cdad30e9ce3e1a65e3c23d69d5f946606ee8504dd70830aa5a8ddd84f10e064695469727d2efeb46186c9d3b7a170057636f05b9ec4c2de7d935fba504a1e7eddf7a5a95226b253b0b9eccec976ca3c57599850db40c27a51ae755c1f30d392467cb74e5c8235861d11d0f8461b0e1d84f5718d64ea92da62f4de184a6499dba473e82b3d197305de0e494f118a263237c7b4c0652327977edb427ccded35552c00a5804b9557ccf2bca2484d9da2c33f6c1bbf2c666ea10b4644a21e3905e5c4eb417ac3572e783428d23dd7222e75c356b99e8183d033034e29e618c90e66ec2f1e9fca47d82c1cffda8ad14c96045159d9437e91ecef41d24cff89009ff57e18c1a422860aa9cd31dd2a85b07422c72a5decc614a9742e62a4988f394421b6918e51c2412d749bb53b1e8fed7b2ef0873ffe14fa77bc366bbd5fa1432be465f5e25266c6c12b55df1f19b1a491acfc5c9019f122c422243d751d8eaa8ff721397915171556e999b34425f7d3ad6f6c3323b8133b4618c65ac16cb5941edc979472734bdccafc73c08939c0b1e306ae3015faa9cfa09ed6560269a1dc54c2c046a12a178144f4381f7b6fd3fd2d28f778d444d9f7a0dae00ea96c6969b78ef326a962d23275f1518f0e6a2469440612f3710b53538fe99a6179471be8c5b2d682ab3e9a5126e41ed6de000cd9e92fec3974e0f4cb2d2245d03d6ee80d6a793b16efa829d75c796f34d4e918250f457703559bb48ff78f0896be1bda403b7f1fd6a319d68478ff70d88238f2b8afc7d20e51757bb9db3bffb35a8040fc0db913c4f03d48619af7fd24cb8986b3e139058be3cc253b3de9b3bb3f8dab7b8818638279b2e6a0c29cfe16fa7250d3c74362ffa07e2977cf562140fe28afba8f61d81f7c73bdd4a2faddb00752bb049d0a57d05c6475c7387e6716ee31974169930c9fd830cef138659cf56f2212de185186c3d683fc6b7fd36e7821f69d0de041a569765066dc4a1934870a7b80f174e8f9e484942e62404a42b21658467873865ef94fc262c231527f39e82dfec91215947b99567daf75c6a28073ee4e67d4307e4b35b46f85433abd9812f35438b34598ff3b6dbd60b60747ad64565391df45ac80b272d0141702ab807fa27c6a6ba2f42c3facfae0c773940cb2943bb1353b41298258bc0d07542b69483e17ab9ce709e4160b80a0968dae9af8fc7c0324c753ca4a11a6df32dfa79a87b445c988154bb3c503e6884cf6d8f5e062a16b4ff230fbda109a6127d35e3bf2b29bfd3b18ba275af773b1981d603300035e046ef023d51874aa105d136bfcc9c7323bd0513a6b2b397ffea71afb7a8d4695411d86164917099eef504f6cff3c5cefb88f23f56c4ae3e2b09a3f353fa55630f45f06c29e8912e8c3c4f493f25eda781680585580595bba43dca9cfd400d9eaf5081d2c6697da59e012dfd0b875336b88fe16609c2e9876737b9afb868ed52417ed0c6b359d582d585ff82d98edd4e63c6b65cf43d4f69eee2af4819157b8a433966953862d1ff2c6d0cba382644a1b0033ddb7be3d1fa9a204042d7b821b293bd659dca980c108ad1db740800b9bd2fc1a163f9b4066f7604f160a7910bd947cb48ce6c81e680fc6571ff0cd12a3ded9c8cd560970ca5cb480a70a8322d5072edcd257604eba8dcf55f9ec97ea2b14fdcc72fbf615131836fb14e42b8d7171d0a06d2fb3caec2e0759e86b0d8f21e312d9211ed7fe0b48669934ffb892baf1db9aa457c07820723e5446420334bf6479f2099e01ef8adf273adfdd9ed0b741931284515d69c211cc2efead8339e450b13be71b35c36c1f00c2b8ed0cfa9792e422912e14b5b1455ef6abdbbec0035480c6cb69d21321d12ee19d528dd48f43b142cf0502eae5304ce52b7fb827552db9ab885b93e83d56a33346135aef11b7e48efca7cd52e2499a7edab0bd0562862187ff4599b2446bff11c37181092fbb05d0e05220ca6bc37f529d6599e8c29acb9f25616c27df291d4fb07430188e6470df7002f73cfe5fe6907dab0b4f90bb58130fe90241c29c6063a22c9f45d032b282eb92c93736692bd5cbde2a17552e942b595b08e6ba0c91a03b9079e9117fbba8f26ce6c5d0500c69bb6e22e3562a50baece49109c2d42b6714250665afd0f0a7e951182012f21aef4b917cd434d9ca22661437608e32666497516be34652500def6c28ef8f56f2273de5416142ce9606faf7df92ab779ed6aa74cb99bb1bfe758ffd344e1d31f479807326d1a7b98f6811e275545d69198707b0fbf027dc6a5e4815d62ef191535569a452c27c4e25ecf139df949d70dd5935bddc04f33b2f0bcf5073c51fc51c15067963a20569b5659f0e7413b347d6d5ee38a92b7e6e656c199149f07ebafe5281db6b1b2ecd9e0384b6f5a8e27ecea9a0249c61b16564964054f5f9621471a98de132e102f518c1419829e2ae2c8c5fffd1270f0a0b33a383437b0034783d50bce8bd7420c059d16364eecbd55b6ac8df8a70382734d8127f4f5895cc9e508b13c000ea053ab59b87ee639745418ffc566ceebad37a17b842d24d3423ac3f086142c622eceaadc4106f8c90c5dae1f52f407fa0bf1e6bf9385cbcbf3b61006ea3b1e66b693ce704577ca9598587f41e05d36d1de424e0e51290a5f2e2f99f1960c0253a046a49b19eef249ca2dda2af1e8dd78411088eff1e9c23c31bd20abd4fc9e7eab19500827d202f76270fe9f90e95309516343e0fca48e5a12182e91c78ebf2cdd4644629afdc90bbccb77546cd765135910ba1cd8a3e3c00fa77e585865e898bfecd06c01a0a4d7be483801099c61941c4967154af5620b171b426cf229df59d2944ba50754140c3f305c16956953be376fe6e7cf31a2e9c276bb09cc24c4b86b2b26f039b0d8511853adcb7feb8502e7641a34e3242bf2c538006bb1983345ec3cacbf219ef10efc1681d52e6e1b1c60bb556b6b8a63d1d1f6869077841d1b816f3165a35833e33d39a8c6e62a2f7c482c395768fc6a0e3cbfc7a1a6d64da53adad66c8016f76eaa73df1b8ef83012ecbe75c92a8e39b48169433f951a539b28a034d5fdd00639a5e3e17ef14dafe869064d130c90c68be4d5ceddabed1bc94e97e2cdf7313f780cd6e175a9e3eba3eaed896fe464073fcf07ae7b5bd41d58c3160f66ac95a76fdaa7a8cbaebb304fe3c8f03cef927a1182ac2281c3b32378813b24bb99e42cb0774331ad78b74d46b8ce48bbf4ef8431a82d4240edfd61b910c38570ba0bfbd4a41665117e6d5f5a97908462e62d0b76160d06aa56cc6e17aaf4607ba8263648f2a0077e306c25486f5f39a75",
+ },
+ {
+ "2f6210063cb3071b3d49339185c2cef8357b08ca826d8d1acd852540c16540f1c850f70404fe1f414853d3cd15a1c64a1cce149e3ca1b80926de4ae8438ad90bdad010decf2f201782f3e49794aae1b079f54eb59607bebde508a528927e346d4e444b1d736b34f65e198df2c36fa23c64f1f1fbf8b0b8ddb85d054bdb39b8297d0347f16f7be7cd9474c058e36294485386434b36fb28ee582e393367f15ce5f5a3d6641fbd31b331f10b1554a05da726a0f35c9b1b4af3498426b17582966a266cce452900f85af1046f45a4ccedca6ce02607fb70fa45f420f66aa38cd4c9f8a30e21a3067b940aebdaaeb7c77824a79e2ba20f26e70346dd6de96942b261e5c08288c7fe1cd1e9f680a0bdf8c46497f007a616eea95ccc17463559f8973eb919c68017e25100d9d1a196ca65fb615502076bf0b0c8bcc70ef22006895ebfa2243fba0791bae0625b762cc1718d1673948264454a200c58122d5e9b8b1e3eb05df8b7eeb297510e0d7dcf7f0be5f29f6756e4b177f109891e6825a9866359e35b10d20da7231bb5a0ea34abd0264b377d2fe9f420f27d3e5aa2e8e00541c46052966ef9b989ae5974e2054409507b867f647aa057f7deb19ac6929f0856005aec6e53a5f702fe6be403afed532b73d38fed73e6e551987f182a1e20801e7a6c8ccd1184cf0fefb4139fa166ca15395902ac40e7fed8661602853682a3b0ee307dffb44d0ea3012142a2880cb7c166ba6ea6a16c7e0882808db8023068f060e5ef1432fdb8331ffad6a7078d686d47d613e94291f1c4117e7c13aee4030fcaf223fcefdb300ed606b5dd931e4adbf45dc437eeb5fbff337812e15c15f026071423f6ef5305c559baa2ecd8ecc7cd498b043740ff3673774855d45d45fa64591d5b4970600ec91ab1b6f39d7dc0e709c41e49c355bd3b9d120ffb57095fb127bafa971a086135b917285794e83e9dac5ce76fb1a4aa4fb6b94a0dc3a9beea64b8817ec1e2b37af9dbd18ec30f2b6f6c12df1db6896c6c43b67a066038f0c4f17142b254f62c4dd1fedb950d07047919e397d06d033cb0bab6b61aefa6dee01720926b16beb9e8bc947dca9b8143b565da85d2dec182987838b267de9047f5b0d961c7971aaf54ae2c1e4aad61ff123c84e41a4566b2bd9e64247cf46b72a444d36bdced1a309b464ee5f4afe406eb68eb05ae51b76bf01b906c0ffbdeb440b11f1c9e3a4c3a809a1f7449047b356c663a1ab7f286a70d16141d11f2d151a4f06d422ab97cab539c1f9da09ad20c000c27b8fead5f0cc37329d466fa260aea934c154dc9c0a065df3d057a0f117a1c38321ae59226a8054f7d6b49a3753436c249838b0924f0e861f5627106dd8d3f0fa724a1cecda71d4a1267ed889b234ae4a7d5edcbc5d52cba389dc0152aff24d224c6a0f16dbd3b7f242807bf4b51a3f22690bdeb66eaa59e8766b3b265d784899d247a0ae1b58a06dd91c529e3691b09f9d9f55fc39afd4a00b0fc668880ef25a46a30861fba8cfd4b51262eba4138b41a2d13ddc71128c8c1242e49a51d6f49879fcfa7595ba4a4adcad3670b0b1b26382f03ff402bc70150f54bf513ba3e9a590e41b269e55616af297ebb3499e16cc8e46c0810330a602955553c0f93d668a1181a0bfd7021ad9a9f68ce39493b012da70a3dda149d0369f23f788616e0272efa322b6a54d804f340d32c890e2eb7b538f48f4c9293b584d22d0ae80d321607644271b81a76ac5b49d8e457069b0c3e909b8a222e3fa6016cb1e979e300804742f2005c68acb7b1849c088b3714c9c7af54e9de9390df0041c87924c8fa6b0aec6b6754171e059cba0d27f221f0b9d044a3aed8338dd8745651981e4b0329376f908b86ae9022699d495bbe3a148f7eb73d56eacb2e5e2180f63fcbfa680369f88eefa71f1210bc5b6b7b957f0a1437476a2112998033197673e470dbe7d9d476c97b95db8b5136f6cccc75d6e0ac1e4ace30e34e64fcc4d7e135b2c80e863ed701d3b28c25e982f1b5f8c895a4e6df7216c3c07abf8551a0ba0469c88aa7a08c7b5218a03b9b91f0935985373f65aa56286ad0e7ef2288a926f172b098123c136455b3a0f04590839e16bade7b6434a3cf048abe2612684c03dafd9cec39af508e63f07ea881014697bc24122058b5ef5d3fae835216d055f0cdf1dc06a12c95041d13ac9e15f235d11747f16ffce1cc3b8f508da520e395edd471f3759d8879ba9c2558b1188d822fd4739ed0546b0ce3bb9988db7c1dc8518ebbc62c4440e6e0653f917dcc13aca1864b71dbb67dbe7117474c936414e4f3cfab1f13eb05f3504484ce11977ab21ec523f97ba1b7ecb8fe384b634c30561cdb752fc67a2316bfa7e4d03f5f825d24a556a0460d8cfe0cc54a6f117ac52d553a5d1bb48031732716436675c5c3996b1939b127c6b0338bfaa29c7467cac9a127e455a715c9ce2b0c35a0d2f83a3d1273ee39399e6cc4980e610c752bd51652b96bf9cf34c7fa41fc9b13f5d55007483e4082ddac4675baa7822fd257452411b01de0e5e5da26e17539d64a89dd93c71d15a4c95b1a83039cb2d5f3f7fa04a817e48dfcbfb3de34ecb47f7592123caf27e17982fbfc8597af5b8aa6558f4e6c73db69328e47677afbe6ef8df82c3d1f0db6a108b2279f61822908d7b856432c32ac5ec0f3c53befab2a7ca356b9c2636f646b228b0a830d348be4ece2271814d477d4c73c0fb6e83a338b90ec4ef45cb25f7e3d6a014a9e8d2e8a6f55a383291a57f15667a73ea1daca31c7182523ca85a107efa2518d2f7f179ed4ba21fed479ef2be09669817133b2384bd85b155dfc1c4c9e6dd9ceecf06cc1ab8ebf7f07aeaae7441468b5471aed93f248a84f44c59be33274b11f651de010ab9f8fb24d3a99914e0147951c34280e7dd15ec196f9a4c86e55e7d373c7e31e6672d1b3ac6a45fa6c8c9088c0b8963d89f4ff1feea3e85cf9cf2f6c97128afd845bb131c6f62b3282bbba42745080fd457f1d3322058f1bd4be876bd01269546d1a853310b165926c1fd4e07054deb5d3fbe8f6007711d435994005aba95918c3df4cd390b165fcd139dd418ebbf661b6de57b655698a8a02ca8fad73e8c536c7110957c36e5494a831d536eccb97a2a9ef58fe58e2885aad170720ffcc57c7de601ea1cf723577a30aad8fd544317e33897c8b6c04e5191bec391ab990e197f10038c0726d371677e4a54c28d7ca5c6046e7cc4acde565b91f7f72af6109a0614160d3ae97e9257b8f71a4663b00c681e793cbb478306e97b0e04711eae7722b4845dadf2fff5bbe71ff24acffea2ee67df99bf62a098ddae9d4ebd3bc5dff04a2d9e3d1d83e8f493db3f63c9e24231b1dbe1147c79f21b0730c842f6983330c5c17dd34556d7e932074cfbe98f2dab5b0ebfd778a1e28fe2bac2d942f61a08b787ebfcdeb3d600bb130ca4922a4ffd38ffc4a1a1a7218451e45da4da67ad81ef898ece3d54cef877cb9d09f5dcf72eccbbc06e62f1e2b4d64059b0a807329780b155ce1614b68de04387d6108ef4dd3ab54b9da72e528d6eac3e16a360ae3421f3f23808a8b5e8ec3dbefcbca3c9f76905850033d78d9283bba9272c475b4e3b4d7643e62c2cc259ebbf168f890de88e82f8b26a7654ee31fe055e45609c70ae02b4942ee15678cd158f4c9e8d351d102ddf7a942458c6125e1457bea0d86ca38cf0c26e474b2b5cca77eb57ad0867cad7d25efc2b250e79396637ea3e948dbb855029cc9b452955bd04ad5a0d0514d4d773c0f298df7bc235a3ac64383a1fbd8a397a158e936b3ba81895a51daa89f51e4ae7a71a53794ff715a42f4fc3dcc9fd56df7bea4ab782534d3760e7b15605fc4dad16911656983c0ab77bce9445bbeb1537c55fef57a32c8f1404306a0a2ca7b73348cd99d0f9948875531cbb0ef7c036cd201614c33293d746c44140e0e8f82421c5bdf2bf428b249597df949fafdb5ccfe1618323f56a6ab9abab9a84a3beb6696ca918af244d34cc1cd95bbca4a87c860a0fa9ff6a04a905b0338a53f230bd5ee9c60e0e0332ca200c15dca0be5936b858d0a7b2e540b8958432e9767396c55d5cc35b60062580023b5cb2f9a5e9a1feba59a19f9a5a251e9d0e8500955a5df21da95213ced2260a2ed8f3d4b295c36cef750c89cf21985c302d5cc577aab7855409a912dbcf1d0a9800df4aa692a78607a40fd6d5a82305c58fcb3d2a82b27e8c5b91681aae62a2bf31ed55c494dbdc38eba30e83c6044945df76705228eede8470369f2e9941ddcb2f239fb3ff6bfcdb0efb5ec50f981adf0e8b213769ffbbea364b08cf8cd69abbfa2a6fe9865cc48558134a57bb5526b9d047e14a379d246de82d3d64f3c810ede280c768dd8bee25af287d5a8d94045ddbf5981382bc716ad9aedfcd66e0ab496172a24efe80649db8e1e83675fc8451e22c6564d8d6dfb285af7fec802b35f19dd8308c68952a11770247fcfecc4ed0e8a445c17b1573f0b4e3ed350f13269ceb572943fc435563459d5044699f1542335b03be6077af156b8c5a6a9f71078ad820cec4642427a9b187ee1b17036d5a5e6108cee8a7d444342eaec3afa64e77c71d3c2b3153d4e2dbb30df2b66b4d14cc45d3a4eda7e911d697e5763e23ee05311a20626df55549b8533c6ebe79737abf472f9cff08bec590943bdeb819d3f923f45b81f9a0cba1f3f800a261842d10cb4cbdba456c7fe5f0abb4a8b58891d97cfd6b669e2708922f1934809d51a1589e5f12e3bb82c9ac3e7e44e3f6e6cd63d428da624fd2f46eec38ff798a90d228efe50c9b67c63796347c8a2b53478f27605999a03c8e1f18b70e92419f646a7f49670aa12d324751aec17d0208fc296955b3098241189af8172d39a6819415cafb107c1842b369f174d6f37dd31cd728dfd0ab10f93609006342b6e4d6ccbfd1ed2bea2fdf5411442b04b1fe218916f159b20242f80b535b4e0a3024c6eff6a40bd0d3db24e51f5ff9c14e1b4a650ca4170ee70f0a3a5a58349a7d0b7a63af86347351696870b95231f76d8c5c6a20736907726341dcbb76672871d18c2157c094b929fd29d34f5bcaacd82706f89a60000cd341d98eb830b73a12335b69f3e0131ded3ce12c98bbd960d2d0696d40696a13ab43925374498d868cd8f070c9039ea6407fc2d92b9c39fe7c935bbcfcc5c0980952fb7dac79042951f49a1af828b138a87401c4104bc28cdf1e39dbd3fa63dd4d5f5ae9d85f032a43ad353bc5e6746e5a76326ab1f4e79103116ce70bc0b459200f32f85e461291e347dda92e421778b849e37a3ecb0b31ec6818e828dd3148dc74313aba43cc9d8b9a36a9dc4e229488060eb6c109f8ad6201958adec6d3bb3b04e5e558a272d44cb98e18f7a0ad8fa6ac3667a62f150830aa930f6166baac6b9081b44304988fbe1698a5b746255de26bb5988aca90bb6523cad68a7572f615f4aa58f932d8a749615cf0a7724e99de042268ceb31433e6df0a61547d576a6201b36b348c028ded5f7e94d1cd2eafc141088ff42cb3dafbbe4c402b93aa9d955df8d9d9fb57c75ac65c2c837acc44bbd4d4aff1888aed46c73d625ad7fff035e8ca0fe411c73ed8135b6b8e17a039ec74e9de0d64cb442bf8a676c0a666f68f21066332cd921ae0ed766f0516a8e19b82cf98e78add0373737a3419e13aa902310c44feae5fdf8bc64e80dce772686a31f141bcce452041bf545b908ef4a2b000e7beaf378e2afdccbbcaa42e330e5024400cf2852d3444718",
+ "fd5008477b0855f6f2486fd4f74b9fb4f6e19726c6996bc66893183bd76054d5b05c1c2b64722256ba912ab2dcca66d2abfdf972966438fff7513acfb18ea461eac08c4e32aea4ed3fcf9f1c9905ee4402e7b6984bef974340d212f160b6524b76de99a98d3e96cc0d35e8a63ad7ea3cbea1d40a906c4dd03e5fc19e1513e9",
+ "390a5e75c9ff4ad38fb6205ff47f209294337c1f25ff54a3c01eee8e1e220257",
+ "8bf183347ec1ca4bceff3374",
+ "19fa2641519e21293094e9d767ee1237f9e0715dc57172794867c3bbe2cb647f9b28a8d3f85c0ff557b91bad66f5ea16e0107757b0277fdd3ca05bf47c19bcb92a958a57e8c142a51af29bddb20af84377b6db65f77494e0dc4d2634a776b3a5d777319873bc0dacbbd4b9ebccfae849fa7e9769cdf54660ecca0d5cf4fa5190713726d54d02b3a3f21857125b8a808c0ca2f99d11dc430ed5113ee49ff8f00bcc08f0370dd510e8100e1285659a7b2c7457a6049f2af7786c4db1471ce5bd164e11c7a2165e83e03a135ae2b3429f82f677de044a067e99e0bda2d65a7270d629c00e1d528212d3aeb2896e58ee5145a93ed06a9c00705ad5c5988d3a192304c1d17661d45257c5d16799ef70771964435b12e3b2ee9d5b467c3b1992f45b7a59871b40d8daa1c280747ecb3d170257b91df1f549ce6d66455b5b6f60b7c6e95c92a67e20cffe8599ceb183de53f1dedfe19bae836447af8e053ba419660e0912cad064d6125b9e978e8d0d5f28f8a4e43ca3cdf2d4c0e9a11221d8184e9eb6c90761b0beac82d0d22793279aedb1c7db3632adbee323bc3bbde4801152694831abf5676979af26af7dcbadfba1cad1306b635840cbca76c558b37db0803b4c12befa27d16f21506b07ade4a838d6beba1816eb29ed5e3c4f132a752fc747bd9ba879156e87e6c1584e911da9f796e1fa4a055e427272559e4bd6d0f54b8257100f8a55d84c27b702bb1fe2f995425c85fd48b0a0610db5b39f7a5031407a12dae9f508b21b1378f14952d1beb2dea81d016b2d9b7f1a67b814569b69c0e619adea02a8683242d63a11d3317d060e5b4d85df5ad73127541ba5314715d187990735aa81f438f8b94070ec506ba536274d98b766c1694e54367891a602b99e370425b47a70b819277a249fa429c5bbd0530267f987e6022f25030c30f3baeedc0d13c95f3d5e4b2b87465d179a3a23b9f9e76a42ceea55226ce072f9488392f40621289124d786109d2498e74fb37e2ef466fe8bf3016d96e34204c32978775765aa80461cac48518157f86d59f6187bad4ee62fba1ddbe166b29452f4a59af1e057300c353440644a8e40ae8171ea028be2fa315804abf518847c7945e8228b7766cfdb08d3a3116b59aab8e94b6d8c8c9ef442c2dc7f923bc2cd3e5c663baca7dded976bf191fe36da16948c89c385fe71434f4aa5dd15fe0e925d2459e3b068b9d82a9cc8b8f9786bd9f5fef9baaaf2d67027d9bfd58bb2c58ec7c746b747ab62f9242e4b53ed14d6fc75f5280eca0de23717c97a2293826e19cc8eb47f946421516c349dc4ba49225b91e4e868874bdebd373700df1f3792aaa140597e58b88f90e163397dbad3941705b53d754e3e0c9003df836a7fb8d23f40362fcb5f3947a4281b24240be4ee89aa8e917b194f94345eeca224df0adc15f22a617b6427f29410bc48ea3f92216163785723efc36301d23ed52780c6fd7924bcfaa03269b13582b7c7ea9c0e4a451f38a469fbdb585dcb7c81452da77945ebe27eb26ff6e8c7b2decea289aac5af74746dc257c9bea44a0847f02c4f586e1d76f39d5bf952355a0875f177a666d1d354ad86ce5ec0aba2c2b20cab050eaffd31095395132f5af80a2d2d53b77bda49f948bbb37bdf31c8a690476488e14e542ff6841e7fbfc2eb84795696562d079dc1612274b6dff362567084f793f0bc2dd8de23392d05aeeeeac6991c9f74387153a4b7da94790375e336a00c8293bad0fcef2dd1880e7094e2e53f738247c860780ebe308410ca02ae409ae720e841f48c9677acc6e7d4ccd18c219c400f8b7e1257f692e09eaef96802b17a1cb7d93eb81d3bfcbc7af4cdf05b98e22556b3d1a8b56d6d83bb5f5724696f8f329839dbe477483ec3c09fa2e0628faeba1bf285c224bea3f6cdc7bbd768133c6ef1da14f248cc3b819b196588811b073a7291817bd1e89c65760435d8d17cbf9423744a92143e0f956e2977b39c54fdead5a57f3a04a0facca01bbf44d3b1fb9c4fa83ae1046985e3f26aa0a437999004dd8adc04c5111759849f919b93558dbc559173a23b069b59f800096d9fcf077c7640f59170bb9a6fffe64778bac272365d27ea62aa956559e90edd3f6393cc8775597bcf7d91990ab9511973d948324a27261059e93f4b5dd2f70caf12e1a08e0493cb05588618764391f355379578cf94dd33e616136eea997ec11c0d4ff064ff51a767e5558433a2e3a9a74c232d8e187f47b8cca010709eb9fea0dac8f1ea53bf18822e154ecd929c83b0eac366e30fffbd5ba6a46d734f58d26e7f5df538e18b3d827884aa857a680823131bcf30a76f1a555bcabb17b02b53aefad96fe76f7312da69719434c580d3ff1bcdcd594e6375935003d5d732cc577e11ea2abb1d04259f50aed4c3af9866e8c4a52a09809046ee330f05c4403acbc297a9416c5208fadb31ed4eb7a3b01b87bf08c75cf44c2b0df84df30872d021d6567ea649859268e5e1b5b6405e1b41e350a32c1af13722959c17c01b52c42241313b26b25995a1c89a53e248488724d280647226195746901929501df36d1e94815d7fe6c4ca2731f3181293217f71b9d7f59c2474856972013924ae4796db4cbd22d8905a6043c959941ca6b556c53d1688c439036c715d33a47a7dfc2fe40e53424c5093020d2e85e4b04aa4c704ea5bfe5a2384878da38319c59d41d66b6add2a443d9ea11edd8d18fa41004251653857733b388b453943eb33df93dcd5d549757fa2967ef0f9a5105836c48826c47fcccb2d9bc349032b286962136b848632bdcf186a08cbeaa52d195efcfc3a440bac154971d11ff4994f293b14fb8c3214ebe7ab8b3d0f2fe0b03ed7b145fafd7730a173e3cc1847f0cdf2cf629f5ea81a07bef716b1a67dd9e3b7a52fea1aaa7a393f53b5bdb5988df78a57a9dad19a8253316835acab8a6b9a9fb42d97bf29b2443322f46de386fd82bd3453ed68e2370c6eac4497b1bde7b42d569c452f377bd38bd50fa5a6792ef5c9ec6c647001149b86fedb3e2f18d4271e9cc4801aa16ecddb31b6a795fecabc613bfbc8e4f5636d71e74595c841fd11b6a6bc7f169317c1added56b82a71fc36d774bb4d661685363e9da5fd2e1f357006dc5b5bbf8b42ee3f869e75a541586fba558a8f490d641b78c27368b9b4c2db046354e9358ae9140e91cd95ebeffc6c0d2676a3ff4ab10d463bf32bed97023a80a79df191ab9858c43537a03072a17c30b1bd99efbd361590ed6b7d5b0ec4e2326fa35904ab9a48596f44491cbbc0112890f9386ed04dec30126be359a05e99b2b77fa2c8f6b7460a6cd590d71c73b2a1b23312ff89306b6e41c76ddc0a099bfa79498e36ae5cf0c560b8854dff32d2b690ce0ac4aabfa723ac6f2e97ad1083235196b464ad67fdd649aec01695d55c8b4bb198f30630ca635aa5a1915f3718341bcfd8b522f764015fa5479004d28eceea7fe67df7ee24a97a9708d528b89589f1899f13242a0d00f7464c3cdfce213699340e754533b934f4a8410224e111f31cf8e54d7b5e90cd8c68bf96edbc8d183894deefdf4fcc1a83162a3f6341dcd9a9aecf171c0df28257a68b1af1b67c54c43c3cff27fed89cc64bc46e23a49ec74a9efbab7981d9f0a018247441e4f0f5b5f68ba9325582f92de4cca4a5f878a0c5c387581e64324e3246d8f3205c838a29f1abeea24446e496421f0e742d411adb55f70272ae4a992e825a3d327e44b8b3762b25aa451d07eb4eac0322b431fa676462632daba2aba7bdeee1b438f051d21d4b1897e2ac2f95ee7c23f9996a805de8fffb3b30b855cd6c5b84c011accf4bf94d304d944079f04b5cadf8fcd6751c22a0f9165ab98998b2d89e6514641f1f3b91b8c0bf057d69c3d893fc4e041e06a2229e2ee58082ffb58cb920972ede58483287d0ace94c1becef26a410b93e4ff402e61dcc574b790d49679f18f4e2004f8b7cc357faba34a80e56821bb5b883d1a8b49c6605002152f270bbc36bc79095644e29ab08cc988deda765d67e4fff12b726d5de135ff9d0cbd9d5f9d440e548836633b93a38330d638468b59a32642da3375cdf70b062d14b46a78569c24a706e179baa2058dcae5c61fb6cadd9e015b017f26e9dbe3e6366cf5f1ec839aa3bbb21dd6c9b8e910245fa95b09b7d6cbf08a4c6c84bef257a70389be962dad14d97a893c128b73bf6580689e540d004f21edf8403f36b1ad7c9a2e83ffceb141af59700c316c8c1e3347187f24819c2ff0c9f9a2360dce354f3374374eab1643d2d8831310a8e3ca6768200ea7759822b82f7027cd450479fcc7f6d04802b15735a137ad489f1e1ee78434a253a9dd16684ad58fc91960cde6754f82e8b38edd5e798fdbbbf8fc2e2380a4e21dd94f8c1c063b18f29d8cd8d89f65deac5640799d4ca2caa29c1e72ad8bc417490d11e4051d94956fbc74289857e5f8e9e87b9a2d83074a994de0b10bc7782f6650cfbdb8c835c81cd88bdce5f04ca939b3c5cd010d4dc5d51224fcacbca9851694b8bf55b22dead859d023eee5a7ad3436a912c3fc0284456d5d72ea5f1afa8545c856676ac2dd9a057028bd3ca0f50e7070fa74152f13997c95c1834c3e67504f1a4165d2b49a96919b88f72caed60f56ca7ab5a3204fb12ad3592c725fdebb048732fc189c7dfed185c6c184a626e07d7356860d00389862d5b9701eaa4e5f7889e6db0f54633369b8d26805c08471de8fc3f8fa1fb0b0711d9e015add5373f7f8b64abaddbac3399c756244b1b07c579d33e4967e5e0cf16de29cb8a7efad07ff9039ca305772a6e45c76bd9b77e24949556766a8b8425c5e595efb431bde4ee222f9eb3fc2d002a1e2d14db2b23135266c942eea33bffd30eb0218405373240e0cd3040436ca895093bf056fd001c00ba59d90502042e6e6c0167105051628895c8164c9ab959400898309cabafdef12be53604fa57df44e0a90a81bd63c331291a93bffefe809e80db0679568f6e94e0d8e2edec0087c35bcb3c4f4725e6013bcf197156cd9d90612423348123383e45c14d27d8833f56ddb04083c069fd6e282fe69c940840f5f747dfb72ad72fd8cf9f3ded15c9e2f4727fd60b4f40e95dbe77a89b47dde7d5326942600554905d9dade9d145ab6da802643f2081678392609c2fdd1b79dd8caec137cbed315374c6f05c0758070f3bb17e23d81ccc39c6aa89913897e487fde889c5aacd422278f8571641cc4f0a93d9768aef9e45d6bd187d1ba637ce0fbd3c573d6778cf7bf5188c00dcdf13be3fd599143952b376220283e34e014e83b214bd5f64eb0ecb098ae8bef883949907cc36e22ece60b893b963cfa73d120513e285aaf70ce5add34edbdac60b3aa7b385b90e339058fb9b3cf984b06f79788016035c5ce490f2de7995b98a8c1c9c80f29603ae2b7fc41886663163e604275cb085f8453b27f4d795b9bad19ade2f98a1c99b43a7581bd991e5d0e5e1a6e713acc522ba9fe8302658a9782558e35436e714ac6bc85ad1d3cd008f24106901fa954f5fefb61210d6f8dc9ff35c480f1d14e59c0e501917a31ee9d00c6bdb06a00af5a8b08c3928cc5f37476248223627cb77eaf0e96213cb0a13e97d3fe9b9814d462690e8d68d02655a32fc271ee73db4f88a33386ea88a5857e15a28d9b3e3a96f00c7cd85aa53f9282ab8c8ca6d6a8afed43aa87fe7fc1ad59b0f0db2dd25c20af96e8c282c19fc883ef01a4060398926a1c82f07bcd3bc314580d7636b623b7bad8ddba05850291a6344df0f346fa4a321a85ee3e9c",
+ },
+ {
+ "67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339fc99a66320db73158a35a255d051758e95ed4abb2cdc69bb454110e827441213ddc8770e93ea141e1fc673e017e97eadc6b968f385c2aecb03bfb32af3c54ec18db5c021afe43fbfaaa3afb29d1e6053c7c9475d8be6189f95cbba8990f95b1ebf1b305eff700e9a13ae5ca0bcbd0484764bd1f231ea81c7b64c514735ac55e4b79633b706424119e09dcaad4acf21b10af3b33cde3504847155cbb6f2219ba9b7df50be11a1c7f23f829f8a41b13b5ca4ee8983238e0794d3d34bc5f4e77facb6c05ac86212baa1a55a2be70b5733b045cd33694b3afe2f0e49e4f321549fd824ea90870d4b28a2954489a0abcd50e18a844ac5bf38e4cd72d9b",
+ "0942e506c433afcda3847f2dad",
+ "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e",
+ "129039b5572e8a7a8131f76a",
+ "588e1356fb8fa32410dad99cf7922aae47b4042502c92f3afe33dc22c1c2e90caf22bc37a254f8dd62a09582c70194f9616982639415178e9fe95740c0f1d497a69b69d4924a7a15290187f9c8acf09cf5b3b3188ecde2d2807207f5bb6a6d3504314b1b47684cf8ba8807eb9a3c497c79ebe1e4c1eca2aa90328563e201425227fca8ee05dcc05fd6c98128626c1e71d2fb3a21860567093db1012dfabe13055c48219d2a301c8a5a49033a811d8d9413bafbb2eefc177226fe578e93c2ef1f309416dc98843bfac387debb1b610b1d2366178ce7212a7312057a3d058357a629f18c78e129e60979a2310455a76207be5611e8b4b840629564020c17f5c9446882e23f610e931246ec434e62de765bf22954cfae02b2ff4b4086fbbd1b6cec23e45481eac5a25d",
+ },
+ {
+ "67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339fc99a66320db73158a35a255d051758e95ed4abb2cdc69bb454110e827441213ddc8770e93ea141e1fc673e017e97eadc6b968f385c2aecb03bfb32af3c54ec18db5c021afe43fbfaaa3afb29d1e6053c7c9475d8be6189f95cbba8990f95b1ebf1b305eff700e9a13ae5ca0bcbd0484764bd1f231ea81c7b64c514735ac55e4b79633b706424119e09dcaad4acf21b10af3b33cde3504847155cbb6f2219ba9b7df50be11a1c7f23f829f8a41b13b5ca4ee8983238e0794d3d34bc5f4e77facb6c05ac86212baa1a55a2be70b5733b045cd33694b3afe2f0e49e4f321549fd824ea90870d4b28a2954489a0abcd50e18a844ac5bf38e4cd72d9b0942e506c433afcda3847f2dadd47647de321cec4ac430f62023856cfbb20704f4ec0bb920ba86c33e05f1ecd96733b79950a3e314",
+ "d3d934f75ea0f210a8f6059401",
+ "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e",
+ "129039b5572e8a7a8131f76a",
+ "588e1356fb8fa32410dad99cf7922aae47b4042502c92f3afe33dc22c1c2e90caf22bc37a254f8dd62a09582c70194f9616982639415178e9fe95740c0f1d497a69b69d4924a7a15290187f9c8acf09cf5b3b3188ecde2d2807207f5bb6a6d3504314b1b47684cf8ba8807eb9a3c497c79ebe1e4c1eca2aa90328563e201425227fca8ee05dcc05fd6c98128626c1e71d2fb3a21860567093db1012dfabe13055c48219d2a301c8a5a49033a811d8d9413bafbb2eefc177226fe578e93c2ef1f309416dc98843bfac387debb1b610b1d2366178ce7212a7312057a3d058357a629f18c78e129e60979a2310455a76207be5611e8b4b840629564020c17f5c9446882e23f610e931246ec434e62de765bf22954cfae02b2ff7c59dfe246e4bb2d6a8afcebdc2beeaabf2a3f43f95a5ea639853f38719875ecdd2bbc0d81bb2a5ed59553b1e76b6365b74f618f685eb7731024bbf6794c3f4c7c5a1cf925",
+ },
+ {
+ "67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339fc99a66320db73158a35a255d051758e95ed4abb2cdc69bb454110e827441213ddc8770e93ea141e1fc673e017e97eadc6b968f385c2aecb03bfb32af3c54ec18db5c021afe43fbfaaa3afb29d1e6053c7c9475d8be6189f95cbba8990f95b1ebf1b305eff700e9a13ae5ca0bcbd0484764bd1f231ea81c7b64c514735ac55e4b79633b706424119e09dcaad4acf21b10af3b33cde3504847155cbb6f2219ba9b7df50be11a1c7f23f829f8a41b13b5ca4ee8983238e0794d3d34bc5f4e77facb6c05ac86212baa1a55a2be70b5733b045cd33694b3afe2f0e49e4f321549fd824ea90870d4b28a2954489a0abcd50e18a844ac5bf38e4cd72d9b0942e506c433afcda3847f2dadd47647de321cec4ac430f62023856cfbb20704f4ec0bb920ba86c33e05f1ecd96733b79950a3e314",
+ "d3d934f75ea0f210a8f6059401beb4bc4478fa4969e623d01ada696a7e4c7e5125b34884533a94fb319990325744ee9bbce9e525cf08f5e9e25e5360aad2b2d085fa54d835e8d466826498d9a8877565705a8a3f62802944de7ca5894e5759d351adac869580ec17e485f18c0c66f17cc07cbb",
+ "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e",
+ "129039b5572e8a7a8131f76a",
+ "588e1356fb8fa32410dad99cf7922aae47b4042502c92f3afe33dc22c1c2e90caf22bc37a254f8dd62a09582c70194f9616982639415178e9fe95740c0f1d497a69b69d4924a7a15290187f9c8acf09cf5b3b3188ecde2d2807207f5bb6a6d3504314b1b47684cf8ba8807eb9a3c497c79ebe1e4c1eca2aa90328563e201425227fca8ee05dcc05fd6c98128626c1e71d2fb3a21860567093db1012dfabe13055c48219d2a301c8a5a49033a811d8d9413bafbb2eefc177226fe578e93c2ef1f309416dc98843bfac387debb1b610b1d2366178ce7212a7312057a3d058357a629f18c78e129e60979a2310455a76207be5611e8b4b840629564020c17f5c9446882e23f610e931246ec434e62de765bf22954cfae02b2ff7c59dfe246e4bb2d6a8afcebdc2beeaabf2a3f43f95a5ea639853f38719875ecdd2bbc0d81bb2a5ed59553b1e76b6365b74f618f68a12d0f1cc99e132db9014100d9668c91",
+ },
+ {
+ "67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339fc99a66320db73158a35a255d051758e95ed4abb2cdc69bb454110e827441213ddc8770e93ea141e1fc673e017e97eadc6b968f385c2aecb03bfb32af3c54ec18db5c021afe43fbfaaa3afb29d1e6053c7c9475d8be6189f95cbba8990f95b1ebf1b305eff700e9a13ae5ca0bcbd0484764bd1f231ea81c7b64c514735ac55e4b79633b706424119e09dcaad4acf21b10af3b33cde3504847155cbb6f2219ba9b7df50be11a1c7f23f829f8a41b13b5ca4ee8983238e0794d3d34bc5f4e77facb6c05ac86212baa1a55a2be70b5733b045cd33694b3afe2f0e49e4f321549fd824ea90870d4b28a2954489a0abcd50e18a844ac5bf38e4cd72d9b0942e506c433afcda3847f2dadd47647de321cec4ac430f62023856cfbb20704f4ec0bb920ba86c33e05f1ecd96733b79950a3e314d3d934f75ea0f210a8f6059401beb4bc4478fa4969e623d01ada696a7e4c7e5125b34884533a94fb319990325744ee9b",
+ "bc",
+ "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e",
+ "129039b5572e8a7a8131f76a",
+ "588e1356fb8fa32410dad99cf7922aae47b4042502c92f3afe33dc22c1c2e90caf22bc37a254f8dd62a09582c70194f9616982639415178e9fe95740c0f1d497a69b69d4924a7a15290187f9c8acf09cf5b3b3188ecde2d2807207f5bb6a6d3504314b1b47684cf8ba8807eb9a3c497c79ebe1e4c1eca2aa90328563e201425227fca8ee05dcc05fd6c98128626c1e71d2fb3a21860567093db1012dfabe13055c48219d2a301c8a5a49033a811d8d9413bafbb2eefc177226fe578e93c2ef1f309416dc98843bfac387debb1b610b1d2366178ce7212a7312057a3d058357a629f18c78e129e60979a2310455a76207be5611e8b4b840629564020c17f5c9446882e23f610e931246ec434e62de765bf22954cfae02b2ff7c59dfe246e4bb2d6a8afcebdc2beeaabf2a3f43f95a5ea639853f38719875ecdd2bbc0d81bb2a5ed59553b1e76b6365b74f618f68d1f05b5662cd6e04de896d3ef5dae4149485a5a2093ff4ec74b20b5e5bf8e61b5c65515938c202beab3eea5a498d2f32d4d00a24b826b6efb16013ef54cbe170",
+ },
+ {
+ "67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339fc99a66320db73158a35a255d051758e95ed4abb2cdc69bb454110e827441213ddc8770e93ea141e1fc673e017e97eadc6b968f385c2aecb03bfb32af3c54ec18db5c021afe43fbfaaa3afb29d1e6053c7c9475d8be6189f95cbba8990f95b1ebf1b305eff700e9a13ae5ca0bcbd0484764bd1f231ea81c7b64c514735ac55e4b79633b706424119e09dcaad4acf21b10af3b33cde3504847155cbb6f2219ba9b7df50be11a1c7f23f829f8a41b13b5ca4ee8983238e0794d3d34bc5f4e77facb6c05ac86212baa1a55a2be70b5733b045cd33694b3afe2f0e49e4f321549fd824ea90870d4b28a2954489a0abcd50e18a844ac5bf38e4cd72d9b0942e506c433afcda3847f2dadd47647de321cec4ac430f62023856cfbb20704f4ec0bb920ba86c33e05f1ecd96733b79950a3e314d3d934f75ea0f210a8f6059401beb4bc4478fa4969e623d01ada696a7e4c7e5125b34884533a94fb319990325744ee9bbce9e525cf08f5e9e25e5360aad2b2d085fa54d835e8d466826498d9a8877565705a8a3f62802944de7ca5894e5759d351adac869580ec17e485f18c0c66f17cc0",
+ "7cbb22fce466da610b63af62bc83b4692f3affaf271693ac071fb86d11342d",
+ "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e",
+ "129039b5572e8a7a8131f76a",
+ "588e1356fb8fa32410dad99cf7922aae47b4042502c92f3afe33dc22c1c2e90caf22bc37a254f8dd62a09582c70194f9616982639415178e9fe95740c0f1d497a69b69d4924a7a15290187f9c8acf09cf5b3b3188ecde2d2807207f5bb6a6d3504314b1b47684cf8ba8807eb9a3c497c79ebe1e4c1eca2aa90328563e201425227fca8ee05dcc05fd6c98128626c1e71d2fb3a21860567093db1012dfabe13055c48219d2a301c8a5a49033a811d8d9413bafbb2eefc177226fe578e93c2ef1f309416dc98843bfac387debb1b610b1d2366178ce7212a7312057a3d058357a629f18c78e129e60979a2310455a76207be5611e8b4b840629564020c17f5c9446882e23f610e931246ec434e62de765bf22954cfae02b2ff7c59dfe246e4bb2d6a8afcebdc2beeaabf2a3f43f95a5ea639853f38719875ecdd2bbc0d81bb2a5ed59553b1e76b6365b74f618f68d1f05b5662cd6e04de896d3ef5dae4149485a5a2093ff4ec74b20b5e5bf8e61b5c65515938c202beab3eea5a498d2f32c38dbb37d04f8272e741da2802c54a9d9aaf8ecf38b36fc9ad0079523f6a4abd5281a22697a3180bc02662a7c13ee23599d18e5c48300dbb831509df4c172f53e524b3c15124a87ac73e5028cde6c94d8d",
+ },
+ {
+ "67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339fc99a66320db73158a35a255d051758e95ed4abb2cdc69bb454110e827441213ddc8770e93ea141e1fc673e017e97eadc6b968f385c2aecb03bfb32af3c54ec18db5c021afe43fbfaaa3afb29d1e6053c7c9475d8be6189f95cbba8990f95b1ebf1b305eff700e9a13ae5ca0bcbd0484764bd1f231ea81c7b64c514735ac55e4b79633b706424119e09dcaad4acf21b10af3b33cde3504847155cbb6f2219ba9b7df50be11a1c7f23f829f8a41b13b5ca4ee8983238e0794d3d34bc5f4e77facb6c05ac86212baa1a55a2be70b5733b045cd33694b3afe2f0e49e4f321549fd824ea90870d4b28a2954489a0abcd50e18a844ac5bf38e4cd72d9b0942e506c433afcda3847f2dadd47647de321cec4ac430f62023856cfbb20704f4ec0bb920ba86c33e05f1ecd96733b79950a3e314d3d934f75ea0f210a8f6059401beb4bc4478fa4969e623d01ada696a7e4c7e5125b34884533a94fb319990325744ee9bbce9e525",
+ "",
+ "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e",
+ "129039b5572e8a7a8131f76a",
+ "588e1356fb8fa32410dad99cf7922aae47b4042502c92f3afe33dc22c1c2e90caf22bc37a254f8dd62a09582c70194f9616982639415178e9fe95740c0f1d497a69b69d4924a7a15290187f9c8acf09cf5b3b3188ecde2d2807207f5bb6a6d3504314b1b47684cf8ba8807eb9a3c497c79ebe1e4c1eca2aa90328563e201425227fca8ee05dcc05fd6c98128626c1e71d2fb3a21860567093db1012dfabe13055c48219d2a301c8a5a49033a811d8d9413bafbb2eefc177226fe578e93c2ef1f309416dc98843bfac387debb1b610b1d2366178ce7212a7312057a3d058357a629f18c78e129e60979a2310455a76207be5611e8b4b840629564020c17f5c9446882e23f610e931246ec434e62de765bf22954cfae02b2ff7c59dfe246e4bb2d6a8afcebdc2beeaabf2a3f43f95a5ea639853f38719875ecdd2bbc0d81bb2a5ed59553b1e76b6365b74f618f68d1f05b5662cd6e04de896d3ef5dae4149485a5a2093ff4ec74b20b5e5bf8e61b5c65515938c202beab3eea5a498d2f32c38dbb370a9bbc3187cc260ddac991f94ce4f0d5",
+ },
+ {
+ "0fb826ddb2eb5e708de203d0438be12cf708d635ebdbae56278be09077009586b9bc646ba7c2db35a5de05e86ae71461efea96dac64430edcf117d461113cccacf303576f310ab98efb180599894ba877e50614494923163a3afa9b4c2757f91a6b40799c5b331b464b10dfc45c783c317e408ab76390e19e8b7ceaa2c4d3bd201436bc6f69c7a5a4d8756924ed95665bd5e1034971e4d80d51b2a",
+ "026866d46aa940309fdcabf92a324fbc",
+ "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e",
+ "129039b5572e8a7a8131f76a",
+ "30f05cf8189bb7b8b4f560e746e228c4cc7e86e8f2fa66e1afe212d1855db51070acd5eb34ce80b2e223957df50fde4c2531d97fc9e573725e7a5e47f0dfc4da1942620320bb2deaf8b17937bae4218d04db8e76f6efe84a117292159507c9f8a09fb2c17921d7762510dbf1dac7b62b1bd7572e3e2cf008d01c445c7fa78833235034281ae180e051451c6a64f22ca9708634bd0d604e4cfcd971b13742efa5b6363e662a875daccb2b00",
+ },
+ {
+ "c7d4f8790e4c47d4daecbddf5939973521ddbf3b832e564afc66f03b5583c41c58bd956609dc3ae3c8f7c2213059575236168dba44e3044049f47c9e7840bbd0fd5036062d70e9f567ac1797056ee93c8476f6c959fa09a3ee854166c6fc36c34d6cca7adcb36f435f86db65f4c4a1793b974294914b377fd179e697751c5ac289243c65d8aca93732849c27483da083d4e218652d4fe5fec8cb953ee7f00070143dd6ece97f241b03c0424bfee2cfd2c4e738f2361df0ffe8863dcf763d408a7a167763959b7f985bc1e359a4b22c6899645ad0814bcf69d10c38474978d1c48e482723e3a6bb3f689f980c51c474eb28cfbba91a8a12eb964b32dfc303a3524ccb752f71316ed9d007e521cb5a0cf429c79d4351b02ee7fb60c7be636a10af3586dfa7b74d80875466a820c0b514e97cb12cce615ab55cba7c1b1de72bcd1cb1acc368f944ef4eaa986e6a4d8253c9337f9795d94df193c90cb0b0387dcde929905223d441717ed9dfe826613bf094ba872993d41b269e27d74e5f541b497eac9ba180dc12ffb6f1e7dc5223cce6dd541071282b97c6526e15b2c330fb41dc96e25d72f45c28e543053766d11d44252db54e584c14abbb295d7e5a58bf36eea1936095ef897a338eb1995fcedd85fc92d354dfe7ff9a115c186bb4d7a1a27835030d248c87571a38f17906cefe0261d15740b9",
+ "56",
+ "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e",
+ "129039b5572e8a7a8131f76a",
+ "f89c825ca43cae1ce3fbdee85c505edd1aabefe69a0f9efd740f027aa7dee48a91ad24e69ad061648f0a52b4afb19d7ffccdc21f4b4247dfd89f5f9f998cb3c02b226173fedb6f8770aceef9271e7236fefd19fb3b87d08a5c587ac7918e80aa4b477f22602189811e270d686bc4949137a41d11d95ec96ee9d26c6126f6e923ab37638b34d1538d2e46d6df6216da4f193a3cecb731e632e109ced643056a1673059355d2d1314df35ded8364efed7de490201090a6f2d1751748585f64d26041637ba3723cbc4b60e226f10a19699d223075bc1f27d82e7f560c0db630ea670b3f8a70a8950894af4d1c7b3f674a3fa00d19ee4cc2b6174c1d259a297424bf2c3943a29a16a9830ce11abaa79cd2eb77b53a02b365b1838e7bfd5ae1bd044ffc885c61c6b2186a357e8b8f732b7ab96517969aeb70c7b493bbaca9462a61815a3c6135c748bf9c8487ac0631807aa69243fa09cd3b8efb63f8d4e090ad30b6c2f08bf4e82f191cedfa5cbe2b42268d67ecd105918181e44fc9879efd642d20be84e6f74717e03fb94fcbaa6ed3b307431d2a9384b8a2b3e5825ffce8d99af48f177e43bb4272226d8a5edd37d53807f768feb9e0733b437a1d0f84779ab68a1804e92a5eecca56364f0fa6dca152203b249fdc8fbd950fdc37c1887596308a90ba3a5751c7096bfbd1cb177bb17847b33c4379b43938a67674459cd9a06e3017ccac5b",
+ },
+ {
+ "135a28170fe89066da7bcff3a9ccc1b27dfe942a6f47b23835ef746aaea63dc10066d90f4e697528e5451b8e11dd408fdbd4b94a1c6c82515bf7bc099df9cb9d5fa4acad0d22d5f267f18078cec107a995c1f3b12d7603886dbf910ab85ca7180053c50e759b00dc8c81555a425c03d71df6894a6c8cd2d94b64e303c08a1bc1dee1cf537ccf300850856292e1656aff5bf349c87f1ca1ca8085cd400fe901edcad04146a0714ef0f6b083d715edd670e020385f3cda29bc5ff6fc6edffe5ca9ce9def6e0e3d5f04ede2db02cfb2",
+ "73afd2ab0e0e8537cae42dc6530dc4afb6934ca6",
+ "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e",
+ "129039b5572e8a7a8131f76a",
+ "2c125232a59879aee36cacc4aca5085a4688c4f776667a8fbd86862b5cfb1d57c976688fdd652eafa2b88b1b8e358aa2110ff6ef13cdc1ceca9c9f087c35c38d89d6fbd8de89538070f17916ecb19ca3ef4a1c834f0bdaa1df62aaabef2e117106787056c909e61ecd208357dd5c363f11c5d6cf24992cc873cf69f59360a820fcf290bd90b2cab24c47286acb4e1033962b6d41e562a206a94796a8ab1c6b8bade804ff9bdf5ba6062d2c1f8fe0f4dfc05720bd9a612b92c26789f9f6a7ce43f5e8e3aee99a9cd7d6c11eaa611983c36935b0dda57d898a60a0ab7c4b54",
+ },
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/chacha20poly1305/internal/chacha20/chacha_generic.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/chacha20poly1305/internal/chacha20/chacha_generic.go
new file mode 100644
index 000000000..0f8efdbaa
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/chacha20poly1305/internal/chacha20/chacha_generic.go
@@ -0,0 +1,198 @@
+// 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.
+
+// Package ChaCha20 implements the core ChaCha20 function as specified in https://tools.ietf.org/html/rfc7539#section-2.3.
+package chacha20
+
+import "encoding/binary"
+
+const rounds = 20
+
+// core applies the ChaCha20 core function to 16-byte input in, 32-byte key k,
+// and 16-byte constant c, and puts the result into 64-byte array out.
+func core(out *[64]byte, in *[16]byte, k *[32]byte) {
+ j0 := uint32(0x61707865)
+ j1 := uint32(0x3320646e)
+ j2 := uint32(0x79622d32)
+ j3 := uint32(0x6b206574)
+ j4 := binary.LittleEndian.Uint32(k[0:4])
+ j5 := binary.LittleEndian.Uint32(k[4:8])
+ j6 := binary.LittleEndian.Uint32(k[8:12])
+ j7 := binary.LittleEndian.Uint32(k[12:16])
+ j8 := binary.LittleEndian.Uint32(k[16:20])
+ j9 := binary.LittleEndian.Uint32(k[20:24])
+ j10 := binary.LittleEndian.Uint32(k[24:28])
+ j11 := binary.LittleEndian.Uint32(k[28:32])
+ j12 := binary.LittleEndian.Uint32(in[0:4])
+ j13 := binary.LittleEndian.Uint32(in[4:8])
+ j14 := binary.LittleEndian.Uint32(in[8:12])
+ j15 := binary.LittleEndian.Uint32(in[12:16])
+
+ x0, x1, x2, x3, x4, x5, x6, x7 := j0, j1, j2, j3, j4, j5, j6, j7
+ x8, x9, x10, x11, x12, x13, x14, x15 := j8, j9, j10, j11, j12, j13, j14, j15
+
+ for i := 0; i < rounds; i += 2 {
+ x0 += x4
+ x12 ^= x0
+ x12 = (x12 << 16) | (x12 >> (16))
+ x8 += x12
+ x4 ^= x8
+ x4 = (x4 << 12) | (x4 >> (20))
+ x0 += x4
+ x12 ^= x0
+ x12 = (x12 << 8) | (x12 >> (24))
+ x8 += x12
+ x4 ^= x8
+ x4 = (x4 << 7) | (x4 >> (25))
+ x1 += x5
+ x13 ^= x1
+ x13 = (x13 << 16) | (x13 >> 16)
+ x9 += x13
+ x5 ^= x9
+ x5 = (x5 << 12) | (x5 >> 20)
+ x1 += x5
+ x13 ^= x1
+ x13 = (x13 << 8) | (x13 >> 24)
+ x9 += x13
+ x5 ^= x9
+ x5 = (x5 << 7) | (x5 >> 25)
+ x2 += x6
+ x14 ^= x2
+ x14 = (x14 << 16) | (x14 >> 16)
+ x10 += x14
+ x6 ^= x10
+ x6 = (x6 << 12) | (x6 >> 20)
+ x2 += x6
+ x14 ^= x2
+ x14 = (x14 << 8) | (x14 >> 24)
+ x10 += x14
+ x6 ^= x10
+ x6 = (x6 << 7) | (x6 >> 25)
+ x3 += x7
+ x15 ^= x3
+ x15 = (x15 << 16) | (x15 >> 16)
+ x11 += x15
+ x7 ^= x11
+ x7 = (x7 << 12) | (x7 >> 20)
+ x3 += x7
+ x15 ^= x3
+ x15 = (x15 << 8) | (x15 >> 24)
+ x11 += x15
+ x7 ^= x11
+ x7 = (x7 << 7) | (x7 >> 25)
+ x0 += x5
+ x15 ^= x0
+ x15 = (x15 << 16) | (x15 >> 16)
+ x10 += x15
+ x5 ^= x10
+ x5 = (x5 << 12) | (x5 >> 20)
+ x0 += x5
+ x15 ^= x0
+ x15 = (x15 << 8) | (x15 >> 24)
+ x10 += x15
+ x5 ^= x10
+ x5 = (x5 << 7) | (x5 >> 25)
+ x1 += x6
+ x12 ^= x1
+ x12 = (x12 << 16) | (x12 >> 16)
+ x11 += x12
+ x6 ^= x11
+ x6 = (x6 << 12) | (x6 >> 20)
+ x1 += x6
+ x12 ^= x1
+ x12 = (x12 << 8) | (x12 >> 24)
+ x11 += x12
+ x6 ^= x11
+ x6 = (x6 << 7) | (x6 >> 25)
+ x2 += x7
+ x13 ^= x2
+ x13 = (x13 << 16) | (x13 >> 16)
+ x8 += x13
+ x7 ^= x8
+ x7 = (x7 << 12) | (x7 >> 20)
+ x2 += x7
+ x13 ^= x2
+ x13 = (x13 << 8) | (x13 >> 24)
+ x8 += x13
+ x7 ^= x8
+ x7 = (x7 << 7) | (x7 >> 25)
+ x3 += x4
+ x14 ^= x3
+ x14 = (x14 << 16) | (x14 >> 16)
+ x9 += x14
+ x4 ^= x9
+ x4 = (x4 << 12) | (x4 >> 20)
+ x3 += x4
+ x14 ^= x3
+ x14 = (x14 << 8) | (x14 >> 24)
+ x9 += x14
+ x4 ^= x9
+ x4 = (x4 << 7) | (x4 >> 25)
+ }
+
+ x0 += j0
+ x1 += j1
+ x2 += j2
+ x3 += j3
+ x4 += j4
+ x5 += j5
+ x6 += j6
+ x7 += j7
+ x8 += j8
+ x9 += j9
+ x10 += j10
+ x11 += j11
+ x12 += j12
+ x13 += j13
+ x14 += j14
+ x15 += j15
+
+ binary.LittleEndian.PutUint32(out[0:4], x0)
+ binary.LittleEndian.PutUint32(out[4:8], x1)
+ binary.LittleEndian.PutUint32(out[8:12], x2)
+ binary.LittleEndian.PutUint32(out[12:16], x3)
+ binary.LittleEndian.PutUint32(out[16:20], x4)
+ binary.LittleEndian.PutUint32(out[20:24], x5)
+ binary.LittleEndian.PutUint32(out[24:28], x6)
+ binary.LittleEndian.PutUint32(out[28:32], x7)
+ binary.LittleEndian.PutUint32(out[32:36], x8)
+ binary.LittleEndian.PutUint32(out[36:40], x9)
+ binary.LittleEndian.PutUint32(out[40:44], x10)
+ binary.LittleEndian.PutUint32(out[44:48], x11)
+ binary.LittleEndian.PutUint32(out[48:52], x12)
+ binary.LittleEndian.PutUint32(out[52:56], x13)
+ binary.LittleEndian.PutUint32(out[56:60], x14)
+ binary.LittleEndian.PutUint32(out[60:64], x15)
+}
+
+// XORKeyStream crypts bytes from in to out using the given key and counters.
+// In and out must overlap entirely or not at all. Counter contains the raw
+// ChaCha20 counter bytes (i.e. block counter followed by nonce).
+func XORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) {
+ var block [64]byte
+ var counterCopy [16]byte
+ copy(counterCopy[:], counter[:])
+
+ for len(in) >= 64 {
+ core(&block, &counterCopy, key)
+ for i, x := range block {
+ out[i] = in[i] ^ x
+ }
+ u := uint32(1)
+ for i := 0; i < 4; i++ {
+ u += uint32(counterCopy[i])
+ counterCopy[i] = byte(u)
+ u >>= 8
+ }
+ in = in[64:]
+ out = out[64:]
+ }
+
+ if len(in) > 0 {
+ core(&block, &counterCopy, key)
+ for i, v := range in {
+ out[i] = v ^ block[i]
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/chacha20poly1305/internal/chacha20/chacha_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/chacha20poly1305/internal/chacha20/chacha_test.go
new file mode 100644
index 000000000..b80d34cdd
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/chacha20poly1305/internal/chacha20/chacha_test.go
@@ -0,0 +1,33 @@
+// 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.
+
+package chacha20
+
+import (
+ "encoding/hex"
+ "testing"
+)
+
+func TestCore(t *testing.T) {
+ // This is just a smoke test that checks the example from
+ // https://tools.ietf.org/html/rfc7539#section-2.3.2. The
+ // chacha20poly1305 package contains much more extensive tests of this
+ // code.
+ var key [32]byte
+ for i := range key {
+ key[i] = byte(i)
+ }
+
+ var input [16]byte
+ input[0] = 1
+ input[7] = 9
+ input[11] = 0x4a
+
+ var out [64]byte
+ XORKeyStream(out[:], out[:], &input, &key)
+ const expected = "10f1e7e4d13b5915500fdd1fa32071c4c7d1f4c733c068030422aa9ac3d46c4ed2826446079faa0914c2d705d98b02a2b5129cd1de164eb9cbd083e8a2503c4e"
+ if result := hex.EncodeToString(out[:]); result != expected {
+ t.Errorf("wanted %x but got %x", expected, result)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/codereview.cfg b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/codereview.cfg
new file mode 100644
index 000000000..3f8b14b64
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/codereview.cfg
@@ -0,0 +1 @@
+issuerepo: golang/go
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/cryptobyte/asn1.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/cryptobyte/asn1.go
new file mode 100644
index 000000000..88ec8b4fb
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/cryptobyte/asn1.go
@@ -0,0 +1,732 @@
+// 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 cryptobyte
+
+import (
+ encoding_asn1 "encoding/asn1"
+ "fmt"
+ "math/big"
+ "reflect"
+ "time"
+
+ "golang.org/x/crypto/cryptobyte/asn1"
+)
+
+// This file contains ASN.1-related methods for String and Builder.
+
+// Builder
+
+// AddASN1Int64 appends a DER-encoded ASN.1 INTEGER.
+func (b *Builder) AddASN1Int64(v int64) {
+ b.addASN1Signed(asn1.INTEGER, v)
+}
+
+// AddASN1Enum appends a DER-encoded ASN.1 ENUMERATION.
+func (b *Builder) AddASN1Enum(v int64) {
+ b.addASN1Signed(asn1.ENUM, v)
+}
+
+func (b *Builder) addASN1Signed(tag asn1.Tag, v int64) {
+ b.AddASN1(tag, func(c *Builder) {
+ length := 1
+ for i := v; i >= 0x80 || i < -0x80; i >>= 8 {
+ length++
+ }
+
+ for ; length > 0; length-- {
+ i := v >> uint((length-1)*8) & 0xff
+ c.AddUint8(uint8(i))
+ }
+ })
+}
+
+// AddASN1Uint64 appends a DER-encoded ASN.1 INTEGER.
+func (b *Builder) AddASN1Uint64(v uint64) {
+ b.AddASN1(asn1.INTEGER, func(c *Builder) {
+ length := 1
+ for i := v; i >= 0x80; i >>= 8 {
+ length++
+ }
+
+ for ; length > 0; length-- {
+ i := v >> uint((length-1)*8) & 0xff
+ c.AddUint8(uint8(i))
+ }
+ })
+}
+
+// AddASN1BigInt appends a DER-encoded ASN.1 INTEGER.
+func (b *Builder) AddASN1BigInt(n *big.Int) {
+ if b.err != nil {
+ return
+ }
+
+ b.AddASN1(asn1.INTEGER, func(c *Builder) {
+ if n.Sign() < 0 {
+ // A negative number has to be converted to two's-complement form. So we
+ // invert and subtract 1. If the most-significant-bit isn't set then
+ // we'll need to pad the beginning with 0xff in order to keep the number
+ // negative.
+ nMinus1 := new(big.Int).Neg(n)
+ nMinus1.Sub(nMinus1, bigOne)
+ bytes := nMinus1.Bytes()
+ for i := range bytes {
+ bytes[i] ^= 0xff
+ }
+ if bytes[0]&0x80 == 0 {
+ c.add(0xff)
+ }
+ c.add(bytes...)
+ } else if n.Sign() == 0 {
+ c.add(0)
+ } else {
+ bytes := n.Bytes()
+ if bytes[0]&0x80 != 0 {
+ c.add(0)
+ }
+ c.add(bytes...)
+ }
+ })
+}
+
+// AddASN1OctetString appends a DER-encoded ASN.1 OCTET STRING.
+func (b *Builder) AddASN1OctetString(bytes []byte) {
+ b.AddASN1(asn1.OCTET_STRING, func(c *Builder) {
+ c.AddBytes(bytes)
+ })
+}
+
+const generalizedTimeFormatStr = "20060102150405Z0700"
+
+// AddASN1GeneralizedTime appends a DER-encoded ASN.1 GENERALIZEDTIME.
+func (b *Builder) AddASN1GeneralizedTime(t time.Time) {
+ if t.Year() < 0 || t.Year() > 9999 {
+ b.err = fmt.Errorf("cryptobyte: cannot represent %v as a GeneralizedTime", t)
+ return
+ }
+ b.AddASN1(asn1.GeneralizedTime, func(c *Builder) {
+ c.AddBytes([]byte(t.Format(generalizedTimeFormatStr)))
+ })
+}
+
+// AddASN1BitString appends a DER-encoded ASN.1 BIT STRING. This does not
+// support BIT STRINGs that are not a whole number of bytes.
+func (b *Builder) AddASN1BitString(data []byte) {
+ b.AddASN1(asn1.BIT_STRING, func(b *Builder) {
+ b.AddUint8(0)
+ b.AddBytes(data)
+ })
+}
+
+func (b *Builder) addBase128Int(n int64) {
+ var length int
+ if n == 0 {
+ length = 1
+ } else {
+ for i := n; i > 0; i >>= 7 {
+ length++
+ }
+ }
+
+ for i := length - 1; i >= 0; i-- {
+ o := byte(n >> uint(i*7))
+ o &= 0x7f
+ if i != 0 {
+ o |= 0x80
+ }
+
+ b.add(o)
+ }
+}
+
+func isValidOID(oid encoding_asn1.ObjectIdentifier) bool {
+ if len(oid) < 2 {
+ return false
+ }
+
+ if oid[0] > 2 || (oid[0] <= 1 && oid[1] >= 40) {
+ return false
+ }
+
+ for _, v := range oid {
+ if v < 0 {
+ return false
+ }
+ }
+
+ return true
+}
+
+func (b *Builder) AddASN1ObjectIdentifier(oid encoding_asn1.ObjectIdentifier) {
+ b.AddASN1(asn1.OBJECT_IDENTIFIER, func(b *Builder) {
+ if !isValidOID(oid) {
+ b.err = fmt.Errorf("cryptobyte: invalid OID: %v", oid)
+ return
+ }
+
+ b.addBase128Int(int64(oid[0])*40 + int64(oid[1]))
+ for _, v := range oid[2:] {
+ b.addBase128Int(int64(v))
+ }
+ })
+}
+
+func (b *Builder) AddASN1Boolean(v bool) {
+ b.AddASN1(asn1.BOOLEAN, func(b *Builder) {
+ if v {
+ b.AddUint8(0xff)
+ } else {
+ b.AddUint8(0)
+ }
+ })
+}
+
+func (b *Builder) AddASN1NULL() {
+ b.add(uint8(asn1.NULL), 0)
+}
+
+// MarshalASN1 calls encoding_asn1.Marshal on its input and appends the result if
+// successful or records an error if one occurred.
+func (b *Builder) MarshalASN1(v interface{}) {
+ // NOTE(martinkr): This is somewhat of a hack to allow propagation of
+ // encoding_asn1.Marshal errors into Builder.err. N.B. if you call MarshalASN1 with a
+ // value embedded into a struct, its tag information is lost.
+ if b.err != nil {
+ return
+ }
+ bytes, err := encoding_asn1.Marshal(v)
+ if err != nil {
+ b.err = err
+ return
+ }
+ b.AddBytes(bytes)
+}
+
+// AddASN1 appends an ASN.1 object. The object is prefixed with the given tag.
+// Tags greater than 30 are not supported and result in an error (i.e.
+// low-tag-number form only). The child builder passed to the
+// BuilderContinuation can be used to build the content of the ASN.1 object.
+func (b *Builder) AddASN1(tag asn1.Tag, f BuilderContinuation) {
+ if b.err != nil {
+ return
+ }
+ // Identifiers with the low five bits set indicate high-tag-number format
+ // (two or more octets), which we don't support.
+ if tag&0x1f == 0x1f {
+ b.err = fmt.Errorf("cryptobyte: high-tag number identifier octects not supported: 0x%x", tag)
+ return
+ }
+ b.AddUint8(uint8(tag))
+ b.addLengthPrefixed(1, true, f)
+}
+
+// String
+
+func (s *String) ReadASN1Boolean(out *bool) bool {
+ var bytes String
+ if !s.ReadASN1(&bytes, asn1.INTEGER) || len(bytes) != 1 {
+ return false
+ }
+
+ switch bytes[0] {
+ case 0:
+ *out = false
+ case 0xff:
+ *out = true
+ default:
+ return false
+ }
+
+ return true
+}
+
+var bigIntType = reflect.TypeOf((*big.Int)(nil)).Elem()
+
+// ReadASN1Integer decodes an ASN.1 INTEGER into out and advances. If out does
+// not point to an integer or to a big.Int, it panics. It returns true on
+// success and false on error.
+func (s *String) ReadASN1Integer(out interface{}) bool {
+ if reflect.TypeOf(out).Kind() != reflect.Ptr {
+ panic("out is not a pointer")
+ }
+ switch reflect.ValueOf(out).Elem().Kind() {
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ var i int64
+ if !s.readASN1Int64(&i) || reflect.ValueOf(out).Elem().OverflowInt(i) {
+ return false
+ }
+ reflect.ValueOf(out).Elem().SetInt(i)
+ return true
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ var u uint64
+ if !s.readASN1Uint64(&u) || reflect.ValueOf(out).Elem().OverflowUint(u) {
+ return false
+ }
+ reflect.ValueOf(out).Elem().SetUint(u)
+ return true
+ case reflect.Struct:
+ if reflect.TypeOf(out).Elem() == bigIntType {
+ return s.readASN1BigInt(out.(*big.Int))
+ }
+ }
+ panic("out does not point to an integer type")
+}
+
+func checkASN1Integer(bytes []byte) bool {
+ if len(bytes) == 0 {
+ // An INTEGER is encoded with at least one octet.
+ return false
+ }
+ if len(bytes) == 1 {
+ return true
+ }
+ if bytes[0] == 0 && bytes[1]&0x80 == 0 || bytes[0] == 0xff && bytes[1]&0x80 == 0x80 {
+ // Value is not minimally encoded.
+ return false
+ }
+ return true
+}
+
+var bigOne = big.NewInt(1)
+
+func (s *String) readASN1BigInt(out *big.Int) bool {
+ var bytes String
+ if !s.ReadASN1(&bytes, asn1.INTEGER) || !checkASN1Integer(bytes) {
+ return false
+ }
+ if bytes[0]&0x80 == 0x80 {
+ // Negative number.
+ neg := make([]byte, len(bytes))
+ for i, b := range bytes {
+ neg[i] = ^b
+ }
+ out.SetBytes(neg)
+ out.Add(out, bigOne)
+ out.Neg(out)
+ } else {
+ out.SetBytes(bytes)
+ }
+ return true
+}
+
+func (s *String) readASN1Int64(out *int64) bool {
+ var bytes String
+ if !s.ReadASN1(&bytes, asn1.INTEGER) || !checkASN1Integer(bytes) || !asn1Signed(out, bytes) {
+ return false
+ }
+ return true
+}
+
+func asn1Signed(out *int64, n []byte) bool {
+ length := len(n)
+ if length > 8 {
+ return false
+ }
+ for i := 0; i < length; i++ {
+ *out <<= 8
+ *out |= int64(n[i])
+ }
+ // Shift up and down in order to sign extend the result.
+ *out <<= 64 - uint8(length)*8
+ *out >>= 64 - uint8(length)*8
+ return true
+}
+
+func (s *String) readASN1Uint64(out *uint64) bool {
+ var bytes String
+ if !s.ReadASN1(&bytes, asn1.INTEGER) || !checkASN1Integer(bytes) || !asn1Unsigned(out, bytes) {
+ return false
+ }
+ return true
+}
+
+func asn1Unsigned(out *uint64, n []byte) bool {
+ length := len(n)
+ if length > 9 || length == 9 && n[0] != 0 {
+ // Too large for uint64.
+ return false
+ }
+ if n[0]&0x80 != 0 {
+ // Negative number.
+ return false
+ }
+ for i := 0; i < length; i++ {
+ *out <<= 8
+ *out |= uint64(n[i])
+ }
+ return true
+}
+
+// ReadASN1Enum decodes an ASN.1 ENUMERATION into out and advances. It returns
+// true on success and false on error.
+func (s *String) ReadASN1Enum(out *int) bool {
+ var bytes String
+ var i int64
+ if !s.ReadASN1(&bytes, asn1.ENUM) || !checkASN1Integer(bytes) || !asn1Signed(&i, bytes) {
+ return false
+ }
+ if int64(int(i)) != i {
+ return false
+ }
+ *out = int(i)
+ return true
+}
+
+func (s *String) readBase128Int(out *int) bool {
+ ret := 0
+ for i := 0; len(*s) > 0; i++ {
+ if i == 4 {
+ return false
+ }
+ ret <<= 7
+ b := s.read(1)[0]
+ ret |= int(b & 0x7f)
+ if b&0x80 == 0 {
+ *out = ret
+ return true
+ }
+ }
+ return false // truncated
+}
+
+// ReadASN1ObjectIdentifier decodes an ASN.1 OBJECT IDENTIFIER into out and
+// advances. It returns true on success and false on error.
+func (s *String) ReadASN1ObjectIdentifier(out *encoding_asn1.ObjectIdentifier) bool {
+ var bytes String
+ if !s.ReadASN1(&bytes, asn1.OBJECT_IDENTIFIER) || len(bytes) == 0 {
+ return false
+ }
+
+ // In the worst case, we get two elements from the first byte (which is
+ // encoded differently) and then every varint is a single byte long.
+ components := make([]int, len(bytes)+1)
+
+ // The first varint is 40*value1 + value2:
+ // According to this packing, value1 can take the values 0, 1 and 2 only.
+ // When value1 = 0 or value1 = 1, then value2 is <= 39. When value1 = 2,
+ // then there are no restrictions on value2.
+ var v int
+ if !bytes.readBase128Int(&v) {
+ return false
+ }
+ if v < 80 {
+ components[0] = v / 40
+ components[1] = v % 40
+ } else {
+ components[0] = 2
+ components[1] = v - 80
+ }
+
+ i := 2
+ for ; len(bytes) > 0; i++ {
+ if !bytes.readBase128Int(&v) {
+ return false
+ }
+ components[i] = v
+ }
+ *out = components[:i]
+ return true
+}
+
+// ReadASN1GeneralizedTime decodes an ASN.1 GENERALIZEDTIME into out and
+// advances. It returns true on success and false on error.
+func (s *String) ReadASN1GeneralizedTime(out *time.Time) bool {
+ var bytes String
+ if !s.ReadASN1(&bytes, asn1.GeneralizedTime) {
+ return false
+ }
+ t := string(bytes)
+ res, err := time.Parse(generalizedTimeFormatStr, t)
+ if err != nil {
+ return false
+ }
+ if serialized := res.Format(generalizedTimeFormatStr); serialized != t {
+ return false
+ }
+ *out = res
+ return true
+}
+
+// ReadASN1BitString decodes an ASN.1 BIT STRING into out and advances. It
+// returns true on success and false on error.
+func (s *String) ReadASN1BitString(out *encoding_asn1.BitString) bool {
+ var bytes String
+ if !s.ReadASN1(&bytes, asn1.BIT_STRING) || len(bytes) == 0 {
+ return false
+ }
+
+ paddingBits := uint8(bytes[0])
+ bytes = bytes[1:]
+ if paddingBits > 7 ||
+ len(bytes) == 0 && paddingBits != 0 ||
+ len(bytes) > 0 && bytes[len(bytes)-1]&(1<<paddingBits-1) != 0 {
+ return false
+ }
+
+ out.BitLength = len(bytes)*8 - int(paddingBits)
+ out.Bytes = bytes
+ return true
+}
+
+// ReadASN1BitString decodes an ASN.1 BIT STRING into out and advances. It is
+// an error if the BIT STRING is not a whole number of bytes. This function
+// returns true on success and false on error.
+func (s *String) ReadASN1BitStringAsBytes(out *[]byte) bool {
+ var bytes String
+ if !s.ReadASN1(&bytes, asn1.BIT_STRING) || len(bytes) == 0 {
+ return false
+ }
+
+ paddingBits := uint8(bytes[0])
+ if paddingBits != 0 {
+ return false
+ }
+ *out = bytes[1:]
+ return true
+}
+
+// ReadASN1Bytes reads the contents of a DER-encoded ASN.1 element (not including
+// tag and length bytes) into out, and advances. The element must match the
+// given tag. It returns true on success and false on error.
+func (s *String) ReadASN1Bytes(out *[]byte, tag asn1.Tag) bool {
+ return s.ReadASN1((*String)(out), tag)
+}
+
+// ReadASN1 reads the contents of a DER-encoded ASN.1 element (not including
+// tag and length bytes) into out, and advances. The element must match the
+// given tag. It returns true on success and false on error.
+//
+// Tags greater than 30 are not supported (i.e. low-tag-number format only).
+func (s *String) ReadASN1(out *String, tag asn1.Tag) bool {
+ var t asn1.Tag
+ if !s.ReadAnyASN1(out, &t) || t != tag {
+ return false
+ }
+ return true
+}
+
+// ReadASN1Element reads the contents of a DER-encoded ASN.1 element (including
+// tag and length bytes) into out, and advances. The element must match the
+// given tag. It returns true on success and false on error.
+//
+// Tags greater than 30 are not supported (i.e. low-tag-number format only).
+func (s *String) ReadASN1Element(out *String, tag asn1.Tag) bool {
+ var t asn1.Tag
+ if !s.ReadAnyASN1Element(out, &t) || t != tag {
+ return false
+ }
+ return true
+}
+
+// ReadAnyASN1 reads the contents of a DER-encoded ASN.1 element (not including
+// tag and length bytes) into out, sets outTag to its tag, and advances. It
+// returns true on success and false on error.
+//
+// Tags greater than 30 are not supported (i.e. low-tag-number format only).
+func (s *String) ReadAnyASN1(out *String, outTag *asn1.Tag) bool {
+ return s.readASN1(out, outTag, true /* skip header */)
+}
+
+// ReadAnyASN1Element reads the contents of a DER-encoded ASN.1 element
+// (including tag and length bytes) into out, sets outTag to is tag, and
+// advances. It returns true on success and false on error.
+//
+// Tags greater than 30 are not supported (i.e. low-tag-number format only).
+func (s *String) ReadAnyASN1Element(out *String, outTag *asn1.Tag) bool {
+ return s.readASN1(out, outTag, false /* include header */)
+}
+
+// PeekASN1Tag returns true if the next ASN.1 value on the string starts with
+// the given tag.
+func (s String) PeekASN1Tag(tag asn1.Tag) bool {
+ if len(s) == 0 {
+ return false
+ }
+ return asn1.Tag(s[0]) == tag
+}
+
+// SkipASN1 reads and discards an ASN.1 element with the given tag.
+func (s *String) SkipASN1(tag asn1.Tag) bool {
+ var unused String
+ return s.ReadASN1(&unused, tag)
+}
+
+// ReadOptionalASN1 attempts to read the contents of a DER-encoded ASN.1
+// element (not including tag and length bytes) tagged with the given tag into
+// out. It stores whether an element with the tag was found in outPresent,
+// unless outPresent is nil. It returns true on success and false on error.
+func (s *String) ReadOptionalASN1(out *String, outPresent *bool, tag asn1.Tag) bool {
+ present := s.PeekASN1Tag(tag)
+ if outPresent != nil {
+ *outPresent = present
+ }
+ if present && !s.ReadASN1(out, tag) {
+ return false
+ }
+ return true
+}
+
+// SkipOptionalASN1 advances s over an ASN.1 element with the given tag, or
+// else leaves s unchanged.
+func (s *String) SkipOptionalASN1(tag asn1.Tag) bool {
+ if !s.PeekASN1Tag(tag) {
+ return true
+ }
+ var unused String
+ return s.ReadASN1(&unused, tag)
+}
+
+// ReadOptionalASN1Integer attempts to read an optional ASN.1 INTEGER
+// explicitly tagged with tag into out and advances. If no element with a
+// matching tag is present, it writes defaultValue into out instead. If out
+// does not point to an integer or to a big.Int, it panics. It returns true on
+// success and false on error.
+func (s *String) ReadOptionalASN1Integer(out interface{}, tag asn1.Tag, defaultValue interface{}) bool {
+ if reflect.TypeOf(out).Kind() != reflect.Ptr {
+ panic("out is not a pointer")
+ }
+ var present bool
+ var i String
+ if !s.ReadOptionalASN1(&i, &present, tag) {
+ return false
+ }
+ if !present {
+ switch reflect.ValueOf(out).Elem().Kind() {
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
+ reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ reflect.ValueOf(out).Elem().Set(reflect.ValueOf(defaultValue))
+ case reflect.Struct:
+ if reflect.TypeOf(out).Elem() != bigIntType {
+ panic("invalid integer type")
+ }
+ if reflect.TypeOf(defaultValue).Kind() != reflect.Ptr ||
+ reflect.TypeOf(defaultValue).Elem() != bigIntType {
+ panic("out points to big.Int, but defaultValue does not")
+ }
+ out.(*big.Int).Set(defaultValue.(*big.Int))
+ default:
+ panic("invalid integer type")
+ }
+ return true
+ }
+ if !i.ReadASN1Integer(out) || !i.Empty() {
+ return false
+ }
+ return true
+}
+
+// ReadOptionalASN1OctetString attempts to read an optional ASN.1 OCTET STRING
+// explicitly tagged with tag into out and advances. If no element with a
+// matching tag is present, it writes defaultValue into out instead. It returns
+// true on success and false on error.
+func (s *String) ReadOptionalASN1OctetString(out *[]byte, outPresent *bool, tag asn1.Tag) bool {
+ var present bool
+ var child String
+ if !s.ReadOptionalASN1(&child, &present, tag) {
+ return false
+ }
+ if outPresent != nil {
+ *outPresent = present
+ }
+ if present {
+ var oct String
+ if !child.ReadASN1(&oct, asn1.OCTET_STRING) || !child.Empty() {
+ return false
+ }
+ *out = oct
+ } else {
+ *out = nil
+ }
+ return true
+}
+
+// ReadOptionalASN1Boolean sets *out to the value of the next ASN.1 BOOLEAN or,
+// if the next bytes are not an ASN.1 BOOLEAN, to the value of defaultValue.
+func (s *String) ReadOptionalASN1Boolean(out *bool, defaultValue bool) bool {
+ var present bool
+ var child String
+ if !s.ReadOptionalASN1(&child, &present, asn1.BOOLEAN) {
+ return false
+ }
+
+ if !present {
+ *out = defaultValue
+ return true
+ }
+
+ return s.ReadASN1Boolean(out)
+}
+
+func (s *String) readASN1(out *String, outTag *asn1.Tag, skipHeader bool) bool {
+ if len(*s) < 2 {
+ return false
+ }
+ tag, lenByte := (*s)[0], (*s)[1]
+
+ if tag&0x1f == 0x1f {
+ // ITU-T X.690 section 8.1.2
+ //
+ // An identifier octet with a tag part of 0x1f indicates a high-tag-number
+ // form identifier with two or more octets. We only support tags less than
+ // 31 (i.e. low-tag-number form, single octet identifier).
+ return false
+ }
+
+ if outTag != nil {
+ *outTag = asn1.Tag(tag)
+ }
+
+ // ITU-T X.690 section 8.1.3
+ //
+ // Bit 8 of the first length byte indicates whether the length is short- or
+ // long-form.
+ var length, headerLen uint32 // length includes headerLen
+ if lenByte&0x80 == 0 {
+ // Short-form length (section 8.1.3.4), encoded in bits 1-7.
+ length = uint32(lenByte) + 2
+ headerLen = 2
+ } else {
+ // Long-form length (section 8.1.3.5). Bits 1-7 encode the number of octets
+ // used to encode the length.
+ lenLen := lenByte & 0x7f
+ var len32 uint32
+
+ if lenLen == 0 || lenLen > 4 || len(*s) < int(2+lenLen) {
+ return false
+ }
+
+ lenBytes := String((*s)[2 : 2+lenLen])
+ if !lenBytes.readUnsigned(&len32, int(lenLen)) {
+ return false
+ }
+
+ // ITU-T X.690 section 10.1 (DER length forms) requires encoding the length
+ // with the minimum number of octets.
+ if len32 < 128 {
+ // Length should have used short-form encoding.
+ return false
+ }
+ if len32>>((lenLen-1)*8) == 0 {
+ // Leading octet is 0. Length should have been at least one byte shorter.
+ return false
+ }
+
+ headerLen = 2 + uint32(lenLen)
+ if headerLen+len32 < len32 {
+ // Overflow.
+ return false
+ }
+ length = headerLen + len32
+ }
+
+ if uint32(int(length)) != length || !s.ReadBytes((*[]byte)(out), int(length)) {
+ return false
+ }
+ if skipHeader && !out.Skip(int(headerLen)) {
+ panic("cryptobyte: internal error")
+ }
+
+ return true
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/cryptobyte/asn1/asn1.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/cryptobyte/asn1/asn1.go
new file mode 100644
index 000000000..cda8e3edf
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/cryptobyte/asn1/asn1.go
@@ -0,0 +1,46 @@
+// 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 asn1 contains supporting types for parsing and building ASN.1
+// messages with the cryptobyte package.
+package asn1 // import "golang.org/x/crypto/cryptobyte/asn1"
+
+// Tag represents an ASN.1 identifier octet, consisting of a tag number
+// (indicating a type) and class (such as context-specific or constructed).
+//
+// Methods in the cryptobyte package only support the low-tag-number form, i.e.
+// a single identifier octet with bits 7-8 encoding the class and bits 1-6
+// encoding the tag number.
+type Tag uint8
+
+const (
+ classConstructed = 0x20
+ classContextSpecific = 0x80
+)
+
+// Constructed returns t with the constructed class bit set.
+func (t Tag) Constructed() Tag { return t | classConstructed }
+
+// ContextSpecific returns t with the context-specific class bit set.
+func (t Tag) ContextSpecific() Tag { return t | classContextSpecific }
+
+// The following is a list of standard tag and class combinations.
+const (
+ BOOLEAN = Tag(1)
+ INTEGER = Tag(2)
+ BIT_STRING = Tag(3)
+ OCTET_STRING = Tag(4)
+ NULL = Tag(5)
+ OBJECT_IDENTIFIER = Tag(6)
+ ENUM = Tag(10)
+ UTF8String = Tag(12)
+ SEQUENCE = Tag(16 | classConstructed)
+ SET = Tag(17 | classConstructed)
+ PrintableString = Tag(19)
+ T61String = Tag(20)
+ IA5String = Tag(22)
+ UTCTime = Tag(23)
+ GeneralizedTime = Tag(24)
+ GeneralString = Tag(27)
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/cryptobyte/asn1_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/cryptobyte/asn1_test.go
new file mode 100644
index 000000000..ee6674a2f
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/cryptobyte/asn1_test.go
@@ -0,0 +1,300 @@
+// 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 cryptobyte
+
+import (
+ "bytes"
+ encoding_asn1 "encoding/asn1"
+ "math/big"
+ "reflect"
+ "testing"
+ "time"
+
+ "golang.org/x/crypto/cryptobyte/asn1"
+)
+
+type readASN1Test struct {
+ name string
+ in []byte
+ tag asn1.Tag
+ ok bool
+ out interface{}
+}
+
+var readASN1TestData = []readASN1Test{
+ {"valid", []byte{0x30, 2, 1, 2}, 0x30, true, []byte{1, 2}},
+ {"truncated", []byte{0x30, 3, 1, 2}, 0x30, false, nil},
+ {"zero length of length", []byte{0x30, 0x80}, 0x30, false, nil},
+ {"invalid long form length", []byte{0x30, 0x81, 1, 1}, 0x30, false, nil},
+ {"non-minimal length", append([]byte{0x30, 0x82, 0, 0x80}, make([]byte, 0x80)...), 0x30, false, nil},
+ {"invalid tag", []byte{0xa1, 3, 0x4, 1, 1}, 31, false, nil},
+ {"high tag", []byte{0x1f, 0x81, 0x80, 0x01, 2, 1, 2}, 0xff /* actually 0x4001, but tag is uint8 */, false, nil},
+}
+
+func TestReadASN1(t *testing.T) {
+ for _, test := range readASN1TestData {
+ t.Run(test.name, func(t *testing.T) {
+ var in, out String = test.in, nil
+ ok := in.ReadASN1(&out, test.tag)
+ if ok != test.ok || ok && !bytes.Equal(out, test.out.([]byte)) {
+ t.Errorf("in.ReadASN1() = %v, want %v; out = %v, want %v", ok, test.ok, out, test.out)
+ }
+ })
+ }
+}
+
+func TestReadASN1Optional(t *testing.T) {
+ var empty String
+ var present bool
+ ok := empty.ReadOptionalASN1(nil, &present, 0xa0)
+ if !ok || present {
+ t.Errorf("empty.ReadOptionalASN1() = %v, want true; present = %v want false", ok, present)
+ }
+
+ var in, out String = []byte{0xa1, 3, 0x4, 1, 1}, nil
+ ok = in.ReadOptionalASN1(&out, &present, 0xa0)
+ if !ok || present {
+ t.Errorf("in.ReadOptionalASN1() = %v, want true, present = %v, want false", ok, present)
+ }
+ ok = in.ReadOptionalASN1(&out, &present, 0xa1)
+ wantBytes := []byte{4, 1, 1}
+ if !ok || !present || !bytes.Equal(out, wantBytes) {
+ t.Errorf("in.ReadOptionalASN1() = %v, want true; present = %v, want true; out = %v, want = %v", ok, present, out, wantBytes)
+ }
+}
+
+var optionalOctetStringTestData = []struct {
+ readASN1Test
+ present bool
+}{
+ {readASN1Test{"empty", []byte{}, 0xa0, true, []byte{}}, false},
+ {readASN1Test{"invalid", []byte{0xa1, 3, 0x4, 2, 1}, 0xa1, false, []byte{}}, true},
+ {readASN1Test{"missing", []byte{0xa1, 3, 0x4, 1, 1}, 0xa0, true, []byte{}}, false},
+ {readASN1Test{"present", []byte{0xa1, 3, 0x4, 1, 1}, 0xa1, true, []byte{1}}, true},
+}
+
+func TestReadASN1OptionalOctetString(t *testing.T) {
+ for _, test := range optionalOctetStringTestData {
+ t.Run(test.name, func(t *testing.T) {
+ in := String(test.in)
+ var out []byte
+ var present bool
+ ok := in.ReadOptionalASN1OctetString(&out, &present, test.tag)
+ if ok != test.ok || present != test.present || !bytes.Equal(out, test.out.([]byte)) {
+ t.Errorf("in.ReadOptionalASN1OctetString() = %v, want %v; present = %v want %v; out = %v, want %v", ok, test.ok, present, test.present, out, test.out)
+ }
+ })
+ }
+}
+
+const defaultInt = -1
+
+var optionalIntTestData = []readASN1Test{
+ {"empty", []byte{}, 0xa0, true, defaultInt},
+ {"invalid", []byte{0xa1, 3, 0x2, 2, 127}, 0xa1, false, 0},
+ {"missing", []byte{0xa1, 3, 0x2, 1, 127}, 0xa0, true, defaultInt},
+ {"present", []byte{0xa1, 3, 0x2, 1, 42}, 0xa1, true, 42},
+}
+
+func TestReadASN1OptionalInteger(t *testing.T) {
+ for _, test := range optionalIntTestData {
+ t.Run(test.name, func(t *testing.T) {
+ in := String(test.in)
+ var out int
+ ok := in.ReadOptionalASN1Integer(&out, test.tag, defaultInt)
+ if ok != test.ok || ok && out != test.out.(int) {
+ t.Errorf("in.ReadOptionalASN1Integer() = %v, want %v; out = %v, want %v", ok, test.ok, out, test.out)
+ }
+ })
+ }
+}
+
+func TestReadASN1IntegerSigned(t *testing.T) {
+ testData64 := []struct {
+ in []byte
+ out int64
+ }{
+ {[]byte{2, 3, 128, 0, 0}, -0x800000},
+ {[]byte{2, 2, 255, 0}, -256},
+ {[]byte{2, 2, 255, 127}, -129},
+ {[]byte{2, 1, 128}, -128},
+ {[]byte{2, 1, 255}, -1},
+ {[]byte{2, 1, 0}, 0},
+ {[]byte{2, 1, 1}, 1},
+ {[]byte{2, 1, 2}, 2},
+ {[]byte{2, 1, 127}, 127},
+ {[]byte{2, 2, 0, 128}, 128},
+ {[]byte{2, 2, 1, 0}, 256},
+ {[]byte{2, 4, 0, 128, 0, 0}, 0x800000},
+ }
+ for i, test := range testData64 {
+ in := String(test.in)
+ var out int64
+ ok := in.ReadASN1Integer(&out)
+ if !ok || out != test.out {
+ t.Errorf("#%d: in.ReadASN1Integer() = %v, want true; out = %d, want %d", i, ok, out, test.out)
+ }
+ }
+
+ // Repeat the same cases, reading into a big.Int.
+ t.Run("big.Int", func(t *testing.T) {
+ for i, test := range testData64 {
+ in := String(test.in)
+ var out big.Int
+ ok := in.ReadASN1Integer(&out)
+ if !ok || out.Int64() != test.out {
+ t.Errorf("#%d: in.ReadASN1Integer() = %v, want true; out = %d, want %d", i, ok, out.Int64(), test.out)
+ }
+ }
+ })
+}
+
+func TestReadASN1IntegerUnsigned(t *testing.T) {
+ testData := []struct {
+ in []byte
+ out uint64
+ }{
+ {[]byte{2, 1, 0}, 0},
+ {[]byte{2, 1, 1}, 1},
+ {[]byte{2, 1, 2}, 2},
+ {[]byte{2, 1, 127}, 127},
+ {[]byte{2, 2, 0, 128}, 128},
+ {[]byte{2, 2, 1, 0}, 256},
+ {[]byte{2, 4, 0, 128, 0, 0}, 0x800000},
+ {[]byte{2, 8, 127, 255, 255, 255, 255, 255, 255, 255}, 0x7fffffffffffffff},
+ {[]byte{2, 9, 0, 128, 0, 0, 0, 0, 0, 0, 0}, 0x8000000000000000},
+ {[]byte{2, 9, 0, 255, 255, 255, 255, 255, 255, 255, 255}, 0xffffffffffffffff},
+ }
+ for i, test := range testData {
+ in := String(test.in)
+ var out uint64
+ ok := in.ReadASN1Integer(&out)
+ if !ok || out != test.out {
+ t.Errorf("#%d: in.ReadASN1Integer() = %v, want true; out = %d, want %d", i, ok, out, test.out)
+ }
+ }
+}
+
+func TestReadASN1IntegerInvalid(t *testing.T) {
+ testData := []String{
+ []byte{3, 1, 0}, // invalid tag
+ // truncated
+ []byte{2, 1},
+ []byte{2, 2, 0},
+ // not minimally encoded
+ []byte{2, 2, 0, 1},
+ []byte{2, 2, 0xff, 0xff},
+ }
+
+ for i, test := range testData {
+ var out int64
+ if test.ReadASN1Integer(&out) {
+ t.Errorf("#%d: in.ReadASN1Integer() = true, want false (out = %d)", i, out)
+ }
+ }
+}
+
+func TestASN1ObjectIdentifier(t *testing.T) {
+ testData := []struct {
+ in []byte
+ ok bool
+ out []int
+ }{
+ {[]byte{}, false, []int{}},
+ {[]byte{6, 0}, false, []int{}},
+ {[]byte{5, 1, 85}, false, []int{2, 5}},
+ {[]byte{6, 1, 85}, true, []int{2, 5}},
+ {[]byte{6, 2, 85, 0x02}, true, []int{2, 5, 2}},
+ {[]byte{6, 4, 85, 0x02, 0xc0, 0x00}, true, []int{2, 5, 2, 0x2000}},
+ {[]byte{6, 3, 0x81, 0x34, 0x03}, true, []int{2, 100, 3}},
+ {[]byte{6, 7, 85, 0x02, 0xc0, 0x80, 0x80, 0x80, 0x80}, false, []int{}},
+ }
+
+ for i, test := range testData {
+ in := String(test.in)
+ var out encoding_asn1.ObjectIdentifier
+ ok := in.ReadASN1ObjectIdentifier(&out)
+ if ok != test.ok || ok && !out.Equal(test.out) {
+ t.Errorf("#%d: in.ReadASN1ObjectIdentifier() = %v, want %v; out = %v, want %v", i, ok, test.ok, out, test.out)
+ continue
+ }
+
+ var b Builder
+ b.AddASN1ObjectIdentifier(out)
+ result, err := b.Bytes()
+ if builderOk := err == nil; test.ok != builderOk {
+ t.Errorf("#%d: error from Builder.Bytes: %s", i, err)
+ continue
+ }
+ if test.ok && !bytes.Equal(result, test.in) {
+ t.Errorf("#%d: reserialisation didn't match, got %x, want %x", i, result, test.in)
+ continue
+ }
+ }
+}
+
+func TestReadASN1GeneralizedTime(t *testing.T) {
+ testData := []struct {
+ in string
+ ok bool
+ out time.Time
+ }{
+ {"20100102030405Z", true, time.Date(2010, 01, 02, 03, 04, 05, 0, time.UTC)},
+ {"20100102030405", false, time.Time{}},
+ {"20100102030405+0607", true, time.Date(2010, 01, 02, 03, 04, 05, 0, time.FixedZone("", 6*60*60+7*60))},
+ {"20100102030405-0607", true, time.Date(2010, 01, 02, 03, 04, 05, 0, time.FixedZone("", -6*60*60-7*60))},
+ /* These are invalid times. However, the time package normalises times
+ * and they were accepted in some versions. See #11134. */
+ {"00000100000000Z", false, time.Time{}},
+ {"20101302030405Z", false, time.Time{}},
+ {"20100002030405Z", false, time.Time{}},
+ {"20100100030405Z", false, time.Time{}},
+ {"20100132030405Z", false, time.Time{}},
+ {"20100231030405Z", false, time.Time{}},
+ {"20100102240405Z", false, time.Time{}},
+ {"20100102036005Z", false, time.Time{}},
+ {"20100102030460Z", false, time.Time{}},
+ {"-20100102030410Z", false, time.Time{}},
+ {"2010-0102030410Z", false, time.Time{}},
+ {"2010-0002030410Z", false, time.Time{}},
+ {"201001-02030410Z", false, time.Time{}},
+ {"20100102-030410Z", false, time.Time{}},
+ {"2010010203-0410Z", false, time.Time{}},
+ {"201001020304-10Z", false, time.Time{}},
+ }
+ for i, test := range testData {
+ in := String(append([]byte{byte(asn1.GeneralizedTime), byte(len(test.in))}, test.in...))
+ var out time.Time
+ ok := in.ReadASN1GeneralizedTime(&out)
+ if ok != test.ok || ok && !reflect.DeepEqual(out, test.out) {
+ t.Errorf("#%d: in.ReadASN1GeneralizedTime() = %v, want %v; out = %q, want %q", i, ok, test.ok, out, test.out)
+ }
+ }
+}
+
+func TestReadASN1BitString(t *testing.T) {
+ testData := []struct {
+ in []byte
+ ok bool
+ out encoding_asn1.BitString
+ }{
+ {[]byte{}, false, encoding_asn1.BitString{}},
+ {[]byte{0x00}, true, encoding_asn1.BitString{}},
+ {[]byte{0x07, 0x00}, true, encoding_asn1.BitString{Bytes: []byte{0}, BitLength: 1}},
+ {[]byte{0x07, 0x01}, false, encoding_asn1.BitString{}},
+ {[]byte{0x07, 0x40}, false, encoding_asn1.BitString{}},
+ {[]byte{0x08, 0x00}, false, encoding_asn1.BitString{}},
+ {[]byte{0xff}, false, encoding_asn1.BitString{}},
+ {[]byte{0xfe, 0x00}, false, encoding_asn1.BitString{}},
+ }
+ for i, test := range testData {
+ in := String(append([]byte{3, byte(len(test.in))}, test.in...))
+ var out encoding_asn1.BitString
+ ok := in.ReadASN1BitString(&out)
+ if ok != test.ok || ok && (!bytes.Equal(out.Bytes, test.out.Bytes) || out.BitLength != test.out.BitLength) {
+ t.Errorf("#%d: in.ReadASN1BitString() = %v, want %v; out = %v, want %v", i, ok, test.ok, out, test.out)
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/cryptobyte/builder.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/cryptobyte/builder.go
new file mode 100644
index 000000000..29b4c7641
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/cryptobyte/builder.go
@@ -0,0 +1,309 @@
+// 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 cryptobyte
+
+import (
+ "errors"
+ "fmt"
+)
+
+// A Builder builds byte strings from fixed-length and length-prefixed values.
+// Builders either allocate space as needed, or are ‘fixed’, which means that
+// they write into a given buffer and produce an error if it's exhausted.
+//
+// The zero value is a usable Builder that allocates space as needed.
+//
+// Simple values are marshaled and appended to a Builder using methods on the
+// Builder. Length-prefixed values are marshaled by providing a
+// BuilderContinuation, which is a function that writes the inner contents of
+// the value to a given Builder. See the documentation for BuilderContinuation
+// for details.
+type Builder struct {
+ err error
+ result []byte
+ fixedSize bool
+ child *Builder
+ offset int
+ pendingLenLen int
+ pendingIsASN1 bool
+ inContinuation *bool
+}
+
+// NewBuilder creates a Builder that appends its output to the given buffer.
+// Like append(), the slice will be reallocated if its capacity is exceeded.
+// Use Bytes to get the final buffer.
+func NewBuilder(buffer []byte) *Builder {
+ return &Builder{
+ result: buffer,
+ }
+}
+
+// NewFixedBuilder creates a Builder that appends its output into the given
+// buffer. This builder does not reallocate the output buffer. Writes that
+// would exceed the buffer's capacity are treated as an error.
+func NewFixedBuilder(buffer []byte) *Builder {
+ return &Builder{
+ result: buffer,
+ fixedSize: true,
+ }
+}
+
+// Bytes returns the bytes written by the builder or an error if one has
+// occurred during during building.
+func (b *Builder) Bytes() ([]byte, error) {
+ if b.err != nil {
+ return nil, b.err
+ }
+ return b.result[b.offset:], nil
+}
+
+// BytesOrPanic returns the bytes written by the builder or panics if an error
+// has occurred during building.
+func (b *Builder) BytesOrPanic() []byte {
+ if b.err != nil {
+ panic(b.err)
+ }
+ return b.result[b.offset:]
+}
+
+// AddUint8 appends an 8-bit value to the byte string.
+func (b *Builder) AddUint8(v uint8) {
+ b.add(byte(v))
+}
+
+// AddUint16 appends a big-endian, 16-bit value to the byte string.
+func (b *Builder) AddUint16(v uint16) {
+ b.add(byte(v>>8), byte(v))
+}
+
+// AddUint24 appends a big-endian, 24-bit value to the byte string. The highest
+// byte of the 32-bit input value is silently truncated.
+func (b *Builder) AddUint24(v uint32) {
+ b.add(byte(v>>16), byte(v>>8), byte(v))
+}
+
+// AddUint32 appends a big-endian, 32-bit value to the byte string.
+func (b *Builder) AddUint32(v uint32) {
+ b.add(byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
+}
+
+// AddBytes appends a sequence of bytes to the byte string.
+func (b *Builder) AddBytes(v []byte) {
+ b.add(v...)
+}
+
+// BuilderContinuation is continuation-passing interface for building
+// length-prefixed byte sequences. Builder methods for length-prefixed
+// sequences (AddUint8LengthPrefixed etc) will invoke the BuilderContinuation
+// supplied to them. The child builder passed to the continuation can be used
+// to build the content of the length-prefixed sequence. For example:
+//
+// parent := cryptobyte.NewBuilder()
+// parent.AddUint8LengthPrefixed(func (child *Builder) {
+// child.AddUint8(42)
+// child.AddUint8LengthPrefixed(func (grandchild *Builder) {
+// grandchild.AddUint8(5)
+// })
+// })
+//
+// It is an error to write more bytes to the child than allowed by the reserved
+// length prefix. After the continuation returns, the child must be considered
+// invalid, i.e. users must not store any copies or references of the child
+// that outlive the continuation.
+//
+// If the continuation panics with a value of type BuildError then the inner
+// error will be returned as the error from Bytes. If the child panics
+// otherwise then Bytes will repanic with the same value.
+type BuilderContinuation func(child *Builder)
+
+// BuildError wraps an error. If a BuilderContinuation panics with this value,
+// the panic will be recovered and the inner error will be returned from
+// Builder.Bytes.
+type BuildError struct {
+ Err error
+}
+
+// AddUint8LengthPrefixed adds a 8-bit length-prefixed byte sequence.
+func (b *Builder) AddUint8LengthPrefixed(f BuilderContinuation) {
+ b.addLengthPrefixed(1, false, f)
+}
+
+// AddUint16LengthPrefixed adds a big-endian, 16-bit length-prefixed byte sequence.
+func (b *Builder) AddUint16LengthPrefixed(f BuilderContinuation) {
+ b.addLengthPrefixed(2, false, f)
+}
+
+// AddUint24LengthPrefixed adds a big-endian, 24-bit length-prefixed byte sequence.
+func (b *Builder) AddUint24LengthPrefixed(f BuilderContinuation) {
+ b.addLengthPrefixed(3, false, f)
+}
+
+// AddUint32LengthPrefixed adds a big-endian, 32-bit length-prefixed byte sequence.
+func (b *Builder) AddUint32LengthPrefixed(f BuilderContinuation) {
+ b.addLengthPrefixed(4, false, f)
+}
+
+func (b *Builder) callContinuation(f BuilderContinuation, arg *Builder) {
+ if !*b.inContinuation {
+ *b.inContinuation = true
+
+ defer func() {
+ *b.inContinuation = false
+
+ r := recover()
+ if r == nil {
+ return
+ }
+
+ if buildError, ok := r.(BuildError); ok {
+ b.err = buildError.Err
+ } else {
+ panic(r)
+ }
+ }()
+ }
+
+ f(arg)
+}
+
+func (b *Builder) addLengthPrefixed(lenLen int, isASN1 bool, f BuilderContinuation) {
+ // Subsequent writes can be ignored if the builder has encountered an error.
+ if b.err != nil {
+ return
+ }
+
+ offset := len(b.result)
+ b.add(make([]byte, lenLen)...)
+
+ if b.inContinuation == nil {
+ b.inContinuation = new(bool)
+ }
+
+ b.child = &Builder{
+ result: b.result,
+ fixedSize: b.fixedSize,
+ offset: offset,
+ pendingLenLen: lenLen,
+ pendingIsASN1: isASN1,
+ inContinuation: b.inContinuation,
+ }
+
+ b.callContinuation(f, b.child)
+ b.flushChild()
+ if b.child != nil {
+ panic("cryptobyte: internal error")
+ }
+}
+
+func (b *Builder) flushChild() {
+ if b.child == nil {
+ return
+ }
+ b.child.flushChild()
+ child := b.child
+ b.child = nil
+
+ if child.err != nil {
+ b.err = child.err
+ return
+ }
+
+ length := len(child.result) - child.pendingLenLen - child.offset
+
+ if length < 0 {
+ panic("cryptobyte: internal error") // result unexpectedly shrunk
+ }
+
+ if child.pendingIsASN1 {
+ // For ASN.1, we reserved a single byte for the length. If that turned out
+ // to be incorrect, we have to move the contents along in order to make
+ // space.
+ if child.pendingLenLen != 1 {
+ panic("cryptobyte: internal error")
+ }
+ var lenLen, lenByte uint8
+ if int64(length) > 0xfffffffe {
+ b.err = errors.New("pending ASN.1 child too long")
+ return
+ } else if length > 0xffffff {
+ lenLen = 5
+ lenByte = 0x80 | 4
+ } else if length > 0xffff {
+ lenLen = 4
+ lenByte = 0x80 | 3
+ } else if length > 0xff {
+ lenLen = 3
+ lenByte = 0x80 | 2
+ } else if length > 0x7f {
+ lenLen = 2
+ lenByte = 0x80 | 1
+ } else {
+ lenLen = 1
+ lenByte = uint8(length)
+ length = 0
+ }
+
+ // Insert the initial length byte, make space for successive length bytes,
+ // and adjust the offset.
+ child.result[child.offset] = lenByte
+ extraBytes := int(lenLen - 1)
+ if extraBytes != 0 {
+ child.add(make([]byte, extraBytes)...)
+ childStart := child.offset + child.pendingLenLen
+ copy(child.result[childStart+extraBytes:], child.result[childStart:])
+ }
+ child.offset++
+ child.pendingLenLen = extraBytes
+ }
+
+ l := length
+ for i := child.pendingLenLen - 1; i >= 0; i-- {
+ child.result[child.offset+i] = uint8(l)
+ l >>= 8
+ }
+ if l != 0 {
+ b.err = fmt.Errorf("cryptobyte: pending child length %d exceeds %d-byte length prefix", length, child.pendingLenLen)
+ return
+ }
+
+ if !b.fixedSize {
+ b.result = child.result // In case child reallocated result.
+ }
+}
+
+func (b *Builder) add(bytes ...byte) {
+ if b.err != nil {
+ return
+ }
+ if b.child != nil {
+ panic("attempted write while child is pending")
+ }
+ if len(b.result)+len(bytes) < len(bytes) {
+ b.err = errors.New("cryptobyte: length overflow")
+ }
+ if b.fixedSize && len(b.result)+len(bytes) > cap(b.result) {
+ b.err = errors.New("cryptobyte: Builder is exceeding its fixed-size buffer")
+ return
+ }
+ b.result = append(b.result, bytes...)
+}
+
+// A MarshalingValue marshals itself into a Builder.
+type MarshalingValue interface {
+ // Marshal is called by Builder.AddValue. It receives a pointer to a builder
+ // to marshal itself into. It may return an error that occurred during
+ // marshaling, such as unset or invalid values.
+ Marshal(b *Builder) error
+}
+
+// AddValue calls Marshal on v, passing a pointer to the builder to append to.
+// If Marshal returns an error, it is set on the Builder so that subsequent
+// appends don't have an effect.
+func (b *Builder) AddValue(v MarshalingValue) {
+ err := v.Marshal(b)
+ if err != nil {
+ b.err = err
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/cryptobyte/cryptobyte_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/cryptobyte/cryptobyte_test.go
new file mode 100644
index 000000000..f294dd552
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/cryptobyte/cryptobyte_test.go
@@ -0,0 +1,428 @@
+// 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 cryptobyte
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "testing"
+)
+
+func builderBytesEq(b *Builder, want ...byte) error {
+ got := b.BytesOrPanic()
+ if !bytes.Equal(got, want) {
+ return fmt.Errorf("Bytes() = %v, want %v", got, want)
+ }
+ return nil
+}
+
+func TestContinuationError(t *testing.T) {
+ const errorStr = "TestContinuationError"
+ var b Builder
+ b.AddUint8LengthPrefixed(func(b *Builder) {
+ b.AddUint8(1)
+ panic(BuildError{Err: errors.New(errorStr)})
+ })
+
+ ret, err := b.Bytes()
+ if ret != nil {
+ t.Error("expected nil result")
+ }
+ if err == nil {
+ t.Fatal("unexpected nil error")
+ }
+ if s := err.Error(); s != errorStr {
+ t.Errorf("expected error %q, got %v", errorStr, s)
+ }
+}
+
+func TestContinuationNonError(t *testing.T) {
+ defer func() {
+ recover()
+ }()
+
+ var b Builder
+ b.AddUint8LengthPrefixed(func(b *Builder) {
+ b.AddUint8(1)
+ panic(1)
+ })
+
+ t.Error("Builder did not panic")
+}
+
+func TestGeneratedPanic(t *testing.T) {
+ defer func() {
+ recover()
+ }()
+
+ var b Builder
+ b.AddUint8LengthPrefixed(func(b *Builder) {
+ var p *byte
+ *p = 0
+ })
+
+ t.Error("Builder did not panic")
+}
+
+func TestBytes(t *testing.T) {
+ var b Builder
+ v := []byte("foobarbaz")
+ b.AddBytes(v[0:3])
+ b.AddBytes(v[3:4])
+ b.AddBytes(v[4:9])
+ if err := builderBytesEq(&b, v...); err != nil {
+ t.Error(err)
+ }
+ s := String(b.BytesOrPanic())
+ for _, w := range []string{"foo", "bar", "baz"} {
+ var got []byte
+ if !s.ReadBytes(&got, 3) {
+ t.Errorf("ReadBytes() = false, want true (w = %v)", w)
+ }
+ want := []byte(w)
+ if !bytes.Equal(got, want) {
+ t.Errorf("ReadBytes(): got = %v, want %v", got, want)
+ }
+ }
+ if len(s) != 0 {
+ t.Errorf("len(s) = %d, want 0", len(s))
+ }
+}
+
+func TestUint8(t *testing.T) {
+ var b Builder
+ b.AddUint8(42)
+ if err := builderBytesEq(&b, 42); err != nil {
+ t.Error(err)
+ }
+
+ var s String = b.BytesOrPanic()
+ var v uint8
+ if !s.ReadUint8(&v) {
+ t.Error("ReadUint8() = false, want true")
+ }
+ if v != 42 {
+ t.Errorf("v = %d, want 42", v)
+ }
+ if len(s) != 0 {
+ t.Errorf("len(s) = %d, want 0", len(s))
+ }
+}
+
+func TestUint16(t *testing.T) {
+ var b Builder
+ b.AddUint16(65534)
+ if err := builderBytesEq(&b, 255, 254); err != nil {
+ t.Error(err)
+ }
+ var s String = b.BytesOrPanic()
+ var v uint16
+ if !s.ReadUint16(&v) {
+ t.Error("ReadUint16() == false, want true")
+ }
+ if v != 65534 {
+ t.Errorf("v = %d, want 65534", v)
+ }
+ if len(s) != 0 {
+ t.Errorf("len(s) = %d, want 0", len(s))
+ }
+}
+
+func TestUint24(t *testing.T) {
+ var b Builder
+ b.AddUint24(0xfffefd)
+ if err := builderBytesEq(&b, 255, 254, 253); err != nil {
+ t.Error(err)
+ }
+
+ var s String = b.BytesOrPanic()
+ var v uint32
+ if !s.ReadUint24(&v) {
+ t.Error("ReadUint8() = false, want true")
+ }
+ if v != 0xfffefd {
+ t.Errorf("v = %d, want fffefd", v)
+ }
+ if len(s) != 0 {
+ t.Errorf("len(s) = %d, want 0", len(s))
+ }
+}
+
+func TestUint24Truncation(t *testing.T) {
+ var b Builder
+ b.AddUint24(0x10111213)
+ if err := builderBytesEq(&b, 0x11, 0x12, 0x13); err != nil {
+ t.Error(err)
+ }
+}
+
+func TestUint32(t *testing.T) {
+ var b Builder
+ b.AddUint32(0xfffefdfc)
+ if err := builderBytesEq(&b, 255, 254, 253, 252); err != nil {
+ t.Error(err)
+ }
+
+ var s String = b.BytesOrPanic()
+ var v uint32
+ if !s.ReadUint32(&v) {
+ t.Error("ReadUint8() = false, want true")
+ }
+ if v != 0xfffefdfc {
+ t.Errorf("v = %x, want fffefdfc", v)
+ }
+ if len(s) != 0 {
+ t.Errorf("len(s) = %d, want 0", len(s))
+ }
+}
+
+func TestUMultiple(t *testing.T) {
+ var b Builder
+ b.AddUint8(23)
+ b.AddUint32(0xfffefdfc)
+ b.AddUint16(42)
+ if err := builderBytesEq(&b, 23, 255, 254, 253, 252, 0, 42); err != nil {
+ t.Error(err)
+ }
+
+ var s String = b.BytesOrPanic()
+ var (
+ x uint8
+ y uint32
+ z uint16
+ )
+ if !s.ReadUint8(&x) || !s.ReadUint32(&y) || !s.ReadUint16(&z) {
+ t.Error("ReadUint8() = false, want true")
+ }
+ if x != 23 || y != 0xfffefdfc || z != 42 {
+ t.Errorf("x, y, z = %d, %d, %d; want 23, 4294901244, 5", x, y, z)
+ }
+ if len(s) != 0 {
+ t.Errorf("len(s) = %d, want 0", len(s))
+ }
+}
+
+func TestUint8LengthPrefixedSimple(t *testing.T) {
+ var b Builder
+ b.AddUint8LengthPrefixed(func(c *Builder) {
+ c.AddUint8(23)
+ c.AddUint8(42)
+ })
+ if err := builderBytesEq(&b, 2, 23, 42); err != nil {
+ t.Error(err)
+ }
+
+ var base, child String = b.BytesOrPanic(), nil
+ var x, y uint8
+ if !base.ReadUint8LengthPrefixed(&child) || !child.ReadUint8(&x) ||
+ !child.ReadUint8(&y) {
+ t.Error("parsing failed")
+ }
+ if x != 23 || y != 42 {
+ t.Errorf("want x, y == 23, 42; got %d, %d", x, y)
+ }
+ if len(base) != 0 {
+ t.Errorf("len(base) = %d, want 0", len(base))
+ }
+ if len(child) != 0 {
+ t.Errorf("len(child) = %d, want 0", len(child))
+ }
+}
+
+func TestUint8LengthPrefixedMulti(t *testing.T) {
+ var b Builder
+ b.AddUint8LengthPrefixed(func(c *Builder) {
+ c.AddUint8(23)
+ c.AddUint8(42)
+ })
+ b.AddUint8(5)
+ b.AddUint8LengthPrefixed(func(c *Builder) {
+ c.AddUint8(123)
+ c.AddUint8(234)
+ })
+ if err := builderBytesEq(&b, 2, 23, 42, 5, 2, 123, 234); err != nil {
+ t.Error(err)
+ }
+
+ var s, child String = b.BytesOrPanic(), nil
+ var u, v, w, x, y uint8
+ if !s.ReadUint8LengthPrefixed(&child) || !child.ReadUint8(&u) || !child.ReadUint8(&v) ||
+ !s.ReadUint8(&w) || !s.ReadUint8LengthPrefixed(&child) || !child.ReadUint8(&x) || !child.ReadUint8(&y) {
+ t.Error("parsing failed")
+ }
+ if u != 23 || v != 42 || w != 5 || x != 123 || y != 234 {
+ t.Errorf("u, v, w, x, y = %d, %d, %d, %d, %d; want 23, 42, 5, 123, 234",
+ u, v, w, x, y)
+ }
+ if len(s) != 0 {
+ t.Errorf("len(s) = %d, want 0", len(s))
+ }
+ if len(child) != 0 {
+ t.Errorf("len(child) = %d, want 0", len(child))
+ }
+}
+
+func TestUint8LengthPrefixedNested(t *testing.T) {
+ var b Builder
+ b.AddUint8LengthPrefixed(func(c *Builder) {
+ c.AddUint8(5)
+ c.AddUint8LengthPrefixed(func(d *Builder) {
+ d.AddUint8(23)
+ d.AddUint8(42)
+ })
+ c.AddUint8(123)
+ })
+ if err := builderBytesEq(&b, 5, 5, 2, 23, 42, 123); err != nil {
+ t.Error(err)
+ }
+
+ var base, child1, child2 String = b.BytesOrPanic(), nil, nil
+ var u, v, w, x uint8
+ if !base.ReadUint8LengthPrefixed(&child1) {
+ t.Error("parsing base failed")
+ }
+ if !child1.ReadUint8(&u) || !child1.ReadUint8LengthPrefixed(&child2) || !child1.ReadUint8(&x) {
+ t.Error("parsing child1 failed")
+ }
+ if !child2.ReadUint8(&v) || !child2.ReadUint8(&w) {
+ t.Error("parsing child2 failed")
+ }
+ if u != 5 || v != 23 || w != 42 || x != 123 {
+ t.Errorf("u, v, w, x = %d, %d, %d, %d, want 5, 23, 42, 123",
+ u, v, w, x)
+ }
+ if len(base) != 0 {
+ t.Errorf("len(base) = %d, want 0", len(base))
+ }
+ if len(child1) != 0 {
+ t.Errorf("len(child1) = %d, want 0", len(child1))
+ }
+ if len(base) != 0 {
+ t.Errorf("len(child2) = %d, want 0", len(child2))
+ }
+}
+
+func TestPreallocatedBuffer(t *testing.T) {
+ var buf [5]byte
+ b := NewBuilder(buf[0:0])
+ b.AddUint8(1)
+ b.AddUint8LengthPrefixed(func(c *Builder) {
+ c.AddUint8(3)
+ c.AddUint8(4)
+ })
+ b.AddUint16(1286) // Outgrow buf by one byte.
+ want := []byte{1, 2, 3, 4, 0}
+ if !bytes.Equal(buf[:], want) {
+ t.Errorf("buf = %v want %v", buf, want)
+ }
+ if err := builderBytesEq(b, 1, 2, 3, 4, 5, 6); err != nil {
+ t.Error(err)
+ }
+}
+
+func TestWriteWithPendingChild(t *testing.T) {
+ var b Builder
+ b.AddUint8LengthPrefixed(func(c *Builder) {
+ c.AddUint8LengthPrefixed(func(d *Builder) {
+ defer func() {
+ if recover() == nil {
+ t.Errorf("recover() = nil, want error; c.AddUint8() did not panic")
+ }
+ }()
+ c.AddUint8(2) // panics
+
+ defer func() {
+ if recover() == nil {
+ t.Errorf("recover() = nil, want error; b.AddUint8() did not panic")
+ }
+ }()
+ b.AddUint8(2) // panics
+ })
+
+ defer func() {
+ if recover() == nil {
+ t.Errorf("recover() = nil, want error; b.AddUint8() did not panic")
+ }
+ }()
+ b.AddUint8(2) // panics
+ })
+}
+
+// ASN.1
+
+func TestASN1Int64(t *testing.T) {
+ tests := []struct {
+ in int64
+ want []byte
+ }{
+ {-0x800000, []byte{2, 3, 128, 0, 0}},
+ {-256, []byte{2, 2, 255, 0}},
+ {-129, []byte{2, 2, 255, 127}},
+ {-128, []byte{2, 1, 128}},
+ {-1, []byte{2, 1, 255}},
+ {0, []byte{2, 1, 0}},
+ {1, []byte{2, 1, 1}},
+ {2, []byte{2, 1, 2}},
+ {127, []byte{2, 1, 127}},
+ {128, []byte{2, 2, 0, 128}},
+ {256, []byte{2, 2, 1, 0}},
+ {0x800000, []byte{2, 4, 0, 128, 0, 0}},
+ }
+ for i, tt := range tests {
+ var b Builder
+ b.AddASN1Int64(tt.in)
+ if err := builderBytesEq(&b, tt.want...); err != nil {
+ t.Errorf("%v, (i = %d; in = %v)", err, i, tt.in)
+ }
+
+ var n int64
+ s := String(b.BytesOrPanic())
+ ok := s.ReadASN1Integer(&n)
+ if !ok || n != tt.in {
+ t.Errorf("s.ReadASN1Integer(&n) = %v, n = %d; want true, n = %d (i = %d)",
+ ok, n, tt.in, i)
+ }
+ if len(s) != 0 {
+ t.Errorf("len(s) = %d, want 0", len(s))
+ }
+ }
+}
+
+func TestASN1Uint64(t *testing.T) {
+ tests := []struct {
+ in uint64
+ want []byte
+ }{
+ {0, []byte{2, 1, 0}},
+ {1, []byte{2, 1, 1}},
+ {2, []byte{2, 1, 2}},
+ {127, []byte{2, 1, 127}},
+ {128, []byte{2, 2, 0, 128}},
+ {256, []byte{2, 2, 1, 0}},
+ {0x800000, []byte{2, 4, 0, 128, 0, 0}},
+ {0x7fffffffffffffff, []byte{2, 8, 127, 255, 255, 255, 255, 255, 255, 255}},
+ {0x8000000000000000, []byte{2, 9, 0, 128, 0, 0, 0, 0, 0, 0, 0}},
+ {0xffffffffffffffff, []byte{2, 9, 0, 255, 255, 255, 255, 255, 255, 255, 255}},
+ }
+ for i, tt := range tests {
+ var b Builder
+ b.AddASN1Uint64(tt.in)
+ if err := builderBytesEq(&b, tt.want...); err != nil {
+ t.Errorf("%v, (i = %d; in = %v)", err, i, tt.in)
+ }
+
+ var n uint64
+ s := String(b.BytesOrPanic())
+ ok := s.ReadASN1Integer(&n)
+ if !ok || n != tt.in {
+ t.Errorf("s.ReadASN1Integer(&n) = %v, n = %d; want true, n = %d (i = %d)",
+ ok, n, tt.in, i)
+ }
+ if len(s) != 0 {
+ t.Errorf("len(s) = %d, want 0", len(s))
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/cryptobyte/example_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/cryptobyte/example_test.go
new file mode 100644
index 000000000..86c098adf
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/cryptobyte/example_test.go
@@ -0,0 +1,154 @@
+// 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 cryptobyte_test
+
+import (
+ "errors"
+ "fmt"
+
+ "golang.org/x/crypto/cryptobyte"
+ "golang.org/x/crypto/cryptobyte/asn1"
+)
+
+func ExampleString_lengthPrefixed() {
+ // This is an example of parsing length-prefixed data (as found in, for
+ // example, TLS). Imagine a 16-bit prefixed series of 8-bit prefixed
+ // strings.
+
+ input := cryptobyte.String([]byte{0, 12, 5, 'h', 'e', 'l', 'l', 'o', 5, 'w', 'o', 'r', 'l', 'd'})
+ var result []string
+
+ var values cryptobyte.String
+ if !input.ReadUint16LengthPrefixed(&values) ||
+ !input.Empty() {
+ panic("bad format")
+ }
+
+ for !values.Empty() {
+ var value cryptobyte.String
+ if !values.ReadUint8LengthPrefixed(&value) {
+ panic("bad format")
+ }
+
+ result = append(result, string(value))
+ }
+
+ // Output: []string{"hello", "world"}
+ fmt.Printf("%#v\n", result)
+}
+
+func ExampleString_aSN1() {
+ // This is an example of parsing ASN.1 data that looks like:
+ // Foo ::= SEQUENCE {
+ // version [6] INTEGER DEFAULT 0
+ // data OCTET STRING
+ // }
+
+ input := cryptobyte.String([]byte{0x30, 12, 0xa6, 3, 2, 1, 2, 4, 5, 'h', 'e', 'l', 'l', 'o'})
+
+ var (
+ version int64
+ data, inner, versionBytes cryptobyte.String
+ haveVersion bool
+ )
+ if !input.ReadASN1(&inner, asn1.SEQUENCE) ||
+ !input.Empty() ||
+ !inner.ReadOptionalASN1(&versionBytes, &haveVersion, asn1.Tag(6).Constructed().ContextSpecific()) ||
+ (haveVersion && !versionBytes.ReadASN1Integer(&version)) ||
+ (haveVersion && !versionBytes.Empty()) ||
+ !inner.ReadASN1(&data, asn1.OCTET_STRING) ||
+ !inner.Empty() {
+ panic("bad format")
+ }
+
+ // Output: haveVersion: true, version: 2, data: hello
+ fmt.Printf("haveVersion: %t, version: %d, data: %s\n", haveVersion, version, string(data))
+}
+
+func ExampleBuilder_aSN1() {
+ // This is an example of building ASN.1 data that looks like:
+ // Foo ::= SEQUENCE {
+ // version [6] INTEGER DEFAULT 0
+ // data OCTET STRING
+ // }
+
+ version := int64(2)
+ data := []byte("hello")
+ const defaultVersion = 0
+
+ var b cryptobyte.Builder
+ b.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) {
+ if version != defaultVersion {
+ b.AddASN1(asn1.Tag(6).Constructed().ContextSpecific(), func(b *cryptobyte.Builder) {
+ b.AddASN1Int64(version)
+ })
+ }
+ b.AddASN1OctetString(data)
+ })
+
+ result, err := b.Bytes()
+ if err != nil {
+ panic(err)
+ }
+
+ // Output: 300ca603020102040568656c6c6f
+ fmt.Printf("%x\n", result)
+}
+
+func ExampleBuilder_lengthPrefixed() {
+ // This is an example of building length-prefixed data (as found in,
+ // for example, TLS). Imagine a 16-bit prefixed series of 8-bit
+ // prefixed strings.
+ input := []string{"hello", "world"}
+
+ var b cryptobyte.Builder
+ b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
+ for _, value := range input {
+ b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) {
+ b.AddBytes([]byte(value))
+ })
+ }
+ })
+
+ result, err := b.Bytes()
+ if err != nil {
+ panic(err)
+ }
+
+ // Output: 000c0568656c6c6f05776f726c64
+ fmt.Printf("%x\n", result)
+}
+
+func ExampleBuilder_lengthPrefixOverflow() {
+ // Writing more data that can be expressed by the length prefix results
+ // in an error from Bytes().
+
+ tooLarge := make([]byte, 256)
+
+ var b cryptobyte.Builder
+ b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) {
+ b.AddBytes(tooLarge)
+ })
+
+ result, err := b.Bytes()
+ fmt.Printf("len=%d err=%s\n", len(result), err)
+
+ // Output: len=0 err=cryptobyte: pending child length 256 exceeds 1-byte length prefix
+}
+
+func ExampleBuilderContinuation_errorHandling() {
+ var b cryptobyte.Builder
+ // Continuations that panic with a BuildError will cause Bytes to
+ // return the inner error.
+ b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
+ b.AddUint32(0)
+ panic(cryptobyte.BuildError{Err: errors.New("example error")})
+ })
+
+ result, err := b.Bytes()
+ fmt.Printf("len=%d err=%s\n", len(result), err)
+
+ // Output: len=0 err=example error
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/cryptobyte/string.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/cryptobyte/string.go
new file mode 100644
index 000000000..7636fb9c8
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/cryptobyte/string.go
@@ -0,0 +1,167 @@
+// 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 cryptobyte contains types that help with parsing and constructing
+// length-prefixed, binary messages, including ASN.1 DER. (The asn1 subpackage
+// contains useful ASN.1 constants.)
+//
+// The String type is for parsing. It wraps a []byte slice and provides helper
+// functions for consuming structures, value by value.
+//
+// The Builder type is for constructing messages. It providers helper functions
+// for appending values and also for appending length-prefixed submessages –
+// without having to worry about calculating the length prefix ahead of time.
+//
+// See the documentation and examples for the Builder and String types to get
+// started.
+package cryptobyte // import "golang.org/x/crypto/cryptobyte"
+
+// String represents a string of bytes. It provides methods for parsing
+// fixed-length and length-prefixed values from it.
+type String []byte
+
+// read advances a String by n bytes and returns them. If less than n bytes
+// remain, it returns nil.
+func (s *String) read(n int) []byte {
+ if len(*s) < n {
+ return nil
+ }
+ v := (*s)[:n]
+ *s = (*s)[n:]
+ return v
+}
+
+// Skip advances the String by n byte and reports whether it was successful.
+func (s *String) Skip(n int) bool {
+ return s.read(n) != nil
+}
+
+// ReadUint8 decodes an 8-bit value into out and advances over it. It
+// returns true on success and false on error.
+func (s *String) ReadUint8(out *uint8) bool {
+ v := s.read(1)
+ if v == nil {
+ return false
+ }
+ *out = uint8(v[0])
+ return true
+}
+
+// ReadUint16 decodes a big-endian, 16-bit value into out and advances over it.
+// It returns true on success and false on error.
+func (s *String) ReadUint16(out *uint16) bool {
+ v := s.read(2)
+ if v == nil {
+ return false
+ }
+ *out = uint16(v[0])<<8 | uint16(v[1])
+ return true
+}
+
+// ReadUint24 decodes a big-endian, 24-bit value into out and advances over it.
+// It returns true on success and false on error.
+func (s *String) ReadUint24(out *uint32) bool {
+ v := s.read(3)
+ if v == nil {
+ return false
+ }
+ *out = uint32(v[0])<<16 | uint32(v[1])<<8 | uint32(v[2])
+ return true
+}
+
+// ReadUint32 decodes a big-endian, 32-bit value into out and advances over it.
+// It returns true on success and false on error.
+func (s *String) ReadUint32(out *uint32) bool {
+ v := s.read(4)
+ if v == nil {
+ return false
+ }
+ *out = uint32(v[0])<<24 | uint32(v[1])<<16 | uint32(v[2])<<8 | uint32(v[3])
+ return true
+}
+
+func (s *String) readUnsigned(out *uint32, length int) bool {
+ v := s.read(length)
+ if v == nil {
+ return false
+ }
+ var result uint32
+ for i := 0; i < length; i++ {
+ result <<= 8
+ result |= uint32(v[i])
+ }
+ *out = result
+ return true
+}
+
+func (s *String) readLengthPrefixed(lenLen int, outChild *String) bool {
+ lenBytes := s.read(lenLen)
+ if lenBytes == nil {
+ return false
+ }
+ var length uint32
+ for _, b := range lenBytes {
+ length = length << 8
+ length = length | uint32(b)
+ }
+ if int(length) < 0 {
+ // This currently cannot overflow because we read uint24 at most, but check
+ // anyway in case that changes in the future.
+ return false
+ }
+ v := s.read(int(length))
+ if v == nil {
+ return false
+ }
+ *outChild = v
+ return true
+}
+
+// ReadUint8LengthPrefixed reads the content of an 8-bit length-prefixed value
+// into out and advances over it. It returns true on success and false on
+// error.
+func (s *String) ReadUint8LengthPrefixed(out *String) bool {
+ return s.readLengthPrefixed(1, out)
+}
+
+// ReadUint16LengthPrefixed reads the content of a big-endian, 16-bit
+// length-prefixed value into out and advances over it. It returns true on
+// success and false on error.
+func (s *String) ReadUint16LengthPrefixed(out *String) bool {
+ return s.readLengthPrefixed(2, out)
+}
+
+// ReadUint24LengthPrefixed reads the content of a big-endian, 24-bit
+// length-prefixed value into out and advances over it. It returns true on
+// success and false on error.
+func (s *String) ReadUint24LengthPrefixed(out *String) bool {
+ return s.readLengthPrefixed(3, out)
+}
+
+// ReadBytes reads n bytes into out and advances over them. It returns true on
+// success and false and error.
+func (s *String) ReadBytes(out *[]byte, n int) bool {
+ v := s.read(n)
+ if v == nil {
+ return false
+ }
+ *out = v
+ return true
+}
+
+// CopyBytes copies len(out) bytes into out and advances over them. It returns
+// true on success and false on error.
+func (s *String) CopyBytes(out []byte) bool {
+ n := len(out)
+ v := s.read(n)
+ if v == nil {
+ return false
+ }
+ return copy(out, v) == n
+}
+
+// Empty reports whether the string does not contain any bytes.
+func (s String) Empty() bool {
+ return len(s) == 0
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/curve25519/const_amd64.h b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/curve25519/const_amd64.h
new file mode 100644
index 000000000..b3f74162f
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/curve25519/const_amd64.h
@@ -0,0 +1,8 @@
+// Copyright 2012 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.
+
+// This code was translated into a form compatible with 6a from the public
+// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html
+
+#define REDMASK51 0x0007FFFFFFFFFFFF
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/curve25519/const_amd64.s b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/curve25519/const_amd64.s
new file mode 100644
index 000000000..ee7b4bd5f
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/curve25519/const_amd64.s
@@ -0,0 +1,20 @@
+// Copyright 2012 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.
+
+// This code was translated into a form compatible with 6a from the public
+// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html
+
+// +build amd64,!gccgo,!appengine
+
+// These constants cannot be encoded in non-MOVQ immediates.
+// We access them directly from memory instead.
+
+DATA ·_121666_213(SB)/8, $996687872
+GLOBL ·_121666_213(SB), 8, $8
+
+DATA ·_2P0(SB)/8, $0xFFFFFFFFFFFDA
+GLOBL ·_2P0(SB), 8, $8
+
+DATA ·_2P1234(SB)/8, $0xFFFFFFFFFFFFE
+GLOBL ·_2P1234(SB), 8, $8
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/curve25519/cswap_amd64.s b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/curve25519/cswap_amd64.s
new file mode 100644
index 000000000..cd793a5b5
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/curve25519/cswap_amd64.s
@@ -0,0 +1,65 @@
+// Copyright 2012 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.
+
+// +build amd64,!gccgo,!appengine
+
+// func cswap(inout *[4][5]uint64, v uint64)
+TEXT ·cswap(SB),7,$0
+ MOVQ inout+0(FP),DI
+ MOVQ v+8(FP),SI
+
+ SUBQ $1, SI
+ NOTQ SI
+ MOVQ SI, X15
+ PSHUFD $0x44, X15, X15
+
+ MOVOU 0(DI), X0
+ MOVOU 16(DI), X2
+ MOVOU 32(DI), X4
+ MOVOU 48(DI), X6
+ MOVOU 64(DI), X8
+ MOVOU 80(DI), X1
+ MOVOU 96(DI), X3
+ MOVOU 112(DI), X5
+ MOVOU 128(DI), X7
+ MOVOU 144(DI), X9
+
+ MOVO X1, X10
+ MOVO X3, X11
+ MOVO X5, X12
+ MOVO X7, X13
+ MOVO X9, X14
+
+ PXOR X0, X10
+ PXOR X2, X11
+ PXOR X4, X12
+ PXOR X6, X13
+ PXOR X8, X14
+ PAND X15, X10
+ PAND X15, X11
+ PAND X15, X12
+ PAND X15, X13
+ PAND X15, X14
+ PXOR X10, X0
+ PXOR X10, X1
+ PXOR X11, X2
+ PXOR X11, X3
+ PXOR X12, X4
+ PXOR X12, X5
+ PXOR X13, X6
+ PXOR X13, X7
+ PXOR X14, X8
+ PXOR X14, X9
+
+ MOVOU X0, 0(DI)
+ MOVOU X2, 16(DI)
+ MOVOU X4, 32(DI)
+ MOVOU X6, 48(DI)
+ MOVOU X8, 64(DI)
+ MOVOU X1, 80(DI)
+ MOVOU X3, 96(DI)
+ MOVOU X5, 112(DI)
+ MOVOU X7, 128(DI)
+ MOVOU X9, 144(DI)
+ RET
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/curve25519/curve25519.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/curve25519/curve25519.go
new file mode 100644
index 000000000..cb8fbc57b
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/curve25519/curve25519.go
@@ -0,0 +1,834 @@
+// Copyright 2013 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.
+
+// We have an implementation in amd64 assembly so this code is only run on
+// non-amd64 platforms. The amd64 assembly does not support gccgo.
+// +build !amd64 gccgo appengine
+
+package curve25519
+
+import (
+ "encoding/binary"
+)
+
+// This code is a port of the public domain, "ref10" implementation of
+// curve25519 from SUPERCOP 20130419 by D. J. Bernstein.
+
+// fieldElement represents an element of the field GF(2^255 - 19). An element
+// t, entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77
+// t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on
+// context.
+type fieldElement [10]int32
+
+func feZero(fe *fieldElement) {
+ for i := range fe {
+ fe[i] = 0
+ }
+}
+
+func feOne(fe *fieldElement) {
+ feZero(fe)
+ fe[0] = 1
+}
+
+func feAdd(dst, a, b *fieldElement) {
+ for i := range dst {
+ dst[i] = a[i] + b[i]
+ }
+}
+
+func feSub(dst, a, b *fieldElement) {
+ for i := range dst {
+ dst[i] = a[i] - b[i]
+ }
+}
+
+func feCopy(dst, src *fieldElement) {
+ for i := range dst {
+ dst[i] = src[i]
+ }
+}
+
+// feCSwap replaces (f,g) with (g,f) if b == 1; replaces (f,g) with (f,g) if b == 0.
+//
+// Preconditions: b in {0,1}.
+func feCSwap(f, g *fieldElement, b int32) {
+ b = -b
+ for i := range f {
+ t := b & (f[i] ^ g[i])
+ f[i] ^= t
+ g[i] ^= t
+ }
+}
+
+// load3 reads a 24-bit, little-endian value from in.
+func load3(in []byte) int64 {
+ var r int64
+ r = int64(in[0])
+ r |= int64(in[1]) << 8
+ r |= int64(in[2]) << 16
+ return r
+}
+
+// load4 reads a 32-bit, little-endian value from in.
+func load4(in []byte) int64 {
+ return int64(binary.LittleEndian.Uint32(in))
+}
+
+func feFromBytes(dst *fieldElement, src *[32]byte) {
+ h0 := load4(src[:])
+ h1 := load3(src[4:]) << 6
+ h2 := load3(src[7:]) << 5
+ h3 := load3(src[10:]) << 3
+ h4 := load3(src[13:]) << 2
+ h5 := load4(src[16:])
+ h6 := load3(src[20:]) << 7
+ h7 := load3(src[23:]) << 5
+ h8 := load3(src[26:]) << 4
+ h9 := load3(src[29:]) << 2
+
+ var carry [10]int64
+ carry[9] = (h9 + 1<<24) >> 25
+ h0 += carry[9] * 19
+ h9 -= carry[9] << 25
+ carry[1] = (h1 + 1<<24) >> 25
+ h2 += carry[1]
+ h1 -= carry[1] << 25
+ carry[3] = (h3 + 1<<24) >> 25
+ h4 += carry[3]
+ h3 -= carry[3] << 25
+ carry[5] = (h5 + 1<<24) >> 25
+ h6 += carry[5]
+ h5 -= carry[5] << 25
+ carry[7] = (h7 + 1<<24) >> 25
+ h8 += carry[7]
+ h7 -= carry[7] << 25
+
+ carry[0] = (h0 + 1<<25) >> 26
+ h1 += carry[0]
+ h0 -= carry[0] << 26
+ carry[2] = (h2 + 1<<25) >> 26
+ h3 += carry[2]
+ h2 -= carry[2] << 26
+ carry[4] = (h4 + 1<<25) >> 26
+ h5 += carry[4]
+ h4 -= carry[4] << 26
+ carry[6] = (h6 + 1<<25) >> 26
+ h7 += carry[6]
+ h6 -= carry[6] << 26
+ carry[8] = (h8 + 1<<25) >> 26
+ h9 += carry[8]
+ h8 -= carry[8] << 26
+
+ dst[0] = int32(h0)
+ dst[1] = int32(h1)
+ dst[2] = int32(h2)
+ dst[3] = int32(h3)
+ dst[4] = int32(h4)
+ dst[5] = int32(h5)
+ dst[6] = int32(h6)
+ dst[7] = int32(h7)
+ dst[8] = int32(h8)
+ dst[9] = int32(h9)
+}
+
+// feToBytes marshals h to s.
+// Preconditions:
+// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+//
+// Write p=2^255-19; q=floor(h/p).
+// Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))).
+//
+// Proof:
+// Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4.
+// Also have |h-2^230 h9|<2^230 so |19 2^(-255)(h-2^230 h9)|<1/4.
+//
+// Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9).
+// Then 0<y<1.
+//
+// Write r=h-pq.
+// Have 0<=r<=p-1=2^255-20.
+// Thus 0<=r+19(2^-255)r<r+19(2^-255)2^255<=2^255-1.
+//
+// Write x=r+19(2^-255)r+y.
+// Then 0<x<2^255 so floor(2^(-255)x) = 0 so floor(q+2^(-255)x) = q.
+//
+// Have q+2^(-255)x = 2^(-255)(h + 19 2^(-25) h9 + 2^(-1))
+// so floor(2^(-255)(h + 19 2^(-25) h9 + 2^(-1))) = q.
+func feToBytes(s *[32]byte, h *fieldElement) {
+ var carry [10]int32
+
+ q := (19*h[9] + (1 << 24)) >> 25
+ q = (h[0] + q) >> 26
+ q = (h[1] + q) >> 25
+ q = (h[2] + q) >> 26
+ q = (h[3] + q) >> 25
+ q = (h[4] + q) >> 26
+ q = (h[5] + q) >> 25
+ q = (h[6] + q) >> 26
+ q = (h[7] + q) >> 25
+ q = (h[8] + q) >> 26
+ q = (h[9] + q) >> 25
+
+ // Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20.
+ h[0] += 19 * q
+ // Goal: Output h-2^255 q, which is between 0 and 2^255-20.
+
+ carry[0] = h[0] >> 26
+ h[1] += carry[0]
+ h[0] -= carry[0] << 26
+ carry[1] = h[1] >> 25
+ h[2] += carry[1]
+ h[1] -= carry[1] << 25
+ carry[2] = h[2] >> 26
+ h[3] += carry[2]
+ h[2] -= carry[2] << 26
+ carry[3] = h[3] >> 25
+ h[4] += carry[3]
+ h[3] -= carry[3] << 25
+ carry[4] = h[4] >> 26
+ h[5] += carry[4]
+ h[4] -= carry[4] << 26
+ carry[5] = h[5] >> 25
+ h[6] += carry[5]
+ h[5] -= carry[5] << 25
+ carry[6] = h[6] >> 26
+ h[7] += carry[6]
+ h[6] -= carry[6] << 26
+ carry[7] = h[7] >> 25
+ h[8] += carry[7]
+ h[7] -= carry[7] << 25
+ carry[8] = h[8] >> 26
+ h[9] += carry[8]
+ h[8] -= carry[8] << 26
+ carry[9] = h[9] >> 25
+ h[9] -= carry[9] << 25
+ // h10 = carry9
+
+ // Goal: Output h[0]+...+2^255 h10-2^255 q, which is between 0 and 2^255-20.
+ // Have h[0]+...+2^230 h[9] between 0 and 2^255-1;
+ // evidently 2^255 h10-2^255 q = 0.
+ // Goal: Output h[0]+...+2^230 h[9].
+
+ s[0] = byte(h[0] >> 0)
+ s[1] = byte(h[0] >> 8)
+ s[2] = byte(h[0] >> 16)
+ s[3] = byte((h[0] >> 24) | (h[1] << 2))
+ s[4] = byte(h[1] >> 6)
+ s[5] = byte(h[1] >> 14)
+ s[6] = byte((h[1] >> 22) | (h[2] << 3))
+ s[7] = byte(h[2] >> 5)
+ s[8] = byte(h[2] >> 13)
+ s[9] = byte((h[2] >> 21) | (h[3] << 5))
+ s[10] = byte(h[3] >> 3)
+ s[11] = byte(h[3] >> 11)
+ s[12] = byte((h[3] >> 19) | (h[4] << 6))
+ s[13] = byte(h[4] >> 2)
+ s[14] = byte(h[4] >> 10)
+ s[15] = byte(h[4] >> 18)
+ s[16] = byte(h[5] >> 0)
+ s[17] = byte(h[5] >> 8)
+ s[18] = byte(h[5] >> 16)
+ s[19] = byte((h[5] >> 24) | (h[6] << 1))
+ s[20] = byte(h[6] >> 7)
+ s[21] = byte(h[6] >> 15)
+ s[22] = byte((h[6] >> 23) | (h[7] << 3))
+ s[23] = byte(h[7] >> 5)
+ s[24] = byte(h[7] >> 13)
+ s[25] = byte((h[7] >> 21) | (h[8] << 4))
+ s[26] = byte(h[8] >> 4)
+ s[27] = byte(h[8] >> 12)
+ s[28] = byte((h[8] >> 20) | (h[9] << 6))
+ s[29] = byte(h[9] >> 2)
+ s[30] = byte(h[9] >> 10)
+ s[31] = byte(h[9] >> 18)
+}
+
+// feMul calculates h = f * g
+// Can overlap h with f or g.
+//
+// Preconditions:
+// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
+// |g| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
+//
+// Postconditions:
+// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+//
+// Notes on implementation strategy:
+//
+// Using schoolbook multiplication.
+// Karatsuba would save a little in some cost models.
+//
+// Most multiplications by 2 and 19 are 32-bit precomputations;
+// cheaper than 64-bit postcomputations.
+//
+// There is one remaining multiplication by 19 in the carry chain;
+// one *19 precomputation can be merged into this,
+// but the resulting data flow is considerably less clean.
+//
+// There are 12 carries below.
+// 10 of them are 2-way parallelizable and vectorizable.
+// Can get away with 11 carries, but then data flow is much deeper.
+//
+// With tighter constraints on inputs can squeeze carries into int32.
+func feMul(h, f, g *fieldElement) {
+ f0 := f[0]
+ f1 := f[1]
+ f2 := f[2]
+ f3 := f[3]
+ f4 := f[4]
+ f5 := f[5]
+ f6 := f[6]
+ f7 := f[7]
+ f8 := f[8]
+ f9 := f[9]
+ g0 := g[0]
+ g1 := g[1]
+ g2 := g[2]
+ g3 := g[3]
+ g4 := g[4]
+ g5 := g[5]
+ g6 := g[6]
+ g7 := g[7]
+ g8 := g[8]
+ g9 := g[9]
+ g1_19 := 19 * g1 // 1.4*2^29
+ g2_19 := 19 * g2 // 1.4*2^30; still ok
+ g3_19 := 19 * g3
+ g4_19 := 19 * g4
+ g5_19 := 19 * g5
+ g6_19 := 19 * g6
+ g7_19 := 19 * g7
+ g8_19 := 19 * g8
+ g9_19 := 19 * g9
+ f1_2 := 2 * f1
+ f3_2 := 2 * f3
+ f5_2 := 2 * f5
+ f7_2 := 2 * f7
+ f9_2 := 2 * f9
+ f0g0 := int64(f0) * int64(g0)
+ f0g1 := int64(f0) * int64(g1)
+ f0g2 := int64(f0) * int64(g2)
+ f0g3 := int64(f0) * int64(g3)
+ f0g4 := int64(f0) * int64(g4)
+ f0g5 := int64(f0) * int64(g5)
+ f0g6 := int64(f0) * int64(g6)
+ f0g7 := int64(f0) * int64(g7)
+ f0g8 := int64(f0) * int64(g8)
+ f0g9 := int64(f0) * int64(g9)
+ f1g0 := int64(f1) * int64(g0)
+ f1g1_2 := int64(f1_2) * int64(g1)
+ f1g2 := int64(f1) * int64(g2)
+ f1g3_2 := int64(f1_2) * int64(g3)
+ f1g4 := int64(f1) * int64(g4)
+ f1g5_2 := int64(f1_2) * int64(g5)
+ f1g6 := int64(f1) * int64(g6)
+ f1g7_2 := int64(f1_2) * int64(g7)
+ f1g8 := int64(f1) * int64(g8)
+ f1g9_38 := int64(f1_2) * int64(g9_19)
+ f2g0 := int64(f2) * int64(g0)
+ f2g1 := int64(f2) * int64(g1)
+ f2g2 := int64(f2) * int64(g2)
+ f2g3 := int64(f2) * int64(g3)
+ f2g4 := int64(f2) * int64(g4)
+ f2g5 := int64(f2) * int64(g5)
+ f2g6 := int64(f2) * int64(g6)
+ f2g7 := int64(f2) * int64(g7)
+ f2g8_19 := int64(f2) * int64(g8_19)
+ f2g9_19 := int64(f2) * int64(g9_19)
+ f3g0 := int64(f3) * int64(g0)
+ f3g1_2 := int64(f3_2) * int64(g1)
+ f3g2 := int64(f3) * int64(g2)
+ f3g3_2 := int64(f3_2) * int64(g3)
+ f3g4 := int64(f3) * int64(g4)
+ f3g5_2 := int64(f3_2) * int64(g5)
+ f3g6 := int64(f3) * int64(g6)
+ f3g7_38 := int64(f3_2) * int64(g7_19)
+ f3g8_19 := int64(f3) * int64(g8_19)
+ f3g9_38 := int64(f3_2) * int64(g9_19)
+ f4g0 := int64(f4) * int64(g0)
+ f4g1 := int64(f4) * int64(g1)
+ f4g2 := int64(f4) * int64(g2)
+ f4g3 := int64(f4) * int64(g3)
+ f4g4 := int64(f4) * int64(g4)
+ f4g5 := int64(f4) * int64(g5)
+ f4g6_19 := int64(f4) * int64(g6_19)
+ f4g7_19 := int64(f4) * int64(g7_19)
+ f4g8_19 := int64(f4) * int64(g8_19)
+ f4g9_19 := int64(f4) * int64(g9_19)
+ f5g0 := int64(f5) * int64(g0)
+ f5g1_2 := int64(f5_2) * int64(g1)
+ f5g2 := int64(f5) * int64(g2)
+ f5g3_2 := int64(f5_2) * int64(g3)
+ f5g4 := int64(f5) * int64(g4)
+ f5g5_38 := int64(f5_2) * int64(g5_19)
+ f5g6_19 := int64(f5) * int64(g6_19)
+ f5g7_38 := int64(f5_2) * int64(g7_19)
+ f5g8_19 := int64(f5) * int64(g8_19)
+ f5g9_38 := int64(f5_2) * int64(g9_19)
+ f6g0 := int64(f6) * int64(g0)
+ f6g1 := int64(f6) * int64(g1)
+ f6g2 := int64(f6) * int64(g2)
+ f6g3 := int64(f6) * int64(g3)
+ f6g4_19 := int64(f6) * int64(g4_19)
+ f6g5_19 := int64(f6) * int64(g5_19)
+ f6g6_19 := int64(f6) * int64(g6_19)
+ f6g7_19 := int64(f6) * int64(g7_19)
+ f6g8_19 := int64(f6) * int64(g8_19)
+ f6g9_19 := int64(f6) * int64(g9_19)
+ f7g0 := int64(f7) * int64(g0)
+ f7g1_2 := int64(f7_2) * int64(g1)
+ f7g2 := int64(f7) * int64(g2)
+ f7g3_38 := int64(f7_2) * int64(g3_19)
+ f7g4_19 := int64(f7) * int64(g4_19)
+ f7g5_38 := int64(f7_2) * int64(g5_19)
+ f7g6_19 := int64(f7) * int64(g6_19)
+ f7g7_38 := int64(f7_2) * int64(g7_19)
+ f7g8_19 := int64(f7) * int64(g8_19)
+ f7g9_38 := int64(f7_2) * int64(g9_19)
+ f8g0 := int64(f8) * int64(g0)
+ f8g1 := int64(f8) * int64(g1)
+ f8g2_19 := int64(f8) * int64(g2_19)
+ f8g3_19 := int64(f8) * int64(g3_19)
+ f8g4_19 := int64(f8) * int64(g4_19)
+ f8g5_19 := int64(f8) * int64(g5_19)
+ f8g6_19 := int64(f8) * int64(g6_19)
+ f8g7_19 := int64(f8) * int64(g7_19)
+ f8g8_19 := int64(f8) * int64(g8_19)
+ f8g9_19 := int64(f8) * int64(g9_19)
+ f9g0 := int64(f9) * int64(g0)
+ f9g1_38 := int64(f9_2) * int64(g1_19)
+ f9g2_19 := int64(f9) * int64(g2_19)
+ f9g3_38 := int64(f9_2) * int64(g3_19)
+ f9g4_19 := int64(f9) * int64(g4_19)
+ f9g5_38 := int64(f9_2) * int64(g5_19)
+ f9g6_19 := int64(f9) * int64(g6_19)
+ f9g7_38 := int64(f9_2) * int64(g7_19)
+ f9g8_19 := int64(f9) * int64(g8_19)
+ f9g9_38 := int64(f9_2) * int64(g9_19)
+ h0 := f0g0 + f1g9_38 + f2g8_19 + f3g7_38 + f4g6_19 + f5g5_38 + f6g4_19 + f7g3_38 + f8g2_19 + f9g1_38
+ h1 := f0g1 + f1g0 + f2g9_19 + f3g8_19 + f4g7_19 + f5g6_19 + f6g5_19 + f7g4_19 + f8g3_19 + f9g2_19
+ h2 := f0g2 + f1g1_2 + f2g0 + f3g9_38 + f4g8_19 + f5g7_38 + f6g6_19 + f7g5_38 + f8g4_19 + f9g3_38
+ h3 := f0g3 + f1g2 + f2g1 + f3g0 + f4g9_19 + f5g8_19 + f6g7_19 + f7g6_19 + f8g5_19 + f9g4_19
+ h4 := f0g4 + f1g3_2 + f2g2 + f3g1_2 + f4g0 + f5g9_38 + f6g8_19 + f7g7_38 + f8g6_19 + f9g5_38
+ h5 := f0g5 + f1g4 + f2g3 + f3g2 + f4g1 + f5g0 + f6g9_19 + f7g8_19 + f8g7_19 + f9g6_19
+ h6 := f0g6 + f1g5_2 + f2g4 + f3g3_2 + f4g2 + f5g1_2 + f6g0 + f7g9_38 + f8g8_19 + f9g7_38
+ h7 := f0g7 + f1g6 + f2g5 + f3g4 + f4g3 + f5g2 + f6g1 + f7g0 + f8g9_19 + f9g8_19
+ h8 := f0g8 + f1g7_2 + f2g6 + f3g5_2 + f4g4 + f5g3_2 + f6g2 + f7g1_2 + f8g0 + f9g9_38
+ h9 := f0g9 + f1g8 + f2g7 + f3g6 + f4g5 + f5g4 + f6g3 + f7g2 + f8g1 + f9g0
+ var carry [10]int64
+
+ // |h0| <= (1.1*1.1*2^52*(1+19+19+19+19)+1.1*1.1*2^50*(38+38+38+38+38))
+ // i.e. |h0| <= 1.2*2^59; narrower ranges for h2, h4, h6, h8
+ // |h1| <= (1.1*1.1*2^51*(1+1+19+19+19+19+19+19+19+19))
+ // i.e. |h1| <= 1.5*2^58; narrower ranges for h3, h5, h7, h9
+
+ carry[0] = (h0 + (1 << 25)) >> 26
+ h1 += carry[0]
+ h0 -= carry[0] << 26
+ carry[4] = (h4 + (1 << 25)) >> 26
+ h5 += carry[4]
+ h4 -= carry[4] << 26
+ // |h0| <= 2^25
+ // |h4| <= 2^25
+ // |h1| <= 1.51*2^58
+ // |h5| <= 1.51*2^58
+
+ carry[1] = (h1 + (1 << 24)) >> 25
+ h2 += carry[1]
+ h1 -= carry[1] << 25
+ carry[5] = (h5 + (1 << 24)) >> 25
+ h6 += carry[5]
+ h5 -= carry[5] << 25
+ // |h1| <= 2^24; from now on fits into int32
+ // |h5| <= 2^24; from now on fits into int32
+ // |h2| <= 1.21*2^59
+ // |h6| <= 1.21*2^59
+
+ carry[2] = (h2 + (1 << 25)) >> 26
+ h3 += carry[2]
+ h2 -= carry[2] << 26
+ carry[6] = (h6 + (1 << 25)) >> 26
+ h7 += carry[6]
+ h6 -= carry[6] << 26
+ // |h2| <= 2^25; from now on fits into int32 unchanged
+ // |h6| <= 2^25; from now on fits into int32 unchanged
+ // |h3| <= 1.51*2^58
+ // |h7| <= 1.51*2^58
+
+ carry[3] = (h3 + (1 << 24)) >> 25
+ h4 += carry[3]
+ h3 -= carry[3] << 25
+ carry[7] = (h7 + (1 << 24)) >> 25
+ h8 += carry[7]
+ h7 -= carry[7] << 25
+ // |h3| <= 2^24; from now on fits into int32 unchanged
+ // |h7| <= 2^24; from now on fits into int32 unchanged
+ // |h4| <= 1.52*2^33
+ // |h8| <= 1.52*2^33
+
+ carry[4] = (h4 + (1 << 25)) >> 26
+ h5 += carry[4]
+ h4 -= carry[4] << 26
+ carry[8] = (h8 + (1 << 25)) >> 26
+ h9 += carry[8]
+ h8 -= carry[8] << 26
+ // |h4| <= 2^25; from now on fits into int32 unchanged
+ // |h8| <= 2^25; from now on fits into int32 unchanged
+ // |h5| <= 1.01*2^24
+ // |h9| <= 1.51*2^58
+
+ carry[9] = (h9 + (1 << 24)) >> 25
+ h0 += carry[9] * 19
+ h9 -= carry[9] << 25
+ // |h9| <= 2^24; from now on fits into int32 unchanged
+ // |h0| <= 1.8*2^37
+
+ carry[0] = (h0 + (1 << 25)) >> 26
+ h1 += carry[0]
+ h0 -= carry[0] << 26
+ // |h0| <= 2^25; from now on fits into int32 unchanged
+ // |h1| <= 1.01*2^24
+
+ h[0] = int32(h0)
+ h[1] = int32(h1)
+ h[2] = int32(h2)
+ h[3] = int32(h3)
+ h[4] = int32(h4)
+ h[5] = int32(h5)
+ h[6] = int32(h6)
+ h[7] = int32(h7)
+ h[8] = int32(h8)
+ h[9] = int32(h9)
+}
+
+// feSquare calculates h = f*f. Can overlap h with f.
+//
+// Preconditions:
+// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
+//
+// Postconditions:
+// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+func feSquare(h, f *fieldElement) {
+ f0 := f[0]
+ f1 := f[1]
+ f2 := f[2]
+ f3 := f[3]
+ f4 := f[4]
+ f5 := f[5]
+ f6 := f[6]
+ f7 := f[7]
+ f8 := f[8]
+ f9 := f[9]
+ f0_2 := 2 * f0
+ f1_2 := 2 * f1
+ f2_2 := 2 * f2
+ f3_2 := 2 * f3
+ f4_2 := 2 * f4
+ f5_2 := 2 * f5
+ f6_2 := 2 * f6
+ f7_2 := 2 * f7
+ f5_38 := 38 * f5 // 1.31*2^30
+ f6_19 := 19 * f6 // 1.31*2^30
+ f7_38 := 38 * f7 // 1.31*2^30
+ f8_19 := 19 * f8 // 1.31*2^30
+ f9_38 := 38 * f9 // 1.31*2^30
+ f0f0 := int64(f0) * int64(f0)
+ f0f1_2 := int64(f0_2) * int64(f1)
+ f0f2_2 := int64(f0_2) * int64(f2)
+ f0f3_2 := int64(f0_2) * int64(f3)
+ f0f4_2 := int64(f0_2) * int64(f4)
+ f0f5_2 := int64(f0_2) * int64(f5)
+ f0f6_2 := int64(f0_2) * int64(f6)
+ f0f7_2 := int64(f0_2) * int64(f7)
+ f0f8_2 := int64(f0_2) * int64(f8)
+ f0f9_2 := int64(f0_2) * int64(f9)
+ f1f1_2 := int64(f1_2) * int64(f1)
+ f1f2_2 := int64(f1_2) * int64(f2)
+ f1f3_4 := int64(f1_2) * int64(f3_2)
+ f1f4_2 := int64(f1_2) * int64(f4)
+ f1f5_4 := int64(f1_2) * int64(f5_2)
+ f1f6_2 := int64(f1_2) * int64(f6)
+ f1f7_4 := int64(f1_2) * int64(f7_2)
+ f1f8_2 := int64(f1_2) * int64(f8)
+ f1f9_76 := int64(f1_2) * int64(f9_38)
+ f2f2 := int64(f2) * int64(f2)
+ f2f3_2 := int64(f2_2) * int64(f3)
+ f2f4_2 := int64(f2_2) * int64(f4)
+ f2f5_2 := int64(f2_2) * int64(f5)
+ f2f6_2 := int64(f2_2) * int64(f6)
+ f2f7_2 := int64(f2_2) * int64(f7)
+ f2f8_38 := int64(f2_2) * int64(f8_19)
+ f2f9_38 := int64(f2) * int64(f9_38)
+ f3f3_2 := int64(f3_2) * int64(f3)
+ f3f4_2 := int64(f3_2) * int64(f4)
+ f3f5_4 := int64(f3_2) * int64(f5_2)
+ f3f6_2 := int64(f3_2) * int64(f6)
+ f3f7_76 := int64(f3_2) * int64(f7_38)
+ f3f8_38 := int64(f3_2) * int64(f8_19)
+ f3f9_76 := int64(f3_2) * int64(f9_38)
+ f4f4 := int64(f4) * int64(f4)
+ f4f5_2 := int64(f4_2) * int64(f5)
+ f4f6_38 := int64(f4_2) * int64(f6_19)
+ f4f7_38 := int64(f4) * int64(f7_38)
+ f4f8_38 := int64(f4_2) * int64(f8_19)
+ f4f9_38 := int64(f4) * int64(f9_38)
+ f5f5_38 := int64(f5) * int64(f5_38)
+ f5f6_38 := int64(f5_2) * int64(f6_19)
+ f5f7_76 := int64(f5_2) * int64(f7_38)
+ f5f8_38 := int64(f5_2) * int64(f8_19)
+ f5f9_76 := int64(f5_2) * int64(f9_38)
+ f6f6_19 := int64(f6) * int64(f6_19)
+ f6f7_38 := int64(f6) * int64(f7_38)
+ f6f8_38 := int64(f6_2) * int64(f8_19)
+ f6f9_38 := int64(f6) * int64(f9_38)
+ f7f7_38 := int64(f7) * int64(f7_38)
+ f7f8_38 := int64(f7_2) * int64(f8_19)
+ f7f9_76 := int64(f7_2) * int64(f9_38)
+ f8f8_19 := int64(f8) * int64(f8_19)
+ f8f9_38 := int64(f8) * int64(f9_38)
+ f9f9_38 := int64(f9) * int64(f9_38)
+ h0 := f0f0 + f1f9_76 + f2f8_38 + f3f7_76 + f4f6_38 + f5f5_38
+ h1 := f0f1_2 + f2f9_38 + f3f8_38 + f4f7_38 + f5f6_38
+ h2 := f0f2_2 + f1f1_2 + f3f9_76 + f4f8_38 + f5f7_76 + f6f6_19
+ h3 := f0f3_2 + f1f2_2 + f4f9_38 + f5f8_38 + f6f7_38
+ h4 := f0f4_2 + f1f3_4 + f2f2 + f5f9_76 + f6f8_38 + f7f7_38
+ h5 := f0f5_2 + f1f4_2 + f2f3_2 + f6f9_38 + f7f8_38
+ h6 := f0f6_2 + f1f5_4 + f2f4_2 + f3f3_2 + f7f9_76 + f8f8_19
+ h7 := f0f7_2 + f1f6_2 + f2f5_2 + f3f4_2 + f8f9_38
+ h8 := f0f8_2 + f1f7_4 + f2f6_2 + f3f5_4 + f4f4 + f9f9_38
+ h9 := f0f9_2 + f1f8_2 + f2f7_2 + f3f6_2 + f4f5_2
+ var carry [10]int64
+
+ carry[0] = (h0 + (1 << 25)) >> 26
+ h1 += carry[0]
+ h0 -= carry[0] << 26
+ carry[4] = (h4 + (1 << 25)) >> 26
+ h5 += carry[4]
+ h4 -= carry[4] << 26
+
+ carry[1] = (h1 + (1 << 24)) >> 25
+ h2 += carry[1]
+ h1 -= carry[1] << 25
+ carry[5] = (h5 + (1 << 24)) >> 25
+ h6 += carry[5]
+ h5 -= carry[5] << 25
+
+ carry[2] = (h2 + (1 << 25)) >> 26
+ h3 += carry[2]
+ h2 -= carry[2] << 26
+ carry[6] = (h6 + (1 << 25)) >> 26
+ h7 += carry[6]
+ h6 -= carry[6] << 26
+
+ carry[3] = (h3 + (1 << 24)) >> 25
+ h4 += carry[3]
+ h3 -= carry[3] << 25
+ carry[7] = (h7 + (1 << 24)) >> 25
+ h8 += carry[7]
+ h7 -= carry[7] << 25
+
+ carry[4] = (h4 + (1 << 25)) >> 26
+ h5 += carry[4]
+ h4 -= carry[4] << 26
+ carry[8] = (h8 + (1 << 25)) >> 26
+ h9 += carry[8]
+ h8 -= carry[8] << 26
+
+ carry[9] = (h9 + (1 << 24)) >> 25
+ h0 += carry[9] * 19
+ h9 -= carry[9] << 25
+
+ carry[0] = (h0 + (1 << 25)) >> 26
+ h1 += carry[0]
+ h0 -= carry[0] << 26
+
+ h[0] = int32(h0)
+ h[1] = int32(h1)
+ h[2] = int32(h2)
+ h[3] = int32(h3)
+ h[4] = int32(h4)
+ h[5] = int32(h5)
+ h[6] = int32(h6)
+ h[7] = int32(h7)
+ h[8] = int32(h8)
+ h[9] = int32(h9)
+}
+
+// feMul121666 calculates h = f * 121666. Can overlap h with f.
+//
+// Preconditions:
+// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
+//
+// Postconditions:
+// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+func feMul121666(h, f *fieldElement) {
+ h0 := int64(f[0]) * 121666
+ h1 := int64(f[1]) * 121666
+ h2 := int64(f[2]) * 121666
+ h3 := int64(f[3]) * 121666
+ h4 := int64(f[4]) * 121666
+ h5 := int64(f[5]) * 121666
+ h6 := int64(f[6]) * 121666
+ h7 := int64(f[7]) * 121666
+ h8 := int64(f[8]) * 121666
+ h9 := int64(f[9]) * 121666
+ var carry [10]int64
+
+ carry[9] = (h9 + (1 << 24)) >> 25
+ h0 += carry[9] * 19
+ h9 -= carry[9] << 25
+ carry[1] = (h1 + (1 << 24)) >> 25
+ h2 += carry[1]
+ h1 -= carry[1] << 25
+ carry[3] = (h3 + (1 << 24)) >> 25
+ h4 += carry[3]
+ h3 -= carry[3] << 25
+ carry[5] = (h5 + (1 << 24)) >> 25
+ h6 += carry[5]
+ h5 -= carry[5] << 25
+ carry[7] = (h7 + (1 << 24)) >> 25
+ h8 += carry[7]
+ h7 -= carry[7] << 25
+
+ carry[0] = (h0 + (1 << 25)) >> 26
+ h1 += carry[0]
+ h0 -= carry[0] << 26
+ carry[2] = (h2 + (1 << 25)) >> 26
+ h3 += carry[2]
+ h2 -= carry[2] << 26
+ carry[4] = (h4 + (1 << 25)) >> 26
+ h5 += carry[4]
+ h4 -= carry[4] << 26
+ carry[6] = (h6 + (1 << 25)) >> 26
+ h7 += carry[6]
+ h6 -= carry[6] << 26
+ carry[8] = (h8 + (1 << 25)) >> 26
+ h9 += carry[8]
+ h8 -= carry[8] << 26
+
+ h[0] = int32(h0)
+ h[1] = int32(h1)
+ h[2] = int32(h2)
+ h[3] = int32(h3)
+ h[4] = int32(h4)
+ h[5] = int32(h5)
+ h[6] = int32(h6)
+ h[7] = int32(h7)
+ h[8] = int32(h8)
+ h[9] = int32(h9)
+}
+
+// feInvert sets out = z^-1.
+func feInvert(out, z *fieldElement) {
+ var t0, t1, t2, t3 fieldElement
+ var i int
+
+ feSquare(&t0, z)
+ for i = 1; i < 1; i++ {
+ feSquare(&t0, &t0)
+ }
+ feSquare(&t1, &t0)
+ for i = 1; i < 2; i++ {
+ feSquare(&t1, &t1)
+ }
+ feMul(&t1, z, &t1)
+ feMul(&t0, &t0, &t1)
+ feSquare(&t2, &t0)
+ for i = 1; i < 1; i++ {
+ feSquare(&t2, &t2)
+ }
+ feMul(&t1, &t1, &t2)
+ feSquare(&t2, &t1)
+ for i = 1; i < 5; i++ {
+ feSquare(&t2, &t2)
+ }
+ feMul(&t1, &t2, &t1)
+ feSquare(&t2, &t1)
+ for i = 1; i < 10; i++ {
+ feSquare(&t2, &t2)
+ }
+ feMul(&t2, &t2, &t1)
+ feSquare(&t3, &t2)
+ for i = 1; i < 20; i++ {
+ feSquare(&t3, &t3)
+ }
+ feMul(&t2, &t3, &t2)
+ feSquare(&t2, &t2)
+ for i = 1; i < 10; i++ {
+ feSquare(&t2, &t2)
+ }
+ feMul(&t1, &t2, &t1)
+ feSquare(&t2, &t1)
+ for i = 1; i < 50; i++ {
+ feSquare(&t2, &t2)
+ }
+ feMul(&t2, &t2, &t1)
+ feSquare(&t3, &t2)
+ for i = 1; i < 100; i++ {
+ feSquare(&t3, &t3)
+ }
+ feMul(&t2, &t3, &t2)
+ feSquare(&t2, &t2)
+ for i = 1; i < 50; i++ {
+ feSquare(&t2, &t2)
+ }
+ feMul(&t1, &t2, &t1)
+ feSquare(&t1, &t1)
+ for i = 1; i < 5; i++ {
+ feSquare(&t1, &t1)
+ }
+ feMul(out, &t1, &t0)
+}
+
+func scalarMult(out, in, base *[32]byte) {
+ var e [32]byte
+
+ copy(e[:], in[:])
+ e[0] &= 248
+ e[31] &= 127
+ e[31] |= 64
+
+ var x1, x2, z2, x3, z3, tmp0, tmp1 fieldElement
+ feFromBytes(&x1, base)
+ feOne(&x2)
+ feCopy(&x3, &x1)
+ feOne(&z3)
+
+ swap := int32(0)
+ for pos := 254; pos >= 0; pos-- {
+ b := e[pos/8] >> uint(pos&7)
+ b &= 1
+ swap ^= int32(b)
+ feCSwap(&x2, &x3, swap)
+ feCSwap(&z2, &z3, swap)
+ swap = int32(b)
+
+ feSub(&tmp0, &x3, &z3)
+ feSub(&tmp1, &x2, &z2)
+ feAdd(&x2, &x2, &z2)
+ feAdd(&z2, &x3, &z3)
+ feMul(&z3, &tmp0, &x2)
+ feMul(&z2, &z2, &tmp1)
+ feSquare(&tmp0, &tmp1)
+ feSquare(&tmp1, &x2)
+ feAdd(&x3, &z3, &z2)
+ feSub(&z2, &z3, &z2)
+ feMul(&x2, &tmp1, &tmp0)
+ feSub(&tmp1, &tmp1, &tmp0)
+ feSquare(&z2, &z2)
+ feMul121666(&z3, &tmp1)
+ feSquare(&x3, &x3)
+ feAdd(&tmp0, &tmp0, &z3)
+ feMul(&z3, &x1, &z2)
+ feMul(&z2, &tmp1, &tmp0)
+ }
+
+ feCSwap(&x2, &x3, swap)
+ feCSwap(&z2, &z3, swap)
+
+ feInvert(&z2, &z2)
+ feMul(&x2, &x2, &z2)
+ feToBytes(out, &x2)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/curve25519/curve25519_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/curve25519/curve25519_test.go
new file mode 100644
index 000000000..051a8301f
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/curve25519/curve25519_test.go
@@ -0,0 +1,39 @@
+// Copyright 2012 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 curve25519
+
+import (
+ "fmt"
+ "testing"
+)
+
+const expectedHex = "89161fde887b2b53de549af483940106ecc114d6982daa98256de23bdf77661a"
+
+func TestBaseScalarMult(t *testing.T) {
+ var a, b [32]byte
+ in := &a
+ out := &b
+ a[0] = 1
+
+ for i := 0; i < 200; i++ {
+ ScalarBaseMult(out, in)
+ in, out = out, in
+ }
+
+ result := fmt.Sprintf("%x", in[:])
+ if result != expectedHex {
+ t.Errorf("incorrect result: got %s, want %s", result, expectedHex)
+ }
+}
+
+func BenchmarkScalarBaseMult(b *testing.B) {
+ var in, out [32]byte
+ in[0] = 1
+
+ b.SetBytes(32)
+ for i := 0; i < b.N; i++ {
+ ScalarBaseMult(&out, &in)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/curve25519/doc.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/curve25519/doc.go
new file mode 100644
index 000000000..da9b10d9c
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/curve25519/doc.go
@@ -0,0 +1,23 @@
+// Copyright 2012 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 curve25519 provides an implementation of scalar multiplication on
+// the elliptic curve known as curve25519. See https://cr.yp.to/ecdh.html
+package curve25519 // import "golang.org/x/crypto/curve25519"
+
+// basePoint is the x coordinate of the generator of the curve.
+var basePoint = [32]byte{9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+
+// ScalarMult sets dst to the product in*base where dst and base are the x
+// coordinates of group points and all values are in little-endian form.
+func ScalarMult(dst, in, base *[32]byte) {
+ scalarMult(dst, in, base)
+}
+
+// ScalarBaseMult sets dst to the product in*base where dst and base are the x
+// coordinates of group points, base is the standard generator and all values
+// are in little-endian form.
+func ScalarBaseMult(dst, in *[32]byte) {
+ ScalarMult(dst, in, &basePoint)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/curve25519/freeze_amd64.s b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/curve25519/freeze_amd64.s
new file mode 100644
index 000000000..390816106
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/curve25519/freeze_amd64.s
@@ -0,0 +1,73 @@
+// Copyright 2012 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.
+
+// This code was translated into a form compatible with 6a from the public
+// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html
+
+// +build amd64,!gccgo,!appengine
+
+#include "const_amd64.h"
+
+// func freeze(inout *[5]uint64)
+TEXT ·freeze(SB),7,$0-8
+ MOVQ inout+0(FP), DI
+
+ MOVQ 0(DI),SI
+ MOVQ 8(DI),DX
+ MOVQ 16(DI),CX
+ MOVQ 24(DI),R8
+ MOVQ 32(DI),R9
+ MOVQ $REDMASK51,AX
+ MOVQ AX,R10
+ SUBQ $18,R10
+ MOVQ $3,R11
+REDUCELOOP:
+ MOVQ SI,R12
+ SHRQ $51,R12
+ ANDQ AX,SI
+ ADDQ R12,DX
+ MOVQ DX,R12
+ SHRQ $51,R12
+ ANDQ AX,DX
+ ADDQ R12,CX
+ MOVQ CX,R12
+ SHRQ $51,R12
+ ANDQ AX,CX
+ ADDQ R12,R8
+ MOVQ R8,R12
+ SHRQ $51,R12
+ ANDQ AX,R8
+ ADDQ R12,R9
+ MOVQ R9,R12
+ SHRQ $51,R12
+ ANDQ AX,R9
+ IMUL3Q $19,R12,R12
+ ADDQ R12,SI
+ SUBQ $1,R11
+ JA REDUCELOOP
+ MOVQ $1,R12
+ CMPQ R10,SI
+ CMOVQLT R11,R12
+ CMPQ AX,DX
+ CMOVQNE R11,R12
+ CMPQ AX,CX
+ CMOVQNE R11,R12
+ CMPQ AX,R8
+ CMOVQNE R11,R12
+ CMPQ AX,R9
+ CMOVQNE R11,R12
+ NEGQ R12
+ ANDQ R12,AX
+ ANDQ R12,R10
+ SUBQ R10,SI
+ SUBQ AX,DX
+ SUBQ AX,CX
+ SUBQ AX,R8
+ SUBQ AX,R9
+ MOVQ SI,0(DI)
+ MOVQ DX,8(DI)
+ MOVQ CX,16(DI)
+ MOVQ R8,24(DI)
+ MOVQ R9,32(DI)
+ RET
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/curve25519/ladderstep_amd64.s b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/curve25519/ladderstep_amd64.s
new file mode 100644
index 000000000..9e9040b25
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/curve25519/ladderstep_amd64.s
@@ -0,0 +1,1377 @@
+// Copyright 2012 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.
+
+// This code was translated into a form compatible with 6a from the public
+// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html
+
+// +build amd64,!gccgo,!appengine
+
+#include "const_amd64.h"
+
+// func ladderstep(inout *[5][5]uint64)
+TEXT ·ladderstep(SB),0,$296-8
+ MOVQ inout+0(FP),DI
+
+ MOVQ 40(DI),SI
+ MOVQ 48(DI),DX
+ MOVQ 56(DI),CX
+ MOVQ 64(DI),R8
+ MOVQ 72(DI),R9
+ MOVQ SI,AX
+ MOVQ DX,R10
+ MOVQ CX,R11
+ MOVQ R8,R12
+ MOVQ R9,R13
+ ADDQ ·_2P0(SB),AX
+ ADDQ ·_2P1234(SB),R10
+ ADDQ ·_2P1234(SB),R11
+ ADDQ ·_2P1234(SB),R12
+ ADDQ ·_2P1234(SB),R13
+ ADDQ 80(DI),SI
+ ADDQ 88(DI),DX
+ ADDQ 96(DI),CX
+ ADDQ 104(DI),R8
+ ADDQ 112(DI),R9
+ SUBQ 80(DI),AX
+ SUBQ 88(DI),R10
+ SUBQ 96(DI),R11
+ SUBQ 104(DI),R12
+ SUBQ 112(DI),R13
+ MOVQ SI,0(SP)
+ MOVQ DX,8(SP)
+ MOVQ CX,16(SP)
+ MOVQ R8,24(SP)
+ MOVQ R9,32(SP)
+ MOVQ AX,40(SP)
+ MOVQ R10,48(SP)
+ MOVQ R11,56(SP)
+ MOVQ R12,64(SP)
+ MOVQ R13,72(SP)
+ MOVQ 40(SP),AX
+ MULQ 40(SP)
+ MOVQ AX,SI
+ MOVQ DX,CX
+ MOVQ 40(SP),AX
+ SHLQ $1,AX
+ MULQ 48(SP)
+ MOVQ AX,R8
+ MOVQ DX,R9
+ MOVQ 40(SP),AX
+ SHLQ $1,AX
+ MULQ 56(SP)
+ MOVQ AX,R10
+ MOVQ DX,R11
+ MOVQ 40(SP),AX
+ SHLQ $1,AX
+ MULQ 64(SP)
+ MOVQ AX,R12
+ MOVQ DX,R13
+ MOVQ 40(SP),AX
+ SHLQ $1,AX
+ MULQ 72(SP)
+ MOVQ AX,R14
+ MOVQ DX,R15
+ MOVQ 48(SP),AX
+ MULQ 48(SP)
+ ADDQ AX,R10
+ ADCQ DX,R11
+ MOVQ 48(SP),AX
+ SHLQ $1,AX
+ MULQ 56(SP)
+ ADDQ AX,R12
+ ADCQ DX,R13
+ MOVQ 48(SP),AX
+ SHLQ $1,AX
+ MULQ 64(SP)
+ ADDQ AX,R14
+ ADCQ DX,R15
+ MOVQ 48(SP),DX
+ IMUL3Q $38,DX,AX
+ MULQ 72(SP)
+ ADDQ AX,SI
+ ADCQ DX,CX
+ MOVQ 56(SP),AX
+ MULQ 56(SP)
+ ADDQ AX,R14
+ ADCQ DX,R15
+ MOVQ 56(SP),DX
+ IMUL3Q $38,DX,AX
+ MULQ 64(SP)
+ ADDQ AX,SI
+ ADCQ DX,CX
+ MOVQ 56(SP),DX
+ IMUL3Q $38,DX,AX
+ MULQ 72(SP)
+ ADDQ AX,R8
+ ADCQ DX,R9
+ MOVQ 64(SP),DX
+ IMUL3Q $19,DX,AX
+ MULQ 64(SP)
+ ADDQ AX,R8
+ ADCQ DX,R9
+ MOVQ 64(SP),DX
+ IMUL3Q $38,DX,AX
+ MULQ 72(SP)
+ ADDQ AX,R10
+ ADCQ DX,R11
+ MOVQ 72(SP),DX
+ IMUL3Q $19,DX,AX
+ MULQ 72(SP)
+ ADDQ AX,R12
+ ADCQ DX,R13
+ MOVQ $REDMASK51,DX
+ SHLQ $13,CX:SI
+ ANDQ DX,SI
+ SHLQ $13,R9:R8
+ ANDQ DX,R8
+ ADDQ CX,R8
+ SHLQ $13,R11:R10
+ ANDQ DX,R10
+ ADDQ R9,R10
+ SHLQ $13,R13:R12
+ ANDQ DX,R12
+ ADDQ R11,R12
+ SHLQ $13,R15:R14
+ ANDQ DX,R14
+ ADDQ R13,R14
+ IMUL3Q $19,R15,CX
+ ADDQ CX,SI
+ MOVQ SI,CX
+ SHRQ $51,CX
+ ADDQ R8,CX
+ ANDQ DX,SI
+ MOVQ CX,R8
+ SHRQ $51,CX
+ ADDQ R10,CX
+ ANDQ DX,R8
+ MOVQ CX,R9
+ SHRQ $51,CX
+ ADDQ R12,CX
+ ANDQ DX,R9
+ MOVQ CX,AX
+ SHRQ $51,CX
+ ADDQ R14,CX
+ ANDQ DX,AX
+ MOVQ CX,R10
+ SHRQ $51,CX
+ IMUL3Q $19,CX,CX
+ ADDQ CX,SI
+ ANDQ DX,R10
+ MOVQ SI,80(SP)
+ MOVQ R8,88(SP)
+ MOVQ R9,96(SP)
+ MOVQ AX,104(SP)
+ MOVQ R10,112(SP)
+ MOVQ 0(SP),AX
+ MULQ 0(SP)
+ MOVQ AX,SI
+ MOVQ DX,CX
+ MOVQ 0(SP),AX
+ SHLQ $1,AX
+ MULQ 8(SP)
+ MOVQ AX,R8
+ MOVQ DX,R9
+ MOVQ 0(SP),AX
+ SHLQ $1,AX
+ MULQ 16(SP)
+ MOVQ AX,R10
+ MOVQ DX,R11
+ MOVQ 0(SP),AX
+ SHLQ $1,AX
+ MULQ 24(SP)
+ MOVQ AX,R12
+ MOVQ DX,R13
+ MOVQ 0(SP),AX
+ SHLQ $1,AX
+ MULQ 32(SP)
+ MOVQ AX,R14
+ MOVQ DX,R15
+ MOVQ 8(SP),AX
+ MULQ 8(SP)
+ ADDQ AX,R10
+ ADCQ DX,R11
+ MOVQ 8(SP),AX
+ SHLQ $1,AX
+ MULQ 16(SP)
+ ADDQ AX,R12
+ ADCQ DX,R13
+ MOVQ 8(SP),AX
+ SHLQ $1,AX
+ MULQ 24(SP)
+ ADDQ AX,R14
+ ADCQ DX,R15
+ MOVQ 8(SP),DX
+ IMUL3Q $38,DX,AX
+ MULQ 32(SP)
+ ADDQ AX,SI
+ ADCQ DX,CX
+ MOVQ 16(SP),AX
+ MULQ 16(SP)
+ ADDQ AX,R14
+ ADCQ DX,R15
+ MOVQ 16(SP),DX
+ IMUL3Q $38,DX,AX
+ MULQ 24(SP)
+ ADDQ AX,SI
+ ADCQ DX,CX
+ MOVQ 16(SP),DX
+ IMUL3Q $38,DX,AX
+ MULQ 32(SP)
+ ADDQ AX,R8
+ ADCQ DX,R9
+ MOVQ 24(SP),DX
+ IMUL3Q $19,DX,AX
+ MULQ 24(SP)
+ ADDQ AX,R8
+ ADCQ DX,R9
+ MOVQ 24(SP),DX
+ IMUL3Q $38,DX,AX
+ MULQ 32(SP)
+ ADDQ AX,R10
+ ADCQ DX,R11
+ MOVQ 32(SP),DX
+ IMUL3Q $19,DX,AX
+ MULQ 32(SP)
+ ADDQ AX,R12
+ ADCQ DX,R13
+ MOVQ $REDMASK51,DX
+ SHLQ $13,CX:SI
+ ANDQ DX,SI
+ SHLQ $13,R9:R8
+ ANDQ DX,R8
+ ADDQ CX,R8
+ SHLQ $13,R11:R10
+ ANDQ DX,R10
+ ADDQ R9,R10
+ SHLQ $13,R13:R12
+ ANDQ DX,R12
+ ADDQ R11,R12
+ SHLQ $13,R15:R14
+ ANDQ DX,R14
+ ADDQ R13,R14
+ IMUL3Q $19,R15,CX
+ ADDQ CX,SI
+ MOVQ SI,CX
+ SHRQ $51,CX
+ ADDQ R8,CX
+ ANDQ DX,SI
+ MOVQ CX,R8
+ SHRQ $51,CX
+ ADDQ R10,CX
+ ANDQ DX,R8
+ MOVQ CX,R9
+ SHRQ $51,CX
+ ADDQ R12,CX
+ ANDQ DX,R9
+ MOVQ CX,AX
+ SHRQ $51,CX
+ ADDQ R14,CX
+ ANDQ DX,AX
+ MOVQ CX,R10
+ SHRQ $51,CX
+ IMUL3Q $19,CX,CX
+ ADDQ CX,SI
+ ANDQ DX,R10
+ MOVQ SI,120(SP)
+ MOVQ R8,128(SP)
+ MOVQ R9,136(SP)
+ MOVQ AX,144(SP)
+ MOVQ R10,152(SP)
+ MOVQ SI,SI
+ MOVQ R8,DX
+ MOVQ R9,CX
+ MOVQ AX,R8
+ MOVQ R10,R9
+ ADDQ ·_2P0(SB),SI
+ ADDQ ·_2P1234(SB),DX
+ ADDQ ·_2P1234(SB),CX
+ ADDQ ·_2P1234(SB),R8
+ ADDQ ·_2P1234(SB),R9
+ SUBQ 80(SP),SI
+ SUBQ 88(SP),DX
+ SUBQ 96(SP),CX
+ SUBQ 104(SP),R8
+ SUBQ 112(SP),R9
+ MOVQ SI,160(SP)
+ MOVQ DX,168(SP)
+ MOVQ CX,176(SP)
+ MOVQ R8,184(SP)
+ MOVQ R9,192(SP)
+ MOVQ 120(DI),SI
+ MOVQ 128(DI),DX
+ MOVQ 136(DI),CX
+ MOVQ 144(DI),R8
+ MOVQ 152(DI),R9
+ MOVQ SI,AX
+ MOVQ DX,R10
+ MOVQ CX,R11
+ MOVQ R8,R12
+ MOVQ R9,R13
+ ADDQ ·_2P0(SB),AX
+ ADDQ ·_2P1234(SB),R10
+ ADDQ ·_2P1234(SB),R11
+ ADDQ ·_2P1234(SB),R12
+ ADDQ ·_2P1234(SB),R13
+ ADDQ 160(DI),SI
+ ADDQ 168(DI),DX
+ ADDQ 176(DI),CX
+ ADDQ 184(DI),R8
+ ADDQ 192(DI),R9
+ SUBQ 160(DI),AX
+ SUBQ 168(DI),R10
+ SUBQ 176(DI),R11
+ SUBQ 184(DI),R12
+ SUBQ 192(DI),R13
+ MOVQ SI,200(SP)
+ MOVQ DX,208(SP)
+ MOVQ CX,216(SP)
+ MOVQ R8,224(SP)
+ MOVQ R9,232(SP)
+ MOVQ AX,240(SP)
+ MOVQ R10,248(SP)
+ MOVQ R11,256(SP)
+ MOVQ R12,264(SP)
+ MOVQ R13,272(SP)
+ MOVQ 224(SP),SI
+ IMUL3Q $19,SI,AX
+ MOVQ AX,280(SP)
+ MULQ 56(SP)
+ MOVQ AX,SI
+ MOVQ DX,CX
+ MOVQ 232(SP),DX
+ IMUL3Q $19,DX,AX
+ MOVQ AX,288(SP)
+ MULQ 48(SP)
+ ADDQ AX,SI
+ ADCQ DX,CX
+ MOVQ 200(SP),AX
+ MULQ 40(SP)
+ ADDQ AX,SI
+ ADCQ DX,CX
+ MOVQ 200(SP),AX
+ MULQ 48(SP)
+ MOVQ AX,R8
+ MOVQ DX,R9
+ MOVQ 200(SP),AX
+ MULQ 56(SP)
+ MOVQ AX,R10
+ MOVQ DX,R11
+ MOVQ 200(SP),AX
+ MULQ 64(SP)
+ MOVQ AX,R12
+ MOVQ DX,R13
+ MOVQ 200(SP),AX
+ MULQ 72(SP)
+ MOVQ AX,R14
+ MOVQ DX,R15
+ MOVQ 208(SP),AX
+ MULQ 40(SP)
+ ADDQ AX,R8
+ ADCQ DX,R9
+ MOVQ 208(SP),AX
+ MULQ 48(SP)
+ ADDQ AX,R10
+ ADCQ DX,R11
+ MOVQ 208(SP),AX
+ MULQ 56(SP)
+ ADDQ AX,R12
+ ADCQ DX,R13
+ MOVQ 208(SP),AX
+ MULQ 64(SP)
+ ADDQ AX,R14
+ ADCQ DX,R15
+ MOVQ 208(SP),DX
+ IMUL3Q $19,DX,AX
+ MULQ 72(SP)
+ ADDQ AX,SI
+ ADCQ DX,CX
+ MOVQ 216(SP),AX
+ MULQ 40(SP)
+ ADDQ AX,R10
+ ADCQ DX,R11
+ MOVQ 216(SP),AX
+ MULQ 48(SP)
+ ADDQ AX,R12
+ ADCQ DX,R13
+ MOVQ 216(SP),AX
+ MULQ 56(SP)
+ ADDQ AX,R14
+ ADCQ DX,R15
+ MOVQ 216(SP),DX
+ IMUL3Q $19,DX,AX
+ MULQ 64(SP)
+ ADDQ AX,SI
+ ADCQ DX,CX
+ MOVQ 216(SP),DX
+ IMUL3Q $19,DX,AX
+ MULQ 72(SP)
+ ADDQ AX,R8
+ ADCQ DX,R9
+ MOVQ 224(SP),AX
+ MULQ 40(SP)
+ ADDQ AX,R12
+ ADCQ DX,R13
+ MOVQ 224(SP),AX
+ MULQ 48(SP)
+ ADDQ AX,R14
+ ADCQ DX,R15
+ MOVQ 280(SP),AX
+ MULQ 64(SP)
+ ADDQ AX,R8
+ ADCQ DX,R9
+ MOVQ 280(SP),AX
+ MULQ 72(SP)
+ ADDQ AX,R10
+ ADCQ DX,R11
+ MOVQ 232(SP),AX
+ MULQ 40(SP)
+ ADDQ AX,R14
+ ADCQ DX,R15
+ MOVQ 288(SP),AX
+ MULQ 56(SP)
+ ADDQ AX,R8
+ ADCQ DX,R9
+ MOVQ 288(SP),AX
+ MULQ 64(SP)
+ ADDQ AX,R10
+ ADCQ DX,R11
+ MOVQ 288(SP),AX
+ MULQ 72(SP)
+ ADDQ AX,R12
+ ADCQ DX,R13
+ MOVQ $REDMASK51,DX
+ SHLQ $13,CX:SI
+ ANDQ DX,SI
+ SHLQ $13,R9:R8
+ ANDQ DX,R8
+ ADDQ CX,R8
+ SHLQ $13,R11:R10
+ ANDQ DX,R10
+ ADDQ R9,R10
+ SHLQ $13,R13:R12
+ ANDQ DX,R12
+ ADDQ R11,R12
+ SHLQ $13,R15:R14
+ ANDQ DX,R14
+ ADDQ R13,R14
+ IMUL3Q $19,R15,CX
+ ADDQ CX,SI
+ MOVQ SI,CX
+ SHRQ $51,CX
+ ADDQ R8,CX
+ MOVQ CX,R8
+ SHRQ $51,CX
+ ANDQ DX,SI
+ ADDQ R10,CX
+ MOVQ CX,R9
+ SHRQ $51,CX
+ ANDQ DX,R8
+ ADDQ R12,CX
+ MOVQ CX,AX
+ SHRQ $51,CX
+ ANDQ DX,R9
+ ADDQ R14,CX
+ MOVQ CX,R10
+ SHRQ $51,CX
+ ANDQ DX,AX
+ IMUL3Q $19,CX,CX
+ ADDQ CX,SI
+ ANDQ DX,R10
+ MOVQ SI,40(SP)
+ MOVQ R8,48(SP)
+ MOVQ R9,56(SP)
+ MOVQ AX,64(SP)
+ MOVQ R10,72(SP)
+ MOVQ 264(SP),SI
+ IMUL3Q $19,SI,AX
+ MOVQ AX,200(SP)
+ MULQ 16(SP)
+ MOVQ AX,SI
+ MOVQ DX,CX
+ MOVQ 272(SP),DX
+ IMUL3Q $19,DX,AX
+ MOVQ AX,208(SP)
+ MULQ 8(SP)
+ ADDQ AX,SI
+ ADCQ DX,CX
+ MOVQ 240(SP),AX
+ MULQ 0(SP)
+ ADDQ AX,SI
+ ADCQ DX,CX
+ MOVQ 240(SP),AX
+ MULQ 8(SP)
+ MOVQ AX,R8
+ MOVQ DX,R9
+ MOVQ 240(SP),AX
+ MULQ 16(SP)
+ MOVQ AX,R10
+ MOVQ DX,R11
+ MOVQ 240(SP),AX
+ MULQ 24(SP)
+ MOVQ AX,R12
+ MOVQ DX,R13
+ MOVQ 240(SP),AX
+ MULQ 32(SP)
+ MOVQ AX,R14
+ MOVQ DX,R15
+ MOVQ 248(SP),AX
+ MULQ 0(SP)
+ ADDQ AX,R8
+ ADCQ DX,R9
+ MOVQ 248(SP),AX
+ MULQ 8(SP)
+ ADDQ AX,R10
+ ADCQ DX,R11
+ MOVQ 248(SP),AX
+ MULQ 16(SP)
+ ADDQ AX,R12
+ ADCQ DX,R13
+ MOVQ 248(SP),AX
+ MULQ 24(SP)
+ ADDQ AX,R14
+ ADCQ DX,R15
+ MOVQ 248(SP),DX
+ IMUL3Q $19,DX,AX
+ MULQ 32(SP)
+ ADDQ AX,SI
+ ADCQ DX,CX
+ MOVQ 256(SP),AX
+ MULQ 0(SP)
+ ADDQ AX,R10
+ ADCQ DX,R11
+ MOVQ 256(SP),AX
+ MULQ 8(SP)
+ ADDQ AX,R12
+ ADCQ DX,R13
+ MOVQ 256(SP),AX
+ MULQ 16(SP)
+ ADDQ AX,R14
+ ADCQ DX,R15
+ MOVQ 256(SP),DX
+ IMUL3Q $19,DX,AX
+ MULQ 24(SP)
+ ADDQ AX,SI
+ ADCQ DX,CX
+ MOVQ 256(SP),DX
+ IMUL3Q $19,DX,AX
+ MULQ 32(SP)
+ ADDQ AX,R8
+ ADCQ DX,R9
+ MOVQ 264(SP),AX
+ MULQ 0(SP)
+ ADDQ AX,R12
+ ADCQ DX,R13
+ MOVQ 264(SP),AX
+ MULQ 8(SP)
+ ADDQ AX,R14
+ ADCQ DX,R15
+ MOVQ 200(SP),AX
+ MULQ 24(SP)
+ ADDQ AX,R8
+ ADCQ DX,R9
+ MOVQ 200(SP),AX
+ MULQ 32(SP)
+ ADDQ AX,R10
+ ADCQ DX,R11
+ MOVQ 272(SP),AX
+ MULQ 0(SP)
+ ADDQ AX,R14
+ ADCQ DX,R15
+ MOVQ 208(SP),AX
+ MULQ 16(SP)
+ ADDQ AX,R8
+ ADCQ DX,R9
+ MOVQ 208(SP),AX
+ MULQ 24(SP)
+ ADDQ AX,R10
+ ADCQ DX,R11
+ MOVQ 208(SP),AX
+ MULQ 32(SP)
+ ADDQ AX,R12
+ ADCQ DX,R13
+ MOVQ $REDMASK51,DX
+ SHLQ $13,CX:SI
+ ANDQ DX,SI
+ SHLQ $13,R9:R8
+ ANDQ DX,R8
+ ADDQ CX,R8
+ SHLQ $13,R11:R10
+ ANDQ DX,R10
+ ADDQ R9,R10
+ SHLQ $13,R13:R12
+ ANDQ DX,R12
+ ADDQ R11,R12
+ SHLQ $13,R15:R14
+ ANDQ DX,R14
+ ADDQ R13,R14
+ IMUL3Q $19,R15,CX
+ ADDQ CX,SI
+ MOVQ SI,CX
+ SHRQ $51,CX
+ ADDQ R8,CX
+ MOVQ CX,R8
+ SHRQ $51,CX
+ ANDQ DX,SI
+ ADDQ R10,CX
+ MOVQ CX,R9
+ SHRQ $51,CX
+ ANDQ DX,R8
+ ADDQ R12,CX
+ MOVQ CX,AX
+ SHRQ $51,CX
+ ANDQ DX,R9
+ ADDQ R14,CX
+ MOVQ CX,R10
+ SHRQ $51,CX
+ ANDQ DX,AX
+ IMUL3Q $19,CX,CX
+ ADDQ CX,SI
+ ANDQ DX,R10
+ MOVQ SI,DX
+ MOVQ R8,CX
+ MOVQ R9,R11
+ MOVQ AX,R12
+ MOVQ R10,R13
+ ADDQ ·_2P0(SB),DX
+ ADDQ ·_2P1234(SB),CX
+ ADDQ ·_2P1234(SB),R11
+ ADDQ ·_2P1234(SB),R12
+ ADDQ ·_2P1234(SB),R13
+ ADDQ 40(SP),SI
+ ADDQ 48(SP),R8
+ ADDQ 56(SP),R9
+ ADDQ 64(SP),AX
+ ADDQ 72(SP),R10
+ SUBQ 40(SP),DX
+ SUBQ 48(SP),CX
+ SUBQ 56(SP),R11
+ SUBQ 64(SP),R12
+ SUBQ 72(SP),R13
+ MOVQ SI,120(DI)
+ MOVQ R8,128(DI)
+ MOVQ R9,136(DI)
+ MOVQ AX,144(DI)
+ MOVQ R10,152(DI)
+ MOVQ DX,160(DI)
+ MOVQ CX,168(DI)
+ MOVQ R11,176(DI)
+ MOVQ R12,184(DI)
+ MOVQ R13,192(DI)
+ MOVQ 120(DI),AX
+ MULQ 120(DI)
+ MOVQ AX,SI
+ MOVQ DX,CX
+ MOVQ 120(DI),AX
+ SHLQ $1,AX
+ MULQ 128(DI)
+ MOVQ AX,R8
+ MOVQ DX,R9
+ MOVQ 120(DI),AX
+ SHLQ $1,AX
+ MULQ 136(DI)
+ MOVQ AX,R10
+ MOVQ DX,R11
+ MOVQ 120(DI),AX
+ SHLQ $1,AX
+ MULQ 144(DI)
+ MOVQ AX,R12
+ MOVQ DX,R13
+ MOVQ 120(DI),AX
+ SHLQ $1,AX
+ MULQ 152(DI)
+ MOVQ AX,R14
+ MOVQ DX,R15
+ MOVQ 128(DI),AX
+ MULQ 128(DI)
+ ADDQ AX,R10
+ ADCQ DX,R11
+ MOVQ 128(DI),AX
+ SHLQ $1,AX
+ MULQ 136(DI)
+ ADDQ AX,R12
+ ADCQ DX,R13
+ MOVQ 128(DI),AX
+ SHLQ $1,AX
+ MULQ 144(DI)
+ ADDQ AX,R14
+ ADCQ DX,R15
+ MOVQ 128(DI),DX
+ IMUL3Q $38,DX,AX
+ MULQ 152(DI)
+ ADDQ AX,SI
+ ADCQ DX,CX
+ MOVQ 136(DI),AX
+ MULQ 136(DI)
+ ADDQ AX,R14
+ ADCQ DX,R15
+ MOVQ 136(DI),DX
+ IMUL3Q $38,DX,AX
+ MULQ 144(DI)
+ ADDQ AX,SI
+ ADCQ DX,CX
+ MOVQ 136(DI),DX
+ IMUL3Q $38,DX,AX
+ MULQ 152(DI)
+ ADDQ AX,R8
+ ADCQ DX,R9
+ MOVQ 144(DI),DX
+ IMUL3Q $19,DX,AX
+ MULQ 144(DI)
+ ADDQ AX,R8
+ ADCQ DX,R9
+ MOVQ 144(DI),DX
+ IMUL3Q $38,DX,AX
+ MULQ 152(DI)
+ ADDQ AX,R10
+ ADCQ DX,R11
+ MOVQ 152(DI),DX
+ IMUL3Q $19,DX,AX
+ MULQ 152(DI)
+ ADDQ AX,R12
+ ADCQ DX,R13
+ MOVQ $REDMASK51,DX
+ SHLQ $13,CX:SI
+ ANDQ DX,SI
+ SHLQ $13,R9:R8
+ ANDQ DX,R8
+ ADDQ CX,R8
+ SHLQ $13,R11:R10
+ ANDQ DX,R10
+ ADDQ R9,R10
+ SHLQ $13,R13:R12
+ ANDQ DX,R12
+ ADDQ R11,R12
+ SHLQ $13,R15:R14
+ ANDQ DX,R14
+ ADDQ R13,R14
+ IMUL3Q $19,R15,CX
+ ADDQ CX,SI
+ MOVQ SI,CX
+ SHRQ $51,CX
+ ADDQ R8,CX
+ ANDQ DX,SI
+ MOVQ CX,R8
+ SHRQ $51,CX
+ ADDQ R10,CX
+ ANDQ DX,R8
+ MOVQ CX,R9
+ SHRQ $51,CX
+ ADDQ R12,CX
+ ANDQ DX,R9
+ MOVQ CX,AX
+ SHRQ $51,CX
+ ADDQ R14,CX
+ ANDQ DX,AX
+ MOVQ CX,R10
+ SHRQ $51,CX
+ IMUL3Q $19,CX,CX
+ ADDQ CX,SI
+ ANDQ DX,R10
+ MOVQ SI,120(DI)
+ MOVQ R8,128(DI)
+ MOVQ R9,136(DI)
+ MOVQ AX,144(DI)
+ MOVQ R10,152(DI)
+ MOVQ 160(DI),AX
+ MULQ 160(DI)
+ MOVQ AX,SI
+ MOVQ DX,CX
+ MOVQ 160(DI),AX
+ SHLQ $1,AX
+ MULQ 168(DI)
+ MOVQ AX,R8
+ MOVQ DX,R9
+ MOVQ 160(DI),AX
+ SHLQ $1,AX
+ MULQ 176(DI)
+ MOVQ AX,R10
+ MOVQ DX,R11
+ MOVQ 160(DI),AX
+ SHLQ $1,AX
+ MULQ 184(DI)
+ MOVQ AX,R12
+ MOVQ DX,R13
+ MOVQ 160(DI),AX
+ SHLQ $1,AX
+ MULQ 192(DI)
+ MOVQ AX,R14
+ MOVQ DX,R15
+ MOVQ 168(DI),AX
+ MULQ 168(DI)
+ ADDQ AX,R10
+ ADCQ DX,R11
+ MOVQ 168(DI),AX
+ SHLQ $1,AX
+ MULQ 176(DI)
+ ADDQ AX,R12
+ ADCQ DX,R13
+ MOVQ 168(DI),AX
+ SHLQ $1,AX
+ MULQ 184(DI)
+ ADDQ AX,R14
+ ADCQ DX,R15
+ MOVQ 168(DI),DX
+ IMUL3Q $38,DX,AX
+ MULQ 192(DI)
+ ADDQ AX,SI
+ ADCQ DX,CX
+ MOVQ 176(DI),AX
+ MULQ 176(DI)
+ ADDQ AX,R14
+ ADCQ DX,R15
+ MOVQ 176(DI),DX
+ IMUL3Q $38,DX,AX
+ MULQ 184(DI)
+ ADDQ AX,SI
+ ADCQ DX,CX
+ MOVQ 176(DI),DX
+ IMUL3Q $38,DX,AX
+ MULQ 192(DI)
+ ADDQ AX,R8
+ ADCQ DX,R9
+ MOVQ 184(DI),DX
+ IMUL3Q $19,DX,AX
+ MULQ 184(DI)
+ ADDQ AX,R8
+ ADCQ DX,R9
+ MOVQ 184(DI),DX
+ IMUL3Q $38,DX,AX
+ MULQ 192(DI)
+ ADDQ AX,R10
+ ADCQ DX,R11
+ MOVQ 192(DI),DX
+ IMUL3Q $19,DX,AX
+ MULQ 192(DI)
+ ADDQ AX,R12
+ ADCQ DX,R13
+ MOVQ $REDMASK51,DX
+ SHLQ $13,CX:SI
+ ANDQ DX,SI
+ SHLQ $13,R9:R8
+ ANDQ DX,R8
+ ADDQ CX,R8
+ SHLQ $13,R11:R10
+ ANDQ DX,R10
+ ADDQ R9,R10
+ SHLQ $13,R13:R12
+ ANDQ DX,R12
+ ADDQ R11,R12
+ SHLQ $13,R15:R14
+ ANDQ DX,R14
+ ADDQ R13,R14
+ IMUL3Q $19,R15,CX
+ ADDQ CX,SI
+ MOVQ SI,CX
+ SHRQ $51,CX
+ ADDQ R8,CX
+ ANDQ DX,SI
+ MOVQ CX,R8
+ SHRQ $51,CX
+ ADDQ R10,CX
+ ANDQ DX,R8
+ MOVQ CX,R9
+ SHRQ $51,CX
+ ADDQ R12,CX
+ ANDQ DX,R9
+ MOVQ CX,AX
+ SHRQ $51,CX
+ ADDQ R14,CX
+ ANDQ DX,AX
+ MOVQ CX,R10
+ SHRQ $51,CX
+ IMUL3Q $19,CX,CX
+ ADDQ CX,SI
+ ANDQ DX,R10
+ MOVQ SI,160(DI)
+ MOVQ R8,168(DI)
+ MOVQ R9,176(DI)
+ MOVQ AX,184(DI)
+ MOVQ R10,192(DI)
+ MOVQ 184(DI),SI
+ IMUL3Q $19,SI,AX
+ MOVQ AX,0(SP)
+ MULQ 16(DI)
+ MOVQ AX,SI
+ MOVQ DX,CX
+ MOVQ 192(DI),DX
+ IMUL3Q $19,DX,AX
+ MOVQ AX,8(SP)
+ MULQ 8(DI)
+ ADDQ AX,SI
+ ADCQ DX,CX
+ MOVQ 160(DI),AX
+ MULQ 0(DI)
+ ADDQ AX,SI
+ ADCQ DX,CX
+ MOVQ 160(DI),AX
+ MULQ 8(DI)
+ MOVQ AX,R8
+ MOVQ DX,R9
+ MOVQ 160(DI),AX
+ MULQ 16(DI)
+ MOVQ AX,R10
+ MOVQ DX,R11
+ MOVQ 160(DI),AX
+ MULQ 24(DI)
+ MOVQ AX,R12
+ MOVQ DX,R13
+ MOVQ 160(DI),AX
+ MULQ 32(DI)
+ MOVQ AX,R14
+ MOVQ DX,R15
+ MOVQ 168(DI),AX
+ MULQ 0(DI)
+ ADDQ AX,R8
+ ADCQ DX,R9
+ MOVQ 168(DI),AX
+ MULQ 8(DI)
+ ADDQ AX,R10
+ ADCQ DX,R11
+ MOVQ 168(DI),AX
+ MULQ 16(DI)
+ ADDQ AX,R12
+ ADCQ DX,R13
+ MOVQ 168(DI),AX
+ MULQ 24(DI)
+ ADDQ AX,R14
+ ADCQ DX,R15
+ MOVQ 168(DI),DX
+ IMUL3Q $19,DX,AX
+ MULQ 32(DI)
+ ADDQ AX,SI
+ ADCQ DX,CX
+ MOVQ 176(DI),AX
+ MULQ 0(DI)
+ ADDQ AX,R10
+ ADCQ DX,R11
+ MOVQ 176(DI),AX
+ MULQ 8(DI)
+ ADDQ AX,R12
+ ADCQ DX,R13
+ MOVQ 176(DI),AX
+ MULQ 16(DI)
+ ADDQ AX,R14
+ ADCQ DX,R15
+ MOVQ 176(DI),DX
+ IMUL3Q $19,DX,AX
+ MULQ 24(DI)
+ ADDQ AX,SI
+ ADCQ DX,CX
+ MOVQ 176(DI),DX
+ IMUL3Q $19,DX,AX
+ MULQ 32(DI)
+ ADDQ AX,R8
+ ADCQ DX,R9
+ MOVQ 184(DI),AX
+ MULQ 0(DI)
+ ADDQ AX,R12
+ ADCQ DX,R13
+ MOVQ 184(DI),AX
+ MULQ 8(DI)
+ ADDQ AX,R14
+ ADCQ DX,R15
+ MOVQ 0(SP),AX
+ MULQ 24(DI)
+ ADDQ AX,R8
+ ADCQ DX,R9
+ MOVQ 0(SP),AX
+ MULQ 32(DI)
+ ADDQ AX,R10
+ ADCQ DX,R11
+ MOVQ 192(DI),AX
+ MULQ 0(DI)
+ ADDQ AX,R14
+ ADCQ DX,R15
+ MOVQ 8(SP),AX
+ MULQ 16(DI)
+ ADDQ AX,R8
+ ADCQ DX,R9
+ MOVQ 8(SP),AX
+ MULQ 24(DI)
+ ADDQ AX,R10
+ ADCQ DX,R11
+ MOVQ 8(SP),AX
+ MULQ 32(DI)
+ ADDQ AX,R12
+ ADCQ DX,R13
+ MOVQ $REDMASK51,DX
+ SHLQ $13,CX:SI
+ ANDQ DX,SI
+ SHLQ $13,R9:R8
+ ANDQ DX,R8
+ ADDQ CX,R8
+ SHLQ $13,R11:R10
+ ANDQ DX,R10
+ ADDQ R9,R10
+ SHLQ $13,R13:R12
+ ANDQ DX,R12
+ ADDQ R11,R12
+ SHLQ $13,R15:R14
+ ANDQ DX,R14
+ ADDQ R13,R14
+ IMUL3Q $19,R15,CX
+ ADDQ CX,SI
+ MOVQ SI,CX
+ SHRQ $51,CX
+ ADDQ R8,CX
+ MOVQ CX,R8
+ SHRQ $51,CX
+ ANDQ DX,SI
+ ADDQ R10,CX
+ MOVQ CX,R9
+ SHRQ $51,CX
+ ANDQ DX,R8
+ ADDQ R12,CX
+ MOVQ CX,AX
+ SHRQ $51,CX
+ ANDQ DX,R9
+ ADDQ R14,CX
+ MOVQ CX,R10
+ SHRQ $51,CX
+ ANDQ DX,AX
+ IMUL3Q $19,CX,CX
+ ADDQ CX,SI
+ ANDQ DX,R10
+ MOVQ SI,160(DI)
+ MOVQ R8,168(DI)
+ MOVQ R9,176(DI)
+ MOVQ AX,184(DI)
+ MOVQ R10,192(DI)
+ MOVQ 144(SP),SI
+ IMUL3Q $19,SI,AX
+ MOVQ AX,0(SP)
+ MULQ 96(SP)
+ MOVQ AX,SI
+ MOVQ DX,CX
+ MOVQ 152(SP),DX
+ IMUL3Q $19,DX,AX
+ MOVQ AX,8(SP)
+ MULQ 88(SP)
+ ADDQ AX,SI
+ ADCQ DX,CX
+ MOVQ 120(SP),AX
+ MULQ 80(SP)
+ ADDQ AX,SI
+ ADCQ DX,CX
+ MOVQ 120(SP),AX
+ MULQ 88(SP)
+ MOVQ AX,R8
+ MOVQ DX,R9
+ MOVQ 120(SP),AX
+ MULQ 96(SP)
+ MOVQ AX,R10
+ MOVQ DX,R11
+ MOVQ 120(SP),AX
+ MULQ 104(SP)
+ MOVQ AX,R12
+ MOVQ DX,R13
+ MOVQ 120(SP),AX
+ MULQ 112(SP)
+ MOVQ AX,R14
+ MOVQ DX,R15
+ MOVQ 128(SP),AX
+ MULQ 80(SP)
+ ADDQ AX,R8
+ ADCQ DX,R9
+ MOVQ 128(SP),AX
+ MULQ 88(SP)
+ ADDQ AX,R10
+ ADCQ DX,R11
+ MOVQ 128(SP),AX
+ MULQ 96(SP)
+ ADDQ AX,R12
+ ADCQ DX,R13
+ MOVQ 128(SP),AX
+ MULQ 104(SP)
+ ADDQ AX,R14
+ ADCQ DX,R15
+ MOVQ 128(SP),DX
+ IMUL3Q $19,DX,AX
+ MULQ 112(SP)
+ ADDQ AX,SI
+ ADCQ DX,CX
+ MOVQ 136(SP),AX
+ MULQ 80(SP)
+ ADDQ AX,R10
+ ADCQ DX,R11
+ MOVQ 136(SP),AX
+ MULQ 88(SP)
+ ADDQ AX,R12
+ ADCQ DX,R13
+ MOVQ 136(SP),AX
+ MULQ 96(SP)
+ ADDQ AX,R14
+ ADCQ DX,R15
+ MOVQ 136(SP),DX
+ IMUL3Q $19,DX,AX
+ MULQ 104(SP)
+ ADDQ AX,SI
+ ADCQ DX,CX
+ MOVQ 136(SP),DX
+ IMUL3Q $19,DX,AX
+ MULQ 112(SP)
+ ADDQ AX,R8
+ ADCQ DX,R9
+ MOVQ 144(SP),AX
+ MULQ 80(SP)
+ ADDQ AX,R12
+ ADCQ DX,R13
+ MOVQ 144(SP),AX
+ MULQ 88(SP)
+ ADDQ AX,R14
+ ADCQ DX,R15
+ MOVQ 0(SP),AX
+ MULQ 104(SP)
+ ADDQ AX,R8
+ ADCQ DX,R9
+ MOVQ 0(SP),AX
+ MULQ 112(SP)
+ ADDQ AX,R10
+ ADCQ DX,R11
+ MOVQ 152(SP),AX
+ MULQ 80(SP)
+ ADDQ AX,R14
+ ADCQ DX,R15
+ MOVQ 8(SP),AX
+ MULQ 96(SP)
+ ADDQ AX,R8
+ ADCQ DX,R9
+ MOVQ 8(SP),AX
+ MULQ 104(SP)
+ ADDQ AX,R10
+ ADCQ DX,R11
+ MOVQ 8(SP),AX
+ MULQ 112(SP)
+ ADDQ AX,R12
+ ADCQ DX,R13
+ MOVQ $REDMASK51,DX
+ SHLQ $13,CX:SI
+ ANDQ DX,SI
+ SHLQ $13,R9:R8
+ ANDQ DX,R8
+ ADDQ CX,R8
+ SHLQ $13,R11:R10
+ ANDQ DX,R10
+ ADDQ R9,R10
+ SHLQ $13,R13:R12
+ ANDQ DX,R12
+ ADDQ R11,R12
+ SHLQ $13,R15:R14
+ ANDQ DX,R14
+ ADDQ R13,R14
+ IMUL3Q $19,R15,CX
+ ADDQ CX,SI
+ MOVQ SI,CX
+ SHRQ $51,CX
+ ADDQ R8,CX
+ MOVQ CX,R8
+ SHRQ $51,CX
+ ANDQ DX,SI
+ ADDQ R10,CX
+ MOVQ CX,R9
+ SHRQ $51,CX
+ ANDQ DX,R8
+ ADDQ R12,CX
+ MOVQ CX,AX
+ SHRQ $51,CX
+ ANDQ DX,R9
+ ADDQ R14,CX
+ MOVQ CX,R10
+ SHRQ $51,CX
+ ANDQ DX,AX
+ IMUL3Q $19,CX,CX
+ ADDQ CX,SI
+ ANDQ DX,R10
+ MOVQ SI,40(DI)
+ MOVQ R8,48(DI)
+ MOVQ R9,56(DI)
+ MOVQ AX,64(DI)
+ MOVQ R10,72(DI)
+ MOVQ 160(SP),AX
+ MULQ ·_121666_213(SB)
+ SHRQ $13,AX
+ MOVQ AX,SI
+ MOVQ DX,CX
+ MOVQ 168(SP),AX
+ MULQ ·_121666_213(SB)
+ SHRQ $13,AX
+ ADDQ AX,CX
+ MOVQ DX,R8
+ MOVQ 176(SP),AX
+ MULQ ·_121666_213(SB)
+ SHRQ $13,AX
+ ADDQ AX,R8
+ MOVQ DX,R9
+ MOVQ 184(SP),AX
+ MULQ ·_121666_213(SB)
+ SHRQ $13,AX
+ ADDQ AX,R9
+ MOVQ DX,R10
+ MOVQ 192(SP),AX
+ MULQ ·_121666_213(SB)
+ SHRQ $13,AX
+ ADDQ AX,R10
+ IMUL3Q $19,DX,DX
+ ADDQ DX,SI
+ ADDQ 80(SP),SI
+ ADDQ 88(SP),CX
+ ADDQ 96(SP),R8
+ ADDQ 104(SP),R9
+ ADDQ 112(SP),R10
+ MOVQ SI,80(DI)
+ MOVQ CX,88(DI)
+ MOVQ R8,96(DI)
+ MOVQ R9,104(DI)
+ MOVQ R10,112(DI)
+ MOVQ 104(DI),SI
+ IMUL3Q $19,SI,AX
+ MOVQ AX,0(SP)
+ MULQ 176(SP)
+ MOVQ AX,SI
+ MOVQ DX,CX
+ MOVQ 112(DI),DX
+ IMUL3Q $19,DX,AX
+ MOVQ AX,8(SP)
+ MULQ 168(SP)
+ ADDQ AX,SI
+ ADCQ DX,CX
+ MOVQ 80(DI),AX
+ MULQ 160(SP)
+ ADDQ AX,SI
+ ADCQ DX,CX
+ MOVQ 80(DI),AX
+ MULQ 168(SP)
+ MOVQ AX,R8
+ MOVQ DX,R9
+ MOVQ 80(DI),AX
+ MULQ 176(SP)
+ MOVQ AX,R10
+ MOVQ DX,R11
+ MOVQ 80(DI),AX
+ MULQ 184(SP)
+ MOVQ AX,R12
+ MOVQ DX,R13
+ MOVQ 80(DI),AX
+ MULQ 192(SP)
+ MOVQ AX,R14
+ MOVQ DX,R15
+ MOVQ 88(DI),AX
+ MULQ 160(SP)
+ ADDQ AX,R8
+ ADCQ DX,R9
+ MOVQ 88(DI),AX
+ MULQ 168(SP)
+ ADDQ AX,R10
+ ADCQ DX,R11
+ MOVQ 88(DI),AX
+ MULQ 176(SP)
+ ADDQ AX,R12
+ ADCQ DX,R13
+ MOVQ 88(DI),AX
+ MULQ 184(SP)
+ ADDQ AX,R14
+ ADCQ DX,R15
+ MOVQ 88(DI),DX
+ IMUL3Q $19,DX,AX
+ MULQ 192(SP)
+ ADDQ AX,SI
+ ADCQ DX,CX
+ MOVQ 96(DI),AX
+ MULQ 160(SP)
+ ADDQ AX,R10
+ ADCQ DX,R11
+ MOVQ 96(DI),AX
+ MULQ 168(SP)
+ ADDQ AX,R12
+ ADCQ DX,R13
+ MOVQ 96(DI),AX
+ MULQ 176(SP)
+ ADDQ AX,R14
+ ADCQ DX,R15
+ MOVQ 96(DI),DX
+ IMUL3Q $19,DX,AX
+ MULQ 184(SP)
+ ADDQ AX,SI
+ ADCQ DX,CX
+ MOVQ 96(DI),DX
+ IMUL3Q $19,DX,AX
+ MULQ 192(SP)
+ ADDQ AX,R8
+ ADCQ DX,R9
+ MOVQ 104(DI),AX
+ MULQ 160(SP)
+ ADDQ AX,R12
+ ADCQ DX,R13
+ MOVQ 104(DI),AX
+ MULQ 168(SP)
+ ADDQ AX,R14
+ ADCQ DX,R15
+ MOVQ 0(SP),AX
+ MULQ 184(SP)
+ ADDQ AX,R8
+ ADCQ DX,R9
+ MOVQ 0(SP),AX
+ MULQ 192(SP)
+ ADDQ AX,R10
+ ADCQ DX,R11
+ MOVQ 112(DI),AX
+ MULQ 160(SP)
+ ADDQ AX,R14
+ ADCQ DX,R15
+ MOVQ 8(SP),AX
+ MULQ 176(SP)
+ ADDQ AX,R8
+ ADCQ DX,R9
+ MOVQ 8(SP),AX
+ MULQ 184(SP)
+ ADDQ AX,R10
+ ADCQ DX,R11
+ MOVQ 8(SP),AX
+ MULQ 192(SP)
+ ADDQ AX,R12
+ ADCQ DX,R13
+ MOVQ $REDMASK51,DX
+ SHLQ $13,CX:SI
+ ANDQ DX,SI
+ SHLQ $13,R9:R8
+ ANDQ DX,R8
+ ADDQ CX,R8
+ SHLQ $13,R11:R10
+ ANDQ DX,R10
+ ADDQ R9,R10
+ SHLQ $13,R13:R12
+ ANDQ DX,R12
+ ADDQ R11,R12
+ SHLQ $13,R15:R14
+ ANDQ DX,R14
+ ADDQ R13,R14
+ IMUL3Q $19,R15,CX
+ ADDQ CX,SI
+ MOVQ SI,CX
+ SHRQ $51,CX
+ ADDQ R8,CX
+ MOVQ CX,R8
+ SHRQ $51,CX
+ ANDQ DX,SI
+ ADDQ R10,CX
+ MOVQ CX,R9
+ SHRQ $51,CX
+ ANDQ DX,R8
+ ADDQ R12,CX
+ MOVQ CX,AX
+ SHRQ $51,CX
+ ANDQ DX,R9
+ ADDQ R14,CX
+ MOVQ CX,R10
+ SHRQ $51,CX
+ ANDQ DX,AX
+ IMUL3Q $19,CX,CX
+ ADDQ CX,SI
+ ANDQ DX,R10
+ MOVQ SI,80(DI)
+ MOVQ R8,88(DI)
+ MOVQ R9,96(DI)
+ MOVQ AX,104(DI)
+ MOVQ R10,112(DI)
+ RET
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/curve25519/mont25519_amd64.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/curve25519/mont25519_amd64.go
new file mode 100644
index 000000000..5822bd533
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/curve25519/mont25519_amd64.go
@@ -0,0 +1,240 @@
+// Copyright 2012 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.
+
+// +build amd64,!gccgo,!appengine
+
+package curve25519
+
+// These functions are implemented in the .s files. The names of the functions
+// in the rest of the file are also taken from the SUPERCOP sources to help
+// people following along.
+
+//go:noescape
+
+func cswap(inout *[5]uint64, v uint64)
+
+//go:noescape
+
+func ladderstep(inout *[5][5]uint64)
+
+//go:noescape
+
+func freeze(inout *[5]uint64)
+
+//go:noescape
+
+func mul(dest, a, b *[5]uint64)
+
+//go:noescape
+
+func square(out, in *[5]uint64)
+
+// mladder uses a Montgomery ladder to calculate (xr/zr) *= s.
+func mladder(xr, zr *[5]uint64, s *[32]byte) {
+ var work [5][5]uint64
+
+ work[0] = *xr
+ setint(&work[1], 1)
+ setint(&work[2], 0)
+ work[3] = *xr
+ setint(&work[4], 1)
+
+ j := uint(6)
+ var prevbit byte
+
+ for i := 31; i >= 0; i-- {
+ for j < 8 {
+ bit := ((*s)[i] >> j) & 1
+ swap := bit ^ prevbit
+ prevbit = bit
+ cswap(&work[1], uint64(swap))
+ ladderstep(&work)
+ j--
+ }
+ j = 7
+ }
+
+ *xr = work[1]
+ *zr = work[2]
+}
+
+func scalarMult(out, in, base *[32]byte) {
+ var e [32]byte
+ copy(e[:], (*in)[:])
+ e[0] &= 248
+ e[31] &= 127
+ e[31] |= 64
+
+ var t, z [5]uint64
+ unpack(&t, base)
+ mladder(&t, &z, &e)
+ invert(&z, &z)
+ mul(&t, &t, &z)
+ pack(out, &t)
+}
+
+func setint(r *[5]uint64, v uint64) {
+ r[0] = v
+ r[1] = 0
+ r[2] = 0
+ r[3] = 0
+ r[4] = 0
+}
+
+// unpack sets r = x where r consists of 5, 51-bit limbs in little-endian
+// order.
+func unpack(r *[5]uint64, x *[32]byte) {
+ r[0] = uint64(x[0]) |
+ uint64(x[1])<<8 |
+ uint64(x[2])<<16 |
+ uint64(x[3])<<24 |
+ uint64(x[4])<<32 |
+ uint64(x[5])<<40 |
+ uint64(x[6]&7)<<48
+
+ r[1] = uint64(x[6])>>3 |
+ uint64(x[7])<<5 |
+ uint64(x[8])<<13 |
+ uint64(x[9])<<21 |
+ uint64(x[10])<<29 |
+ uint64(x[11])<<37 |
+ uint64(x[12]&63)<<45
+
+ r[2] = uint64(x[12])>>6 |
+ uint64(x[13])<<2 |
+ uint64(x[14])<<10 |
+ uint64(x[15])<<18 |
+ uint64(x[16])<<26 |
+ uint64(x[17])<<34 |
+ uint64(x[18])<<42 |
+ uint64(x[19]&1)<<50
+
+ r[3] = uint64(x[19])>>1 |
+ uint64(x[20])<<7 |
+ uint64(x[21])<<15 |
+ uint64(x[22])<<23 |
+ uint64(x[23])<<31 |
+ uint64(x[24])<<39 |
+ uint64(x[25]&15)<<47
+
+ r[4] = uint64(x[25])>>4 |
+ uint64(x[26])<<4 |
+ uint64(x[27])<<12 |
+ uint64(x[28])<<20 |
+ uint64(x[29])<<28 |
+ uint64(x[30])<<36 |
+ uint64(x[31]&127)<<44
+}
+
+// pack sets out = x where out is the usual, little-endian form of the 5,
+// 51-bit limbs in x.
+func pack(out *[32]byte, x *[5]uint64) {
+ t := *x
+ freeze(&t)
+
+ out[0] = byte(t[0])
+ out[1] = byte(t[0] >> 8)
+ out[2] = byte(t[0] >> 16)
+ out[3] = byte(t[0] >> 24)
+ out[4] = byte(t[0] >> 32)
+ out[5] = byte(t[0] >> 40)
+ out[6] = byte(t[0] >> 48)
+
+ out[6] ^= byte(t[1]<<3) & 0xf8
+ out[7] = byte(t[1] >> 5)
+ out[8] = byte(t[1] >> 13)
+ out[9] = byte(t[1] >> 21)
+ out[10] = byte(t[1] >> 29)
+ out[11] = byte(t[1] >> 37)
+ out[12] = byte(t[1] >> 45)
+
+ out[12] ^= byte(t[2]<<6) & 0xc0
+ out[13] = byte(t[2] >> 2)
+ out[14] = byte(t[2] >> 10)
+ out[15] = byte(t[2] >> 18)
+ out[16] = byte(t[2] >> 26)
+ out[17] = byte(t[2] >> 34)
+ out[18] = byte(t[2] >> 42)
+ out[19] = byte(t[2] >> 50)
+
+ out[19] ^= byte(t[3]<<1) & 0xfe
+ out[20] = byte(t[3] >> 7)
+ out[21] = byte(t[3] >> 15)
+ out[22] = byte(t[3] >> 23)
+ out[23] = byte(t[3] >> 31)
+ out[24] = byte(t[3] >> 39)
+ out[25] = byte(t[3] >> 47)
+
+ out[25] ^= byte(t[4]<<4) & 0xf0
+ out[26] = byte(t[4] >> 4)
+ out[27] = byte(t[4] >> 12)
+ out[28] = byte(t[4] >> 20)
+ out[29] = byte(t[4] >> 28)
+ out[30] = byte(t[4] >> 36)
+ out[31] = byte(t[4] >> 44)
+}
+
+// invert calculates r = x^-1 mod p using Fermat's little theorem.
+func invert(r *[5]uint64, x *[5]uint64) {
+ var z2, z9, z11, z2_5_0, z2_10_0, z2_20_0, z2_50_0, z2_100_0, t [5]uint64
+
+ square(&z2, x) /* 2 */
+ square(&t, &z2) /* 4 */
+ square(&t, &t) /* 8 */
+ mul(&z9, &t, x) /* 9 */
+ mul(&z11, &z9, &z2) /* 11 */
+ square(&t, &z11) /* 22 */
+ mul(&z2_5_0, &t, &z9) /* 2^5 - 2^0 = 31 */
+
+ square(&t, &z2_5_0) /* 2^6 - 2^1 */
+ for i := 1; i < 5; i++ { /* 2^20 - 2^10 */
+ square(&t, &t)
+ }
+ mul(&z2_10_0, &t, &z2_5_0) /* 2^10 - 2^0 */
+
+ square(&t, &z2_10_0) /* 2^11 - 2^1 */
+ for i := 1; i < 10; i++ { /* 2^20 - 2^10 */
+ square(&t, &t)
+ }
+ mul(&z2_20_0, &t, &z2_10_0) /* 2^20 - 2^0 */
+
+ square(&t, &z2_20_0) /* 2^21 - 2^1 */
+ for i := 1; i < 20; i++ { /* 2^40 - 2^20 */
+ square(&t, &t)
+ }
+ mul(&t, &t, &z2_20_0) /* 2^40 - 2^0 */
+
+ square(&t, &t) /* 2^41 - 2^1 */
+ for i := 1; i < 10; i++ { /* 2^50 - 2^10 */
+ square(&t, &t)
+ }
+ mul(&z2_50_0, &t, &z2_10_0) /* 2^50 - 2^0 */
+
+ square(&t, &z2_50_0) /* 2^51 - 2^1 */
+ for i := 1; i < 50; i++ { /* 2^100 - 2^50 */
+ square(&t, &t)
+ }
+ mul(&z2_100_0, &t, &z2_50_0) /* 2^100 - 2^0 */
+
+ square(&t, &z2_100_0) /* 2^101 - 2^1 */
+ for i := 1; i < 100; i++ { /* 2^200 - 2^100 */
+ square(&t, &t)
+ }
+ mul(&t, &t, &z2_100_0) /* 2^200 - 2^0 */
+
+ square(&t, &t) /* 2^201 - 2^1 */
+ for i := 1; i < 50; i++ { /* 2^250 - 2^50 */
+ square(&t, &t)
+ }
+ mul(&t, &t, &z2_50_0) /* 2^250 - 2^0 */
+
+ square(&t, &t) /* 2^251 - 2^1 */
+ square(&t, &t) /* 2^252 - 2^2 */
+ square(&t, &t) /* 2^253 - 2^3 */
+
+ square(&t, &t) /* 2^254 - 2^4 */
+
+ square(&t, &t) /* 2^255 - 2^5 */
+ mul(r, &t, &z11) /* 2^255 - 21 */
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/curve25519/mul_amd64.s b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/curve25519/mul_amd64.s
new file mode 100644
index 000000000..5ce80a2e5
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/curve25519/mul_amd64.s
@@ -0,0 +1,169 @@
+// Copyright 2012 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.
+
+// This code was translated into a form compatible with 6a from the public
+// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html
+
+// +build amd64,!gccgo,!appengine
+
+#include "const_amd64.h"
+
+// func mul(dest, a, b *[5]uint64)
+TEXT ·mul(SB),0,$16-24
+ MOVQ dest+0(FP), DI
+ MOVQ a+8(FP), SI
+ MOVQ b+16(FP), DX
+
+ MOVQ DX,CX
+ MOVQ 24(SI),DX
+ IMUL3Q $19,DX,AX
+ MOVQ AX,0(SP)
+ MULQ 16(CX)
+ MOVQ AX,R8
+ MOVQ DX,R9
+ MOVQ 32(SI),DX
+ IMUL3Q $19,DX,AX
+ MOVQ AX,8(SP)
+ MULQ 8(CX)
+ ADDQ AX,R8
+ ADCQ DX,R9
+ MOVQ 0(SI),AX
+ MULQ 0(CX)
+ ADDQ AX,R8
+ ADCQ DX,R9
+ MOVQ 0(SI),AX
+ MULQ 8(CX)
+ MOVQ AX,R10
+ MOVQ DX,R11
+ MOVQ 0(SI),AX
+ MULQ 16(CX)
+ MOVQ AX,R12
+ MOVQ DX,R13
+ MOVQ 0(SI),AX
+ MULQ 24(CX)
+ MOVQ AX,R14
+ MOVQ DX,R15
+ MOVQ 0(SI),AX
+ MULQ 32(CX)
+ MOVQ AX,BX
+ MOVQ DX,BP
+ MOVQ 8(SI),AX
+ MULQ 0(CX)
+ ADDQ AX,R10
+ ADCQ DX,R11
+ MOVQ 8(SI),AX
+ MULQ 8(CX)
+ ADDQ AX,R12
+ ADCQ DX,R13
+ MOVQ 8(SI),AX
+ MULQ 16(CX)
+ ADDQ AX,R14
+ ADCQ DX,R15
+ MOVQ 8(SI),AX
+ MULQ 24(CX)
+ ADDQ AX,BX
+ ADCQ DX,BP
+ MOVQ 8(SI),DX
+ IMUL3Q $19,DX,AX
+ MULQ 32(CX)
+ ADDQ AX,R8
+ ADCQ DX,R9
+ MOVQ 16(SI),AX
+ MULQ 0(CX)
+ ADDQ AX,R12
+ ADCQ DX,R13
+ MOVQ 16(SI),AX
+ MULQ 8(CX)
+ ADDQ AX,R14
+ ADCQ DX,R15
+ MOVQ 16(SI),AX
+ MULQ 16(CX)
+ ADDQ AX,BX
+ ADCQ DX,BP
+ MOVQ 16(SI),DX
+ IMUL3Q $19,DX,AX
+ MULQ 24(CX)
+ ADDQ AX,R8
+ ADCQ DX,R9
+ MOVQ 16(SI),DX
+ IMUL3Q $19,DX,AX
+ MULQ 32(CX)
+ ADDQ AX,R10
+ ADCQ DX,R11
+ MOVQ 24(SI),AX
+ MULQ 0(CX)
+ ADDQ AX,R14
+ ADCQ DX,R15
+ MOVQ 24(SI),AX
+ MULQ 8(CX)
+ ADDQ AX,BX
+ ADCQ DX,BP
+ MOVQ 0(SP),AX
+ MULQ 24(CX)
+ ADDQ AX,R10
+ ADCQ DX,R11
+ MOVQ 0(SP),AX
+ MULQ 32(CX)
+ ADDQ AX,R12
+ ADCQ DX,R13
+ MOVQ 32(SI),AX
+ MULQ 0(CX)
+ ADDQ AX,BX
+ ADCQ DX,BP
+ MOVQ 8(SP),AX
+ MULQ 16(CX)
+ ADDQ AX,R10
+ ADCQ DX,R11
+ MOVQ 8(SP),AX
+ MULQ 24(CX)
+ ADDQ AX,R12
+ ADCQ DX,R13
+ MOVQ 8(SP),AX
+ MULQ 32(CX)
+ ADDQ AX,R14
+ ADCQ DX,R15
+ MOVQ $REDMASK51,SI
+ SHLQ $13,R9:R8
+ ANDQ SI,R8
+ SHLQ $13,R11:R10
+ ANDQ SI,R10
+ ADDQ R9,R10
+ SHLQ $13,R13:R12
+ ANDQ SI,R12
+ ADDQ R11,R12
+ SHLQ $13,R15:R14
+ ANDQ SI,R14
+ ADDQ R13,R14
+ SHLQ $13,BP:BX
+ ANDQ SI,BX
+ ADDQ R15,BX
+ IMUL3Q $19,BP,DX
+ ADDQ DX,R8
+ MOVQ R8,DX
+ SHRQ $51,DX
+ ADDQ R10,DX
+ MOVQ DX,CX
+ SHRQ $51,DX
+ ANDQ SI,R8
+ ADDQ R12,DX
+ MOVQ DX,R9
+ SHRQ $51,DX
+ ANDQ SI,CX
+ ADDQ R14,DX
+ MOVQ DX,AX
+ SHRQ $51,DX
+ ANDQ SI,R9
+ ADDQ BX,DX
+ MOVQ DX,R10
+ SHRQ $51,DX
+ ANDQ SI,AX
+ IMUL3Q $19,DX,DX
+ ADDQ DX,R8
+ ANDQ SI,R10
+ MOVQ R8,0(DI)
+ MOVQ CX,8(DI)
+ MOVQ R9,16(DI)
+ MOVQ AX,24(DI)
+ MOVQ R10,32(DI)
+ RET
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/curve25519/square_amd64.s b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/curve25519/square_amd64.s
new file mode 100644
index 000000000..12f73734f
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/curve25519/square_amd64.s
@@ -0,0 +1,132 @@
+// Copyright 2012 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.
+
+// This code was translated into a form compatible with 6a from the public
+// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html
+
+// +build amd64,!gccgo,!appengine
+
+#include "const_amd64.h"
+
+// func square(out, in *[5]uint64)
+TEXT ·square(SB),7,$0-16
+ MOVQ out+0(FP), DI
+ MOVQ in+8(FP), SI
+
+ MOVQ 0(SI),AX
+ MULQ 0(SI)
+ MOVQ AX,CX
+ MOVQ DX,R8
+ MOVQ 0(SI),AX
+ SHLQ $1,AX
+ MULQ 8(SI)
+ MOVQ AX,R9
+ MOVQ DX,R10
+ MOVQ 0(SI),AX
+ SHLQ $1,AX
+ MULQ 16(SI)
+ MOVQ AX,R11
+ MOVQ DX,R12
+ MOVQ 0(SI),AX
+ SHLQ $1,AX
+ MULQ 24(SI)
+ MOVQ AX,R13
+ MOVQ DX,R14
+ MOVQ 0(SI),AX
+ SHLQ $1,AX
+ MULQ 32(SI)
+ MOVQ AX,R15
+ MOVQ DX,BX
+ MOVQ 8(SI),AX
+ MULQ 8(SI)
+ ADDQ AX,R11
+ ADCQ DX,R12
+ MOVQ 8(SI),AX
+ SHLQ $1,AX
+ MULQ 16(SI)
+ ADDQ AX,R13
+ ADCQ DX,R14
+ MOVQ 8(SI),AX
+ SHLQ $1,AX
+ MULQ 24(SI)
+ ADDQ AX,R15
+ ADCQ DX,BX
+ MOVQ 8(SI),DX
+ IMUL3Q $38,DX,AX
+ MULQ 32(SI)
+ ADDQ AX,CX
+ ADCQ DX,R8
+ MOVQ 16(SI),AX
+ MULQ 16(SI)
+ ADDQ AX,R15
+ ADCQ DX,BX
+ MOVQ 16(SI),DX
+ IMUL3Q $38,DX,AX
+ MULQ 24(SI)
+ ADDQ AX,CX
+ ADCQ DX,R8
+ MOVQ 16(SI),DX
+ IMUL3Q $38,DX,AX
+ MULQ 32(SI)
+ ADDQ AX,R9
+ ADCQ DX,R10
+ MOVQ 24(SI),DX
+ IMUL3Q $19,DX,AX
+ MULQ 24(SI)
+ ADDQ AX,R9
+ ADCQ DX,R10
+ MOVQ 24(SI),DX
+ IMUL3Q $38,DX,AX
+ MULQ 32(SI)
+ ADDQ AX,R11
+ ADCQ DX,R12
+ MOVQ 32(SI),DX
+ IMUL3Q $19,DX,AX
+ MULQ 32(SI)
+ ADDQ AX,R13
+ ADCQ DX,R14
+ MOVQ $REDMASK51,SI
+ SHLQ $13,R8:CX
+ ANDQ SI,CX
+ SHLQ $13,R10:R9
+ ANDQ SI,R9
+ ADDQ R8,R9
+ SHLQ $13,R12:R11
+ ANDQ SI,R11
+ ADDQ R10,R11
+ SHLQ $13,R14:R13
+ ANDQ SI,R13
+ ADDQ R12,R13
+ SHLQ $13,BX:R15
+ ANDQ SI,R15
+ ADDQ R14,R15
+ IMUL3Q $19,BX,DX
+ ADDQ DX,CX
+ MOVQ CX,DX
+ SHRQ $51,DX
+ ADDQ R9,DX
+ ANDQ SI,CX
+ MOVQ DX,R8
+ SHRQ $51,DX
+ ADDQ R11,DX
+ ANDQ SI,R8
+ MOVQ DX,R9
+ SHRQ $51,DX
+ ADDQ R13,DX
+ ANDQ SI,R9
+ MOVQ DX,AX
+ SHRQ $51,DX
+ ADDQ R15,DX
+ ANDQ SI,AX
+ MOVQ DX,R10
+ SHRQ $51,DX
+ IMUL3Q $19,DX,DX
+ ADDQ DX,CX
+ ANDQ SI,R10
+ MOVQ CX,0(DI)
+ MOVQ R8,8(DI)
+ MOVQ R9,16(DI)
+ MOVQ AX,24(DI)
+ MOVQ R10,32(DI)
+ RET
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ed25519/ed25519.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ed25519/ed25519.go
new file mode 100644
index 000000000..4f26b49b6
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ed25519/ed25519.go
@@ -0,0 +1,181 @@
+// 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.
+
+// Package ed25519 implements the Ed25519 signature algorithm. See
+// https://ed25519.cr.yp.to/.
+//
+// These functions are also compatible with the “Ed25519” function defined in
+// RFC 8032.
+package ed25519
+
+// This code is a port of the public domain, “ref10” implementation of ed25519
+// from SUPERCOP.
+
+import (
+ "bytes"
+ "crypto"
+ cryptorand "crypto/rand"
+ "crypto/sha512"
+ "errors"
+ "io"
+ "strconv"
+
+ "golang.org/x/crypto/ed25519/internal/edwards25519"
+)
+
+const (
+ // PublicKeySize is the size, in bytes, of public keys as used in this package.
+ PublicKeySize = 32
+ // PrivateKeySize is the size, in bytes, of private keys as used in this package.
+ PrivateKeySize = 64
+ // SignatureSize is the size, in bytes, of signatures generated and verified by this package.
+ SignatureSize = 64
+)
+
+// PublicKey is the type of Ed25519 public keys.
+type PublicKey []byte
+
+// PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer.
+type PrivateKey []byte
+
+// Public returns the PublicKey corresponding to priv.
+func (priv PrivateKey) Public() crypto.PublicKey {
+ publicKey := make([]byte, PublicKeySize)
+ copy(publicKey, priv[32:])
+ return PublicKey(publicKey)
+}
+
+// Sign signs the given message with priv.
+// Ed25519 performs two passes over messages to be signed and therefore cannot
+// handle pre-hashed messages. Thus opts.HashFunc() must return zero to
+// indicate the message hasn't been hashed. This can be achieved by passing
+// crypto.Hash(0) as the value for opts.
+func (priv PrivateKey) Sign(rand io.Reader, message []byte, opts crypto.SignerOpts) (signature []byte, err error) {
+ if opts.HashFunc() != crypto.Hash(0) {
+ return nil, errors.New("ed25519: cannot sign hashed message")
+ }
+
+ return Sign(priv, message), nil
+}
+
+// GenerateKey generates a public/private key pair using entropy from rand.
+// If rand is nil, crypto/rand.Reader will be used.
+func GenerateKey(rand io.Reader) (publicKey PublicKey, privateKey PrivateKey, err error) {
+ if rand == nil {
+ rand = cryptorand.Reader
+ }
+
+ privateKey = make([]byte, PrivateKeySize)
+ publicKey = make([]byte, PublicKeySize)
+ _, err = io.ReadFull(rand, privateKey[:32])
+ if err != nil {
+ return nil, nil, err
+ }
+
+ digest := sha512.Sum512(privateKey[:32])
+ digest[0] &= 248
+ digest[31] &= 127
+ digest[31] |= 64
+
+ var A edwards25519.ExtendedGroupElement
+ var hBytes [32]byte
+ copy(hBytes[:], digest[:])
+ edwards25519.GeScalarMultBase(&A, &hBytes)
+ var publicKeyBytes [32]byte
+ A.ToBytes(&publicKeyBytes)
+
+ copy(privateKey[32:], publicKeyBytes[:])
+ copy(publicKey, publicKeyBytes[:])
+
+ return publicKey, privateKey, nil
+}
+
+// Sign signs the message with privateKey and returns a signature. It will
+// panic if len(privateKey) is not PrivateKeySize.
+func Sign(privateKey PrivateKey, message []byte) []byte {
+ if l := len(privateKey); l != PrivateKeySize {
+ panic("ed25519: bad private key length: " + strconv.Itoa(l))
+ }
+
+ h := sha512.New()
+ h.Write(privateKey[:32])
+
+ var digest1, messageDigest, hramDigest [64]byte
+ var expandedSecretKey [32]byte
+ h.Sum(digest1[:0])
+ copy(expandedSecretKey[:], digest1[:])
+ expandedSecretKey[0] &= 248
+ expandedSecretKey[31] &= 63
+ expandedSecretKey[31] |= 64
+
+ h.Reset()
+ h.Write(digest1[32:])
+ h.Write(message)
+ h.Sum(messageDigest[:0])
+
+ var messageDigestReduced [32]byte
+ edwards25519.ScReduce(&messageDigestReduced, &messageDigest)
+ var R edwards25519.ExtendedGroupElement
+ edwards25519.GeScalarMultBase(&R, &messageDigestReduced)
+
+ var encodedR [32]byte
+ R.ToBytes(&encodedR)
+
+ h.Reset()
+ h.Write(encodedR[:])
+ h.Write(privateKey[32:])
+ h.Write(message)
+ h.Sum(hramDigest[:0])
+ var hramDigestReduced [32]byte
+ edwards25519.ScReduce(&hramDigestReduced, &hramDigest)
+
+ var s [32]byte
+ edwards25519.ScMulAdd(&s, &hramDigestReduced, &expandedSecretKey, &messageDigestReduced)
+
+ signature := make([]byte, SignatureSize)
+ copy(signature[:], encodedR[:])
+ copy(signature[32:], s[:])
+
+ return signature
+}
+
+// Verify reports whether sig is a valid signature of message by publicKey. It
+// will panic if len(publicKey) is not PublicKeySize.
+func Verify(publicKey PublicKey, message, sig []byte) bool {
+ if l := len(publicKey); l != PublicKeySize {
+ panic("ed25519: bad public key length: " + strconv.Itoa(l))
+ }
+
+ if len(sig) != SignatureSize || sig[63]&224 != 0 {
+ return false
+ }
+
+ var A edwards25519.ExtendedGroupElement
+ var publicKeyBytes [32]byte
+ copy(publicKeyBytes[:], publicKey)
+ if !A.FromBytes(&publicKeyBytes) {
+ return false
+ }
+ edwards25519.FeNeg(&A.X, &A.X)
+ edwards25519.FeNeg(&A.T, &A.T)
+
+ h := sha512.New()
+ h.Write(sig[:32])
+ h.Write(publicKey[:])
+ h.Write(message)
+ var digest [64]byte
+ h.Sum(digest[:0])
+
+ var hReduced [32]byte
+ edwards25519.ScReduce(&hReduced, &digest)
+
+ var R edwards25519.ProjectiveGroupElement
+ var b [32]byte
+ copy(b[:], sig[32:])
+ edwards25519.GeDoubleScalarMultVartime(&R, &hReduced, &A, &b)
+
+ var checkR [32]byte
+ R.ToBytes(&checkR)
+ return bytes.Equal(sig[:32], checkR[:])
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ed25519/ed25519_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ed25519/ed25519_test.go
new file mode 100644
index 000000000..e272f8a55
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ed25519/ed25519_test.go
@@ -0,0 +1,183 @@
+// 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.
+
+package ed25519
+
+import (
+ "bufio"
+ "bytes"
+ "compress/gzip"
+ "crypto"
+ "crypto/rand"
+ "encoding/hex"
+ "os"
+ "strings"
+ "testing"
+
+ "golang.org/x/crypto/ed25519/internal/edwards25519"
+)
+
+type zeroReader struct{}
+
+func (zeroReader) Read(buf []byte) (int, error) {
+ for i := range buf {
+ buf[i] = 0
+ }
+ return len(buf), nil
+}
+
+func TestUnmarshalMarshal(t *testing.T) {
+ pub, _, _ := GenerateKey(rand.Reader)
+
+ var A edwards25519.ExtendedGroupElement
+ var pubBytes [32]byte
+ copy(pubBytes[:], pub)
+ if !A.FromBytes(&pubBytes) {
+ t.Fatalf("ExtendedGroupElement.FromBytes failed")
+ }
+
+ var pub2 [32]byte
+ A.ToBytes(&pub2)
+
+ if pubBytes != pub2 {
+ t.Errorf("FromBytes(%v)->ToBytes does not round-trip, got %x\n", pubBytes, pub2)
+ }
+}
+
+func TestSignVerify(t *testing.T) {
+ var zero zeroReader
+ public, private, _ := GenerateKey(zero)
+
+ message := []byte("test message")
+ sig := Sign(private, message)
+ if !Verify(public, message, sig) {
+ t.Errorf("valid signature rejected")
+ }
+
+ wrongMessage := []byte("wrong message")
+ if Verify(public, wrongMessage, sig) {
+ t.Errorf("signature of different message accepted")
+ }
+}
+
+func TestCryptoSigner(t *testing.T) {
+ var zero zeroReader
+ public, private, _ := GenerateKey(zero)
+
+ signer := crypto.Signer(private)
+
+ publicInterface := signer.Public()
+ public2, ok := publicInterface.(PublicKey)
+ if !ok {
+ t.Fatalf("expected PublicKey from Public() but got %T", publicInterface)
+ }
+
+ if !bytes.Equal(public, public2) {
+ t.Errorf("public keys do not match: original:%x vs Public():%x", public, public2)
+ }
+
+ message := []byte("message")
+ var noHash crypto.Hash
+ signature, err := signer.Sign(zero, message, noHash)
+ if err != nil {
+ t.Fatalf("error from Sign(): %s", err)
+ }
+
+ if !Verify(public, message, signature) {
+ t.Errorf("Verify failed on signature from Sign()")
+ }
+}
+
+func TestGolden(t *testing.T) {
+ // sign.input.gz is a selection of test cases from
+ // https://ed25519.cr.yp.to/python/sign.input
+ testDataZ, err := os.Open("testdata/sign.input.gz")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer testDataZ.Close()
+ testData, err := gzip.NewReader(testDataZ)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer testData.Close()
+
+ scanner := bufio.NewScanner(testData)
+ lineNo := 0
+
+ for scanner.Scan() {
+ lineNo++
+
+ line := scanner.Text()
+ parts := strings.Split(line, ":")
+ if len(parts) != 5 {
+ t.Fatalf("bad number of parts on line %d", lineNo)
+ }
+
+ privBytes, _ := hex.DecodeString(parts[0])
+ pubKey, _ := hex.DecodeString(parts[1])
+ msg, _ := hex.DecodeString(parts[2])
+ sig, _ := hex.DecodeString(parts[3])
+ // The signatures in the test vectors also include the message
+ // at the end, but we just want R and S.
+ sig = sig[:SignatureSize]
+
+ if l := len(pubKey); l != PublicKeySize {
+ t.Fatalf("bad public key length on line %d: got %d bytes", lineNo, l)
+ }
+
+ var priv [PrivateKeySize]byte
+ copy(priv[:], privBytes)
+ copy(priv[32:], pubKey)
+
+ sig2 := Sign(priv[:], msg)
+ if !bytes.Equal(sig, sig2[:]) {
+ t.Errorf("different signature result on line %d: %x vs %x", lineNo, sig, sig2)
+ }
+
+ if !Verify(pubKey, msg, sig2) {
+ t.Errorf("signature failed to verify on line %d", lineNo)
+ }
+ }
+
+ if err := scanner.Err(); err != nil {
+ t.Fatalf("error reading test data: %s", err)
+ }
+}
+
+func BenchmarkKeyGeneration(b *testing.B) {
+ var zero zeroReader
+ for i := 0; i < b.N; i++ {
+ if _, _, err := GenerateKey(zero); err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+func BenchmarkSigning(b *testing.B) {
+ var zero zeroReader
+ _, priv, err := GenerateKey(zero)
+ if err != nil {
+ b.Fatal(err)
+ }
+ message := []byte("Hello, world!")
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ Sign(priv, message)
+ }
+}
+
+func BenchmarkVerification(b *testing.B) {
+ var zero zeroReader
+ pub, priv, err := GenerateKey(zero)
+ if err != nil {
+ b.Fatal(err)
+ }
+ message := []byte("Hello, world!")
+ signature := Sign(priv, message)
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ Verify(pub, message, signature)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/const.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/const.go
new file mode 100644
index 000000000..e39f086c1
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/const.go
@@ -0,0 +1,1422 @@
+// 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.
+
+package edwards25519
+
+// These values are from the public domain, “ref10” implementation of ed25519
+// from SUPERCOP.
+
+// d is a constant in the Edwards curve equation.
+var d = FieldElement{
+ -10913610, 13857413, -15372611, 6949391, 114729, -8787816, -6275908, -3247719, -18696448, -12055116,
+}
+
+// d2 is 2*d.
+var d2 = FieldElement{
+ -21827239, -5839606, -30745221, 13898782, 229458, 15978800, -12551817, -6495438, 29715968, 9444199,
+}
+
+// SqrtM1 is the square-root of -1 in the field.
+var SqrtM1 = FieldElement{
+ -32595792, -7943725, 9377950, 3500415, 12389472, -272473, -25146209, -2005654, 326686, 11406482,
+}
+
+// A is a constant in the Montgomery-form of curve25519.
+var A = FieldElement{
+ 486662, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+}
+
+// bi contains precomputed multiples of the base-point. See the Ed25519 paper
+// for a discussion about how these values are used.
+var bi = [8]PreComputedGroupElement{
+ {
+ FieldElement{25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605},
+ FieldElement{-12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692, 5043384, 19500929, -15469378},
+ FieldElement{-8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919, 11864899, -24514362, -4438546},
+ },
+ {
+ FieldElement{15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600, -14772189, 28944400, -1550024},
+ FieldElement{16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577, -11775962, 7689662, 11199574},
+ FieldElement{30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774, 10017326, -17749093, -9920357},
+ },
+ {
+ FieldElement{10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885, 14515107, -15438304, 10819380},
+ FieldElement{4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668, 12483688, -12668491, 5581306},
+ FieldElement{19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350, 13850243, -23678021, -15815942},
+ },
+ {
+ FieldElement{5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852, 5230134, -23952439, -15175766},
+ FieldElement{-30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025, 16520125, 30598449, 7715701},
+ FieldElement{28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660, 1370708, 29794553, -1409300},
+ },
+ {
+ FieldElement{-22518993, -6692182, 14201702, -8745502, -23510406, 8844726, 18474211, -1361450, -13062696, 13821877},
+ FieldElement{-6455177, -7839871, 3374702, -4740862, -27098617, -10571707, 31655028, -7212327, 18853322, -14220951},
+ FieldElement{4566830, -12963868, -28974889, -12240689, -7602672, -2830569, -8514358, -10431137, 2207753, -3209784},
+ },
+ {
+ FieldElement{-25154831, -4185821, 29681144, 7868801, -6854661, -9423865, -12437364, -663000, -31111463, -16132436},
+ FieldElement{25576264, -2703214, 7349804, -11814844, 16472782, 9300885, 3844789, 15725684, 171356, 6466918},
+ FieldElement{23103977, 13316479, 9739013, -16149481, 817875, -15038942, 8965339, -14088058, -30714912, 16193877},
+ },
+ {
+ FieldElement{-33521811, 3180713, -2394130, 14003687, -16903474, -16270840, 17238398, 4729455, -18074513, 9256800},
+ FieldElement{-25182317, -4174131, 32336398, 5036987, -21236817, 11360617, 22616405, 9761698, -19827198, 630305},
+ FieldElement{-13720693, 2639453, -24237460, -7406481, 9494427, -5774029, -6554551, -15960994, -2449256, -14291300},
+ },
+ {
+ FieldElement{-3151181, -5046075, 9282714, 6866145, -31907062, -863023, -18940575, 15033784, 25105118, -7894876},
+ FieldElement{-24326370, 15950226, -31801215, -14592823, -11662737, -5090925, 1573892, -2625887, 2198790, -15804619},
+ FieldElement{-3099351, 10324967, -2241613, 7453183, -5446979, -2735503, -13812022, -16236442, -32461234, -12290683},
+ },
+}
+
+// base contains precomputed multiples of the base-point. See the Ed25519 paper
+// for a discussion about how these values are used.
+var base = [32][8]PreComputedGroupElement{
+ {
+ {
+ FieldElement{25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605},
+ FieldElement{-12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692, 5043384, 19500929, -15469378},
+ FieldElement{-8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919, 11864899, -24514362, -4438546},
+ },
+ {
+ FieldElement{-12815894, -12976347, -21581243, 11784320, -25355658, -2750717, -11717903, -3814571, -358445, -10211303},
+ FieldElement{-21703237, 6903825, 27185491, 6451973, -29577724, -9554005, -15616551, 11189268, -26829678, -5319081},
+ FieldElement{26966642, 11152617, 32442495, 15396054, 14353839, -12752335, -3128826, -9541118, -15472047, -4166697},
+ },
+ {
+ FieldElement{15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600, -14772189, 28944400, -1550024},
+ FieldElement{16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577, -11775962, 7689662, 11199574},
+ FieldElement{30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774, 10017326, -17749093, -9920357},
+ },
+ {
+ FieldElement{-17036878, 13921892, 10945806, -6033431, 27105052, -16084379, -28926210, 15006023, 3284568, -6276540},
+ FieldElement{23599295, -8306047, -11193664, -7687416, 13236774, 10506355, 7464579, 9656445, 13059162, 10374397},
+ FieldElement{7798556, 16710257, 3033922, 2874086, 28997861, 2835604, 32406664, -3839045, -641708, -101325},
+ },
+ {
+ FieldElement{10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885, 14515107, -15438304, 10819380},
+ FieldElement{4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668, 12483688, -12668491, 5581306},
+ FieldElement{19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350, 13850243, -23678021, -15815942},
+ },
+ {
+ FieldElement{-15371964, -12862754, 32573250, 4720197, -26436522, 5875511, -19188627, -15224819, -9818940, -12085777},
+ FieldElement{-8549212, 109983, 15149363, 2178705, 22900618, 4543417, 3044240, -15689887, 1762328, 14866737},
+ FieldElement{-18199695, -15951423, -10473290, 1707278, -17185920, 3916101, -28236412, 3959421, 27914454, 4383652},
+ },
+ {
+ FieldElement{5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852, 5230134, -23952439, -15175766},
+ FieldElement{-30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025, 16520125, 30598449, 7715701},
+ FieldElement{28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660, 1370708, 29794553, -1409300},
+ },
+ {
+ FieldElement{14499471, -2729599, -33191113, -4254652, 28494862, 14271267, 30290735, 10876454, -33154098, 2381726},
+ FieldElement{-7195431, -2655363, -14730155, 462251, -27724326, 3941372, -6236617, 3696005, -32300832, 15351955},
+ FieldElement{27431194, 8222322, 16448760, -3907995, -18707002, 11938355, -32961401, -2970515, 29551813, 10109425},
+ },
+ },
+ {
+ {
+ FieldElement{-13657040, -13155431, -31283750, 11777098, 21447386, 6519384, -2378284, -1627556, 10092783, -4764171},
+ FieldElement{27939166, 14210322, 4677035, 16277044, -22964462, -12398139, -32508754, 12005538, -17810127, 12803510},
+ FieldElement{17228999, -15661624, -1233527, 300140, -1224870, -11714777, 30364213, -9038194, 18016357, 4397660},
+ },
+ {
+ FieldElement{-10958843, -7690207, 4776341, -14954238, 27850028, -15602212, -26619106, 14544525, -17477504, 982639},
+ FieldElement{29253598, 15796703, -2863982, -9908884, 10057023, 3163536, 7332899, -4120128, -21047696, 9934963},
+ FieldElement{5793303, 16271923, -24131614, -10116404, 29188560, 1206517, -14747930, 4559895, -30123922, -10897950},
+ },
+ {
+ FieldElement{-27643952, -11493006, 16282657, -11036493, 28414021, -15012264, 24191034, 4541697, -13338309, 5500568},
+ FieldElement{12650548, -1497113, 9052871, 11355358, -17680037, -8400164, -17430592, 12264343, 10874051, 13524335},
+ FieldElement{25556948, -3045990, 714651, 2510400, 23394682, -10415330, 33119038, 5080568, -22528059, 5376628},
+ },
+ {
+ FieldElement{-26088264, -4011052, -17013699, -3537628, -6726793, 1920897, -22321305, -9447443, 4535768, 1569007},
+ FieldElement{-2255422, 14606630, -21692440, -8039818, 28430649, 8775819, -30494562, 3044290, 31848280, 12543772},
+ FieldElement{-22028579, 2943893, -31857513, 6777306, 13784462, -4292203, -27377195, -2062731, 7718482, 14474653},
+ },
+ {
+ FieldElement{2385315, 2454213, -22631320, 46603, -4437935, -15680415, 656965, -7236665, 24316168, -5253567},
+ FieldElement{13741529, 10911568, -33233417, -8603737, -20177830, -1033297, 33040651, -13424532, -20729456, 8321686},
+ FieldElement{21060490, -2212744, 15712757, -4336099, 1639040, 10656336, 23845965, -11874838, -9984458, 608372},
+ },
+ {
+ FieldElement{-13672732, -15087586, -10889693, -7557059, -6036909, 11305547, 1123968, -6780577, 27229399, 23887},
+ FieldElement{-23244140, -294205, -11744728, 14712571, -29465699, -2029617, 12797024, -6440308, -1633405, 16678954},
+ FieldElement{-29500620, 4770662, -16054387, 14001338, 7830047, 9564805, -1508144, -4795045, -17169265, 4904953},
+ },
+ {
+ FieldElement{24059557, 14617003, 19037157, -15039908, 19766093, -14906429, 5169211, 16191880, 2128236, -4326833},
+ FieldElement{-16981152, 4124966, -8540610, -10653797, 30336522, -14105247, -29806336, 916033, -6882542, -2986532},
+ FieldElement{-22630907, 12419372, -7134229, -7473371, -16478904, 16739175, 285431, 2763829, 15736322, 4143876},
+ },
+ {
+ FieldElement{2379352, 11839345, -4110402, -5988665, 11274298, 794957, 212801, -14594663, 23527084, -16458268},
+ FieldElement{33431127, -11130478, -17838966, -15626900, 8909499, 8376530, -32625340, 4087881, -15188911, -14416214},
+ FieldElement{1767683, 7197987, -13205226, -2022635, -13091350, 448826, 5799055, 4357868, -4774191, -16323038},
+ },
+ },
+ {
+ {
+ FieldElement{6721966, 13833823, -23523388, -1551314, 26354293, -11863321, 23365147, -3949732, 7390890, 2759800},
+ FieldElement{4409041, 2052381, 23373853, 10530217, 7676779, -12885954, 21302353, -4264057, 1244380, -12919645},
+ FieldElement{-4421239, 7169619, 4982368, -2957590, 30256825, -2777540, 14086413, 9208236, 15886429, 16489664},
+ },
+ {
+ FieldElement{1996075, 10375649, 14346367, 13311202, -6874135, -16438411, -13693198, 398369, -30606455, -712933},
+ FieldElement{-25307465, 9795880, -2777414, 14878809, -33531835, 14780363, 13348553, 12076947, -30836462, 5113182},
+ FieldElement{-17770784, 11797796, 31950843, 13929123, -25888302, 12288344, -30341101, -7336386, 13847711, 5387222},
+ },
+ {
+ FieldElement{-18582163, -3416217, 17824843, -2340966, 22744343, -10442611, 8763061, 3617786, -19600662, 10370991},
+ FieldElement{20246567, -14369378, 22358229, -543712, 18507283, -10413996, 14554437, -8746092, 32232924, 16763880},
+ FieldElement{9648505, 10094563, 26416693, 14745928, -30374318, -6472621, 11094161, 15689506, 3140038, -16510092},
+ },
+ {
+ FieldElement{-16160072, 5472695, 31895588, 4744994, 8823515, 10365685, -27224800, 9448613, -28774454, 366295},
+ FieldElement{19153450, 11523972, -11096490, -6503142, -24647631, 5420647, 28344573, 8041113, 719605, 11671788},
+ FieldElement{8678025, 2694440, -6808014, 2517372, 4964326, 11152271, -15432916, -15266516, 27000813, -10195553},
+ },
+ {
+ FieldElement{-15157904, 7134312, 8639287, -2814877, -7235688, 10421742, 564065, 5336097, 6750977, -14521026},
+ FieldElement{11836410, -3979488, 26297894, 16080799, 23455045, 15735944, 1695823, -8819122, 8169720, 16220347},
+ FieldElement{-18115838, 8653647, 17578566, -6092619, -8025777, -16012763, -11144307, -2627664, -5990708, -14166033},
+ },
+ {
+ FieldElement{-23308498, -10968312, 15213228, -10081214, -30853605, -11050004, 27884329, 2847284, 2655861, 1738395},
+ FieldElement{-27537433, -14253021, -25336301, -8002780, -9370762, 8129821, 21651608, -3239336, -19087449, -11005278},
+ FieldElement{1533110, 3437855, 23735889, 459276, 29970501, 11335377, 26030092, 5821408, 10478196, 8544890},
+ },
+ {
+ FieldElement{32173121, -16129311, 24896207, 3921497, 22579056, -3410854, 19270449, 12217473, 17789017, -3395995},
+ FieldElement{-30552961, -2228401, -15578829, -10147201, 13243889, 517024, 15479401, -3853233, 30460520, 1052596},
+ FieldElement{-11614875, 13323618, 32618793, 8175907, -15230173, 12596687, 27491595, -4612359, 3179268, -9478891},
+ },
+ {
+ FieldElement{31947069, -14366651, -4640583, -15339921, -15125977, -6039709, -14756777, -16411740, 19072640, -9511060},
+ FieldElement{11685058, 11822410, 3158003, -13952594, 33402194, -4165066, 5977896, -5215017, 473099, 5040608},
+ FieldElement{-20290863, 8198642, -27410132, 11602123, 1290375, -2799760, 28326862, 1721092, -19558642, -3131606},
+ },
+ },
+ {
+ {
+ FieldElement{7881532, 10687937, 7578723, 7738378, -18951012, -2553952, 21820786, 8076149, -27868496, 11538389},
+ FieldElement{-19935666, 3899861, 18283497, -6801568, -15728660, -11249211, 8754525, 7446702, -5676054, 5797016},
+ FieldElement{-11295600, -3793569, -15782110, -7964573, 12708869, -8456199, 2014099, -9050574, -2369172, -5877341},
+ },
+ {
+ FieldElement{-22472376, -11568741, -27682020, 1146375, 18956691, 16640559, 1192730, -3714199, 15123619, 10811505},
+ FieldElement{14352098, -3419715, -18942044, 10822655, 32750596, 4699007, -70363, 15776356, -28886779, -11974553},
+ FieldElement{-28241164, -8072475, -4978962, -5315317, 29416931, 1847569, -20654173, -16484855, 4714547, -9600655},
+ },
+ {
+ FieldElement{15200332, 8368572, 19679101, 15970074, -31872674, 1959451, 24611599, -4543832, -11745876, 12340220},
+ FieldElement{12876937, -10480056, 33134381, 6590940, -6307776, 14872440, 9613953, 8241152, 15370987, 9608631},
+ FieldElement{-4143277, -12014408, 8446281, -391603, 4407738, 13629032, -7724868, 15866074, -28210621, -8814099},
+ },
+ {
+ FieldElement{26660628, -15677655, 8393734, 358047, -7401291, 992988, -23904233, 858697, 20571223, 8420556},
+ FieldElement{14620715, 13067227, -15447274, 8264467, 14106269, 15080814, 33531827, 12516406, -21574435, -12476749},
+ FieldElement{236881, 10476226, 57258, -14677024, 6472998, 2466984, 17258519, 7256740, 8791136, 15069930},
+ },
+ {
+ FieldElement{1276410, -9371918, 22949635, -16322807, -23493039, -5702186, 14711875, 4874229, -30663140, -2331391},
+ FieldElement{5855666, 4990204, -13711848, 7294284, -7804282, 1924647, -1423175, -7912378, -33069337, 9234253},
+ FieldElement{20590503, -9018988, 31529744, -7352666, -2706834, 10650548, 31559055, -11609587, 18979186, 13396066},
+ },
+ {
+ FieldElement{24474287, 4968103, 22267082, 4407354, 24063882, -8325180, -18816887, 13594782, 33514650, 7021958},
+ FieldElement{-11566906, -6565505, -21365085, 15928892, -26158305, 4315421, -25948728, -3916677, -21480480, 12868082},
+ FieldElement{-28635013, 13504661, 19988037, -2132761, 21078225, 6443208, -21446107, 2244500, -12455797, -8089383},
+ },
+ {
+ FieldElement{-30595528, 13793479, -5852820, 319136, -25723172, -6263899, 33086546, 8957937, -15233648, 5540521},
+ FieldElement{-11630176, -11503902, -8119500, -7643073, 2620056, 1022908, -23710744, -1568984, -16128528, -14962807},
+ FieldElement{23152971, 775386, 27395463, 14006635, -9701118, 4649512, 1689819, 892185, -11513277, -15205948},
+ },
+ {
+ FieldElement{9770129, 9586738, 26496094, 4324120, 1556511, -3550024, 27453819, 4763127, -19179614, 5867134},
+ FieldElement{-32765025, 1927590, 31726409, -4753295, 23962434, -16019500, 27846559, 5931263, -29749703, -16108455},
+ FieldElement{27461885, -2977536, 22380810, 1815854, -23033753, -3031938, 7283490, -15148073, -19526700, 7734629},
+ },
+ },
+ {
+ {
+ FieldElement{-8010264, -9590817, -11120403, 6196038, 29344158, -13430885, 7585295, -3176626, 18549497, 15302069},
+ FieldElement{-32658337, -6171222, -7672793, -11051681, 6258878, 13504381, 10458790, -6418461, -8872242, 8424746},
+ FieldElement{24687205, 8613276, -30667046, -3233545, 1863892, -1830544, 19206234, 7134917, -11284482, -828919},
+ },
+ {
+ FieldElement{11334899, -9218022, 8025293, 12707519, 17523892, -10476071, 10243738, -14685461, -5066034, 16498837},
+ FieldElement{8911542, 6887158, -9584260, -6958590, 11145641, -9543680, 17303925, -14124238, 6536641, 10543906},
+ FieldElement{-28946384, 15479763, -17466835, 568876, -1497683, 11223454, -2669190, -16625574, -27235709, 8876771},
+ },
+ {
+ FieldElement{-25742899, -12566864, -15649966, -846607, -33026686, -796288, -33481822, 15824474, -604426, -9039817},
+ FieldElement{10330056, 70051, 7957388, -9002667, 9764902, 15609756, 27698697, -4890037, 1657394, 3084098},
+ FieldElement{10477963, -7470260, 12119566, -13250805, 29016247, -5365589, 31280319, 14396151, -30233575, 15272409},
+ },
+ {
+ FieldElement{-12288309, 3169463, 28813183, 16658753, 25116432, -5630466, -25173957, -12636138, -25014757, 1950504},
+ FieldElement{-26180358, 9489187, 11053416, -14746161, -31053720, 5825630, -8384306, -8767532, 15341279, 8373727},
+ FieldElement{28685821, 7759505, -14378516, -12002860, -31971820, 4079242, 298136, -10232602, -2878207, 15190420},
+ },
+ {
+ FieldElement{-32932876, 13806336, -14337485, -15794431, -24004620, 10940928, 8669718, 2742393, -26033313, -6875003},
+ FieldElement{-1580388, -11729417, -25979658, -11445023, -17411874, -10912854, 9291594, -16247779, -12154742, 6048605},
+ FieldElement{-30305315, 14843444, 1539301, 11864366, 20201677, 1900163, 13934231, 5128323, 11213262, 9168384},
+ },
+ {
+ FieldElement{-26280513, 11007847, 19408960, -940758, -18592965, -4328580, -5088060, -11105150, 20470157, -16398701},
+ FieldElement{-23136053, 9282192, 14855179, -15390078, -7362815, -14408560, -22783952, 14461608, 14042978, 5230683},
+ FieldElement{29969567, -2741594, -16711867, -8552442, 9175486, -2468974, 21556951, 3506042, -5933891, -12449708},
+ },
+ {
+ FieldElement{-3144746, 8744661, 19704003, 4581278, -20430686, 6830683, -21284170, 8971513, -28539189, 15326563},
+ FieldElement{-19464629, 10110288, -17262528, -3503892, -23500387, 1355669, -15523050, 15300988, -20514118, 9168260},
+ FieldElement{-5353335, 4488613, -23803248, 16314347, 7780487, -15638939, -28948358, 9601605, 33087103, -9011387},
+ },
+ {
+ FieldElement{-19443170, -15512900, -20797467, -12445323, -29824447, 10229461, -27444329, -15000531, -5996870, 15664672},
+ FieldElement{23294591, -16632613, -22650781, -8470978, 27844204, 11461195, 13099750, -2460356, 18151676, 13417686},
+ FieldElement{-24722913, -4176517, -31150679, 5988919, -26858785, 6685065, 1661597, -12551441, 15271676, -15452665},
+ },
+ },
+ {
+ {
+ FieldElement{11433042, -13228665, 8239631, -5279517, -1985436, -725718, -18698764, 2167544, -6921301, -13440182},
+ FieldElement{-31436171, 15575146, 30436815, 12192228, -22463353, 9395379, -9917708, -8638997, 12215110, 12028277},
+ FieldElement{14098400, 6555944, 23007258, 5757252, -15427832, -12950502, 30123440, 4617780, -16900089, -655628},
+ },
+ {
+ FieldElement{-4026201, -15240835, 11893168, 13718664, -14809462, 1847385, -15819999, 10154009, 23973261, -12684474},
+ FieldElement{-26531820, -3695990, -1908898, 2534301, -31870557, -16550355, 18341390, -11419951, 32013174, -10103539},
+ FieldElement{-25479301, 10876443, -11771086, -14625140, -12369567, 1838104, 21911214, 6354752, 4425632, -837822},
+ },
+ {
+ FieldElement{-10433389, -14612966, 22229858, -3091047, -13191166, 776729, -17415375, -12020462, 4725005, 14044970},
+ FieldElement{19268650, -7304421, 1555349, 8692754, -21474059, -9910664, 6347390, -1411784, -19522291, -16109756},
+ FieldElement{-24864089, 12986008, -10898878, -5558584, -11312371, -148526, 19541418, 8180106, 9282262, 10282508},
+ },
+ {
+ FieldElement{-26205082, 4428547, -8661196, -13194263, 4098402, -14165257, 15522535, 8372215, 5542595, -10702683},
+ FieldElement{-10562541, 14895633, 26814552, -16673850, -17480754, -2489360, -2781891, 6993761, -18093885, 10114655},
+ FieldElement{-20107055, -929418, 31422704, 10427861, -7110749, 6150669, -29091755, -11529146, 25953725, -106158},
+ },
+ {
+ FieldElement{-4234397, -8039292, -9119125, 3046000, 2101609, -12607294, 19390020, 6094296, -3315279, 12831125},
+ FieldElement{-15998678, 7578152, 5310217, 14408357, -33548620, -224739, 31575954, 6326196, 7381791, -2421839},
+ FieldElement{-20902779, 3296811, 24736065, -16328389, 18374254, 7318640, 6295303, 8082724, -15362489, 12339664},
+ },
+ {
+ FieldElement{27724736, 2291157, 6088201, -14184798, 1792727, 5857634, 13848414, 15768922, 25091167, 14856294},
+ FieldElement{-18866652, 8331043, 24373479, 8541013, -701998, -9269457, 12927300, -12695493, -22182473, -9012899},
+ FieldElement{-11423429, -5421590, 11632845, 3405020, 30536730, -11674039, -27260765, 13866390, 30146206, 9142070},
+ },
+ {
+ FieldElement{3924129, -15307516, -13817122, -10054960, 12291820, -668366, -27702774, 9326384, -8237858, 4171294},
+ FieldElement{-15921940, 16037937, 6713787, 16606682, -21612135, 2790944, 26396185, 3731949, 345228, -5462949},
+ FieldElement{-21327538, 13448259, 25284571, 1143661, 20614966, -8849387, 2031539, -12391231, -16253183, -13582083},
+ },
+ {
+ FieldElement{31016211, -16722429, 26371392, -14451233, -5027349, 14854137, 17477601, 3842657, 28012650, -16405420},
+ FieldElement{-5075835, 9368966, -8562079, -4600902, -15249953, 6970560, -9189873, 16292057, -8867157, 3507940},
+ FieldElement{29439664, 3537914, 23333589, 6997794, -17555561, -11018068, -15209202, -15051267, -9164929, 6580396},
+ },
+ },
+ {
+ {
+ FieldElement{-12185861, -7679788, 16438269, 10826160, -8696817, -6235611, 17860444, -9273846, -2095802, 9304567},
+ FieldElement{20714564, -4336911, 29088195, 7406487, 11426967, -5095705, 14792667, -14608617, 5289421, -477127},
+ FieldElement{-16665533, -10650790, -6160345, -13305760, 9192020, -1802462, 17271490, 12349094, 26939669, -3752294},
+ },
+ {
+ FieldElement{-12889898, 9373458, 31595848, 16374215, 21471720, 13221525, -27283495, -12348559, -3698806, 117887},
+ FieldElement{22263325, -6560050, 3984570, -11174646, -15114008, -566785, 28311253, 5358056, -23319780, 541964},
+ FieldElement{16259219, 3261970, 2309254, -15534474, -16885711, -4581916, 24134070, -16705829, -13337066, -13552195},
+ },
+ {
+ FieldElement{9378160, -13140186, -22845982, -12745264, 28198281, -7244098, -2399684, -717351, 690426, 14876244},
+ FieldElement{24977353, -314384, -8223969, -13465086, 28432343, -1176353, -13068804, -12297348, -22380984, 6618999},
+ FieldElement{-1538174, 11685646, 12944378, 13682314, -24389511, -14413193, 8044829, -13817328, 32239829, -5652762},
+ },
+ {
+ FieldElement{-18603066, 4762990, -926250, 8885304, -28412480, -3187315, 9781647, -10350059, 32779359, 5095274},
+ FieldElement{-33008130, -5214506, -32264887, -3685216, 9460461, -9327423, -24601656, 14506724, 21639561, -2630236},
+ FieldElement{-16400943, -13112215, 25239338, 15531969, 3987758, -4499318, -1289502, -6863535, 17874574, 558605},
+ },
+ {
+ FieldElement{-13600129, 10240081, 9171883, 16131053, -20869254, 9599700, 33499487, 5080151, 2085892, 5119761},
+ FieldElement{-22205145, -2519528, -16381601, 414691, -25019550, 2170430, 30634760, -8363614, -31999993, -5759884},
+ FieldElement{-6845704, 15791202, 8550074, -1312654, 29928809, -12092256, 27534430, -7192145, -22351378, 12961482},
+ },
+ {
+ FieldElement{-24492060, -9570771, 10368194, 11582341, -23397293, -2245287, 16533930, 8206996, -30194652, -5159638},
+ FieldElement{-11121496, -3382234, 2307366, 6362031, -135455, 8868177, -16835630, 7031275, 7589640, 8945490},
+ FieldElement{-32152748, 8917967, 6661220, -11677616, -1192060, -15793393, 7251489, -11182180, 24099109, -14456170},
+ },
+ {
+ FieldElement{5019558, -7907470, 4244127, -14714356, -26933272, 6453165, -19118182, -13289025, -6231896, -10280736},
+ FieldElement{10853594, 10721687, 26480089, 5861829, -22995819, 1972175, -1866647, -10557898, -3363451, -6441124},
+ FieldElement{-17002408, 5906790, 221599, -6563147, 7828208, -13248918, 24362661, -2008168, -13866408, 7421392},
+ },
+ {
+ FieldElement{8139927, -6546497, 32257646, -5890546, 30375719, 1886181, -21175108, 15441252, 28826358, -4123029},
+ FieldElement{6267086, 9695052, 7709135, -16603597, -32869068, -1886135, 14795160, -7840124, 13746021, -1742048},
+ FieldElement{28584902, 7787108, -6732942, -15050729, 22846041, -7571236, -3181936, -363524, 4771362, -8419958},
+ },
+ },
+ {
+ {
+ FieldElement{24949256, 6376279, -27466481, -8174608, -18646154, -9930606, 33543569, -12141695, 3569627, 11342593},
+ FieldElement{26514989, 4740088, 27912651, 3697550, 19331575, -11472339, 6809886, 4608608, 7325975, -14801071},
+ FieldElement{-11618399, -14554430, -24321212, 7655128, -1369274, 5214312, -27400540, 10258390, -17646694, -8186692},
+ },
+ {
+ FieldElement{11431204, 15823007, 26570245, 14329124, 18029990, 4796082, -31446179, 15580664, 9280358, -3973687},
+ FieldElement{-160783, -10326257, -22855316, -4304997, -20861367, -13621002, -32810901, -11181622, -15545091, 4387441},
+ FieldElement{-20799378, 12194512, 3937617, -5805892, -27154820, 9340370, -24513992, 8548137, 20617071, -7482001},
+ },
+ {
+ FieldElement{-938825, -3930586, -8714311, 16124718, 24603125, -6225393, -13775352, -11875822, 24345683, 10325460},
+ FieldElement{-19855277, -1568885, -22202708, 8714034, 14007766, 6928528, 16318175, -1010689, 4766743, 3552007},
+ FieldElement{-21751364, -16730916, 1351763, -803421, -4009670, 3950935, 3217514, 14481909, 10988822, -3994762},
+ },
+ {
+ FieldElement{15564307, -14311570, 3101243, 5684148, 30446780, -8051356, 12677127, -6505343, -8295852, 13296005},
+ FieldElement{-9442290, 6624296, -30298964, -11913677, -4670981, -2057379, 31521204, 9614054, -30000824, 12074674},
+ FieldElement{4771191, -135239, 14290749, -13089852, 27992298, 14998318, -1413936, -1556716, 29832613, -16391035},
+ },
+ {
+ FieldElement{7064884, -7541174, -19161962, -5067537, -18891269, -2912736, 25825242, 5293297, -27122660, 13101590},
+ FieldElement{-2298563, 2439670, -7466610, 1719965, -27267541, -16328445, 32512469, -5317593, -30356070, -4190957},
+ FieldElement{-30006540, 10162316, -33180176, 3981723, -16482138, -13070044, 14413974, 9515896, 19568978, 9628812},
+ },
+ {
+ FieldElement{33053803, 199357, 15894591, 1583059, 27380243, -4580435, -17838894, -6106839, -6291786, 3437740},
+ FieldElement{-18978877, 3884493, 19469877, 12726490, 15913552, 13614290, -22961733, 70104, 7463304, 4176122},
+ FieldElement{-27124001, 10659917, 11482427, -16070381, 12771467, -6635117, -32719404, -5322751, 24216882, 5944158},
+ },
+ {
+ FieldElement{8894125, 7450974, -2664149, -9765752, -28080517, -12389115, 19345746, 14680796, 11632993, 5847885},
+ FieldElement{26942781, -2315317, 9129564, -4906607, 26024105, 11769399, -11518837, 6367194, -9727230, 4782140},
+ FieldElement{19916461, -4828410, -22910704, -11414391, 25606324, -5972441, 33253853, 8220911, 6358847, -1873857},
+ },
+ {
+ FieldElement{801428, -2081702, 16569428, 11065167, 29875704, 96627, 7908388, -4480480, -13538503, 1387155},
+ FieldElement{19646058, 5720633, -11416706, 12814209, 11607948, 12749789, 14147075, 15156355, -21866831, 11835260},
+ FieldElement{19299512, 1155910, 28703737, 14890794, 2925026, 7269399, 26121523, 15467869, -26560550, 5052483},
+ },
+ },
+ {
+ {
+ FieldElement{-3017432, 10058206, 1980837, 3964243, 22160966, 12322533, -6431123, -12618185, 12228557, -7003677},
+ FieldElement{32944382, 14922211, -22844894, 5188528, 21913450, -8719943, 4001465, 13238564, -6114803, 8653815},
+ FieldElement{22865569, -4652735, 27603668, -12545395, 14348958, 8234005, 24808405, 5719875, 28483275, 2841751},
+ },
+ {
+ FieldElement{-16420968, -1113305, -327719, -12107856, 21886282, -15552774, -1887966, -315658, 19932058, -12739203},
+ FieldElement{-11656086, 10087521, -8864888, -5536143, -19278573, -3055912, 3999228, 13239134, -4777469, -13910208},
+ FieldElement{1382174, -11694719, 17266790, 9194690, -13324356, 9720081, 20403944, 11284705, -14013818, 3093230},
+ },
+ {
+ FieldElement{16650921, -11037932, -1064178, 1570629, -8329746, 7352753, -302424, 16271225, -24049421, -6691850},
+ FieldElement{-21911077, -5927941, -4611316, -5560156, -31744103, -10785293, 24123614, 15193618, -21652117, -16739389},
+ FieldElement{-9935934, -4289447, -25279823, 4372842, 2087473, 10399484, 31870908, 14690798, 17361620, 11864968},
+ },
+ {
+ FieldElement{-11307610, 6210372, 13206574, 5806320, -29017692, -13967200, -12331205, -7486601, -25578460, -16240689},
+ FieldElement{14668462, -12270235, 26039039, 15305210, 25515617, 4542480, 10453892, 6577524, 9145645, -6443880},
+ FieldElement{5974874, 3053895, -9433049, -10385191, -31865124, 3225009, -7972642, 3936128, -5652273, -3050304},
+ },
+ {
+ FieldElement{30625386, -4729400, -25555961, -12792866, -20484575, 7695099, 17097188, -16303496, -27999779, 1803632},
+ FieldElement{-3553091, 9865099, -5228566, 4272701, -5673832, -16689700, 14911344, 12196514, -21405489, 7047412},
+ FieldElement{20093277, 9920966, -11138194, -5343857, 13161587, 12044805, -32856851, 4124601, -32343828, -10257566},
+ },
+ {
+ FieldElement{-20788824, 14084654, -13531713, 7842147, 19119038, -13822605, 4752377, -8714640, -21679658, 2288038},
+ FieldElement{-26819236, -3283715, 29965059, 3039786, -14473765, 2540457, 29457502, 14625692, -24819617, 12570232},
+ FieldElement{-1063558, -11551823, 16920318, 12494842, 1278292, -5869109, -21159943, -3498680, -11974704, 4724943},
+ },
+ {
+ FieldElement{17960970, -11775534, -4140968, -9702530, -8876562, -1410617, -12907383, -8659932, -29576300, 1903856},
+ FieldElement{23134274, -14279132, -10681997, -1611936, 20684485, 15770816, -12989750, 3190296, 26955097, 14109738},
+ FieldElement{15308788, 5320727, -30113809, -14318877, 22902008, 7767164, 29425325, -11277562, 31960942, 11934971},
+ },
+ {
+ FieldElement{-27395711, 8435796, 4109644, 12222639, -24627868, 14818669, 20638173, 4875028, 10491392, 1379718},
+ FieldElement{-13159415, 9197841, 3875503, -8936108, -1383712, -5879801, 33518459, 16176658, 21432314, 12180697},
+ FieldElement{-11787308, 11500838, 13787581, -13832590, -22430679, 10140205, 1465425, 12689540, -10301319, -13872883},
+ },
+ },
+ {
+ {
+ FieldElement{5414091, -15386041, -21007664, 9643570, 12834970, 1186149, -2622916, -1342231, 26128231, 6032912},
+ FieldElement{-26337395, -13766162, 32496025, -13653919, 17847801, -12669156, 3604025, 8316894, -25875034, -10437358},
+ FieldElement{3296484, 6223048, 24680646, -12246460, -23052020, 5903205, -8862297, -4639164, 12376617, 3188849},
+ },
+ {
+ FieldElement{29190488, -14659046, 27549113, -1183516, 3520066, -10697301, 32049515, -7309113, -16109234, -9852307},
+ FieldElement{-14744486, -9309156, 735818, -598978, -20407687, -5057904, 25246078, -15795669, 18640741, -960977},
+ FieldElement{-6928835, -16430795, 10361374, 5642961, 4910474, 12345252, -31638386, -494430, 10530747, 1053335},
+ },
+ {
+ FieldElement{-29265967, -14186805, -13538216, -12117373, -19457059, -10655384, -31462369, -2948985, 24018831, 15026644},
+ FieldElement{-22592535, -3145277, -2289276, 5953843, -13440189, 9425631, 25310643, 13003497, -2314791, -15145616},
+ FieldElement{-27419985, -603321, -8043984, -1669117, -26092265, 13987819, -27297622, 187899, -23166419, -2531735},
+ },
+ {
+ FieldElement{-21744398, -13810475, 1844840, 5021428, -10434399, -15911473, 9716667, 16266922, -5070217, 726099},
+ FieldElement{29370922, -6053998, 7334071, -15342259, 9385287, 2247707, -13661962, -4839461, 30007388, -15823341},
+ FieldElement{-936379, 16086691, 23751945, -543318, -1167538, -5189036, 9137109, 730663, 9835848, 4555336},
+ },
+ {
+ FieldElement{-23376435, 1410446, -22253753, -12899614, 30867635, 15826977, 17693930, 544696, -11985298, 12422646},
+ FieldElement{31117226, -12215734, -13502838, 6561947, -9876867, -12757670, -5118685, -4096706, 29120153, 13924425},
+ FieldElement{-17400879, -14233209, 19675799, -2734756, -11006962, -5858820, -9383939, -11317700, 7240931, -237388},
+ },
+ {
+ FieldElement{-31361739, -11346780, -15007447, -5856218, -22453340, -12152771, 1222336, 4389483, 3293637, -15551743},
+ FieldElement{-16684801, -14444245, 11038544, 11054958, -13801175, -3338533, -24319580, 7733547, 12796905, -6335822},
+ FieldElement{-8759414, -10817836, -25418864, 10783769, -30615557, -9746811, -28253339, 3647836, 3222231, -11160462},
+ },
+ {
+ FieldElement{18606113, 1693100, -25448386, -15170272, 4112353, 10045021, 23603893, -2048234, -7550776, 2484985},
+ FieldElement{9255317, -3131197, -12156162, -1004256, 13098013, -9214866, 16377220, -2102812, -19802075, -3034702},
+ FieldElement{-22729289, 7496160, -5742199, 11329249, 19991973, -3347502, -31718148, 9936966, -30097688, -10618797},
+ },
+ {
+ FieldElement{21878590, -5001297, 4338336, 13643897, -3036865, 13160960, 19708896, 5415497, -7360503, -4109293},
+ FieldElement{27736861, 10103576, 12500508, 8502413, -3413016, -9633558, 10436918, -1550276, -23659143, -8132100},
+ FieldElement{19492550, -12104365, -29681976, -852630, -3208171, 12403437, 30066266, 8367329, 13243957, 8709688},
+ },
+ },
+ {
+ {
+ FieldElement{12015105, 2801261, 28198131, 10151021, 24818120, -4743133, -11194191, -5645734, 5150968, 7274186},
+ FieldElement{2831366, -12492146, 1478975, 6122054, 23825128, -12733586, 31097299, 6083058, 31021603, -9793610},
+ FieldElement{-2529932, -2229646, 445613, 10720828, -13849527, -11505937, -23507731, 16354465, 15067285, -14147707},
+ },
+ {
+ FieldElement{7840942, 14037873, -33364863, 15934016, -728213, -3642706, 21403988, 1057586, -19379462, -12403220},
+ FieldElement{915865, -16469274, 15608285, -8789130, -24357026, 6060030, -17371319, 8410997, -7220461, 16527025},
+ FieldElement{32922597, -556987, 20336074, -16184568, 10903705, -5384487, 16957574, 52992, 23834301, 6588044},
+ },
+ {
+ FieldElement{32752030, 11232950, 3381995, -8714866, 22652988, -10744103, 17159699, 16689107, -20314580, -1305992},
+ FieldElement{-4689649, 9166776, -25710296, -10847306, 11576752, 12733943, 7924251, -2752281, 1976123, -7249027},
+ FieldElement{21251222, 16309901, -2983015, -6783122, 30810597, 12967303, 156041, -3371252, 12331345, -8237197},
+ },
+ {
+ FieldElement{8651614, -4477032, -16085636, -4996994, 13002507, 2950805, 29054427, -5106970, 10008136, -4667901},
+ FieldElement{31486080, 15114593, -14261250, 12951354, 14369431, -7387845, 16347321, -13662089, 8684155, -10532952},
+ FieldElement{19443825, 11385320, 24468943, -9659068, -23919258, 2187569, -26263207, -6086921, 31316348, 14219878},
+ },
+ {
+ FieldElement{-28594490, 1193785, 32245219, 11392485, 31092169, 15722801, 27146014, 6992409, 29126555, 9207390},
+ FieldElement{32382935, 1110093, 18477781, 11028262, -27411763, -7548111, -4980517, 10843782, -7957600, -14435730},
+ FieldElement{2814918, 7836403, 27519878, -7868156, -20894015, -11553689, -21494559, 8550130, 28346258, 1994730},
+ },
+ {
+ FieldElement{-19578299, 8085545, -14000519, -3948622, 2785838, -16231307, -19516951, 7174894, 22628102, 8115180},
+ FieldElement{-30405132, 955511, -11133838, -15078069, -32447087, -13278079, -25651578, 3317160, -9943017, 930272},
+ FieldElement{-15303681, -6833769, 28856490, 1357446, 23421993, 1057177, 24091212, -1388970, -22765376, -10650715},
+ },
+ {
+ FieldElement{-22751231, -5303997, -12907607, -12768866, -15811511, -7797053, -14839018, -16554220, -1867018, 8398970},
+ FieldElement{-31969310, 2106403, -4736360, 1362501, 12813763, 16200670, 22981545, -6291273, 18009408, -15772772},
+ FieldElement{-17220923, -9545221, -27784654, 14166835, 29815394, 7444469, 29551787, -3727419, 19288549, 1325865},
+ },
+ {
+ FieldElement{15100157, -15835752, -23923978, -1005098, -26450192, 15509408, 12376730, -3479146, 33166107, -8042750},
+ FieldElement{20909231, 13023121, -9209752, 16251778, -5778415, -8094914, 12412151, 10018715, 2213263, -13878373},
+ FieldElement{32529814, -11074689, 30361439, -16689753, -9135940, 1513226, 22922121, 6382134, -5766928, 8371348},
+ },
+ },
+ {
+ {
+ FieldElement{9923462, 11271500, 12616794, 3544722, -29998368, -1721626, 12891687, -8193132, -26442943, 10486144},
+ FieldElement{-22597207, -7012665, 8587003, -8257861, 4084309, -12970062, 361726, 2610596, -23921530, -11455195},
+ FieldElement{5408411, -1136691, -4969122, 10561668, 24145918, 14240566, 31319731, -4235541, 19985175, -3436086},
+ },
+ {
+ FieldElement{-13994457, 16616821, 14549246, 3341099, 32155958, 13648976, -17577068, 8849297, 65030, 8370684},
+ FieldElement{-8320926, -12049626, 31204563, 5839400, -20627288, -1057277, -19442942, 6922164, 12743482, -9800518},
+ FieldElement{-2361371, 12678785, 28815050, 4759974, -23893047, 4884717, 23783145, 11038569, 18800704, 255233},
+ },
+ {
+ FieldElement{-5269658, -1773886, 13957886, 7990715, 23132995, 728773, 13393847, 9066957, 19258688, -14753793},
+ FieldElement{-2936654, -10827535, -10432089, 14516793, -3640786, 4372541, -31934921, 2209390, -1524053, 2055794},
+ FieldElement{580882, 16705327, 5468415, -2683018, -30926419, -14696000, -7203346, -8994389, -30021019, 7394435},
+ },
+ {
+ FieldElement{23838809, 1822728, -15738443, 15242727, 8318092, -3733104, -21672180, -3492205, -4821741, 14799921},
+ FieldElement{13345610, 9759151, 3371034, -16137791, 16353039, 8577942, 31129804, 13496856, -9056018, 7402518},
+ FieldElement{2286874, -4435931, -20042458, -2008336, -13696227, 5038122, 11006906, -15760352, 8205061, 1607563},
+ },
+ {
+ FieldElement{14414086, -8002132, 3331830, -3208217, 22249151, -5594188, 18364661, -2906958, 30019587, -9029278},
+ FieldElement{-27688051, 1585953, -10775053, 931069, -29120221, -11002319, -14410829, 12029093, 9944378, 8024},
+ FieldElement{4368715, -3709630, 29874200, -15022983, -20230386, -11410704, -16114594, -999085, -8142388, 5640030},
+ },
+ {
+ FieldElement{10299610, 13746483, 11661824, 16234854, 7630238, 5998374, 9809887, -16694564, 15219798, -14327783},
+ FieldElement{27425505, -5719081, 3055006, 10660664, 23458024, 595578, -15398605, -1173195, -18342183, 9742717},
+ FieldElement{6744077, 2427284, 26042789, 2720740, -847906, 1118974, 32324614, 7406442, 12420155, 1994844},
+ },
+ {
+ FieldElement{14012521, -5024720, -18384453, -9578469, -26485342, -3936439, -13033478, -10909803, 24319929, -6446333},
+ FieldElement{16412690, -4507367, 10772641, 15929391, -17068788, -4658621, 10555945, -10484049, -30102368, -4739048},
+ FieldElement{22397382, -7767684, -9293161, -12792868, 17166287, -9755136, -27333065, 6199366, 21880021, -12250760},
+ },
+ {
+ FieldElement{-4283307, 5368523, -31117018, 8163389, -30323063, 3209128, 16557151, 8890729, 8840445, 4957760},
+ FieldElement{-15447727, 709327, -6919446, -10870178, -29777922, 6522332, -21720181, 12130072, -14796503, 5005757},
+ FieldElement{-2114751, -14308128, 23019042, 15765735, -25269683, 6002752, 10183197, -13239326, -16395286, -2176112},
+ },
+ },
+ {
+ {
+ FieldElement{-19025756, 1632005, 13466291, -7995100, -23640451, 16573537, -32013908, -3057104, 22208662, 2000468},
+ FieldElement{3065073, -1412761, -25598674, -361432, -17683065, -5703415, -8164212, 11248527, -3691214, -7414184},
+ FieldElement{10379208, -6045554, 8877319, 1473647, -29291284, -12507580, 16690915, 2553332, -3132688, 16400289},
+ },
+ {
+ FieldElement{15716668, 1254266, -18472690, 7446274, -8448918, 6344164, -22097271, -7285580, 26894937, 9132066},
+ FieldElement{24158887, 12938817, 11085297, -8177598, -28063478, -4457083, -30576463, 64452, -6817084, -2692882},
+ FieldElement{13488534, 7794716, 22236231, 5989356, 25426474, -12578208, 2350710, -3418511, -4688006, 2364226},
+ },
+ {
+ FieldElement{16335052, 9132434, 25640582, 6678888, 1725628, 8517937, -11807024, -11697457, 15445875, -7798101},
+ FieldElement{29004207, -7867081, 28661402, -640412, -12794003, -7943086, 31863255, -4135540, -278050, -15759279},
+ FieldElement{-6122061, -14866665, -28614905, 14569919, -10857999, -3591829, 10343412, -6976290, -29828287, -10815811},
+ },
+ {
+ FieldElement{27081650, 3463984, 14099042, -4517604, 1616303, -6205604, 29542636, 15372179, 17293797, 960709},
+ FieldElement{20263915, 11434237, -5765435, 11236810, 13505955, -10857102, -16111345, 6493122, -19384511, 7639714},
+ FieldElement{-2830798, -14839232, 25403038, -8215196, -8317012, -16173699, 18006287, -16043750, 29994677, -15808121},
+ },
+ {
+ FieldElement{9769828, 5202651, -24157398, -13631392, -28051003, -11561624, -24613141, -13860782, -31184575, 709464},
+ FieldElement{12286395, 13076066, -21775189, -1176622, -25003198, 4057652, -32018128, -8890874, 16102007, 13205847},
+ FieldElement{13733362, 5599946, 10557076, 3195751, -5557991, 8536970, -25540170, 8525972, 10151379, 10394400},
+ },
+ {
+ FieldElement{4024660, -16137551, 22436262, 12276534, -9099015, -2686099, 19698229, 11743039, -33302334, 8934414},
+ FieldElement{-15879800, -4525240, -8580747, -2934061, 14634845, -698278, -9449077, 3137094, -11536886, 11721158},
+ FieldElement{17555939, -5013938, 8268606, 2331751, -22738815, 9761013, 9319229, 8835153, -9205489, -1280045},
+ },
+ {
+ FieldElement{-461409, -7830014, 20614118, 16688288, -7514766, -4807119, 22300304, 505429, 6108462, -6183415},
+ FieldElement{-5070281, 12367917, -30663534, 3234473, 32617080, -8422642, 29880583, -13483331, -26898490, -7867459},
+ FieldElement{-31975283, 5726539, 26934134, 10237677, -3173717, -605053, 24199304, 3795095, 7592688, -14992079},
+ },
+ {
+ FieldElement{21594432, -14964228, 17466408, -4077222, 32537084, 2739898, 6407723, 12018833, -28256052, 4298412},
+ FieldElement{-20650503, -11961496, -27236275, 570498, 3767144, -1717540, 13891942, -1569194, 13717174, 10805743},
+ FieldElement{-14676630, -15644296, 15287174, 11927123, 24177847, -8175568, -796431, 14860609, -26938930, -5863836},
+ },
+ },
+ {
+ {
+ FieldElement{12962541, 5311799, -10060768, 11658280, 18855286, -7954201, 13286263, -12808704, -4381056, 9882022},
+ FieldElement{18512079, 11319350, -20123124, 15090309, 18818594, 5271736, -22727904, 3666879, -23967430, -3299429},
+ FieldElement{-6789020, -3146043, 16192429, 13241070, 15898607, -14206114, -10084880, -6661110, -2403099, 5276065},
+ },
+ {
+ FieldElement{30169808, -5317648, 26306206, -11750859, 27814964, 7069267, 7152851, 3684982, 1449224, 13082861},
+ FieldElement{10342826, 3098505, 2119311, 193222, 25702612, 12233820, 23697382, 15056736, -21016438, -8202000},
+ FieldElement{-33150110, 3261608, 22745853, 7948688, 19370557, -15177665, -26171976, 6482814, -10300080, -11060101},
+ },
+ {
+ FieldElement{32869458, -5408545, 25609743, 15678670, -10687769, -15471071, 26112421, 2521008, -22664288, 6904815},
+ FieldElement{29506923, 4457497, 3377935, -9796444, -30510046, 12935080, 1561737, 3841096, -29003639, -6657642},
+ FieldElement{10340844, -6630377, -18656632, -2278430, 12621151, -13339055, 30878497, -11824370, -25584551, 5181966},
+ },
+ {
+ FieldElement{25940115, -12658025, 17324188, -10307374, -8671468, 15029094, 24396252, -16450922, -2322852, -12388574},
+ FieldElement{-21765684, 9916823, -1300409, 4079498, -1028346, 11909559, 1782390, 12641087, 20603771, -6561742},
+ FieldElement{-18882287, -11673380, 24849422, 11501709, 13161720, -4768874, 1925523, 11914390, 4662781, 7820689},
+ },
+ {
+ FieldElement{12241050, -425982, 8132691, 9393934, 32846760, -1599620, 29749456, 12172924, 16136752, 15264020},
+ FieldElement{-10349955, -14680563, -8211979, 2330220, -17662549, -14545780, 10658213, 6671822, 19012087, 3772772},
+ FieldElement{3753511, -3421066, 10617074, 2028709, 14841030, -6721664, 28718732, -15762884, 20527771, 12988982},
+ },
+ {
+ FieldElement{-14822485, -5797269, -3707987, 12689773, -898983, -10914866, -24183046, -10564943, 3299665, -12424953},
+ FieldElement{-16777703, -15253301, -9642417, 4978983, 3308785, 8755439, 6943197, 6461331, -25583147, 8991218},
+ FieldElement{-17226263, 1816362, -1673288, -6086439, 31783888, -8175991, -32948145, 7417950, -30242287, 1507265},
+ },
+ {
+ FieldElement{29692663, 6829891, -10498800, 4334896, 20945975, -11906496, -28887608, 8209391, 14606362, -10647073},
+ FieldElement{-3481570, 8707081, 32188102, 5672294, 22096700, 1711240, -33020695, 9761487, 4170404, -2085325},
+ FieldElement{-11587470, 14855945, -4127778, -1531857, -26649089, 15084046, 22186522, 16002000, -14276837, -8400798},
+ },
+ {
+ FieldElement{-4811456, 13761029, -31703877, -2483919, -3312471, 7869047, -7113572, -9620092, 13240845, 10965870},
+ FieldElement{-7742563, -8256762, -14768334, -13656260, -23232383, 12387166, 4498947, 14147411, 29514390, 4302863},
+ FieldElement{-13413405, -12407859, 20757302, -13801832, 14785143, 8976368, -5061276, -2144373, 17846988, -13971927},
+ },
+ },
+ {
+ {
+ FieldElement{-2244452, -754728, -4597030, -1066309, -6247172, 1455299, -21647728, -9214789, -5222701, 12650267},
+ FieldElement{-9906797, -16070310, 21134160, 12198166, -27064575, 708126, 387813, 13770293, -19134326, 10958663},
+ FieldElement{22470984, 12369526, 23446014, -5441109, -21520802, -9698723, -11772496, -11574455, -25083830, 4271862},
+ },
+ {
+ FieldElement{-25169565, -10053642, -19909332, 15361595, -5984358, 2159192, 75375, -4278529, -32526221, 8469673},
+ FieldElement{15854970, 4148314, -8893890, 7259002, 11666551, 13824734, -30531198, 2697372, 24154791, -9460943},
+ FieldElement{15446137, -15806644, 29759747, 14019369, 30811221, -9610191, -31582008, 12840104, 24913809, 9815020},
+ },
+ {
+ FieldElement{-4709286, -5614269, -31841498, -12288893, -14443537, 10799414, -9103676, 13438769, 18735128, 9466238},
+ FieldElement{11933045, 9281483, 5081055, -5183824, -2628162, -4905629, -7727821, -10896103, -22728655, 16199064},
+ FieldElement{14576810, 379472, -26786533, -8317236, -29426508, -10812974, -102766, 1876699, 30801119, 2164795},
+ },
+ {
+ FieldElement{15995086, 3199873, 13672555, 13712240, -19378835, -4647646, -13081610, -15496269, -13492807, 1268052},
+ FieldElement{-10290614, -3659039, -3286592, 10948818, 23037027, 3794475, -3470338, -12600221, -17055369, 3565904},
+ FieldElement{29210088, -9419337, -5919792, -4952785, 10834811, -13327726, -16512102, -10820713, -27162222, -14030531},
+ },
+ {
+ FieldElement{-13161890, 15508588, 16663704, -8156150, -28349942, 9019123, -29183421, -3769423, 2244111, -14001979},
+ FieldElement{-5152875, -3800936, -9306475, -6071583, 16243069, 14684434, -25673088, -16180800, 13491506, 4641841},
+ FieldElement{10813417, 643330, -19188515, -728916, 30292062, -16600078, 27548447, -7721242, 14476989, -12767431},
+ },
+ {
+ FieldElement{10292079, 9984945, 6481436, 8279905, -7251514, 7032743, 27282937, -1644259, -27912810, 12651324},
+ FieldElement{-31185513, -813383, 22271204, 11835308, 10201545, 15351028, 17099662, 3988035, 21721536, -3148940},
+ FieldElement{10202177, -6545839, -31373232, -9574638, -32150642, -8119683, -12906320, 3852694, 13216206, 14842320},
+ },
+ {
+ FieldElement{-15815640, -10601066, -6538952, -7258995, -6984659, -6581778, -31500847, 13765824, -27434397, 9900184},
+ FieldElement{14465505, -13833331, -32133984, -14738873, -27443187, 12990492, 33046193, 15796406, -7051866, -8040114},
+ FieldElement{30924417, -8279620, 6359016, -12816335, 16508377, 9071735, -25488601, 15413635, 9524356, -7018878},
+ },
+ {
+ FieldElement{12274201, -13175547, 32627641, -1785326, 6736625, 13267305, 5237659, -5109483, 15663516, 4035784},
+ FieldElement{-2951309, 8903985, 17349946, 601635, -16432815, -4612556, -13732739, -15889334, -22258478, 4659091},
+ FieldElement{-16916263, -4952973, -30393711, -15158821, 20774812, 15897498, 5736189, 15026997, -2178256, -13455585},
+ },
+ },
+ {
+ {
+ FieldElement{-8858980, -2219056, 28571666, -10155518, -474467, -10105698, -3801496, 278095, 23440562, -290208},
+ FieldElement{10226241, -5928702, 15139956, 120818, -14867693, 5218603, 32937275, 11551483, -16571960, -7442864},
+ FieldElement{17932739, -12437276, -24039557, 10749060, 11316803, 7535897, 22503767, 5561594, -3646624, 3898661},
+ },
+ {
+ FieldElement{7749907, -969567, -16339731, -16464, -25018111, 15122143, -1573531, 7152530, 21831162, 1245233},
+ FieldElement{26958459, -14658026, 4314586, 8346991, -5677764, 11960072, -32589295, -620035, -30402091, -16716212},
+ FieldElement{-12165896, 9166947, 33491384, 13673479, 29787085, 13096535, 6280834, 14587357, -22338025, 13987525},
+ },
+ {
+ FieldElement{-24349909, 7778775, 21116000, 15572597, -4833266, -5357778, -4300898, -5124639, -7469781, -2858068},
+ FieldElement{9681908, -6737123, -31951644, 13591838, -6883821, 386950, 31622781, 6439245, -14581012, 4091397},
+ FieldElement{-8426427, 1470727, -28109679, -1596990, 3978627, -5123623, -19622683, 12092163, 29077877, -14741988},
+ },
+ {
+ FieldElement{5269168, -6859726, -13230211, -8020715, 25932563, 1763552, -5606110, -5505881, -20017847, 2357889},
+ FieldElement{32264008, -15407652, -5387735, -1160093, -2091322, -3946900, 23104804, -12869908, 5727338, 189038},
+ FieldElement{14609123, -8954470, -6000566, -16622781, -14577387, -7743898, -26745169, 10942115, -25888931, -14884697},
+ },
+ {
+ FieldElement{20513500, 5557931, -15604613, 7829531, 26413943, -2019404, -21378968, 7471781, 13913677, -5137875},
+ FieldElement{-25574376, 11967826, 29233242, 12948236, -6754465, 4713227, -8940970, 14059180, 12878652, 8511905},
+ FieldElement{-25656801, 3393631, -2955415, -7075526, -2250709, 9366908, -30223418, 6812974, 5568676, -3127656},
+ },
+ {
+ FieldElement{11630004, 12144454, 2116339, 13606037, 27378885, 15676917, -17408753, -13504373, -14395196, 8070818},
+ FieldElement{27117696, -10007378, -31282771, -5570088, 1127282, 12772488, -29845906, 10483306, -11552749, -1028714},
+ FieldElement{10637467, -5688064, 5674781, 1072708, -26343588, -6982302, -1683975, 9177853, -27493162, 15431203},
+ },
+ {
+ FieldElement{20525145, 10892566, -12742472, 12779443, -29493034, 16150075, -28240519, 14943142, -15056790, -7935931},
+ FieldElement{-30024462, 5626926, -551567, -9981087, 753598, 11981191, 25244767, -3239766, -3356550, 9594024},
+ FieldElement{-23752644, 2636870, -5163910, -10103818, 585134, 7877383, 11345683, -6492290, 13352335, -10977084},
+ },
+ {
+ FieldElement{-1931799, -5407458, 3304649, -12884869, 17015806, -4877091, -29783850, -7752482, -13215537, -319204},
+ FieldElement{20239939, 6607058, 6203985, 3483793, -18386976, -779229, -20723742, 15077870, -22750759, 14523817},
+ FieldElement{27406042, -6041657, 27423596, -4497394, 4996214, 10002360, -28842031, -4545494, -30172742, -4805667},
+ },
+ },
+ {
+ {
+ FieldElement{11374242, 12660715, 17861383, -12540833, 10935568, 1099227, -13886076, -9091740, -27727044, 11358504},
+ FieldElement{-12730809, 10311867, 1510375, 10778093, -2119455, -9145702, 32676003, 11149336, -26123651, 4985768},
+ FieldElement{-19096303, 341147, -6197485, -239033, 15756973, -8796662, -983043, 13794114, -19414307, -15621255},
+ },
+ {
+ FieldElement{6490081, 11940286, 25495923, -7726360, 8668373, -8751316, 3367603, 6970005, -1691065, -9004790},
+ FieldElement{1656497, 13457317, 15370807, 6364910, 13605745, 8362338, -19174622, -5475723, -16796596, -5031438},
+ FieldElement{-22273315, -13524424, -64685, -4334223, -18605636, -10921968, -20571065, -7007978, -99853, -10237333},
+ },
+ {
+ FieldElement{17747465, 10039260, 19368299, -4050591, -20630635, -16041286, 31992683, -15857976, -29260363, -5511971},
+ FieldElement{31932027, -4986141, -19612382, 16366580, 22023614, 88450, 11371999, -3744247, 4882242, -10626905},
+ FieldElement{29796507, 37186, 19818052, 10115756, -11829032, 3352736, 18551198, 3272828, -5190932, -4162409},
+ },
+ {
+ FieldElement{12501286, 4044383, -8612957, -13392385, -32430052, 5136599, -19230378, -3529697, 330070, -3659409},
+ FieldElement{6384877, 2899513, 17807477, 7663917, -2358888, 12363165, 25366522, -8573892, -271295, 12071499},
+ FieldElement{-8365515, -4042521, 25133448, -4517355, -6211027, 2265927, -32769618, 1936675, -5159697, 3829363},
+ },
+ {
+ FieldElement{28425966, -5835433, -577090, -4697198, -14217555, 6870930, 7921550, -6567787, 26333140, 14267664},
+ FieldElement{-11067219, 11871231, 27385719, -10559544, -4585914, -11189312, 10004786, -8709488, -21761224, 8930324},
+ FieldElement{-21197785, -16396035, 25654216, -1725397, 12282012, 11008919, 1541940, 4757911, -26491501, -16408940},
+ },
+ {
+ FieldElement{13537262, -7759490, -20604840, 10961927, -5922820, -13218065, -13156584, 6217254, -15943699, 13814990},
+ FieldElement{-17422573, 15157790, 18705543, 29619, 24409717, -260476, 27361681, 9257833, -1956526, -1776914},
+ FieldElement{-25045300, -10191966, 15366585, 15166509, -13105086, 8423556, -29171540, 12361135, -18685978, 4578290},
+ },
+ {
+ FieldElement{24579768, 3711570, 1342322, -11180126, -27005135, 14124956, -22544529, 14074919, 21964432, 8235257},
+ FieldElement{-6528613, -2411497, 9442966, -5925588, 12025640, -1487420, -2981514, -1669206, 13006806, 2355433},
+ FieldElement{-16304899, -13605259, -6632427, -5142349, 16974359, -10911083, 27202044, 1719366, 1141648, -12796236},
+ },
+ {
+ FieldElement{-12863944, -13219986, -8318266, -11018091, -6810145, -4843894, 13475066, -3133972, 32674895, 13715045},
+ FieldElement{11423335, -5468059, 32344216, 8962751, 24989809, 9241752, -13265253, 16086212, -28740881, -15642093},
+ FieldElement{-1409668, 12530728, -6368726, 10847387, 19531186, -14132160, -11709148, 7791794, -27245943, 4383347},
+ },
+ },
+ {
+ {
+ FieldElement{-28970898, 5271447, -1266009, -9736989, -12455236, 16732599, -4862407, -4906449, 27193557, 6245191},
+ FieldElement{-15193956, 5362278, -1783893, 2695834, 4960227, 12840725, 23061898, 3260492, 22510453, 8577507},
+ FieldElement{-12632451, 11257346, -32692994, 13548177, -721004, 10879011, 31168030, 13952092, -29571492, -3635906},
+ },
+ {
+ FieldElement{3877321, -9572739, 32416692, 5405324, -11004407, -13656635, 3759769, 11935320, 5611860, 8164018},
+ FieldElement{-16275802, 14667797, 15906460, 12155291, -22111149, -9039718, 32003002, -8832289, 5773085, -8422109},
+ FieldElement{-23788118, -8254300, 1950875, 8937633, 18686727, 16459170, -905725, 12376320, 31632953, 190926},
+ },
+ {
+ FieldElement{-24593607, -16138885, -8423991, 13378746, 14162407, 6901328, -8288749, 4508564, -25341555, -3627528},
+ FieldElement{8884438, -5884009, 6023974, 10104341, -6881569, -4941533, 18722941, -14786005, -1672488, 827625},
+ FieldElement{-32720583, -16289296, -32503547, 7101210, 13354605, 2659080, -1800575, -14108036, -24878478, 1541286},
+ },
+ {
+ FieldElement{2901347, -1117687, 3880376, -10059388, -17620940, -3612781, -21802117, -3567481, 20456845, -1885033},
+ FieldElement{27019610, 12299467, -13658288, -1603234, -12861660, -4861471, -19540150, -5016058, 29439641, 15138866},
+ FieldElement{21536104, -6626420, -32447818, -10690208, -22408077, 5175814, -5420040, -16361163, 7779328, 109896},
+ },
+ {
+ FieldElement{30279744, 14648750, -8044871, 6425558, 13639621, -743509, 28698390, 12180118, 23177719, -554075},
+ FieldElement{26572847, 3405927, -31701700, 12890905, -19265668, 5335866, -6493768, 2378492, 4439158, -13279347},
+ FieldElement{-22716706, 3489070, -9225266, -332753, 18875722, -1140095, 14819434, -12731527, -17717757, -5461437},
+ },
+ {
+ FieldElement{-5056483, 16566551, 15953661, 3767752, -10436499, 15627060, -820954, 2177225, 8550082, -15114165},
+ FieldElement{-18473302, 16596775, -381660, 15663611, 22860960, 15585581, -27844109, -3582739, -23260460, -8428588},
+ FieldElement{-32480551, 15707275, -8205912, -5652081, 29464558, 2713815, -22725137, 15860482, -21902570, 1494193},
+ },
+ {
+ FieldElement{-19562091, -14087393, -25583872, -9299552, 13127842, 759709, 21923482, 16529112, 8742704, 12967017},
+ FieldElement{-28464899, 1553205, 32536856, -10473729, -24691605, -406174, -8914625, -2933896, -29903758, 15553883},
+ FieldElement{21877909, 3230008, 9881174, 10539357, -4797115, 2841332, 11543572, 14513274, 19375923, -12647961},
+ },
+ {
+ FieldElement{8832269, -14495485, 13253511, 5137575, 5037871, 4078777, 24880818, -6222716, 2862653, 9455043},
+ FieldElement{29306751, 5123106, 20245049, -14149889, 9592566, 8447059, -2077124, -2990080, 15511449, 4789663},
+ FieldElement{-20679756, 7004547, 8824831, -9434977, -4045704, -3750736, -5754762, 108893, 23513200, 16652362},
+ },
+ },
+ {
+ {
+ FieldElement{-33256173, 4144782, -4476029, -6579123, 10770039, -7155542, -6650416, -12936300, -18319198, 10212860},
+ FieldElement{2756081, 8598110, 7383731, -6859892, 22312759, -1105012, 21179801, 2600940, -9988298, -12506466},
+ FieldElement{-24645692, 13317462, -30449259, -15653928, 21365574, -10869657, 11344424, 864440, -2499677, -16710063},
+ },
+ {
+ FieldElement{-26432803, 6148329, -17184412, -14474154, 18782929, -275997, -22561534, 211300, 2719757, 4940997},
+ FieldElement{-1323882, 3911313, -6948744, 14759765, -30027150, 7851207, 21690126, 8518463, 26699843, 5276295},
+ FieldElement{-13149873, -6429067, 9396249, 365013, 24703301, -10488939, 1321586, 149635, -15452774, 7159369},
+ },
+ {
+ FieldElement{9987780, -3404759, 17507962, 9505530, 9731535, -2165514, 22356009, 8312176, 22477218, -8403385},
+ FieldElement{18155857, -16504990, 19744716, 9006923, 15154154, -10538976, 24256460, -4864995, -22548173, 9334109},
+ FieldElement{2986088, -4911893, 10776628, -3473844, 10620590, -7083203, -21413845, 14253545, -22587149, 536906},
+ },
+ {
+ FieldElement{4377756, 8115836, 24567078, 15495314, 11625074, 13064599, 7390551, 10589625, 10838060, -15420424},
+ FieldElement{-19342404, 867880, 9277171, -3218459, -14431572, -1986443, 19295826, -15796950, 6378260, 699185},
+ FieldElement{7895026, 4057113, -7081772, -13077756, -17886831, -323126, -716039, 15693155, -5045064, -13373962},
+ },
+ {
+ FieldElement{-7737563, -5869402, -14566319, -7406919, 11385654, 13201616, 31730678, -10962840, -3918636, -9669325},
+ FieldElement{10188286, -15770834, -7336361, 13427543, 22223443, 14896287, 30743455, 7116568, -21786507, 5427593},
+ FieldElement{696102, 13206899, 27047647, -10632082, 15285305, -9853179, 10798490, -4578720, 19236243, 12477404},
+ },
+ {
+ FieldElement{-11229439, 11243796, -17054270, -8040865, -788228, -8167967, -3897669, 11180504, -23169516, 7733644},
+ FieldElement{17800790, -14036179, -27000429, -11766671, 23887827, 3149671, 23466177, -10538171, 10322027, 15313801},
+ FieldElement{26246234, 11968874, 32263343, -5468728, 6830755, -13323031, -15794704, -101982, -24449242, 10890804},
+ },
+ {
+ FieldElement{-31365647, 10271363, -12660625, -6267268, 16690207, -13062544, -14982212, 16484931, 25180797, -5334884},
+ FieldElement{-586574, 10376444, -32586414, -11286356, 19801893, 10997610, 2276632, 9482883, 316878, 13820577},
+ FieldElement{-9882808, -4510367, -2115506, 16457136, -11100081, 11674996, 30756178, -7515054, 30696930, -3712849},
+ },
+ {
+ FieldElement{32988917, -9603412, 12499366, 7910787, -10617257, -11931514, -7342816, -9985397, -32349517, 7392473},
+ FieldElement{-8855661, 15927861, 9866406, -3649411, -2396914, -16655781, -30409476, -9134995, 25112947, -2926644},
+ FieldElement{-2504044, -436966, 25621774, -5678772, 15085042, -5479877, -24884878, -13526194, 5537438, -13914319},
+ },
+ },
+ {
+ {
+ FieldElement{-11225584, 2320285, -9584280, 10149187, -33444663, 5808648, -14876251, -1729667, 31234590, 6090599},
+ FieldElement{-9633316, 116426, 26083934, 2897444, -6364437, -2688086, 609721, 15878753, -6970405, -9034768},
+ FieldElement{-27757857, 247744, -15194774, -9002551, 23288161, -10011936, -23869595, 6503646, 20650474, 1804084},
+ },
+ {
+ FieldElement{-27589786, 15456424, 8972517, 8469608, 15640622, 4439847, 3121995, -10329713, 27842616, -202328},
+ FieldElement{-15306973, 2839644, 22530074, 10026331, 4602058, 5048462, 28248656, 5031932, -11375082, 12714369},
+ FieldElement{20807691, -7270825, 29286141, 11421711, -27876523, -13868230, -21227475, 1035546, -19733229, 12796920},
+ },
+ {
+ FieldElement{12076899, -14301286, -8785001, -11848922, -25012791, 16400684, -17591495, -12899438, 3480665, -15182815},
+ FieldElement{-32361549, 5457597, 28548107, 7833186, 7303070, -11953545, -24363064, -15921875, -33374054, 2771025},
+ FieldElement{-21389266, 421932, 26597266, 6860826, 22486084, -6737172, -17137485, -4210226, -24552282, 15673397},
+ },
+ {
+ FieldElement{-20184622, 2338216, 19788685, -9620956, -4001265, -8740893, -20271184, 4733254, 3727144, -12934448},
+ FieldElement{6120119, 814863, -11794402, -622716, 6812205, -15747771, 2019594, 7975683, 31123697, -10958981},
+ FieldElement{30069250, -11435332, 30434654, 2958439, 18399564, -976289, 12296869, 9204260, -16432438, 9648165},
+ },
+ {
+ FieldElement{32705432, -1550977, 30705658, 7451065, -11805606, 9631813, 3305266, 5248604, -26008332, -11377501},
+ FieldElement{17219865, 2375039, -31570947, -5575615, -19459679, 9219903, 294711, 15298639, 2662509, -16297073},
+ FieldElement{-1172927, -7558695, -4366770, -4287744, -21346413, -8434326, 32087529, -1222777, 32247248, -14389861},
+ },
+ {
+ FieldElement{14312628, 1221556, 17395390, -8700143, -4945741, -8684635, -28197744, -9637817, -16027623, -13378845},
+ FieldElement{-1428825, -9678990, -9235681, 6549687, -7383069, -468664, 23046502, 9803137, 17597934, 2346211},
+ FieldElement{18510800, 15337574, 26171504, 981392, -22241552, 7827556, -23491134, -11323352, 3059833, -11782870},
+ },
+ {
+ FieldElement{10141598, 6082907, 17829293, -1947643, 9830092, 13613136, -25556636, -5544586, -33502212, 3592096},
+ FieldElement{33114168, -15889352, -26525686, -13343397, 33076705, 8716171, 1151462, 1521897, -982665, -6837803},
+ FieldElement{-32939165, -4255815, 23947181, -324178, -33072974, -12305637, -16637686, 3891704, 26353178, 693168},
+ },
+ {
+ FieldElement{30374239, 1595580, -16884039, 13186931, 4600344, 406904, 9585294, -400668, 31375464, 14369965},
+ FieldElement{-14370654, -7772529, 1510301, 6434173, -18784789, -6262728, 32732230, -13108839, 17901441, 16011505},
+ FieldElement{18171223, -11934626, -12500402, 15197122, -11038147, -15230035, -19172240, -16046376, 8764035, 12309598},
+ },
+ },
+ {
+ {
+ FieldElement{5975908, -5243188, -19459362, -9681747, -11541277, 14015782, -23665757, 1228319, 17544096, -10593782},
+ FieldElement{5811932, -1715293, 3442887, -2269310, -18367348, -8359541, -18044043, -15410127, -5565381, 12348900},
+ FieldElement{-31399660, 11407555, 25755363, 6891399, -3256938, 14872274, -24849353, 8141295, -10632534, -585479},
+ },
+ {
+ FieldElement{-12675304, 694026, -5076145, 13300344, 14015258, -14451394, -9698672, -11329050, 30944593, 1130208},
+ FieldElement{8247766, -6710942, -26562381, -7709309, -14401939, -14648910, 4652152, 2488540, 23550156, -271232},
+ FieldElement{17294316, -3788438, 7026748, 15626851, 22990044, 113481, 2267737, -5908146, -408818, -137719},
+ },
+ {
+ FieldElement{16091085, -16253926, 18599252, 7340678, 2137637, -1221657, -3364161, 14550936, 3260525, -7166271},
+ FieldElement{-4910104, -13332887, 18550887, 10864893, -16459325, -7291596, -23028869, -13204905, -12748722, 2701326},
+ FieldElement{-8574695, 16099415, 4629974, -16340524, -20786213, -6005432, -10018363, 9276971, 11329923, 1862132},
+ },
+ {
+ FieldElement{14763076, -15903608, -30918270, 3689867, 3511892, 10313526, -21951088, 12219231, -9037963, -940300},
+ FieldElement{8894987, -3446094, 6150753, 3013931, 301220, 15693451, -31981216, -2909717, -15438168, 11595570},
+ FieldElement{15214962, 3537601, -26238722, -14058872, 4418657, -15230761, 13947276, 10730794, -13489462, -4363670},
+ },
+ {
+ FieldElement{-2538306, 7682793, 32759013, 263109, -29984731, -7955452, -22332124, -10188635, 977108, 699994},
+ FieldElement{-12466472, 4195084, -9211532, 550904, -15565337, 12917920, 19118110, -439841, -30534533, -14337913},
+ FieldElement{31788461, -14507657, 4799989, 7372237, 8808585, -14747943, 9408237, -10051775, 12493932, -5409317},
+ },
+ {
+ FieldElement{-25680606, 5260744, -19235809, -6284470, -3695942, 16566087, 27218280, 2607121, 29375955, 6024730},
+ FieldElement{842132, -2794693, -4763381, -8722815, 26332018, -12405641, 11831880, 6985184, -9940361, 2854096},
+ FieldElement{-4847262, -7969331, 2516242, -5847713, 9695691, -7221186, 16512645, 960770, 12121869, 16648078},
+ },
+ {
+ FieldElement{-15218652, 14667096, -13336229, 2013717, 30598287, -464137, -31504922, -7882064, 20237806, 2838411},
+ FieldElement{-19288047, 4453152, 15298546, -16178388, 22115043, -15972604, 12544294, -13470457, 1068881, -12499905},
+ FieldElement{-9558883, -16518835, 33238498, 13506958, 30505848, -1114596, -8486907, -2630053, 12521378, 4845654},
+ },
+ {
+ FieldElement{-28198521, 10744108, -2958380, 10199664, 7759311, -13088600, 3409348, -873400, -6482306, -12885870},
+ FieldElement{-23561822, 6230156, -20382013, 10655314, -24040585, -11621172, 10477734, -1240216, -3113227, 13974498},
+ FieldElement{12966261, 15550616, -32038948, -1615346, 21025980, -629444, 5642325, 7188737, 18895762, 12629579},
+ },
+ },
+ {
+ {
+ FieldElement{14741879, -14946887, 22177208, -11721237, 1279741, 8058600, 11758140, 789443, 32195181, 3895677},
+ FieldElement{10758205, 15755439, -4509950, 9243698, -4879422, 6879879, -2204575, -3566119, -8982069, 4429647},
+ FieldElement{-2453894, 15725973, -20436342, -10410672, -5803908, -11040220, -7135870, -11642895, 18047436, -15281743},
+ },
+ {
+ FieldElement{-25173001, -11307165, 29759956, 11776784, -22262383, -15820455, 10993114, -12850837, -17620701, -9408468},
+ FieldElement{21987233, 700364, -24505048, 14972008, -7774265, -5718395, 32155026, 2581431, -29958985, 8773375},
+ FieldElement{-25568350, 454463, -13211935, 16126715, 25240068, 8594567, 20656846, 12017935, -7874389, -13920155},
+ },
+ {
+ FieldElement{6028182, 6263078, -31011806, -11301710, -818919, 2461772, -31841174, -5468042, -1721788, -2776725},
+ FieldElement{-12278994, 16624277, 987579, -5922598, 32908203, 1248608, 7719845, -4166698, 28408820, 6816612},
+ FieldElement{-10358094, -8237829, 19549651, -12169222, 22082623, 16147817, 20613181, 13982702, -10339570, 5067943},
+ },
+ {
+ FieldElement{-30505967, -3821767, 12074681, 13582412, -19877972, 2443951, -19719286, 12746132, 5331210, -10105944},
+ FieldElement{30528811, 3601899, -1957090, 4619785, -27361822, -15436388, 24180793, -12570394, 27679908, -1648928},
+ FieldElement{9402404, -13957065, 32834043, 10838634, -26580150, -13237195, 26653274, -8685565, 22611444, -12715406},
+ },
+ {
+ FieldElement{22190590, 1118029, 22736441, 15130463, -30460692, -5991321, 19189625, -4648942, 4854859, 6622139},
+ FieldElement{-8310738, -2953450, -8262579, -3388049, -10401731, -271929, 13424426, -3567227, 26404409, 13001963},
+ FieldElement{-31241838, -15415700, -2994250, 8939346, 11562230, -12840670, -26064365, -11621720, -15405155, 11020693},
+ },
+ {
+ FieldElement{1866042, -7949489, -7898649, -10301010, 12483315, 13477547, 3175636, -12424163, 28761762, 1406734},
+ FieldElement{-448555, -1777666, 13018551, 3194501, -9580420, -11161737, 24760585, -4347088, 25577411, -13378680},
+ FieldElement{-24290378, 4759345, -690653, -1852816, 2066747, 10693769, -29595790, 9884936, -9368926, 4745410},
+ },
+ {
+ FieldElement{-9141284, 6049714, -19531061, -4341411, -31260798, 9944276, -15462008, -11311852, 10931924, -11931931},
+ FieldElement{-16561513, 14112680, -8012645, 4817318, -8040464, -11414606, -22853429, 10856641, -20470770, 13434654},
+ FieldElement{22759489, -10073434, -16766264, -1871422, 13637442, -10168091, 1765144, -12654326, 28445307, -5364710},
+ },
+ {
+ FieldElement{29875063, 12493613, 2795536, -3786330, 1710620, 15181182, -10195717, -8788675, 9074234, 1167180},
+ FieldElement{-26205683, 11014233, -9842651, -2635485, -26908120, 7532294, -18716888, -9535498, 3843903, 9367684},
+ FieldElement{-10969595, -6403711, 9591134, 9582310, 11349256, 108879, 16235123, 8601684, -139197, 4242895},
+ },
+ },
+ {
+ {
+ FieldElement{22092954, -13191123, -2042793, -11968512, 32186753, -11517388, -6574341, 2470660, -27417366, 16625501},
+ FieldElement{-11057722, 3042016, 13770083, -9257922, 584236, -544855, -7770857, 2602725, -27351616, 14247413},
+ FieldElement{6314175, -10264892, -32772502, 15957557, -10157730, 168750, -8618807, 14290061, 27108877, -1180880},
+ },
+ {
+ FieldElement{-8586597, -7170966, 13241782, 10960156, -32991015, -13794596, 33547976, -11058889, -27148451, 981874},
+ FieldElement{22833440, 9293594, -32649448, -13618667, -9136966, 14756819, -22928859, -13970780, -10479804, -16197962},
+ FieldElement{-7768587, 3326786, -28111797, 10783824, 19178761, 14905060, 22680049, 13906969, -15933690, 3797899},
+ },
+ {
+ FieldElement{21721356, -4212746, -12206123, 9310182, -3882239, -13653110, 23740224, -2709232, 20491983, -8042152},
+ FieldElement{9209270, -15135055, -13256557, -6167798, -731016, 15289673, 25947805, 15286587, 30997318, -6703063},
+ FieldElement{7392032, 16618386, 23946583, -8039892, -13265164, -1533858, -14197445, -2321576, 17649998, -250080},
+ },
+ {
+ FieldElement{-9301088, -14193827, 30609526, -3049543, -25175069, -1283752, -15241566, -9525724, -2233253, 7662146},
+ FieldElement{-17558673, 1763594, -33114336, 15908610, -30040870, -12174295, 7335080, -8472199, -3174674, 3440183},
+ FieldElement{-19889700, -5977008, -24111293, -9688870, 10799743, -16571957, 40450, -4431835, 4862400, 1133},
+ },
+ {
+ FieldElement{-32856209, -7873957, -5422389, 14860950, -16319031, 7956142, 7258061, 311861, -30594991, -7379421},
+ FieldElement{-3773428, -1565936, 28985340, 7499440, 24445838, 9325937, 29727763, 16527196, 18278453, 15405622},
+ FieldElement{-4381906, 8508652, -19898366, -3674424, -5984453, 15149970, -13313598, 843523, -21875062, 13626197},
+ },
+ {
+ FieldElement{2281448, -13487055, -10915418, -2609910, 1879358, 16164207, -10783882, 3953792, 13340839, 15928663},
+ FieldElement{31727126, -7179855, -18437503, -8283652, 2875793, -16390330, -25269894, -7014826, -23452306, 5964753},
+ FieldElement{4100420, -5959452, -17179337, 6017714, -18705837, 12227141, -26684835, 11344144, 2538215, -7570755},
+ },
+ {
+ FieldElement{-9433605, 6123113, 11159803, -2156608, 30016280, 14966241, -20474983, 1485421, -629256, -15958862},
+ FieldElement{-26804558, 4260919, 11851389, 9658551, -32017107, 16367492, -20205425, -13191288, 11659922, -11115118},
+ FieldElement{26180396, 10015009, -30844224, -8581293, 5418197, 9480663, 2231568, -10170080, 33100372, -1306171},
+ },
+ {
+ FieldElement{15121113, -5201871, -10389905, 15427821, -27509937, -15992507, 21670947, 4486675, -5931810, -14466380},
+ FieldElement{16166486, -9483733, -11104130, 6023908, -31926798, -1364923, 2340060, -16254968, -10735770, -10039824},
+ FieldElement{28042865, -3557089, -12126526, 12259706, -3717498, -6945899, 6766453, -8689599, 18036436, 5803270},
+ },
+ },
+ {
+ {
+ FieldElement{-817581, 6763912, 11803561, 1585585, 10958447, -2671165, 23855391, 4598332, -6159431, -14117438},
+ FieldElement{-31031306, -14256194, 17332029, -2383520, 31312682, -5967183, 696309, 50292, -20095739, 11763584},
+ FieldElement{-594563, -2514283, -32234153, 12643980, 12650761, 14811489, 665117, -12613632, -19773211, -10713562},
+ },
+ {
+ FieldElement{30464590, -11262872, -4127476, -12734478, 19835327, -7105613, -24396175, 2075773, -17020157, 992471},
+ FieldElement{18357185, -6994433, 7766382, 16342475, -29324918, 411174, 14578841, 8080033, -11574335, -10601610},
+ FieldElement{19598397, 10334610, 12555054, 2555664, 18821899, -10339780, 21873263, 16014234, 26224780, 16452269},
+ },
+ {
+ FieldElement{-30223925, 5145196, 5944548, 16385966, 3976735, 2009897, -11377804, -7618186, -20533829, 3698650},
+ FieldElement{14187449, 3448569, -10636236, -10810935, -22663880, -3433596, 7268410, -10890444, 27394301, 12015369},
+ FieldElement{19695761, 16087646, 28032085, 12999827, 6817792, 11427614, 20244189, -1312777, -13259127, -3402461},
+ },
+ {
+ FieldElement{30860103, 12735208, -1888245, -4699734, -16974906, 2256940, -8166013, 12298312, -8550524, -10393462},
+ FieldElement{-5719826, -11245325, -1910649, 15569035, 26642876, -7587760, -5789354, -15118654, -4976164, 12651793},
+ FieldElement{-2848395, 9953421, 11531313, -5282879, 26895123, -12697089, -13118820, -16517902, 9768698, -2533218},
+ },
+ {
+ FieldElement{-24719459, 1894651, -287698, -4704085, 15348719, -8156530, 32767513, 12765450, 4940095, 10678226},
+ FieldElement{18860224, 15980149, -18987240, -1562570, -26233012, -11071856, -7843882, 13944024, -24372348, 16582019},
+ FieldElement{-15504260, 4970268, -29893044, 4175593, -20993212, -2199756, -11704054, 15444560, -11003761, 7989037},
+ },
+ {
+ FieldElement{31490452, 5568061, -2412803, 2182383, -32336847, 4531686, -32078269, 6200206, -19686113, -14800171},
+ FieldElement{-17308668, -15879940, -31522777, -2831, -32887382, 16375549, 8680158, -16371713, 28550068, -6857132},
+ FieldElement{-28126887, -5688091, 16837845, -1820458, -6850681, 12700016, -30039981, 4364038, 1155602, 5988841},
+ },
+ {
+ FieldElement{21890435, -13272907, -12624011, 12154349, -7831873, 15300496, 23148983, -4470481, 24618407, 8283181},
+ FieldElement{-33136107, -10512751, 9975416, 6841041, -31559793, 16356536, 3070187, -7025928, 1466169, 10740210},
+ FieldElement{-1509399, -15488185, -13503385, -10655916, 32799044, 909394, -13938903, -5779719, -32164649, -15327040},
+ },
+ {
+ FieldElement{3960823, -14267803, -28026090, -15918051, -19404858, 13146868, 15567327, 951507, -3260321, -573935},
+ FieldElement{24740841, 5052253, -30094131, 8961361, 25877428, 6165135, -24368180, 14397372, -7380369, -6144105},
+ FieldElement{-28888365, 3510803, -28103278, -1158478, -11238128, -10631454, -15441463, -14453128, -1625486, -6494814},
+ },
+ },
+ {
+ {
+ FieldElement{793299, -9230478, 8836302, -6235707, -27360908, -2369593, 33152843, -4885251, -9906200, -621852},
+ FieldElement{5666233, 525582, 20782575, -8038419, -24538499, 14657740, 16099374, 1468826, -6171428, -15186581},
+ FieldElement{-4859255, -3779343, -2917758, -6748019, 7778750, 11688288, -30404353, -9871238, -1558923, -9863646},
+ },
+ {
+ FieldElement{10896332, -7719704, 824275, 472601, -19460308, 3009587, 25248958, 14783338, -30581476, -15757844},
+ FieldElement{10566929, 12612572, -31944212, 11118703, -12633376, 12362879, 21752402, 8822496, 24003793, 14264025},
+ FieldElement{27713862, -7355973, -11008240, 9227530, 27050101, 2504721, 23886875, -13117525, 13958495, -5732453},
+ },
+ {
+ FieldElement{-23481610, 4867226, -27247128, 3900521, 29838369, -8212291, -31889399, -10041781, 7340521, -15410068},
+ FieldElement{4646514, -8011124, -22766023, -11532654, 23184553, 8566613, 31366726, -1381061, -15066784, -10375192},
+ FieldElement{-17270517, 12723032, -16993061, 14878794, 21619651, -6197576, 27584817, 3093888, -8843694, 3849921},
+ },
+ {
+ FieldElement{-9064912, 2103172, 25561640, -15125738, -5239824, 9582958, 32477045, -9017955, 5002294, -15550259},
+ FieldElement{-12057553, -11177906, 21115585, -13365155, 8808712, -12030708, 16489530, 13378448, -25845716, 12741426},
+ FieldElement{-5946367, 10645103, -30911586, 15390284, -3286982, -7118677, 24306472, 15852464, 28834118, -7646072},
+ },
+ {
+ FieldElement{-17335748, -9107057, -24531279, 9434953, -8472084, -583362, -13090771, 455841, 20461858, 5491305},
+ FieldElement{13669248, -16095482, -12481974, -10203039, -14569770, -11893198, -24995986, 11293807, -28588204, -9421832},
+ FieldElement{28497928, 6272777, -33022994, 14470570, 8906179, -1225630, 18504674, -14165166, 29867745, -8795943},
+ },
+ {
+ FieldElement{-16207023, 13517196, -27799630, -13697798, 24009064, -6373891, -6367600, -13175392, 22853429, -4012011},
+ FieldElement{24191378, 16712145, -13931797, 15217831, 14542237, 1646131, 18603514, -11037887, 12876623, -2112447},
+ FieldElement{17902668, 4518229, -411702, -2829247, 26878217, 5258055, -12860753, 608397, 16031844, 3723494},
+ },
+ {
+ FieldElement{-28632773, 12763728, -20446446, 7577504, 33001348, -13017745, 17558842, -7872890, 23896954, -4314245},
+ FieldElement{-20005381, -12011952, 31520464, 605201, 2543521, 5991821, -2945064, 7229064, -9919646, -8826859},
+ FieldElement{28816045, 298879, -28165016, -15920938, 19000928, -1665890, -12680833, -2949325, -18051778, -2082915},
+ },
+ {
+ FieldElement{16000882, -344896, 3493092, -11447198, -29504595, -13159789, 12577740, 16041268, -19715240, 7847707},
+ FieldElement{10151868, 10572098, 27312476, 7922682, 14825339, 4723128, -32855931, -6519018, -10020567, 3852848},
+ FieldElement{-11430470, 15697596, -21121557, -4420647, 5386314, 15063598, 16514493, -15932110, 29330899, -15076224},
+ },
+ },
+ {
+ {
+ FieldElement{-25499735, -4378794, -15222908, -6901211, 16615731, 2051784, 3303702, 15490, -27548796, 12314391},
+ FieldElement{15683520, -6003043, 18109120, -9980648, 15337968, -5997823, -16717435, 15921866, 16103996, -3731215},
+ FieldElement{-23169824, -10781249, 13588192, -1628807, -3798557, -1074929, -19273607, 5402699, -29815713, -9841101},
+ },
+ {
+ FieldElement{23190676, 2384583, -32714340, 3462154, -29903655, -1529132, -11266856, 8911517, -25205859, 2739713},
+ FieldElement{21374101, -3554250, -33524649, 9874411, 15377179, 11831242, -33529904, 6134907, 4931255, 11987849},
+ FieldElement{-7732, -2978858, -16223486, 7277597, 105524, -322051, -31480539, 13861388, -30076310, 10117930},
+ },
+ {
+ FieldElement{-29501170, -10744872, -26163768, 13051539, -25625564, 5089643, -6325503, 6704079, 12890019, 15728940},
+ FieldElement{-21972360, -11771379, -951059, -4418840, 14704840, 2695116, 903376, -10428139, 12885167, 8311031},
+ FieldElement{-17516482, 5352194, 10384213, -13811658, 7506451, 13453191, 26423267, 4384730, 1888765, -5435404},
+ },
+ {
+ FieldElement{-25817338, -3107312, -13494599, -3182506, 30896459, -13921729, -32251644, -12707869, -19464434, -3340243},
+ FieldElement{-23607977, -2665774, -526091, 4651136, 5765089, 4618330, 6092245, 14845197, 17151279, -9854116},
+ FieldElement{-24830458, -12733720, -15165978, 10367250, -29530908, -265356, 22825805, -7087279, -16866484, 16176525},
+ },
+ {
+ FieldElement{-23583256, 6564961, 20063689, 3798228, -4740178, 7359225, 2006182, -10363426, -28746253, -10197509},
+ FieldElement{-10626600, -4486402, -13320562, -5125317, 3432136, -6393229, 23632037, -1940610, 32808310, 1099883},
+ FieldElement{15030977, 5768825, -27451236, -2887299, -6427378, -15361371, -15277896, -6809350, 2051441, -15225865},
+ },
+ {
+ FieldElement{-3362323, -7239372, 7517890, 9824992, 23555850, 295369, 5148398, -14154188, -22686354, 16633660},
+ FieldElement{4577086, -16752288, 13249841, -15304328, 19958763, -14537274, 18559670, -10759549, 8402478, -9864273},
+ FieldElement{-28406330, -1051581, -26790155, -907698, -17212414, -11030789, 9453451, -14980072, 17983010, 9967138},
+ },
+ {
+ FieldElement{-25762494, 6524722, 26585488, 9969270, 24709298, 1220360, -1677990, 7806337, 17507396, 3651560},
+ FieldElement{-10420457, -4118111, 14584639, 15971087, -15768321, 8861010, 26556809, -5574557, -18553322, -11357135},
+ FieldElement{2839101, 14284142, 4029895, 3472686, 14402957, 12689363, -26642121, 8459447, -5605463, -7621941},
+ },
+ {
+ FieldElement{-4839289, -3535444, 9744961, 2871048, 25113978, 3187018, -25110813, -849066, 17258084, -7977739},
+ FieldElement{18164541, -10595176, -17154882, -1542417, 19237078, -9745295, 23357533, -15217008, 26908270, 12150756},
+ FieldElement{-30264870, -7647865, 5112249, -7036672, -1499807, -6974257, 43168, -5537701, -32302074, 16215819},
+ },
+ },
+ {
+ {
+ FieldElement{-6898905, 9824394, -12304779, -4401089, -31397141, -6276835, 32574489, 12532905, -7503072, -8675347},
+ FieldElement{-27343522, -16515468, -27151524, -10722951, 946346, 16291093, 254968, 7168080, 21676107, -1943028},
+ FieldElement{21260961, -8424752, -16831886, -11920822, -23677961, 3968121, -3651949, -6215466, -3556191, -7913075},
+ },
+ {
+ FieldElement{16544754, 13250366, -16804428, 15546242, -4583003, 12757258, -2462308, -8680336, -18907032, -9662799},
+ FieldElement{-2415239, -15577728, 18312303, 4964443, -15272530, -12653564, 26820651, 16690659, 25459437, -4564609},
+ FieldElement{-25144690, 11425020, 28423002, -11020557, -6144921, -15826224, 9142795, -2391602, -6432418, -1644817},
+ },
+ {
+ FieldElement{-23104652, 6253476, 16964147, -3768872, -25113972, -12296437, -27457225, -16344658, 6335692, 7249989},
+ FieldElement{-30333227, 13979675, 7503222, -12368314, -11956721, -4621693, -30272269, 2682242, 25993170, -12478523},
+ FieldElement{4364628, 5930691, 32304656, -10044554, -8054781, 15091131, 22857016, -10598955, 31820368, 15075278},
+ },
+ {
+ FieldElement{31879134, -8918693, 17258761, 90626, -8041836, -4917709, 24162788, -9650886, -17970238, 12833045},
+ FieldElement{19073683, 14851414, -24403169, -11860168, 7625278, 11091125, -19619190, 2074449, -9413939, 14905377},
+ FieldElement{24483667, -11935567, -2518866, -11547418, -1553130, 15355506, -25282080, 9253129, 27628530, -7555480},
+ },
+ {
+ FieldElement{17597607, 8340603, 19355617, 552187, 26198470, -3176583, 4593324, -9157582, -14110875, 15297016},
+ FieldElement{510886, 14337390, -31785257, 16638632, 6328095, 2713355, -20217417, -11864220, 8683221, 2921426},
+ FieldElement{18606791, 11874196, 27155355, -5281482, -24031742, 6265446, -25178240, -1278924, 4674690, 13890525},
+ },
+ {
+ FieldElement{13609624, 13069022, -27372361, -13055908, 24360586, 9592974, 14977157, 9835105, 4389687, 288396},
+ FieldElement{9922506, -519394, 13613107, 5883594, -18758345, -434263, -12304062, 8317628, 23388070, 16052080},
+ FieldElement{12720016, 11937594, -31970060, -5028689, 26900120, 8561328, -20155687, -11632979, -14754271, -10812892},
+ },
+ {
+ FieldElement{15961858, 14150409, 26716931, -665832, -22794328, 13603569, 11829573, 7467844, -28822128, 929275},
+ FieldElement{11038231, -11582396, -27310482, -7316562, -10498527, -16307831, -23479533, -9371869, -21393143, 2465074},
+ FieldElement{20017163, -4323226, 27915242, 1529148, 12396362, 15675764, 13817261, -9658066, 2463391, -4622140},
+ },
+ {
+ FieldElement{-16358878, -12663911, -12065183, 4996454, -1256422, 1073572, 9583558, 12851107, 4003896, 12673717},
+ FieldElement{-1731589, -15155870, -3262930, 16143082, 19294135, 13385325, 14741514, -9103726, 7903886, 2348101},
+ FieldElement{24536016, -16515207, 12715592, -3862155, 1511293, 10047386, -3842346, -7129159, -28377538, 10048127},
+ },
+ },
+ {
+ {
+ FieldElement{-12622226, -6204820, 30718825, 2591312, -10617028, 12192840, 18873298, -7297090, -32297756, 15221632},
+ FieldElement{-26478122, -11103864, 11546244, -1852483, 9180880, 7656409, -21343950, 2095755, 29769758, 6593415},
+ FieldElement{-31994208, -2907461, 4176912, 3264766, 12538965, -868111, 26312345, -6118678, 30958054, 8292160},
+ },
+ {
+ FieldElement{31429822, -13959116, 29173532, 15632448, 12174511, -2760094, 32808831, 3977186, 26143136, -3148876},
+ FieldElement{22648901, 1402143, -22799984, 13746059, 7936347, 365344, -8668633, -1674433, -3758243, -2304625},
+ FieldElement{-15491917, 8012313, -2514730, -12702462, -23965846, -10254029, -1612713, -1535569, -16664475, 8194478},
+ },
+ {
+ FieldElement{27338066, -7507420, -7414224, 10140405, -19026427, -6589889, 27277191, 8855376, 28572286, 3005164},
+ FieldElement{26287124, 4821776, 25476601, -4145903, -3764513, -15788984, -18008582, 1182479, -26094821, -13079595},
+ FieldElement{-7171154, 3178080, 23970071, 6201893, -17195577, -4489192, -21876275, -13982627, 32208683, -1198248},
+ },
+ {
+ FieldElement{-16657702, 2817643, -10286362, 14811298, 6024667, 13349505, -27315504, -10497842, -27672585, -11539858},
+ FieldElement{15941029, -9405932, -21367050, 8062055, 31876073, -238629, -15278393, -1444429, 15397331, -4130193},
+ FieldElement{8934485, -13485467, -23286397, -13423241, -32446090, 14047986, 31170398, -1441021, -27505566, 15087184},
+ },
+ {
+ FieldElement{-18357243, -2156491, 24524913, -16677868, 15520427, -6360776, -15502406, 11461896, 16788528, -5868942},
+ FieldElement{-1947386, 16013773, 21750665, 3714552, -17401782, -16055433, -3770287, -10323320, 31322514, -11615635},
+ FieldElement{21426655, -5650218, -13648287, -5347537, -28812189, -4920970, -18275391, -14621414, 13040862, -12112948},
+ },
+ {
+ FieldElement{11293895, 12478086, -27136401, 15083750, -29307421, 14748872, 14555558, -13417103, 1613711, 4896935},
+ FieldElement{-25894883, 15323294, -8489791, -8057900, 25967126, -13425460, 2825960, -4897045, -23971776, -11267415},
+ FieldElement{-15924766, -5229880, -17443532, 6410664, 3622847, 10243618, 20615400, 12405433, -23753030, -8436416},
+ },
+ {
+ FieldElement{-7091295, 12556208, -20191352, 9025187, -17072479, 4333801, 4378436, 2432030, 23097949, -566018},
+ FieldElement{4565804, -16025654, 20084412, -7842817, 1724999, 189254, 24767264, 10103221, -18512313, 2424778},
+ FieldElement{366633, -11976806, 8173090, -6890119, 30788634, 5745705, -7168678, 1344109, -3642553, 12412659},
+ },
+ {
+ FieldElement{-24001791, 7690286, 14929416, -168257, -32210835, -13412986, 24162697, -15326504, -3141501, 11179385},
+ FieldElement{18289522, -14724954, 8056945, 16430056, -21729724, 7842514, -6001441, -1486897, -18684645, -11443503},
+ FieldElement{476239, 6601091, -6152790, -9723375, 17503545, -4863900, 27672959, 13403813, 11052904, 5219329},
+ },
+ },
+ {
+ {
+ FieldElement{20678546, -8375738, -32671898, 8849123, -5009758, 14574752, 31186971, -3973730, 9014762, -8579056},
+ FieldElement{-13644050, -10350239, -15962508, 5075808, -1514661, -11534600, -33102500, 9160280, 8473550, -3256838},
+ FieldElement{24900749, 14435722, 17209120, -15292541, -22592275, 9878983, -7689309, -16335821, -24568481, 11788948},
+ },
+ {
+ FieldElement{-3118155, -11395194, -13802089, 14797441, 9652448, -6845904, -20037437, 10410733, -24568470, -1458691},
+ FieldElement{-15659161, 16736706, -22467150, 10215878, -9097177, 7563911, 11871841, -12505194, -18513325, 8464118},
+ FieldElement{-23400612, 8348507, -14585951, -861714, -3950205, -6373419, 14325289, 8628612, 33313881, -8370517},
+ },
+ {
+ FieldElement{-20186973, -4967935, 22367356, 5271547, -1097117, -4788838, -24805667, -10236854, -8940735, -5818269},
+ FieldElement{-6948785, -1795212, -32625683, -16021179, 32635414, -7374245, 15989197, -12838188, 28358192, -4253904},
+ FieldElement{-23561781, -2799059, -32351682, -1661963, -9147719, 10429267, -16637684, 4072016, -5351664, 5596589},
+ },
+ {
+ FieldElement{-28236598, -3390048, 12312896, 6213178, 3117142, 16078565, 29266239, 2557221, 1768301, 15373193},
+ FieldElement{-7243358, -3246960, -4593467, -7553353, -127927, -912245, -1090902, -4504991, -24660491, 3442910},
+ FieldElement{-30210571, 5124043, 14181784, 8197961, 18964734, -11939093, 22597931, 7176455, -18585478, 13365930},
+ },
+ {
+ FieldElement{-7877390, -1499958, 8324673, 4690079, 6261860, 890446, 24538107, -8570186, -9689599, -3031667},
+ FieldElement{25008904, -10771599, -4305031, -9638010, 16265036, 15721635, 683793, -11823784, 15723479, -15163481},
+ FieldElement{-9660625, 12374379, -27006999, -7026148, -7724114, -12314514, 11879682, 5400171, 519526, -1235876},
+ },
+ {
+ FieldElement{22258397, -16332233, -7869817, 14613016, -22520255, -2950923, -20353881, 7315967, 16648397, 7605640},
+ FieldElement{-8081308, -8464597, -8223311, 9719710, 19259459, -15348212, 23994942, -5281555, -9468848, 4763278},
+ FieldElement{-21699244, 9220969, -15730624, 1084137, -25476107, -2852390, 31088447, -7764523, -11356529, 728112},
+ },
+ {
+ FieldElement{26047220, -11751471, -6900323, -16521798, 24092068, 9158119, -4273545, -12555558, -29365436, -5498272},
+ FieldElement{17510331, -322857, 5854289, 8403524, 17133918, -3112612, -28111007, 12327945, 10750447, 10014012},
+ FieldElement{-10312768, 3936952, 9156313, -8897683, 16498692, -994647, -27481051, -666732, 3424691, 7540221},
+ },
+ {
+ FieldElement{30322361, -6964110, 11361005, -4143317, 7433304, 4989748, -7071422, -16317219, -9244265, 15258046},
+ FieldElement{13054562, -2779497, 19155474, 469045, -12482797, 4566042, 5631406, 2711395, 1062915, -5136345},
+ FieldElement{-19240248, -11254599, -29509029, -7499965, -5835763, 13005411, -6066489, 12194497, 32960380, 1459310},
+ },
+ },
+ {
+ {
+ FieldElement{19852034, 7027924, 23669353, 10020366, 8586503, -6657907, 394197, -6101885, 18638003, -11174937},
+ FieldElement{31395534, 15098109, 26581030, 8030562, -16527914, -5007134, 9012486, -7584354, -6643087, -5442636},
+ FieldElement{-9192165, -2347377, -1997099, 4529534, 25766844, 607986, -13222, 9677543, -32294889, -6456008},
+ },
+ {
+ FieldElement{-2444496, -149937, 29348902, 8186665, 1873760, 12489863, -30934579, -7839692, -7852844, -8138429},
+ FieldElement{-15236356, -15433509, 7766470, 746860, 26346930, -10221762, -27333451, 10754588, -9431476, 5203576},
+ FieldElement{31834314, 14135496, -770007, 5159118, 20917671, -16768096, -7467973, -7337524, 31809243, 7347066},
+ },
+ {
+ FieldElement{-9606723, -11874240, 20414459, 13033986, 13716524, -11691881, 19797970, -12211255, 15192876, -2087490},
+ FieldElement{-12663563, -2181719, 1168162, -3804809, 26747877, -14138091, 10609330, 12694420, 33473243, -13382104},
+ FieldElement{33184999, 11180355, 15832085, -11385430, -1633671, 225884, 15089336, -11023903, -6135662, 14480053},
+ },
+ {
+ FieldElement{31308717, -5619998, 31030840, -1897099, 15674547, -6582883, 5496208, 13685227, 27595050, 8737275},
+ FieldElement{-20318852, -15150239, 10933843, -16178022, 8335352, -7546022, -31008351, -12610604, 26498114, 66511},
+ FieldElement{22644454, -8761729, -16671776, 4884562, -3105614, -13559366, 30540766, -4286747, -13327787, -7515095},
+ },
+ {
+ FieldElement{-28017847, 9834845, 18617207, -2681312, -3401956, -13307506, 8205540, 13585437, -17127465, 15115439},
+ FieldElement{23711543, -672915, 31206561, -8362711, 6164647, -9709987, -33535882, -1426096, 8236921, 16492939},
+ FieldElement{-23910559, -13515526, -26299483, -4503841, 25005590, -7687270, 19574902, 10071562, 6708380, -6222424},
+ },
+ {
+ FieldElement{2101391, -4930054, 19702731, 2367575, -15427167, 1047675, 5301017, 9328700, 29955601, -11678310},
+ FieldElement{3096359, 9271816, -21620864, -15521844, -14847996, -7592937, -25892142, -12635595, -9917575, 6216608},
+ FieldElement{-32615849, 338663, -25195611, 2510422, -29213566, -13820213, 24822830, -6146567, -26767480, 7525079},
+ },
+ {
+ FieldElement{-23066649, -13985623, 16133487, -7896178, -3389565, 778788, -910336, -2782495, -19386633, 11994101},
+ FieldElement{21691500, -13624626, -641331, -14367021, 3285881, -3483596, -25064666, 9718258, -7477437, 13381418},
+ FieldElement{18445390, -4202236, 14979846, 11622458, -1727110, -3582980, 23111648, -6375247, 28535282, 15779576},
+ },
+ {
+ FieldElement{30098053, 3089662, -9234387, 16662135, -21306940, 11308411, -14068454, 12021730, 9955285, -16303356},
+ FieldElement{9734894, -14576830, -7473633, -9138735, 2060392, 11313496, -18426029, 9924399, 20194861, 13380996},
+ FieldElement{-26378102, -7965207, -22167821, 15789297, -18055342, -6168792, -1984914, 15707771, 26342023, 10146099},
+ },
+ },
+ {
+ {
+ FieldElement{-26016874, -219943, 21339191, -41388, 19745256, -2878700, -29637280, 2227040, 21612326, -545728},
+ FieldElement{-13077387, 1184228, 23562814, -5970442, -20351244, -6348714, 25764461, 12243797, -20856566, 11649658},
+ FieldElement{-10031494, 11262626, 27384172, 2271902, 26947504, -15997771, 39944, 6114064, 33514190, 2333242},
+ },
+ {
+ FieldElement{-21433588, -12421821, 8119782, 7219913, -21830522, -9016134, -6679750, -12670638, 24350578, -13450001},
+ FieldElement{-4116307, -11271533, -23886186, 4843615, -30088339, 690623, -31536088, -10406836, 8317860, 12352766},
+ FieldElement{18200138, -14475911, -33087759, -2696619, -23702521, -9102511, -23552096, -2287550, 20712163, 6719373},
+ },
+ {
+ FieldElement{26656208, 6075253, -7858556, 1886072, -28344043, 4262326, 11117530, -3763210, 26224235, -3297458},
+ FieldElement{-17168938, -14854097, -3395676, -16369877, -19954045, 14050420, 21728352, 9493610, 18620611, -16428628},
+ FieldElement{-13323321, 13325349, 11432106, 5964811, 18609221, 6062965, -5269471, -9725556, -30701573, -16479657},
+ },
+ {
+ FieldElement{-23860538, -11233159, 26961357, 1640861, -32413112, -16737940, 12248509, -5240639, 13735342, 1934062},
+ FieldElement{25089769, 6742589, 17081145, -13406266, 21909293, -16067981, -15136294, -3765346, -21277997, 5473616},
+ FieldElement{31883677, -7961101, 1083432, -11572403, 22828471, 13290673, -7125085, 12469656, 29111212, -5451014},
+ },
+ {
+ FieldElement{24244947, -15050407, -26262976, 2791540, -14997599, 16666678, 24367466, 6388839, -10295587, 452383},
+ FieldElement{-25640782, -3417841, 5217916, 16224624, 19987036, -4082269, -24236251, -5915248, 15766062, 8407814},
+ FieldElement{-20406999, 13990231, 15495425, 16395525, 5377168, 15166495, -8917023, -4388953, -8067909, 2276718},
+ },
+ {
+ FieldElement{30157918, 12924066, -17712050, 9245753, 19895028, 3368142, -23827587, 5096219, 22740376, -7303417},
+ FieldElement{2041139, -14256350, 7783687, 13876377, -25946985, -13352459, 24051124, 13742383, -15637599, 13295222},
+ FieldElement{33338237, -8505733, 12532113, 7977527, 9106186, -1715251, -17720195, -4612972, -4451357, -14669444},
+ },
+ {
+ FieldElement{-20045281, 5454097, -14346548, 6447146, 28862071, 1883651, -2469266, -4141880, 7770569, 9620597},
+ FieldElement{23208068, 7979712, 33071466, 8149229, 1758231, -10834995, 30945528, -1694323, -33502340, -14767970},
+ FieldElement{1439958, -16270480, -1079989, -793782, 4625402, 10647766, -5043801, 1220118, 30494170, -11440799},
+ },
+ {
+ FieldElement{-5037580, -13028295, -2970559, -3061767, 15640974, -6701666, -26739026, 926050, -1684339, -13333647},
+ FieldElement{13908495, -3549272, 30919928, -6273825, -21521863, 7989039, 9021034, 9078865, 3353509, 4033511},
+ FieldElement{-29663431, -15113610, 32259991, -344482, 24295849, -12912123, 23161163, 8839127, 27485041, 7356032},
+ },
+ },
+ {
+ {
+ FieldElement{9661027, 705443, 11980065, -5370154, -1628543, 14661173, -6346142, 2625015, 28431036, -16771834},
+ FieldElement{-23839233, -8311415, -25945511, 7480958, -17681669, -8354183, -22545972, 14150565, 15970762, 4099461},
+ FieldElement{29262576, 16756590, 26350592, -8793563, 8529671, -11208050, 13617293, -9937143, 11465739, 8317062},
+ },
+ {
+ FieldElement{-25493081, -6962928, 32500200, -9419051, -23038724, -2302222, 14898637, 3848455, 20969334, -5157516},
+ FieldElement{-20384450, -14347713, -18336405, 13884722, -33039454, 2842114, -21610826, -3649888, 11177095, 14989547},
+ FieldElement{-24496721, -11716016, 16959896, 2278463, 12066309, 10137771, 13515641, 2581286, -28487508, 9930240},
+ },
+ {
+ FieldElement{-17751622, -2097826, 16544300, -13009300, -15914807, -14949081, 18345767, -13403753, 16291481, -5314038},
+ FieldElement{-33229194, 2553288, 32678213, 9875984, 8534129, 6889387, -9676774, 6957617, 4368891, 9788741},
+ FieldElement{16660756, 7281060, -10830758, 12911820, 20108584, -8101676, -21722536, -8613148, 16250552, -11111103},
+ },
+ {
+ FieldElement{-19765507, 2390526, -16551031, 14161980, 1905286, 6414907, 4689584, 10604807, -30190403, 4782747},
+ FieldElement{-1354539, 14736941, -7367442, -13292886, 7710542, -14155590, -9981571, 4383045, 22546403, 437323},
+ FieldElement{31665577, -12180464, -16186830, 1491339, -18368625, 3294682, 27343084, 2786261, -30633590, -14097016},
+ },
+ {
+ FieldElement{-14467279, -683715, -33374107, 7448552, 19294360, 14334329, -19690631, 2355319, -19284671, -6114373},
+ FieldElement{15121312, -15796162, 6377020, -6031361, -10798111, -12957845, 18952177, 15496498, -29380133, 11754228},
+ FieldElement{-2637277, -13483075, 8488727, -14303896, 12728761, -1622493, 7141596, 11724556, 22761615, -10134141},
+ },
+ {
+ FieldElement{16918416, 11729663, -18083579, 3022987, -31015732, -13339659, -28741185, -12227393, 32851222, 11717399},
+ FieldElement{11166634, 7338049, -6722523, 4531520, -29468672, -7302055, 31474879, 3483633, -1193175, -4030831},
+ FieldElement{-185635, 9921305, 31456609, -13536438, -12013818, 13348923, 33142652, 6546660, -19985279, -3948376},
+ },
+ {
+ FieldElement{-32460596, 11266712, -11197107, -7899103, 31703694, 3855903, -8537131, -12833048, -30772034, -15486313},
+ FieldElement{-18006477, 12709068, 3991746, -6479188, -21491523, -10550425, -31135347, -16049879, 10928917, 3011958},
+ FieldElement{-6957757, -15594337, 31696059, 334240, 29576716, 14796075, -30831056, -12805180, 18008031, 10258577},
+ },
+ {
+ FieldElement{-22448644, 15655569, 7018479, -4410003, -30314266, -1201591, -1853465, 1367120, 25127874, 6671743},
+ FieldElement{29701166, -14373934, -10878120, 9279288, -17568, 13127210, 21382910, 11042292, 25838796, 4642684},
+ FieldElement{-20430234, 14955537, -24126347, 8124619, -5369288, -5990470, 30468147, -13900640, 18423289, 4177476},
+ },
+ },
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go
new file mode 100644
index 000000000..5f8b99478
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go
@@ -0,0 +1,1771 @@
+// 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.
+
+package edwards25519
+
+// This code is a port of the public domain, “ref10” implementation of ed25519
+// from SUPERCOP.
+
+// FieldElement represents an element of the field GF(2^255 - 19). An element
+// t, entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77
+// t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on
+// context.
+type FieldElement [10]int32
+
+var zero FieldElement
+
+func FeZero(fe *FieldElement) {
+ copy(fe[:], zero[:])
+}
+
+func FeOne(fe *FieldElement) {
+ FeZero(fe)
+ fe[0] = 1
+}
+
+func FeAdd(dst, a, b *FieldElement) {
+ dst[0] = a[0] + b[0]
+ dst[1] = a[1] + b[1]
+ dst[2] = a[2] + b[2]
+ dst[3] = a[3] + b[3]
+ dst[4] = a[4] + b[4]
+ dst[5] = a[5] + b[5]
+ dst[6] = a[6] + b[6]
+ dst[7] = a[7] + b[7]
+ dst[8] = a[8] + b[8]
+ dst[9] = a[9] + b[9]
+}
+
+func FeSub(dst, a, b *FieldElement) {
+ dst[0] = a[0] - b[0]
+ dst[1] = a[1] - b[1]
+ dst[2] = a[2] - b[2]
+ dst[3] = a[3] - b[3]
+ dst[4] = a[4] - b[4]
+ dst[5] = a[5] - b[5]
+ dst[6] = a[6] - b[6]
+ dst[7] = a[7] - b[7]
+ dst[8] = a[8] - b[8]
+ dst[9] = a[9] - b[9]
+}
+
+func FeCopy(dst, src *FieldElement) {
+ copy(dst[:], src[:])
+}
+
+// Replace (f,g) with (g,g) if b == 1;
+// replace (f,g) with (f,g) if b == 0.
+//
+// Preconditions: b in {0,1}.
+func FeCMove(f, g *FieldElement, b int32) {
+ b = -b
+ f[0] ^= b & (f[0] ^ g[0])
+ f[1] ^= b & (f[1] ^ g[1])
+ f[2] ^= b & (f[2] ^ g[2])
+ f[3] ^= b & (f[3] ^ g[3])
+ f[4] ^= b & (f[4] ^ g[4])
+ f[5] ^= b & (f[5] ^ g[5])
+ f[6] ^= b & (f[6] ^ g[6])
+ f[7] ^= b & (f[7] ^ g[7])
+ f[8] ^= b & (f[8] ^ g[8])
+ f[9] ^= b & (f[9] ^ g[9])
+}
+
+func load3(in []byte) int64 {
+ var r int64
+ r = int64(in[0])
+ r |= int64(in[1]) << 8
+ r |= int64(in[2]) << 16
+ return r
+}
+
+func load4(in []byte) int64 {
+ var r int64
+ r = int64(in[0])
+ r |= int64(in[1]) << 8
+ r |= int64(in[2]) << 16
+ r |= int64(in[3]) << 24
+ return r
+}
+
+func FeFromBytes(dst *FieldElement, src *[32]byte) {
+ h0 := load4(src[:])
+ h1 := load3(src[4:]) << 6
+ h2 := load3(src[7:]) << 5
+ h3 := load3(src[10:]) << 3
+ h4 := load3(src[13:]) << 2
+ h5 := load4(src[16:])
+ h6 := load3(src[20:]) << 7
+ h7 := load3(src[23:]) << 5
+ h8 := load3(src[26:]) << 4
+ h9 := (load3(src[29:]) & 8388607) << 2
+
+ FeCombine(dst, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9)
+}
+
+// FeToBytes marshals h to s.
+// Preconditions:
+// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+//
+// Write p=2^255-19; q=floor(h/p).
+// Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))).
+//
+// Proof:
+// Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4.
+// Also have |h-2^230 h9|<2^230 so |19 2^(-255)(h-2^230 h9)|<1/4.
+//
+// Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9).
+// Then 0<y<1.
+//
+// Write r=h-pq.
+// Have 0<=r<=p-1=2^255-20.
+// Thus 0<=r+19(2^-255)r<r+19(2^-255)2^255<=2^255-1.
+//
+// Write x=r+19(2^-255)r+y.
+// Then 0<x<2^255 so floor(2^(-255)x) = 0 so floor(q+2^(-255)x) = q.
+//
+// Have q+2^(-255)x = 2^(-255)(h + 19 2^(-25) h9 + 2^(-1))
+// so floor(2^(-255)(h + 19 2^(-25) h9 + 2^(-1))) = q.
+func FeToBytes(s *[32]byte, h *FieldElement) {
+ var carry [10]int32
+
+ q := (19*h[9] + (1 << 24)) >> 25
+ q = (h[0] + q) >> 26
+ q = (h[1] + q) >> 25
+ q = (h[2] + q) >> 26
+ q = (h[3] + q) >> 25
+ q = (h[4] + q) >> 26
+ q = (h[5] + q) >> 25
+ q = (h[6] + q) >> 26
+ q = (h[7] + q) >> 25
+ q = (h[8] + q) >> 26
+ q = (h[9] + q) >> 25
+
+ // Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20.
+ h[0] += 19 * q
+ // Goal: Output h-2^255 q, which is between 0 and 2^255-20.
+
+ carry[0] = h[0] >> 26
+ h[1] += carry[0]
+ h[0] -= carry[0] << 26
+ carry[1] = h[1] >> 25
+ h[2] += carry[1]
+ h[1] -= carry[1] << 25
+ carry[2] = h[2] >> 26
+ h[3] += carry[2]
+ h[2] -= carry[2] << 26
+ carry[3] = h[3] >> 25
+ h[4] += carry[3]
+ h[3] -= carry[3] << 25
+ carry[4] = h[4] >> 26
+ h[5] += carry[4]
+ h[4] -= carry[4] << 26
+ carry[5] = h[5] >> 25
+ h[6] += carry[5]
+ h[5] -= carry[5] << 25
+ carry[6] = h[6] >> 26
+ h[7] += carry[6]
+ h[6] -= carry[6] << 26
+ carry[7] = h[7] >> 25
+ h[8] += carry[7]
+ h[7] -= carry[7] << 25
+ carry[8] = h[8] >> 26
+ h[9] += carry[8]
+ h[8] -= carry[8] << 26
+ carry[9] = h[9] >> 25
+ h[9] -= carry[9] << 25
+ // h10 = carry9
+
+ // Goal: Output h[0]+...+2^255 h10-2^255 q, which is between 0 and 2^255-20.
+ // Have h[0]+...+2^230 h[9] between 0 and 2^255-1;
+ // evidently 2^255 h10-2^255 q = 0.
+ // Goal: Output h[0]+...+2^230 h[9].
+
+ s[0] = byte(h[0] >> 0)
+ s[1] = byte(h[0] >> 8)
+ s[2] = byte(h[0] >> 16)
+ s[3] = byte((h[0] >> 24) | (h[1] << 2))
+ s[4] = byte(h[1] >> 6)
+ s[5] = byte(h[1] >> 14)
+ s[6] = byte((h[1] >> 22) | (h[2] << 3))
+ s[7] = byte(h[2] >> 5)
+ s[8] = byte(h[2] >> 13)
+ s[9] = byte((h[2] >> 21) | (h[3] << 5))
+ s[10] = byte(h[3] >> 3)
+ s[11] = byte(h[3] >> 11)
+ s[12] = byte((h[3] >> 19) | (h[4] << 6))
+ s[13] = byte(h[4] >> 2)
+ s[14] = byte(h[4] >> 10)
+ s[15] = byte(h[4] >> 18)
+ s[16] = byte(h[5] >> 0)
+ s[17] = byte(h[5] >> 8)
+ s[18] = byte(h[5] >> 16)
+ s[19] = byte((h[5] >> 24) | (h[6] << 1))
+ s[20] = byte(h[6] >> 7)
+ s[21] = byte(h[6] >> 15)
+ s[22] = byte((h[6] >> 23) | (h[7] << 3))
+ s[23] = byte(h[7] >> 5)
+ s[24] = byte(h[7] >> 13)
+ s[25] = byte((h[7] >> 21) | (h[8] << 4))
+ s[26] = byte(h[8] >> 4)
+ s[27] = byte(h[8] >> 12)
+ s[28] = byte((h[8] >> 20) | (h[9] << 6))
+ s[29] = byte(h[9] >> 2)
+ s[30] = byte(h[9] >> 10)
+ s[31] = byte(h[9] >> 18)
+}
+
+func FeIsNegative(f *FieldElement) byte {
+ var s [32]byte
+ FeToBytes(&s, f)
+ return s[0] & 1
+}
+
+func FeIsNonZero(f *FieldElement) int32 {
+ var s [32]byte
+ FeToBytes(&s, f)
+ var x uint8
+ for _, b := range s {
+ x |= b
+ }
+ x |= x >> 4
+ x |= x >> 2
+ x |= x >> 1
+ return int32(x & 1)
+}
+
+// FeNeg sets h = -f
+//
+// Preconditions:
+// |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+//
+// Postconditions:
+// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+func FeNeg(h, f *FieldElement) {
+ h[0] = -f[0]
+ h[1] = -f[1]
+ h[2] = -f[2]
+ h[3] = -f[3]
+ h[4] = -f[4]
+ h[5] = -f[5]
+ h[6] = -f[6]
+ h[7] = -f[7]
+ h[8] = -f[8]
+ h[9] = -f[9]
+}
+
+func FeCombine(h *FieldElement, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 int64) {
+ var c0, c1, c2, c3, c4, c5, c6, c7, c8, c9 int64
+
+ /*
+ |h0| <= (1.1*1.1*2^52*(1+19+19+19+19)+1.1*1.1*2^50*(38+38+38+38+38))
+ i.e. |h0| <= 1.2*2^59; narrower ranges for h2, h4, h6, h8
+ |h1| <= (1.1*1.1*2^51*(1+1+19+19+19+19+19+19+19+19))
+ i.e. |h1| <= 1.5*2^58; narrower ranges for h3, h5, h7, h9
+ */
+
+ c0 = (h0 + (1 << 25)) >> 26
+ h1 += c0
+ h0 -= c0 << 26
+ c4 = (h4 + (1 << 25)) >> 26
+ h5 += c4
+ h4 -= c4 << 26
+ /* |h0| <= 2^25 */
+ /* |h4| <= 2^25 */
+ /* |h1| <= 1.51*2^58 */
+ /* |h5| <= 1.51*2^58 */
+
+ c1 = (h1 + (1 << 24)) >> 25
+ h2 += c1
+ h1 -= c1 << 25
+ c5 = (h5 + (1 << 24)) >> 25
+ h6 += c5
+ h5 -= c5 << 25
+ /* |h1| <= 2^24; from now on fits into int32 */
+ /* |h5| <= 2^24; from now on fits into int32 */
+ /* |h2| <= 1.21*2^59 */
+ /* |h6| <= 1.21*2^59 */
+
+ c2 = (h2 + (1 << 25)) >> 26
+ h3 += c2
+ h2 -= c2 << 26
+ c6 = (h6 + (1 << 25)) >> 26
+ h7 += c6
+ h6 -= c6 << 26
+ /* |h2| <= 2^25; from now on fits into int32 unchanged */
+ /* |h6| <= 2^25; from now on fits into int32 unchanged */
+ /* |h3| <= 1.51*2^58 */
+ /* |h7| <= 1.51*2^58 */
+
+ c3 = (h3 + (1 << 24)) >> 25
+ h4 += c3
+ h3 -= c3 << 25
+ c7 = (h7 + (1 << 24)) >> 25
+ h8 += c7
+ h7 -= c7 << 25
+ /* |h3| <= 2^24; from now on fits into int32 unchanged */
+ /* |h7| <= 2^24; from now on fits into int32 unchanged */
+ /* |h4| <= 1.52*2^33 */
+ /* |h8| <= 1.52*2^33 */
+
+ c4 = (h4 + (1 << 25)) >> 26
+ h5 += c4
+ h4 -= c4 << 26
+ c8 = (h8 + (1 << 25)) >> 26
+ h9 += c8
+ h8 -= c8 << 26
+ /* |h4| <= 2^25; from now on fits into int32 unchanged */
+ /* |h8| <= 2^25; from now on fits into int32 unchanged */
+ /* |h5| <= 1.01*2^24 */
+ /* |h9| <= 1.51*2^58 */
+
+ c9 = (h9 + (1 << 24)) >> 25
+ h0 += c9 * 19
+ h9 -= c9 << 25
+ /* |h9| <= 2^24; from now on fits into int32 unchanged */
+ /* |h0| <= 1.8*2^37 */
+
+ c0 = (h0 + (1 << 25)) >> 26
+ h1 += c0
+ h0 -= c0 << 26
+ /* |h0| <= 2^25; from now on fits into int32 unchanged */
+ /* |h1| <= 1.01*2^24 */
+
+ h[0] = int32(h0)
+ h[1] = int32(h1)
+ h[2] = int32(h2)
+ h[3] = int32(h3)
+ h[4] = int32(h4)
+ h[5] = int32(h5)
+ h[6] = int32(h6)
+ h[7] = int32(h7)
+ h[8] = int32(h8)
+ h[9] = int32(h9)
+}
+
+// FeMul calculates h = f * g
+// Can overlap h with f or g.
+//
+// Preconditions:
+// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
+// |g| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
+//
+// Postconditions:
+// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+//
+// Notes on implementation strategy:
+//
+// Using schoolbook multiplication.
+// Karatsuba would save a little in some cost models.
+//
+// Most multiplications by 2 and 19 are 32-bit precomputations;
+// cheaper than 64-bit postcomputations.
+//
+// There is one remaining multiplication by 19 in the carry chain;
+// one *19 precomputation can be merged into this,
+// but the resulting data flow is considerably less clean.
+//
+// There are 12 carries below.
+// 10 of them are 2-way parallelizable and vectorizable.
+// Can get away with 11 carries, but then data flow is much deeper.
+//
+// With tighter constraints on inputs, can squeeze carries into int32.
+func FeMul(h, f, g *FieldElement) {
+ f0 := int64(f[0])
+ f1 := int64(f[1])
+ f2 := int64(f[2])
+ f3 := int64(f[3])
+ f4 := int64(f[4])
+ f5 := int64(f[5])
+ f6 := int64(f[6])
+ f7 := int64(f[7])
+ f8 := int64(f[8])
+ f9 := int64(f[9])
+
+ f1_2 := int64(2 * f[1])
+ f3_2 := int64(2 * f[3])
+ f5_2 := int64(2 * f[5])
+ f7_2 := int64(2 * f[7])
+ f9_2 := int64(2 * f[9])
+
+ g0 := int64(g[0])
+ g1 := int64(g[1])
+ g2 := int64(g[2])
+ g3 := int64(g[3])
+ g4 := int64(g[4])
+ g5 := int64(g[5])
+ g6 := int64(g[6])
+ g7 := int64(g[7])
+ g8 := int64(g[8])
+ g9 := int64(g[9])
+
+ g1_19 := int64(19 * g[1]) /* 1.4*2^29 */
+ g2_19 := int64(19 * g[2]) /* 1.4*2^30; still ok */
+ g3_19 := int64(19 * g[3])
+ g4_19 := int64(19 * g[4])
+ g5_19 := int64(19 * g[5])
+ g6_19 := int64(19 * g[6])
+ g7_19 := int64(19 * g[7])
+ g8_19 := int64(19 * g[8])
+ g9_19 := int64(19 * g[9])
+
+ h0 := f0*g0 + f1_2*g9_19 + f2*g8_19 + f3_2*g7_19 + f4*g6_19 + f5_2*g5_19 + f6*g4_19 + f7_2*g3_19 + f8*g2_19 + f9_2*g1_19
+ h1 := f0*g1 + f1*g0 + f2*g9_19 + f3*g8_19 + f4*g7_19 + f5*g6_19 + f6*g5_19 + f7*g4_19 + f8*g3_19 + f9*g2_19
+ h2 := f0*g2 + f1_2*g1 + f2*g0 + f3_2*g9_19 + f4*g8_19 + f5_2*g7_19 + f6*g6_19 + f7_2*g5_19 + f8*g4_19 + f9_2*g3_19
+ h3 := f0*g3 + f1*g2 + f2*g1 + f3*g0 + f4*g9_19 + f5*g8_19 + f6*g7_19 + f7*g6_19 + f8*g5_19 + f9*g4_19
+ h4 := f0*g4 + f1_2*g3 + f2*g2 + f3_2*g1 + f4*g0 + f5_2*g9_19 + f6*g8_19 + f7_2*g7_19 + f8*g6_19 + f9_2*g5_19
+ h5 := f0*g5 + f1*g4 + f2*g3 + f3*g2 + f4*g1 + f5*g0 + f6*g9_19 + f7*g8_19 + f8*g7_19 + f9*g6_19
+ h6 := f0*g6 + f1_2*g5 + f2*g4 + f3_2*g3 + f4*g2 + f5_2*g1 + f6*g0 + f7_2*g9_19 + f8*g8_19 + f9_2*g7_19
+ h7 := f0*g7 + f1*g6 + f2*g5 + f3*g4 + f4*g3 + f5*g2 + f6*g1 + f7*g0 + f8*g9_19 + f9*g8_19
+ h8 := f0*g8 + f1_2*g7 + f2*g6 + f3_2*g5 + f4*g4 + f5_2*g3 + f6*g2 + f7_2*g1 + f8*g0 + f9_2*g9_19
+ h9 := f0*g9 + f1*g8 + f2*g7 + f3*g6 + f4*g5 + f5*g4 + f6*g3 + f7*g2 + f8*g1 + f9*g0
+
+ FeCombine(h, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9)
+}
+
+func feSquare(f *FieldElement) (h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 int64) {
+ f0 := int64(f[0])
+ f1 := int64(f[1])
+ f2 := int64(f[2])
+ f3 := int64(f[3])
+ f4 := int64(f[4])
+ f5 := int64(f[5])
+ f6 := int64(f[6])
+ f7 := int64(f[7])
+ f8 := int64(f[8])
+ f9 := int64(f[9])
+ f0_2 := int64(2 * f[0])
+ f1_2 := int64(2 * f[1])
+ f2_2 := int64(2 * f[2])
+ f3_2 := int64(2 * f[3])
+ f4_2 := int64(2 * f[4])
+ f5_2 := int64(2 * f[5])
+ f6_2 := int64(2 * f[6])
+ f7_2 := int64(2 * f[7])
+ f5_38 := 38 * f5 // 1.31*2^30
+ f6_19 := 19 * f6 // 1.31*2^30
+ f7_38 := 38 * f7 // 1.31*2^30
+ f8_19 := 19 * f8 // 1.31*2^30
+ f9_38 := 38 * f9 // 1.31*2^30
+
+ h0 = f0*f0 + f1_2*f9_38 + f2_2*f8_19 + f3_2*f7_38 + f4_2*f6_19 + f5*f5_38
+ h1 = f0_2*f1 + f2*f9_38 + f3_2*f8_19 + f4*f7_38 + f5_2*f6_19
+ h2 = f0_2*f2 + f1_2*f1 + f3_2*f9_38 + f4_2*f8_19 + f5_2*f7_38 + f6*f6_19
+ h3 = f0_2*f3 + f1_2*f2 + f4*f9_38 + f5_2*f8_19 + f6*f7_38
+ h4 = f0_2*f4 + f1_2*f3_2 + f2*f2 + f5_2*f9_38 + f6_2*f8_19 + f7*f7_38
+ h5 = f0_2*f5 + f1_2*f4 + f2_2*f3 + f6*f9_38 + f7_2*f8_19
+ h6 = f0_2*f6 + f1_2*f5_2 + f2_2*f4 + f3_2*f3 + f7_2*f9_38 + f8*f8_19
+ h7 = f0_2*f7 + f1_2*f6 + f2_2*f5 + f3_2*f4 + f8*f9_38
+ h8 = f0_2*f8 + f1_2*f7_2 + f2_2*f6 + f3_2*f5_2 + f4*f4 + f9*f9_38
+ h9 = f0_2*f9 + f1_2*f8 + f2_2*f7 + f3_2*f6 + f4_2*f5
+
+ return
+}
+
+// FeSquare calculates h = f*f. Can overlap h with f.
+//
+// Preconditions:
+// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
+//
+// Postconditions:
+// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+func FeSquare(h, f *FieldElement) {
+ h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 := feSquare(f)
+ FeCombine(h, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9)
+}
+
+// FeSquare2 sets h = 2 * f * f
+//
+// Can overlap h with f.
+//
+// Preconditions:
+// |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc.
+//
+// Postconditions:
+// |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc.
+// See fe_mul.c for discussion of implementation strategy.
+func FeSquare2(h, f *FieldElement) {
+ h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 := feSquare(f)
+
+ h0 += h0
+ h1 += h1
+ h2 += h2
+ h3 += h3
+ h4 += h4
+ h5 += h5
+ h6 += h6
+ h7 += h7
+ h8 += h8
+ h9 += h9
+
+ FeCombine(h, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9)
+}
+
+func FeInvert(out, z *FieldElement) {
+ var t0, t1, t2, t3 FieldElement
+ var i int
+
+ FeSquare(&t0, z) // 2^1
+ FeSquare(&t1, &t0) // 2^2
+ for i = 1; i < 2; i++ { // 2^3
+ FeSquare(&t1, &t1)
+ }
+ FeMul(&t1, z, &t1) // 2^3 + 2^0
+ FeMul(&t0, &t0, &t1) // 2^3 + 2^1 + 2^0
+ FeSquare(&t2, &t0) // 2^4 + 2^2 + 2^1
+ FeMul(&t1, &t1, &t2) // 2^4 + 2^3 + 2^2 + 2^1 + 2^0
+ FeSquare(&t2, &t1) // 5,4,3,2,1
+ for i = 1; i < 5; i++ { // 9,8,7,6,5
+ FeSquare(&t2, &t2)
+ }
+ FeMul(&t1, &t2, &t1) // 9,8,7,6,5,4,3,2,1,0
+ FeSquare(&t2, &t1) // 10..1
+ for i = 1; i < 10; i++ { // 19..10
+ FeSquare(&t2, &t2)
+ }
+ FeMul(&t2, &t2, &t1) // 19..0
+ FeSquare(&t3, &t2) // 20..1
+ for i = 1; i < 20; i++ { // 39..20
+ FeSquare(&t3, &t3)
+ }
+ FeMul(&t2, &t3, &t2) // 39..0
+ FeSquare(&t2, &t2) // 40..1
+ for i = 1; i < 10; i++ { // 49..10
+ FeSquare(&t2, &t2)
+ }
+ FeMul(&t1, &t2, &t1) // 49..0
+ FeSquare(&t2, &t1) // 50..1
+ for i = 1; i < 50; i++ { // 99..50
+ FeSquare(&t2, &t2)
+ }
+ FeMul(&t2, &t2, &t1) // 99..0
+ FeSquare(&t3, &t2) // 100..1
+ for i = 1; i < 100; i++ { // 199..100
+ FeSquare(&t3, &t3)
+ }
+ FeMul(&t2, &t3, &t2) // 199..0
+ FeSquare(&t2, &t2) // 200..1
+ for i = 1; i < 50; i++ { // 249..50
+ FeSquare(&t2, &t2)
+ }
+ FeMul(&t1, &t2, &t1) // 249..0
+ FeSquare(&t1, &t1) // 250..1
+ for i = 1; i < 5; i++ { // 254..5
+ FeSquare(&t1, &t1)
+ }
+ FeMul(out, &t1, &t0) // 254..5,3,1,0
+}
+
+func fePow22523(out, z *FieldElement) {
+ var t0, t1, t2 FieldElement
+ var i int
+
+ FeSquare(&t0, z)
+ for i = 1; i < 1; i++ {
+ FeSquare(&t0, &t0)
+ }
+ FeSquare(&t1, &t0)
+ for i = 1; i < 2; i++ {
+ FeSquare(&t1, &t1)
+ }
+ FeMul(&t1, z, &t1)
+ FeMul(&t0, &t0, &t1)
+ FeSquare(&t0, &t0)
+ for i = 1; i < 1; i++ {
+ FeSquare(&t0, &t0)
+ }
+ FeMul(&t0, &t1, &t0)
+ FeSquare(&t1, &t0)
+ for i = 1; i < 5; i++ {
+ FeSquare(&t1, &t1)
+ }
+ FeMul(&t0, &t1, &t0)
+ FeSquare(&t1, &t0)
+ for i = 1; i < 10; i++ {
+ FeSquare(&t1, &t1)
+ }
+ FeMul(&t1, &t1, &t0)
+ FeSquare(&t2, &t1)
+ for i = 1; i < 20; i++ {
+ FeSquare(&t2, &t2)
+ }
+ FeMul(&t1, &t2, &t1)
+ FeSquare(&t1, &t1)
+ for i = 1; i < 10; i++ {
+ FeSquare(&t1, &t1)
+ }
+ FeMul(&t0, &t1, &t0)
+ FeSquare(&t1, &t0)
+ for i = 1; i < 50; i++ {
+ FeSquare(&t1, &t1)
+ }
+ FeMul(&t1, &t1, &t0)
+ FeSquare(&t2, &t1)
+ for i = 1; i < 100; i++ {
+ FeSquare(&t2, &t2)
+ }
+ FeMul(&t1, &t2, &t1)
+ FeSquare(&t1, &t1)
+ for i = 1; i < 50; i++ {
+ FeSquare(&t1, &t1)
+ }
+ FeMul(&t0, &t1, &t0)
+ FeSquare(&t0, &t0)
+ for i = 1; i < 2; i++ {
+ FeSquare(&t0, &t0)
+ }
+ FeMul(out, &t0, z)
+}
+
+// Group elements are members of the elliptic curve -x^2 + y^2 = 1 + d * x^2 *
+// y^2 where d = -121665/121666.
+//
+// Several representations are used:
+// ProjectiveGroupElement: (X:Y:Z) satisfying x=X/Z, y=Y/Z
+// ExtendedGroupElement: (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT
+// CompletedGroupElement: ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T
+// PreComputedGroupElement: (y+x,y-x,2dxy)
+
+type ProjectiveGroupElement struct {
+ X, Y, Z FieldElement
+}
+
+type ExtendedGroupElement struct {
+ X, Y, Z, T FieldElement
+}
+
+type CompletedGroupElement struct {
+ X, Y, Z, T FieldElement
+}
+
+type PreComputedGroupElement struct {
+ yPlusX, yMinusX, xy2d FieldElement
+}
+
+type CachedGroupElement struct {
+ yPlusX, yMinusX, Z, T2d FieldElement
+}
+
+func (p *ProjectiveGroupElement) Zero() {
+ FeZero(&p.X)
+ FeOne(&p.Y)
+ FeOne(&p.Z)
+}
+
+func (p *ProjectiveGroupElement) Double(r *CompletedGroupElement) {
+ var t0 FieldElement
+
+ FeSquare(&r.X, &p.X)
+ FeSquare(&r.Z, &p.Y)
+ FeSquare2(&r.T, &p.Z)
+ FeAdd(&r.Y, &p.X, &p.Y)
+ FeSquare(&t0, &r.Y)
+ FeAdd(&r.Y, &r.Z, &r.X)
+ FeSub(&r.Z, &r.Z, &r.X)
+ FeSub(&r.X, &t0, &r.Y)
+ FeSub(&r.T, &r.T, &r.Z)
+}
+
+func (p *ProjectiveGroupElement) ToBytes(s *[32]byte) {
+ var recip, x, y FieldElement
+
+ FeInvert(&recip, &p.Z)
+ FeMul(&x, &p.X, &recip)
+ FeMul(&y, &p.Y, &recip)
+ FeToBytes(s, &y)
+ s[31] ^= FeIsNegative(&x) << 7
+}
+
+func (p *ExtendedGroupElement) Zero() {
+ FeZero(&p.X)
+ FeOne(&p.Y)
+ FeOne(&p.Z)
+ FeZero(&p.T)
+}
+
+func (p *ExtendedGroupElement) Double(r *CompletedGroupElement) {
+ var q ProjectiveGroupElement
+ p.ToProjective(&q)
+ q.Double(r)
+}
+
+func (p *ExtendedGroupElement) ToCached(r *CachedGroupElement) {
+ FeAdd(&r.yPlusX, &p.Y, &p.X)
+ FeSub(&r.yMinusX, &p.Y, &p.X)
+ FeCopy(&r.Z, &p.Z)
+ FeMul(&r.T2d, &p.T, &d2)
+}
+
+func (p *ExtendedGroupElement) ToProjective(r *ProjectiveGroupElement) {
+ FeCopy(&r.X, &p.X)
+ FeCopy(&r.Y, &p.Y)
+ FeCopy(&r.Z, &p.Z)
+}
+
+func (p *ExtendedGroupElement) ToBytes(s *[32]byte) {
+ var recip, x, y FieldElement
+
+ FeInvert(&recip, &p.Z)
+ FeMul(&x, &p.X, &recip)
+ FeMul(&y, &p.Y, &recip)
+ FeToBytes(s, &y)
+ s[31] ^= FeIsNegative(&x) << 7
+}
+
+func (p *ExtendedGroupElement) FromBytes(s *[32]byte) bool {
+ var u, v, v3, vxx, check FieldElement
+
+ FeFromBytes(&p.Y, s)
+ FeOne(&p.Z)
+ FeSquare(&u, &p.Y)
+ FeMul(&v, &u, &d)
+ FeSub(&u, &u, &p.Z) // y = y^2-1
+ FeAdd(&v, &v, &p.Z) // v = dy^2+1
+
+ FeSquare(&v3, &v)
+ FeMul(&v3, &v3, &v) // v3 = v^3
+ FeSquare(&p.X, &v3)
+ FeMul(&p.X, &p.X, &v)
+ FeMul(&p.X, &p.X, &u) // x = uv^7
+
+ fePow22523(&p.X, &p.X) // x = (uv^7)^((q-5)/8)
+ FeMul(&p.X, &p.X, &v3)
+ FeMul(&p.X, &p.X, &u) // x = uv^3(uv^7)^((q-5)/8)
+
+ var tmpX, tmp2 [32]byte
+
+ FeSquare(&vxx, &p.X)
+ FeMul(&vxx, &vxx, &v)
+ FeSub(&check, &vxx, &u) // vx^2-u
+ if FeIsNonZero(&check) == 1 {
+ FeAdd(&check, &vxx, &u) // vx^2+u
+ if FeIsNonZero(&check) == 1 {
+ return false
+ }
+ FeMul(&p.X, &p.X, &SqrtM1)
+
+ FeToBytes(&tmpX, &p.X)
+ for i, v := range tmpX {
+ tmp2[31-i] = v
+ }
+ }
+
+ if FeIsNegative(&p.X) != (s[31] >> 7) {
+ FeNeg(&p.X, &p.X)
+ }
+
+ FeMul(&p.T, &p.X, &p.Y)
+ return true
+}
+
+func (p *CompletedGroupElement) ToProjective(r *ProjectiveGroupElement) {
+ FeMul(&r.X, &p.X, &p.T)
+ FeMul(&r.Y, &p.Y, &p.Z)
+ FeMul(&r.Z, &p.Z, &p.T)
+}
+
+func (p *CompletedGroupElement) ToExtended(r *ExtendedGroupElement) {
+ FeMul(&r.X, &p.X, &p.T)
+ FeMul(&r.Y, &p.Y, &p.Z)
+ FeMul(&r.Z, &p.Z, &p.T)
+ FeMul(&r.T, &p.X, &p.Y)
+}
+
+func (p *PreComputedGroupElement) Zero() {
+ FeOne(&p.yPlusX)
+ FeOne(&p.yMinusX)
+ FeZero(&p.xy2d)
+}
+
+func geAdd(r *CompletedGroupElement, p *ExtendedGroupElement, q *CachedGroupElement) {
+ var t0 FieldElement
+
+ FeAdd(&r.X, &p.Y, &p.X)
+ FeSub(&r.Y, &p.Y, &p.X)
+ FeMul(&r.Z, &r.X, &q.yPlusX)
+ FeMul(&r.Y, &r.Y, &q.yMinusX)
+ FeMul(&r.T, &q.T2d, &p.T)
+ FeMul(&r.X, &p.Z, &q.Z)
+ FeAdd(&t0, &r.X, &r.X)
+ FeSub(&r.X, &r.Z, &r.Y)
+ FeAdd(&r.Y, &r.Z, &r.Y)
+ FeAdd(&r.Z, &t0, &r.T)
+ FeSub(&r.T, &t0, &r.T)
+}
+
+func geSub(r *CompletedGroupElement, p *ExtendedGroupElement, q *CachedGroupElement) {
+ var t0 FieldElement
+
+ FeAdd(&r.X, &p.Y, &p.X)
+ FeSub(&r.Y, &p.Y, &p.X)
+ FeMul(&r.Z, &r.X, &q.yMinusX)
+ FeMul(&r.Y, &r.Y, &q.yPlusX)
+ FeMul(&r.T, &q.T2d, &p.T)
+ FeMul(&r.X, &p.Z, &q.Z)
+ FeAdd(&t0, &r.X, &r.X)
+ FeSub(&r.X, &r.Z, &r.Y)
+ FeAdd(&r.Y, &r.Z, &r.Y)
+ FeSub(&r.Z, &t0, &r.T)
+ FeAdd(&r.T, &t0, &r.T)
+}
+
+func geMixedAdd(r *CompletedGroupElement, p *ExtendedGroupElement, q *PreComputedGroupElement) {
+ var t0 FieldElement
+
+ FeAdd(&r.X, &p.Y, &p.X)
+ FeSub(&r.Y, &p.Y, &p.X)
+ FeMul(&r.Z, &r.X, &q.yPlusX)
+ FeMul(&r.Y, &r.Y, &q.yMinusX)
+ FeMul(&r.T, &q.xy2d, &p.T)
+ FeAdd(&t0, &p.Z, &p.Z)
+ FeSub(&r.X, &r.Z, &r.Y)
+ FeAdd(&r.Y, &r.Z, &r.Y)
+ FeAdd(&r.Z, &t0, &r.T)
+ FeSub(&r.T, &t0, &r.T)
+}
+
+func geMixedSub(r *CompletedGroupElement, p *ExtendedGroupElement, q *PreComputedGroupElement) {
+ var t0 FieldElement
+
+ FeAdd(&r.X, &p.Y, &p.X)
+ FeSub(&r.Y, &p.Y, &p.X)
+ FeMul(&r.Z, &r.X, &q.yMinusX)
+ FeMul(&r.Y, &r.Y, &q.yPlusX)
+ FeMul(&r.T, &q.xy2d, &p.T)
+ FeAdd(&t0, &p.Z, &p.Z)
+ FeSub(&r.X, &r.Z, &r.Y)
+ FeAdd(&r.Y, &r.Z, &r.Y)
+ FeSub(&r.Z, &t0, &r.T)
+ FeAdd(&r.T, &t0, &r.T)
+}
+
+func slide(r *[256]int8, a *[32]byte) {
+ for i := range r {
+ r[i] = int8(1 & (a[i>>3] >> uint(i&7)))
+ }
+
+ for i := range r {
+ if r[i] != 0 {
+ for b := 1; b <= 6 && i+b < 256; b++ {
+ if r[i+b] != 0 {
+ if r[i]+(r[i+b]<<uint(b)) <= 15 {
+ r[i] += r[i+b] << uint(b)
+ r[i+b] = 0
+ } else if r[i]-(r[i+b]<<uint(b)) >= -15 {
+ r[i] -= r[i+b] << uint(b)
+ for k := i + b; k < 256; k++ {
+ if r[k] == 0 {
+ r[k] = 1
+ break
+ }
+ r[k] = 0
+ }
+ } else {
+ break
+ }
+ }
+ }
+ }
+ }
+}
+
+// GeDoubleScalarMultVartime sets r = a*A + b*B
+// where a = a[0]+256*a[1]+...+256^31 a[31].
+// and b = b[0]+256*b[1]+...+256^31 b[31].
+// B is the Ed25519 base point (x,4/5) with x positive.
+func GeDoubleScalarMultVartime(r *ProjectiveGroupElement, a *[32]byte, A *ExtendedGroupElement, b *[32]byte) {
+ var aSlide, bSlide [256]int8
+ var Ai [8]CachedGroupElement // A,3A,5A,7A,9A,11A,13A,15A
+ var t CompletedGroupElement
+ var u, A2 ExtendedGroupElement
+ var i int
+
+ slide(&aSlide, a)
+ slide(&bSlide, b)
+
+ A.ToCached(&Ai[0])
+ A.Double(&t)
+ t.ToExtended(&A2)
+
+ for i := 0; i < 7; i++ {
+ geAdd(&t, &A2, &Ai[i])
+ t.ToExtended(&u)
+ u.ToCached(&Ai[i+1])
+ }
+
+ r.Zero()
+
+ for i = 255; i >= 0; i-- {
+ if aSlide[i] != 0 || bSlide[i] != 0 {
+ break
+ }
+ }
+
+ for ; i >= 0; i-- {
+ r.Double(&t)
+
+ if aSlide[i] > 0 {
+ t.ToExtended(&u)
+ geAdd(&t, &u, &Ai[aSlide[i]/2])
+ } else if aSlide[i] < 0 {
+ t.ToExtended(&u)
+ geSub(&t, &u, &Ai[(-aSlide[i])/2])
+ }
+
+ if bSlide[i] > 0 {
+ t.ToExtended(&u)
+ geMixedAdd(&t, &u, &bi[bSlide[i]/2])
+ } else if bSlide[i] < 0 {
+ t.ToExtended(&u)
+ geMixedSub(&t, &u, &bi[(-bSlide[i])/2])
+ }
+
+ t.ToProjective(r)
+ }
+}
+
+// equal returns 1 if b == c and 0 otherwise, assuming that b and c are
+// non-negative.
+func equal(b, c int32) int32 {
+ x := uint32(b ^ c)
+ x--
+ return int32(x >> 31)
+}
+
+// negative returns 1 if b < 0 and 0 otherwise.
+func negative(b int32) int32 {
+ return (b >> 31) & 1
+}
+
+func PreComputedGroupElementCMove(t, u *PreComputedGroupElement, b int32) {
+ FeCMove(&t.yPlusX, &u.yPlusX, b)
+ FeCMove(&t.yMinusX, &u.yMinusX, b)
+ FeCMove(&t.xy2d, &u.xy2d, b)
+}
+
+func selectPoint(t *PreComputedGroupElement, pos int32, b int32) {
+ var minusT PreComputedGroupElement
+ bNegative := negative(b)
+ bAbs := b - (((-bNegative) & b) << 1)
+
+ t.Zero()
+ for i := int32(0); i < 8; i++ {
+ PreComputedGroupElementCMove(t, &base[pos][i], equal(bAbs, i+1))
+ }
+ FeCopy(&minusT.yPlusX, &t.yMinusX)
+ FeCopy(&minusT.yMinusX, &t.yPlusX)
+ FeNeg(&minusT.xy2d, &t.xy2d)
+ PreComputedGroupElementCMove(t, &minusT, bNegative)
+}
+
+// GeScalarMultBase computes h = a*B, where
+// a = a[0]+256*a[1]+...+256^31 a[31]
+// B is the Ed25519 base point (x,4/5) with x positive.
+//
+// Preconditions:
+// a[31] <= 127
+func GeScalarMultBase(h *ExtendedGroupElement, a *[32]byte) {
+ var e [64]int8
+
+ for i, v := range a {
+ e[2*i] = int8(v & 15)
+ e[2*i+1] = int8((v >> 4) & 15)
+ }
+
+ // each e[i] is between 0 and 15 and e[63] is between 0 and 7.
+
+ carry := int8(0)
+ for i := 0; i < 63; i++ {
+ e[i] += carry
+ carry = (e[i] + 8) >> 4
+ e[i] -= carry << 4
+ }
+ e[63] += carry
+ // each e[i] is between -8 and 8.
+
+ h.Zero()
+ var t PreComputedGroupElement
+ var r CompletedGroupElement
+ for i := int32(1); i < 64; i += 2 {
+ selectPoint(&t, i/2, int32(e[i]))
+ geMixedAdd(&r, h, &t)
+ r.ToExtended(h)
+ }
+
+ var s ProjectiveGroupElement
+
+ h.Double(&r)
+ r.ToProjective(&s)
+ s.Double(&r)
+ r.ToProjective(&s)
+ s.Double(&r)
+ r.ToProjective(&s)
+ s.Double(&r)
+ r.ToExtended(h)
+
+ for i := int32(0); i < 64; i += 2 {
+ selectPoint(&t, i/2, int32(e[i]))
+ geMixedAdd(&r, h, &t)
+ r.ToExtended(h)
+ }
+}
+
+// The scalars are GF(2^252 + 27742317777372353535851937790883648493).
+
+// Input:
+// a[0]+256*a[1]+...+256^31*a[31] = a
+// b[0]+256*b[1]+...+256^31*b[31] = b
+// c[0]+256*c[1]+...+256^31*c[31] = c
+//
+// Output:
+// s[0]+256*s[1]+...+256^31*s[31] = (ab+c) mod l
+// where l = 2^252 + 27742317777372353535851937790883648493.
+func ScMulAdd(s, a, b, c *[32]byte) {
+ a0 := 2097151 & load3(a[:])
+ a1 := 2097151 & (load4(a[2:]) >> 5)
+ a2 := 2097151 & (load3(a[5:]) >> 2)
+ a3 := 2097151 & (load4(a[7:]) >> 7)
+ a4 := 2097151 & (load4(a[10:]) >> 4)
+ a5 := 2097151 & (load3(a[13:]) >> 1)
+ a6 := 2097151 & (load4(a[15:]) >> 6)
+ a7 := 2097151 & (load3(a[18:]) >> 3)
+ a8 := 2097151 & load3(a[21:])
+ a9 := 2097151 & (load4(a[23:]) >> 5)
+ a10 := 2097151 & (load3(a[26:]) >> 2)
+ a11 := (load4(a[28:]) >> 7)
+ b0 := 2097151 & load3(b[:])
+ b1 := 2097151 & (load4(b[2:]) >> 5)
+ b2 := 2097151 & (load3(b[5:]) >> 2)
+ b3 := 2097151 & (load4(b[7:]) >> 7)
+ b4 := 2097151 & (load4(b[10:]) >> 4)
+ b5 := 2097151 & (load3(b[13:]) >> 1)
+ b6 := 2097151 & (load4(b[15:]) >> 6)
+ b7 := 2097151 & (load3(b[18:]) >> 3)
+ b8 := 2097151 & load3(b[21:])
+ b9 := 2097151 & (load4(b[23:]) >> 5)
+ b10 := 2097151 & (load3(b[26:]) >> 2)
+ b11 := (load4(b[28:]) >> 7)
+ c0 := 2097151 & load3(c[:])
+ c1 := 2097151 & (load4(c[2:]) >> 5)
+ c2 := 2097151 & (load3(c[5:]) >> 2)
+ c3 := 2097151 & (load4(c[7:]) >> 7)
+ c4 := 2097151 & (load4(c[10:]) >> 4)
+ c5 := 2097151 & (load3(c[13:]) >> 1)
+ c6 := 2097151 & (load4(c[15:]) >> 6)
+ c7 := 2097151 & (load3(c[18:]) >> 3)
+ c8 := 2097151 & load3(c[21:])
+ c9 := 2097151 & (load4(c[23:]) >> 5)
+ c10 := 2097151 & (load3(c[26:]) >> 2)
+ c11 := (load4(c[28:]) >> 7)
+ var carry [23]int64
+
+ s0 := c0 + a0*b0
+ s1 := c1 + a0*b1 + a1*b0
+ s2 := c2 + a0*b2 + a1*b1 + a2*b0
+ s3 := c3 + a0*b3 + a1*b2 + a2*b1 + a3*b0
+ s4 := c4 + a0*b4 + a1*b3 + a2*b2 + a3*b1 + a4*b0
+ s5 := c5 + a0*b5 + a1*b4 + a2*b3 + a3*b2 + a4*b1 + a5*b0
+ s6 := c6 + a0*b6 + a1*b5 + a2*b4 + a3*b3 + a4*b2 + a5*b1 + a6*b0
+ s7 := c7 + a0*b7 + a1*b6 + a2*b5 + a3*b4 + a4*b3 + a5*b2 + a6*b1 + a7*b0
+ s8 := c8 + a0*b8 + a1*b7 + a2*b6 + a3*b5 + a4*b4 + a5*b3 + a6*b2 + a7*b1 + a8*b0
+ s9 := c9 + a0*b9 + a1*b8 + a2*b7 + a3*b6 + a4*b5 + a5*b4 + a6*b3 + a7*b2 + a8*b1 + a9*b0
+ s10 := c10 + a0*b10 + a1*b9 + a2*b8 + a3*b7 + a4*b6 + a5*b5 + a6*b4 + a7*b3 + a8*b2 + a9*b1 + a10*b0
+ s11 := c11 + a0*b11 + a1*b10 + a2*b9 + a3*b8 + a4*b7 + a5*b6 + a6*b5 + a7*b4 + a8*b3 + a9*b2 + a10*b1 + a11*b0
+ s12 := a1*b11 + a2*b10 + a3*b9 + a4*b8 + a5*b7 + a6*b6 + a7*b5 + a8*b4 + a9*b3 + a10*b2 + a11*b1
+ s13 := a2*b11 + a3*b10 + a4*b9 + a5*b8 + a6*b7 + a7*b6 + a8*b5 + a9*b4 + a10*b3 + a11*b2
+ s14 := a3*b11 + a4*b10 + a5*b9 + a6*b8 + a7*b7 + a8*b6 + a9*b5 + a10*b4 + a11*b3
+ s15 := a4*b11 + a5*b10 + a6*b9 + a7*b8 + a8*b7 + a9*b6 + a10*b5 + a11*b4
+ s16 := a5*b11 + a6*b10 + a7*b9 + a8*b8 + a9*b7 + a10*b6 + a11*b5
+ s17 := a6*b11 + a7*b10 + a8*b9 + a9*b8 + a10*b7 + a11*b6
+ s18 := a7*b11 + a8*b10 + a9*b9 + a10*b8 + a11*b7
+ s19 := a8*b11 + a9*b10 + a10*b9 + a11*b8
+ s20 := a9*b11 + a10*b10 + a11*b9
+ s21 := a10*b11 + a11*b10
+ s22 := a11 * b11
+ s23 := int64(0)
+
+ carry[0] = (s0 + (1 << 20)) >> 21
+ s1 += carry[0]
+ s0 -= carry[0] << 21
+ carry[2] = (s2 + (1 << 20)) >> 21
+ s3 += carry[2]
+ s2 -= carry[2] << 21
+ carry[4] = (s4 + (1 << 20)) >> 21
+ s5 += carry[4]
+ s4 -= carry[4] << 21
+ carry[6] = (s6 + (1 << 20)) >> 21
+ s7 += carry[6]
+ s6 -= carry[6] << 21
+ carry[8] = (s8 + (1 << 20)) >> 21
+ s9 += carry[8]
+ s8 -= carry[8] << 21
+ carry[10] = (s10 + (1 << 20)) >> 21
+ s11 += carry[10]
+ s10 -= carry[10] << 21
+ carry[12] = (s12 + (1 << 20)) >> 21
+ s13 += carry[12]
+ s12 -= carry[12] << 21
+ carry[14] = (s14 + (1 << 20)) >> 21
+ s15 += carry[14]
+ s14 -= carry[14] << 21
+ carry[16] = (s16 + (1 << 20)) >> 21
+ s17 += carry[16]
+ s16 -= carry[16] << 21
+ carry[18] = (s18 + (1 << 20)) >> 21
+ s19 += carry[18]
+ s18 -= carry[18] << 21
+ carry[20] = (s20 + (1 << 20)) >> 21
+ s21 += carry[20]
+ s20 -= carry[20] << 21
+ carry[22] = (s22 + (1 << 20)) >> 21
+ s23 += carry[22]
+ s22 -= carry[22] << 21
+
+ carry[1] = (s1 + (1 << 20)) >> 21
+ s2 += carry[1]
+ s1 -= carry[1] << 21
+ carry[3] = (s3 + (1 << 20)) >> 21
+ s4 += carry[3]
+ s3 -= carry[3] << 21
+ carry[5] = (s5 + (1 << 20)) >> 21
+ s6 += carry[5]
+ s5 -= carry[5] << 21
+ carry[7] = (s7 + (1 << 20)) >> 21
+ s8 += carry[7]
+ s7 -= carry[7] << 21
+ carry[9] = (s9 + (1 << 20)) >> 21
+ s10 += carry[9]
+ s9 -= carry[9] << 21
+ carry[11] = (s11 + (1 << 20)) >> 21
+ s12 += carry[11]
+ s11 -= carry[11] << 21
+ carry[13] = (s13 + (1 << 20)) >> 21
+ s14 += carry[13]
+ s13 -= carry[13] << 21
+ carry[15] = (s15 + (1 << 20)) >> 21
+ s16 += carry[15]
+ s15 -= carry[15] << 21
+ carry[17] = (s17 + (1 << 20)) >> 21
+ s18 += carry[17]
+ s17 -= carry[17] << 21
+ carry[19] = (s19 + (1 << 20)) >> 21
+ s20 += carry[19]
+ s19 -= carry[19] << 21
+ carry[21] = (s21 + (1 << 20)) >> 21
+ s22 += carry[21]
+ s21 -= carry[21] << 21
+
+ s11 += s23 * 666643
+ s12 += s23 * 470296
+ s13 += s23 * 654183
+ s14 -= s23 * 997805
+ s15 += s23 * 136657
+ s16 -= s23 * 683901
+ s23 = 0
+
+ s10 += s22 * 666643
+ s11 += s22 * 470296
+ s12 += s22 * 654183
+ s13 -= s22 * 997805
+ s14 += s22 * 136657
+ s15 -= s22 * 683901
+ s22 = 0
+
+ s9 += s21 * 666643
+ s10 += s21 * 470296
+ s11 += s21 * 654183
+ s12 -= s21 * 997805
+ s13 += s21 * 136657
+ s14 -= s21 * 683901
+ s21 = 0
+
+ s8 += s20 * 666643
+ s9 += s20 * 470296
+ s10 += s20 * 654183
+ s11 -= s20 * 997805
+ s12 += s20 * 136657
+ s13 -= s20 * 683901
+ s20 = 0
+
+ s7 += s19 * 666643
+ s8 += s19 * 470296
+ s9 += s19 * 654183
+ s10 -= s19 * 997805
+ s11 += s19 * 136657
+ s12 -= s19 * 683901
+ s19 = 0
+
+ s6 += s18 * 666643
+ s7 += s18 * 470296
+ s8 += s18 * 654183
+ s9 -= s18 * 997805
+ s10 += s18 * 136657
+ s11 -= s18 * 683901
+ s18 = 0
+
+ carry[6] = (s6 + (1 << 20)) >> 21
+ s7 += carry[6]
+ s6 -= carry[6] << 21
+ carry[8] = (s8 + (1 << 20)) >> 21
+ s9 += carry[8]
+ s8 -= carry[8] << 21
+ carry[10] = (s10 + (1 << 20)) >> 21
+ s11 += carry[10]
+ s10 -= carry[10] << 21
+ carry[12] = (s12 + (1 << 20)) >> 21
+ s13 += carry[12]
+ s12 -= carry[12] << 21
+ carry[14] = (s14 + (1 << 20)) >> 21
+ s15 += carry[14]
+ s14 -= carry[14] << 21
+ carry[16] = (s16 + (1 << 20)) >> 21
+ s17 += carry[16]
+ s16 -= carry[16] << 21
+
+ carry[7] = (s7 + (1 << 20)) >> 21
+ s8 += carry[7]
+ s7 -= carry[7] << 21
+ carry[9] = (s9 + (1 << 20)) >> 21
+ s10 += carry[9]
+ s9 -= carry[9] << 21
+ carry[11] = (s11 + (1 << 20)) >> 21
+ s12 += carry[11]
+ s11 -= carry[11] << 21
+ carry[13] = (s13 + (1 << 20)) >> 21
+ s14 += carry[13]
+ s13 -= carry[13] << 21
+ carry[15] = (s15 + (1 << 20)) >> 21
+ s16 += carry[15]
+ s15 -= carry[15] << 21
+
+ s5 += s17 * 666643
+ s6 += s17 * 470296
+ s7 += s17 * 654183
+ s8 -= s17 * 997805
+ s9 += s17 * 136657
+ s10 -= s17 * 683901
+ s17 = 0
+
+ s4 += s16 * 666643
+ s5 += s16 * 470296
+ s6 += s16 * 654183
+ s7 -= s16 * 997805
+ s8 += s16 * 136657
+ s9 -= s16 * 683901
+ s16 = 0
+
+ s3 += s15 * 666643
+ s4 += s15 * 470296
+ s5 += s15 * 654183
+ s6 -= s15 * 997805
+ s7 += s15 * 136657
+ s8 -= s15 * 683901
+ s15 = 0
+
+ s2 += s14 * 666643
+ s3 += s14 * 470296
+ s4 += s14 * 654183
+ s5 -= s14 * 997805
+ s6 += s14 * 136657
+ s7 -= s14 * 683901
+ s14 = 0
+
+ s1 += s13 * 666643
+ s2 += s13 * 470296
+ s3 += s13 * 654183
+ s4 -= s13 * 997805
+ s5 += s13 * 136657
+ s6 -= s13 * 683901
+ s13 = 0
+
+ s0 += s12 * 666643
+ s1 += s12 * 470296
+ s2 += s12 * 654183
+ s3 -= s12 * 997805
+ s4 += s12 * 136657
+ s5 -= s12 * 683901
+ s12 = 0
+
+ carry[0] = (s0 + (1 << 20)) >> 21
+ s1 += carry[0]
+ s0 -= carry[0] << 21
+ carry[2] = (s2 + (1 << 20)) >> 21
+ s3 += carry[2]
+ s2 -= carry[2] << 21
+ carry[4] = (s4 + (1 << 20)) >> 21
+ s5 += carry[4]
+ s4 -= carry[4] << 21
+ carry[6] = (s6 + (1 << 20)) >> 21
+ s7 += carry[6]
+ s6 -= carry[6] << 21
+ carry[8] = (s8 + (1 << 20)) >> 21
+ s9 += carry[8]
+ s8 -= carry[8] << 21
+ carry[10] = (s10 + (1 << 20)) >> 21
+ s11 += carry[10]
+ s10 -= carry[10] << 21
+
+ carry[1] = (s1 + (1 << 20)) >> 21
+ s2 += carry[1]
+ s1 -= carry[1] << 21
+ carry[3] = (s3 + (1 << 20)) >> 21
+ s4 += carry[3]
+ s3 -= carry[3] << 21
+ carry[5] = (s5 + (1 << 20)) >> 21
+ s6 += carry[5]
+ s5 -= carry[5] << 21
+ carry[7] = (s7 + (1 << 20)) >> 21
+ s8 += carry[7]
+ s7 -= carry[7] << 21
+ carry[9] = (s9 + (1 << 20)) >> 21
+ s10 += carry[9]
+ s9 -= carry[9] << 21
+ carry[11] = (s11 + (1 << 20)) >> 21
+ s12 += carry[11]
+ s11 -= carry[11] << 21
+
+ s0 += s12 * 666643
+ s1 += s12 * 470296
+ s2 += s12 * 654183
+ s3 -= s12 * 997805
+ s4 += s12 * 136657
+ s5 -= s12 * 683901
+ s12 = 0
+
+ carry[0] = s0 >> 21
+ s1 += carry[0]
+ s0 -= carry[0] << 21
+ carry[1] = s1 >> 21
+ s2 += carry[1]
+ s1 -= carry[1] << 21
+ carry[2] = s2 >> 21
+ s3 += carry[2]
+ s2 -= carry[2] << 21
+ carry[3] = s3 >> 21
+ s4 += carry[3]
+ s3 -= carry[3] << 21
+ carry[4] = s4 >> 21
+ s5 += carry[4]
+ s4 -= carry[4] << 21
+ carry[5] = s5 >> 21
+ s6 += carry[5]
+ s5 -= carry[5] << 21
+ carry[6] = s6 >> 21
+ s7 += carry[6]
+ s6 -= carry[6] << 21
+ carry[7] = s7 >> 21
+ s8 += carry[7]
+ s7 -= carry[7] << 21
+ carry[8] = s8 >> 21
+ s9 += carry[8]
+ s8 -= carry[8] << 21
+ carry[9] = s9 >> 21
+ s10 += carry[9]
+ s9 -= carry[9] << 21
+ carry[10] = s10 >> 21
+ s11 += carry[10]
+ s10 -= carry[10] << 21
+ carry[11] = s11 >> 21
+ s12 += carry[11]
+ s11 -= carry[11] << 21
+
+ s0 += s12 * 666643
+ s1 += s12 * 470296
+ s2 += s12 * 654183
+ s3 -= s12 * 997805
+ s4 += s12 * 136657
+ s5 -= s12 * 683901
+ s12 = 0
+
+ carry[0] = s0 >> 21
+ s1 += carry[0]
+ s0 -= carry[0] << 21
+ carry[1] = s1 >> 21
+ s2 += carry[1]
+ s1 -= carry[1] << 21
+ carry[2] = s2 >> 21
+ s3 += carry[2]
+ s2 -= carry[2] << 21
+ carry[3] = s3 >> 21
+ s4 += carry[3]
+ s3 -= carry[3] << 21
+ carry[4] = s4 >> 21
+ s5 += carry[4]
+ s4 -= carry[4] << 21
+ carry[5] = s5 >> 21
+ s6 += carry[5]
+ s5 -= carry[5] << 21
+ carry[6] = s6 >> 21
+ s7 += carry[6]
+ s6 -= carry[6] << 21
+ carry[7] = s7 >> 21
+ s8 += carry[7]
+ s7 -= carry[7] << 21
+ carry[8] = s8 >> 21
+ s9 += carry[8]
+ s8 -= carry[8] << 21
+ carry[9] = s9 >> 21
+ s10 += carry[9]
+ s9 -= carry[9] << 21
+ carry[10] = s10 >> 21
+ s11 += carry[10]
+ s10 -= carry[10] << 21
+
+ s[0] = byte(s0 >> 0)
+ s[1] = byte(s0 >> 8)
+ s[2] = byte((s0 >> 16) | (s1 << 5))
+ s[3] = byte(s1 >> 3)
+ s[4] = byte(s1 >> 11)
+ s[5] = byte((s1 >> 19) | (s2 << 2))
+ s[6] = byte(s2 >> 6)
+ s[7] = byte((s2 >> 14) | (s3 << 7))
+ s[8] = byte(s3 >> 1)
+ s[9] = byte(s3 >> 9)
+ s[10] = byte((s3 >> 17) | (s4 << 4))
+ s[11] = byte(s4 >> 4)
+ s[12] = byte(s4 >> 12)
+ s[13] = byte((s4 >> 20) | (s5 << 1))
+ s[14] = byte(s5 >> 7)
+ s[15] = byte((s5 >> 15) | (s6 << 6))
+ s[16] = byte(s6 >> 2)
+ s[17] = byte(s6 >> 10)
+ s[18] = byte((s6 >> 18) | (s7 << 3))
+ s[19] = byte(s7 >> 5)
+ s[20] = byte(s7 >> 13)
+ s[21] = byte(s8 >> 0)
+ s[22] = byte(s8 >> 8)
+ s[23] = byte((s8 >> 16) | (s9 << 5))
+ s[24] = byte(s9 >> 3)
+ s[25] = byte(s9 >> 11)
+ s[26] = byte((s9 >> 19) | (s10 << 2))
+ s[27] = byte(s10 >> 6)
+ s[28] = byte((s10 >> 14) | (s11 << 7))
+ s[29] = byte(s11 >> 1)
+ s[30] = byte(s11 >> 9)
+ s[31] = byte(s11 >> 17)
+}
+
+// Input:
+// s[0]+256*s[1]+...+256^63*s[63] = s
+//
+// Output:
+// s[0]+256*s[1]+...+256^31*s[31] = s mod l
+// where l = 2^252 + 27742317777372353535851937790883648493.
+func ScReduce(out *[32]byte, s *[64]byte) {
+ s0 := 2097151 & load3(s[:])
+ s1 := 2097151 & (load4(s[2:]) >> 5)
+ s2 := 2097151 & (load3(s[5:]) >> 2)
+ s3 := 2097151 & (load4(s[7:]) >> 7)
+ s4 := 2097151 & (load4(s[10:]) >> 4)
+ s5 := 2097151 & (load3(s[13:]) >> 1)
+ s6 := 2097151 & (load4(s[15:]) >> 6)
+ s7 := 2097151 & (load3(s[18:]) >> 3)
+ s8 := 2097151 & load3(s[21:])
+ s9 := 2097151 & (load4(s[23:]) >> 5)
+ s10 := 2097151 & (load3(s[26:]) >> 2)
+ s11 := 2097151 & (load4(s[28:]) >> 7)
+ s12 := 2097151 & (load4(s[31:]) >> 4)
+ s13 := 2097151 & (load3(s[34:]) >> 1)
+ s14 := 2097151 & (load4(s[36:]) >> 6)
+ s15 := 2097151 & (load3(s[39:]) >> 3)
+ s16 := 2097151 & load3(s[42:])
+ s17 := 2097151 & (load4(s[44:]) >> 5)
+ s18 := 2097151 & (load3(s[47:]) >> 2)
+ s19 := 2097151 & (load4(s[49:]) >> 7)
+ s20 := 2097151 & (load4(s[52:]) >> 4)
+ s21 := 2097151 & (load3(s[55:]) >> 1)
+ s22 := 2097151 & (load4(s[57:]) >> 6)
+ s23 := (load4(s[60:]) >> 3)
+
+ s11 += s23 * 666643
+ s12 += s23 * 470296
+ s13 += s23 * 654183
+ s14 -= s23 * 997805
+ s15 += s23 * 136657
+ s16 -= s23 * 683901
+ s23 = 0
+
+ s10 += s22 * 666643
+ s11 += s22 * 470296
+ s12 += s22 * 654183
+ s13 -= s22 * 997805
+ s14 += s22 * 136657
+ s15 -= s22 * 683901
+ s22 = 0
+
+ s9 += s21 * 666643
+ s10 += s21 * 470296
+ s11 += s21 * 654183
+ s12 -= s21 * 997805
+ s13 += s21 * 136657
+ s14 -= s21 * 683901
+ s21 = 0
+
+ s8 += s20 * 666643
+ s9 += s20 * 470296
+ s10 += s20 * 654183
+ s11 -= s20 * 997805
+ s12 += s20 * 136657
+ s13 -= s20 * 683901
+ s20 = 0
+
+ s7 += s19 * 666643
+ s8 += s19 * 470296
+ s9 += s19 * 654183
+ s10 -= s19 * 997805
+ s11 += s19 * 136657
+ s12 -= s19 * 683901
+ s19 = 0
+
+ s6 += s18 * 666643
+ s7 += s18 * 470296
+ s8 += s18 * 654183
+ s9 -= s18 * 997805
+ s10 += s18 * 136657
+ s11 -= s18 * 683901
+ s18 = 0
+
+ var carry [17]int64
+
+ carry[6] = (s6 + (1 << 20)) >> 21
+ s7 += carry[6]
+ s6 -= carry[6] << 21
+ carry[8] = (s8 + (1 << 20)) >> 21
+ s9 += carry[8]
+ s8 -= carry[8] << 21
+ carry[10] = (s10 + (1 << 20)) >> 21
+ s11 += carry[10]
+ s10 -= carry[10] << 21
+ carry[12] = (s12 + (1 << 20)) >> 21
+ s13 += carry[12]
+ s12 -= carry[12] << 21
+ carry[14] = (s14 + (1 << 20)) >> 21
+ s15 += carry[14]
+ s14 -= carry[14] << 21
+ carry[16] = (s16 + (1 << 20)) >> 21
+ s17 += carry[16]
+ s16 -= carry[16] << 21
+
+ carry[7] = (s7 + (1 << 20)) >> 21
+ s8 += carry[7]
+ s7 -= carry[7] << 21
+ carry[9] = (s9 + (1 << 20)) >> 21
+ s10 += carry[9]
+ s9 -= carry[9] << 21
+ carry[11] = (s11 + (1 << 20)) >> 21
+ s12 += carry[11]
+ s11 -= carry[11] << 21
+ carry[13] = (s13 + (1 << 20)) >> 21
+ s14 += carry[13]
+ s13 -= carry[13] << 21
+ carry[15] = (s15 + (1 << 20)) >> 21
+ s16 += carry[15]
+ s15 -= carry[15] << 21
+
+ s5 += s17 * 666643
+ s6 += s17 * 470296
+ s7 += s17 * 654183
+ s8 -= s17 * 997805
+ s9 += s17 * 136657
+ s10 -= s17 * 683901
+ s17 = 0
+
+ s4 += s16 * 666643
+ s5 += s16 * 470296
+ s6 += s16 * 654183
+ s7 -= s16 * 997805
+ s8 += s16 * 136657
+ s9 -= s16 * 683901
+ s16 = 0
+
+ s3 += s15 * 666643
+ s4 += s15 * 470296
+ s5 += s15 * 654183
+ s6 -= s15 * 997805
+ s7 += s15 * 136657
+ s8 -= s15 * 683901
+ s15 = 0
+
+ s2 += s14 * 666643
+ s3 += s14 * 470296
+ s4 += s14 * 654183
+ s5 -= s14 * 997805
+ s6 += s14 * 136657
+ s7 -= s14 * 683901
+ s14 = 0
+
+ s1 += s13 * 666643
+ s2 += s13 * 470296
+ s3 += s13 * 654183
+ s4 -= s13 * 997805
+ s5 += s13 * 136657
+ s6 -= s13 * 683901
+ s13 = 0
+
+ s0 += s12 * 666643
+ s1 += s12 * 470296
+ s2 += s12 * 654183
+ s3 -= s12 * 997805
+ s4 += s12 * 136657
+ s5 -= s12 * 683901
+ s12 = 0
+
+ carry[0] = (s0 + (1 << 20)) >> 21
+ s1 += carry[0]
+ s0 -= carry[0] << 21
+ carry[2] = (s2 + (1 << 20)) >> 21
+ s3 += carry[2]
+ s2 -= carry[2] << 21
+ carry[4] = (s4 + (1 << 20)) >> 21
+ s5 += carry[4]
+ s4 -= carry[4] << 21
+ carry[6] = (s6 + (1 << 20)) >> 21
+ s7 += carry[6]
+ s6 -= carry[6] << 21
+ carry[8] = (s8 + (1 << 20)) >> 21
+ s9 += carry[8]
+ s8 -= carry[8] << 21
+ carry[10] = (s10 + (1 << 20)) >> 21
+ s11 += carry[10]
+ s10 -= carry[10] << 21
+
+ carry[1] = (s1 + (1 << 20)) >> 21
+ s2 += carry[1]
+ s1 -= carry[1] << 21
+ carry[3] = (s3 + (1 << 20)) >> 21
+ s4 += carry[3]
+ s3 -= carry[3] << 21
+ carry[5] = (s5 + (1 << 20)) >> 21
+ s6 += carry[5]
+ s5 -= carry[5] << 21
+ carry[7] = (s7 + (1 << 20)) >> 21
+ s8 += carry[7]
+ s7 -= carry[7] << 21
+ carry[9] = (s9 + (1 << 20)) >> 21
+ s10 += carry[9]
+ s9 -= carry[9] << 21
+ carry[11] = (s11 + (1 << 20)) >> 21
+ s12 += carry[11]
+ s11 -= carry[11] << 21
+
+ s0 += s12 * 666643
+ s1 += s12 * 470296
+ s2 += s12 * 654183
+ s3 -= s12 * 997805
+ s4 += s12 * 136657
+ s5 -= s12 * 683901
+ s12 = 0
+
+ carry[0] = s0 >> 21
+ s1 += carry[0]
+ s0 -= carry[0] << 21
+ carry[1] = s1 >> 21
+ s2 += carry[1]
+ s1 -= carry[1] << 21
+ carry[2] = s2 >> 21
+ s3 += carry[2]
+ s2 -= carry[2] << 21
+ carry[3] = s3 >> 21
+ s4 += carry[3]
+ s3 -= carry[3] << 21
+ carry[4] = s4 >> 21
+ s5 += carry[4]
+ s4 -= carry[4] << 21
+ carry[5] = s5 >> 21
+ s6 += carry[5]
+ s5 -= carry[5] << 21
+ carry[6] = s6 >> 21
+ s7 += carry[6]
+ s6 -= carry[6] << 21
+ carry[7] = s7 >> 21
+ s8 += carry[7]
+ s7 -= carry[7] << 21
+ carry[8] = s8 >> 21
+ s9 += carry[8]
+ s8 -= carry[8] << 21
+ carry[9] = s9 >> 21
+ s10 += carry[9]
+ s9 -= carry[9] << 21
+ carry[10] = s10 >> 21
+ s11 += carry[10]
+ s10 -= carry[10] << 21
+ carry[11] = s11 >> 21
+ s12 += carry[11]
+ s11 -= carry[11] << 21
+
+ s0 += s12 * 666643
+ s1 += s12 * 470296
+ s2 += s12 * 654183
+ s3 -= s12 * 997805
+ s4 += s12 * 136657
+ s5 -= s12 * 683901
+ s12 = 0
+
+ carry[0] = s0 >> 21
+ s1 += carry[0]
+ s0 -= carry[0] << 21
+ carry[1] = s1 >> 21
+ s2 += carry[1]
+ s1 -= carry[1] << 21
+ carry[2] = s2 >> 21
+ s3 += carry[2]
+ s2 -= carry[2] << 21
+ carry[3] = s3 >> 21
+ s4 += carry[3]
+ s3 -= carry[3] << 21
+ carry[4] = s4 >> 21
+ s5 += carry[4]
+ s4 -= carry[4] << 21
+ carry[5] = s5 >> 21
+ s6 += carry[5]
+ s5 -= carry[5] << 21
+ carry[6] = s6 >> 21
+ s7 += carry[6]
+ s6 -= carry[6] << 21
+ carry[7] = s7 >> 21
+ s8 += carry[7]
+ s7 -= carry[7] << 21
+ carry[8] = s8 >> 21
+ s9 += carry[8]
+ s8 -= carry[8] << 21
+ carry[9] = s9 >> 21
+ s10 += carry[9]
+ s9 -= carry[9] << 21
+ carry[10] = s10 >> 21
+ s11 += carry[10]
+ s10 -= carry[10] << 21
+
+ out[0] = byte(s0 >> 0)
+ out[1] = byte(s0 >> 8)
+ out[2] = byte((s0 >> 16) | (s1 << 5))
+ out[3] = byte(s1 >> 3)
+ out[4] = byte(s1 >> 11)
+ out[5] = byte((s1 >> 19) | (s2 << 2))
+ out[6] = byte(s2 >> 6)
+ out[7] = byte((s2 >> 14) | (s3 << 7))
+ out[8] = byte(s3 >> 1)
+ out[9] = byte(s3 >> 9)
+ out[10] = byte((s3 >> 17) | (s4 << 4))
+ out[11] = byte(s4 >> 4)
+ out[12] = byte(s4 >> 12)
+ out[13] = byte((s4 >> 20) | (s5 << 1))
+ out[14] = byte(s5 >> 7)
+ out[15] = byte((s5 >> 15) | (s6 << 6))
+ out[16] = byte(s6 >> 2)
+ out[17] = byte(s6 >> 10)
+ out[18] = byte((s6 >> 18) | (s7 << 3))
+ out[19] = byte(s7 >> 5)
+ out[20] = byte(s7 >> 13)
+ out[21] = byte(s8 >> 0)
+ out[22] = byte(s8 >> 8)
+ out[23] = byte((s8 >> 16) | (s9 << 5))
+ out[24] = byte(s9 >> 3)
+ out[25] = byte(s9 >> 11)
+ out[26] = byte((s9 >> 19) | (s10 << 2))
+ out[27] = byte(s10 >> 6)
+ out[28] = byte((s10 >> 14) | (s11 << 7))
+ out[29] = byte(s11 >> 1)
+ out[30] = byte(s11 >> 9)
+ out[31] = byte(s11 >> 17)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ed25519/testdata/sign.input.gz b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ed25519/testdata/sign.input.gz
new file mode 100644
index 000000000..41030690c
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ed25519/testdata/sign.input.gz
Binary files differ
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/hkdf/example_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/hkdf/example_test.go
new file mode 100644
index 000000000..df8439512
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/hkdf/example_test.go
@@ -0,0 +1,61 @@
+// Copyright 2014 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 hkdf_test
+
+import (
+ "bytes"
+ "crypto/rand"
+ "crypto/sha256"
+ "fmt"
+ "golang.org/x/crypto/hkdf"
+ "io"
+)
+
+// Usage example that expands one master key into three other cryptographically
+// secure keys.
+func Example_usage() {
+ // Underlying hash function to use
+ hash := sha256.New
+
+ // Cryptographically secure master key.
+ master := []byte{0x00, 0x01, 0x02, 0x03} // i.e. NOT this.
+
+ // Non secret salt, optional (can be nil)
+ // Recommended: hash-length sized random
+ salt := make([]byte, hash().Size())
+ n, err := io.ReadFull(rand.Reader, salt)
+ if n != len(salt) || err != nil {
+ fmt.Println("error:", err)
+ return
+ }
+
+ // Non secret context specific info, optional (can be nil).
+ // Note, independent from the master key.
+ info := []byte{0x03, 0x14, 0x15, 0x92, 0x65}
+
+ // Create the key derivation function
+ hkdf := hkdf.New(hash, master, salt, info)
+
+ // Generate the required keys
+ keys := make([][]byte, 3)
+ for i := 0; i < len(keys); i++ {
+ keys[i] = make([]byte, 24)
+ n, err := io.ReadFull(hkdf, keys[i])
+ if n != len(keys[i]) || err != nil {
+ fmt.Println("error:", err)
+ return
+ }
+ }
+
+ // Keys should contain 192 bit random keys
+ for i := 1; i <= len(keys); i++ {
+ fmt.Printf("Key #%d: %v\n", i, !bytes.Equal(keys[i-1], make([]byte, 24)))
+ }
+
+ // Output:
+ // Key #1: true
+ // Key #2: true
+ // Key #3: true
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/hkdf/hkdf.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/hkdf/hkdf.go
new file mode 100644
index 000000000..5bc246355
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/hkdf/hkdf.go
@@ -0,0 +1,75 @@
+// Copyright 2014 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 hkdf implements the HMAC-based Extract-and-Expand Key Derivation
+// Function (HKDF) as defined in RFC 5869.
+//
+// HKDF is a cryptographic key derivation function (KDF) with the goal of
+// expanding limited input keying material into one or more cryptographically
+// strong secret keys.
+//
+// RFC 5869: https://tools.ietf.org/html/rfc5869
+package hkdf // import "golang.org/x/crypto/hkdf"
+
+import (
+ "crypto/hmac"
+ "errors"
+ "hash"
+ "io"
+)
+
+type hkdf struct {
+ expander hash.Hash
+ size int
+
+ info []byte
+ counter byte
+
+ prev []byte
+ cache []byte
+}
+
+func (f *hkdf) Read(p []byte) (int, error) {
+ // Check whether enough data can be generated
+ need := len(p)
+ remains := len(f.cache) + int(255-f.counter+1)*f.size
+ if remains < need {
+ return 0, errors.New("hkdf: entropy limit reached")
+ }
+ // Read from the cache, if enough data is present
+ n := copy(p, f.cache)
+ p = p[n:]
+
+ // Fill the buffer
+ for len(p) > 0 {
+ f.expander.Reset()
+ f.expander.Write(f.prev)
+ f.expander.Write(f.info)
+ f.expander.Write([]byte{f.counter})
+ f.prev = f.expander.Sum(f.prev[:0])
+ f.counter++
+
+ // Copy the new batch into p
+ f.cache = f.prev
+ n = copy(p, f.cache)
+ p = p[n:]
+ }
+ // Save leftovers for next run
+ f.cache = f.cache[n:]
+
+ return need, nil
+}
+
+// New returns a new HKDF using the given hash, the secret keying material to expand
+// and optional salt and info fields.
+func New(hash func() hash.Hash, secret, salt, info []byte) io.Reader {
+ if salt == nil {
+ salt = make([]byte, hash().Size())
+ }
+ extractor := hmac.New(hash, salt)
+ extractor.Write(secret)
+ prk := extractor.Sum(nil)
+
+ return &hkdf{hmac.New(hash, prk), extractor.Size(), info, 1, nil, nil}
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/hkdf/hkdf_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/hkdf/hkdf_test.go
new file mode 100644
index 000000000..cee659bcd
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/hkdf/hkdf_test.go
@@ -0,0 +1,370 @@
+// Copyright 2014 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 hkdf
+
+import (
+ "bytes"
+ "crypto/md5"
+ "crypto/sha1"
+ "crypto/sha256"
+ "crypto/sha512"
+ "hash"
+ "io"
+ "testing"
+)
+
+type hkdfTest struct {
+ hash func() hash.Hash
+ master []byte
+ salt []byte
+ info []byte
+ out []byte
+}
+
+var hkdfTests = []hkdfTest{
+ // Tests from RFC 5869
+ {
+ sha256.New,
+ []byte{
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ },
+ []byte{
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c,
+ },
+ []byte{
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9,
+ },
+ []byte{
+ 0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a,
+ 0x90, 0x43, 0x4f, 0x64, 0xd0, 0x36, 0x2f, 0x2a,
+ 0x2d, 0x2d, 0x0a, 0x90, 0xcf, 0x1a, 0x5a, 0x4c,
+ 0x5d, 0xb0, 0x2d, 0x56, 0xec, 0xc4, 0xc5, 0xbf,
+ 0x34, 0x00, 0x72, 0x08, 0xd5, 0xb8, 0x87, 0x18,
+ 0x58, 0x65,
+ },
+ },
+ {
+ sha256.New,
+ []byte{
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ },
+ []byte{
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+ },
+ []byte{
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
+ },
+ []byte{
+ 0xb1, 0x1e, 0x39, 0x8d, 0xc8, 0x03, 0x27, 0xa1,
+ 0xc8, 0xe7, 0xf7, 0x8c, 0x59, 0x6a, 0x49, 0x34,
+ 0x4f, 0x01, 0x2e, 0xda, 0x2d, 0x4e, 0xfa, 0xd8,
+ 0xa0, 0x50, 0xcc, 0x4c, 0x19, 0xaf, 0xa9, 0x7c,
+ 0x59, 0x04, 0x5a, 0x99, 0xca, 0xc7, 0x82, 0x72,
+ 0x71, 0xcb, 0x41, 0xc6, 0x5e, 0x59, 0x0e, 0x09,
+ 0xda, 0x32, 0x75, 0x60, 0x0c, 0x2f, 0x09, 0xb8,
+ 0x36, 0x77, 0x93, 0xa9, 0xac, 0xa3, 0xdb, 0x71,
+ 0xcc, 0x30, 0xc5, 0x81, 0x79, 0xec, 0x3e, 0x87,
+ 0xc1, 0x4c, 0x01, 0xd5, 0xc1, 0xf3, 0x43, 0x4f,
+ 0x1d, 0x87,
+ },
+ },
+ {
+ sha256.New,
+ []byte{
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ },
+ []byte{},
+ []byte{},
+ []byte{
+ 0x8d, 0xa4, 0xe7, 0x75, 0xa5, 0x63, 0xc1, 0x8f,
+ 0x71, 0x5f, 0x80, 0x2a, 0x06, 0x3c, 0x5a, 0x31,
+ 0xb8, 0xa1, 0x1f, 0x5c, 0x5e, 0xe1, 0x87, 0x9e,
+ 0xc3, 0x45, 0x4e, 0x5f, 0x3c, 0x73, 0x8d, 0x2d,
+ 0x9d, 0x20, 0x13, 0x95, 0xfa, 0xa4, 0xb6, 0x1a,
+ 0x96, 0xc8,
+ },
+ },
+ {
+ sha1.New,
+ []byte{
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b,
+ },
+ []byte{
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c,
+ },
+ []byte{
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9,
+ },
+ []byte{
+ 0x08, 0x5a, 0x01, 0xea, 0x1b, 0x10, 0xf3, 0x69,
+ 0x33, 0x06, 0x8b, 0x56, 0xef, 0xa5, 0xad, 0x81,
+ 0xa4, 0xf1, 0x4b, 0x82, 0x2f, 0x5b, 0x09, 0x15,
+ 0x68, 0xa9, 0xcd, 0xd4, 0xf1, 0x55, 0xfd, 0xa2,
+ 0xc2, 0x2e, 0x42, 0x24, 0x78, 0xd3, 0x05, 0xf3,
+ 0xf8, 0x96,
+ },
+ },
+ {
+ sha1.New,
+ []byte{
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ },
+ []byte{
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+ },
+ []byte{
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
+ },
+ []byte{
+ 0x0b, 0xd7, 0x70, 0xa7, 0x4d, 0x11, 0x60, 0xf7,
+ 0xc9, 0xf1, 0x2c, 0xd5, 0x91, 0x2a, 0x06, 0xeb,
+ 0xff, 0x6a, 0xdc, 0xae, 0x89, 0x9d, 0x92, 0x19,
+ 0x1f, 0xe4, 0x30, 0x56, 0x73, 0xba, 0x2f, 0xfe,
+ 0x8f, 0xa3, 0xf1, 0xa4, 0xe5, 0xad, 0x79, 0xf3,
+ 0xf3, 0x34, 0xb3, 0xb2, 0x02, 0xb2, 0x17, 0x3c,
+ 0x48, 0x6e, 0xa3, 0x7c, 0xe3, 0xd3, 0x97, 0xed,
+ 0x03, 0x4c, 0x7f, 0x9d, 0xfe, 0xb1, 0x5c, 0x5e,
+ 0x92, 0x73, 0x36, 0xd0, 0x44, 0x1f, 0x4c, 0x43,
+ 0x00, 0xe2, 0xcf, 0xf0, 0xd0, 0x90, 0x0b, 0x52,
+ 0xd3, 0xb4,
+ },
+ },
+ {
+ sha1.New,
+ []byte{
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ },
+ []byte{},
+ []byte{},
+ []byte{
+ 0x0a, 0xc1, 0xaf, 0x70, 0x02, 0xb3, 0xd7, 0x61,
+ 0xd1, 0xe5, 0x52, 0x98, 0xda, 0x9d, 0x05, 0x06,
+ 0xb9, 0xae, 0x52, 0x05, 0x72, 0x20, 0xa3, 0x06,
+ 0xe0, 0x7b, 0x6b, 0x87, 0xe8, 0xdf, 0x21, 0xd0,
+ 0xea, 0x00, 0x03, 0x3d, 0xe0, 0x39, 0x84, 0xd3,
+ 0x49, 0x18,
+ },
+ },
+ {
+ sha1.New,
+ []byte{
+ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+ },
+ nil,
+ []byte{},
+ []byte{
+ 0x2c, 0x91, 0x11, 0x72, 0x04, 0xd7, 0x45, 0xf3,
+ 0x50, 0x0d, 0x63, 0x6a, 0x62, 0xf6, 0x4f, 0x0a,
+ 0xb3, 0xba, 0xe5, 0x48, 0xaa, 0x53, 0xd4, 0x23,
+ 0xb0, 0xd1, 0xf2, 0x7e, 0xbb, 0xa6, 0xf5, 0xe5,
+ 0x67, 0x3a, 0x08, 0x1d, 0x70, 0xcc, 0xe7, 0xac,
+ 0xfc, 0x48,
+ },
+ },
+}
+
+func TestHKDF(t *testing.T) {
+ for i, tt := range hkdfTests {
+ hkdf := New(tt.hash, tt.master, tt.salt, tt.info)
+ out := make([]byte, len(tt.out))
+
+ n, err := io.ReadFull(hkdf, out)
+ if n != len(tt.out) || err != nil {
+ t.Errorf("test %d: not enough output bytes: %d.", i, n)
+ }
+
+ if !bytes.Equal(out, tt.out) {
+ t.Errorf("test %d: incorrect output: have %v, need %v.", i, out, tt.out)
+ }
+ }
+}
+
+func TestHKDFMultiRead(t *testing.T) {
+ for i, tt := range hkdfTests {
+ hkdf := New(tt.hash, tt.master, tt.salt, tt.info)
+ out := make([]byte, len(tt.out))
+
+ for b := 0; b < len(tt.out); b++ {
+ n, err := io.ReadFull(hkdf, out[b:b+1])
+ if n != 1 || err != nil {
+ t.Errorf("test %d.%d: not enough output bytes: have %d, need %d .", i, b, n, len(tt.out))
+ }
+ }
+
+ if !bytes.Equal(out, tt.out) {
+ t.Errorf("test %d: incorrect output: have %v, need %v.", i, out, tt.out)
+ }
+ }
+}
+
+func TestHKDFLimit(t *testing.T) {
+ hash := sha1.New
+ master := []byte{0x00, 0x01, 0x02, 0x03}
+ info := []byte{}
+
+ hkdf := New(hash, master, nil, info)
+ limit := hash().Size() * 255
+ out := make([]byte, limit)
+
+ // The maximum output bytes should be extractable
+ n, err := io.ReadFull(hkdf, out)
+ if n != limit || err != nil {
+ t.Errorf("not enough output bytes: %d, %v.", n, err)
+ }
+
+ // Reading one more should fail
+ n, err = io.ReadFull(hkdf, make([]byte, 1))
+ if n > 0 || err == nil {
+ t.Errorf("key expansion overflowed: n = %d, err = %v", n, err)
+ }
+}
+
+func Benchmark16ByteMD5Single(b *testing.B) {
+ benchmarkHKDFSingle(md5.New, 16, b)
+}
+
+func Benchmark20ByteSHA1Single(b *testing.B) {
+ benchmarkHKDFSingle(sha1.New, 20, b)
+}
+
+func Benchmark32ByteSHA256Single(b *testing.B) {
+ benchmarkHKDFSingle(sha256.New, 32, b)
+}
+
+func Benchmark64ByteSHA512Single(b *testing.B) {
+ benchmarkHKDFSingle(sha512.New, 64, b)
+}
+
+func Benchmark8ByteMD5Stream(b *testing.B) {
+ benchmarkHKDFStream(md5.New, 8, b)
+}
+
+func Benchmark16ByteMD5Stream(b *testing.B) {
+ benchmarkHKDFStream(md5.New, 16, b)
+}
+
+func Benchmark8ByteSHA1Stream(b *testing.B) {
+ benchmarkHKDFStream(sha1.New, 8, b)
+}
+
+func Benchmark20ByteSHA1Stream(b *testing.B) {
+ benchmarkHKDFStream(sha1.New, 20, b)
+}
+
+func Benchmark8ByteSHA256Stream(b *testing.B) {
+ benchmarkHKDFStream(sha256.New, 8, b)
+}
+
+func Benchmark32ByteSHA256Stream(b *testing.B) {
+ benchmarkHKDFStream(sha256.New, 32, b)
+}
+
+func Benchmark8ByteSHA512Stream(b *testing.B) {
+ benchmarkHKDFStream(sha512.New, 8, b)
+}
+
+func Benchmark64ByteSHA512Stream(b *testing.B) {
+ benchmarkHKDFStream(sha512.New, 64, b)
+}
+
+func benchmarkHKDFSingle(hasher func() hash.Hash, block int, b *testing.B) {
+ master := []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}
+ salt := []byte{0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17}
+ info := []byte{0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27}
+ out := make([]byte, block)
+
+ b.SetBytes(int64(block))
+ b.ResetTimer()
+
+ for i := 0; i < b.N; i++ {
+ hkdf := New(hasher, master, salt, info)
+ io.ReadFull(hkdf, out)
+ }
+}
+
+func benchmarkHKDFStream(hasher func() hash.Hash, block int, b *testing.B) {
+ master := []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}
+ salt := []byte{0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17}
+ info := []byte{0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27}
+ out := make([]byte, block)
+
+ b.SetBytes(int64(block))
+ b.ResetTimer()
+
+ hkdf := New(hasher, master, salt, info)
+ for i := 0; i < b.N; i++ {
+ _, err := io.ReadFull(hkdf, out)
+ if err != nil {
+ hkdf = New(hasher, master, salt, info)
+ i--
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/md4/example_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/md4/example_test.go
new file mode 100644
index 000000000..db3f59b19
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/md4/example_test.go
@@ -0,0 +1,20 @@
+// 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 md4_test
+
+import (
+ "fmt"
+ "io"
+
+ "golang.org/x/crypto/md4"
+)
+
+func ExampleNew() {
+ h := md4.New()
+ data := "These pretzels are making me thirsty."
+ io.WriteString(h, data)
+ fmt.Printf("%x", h.Sum(nil))
+ // Output: 48c4e365090b30a32f084c4888deceaa
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/md4/md4.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/md4/md4.go
new file mode 100644
index 000000000..6d9ba9e5f
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/md4/md4.go
@@ -0,0 +1,118 @@
+// Copyright 2009 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 md4 implements the MD4 hash algorithm as defined in RFC 1320.
+package md4 // import "golang.org/x/crypto/md4"
+
+import (
+ "crypto"
+ "hash"
+)
+
+func init() {
+ crypto.RegisterHash(crypto.MD4, New)
+}
+
+// The size of an MD4 checksum in bytes.
+const Size = 16
+
+// The blocksize of MD4 in bytes.
+const BlockSize = 64
+
+const (
+ _Chunk = 64
+ _Init0 = 0x67452301
+ _Init1 = 0xEFCDAB89
+ _Init2 = 0x98BADCFE
+ _Init3 = 0x10325476
+)
+
+// digest represents the partial evaluation of a checksum.
+type digest struct {
+ s [4]uint32
+ x [_Chunk]byte
+ nx int
+ len uint64
+}
+
+func (d *digest) Reset() {
+ d.s[0] = _Init0
+ d.s[1] = _Init1
+ d.s[2] = _Init2
+ d.s[3] = _Init3
+ d.nx = 0
+ d.len = 0
+}
+
+// New returns a new hash.Hash computing the MD4 checksum.
+func New() hash.Hash {
+ d := new(digest)
+ d.Reset()
+ return d
+}
+
+func (d *digest) Size() int { return Size }
+
+func (d *digest) BlockSize() int { return BlockSize }
+
+func (d *digest) Write(p []byte) (nn int, err error) {
+ nn = len(p)
+ d.len += uint64(nn)
+ if d.nx > 0 {
+ n := len(p)
+ if n > _Chunk-d.nx {
+ n = _Chunk - d.nx
+ }
+ for i := 0; i < n; i++ {
+ d.x[d.nx+i] = p[i]
+ }
+ d.nx += n
+ if d.nx == _Chunk {
+ _Block(d, d.x[0:])
+ d.nx = 0
+ }
+ p = p[n:]
+ }
+ n := _Block(d, p)
+ p = p[n:]
+ if len(p) > 0 {
+ d.nx = copy(d.x[:], p)
+ }
+ return
+}
+
+func (d0 *digest) Sum(in []byte) []byte {
+ // Make a copy of d0, so that caller can keep writing and summing.
+ d := new(digest)
+ *d = *d0
+
+ // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64.
+ len := d.len
+ var tmp [64]byte
+ tmp[0] = 0x80
+ if len%64 < 56 {
+ d.Write(tmp[0 : 56-len%64])
+ } else {
+ d.Write(tmp[0 : 64+56-len%64])
+ }
+
+ // Length in bits.
+ len <<= 3
+ for i := uint(0); i < 8; i++ {
+ tmp[i] = byte(len >> (8 * i))
+ }
+ d.Write(tmp[0:8])
+
+ if d.nx != 0 {
+ panic("d.nx != 0")
+ }
+
+ for _, s := range d.s {
+ in = append(in, byte(s>>0))
+ in = append(in, byte(s>>8))
+ in = append(in, byte(s>>16))
+ in = append(in, byte(s>>24))
+ }
+ return in
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/md4/md4_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/md4/md4_test.go
new file mode 100644
index 000000000..b56edd787
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/md4/md4_test.go
@@ -0,0 +1,71 @@
+// Copyright 2009 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 md4
+
+import (
+ "fmt"
+ "io"
+ "testing"
+)
+
+type md4Test struct {
+ out string
+ in string
+}
+
+var golden = []md4Test{
+ {"31d6cfe0d16ae931b73c59d7e0c089c0", ""},
+ {"bde52cb31de33e46245e05fbdbd6fb24", "a"},
+ {"ec388dd78999dfc7cf4632465693b6bf", "ab"},
+ {"a448017aaf21d8525fc10ae87aa6729d", "abc"},
+ {"41decd8f579255c5200f86a4bb3ba740", "abcd"},
+ {"9803f4a34e8eb14f96adba49064a0c41", "abcde"},
+ {"804e7f1c2586e50b49ac65db5b645131", "abcdef"},
+ {"752f4adfe53d1da0241b5bc216d098fc", "abcdefg"},
+ {"ad9daf8d49d81988590a6f0e745d15dd", "abcdefgh"},
+ {"1e4e28b05464316b56402b3815ed2dfd", "abcdefghi"},
+ {"dc959c6f5d6f9e04e4380777cc964b3d", "abcdefghij"},
+ {"1b5701e265778898ef7de5623bbe7cc0", "Discard medicine more than two years old."},
+ {"d7f087e090fe7ad4a01cb59dacc9a572", "He who has a shady past knows that nice guys finish last."},
+ {"a6f8fd6df617c72837592fc3570595c9", "I wouldn't marry him with a ten foot pole."},
+ {"c92a84a9526da8abc240c05d6b1a1ce0", "Free! Free!/A trip/to Mars/for 900/empty jars/Burma Shave"},
+ {"f6013160c4dcb00847069fee3bb09803", "The days of the digital watch are numbered. -Tom Stoppard"},
+ {"2c3bb64f50b9107ed57640fe94bec09f", "Nepal premier won't resign."},
+ {"45b7d8a32c7806f2f7f897332774d6e4", "For every action there is an equal and opposite government program."},
+ {"b5b4f9026b175c62d7654bdc3a1cd438", "His money is twice tainted: 'taint yours and 'taint mine."},
+ {"caf44e80f2c20ce19b5ba1cab766e7bd", "There is no reason for any individual to have a computer in their home. -Ken Olsen, 1977"},
+ {"191fae6707f496aa54a6bce9f2ecf74d", "It's a tiny change to the code and not completely disgusting. - Bob Manchek"},
+ {"9ddc753e7a4ccee6081cd1b45b23a834", "size: a.out: bad magic"},
+ {"8d050f55b1cadb9323474564be08a521", "The major problem is with sendmail. -Mark Horton"},
+ {"ad6e2587f74c3e3cc19146f6127fa2e3", "Give me a rock, paper and scissors and I will move the world. CCFestoon"},
+ {"1d616d60a5fabe85589c3f1566ca7fca", "If the enemy is within range, then so are you."},
+ {"aec3326a4f496a2ced65a1963f84577f", "It's well we cannot hear the screams/That we create in others' dreams."},
+ {"77b4fd762d6b9245e61c50bf6ebf118b", "You remind me of a TV show, but that's all right: I watch it anyway."},
+ {"e8f48c726bae5e516f6ddb1a4fe62438", "C is as portable as Stonehedge!!"},
+ {"a3a84366e7219e887423b01f9be7166e", "Even if I could be Shakespeare, I think I should still choose to be Faraday. - A. Huxley"},
+ {"a6b7aa35157e984ef5d9b7f32e5fbb52", "The fugacity of a constituent in a mixture of gases at a given temperature is proportional to its mole fraction. Lewis-Randall Rule"},
+ {"75661f0545955f8f9abeeb17845f3fd6", "How can you write a big system without C++? -Paul Glick"},
+}
+
+func TestGolden(t *testing.T) {
+ for i := 0; i < len(golden); i++ {
+ g := golden[i]
+ c := New()
+ for j := 0; j < 3; j++ {
+ if j < 2 {
+ io.WriteString(c, g.in)
+ } else {
+ io.WriteString(c, g.in[0:len(g.in)/2])
+ c.Sum(nil)
+ io.WriteString(c, g.in[len(g.in)/2:])
+ }
+ s := fmt.Sprintf("%x", c.Sum(nil))
+ if s != g.out {
+ t.Fatalf("md4[%d](%s) = %s want %s", j, g.in, s, g.out)
+ }
+ c.Reset()
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/md4/md4block.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/md4/md4block.go
new file mode 100644
index 000000000..3fed475f3
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/md4/md4block.go
@@ -0,0 +1,89 @@
+// Copyright 2009 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.
+
+// MD4 block step.
+// In its own file so that a faster assembly or C version
+// can be substituted easily.
+
+package md4
+
+var shift1 = []uint{3, 7, 11, 19}
+var shift2 = []uint{3, 5, 9, 13}
+var shift3 = []uint{3, 9, 11, 15}
+
+var xIndex2 = []uint{0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15}
+var xIndex3 = []uint{0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15}
+
+func _Block(dig *digest, p []byte) int {
+ a := dig.s[0]
+ b := dig.s[1]
+ c := dig.s[2]
+ d := dig.s[3]
+ n := 0
+ var X [16]uint32
+ for len(p) >= _Chunk {
+ aa, bb, cc, dd := a, b, c, d
+
+ j := 0
+ for i := 0; i < 16; i++ {
+ X[i] = uint32(p[j]) | uint32(p[j+1])<<8 | uint32(p[j+2])<<16 | uint32(p[j+3])<<24
+ j += 4
+ }
+
+ // If this needs to be made faster in the future,
+ // the usual trick is to unroll each of these
+ // loops by a factor of 4; that lets you replace
+ // the shift[] lookups with constants and,
+ // with suitable variable renaming in each
+ // unrolled body, delete the a, b, c, d = d, a, b, c
+ // (or you can let the optimizer do the renaming).
+ //
+ // The index variables are uint so that % by a power
+ // of two can be optimized easily by a compiler.
+
+ // Round 1.
+ for i := uint(0); i < 16; i++ {
+ x := i
+ s := shift1[i%4]
+ f := ((c ^ d) & b) ^ d
+ a += f + X[x]
+ a = a<<s | a>>(32-s)
+ a, b, c, d = d, a, b, c
+ }
+
+ // Round 2.
+ for i := uint(0); i < 16; i++ {
+ x := xIndex2[i]
+ s := shift2[i%4]
+ g := (b & c) | (b & d) | (c & d)
+ a += g + X[x] + 0x5a827999
+ a = a<<s | a>>(32-s)
+ a, b, c, d = d, a, b, c
+ }
+
+ // Round 3.
+ for i := uint(0); i < 16; i++ {
+ x := xIndex3[i]
+ s := shift3[i%4]
+ h := b ^ c ^ d
+ a += h + X[x] + 0x6ed9eba1
+ a = a<<s | a>>(32-s)
+ a, b, c, d = d, a, b, c
+ }
+
+ a += aa
+ b += bb
+ c += cc
+ d += dd
+
+ p = p[_Chunk:]
+ n += _Chunk
+ }
+
+ dig.s[0] = a
+ dig.s[1] = b
+ dig.s[2] = c
+ dig.s[3] = d
+ return n
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/nacl/auth/auth.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/nacl/auth/auth.go
new file mode 100644
index 000000000..0835d3bf9
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/nacl/auth/auth.go
@@ -0,0 +1,58 @@
+// 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 auth authenticates a message using a secret key.
+
+The Sum function, viewed as a function of the message for a uniform random
+key, is designed to meet the standard notion of unforgeability. This means
+that an attacker cannot find authenticators for any messages not authenticated
+by the sender, even if the attacker has adaptively influenced the messages
+authenticated by the sender. For a formal definition see, e.g., Section 2.4
+of Bellare, Kilian, and Rogaway, "The security of the cipher block chaining
+message authentication code," Journal of Computer and System Sciences 61 (2000),
+362–399; http://www-cse.ucsd.edu/~mihir/papers/cbc.html.
+
+auth does not make any promises regarding "strong" unforgeability; perhaps
+one valid authenticator can be converted into another valid authenticator for
+the same message. NaCl also does not make any promises regarding "truncated
+unforgeability."
+
+This package is interoperable with NaCl: https://nacl.cr.yp.to/auth.html.
+*/
+package auth
+
+import (
+ "crypto/hmac"
+ "crypto/sha512"
+)
+
+const (
+ // Size is the size, in bytes, of an authenticated digest.
+ Size = 32
+ // KeySize is the size, in bytes, of an authentication key.
+ KeySize = 32
+)
+
+// Sum generates an authenticator for m using a secret key and returns the
+// 32-byte digest.
+func Sum(m []byte, key *[KeySize]byte) *[Size]byte {
+ mac := hmac.New(sha512.New, key[:])
+ mac.Write(m)
+ out := new([KeySize]byte)
+ copy(out[:], mac.Sum(nil)[:Size])
+ return out
+}
+
+// Verify checks that digest is a valid authenticator of message m under the
+// given secret key. Verify does not leak timing information.
+func Verify(digest []byte, m []byte, key *[32]byte) bool {
+ if len(digest) != Size {
+ return false
+ }
+ mac := hmac.New(sha512.New, key[:])
+ mac.Write(m)
+ expectedMAC := mac.Sum(nil) // first 256 bits of 512-bit sum
+ return hmac.Equal(digest, expectedMAC[:Size])
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/nacl/auth/auth_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/nacl/auth/auth_test.go
new file mode 100644
index 000000000..92074b50b
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/nacl/auth/auth_test.go
@@ -0,0 +1,172 @@
+// 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 auth
+
+import (
+ "bytes"
+ rand "crypto/rand"
+ mrand "math/rand"
+ "testing"
+)
+
+// Test cases are from RFC 4231, and match those present in the tests directory
+// of the download here: https://nacl.cr.yp.to/install.html
+var testCases = []struct {
+ key [32]byte
+ msg []byte
+ out [32]byte
+}{
+ {
+ key: [32]byte{
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b,
+ },
+ msg: []byte("Hi There"),
+ out: [32]byte{
+ 0x87, 0xaa, 0x7c, 0xde, 0xa5, 0xef, 0x61, 0x9d,
+ 0x4f, 0xf0, 0xb4, 0x24, 0x1a, 0x1d, 0x6c, 0xb0,
+ 0x23, 0x79, 0xf4, 0xe2, 0xce, 0x4e, 0xc2, 0x78,
+ 0x7a, 0xd0, 0xb3, 0x05, 0x45, 0xe1, 0x7c, 0xde,
+ },
+ },
+ {
+ key: [32]byte{'J', 'e', 'f', 'e'},
+ msg: []byte("what do ya want for nothing?"),
+ out: [32]byte{
+ 0x16, 0x4b, 0x7a, 0x7b, 0xfc, 0xf8, 0x19, 0xe2,
+ 0xe3, 0x95, 0xfb, 0xe7, 0x3b, 0x56, 0xe0, 0xa3,
+ 0x87, 0xbd, 0x64, 0x22, 0x2e, 0x83, 0x1f, 0xd6,
+ 0x10, 0x27, 0x0c, 0xd7, 0xea, 0x25, 0x05, 0x54,
+ },
+ },
+ {
+ key: [32]byte{
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa,
+ },
+ msg: []byte{ // 50 bytes of 0xdd
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd,
+ },
+ out: [32]byte{
+ 0xfa, 0x73, 0xb0, 0x08, 0x9d, 0x56, 0xa2, 0x84,
+ 0xef, 0xb0, 0xf0, 0x75, 0x6c, 0x89, 0x0b, 0xe9,
+ 0xb1, 0xb5, 0xdb, 0xdd, 0x8e, 0xe8, 0x1a, 0x36,
+ 0x55, 0xf8, 0x3e, 0x33, 0xb2, 0x27, 0x9d, 0x39,
+ },
+ },
+ {
+ key: [32]byte{
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
+ 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+ 0x19,
+ },
+ msg: []byte{
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd,
+ },
+ out: [32]byte{
+ 0xb0, 0xba, 0x46, 0x56, 0x37, 0x45, 0x8c, 0x69,
+ 0x90, 0xe5, 0xa8, 0xc5, 0xf6, 0x1d, 0x4a, 0xf7,
+ 0xe5, 0x76, 0xd9, 0x7f, 0xf9, 0x4b, 0x87, 0x2d,
+ 0xe7, 0x6f, 0x80, 0x50, 0x36, 0x1e, 0xe3, 0xdb,
+ },
+ },
+}
+
+func TestSum(t *testing.T) {
+ for i, test := range testCases {
+ tag := Sum(test.msg, &test.key)
+ if !bytes.Equal(tag[:], test.out[:]) {
+ t.Errorf("#%d: Sum: got\n%x\nwant\n%x", i, tag, test.out)
+ }
+ }
+}
+
+func TestVerify(t *testing.T) {
+ wrongMsg := []byte("unknown msg")
+
+ for i, test := range testCases {
+ if !Verify(test.out[:], test.msg, &test.key) {
+ t.Errorf("#%d: Verify(%x, %q, %x) failed", i, test.out, test.msg, test.key)
+ }
+ if Verify(test.out[:], wrongMsg, &test.key) {
+ t.Errorf("#%d: Verify(%x, %q, %x) unexpectedly passed", i, test.out, wrongMsg, test.key)
+ }
+ }
+}
+
+func TestStress(t *testing.T) {
+ if testing.Short() {
+ t.Skip("exhaustiveness test")
+ }
+
+ var key [32]byte
+ msg := make([]byte, 10000)
+ prng := mrand.New(mrand.NewSource(0))
+
+ // copied from tests/auth5.c in nacl
+ for i := 0; i < 10000; i++ {
+ if _, err := rand.Read(key[:]); err != nil {
+ t.Fatal(err)
+ }
+ if _, err := rand.Read(msg[:i]); err != nil {
+ t.Fatal(err)
+ }
+ tag := Sum(msg[:i], &key)
+ if !Verify(tag[:], msg[:i], &key) {
+ t.Errorf("#%d: unexpected failure from Verify", i)
+ }
+ if i > 0 {
+ msgIndex := prng.Intn(i)
+ oldMsgByte := msg[msgIndex]
+ msg[msgIndex] += byte(1 + prng.Intn(255))
+ if Verify(tag[:], msg[:i], &key) {
+ t.Errorf("#%d: unexpected success from Verify after corrupting message", i)
+ }
+ msg[msgIndex] = oldMsgByte
+
+ tag[prng.Intn(len(tag))] += byte(1 + prng.Intn(255))
+ if Verify(tag[:], msg[:i], &key) {
+ t.Errorf("#%d: unexpected success from Verify after corrupting authenticator", i)
+ }
+ }
+ }
+}
+
+func BenchmarkAuth(b *testing.B) {
+ var key [32]byte
+ if _, err := rand.Read(key[:]); err != nil {
+ b.Fatal(err)
+ }
+ buf := make([]byte, 1024)
+ if _, err := rand.Read(buf[:]); err != nil {
+ b.Fatal(err)
+ }
+
+ b.SetBytes(int64(len(buf)))
+ b.ReportAllocs()
+ b.ResetTimer()
+
+ for i := 0; i < b.N; i++ {
+ tag := Sum(buf, &key)
+ if Verify(tag[:], buf, &key) == false {
+ b.Fatal("unexpected failure from Verify")
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/nacl/auth/example_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/nacl/auth/example_test.go
new file mode 100644
index 000000000..02a2cd6c4
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/nacl/auth/example_test.go
@@ -0,0 +1,36 @@
+// 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 auth_test
+
+import (
+ "encoding/hex"
+ "fmt"
+
+ "golang.org/x/crypto/nacl/auth"
+)
+
+func Example() {
+ // Load your secret key from a safe place and reuse it across multiple
+ // Sum calls. (Obviously don't use this example key for anything
+ // real.) If you want to convert a passphrase to a key, use a suitable
+ // package like bcrypt or scrypt.
+ secretKeyBytes, err := hex.DecodeString("6368616e676520746869732070617373776f726420746f206120736563726574")
+ if err != nil {
+ panic(err)
+ }
+
+ var secretKey [32]byte
+ copy(secretKey[:], secretKeyBytes)
+
+ mac := auth.Sum([]byte("hello world"), &secretKey)
+ fmt.Printf("%x\n", *mac)
+ result := auth.Verify(mac[:], []byte("hello world"), &secretKey)
+ fmt.Println(result)
+ badResult := auth.Verify(mac[:], []byte("different message"), &secretKey)
+ fmt.Println(badResult)
+ // Output: eca5a521f3d77b63f567fb0cb6f5f2d200641bc8dada42f60c5f881260c30317
+ // true
+ // false
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/nacl/box/box.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/nacl/box/box.go
new file mode 100644
index 000000000..31b697be4
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/nacl/box/box.go
@@ -0,0 +1,103 @@
+// Copyright 2012 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 box authenticates and encrypts small messages using public-key cryptography.
+
+Box uses Curve25519, XSalsa20 and Poly1305 to encrypt and authenticate
+messages. The length of messages is not hidden.
+
+It is the caller's responsibility to ensure the uniqueness of nonces—for
+example, by using nonce 1 for the first message, nonce 2 for the second
+message, etc. Nonces are long enough that randomly generated nonces have
+negligible risk of collision.
+
+Messages should be small because:
+
+1. The whole message needs to be held in memory to be processed.
+
+2. Using large messages pressures implementations on small machines to decrypt
+and process plaintext before authenticating it. This is very dangerous, and
+this API does not allow it, but a protocol that uses excessive message sizes
+might present some implementations with no other choice.
+
+3. Fixed overheads will be sufficiently amortised by messages as small as 8KB.
+
+4. Performance may be improved by working with messages that fit into data caches.
+
+Thus large amounts of data should be chunked so that each message is small.
+(Each message still needs a unique nonce.) If in doubt, 16KB is a reasonable
+chunk size.
+
+This package is interoperable with NaCl: https://nacl.cr.yp.to/box.html.
+*/
+package box // import "golang.org/x/crypto/nacl/box"
+
+import (
+ "io"
+
+ "golang.org/x/crypto/curve25519"
+ "golang.org/x/crypto/nacl/secretbox"
+ "golang.org/x/crypto/salsa20/salsa"
+)
+
+// Overhead is the number of bytes of overhead when boxing a message.
+const Overhead = secretbox.Overhead
+
+// GenerateKey generates a new public/private key pair suitable for use with
+// Seal and Open.
+func GenerateKey(rand io.Reader) (publicKey, privateKey *[32]byte, err error) {
+ publicKey = new([32]byte)
+ privateKey = new([32]byte)
+ _, err = io.ReadFull(rand, privateKey[:])
+ if err != nil {
+ publicKey = nil
+ privateKey = nil
+ return
+ }
+
+ curve25519.ScalarBaseMult(publicKey, privateKey)
+ return
+}
+
+var zeros [16]byte
+
+// Precompute calculates the shared key between peersPublicKey and privateKey
+// and writes it to sharedKey. The shared key can be used with
+// OpenAfterPrecomputation and SealAfterPrecomputation to speed up processing
+// when using the same pair of keys repeatedly.
+func Precompute(sharedKey, peersPublicKey, privateKey *[32]byte) {
+ curve25519.ScalarMult(sharedKey, privateKey, peersPublicKey)
+ salsa.HSalsa20(sharedKey, &zeros, sharedKey, &salsa.Sigma)
+}
+
+// Seal appends an encrypted and authenticated copy of message to out, which
+// will be Overhead bytes longer than the original and must not overlap it. The
+// nonce must be unique for each distinct message for a given pair of keys.
+func Seal(out, message []byte, nonce *[24]byte, peersPublicKey, privateKey *[32]byte) []byte {
+ var sharedKey [32]byte
+ Precompute(&sharedKey, peersPublicKey, privateKey)
+ return secretbox.Seal(out, message, nonce, &sharedKey)
+}
+
+// SealAfterPrecomputation performs the same actions as Seal, but takes a
+// shared key as generated by Precompute.
+func SealAfterPrecomputation(out, message []byte, nonce *[24]byte, sharedKey *[32]byte) []byte {
+ return secretbox.Seal(out, message, nonce, sharedKey)
+}
+
+// Open authenticates and decrypts a box produced by Seal and appends the
+// message to out, which must not overlap box. The output will be Overhead
+// bytes smaller than box.
+func Open(out, box []byte, nonce *[24]byte, peersPublicKey, privateKey *[32]byte) ([]byte, bool) {
+ var sharedKey [32]byte
+ Precompute(&sharedKey, peersPublicKey, privateKey)
+ return secretbox.Open(out, box, nonce, &sharedKey)
+}
+
+// OpenAfterPrecomputation performs the same actions as Open, but takes a
+// shared key as generated by Precompute.
+func OpenAfterPrecomputation(out, box []byte, nonce *[24]byte, sharedKey *[32]byte) ([]byte, bool) {
+ return secretbox.Open(out, box, nonce, sharedKey)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/nacl/box/box_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/nacl/box/box_test.go
new file mode 100644
index 000000000..481ade28a
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/nacl/box/box_test.go
@@ -0,0 +1,78 @@
+// Copyright 2012 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 box
+
+import (
+ "bytes"
+ "crypto/rand"
+ "encoding/hex"
+ "testing"
+
+ "golang.org/x/crypto/curve25519"
+)
+
+func TestSealOpen(t *testing.T) {
+ publicKey1, privateKey1, _ := GenerateKey(rand.Reader)
+ publicKey2, privateKey2, _ := GenerateKey(rand.Reader)
+
+ if *privateKey1 == *privateKey2 {
+ t.Fatalf("private keys are equal!")
+ }
+ if *publicKey1 == *publicKey2 {
+ t.Fatalf("public keys are equal!")
+ }
+ message := []byte("test message")
+ var nonce [24]byte
+
+ box := Seal(nil, message, &nonce, publicKey1, privateKey2)
+ opened, ok := Open(nil, box, &nonce, publicKey2, privateKey1)
+ if !ok {
+ t.Fatalf("failed to open box")
+ }
+
+ if !bytes.Equal(opened, message) {
+ t.Fatalf("got %x, want %x", opened, message)
+ }
+
+ for i := range box {
+ box[i] ^= 0x40
+ _, ok := Open(nil, box, &nonce, publicKey2, privateKey1)
+ if ok {
+ t.Fatalf("opened box with byte %d corrupted", i)
+ }
+ box[i] ^= 0x40
+ }
+}
+
+func TestBox(t *testing.T) {
+ var privateKey1, privateKey2 [32]byte
+ for i := range privateKey1[:] {
+ privateKey1[i] = 1
+ }
+ for i := range privateKey2[:] {
+ privateKey2[i] = 2
+ }
+
+ var publicKey1 [32]byte
+ curve25519.ScalarBaseMult(&publicKey1, &privateKey1)
+ var message [64]byte
+ for i := range message[:] {
+ message[i] = 3
+ }
+
+ var nonce [24]byte
+ for i := range nonce[:] {
+ nonce[i] = 4
+ }
+
+ box := Seal(nil, message[:], &nonce, &publicKey1, &privateKey2)
+
+ // expected was generated using the C implementation of NaCl.
+ expected, _ := hex.DecodeString("78ea30b19d2341ebbdba54180f821eec265cf86312549bea8a37652a8bb94f07b78a73ed1708085e6ddd0e943bbdeb8755079a37eb31d86163ce241164a47629c0539f330b4914cd135b3855bc2a2dfc")
+
+ if !bytes.Equal(box, expected) {
+ t.Fatalf("box didn't match, got\n%x\n, expected\n%x", box, expected)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/nacl/box/example_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/nacl/box/example_test.go
new file mode 100644
index 000000000..25e42d2be
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/nacl/box/example_test.go
@@ -0,0 +1,95 @@
+package box_test
+
+import (
+ crypto_rand "crypto/rand" // Custom so it's clear which rand we're using.
+ "fmt"
+ "io"
+
+ "golang.org/x/crypto/nacl/box"
+)
+
+func Example() {
+ senderPublicKey, senderPrivateKey, err := box.GenerateKey(crypto_rand.Reader)
+ if err != nil {
+ panic(err)
+ }
+
+ recipientPublicKey, recipientPrivateKey, err := box.GenerateKey(crypto_rand.Reader)
+ if err != nil {
+ panic(err)
+ }
+
+ // You must use a different nonce for each message you encrypt with the
+ // same key. Since the nonce here is 192 bits long, a random value
+ // provides a sufficiently small probability of repeats.
+ var nonce [24]byte
+ if _, err := io.ReadFull(crypto_rand.Reader, nonce[:]); err != nil {
+ panic(err)
+ }
+
+ msg := []byte("Alas, poor Yorick! I knew him, Horatio")
+ // This encrypts msg and appends the result to the nonce.
+ encrypted := box.Seal(nonce[:], msg, &nonce, recipientPublicKey, senderPrivateKey)
+
+ // The recipient can decrypt the message using their private key and the
+ // sender's public key. When you decrypt, you must use the same nonce you
+ // used to encrypt the message. One way to achieve this is to store the
+ // nonce alongside the encrypted message. Above, we stored the nonce in the
+ // first 24 bytes of the encrypted text.
+ var decryptNonce [24]byte
+ copy(decryptNonce[:], encrypted[:24])
+ decrypted, ok := box.Open(nil, encrypted[24:], &decryptNonce, senderPublicKey, recipientPrivateKey)
+ if !ok {
+ panic("decryption error")
+ }
+ fmt.Println(string(decrypted))
+ // Output: Alas, poor Yorick! I knew him, Horatio
+}
+
+func Example_precompute() {
+ senderPublicKey, senderPrivateKey, err := box.GenerateKey(crypto_rand.Reader)
+ if err != nil {
+ panic(err)
+ }
+
+ recipientPublicKey, recipientPrivateKey, err := box.GenerateKey(crypto_rand.Reader)
+ if err != nil {
+ panic(err)
+ }
+
+ // The shared key can be used to speed up processing when using the same
+ // pair of keys repeatedly.
+ sharedEncryptKey := new([32]byte)
+ box.Precompute(sharedEncryptKey, recipientPublicKey, senderPrivateKey)
+
+ // You must use a different nonce for each message you encrypt with the
+ // same key. Since the nonce here is 192 bits long, a random value
+ // provides a sufficiently small probability of repeats.
+ var nonce [24]byte
+ if _, err := io.ReadFull(crypto_rand.Reader, nonce[:]); err != nil {
+ panic(err)
+ }
+
+ msg := []byte("A fellow of infinite jest, of most excellent fancy")
+ // This encrypts msg and appends the result to the nonce.
+ encrypted := box.SealAfterPrecomputation(nonce[:], msg, &nonce, sharedEncryptKey)
+
+ // The shared key can be used to speed up processing when using the same
+ // pair of keys repeatedly.
+ var sharedDecryptKey [32]byte
+ box.Precompute(&sharedDecryptKey, senderPublicKey, recipientPrivateKey)
+
+ // The recipient can decrypt the message using the shared key. When you
+ // decrypt, you must use the same nonce you used to encrypt the message.
+ // One way to achieve this is to store the nonce alongside the encrypted
+ // message. Above, we stored the nonce in the first 24 bytes of the
+ // encrypted text.
+ var decryptNonce [24]byte
+ copy(decryptNonce[:], encrypted[:24])
+ decrypted, ok := box.OpenAfterPrecomputation(nil, encrypted[24:], &decryptNonce, &sharedDecryptKey)
+ if !ok {
+ panic("decryption error")
+ }
+ fmt.Println(string(decrypted))
+ // Output: A fellow of infinite jest, of most excellent fancy
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/nacl/secretbox/example_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/nacl/secretbox/example_test.go
new file mode 100644
index 000000000..789f4ff03
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/nacl/secretbox/example_test.go
@@ -0,0 +1,53 @@
+// 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.
+
+package secretbox_test
+
+import (
+ "crypto/rand"
+ "encoding/hex"
+ "fmt"
+ "io"
+
+ "golang.org/x/crypto/nacl/secretbox"
+)
+
+func Example() {
+ // Load your secret key from a safe place and reuse it across multiple
+ // Seal calls. (Obviously don't use this example key for anything
+ // real.) If you want to convert a passphrase to a key, use a suitable
+ // package like bcrypt or scrypt.
+ secretKeyBytes, err := hex.DecodeString("6368616e676520746869732070617373776f726420746f206120736563726574")
+ if err != nil {
+ panic(err)
+ }
+
+ var secretKey [32]byte
+ copy(secretKey[:], secretKeyBytes)
+
+ // You must use a different nonce for each message you encrypt with the
+ // same key. Since the nonce here is 192 bits long, a random value
+ // provides a sufficiently small probability of repeats.
+ var nonce [24]byte
+ if _, err := io.ReadFull(rand.Reader, nonce[:]); err != nil {
+ panic(err)
+ }
+
+ // This encrypts "hello world" and appends the result to the nonce.
+ encrypted := secretbox.Seal(nonce[:], []byte("hello world"), &nonce, &secretKey)
+
+ // When you decrypt, you must use the same nonce and key you used to
+ // encrypt the message. One way to achieve this is to store the nonce
+ // alongside the encrypted message. Above, we stored the nonce in the first
+ // 24 bytes of the encrypted text.
+ var decryptNonce [24]byte
+ copy(decryptNonce[:], encrypted[:24])
+ decrypted, ok := secretbox.Open(nil, encrypted[24:], &decryptNonce, &secretKey)
+ if !ok {
+ panic("decryption error")
+ }
+
+ fmt.Println(string(decrypted))
+ // Output: hello world
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/nacl/secretbox/secretbox.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/nacl/secretbox/secretbox.go
new file mode 100644
index 000000000..53ee83cfb
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/nacl/secretbox/secretbox.go
@@ -0,0 +1,166 @@
+// Copyright 2012 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 secretbox encrypts and authenticates small messages.
+
+Secretbox uses XSalsa20 and Poly1305 to encrypt and authenticate messages with
+secret-key cryptography. The length of messages is not hidden.
+
+It is the caller's responsibility to ensure the uniqueness of nonces—for
+example, by using nonce 1 for the first message, nonce 2 for the second
+message, etc. Nonces are long enough that randomly generated nonces have
+negligible risk of collision.
+
+Messages should be small because:
+
+1. The whole message needs to be held in memory to be processed.
+
+2. Using large messages pressures implementations on small machines to decrypt
+and process plaintext before authenticating it. This is very dangerous, and
+this API does not allow it, but a protocol that uses excessive message sizes
+might present some implementations with no other choice.
+
+3. Fixed overheads will be sufficiently amortised by messages as small as 8KB.
+
+4. Performance may be improved by working with messages that fit into data caches.
+
+Thus large amounts of data should be chunked so that each message is small.
+(Each message still needs a unique nonce.) If in doubt, 16KB is a reasonable
+chunk size.
+
+This package is interoperable with NaCl: https://nacl.cr.yp.to/secretbox.html.
+*/
+package secretbox // import "golang.org/x/crypto/nacl/secretbox"
+
+import (
+ "golang.org/x/crypto/poly1305"
+ "golang.org/x/crypto/salsa20/salsa"
+)
+
+// Overhead is the number of bytes of overhead when boxing a message.
+const Overhead = poly1305.TagSize
+
+// setup produces a sub-key and Salsa20 counter given a nonce and key.
+func setup(subKey *[32]byte, counter *[16]byte, nonce *[24]byte, key *[32]byte) {
+ // We use XSalsa20 for encryption so first we need to generate a
+ // key and nonce with HSalsa20.
+ var hNonce [16]byte
+ copy(hNonce[:], nonce[:])
+ salsa.HSalsa20(subKey, &hNonce, key, &salsa.Sigma)
+
+ // The final 8 bytes of the original nonce form the new nonce.
+ copy(counter[:], nonce[16:])
+}
+
+// sliceForAppend takes a slice and a requested number of bytes. It returns a
+// slice with the contents of the given slice followed by that many bytes and a
+// second slice that aliases into it and contains only the extra bytes. If the
+// original slice has sufficient capacity then no allocation is performed.
+func sliceForAppend(in []byte, n int) (head, tail []byte) {
+ if total := len(in) + n; cap(in) >= total {
+ head = in[:total]
+ } else {
+ head = make([]byte, total)
+ copy(head, in)
+ }
+ tail = head[len(in):]
+ return
+}
+
+// Seal appends an encrypted and authenticated copy of message to out, which
+// must not overlap message. The key and nonce pair must be unique for each
+// distinct message and the output will be Overhead bytes longer than message.
+func Seal(out, message []byte, nonce *[24]byte, key *[32]byte) []byte {
+ var subKey [32]byte
+ var counter [16]byte
+ setup(&subKey, &counter, nonce, key)
+
+ // The Poly1305 key is generated by encrypting 32 bytes of zeros. Since
+ // Salsa20 works with 64-byte blocks, we also generate 32 bytes of
+ // keystream as a side effect.
+ var firstBlock [64]byte
+ salsa.XORKeyStream(firstBlock[:], firstBlock[:], &counter, &subKey)
+
+ var poly1305Key [32]byte
+ copy(poly1305Key[:], firstBlock[:])
+
+ ret, out := sliceForAppend(out, len(message)+poly1305.TagSize)
+
+ // We XOR up to 32 bytes of message with the keystream generated from
+ // the first block.
+ firstMessageBlock := message
+ if len(firstMessageBlock) > 32 {
+ firstMessageBlock = firstMessageBlock[:32]
+ }
+
+ tagOut := out
+ out = out[poly1305.TagSize:]
+ for i, x := range firstMessageBlock {
+ out[i] = firstBlock[32+i] ^ x
+ }
+ message = message[len(firstMessageBlock):]
+ ciphertext := out
+ out = out[len(firstMessageBlock):]
+
+ // Now encrypt the rest.
+ counter[8] = 1
+ salsa.XORKeyStream(out, message, &counter, &subKey)
+
+ var tag [poly1305.TagSize]byte
+ poly1305.Sum(&tag, ciphertext, &poly1305Key)
+ copy(tagOut, tag[:])
+
+ return ret
+}
+
+// Open authenticates and decrypts a box produced by Seal and appends the
+// message to out, which must not overlap box. The output will be Overhead
+// bytes smaller than box.
+func Open(out []byte, box []byte, nonce *[24]byte, key *[32]byte) ([]byte, bool) {
+ if len(box) < Overhead {
+ return nil, false
+ }
+
+ var subKey [32]byte
+ var counter [16]byte
+ setup(&subKey, &counter, nonce, key)
+
+ // The Poly1305 key is generated by encrypting 32 bytes of zeros. Since
+ // Salsa20 works with 64-byte blocks, we also generate 32 bytes of
+ // keystream as a side effect.
+ var firstBlock [64]byte
+ salsa.XORKeyStream(firstBlock[:], firstBlock[:], &counter, &subKey)
+
+ var poly1305Key [32]byte
+ copy(poly1305Key[:], firstBlock[:])
+ var tag [poly1305.TagSize]byte
+ copy(tag[:], box)
+
+ if !poly1305.Verify(&tag, box[poly1305.TagSize:], &poly1305Key) {
+ return nil, false
+ }
+
+ ret, out := sliceForAppend(out, len(box)-Overhead)
+
+ // We XOR up to 32 bytes of box with the keystream generated from
+ // the first block.
+ box = box[Overhead:]
+ firstMessageBlock := box
+ if len(firstMessageBlock) > 32 {
+ firstMessageBlock = firstMessageBlock[:32]
+ }
+ for i, x := range firstMessageBlock {
+ out[i] = firstBlock[32+i] ^ x
+ }
+
+ box = box[len(firstMessageBlock):]
+ out = out[len(firstMessageBlock):]
+
+ // Now decrypt the rest.
+ counter[8] = 1
+ salsa.XORKeyStream(out, box, &counter, &subKey)
+
+ return ret, true
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/nacl/secretbox/secretbox_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/nacl/secretbox/secretbox_test.go
new file mode 100644
index 000000000..3c70b0f4b
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/nacl/secretbox/secretbox_test.go
@@ -0,0 +1,154 @@
+// Copyright 2012 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 secretbox
+
+import (
+ "bytes"
+ "crypto/rand"
+ "encoding/hex"
+ "testing"
+)
+
+func TestSealOpen(t *testing.T) {
+ var key [32]byte
+ var nonce [24]byte
+
+ rand.Reader.Read(key[:])
+ rand.Reader.Read(nonce[:])
+
+ var box, opened []byte
+
+ for msgLen := 0; msgLen < 128; msgLen += 17 {
+ message := make([]byte, msgLen)
+ rand.Reader.Read(message)
+
+ box = Seal(box[:0], message, &nonce, &key)
+ var ok bool
+ opened, ok = Open(opened[:0], box, &nonce, &key)
+ if !ok {
+ t.Errorf("%d: failed to open box", msgLen)
+ continue
+ }
+
+ if !bytes.Equal(opened, message) {
+ t.Errorf("%d: got %x, expected %x", msgLen, opened, message)
+ continue
+ }
+ }
+
+ for i := range box {
+ box[i] ^= 0x20
+ _, ok := Open(opened[:0], box, &nonce, &key)
+ if ok {
+ t.Errorf("box was opened after corrupting byte %d", i)
+ }
+ box[i] ^= 0x20
+ }
+}
+
+func TestSecretBox(t *testing.T) {
+ var key [32]byte
+ var nonce [24]byte
+ var message [64]byte
+
+ for i := range key[:] {
+ key[i] = 1
+ }
+ for i := range nonce[:] {
+ nonce[i] = 2
+ }
+ for i := range message[:] {
+ message[i] = 3
+ }
+
+ box := Seal(nil, message[:], &nonce, &key)
+ // expected was generated using the C implementation of NaCl.
+ expected, _ := hex.DecodeString("8442bc313f4626f1359e3b50122b6ce6fe66ddfe7d39d14e637eb4fd5b45beadab55198df6ab5368439792a23c87db70acb6156dc5ef957ac04f6276cf6093b84be77ff0849cc33e34b7254d5a8f65ad")
+
+ if !bytes.Equal(box, expected) {
+ t.Fatalf("box didn't match, got\n%x\n, expected\n%x", box, expected)
+ }
+}
+
+func TestAppend(t *testing.T) {
+ var key [32]byte
+ var nonce [24]byte
+ var message [8]byte
+
+ out := make([]byte, 4)
+ box := Seal(out, message[:], &nonce, &key)
+ if !bytes.Equal(box[:4], out[:4]) {
+ t.Fatalf("Seal didn't correctly append")
+ }
+
+ out = make([]byte, 4, 100)
+ box = Seal(out, message[:], &nonce, &key)
+ if !bytes.Equal(box[:4], out[:4]) {
+ t.Fatalf("Seal didn't correctly append with sufficient capacity.")
+ }
+}
+
+func benchmarkSealSize(b *testing.B, size int) {
+ message := make([]byte, size)
+ out := make([]byte, size+Overhead)
+ var nonce [24]byte
+ var key [32]byte
+
+ b.SetBytes(int64(size))
+ b.ResetTimer()
+
+ for i := 0; i < b.N; i++ {
+ out = Seal(out[:0], message, &nonce, &key)
+ }
+}
+
+func BenchmarkSeal8Bytes(b *testing.B) {
+ benchmarkSealSize(b, 8)
+}
+
+func BenchmarkSeal100Bytes(b *testing.B) {
+ benchmarkSealSize(b, 100)
+}
+
+func BenchmarkSeal1K(b *testing.B) {
+ benchmarkSealSize(b, 1024)
+}
+
+func BenchmarkSeal8K(b *testing.B) {
+ benchmarkSealSize(b, 8192)
+}
+
+func benchmarkOpenSize(b *testing.B, size int) {
+ msg := make([]byte, size)
+ result := make([]byte, size)
+ var nonce [24]byte
+ var key [32]byte
+ box := Seal(nil, msg, &nonce, &key)
+
+ b.SetBytes(int64(size))
+ b.ResetTimer()
+
+ for i := 0; i < b.N; i++ {
+ if _, ok := Open(result[:0], box, &nonce, &key); !ok {
+ panic("Open failed")
+ }
+ }
+}
+
+func BenchmarkOpen8Bytes(b *testing.B) {
+ benchmarkOpenSize(b, 8)
+}
+
+func BenchmarkOpen100Bytes(b *testing.B) {
+ benchmarkOpenSize(b, 100)
+}
+
+func BenchmarkOpen1K(b *testing.B) {
+ benchmarkOpenSize(b, 1024)
+}
+
+func BenchmarkOpen8K(b *testing.B) {
+ benchmarkOpenSize(b, 8192)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ocsp/ocsp.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ocsp/ocsp.go
new file mode 100644
index 000000000..5e73146d7
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ocsp/ocsp.go
@@ -0,0 +1,778 @@
+// Copyright 2013 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 ocsp parses OCSP responses as specified in RFC 2560. OCSP responses
+// are signed messages attesting to the validity of a certificate for a small
+// period of time. This is used to manage revocation for X.509 certificates.
+package ocsp // import "golang.org/x/crypto/ocsp"
+
+import (
+ "crypto"
+ "crypto/ecdsa"
+ "crypto/elliptic"
+ "crypto/rand"
+ "crypto/rsa"
+ _ "crypto/sha1"
+ _ "crypto/sha256"
+ _ "crypto/sha512"
+ "crypto/x509"
+ "crypto/x509/pkix"
+ "encoding/asn1"
+ "errors"
+ "fmt"
+ "math/big"
+ "strconv"
+ "time"
+)
+
+var idPKIXOCSPBasic = asn1.ObjectIdentifier([]int{1, 3, 6, 1, 5, 5, 7, 48, 1, 1})
+
+// ResponseStatus contains the result of an OCSP request. See
+// https://tools.ietf.org/html/rfc6960#section-2.3
+type ResponseStatus int
+
+const (
+ Success ResponseStatus = 0
+ Malformed ResponseStatus = 1
+ InternalError ResponseStatus = 2
+ TryLater ResponseStatus = 3
+ // Status code four is unused in OCSP. See
+ // https://tools.ietf.org/html/rfc6960#section-4.2.1
+ SignatureRequired ResponseStatus = 5
+ Unauthorized ResponseStatus = 6
+)
+
+func (r ResponseStatus) String() string {
+ switch r {
+ case Success:
+ return "success"
+ case Malformed:
+ return "malformed"
+ case InternalError:
+ return "internal error"
+ case TryLater:
+ return "try later"
+ case SignatureRequired:
+ return "signature required"
+ case Unauthorized:
+ return "unauthorized"
+ default:
+ return "unknown OCSP status: " + strconv.Itoa(int(r))
+ }
+}
+
+// ResponseError is an error that may be returned by ParseResponse to indicate
+// that the response itself is an error, not just that its indicating that a
+// certificate is revoked, unknown, etc.
+type ResponseError struct {
+ Status ResponseStatus
+}
+
+func (r ResponseError) Error() string {
+ return "ocsp: error from server: " + r.Status.String()
+}
+
+// These are internal structures that reflect the ASN.1 structure of an OCSP
+// response. See RFC 2560, section 4.2.
+
+type certID struct {
+ HashAlgorithm pkix.AlgorithmIdentifier
+ NameHash []byte
+ IssuerKeyHash []byte
+ SerialNumber *big.Int
+}
+
+// https://tools.ietf.org/html/rfc2560#section-4.1.1
+type ocspRequest struct {
+ TBSRequest tbsRequest
+}
+
+type tbsRequest struct {
+ Version int `asn1:"explicit,tag:0,default:0,optional"`
+ RequestorName pkix.RDNSequence `asn1:"explicit,tag:1,optional"`
+ RequestList []request
+}
+
+type request struct {
+ Cert certID
+}
+
+type responseASN1 struct {
+ Status asn1.Enumerated
+ Response responseBytes `asn1:"explicit,tag:0,optional"`
+}
+
+type responseBytes struct {
+ ResponseType asn1.ObjectIdentifier
+ Response []byte
+}
+
+type basicResponse struct {
+ TBSResponseData responseData
+ SignatureAlgorithm pkix.AlgorithmIdentifier
+ Signature asn1.BitString
+ Certificates []asn1.RawValue `asn1:"explicit,tag:0,optional"`
+}
+
+type responseData struct {
+ Raw asn1.RawContent
+ Version int `asn1:"optional,default:0,explicit,tag:0"`
+ RawResponderID asn1.RawValue
+ ProducedAt time.Time `asn1:"generalized"`
+ Responses []singleResponse
+}
+
+type singleResponse struct {
+ CertID certID
+ Good asn1.Flag `asn1:"tag:0,optional"`
+ Revoked revokedInfo `asn1:"tag:1,optional"`
+ Unknown asn1.Flag `asn1:"tag:2,optional"`
+ ThisUpdate time.Time `asn1:"generalized"`
+ NextUpdate time.Time `asn1:"generalized,explicit,tag:0,optional"`
+ SingleExtensions []pkix.Extension `asn1:"explicit,tag:1,optional"`
+}
+
+type revokedInfo struct {
+ RevocationTime time.Time `asn1:"generalized"`
+ Reason asn1.Enumerated `asn1:"explicit,tag:0,optional"`
+}
+
+var (
+ oidSignatureMD2WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 2}
+ oidSignatureMD5WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 4}
+ oidSignatureSHA1WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5}
+ oidSignatureSHA256WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 11}
+ oidSignatureSHA384WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 12}
+ oidSignatureSHA512WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 13}
+ oidSignatureDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 3}
+ oidSignatureDSAWithSHA256 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 3, 2}
+ oidSignatureECDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 1}
+ oidSignatureECDSAWithSHA256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 2}
+ oidSignatureECDSAWithSHA384 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 3}
+ oidSignatureECDSAWithSHA512 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 4}
+)
+
+var hashOIDs = map[crypto.Hash]asn1.ObjectIdentifier{
+ crypto.SHA1: asn1.ObjectIdentifier([]int{1, 3, 14, 3, 2, 26}),
+ crypto.SHA256: asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 1}),
+ crypto.SHA384: asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 2}),
+ crypto.SHA512: asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 3}),
+}
+
+// TODO(rlb): This is also from crypto/x509, so same comment as AGL's below
+var signatureAlgorithmDetails = []struct {
+ algo x509.SignatureAlgorithm
+ oid asn1.ObjectIdentifier
+ pubKeyAlgo x509.PublicKeyAlgorithm
+ hash crypto.Hash
+}{
+ {x509.MD2WithRSA, oidSignatureMD2WithRSA, x509.RSA, crypto.Hash(0) /* no value for MD2 */},
+ {x509.MD5WithRSA, oidSignatureMD5WithRSA, x509.RSA, crypto.MD5},
+ {x509.SHA1WithRSA, oidSignatureSHA1WithRSA, x509.RSA, crypto.SHA1},
+ {x509.SHA256WithRSA, oidSignatureSHA256WithRSA, x509.RSA, crypto.SHA256},
+ {x509.SHA384WithRSA, oidSignatureSHA384WithRSA, x509.RSA, crypto.SHA384},
+ {x509.SHA512WithRSA, oidSignatureSHA512WithRSA, x509.RSA, crypto.SHA512},
+ {x509.DSAWithSHA1, oidSignatureDSAWithSHA1, x509.DSA, crypto.SHA1},
+ {x509.DSAWithSHA256, oidSignatureDSAWithSHA256, x509.DSA, crypto.SHA256},
+ {x509.ECDSAWithSHA1, oidSignatureECDSAWithSHA1, x509.ECDSA, crypto.SHA1},
+ {x509.ECDSAWithSHA256, oidSignatureECDSAWithSHA256, x509.ECDSA, crypto.SHA256},
+ {x509.ECDSAWithSHA384, oidSignatureECDSAWithSHA384, x509.ECDSA, crypto.SHA384},
+ {x509.ECDSAWithSHA512, oidSignatureECDSAWithSHA512, x509.ECDSA, crypto.SHA512},
+}
+
+// TODO(rlb): This is also from crypto/x509, so same comment as AGL's below
+func signingParamsForPublicKey(pub interface{}, requestedSigAlgo x509.SignatureAlgorithm) (hashFunc crypto.Hash, sigAlgo pkix.AlgorithmIdentifier, err error) {
+ var pubType x509.PublicKeyAlgorithm
+
+ switch pub := pub.(type) {
+ case *rsa.PublicKey:
+ pubType = x509.RSA
+ hashFunc = crypto.SHA256
+ sigAlgo.Algorithm = oidSignatureSHA256WithRSA
+ sigAlgo.Parameters = asn1.RawValue{
+ Tag: 5,
+ }
+
+ case *ecdsa.PublicKey:
+ pubType = x509.ECDSA
+
+ switch pub.Curve {
+ case elliptic.P224(), elliptic.P256():
+ hashFunc = crypto.SHA256
+ sigAlgo.Algorithm = oidSignatureECDSAWithSHA256
+ case elliptic.P384():
+ hashFunc = crypto.SHA384
+ sigAlgo.Algorithm = oidSignatureECDSAWithSHA384
+ case elliptic.P521():
+ hashFunc = crypto.SHA512
+ sigAlgo.Algorithm = oidSignatureECDSAWithSHA512
+ default:
+ err = errors.New("x509: unknown elliptic curve")
+ }
+
+ default:
+ err = errors.New("x509: only RSA and ECDSA keys supported")
+ }
+
+ if err != nil {
+ return
+ }
+
+ if requestedSigAlgo == 0 {
+ return
+ }
+
+ found := false
+ for _, details := range signatureAlgorithmDetails {
+ if details.algo == requestedSigAlgo {
+ if details.pubKeyAlgo != pubType {
+ err = errors.New("x509: requested SignatureAlgorithm does not match private key type")
+ return
+ }
+ sigAlgo.Algorithm, hashFunc = details.oid, details.hash
+ if hashFunc == 0 {
+ err = errors.New("x509: cannot sign with hash function requested")
+ return
+ }
+ found = true
+ break
+ }
+ }
+
+ if !found {
+ err = errors.New("x509: unknown SignatureAlgorithm")
+ }
+
+ return
+}
+
+// TODO(agl): this is taken from crypto/x509 and so should probably be exported
+// from crypto/x509 or crypto/x509/pkix.
+func getSignatureAlgorithmFromOID(oid asn1.ObjectIdentifier) x509.SignatureAlgorithm {
+ for _, details := range signatureAlgorithmDetails {
+ if oid.Equal(details.oid) {
+ return details.algo
+ }
+ }
+ return x509.UnknownSignatureAlgorithm
+}
+
+// TODO(rlb): This is not taken from crypto/x509, but it's of the same general form.
+func getHashAlgorithmFromOID(target asn1.ObjectIdentifier) crypto.Hash {
+ for hash, oid := range hashOIDs {
+ if oid.Equal(target) {
+ return hash
+ }
+ }
+ return crypto.Hash(0)
+}
+
+func getOIDFromHashAlgorithm(target crypto.Hash) asn1.ObjectIdentifier {
+ for hash, oid := range hashOIDs {
+ if hash == target {
+ return oid
+ }
+ }
+ return nil
+}
+
+// This is the exposed reflection of the internal OCSP structures.
+
+// The status values that can be expressed in OCSP. See RFC 6960.
+const (
+ // Good means that the certificate is valid.
+ Good = iota
+ // Revoked means that the certificate has been deliberately revoked.
+ Revoked
+ // Unknown means that the OCSP responder doesn't know about the certificate.
+ Unknown
+ // ServerFailed is unused and was never used (see
+ // https://go-review.googlesource.com/#/c/18944). ParseResponse will
+ // return a ResponseError when an error response is parsed.
+ ServerFailed
+)
+
+// The enumerated reasons for revoking a certificate. See RFC 5280.
+const (
+ Unspecified = 0
+ KeyCompromise = 1
+ CACompromise = 2
+ AffiliationChanged = 3
+ Superseded = 4
+ CessationOfOperation = 5
+ CertificateHold = 6
+
+ RemoveFromCRL = 8
+ PrivilegeWithdrawn = 9
+ AACompromise = 10
+)
+
+// Request represents an OCSP request. See RFC 6960.
+type Request struct {
+ HashAlgorithm crypto.Hash
+ IssuerNameHash []byte
+ IssuerKeyHash []byte
+ SerialNumber *big.Int
+}
+
+// Marshal marshals the OCSP request to ASN.1 DER encoded form.
+func (req *Request) Marshal() ([]byte, error) {
+ hashAlg := getOIDFromHashAlgorithm(req.HashAlgorithm)
+ if hashAlg == nil {
+ return nil, errors.New("Unknown hash algorithm")
+ }
+ return asn1.Marshal(ocspRequest{
+ tbsRequest{
+ Version: 0,
+ RequestList: []request{
+ {
+ Cert: certID{
+ pkix.AlgorithmIdentifier{
+ Algorithm: hashAlg,
+ Parameters: asn1.RawValue{Tag: 5 /* ASN.1 NULL */},
+ },
+ req.IssuerNameHash,
+ req.IssuerKeyHash,
+ req.SerialNumber,
+ },
+ },
+ },
+ },
+ })
+}
+
+// Response represents an OCSP response containing a single SingleResponse. See
+// RFC 6960.
+type Response struct {
+ // Status is one of {Good, Revoked, Unknown}
+ Status int
+ SerialNumber *big.Int
+ ProducedAt, ThisUpdate, NextUpdate, RevokedAt time.Time
+ RevocationReason int
+ Certificate *x509.Certificate
+ // TBSResponseData contains the raw bytes of the signed response. If
+ // Certificate is nil then this can be used to verify Signature.
+ TBSResponseData []byte
+ Signature []byte
+ SignatureAlgorithm x509.SignatureAlgorithm
+
+ // IssuerHash is the hash used to compute the IssuerNameHash and IssuerKeyHash.
+ // Valid values are crypto.SHA1, crypto.SHA256, crypto.SHA384, and crypto.SHA512.
+ // If zero, the default is crypto.SHA1.
+ IssuerHash crypto.Hash
+
+ // RawResponderName optionally contains the DER-encoded subject of the
+ // responder certificate. Exactly one of RawResponderName and
+ // ResponderKeyHash is set.
+ RawResponderName []byte
+ // ResponderKeyHash optionally contains the SHA-1 hash of the
+ // responder's public key. Exactly one of RawResponderName and
+ // ResponderKeyHash is set.
+ ResponderKeyHash []byte
+
+ // Extensions contains raw X.509 extensions from the singleExtensions field
+ // of the OCSP response. When parsing certificates, this can be used to
+ // extract non-critical extensions that are not parsed by this package. When
+ // marshaling OCSP responses, the Extensions field is ignored, see
+ // ExtraExtensions.
+ Extensions []pkix.Extension
+
+ // ExtraExtensions contains extensions to be copied, raw, into any marshaled
+ // OCSP response (in the singleExtensions field). Values override any
+ // extensions that would otherwise be produced based on the other fields. The
+ // ExtraExtensions field is not populated when parsing certificates, see
+ // Extensions.
+ ExtraExtensions []pkix.Extension
+}
+
+// These are pre-serialized error responses for the various non-success codes
+// defined by OCSP. The Unauthorized code in particular can be used by an OCSP
+// responder that supports only pre-signed responses as a response to requests
+// for certificates with unknown status. See RFC 5019.
+var (
+ MalformedRequestErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x01}
+ InternalErrorErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x02}
+ TryLaterErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x03}
+ SigRequredErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x05}
+ UnauthorizedErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x06}
+)
+
+// CheckSignatureFrom checks that the signature in resp is a valid signature
+// from issuer. This should only be used if resp.Certificate is nil. Otherwise,
+// the OCSP response contained an intermediate certificate that created the
+// signature. That signature is checked by ParseResponse and only
+// resp.Certificate remains to be validated.
+func (resp *Response) CheckSignatureFrom(issuer *x509.Certificate) error {
+ return issuer.CheckSignature(resp.SignatureAlgorithm, resp.TBSResponseData, resp.Signature)
+}
+
+// ParseError results from an invalid OCSP response.
+type ParseError string
+
+func (p ParseError) Error() string {
+ return string(p)
+}
+
+// ParseRequest parses an OCSP request in DER form. It only supports
+// requests for a single certificate. Signed requests are not supported.
+// If a request includes a signature, it will result in a ParseError.
+func ParseRequest(bytes []byte) (*Request, error) {
+ var req ocspRequest
+ rest, err := asn1.Unmarshal(bytes, &req)
+ if err != nil {
+ return nil, err
+ }
+ if len(rest) > 0 {
+ return nil, ParseError("trailing data in OCSP request")
+ }
+
+ if len(req.TBSRequest.RequestList) == 0 {
+ return nil, ParseError("OCSP request contains no request body")
+ }
+ innerRequest := req.TBSRequest.RequestList[0]
+
+ hashFunc := getHashAlgorithmFromOID(innerRequest.Cert.HashAlgorithm.Algorithm)
+ if hashFunc == crypto.Hash(0) {
+ return nil, ParseError("OCSP request uses unknown hash function")
+ }
+
+ return &Request{
+ HashAlgorithm: hashFunc,
+ IssuerNameHash: innerRequest.Cert.NameHash,
+ IssuerKeyHash: innerRequest.Cert.IssuerKeyHash,
+ SerialNumber: innerRequest.Cert.SerialNumber,
+ }, nil
+}
+
+// ParseResponse parses an OCSP response in DER form. It only supports
+// responses for a single certificate. If the response contains a certificate
+// then the signature over the response is checked. If issuer is not nil then
+// it will be used to validate the signature or embedded certificate.
+//
+// Invalid responses and parse failures will result in a ParseError.
+// Error responses will result in a ResponseError.
+func ParseResponse(bytes []byte, issuer *x509.Certificate) (*Response, error) {
+ return ParseResponseForCert(bytes, nil, issuer)
+}
+
+// ParseResponseForCert parses an OCSP response in DER form and searches for a
+// Response relating to cert. If such a Response is found and the OCSP response
+// contains a certificate then the signature over the response is checked. If
+// issuer is not nil then it will be used to validate the signature or embedded
+// certificate.
+//
+// Invalid responses and parse failures will result in a ParseError.
+// Error responses will result in a ResponseError.
+func ParseResponseForCert(bytes []byte, cert, issuer *x509.Certificate) (*Response, error) {
+ var resp responseASN1
+ rest, err := asn1.Unmarshal(bytes, &resp)
+ if err != nil {
+ return nil, err
+ }
+ if len(rest) > 0 {
+ return nil, ParseError("trailing data in OCSP response")
+ }
+
+ if status := ResponseStatus(resp.Status); status != Success {
+ return nil, ResponseError{status}
+ }
+
+ if !resp.Response.ResponseType.Equal(idPKIXOCSPBasic) {
+ return nil, ParseError("bad OCSP response type")
+ }
+
+ var basicResp basicResponse
+ rest, err = asn1.Unmarshal(resp.Response.Response, &basicResp)
+ if err != nil {
+ return nil, err
+ }
+
+ if len(basicResp.Certificates) > 1 {
+ return nil, ParseError("OCSP response contains bad number of certificates")
+ }
+
+ if n := len(basicResp.TBSResponseData.Responses); n == 0 || cert == nil && n > 1 {
+ return nil, ParseError("OCSP response contains bad number of responses")
+ }
+
+ var singleResp singleResponse
+ if cert == nil {
+ singleResp = basicResp.TBSResponseData.Responses[0]
+ } else {
+ match := false
+ for _, resp := range basicResp.TBSResponseData.Responses {
+ if cert.SerialNumber.Cmp(resp.CertID.SerialNumber) == 0 {
+ singleResp = resp
+ match = true
+ break
+ }
+ }
+ if !match {
+ return nil, ParseError("no response matching the supplied certificate")
+ }
+ }
+
+ ret := &Response{
+ TBSResponseData: basicResp.TBSResponseData.Raw,
+ Signature: basicResp.Signature.RightAlign(),
+ SignatureAlgorithm: getSignatureAlgorithmFromOID(basicResp.SignatureAlgorithm.Algorithm),
+ Extensions: singleResp.SingleExtensions,
+ SerialNumber: singleResp.CertID.SerialNumber,
+ ProducedAt: basicResp.TBSResponseData.ProducedAt,
+ ThisUpdate: singleResp.ThisUpdate,
+ NextUpdate: singleResp.NextUpdate,
+ }
+
+ // Handle the ResponderID CHOICE tag. ResponderID can be flattened into
+ // TBSResponseData once https://go-review.googlesource.com/34503 has been
+ // released.
+ rawResponderID := basicResp.TBSResponseData.RawResponderID
+ switch rawResponderID.Tag {
+ case 1: // Name
+ var rdn pkix.RDNSequence
+ if rest, err := asn1.Unmarshal(rawResponderID.Bytes, &rdn); err != nil || len(rest) != 0 {
+ return nil, ParseError("invalid responder name")
+ }
+ ret.RawResponderName = rawResponderID.Bytes
+ case 2: // KeyHash
+ if rest, err := asn1.Unmarshal(rawResponderID.Bytes, &ret.ResponderKeyHash); err != nil || len(rest) != 0 {
+ return nil, ParseError("invalid responder key hash")
+ }
+ default:
+ return nil, ParseError("invalid responder id tag")
+ }
+
+ if len(basicResp.Certificates) > 0 {
+ ret.Certificate, err = x509.ParseCertificate(basicResp.Certificates[0].FullBytes)
+ if err != nil {
+ return nil, err
+ }
+
+ if err := ret.CheckSignatureFrom(ret.Certificate); err != nil {
+ return nil, ParseError("bad signature on embedded certificate: " + err.Error())
+ }
+
+ if issuer != nil {
+ if err := issuer.CheckSignature(ret.Certificate.SignatureAlgorithm, ret.Certificate.RawTBSCertificate, ret.Certificate.Signature); err != nil {
+ return nil, ParseError("bad OCSP signature: " + err.Error())
+ }
+ }
+ } else if issuer != nil {
+ if err := ret.CheckSignatureFrom(issuer); err != nil {
+ return nil, ParseError("bad OCSP signature: " + err.Error())
+ }
+ }
+
+ for _, ext := range singleResp.SingleExtensions {
+ if ext.Critical {
+ return nil, ParseError("unsupported critical extension")
+ }
+ }
+
+ for h, oid := range hashOIDs {
+ if singleResp.CertID.HashAlgorithm.Algorithm.Equal(oid) {
+ ret.IssuerHash = h
+ break
+ }
+ }
+ if ret.IssuerHash == 0 {
+ return nil, ParseError("unsupported issuer hash algorithm")
+ }
+
+ switch {
+ case bool(singleResp.Good):
+ ret.Status = Good
+ case bool(singleResp.Unknown):
+ ret.Status = Unknown
+ default:
+ ret.Status = Revoked
+ ret.RevokedAt = singleResp.Revoked.RevocationTime
+ ret.RevocationReason = int(singleResp.Revoked.Reason)
+ }
+
+ return ret, nil
+}
+
+// RequestOptions contains options for constructing OCSP requests.
+type RequestOptions struct {
+ // Hash contains the hash function that should be used when
+ // constructing the OCSP request. If zero, SHA-1 will be used.
+ Hash crypto.Hash
+}
+
+func (opts *RequestOptions) hash() crypto.Hash {
+ if opts == nil || opts.Hash == 0 {
+ // SHA-1 is nearly universally used in OCSP.
+ return crypto.SHA1
+ }
+ return opts.Hash
+}
+
+// CreateRequest returns a DER-encoded, OCSP request for the status of cert. If
+// opts is nil then sensible defaults are used.
+func CreateRequest(cert, issuer *x509.Certificate, opts *RequestOptions) ([]byte, error) {
+ hashFunc := opts.hash()
+
+ // OCSP seems to be the only place where these raw hash identifiers are
+ // used. I took the following from
+ // http://msdn.microsoft.com/en-us/library/ff635603.aspx
+ _, ok := hashOIDs[hashFunc]
+ if !ok {
+ return nil, x509.ErrUnsupportedAlgorithm
+ }
+
+ if !hashFunc.Available() {
+ return nil, x509.ErrUnsupportedAlgorithm
+ }
+ h := opts.hash().New()
+
+ var publicKeyInfo struct {
+ Algorithm pkix.AlgorithmIdentifier
+ PublicKey asn1.BitString
+ }
+ if _, err := asn1.Unmarshal(issuer.RawSubjectPublicKeyInfo, &publicKeyInfo); err != nil {
+ return nil, err
+ }
+
+ h.Write(publicKeyInfo.PublicKey.RightAlign())
+ issuerKeyHash := h.Sum(nil)
+
+ h.Reset()
+ h.Write(issuer.RawSubject)
+ issuerNameHash := h.Sum(nil)
+
+ req := &Request{
+ HashAlgorithm: hashFunc,
+ IssuerNameHash: issuerNameHash,
+ IssuerKeyHash: issuerKeyHash,
+ SerialNumber: cert.SerialNumber,
+ }
+ return req.Marshal()
+}
+
+// CreateResponse returns a DER-encoded OCSP response with the specified contents.
+// The fields in the response are populated as follows:
+//
+// The responder cert is used to populate the responder's name field, and the
+// certificate itself is provided alongside the OCSP response signature.
+//
+// The issuer cert is used to puplate the IssuerNameHash and IssuerKeyHash fields.
+//
+// The template is used to populate the SerialNumber, Status, RevokedAt,
+// RevocationReason, ThisUpdate, and NextUpdate fields.
+//
+// If template.IssuerHash is not set, SHA1 will be used.
+//
+// The ProducedAt date is automatically set to the current date, to the nearest minute.
+func CreateResponse(issuer, responderCert *x509.Certificate, template Response, priv crypto.Signer) ([]byte, error) {
+ var publicKeyInfo struct {
+ Algorithm pkix.AlgorithmIdentifier
+ PublicKey asn1.BitString
+ }
+ if _, err := asn1.Unmarshal(issuer.RawSubjectPublicKeyInfo, &publicKeyInfo); err != nil {
+ return nil, err
+ }
+
+ if template.IssuerHash == 0 {
+ template.IssuerHash = crypto.SHA1
+ }
+ hashOID := getOIDFromHashAlgorithm(template.IssuerHash)
+ if hashOID == nil {
+ return nil, errors.New("unsupported issuer hash algorithm")
+ }
+
+ if !template.IssuerHash.Available() {
+ return nil, fmt.Errorf("issuer hash algorithm %v not linked into binary", template.IssuerHash)
+ }
+ h := template.IssuerHash.New()
+ h.Write(publicKeyInfo.PublicKey.RightAlign())
+ issuerKeyHash := h.Sum(nil)
+
+ h.Reset()
+ h.Write(issuer.RawSubject)
+ issuerNameHash := h.Sum(nil)
+
+ innerResponse := singleResponse{
+ CertID: certID{
+ HashAlgorithm: pkix.AlgorithmIdentifier{
+ Algorithm: hashOID,
+ Parameters: asn1.RawValue{Tag: 5 /* ASN.1 NULL */},
+ },
+ NameHash: issuerNameHash,
+ IssuerKeyHash: issuerKeyHash,
+ SerialNumber: template.SerialNumber,
+ },
+ ThisUpdate: template.ThisUpdate.UTC(),
+ NextUpdate: template.NextUpdate.UTC(),
+ SingleExtensions: template.ExtraExtensions,
+ }
+
+ switch template.Status {
+ case Good:
+ innerResponse.Good = true
+ case Unknown:
+ innerResponse.Unknown = true
+ case Revoked:
+ innerResponse.Revoked = revokedInfo{
+ RevocationTime: template.RevokedAt.UTC(),
+ Reason: asn1.Enumerated(template.RevocationReason),
+ }
+ }
+
+ rawResponderID := asn1.RawValue{
+ Class: 2, // context-specific
+ Tag: 1, // Name (explicit tag)
+ IsCompound: true,
+ Bytes: responderCert.RawSubject,
+ }
+ tbsResponseData := responseData{
+ Version: 0,
+ RawResponderID: rawResponderID,
+ ProducedAt: time.Now().Truncate(time.Minute).UTC(),
+ Responses: []singleResponse{innerResponse},
+ }
+
+ tbsResponseDataDER, err := asn1.Marshal(tbsResponseData)
+ if err != nil {
+ return nil, err
+ }
+
+ hashFunc, signatureAlgorithm, err := signingParamsForPublicKey(priv.Public(), template.SignatureAlgorithm)
+ if err != nil {
+ return nil, err
+ }
+
+ responseHash := hashFunc.New()
+ responseHash.Write(tbsResponseDataDER)
+ signature, err := priv.Sign(rand.Reader, responseHash.Sum(nil), hashFunc)
+ if err != nil {
+ return nil, err
+ }
+
+ response := basicResponse{
+ TBSResponseData: tbsResponseData,
+ SignatureAlgorithm: signatureAlgorithm,
+ Signature: asn1.BitString{
+ Bytes: signature,
+ BitLength: 8 * len(signature),
+ },
+ }
+ if template.Certificate != nil {
+ response.Certificates = []asn1.RawValue{
+ asn1.RawValue{FullBytes: template.Certificate.Raw},
+ }
+ }
+ responseDER, err := asn1.Marshal(response)
+ if err != nil {
+ return nil, err
+ }
+
+ return asn1.Marshal(responseASN1{
+ Status: asn1.Enumerated(Success),
+ Response: responseBytes{
+ ResponseType: idPKIXOCSPBasic,
+ Response: responseDER,
+ },
+ })
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ocsp/ocsp_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ocsp/ocsp_test.go
new file mode 100644
index 000000000..1fadfec4c
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ocsp/ocsp_test.go
@@ -0,0 +1,875 @@
+// Copyright 2013 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.
+
+// +build go1.7
+
+package ocsp
+
+import (
+ "bytes"
+ "crypto"
+ "crypto/sha1"
+ "crypto/x509"
+ "crypto/x509/pkix"
+ "encoding/asn1"
+ "encoding/hex"
+ "math/big"
+ "reflect"
+ "testing"
+ "time"
+)
+
+func TestOCSPDecode(t *testing.T) {
+ responseBytes, _ := hex.DecodeString(ocspResponseHex)
+ resp, err := ParseResponse(responseBytes, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ responderCert, _ := hex.DecodeString(startComResponderCertHex)
+ responder, err := x509.ParseCertificate(responderCert)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ expected := Response{
+ Status: Good,
+ SerialNumber: big.NewInt(0x1d0fa),
+ RevocationReason: Unspecified,
+ ThisUpdate: time.Date(2010, 7, 7, 15, 1, 5, 0, time.UTC),
+ NextUpdate: time.Date(2010, 7, 7, 18, 35, 17, 0, time.UTC),
+ RawResponderName: responder.RawSubject,
+ }
+
+ if !reflect.DeepEqual(resp.ThisUpdate, expected.ThisUpdate) {
+ t.Errorf("resp.ThisUpdate: got %v, want %v", resp.ThisUpdate, expected.ThisUpdate)
+ }
+
+ if !reflect.DeepEqual(resp.NextUpdate, expected.NextUpdate) {
+ t.Errorf("resp.NextUpdate: got %v, want %v", resp.NextUpdate, expected.NextUpdate)
+ }
+
+ if resp.Status != expected.Status {
+ t.Errorf("resp.Status: got %d, want %d", resp.Status, expected.Status)
+ }
+
+ if resp.SerialNumber.Cmp(expected.SerialNumber) != 0 {
+ t.Errorf("resp.SerialNumber: got %x, want %x", resp.SerialNumber, expected.SerialNumber)
+ }
+
+ if resp.RevocationReason != expected.RevocationReason {
+ t.Errorf("resp.RevocationReason: got %d, want %d", resp.RevocationReason, expected.RevocationReason)
+ }
+
+ if !bytes.Equal(resp.RawResponderName, expected.RawResponderName) {
+ t.Errorf("resp.RawResponderName: got %x, want %x", resp.RawResponderName, expected.RawResponderName)
+ }
+
+ if !bytes.Equal(resp.ResponderKeyHash, expected.ResponderKeyHash) {
+ t.Errorf("resp.ResponderKeyHash: got %x, want %x", resp.ResponderKeyHash, expected.ResponderKeyHash)
+ }
+}
+
+func TestOCSPDecodeWithoutCert(t *testing.T) {
+ responseBytes, _ := hex.DecodeString(ocspResponseWithoutCertHex)
+ _, err := ParseResponse(responseBytes, nil)
+ if err != nil {
+ t.Error(err)
+ }
+}
+
+func TestOCSPDecodeWithExtensions(t *testing.T) {
+ responseBytes, _ := hex.DecodeString(ocspResponseWithCriticalExtensionHex)
+ _, err := ParseResponse(responseBytes, nil)
+ if err == nil {
+ t.Error(err)
+ }
+
+ responseBytes, _ = hex.DecodeString(ocspResponseWithExtensionHex)
+ response, err := ParseResponse(responseBytes, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if len(response.Extensions) != 1 {
+ t.Errorf("len(response.Extensions): got %v, want %v", len(response.Extensions), 1)
+ }
+
+ extensionBytes := response.Extensions[0].Value
+ expectedBytes, _ := hex.DecodeString(ocspExtensionValueHex)
+ if !bytes.Equal(extensionBytes, expectedBytes) {
+ t.Errorf("response.Extensions[0]: got %x, want %x", extensionBytes, expectedBytes)
+ }
+}
+
+func TestOCSPSignature(t *testing.T) {
+ issuerCert, _ := hex.DecodeString(startComHex)
+ issuer, err := x509.ParseCertificate(issuerCert)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ response, _ := hex.DecodeString(ocspResponseHex)
+ if _, err := ParseResponse(response, issuer); err != nil {
+ t.Error(err)
+ }
+}
+
+func TestOCSPRequest(t *testing.T) {
+ leafCert, _ := hex.DecodeString(leafCertHex)
+ cert, err := x509.ParseCertificate(leafCert)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ issuerCert, _ := hex.DecodeString(issuerCertHex)
+ issuer, err := x509.ParseCertificate(issuerCert)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ request, err := CreateRequest(cert, issuer, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ expectedBytes, _ := hex.DecodeString(ocspRequestHex)
+ if !bytes.Equal(request, expectedBytes) {
+ t.Errorf("request: got %x, wanted %x", request, expectedBytes)
+ }
+
+ decodedRequest, err := ParseRequest(expectedBytes)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if decodedRequest.HashAlgorithm != crypto.SHA1 {
+ t.Errorf("request.HashAlgorithm: got %v, want %v", decodedRequest.HashAlgorithm, crypto.SHA1)
+ }
+
+ var publicKeyInfo struct {
+ Algorithm pkix.AlgorithmIdentifier
+ PublicKey asn1.BitString
+ }
+ _, err = asn1.Unmarshal(issuer.RawSubjectPublicKeyInfo, &publicKeyInfo)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ h := sha1.New()
+ h.Write(publicKeyInfo.PublicKey.RightAlign())
+ issuerKeyHash := h.Sum(nil)
+
+ h.Reset()
+ h.Write(issuer.RawSubject)
+ issuerNameHash := h.Sum(nil)
+
+ if got := decodedRequest.IssuerKeyHash; !bytes.Equal(got, issuerKeyHash) {
+ t.Errorf("request.IssuerKeyHash: got %x, want %x", got, issuerKeyHash)
+ }
+
+ if got := decodedRequest.IssuerNameHash; !bytes.Equal(got, issuerNameHash) {
+ t.Errorf("request.IssuerKeyHash: got %x, want %x", got, issuerNameHash)
+ }
+
+ if got := decodedRequest.SerialNumber; got.Cmp(cert.SerialNumber) != 0 {
+ t.Errorf("request.SerialNumber: got %x, want %x", got, cert.SerialNumber)
+ }
+
+ marshaledRequest, err := decodedRequest.Marshal()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if bytes.Compare(expectedBytes, marshaledRequest) != 0 {
+ t.Errorf(
+ "Marshaled request doesn't match expected: wanted %x, got %x",
+ expectedBytes,
+ marshaledRequest,
+ )
+ }
+}
+
+func TestOCSPResponse(t *testing.T) {
+ leafCert, _ := hex.DecodeString(leafCertHex)
+ leaf, err := x509.ParseCertificate(leafCert)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ issuerCert, _ := hex.DecodeString(issuerCertHex)
+ issuer, err := x509.ParseCertificate(issuerCert)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ responderCert, _ := hex.DecodeString(responderCertHex)
+ responder, err := x509.ParseCertificate(responderCert)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ responderPrivateKeyDER, _ := hex.DecodeString(responderPrivateKeyHex)
+ responderPrivateKey, err := x509.ParsePKCS1PrivateKey(responderPrivateKeyDER)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ extensionBytes, _ := hex.DecodeString(ocspExtensionValueHex)
+ extensions := []pkix.Extension{
+ pkix.Extension{
+ Id: ocspExtensionOID,
+ Critical: false,
+ Value: extensionBytes,
+ },
+ }
+
+ thisUpdate := time.Date(2010, 7, 7, 15, 1, 5, 0, time.UTC)
+ nextUpdate := time.Date(2010, 7, 7, 18, 35, 17, 0, time.UTC)
+ template := Response{
+ Status: Revoked,
+ SerialNumber: leaf.SerialNumber,
+ ThisUpdate: thisUpdate,
+ NextUpdate: nextUpdate,
+ RevokedAt: thisUpdate,
+ RevocationReason: KeyCompromise,
+ Certificate: responder,
+ ExtraExtensions: extensions,
+ }
+
+ template.IssuerHash = crypto.MD5
+ _, err = CreateResponse(issuer, responder, template, responderPrivateKey)
+ if err == nil {
+ t.Fatal("CreateResponse didn't fail with non-valid template.IssuerHash value crypto.MD5")
+ }
+
+ testCases := []struct {
+ name string
+ issuerHash crypto.Hash
+ }{
+ {"Zero value", 0},
+ {"crypto.SHA1", crypto.SHA1},
+ {"crypto.SHA256", crypto.SHA256},
+ {"crypto.SHA384", crypto.SHA384},
+ {"crypto.SHA512", crypto.SHA512},
+ }
+ for _, tc := range testCases {
+ t.Run(tc.name, func(t *testing.T) {
+ template.IssuerHash = tc.issuerHash
+ responseBytes, err := CreateResponse(issuer, responder, template, responderPrivateKey)
+ if err != nil {
+ t.Fatalf("CreateResponse failed: %s", err)
+ }
+
+ resp, err := ParseResponse(responseBytes, nil)
+ if err != nil {
+ t.Fatalf("ParseResponse failed: %s", err)
+ }
+
+ if !reflect.DeepEqual(resp.ThisUpdate, template.ThisUpdate) {
+ t.Errorf("resp.ThisUpdate: got %v, want %v", resp.ThisUpdate, template.ThisUpdate)
+ }
+
+ if !reflect.DeepEqual(resp.NextUpdate, template.NextUpdate) {
+ t.Errorf("resp.NextUpdate: got %v, want %v", resp.NextUpdate, template.NextUpdate)
+ }
+
+ if !reflect.DeepEqual(resp.RevokedAt, template.RevokedAt) {
+ t.Errorf("resp.RevokedAt: got %v, want %v", resp.RevokedAt, template.RevokedAt)
+ }
+
+ if !reflect.DeepEqual(resp.Extensions, template.ExtraExtensions) {
+ t.Errorf("resp.Extensions: got %v, want %v", resp.Extensions, template.ExtraExtensions)
+ }
+
+ delay := time.Since(resp.ProducedAt)
+ if delay < -time.Hour || delay > time.Hour {
+ t.Errorf("resp.ProducedAt: got %s, want close to current time (%s)", resp.ProducedAt, time.Now())
+ }
+
+ if resp.Status != template.Status {
+ t.Errorf("resp.Status: got %d, want %d", resp.Status, template.Status)
+ }
+
+ if resp.SerialNumber.Cmp(template.SerialNumber) != 0 {
+ t.Errorf("resp.SerialNumber: got %x, want %x", resp.SerialNumber, template.SerialNumber)
+ }
+
+ if resp.RevocationReason != template.RevocationReason {
+ t.Errorf("resp.RevocationReason: got %d, want %d", resp.RevocationReason, template.RevocationReason)
+ }
+
+ expectedHash := tc.issuerHash
+ if tc.issuerHash == 0 {
+ expectedHash = crypto.SHA1
+ }
+
+ if resp.IssuerHash != expectedHash {
+ t.Errorf("resp.IssuerHash: got %d, want %d", resp.IssuerHash, expectedHash)
+ }
+ })
+ }
+}
+
+func TestErrorResponse(t *testing.T) {
+ responseBytes, _ := hex.DecodeString(errorResponseHex)
+ _, err := ParseResponse(responseBytes, nil)
+
+ respErr, ok := err.(ResponseError)
+ if !ok {
+ t.Fatalf("expected ResponseError from ParseResponse but got %#v", err)
+ }
+ if respErr.Status != Malformed {
+ t.Fatalf("expected Malformed status from ParseResponse but got %d", respErr.Status)
+ }
+}
+
+func TestOCSPDecodeMultiResponse(t *testing.T) {
+ inclCert, _ := hex.DecodeString(ocspMultiResponseCertHex)
+ cert, err := x509.ParseCertificate(inclCert)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ responseBytes, _ := hex.DecodeString(ocspMultiResponseHex)
+ resp, err := ParseResponseForCert(responseBytes, cert, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if resp.SerialNumber.Cmp(cert.SerialNumber) != 0 {
+ t.Errorf("resp.SerialNumber: got %x, want %x", resp.SerialNumber, cert.SerialNumber)
+ }
+}
+
+func TestOCSPDecodeMultiResponseWithoutMatchingCert(t *testing.T) {
+ wrongCert, _ := hex.DecodeString(startComHex)
+ cert, err := x509.ParseCertificate(wrongCert)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ responseBytes, _ := hex.DecodeString(ocspMultiResponseHex)
+ _, err = ParseResponseForCert(responseBytes, cert, nil)
+ want := ParseError("no response matching the supplied certificate")
+ if err != want {
+ t.Errorf("err: got %q, want %q", err, want)
+ }
+}
+
+// This OCSP response was taken from Thawte's public OCSP responder.
+// To recreate:
+// $ openssl s_client -tls1 -showcerts -servername www.google.com -connect www.google.com:443
+// Copy and paste the first certificate into /tmp/cert.crt and the second into
+// /tmp/intermediate.crt
+// $ openssl ocsp -issuer /tmp/intermediate.crt -cert /tmp/cert.crt -url http://ocsp.thawte.com -resp_text -respout /tmp/ocsp.der
+// Then hex encode the result:
+// $ python -c 'print file("/tmp/ocsp.der", "r").read().encode("hex")'
+
+const ocspResponseHex = "308206bc0a0100a08206b5308206b106092b0601050507300101048206a23082069e3081" +
+ "c9a14e304c310b300906035504061302494c31163014060355040a130d5374617274436f" +
+ "6d204c74642e312530230603550403131c5374617274436f6d20436c6173732031204f43" +
+ "5350205369676e6572180f32303130303730373137333531375a30663064303c30090605" +
+ "2b0e03021a050004146568874f40750f016a3475625e1f5c93e5a26d580414eb4234d098" +
+ "b0ab9ff41b6b08f7cc642eef0e2c45020301d0fa8000180f323031303037303731353031" +
+ "30355aa011180f32303130303730373138333531375a300d06092a864886f70d01010505" +
+ "000382010100ab557ff070d1d7cebbb5f0ec91a15c3fed22eb2e1b8244f1b84545f013a4" +
+ "fb46214c5e3fbfbebb8a56acc2b9db19f68fd3c3201046b3824d5ba689f99864328710cb" +
+ "467195eb37d84f539e49f859316b32964dc3e47e36814ce94d6c56dd02733b1d0802f7ff" +
+ "4eebdbbd2927dcf580f16cbc290f91e81b53cb365e7223f1d6e20a88ea064104875e0145" +
+ "672b20fc14829d51ca122f5f5d77d3ad6c83889c55c7dc43680ba2fe3cef8b05dbcabdc0" +
+ "d3e09aaf9725597f8c858c2fa38c0d6aed2e6318194420dd1a1137445d13e1c97ab47896" +
+ "17a4e08925f46f867b72e3a4dc1f08cb870b2b0717f7207faa0ac512e628a029aba7457a" +
+ "e63dcf3281e2162d9349a08204ba308204b6308204b23082039aa003020102020101300d" +
+ "06092a864886f70d010105050030818c310b300906035504061302494c31163014060355" +
+ "040a130d5374617274436f6d204c74642e312b3029060355040b13225365637572652044" +
+ "69676974616c204365727469666963617465205369676e696e6731383036060355040313" +
+ "2f5374617274436f6d20436c6173732031205072696d61727920496e7465726d65646961" +
+ "746520536572766572204341301e170d3037313032353030323330365a170d3132313032" +
+ "333030323330365a304c310b300906035504061302494c31163014060355040a130d5374" +
+ "617274436f6d204c74642e312530230603550403131c5374617274436f6d20436c617373" +
+ "2031204f435350205369676e657230820122300d06092a864886f70d0101010500038201" +
+ "0f003082010a0282010100b9561b4c45318717178084e96e178df2255e18ed8d8ecc7c2b" +
+ "7b51a6c1c2e6bf0aa3603066f132fe10ae97b50e99fa24b83fc53dd2777496387d14e1c3" +
+ "a9b6a4933e2ac12413d085570a95b8147414a0bc007c7bcf222446ef7f1a156d7ea1c577" +
+ "fc5f0facdfd42eb0f5974990cb2f5cefebceef4d1bdc7ae5c1075c5a99a93171f2b0845b" +
+ "4ff0864e973fcfe32f9d7511ff87a3e943410c90a4493a306b6944359340a9ca96f02b66" +
+ "ce67f028df2980a6aaee8d5d5d452b8b0eb93f923cc1e23fcccbdbe7ffcb114d08fa7a6a" +
+ "3c404f825d1a0e715935cf623a8c7b59670014ed0622f6089a9447a7a19010f7fe58f841" +
+ "29a2765ea367824d1c3bb2fda308530203010001a382015c30820158300c0603551d1301" +
+ "01ff04023000300b0603551d0f0404030203a8301e0603551d250417301506082b060105" +
+ "0507030906092b0601050507300105301d0603551d0e0416041445e0a36695414c5dd449" +
+ "bc00e33cdcdbd2343e173081a80603551d230481a030819d8014eb4234d098b0ab9ff41b" +
+ "6b08f7cc642eef0e2c45a18181a47f307d310b300906035504061302494c311630140603" +
+ "55040a130d5374617274436f6d204c74642e312b3029060355040b132253656375726520" +
+ "4469676974616c204365727469666963617465205369676e696e67312930270603550403" +
+ "13205374617274436f6d2043657274696669636174696f6e20417574686f726974798201" +
+ "0a30230603551d12041c301a8618687474703a2f2f7777772e737461727473736c2e636f" +
+ "6d2f302c06096086480186f842010d041f161d5374617274436f6d205265766f63617469" +
+ "6f6e20417574686f72697479300d06092a864886f70d01010505000382010100182d2215" +
+ "8f0fc0291324fa8574c49bb8ff2835085adcbf7b7fc4191c397ab6951328253fffe1e5ec" +
+ "2a7da0d50fca1a404e6968481366939e666c0a6209073eca57973e2fefa9ed1718e8176f" +
+ "1d85527ff522c08db702e3b2b180f1cbff05d98128252cf0f450f7dd2772f4188047f19d" +
+ "c85317366f94bc52d60f453a550af58e308aaab00ced33040b62bf37f5b1ab2a4f7f0f80" +
+ "f763bf4d707bc8841d7ad9385ee2a4244469260b6f2bf085977af9074796048ecc2f9d48" +
+ "a1d24ce16e41a9941568fec5b42771e118f16c106a54ccc339a4b02166445a167902e75e" +
+ "6d8620b0825dcd18a069b90fd851d10fa8effd409deec02860d26d8d833f304b10669b42"
+
+const startComResponderCertHex = "308204b23082039aa003020102020101300d06092a864886f70d010105050030818c310b" +
+ "300906035504061302494c31163014060355040a130d5374617274436f6d204c74642e31" +
+ "2b3029060355040b1322536563757265204469676974616c204365727469666963617465" +
+ "205369676e696e67313830360603550403132f5374617274436f6d20436c617373203120" +
+ "5072696d61727920496e7465726d65646961746520536572766572204341301e170d3037" +
+ "313032353030323330365a170d3132313032333030323330365a304c310b300906035504" +
+ "061302494c31163014060355040a130d5374617274436f6d204c74642e31253023060355" +
+ "0403131c5374617274436f6d20436c6173732031204f435350205369676e657230820122" +
+ "300d06092a864886f70d01010105000382010f003082010a0282010100b9561b4c453187" +
+ "17178084e96e178df2255e18ed8d8ecc7c2b7b51a6c1c2e6bf0aa3603066f132fe10ae97" +
+ "b50e99fa24b83fc53dd2777496387d14e1c3a9b6a4933e2ac12413d085570a95b8147414" +
+ "a0bc007c7bcf222446ef7f1a156d7ea1c577fc5f0facdfd42eb0f5974990cb2f5cefebce" +
+ "ef4d1bdc7ae5c1075c5a99a93171f2b0845b4ff0864e973fcfe32f9d7511ff87a3e94341" +
+ "0c90a4493a306b6944359340a9ca96f02b66ce67f028df2980a6aaee8d5d5d452b8b0eb9" +
+ "3f923cc1e23fcccbdbe7ffcb114d08fa7a6a3c404f825d1a0e715935cf623a8c7b596700" +
+ "14ed0622f6089a9447a7a19010f7fe58f84129a2765ea367824d1c3bb2fda30853020301" +
+ "0001a382015c30820158300c0603551d130101ff04023000300b0603551d0f0404030203" +
+ "a8301e0603551d250417301506082b0601050507030906092b0601050507300105301d06" +
+ "03551d0e0416041445e0a36695414c5dd449bc00e33cdcdbd2343e173081a80603551d23" +
+ "0481a030819d8014eb4234d098b0ab9ff41b6b08f7cc642eef0e2c45a18181a47f307d31" +
+ "0b300906035504061302494c31163014060355040a130d5374617274436f6d204c74642e" +
+ "312b3029060355040b1322536563757265204469676974616c2043657274696669636174" +
+ "65205369676e696e6731293027060355040313205374617274436f6d2043657274696669" +
+ "636174696f6e20417574686f7269747982010a30230603551d12041c301a861868747470" +
+ "3a2f2f7777772e737461727473736c2e636f6d2f302c06096086480186f842010d041f16" +
+ "1d5374617274436f6d205265766f636174696f6e20417574686f72697479300d06092a86" +
+ "4886f70d01010505000382010100182d22158f0fc0291324fa8574c49bb8ff2835085adc" +
+ "bf7b7fc4191c397ab6951328253fffe1e5ec2a7da0d50fca1a404e6968481366939e666c" +
+ "0a6209073eca57973e2fefa9ed1718e8176f1d85527ff522c08db702e3b2b180f1cbff05" +
+ "d98128252cf0f450f7dd2772f4188047f19dc85317366f94bc52d60f453a550af58e308a" +
+ "aab00ced33040b62bf37f5b1ab2a4f7f0f80f763bf4d707bc8841d7ad9385ee2a4244469" +
+ "260b6f2bf085977af9074796048ecc2f9d48a1d24ce16e41a9941568fec5b42771e118f1" +
+ "6c106a54ccc339a4b02166445a167902e75e6d8620b0825dcd18a069b90fd851d10fa8ef" +
+ "fd409deec02860d26d8d833f304b10669b42"
+
+const startComHex = "308206343082041ca003020102020118300d06092a864886f70d0101050500307d310b30" +
+ "0906035504061302494c31163014060355040a130d5374617274436f6d204c74642e312b" +
+ "3029060355040b1322536563757265204469676974616c20436572746966696361746520" +
+ "5369676e696e6731293027060355040313205374617274436f6d20436572746966696361" +
+ "74696f6e20417574686f72697479301e170d3037313032343230353431375a170d313731" +
+ "3032343230353431375a30818c310b300906035504061302494c31163014060355040a13" +
+ "0d5374617274436f6d204c74642e312b3029060355040b13225365637572652044696769" +
+ "74616c204365727469666963617465205369676e696e67313830360603550403132f5374" +
+ "617274436f6d20436c6173732031205072696d61727920496e7465726d65646961746520" +
+ "53657276657220434130820122300d06092a864886f70d01010105000382010f00308201" +
+ "0a0282010100b689c6acef09527807ac9263d0f44418188480561f91aee187fa3250b4d3" +
+ "4706f0e6075f700e10f71dc0ce103634855a0f92ac83c6ac58523fba38e8fce7a724e240" +
+ "a60876c0926e9e2a6d4d3f6e61200adb59ded27d63b33e46fefa215118d7cd30a6ed076e" +
+ "3b7087b4f9faebee823c056f92f7a4dc0a301e9373fe07cad75f809d225852ae06da8b87" +
+ "2369b0e42ad8ea83d2bdf371db705a280faf5a387045123f304dcd3baf17e50fcba0a95d" +
+ "48aab16150cb34cd3c5cc30be810c08c9bf0030362feb26c3e720eee1c432ac9480e5739" +
+ "c43121c810c12c87fe5495521f523c31129b7fe7c0a0a559d5e28f3ef0d5a8e1d77031a9" +
+ "c4b3cfaf6d532f06f4a70203010001a38201ad308201a9300f0603551d130101ff040530" +
+ "030101ff300e0603551d0f0101ff040403020106301d0603551d0e04160414eb4234d098" +
+ "b0ab9ff41b6b08f7cc642eef0e2c45301f0603551d230418301680144e0bef1aa4405ba5" +
+ "17698730ca346843d041aef2306606082b06010505070101045a3058302706082b060105" +
+ "05073001861b687474703a2f2f6f6373702e737461727473736c2e636f6d2f6361302d06" +
+ "082b060105050730028621687474703a2f2f7777772e737461727473736c2e636f6d2f73" +
+ "667363612e637274305b0603551d1f045430523027a025a0238621687474703a2f2f7777" +
+ "772e737461727473736c2e636f6d2f73667363612e63726c3027a025a023862168747470" +
+ "3a2f2f63726c2e737461727473736c2e636f6d2f73667363612e63726c3081800603551d" +
+ "20047930773075060b2b0601040181b5370102013066302e06082b060105050702011622" +
+ "687474703a2f2f7777772e737461727473736c2e636f6d2f706f6c6963792e7064663034" +
+ "06082b060105050702011628687474703a2f2f7777772e737461727473736c2e636f6d2f" +
+ "696e7465726d6564696174652e706466300d06092a864886f70d01010505000382020100" +
+ "2109493ea5886ee00b8b48da314d8ff75657a2e1d36257e9b556f38545753be5501f048b" +
+ "e6a05a3ee700ae85d0fbff200364cbad02e1c69172f8a34dd6dee8cc3fa18aa2e37c37a7" +
+ "c64f8f35d6f4d66e067bdd21d9cf56ffcb302249fe8904f385e5aaf1e71fe875904dddf9" +
+ "46f74234f745580c110d84b0c6da5d3ef9019ee7e1da5595be741c7bfc4d144fac7e5547" +
+ "7d7bf4a50d491e95e8f712c1ccff76a62547d0f37535be97b75816ebaa5c786fec5330af" +
+ "ea044dcca902e3f0b60412f630b1113d904e5664d7dc3c435f7339ef4baf87ebf6fe6888" +
+ "4472ead207c669b0c1a18bef1749d761b145485f3b2021e95bb2ccf4d7e931f50b15613b" +
+ "7a94e3ebd9bc7f94ae6ae3626296a8647cb887f399327e92a252bebbf865cfc9f230fc8b" +
+ "c1c2a696d75f89e15c3480f58f47072fb491bfb1a27e5f4b5ad05b9f248605515a690365" +
+ "434971c5e06f94346bf61bd8a9b04c7e53eb8f48dfca33b548fa364a1a53a6330cd089cd" +
+ "4915cd89313c90c072d7654b52358a461144b93d8e2865a63e799e5c084429adb035112e" +
+ "214eb8d2e7103e5d8483b3c3c2e4d2c6fd094b7409ddf1b3d3193e800da20b19f038e7c5" +
+ "c2afe223db61e29d5c6e2089492e236ab262c145b49faf8ba7f1223bf87de290d07a19fb" +
+ "4a4ce3d27d5f4a8303ed27d6239e6b8db459a2d9ef6c8229dd75193c3f4c108defbb7527" +
+ "d2ae83a7a8ce5ba7"
+
+const ocspResponseWithoutCertHex = "308201d40a0100a08201cd308201c906092b0601050507300101048201ba3082" +
+ "01b630819fa2160414884451ff502a695e2d88f421bad90cf2cecbea7c180f3230313330" +
+ "3631383037323434335a30743072304a300906052b0e03021a0500041448b60d38238df8" +
+ "456e4ee5843ea394111802979f0414884451ff502a695e2d88f421bad90cf2cecbea7c02" +
+ "1100f78b13b946fc9635d8ab49de9d2148218000180f3230313330363138303732343433" +
+ "5aa011180f32303133303632323037323434335a300d06092a864886f70d010105050003" +
+ "82010100103e18b3d297a5e7a6c07a4fc52ac46a15c0eba96f3be17f0ffe84de5b8c8e05" +
+ "5a8f577586a849dc4abd6440eb6fedde4622451e2823c1cbf3558b4e8184959c9fe96eff" +
+ "8bc5f95866c58c6d087519faabfdae37e11d9874f1bc0db292208f645dd848185e4dd38b" +
+ "6a8547dfa7b74d514a8470015719064d35476b95bebb03d4d2845c5ca15202d2784878f2" +
+ "0f904c24f09736f044609e9c271381713400e563023d212db422236440c6f377bbf24b2b" +
+ "9e7dec8698e36a8df68b7592ad3489fb2937afb90eb85d2aa96b81c94c25057dbd4759d9" +
+ "20a1a65c7f0b6427a224b3c98edd96b9b61f706099951188b0289555ad30a216fb774651" +
+ "5a35fca2e054dfa8"
+
+// PKIX nonce extension
+var ocspExtensionOID = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 48, 1, 2}
+var ocspExtensionValueHex = "0403000000"
+
+const ocspResponseWithCriticalExtensionHex = "308204fe0a0100a08204f7308204f306092b0601050507300101048204e4308204e03081" +
+ "dba003020100a11b3019311730150603550403130e4f43535020526573706f6e64657218" +
+ "0f32303136303130343137303130305a3081a53081a23049300906052b0e03021a050004" +
+ "14c0fe0278fc99188891b3f212e9c7e1b21ab7bfc004140dfc1df0a9e0f01ce7f2b21317" +
+ "7e6f8d157cd4f60210017f77deb3bcbb235d44ccc7dba62e72a116180f32303130303730" +
+ "373135303130355aa0030a0101180f32303130303730373135303130355aa011180f3230" +
+ "3130303730373138333531375aa1193017301506092b06010505073001020101ff040504" +
+ "03000000300d06092a864886f70d01010b0500038201010031c730ca60a7a0d92d8e4010" +
+ "911b469de95b4d27e89de6537552436237967694f76f701cf6b45c932bd308bca4a8d092" +
+ "5c604ba94796903091d9e6c000178e72c1f0a24a277dd262835af5d17d3f9d7869606c9f" +
+ "e7c8e708a41645699895beee38bfa63bb46296683761c5d1d65439b8ab868dc3017c9eeb" +
+ "b70b82dbf3a31c55b457d48bb9e82b335ed49f445042eaf606b06a3e0639824924c89c63" +
+ "eccddfe85e6694314138b2536f5e15e07085d0f6e26d4b2f8244bab0d70de07283ac6384" +
+ "a0501fc3dea7cf0adfd4c7f34871080900e252ddc403e3f0265f2a704af905d3727504ed" +
+ "28f3214a219d898a022463c78439799ca81c8cbafdbcec34ea937cd6a08202ea308202e6" +
+ "308202e2308201caa003020102020101300d06092a864886f70d01010b05003019311730" +
+ "150603550403130e4f43535020526573706f6e646572301e170d31353031333031353530" +
+ "33335a170d3136303133303135353033335a3019311730150603550403130e4f43535020" +
+ "526573706f6e64657230820122300d06092a864886f70d01010105000382010f00308201" +
+ "0a0282010100e8155f2d3e6f2e8d14c62a788bd462f9f844e7a6977c83ef1099f0f6616e" +
+ "c5265b56f356e62c5400f0b06a2e7945a82752c636df32a895152d6074df1701dc6ccfbc" +
+ "bec75a70bd2b55ae2be7e6cad3b5fd4cd5b7790ab401a436d3f5f346074ffde8a99d5b72" +
+ "3350f0a112076614b12ef79c78991b119453445acf2416ab0046b540db14c9fc0f27b898" +
+ "9ad0f63aa4b8aefc91aa8a72160c36307c60fec78a93d3fddf4259902aa77e7332971c7d" +
+ "285b6a04f648993c6922a3e9da9adf5f81508c3228791843e5d49f24db2f1290bafd97e6" +
+ "55b1049a199f652cd603c4fafa330c390b0da78fbbc67e8fa021cbd74eb96222b12ace31" +
+ "a77dcf920334dc94581b0203010001a3353033300e0603551d0f0101ff04040302078030" +
+ "130603551d25040c300a06082b06010505070309300c0603551d130101ff04023000300d" +
+ "06092a864886f70d01010b05000382010100718012761b5063e18f0dc44644d8e6ab8612" +
+ "31c15fd5357805425d82aec1de85bf6d3e30fce205e3e3b8b795bbe52e40a439286d2288" +
+ "9064f4aeeb150359b9425f1da51b3a5c939018555d13ac42c565a0603786a919328f3267" +
+ "09dce52c22ad958ecb7873b9771d1148b1c4be2efe80ba868919fc9f68b6090c2f33c156" +
+ "d67156e42766a50b5d51e79637b7e58af74c2a951b1e642fa7741fec982cc937de37eff5" +
+ "9e2005d5939bfc031589ca143e6e8ab83f40ee08cc20a6b4a95a318352c28d18528dcaf9" +
+ "66705de17afa19d6e8ae91ddf33179d16ebb6ac2c69cae8373d408ebf8c55308be6c04d9" +
+ "3a25439a94299a65a709756c7a3e568be049d5c38839"
+
+const ocspResponseWithExtensionHex = "308204fb0a0100a08204f4308204f006092b0601050507300101048204e1308204dd3081" +
+ "d8a003020100a11b3019311730150603550403130e4f43535020526573706f6e64657218" +
+ "0f32303136303130343136353930305a3081a230819f3049300906052b0e03021a050004" +
+ "14c0fe0278fc99188891b3f212e9c7e1b21ab7bfc004140dfc1df0a9e0f01ce7f2b21317" +
+ "7e6f8d157cd4f60210017f77deb3bcbb235d44ccc7dba62e72a116180f32303130303730" +
+ "373135303130355aa0030a0101180f32303130303730373135303130355aa011180f3230" +
+ "3130303730373138333531375aa1163014301206092b0601050507300102040504030000" +
+ "00300d06092a864886f70d01010b05000382010100c09a33e0b2324c852421bb83f85ac9" +
+ "9113f5426012bd2d2279a8166e9241d18a33c870894250622ffc7ed0c4601b16d624f90b" +
+ "779265442cdb6868cf40ab304ab4b66e7315ed02cf663b1601d1d4751772b31bc299db23" +
+ "9aebac78ed6797c06ed815a7a8d18d63cfbb609cafb47ec2e89e37db255216eb09307848" +
+ "d01be0a3e943653c78212b96ff524b74c9ec456b17cdfb950cc97645c577b2e09ff41dde" +
+ "b03afb3adaa381cc0f7c1d95663ef22a0f72f2c45613ae8e2b2d1efc96e8463c7d1d8a1d" +
+ "7e3b35df8fe73a301fc3f804b942b2b3afa337ff105fc1462b7b1c1d75eb4566c8665e59" +
+ "f80393b0adbf8004ff6c3327ed34f007cb4a3348a7d55e06e3a08202ea308202e6308202" +
+ "e2308201caa003020102020101300d06092a864886f70d01010b05003019311730150603" +
+ "550403130e4f43535020526573706f6e646572301e170d3135303133303135353033335a" +
+ "170d3136303133303135353033335a3019311730150603550403130e4f43535020526573" +
+ "706f6e64657230820122300d06092a864886f70d01010105000382010f003082010a0282" +
+ "010100e8155f2d3e6f2e8d14c62a788bd462f9f844e7a6977c83ef1099f0f6616ec5265b" +
+ "56f356e62c5400f0b06a2e7945a82752c636df32a895152d6074df1701dc6ccfbcbec75a" +
+ "70bd2b55ae2be7e6cad3b5fd4cd5b7790ab401a436d3f5f346074ffde8a99d5b723350f0" +
+ "a112076614b12ef79c78991b119453445acf2416ab0046b540db14c9fc0f27b8989ad0f6" +
+ "3aa4b8aefc91aa8a72160c36307c60fec78a93d3fddf4259902aa77e7332971c7d285b6a" +
+ "04f648993c6922a3e9da9adf5f81508c3228791843e5d49f24db2f1290bafd97e655b104" +
+ "9a199f652cd603c4fafa330c390b0da78fbbc67e8fa021cbd74eb96222b12ace31a77dcf" +
+ "920334dc94581b0203010001a3353033300e0603551d0f0101ff04040302078030130603" +
+ "551d25040c300a06082b06010505070309300c0603551d130101ff04023000300d06092a" +
+ "864886f70d01010b05000382010100718012761b5063e18f0dc44644d8e6ab861231c15f" +
+ "d5357805425d82aec1de85bf6d3e30fce205e3e3b8b795bbe52e40a439286d22889064f4" +
+ "aeeb150359b9425f1da51b3a5c939018555d13ac42c565a0603786a919328f326709dce5" +
+ "2c22ad958ecb7873b9771d1148b1c4be2efe80ba868919fc9f68b6090c2f33c156d67156" +
+ "e42766a50b5d51e79637b7e58af74c2a951b1e642fa7741fec982cc937de37eff59e2005" +
+ "d5939bfc031589ca143e6e8ab83f40ee08cc20a6b4a95a318352c28d18528dcaf966705d" +
+ "e17afa19d6e8ae91ddf33179d16ebb6ac2c69cae8373d408ebf8c55308be6c04d93a2543" +
+ "9a94299a65a709756c7a3e568be049d5c38839"
+
+const ocspMultiResponseHex = "30820ee60a0100a0820edf30820edb06092b060105050730010104820ecc30820ec83082" +
+ "0839a216041445ac2ecd75f53f1cf6e4c51d3de0047ad0aa7465180f3230313530363032" +
+ "3130303033305a3082080c3065303d300906052b0e03021a05000414f7452a0080601527" +
+ "72e4a135e76e9e52fde0f1580414edd8f2ee977252853a330b297a18f5c993853b3f0204" +
+ "5456656a8000180f32303135303630323039303230375aa011180f323031353036303331" +
+ "30303033305a3065303d300906052b0e03021a05000414f7452a008060152772e4a135e7" +
+ "6e9e52fde0f1580414edd8f2ee977252853a330b297a18f5c993853b3f02045456656b80" +
+ "00180f32303135303630323039303230375aa011180f3230313530363033313030303330" +
+ "5a3065303d300906052b0e03021a05000414f7452a008060152772e4a135e76e9e52fde0" +
+ "f1580414edd8f2ee977252853a330b297a18f5c993853b3f02045456656c8000180f3230" +
+ "3135303630323039303230375aa011180f32303135303630333130303033305a3065303d" +
+ "300906052b0e03021a05000414f7452a008060152772e4a135e76e9e52fde0f1580414ed" +
+ "d8f2ee977252853a330b297a18f5c993853b3f02045456656d8000180f32303135303630" +
+ "323039303230375aa011180f32303135303630333130303033305a3065303d300906052b" +
+ "0e03021a05000414f7452a008060152772e4a135e76e9e52fde0f1580414edd8f2ee9772" +
+ "52853a330b297a18f5c993853b3f02045456656e8000180f323031353036303230393032" +
+ "30375aa011180f32303135303630333130303033305a3065303d300906052b0e03021a05" +
+ "000414f7452a008060152772e4a135e76e9e52fde0f1580414edd8f2ee977252853a330b" +
+ "297a18f5c993853b3f02045456656f8000180f32303135303630323039303230375aa011" +
+ "180f32303135303630333130303033305a3065303d300906052b0e03021a05000414f745" +
+ "2a008060152772e4a135e76e9e52fde0f1580414edd8f2ee977252853a330b297a18f5c9" +
+ "93853b3f0204545665708000180f32303135303630323039303230375aa011180f323031" +
+ "35303630333130303033305a3065303d300906052b0e03021a05000414f7452a00806015" +
+ "2772e4a135e76e9e52fde0f1580414edd8f2ee977252853a330b297a18f5c993853b3f02" +
+ "04545665718000180f32303135303630323039303230375aa011180f3230313530363033" +
+ "3130303033305a3065303d300906052b0e03021a05000414f7452a008060152772e4a135" +
+ "e76e9e52fde0f1580414edd8f2ee977252853a330b297a18f5c993853b3f020454566572" +
+ "8000180f32303135303630323039303230375aa011180f32303135303630333130303033" +
+ "305a3065303d300906052b0e03021a05000414f7452a008060152772e4a135e76e9e52fd" +
+ "e0f1580414edd8f2ee977252853a330b297a18f5c993853b3f0204545665738000180f32" +
+ "303135303630323039303230375aa011180f32303135303630333130303033305a306530" +
+ "3d300906052b0e03021a05000414f7452a008060152772e4a135e76e9e52fde0f1580414" +
+ "edd8f2ee977252853a330b297a18f5c993853b3f0204545665748000180f323031353036" +
+ "30323039303230375aa011180f32303135303630333130303033305a3065303d30090605" +
+ "2b0e03021a05000414f7452a008060152772e4a135e76e9e52fde0f1580414edd8f2ee97" +
+ "7252853a330b297a18f5c993853b3f0204545665758000180f3230313530363032303930" +
+ "3230375aa011180f32303135303630333130303033305a3065303d300906052b0e03021a" +
+ "05000414f7452a008060152772e4a135e76e9e52fde0f1580414edd8f2ee977252853a33" +
+ "0b297a18f5c993853b3f0204545665768000180f32303135303630323039303230375aa0" +
+ "11180f32303135303630333130303033305a3065303d300906052b0e03021a05000414f7" +
+ "452a008060152772e4a135e76e9e52fde0f1580414edd8f2ee977252853a330b297a18f5" +
+ "c993853b3f0204545665778000180f32303135303630323039303230375aa011180f3230" +
+ "3135303630333130303033305a3065303d300906052b0e03021a05000414f7452a008060" +
+ "152772e4a135e76e9e52fde0f1580414edd8f2ee977252853a330b297a18f5c993853b3f" +
+ "0204545665788000180f32303135303630323039303230375aa011180f32303135303630" +
+ "333130303033305a3065303d300906052b0e03021a05000414f7452a008060152772e4a1" +
+ "35e76e9e52fde0f1580414edd8f2ee977252853a330b297a18f5c993853b3f0204545665" +
+ "798000180f32303135303630323039303230375aa011180f323031353036303331303030" +
+ "33305a3065303d300906052b0e03021a05000414f7452a008060152772e4a135e76e9e52" +
+ "fde0f1580414edd8f2ee977252853a330b297a18f5c993853b3f02045456657a8000180f" +
+ "32303135303630323039303230375aa011180f32303135303630333130303033305a3065" +
+ "303d300906052b0e03021a05000414f7452a008060152772e4a135e76e9e52fde0f15804" +
+ "14edd8f2ee977252853a330b297a18f5c993853b3f02045456657b8000180f3230313530" +
+ "3630323039303230375aa011180f32303135303630333130303033305a3065303d300906" +
+ "052b0e03021a05000414f7452a008060152772e4a135e76e9e52fde0f1580414edd8f2ee" +
+ "977252853a330b297a18f5c993853b3f02045456657c8000180f32303135303630323039" +
+ "303230375aa011180f32303135303630333130303033305a3065303d300906052b0e0302" +
+ "1a05000414f7452a008060152772e4a135e76e9e52fde0f1580414edd8f2ee977252853a" +
+ "330b297a18f5c993853b3f02045456657d8000180f32303135303630323039303230375a" +
+ "a011180f32303135303630333130303033305a300d06092a864886f70d01010505000382" +
+ "01010016b73b92859979f27d15eb018cf069eed39c3d280213565f3026de11ba15bdb94d" +
+ "764cf2d0fdd204ef926c588d7b183483c8a2b1995079c7ed04dcefcc650c1965be4b6832" +
+ "a8839e832f7f60f638425eccdf9bc3a81fbe700fda426ddf4f06c29bee431bbbe81effda" +
+ "a60b7da5b378f199af2f3c8380be7ba6c21c8e27124f8a4d8989926aea19055700848d33" +
+ "799e833512945fd75364edbd2dd18b783c1e96e332266b17979a0b88c35b43f47c87c493" +
+ "19155056ad8dbbae5ff2afad3c0e1c69ed111206ffda49875e8e4efc0926264823bc4423" +
+ "c8a002f34288c4bc22516f98f54fc609943721f590ddd8d24f989457526b599b0eb75cb5" +
+ "a80da1ad93a621a08205733082056f3082056b30820453a0030201020204545638c4300d" +
+ "06092a864886f70d01010b0500308182310b300906035504061302555331183016060355" +
+ "040a130f552e532e20476f7665726e6d656e7431233021060355040b131a446570617274" +
+ "6d656e74206f662074686520547265617375727931223020060355040b13194365727469" +
+ "6669636174696f6e20417574686f7269746965733110300e060355040b13074f43494f20" +
+ "4341301e170d3135303332303131353531335a170d3135303633303034303030305a3081" +
+ "98310b300906035504061302555331183016060355040a130f552e532e20476f7665726e" +
+ "6d656e7431233021060355040b131a4465706172746d656e74206f662074686520547265" +
+ "617375727931223020060355040b131943657274696669636174696f6e20417574686f72" +
+ "69746965733110300e060355040b13074f43494f204341311430120603550403130b4f43" +
+ "5350205369676e657230820122300d06092a864886f70d01010105000382010f00308201" +
+ "0a0282010100c1b6fe1ba1ad50bb98c855811acbd67fe68057f48b8e08d3800e7f2c51b7" +
+ "9e20551934971fd92b9c9e6c49453097927cba83a94c0b2fea7124ba5ac442b38e37dba6" +
+ "7303d4962dd7d92b22a04b0e0e182e9ea67620b1c6ce09ee607c19e0e6e3adae81151db1" +
+ "2bb7f706149349a292e21c1eb28565b6839df055e1a838a772ff34b5a1452618e2c26042" +
+ "705d53f0af4b57aae6163f58216af12f3887813fe44b0321827b3a0c52b0e47d0aab94a2" +
+ "f768ab0ba3901d22f8bb263823090b0e37a7f8856db4b0d165c42f3aa7e94f5f6ce1855e" +
+ "98dc57adea0ae98ad39f67ecdec00b88685566e9e8d69f6cefb6ddced53015d0d3b862bc" +
+ "be21f3d72251eefcec730203010001a38201cf308201cb300e0603551d0f0101ff040403" +
+ "020780306b0603551d2004643062300c060a60864801650302010502300c060a60864801" +
+ "650302010503300c060a60864801650302010504300c060a60864801650302010507300c" +
+ "060a60864801650302010508300c060a6086480165030201030d300c060a608648016503" +
+ "020103113081e506082b060105050701010481d83081d5303006082b0601050507300286" +
+ "24687474703a2f2f706b692e74726561732e676f762f746f63615f65655f6169612e7037" +
+ "633081a006082b060105050730028681936c6461703a2f2f6c6461702e74726561732e67" +
+ "6f762f6f753d4f43494f25323043412c6f753d43657274696669636174696f6e25323041" +
+ "7574686f7269746965732c6f753d4465706172746d656e742532306f6625323074686525" +
+ "323054726561737572792c6f3d552e532e253230476f7665726e6d656e742c633d55533f" +
+ "634143657274696669636174653b62696e61727930130603551d25040c300a06082b0601" +
+ "0505070309300f06092b060105050730010504020500301f0603551d23041830168014a2" +
+ "13a8e5c607546c243d4eb72b27a2a7711ab5af301d0603551d0e0416041451f98046818a" +
+ "e46d953ac90c210ccfaa1a06980c300d06092a864886f70d01010b050003820101003a37" +
+ "0b301d14ffdeb370883639bec5ae6f572dcbddadd672af16ee2a8303316b14e1fbdca8c2" +
+ "8f4bad9c7b1410250e149c14e9830ca6f17370a8d13151205d956e28c141cc0500379596" +
+ "c5b9239fcfa3d2de8f1d4f1a2b1bf2d1851bed1c86012ee8135bdc395cd4496ce69fadd0" +
+ "3b682b90350ca7b4f458190b7a0ab5c33a04cf1347a77d541877a380a4c94988c5658908" +
+ "44fdc22637a72b9fa410333e2caf969477f9fe07f50e3681c204fb3bf073b9da01cd8d91" +
+ "8044c40b1159955af12a3263ab1d34119d7f59bfa6cae88ed058addc4e08250263f8f836" +
+ "2f5bdffd45636fea7474c60a55c535954477b2f286e1b2535f0dd12c162f1b353c370e08" +
+ "be67"
+
+const ocspMultiResponseCertHex = "308207943082067ca003020102020454566573300d06092a864886f70d01010b05003081" +
+ "82310b300906035504061302555331183016060355040a130f552e532e20476f7665726e" +
+ "6d656e7431233021060355040b131a4465706172746d656e74206f662074686520547265" +
+ "617375727931223020060355040b131943657274696669636174696f6e20417574686f72" +
+ "69746965733110300e060355040b13074f43494f204341301e170d313530343130313535" +
+ "3733385a170d3138303431303136323733385a30819d310b300906035504061302555331" +
+ "183016060355040a130f552e532e20476f7665726e6d656e7431233021060355040b131a" +
+ "4465706172746d656e74206f662074686520547265617375727931253023060355040b13" +
+ "1c427572656175206f66207468652046697363616c20536572766963653110300e060355" +
+ "040b130744657669636573311630140603550403130d706b692e74726561732e676f7630" +
+ "820122300d06092a864886f70d01010105000382010f003082010a0282010100c7273623" +
+ "8c49c48bf501515a2490ef6e5ae0c06e0ad2aa9a6bb77f3d0370d846b2571581ebf38fd3" +
+ "1948daad3dec7a4da095f1dcbe9654e65bcf7acdfd4ee802421dad9b90536c721d2bca58" +
+ "8413e6bfd739a72470560bb7d64f9a09284f90ff8af1d5a3c5c84d0f95a00f9c6d988dd0" +
+ "d87f1d0d3344580901c955139f54d09de0acdbd3322b758cb0c58881bf04913243401f44" +
+ "013fd9f6d8348044cc8bb0a71978ad93366b2a4687a5274b2ee07d0fb40225453eb244ed" +
+ "b20152251ac77c59455260ff07eeceb3cb3c60fb8121cf92afd3daa2a4650e1942ccb555" +
+ "de10b3d481feb299838ef05d0fd1810b146753472ae80da65dd34da25ca1f89971f10039" +
+ "0203010001a38203f3308203ef300e0603551d0f0101ff0404030205a030170603551d20" +
+ "0410300e300c060a60864801650302010503301106096086480186f84201010404030206" +
+ "4030130603551d25040c300a06082b060105050703013082010806082b06010505070101" +
+ "0481fb3081f8303006082b060105050730028624687474703a2f2f706b692e7472656173" +
+ "2e676f762f746f63615f65655f6169612e7037633081a006082b06010505073002868193" +
+ "6c6461703a2f2f6c6461702e74726561732e676f762f6f753d4f43494f25323043412c6f" +
+ "753d43657274696669636174696f6e253230417574686f7269746965732c6f753d446570" +
+ "6172746d656e742532306f6625323074686525323054726561737572792c6f3d552e532e" +
+ "253230476f7665726e6d656e742c633d55533f634143657274696669636174653b62696e" +
+ "617279302106082b060105050730018615687474703a2f2f6f6373702e74726561732e67" +
+ "6f76307b0603551d1104743072811c6373612d7465616d4066697363616c2e7472656173" +
+ "7572792e676f768210706b692e74726561737572792e676f768210706b692e64696d632e" +
+ "6468732e676f76820d706b692e74726561732e676f76811f6563622d686f7374696e6740" +
+ "66697363616c2e74726561737572792e676f76308201890603551d1f048201803082017c" +
+ "3027a025a0238621687474703a2f2f706b692e74726561732e676f762f4f43494f5f4341" +
+ "332e63726c3082014fa082014ba0820147a48197308194310b3009060355040613025553" +
+ "31183016060355040a130f552e532e20476f7665726e6d656e7431233021060355040b13" +
+ "1a4465706172746d656e74206f662074686520547265617375727931223020060355040b" +
+ "131943657274696669636174696f6e20417574686f7269746965733110300e060355040b" +
+ "13074f43494f2043413110300e0603550403130743524c313430398681aa6c6461703a2f" +
+ "2f6c6461702e74726561732e676f762f636e3d43524c313430392c6f753d4f43494f2532" +
+ "3043412c6f753d43657274696669636174696f6e253230417574686f7269746965732c6f" +
+ "753d4465706172746d656e742532306f6625323074686525323054726561737572792c6f" +
+ "3d552e532e253230476f7665726e6d656e742c633d55533f636572746966696361746552" +
+ "65766f636174696f6e4c6973743b62696e617279302b0603551d1004243022800f323031" +
+ "35303431303135353733385a810f32303138303431303136323733385a301f0603551d23" +
+ "041830168014a213a8e5c607546c243d4eb72b27a2a7711ab5af301d0603551d0e041604" +
+ "14b0869c12c293914cd460e33ed43e6c5a26e0d68f301906092a864886f67d074100040c" +
+ "300a1b0456382e31030203a8300d06092a864886f70d01010b050003820101004968d182" +
+ "8f9efdc147e747bb5dda15536a42a079b32d3d7f87e619b483aeee70b7e26bda393c6028" +
+ "7c733ecb468fe8b8b11bf809ff76add6b90eb25ad8d3a1052e43ee281e48a3a1ebe7efb5" +
+ "9e2c4a48765dedeb23f5346242145786cc988c762d230d28dd33bf4c2405d80cbb2cb1d6" +
+ "4c8f10ba130d50cb174f6ffb9cfc12808297a2cefba385f4fad170f39b51ebd87c12abf9" +
+ "3c51fc000af90d8aaba78f48923908804a5eb35f617ccf71d201e3708a559e6d16f9f13e" +
+ "074361eb9007e28d86bb4e0bfa13aad0e9ddd9124e84519de60e2fc6040b18d9fd602b02" +
+ "684b4c071c3019fc842197d00c120c41654bcbfbc4a096a1c637b79112b81ce1fa3899f9"
+
+const ocspRequestHex = "3051304f304d304b3049300906052b0e03021a05000414c0fe0278fc99188891b3f212e9" +
+ "c7e1b21ab7bfc004140dfc1df0a9e0f01ce7f2b213177e6f8d157cd4f60210017f77deb3" +
+ "bcbb235d44ccc7dba62e72"
+
+const leafCertHex = "308203c830820331a0030201020210017f77deb3bcbb235d44ccc7dba62e72300d06092a" +
+ "864886f70d01010505003081ba311f301d060355040a1316566572695369676e20547275" +
+ "7374204e6574776f726b31173015060355040b130e566572695369676e2c20496e632e31" +
+ "333031060355040b132a566572695369676e20496e7465726e6174696f6e616c20536572" +
+ "766572204341202d20436c617373203331493047060355040b13407777772e7665726973" +
+ "69676e2e636f6d2f43505320496e636f72702e6279205265662e204c494142494c495459" +
+ "204c54442e286329393720566572695369676e301e170d3132303632313030303030305a" +
+ "170d3133313233313233353935395a3068310b3009060355040613025553311330110603" +
+ "550408130a43616c69666f726e6961311230100603550407130950616c6f20416c746f31" +
+ "173015060355040a130e46616365626f6f6b2c20496e632e311730150603550403140e2a" +
+ "2e66616365626f6f6b2e636f6d30819f300d06092a864886f70d010101050003818d0030" +
+ "818902818100ae94b171e2deccc1693e051063240102e0689ae83c39b6b3e74b97d48d7b" +
+ "23689100b0b496ee62f0e6d356bcf4aa0f50643402f5d1766aa972835a7564723f39bbef" +
+ "5290ded9bcdbf9d3d55dfad23aa03dc604c54d29cf1d4b3bdbd1a809cfae47b44c7eae17" +
+ "c5109bee24a9cf4a8d911bb0fd0415ae4c3f430aa12a557e2ae10203010001a382011e30" +
+ "82011a30090603551d130402300030440603551d20043d303b3039060b6086480186f845" +
+ "01071703302a302806082b06010505070201161c68747470733a2f2f7777772e76657269" +
+ "7369676e2e636f6d2f727061303c0603551d1f043530333031a02fa02d862b687474703a" +
+ "2f2f535652496e746c2d63726c2e766572697369676e2e636f6d2f535652496e746c2e63" +
+ "726c301d0603551d250416301406082b0601050507030106082b06010505070302300b06" +
+ "03551d0f0404030205a0303406082b0601050507010104283026302406082b0601050507" +
+ "30018618687474703a2f2f6f6373702e766572697369676e2e636f6d30270603551d1104" +
+ "20301e820e2a2e66616365626f6f6b2e636f6d820c66616365626f6f6b2e636f6d300d06" +
+ "092a864886f70d0101050500038181005b6c2b75f8ed30aa51aad36aba595e555141951f" +
+ "81a53b447910ac1f76ff78fc2781616b58f3122afc1c87010425e9ed43df1a7ba6498060" +
+ "67e2688af03db58c7df4ee03309a6afc247ccb134dc33e54c6bc1d5133a532a73273b1d7" +
+ "9cadc08e7e1a83116d34523340b0305427a21742827c98916698ee7eaf8c3bdd71700817"
+
+const issuerCertHex = "30820383308202eca003020102021046fcebbab4d02f0f926098233f93078f300d06092a" +
+ "864886f70d0101050500305f310b300906035504061302555331173015060355040a130e" +
+ "566572695369676e2c20496e632e31373035060355040b132e436c617373203320507562" +
+ "6c6963205072696d6172792043657274696669636174696f6e20417574686f7269747930" +
+ "1e170d3937303431373030303030305a170d3136313032343233353935395a3081ba311f" +
+ "301d060355040a1316566572695369676e205472757374204e6574776f726b3117301506" +
+ "0355040b130e566572695369676e2c20496e632e31333031060355040b132a5665726953" +
+ "69676e20496e7465726e6174696f6e616c20536572766572204341202d20436c61737320" +
+ "3331493047060355040b13407777772e766572697369676e2e636f6d2f43505320496e63" +
+ "6f72702e6279205265662e204c494142494c495459204c54442e28632939372056657269" +
+ "5369676e30819f300d06092a864886f70d010101050003818d0030818902818100d88280" +
+ "e8d619027d1f85183925a2652be1bfd405d3bce6363baaf04c6c5bb6e7aa3c734555b2f1" +
+ "bdea9742ed9a340a15d4a95cf54025ddd907c132b2756cc4cabba3fe56277143aa63f530" +
+ "3e9328e5faf1093bf3b74d4e39f75c495ab8c11dd3b28afe70309542cbfe2b518b5a3c3a" +
+ "f9224f90b202a7539c4f34e7ab04b27b6f0203010001a381e33081e0300f0603551d1304" +
+ "0830060101ff02010030440603551d20043d303b3039060b6086480186f8450107010130" +
+ "2a302806082b06010505070201161c68747470733a2f2f7777772e766572697369676e2e" +
+ "636f6d2f43505330340603551d25042d302b06082b0601050507030106082b0601050507" +
+ "030206096086480186f8420401060a6086480186f845010801300b0603551d0f04040302" +
+ "0106301106096086480186f842010104040302010630310603551d1f042a30283026a024" +
+ "a0228620687474703a2f2f63726c2e766572697369676e2e636f6d2f706361332e63726c" +
+ "300d06092a864886f70d010105050003818100408e4997968a73dd8e4def3e61b7caa062" +
+ "adf40e0abb753de26ed82cc7bff4b98c369bcaa2d09c724639f6a682036511c4bcbf2da6" +
+ "f5d93b0ab598fab378b91ef22b4c62d5fdb27a1ddf33fd73f9a5d82d8c2aead1fcb028b6" +
+ "e94948134b838a1b487b24f738de6f4154b8ab576b06dfc7a2d4a9f6f136628088f28b75" +
+ "d68071"
+
+// Key and certificate for the OCSP responder were not taken from the Thawte
+// responder, since CreateResponse requires that we have the private key.
+// Instead, they were generated randomly.
+const responderPrivateKeyHex = "308204a40201000282010100e8155f2d3e6f2e8d14c62a788bd462f9f844e7a6977c83ef" +
+ "1099f0f6616ec5265b56f356e62c5400f0b06a2e7945a82752c636df32a895152d6074df" +
+ "1701dc6ccfbcbec75a70bd2b55ae2be7e6cad3b5fd4cd5b7790ab401a436d3f5f346074f" +
+ "fde8a99d5b723350f0a112076614b12ef79c78991b119453445acf2416ab0046b540db14" +
+ "c9fc0f27b8989ad0f63aa4b8aefc91aa8a72160c36307c60fec78a93d3fddf4259902aa7" +
+ "7e7332971c7d285b6a04f648993c6922a3e9da9adf5f81508c3228791843e5d49f24db2f" +
+ "1290bafd97e655b1049a199f652cd603c4fafa330c390b0da78fbbc67e8fa021cbd74eb9" +
+ "6222b12ace31a77dcf920334dc94581b02030100010282010100bcf0b93d7238bda329a8" +
+ "72e7149f61bcb37c154330ccb3f42a85c9002c2e2bdea039d77d8581cd19bed94078794e" +
+ "56293d601547fc4bf6a2f9002fe5772b92b21b254403b403585e3130cc99ccf08f0ef81a" +
+ "575b38f597ba4660448b54f44bfbb97072b5a2bf043bfeca828cf7741d13698e3f38162b" +
+ "679faa646b82abd9a72c5c7d722c5fc577a76d2c2daac588accad18516d1bbad10b0dfa2" +
+ "05cfe246b59e28608a43942e1b71b0c80498075121de5b900d727c31c42c78cf1db5c0aa" +
+ "5b491e10ea4ed5c0962aaf2ae025dd81fa4ce490d9d6b4a4465411d8e542fc88617e5695" +
+ "1aa4fc8ea166f2b4d0eb89ef17f2b206bd5f1014bf8fe0e71fe62f2cccf102818100f2dc" +
+ "ddf878d553286daad68bac4070a82ffec3dc4666a2750f47879eec913f91836f1d976b60" +
+ "daf9356e078446dafab5bd2e489e5d64f8572ba24a4ba4f3729b5e106c4dd831cc2497a7" +
+ "e6c7507df05cb64aeb1bbc81c1e340d58b5964cf39cff84ea30c29ec5d3f005ee1362698" +
+ "07395037955955655292c3e85f6187fa1f9502818100f4a33c102630840705f8c778a47b" +
+ "87e8da31e68809af981ac5e5999cf1551685d761cdf0d6520361b99aebd5777a940fa64d" +
+ "327c09fa63746fbb3247ec73a86edf115f1fe5c83598db803881ade71c33c6e956118345" +
+ "497b98b5e07bb5be75971465ec78f2f9467e1b74956ca9d4c7c3e314e742a72d8b33889c" +
+ "6c093a466cef0281801d3df0d02124766dd0be98349b19eb36a508c4e679e793ba0a8bef" +
+ "4d786888c1e9947078b1ea28938716677b4ad8c5052af12eb73ac194915264a913709a0b" +
+ "7b9f98d4a18edd781a13d49899f91c20dbd8eb2e61d991ba19b5cdc08893f5cb9d39e5a6" +
+ "0629ea16d426244673b1b3ee72bd30e41fac8395acac40077403de5efd028180050731dd" +
+ "d71b1a2b96c8d538ba90bb6b62c8b1c74c03aae9a9f59d21a7a82b0d572ef06fa9c807bf" +
+ "c373d6b30d809c7871df96510c577421d9860c7383fda0919ece19996b3ca13562159193" +
+ "c0c246471e287f975e8e57034e5136aaf44254e2650def3d51292474c515b1588969112e" +
+ "0a85cc77073e9d64d2c2fc497844284b02818100d71d63eabf416cf677401ebf965f8314" +
+ "120b568a57dd3bd9116c629c40dc0c6948bab3a13cc544c31c7da40e76132ef5dd3f7534" +
+ "45a635930c74326ae3df0edd1bfb1523e3aa259873ac7cf1ac31151ec8f37b528c275622" +
+ "48f99b8bed59fd4da2576aa6ee20d93a684900bf907e80c66d6e2261ae15e55284b4ed9d" +
+ "6bdaa059"
+
+const responderCertHex = "308202e2308201caa003020102020101300d06092a864886f70d01010b05003019311730" +
+ "150603550403130e4f43535020526573706f6e646572301e170d31353031333031353530" +
+ "33335a170d3136303133303135353033335a3019311730150603550403130e4f43535020" +
+ "526573706f6e64657230820122300d06092a864886f70d01010105000382010f00308201" +
+ "0a0282010100e8155f2d3e6f2e8d14c62a788bd462f9f844e7a6977c83ef1099f0f6616e" +
+ "c5265b56f356e62c5400f0b06a2e7945a82752c636df32a895152d6074df1701dc6ccfbc" +
+ "bec75a70bd2b55ae2be7e6cad3b5fd4cd5b7790ab401a436d3f5f346074ffde8a99d5b72" +
+ "3350f0a112076614b12ef79c78991b119453445acf2416ab0046b540db14c9fc0f27b898" +
+ "9ad0f63aa4b8aefc91aa8a72160c36307c60fec78a93d3fddf4259902aa77e7332971c7d" +
+ "285b6a04f648993c6922a3e9da9adf5f81508c3228791843e5d49f24db2f1290bafd97e6" +
+ "55b1049a199f652cd603c4fafa330c390b0da78fbbc67e8fa021cbd74eb96222b12ace31" +
+ "a77dcf920334dc94581b0203010001a3353033300e0603551d0f0101ff04040302078030" +
+ "130603551d25040c300a06082b06010505070309300c0603551d130101ff04023000300d" +
+ "06092a864886f70d01010b05000382010100718012761b5063e18f0dc44644d8e6ab8612" +
+ "31c15fd5357805425d82aec1de85bf6d3e30fce205e3e3b8b795bbe52e40a439286d2288" +
+ "9064f4aeeb150359b9425f1da51b3a5c939018555d13ac42c565a0603786a919328f3267" +
+ "09dce52c22ad958ecb7873b9771d1148b1c4be2efe80ba868919fc9f68b6090c2f33c156" +
+ "d67156e42766a50b5d51e79637b7e58af74c2a951b1e642fa7741fec982cc937de37eff5" +
+ "9e2005d5939bfc031589ca143e6e8ab83f40ee08cc20a6b4a95a318352c28d18528dcaf9" +
+ "66705de17afa19d6e8ae91ddf33179d16ebb6ac2c69cae8373d408ebf8c55308be6c04d9" +
+ "3a25439a94299a65a709756c7a3e568be049d5c38839"
+
+const errorResponseHex = "30030a0101"
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/armor/armor.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/armor/armor.go
new file mode 100644
index 000000000..592d18643
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/armor/armor.go
@@ -0,0 +1,219 @@
+// Copyright 2010 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 armor implements OpenPGP ASCII Armor, see RFC 4880. OpenPGP Armor is
+// very similar to PEM except that it has an additional CRC checksum.
+package armor // import "golang.org/x/crypto/openpgp/armor"
+
+import (
+ "bufio"
+ "bytes"
+ "encoding/base64"
+ "golang.org/x/crypto/openpgp/errors"
+ "io"
+)
+
+// A Block represents an OpenPGP armored structure.
+//
+// The encoded form is:
+// -----BEGIN Type-----
+// Headers
+//
+// base64-encoded Bytes
+// '=' base64 encoded checksum
+// -----END Type-----
+// where Headers is a possibly empty sequence of Key: Value lines.
+//
+// Since the armored data can be very large, this package presents a streaming
+// interface.
+type Block struct {
+ Type string // The type, taken from the preamble (i.e. "PGP SIGNATURE").
+ Header map[string]string // Optional headers.
+ Body io.Reader // A Reader from which the contents can be read
+ lReader lineReader
+ oReader openpgpReader
+}
+
+var ArmorCorrupt error = errors.StructuralError("armor invalid")
+
+const crc24Init = 0xb704ce
+const crc24Poly = 0x1864cfb
+const crc24Mask = 0xffffff
+
+// crc24 calculates the OpenPGP checksum as specified in RFC 4880, section 6.1
+func crc24(crc uint32, d []byte) uint32 {
+ for _, b := range d {
+ crc ^= uint32(b) << 16
+ for i := 0; i < 8; i++ {
+ crc <<= 1
+ if crc&0x1000000 != 0 {
+ crc ^= crc24Poly
+ }
+ }
+ }
+ return crc
+}
+
+var armorStart = []byte("-----BEGIN ")
+var armorEnd = []byte("-----END ")
+var armorEndOfLine = []byte("-----")
+
+// lineReader wraps a line based reader. It watches for the end of an armor
+// block and records the expected CRC value.
+type lineReader struct {
+ in *bufio.Reader
+ buf []byte
+ eof bool
+ crc uint32
+}
+
+func (l *lineReader) Read(p []byte) (n int, err error) {
+ if l.eof {
+ return 0, io.EOF
+ }
+
+ if len(l.buf) > 0 {
+ n = copy(p, l.buf)
+ l.buf = l.buf[n:]
+ return
+ }
+
+ line, isPrefix, err := l.in.ReadLine()
+ if err != nil {
+ return
+ }
+ if isPrefix {
+ return 0, ArmorCorrupt
+ }
+
+ if len(line) == 5 && line[0] == '=' {
+ // This is the checksum line
+ var expectedBytes [3]byte
+ var m int
+ m, err = base64.StdEncoding.Decode(expectedBytes[0:], line[1:])
+ if m != 3 || err != nil {
+ return
+ }
+ l.crc = uint32(expectedBytes[0])<<16 |
+ uint32(expectedBytes[1])<<8 |
+ uint32(expectedBytes[2])
+
+ line, _, err = l.in.ReadLine()
+ if err != nil && err != io.EOF {
+ return
+ }
+ if !bytes.HasPrefix(line, armorEnd) {
+ return 0, ArmorCorrupt
+ }
+
+ l.eof = true
+ return 0, io.EOF
+ }
+
+ if len(line) > 96 {
+ return 0, ArmorCorrupt
+ }
+
+ n = copy(p, line)
+ bytesToSave := len(line) - n
+ if bytesToSave > 0 {
+ if cap(l.buf) < bytesToSave {
+ l.buf = make([]byte, 0, bytesToSave)
+ }
+ l.buf = l.buf[0:bytesToSave]
+ copy(l.buf, line[n:])
+ }
+
+ return
+}
+
+// openpgpReader passes Read calls to the underlying base64 decoder, but keeps
+// a running CRC of the resulting data and checks the CRC against the value
+// found by the lineReader at EOF.
+type openpgpReader struct {
+ lReader *lineReader
+ b64Reader io.Reader
+ currentCRC uint32
+}
+
+func (r *openpgpReader) Read(p []byte) (n int, err error) {
+ n, err = r.b64Reader.Read(p)
+ r.currentCRC = crc24(r.currentCRC, p[:n])
+
+ if err == io.EOF {
+ if r.lReader.crc != uint32(r.currentCRC&crc24Mask) {
+ return 0, ArmorCorrupt
+ }
+ }
+
+ return
+}
+
+// Decode reads a PGP armored block from the given Reader. It will ignore
+// leading garbage. If it doesn't find a block, it will return nil, io.EOF. The
+// given Reader is not usable after calling this function: an arbitrary amount
+// of data may have been read past the end of the block.
+func Decode(in io.Reader) (p *Block, err error) {
+ r := bufio.NewReaderSize(in, 100)
+ var line []byte
+ ignoreNext := false
+
+TryNextBlock:
+ p = nil
+
+ // Skip leading garbage
+ for {
+ ignoreThis := ignoreNext
+ line, ignoreNext, err = r.ReadLine()
+ if err != nil {
+ return
+ }
+ if ignoreNext || ignoreThis {
+ continue
+ }
+ line = bytes.TrimSpace(line)
+ if len(line) > len(armorStart)+len(armorEndOfLine) && bytes.HasPrefix(line, armorStart) {
+ break
+ }
+ }
+
+ p = new(Block)
+ p.Type = string(line[len(armorStart) : len(line)-len(armorEndOfLine)])
+ p.Header = make(map[string]string)
+ nextIsContinuation := false
+ var lastKey string
+
+ // Read headers
+ for {
+ isContinuation := nextIsContinuation
+ line, nextIsContinuation, err = r.ReadLine()
+ if err != nil {
+ p = nil
+ return
+ }
+ if isContinuation {
+ p.Header[lastKey] += string(line)
+ continue
+ }
+ line = bytes.TrimSpace(line)
+ if len(line) == 0 {
+ break
+ }
+
+ i := bytes.Index(line, []byte(": "))
+ if i == -1 {
+ goto TryNextBlock
+ }
+ lastKey = string(line[:i])
+ p.Header[lastKey] = string(line[i+2:])
+ }
+
+ p.lReader.in = r
+ p.oReader.currentCRC = crc24Init
+ p.oReader.lReader = &p.lReader
+ p.oReader.b64Reader = base64.NewDecoder(base64.StdEncoding, &p.lReader)
+ p.Body = &p.oReader
+
+ return
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/armor/armor_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/armor/armor_test.go
new file mode 100644
index 000000000..9334e94e9
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/armor/armor_test.go
@@ -0,0 +1,95 @@
+// Copyright 2010 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 armor
+
+import (
+ "bytes"
+ "hash/adler32"
+ "io/ioutil"
+ "testing"
+)
+
+func TestDecodeEncode(t *testing.T) {
+ buf := bytes.NewBuffer([]byte(armorExample1))
+ result, err := Decode(buf)
+ if err != nil {
+ t.Error(err)
+ }
+ expectedType := "PGP SIGNATURE"
+ if result.Type != expectedType {
+ t.Errorf("result.Type: got:%s want:%s", result.Type, expectedType)
+ }
+ if len(result.Header) != 1 {
+ t.Errorf("len(result.Header): got:%d want:1", len(result.Header))
+ }
+ v, ok := result.Header["Version"]
+ if !ok || v != "GnuPG v1.4.10 (GNU/Linux)" {
+ t.Errorf("result.Header: got:%#v", result.Header)
+ }
+
+ contents, err := ioutil.ReadAll(result.Body)
+ if err != nil {
+ t.Error(err)
+ }
+
+ if adler32.Checksum(contents) != 0x27b144be {
+ t.Errorf("contents: got: %x", contents)
+ }
+
+ buf = bytes.NewBuffer(nil)
+ w, err := Encode(buf, result.Type, result.Header)
+ if err != nil {
+ t.Error(err)
+ }
+ _, err = w.Write(contents)
+ if err != nil {
+ t.Error(err)
+ }
+ w.Close()
+
+ if !bytes.Equal(buf.Bytes(), []byte(armorExample1)) {
+ t.Errorf("got: %s\nwant: %s", string(buf.Bytes()), armorExample1)
+ }
+}
+
+func TestLongHeader(t *testing.T) {
+ buf := bytes.NewBuffer([]byte(armorLongLine))
+ result, err := Decode(buf)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ value, ok := result.Header["Version"]
+ if !ok {
+ t.Errorf("missing Version header")
+ }
+ if value != longValueExpected {
+ t.Errorf("got: %s want: %s", value, longValueExpected)
+ }
+}
+
+const armorExample1 = `-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.4.10 (GNU/Linux)
+
+iJwEAAECAAYFAk1Fv/0ACgkQo01+GMIMMbsYTwQAiAw+QAaNfY6WBdplZ/uMAccm
+4g+81QPmTSGHnetSb6WBiY13kVzK4HQiZH8JSkmmroMLuGeJwsRTEL4wbjRyUKEt
+p1xwUZDECs234F1xiG5enc5SGlRtP7foLBz9lOsjx+LEcA4sTl5/2eZR9zyFZqWW
+TxRjs+fJCIFuo71xb1g=
+=/teI
+-----END PGP SIGNATURE-----`
+
+const armorLongLine = `-----BEGIN PGP SIGNATURE-----
+Version: 0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz
+
+iQEcBAABAgAGBQJMtFESAAoJEKsQXJGvOPsVj40H/1WW6jaMXv4BW+1ueDSMDwM8
+kx1fLOXbVM5/Kn5LStZNt1jWWnpxdz7eq3uiqeCQjmqUoRde3YbB2EMnnwRbAhpp
+cacnAvy9ZQ78OTxUdNW1mhX5bS6q1MTEJnl+DcyigD70HG/yNNQD7sOPMdYQw0TA
+byQBwmLwmTsuZsrYqB68QyLHI+DUugn+kX6Hd2WDB62DKa2suoIUIHQQCd/ofwB3
+WfCYInXQKKOSxu2YOg2Eb4kLNhSMc1i9uKUWAH+sdgJh7NBgdoE4MaNtBFkHXRvv
+okWuf3+xA9ksp1npSY/mDvgHijmjvtpRDe6iUeqfCn8N9u9CBg8geANgaG8+QA4=
+=wfQG
+-----END PGP SIGNATURE-----`
+
+const longValueExpected = "0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz"
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/armor/encode.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/armor/encode.go
new file mode 100644
index 000000000..6f07582c3
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/armor/encode.go
@@ -0,0 +1,160 @@
+// Copyright 2010 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 armor
+
+import (
+ "encoding/base64"
+ "io"
+)
+
+var armorHeaderSep = []byte(": ")
+var blockEnd = []byte("\n=")
+var newline = []byte("\n")
+var armorEndOfLineOut = []byte("-----\n")
+
+// writeSlices writes its arguments to the given Writer.
+func writeSlices(out io.Writer, slices ...[]byte) (err error) {
+ for _, s := range slices {
+ _, err = out.Write(s)
+ if err != nil {
+ return err
+ }
+ }
+ return
+}
+
+// lineBreaker breaks data across several lines, all of the same byte length
+// (except possibly the last). Lines are broken with a single '\n'.
+type lineBreaker struct {
+ lineLength int
+ line []byte
+ used int
+ out io.Writer
+ haveWritten bool
+}
+
+func newLineBreaker(out io.Writer, lineLength int) *lineBreaker {
+ return &lineBreaker{
+ lineLength: lineLength,
+ line: make([]byte, lineLength),
+ used: 0,
+ out: out,
+ }
+}
+
+func (l *lineBreaker) Write(b []byte) (n int, err error) {
+ n = len(b)
+
+ if n == 0 {
+ return
+ }
+
+ if l.used == 0 && l.haveWritten {
+ _, err = l.out.Write([]byte{'\n'})
+ if err != nil {
+ return
+ }
+ }
+
+ if l.used+len(b) < l.lineLength {
+ l.used += copy(l.line[l.used:], b)
+ return
+ }
+
+ l.haveWritten = true
+ _, err = l.out.Write(l.line[0:l.used])
+ if err != nil {
+ return
+ }
+ excess := l.lineLength - l.used
+ l.used = 0
+
+ _, err = l.out.Write(b[0:excess])
+ if err != nil {
+ return
+ }
+
+ _, err = l.Write(b[excess:])
+ return
+}
+
+func (l *lineBreaker) Close() (err error) {
+ if l.used > 0 {
+ _, err = l.out.Write(l.line[0:l.used])
+ if err != nil {
+ return
+ }
+ }
+
+ return
+}
+
+// encoding keeps track of a running CRC24 over the data which has been written
+// to it and outputs a OpenPGP checksum when closed, followed by an armor
+// trailer.
+//
+// It's built into a stack of io.Writers:
+// encoding -> base64 encoder -> lineBreaker -> out
+type encoding struct {
+ out io.Writer
+ breaker *lineBreaker
+ b64 io.WriteCloser
+ crc uint32
+ blockType []byte
+}
+
+func (e *encoding) Write(data []byte) (n int, err error) {
+ e.crc = crc24(e.crc, data)
+ return e.b64.Write(data)
+}
+
+func (e *encoding) Close() (err error) {
+ err = e.b64.Close()
+ if err != nil {
+ return
+ }
+ e.breaker.Close()
+
+ var checksumBytes [3]byte
+ checksumBytes[0] = byte(e.crc >> 16)
+ checksumBytes[1] = byte(e.crc >> 8)
+ checksumBytes[2] = byte(e.crc)
+
+ var b64ChecksumBytes [4]byte
+ base64.StdEncoding.Encode(b64ChecksumBytes[:], checksumBytes[:])
+
+ return writeSlices(e.out, blockEnd, b64ChecksumBytes[:], newline, armorEnd, e.blockType, armorEndOfLine)
+}
+
+// Encode returns a WriteCloser which will encode the data written to it in
+// OpenPGP armor.
+func Encode(out io.Writer, blockType string, headers map[string]string) (w io.WriteCloser, err error) {
+ bType := []byte(blockType)
+ err = writeSlices(out, armorStart, bType, armorEndOfLineOut)
+ if err != nil {
+ return
+ }
+
+ for k, v := range headers {
+ err = writeSlices(out, []byte(k), armorHeaderSep, []byte(v), newline)
+ if err != nil {
+ return
+ }
+ }
+
+ _, err = out.Write(newline)
+ if err != nil {
+ return
+ }
+
+ e := &encoding{
+ out: out,
+ breaker: newLineBreaker(out, 64),
+ crc: crc24Init,
+ blockType: bType,
+ }
+ e.b64 = base64.NewEncoder(base64.StdEncoding, e.breaker)
+ return e, nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/canonical_text.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/canonical_text.go
new file mode 100644
index 000000000..e601e389f
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/canonical_text.go
@@ -0,0 +1,59 @@
+// Copyright 2011 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 openpgp
+
+import "hash"
+
+// NewCanonicalTextHash reformats text written to it into the canonical
+// form and then applies the hash h. See RFC 4880, section 5.2.1.
+func NewCanonicalTextHash(h hash.Hash) hash.Hash {
+ return &canonicalTextHash{h, 0}
+}
+
+type canonicalTextHash struct {
+ h hash.Hash
+ s int
+}
+
+var newline = []byte{'\r', '\n'}
+
+func (cth *canonicalTextHash) Write(buf []byte) (int, error) {
+ start := 0
+
+ for i, c := range buf {
+ switch cth.s {
+ case 0:
+ if c == '\r' {
+ cth.s = 1
+ } else if c == '\n' {
+ cth.h.Write(buf[start:i])
+ cth.h.Write(newline)
+ start = i + 1
+ }
+ case 1:
+ cth.s = 0
+ }
+ }
+
+ cth.h.Write(buf[start:])
+ return len(buf), nil
+}
+
+func (cth *canonicalTextHash) Sum(in []byte) []byte {
+ return cth.h.Sum(in)
+}
+
+func (cth *canonicalTextHash) Reset() {
+ cth.h.Reset()
+ cth.s = 0
+}
+
+func (cth *canonicalTextHash) Size() int {
+ return cth.h.Size()
+}
+
+func (cth *canonicalTextHash) BlockSize() int {
+ return cth.h.BlockSize()
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/canonical_text_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/canonical_text_test.go
new file mode 100644
index 000000000..8f3ba2a88
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/canonical_text_test.go
@@ -0,0 +1,52 @@
+// Copyright 2011 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 openpgp
+
+import (
+ "bytes"
+ "testing"
+)
+
+type recordingHash struct {
+ buf *bytes.Buffer
+}
+
+func (r recordingHash) Write(b []byte) (n int, err error) {
+ return r.buf.Write(b)
+}
+
+func (r recordingHash) Sum(in []byte) []byte {
+ return append(in, r.buf.Bytes()...)
+}
+
+func (r recordingHash) Reset() {
+ panic("shouldn't be called")
+}
+
+func (r recordingHash) Size() int {
+ panic("shouldn't be called")
+}
+
+func (r recordingHash) BlockSize() int {
+ panic("shouldn't be called")
+}
+
+func testCanonicalText(t *testing.T, input, expected string) {
+ r := recordingHash{bytes.NewBuffer(nil)}
+ c := NewCanonicalTextHash(r)
+ c.Write([]byte(input))
+ result := c.Sum(nil)
+ if expected != string(result) {
+ t.Errorf("input: %x got: %x want: %x", input, result, expected)
+ }
+}
+
+func TestCanonicalText(t *testing.T) {
+ testCanonicalText(t, "foo\n", "foo\r\n")
+ testCanonicalText(t, "foo", "foo")
+ testCanonicalText(t, "foo\r\n", "foo\r\n")
+ testCanonicalText(t, "foo\r\nbar", "foo\r\nbar")
+ testCanonicalText(t, "foo\r\nbar\n\n", "foo\r\nbar\r\n\r\n")
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/clearsign/clearsign.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/clearsign/clearsign.go
new file mode 100644
index 000000000..def4cabaf
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/clearsign/clearsign.go
@@ -0,0 +1,376 @@
+// Copyright 2012 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 clearsign generates and processes OpenPGP, clear-signed data. See
+// RFC 4880, section 7.
+//
+// Clearsigned messages are cryptographically signed, but the contents of the
+// message are kept in plaintext so that it can be read without special tools.
+package clearsign // import "golang.org/x/crypto/openpgp/clearsign"
+
+import (
+ "bufio"
+ "bytes"
+ "crypto"
+ "hash"
+ "io"
+ "net/textproto"
+ "strconv"
+
+ "golang.org/x/crypto/openpgp/armor"
+ "golang.org/x/crypto/openpgp/errors"
+ "golang.org/x/crypto/openpgp/packet"
+)
+
+// A Block represents a clearsigned message. A signature on a Block can
+// be checked by passing Bytes into openpgp.CheckDetachedSignature.
+type Block struct {
+ Headers textproto.MIMEHeader // Optional message headers
+ Plaintext []byte // The original message text
+ Bytes []byte // The signed message
+ ArmoredSignature *armor.Block // The signature block
+}
+
+// start is the marker which denotes the beginning of a clearsigned message.
+var start = []byte("\n-----BEGIN PGP SIGNED MESSAGE-----")
+
+// dashEscape is prefixed to any lines that begin with a hyphen so that they
+// can't be confused with endText.
+var dashEscape = []byte("- ")
+
+// endText is a marker which denotes the end of the message and the start of
+// an armored signature.
+var endText = []byte("-----BEGIN PGP SIGNATURE-----")
+
+// end is a marker which denotes the end of the armored signature.
+var end = []byte("\n-----END PGP SIGNATURE-----")
+
+var crlf = []byte("\r\n")
+var lf = byte('\n')
+
+// getLine returns the first \r\n or \n delineated line from the given byte
+// array. The line does not include the \r\n or \n. The remainder of the byte
+// array (also not including the new line bytes) is also returned and this will
+// always be smaller than the original argument.
+func getLine(data []byte) (line, rest []byte) {
+ i := bytes.Index(data, []byte{'\n'})
+ var j int
+ if i < 0 {
+ i = len(data)
+ j = i
+ } else {
+ j = i + 1
+ if i > 0 && data[i-1] == '\r' {
+ i--
+ }
+ }
+ return data[0:i], data[j:]
+}
+
+// Decode finds the first clearsigned message in data and returns it, as well
+// as the suffix of data which remains after the message.
+func Decode(data []byte) (b *Block, rest []byte) {
+ // start begins with a newline. However, at the very beginning of
+ // the byte array, we'll accept the start string without it.
+ rest = data
+ if bytes.HasPrefix(data, start[1:]) {
+ rest = rest[len(start)-1:]
+ } else if i := bytes.Index(data, start); i >= 0 {
+ rest = rest[i+len(start):]
+ } else {
+ return nil, data
+ }
+
+ // Consume the start line.
+ _, rest = getLine(rest)
+
+ var line []byte
+ b = &Block{
+ Headers: make(textproto.MIMEHeader),
+ }
+
+ // Next come a series of header lines.
+ for {
+ // This loop terminates because getLine's second result is
+ // always smaller than its argument.
+ if len(rest) == 0 {
+ return nil, data
+ }
+ // An empty line marks the end of the headers.
+ if line, rest = getLine(rest); len(line) == 0 {
+ break
+ }
+
+ i := bytes.Index(line, []byte{':'})
+ if i == -1 {
+ return nil, data
+ }
+
+ key, val := line[0:i], line[i+1:]
+ key = bytes.TrimSpace(key)
+ val = bytes.TrimSpace(val)
+ b.Headers.Add(string(key), string(val))
+ }
+
+ firstLine := true
+ for {
+ start := rest
+
+ line, rest = getLine(rest)
+ if len(line) == 0 && len(rest) == 0 {
+ // No armored data was found, so this isn't a complete message.
+ return nil, data
+ }
+ if bytes.Equal(line, endText) {
+ // Back up to the start of the line because armor expects to see the
+ // header line.
+ rest = start
+ break
+ }
+
+ // The final CRLF isn't included in the hash so we don't write it until
+ // we've seen the next line.
+ if firstLine {
+ firstLine = false
+ } else {
+ b.Bytes = append(b.Bytes, crlf...)
+ }
+
+ if bytes.HasPrefix(line, dashEscape) {
+ line = line[2:]
+ }
+ line = bytes.TrimRight(line, " \t")
+ b.Bytes = append(b.Bytes, line...)
+
+ b.Plaintext = append(b.Plaintext, line...)
+ b.Plaintext = append(b.Plaintext, lf)
+ }
+
+ // We want to find the extent of the armored data (including any newlines at
+ // the end).
+ i := bytes.Index(rest, end)
+ if i == -1 {
+ return nil, data
+ }
+ i += len(end)
+ for i < len(rest) && (rest[i] == '\r' || rest[i] == '\n') {
+ i++
+ }
+ armored := rest[:i]
+ rest = rest[i:]
+
+ var err error
+ b.ArmoredSignature, err = armor.Decode(bytes.NewBuffer(armored))
+ if err != nil {
+ return nil, data
+ }
+
+ return b, rest
+}
+
+// A dashEscaper is an io.WriteCloser which processes the body of a clear-signed
+// message. The clear-signed message is written to buffered and a hash, suitable
+// for signing, is maintained in h.
+//
+// When closed, an armored signature is created and written to complete the
+// message.
+type dashEscaper struct {
+ buffered *bufio.Writer
+ h hash.Hash
+ hashType crypto.Hash
+
+ atBeginningOfLine bool
+ isFirstLine bool
+
+ whitespace []byte
+ byteBuf []byte // a one byte buffer to save allocations
+
+ privateKey *packet.PrivateKey
+ config *packet.Config
+}
+
+func (d *dashEscaper) Write(data []byte) (n int, err error) {
+ for _, b := range data {
+ d.byteBuf[0] = b
+
+ if d.atBeginningOfLine {
+ // The final CRLF isn't included in the hash so we have to wait
+ // until this point (the start of the next line) before writing it.
+ if !d.isFirstLine {
+ d.h.Write(crlf)
+ }
+ d.isFirstLine = false
+ }
+
+ // Any whitespace at the end of the line has to be removed so we
+ // buffer it until we find out whether there's more on this line.
+ if b == ' ' || b == '\t' || b == '\r' {
+ d.whitespace = append(d.whitespace, b)
+ d.atBeginningOfLine = false
+ continue
+ }
+
+ if d.atBeginningOfLine {
+ // At the beginning of a line, hyphens have to be escaped.
+ if b == '-' {
+ // The signature isn't calculated over the dash-escaped text so
+ // the escape is only written to buffered.
+ if _, err = d.buffered.Write(dashEscape); err != nil {
+ return
+ }
+ d.h.Write(d.byteBuf)
+ d.atBeginningOfLine = false
+ } else if b == '\n' {
+ // Nothing to do because we delay writing CRLF to the hash.
+ } else {
+ d.h.Write(d.byteBuf)
+ d.atBeginningOfLine = false
+ }
+ if err = d.buffered.WriteByte(b); err != nil {
+ return
+ }
+ } else {
+ if b == '\n' {
+ // We got a raw \n. Drop any trailing whitespace and write a
+ // CRLF.
+ d.whitespace = d.whitespace[:0]
+ // We delay writing CRLF to the hash until the start of the
+ // next line.
+ if err = d.buffered.WriteByte(b); err != nil {
+ return
+ }
+ d.atBeginningOfLine = true
+ } else {
+ // Any buffered whitespace wasn't at the end of the line so
+ // we need to write it out.
+ if len(d.whitespace) > 0 {
+ d.h.Write(d.whitespace)
+ if _, err = d.buffered.Write(d.whitespace); err != nil {
+ return
+ }
+ d.whitespace = d.whitespace[:0]
+ }
+ d.h.Write(d.byteBuf)
+ if err = d.buffered.WriteByte(b); err != nil {
+ return
+ }
+ }
+ }
+ }
+
+ n = len(data)
+ return
+}
+
+func (d *dashEscaper) Close() (err error) {
+ if !d.atBeginningOfLine {
+ if err = d.buffered.WriteByte(lf); err != nil {
+ return
+ }
+ }
+ sig := new(packet.Signature)
+ sig.SigType = packet.SigTypeText
+ sig.PubKeyAlgo = d.privateKey.PubKeyAlgo
+ sig.Hash = d.hashType
+ sig.CreationTime = d.config.Now()
+ sig.IssuerKeyId = &d.privateKey.KeyId
+
+ if err = sig.Sign(d.h, d.privateKey, d.config); err != nil {
+ return
+ }
+
+ out, err := armor.Encode(d.buffered, "PGP SIGNATURE", nil)
+ if err != nil {
+ return
+ }
+
+ if err = sig.Serialize(out); err != nil {
+ return
+ }
+ if err = out.Close(); err != nil {
+ return
+ }
+ if err = d.buffered.Flush(); err != nil {
+ return
+ }
+ return
+}
+
+// Encode returns a WriteCloser which will clear-sign a message with privateKey
+// and write it to w. If config is nil, sensible defaults are used.
+func Encode(w io.Writer, privateKey *packet.PrivateKey, config *packet.Config) (plaintext io.WriteCloser, err error) {
+ if privateKey.Encrypted {
+ return nil, errors.InvalidArgumentError("signing key is encrypted")
+ }
+
+ hashType := config.Hash()
+ name := nameOfHash(hashType)
+ if len(name) == 0 {
+ return nil, errors.UnsupportedError("unknown hash type: " + strconv.Itoa(int(hashType)))
+ }
+
+ if !hashType.Available() {
+ return nil, errors.UnsupportedError("unsupported hash type: " + strconv.Itoa(int(hashType)))
+ }
+ h := hashType.New()
+
+ buffered := bufio.NewWriter(w)
+ // start has a \n at the beginning that we don't want here.
+ if _, err = buffered.Write(start[1:]); err != nil {
+ return
+ }
+ if err = buffered.WriteByte(lf); err != nil {
+ return
+ }
+ if _, err = buffered.WriteString("Hash: "); err != nil {
+ return
+ }
+ if _, err = buffered.WriteString(name); err != nil {
+ return
+ }
+ if err = buffered.WriteByte(lf); err != nil {
+ return
+ }
+ if err = buffered.WriteByte(lf); err != nil {
+ return
+ }
+
+ plaintext = &dashEscaper{
+ buffered: buffered,
+ h: h,
+ hashType: hashType,
+
+ atBeginningOfLine: true,
+ isFirstLine: true,
+
+ byteBuf: make([]byte, 1),
+
+ privateKey: privateKey,
+ config: config,
+ }
+
+ return
+}
+
+// nameOfHash returns the OpenPGP name for the given hash, or the empty string
+// if the name isn't known. See RFC 4880, section 9.4.
+func nameOfHash(h crypto.Hash) string {
+ switch h {
+ case crypto.MD5:
+ return "MD5"
+ case crypto.SHA1:
+ return "SHA1"
+ case crypto.RIPEMD160:
+ return "RIPEMD160"
+ case crypto.SHA224:
+ return "SHA224"
+ case crypto.SHA256:
+ return "SHA256"
+ case crypto.SHA384:
+ return "SHA384"
+ case crypto.SHA512:
+ return "SHA512"
+ }
+ return ""
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/clearsign/clearsign_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/clearsign/clearsign_test.go
new file mode 100644
index 000000000..2c0948078
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/clearsign/clearsign_test.go
@@ -0,0 +1,210 @@
+// Copyright 2012 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 clearsign
+
+import (
+ "bytes"
+ "golang.org/x/crypto/openpgp"
+ "testing"
+)
+
+func testParse(t *testing.T, input []byte, expected, expectedPlaintext string) {
+ b, rest := Decode(input)
+ if b == nil {
+ t.Fatal("failed to decode clearsign message")
+ }
+ if !bytes.Equal(rest, []byte("trailing")) {
+ t.Errorf("unexpected remaining bytes returned: %s", string(rest))
+ }
+ if b.ArmoredSignature.Type != "PGP SIGNATURE" {
+ t.Errorf("bad armor type, got:%s, want:PGP SIGNATURE", b.ArmoredSignature.Type)
+ }
+ if !bytes.Equal(b.Bytes, []byte(expected)) {
+ t.Errorf("bad body, got:%x want:%x", b.Bytes, expected)
+ }
+
+ if !bytes.Equal(b.Plaintext, []byte(expectedPlaintext)) {
+ t.Errorf("bad plaintext, got:%x want:%x", b.Plaintext, expectedPlaintext)
+ }
+
+ keyring, err := openpgp.ReadArmoredKeyRing(bytes.NewBufferString(signingKey))
+ if err != nil {
+ t.Errorf("failed to parse public key: %s", err)
+ }
+
+ if _, err := openpgp.CheckDetachedSignature(keyring, bytes.NewBuffer(b.Bytes), b.ArmoredSignature.Body); err != nil {
+ t.Errorf("failed to check signature: %s", err)
+ }
+}
+
+func TestParse(t *testing.T) {
+ testParse(t, clearsignInput, "Hello world\r\nline 2", "Hello world\nline 2\n")
+ testParse(t, clearsignInput2, "\r\n\r\n(This message has a couple of blank lines at the start and end.)\r\n\r\n", "\n\n(This message has a couple of blank lines at the start and end.)\n\n\n")
+}
+
+func TestParseInvalid(t *testing.T) {
+ if b, _ := Decode(clearsignInput3); b != nil {
+ t.Fatal("decoded a bad clearsigned message without any error")
+ }
+}
+
+func TestParseWithNoNewlineAtEnd(t *testing.T) {
+ input := clearsignInput
+ input = input[:len(input)-len("trailing")-1]
+ b, rest := Decode(input)
+ if b == nil {
+ t.Fatal("failed to decode clearsign message")
+ }
+ if len(rest) > 0 {
+ t.Errorf("unexpected remaining bytes returned: %s", string(rest))
+ }
+}
+
+var signingTests = []struct {
+ in, signed, plaintext string
+}{
+ {"", "", ""},
+ {"a", "a", "a\n"},
+ {"a\n", "a", "a\n"},
+ {"-a\n", "-a", "-a\n"},
+ {"--a\nb", "--a\r\nb", "--a\nb\n"},
+ // leading whitespace
+ {" a\n", " a", " a\n"},
+ {" a\n", " a", " a\n"},
+ // trailing whitespace (should be stripped)
+ {"a \n", "a", "a\n"},
+ {"a ", "a", "a\n"},
+ // whitespace-only lines (should be stripped)
+ {" \n", "", "\n"},
+ {" ", "", "\n"},
+ {"a\n \n \nb\n", "a\r\n\r\n\r\nb", "a\n\n\nb\n"},
+}
+
+func TestSigning(t *testing.T) {
+ keyring, err := openpgp.ReadArmoredKeyRing(bytes.NewBufferString(signingKey))
+ if err != nil {
+ t.Errorf("failed to parse public key: %s", err)
+ }
+
+ for i, test := range signingTests {
+ var buf bytes.Buffer
+
+ plaintext, err := Encode(&buf, keyring[0].PrivateKey, nil)
+ if err != nil {
+ t.Errorf("#%d: error from Encode: %s", i, err)
+ continue
+ }
+ if _, err := plaintext.Write([]byte(test.in)); err != nil {
+ t.Errorf("#%d: error from Write: %s", i, err)
+ continue
+ }
+ if err := plaintext.Close(); err != nil {
+ t.Fatalf("#%d: error from Close: %s", i, err)
+ continue
+ }
+
+ b, _ := Decode(buf.Bytes())
+ if b == nil {
+ t.Errorf("#%d: failed to decode clearsign message", i)
+ continue
+ }
+ if !bytes.Equal(b.Bytes, []byte(test.signed)) {
+ t.Errorf("#%d: bad result, got:%x, want:%x", i, b.Bytes, test.signed)
+ continue
+ }
+ if !bytes.Equal(b.Plaintext, []byte(test.plaintext)) {
+ t.Errorf("#%d: bad result, got:%x, want:%x", i, b.Plaintext, test.plaintext)
+ continue
+ }
+
+ if _, err := openpgp.CheckDetachedSignature(keyring, bytes.NewBuffer(b.Bytes), b.ArmoredSignature.Body); err != nil {
+ t.Errorf("#%d: failed to check signature: %s", i, err)
+ }
+ }
+}
+
+var clearsignInput = []byte(`
+;lasjlkfdsa
+
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA1
+
+Hello world
+line 2
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.4.10 (GNU/Linux)
+
+iJwEAQECAAYFAk8kMuEACgkQO9o98PRieSpMsAQAhmY/vwmNpflrPgmfWsYhk5O8
+pjnBUzZwqTDoDeINjZEoPDSpQAHGhjFjgaDx/Gj4fAl0dM4D0wuUEBb6QOrwflog
+2A2k9kfSOMOtk0IH/H5VuFN1Mie9L/erYXjTQIptv9t9J7NoRBMU0QOOaFU0JaO9
+MyTpno24AjIAGb+mH1U=
+=hIJ6
+-----END PGP SIGNATURE-----
+trailing`)
+
+var clearsignInput2 = []byte(`
+asdlfkjasdlkfjsadf
+
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA256
+
+
+
+(This message has a couple of blank lines at the start and end.)
+
+
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.4.11 (GNU/Linux)
+
+iJwEAQEIAAYFAlPpSREACgkQO9o98PRieSpZTAP+M8QUoCt/7Rf3YbXPcdzIL32v
+pt1I+cMNeopzfLy0u4ioEFi8s5VkwpL1AFmirvgViCwlf82inoRxzZRiW05JQ5LI
+ESEzeCoy2LIdRCQ2hcrG8pIUPzUO4TqO5D/dMbdHwNH4h5nNmGJUAEG6FpURlPm+
+qZg6BaTvOxepqOxnhVU=
+=e+C6
+-----END PGP SIGNATURE-----
+
+trailing`)
+
+var clearsignInput3 = []byte(`
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA256
+
+(This message was truncated.)
+`)
+
+var signingKey = `-----BEGIN PGP PRIVATE KEY BLOCK-----
+Version: GnuPG v1.4.10 (GNU/Linux)
+
+lQHYBE2rFNoBBADFwqWQIW/DSqcB4yCQqnAFTJ27qS5AnB46ccAdw3u4Greeu3Bp
+idpoHdjULy7zSKlwR1EA873dO/k/e11Ml3dlAFUinWeejWaK2ugFP6JjiieSsrKn
+vWNicdCS4HTWn0X4sjl0ZiAygw6GNhqEQ3cpLeL0g8E9hnYzJKQ0LWJa0QARAQAB
+AAP/TB81EIo2VYNmTq0pK1ZXwUpxCrvAAIG3hwKjEzHcbQznsjNvPUihZ+NZQ6+X
+0HCfPAdPkGDCLCb6NavcSW+iNnLTrdDnSI6+3BbIONqWWdRDYJhqZCkqmG6zqSfL
+IdkJgCw94taUg5BWP/AAeQrhzjChvpMQTVKQL5mnuZbUCeMCAN5qrYMP2S9iKdnk
+VANIFj7656ARKt/nf4CBzxcpHTyB8+d2CtPDKCmlJP6vL8t58Jmih+kHJMvC0dzn
+gr5f5+sCAOOe5gt9e0am7AvQWhdbHVfJU0TQJx+m2OiCJAqGTB1nvtBLHdJnfdC9
+TnXXQ6ZXibqLyBies/xeY2sCKL5qtTMCAKnX9+9d/5yQxRyrQUHt1NYhaXZnJbHx
+q4ytu0eWz+5i68IYUSK69jJ1NWPM0T6SkqpB3KCAIv68VFm9PxqG1KmhSrQIVGVz
+dCBLZXmIuAQTAQIAIgUCTasU2gIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AA
+CgkQO9o98PRieSoLhgQAkLEZex02Qt7vGhZzMwuN0R22w3VwyYyjBx+fM3JFETy1
+ut4xcLJoJfIaF5ZS38UplgakHG0FQ+b49i8dMij0aZmDqGxrew1m4kBfjXw9B/v+
+eIqpODryb6cOSwyQFH0lQkXC040pjq9YqDsO5w0WYNXYKDnzRV0p4H1pweo2VDid
+AdgETasU2gEEAN46UPeWRqKHvA99arOxee38fBt2CI08iiWyI8T3J6ivtFGixSqV
+bRcPxYO/qLpVe5l84Nb3X71GfVXlc9hyv7CD6tcowL59hg1E/DC5ydI8K8iEpUmK
+/UnHdIY5h8/kqgGxkY/T/hgp5fRQgW1ZoZxLajVlMRZ8W4tFtT0DeA+JABEBAAEA
+A/0bE1jaaZKj6ndqcw86jd+QtD1SF+Cf21CWRNeLKnUds4FRRvclzTyUMuWPkUeX
+TaNNsUOFqBsf6QQ2oHUBBK4VCHffHCW4ZEX2cd6umz7mpHW6XzN4DECEzOVksXtc
+lUC1j4UB91DC/RNQqwX1IV2QLSwssVotPMPqhOi0ZLNY7wIA3n7DWKInxYZZ4K+6
+rQ+POsz6brEoRHwr8x6XlHenq1Oki855pSa1yXIARoTrSJkBtn5oI+f8AzrnN0BN
+oyeQAwIA/7E++3HDi5aweWrViiul9cd3rcsS0dEnksPhvS0ozCJiHsq/6GFmy7J8
+QSHZPteedBnZyNp5jR+H7cIfVN3KgwH/Skq4PsuPhDq5TKK6i8Pc1WW8MA6DXTdU
+nLkX7RGmMwjC0DBf7KWAlPjFaONAX3a8ndnz//fy1q7u2l9AZwrj1qa1iJ8EGAEC
+AAkFAk2rFNoCGwwACgkQO9o98PRieSo2/QP/WTzr4ioINVsvN1akKuekmEMI3LAp
+BfHwatufxxP1U+3Si/6YIk7kuPB9Hs+pRqCXzbvPRrI8NHZBmc8qIGthishdCYad
+AHcVnXjtxrULkQFGbGvhKURLvS9WnzD/m1K2zzwxzkPTzT9/Yf06O6Mal5AdugPL
+VrM0m72/jnpKo04=
+=zNCn
+-----END PGP PRIVATE KEY BLOCK-----
+`
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/elgamal/elgamal.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/elgamal/elgamal.go
new file mode 100644
index 000000000..73f4fe378
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/elgamal/elgamal.go
@@ -0,0 +1,122 @@
+// Copyright 2011 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 elgamal implements ElGamal encryption, suitable for OpenPGP,
+// as specified in "A Public-Key Cryptosystem and a Signature Scheme Based on
+// Discrete Logarithms," IEEE Transactions on Information Theory, v. IT-31,
+// n. 4, 1985, pp. 469-472.
+//
+// This form of ElGamal embeds PKCS#1 v1.5 padding, which may make it
+// unsuitable for other protocols. RSA should be used in preference in any
+// case.
+package elgamal // import "golang.org/x/crypto/openpgp/elgamal"
+
+import (
+ "crypto/rand"
+ "crypto/subtle"
+ "errors"
+ "io"
+ "math/big"
+)
+
+// PublicKey represents an ElGamal public key.
+type PublicKey struct {
+ G, P, Y *big.Int
+}
+
+// PrivateKey represents an ElGamal private key.
+type PrivateKey struct {
+ PublicKey
+ X *big.Int
+}
+
+// Encrypt encrypts the given message to the given public key. The result is a
+// pair of integers. Errors can result from reading random, or because msg is
+// too large to be encrypted to the public key.
+func Encrypt(random io.Reader, pub *PublicKey, msg []byte) (c1, c2 *big.Int, err error) {
+ pLen := (pub.P.BitLen() + 7) / 8
+ if len(msg) > pLen-11 {
+ err = errors.New("elgamal: message too long")
+ return
+ }
+
+ // EM = 0x02 || PS || 0x00 || M
+ em := make([]byte, pLen-1)
+ em[0] = 2
+ ps, mm := em[1:len(em)-len(msg)-1], em[len(em)-len(msg):]
+ err = nonZeroRandomBytes(ps, random)
+ if err != nil {
+ return
+ }
+ em[len(em)-len(msg)-1] = 0
+ copy(mm, msg)
+
+ m := new(big.Int).SetBytes(em)
+
+ k, err := rand.Int(random, pub.P)
+ if err != nil {
+ return
+ }
+
+ c1 = new(big.Int).Exp(pub.G, k, pub.P)
+ s := new(big.Int).Exp(pub.Y, k, pub.P)
+ c2 = s.Mul(s, m)
+ c2.Mod(c2, pub.P)
+
+ return
+}
+
+// Decrypt takes two integers, resulting from an ElGamal encryption, and
+// returns the plaintext of the message. An error can result only if the
+// ciphertext is invalid. Users should keep in mind that this is a padding
+// oracle and thus, if exposed to an adaptive chosen ciphertext attack, can
+// be used to break the cryptosystem. See ``Chosen Ciphertext Attacks
+// Against Protocols Based on the RSA Encryption Standard PKCS #1'', Daniel
+// Bleichenbacher, Advances in Cryptology (Crypto '98),
+func Decrypt(priv *PrivateKey, c1, c2 *big.Int) (msg []byte, err error) {
+ s := new(big.Int).Exp(c1, priv.X, priv.P)
+ s.ModInverse(s, priv.P)
+ s.Mul(s, c2)
+ s.Mod(s, priv.P)
+ em := s.Bytes()
+
+ firstByteIsTwo := subtle.ConstantTimeByteEq(em[0], 2)
+
+ // The remainder of the plaintext must be a string of non-zero random
+ // octets, followed by a 0, followed by the message.
+ // lookingForIndex: 1 iff we are still looking for the zero.
+ // index: the offset of the first zero byte.
+ var lookingForIndex, index int
+ lookingForIndex = 1
+
+ for i := 1; i < len(em); i++ {
+ equals0 := subtle.ConstantTimeByteEq(em[i], 0)
+ index = subtle.ConstantTimeSelect(lookingForIndex&equals0, i, index)
+ lookingForIndex = subtle.ConstantTimeSelect(equals0, 0, lookingForIndex)
+ }
+
+ if firstByteIsTwo != 1 || lookingForIndex != 0 || index < 9 {
+ return nil, errors.New("elgamal: decryption error")
+ }
+ return em[index+1:], nil
+}
+
+// nonZeroRandomBytes fills the given slice with non-zero random octets.
+func nonZeroRandomBytes(s []byte, rand io.Reader) (err error) {
+ _, err = io.ReadFull(rand, s)
+ if err != nil {
+ return
+ }
+
+ for i := 0; i < len(s); i++ {
+ for s[i] == 0 {
+ _, err = io.ReadFull(rand, s[i:i+1])
+ if err != nil {
+ return
+ }
+ }
+ }
+
+ return
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/elgamal/elgamal_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/elgamal/elgamal_test.go
new file mode 100644
index 000000000..c4f99f5c4
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/elgamal/elgamal_test.go
@@ -0,0 +1,49 @@
+// Copyright 2011 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 elgamal
+
+import (
+ "bytes"
+ "crypto/rand"
+ "math/big"
+ "testing"
+)
+
+// This is the 1024-bit MODP group from RFC 5114, section 2.1:
+const primeHex = "B10B8F96A080E01DDE92DE5EAE5D54EC52C99FBCFB06A3C69A6A9DCA52D23B616073E28675A23D189838EF1E2EE652C013ECB4AEA906112324975C3CD49B83BFACCBDD7D90C4BD7098488E9C219A73724EFFD6FAE5644738FAA31A4FF55BCCC0A151AF5F0DC8B4BD45BF37DF365C1A65E68CFDA76D4DA708DF1FB2BC2E4A4371"
+
+const generatorHex = "A4D1CBD5C3FD34126765A442EFB99905F8104DD258AC507FD6406CFF14266D31266FEA1E5C41564B777E690F5504F213160217B4B01B886A5E91547F9E2749F4D7FBD7D3B9A92EE1909D0D2263F80A76A6A24C087A091F531DBF0A0169B6A28AD662A4D18E73AFA32D779D5918D08BC8858F4DCEF97C2A24855E6EEB22B3B2E5"
+
+func fromHex(hex string) *big.Int {
+ n, ok := new(big.Int).SetString(hex, 16)
+ if !ok {
+ panic("failed to parse hex number")
+ }
+ return n
+}
+
+func TestEncryptDecrypt(t *testing.T) {
+ priv := &PrivateKey{
+ PublicKey: PublicKey{
+ G: fromHex(generatorHex),
+ P: fromHex(primeHex),
+ },
+ X: fromHex("42"),
+ }
+ priv.Y = new(big.Int).Exp(priv.G, priv.X, priv.P)
+
+ message := []byte("hello world")
+ c1, c2, err := Encrypt(rand.Reader, &priv.PublicKey, message)
+ if err != nil {
+ t.Errorf("error encrypting: %s", err)
+ }
+ message2, err := Decrypt(priv, c1, c2)
+ if err != nil {
+ t.Errorf("error decrypting: %s", err)
+ }
+ if !bytes.Equal(message2, message) {
+ t.Errorf("decryption failed, got: %x, want: %x", message2, message)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/errors/errors.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/errors/errors.go
new file mode 100644
index 000000000..eb0550b2d
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/errors/errors.go
@@ -0,0 +1,72 @@
+// Copyright 2010 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 errors contains common error types for the OpenPGP packages.
+package errors // import "golang.org/x/crypto/openpgp/errors"
+
+import (
+ "strconv"
+)
+
+// A StructuralError is returned when OpenPGP data is found to be syntactically
+// invalid.
+type StructuralError string
+
+func (s StructuralError) Error() string {
+ return "openpgp: invalid data: " + string(s)
+}
+
+// UnsupportedError indicates that, although the OpenPGP data is valid, it
+// makes use of currently unimplemented features.
+type UnsupportedError string
+
+func (s UnsupportedError) Error() string {
+ return "openpgp: unsupported feature: " + string(s)
+}
+
+// InvalidArgumentError indicates that the caller is in error and passed an
+// incorrect value.
+type InvalidArgumentError string
+
+func (i InvalidArgumentError) Error() string {
+ return "openpgp: invalid argument: " + string(i)
+}
+
+// SignatureError indicates that a syntactically valid signature failed to
+// validate.
+type SignatureError string
+
+func (b SignatureError) Error() string {
+ return "openpgp: invalid signature: " + string(b)
+}
+
+type keyIncorrectError int
+
+func (ki keyIncorrectError) Error() string {
+ return "openpgp: incorrect key"
+}
+
+var ErrKeyIncorrect error = keyIncorrectError(0)
+
+type unknownIssuerError int
+
+func (unknownIssuerError) Error() string {
+ return "openpgp: signature made by unknown entity"
+}
+
+var ErrUnknownIssuer error = unknownIssuerError(0)
+
+type keyRevokedError int
+
+func (keyRevokedError) Error() string {
+ return "openpgp: signature made by revoked key"
+}
+
+var ErrKeyRevoked error = keyRevokedError(0)
+
+type UnknownPacketTypeError uint8
+
+func (upte UnknownPacketTypeError) Error() string {
+ return "openpgp: unknown packet type: " + strconv.Itoa(int(upte))
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/keys.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/keys.go
new file mode 100644
index 000000000..68b14c6ae
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/keys.go
@@ -0,0 +1,637 @@
+// Copyright 2011 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 openpgp
+
+import (
+ "crypto/rsa"
+ "io"
+ "time"
+
+ "golang.org/x/crypto/openpgp/armor"
+ "golang.org/x/crypto/openpgp/errors"
+ "golang.org/x/crypto/openpgp/packet"
+)
+
+// PublicKeyType is the armor type for a PGP public key.
+var PublicKeyType = "PGP PUBLIC KEY BLOCK"
+
+// PrivateKeyType is the armor type for a PGP private key.
+var PrivateKeyType = "PGP PRIVATE KEY BLOCK"
+
+// An Entity represents the components of an OpenPGP key: a primary public key
+// (which must be a signing key), one or more identities claimed by that key,
+// and zero or more subkeys, which may be encryption keys.
+type Entity struct {
+ PrimaryKey *packet.PublicKey
+ PrivateKey *packet.PrivateKey
+ Identities map[string]*Identity // indexed by Identity.Name
+ Revocations []*packet.Signature
+ Subkeys []Subkey
+}
+
+// An Identity represents an identity claimed by an Entity and zero or more
+// assertions by other entities about that claim.
+type Identity struct {
+ Name string // by convention, has the form "Full Name (comment) <email@example.com>"
+ UserId *packet.UserId
+ SelfSignature *packet.Signature
+ Signatures []*packet.Signature
+}
+
+// A Subkey is an additional public key in an Entity. Subkeys can be used for
+// encryption.
+type Subkey struct {
+ PublicKey *packet.PublicKey
+ PrivateKey *packet.PrivateKey
+ Sig *packet.Signature
+}
+
+// A Key identifies a specific public key in an Entity. This is either the
+// Entity's primary key or a subkey.
+type Key struct {
+ Entity *Entity
+ PublicKey *packet.PublicKey
+ PrivateKey *packet.PrivateKey
+ SelfSignature *packet.Signature
+}
+
+// A KeyRing provides access to public and private keys.
+type KeyRing interface {
+ // KeysById returns the set of keys that have the given key id.
+ KeysById(id uint64) []Key
+ // KeysByIdAndUsage returns the set of keys with the given id
+ // that also meet the key usage given by requiredUsage.
+ // The requiredUsage is expressed as the bitwise-OR of
+ // packet.KeyFlag* values.
+ KeysByIdUsage(id uint64, requiredUsage byte) []Key
+ // DecryptionKeys returns all private keys that are valid for
+ // decryption.
+ DecryptionKeys() []Key
+}
+
+// primaryIdentity returns the Identity marked as primary or the first identity
+// if none are so marked.
+func (e *Entity) primaryIdentity() *Identity {
+ var firstIdentity *Identity
+ for _, ident := range e.Identities {
+ if firstIdentity == nil {
+ firstIdentity = ident
+ }
+ if ident.SelfSignature.IsPrimaryId != nil && *ident.SelfSignature.IsPrimaryId {
+ return ident
+ }
+ }
+ return firstIdentity
+}
+
+// encryptionKey returns the best candidate Key for encrypting a message to the
+// given Entity.
+func (e *Entity) encryptionKey(now time.Time) (Key, bool) {
+ candidateSubkey := -1
+
+ // Iterate the keys to find the newest key
+ var maxTime time.Time
+ for i, subkey := range e.Subkeys {
+ if subkey.Sig.FlagsValid &&
+ subkey.Sig.FlagEncryptCommunications &&
+ subkey.PublicKey.PubKeyAlgo.CanEncrypt() &&
+ !subkey.Sig.KeyExpired(now) &&
+ (maxTime.IsZero() || subkey.Sig.CreationTime.After(maxTime)) {
+ candidateSubkey = i
+ maxTime = subkey.Sig.CreationTime
+ }
+ }
+
+ if candidateSubkey != -1 {
+ subkey := e.Subkeys[candidateSubkey]
+ return Key{e, subkey.PublicKey, subkey.PrivateKey, subkey.Sig}, true
+ }
+
+ // If we don't have any candidate subkeys for encryption and
+ // the primary key doesn't have any usage metadata then we
+ // assume that the primary key is ok. Or, if the primary key is
+ // marked as ok to encrypt to, then we can obviously use it.
+ i := e.primaryIdentity()
+ if !i.SelfSignature.FlagsValid || i.SelfSignature.FlagEncryptCommunications &&
+ e.PrimaryKey.PubKeyAlgo.CanEncrypt() &&
+ !i.SelfSignature.KeyExpired(now) {
+ return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature}, true
+ }
+
+ // This Entity appears to be signing only.
+ return Key{}, false
+}
+
+// signingKey return the best candidate Key for signing a message with this
+// Entity.
+func (e *Entity) signingKey(now time.Time) (Key, bool) {
+ candidateSubkey := -1
+
+ for i, subkey := range e.Subkeys {
+ if subkey.Sig.FlagsValid &&
+ subkey.Sig.FlagSign &&
+ subkey.PublicKey.PubKeyAlgo.CanSign() &&
+ !subkey.Sig.KeyExpired(now) {
+ candidateSubkey = i
+ break
+ }
+ }
+
+ if candidateSubkey != -1 {
+ subkey := e.Subkeys[candidateSubkey]
+ return Key{e, subkey.PublicKey, subkey.PrivateKey, subkey.Sig}, true
+ }
+
+ // If we have no candidate subkey then we assume that it's ok to sign
+ // with the primary key.
+ i := e.primaryIdentity()
+ if !i.SelfSignature.FlagsValid || i.SelfSignature.FlagSign &&
+ !i.SelfSignature.KeyExpired(now) {
+ return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature}, true
+ }
+
+ return Key{}, false
+}
+
+// An EntityList contains one or more Entities.
+type EntityList []*Entity
+
+// KeysById returns the set of keys that have the given key id.
+func (el EntityList) KeysById(id uint64) (keys []Key) {
+ for _, e := range el {
+ if e.PrimaryKey.KeyId == id {
+ var selfSig *packet.Signature
+ for _, ident := range e.Identities {
+ if selfSig == nil {
+ selfSig = ident.SelfSignature
+ } else if ident.SelfSignature.IsPrimaryId != nil && *ident.SelfSignature.IsPrimaryId {
+ selfSig = ident.SelfSignature
+ break
+ }
+ }
+ keys = append(keys, Key{e, e.PrimaryKey, e.PrivateKey, selfSig})
+ }
+
+ for _, subKey := range e.Subkeys {
+ if subKey.PublicKey.KeyId == id {
+ keys = append(keys, Key{e, subKey.PublicKey, subKey.PrivateKey, subKey.Sig})
+ }
+ }
+ }
+ return
+}
+
+// KeysByIdAndUsage returns the set of keys with the given id that also meet
+// the key usage given by requiredUsage. The requiredUsage is expressed as
+// the bitwise-OR of packet.KeyFlag* values.
+func (el EntityList) KeysByIdUsage(id uint64, requiredUsage byte) (keys []Key) {
+ for _, key := range el.KeysById(id) {
+ if len(key.Entity.Revocations) > 0 {
+ continue
+ }
+
+ if key.SelfSignature.RevocationReason != nil {
+ continue
+ }
+
+ if key.SelfSignature.FlagsValid && requiredUsage != 0 {
+ var usage byte
+ if key.SelfSignature.FlagCertify {
+ usage |= packet.KeyFlagCertify
+ }
+ if key.SelfSignature.FlagSign {
+ usage |= packet.KeyFlagSign
+ }
+ if key.SelfSignature.FlagEncryptCommunications {
+ usage |= packet.KeyFlagEncryptCommunications
+ }
+ if key.SelfSignature.FlagEncryptStorage {
+ usage |= packet.KeyFlagEncryptStorage
+ }
+ if usage&requiredUsage != requiredUsage {
+ continue
+ }
+ }
+
+ keys = append(keys, key)
+ }
+ return
+}
+
+// DecryptionKeys returns all private keys that are valid for decryption.
+func (el EntityList) DecryptionKeys() (keys []Key) {
+ for _, e := range el {
+ for _, subKey := range e.Subkeys {
+ if subKey.PrivateKey != nil && (!subKey.Sig.FlagsValid || subKey.Sig.FlagEncryptStorage || subKey.Sig.FlagEncryptCommunications) {
+ keys = append(keys, Key{e, subKey.PublicKey, subKey.PrivateKey, subKey.Sig})
+ }
+ }
+ }
+ return
+}
+
+// ReadArmoredKeyRing reads one or more public/private keys from an armor keyring file.
+func ReadArmoredKeyRing(r io.Reader) (EntityList, error) {
+ block, err := armor.Decode(r)
+ if err == io.EOF {
+ return nil, errors.InvalidArgumentError("no armored data found")
+ }
+ if err != nil {
+ return nil, err
+ }
+ if block.Type != PublicKeyType && block.Type != PrivateKeyType {
+ return nil, errors.InvalidArgumentError("expected public or private key block, got: " + block.Type)
+ }
+
+ return ReadKeyRing(block.Body)
+}
+
+// ReadKeyRing reads one or more public/private keys. Unsupported keys are
+// ignored as long as at least a single valid key is found.
+func ReadKeyRing(r io.Reader) (el EntityList, err error) {
+ packets := packet.NewReader(r)
+ var lastUnsupportedError error
+
+ for {
+ var e *Entity
+ e, err = ReadEntity(packets)
+ if err != nil {
+ // TODO: warn about skipped unsupported/unreadable keys
+ if _, ok := err.(errors.UnsupportedError); ok {
+ lastUnsupportedError = err
+ err = readToNextPublicKey(packets)
+ } else if _, ok := err.(errors.StructuralError); ok {
+ // Skip unreadable, badly-formatted keys
+ lastUnsupportedError = err
+ err = readToNextPublicKey(packets)
+ }
+ if err == io.EOF {
+ err = nil
+ break
+ }
+ if err != nil {
+ el = nil
+ break
+ }
+ } else {
+ el = append(el, e)
+ }
+ }
+
+ if len(el) == 0 && err == nil {
+ err = lastUnsupportedError
+ }
+ return
+}
+
+// readToNextPublicKey reads packets until the start of the entity and leaves
+// the first packet of the new entity in the Reader.
+func readToNextPublicKey(packets *packet.Reader) (err error) {
+ var p packet.Packet
+ for {
+ p, err = packets.Next()
+ if err == io.EOF {
+ return
+ } else if err != nil {
+ if _, ok := err.(errors.UnsupportedError); ok {
+ err = nil
+ continue
+ }
+ return
+ }
+
+ if pk, ok := p.(*packet.PublicKey); ok && !pk.IsSubkey {
+ packets.Unread(p)
+ return
+ }
+ }
+}
+
+// ReadEntity reads an entity (public key, identities, subkeys etc) from the
+// given Reader.
+func ReadEntity(packets *packet.Reader) (*Entity, error) {
+ e := new(Entity)
+ e.Identities = make(map[string]*Identity)
+
+ p, err := packets.Next()
+ if err != nil {
+ return nil, err
+ }
+
+ var ok bool
+ if e.PrimaryKey, ok = p.(*packet.PublicKey); !ok {
+ if e.PrivateKey, ok = p.(*packet.PrivateKey); !ok {
+ packets.Unread(p)
+ return nil, errors.StructuralError("first packet was not a public/private key")
+ } else {
+ e.PrimaryKey = &e.PrivateKey.PublicKey
+ }
+ }
+
+ if !e.PrimaryKey.PubKeyAlgo.CanSign() {
+ return nil, errors.StructuralError("primary key cannot be used for signatures")
+ }
+
+ var current *Identity
+ var revocations []*packet.Signature
+EachPacket:
+ for {
+ p, err := packets.Next()
+ if err == io.EOF {
+ break
+ } else if err != nil {
+ return nil, err
+ }
+
+ switch pkt := p.(type) {
+ case *packet.UserId:
+ current = new(Identity)
+ current.Name = pkt.Id
+ current.UserId = pkt
+ e.Identities[pkt.Id] = current
+
+ for {
+ p, err = packets.Next()
+ if err == io.EOF {
+ return nil, io.ErrUnexpectedEOF
+ } else if err != nil {
+ return nil, err
+ }
+
+ sig, ok := p.(*packet.Signature)
+ if !ok {
+ return nil, errors.StructuralError("user ID packet not followed by self-signature")
+ }
+
+ if (sig.SigType == packet.SigTypePositiveCert || sig.SigType == packet.SigTypeGenericCert) && sig.IssuerKeyId != nil && *sig.IssuerKeyId == e.PrimaryKey.KeyId {
+ if err = e.PrimaryKey.VerifyUserIdSignature(pkt.Id, e.PrimaryKey, sig); err != nil {
+ return nil, errors.StructuralError("user ID self-signature invalid: " + err.Error())
+ }
+ current.SelfSignature = sig
+ break
+ }
+ current.Signatures = append(current.Signatures, sig)
+ }
+ case *packet.Signature:
+ if pkt.SigType == packet.SigTypeKeyRevocation {
+ revocations = append(revocations, pkt)
+ } else if pkt.SigType == packet.SigTypeDirectSignature {
+ // TODO: RFC4880 5.2.1 permits signatures
+ // directly on keys (eg. to bind additional
+ // revocation keys).
+ } else if current == nil {
+ return nil, errors.StructuralError("signature packet found before user id packet")
+ } else {
+ current.Signatures = append(current.Signatures, pkt)
+ }
+ case *packet.PrivateKey:
+ if pkt.IsSubkey == false {
+ packets.Unread(p)
+ break EachPacket
+ }
+ err = addSubkey(e, packets, &pkt.PublicKey, pkt)
+ if err != nil {
+ return nil, err
+ }
+ case *packet.PublicKey:
+ if pkt.IsSubkey == false {
+ packets.Unread(p)
+ break EachPacket
+ }
+ err = addSubkey(e, packets, pkt, nil)
+ if err != nil {
+ return nil, err
+ }
+ default:
+ // we ignore unknown packets
+ }
+ }
+
+ if len(e.Identities) == 0 {
+ return nil, errors.StructuralError("entity without any identities")
+ }
+
+ for _, revocation := range revocations {
+ err = e.PrimaryKey.VerifyRevocationSignature(revocation)
+ if err == nil {
+ e.Revocations = append(e.Revocations, revocation)
+ } else {
+ // TODO: RFC 4880 5.2.3.15 defines revocation keys.
+ return nil, errors.StructuralError("revocation signature signed by alternate key")
+ }
+ }
+
+ return e, nil
+}
+
+func addSubkey(e *Entity, packets *packet.Reader, pub *packet.PublicKey, priv *packet.PrivateKey) error {
+ var subKey Subkey
+ subKey.PublicKey = pub
+ subKey.PrivateKey = priv
+ p, err := packets.Next()
+ if err == io.EOF {
+ return io.ErrUnexpectedEOF
+ }
+ if err != nil {
+ return errors.StructuralError("subkey signature invalid: " + err.Error())
+ }
+ var ok bool
+ subKey.Sig, ok = p.(*packet.Signature)
+ if !ok {
+ return errors.StructuralError("subkey packet not followed by signature")
+ }
+ if subKey.Sig.SigType != packet.SigTypeSubkeyBinding && subKey.Sig.SigType != packet.SigTypeSubkeyRevocation {
+ return errors.StructuralError("subkey signature with wrong type")
+ }
+ err = e.PrimaryKey.VerifyKeySignature(subKey.PublicKey, subKey.Sig)
+ if err != nil {
+ return errors.StructuralError("subkey signature invalid: " + err.Error())
+ }
+ e.Subkeys = append(e.Subkeys, subKey)
+ return nil
+}
+
+const defaultRSAKeyBits = 2048
+
+// NewEntity returns an Entity that contains a fresh RSA/RSA keypair with a
+// single identity composed of the given full name, comment and email, any of
+// which may be empty but must not contain any of "()<>\x00".
+// If config is nil, sensible defaults will be used.
+func NewEntity(name, comment, email string, config *packet.Config) (*Entity, error) {
+ currentTime := config.Now()
+
+ bits := defaultRSAKeyBits
+ if config != nil && config.RSABits != 0 {
+ bits = config.RSABits
+ }
+
+ uid := packet.NewUserId(name, comment, email)
+ if uid == nil {
+ return nil, errors.InvalidArgumentError("user id field contained invalid characters")
+ }
+ signingPriv, err := rsa.GenerateKey(config.Random(), bits)
+ if err != nil {
+ return nil, err
+ }
+ encryptingPriv, err := rsa.GenerateKey(config.Random(), bits)
+ if err != nil {
+ return nil, err
+ }
+
+ e := &Entity{
+ PrimaryKey: packet.NewRSAPublicKey(currentTime, &signingPriv.PublicKey),
+ PrivateKey: packet.NewRSAPrivateKey(currentTime, signingPriv),
+ Identities: make(map[string]*Identity),
+ }
+ isPrimaryId := true
+ e.Identities[uid.Id] = &Identity{
+ Name: uid.Name,
+ UserId: uid,
+ SelfSignature: &packet.Signature{
+ CreationTime: currentTime,
+ SigType: packet.SigTypePositiveCert,
+ PubKeyAlgo: packet.PubKeyAlgoRSA,
+ Hash: config.Hash(),
+ IsPrimaryId: &isPrimaryId,
+ FlagsValid: true,
+ FlagSign: true,
+ FlagCertify: true,
+ IssuerKeyId: &e.PrimaryKey.KeyId,
+ },
+ }
+
+ // If the user passes in a DefaultHash via packet.Config,
+ // set the PreferredHash for the SelfSignature.
+ if config != nil && config.DefaultHash != 0 {
+ e.Identities[uid.Id].SelfSignature.PreferredHash = []uint8{hashToHashId(config.DefaultHash)}
+ }
+
+ e.Subkeys = make([]Subkey, 1)
+ e.Subkeys[0] = Subkey{
+ PublicKey: packet.NewRSAPublicKey(currentTime, &encryptingPriv.PublicKey),
+ PrivateKey: packet.NewRSAPrivateKey(currentTime, encryptingPriv),
+ Sig: &packet.Signature{
+ CreationTime: currentTime,
+ SigType: packet.SigTypeSubkeyBinding,
+ PubKeyAlgo: packet.PubKeyAlgoRSA,
+ Hash: config.Hash(),
+ FlagsValid: true,
+ FlagEncryptStorage: true,
+ FlagEncryptCommunications: true,
+ IssuerKeyId: &e.PrimaryKey.KeyId,
+ },
+ }
+ e.Subkeys[0].PublicKey.IsSubkey = true
+ e.Subkeys[0].PrivateKey.IsSubkey = true
+
+ return e, nil
+}
+
+// SerializePrivate serializes an Entity, including private key material, to
+// the given Writer. For now, it must only be used on an Entity returned from
+// NewEntity.
+// If config is nil, sensible defaults will be used.
+func (e *Entity) SerializePrivate(w io.Writer, config *packet.Config) (err error) {
+ err = e.PrivateKey.Serialize(w)
+ if err != nil {
+ return
+ }
+ for _, ident := range e.Identities {
+ err = ident.UserId.Serialize(w)
+ if err != nil {
+ return
+ }
+ err = ident.SelfSignature.SignUserId(ident.UserId.Id, e.PrimaryKey, e.PrivateKey, config)
+ if err != nil {
+ return
+ }
+ err = ident.SelfSignature.Serialize(w)
+ if err != nil {
+ return
+ }
+ }
+ for _, subkey := range e.Subkeys {
+ err = subkey.PrivateKey.Serialize(w)
+ if err != nil {
+ return
+ }
+ err = subkey.Sig.SignKey(subkey.PublicKey, e.PrivateKey, config)
+ if err != nil {
+ return
+ }
+ err = subkey.Sig.Serialize(w)
+ if err != nil {
+ return
+ }
+ }
+ return nil
+}
+
+// Serialize writes the public part of the given Entity to w. (No private
+// key material will be output).
+func (e *Entity) Serialize(w io.Writer) error {
+ err := e.PrimaryKey.Serialize(w)
+ if err != nil {
+ return err
+ }
+ for _, ident := range e.Identities {
+ err = ident.UserId.Serialize(w)
+ if err != nil {
+ return err
+ }
+ err = ident.SelfSignature.Serialize(w)
+ if err != nil {
+ return err
+ }
+ for _, sig := range ident.Signatures {
+ err = sig.Serialize(w)
+ if err != nil {
+ return err
+ }
+ }
+ }
+ for _, subkey := range e.Subkeys {
+ err = subkey.PublicKey.Serialize(w)
+ if err != nil {
+ return err
+ }
+ err = subkey.Sig.Serialize(w)
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// SignIdentity adds a signature to e, from signer, attesting that identity is
+// associated with e. The provided identity must already be an element of
+// e.Identities and the private key of signer must have been decrypted if
+// necessary.
+// If config is nil, sensible defaults will be used.
+func (e *Entity) SignIdentity(identity string, signer *Entity, config *packet.Config) error {
+ if signer.PrivateKey == nil {
+ return errors.InvalidArgumentError("signing Entity must have a private key")
+ }
+ if signer.PrivateKey.Encrypted {
+ return errors.InvalidArgumentError("signing Entity's private key must be decrypted")
+ }
+ ident, ok := e.Identities[identity]
+ if !ok {
+ return errors.InvalidArgumentError("given identity string not found in Entity")
+ }
+
+ sig := &packet.Signature{
+ SigType: packet.SigTypeGenericCert,
+ PubKeyAlgo: signer.PrivateKey.PubKeyAlgo,
+ Hash: config.Hash(),
+ CreationTime: config.Now(),
+ IssuerKeyId: &signer.PrivateKey.KeyId,
+ }
+ if err := sig.SignUserId(identity, e.PrimaryKey, signer.PrivateKey, config); err != nil {
+ return err
+ }
+ ident.Signatures = append(ident.Signatures, sig)
+ return nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/keys_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/keys_test.go
new file mode 100644
index 000000000..76ba13ed1
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/keys_test.go
@@ -0,0 +1,419 @@
+package openpgp
+
+import (
+ "bytes"
+ "crypto"
+ "strings"
+ "testing"
+ "time"
+
+ "golang.org/x/crypto/openpgp/errors"
+ "golang.org/x/crypto/openpgp/packet"
+)
+
+func TestKeyExpiry(t *testing.T) {
+ kring, err := ReadKeyRing(readerFromHex(expiringKeyHex))
+ if err != nil {
+ t.Fatal(err)
+ }
+ entity := kring[0]
+
+ const timeFormat = "2006-01-02"
+ time1, _ := time.Parse(timeFormat, "2013-07-01")
+
+ // The expiringKeyHex key is structured as:
+ //
+ // pub 1024R/5E237D8C created: 2013-07-01 expires: 2013-07-31 usage: SC
+ // sub 1024R/1ABB25A0 created: 2013-07-01 23:11:07 +0200 CEST expires: 2013-07-08 usage: E
+ // sub 1024R/96A672F5 created: 2013-07-01 23:11:23 +0200 CEST expires: 2013-07-31 usage: E
+ //
+ // So this should select the newest, non-expired encryption key.
+ key, _ := entity.encryptionKey(time1)
+ if id := key.PublicKey.KeyIdShortString(); id != "96A672F5" {
+ t.Errorf("Expected key 1ABB25A0 at time %s, but got key %s", time1.Format(timeFormat), id)
+ }
+
+ // Once the first encryption subkey has expired, the second should be
+ // selected.
+ time2, _ := time.Parse(timeFormat, "2013-07-09")
+ key, _ = entity.encryptionKey(time2)
+ if id := key.PublicKey.KeyIdShortString(); id != "96A672F5" {
+ t.Errorf("Expected key 96A672F5 at time %s, but got key %s", time2.Format(timeFormat), id)
+ }
+
+ // Once all the keys have expired, nothing should be returned.
+ time3, _ := time.Parse(timeFormat, "2013-08-01")
+ if key, ok := entity.encryptionKey(time3); ok {
+ t.Errorf("Expected no key at time %s, but got key %s", time3.Format(timeFormat), key.PublicKey.KeyIdShortString())
+ }
+}
+
+func TestMissingCrossSignature(t *testing.T) {
+ // This public key has a signing subkey, but the subkey does not
+ // contain a cross-signature.
+ keys, err := ReadArmoredKeyRing(bytes.NewBufferString(missingCrossSignatureKey))
+ if len(keys) != 0 {
+ t.Errorf("Accepted key with missing cross signature")
+ }
+ if err == nil {
+ t.Fatal("Failed to detect error in keyring with missing cross signature")
+ }
+ structural, ok := err.(errors.StructuralError)
+ if !ok {
+ t.Fatalf("Unexpected class of error: %T. Wanted StructuralError", err)
+ }
+ const expectedMsg = "signing subkey is missing cross-signature"
+ if !strings.Contains(string(structural), expectedMsg) {
+ t.Fatalf("Unexpected error: %q. Expected it to contain %q", err, expectedMsg)
+ }
+}
+
+func TestInvalidCrossSignature(t *testing.T) {
+ // This public key has a signing subkey, and the subkey has an
+ // embedded cross-signature. However, the cross-signature does
+ // not correctly validate over the primary and subkey.
+ keys, err := ReadArmoredKeyRing(bytes.NewBufferString(invalidCrossSignatureKey))
+ if len(keys) != 0 {
+ t.Errorf("Accepted key with invalid cross signature")
+ }
+ if err == nil {
+ t.Fatal("Failed to detect error in keyring with an invalid cross signature")
+ }
+ structural, ok := err.(errors.StructuralError)
+ if !ok {
+ t.Fatalf("Unexpected class of error: %T. Wanted StructuralError", err)
+ }
+ const expectedMsg = "subkey signature invalid"
+ if !strings.Contains(string(structural), expectedMsg) {
+ t.Fatalf("Unexpected error: %q. Expected it to contain %q", err, expectedMsg)
+ }
+}
+
+func TestGoodCrossSignature(t *testing.T) {
+ // This public key has a signing subkey, and the subkey has an
+ // embedded cross-signature which correctly validates over the
+ // primary and subkey.
+ keys, err := ReadArmoredKeyRing(bytes.NewBufferString(goodCrossSignatureKey))
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(keys) != 1 {
+ t.Errorf("Failed to accept key with good cross signature, %d", len(keys))
+ }
+ if len(keys[0].Subkeys) != 1 {
+ t.Errorf("Failed to accept good subkey, %d", len(keys[0].Subkeys))
+ }
+}
+
+// TestExternallyRevokableKey attempts to load and parse a key with a third party revocation permission.
+func TestExternallyRevocableKey(t *testing.T) {
+ kring, err := ReadKeyRing(readerFromHex(subkeyUsageHex))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // The 0xA42704B92866382A key can be revoked by 0xBE3893CB843D0FE70C
+ // according to this signature that appears within the key:
+ // :signature packet: algo 1, keyid A42704B92866382A
+ // version 4, created 1396409682, md5len 0, sigclass 0x1f
+ // digest algo 2, begin of digest a9 84
+ // hashed subpkt 2 len 4 (sig created 2014-04-02)
+ // hashed subpkt 12 len 22 (revocation key: c=80 a=1 f=CE094AA433F7040BB2DDF0BE3893CB843D0FE70C)
+ // hashed subpkt 7 len 1 (not revocable)
+ // subpkt 16 len 8 (issuer key ID A42704B92866382A)
+ // data: [1024 bits]
+
+ id := uint64(0xA42704B92866382A)
+ keys := kring.KeysById(id)
+ if len(keys) != 1 {
+ t.Errorf("Expected to find key id %X, but got %d matches", id, len(keys))
+ }
+}
+
+func TestKeyRevocation(t *testing.T) {
+ kring, err := ReadKeyRing(readerFromHex(revokedKeyHex))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // revokedKeyHex contains these keys:
+ // pub 1024R/9A34F7C0 2014-03-25 [revoked: 2014-03-25]
+ // sub 1024R/1BA3CD60 2014-03-25 [revoked: 2014-03-25]
+ ids := []uint64{0xA401D9F09A34F7C0, 0x5CD3BE0A1BA3CD60}
+
+ for _, id := range ids {
+ keys := kring.KeysById(id)
+ if len(keys) != 1 {
+ t.Errorf("Expected KeysById to find revoked key %X, but got %d matches", id, len(keys))
+ }
+ keys = kring.KeysByIdUsage(id, 0)
+ if len(keys) != 0 {
+ t.Errorf("Expected KeysByIdUsage to filter out revoked key %X, but got %d matches", id, len(keys))
+ }
+ }
+}
+
+func TestSubkeyRevocation(t *testing.T) {
+ kring, err := ReadKeyRing(readerFromHex(revokedSubkeyHex))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // revokedSubkeyHex contains these keys:
+ // pub 1024R/4EF7E4BECCDE97F0 2014-03-25
+ // sub 1024R/D63636E2B96AE423 2014-03-25
+ // sub 1024D/DBCE4EE19529437F 2014-03-25
+ // sub 1024R/677815E371C2FD23 2014-03-25 [revoked: 2014-03-25]
+ validKeys := []uint64{0x4EF7E4BECCDE97F0, 0xD63636E2B96AE423, 0xDBCE4EE19529437F}
+ revokedKey := uint64(0x677815E371C2FD23)
+
+ for _, id := range validKeys {
+ keys := kring.KeysById(id)
+ if len(keys) != 1 {
+ t.Errorf("Expected KeysById to find key %X, but got %d matches", id, len(keys))
+ }
+ keys = kring.KeysByIdUsage(id, 0)
+ if len(keys) != 1 {
+ t.Errorf("Expected KeysByIdUsage to find key %X, but got %d matches", id, len(keys))
+ }
+ }
+
+ keys := kring.KeysById(revokedKey)
+ if len(keys) != 1 {
+ t.Errorf("Expected KeysById to find key %X, but got %d matches", revokedKey, len(keys))
+ }
+
+ keys = kring.KeysByIdUsage(revokedKey, 0)
+ if len(keys) != 0 {
+ t.Errorf("Expected KeysByIdUsage to filter out revoked key %X, but got %d matches", revokedKey, len(keys))
+ }
+}
+
+func TestKeyUsage(t *testing.T) {
+ kring, err := ReadKeyRing(readerFromHex(subkeyUsageHex))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // subkeyUsageHex contains these keys:
+ // pub 1024R/2866382A created: 2014-04-01 expires: never usage: SC
+ // sub 1024R/936C9153 created: 2014-04-01 expires: never usage: E
+ // sub 1024R/64D5F5BB created: 2014-04-02 expires: never usage: E
+ // sub 1024D/BC0BA992 created: 2014-04-02 expires: never usage: S
+ certifiers := []uint64{0xA42704B92866382A}
+ signers := []uint64{0xA42704B92866382A, 0x42CE2C64BC0BA992}
+ encrypters := []uint64{0x09C0C7D9936C9153, 0xC104E98664D5F5BB}
+
+ for _, id := range certifiers {
+ keys := kring.KeysByIdUsage(id, packet.KeyFlagCertify)
+ if len(keys) == 1 {
+ if keys[0].PublicKey.KeyId != id {
+ t.Errorf("Expected to find certifier key id %X, but got %X", id, keys[0].PublicKey.KeyId)
+ }
+ } else {
+ t.Errorf("Expected one match for certifier key id %X, but got %d matches", id, len(keys))
+ }
+ }
+
+ for _, id := range signers {
+ keys := kring.KeysByIdUsage(id, packet.KeyFlagSign)
+ if len(keys) == 1 {
+ if keys[0].PublicKey.KeyId != id {
+ t.Errorf("Expected to find signing key id %X, but got %X", id, keys[0].PublicKey.KeyId)
+ }
+ } else {
+ t.Errorf("Expected one match for signing key id %X, but got %d matches", id, len(keys))
+ }
+
+ // This keyring contains no encryption keys that are also good for signing.
+ keys = kring.KeysByIdUsage(id, packet.KeyFlagEncryptStorage|packet.KeyFlagEncryptCommunications)
+ if len(keys) != 0 {
+ t.Errorf("Unexpected match for encryption key id %X", id)
+ }
+ }
+
+ for _, id := range encrypters {
+ keys := kring.KeysByIdUsage(id, packet.KeyFlagEncryptStorage|packet.KeyFlagEncryptCommunications)
+ if len(keys) == 1 {
+ if keys[0].PublicKey.KeyId != id {
+ t.Errorf("Expected to find encryption key id %X, but got %X", id, keys[0].PublicKey.KeyId)
+ }
+ } else {
+ t.Errorf("Expected one match for encryption key id %X, but got %d matches", id, len(keys))
+ }
+
+ // This keyring contains no encryption keys that are also good for signing.
+ keys = kring.KeysByIdUsage(id, packet.KeyFlagSign)
+ if len(keys) != 0 {
+ t.Errorf("Unexpected match for signing key id %X", id)
+ }
+ }
+}
+
+func TestIdVerification(t *testing.T) {
+ kring, err := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex))
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := kring[1].PrivateKey.Decrypt([]byte("passphrase")); err != nil {
+ t.Fatal(err)
+ }
+
+ const identity = "Test Key 1 (RSA)"
+ if err := kring[0].SignIdentity(identity, kring[1], nil); err != nil {
+ t.Fatal(err)
+ }
+
+ ident, ok := kring[0].Identities[identity]
+ if !ok {
+ t.Fatal("identity missing from key after signing")
+ }
+
+ checked := false
+ for _, sig := range ident.Signatures {
+ if sig.IssuerKeyId == nil || *sig.IssuerKeyId != kring[1].PrimaryKey.KeyId {
+ continue
+ }
+
+ if err := kring[1].PrimaryKey.VerifyUserIdSignature(identity, kring[0].PrimaryKey, sig); err != nil {
+ t.Fatalf("error verifying new identity signature: %s", err)
+ }
+ checked = true
+ break
+ }
+
+ if !checked {
+ t.Fatal("didn't find identity signature in Entity")
+ }
+}
+
+func TestNewEntityWithPreferredHash(t *testing.T) {
+ c := &packet.Config{
+ DefaultHash: crypto.SHA256,
+ }
+ entity, err := NewEntity("Golang Gopher", "Test Key", "no-reply@golang.com", c)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ for _, identity := range entity.Identities {
+ if len(identity.SelfSignature.PreferredHash) == 0 {
+ t.Fatal("didn't find a preferred hash in self signature")
+ }
+ ph := hashToHashId(c.DefaultHash)
+ if identity.SelfSignature.PreferredHash[0] != ph {
+ t.Fatalf("Expected preferred hash to be %d, got %d", ph, identity.SelfSignature.PreferredHash[0])
+ }
+ }
+}
+
+func TestNewEntityWithoutPreferredHash(t *testing.T) {
+ entity, err := NewEntity("Golang Gopher", "Test Key", "no-reply@golang.com", nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ for _, identity := range entity.Identities {
+ if len(identity.SelfSignature.PreferredHash) != 0 {
+ t.Fatalf("Expected preferred hash to be empty but got length %d", len(identity.SelfSignature.PreferredHash))
+ }
+ }
+}
+
+const expiringKeyHex = "988d0451d1ec5d010400ba3385721f2dc3f4ab096b2ee867ab77213f0a27a8538441c35d2fa225b08798a1439a66a5150e6bdc3f40f5d28d588c712394c632b6299f77db8c0d48d37903fb72ebd794d61be6aa774688839e5fdecfe06b2684cc115d240c98c66cb1ef22ae84e3aa0c2b0c28665c1e7d4d044e7f270706193f5223c8d44e0d70b7b8da830011010001b40f4578706972792074657374206b657988be041301020028050251d1ec5d021b03050900278d00060b090807030206150802090a0b0416020301021e01021780000a091072589ad75e237d8c033503fd10506d72837834eb7f994117740723adc39227104b0d326a1161871c0b415d25b4aedef946ca77ea4c05af9c22b32cf98be86ab890111fced1ee3f75e87b7cc3c00dc63bbc85dfab91c0dc2ad9de2c4d13a34659333a85c6acc1a669c5e1d6cecb0cf1e56c10e72d855ae177ddc9e766f9b2dda57ccbb75f57156438bbdb4e42b88d0451d1ec5d0104009c64906559866c5cb61578f5846a94fcee142a489c9b41e67b12bb54cfe86eb9bc8566460f9a720cb00d6526fbccfd4f552071a8e3f7744b1882d01036d811ee5a3fb91a1c568055758f43ba5d2c6a9676b012f3a1a89e47bbf624f1ad571b208f3cc6224eb378f1645dd3d47584463f9eadeacfd1ce6f813064fbfdcc4b5a53001101000188a504180102000f021b0c050251d1f06b050900093e89000a091072589ad75e237d8c20e00400ab8310a41461425b37889c4da28129b5fae6084fafbc0a47dd1adc74a264c6e9c9cc125f40462ee1433072a58384daef88c961c390ed06426a81b464a53194c4e291ddd7e2e2ba3efced01537d713bd111f48437bde2363446200995e8e0d4e528dda377fd1e8f8ede9c8e2198b393bd86852ce7457a7e3daf74d510461a5b77b88d0451d1ece8010400b3a519f83ab0010307e83bca895170acce8964a044190a2b368892f7a244758d9fc193482648acb1fb9780d28cc22d171931f38bb40279389fc9bf2110876d4f3db4fcfb13f22f7083877fe56592b3b65251312c36f83ffcb6d313c6a17f197dd471f0712aad15a8537b435a92471ba2e5b0c72a6c72536c3b567c558d7b6051001101000188a504180102000f021b0c050251d1f07b050900279091000a091072589ad75e237d8ce69e03fe286026afacf7c97ee20673864d4459a2240b5655219950643c7dba0ac384b1d4359c67805b21d98211f7b09c2a0ccf6410c8c04d4ff4a51293725d8d6570d9d8bb0e10c07d22357caeb49626df99c180be02d77d1fe8ed25e7a54481237646083a9f89a11566cd20b9e995b1487c5f9e02aeb434f3a1897cd416dd0a87861838da3e9e"
+const subkeyUsageHex = "988d04533a52bc010400d26af43085558f65b9e7dbc90cb9238015259aed5e954637adcfa2181548b2d0b60c65f1f42ec5081cbf1bc0a8aa4900acfb77070837c58f26012fbce297d70afe96e759ad63531f0037538e70dbf8e384569b9720d99d8eb39d8d0a2947233ed242436cb6ac7dfe74123354b3d0119b5c235d3dd9c9d6c004f8ffaf67ad8583001101000188b7041f010200210502533b8552170c8001ce094aa433f7040bb2ddf0be3893cb843d0fe70c020700000a0910a42704b92866382aa98404009d63d916a27543da4221c60087c33f1c44bec9998c5438018ed370cca4962876c748e94b73eb39c58eb698063f3fd6346d58dd2a11c0247934c4a9d71f24754f7468f96fb24c3e791dd2392b62f626148ad724189498cbf993db2df7c0cdc2d677c35da0f16cb16c9ce7c33b4de65a4a91b1d21a130ae9cc26067718910ef8e2b417556d627261203c756d627261407379642e65642e61753e88b80413010200220502533a52bc021b03060b090807030206150802090a0b0416020301021e01021780000a0910a42704b92866382a47840400c0c2bd04f5fca586de408b395b3c280a278259c93eaaa8b79a53b97003f8ed502a8a00446dd9947fb462677e4fcac0dac2f0701847d15130aadb6cd9e0705ea0cf5f92f129136c7be21a718d46c8e641eb7f044f2adae573e11ae423a0a9ca51324f03a8a2f34b91fa40c3cc764bee4dccadedb54c768ba0469b683ea53f1c29b88d04533a52bc01040099c92a5d6f8b744224da27bc2369127c35269b58bec179de6bbc038f749344222f85a31933224f26b70243c4e4b2d242f0c4777eaef7b5502f9dad6d8bf3aaeb471210674b74de2d7078af497d55f5cdad97c7bedfbc1b41e8065a97c9c3d344b21fc81d27723af8e374bc595da26ea242dccb6ae497be26eea57e563ed517e90011010001889f0418010200090502533a52bc021b0c000a0910a42704b92866382afa1403ff70284c2de8a043ff51d8d29772602fa98009b7861c540535f874f2c230af8caf5638151a636b21f8255003997ccd29747fdd06777bb24f9593bd7d98a3e887689bf902f999915fcc94625ae487e5d13e6616f89090ebc4fdc7eb5cad8943e4056995bb61c6af37f8043016876a958ec7ebf39c43d20d53b7f546cfa83e8d2604b88d04533b8283010400c0b529316dbdf58b4c54461e7e669dc11c09eb7f73819f178ccd4177b9182b91d138605fcf1e463262fabefa73f94a52b5e15d1904635541c7ea540f07050ce0fb51b73e6f88644cec86e91107c957a114f69554548a85295d2b70bd0b203992f76eb5d493d86d9eabcaa7ef3fc7db7e458438db3fcdb0ca1cc97c638439a9170011010001889f0418010200090502533b8283021b0c000a0910a42704b92866382adc6d0400cfff6258485a21675adb7a811c3e19ebca18851533f75a7ba317950b9997fda8d1a4c8c76505c08c04b6c2cc31dc704d33da36a21273f2b388a1a706f7c3378b66d887197a525936ed9a69acb57fe7f718133da85ec742001c5d1864e9c6c8ea1b94f1c3759cebfd93b18606066c063a63be86085b7e37bdbc65f9a915bf084bb901a204533b85cd110400aed3d2c52af2b38b5b67904b0ef73d6dd7aef86adb770e2b153cd22489654dcc91730892087bb9856ae2d9f7ed1eb48f214243fe86bfe87b349ebd7c30e630e49c07b21fdabf78b7a95c8b7f969e97e3d33f2e074c63552ba64a2ded7badc05ce0ea2be6d53485f6900c7860c7aa76560376ce963d7271b9b54638a4028b573f00a0d8854bfcdb04986141568046202192263b9b67350400aaa1049dbc7943141ef590a70dcb028d730371d92ea4863de715f7f0f16d168bd3dc266c2450457d46dcbbf0b071547e5fbee7700a820c3750b236335d8d5848adb3c0da010e998908dfd93d961480084f3aea20b247034f8988eccb5546efaa35a92d0451df3aaf1aee5aa36a4c4d462c760ecd9cebcabfbe1412b1f21450f203fd126687cd486496e971a87fd9e1a8a765fe654baa219a6871ab97768596ab05c26c1aeea8f1a2c72395a58dbc12ef9640d2b95784e974a4d2d5a9b17c25fedacfe551bda52602de8f6d2e48443f5dd1a2a2a8e6a5e70ecdb88cd6e766ad9745c7ee91d78cc55c3d06536b49c3fee6c3d0b6ff0fb2bf13a314f57c953b8f4d93bf88e70418010200090502533b85cd021b0200520910a42704b92866382a47200419110200060502533b85cd000a091042ce2c64bc0ba99214b2009e26b26852c8b13b10c35768e40e78fbbb48bd084100a0c79d9ea0844fa5853dd3c85ff3ecae6f2c9dd6c557aa04008bbbc964cd65b9b8299d4ebf31f41cc7264b8cf33a00e82c5af022331fac79efc9563a822497ba012953cefe2629f1242fcdcb911dbb2315985bab060bfd58261ace3c654bdbbe2e8ed27a46e836490145c86dc7bae15c011f7e1ffc33730109b9338cd9f483e7cef3d2f396aab5bd80efb6646d7e778270ee99d934d187dd98"
+const revokedKeyHex = "988d045331ce82010400c4fdf7b40a5477f206e6ee278eaef888ca73bf9128a9eef9f2f1ddb8b7b71a4c07cfa241f028a04edb405e4d916c61d6beabc333813dc7b484d2b3c52ee233c6a79b1eea4e9cc51596ba9cd5ac5aeb9df62d86ea051055b79d03f8a4fa9f38386f5bd17529138f3325d46801514ea9047977e0829ed728e68636802796801be10011010001889f04200102000905025331d0e3021d03000a0910a401d9f09a34f7c042aa040086631196405b7e6af71026b88e98012eab44aa9849f6ef3fa930c7c9f23deaedba9db1538830f8652fb7648ec3fcade8dbcbf9eaf428e83c6cbcc272201bfe2fbb90d41963397a7c0637a1a9d9448ce695d9790db2dc95433ad7be19eb3de72dacf1d6db82c3644c13eae2a3d072b99bb341debba012c5ce4006a7d34a1f4b94b444526567205265766f6b657220283c52656727732022424d204261726973746122204b657920262530305c303e5c29203c72656740626d626172697374612e636f2e61753e88b704130102002205025331ce82021b03060b090807030206150802090a0b0416020301021e01021780000a0910a401d9f09a34f7c0019c03f75edfbeb6a73e7225ad3cc52724e2872e04260d7daf0d693c170d8c4b243b8767bc7785763533febc62ec2600c30603c433c095453ede59ff2fcabeb84ce32e0ed9d5cf15ffcbc816202b64370d4d77c1e9077d74e94a16fb4fa2e5bec23a56d7a73cf275f91691ae1801a976fcde09e981a2f6327ac27ea1fecf3185df0d56889c04100102000605025331cfb5000a0910fe9645554e8266b64b4303fc084075396674fb6f778d302ac07cef6bc0b5d07b66b2004c44aef711cbac79617ef06d836b4957522d8772dd94bf41a2f4ac8b1ee6d70c57503f837445a74765a076d07b829b8111fc2a918423ddb817ead7ca2a613ef0bfb9c6b3562aec6c3cf3c75ef3031d81d95f6563e4cdcc9960bcb386c5d757b104fcca5fe11fc709df884604101102000605025331cfe7000a09107b15a67f0b3ddc0317f6009e360beea58f29c1d963a22b962b80788c3fa6c84e009d148cfde6b351469b8eae91187eff07ad9d08fcaab88d045331ce820104009f25e20a42b904f3fa555530fe5c46737cf7bd076c35a2a0d22b11f7e0b61a69320b768f4a80fe13980ce380d1cfc4a0cd8fbe2d2e2ef85416668b77208baa65bf973fe8e500e78cc310d7c8705cdb34328bf80e24f0385fce5845c33bc7943cf6b11b02348a23da0bf6428e57c05135f2dc6bd7c1ce325d666d5a5fd2fd5e410011010001889f04180102000905025331ce82021b0c000a0910a401d9f09a34f7c0418003fe34feafcbeaef348a800a0d908a7a6809cc7304017d820f70f0474d5e23cb17e38b67dc6dca282c6ca00961f4ec9edf2738d0f087b1d81e4871ef08e1798010863afb4eac4c44a376cb343be929c5be66a78cfd4456ae9ec6a99d97f4e1c3ff3583351db2147a65c0acef5c003fb544ab3a2e2dc4d43646f58b811a6c3a369d1f"
+const revokedSubkeyHex = "988d04533121f6010400aefc803a3e4bb1a61c86e8a86d2726c6a43e0079e9f2713f1fa017e9854c83877f4aced8e331d675c67ea83ddab80aacbfa0b9040bb12d96f5a3d6be09455e2a76546cbd21677537db941cab710216b6d24ec277ee0bd65b910f416737ed120f6b93a9d3b306245c8cfd8394606fdb462e5cf43c551438d2864506c63367fc890011010001b41d416c696365203c616c69636540626d626172697374612e636f2e61753e88bb041301020025021b03060b090807030206150802090a0b0416020301021e01021780050253312798021901000a09104ef7e4beccde97f015a803ff5448437780f63263b0df8442a995e7f76c221351a51edd06f2063d8166cf3157aada4923dfc44aa0f2a6a4da5cf83b7fe722ba8ab416c976e77c6b5682e7f1069026673bd0de56ba06fd5d7a9f177607f277d9b55ff940a638c3e68525c67517e2b3d976899b93ca267f705b3e5efad7d61220e96b618a4497eab8d04403d23f8846041011020006050253312910000a09107b15a67f0b3ddc03d96e009f50b6365d86c4be5d5e9d0ea42d5e56f5794c617700a0ab274e19c2827780016d23417ce89e0a2c0d987d889c04100102000605025331cf7a000a0910a401d9f09a34f7c0ee970400aca292f213041c9f3b3fc49148cbda9d84afee6183c8dd6c5ff2600b29482db5fecd4303797be1ee6d544a20a858080fec43412061c9a71fae4039fd58013b4ae341273e6c66ad4c7cdd9e68245bedb260562e7b166f2461a1032f2b38c0e0e5715fb3d1656979e052b55ca827a76f872b78a9fdae64bc298170bfcebedc1271b41a416c696365203c616c696365407379646973702e6f722e61753e88b804130102002205025331278b021b03060b090807030206150802090a0b0416020301021e01021780000a09104ef7e4beccde97f06a7003fa03c3af68d272ebc1fa08aa72a03b02189c26496a2833d90450801c4e42c5b5f51ad96ce2d2c9cef4b7c02a6a2fcf1412d6a2d486098eb762f5010a201819c17fd2888aec8eda20c65a3b75744de7ee5cc8ac7bfc470cbe3cb982720405a27a3c6a8c229cfe36905f881b02ed5680f6a8f05866efb9d6c5844897e631deb949ca8846041011020006050253312910000a09107b15a67f0b3ddc0347bc009f7fa35db59147469eb6f2c5aaf6428accb138b22800a0caa2f5f0874bacc5909c652a57a31beda65eddd5889c04100102000605025331cf7a000a0910a401d9f09a34f7c0316403ff46f2a5c101256627f16384d34a38fb47a6c88ba60506843e532d91614339fccae5f884a5741e7582ffaf292ba38ee10a270a05f139bde3814b6a077e8cd2db0f105ebea2a83af70d385f13b507fac2ad93ff79d84950328bb86f3074745a8b7f9b64990fb142e2a12976e27e8d09a28dc5621f957ac49091116da410ac3cbde1b88d04533121f6010400cbd785b56905e4192e2fb62a720727d43c4fa487821203cf72138b884b78b701093243e1d8c92a0248a6c0203a5a88693da34af357499abacaf4b3309c640797d03093870a323b4b6f37865f6eaa2838148a67df4735d43a90ca87942554cdf1c4a751b1e75f9fd4ce4e97e278d6c1c7ed59d33441df7d084f3f02beb68896c70011010001889f0418010200090502533121f6021b0c000a09104ef7e4beccde97f0b98b03fc0a5ccf6a372995835a2f5da33b282a7d612c0ab2a97f59cf9fff73e9110981aac2858c41399afa29624a7fd8a0add11654e3d882c0fd199e161bdad65e5e2548f7b68a437ea64293db1246e3011cbb94dc1bcdeaf0f2539bd88ff16d95547144d97cead6a8c5927660a91e6db0d16eb36b7b49a3525b54d1644e65599b032b7eb901a204533127a0110400bd3edaa09eff9809c4edc2c2a0ebe52e53c50a19c1e49ab78e6167bf61473bb08f2050d78a5cbbc6ed66aff7b42cd503f16b4a0b99fa1609681fca9b7ce2bbb1a5b3864d6cdda4d7ef7849d156d534dea30fb0efb9e4cf8959a2b2ce623905882d5430b995a15c3b9fe92906086788b891002924f94abe139b42cbbfaaabe42f00a0b65dc1a1ad27d798adbcb5b5ad02d2688c89477b03ff4eebb6f7b15a73b96a96bed201c0e5e4ea27e4c6e2dd1005b94d4b90137a5b1cf5e01c6226c070c4cc999938101578877ee76d296b9aab8246d57049caacf489e80a3f40589cade790a020b1ac146d6f7a6241184b8c7fcde680eae3188f5dcbe846d7f7bdad34f6fcfca08413e19c1d5df83fc7c7c627d493492e009c2f52a80400a2fe82de87136fd2e8845888c4431b032ba29d9a29a804277e31002a8201fb8591a3e55c7a0d0881496caf8b9fb07544a5a4879291d0dc026a0ea9e5bd88eb4aa4947bbd694b25012e208a250d65ddc6f1eea59d3aed3b4ec15fcab85e2afaa23a40ab1ef9ce3e11e1bc1c34a0e758e7aa64deb8739276df0af7d4121f834a9b88e70418010200090502533127a0021b02005209104ef7e4beccde97f047200419110200060502533127a0000a0910dbce4ee19529437fe045009c0b32f5ead48ee8a7e98fac0dea3d3e6c0e2c552500a0ad71fadc5007cfaf842d9b7db3335a8cdad15d3d1a6404009b08e2c68fe8f3b45c1bb72a4b3278cdf3012aa0f229883ad74aa1f6000bb90b18301b2f85372ca5d6b9bf478d235b733b1b197d19ccca48e9daf8e890cb64546b4ce1b178faccfff07003c172a2d4f5ebaba9f57153955f3f61a9b80a4f5cb959908f8b211b03b7026a8a82fc612bfedd3794969bcf458c4ce92be215a1176ab88d045331d144010400a5063000c5aaf34953c1aa3bfc95045b3aab9882b9a8027fecfe2142dc6b47ba8aca667399990244d513dd0504716908c17d92c65e74219e004f7b83fc125e575dd58efec3ab6dd22e3580106998523dea42ec75bf9aa111734c82df54630bebdff20fe981cfc36c76f865eb1c2fb62c9e85bc3a6e5015a361a2eb1c8431578d0011010001889f04280102000905025331d433021d03000a09104ef7e4beccde97f02e5503ff5e0630d1b65291f4882b6d40a29da4616bb5088717d469fbcc3648b8276de04a04988b1f1b9f3e18f52265c1f8b6c85861691c1a6b8a3a25a1809a0b32ad330aec5667cb4262f4450649184e8113849b05e5ad06a316ea80c001e8e71838190339a6e48bbde30647bcf245134b9a97fa875c1d83a9862cae87ffd7e2c4ce3a1b89013d04180102000905025331d144021b0200a809104ef7e4beccde97f09d2004190102000605025331d144000a0910677815e371c2fd23522203fe22ab62b8e7a151383cea3edd3a12995693911426f8ccf125e1f6426388c0010f88d9ca7da2224aee8d1c12135998640c5e1813d55a93df472faae75bef858457248db41b4505827590aeccf6f9eb646da7f980655dd3050c6897feddddaca90676dee856d66db8923477d251712bb9b3186b4d0114daf7d6b59272b53218dd1da94a03ff64006fcbe71211e5daecd9961fba66cdb6de3f914882c58ba5beddeba7dcb950c1156d7fba18c19ea880dccc800eae335deec34e3b84ac75ffa24864f782f87815cda1c0f634b3dd2fa67cea30811d21723d21d9551fa12ccbcfa62b6d3a15d01307b99925707992556d50065505b090aadb8579083a20fe65bd2a270da9b011"
+const missingCrossSignatureKey = `-----BEGIN PGP PUBLIC KEY BLOCK-----
+Charset: UTF-8
+
+mQENBFMYynYBCACVOZ3/e8Bm2b9KH9QyIlHGo/i1bnkpqsgXj8tpJ2MIUOnXMMAY
+ztW7kKFLCmgVdLIC0vSoLA4yhaLcMojznh/2CcUglZeb6Ao8Gtelr//Rd5DRfPpG
+zqcfUo+m+eO1co2Orabw0tZDfGpg5p3AYl0hmxhUyYSc/xUq93xL1UJzBFgYXY54
+QsM8dgeQgFseSk/YvdP5SMx1ev+eraUyiiUtWzWrWC1TdyRa5p4UZg6Rkoppf+WJ
+QrW6BWrhAtqATHc8ozV7uJjeONjUEq24roRc/OFZdmQQGK6yrzKnnbA6MdHhqpdo
+9kWDcXYb7pSE63Lc+OBa5X2GUVvXJLS/3nrtABEBAAG0F2ludmFsaWQtc2lnbmlu
+Zy1zdWJrZXlziQEoBBMBAgASBQJTnKB5AhsBAgsHAhUIAh4BAAoJEO3UDQUIHpI/
+dN4H/idX4FQ1LIZCnpHS/oxoWQWfpRgdKAEM0qCqjMgiipJeEwSQbqjTCynuh5/R
+JlODDz85ABR06aoF4l5ebGLQWFCYifPnJZ/Yf5OYcMGtb7dIbqxWVFL9iLMO/oDL
+ioI3dotjPui5e+2hI9pVH1UHB/bZ/GvMGo6Zg0XxLPolKQODMVjpjLAQ0YJ3spew
+RAmOGre6tIvbDsMBnm8qREt7a07cBJ6XK7xjxYaZHQBiHVxyEWDa6gyANONx8duW
+/fhQ/zDTnyVM/ik6VO0Ty9BhPpcEYLFwh5c1ilFari1ta3e6qKo6ZGa9YMk/REhu
+yBHd9nTkI+0CiQUmbckUiVjDKKe5AQ0EUxjKdgEIAJcXQeP+NmuciE99YcJoffxv
+2gVLU4ZXBNHEaP0mgaJ1+tmMD089vUQAcyGRvw8jfsNsVZQIOAuRxY94aHQhIRHR
+bUzBN28ofo/AJJtfx62C15xt6fDKRV6HXYqAiygrHIpEoRLyiN69iScUsjIJeyFL
+C8wa72e8pSL6dkHoaV1N9ZH/xmrJ+k0vsgkQaAh9CzYufncDxcwkoP+aOlGtX1gP
+WwWoIbz0JwLEMPHBWvDDXQcQPQTYQyj+LGC9U6f9VZHN25E94subM1MjuT9OhN9Y
+MLfWaaIc5WyhLFyQKW2Upofn9wSFi8ubyBnv640Dfd0rVmaWv7LNTZpoZ/GbJAMA
+EQEAAYkBHwQYAQIACQUCU5ygeQIbAgAKCRDt1A0FCB6SP0zCB/sEzaVR38vpx+OQ
+MMynCBJrakiqDmUZv9xtplY7zsHSQjpd6xGflbU2n+iX99Q+nav0ETQZifNUEd4N
+1ljDGQejcTyKD6Pkg6wBL3x9/RJye7Zszazm4+toJXZ8xJ3800+BtaPoI39akYJm
++ijzbskvN0v/j5GOFJwQO0pPRAFtdHqRs9Kf4YanxhedB4dIUblzlIJuKsxFit6N
+lgGRblagG3Vv2eBszbxzPbJjHCgVLR3RmrVezKOsZjr/2i7X+xLWIR0uD3IN1qOW
+CXQxLBizEEmSNVNxsp7KPGTLnqO3bPtqFirxS9PJLIMPTPLNBY7ZYuPNTMqVIUWF
+4artDmrG
+=7FfJ
+-----END PGP PUBLIC KEY BLOCK-----`
+
+const invalidCrossSignatureKey = `-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mQENBFMYynYBCACVOZ3/e8Bm2b9KH9QyIlHGo/i1bnkpqsgXj8tpJ2MIUOnXMMAY
+ztW7kKFLCmgVdLIC0vSoLA4yhaLcMojznh/2CcUglZeb6Ao8Gtelr//Rd5DRfPpG
+zqcfUo+m+eO1co2Orabw0tZDfGpg5p3AYl0hmxhUyYSc/xUq93xL1UJzBFgYXY54
+QsM8dgeQgFseSk/YvdP5SMx1ev+eraUyiiUtWzWrWC1TdyRa5p4UZg6Rkoppf+WJ
+QrW6BWrhAtqATHc8ozV7uJjeONjUEq24roRc/OFZdmQQGK6yrzKnnbA6MdHhqpdo
+9kWDcXYb7pSE63Lc+OBa5X2GUVvXJLS/3nrtABEBAAG0F2ludmFsaWQtc2lnbmlu
+Zy1zdWJrZXlziQEoBBMBAgASBQJTnKB5AhsBAgsHAhUIAh4BAAoJEO3UDQUIHpI/
+dN4H/idX4FQ1LIZCnpHS/oxoWQWfpRgdKAEM0qCqjMgiipJeEwSQbqjTCynuh5/R
+JlODDz85ABR06aoF4l5ebGLQWFCYifPnJZ/Yf5OYcMGtb7dIbqxWVFL9iLMO/oDL
+ioI3dotjPui5e+2hI9pVH1UHB/bZ/GvMGo6Zg0XxLPolKQODMVjpjLAQ0YJ3spew
+RAmOGre6tIvbDsMBnm8qREt7a07cBJ6XK7xjxYaZHQBiHVxyEWDa6gyANONx8duW
+/fhQ/zDTnyVM/ik6VO0Ty9BhPpcEYLFwh5c1ilFari1ta3e6qKo6ZGa9YMk/REhu
+yBHd9nTkI+0CiQUmbckUiVjDKKe5AQ0EUxjKdgEIAIINDqlj7X6jYKc6DjwrOkjQ
+UIRWbQQar0LwmNilehmt70g5DCL1SYm9q4LcgJJ2Nhxj0/5qqsYib50OSWMcKeEe
+iRXpXzv1ObpcQtI5ithp0gR53YPXBib80t3bUzomQ5UyZqAAHzMp3BKC54/vUrSK
+FeRaxDzNLrCeyI00+LHNUtwghAqHvdNcsIf8VRumK8oTm3RmDh0TyjASWYbrt9c8
+R1Um3zuoACOVy+mEIgIzsfHq0u7dwYwJB5+KeM7ZLx+HGIYdUYzHuUE1sLwVoELh
++SHIGHI1HDicOjzqgajShuIjj5hZTyQySVprrsLKiXS6NEwHAP20+XjayJ/R3tEA
+EQEAAYkCPgQYAQIBKAUCU5ygeQIbAsBdIAQZAQIABgUCU5ygeQAKCRCpVlnFZmhO
+52RJB/9uD1MSa0wjY6tHOIgquZcP3bHBvHmrHNMw9HR2wRCMO91ZkhrpdS3ZHtgb
+u3/55etj0FdvDo1tb8P8FGSVtO5Vcwf5APM8sbbqoi8L951Q3i7qt847lfhu6sMl
+w0LWFvPTOLHrliZHItPRjOltS1WAWfr2jUYhsU9ytaDAJmvf9DujxEOsN5G1YJep
+54JCKVCkM/y585Zcnn+yxk/XwqoNQ0/iJUT9qRrZWvoeasxhl1PQcwihCwss44A+
+YXaAt3hbk+6LEQuZoYS73yR3WHj+42tfm7YxRGeubXfgCEz/brETEWXMh4pe0vCL
+bfWrmfSPq2rDegYcAybxRQz0lF8PAAoJEO3UDQUIHpI/exkH/0vQfdHA8g/N4T6E
+i6b1CUVBAkvtdJpCATZjWPhXmShOw62gkDw306vHPilL4SCvEEi4KzG72zkp6VsB
+DSRcpxCwT4mHue+duiy53/aRMtSJ+vDfiV1Vhq+3sWAck/yUtfDU9/u4eFaiNok1
+8/Gd7reyuZt5CiJnpdPpjCwelK21l2w7sHAnJF55ITXdOxI8oG3BRKufz0z5lyDY
+s2tXYmhhQIggdgelN8LbcMhWs/PBbtUr6uZlNJG2lW1yscD4aI529VjwJlCeo745
+U7pO4eF05VViUJ2mmfoivL3tkhoTUWhx8xs8xCUcCg8DoEoSIhxtOmoTPR22Z9BL
+6LCg2mg=
+=Dhm4
+-----END PGP PUBLIC KEY BLOCK-----`
+
+const goodCrossSignatureKey = `-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v1
+
+mI0EVUqeVwEEAMufHRrMPWK3gyvi0O0tABCs/oON9zV9KDZlr1a1M91ShCSFwCPo
+7r80PxdWVWcj0V5h50/CJYtpN3eE/mUIgW2z1uDYQF1OzrQ8ubrksfsJvpAhENom
+lTQEppv9mV8qhcM278teb7TX0pgrUHLYF5CfPdp1L957JLLXoQR/lwLVABEBAAG0
+E2dvb2Qtc2lnbmluZy1zdWJrZXmIuAQTAQIAIgUCVUqeVwIbAwYLCQgHAwIGFQgC
+CQoLBBYCAwECHgECF4AACgkQNRjL95IRWP69XQQAlH6+eyXJN4DZTLX78KGjHrsw
+6FCvxxClEPtPUjcJy/1KCRQmtLAt9PbbA78dvgzjDeZMZqRAwdjyJhjyg/fkU2OH
+7wq4ktjUu+dLcOBb+BFMEY+YjKZhf6EJuVfxoTVr5f82XNPbYHfTho9/OABKH6kv
+X70PaKZhbwnwij8Nts65AaIEVUqftREEAJ3WxZfqAX0bTDbQPf2CMT2IVMGDfhK7
+GyubOZgDFFjwUJQvHNvsrbeGLZ0xOBumLINyPO1amIfTgJNm1iiWFWfmnHReGcDl
+y5mpYG60Mb79Whdcer7CMm3AqYh/dW4g6IB02NwZMKoUHo3PXmFLxMKXnWyJ0clw
+R0LI/Qn509yXAKDh1SO20rqrBM+EAP2c5bfI98kyNwQAi3buu94qo3RR1ZbvfxgW
+CKXDVm6N99jdZGNK7FbRifXqzJJDLcXZKLnstnC4Sd3uyfyf1uFhmDLIQRryn5m+
+LBYHfDBPN3kdm7bsZDDq9GbTHiFZUfm/tChVKXWxkhpAmHhU/tH6GGzNSMXuIWSO
+aOz3Rqq0ED4NXyNKjdF9MiwD/i83S0ZBc0LmJYt4Z10jtH2B6tYdqnAK29uQaadx
+yZCX2scE09UIm32/w7pV77CKr1Cp/4OzAXS1tmFzQ+bX7DR+Gl8t4wxr57VeEMvl
+BGw4Vjh3X8//m3xynxycQU18Q1zJ6PkiMyPw2owZ/nss3hpSRKFJsxMLhW3fKmKr
+Ey2KiOcEGAECAAkFAlVKn7UCGwIAUgkQNRjL95IRWP5HIAQZEQIABgUCVUqftQAK
+CRD98VjDN10SqkWrAKDTpEY8D8HC02E/KVC5YUI01B30wgCgurpILm20kXEDCeHp
+C5pygfXw1DJrhAP+NyPJ4um/bU1I+rXaHHJYroYJs8YSweiNcwiHDQn0Engh/mVZ
+SqLHvbKh2dL/RXymC3+rjPvQf5cup9bPxNMa6WagdYBNAfzWGtkVISeaQW+cTEp/
+MtgVijRGXR/lGLGETPg2X3Afwn9N9bLMBkBprKgbBqU7lpaoPupxT61bL70=
+=vtbN
+-----END PGP PUBLIC KEY BLOCK-----`
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/compressed.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/compressed.go
new file mode 100644
index 000000000..e8f0b5caa
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/compressed.go
@@ -0,0 +1,123 @@
+// Copyright 2011 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 packet
+
+import (
+ "compress/bzip2"
+ "compress/flate"
+ "compress/zlib"
+ "golang.org/x/crypto/openpgp/errors"
+ "io"
+ "strconv"
+)
+
+// Compressed represents a compressed OpenPGP packet. The decompressed contents
+// will contain more OpenPGP packets. See RFC 4880, section 5.6.
+type Compressed struct {
+ Body io.Reader
+}
+
+const (
+ NoCompression = flate.NoCompression
+ BestSpeed = flate.BestSpeed
+ BestCompression = flate.BestCompression
+ DefaultCompression = flate.DefaultCompression
+)
+
+// CompressionConfig contains compressor configuration settings.
+type CompressionConfig struct {
+ // Level is the compression level to use. It must be set to
+ // between -1 and 9, with -1 causing the compressor to use the
+ // default compression level, 0 causing the compressor to use
+ // no compression and 1 to 9 representing increasing (better,
+ // slower) compression levels. If Level is less than -1 or
+ // more then 9, a non-nil error will be returned during
+ // encryption. See the constants above for convenient common
+ // settings for Level.
+ Level int
+}
+
+func (c *Compressed) parse(r io.Reader) error {
+ var buf [1]byte
+ _, err := readFull(r, buf[:])
+ if err != nil {
+ return err
+ }
+
+ switch buf[0] {
+ case 1:
+ c.Body = flate.NewReader(r)
+ case 2:
+ c.Body, err = zlib.NewReader(r)
+ case 3:
+ c.Body = bzip2.NewReader(r)
+ default:
+ err = errors.UnsupportedError("unknown compression algorithm: " + strconv.Itoa(int(buf[0])))
+ }
+
+ return err
+}
+
+// compressedWriterCloser represents the serialized compression stream
+// header and the compressor. Its Close() method ensures that both the
+// compressor and serialized stream header are closed. Its Write()
+// method writes to the compressor.
+type compressedWriteCloser struct {
+ sh io.Closer // Stream Header
+ c io.WriteCloser // Compressor
+}
+
+func (cwc compressedWriteCloser) Write(p []byte) (int, error) {
+ return cwc.c.Write(p)
+}
+
+func (cwc compressedWriteCloser) Close() (err error) {
+ err = cwc.c.Close()
+ if err != nil {
+ return err
+ }
+
+ return cwc.sh.Close()
+}
+
+// SerializeCompressed serializes a compressed data packet to w and
+// returns a WriteCloser to which the literal data packets themselves
+// can be written and which MUST be closed on completion. If cc is
+// nil, sensible defaults will be used to configure the compression
+// algorithm.
+func SerializeCompressed(w io.WriteCloser, algo CompressionAlgo, cc *CompressionConfig) (literaldata io.WriteCloser, err error) {
+ compressed, err := serializeStreamHeader(w, packetTypeCompressed)
+ if err != nil {
+ return
+ }
+
+ _, err = compressed.Write([]byte{uint8(algo)})
+ if err != nil {
+ return
+ }
+
+ level := DefaultCompression
+ if cc != nil {
+ level = cc.Level
+ }
+
+ var compressor io.WriteCloser
+ switch algo {
+ case CompressionZIP:
+ compressor, err = flate.NewWriter(compressed, level)
+ case CompressionZLIB:
+ compressor, err = zlib.NewWriterLevel(compressed, level)
+ default:
+ s := strconv.Itoa(int(algo))
+ err = errors.UnsupportedError("Unsupported compression algorithm: " + s)
+ }
+ if err != nil {
+ return
+ }
+
+ literaldata = compressedWriteCloser{compressed, compressor}
+
+ return
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/compressed_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/compressed_test.go
new file mode 100644
index 000000000..cb2d70bd4
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/compressed_test.go
@@ -0,0 +1,41 @@
+// Copyright 2011 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 packet
+
+import (
+ "bytes"
+ "encoding/hex"
+ "io"
+ "io/ioutil"
+ "testing"
+)
+
+func TestCompressed(t *testing.T) {
+ packet, err := Read(readerFromHex(compressedHex))
+ if err != nil {
+ t.Errorf("failed to read Compressed: %s", err)
+ return
+ }
+
+ c, ok := packet.(*Compressed)
+ if !ok {
+ t.Error("didn't find Compressed packet")
+ return
+ }
+
+ contents, err := ioutil.ReadAll(c.Body)
+ if err != nil && err != io.EOF {
+ t.Error(err)
+ return
+ }
+
+ expected, _ := hex.DecodeString(compressedExpectedHex)
+ if !bytes.Equal(expected, contents) {
+ t.Errorf("got:%x want:%x", contents, expected)
+ }
+}
+
+const compressedHex = "a3013b2d90c4e02b72e25f727e5e496a5e49b11e1700"
+const compressedExpectedHex = "cb1062004d14c8fe636f6e74656e74732e0a"
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/config.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/config.go
new file mode 100644
index 000000000..c76eecc96
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/config.go
@@ -0,0 +1,91 @@
+// Copyright 2012 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 packet
+
+import (
+ "crypto"
+ "crypto/rand"
+ "io"
+ "time"
+)
+
+// Config collects a number of parameters along with sensible defaults.
+// A nil *Config is valid and results in all default values.
+type Config struct {
+ // Rand provides the source of entropy.
+ // If nil, the crypto/rand Reader is used.
+ Rand io.Reader
+ // DefaultHash is the default hash function to be used.
+ // If zero, SHA-256 is used.
+ DefaultHash crypto.Hash
+ // DefaultCipher is the cipher to be used.
+ // If zero, AES-128 is used.
+ DefaultCipher CipherFunction
+ // Time returns the current time as the number of seconds since the
+ // epoch. If Time is nil, time.Now is used.
+ Time func() time.Time
+ // DefaultCompressionAlgo is the compression algorithm to be
+ // applied to the plaintext before encryption. If zero, no
+ // compression is done.
+ DefaultCompressionAlgo CompressionAlgo
+ // CompressionConfig configures the compression settings.
+ CompressionConfig *CompressionConfig
+ // S2KCount is only used for symmetric encryption. It
+ // determines the strength of the passphrase stretching when
+ // the said passphrase is hashed to produce a key. S2KCount
+ // should be between 1024 and 65011712, inclusive. If Config
+ // is nil or S2KCount is 0, the value 65536 used. Not all
+ // values in the above range can be represented. S2KCount will
+ // be rounded up to the next representable value if it cannot
+ // be encoded exactly. When set, it is strongly encrouraged to
+ // use a value that is at least 65536. See RFC 4880 Section
+ // 3.7.1.3.
+ S2KCount int
+ // RSABits is the number of bits in new RSA keys made with NewEntity.
+ // If zero, then 2048 bit keys are created.
+ RSABits int
+}
+
+func (c *Config) Random() io.Reader {
+ if c == nil || c.Rand == nil {
+ return rand.Reader
+ }
+ return c.Rand
+}
+
+func (c *Config) Hash() crypto.Hash {
+ if c == nil || uint(c.DefaultHash) == 0 {
+ return crypto.SHA256
+ }
+ return c.DefaultHash
+}
+
+func (c *Config) Cipher() CipherFunction {
+ if c == nil || uint8(c.DefaultCipher) == 0 {
+ return CipherAES128
+ }
+ return c.DefaultCipher
+}
+
+func (c *Config) Now() time.Time {
+ if c == nil || c.Time == nil {
+ return time.Now()
+ }
+ return c.Time()
+}
+
+func (c *Config) Compression() CompressionAlgo {
+ if c == nil {
+ return CompressionNone
+ }
+ return c.DefaultCompressionAlgo
+}
+
+func (c *Config) PasswordHashIterations() int {
+ if c == nil || c.S2KCount == 0 {
+ return 0
+ }
+ return c.S2KCount
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/encrypted_key.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/encrypted_key.go
new file mode 100644
index 000000000..266840d05
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/encrypted_key.go
@@ -0,0 +1,199 @@
+// Copyright 2011 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 packet
+
+import (
+ "crypto/rsa"
+ "encoding/binary"
+ "io"
+ "math/big"
+ "strconv"
+
+ "golang.org/x/crypto/openpgp/elgamal"
+ "golang.org/x/crypto/openpgp/errors"
+)
+
+const encryptedKeyVersion = 3
+
+// EncryptedKey represents a public-key encrypted session key. See RFC 4880,
+// section 5.1.
+type EncryptedKey struct {
+ KeyId uint64
+ Algo PublicKeyAlgorithm
+ CipherFunc CipherFunction // only valid after a successful Decrypt
+ Key []byte // only valid after a successful Decrypt
+
+ encryptedMPI1, encryptedMPI2 parsedMPI
+}
+
+func (e *EncryptedKey) parse(r io.Reader) (err error) {
+ var buf [10]byte
+ _, err = readFull(r, buf[:])
+ if err != nil {
+ return
+ }
+ if buf[0] != encryptedKeyVersion {
+ return errors.UnsupportedError("unknown EncryptedKey version " + strconv.Itoa(int(buf[0])))
+ }
+ e.KeyId = binary.BigEndian.Uint64(buf[1:9])
+ e.Algo = PublicKeyAlgorithm(buf[9])
+ switch e.Algo {
+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
+ e.encryptedMPI1.bytes, e.encryptedMPI1.bitLength, err = readMPI(r)
+ case PubKeyAlgoElGamal:
+ e.encryptedMPI1.bytes, e.encryptedMPI1.bitLength, err = readMPI(r)
+ if err != nil {
+ return
+ }
+ e.encryptedMPI2.bytes, e.encryptedMPI2.bitLength, err = readMPI(r)
+ }
+ _, err = consumeAll(r)
+ return
+}
+
+func checksumKeyMaterial(key []byte) uint16 {
+ var checksum uint16
+ for _, v := range key {
+ checksum += uint16(v)
+ }
+ return checksum
+}
+
+// Decrypt decrypts an encrypted session key with the given private key. The
+// private key must have been decrypted first.
+// If config is nil, sensible defaults will be used.
+func (e *EncryptedKey) Decrypt(priv *PrivateKey, config *Config) error {
+ var err error
+ var b []byte
+
+ // TODO(agl): use session key decryption routines here to avoid
+ // padding oracle attacks.
+ switch priv.PubKeyAlgo {
+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
+ b, err = rsa.DecryptPKCS1v15(config.Random(), priv.PrivateKey.(*rsa.PrivateKey), e.encryptedMPI1.bytes)
+ case PubKeyAlgoElGamal:
+ c1 := new(big.Int).SetBytes(e.encryptedMPI1.bytes)
+ c2 := new(big.Int).SetBytes(e.encryptedMPI2.bytes)
+ b, err = elgamal.Decrypt(priv.PrivateKey.(*elgamal.PrivateKey), c1, c2)
+ default:
+ err = errors.InvalidArgumentError("cannot decrypted encrypted session key with private key of type " + strconv.Itoa(int(priv.PubKeyAlgo)))
+ }
+
+ if err != nil {
+ return err
+ }
+
+ e.CipherFunc = CipherFunction(b[0])
+ e.Key = b[1 : len(b)-2]
+ expectedChecksum := uint16(b[len(b)-2])<<8 | uint16(b[len(b)-1])
+ checksum := checksumKeyMaterial(e.Key)
+ if checksum != expectedChecksum {
+ return errors.StructuralError("EncryptedKey checksum incorrect")
+ }
+
+ return nil
+}
+
+// Serialize writes the encrypted key packet, e, to w.
+func (e *EncryptedKey) Serialize(w io.Writer) error {
+ var mpiLen int
+ switch e.Algo {
+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
+ mpiLen = 2 + len(e.encryptedMPI1.bytes)
+ case PubKeyAlgoElGamal:
+ mpiLen = 2 + len(e.encryptedMPI1.bytes) + 2 + len(e.encryptedMPI2.bytes)
+ default:
+ return errors.InvalidArgumentError("don't know how to serialize encrypted key type " + strconv.Itoa(int(e.Algo)))
+ }
+
+ serializeHeader(w, packetTypeEncryptedKey, 1 /* version */ +8 /* key id */ +1 /* algo */ +mpiLen)
+
+ w.Write([]byte{encryptedKeyVersion})
+ binary.Write(w, binary.BigEndian, e.KeyId)
+ w.Write([]byte{byte(e.Algo)})
+
+ switch e.Algo {
+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
+ writeMPIs(w, e.encryptedMPI1)
+ case PubKeyAlgoElGamal:
+ writeMPIs(w, e.encryptedMPI1, e.encryptedMPI2)
+ default:
+ panic("internal error")
+ }
+
+ return nil
+}
+
+// SerializeEncryptedKey serializes an encrypted key packet to w that contains
+// key, encrypted to pub.
+// If config is nil, sensible defaults will be used.
+func SerializeEncryptedKey(w io.Writer, pub *PublicKey, cipherFunc CipherFunction, key []byte, config *Config) error {
+ var buf [10]byte
+ buf[0] = encryptedKeyVersion
+ binary.BigEndian.PutUint64(buf[1:9], pub.KeyId)
+ buf[9] = byte(pub.PubKeyAlgo)
+
+ keyBlock := make([]byte, 1 /* cipher type */ +len(key)+2 /* checksum */)
+ keyBlock[0] = byte(cipherFunc)
+ copy(keyBlock[1:], key)
+ checksum := checksumKeyMaterial(key)
+ keyBlock[1+len(key)] = byte(checksum >> 8)
+ keyBlock[1+len(key)+1] = byte(checksum)
+
+ switch pub.PubKeyAlgo {
+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
+ return serializeEncryptedKeyRSA(w, config.Random(), buf, pub.PublicKey.(*rsa.PublicKey), keyBlock)
+ case PubKeyAlgoElGamal:
+ return serializeEncryptedKeyElGamal(w, config.Random(), buf, pub.PublicKey.(*elgamal.PublicKey), keyBlock)
+ case PubKeyAlgoDSA, PubKeyAlgoRSASignOnly:
+ return errors.InvalidArgumentError("cannot encrypt to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo)))
+ }
+
+ return errors.UnsupportedError("encrypting a key to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo)))
+}
+
+func serializeEncryptedKeyRSA(w io.Writer, rand io.Reader, header [10]byte, pub *rsa.PublicKey, keyBlock []byte) error {
+ cipherText, err := rsa.EncryptPKCS1v15(rand, pub, keyBlock)
+ if err != nil {
+ return errors.InvalidArgumentError("RSA encryption failed: " + err.Error())
+ }
+
+ packetLen := 10 /* header length */ + 2 /* mpi size */ + len(cipherText)
+
+ err = serializeHeader(w, packetTypeEncryptedKey, packetLen)
+ if err != nil {
+ return err
+ }
+ _, err = w.Write(header[:])
+ if err != nil {
+ return err
+ }
+ return writeMPI(w, 8*uint16(len(cipherText)), cipherText)
+}
+
+func serializeEncryptedKeyElGamal(w io.Writer, rand io.Reader, header [10]byte, pub *elgamal.PublicKey, keyBlock []byte) error {
+ c1, c2, err := elgamal.Encrypt(rand, pub, keyBlock)
+ if err != nil {
+ return errors.InvalidArgumentError("ElGamal encryption failed: " + err.Error())
+ }
+
+ packetLen := 10 /* header length */
+ packetLen += 2 /* mpi size */ + (c1.BitLen()+7)/8
+ packetLen += 2 /* mpi size */ + (c2.BitLen()+7)/8
+
+ err = serializeHeader(w, packetTypeEncryptedKey, packetLen)
+ if err != nil {
+ return err
+ }
+ _, err = w.Write(header[:])
+ if err != nil {
+ return err
+ }
+ err = writeBig(w, c1)
+ if err != nil {
+ return err
+ }
+ return writeBig(w, c2)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/encrypted_key_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/encrypted_key_test.go
new file mode 100644
index 000000000..fee14cf3c
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/encrypted_key_test.go
@@ -0,0 +1,146 @@
+// Copyright 2011 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 packet
+
+import (
+ "bytes"
+ "crypto/rsa"
+ "encoding/hex"
+ "fmt"
+ "math/big"
+ "testing"
+)
+
+func bigFromBase10(s string) *big.Int {
+ b, ok := new(big.Int).SetString(s, 10)
+ if !ok {
+ panic("bigFromBase10 failed")
+ }
+ return b
+}
+
+var encryptedKeyPub = rsa.PublicKey{
+ E: 65537,
+ N: bigFromBase10("115804063926007623305902631768113868327816898845124614648849934718568541074358183759250136204762053879858102352159854352727097033322663029387610959884180306668628526686121021235757016368038585212410610742029286439607686208110250133174279811431933746643015923132833417396844716207301518956640020862630546868823"),
+}
+
+var encryptedKeyRSAPriv = &rsa.PrivateKey{
+ PublicKey: encryptedKeyPub,
+ D: bigFromBase10("32355588668219869544751561565313228297765464314098552250409557267371233892496951383426602439009993875125222579159850054973310859166139474359774543943714622292329487391199285040721944491839695981199720170366763547754915493640685849961780092241140181198779299712578774460837139360803883139311171713302987058393"),
+}
+
+var encryptedKeyPriv = &PrivateKey{
+ PublicKey: PublicKey{
+ PubKeyAlgo: PubKeyAlgoRSA,
+ },
+ PrivateKey: encryptedKeyRSAPriv,
+}
+
+func TestDecryptingEncryptedKey(t *testing.T) {
+ const encryptedKeyHex = "c18c032a67d68660df41c70104005789d0de26b6a50c985a02a13131ca829c413a35d0e6fa8d6842599252162808ac7439c72151c8c6183e76923fe3299301414d0c25a2f06a2257db3839e7df0ec964773f6e4c4ac7ff3b48c444237166dd46ba8ff443a5410dc670cb486672fdbe7c9dfafb75b4fea83af3a204fe2a7dfa86bd20122b4f3d2646cbeecb8f7be8"
+ const expectedKeyHex = "d930363f7e0308c333b9618617ea728963d8df993665ae7be1092d4926fd864b"
+
+ p, err := Read(readerFromHex(encryptedKeyHex))
+ if err != nil {
+ t.Errorf("error from Read: %s", err)
+ return
+ }
+ ek, ok := p.(*EncryptedKey)
+ if !ok {
+ t.Errorf("didn't parse an EncryptedKey, got %#v", p)
+ return
+ }
+
+ if ek.KeyId != 0x2a67d68660df41c7 || ek.Algo != PubKeyAlgoRSA {
+ t.Errorf("unexpected EncryptedKey contents: %#v", ek)
+ return
+ }
+
+ err = ek.Decrypt(encryptedKeyPriv, nil)
+ if err != nil {
+ t.Errorf("error from Decrypt: %s", err)
+ return
+ }
+
+ if ek.CipherFunc != CipherAES256 {
+ t.Errorf("unexpected EncryptedKey contents: %#v", ek)
+ return
+ }
+
+ keyHex := fmt.Sprintf("%x", ek.Key)
+ if keyHex != expectedKeyHex {
+ t.Errorf("bad key, got %s want %x", keyHex, expectedKeyHex)
+ }
+}
+
+func TestEncryptingEncryptedKey(t *testing.T) {
+ key := []byte{1, 2, 3, 4}
+ const expectedKeyHex = "01020304"
+ const keyId = 42
+
+ pub := &PublicKey{
+ PublicKey: &encryptedKeyPub,
+ KeyId: keyId,
+ PubKeyAlgo: PubKeyAlgoRSAEncryptOnly,
+ }
+
+ buf := new(bytes.Buffer)
+ err := SerializeEncryptedKey(buf, pub, CipherAES128, key, nil)
+ if err != nil {
+ t.Errorf("error writing encrypted key packet: %s", err)
+ }
+
+ p, err := Read(buf)
+ if err != nil {
+ t.Errorf("error from Read: %s", err)
+ return
+ }
+ ek, ok := p.(*EncryptedKey)
+ if !ok {
+ t.Errorf("didn't parse an EncryptedKey, got %#v", p)
+ return
+ }
+
+ if ek.KeyId != keyId || ek.Algo != PubKeyAlgoRSAEncryptOnly {
+ t.Errorf("unexpected EncryptedKey contents: %#v", ek)
+ return
+ }
+
+ err = ek.Decrypt(encryptedKeyPriv, nil)
+ if err != nil {
+ t.Errorf("error from Decrypt: %s", err)
+ return
+ }
+
+ if ek.CipherFunc != CipherAES128 {
+ t.Errorf("unexpected EncryptedKey contents: %#v", ek)
+ return
+ }
+
+ keyHex := fmt.Sprintf("%x", ek.Key)
+ if keyHex != expectedKeyHex {
+ t.Errorf("bad key, got %s want %x", keyHex, expectedKeyHex)
+ }
+}
+
+func TestSerializingEncryptedKey(t *testing.T) {
+ const encryptedKeyHex = "c18c032a67d68660df41c70104005789d0de26b6a50c985a02a13131ca829c413a35d0e6fa8d6842599252162808ac7439c72151c8c6183e76923fe3299301414d0c25a2f06a2257db3839e7df0ec964773f6e4c4ac7ff3b48c444237166dd46ba8ff443a5410dc670cb486672fdbe7c9dfafb75b4fea83af3a204fe2a7dfa86bd20122b4f3d2646cbeecb8f7be8"
+
+ p, err := Read(readerFromHex(encryptedKeyHex))
+ if err != nil {
+ t.Fatalf("error from Read: %s", err)
+ }
+ ek, ok := p.(*EncryptedKey)
+ if !ok {
+ t.Fatalf("didn't parse an EncryptedKey, got %#v", p)
+ }
+
+ var buf bytes.Buffer
+ ek.Serialize(&buf)
+
+ if bufHex := hex.EncodeToString(buf.Bytes()); bufHex != encryptedKeyHex {
+ t.Fatalf("serialization of encrypted key differed from original. Original was %s, but reserialized as %s", encryptedKeyHex, bufHex)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/literal.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/literal.go
new file mode 100644
index 000000000..1a9ec6e51
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/literal.go
@@ -0,0 +1,89 @@
+// Copyright 2011 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 packet
+
+import (
+ "encoding/binary"
+ "io"
+)
+
+// LiteralData represents an encrypted file. See RFC 4880, section 5.9.
+type LiteralData struct {
+ IsBinary bool
+ FileName string
+ Time uint32 // Unix epoch time. Either creation time or modification time. 0 means undefined.
+ Body io.Reader
+}
+
+// ForEyesOnly returns whether the contents of the LiteralData have been marked
+// as especially sensitive.
+func (l *LiteralData) ForEyesOnly() bool {
+ return l.FileName == "_CONSOLE"
+}
+
+func (l *LiteralData) parse(r io.Reader) (err error) {
+ var buf [256]byte
+
+ _, err = readFull(r, buf[:2])
+ if err != nil {
+ return
+ }
+
+ l.IsBinary = buf[0] == 'b'
+ fileNameLen := int(buf[1])
+
+ _, err = readFull(r, buf[:fileNameLen])
+ if err != nil {
+ return
+ }
+
+ l.FileName = string(buf[:fileNameLen])
+
+ _, err = readFull(r, buf[:4])
+ if err != nil {
+ return
+ }
+
+ l.Time = binary.BigEndian.Uint32(buf[:4])
+ l.Body = r
+ return
+}
+
+// SerializeLiteral serializes a literal data packet to w and returns a
+// WriteCloser to which the data itself can be written and which MUST be closed
+// on completion. The fileName is truncated to 255 bytes.
+func SerializeLiteral(w io.WriteCloser, isBinary bool, fileName string, time uint32) (plaintext io.WriteCloser, err error) {
+ var buf [4]byte
+ buf[0] = 't'
+ if isBinary {
+ buf[0] = 'b'
+ }
+ if len(fileName) > 255 {
+ fileName = fileName[:255]
+ }
+ buf[1] = byte(len(fileName))
+
+ inner, err := serializeStreamHeader(w, packetTypeLiteralData)
+ if err != nil {
+ return
+ }
+
+ _, err = inner.Write(buf[:2])
+ if err != nil {
+ return
+ }
+ _, err = inner.Write([]byte(fileName))
+ if err != nil {
+ return
+ }
+ binary.BigEndian.PutUint32(buf[:], time)
+ _, err = inner.Write(buf[:])
+ if err != nil {
+ return
+ }
+
+ plaintext = inner
+ return
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/ocfb.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/ocfb.go
new file mode 100644
index 000000000..ce2a33a54
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/ocfb.go
@@ -0,0 +1,143 @@
+// Copyright 2010 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.
+
+// OpenPGP CFB Mode. http://tools.ietf.org/html/rfc4880#section-13.9
+
+package packet
+
+import (
+ "crypto/cipher"
+)
+
+type ocfbEncrypter struct {
+ b cipher.Block
+ fre []byte
+ outUsed int
+}
+
+// An OCFBResyncOption determines if the "resynchronization step" of OCFB is
+// performed.
+type OCFBResyncOption bool
+
+const (
+ OCFBResync OCFBResyncOption = true
+ OCFBNoResync OCFBResyncOption = false
+)
+
+// NewOCFBEncrypter returns a cipher.Stream which encrypts data with OpenPGP's
+// cipher feedback mode using the given cipher.Block, and an initial amount of
+// ciphertext. randData must be random bytes and be the same length as the
+// cipher.Block's block size. Resync determines if the "resynchronization step"
+// from RFC 4880, 13.9 step 7 is performed. Different parts of OpenPGP vary on
+// this point.
+func NewOCFBEncrypter(block cipher.Block, randData []byte, resync OCFBResyncOption) (cipher.Stream, []byte) {
+ blockSize := block.BlockSize()
+ if len(randData) != blockSize {
+ return nil, nil
+ }
+
+ x := &ocfbEncrypter{
+ b: block,
+ fre: make([]byte, blockSize),
+ outUsed: 0,
+ }
+ prefix := make([]byte, blockSize+2)
+
+ block.Encrypt(x.fre, x.fre)
+ for i := 0; i < blockSize; i++ {
+ prefix[i] = randData[i] ^ x.fre[i]
+ }
+
+ block.Encrypt(x.fre, prefix[:blockSize])
+ prefix[blockSize] = x.fre[0] ^ randData[blockSize-2]
+ prefix[blockSize+1] = x.fre[1] ^ randData[blockSize-1]
+
+ if resync {
+ block.Encrypt(x.fre, prefix[2:])
+ } else {
+ x.fre[0] = prefix[blockSize]
+ x.fre[1] = prefix[blockSize+1]
+ x.outUsed = 2
+ }
+ return x, prefix
+}
+
+func (x *ocfbEncrypter) XORKeyStream(dst, src []byte) {
+ for i := 0; i < len(src); i++ {
+ if x.outUsed == len(x.fre) {
+ x.b.Encrypt(x.fre, x.fre)
+ x.outUsed = 0
+ }
+
+ x.fre[x.outUsed] ^= src[i]
+ dst[i] = x.fre[x.outUsed]
+ x.outUsed++
+ }
+}
+
+type ocfbDecrypter struct {
+ b cipher.Block
+ fre []byte
+ outUsed int
+}
+
+// NewOCFBDecrypter returns a cipher.Stream which decrypts data with OpenPGP's
+// cipher feedback mode using the given cipher.Block. Prefix must be the first
+// blockSize + 2 bytes of the ciphertext, where blockSize is the cipher.Block's
+// block size. If an incorrect key is detected then nil is returned. On
+// successful exit, blockSize+2 bytes of decrypted data are written into
+// prefix. Resync determines if the "resynchronization step" from RFC 4880,
+// 13.9 step 7 is performed. Different parts of OpenPGP vary on this point.
+func NewOCFBDecrypter(block cipher.Block, prefix []byte, resync OCFBResyncOption) cipher.Stream {
+ blockSize := block.BlockSize()
+ if len(prefix) != blockSize+2 {
+ return nil
+ }
+
+ x := &ocfbDecrypter{
+ b: block,
+ fre: make([]byte, blockSize),
+ outUsed: 0,
+ }
+ prefixCopy := make([]byte, len(prefix))
+ copy(prefixCopy, prefix)
+
+ block.Encrypt(x.fre, x.fre)
+ for i := 0; i < blockSize; i++ {
+ prefixCopy[i] ^= x.fre[i]
+ }
+
+ block.Encrypt(x.fre, prefix[:blockSize])
+ prefixCopy[blockSize] ^= x.fre[0]
+ prefixCopy[blockSize+1] ^= x.fre[1]
+
+ if prefixCopy[blockSize-2] != prefixCopy[blockSize] ||
+ prefixCopy[blockSize-1] != prefixCopy[blockSize+1] {
+ return nil
+ }
+
+ if resync {
+ block.Encrypt(x.fre, prefix[2:])
+ } else {
+ x.fre[0] = prefix[blockSize]
+ x.fre[1] = prefix[blockSize+1]
+ x.outUsed = 2
+ }
+ copy(prefix, prefixCopy)
+ return x
+}
+
+func (x *ocfbDecrypter) XORKeyStream(dst, src []byte) {
+ for i := 0; i < len(src); i++ {
+ if x.outUsed == len(x.fre) {
+ x.b.Encrypt(x.fre, x.fre)
+ x.outUsed = 0
+ }
+
+ c := src[i]
+ dst[i] = x.fre[x.outUsed] ^ src[i]
+ x.fre[x.outUsed] = c
+ x.outUsed++
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/ocfb_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/ocfb_test.go
new file mode 100644
index 000000000..91022c042
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/ocfb_test.go
@@ -0,0 +1,46 @@
+// Copyright 2010 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 packet
+
+import (
+ "bytes"
+ "crypto/aes"
+ "crypto/rand"
+ "testing"
+)
+
+var commonKey128 = []byte{0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c}
+
+func testOCFB(t *testing.T, resync OCFBResyncOption) {
+ block, err := aes.NewCipher(commonKey128)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+
+ plaintext := []byte("this is the plaintext, which is long enough to span several blocks.")
+ randData := make([]byte, block.BlockSize())
+ rand.Reader.Read(randData)
+ ocfb, prefix := NewOCFBEncrypter(block, randData, resync)
+ ciphertext := make([]byte, len(plaintext))
+ ocfb.XORKeyStream(ciphertext, plaintext)
+
+ ocfbdec := NewOCFBDecrypter(block, prefix, resync)
+ if ocfbdec == nil {
+ t.Errorf("NewOCFBDecrypter failed (resync: %t)", resync)
+ return
+ }
+ plaintextCopy := make([]byte, len(plaintext))
+ ocfbdec.XORKeyStream(plaintextCopy, ciphertext)
+
+ if !bytes.Equal(plaintextCopy, plaintext) {
+ t.Errorf("got: %x, want: %x (resync: %t)", plaintextCopy, plaintext, resync)
+ }
+}
+
+func TestOCFB(t *testing.T) {
+ testOCFB(t, OCFBNoResync)
+ testOCFB(t, OCFBResync)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/one_pass_signature.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/one_pass_signature.go
new file mode 100644
index 000000000..171350339
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/one_pass_signature.go
@@ -0,0 +1,73 @@
+// Copyright 2011 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 packet
+
+import (
+ "crypto"
+ "encoding/binary"
+ "golang.org/x/crypto/openpgp/errors"
+ "golang.org/x/crypto/openpgp/s2k"
+ "io"
+ "strconv"
+)
+
+// OnePassSignature represents a one-pass signature packet. See RFC 4880,
+// section 5.4.
+type OnePassSignature struct {
+ SigType SignatureType
+ Hash crypto.Hash
+ PubKeyAlgo PublicKeyAlgorithm
+ KeyId uint64
+ IsLast bool
+}
+
+const onePassSignatureVersion = 3
+
+func (ops *OnePassSignature) parse(r io.Reader) (err error) {
+ var buf [13]byte
+
+ _, err = readFull(r, buf[:])
+ if err != nil {
+ return
+ }
+ if buf[0] != onePassSignatureVersion {
+ err = errors.UnsupportedError("one-pass-signature packet version " + strconv.Itoa(int(buf[0])))
+ }
+
+ var ok bool
+ ops.Hash, ok = s2k.HashIdToHash(buf[2])
+ if !ok {
+ return errors.UnsupportedError("hash function: " + strconv.Itoa(int(buf[2])))
+ }
+
+ ops.SigType = SignatureType(buf[1])
+ ops.PubKeyAlgo = PublicKeyAlgorithm(buf[3])
+ ops.KeyId = binary.BigEndian.Uint64(buf[4:12])
+ ops.IsLast = buf[12] != 0
+ return
+}
+
+// Serialize marshals the given OnePassSignature to w.
+func (ops *OnePassSignature) Serialize(w io.Writer) error {
+ var buf [13]byte
+ buf[0] = onePassSignatureVersion
+ buf[1] = uint8(ops.SigType)
+ var ok bool
+ buf[2], ok = s2k.HashToHashId(ops.Hash)
+ if !ok {
+ return errors.UnsupportedError("hash type: " + strconv.Itoa(int(ops.Hash)))
+ }
+ buf[3] = uint8(ops.PubKeyAlgo)
+ binary.BigEndian.PutUint64(buf[4:12], ops.KeyId)
+ if ops.IsLast {
+ buf[12] = 1
+ }
+
+ if err := serializeHeader(w, packetTypeOnePassSignature, len(buf)); err != nil {
+ return err
+ }
+ _, err := w.Write(buf[:])
+ return err
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/opaque.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/opaque.go
new file mode 100644
index 000000000..456d807f2
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/opaque.go
@@ -0,0 +1,162 @@
+// Copyright 2012 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 packet
+
+import (
+ "bytes"
+ "io"
+ "io/ioutil"
+
+ "golang.org/x/crypto/openpgp/errors"
+)
+
+// OpaquePacket represents an OpenPGP packet as raw, unparsed data. This is
+// useful for splitting and storing the original packet contents separately,
+// handling unsupported packet types or accessing parts of the packet not yet
+// implemented by this package.
+type OpaquePacket struct {
+ // Packet type
+ Tag uint8
+ // Reason why the packet was parsed opaquely
+ Reason error
+ // Binary contents of the packet data
+ Contents []byte
+}
+
+func (op *OpaquePacket) parse(r io.Reader) (err error) {
+ op.Contents, err = ioutil.ReadAll(r)
+ return
+}
+
+// Serialize marshals the packet to a writer in its original form, including
+// the packet header.
+func (op *OpaquePacket) Serialize(w io.Writer) (err error) {
+ err = serializeHeader(w, packetType(op.Tag), len(op.Contents))
+ if err == nil {
+ _, err = w.Write(op.Contents)
+ }
+ return
+}
+
+// Parse attempts to parse the opaque contents into a structure supported by
+// this package. If the packet is not known then the result will be another
+// OpaquePacket.
+func (op *OpaquePacket) Parse() (p Packet, err error) {
+ hdr := bytes.NewBuffer(nil)
+ err = serializeHeader(hdr, packetType(op.Tag), len(op.Contents))
+ if err != nil {
+ op.Reason = err
+ return op, err
+ }
+ p, err = Read(io.MultiReader(hdr, bytes.NewBuffer(op.Contents)))
+ if err != nil {
+ op.Reason = err
+ p = op
+ }
+ return
+}
+
+// OpaqueReader reads OpaquePackets from an io.Reader.
+type OpaqueReader struct {
+ r io.Reader
+}
+
+func NewOpaqueReader(r io.Reader) *OpaqueReader {
+ return &OpaqueReader{r: r}
+}
+
+// Read the next OpaquePacket.
+func (or *OpaqueReader) Next() (op *OpaquePacket, err error) {
+ tag, _, contents, err := readHeader(or.r)
+ if err != nil {
+ return
+ }
+ op = &OpaquePacket{Tag: uint8(tag), Reason: err}
+ err = op.parse(contents)
+ if err != nil {
+ consumeAll(contents)
+ }
+ return
+}
+
+// OpaqueSubpacket represents an unparsed OpenPGP subpacket,
+// as found in signature and user attribute packets.
+type OpaqueSubpacket struct {
+ SubType uint8
+ Contents []byte
+}
+
+// OpaqueSubpackets extracts opaque, unparsed OpenPGP subpackets from
+// their byte representation.
+func OpaqueSubpackets(contents []byte) (result []*OpaqueSubpacket, err error) {
+ var (
+ subHeaderLen int
+ subPacket *OpaqueSubpacket
+ )
+ for len(contents) > 0 {
+ subHeaderLen, subPacket, err = nextSubpacket(contents)
+ if err != nil {
+ break
+ }
+ result = append(result, subPacket)
+ contents = contents[subHeaderLen+len(subPacket.Contents):]
+ }
+ return
+}
+
+func nextSubpacket(contents []byte) (subHeaderLen int, subPacket *OpaqueSubpacket, err error) {
+ // RFC 4880, section 5.2.3.1
+ var subLen uint32
+ if len(contents) < 1 {
+ goto Truncated
+ }
+ subPacket = &OpaqueSubpacket{}
+ switch {
+ case contents[0] < 192:
+ subHeaderLen = 2 // 1 length byte, 1 subtype byte
+ if len(contents) < subHeaderLen {
+ goto Truncated
+ }
+ subLen = uint32(contents[0])
+ contents = contents[1:]
+ case contents[0] < 255:
+ subHeaderLen = 3 // 2 length bytes, 1 subtype
+ if len(contents) < subHeaderLen {
+ goto Truncated
+ }
+ subLen = uint32(contents[0]-192)<<8 + uint32(contents[1]) + 192
+ contents = contents[2:]
+ default:
+ subHeaderLen = 6 // 5 length bytes, 1 subtype
+ if len(contents) < subHeaderLen {
+ goto Truncated
+ }
+ subLen = uint32(contents[1])<<24 |
+ uint32(contents[2])<<16 |
+ uint32(contents[3])<<8 |
+ uint32(contents[4])
+ contents = contents[5:]
+ }
+ if subLen > uint32(len(contents)) || subLen == 0 {
+ goto Truncated
+ }
+ subPacket.SubType = contents[0]
+ subPacket.Contents = contents[1:subLen]
+ return
+Truncated:
+ err = errors.StructuralError("subpacket truncated")
+ return
+}
+
+func (osp *OpaqueSubpacket) Serialize(w io.Writer) (err error) {
+ buf := make([]byte, 6)
+ n := serializeSubpacketLength(buf, len(osp.Contents)+1)
+ buf[n] = osp.SubType
+ if _, err = w.Write(buf[:n+1]); err != nil {
+ return
+ }
+ _, err = w.Write(osp.Contents)
+ return
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/opaque_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/opaque_test.go
new file mode 100644
index 000000000..f27bbfe09
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/opaque_test.go
@@ -0,0 +1,67 @@
+// Copyright 2011 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 packet
+
+import (
+ "bytes"
+ "encoding/hex"
+ "io"
+ "testing"
+)
+
+// Test packet.Read error handling in OpaquePacket.Parse,
+// which attempts to re-read an OpaquePacket as a supported
+// Packet type.
+func TestOpaqueParseReason(t *testing.T) {
+ buf, err := hex.DecodeString(UnsupportedKeyHex)
+ if err != nil {
+ t.Fatal(err)
+ }
+ or := NewOpaqueReader(bytes.NewBuffer(buf))
+ count := 0
+ badPackets := 0
+ var uid *UserId
+ for {
+ op, err := or.Next()
+ if err == io.EOF {
+ break
+ } else if err != nil {
+ t.Errorf("#%d: opaque read error: %v", count, err)
+ break
+ }
+ // try to parse opaque packet
+ p, err := op.Parse()
+ switch pkt := p.(type) {
+ case *UserId:
+ uid = pkt
+ case *OpaquePacket:
+ // If an OpaquePacket can't re-parse, packet.Read
+ // certainly had its reasons.
+ if pkt.Reason == nil {
+ t.Errorf("#%d: opaque packet, no reason", count)
+ } else {
+ badPackets++
+ }
+ }
+ count++
+ }
+
+ const expectedBad = 3
+ // Test post-conditions, make sure we actually parsed packets as expected.
+ if badPackets != expectedBad {
+ t.Errorf("unexpected # unparseable packets: %d (want %d)", badPackets, expectedBad)
+ }
+ if uid == nil {
+ t.Errorf("failed to find expected UID in unsupported keyring")
+ } else if uid.Id != "Armin M. Warda <warda@nephilim.ruhr.de>" {
+ t.Errorf("unexpected UID: %v", uid.Id)
+ }
+}
+
+// This key material has public key and signature packet versions modified to
+// an unsupported value (1), so that trying to parse the OpaquePacket to
+// a typed packet will get an error. It also contains a GnuPG trust packet.
+// (Created with: od -An -t x1 pubring.gpg | xargs | sed 's/ //g')
+const UnsupportedKeyHex = `988d012e7a18a20000010400d6ac00d92b89c1f4396c243abb9b76d2e9673ad63483291fed88e22b82e255e441c078c6abbbf7d2d195e50b62eeaa915b85b0ec20c225ce2c64c167cacb6e711daf2e45da4a8356a059b8160e3b3628ac0dd8437b31f06d53d6e8ea4214d4a26406a6b63e1001406ef23e0bb3069fac9a99a91f77dfafd5de0f188a5da5e3c9000511b42741726d696e204d2e205761726461203c7761726461406e657068696c696d2e727568722e64653e8900950105102e8936c705d1eb399e58489901013f0e03ff5a0c4f421e34fcfa388129166420c08cd76987bcdec6f01bd0271459a85cc22048820dd4e44ac2c7d23908d540f54facf1b36b0d9c20488781ce9dca856531e76e2e846826e9951338020a03a09b57aa5faa82e9267458bd76105399885ac35af7dc1cbb6aaed7c39e1039f3b5beda2c0e916bd38560509bab81235d1a0ead83b0020000`
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/packet.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/packet.go
new file mode 100644
index 000000000..3eded93f0
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/packet.go
@@ -0,0 +1,537 @@
+// Copyright 2011 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 packet implements parsing and serialization of OpenPGP packets, as
+// specified in RFC 4880.
+package packet // import "golang.org/x/crypto/openpgp/packet"
+
+import (
+ "bufio"
+ "crypto/aes"
+ "crypto/cipher"
+ "crypto/des"
+ "golang.org/x/crypto/cast5"
+ "golang.org/x/crypto/openpgp/errors"
+ "io"
+ "math/big"
+)
+
+// readFull is the same as io.ReadFull except that reading zero bytes returns
+// ErrUnexpectedEOF rather than EOF.
+func readFull(r io.Reader, buf []byte) (n int, err error) {
+ n, err = io.ReadFull(r, buf)
+ if err == io.EOF {
+ err = io.ErrUnexpectedEOF
+ }
+ return
+}
+
+// readLength reads an OpenPGP length from r. See RFC 4880, section 4.2.2.
+func readLength(r io.Reader) (length int64, isPartial bool, err error) {
+ var buf [4]byte
+ _, err = readFull(r, buf[:1])
+ if err != nil {
+ return
+ }
+ switch {
+ case buf[0] < 192:
+ length = int64(buf[0])
+ case buf[0] < 224:
+ length = int64(buf[0]-192) << 8
+ _, err = readFull(r, buf[0:1])
+ if err != nil {
+ return
+ }
+ length += int64(buf[0]) + 192
+ case buf[0] < 255:
+ length = int64(1) << (buf[0] & 0x1f)
+ isPartial = true
+ default:
+ _, err = readFull(r, buf[0:4])
+ if err != nil {
+ return
+ }
+ length = int64(buf[0])<<24 |
+ int64(buf[1])<<16 |
+ int64(buf[2])<<8 |
+ int64(buf[3])
+ }
+ return
+}
+
+// partialLengthReader wraps an io.Reader and handles OpenPGP partial lengths.
+// The continuation lengths are parsed and removed from the stream and EOF is
+// returned at the end of the packet. See RFC 4880, section 4.2.2.4.
+type partialLengthReader struct {
+ r io.Reader
+ remaining int64
+ isPartial bool
+}
+
+func (r *partialLengthReader) Read(p []byte) (n int, err error) {
+ for r.remaining == 0 {
+ if !r.isPartial {
+ return 0, io.EOF
+ }
+ r.remaining, r.isPartial, err = readLength(r.r)
+ if err != nil {
+ return 0, err
+ }
+ }
+
+ toRead := int64(len(p))
+ if toRead > r.remaining {
+ toRead = r.remaining
+ }
+
+ n, err = r.r.Read(p[:int(toRead)])
+ r.remaining -= int64(n)
+ if n < int(toRead) && err == io.EOF {
+ err = io.ErrUnexpectedEOF
+ }
+ return
+}
+
+// partialLengthWriter writes a stream of data using OpenPGP partial lengths.
+// See RFC 4880, section 4.2.2.4.
+type partialLengthWriter struct {
+ w io.WriteCloser
+ lengthByte [1]byte
+}
+
+func (w *partialLengthWriter) Write(p []byte) (n int, err error) {
+ for len(p) > 0 {
+ for power := uint(14); power < 32; power-- {
+ l := 1 << power
+ if len(p) >= l {
+ w.lengthByte[0] = 224 + uint8(power)
+ _, err = w.w.Write(w.lengthByte[:])
+ if err != nil {
+ return
+ }
+ var m int
+ m, err = w.w.Write(p[:l])
+ n += m
+ if err != nil {
+ return
+ }
+ p = p[l:]
+ break
+ }
+ }
+ }
+ return
+}
+
+func (w *partialLengthWriter) Close() error {
+ w.lengthByte[0] = 0
+ _, err := w.w.Write(w.lengthByte[:])
+ if err != nil {
+ return err
+ }
+ return w.w.Close()
+}
+
+// A spanReader is an io.LimitReader, but it returns ErrUnexpectedEOF if the
+// underlying Reader returns EOF before the limit has been reached.
+type spanReader struct {
+ r io.Reader
+ n int64
+}
+
+func (l *spanReader) Read(p []byte) (n int, err error) {
+ if l.n <= 0 {
+ return 0, io.EOF
+ }
+ if int64(len(p)) > l.n {
+ p = p[0:l.n]
+ }
+ n, err = l.r.Read(p)
+ l.n -= int64(n)
+ if l.n > 0 && err == io.EOF {
+ err = io.ErrUnexpectedEOF
+ }
+ return
+}
+
+// readHeader parses a packet header and returns an io.Reader which will return
+// the contents of the packet. See RFC 4880, section 4.2.
+func readHeader(r io.Reader) (tag packetType, length int64, contents io.Reader, err error) {
+ var buf [4]byte
+ _, err = io.ReadFull(r, buf[:1])
+ if err != nil {
+ return
+ }
+ if buf[0]&0x80 == 0 {
+ err = errors.StructuralError("tag byte does not have MSB set")
+ return
+ }
+ if buf[0]&0x40 == 0 {
+ // Old format packet
+ tag = packetType((buf[0] & 0x3f) >> 2)
+ lengthType := buf[0] & 3
+ if lengthType == 3 {
+ length = -1
+ contents = r
+ return
+ }
+ lengthBytes := 1 << lengthType
+ _, err = readFull(r, buf[0:lengthBytes])
+ if err != nil {
+ return
+ }
+ for i := 0; i < lengthBytes; i++ {
+ length <<= 8
+ length |= int64(buf[i])
+ }
+ contents = &spanReader{r, length}
+ return
+ }
+
+ // New format packet
+ tag = packetType(buf[0] & 0x3f)
+ length, isPartial, err := readLength(r)
+ if err != nil {
+ return
+ }
+ if isPartial {
+ contents = &partialLengthReader{
+ remaining: length,
+ isPartial: true,
+ r: r,
+ }
+ length = -1
+ } else {
+ contents = &spanReader{r, length}
+ }
+ return
+}
+
+// serializeHeader writes an OpenPGP packet header to w. See RFC 4880, section
+// 4.2.
+func serializeHeader(w io.Writer, ptype packetType, length int) (err error) {
+ var buf [6]byte
+ var n int
+
+ buf[0] = 0x80 | 0x40 | byte(ptype)
+ if length < 192 {
+ buf[1] = byte(length)
+ n = 2
+ } else if length < 8384 {
+ length -= 192
+ buf[1] = 192 + byte(length>>8)
+ buf[2] = byte(length)
+ n = 3
+ } else {
+ buf[1] = 255
+ buf[2] = byte(length >> 24)
+ buf[3] = byte(length >> 16)
+ buf[4] = byte(length >> 8)
+ buf[5] = byte(length)
+ n = 6
+ }
+
+ _, err = w.Write(buf[:n])
+ return
+}
+
+// serializeStreamHeader writes an OpenPGP packet header to w where the
+// length of the packet is unknown. It returns a io.WriteCloser which can be
+// used to write the contents of the packet. See RFC 4880, section 4.2.
+func serializeStreamHeader(w io.WriteCloser, ptype packetType) (out io.WriteCloser, err error) {
+ var buf [1]byte
+ buf[0] = 0x80 | 0x40 | byte(ptype)
+ _, err = w.Write(buf[:])
+ if err != nil {
+ return
+ }
+ out = &partialLengthWriter{w: w}
+ return
+}
+
+// Packet represents an OpenPGP packet. Users are expected to try casting
+// instances of this interface to specific packet types.
+type Packet interface {
+ parse(io.Reader) error
+}
+
+// consumeAll reads from the given Reader until error, returning the number of
+// bytes read.
+func consumeAll(r io.Reader) (n int64, err error) {
+ var m int
+ var buf [1024]byte
+
+ for {
+ m, err = r.Read(buf[:])
+ n += int64(m)
+ if err == io.EOF {
+ err = nil
+ return
+ }
+ if err != nil {
+ return
+ }
+ }
+}
+
+// packetType represents the numeric ids of the different OpenPGP packet types. See
+// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-2
+type packetType uint8
+
+const (
+ packetTypeEncryptedKey packetType = 1
+ packetTypeSignature packetType = 2
+ packetTypeSymmetricKeyEncrypted packetType = 3
+ packetTypeOnePassSignature packetType = 4
+ packetTypePrivateKey packetType = 5
+ packetTypePublicKey packetType = 6
+ packetTypePrivateSubkey packetType = 7
+ packetTypeCompressed packetType = 8
+ packetTypeSymmetricallyEncrypted packetType = 9
+ packetTypeLiteralData packetType = 11
+ packetTypeUserId packetType = 13
+ packetTypePublicSubkey packetType = 14
+ packetTypeUserAttribute packetType = 17
+ packetTypeSymmetricallyEncryptedMDC packetType = 18
+)
+
+// peekVersion detects the version of a public key packet about to
+// be read. A bufio.Reader at the original position of the io.Reader
+// is returned.
+func peekVersion(r io.Reader) (bufr *bufio.Reader, ver byte, err error) {
+ bufr = bufio.NewReader(r)
+ var verBuf []byte
+ if verBuf, err = bufr.Peek(1); err != nil {
+ return
+ }
+ ver = verBuf[0]
+ return
+}
+
+// Read reads a single OpenPGP packet from the given io.Reader. If there is an
+// error parsing a packet, the whole packet is consumed from the input.
+func Read(r io.Reader) (p Packet, err error) {
+ tag, _, contents, err := readHeader(r)
+ if err != nil {
+ return
+ }
+
+ switch tag {
+ case packetTypeEncryptedKey:
+ p = new(EncryptedKey)
+ case packetTypeSignature:
+ var version byte
+ // Detect signature version
+ if contents, version, err = peekVersion(contents); err != nil {
+ return
+ }
+ if version < 4 {
+ p = new(SignatureV3)
+ } else {
+ p = new(Signature)
+ }
+ case packetTypeSymmetricKeyEncrypted:
+ p = new(SymmetricKeyEncrypted)
+ case packetTypeOnePassSignature:
+ p = new(OnePassSignature)
+ case packetTypePrivateKey, packetTypePrivateSubkey:
+ pk := new(PrivateKey)
+ if tag == packetTypePrivateSubkey {
+ pk.IsSubkey = true
+ }
+ p = pk
+ case packetTypePublicKey, packetTypePublicSubkey:
+ var version byte
+ if contents, version, err = peekVersion(contents); err != nil {
+ return
+ }
+ isSubkey := tag == packetTypePublicSubkey
+ if version < 4 {
+ p = &PublicKeyV3{IsSubkey: isSubkey}
+ } else {
+ p = &PublicKey{IsSubkey: isSubkey}
+ }
+ case packetTypeCompressed:
+ p = new(Compressed)
+ case packetTypeSymmetricallyEncrypted:
+ p = new(SymmetricallyEncrypted)
+ case packetTypeLiteralData:
+ p = new(LiteralData)
+ case packetTypeUserId:
+ p = new(UserId)
+ case packetTypeUserAttribute:
+ p = new(UserAttribute)
+ case packetTypeSymmetricallyEncryptedMDC:
+ se := new(SymmetricallyEncrypted)
+ se.MDC = true
+ p = se
+ default:
+ err = errors.UnknownPacketTypeError(tag)
+ }
+ if p != nil {
+ err = p.parse(contents)
+ }
+ if err != nil {
+ consumeAll(contents)
+ }
+ return
+}
+
+// SignatureType represents the different semantic meanings of an OpenPGP
+// signature. See RFC 4880, section 5.2.1.
+type SignatureType uint8
+
+const (
+ SigTypeBinary SignatureType = 0
+ SigTypeText = 1
+ SigTypeGenericCert = 0x10
+ SigTypePersonaCert = 0x11
+ SigTypeCasualCert = 0x12
+ SigTypePositiveCert = 0x13
+ SigTypeSubkeyBinding = 0x18
+ SigTypePrimaryKeyBinding = 0x19
+ SigTypeDirectSignature = 0x1F
+ SigTypeKeyRevocation = 0x20
+ SigTypeSubkeyRevocation = 0x28
+)
+
+// PublicKeyAlgorithm represents the different public key system specified for
+// OpenPGP. See
+// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-12
+type PublicKeyAlgorithm uint8
+
+const (
+ PubKeyAlgoRSA PublicKeyAlgorithm = 1
+ PubKeyAlgoRSAEncryptOnly PublicKeyAlgorithm = 2
+ PubKeyAlgoRSASignOnly PublicKeyAlgorithm = 3
+ PubKeyAlgoElGamal PublicKeyAlgorithm = 16
+ PubKeyAlgoDSA PublicKeyAlgorithm = 17
+ // RFC 6637, Section 5.
+ PubKeyAlgoECDH PublicKeyAlgorithm = 18
+ PubKeyAlgoECDSA PublicKeyAlgorithm = 19
+)
+
+// CanEncrypt returns true if it's possible to encrypt a message to a public
+// key of the given type.
+func (pka PublicKeyAlgorithm) CanEncrypt() bool {
+ switch pka {
+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoElGamal:
+ return true
+ }
+ return false
+}
+
+// CanSign returns true if it's possible for a public key of the given type to
+// sign a message.
+func (pka PublicKeyAlgorithm) CanSign() bool {
+ switch pka {
+ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA:
+ return true
+ }
+ return false
+}
+
+// CipherFunction represents the different block ciphers specified for OpenPGP. See
+// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-13
+type CipherFunction uint8
+
+const (
+ Cipher3DES CipherFunction = 2
+ CipherCAST5 CipherFunction = 3
+ CipherAES128 CipherFunction = 7
+ CipherAES192 CipherFunction = 8
+ CipherAES256 CipherFunction = 9
+)
+
+// KeySize returns the key size, in bytes, of cipher.
+func (cipher CipherFunction) KeySize() int {
+ switch cipher {
+ case Cipher3DES:
+ return 24
+ case CipherCAST5:
+ return cast5.KeySize
+ case CipherAES128:
+ return 16
+ case CipherAES192:
+ return 24
+ case CipherAES256:
+ return 32
+ }
+ return 0
+}
+
+// blockSize returns the block size, in bytes, of cipher.
+func (cipher CipherFunction) blockSize() int {
+ switch cipher {
+ case Cipher3DES:
+ return des.BlockSize
+ case CipherCAST5:
+ return 8
+ case CipherAES128, CipherAES192, CipherAES256:
+ return 16
+ }
+ return 0
+}
+
+// new returns a fresh instance of the given cipher.
+func (cipher CipherFunction) new(key []byte) (block cipher.Block) {
+ switch cipher {
+ case Cipher3DES:
+ block, _ = des.NewTripleDESCipher(key)
+ case CipherCAST5:
+ block, _ = cast5.NewCipher(key)
+ case CipherAES128, CipherAES192, CipherAES256:
+ block, _ = aes.NewCipher(key)
+ }
+ return
+}
+
+// readMPI reads a big integer from r. The bit length returned is the bit
+// length that was specified in r. This is preserved so that the integer can be
+// reserialized exactly.
+func readMPI(r io.Reader) (mpi []byte, bitLength uint16, err error) {
+ var buf [2]byte
+ _, err = readFull(r, buf[0:])
+ if err != nil {
+ return
+ }
+ bitLength = uint16(buf[0])<<8 | uint16(buf[1])
+ numBytes := (int(bitLength) + 7) / 8
+ mpi = make([]byte, numBytes)
+ _, err = readFull(r, mpi)
+ return
+}
+
+// mpiLength returns the length of the given *big.Int when serialized as an
+// MPI.
+func mpiLength(n *big.Int) (mpiLengthInBytes int) {
+ mpiLengthInBytes = 2 /* MPI length */
+ mpiLengthInBytes += (n.BitLen() + 7) / 8
+ return
+}
+
+// writeMPI serializes a big integer to w.
+func writeMPI(w io.Writer, bitLength uint16, mpiBytes []byte) (err error) {
+ _, err = w.Write([]byte{byte(bitLength >> 8), byte(bitLength)})
+ if err == nil {
+ _, err = w.Write(mpiBytes)
+ }
+ return
+}
+
+// writeBig serializes a *big.Int to w.
+func writeBig(w io.Writer, i *big.Int) error {
+ return writeMPI(w, uint16(i.BitLen()), i.Bytes())
+}
+
+// CompressionAlgo Represents the different compression algorithms
+// supported by OpenPGP (except for BZIP2, which is not currently
+// supported). See Section 9.3 of RFC 4880.
+type CompressionAlgo uint8
+
+const (
+ CompressionNone CompressionAlgo = 0
+ CompressionZIP CompressionAlgo = 1
+ CompressionZLIB CompressionAlgo = 2
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/packet_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/packet_test.go
new file mode 100644
index 000000000..1dab5c3d5
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/packet_test.go
@@ -0,0 +1,255 @@
+// Copyright 2011 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 packet
+
+import (
+ "bytes"
+ "encoding/hex"
+ "fmt"
+ "golang.org/x/crypto/openpgp/errors"
+ "io"
+ "io/ioutil"
+ "testing"
+)
+
+func TestReadFull(t *testing.T) {
+ var out [4]byte
+
+ b := bytes.NewBufferString("foo")
+ n, err := readFull(b, out[:3])
+ if n != 3 || err != nil {
+ t.Errorf("full read failed n:%d err:%s", n, err)
+ }
+
+ b = bytes.NewBufferString("foo")
+ n, err = readFull(b, out[:4])
+ if n != 3 || err != io.ErrUnexpectedEOF {
+ t.Errorf("partial read failed n:%d err:%s", n, err)
+ }
+
+ b = bytes.NewBuffer(nil)
+ n, err = readFull(b, out[:3])
+ if n != 0 || err != io.ErrUnexpectedEOF {
+ t.Errorf("empty read failed n:%d err:%s", n, err)
+ }
+}
+
+func readerFromHex(s string) io.Reader {
+ data, err := hex.DecodeString(s)
+ if err != nil {
+ panic("readerFromHex: bad input")
+ }
+ return bytes.NewBuffer(data)
+}
+
+var readLengthTests = []struct {
+ hexInput string
+ length int64
+ isPartial bool
+ err error
+}{
+ {"", 0, false, io.ErrUnexpectedEOF},
+ {"1f", 31, false, nil},
+ {"c0", 0, false, io.ErrUnexpectedEOF},
+ {"c101", 256 + 1 + 192, false, nil},
+ {"e0", 1, true, nil},
+ {"e1", 2, true, nil},
+ {"e2", 4, true, nil},
+ {"ff", 0, false, io.ErrUnexpectedEOF},
+ {"ff00", 0, false, io.ErrUnexpectedEOF},
+ {"ff0000", 0, false, io.ErrUnexpectedEOF},
+ {"ff000000", 0, false, io.ErrUnexpectedEOF},
+ {"ff00000000", 0, false, nil},
+ {"ff01020304", 16909060, false, nil},
+}
+
+func TestReadLength(t *testing.T) {
+ for i, test := range readLengthTests {
+ length, isPartial, err := readLength(readerFromHex(test.hexInput))
+ if test.err != nil {
+ if err != test.err {
+ t.Errorf("%d: expected different error got:%s want:%s", i, err, test.err)
+ }
+ continue
+ }
+ if err != nil {
+ t.Errorf("%d: unexpected error: %s", i, err)
+ continue
+ }
+ if length != test.length || isPartial != test.isPartial {
+ t.Errorf("%d: bad result got:(%d,%t) want:(%d,%t)", i, length, isPartial, test.length, test.isPartial)
+ }
+ }
+}
+
+var partialLengthReaderTests = []struct {
+ hexInput string
+ err error
+ hexOutput string
+}{
+ {"e0", io.ErrUnexpectedEOF, ""},
+ {"e001", io.ErrUnexpectedEOF, ""},
+ {"e0010102", nil, "0102"},
+ {"ff00000000", nil, ""},
+ {"e10102e1030400", nil, "01020304"},
+ {"e101", io.ErrUnexpectedEOF, ""},
+}
+
+func TestPartialLengthReader(t *testing.T) {
+ for i, test := range partialLengthReaderTests {
+ r := &partialLengthReader{readerFromHex(test.hexInput), 0, true}
+ out, err := ioutil.ReadAll(r)
+ if test.err != nil {
+ if err != test.err {
+ t.Errorf("%d: expected different error got:%s want:%s", i, err, test.err)
+ }
+ continue
+ }
+ if err != nil {
+ t.Errorf("%d: unexpected error: %s", i, err)
+ continue
+ }
+
+ got := fmt.Sprintf("%x", out)
+ if got != test.hexOutput {
+ t.Errorf("%d: got:%s want:%s", i, test.hexOutput, got)
+ }
+ }
+}
+
+var readHeaderTests = []struct {
+ hexInput string
+ structuralError bool
+ unexpectedEOF bool
+ tag int
+ length int64
+ hexOutput string
+}{
+ {"", false, false, 0, 0, ""},
+ {"7f", true, false, 0, 0, ""},
+
+ // Old format headers
+ {"80", false, true, 0, 0, ""},
+ {"8001", false, true, 0, 1, ""},
+ {"800102", false, false, 0, 1, "02"},
+ {"81000102", false, false, 0, 1, "02"},
+ {"820000000102", false, false, 0, 1, "02"},
+ {"860000000102", false, false, 1, 1, "02"},
+ {"83010203", false, false, 0, -1, "010203"},
+
+ // New format headers
+ {"c0", false, true, 0, 0, ""},
+ {"c000", false, false, 0, 0, ""},
+ {"c00102", false, false, 0, 1, "02"},
+ {"c0020203", false, false, 0, 2, "0203"},
+ {"c00202", false, true, 0, 2, ""},
+ {"c3020203", false, false, 3, 2, "0203"},
+}
+
+func TestReadHeader(t *testing.T) {
+ for i, test := range readHeaderTests {
+ tag, length, contents, err := readHeader(readerFromHex(test.hexInput))
+ if test.structuralError {
+ if _, ok := err.(errors.StructuralError); ok {
+ continue
+ }
+ t.Errorf("%d: expected StructuralError, got:%s", i, err)
+ continue
+ }
+ if err != nil {
+ if len(test.hexInput) == 0 && err == io.EOF {
+ continue
+ }
+ if !test.unexpectedEOF || err != io.ErrUnexpectedEOF {
+ t.Errorf("%d: unexpected error from readHeader: %s", i, err)
+ }
+ continue
+ }
+ if int(tag) != test.tag || length != test.length {
+ t.Errorf("%d: got:(%d,%d) want:(%d,%d)", i, int(tag), length, test.tag, test.length)
+ continue
+ }
+
+ body, err := ioutil.ReadAll(contents)
+ if err != nil {
+ if !test.unexpectedEOF || err != io.ErrUnexpectedEOF {
+ t.Errorf("%d: unexpected error from contents: %s", i, err)
+ }
+ continue
+ }
+ if test.unexpectedEOF {
+ t.Errorf("%d: expected ErrUnexpectedEOF from contents but got no error", i)
+ continue
+ }
+ got := fmt.Sprintf("%x", body)
+ if got != test.hexOutput {
+ t.Errorf("%d: got:%s want:%s", i, got, test.hexOutput)
+ }
+ }
+}
+
+func TestSerializeHeader(t *testing.T) {
+ tag := packetTypePublicKey
+ lengths := []int{0, 1, 2, 64, 192, 193, 8000, 8384, 8385, 10000}
+
+ for _, length := range lengths {
+ buf := bytes.NewBuffer(nil)
+ serializeHeader(buf, tag, length)
+ tag2, length2, _, err := readHeader(buf)
+ if err != nil {
+ t.Errorf("length %d, err: %s", length, err)
+ }
+ if tag2 != tag {
+ t.Errorf("length %d, tag incorrect (got %d, want %d)", length, tag2, tag)
+ }
+ if int(length2) != length {
+ t.Errorf("length %d, length incorrect (got %d)", length, length2)
+ }
+ }
+}
+
+func TestPartialLengths(t *testing.T) {
+ buf := bytes.NewBuffer(nil)
+ w := new(partialLengthWriter)
+ w.w = noOpCloser{buf}
+
+ const maxChunkSize = 64
+
+ var b [maxChunkSize]byte
+ var n uint8
+ for l := 1; l <= maxChunkSize; l++ {
+ for i := 0; i < l; i++ {
+ b[i] = n
+ n++
+ }
+ m, err := w.Write(b[:l])
+ if m != l {
+ t.Errorf("short write got: %d want: %d", m, l)
+ }
+ if err != nil {
+ t.Errorf("error from write: %s", err)
+ }
+ }
+ w.Close()
+
+ want := (maxChunkSize * (maxChunkSize + 1)) / 2
+ copyBuf := bytes.NewBuffer(nil)
+ r := &partialLengthReader{buf, 0, true}
+ m, err := io.Copy(copyBuf, r)
+ if m != int64(want) {
+ t.Errorf("short copy got: %d want: %d", m, want)
+ }
+ if err != nil {
+ t.Errorf("error from copy: %s", err)
+ }
+
+ copyBytes := copyBuf.Bytes()
+ for i := 0; i < want; i++ {
+ if copyBytes[i] != uint8(i) {
+ t.Errorf("bad pattern in copy at %d", i)
+ break
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/private_key.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/private_key.go
new file mode 100644
index 000000000..34734cc63
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/private_key.go
@@ -0,0 +1,380 @@
+// Copyright 2011 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 packet
+
+import (
+ "bytes"
+ "crypto"
+ "crypto/cipher"
+ "crypto/dsa"
+ "crypto/ecdsa"
+ "crypto/rsa"
+ "crypto/sha1"
+ "io"
+ "io/ioutil"
+ "math/big"
+ "strconv"
+ "time"
+
+ "golang.org/x/crypto/openpgp/elgamal"
+ "golang.org/x/crypto/openpgp/errors"
+ "golang.org/x/crypto/openpgp/s2k"
+)
+
+// PrivateKey represents a possibly encrypted private key. See RFC 4880,
+// section 5.5.3.
+type PrivateKey struct {
+ PublicKey
+ Encrypted bool // if true then the private key is unavailable until Decrypt has been called.
+ encryptedData []byte
+ cipher CipherFunction
+ s2k func(out, in []byte)
+ PrivateKey interface{} // An *{rsa|dsa|ecdsa}.PrivateKey or a crypto.Signer.
+ sha1Checksum bool
+ iv []byte
+}
+
+func NewRSAPrivateKey(currentTime time.Time, priv *rsa.PrivateKey) *PrivateKey {
+ pk := new(PrivateKey)
+ pk.PublicKey = *NewRSAPublicKey(currentTime, &priv.PublicKey)
+ pk.PrivateKey = priv
+ return pk
+}
+
+func NewDSAPrivateKey(currentTime time.Time, priv *dsa.PrivateKey) *PrivateKey {
+ pk := new(PrivateKey)
+ pk.PublicKey = *NewDSAPublicKey(currentTime, &priv.PublicKey)
+ pk.PrivateKey = priv
+ return pk
+}
+
+func NewElGamalPrivateKey(currentTime time.Time, priv *elgamal.PrivateKey) *PrivateKey {
+ pk := new(PrivateKey)
+ pk.PublicKey = *NewElGamalPublicKey(currentTime, &priv.PublicKey)
+ pk.PrivateKey = priv
+ return pk
+}
+
+func NewECDSAPrivateKey(currentTime time.Time, priv *ecdsa.PrivateKey) *PrivateKey {
+ pk := new(PrivateKey)
+ pk.PublicKey = *NewECDSAPublicKey(currentTime, &priv.PublicKey)
+ pk.PrivateKey = priv
+ return pk
+}
+
+// NewSignerPrivateKey creates a sign-only PrivateKey from a crypto.Signer that
+// implements RSA or ECDSA.
+func NewSignerPrivateKey(currentTime time.Time, signer crypto.Signer) *PrivateKey {
+ pk := new(PrivateKey)
+ switch pubkey := signer.Public().(type) {
+ case rsa.PublicKey:
+ pk.PublicKey = *NewRSAPublicKey(currentTime, &pubkey)
+ pk.PubKeyAlgo = PubKeyAlgoRSASignOnly
+ case ecdsa.PublicKey:
+ pk.PublicKey = *NewECDSAPublicKey(currentTime, &pubkey)
+ default:
+ panic("openpgp: unknown crypto.Signer type in NewSignerPrivateKey")
+ }
+ pk.PrivateKey = signer
+ return pk
+}
+
+func (pk *PrivateKey) parse(r io.Reader) (err error) {
+ err = (&pk.PublicKey).parse(r)
+ if err != nil {
+ return
+ }
+ var buf [1]byte
+ _, err = readFull(r, buf[:])
+ if err != nil {
+ return
+ }
+
+ s2kType := buf[0]
+
+ switch s2kType {
+ case 0:
+ pk.s2k = nil
+ pk.Encrypted = false
+ case 254, 255:
+ _, err = readFull(r, buf[:])
+ if err != nil {
+ return
+ }
+ pk.cipher = CipherFunction(buf[0])
+ pk.Encrypted = true
+ pk.s2k, err = s2k.Parse(r)
+ if err != nil {
+ return
+ }
+ if s2kType == 254 {
+ pk.sha1Checksum = true
+ }
+ default:
+ return errors.UnsupportedError("deprecated s2k function in private key")
+ }
+
+ if pk.Encrypted {
+ blockSize := pk.cipher.blockSize()
+ if blockSize == 0 {
+ return errors.UnsupportedError("unsupported cipher in private key: " + strconv.Itoa(int(pk.cipher)))
+ }
+ pk.iv = make([]byte, blockSize)
+ _, err = readFull(r, pk.iv)
+ if err != nil {
+ return
+ }
+ }
+
+ pk.encryptedData, err = ioutil.ReadAll(r)
+ if err != nil {
+ return
+ }
+
+ if !pk.Encrypted {
+ return pk.parsePrivateKey(pk.encryptedData)
+ }
+
+ return
+}
+
+func mod64kHash(d []byte) uint16 {
+ var h uint16
+ for _, b := range d {
+ h += uint16(b)
+ }
+ return h
+}
+
+func (pk *PrivateKey) Serialize(w io.Writer) (err error) {
+ // TODO(agl): support encrypted private keys
+ buf := bytes.NewBuffer(nil)
+ err = pk.PublicKey.serializeWithoutHeaders(buf)
+ if err != nil {
+ return
+ }
+ buf.WriteByte(0 /* no encryption */)
+
+ privateKeyBuf := bytes.NewBuffer(nil)
+
+ switch priv := pk.PrivateKey.(type) {
+ case *rsa.PrivateKey:
+ err = serializeRSAPrivateKey(privateKeyBuf, priv)
+ case *dsa.PrivateKey:
+ err = serializeDSAPrivateKey(privateKeyBuf, priv)
+ case *elgamal.PrivateKey:
+ err = serializeElGamalPrivateKey(privateKeyBuf, priv)
+ case *ecdsa.PrivateKey:
+ err = serializeECDSAPrivateKey(privateKeyBuf, priv)
+ default:
+ err = errors.InvalidArgumentError("unknown private key type")
+ }
+ if err != nil {
+ return
+ }
+
+ ptype := packetTypePrivateKey
+ contents := buf.Bytes()
+ privateKeyBytes := privateKeyBuf.Bytes()
+ if pk.IsSubkey {
+ ptype = packetTypePrivateSubkey
+ }
+ err = serializeHeader(w, ptype, len(contents)+len(privateKeyBytes)+2)
+ if err != nil {
+ return
+ }
+ _, err = w.Write(contents)
+ if err != nil {
+ return
+ }
+ _, err = w.Write(privateKeyBytes)
+ if err != nil {
+ return
+ }
+
+ checksum := mod64kHash(privateKeyBytes)
+ var checksumBytes [2]byte
+ checksumBytes[0] = byte(checksum >> 8)
+ checksumBytes[1] = byte(checksum)
+ _, err = w.Write(checksumBytes[:])
+
+ return
+}
+
+func serializeRSAPrivateKey(w io.Writer, priv *rsa.PrivateKey) error {
+ err := writeBig(w, priv.D)
+ if err != nil {
+ return err
+ }
+ err = writeBig(w, priv.Primes[1])
+ if err != nil {
+ return err
+ }
+ err = writeBig(w, priv.Primes[0])
+ if err != nil {
+ return err
+ }
+ return writeBig(w, priv.Precomputed.Qinv)
+}
+
+func serializeDSAPrivateKey(w io.Writer, priv *dsa.PrivateKey) error {
+ return writeBig(w, priv.X)
+}
+
+func serializeElGamalPrivateKey(w io.Writer, priv *elgamal.PrivateKey) error {
+ return writeBig(w, priv.X)
+}
+
+func serializeECDSAPrivateKey(w io.Writer, priv *ecdsa.PrivateKey) error {
+ return writeBig(w, priv.D)
+}
+
+// Decrypt decrypts an encrypted private key using a passphrase.
+func (pk *PrivateKey) Decrypt(passphrase []byte) error {
+ if !pk.Encrypted {
+ return nil
+ }
+
+ key := make([]byte, pk.cipher.KeySize())
+ pk.s2k(key, passphrase)
+ block := pk.cipher.new(key)
+ cfb := cipher.NewCFBDecrypter(block, pk.iv)
+
+ data := make([]byte, len(pk.encryptedData))
+ cfb.XORKeyStream(data, pk.encryptedData)
+
+ if pk.sha1Checksum {
+ if len(data) < sha1.Size {
+ return errors.StructuralError("truncated private key data")
+ }
+ h := sha1.New()
+ h.Write(data[:len(data)-sha1.Size])
+ sum := h.Sum(nil)
+ if !bytes.Equal(sum, data[len(data)-sha1.Size:]) {
+ return errors.StructuralError("private key checksum failure")
+ }
+ data = data[:len(data)-sha1.Size]
+ } else {
+ if len(data) < 2 {
+ return errors.StructuralError("truncated private key data")
+ }
+ var sum uint16
+ for i := 0; i < len(data)-2; i++ {
+ sum += uint16(data[i])
+ }
+ if data[len(data)-2] != uint8(sum>>8) ||
+ data[len(data)-1] != uint8(sum) {
+ return errors.StructuralError("private key checksum failure")
+ }
+ data = data[:len(data)-2]
+ }
+
+ return pk.parsePrivateKey(data)
+}
+
+func (pk *PrivateKey) parsePrivateKey(data []byte) (err error) {
+ switch pk.PublicKey.PubKeyAlgo {
+ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoRSAEncryptOnly:
+ return pk.parseRSAPrivateKey(data)
+ case PubKeyAlgoDSA:
+ return pk.parseDSAPrivateKey(data)
+ case PubKeyAlgoElGamal:
+ return pk.parseElGamalPrivateKey(data)
+ case PubKeyAlgoECDSA:
+ return pk.parseECDSAPrivateKey(data)
+ }
+ panic("impossible")
+}
+
+func (pk *PrivateKey) parseRSAPrivateKey(data []byte) (err error) {
+ rsaPub := pk.PublicKey.PublicKey.(*rsa.PublicKey)
+ rsaPriv := new(rsa.PrivateKey)
+ rsaPriv.PublicKey = *rsaPub
+
+ buf := bytes.NewBuffer(data)
+ d, _, err := readMPI(buf)
+ if err != nil {
+ return
+ }
+ p, _, err := readMPI(buf)
+ if err != nil {
+ return
+ }
+ q, _, err := readMPI(buf)
+ if err != nil {
+ return
+ }
+
+ rsaPriv.D = new(big.Int).SetBytes(d)
+ rsaPriv.Primes = make([]*big.Int, 2)
+ rsaPriv.Primes[0] = new(big.Int).SetBytes(p)
+ rsaPriv.Primes[1] = new(big.Int).SetBytes(q)
+ if err := rsaPriv.Validate(); err != nil {
+ return err
+ }
+ rsaPriv.Precompute()
+ pk.PrivateKey = rsaPriv
+ pk.Encrypted = false
+ pk.encryptedData = nil
+
+ return nil
+}
+
+func (pk *PrivateKey) parseDSAPrivateKey(data []byte) (err error) {
+ dsaPub := pk.PublicKey.PublicKey.(*dsa.PublicKey)
+ dsaPriv := new(dsa.PrivateKey)
+ dsaPriv.PublicKey = *dsaPub
+
+ buf := bytes.NewBuffer(data)
+ x, _, err := readMPI(buf)
+ if err != nil {
+ return
+ }
+
+ dsaPriv.X = new(big.Int).SetBytes(x)
+ pk.PrivateKey = dsaPriv
+ pk.Encrypted = false
+ pk.encryptedData = nil
+
+ return nil
+}
+
+func (pk *PrivateKey) parseElGamalPrivateKey(data []byte) (err error) {
+ pub := pk.PublicKey.PublicKey.(*elgamal.PublicKey)
+ priv := new(elgamal.PrivateKey)
+ priv.PublicKey = *pub
+
+ buf := bytes.NewBuffer(data)
+ x, _, err := readMPI(buf)
+ if err != nil {
+ return
+ }
+
+ priv.X = new(big.Int).SetBytes(x)
+ pk.PrivateKey = priv
+ pk.Encrypted = false
+ pk.encryptedData = nil
+
+ return nil
+}
+
+func (pk *PrivateKey) parseECDSAPrivateKey(data []byte) (err error) {
+ ecdsaPub := pk.PublicKey.PublicKey.(*ecdsa.PublicKey)
+
+ buf := bytes.NewBuffer(data)
+ d, _, err := readMPI(buf)
+ if err != nil {
+ return
+ }
+
+ pk.PrivateKey = &ecdsa.PrivateKey{
+ PublicKey: *ecdsaPub,
+ D: new(big.Int).SetBytes(d),
+ }
+ pk.Encrypted = false
+ pk.encryptedData = nil
+
+ return nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/private_key_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/private_key_test.go
new file mode 100644
index 000000000..ac651d917
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/private_key_test.go
@@ -0,0 +1,270 @@
+// Copyright 2011 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 packet
+
+import (
+ "bytes"
+ "crypto"
+ "crypto/ecdsa"
+ "crypto/elliptic"
+ "crypto/rand"
+ "crypto/rsa"
+ "crypto/x509"
+ "encoding/hex"
+ "hash"
+ "io"
+ "testing"
+ "time"
+)
+
+var privateKeyTests = []struct {
+ privateKeyHex string
+ creationTime time.Time
+}{
+ {
+ privKeyRSAHex,
+ time.Unix(0x4cc349a8, 0),
+ },
+ {
+ privKeyElGamalHex,
+ time.Unix(0x4df9ee1a, 0),
+ },
+}
+
+func TestPrivateKeyRead(t *testing.T) {
+ for i, test := range privateKeyTests {
+ packet, err := Read(readerFromHex(test.privateKeyHex))
+ if err != nil {
+ t.Errorf("#%d: failed to parse: %s", i, err)
+ continue
+ }
+
+ privKey := packet.(*PrivateKey)
+
+ if !privKey.Encrypted {
+ t.Errorf("#%d: private key isn't encrypted", i)
+ continue
+ }
+
+ err = privKey.Decrypt([]byte("wrong password"))
+ if err == nil {
+ t.Errorf("#%d: decrypted with incorrect key", i)
+ continue
+ }
+
+ err = privKey.Decrypt([]byte("testing"))
+ if err != nil {
+ t.Errorf("#%d: failed to decrypt: %s", i, err)
+ continue
+ }
+
+ if !privKey.CreationTime.Equal(test.creationTime) || privKey.Encrypted {
+ t.Errorf("#%d: bad result, got: %#v", i, privKey)
+ }
+ }
+}
+
+func populateHash(hashFunc crypto.Hash, msg []byte) (hash.Hash, error) {
+ h := hashFunc.New()
+ if _, err := h.Write(msg); err != nil {
+ return nil, err
+ }
+ return h, nil
+}
+
+func TestRSAPrivateKey(t *testing.T) {
+ privKeyDER, _ := hex.DecodeString(pkcs1PrivKeyHex)
+ rsaPriv, err := x509.ParsePKCS1PrivateKey(privKeyDER)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ var buf bytes.Buffer
+ if err := NewRSAPrivateKey(time.Now(), rsaPriv).Serialize(&buf); err != nil {
+ t.Fatal(err)
+ }
+
+ p, err := Read(&buf)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ priv, ok := p.(*PrivateKey)
+ if !ok {
+ t.Fatal("didn't parse private key")
+ }
+
+ sig := &Signature{
+ PubKeyAlgo: PubKeyAlgoRSA,
+ Hash: crypto.SHA256,
+ }
+ msg := []byte("Hello World!")
+
+ h, err := populateHash(sig.Hash, msg)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := sig.Sign(h, priv, nil); err != nil {
+ t.Fatal(err)
+ }
+
+ if h, err = populateHash(sig.Hash, msg); err != nil {
+ t.Fatal(err)
+ }
+ if err := priv.VerifySignature(h, sig); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestECDSAPrivateKey(t *testing.T) {
+ ecdsaPriv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ var buf bytes.Buffer
+ if err := NewECDSAPrivateKey(time.Now(), ecdsaPriv).Serialize(&buf); err != nil {
+ t.Fatal(err)
+ }
+
+ p, err := Read(&buf)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ priv, ok := p.(*PrivateKey)
+ if !ok {
+ t.Fatal("didn't parse private key")
+ }
+
+ sig := &Signature{
+ PubKeyAlgo: PubKeyAlgoECDSA,
+ Hash: crypto.SHA256,
+ }
+ msg := []byte("Hello World!")
+
+ h, err := populateHash(sig.Hash, msg)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := sig.Sign(h, priv, nil); err != nil {
+ t.Fatal(err)
+ }
+
+ if h, err = populateHash(sig.Hash, msg); err != nil {
+ t.Fatal(err)
+ }
+ if err := priv.VerifySignature(h, sig); err != nil {
+ t.Fatal(err)
+ }
+}
+
+type rsaSigner struct {
+ priv *rsa.PrivateKey
+}
+
+func (s *rsaSigner) Public() crypto.PublicKey {
+ return s.priv.PublicKey
+}
+
+func (s *rsaSigner) Sign(rand io.Reader, msg []byte, opts crypto.SignerOpts) ([]byte, error) {
+ return s.priv.Sign(rand, msg, opts)
+}
+
+func TestRSASignerPrivateKey(t *testing.T) {
+ rsaPriv, err := rsa.GenerateKey(rand.Reader, 1024)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ priv := NewSignerPrivateKey(time.Now(), &rsaSigner{rsaPriv})
+
+ if priv.PubKeyAlgo != PubKeyAlgoRSASignOnly {
+ t.Fatal("NewSignerPrivateKey should have made a sign-only RSA private key")
+ }
+
+ sig := &Signature{
+ PubKeyAlgo: PubKeyAlgoRSASignOnly,
+ Hash: crypto.SHA256,
+ }
+ msg := []byte("Hello World!")
+
+ h, err := populateHash(sig.Hash, msg)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := sig.Sign(h, priv, nil); err != nil {
+ t.Fatal(err)
+ }
+
+ if h, err = populateHash(sig.Hash, msg); err != nil {
+ t.Fatal(err)
+ }
+ if err := priv.VerifySignature(h, sig); err != nil {
+ t.Fatal(err)
+ }
+}
+
+type ecdsaSigner struct {
+ priv *ecdsa.PrivateKey
+}
+
+func (s *ecdsaSigner) Public() crypto.PublicKey {
+ return s.priv.PublicKey
+}
+
+func (s *ecdsaSigner) Sign(rand io.Reader, msg []byte, opts crypto.SignerOpts) ([]byte, error) {
+ return s.priv.Sign(rand, msg, opts)
+}
+
+func TestECDSASignerPrivateKey(t *testing.T) {
+ ecdsaPriv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ priv := NewSignerPrivateKey(time.Now(), &ecdsaSigner{ecdsaPriv})
+
+ if priv.PubKeyAlgo != PubKeyAlgoECDSA {
+ t.Fatal("NewSignerPrivateKey should have made an ECSDA private key")
+ }
+
+ sig := &Signature{
+ PubKeyAlgo: PubKeyAlgoECDSA,
+ Hash: crypto.SHA256,
+ }
+ msg := []byte("Hello World!")
+
+ h, err := populateHash(sig.Hash, msg)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := sig.Sign(h, priv, nil); err != nil {
+ t.Fatal(err)
+ }
+
+ if h, err = populateHash(sig.Hash, msg); err != nil {
+ t.Fatal(err)
+ }
+ if err := priv.VerifySignature(h, sig); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestIssue11505(t *testing.T) {
+ // parsing a rsa private key with p or q == 1 used to panic due to a divide by zero
+ _, _ = Read(readerFromHex("9c3004303030300100000011303030000000000000010130303030303030303030303030303030303030303030303030303030303030303030303030303030303030"))
+}
+
+// Generated with `gpg --export-secret-keys "Test Key 2"`
+const privKeyRSAHex = "9501fe044cc349a8010400b70ca0010e98c090008d45d1ee8f9113bd5861fd57b88bacb7c68658747663f1e1a3b5a98f32fda6472373c024b97359cd2efc88ff60f77751adfbf6af5e615e6a1408cfad8bf0cea30b0d5f53aa27ad59089ba9b15b7ebc2777a25d7b436144027e3bcd203909f147d0e332b240cf63d3395f5dfe0df0a6c04e8655af7eacdf0011010001fe0303024a252e7d475fd445607de39a265472aa74a9320ba2dac395faa687e9e0336aeb7e9a7397e511b5afd9dc84557c80ac0f3d4d7bfec5ae16f20d41c8c84a04552a33870b930420e230e179564f6d19bb153145e76c33ae993886c388832b0fa042ddda7f133924f3854481533e0ede31d51278c0519b29abc3bf53da673e13e3e1214b52413d179d7f66deee35cac8eacb060f78379d70ef4af8607e68131ff529439668fc39c9ce6dfef8a5ac234d234802cbfb749a26107db26406213ae5c06d4673253a3cbee1fcbae58d6ab77e38d6e2c0e7c6317c48e054edadb5a40d0d48acb44643d998139a8a66bb820be1f3f80185bc777d14b5954b60effe2448a036d565c6bc0b915fcea518acdd20ab07bc1529f561c58cd044f723109b93f6fd99f876ff891d64306b5d08f48bab59f38695e9109c4dec34013ba3153488ce070268381ba923ee1eb77125b36afcb4347ec3478c8f2735b06ef17351d872e577fa95d0c397c88c71b59629a36aec"
+
+// Generated by `gpg --export-secret-keys` followed by a manual extraction of
+// the ElGamal subkey from the packets.
+const privKeyElGamalHex = "9d0157044df9ee1a100400eb8e136a58ec39b582629cdadf830bc64e0a94ed8103ca8bb247b27b11b46d1d25297ef4bcc3071785ba0c0bedfe89eabc5287fcc0edf81ab5896c1c8e4b20d27d79813c7aede75320b33eaeeaa586edc00fd1036c10133e6ba0ff277245d0d59d04b2b3421b7244aca5f4a8d870c6f1c1fbff9e1c26699a860b9504f35ca1d700030503fd1ededd3b840795be6d9ccbe3c51ee42e2f39233c432b831ddd9c4e72b7025a819317e47bf94f9ee316d7273b05d5fcf2999c3a681f519b1234bbfa6d359b4752bd9c3f77d6b6456cde152464763414ca130f4e91d91041432f90620fec0e6d6b5116076c2985d5aeaae13be492b9b329efcaf7ee25120159a0a30cd976b42d7afe030302dae7eb80db744d4960c4df930d57e87fe81412eaace9f900e6c839817a614ddb75ba6603b9417c33ea7b6c93967dfa2bcff3fa3c74a5ce2c962db65b03aece14c96cbd0038fc"
+
+// pkcs1PrivKeyHex is a PKCS#1, RSA private key.
+// Generated by `openssl genrsa 1024 | openssl rsa -outform DER | xxd -p`
+const pkcs1PrivKeyHex = "3082025d02010002818100e98edfa1c3b35884a54d0b36a6a603b0290fa85e49e30fa23fc94fef9c6790bc4849928607aa48d809da326fb42a969d06ad756b98b9c1a90f5d4a2b6d0ac05953c97f4da3120164a21a679793ce181c906dc01d235cc085ddcdf6ea06c389b6ab8885dfd685959e693138856a68a7e5db263337ff82a088d583a897cf2d59e9020301000102818100b6d5c9eb70b02d5369b3ee5b520a14490b5bde8a317d36f7e4c74b7460141311d1e5067735f8f01d6f5908b2b96fbd881f7a1ab9a84d82753e39e19e2d36856be960d05ac9ef8e8782ea1b6d65aee28fdfe1d61451e8cff0adfe84322f12cf455028b581cf60eb9e0e140ba5d21aeba6c2634d7c65318b9a665fc01c3191ca21024100fa5e818da3705b0fa33278bb28d4b6f6050388af2d4b75ec9375dd91ccf2e7d7068086a8b82a8f6282e4fbbdb8a7f2622eb97295249d87acea7f5f816f54d347024100eecf9406d7dc49cdfb95ab1eff4064de84c7a30f64b2798936a0d2018ba9eb52e4b636f82e96c49cc63b80b675e91e40d1b2e4017d4b9adaf33ab3d9cf1c214f024100c173704ace742c082323066226a4655226819a85304c542b9dacbeacbf5d1881ee863485fcf6f59f3a604f9b42289282067447f2b13dfeed3eab7851fc81e0550240741fc41f3fc002b382eed8730e33c5d8de40256e4accee846667f536832f711ab1d4590e7db91a8a116ac5bff3be13d3f9243ff2e976662aa9b395d907f8e9c9024046a5696c9ef882363e06c9fa4e2f5b580906452befba03f4a99d0f873697ef1f851d2226ca7934b30b7c3e80cb634a67172bbbf4781735fe3e09263e2dd723e7"
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/public_key.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/public_key.go
new file mode 100644
index 000000000..ead26233d
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/public_key.go
@@ -0,0 +1,748 @@
+// Copyright 2011 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 packet
+
+import (
+ "bytes"
+ "crypto"
+ "crypto/dsa"
+ "crypto/ecdsa"
+ "crypto/elliptic"
+ "crypto/rsa"
+ "crypto/sha1"
+ _ "crypto/sha256"
+ _ "crypto/sha512"
+ "encoding/binary"
+ "fmt"
+ "hash"
+ "io"
+ "math/big"
+ "strconv"
+ "time"
+
+ "golang.org/x/crypto/openpgp/elgamal"
+ "golang.org/x/crypto/openpgp/errors"
+)
+
+var (
+ // NIST curve P-256
+ oidCurveP256 []byte = []byte{0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07}
+ // NIST curve P-384
+ oidCurveP384 []byte = []byte{0x2B, 0x81, 0x04, 0x00, 0x22}
+ // NIST curve P-521
+ oidCurveP521 []byte = []byte{0x2B, 0x81, 0x04, 0x00, 0x23}
+)
+
+const maxOIDLength = 8
+
+// ecdsaKey stores the algorithm-specific fields for ECDSA keys.
+// as defined in RFC 6637, Section 9.
+type ecdsaKey struct {
+ // oid contains the OID byte sequence identifying the elliptic curve used
+ oid []byte
+ // p contains the elliptic curve point that represents the public key
+ p parsedMPI
+}
+
+// parseOID reads the OID for the curve as defined in RFC 6637, Section 9.
+func parseOID(r io.Reader) (oid []byte, err error) {
+ buf := make([]byte, maxOIDLength)
+ if _, err = readFull(r, buf[:1]); err != nil {
+ return
+ }
+ oidLen := buf[0]
+ if int(oidLen) > len(buf) {
+ err = errors.UnsupportedError("invalid oid length: " + strconv.Itoa(int(oidLen)))
+ return
+ }
+ oid = buf[:oidLen]
+ _, err = readFull(r, oid)
+ return
+}
+
+func (f *ecdsaKey) parse(r io.Reader) (err error) {
+ if f.oid, err = parseOID(r); err != nil {
+ return err
+ }
+ f.p.bytes, f.p.bitLength, err = readMPI(r)
+ return
+}
+
+func (f *ecdsaKey) serialize(w io.Writer) (err error) {
+ buf := make([]byte, maxOIDLength+1)
+ buf[0] = byte(len(f.oid))
+ copy(buf[1:], f.oid)
+ if _, err = w.Write(buf[:len(f.oid)+1]); err != nil {
+ return
+ }
+ return writeMPIs(w, f.p)
+}
+
+func (f *ecdsaKey) newECDSA() (*ecdsa.PublicKey, error) {
+ var c elliptic.Curve
+ if bytes.Equal(f.oid, oidCurveP256) {
+ c = elliptic.P256()
+ } else if bytes.Equal(f.oid, oidCurveP384) {
+ c = elliptic.P384()
+ } else if bytes.Equal(f.oid, oidCurveP521) {
+ c = elliptic.P521()
+ } else {
+ return nil, errors.UnsupportedError(fmt.Sprintf("unsupported oid: %x", f.oid))
+ }
+ x, y := elliptic.Unmarshal(c, f.p.bytes)
+ if x == nil {
+ return nil, errors.UnsupportedError("failed to parse EC point")
+ }
+ return &ecdsa.PublicKey{Curve: c, X: x, Y: y}, nil
+}
+
+func (f *ecdsaKey) byteLen() int {
+ return 1 + len(f.oid) + 2 + len(f.p.bytes)
+}
+
+type kdfHashFunction byte
+type kdfAlgorithm byte
+
+// ecdhKdf stores key derivation function parameters
+// used for ECDH encryption. See RFC 6637, Section 9.
+type ecdhKdf struct {
+ KdfHash kdfHashFunction
+ KdfAlgo kdfAlgorithm
+}
+
+func (f *ecdhKdf) parse(r io.Reader) (err error) {
+ buf := make([]byte, 1)
+ if _, err = readFull(r, buf); err != nil {
+ return
+ }
+ kdfLen := int(buf[0])
+ if kdfLen < 3 {
+ return errors.UnsupportedError("Unsupported ECDH KDF length: " + strconv.Itoa(kdfLen))
+ }
+ buf = make([]byte, kdfLen)
+ if _, err = readFull(r, buf); err != nil {
+ return
+ }
+ reserved := int(buf[0])
+ f.KdfHash = kdfHashFunction(buf[1])
+ f.KdfAlgo = kdfAlgorithm(buf[2])
+ if reserved != 0x01 {
+ return errors.UnsupportedError("Unsupported KDF reserved field: " + strconv.Itoa(reserved))
+ }
+ return
+}
+
+func (f *ecdhKdf) serialize(w io.Writer) (err error) {
+ buf := make([]byte, 4)
+ // See RFC 6637, Section 9, Algorithm-Specific Fields for ECDH keys.
+ buf[0] = byte(0x03) // Length of the following fields
+ buf[1] = byte(0x01) // Reserved for future extensions, must be 1 for now
+ buf[2] = byte(f.KdfHash)
+ buf[3] = byte(f.KdfAlgo)
+ _, err = w.Write(buf[:])
+ return
+}
+
+func (f *ecdhKdf) byteLen() int {
+ return 4
+}
+
+// PublicKey represents an OpenPGP public key. See RFC 4880, section 5.5.2.
+type PublicKey struct {
+ CreationTime time.Time
+ PubKeyAlgo PublicKeyAlgorithm
+ PublicKey interface{} // *rsa.PublicKey, *dsa.PublicKey or *ecdsa.PublicKey
+ Fingerprint [20]byte
+ KeyId uint64
+ IsSubkey bool
+
+ n, e, p, q, g, y parsedMPI
+
+ // RFC 6637 fields
+ ec *ecdsaKey
+ ecdh *ecdhKdf
+}
+
+// signingKey provides a convenient abstraction over signature verification
+// for v3 and v4 public keys.
+type signingKey interface {
+ SerializeSignaturePrefix(io.Writer)
+ serializeWithoutHeaders(io.Writer) error
+}
+
+func fromBig(n *big.Int) parsedMPI {
+ return parsedMPI{
+ bytes: n.Bytes(),
+ bitLength: uint16(n.BitLen()),
+ }
+}
+
+// NewRSAPublicKey returns a PublicKey that wraps the given rsa.PublicKey.
+func NewRSAPublicKey(creationTime time.Time, pub *rsa.PublicKey) *PublicKey {
+ pk := &PublicKey{
+ CreationTime: creationTime,
+ PubKeyAlgo: PubKeyAlgoRSA,
+ PublicKey: pub,
+ n: fromBig(pub.N),
+ e: fromBig(big.NewInt(int64(pub.E))),
+ }
+
+ pk.setFingerPrintAndKeyId()
+ return pk
+}
+
+// NewDSAPublicKey returns a PublicKey that wraps the given dsa.PublicKey.
+func NewDSAPublicKey(creationTime time.Time, pub *dsa.PublicKey) *PublicKey {
+ pk := &PublicKey{
+ CreationTime: creationTime,
+ PubKeyAlgo: PubKeyAlgoDSA,
+ PublicKey: pub,
+ p: fromBig(pub.P),
+ q: fromBig(pub.Q),
+ g: fromBig(pub.G),
+ y: fromBig(pub.Y),
+ }
+
+ pk.setFingerPrintAndKeyId()
+ return pk
+}
+
+// NewElGamalPublicKey returns a PublicKey that wraps the given elgamal.PublicKey.
+func NewElGamalPublicKey(creationTime time.Time, pub *elgamal.PublicKey) *PublicKey {
+ pk := &PublicKey{
+ CreationTime: creationTime,
+ PubKeyAlgo: PubKeyAlgoElGamal,
+ PublicKey: pub,
+ p: fromBig(pub.P),
+ g: fromBig(pub.G),
+ y: fromBig(pub.Y),
+ }
+
+ pk.setFingerPrintAndKeyId()
+ return pk
+}
+
+func NewECDSAPublicKey(creationTime time.Time, pub *ecdsa.PublicKey) *PublicKey {
+ pk := &PublicKey{
+ CreationTime: creationTime,
+ PubKeyAlgo: PubKeyAlgoECDSA,
+ PublicKey: pub,
+ ec: new(ecdsaKey),
+ }
+
+ switch pub.Curve {
+ case elliptic.P256():
+ pk.ec.oid = oidCurveP256
+ case elliptic.P384():
+ pk.ec.oid = oidCurveP384
+ case elliptic.P521():
+ pk.ec.oid = oidCurveP521
+ default:
+ panic("unknown elliptic curve")
+ }
+
+ pk.ec.p.bytes = elliptic.Marshal(pub.Curve, pub.X, pub.Y)
+ pk.ec.p.bitLength = uint16(8 * len(pk.ec.p.bytes))
+
+ pk.setFingerPrintAndKeyId()
+ return pk
+}
+
+func (pk *PublicKey) parse(r io.Reader) (err error) {
+ // RFC 4880, section 5.5.2
+ var buf [6]byte
+ _, err = readFull(r, buf[:])
+ if err != nil {
+ return
+ }
+ if buf[0] != 4 {
+ return errors.UnsupportedError("public key version")
+ }
+ pk.CreationTime = time.Unix(int64(uint32(buf[1])<<24|uint32(buf[2])<<16|uint32(buf[3])<<8|uint32(buf[4])), 0)
+ pk.PubKeyAlgo = PublicKeyAlgorithm(buf[5])
+ switch pk.PubKeyAlgo {
+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
+ err = pk.parseRSA(r)
+ case PubKeyAlgoDSA:
+ err = pk.parseDSA(r)
+ case PubKeyAlgoElGamal:
+ err = pk.parseElGamal(r)
+ case PubKeyAlgoECDSA:
+ pk.ec = new(ecdsaKey)
+ if err = pk.ec.parse(r); err != nil {
+ return err
+ }
+ pk.PublicKey, err = pk.ec.newECDSA()
+ case PubKeyAlgoECDH:
+ pk.ec = new(ecdsaKey)
+ if err = pk.ec.parse(r); err != nil {
+ return
+ }
+ pk.ecdh = new(ecdhKdf)
+ if err = pk.ecdh.parse(r); err != nil {
+ return
+ }
+ // The ECDH key is stored in an ecdsa.PublicKey for convenience.
+ pk.PublicKey, err = pk.ec.newECDSA()
+ default:
+ err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo)))
+ }
+ if err != nil {
+ return
+ }
+
+ pk.setFingerPrintAndKeyId()
+ return
+}
+
+func (pk *PublicKey) setFingerPrintAndKeyId() {
+ // RFC 4880, section 12.2
+ fingerPrint := sha1.New()
+ pk.SerializeSignaturePrefix(fingerPrint)
+ pk.serializeWithoutHeaders(fingerPrint)
+ copy(pk.Fingerprint[:], fingerPrint.Sum(nil))
+ pk.KeyId = binary.BigEndian.Uint64(pk.Fingerprint[12:20])
+}
+
+// parseRSA parses RSA public key material from the given Reader. See RFC 4880,
+// section 5.5.2.
+func (pk *PublicKey) parseRSA(r io.Reader) (err error) {
+ pk.n.bytes, pk.n.bitLength, err = readMPI(r)
+ if err != nil {
+ return
+ }
+ pk.e.bytes, pk.e.bitLength, err = readMPI(r)
+ if err != nil {
+ return
+ }
+
+ if len(pk.e.bytes) > 3 {
+ err = errors.UnsupportedError("large public exponent")
+ return
+ }
+ rsa := &rsa.PublicKey{
+ N: new(big.Int).SetBytes(pk.n.bytes),
+ E: 0,
+ }
+ for i := 0; i < len(pk.e.bytes); i++ {
+ rsa.E <<= 8
+ rsa.E |= int(pk.e.bytes[i])
+ }
+ pk.PublicKey = rsa
+ return
+}
+
+// parseDSA parses DSA public key material from the given Reader. See RFC 4880,
+// section 5.5.2.
+func (pk *PublicKey) parseDSA(r io.Reader) (err error) {
+ pk.p.bytes, pk.p.bitLength, err = readMPI(r)
+ if err != nil {
+ return
+ }
+ pk.q.bytes, pk.q.bitLength, err = readMPI(r)
+ if err != nil {
+ return
+ }
+ pk.g.bytes, pk.g.bitLength, err = readMPI(r)
+ if err != nil {
+ return
+ }
+ pk.y.bytes, pk.y.bitLength, err = readMPI(r)
+ if err != nil {
+ return
+ }
+
+ dsa := new(dsa.PublicKey)
+ dsa.P = new(big.Int).SetBytes(pk.p.bytes)
+ dsa.Q = new(big.Int).SetBytes(pk.q.bytes)
+ dsa.G = new(big.Int).SetBytes(pk.g.bytes)
+ dsa.Y = new(big.Int).SetBytes(pk.y.bytes)
+ pk.PublicKey = dsa
+ return
+}
+
+// parseElGamal parses ElGamal public key material from the given Reader. See
+// RFC 4880, section 5.5.2.
+func (pk *PublicKey) parseElGamal(r io.Reader) (err error) {
+ pk.p.bytes, pk.p.bitLength, err = readMPI(r)
+ if err != nil {
+ return
+ }
+ pk.g.bytes, pk.g.bitLength, err = readMPI(r)
+ if err != nil {
+ return
+ }
+ pk.y.bytes, pk.y.bitLength, err = readMPI(r)
+ if err != nil {
+ return
+ }
+
+ elgamal := new(elgamal.PublicKey)
+ elgamal.P = new(big.Int).SetBytes(pk.p.bytes)
+ elgamal.G = new(big.Int).SetBytes(pk.g.bytes)
+ elgamal.Y = new(big.Int).SetBytes(pk.y.bytes)
+ pk.PublicKey = elgamal
+ return
+}
+
+// SerializeSignaturePrefix writes the prefix for this public key to the given Writer.
+// The prefix is used when calculating a signature over this public key. See
+// RFC 4880, section 5.2.4.
+func (pk *PublicKey) SerializeSignaturePrefix(h io.Writer) {
+ var pLength uint16
+ switch pk.PubKeyAlgo {
+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
+ pLength += 2 + uint16(len(pk.n.bytes))
+ pLength += 2 + uint16(len(pk.e.bytes))
+ case PubKeyAlgoDSA:
+ pLength += 2 + uint16(len(pk.p.bytes))
+ pLength += 2 + uint16(len(pk.q.bytes))
+ pLength += 2 + uint16(len(pk.g.bytes))
+ pLength += 2 + uint16(len(pk.y.bytes))
+ case PubKeyAlgoElGamal:
+ pLength += 2 + uint16(len(pk.p.bytes))
+ pLength += 2 + uint16(len(pk.g.bytes))
+ pLength += 2 + uint16(len(pk.y.bytes))
+ case PubKeyAlgoECDSA:
+ pLength += uint16(pk.ec.byteLen())
+ case PubKeyAlgoECDH:
+ pLength += uint16(pk.ec.byteLen())
+ pLength += uint16(pk.ecdh.byteLen())
+ default:
+ panic("unknown public key algorithm")
+ }
+ pLength += 6
+ h.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)})
+ return
+}
+
+func (pk *PublicKey) Serialize(w io.Writer) (err error) {
+ length := 6 // 6 byte header
+
+ switch pk.PubKeyAlgo {
+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
+ length += 2 + len(pk.n.bytes)
+ length += 2 + len(pk.e.bytes)
+ case PubKeyAlgoDSA:
+ length += 2 + len(pk.p.bytes)
+ length += 2 + len(pk.q.bytes)
+ length += 2 + len(pk.g.bytes)
+ length += 2 + len(pk.y.bytes)
+ case PubKeyAlgoElGamal:
+ length += 2 + len(pk.p.bytes)
+ length += 2 + len(pk.g.bytes)
+ length += 2 + len(pk.y.bytes)
+ case PubKeyAlgoECDSA:
+ length += pk.ec.byteLen()
+ case PubKeyAlgoECDH:
+ length += pk.ec.byteLen()
+ length += pk.ecdh.byteLen()
+ default:
+ panic("unknown public key algorithm")
+ }
+
+ packetType := packetTypePublicKey
+ if pk.IsSubkey {
+ packetType = packetTypePublicSubkey
+ }
+ err = serializeHeader(w, packetType, length)
+ if err != nil {
+ return
+ }
+ return pk.serializeWithoutHeaders(w)
+}
+
+// serializeWithoutHeaders marshals the PublicKey to w in the form of an
+// OpenPGP public key packet, not including the packet header.
+func (pk *PublicKey) serializeWithoutHeaders(w io.Writer) (err error) {
+ var buf [6]byte
+ buf[0] = 4
+ t := uint32(pk.CreationTime.Unix())
+ buf[1] = byte(t >> 24)
+ buf[2] = byte(t >> 16)
+ buf[3] = byte(t >> 8)
+ buf[4] = byte(t)
+ buf[5] = byte(pk.PubKeyAlgo)
+
+ _, err = w.Write(buf[:])
+ if err != nil {
+ return
+ }
+
+ switch pk.PubKeyAlgo {
+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
+ return writeMPIs(w, pk.n, pk.e)
+ case PubKeyAlgoDSA:
+ return writeMPIs(w, pk.p, pk.q, pk.g, pk.y)
+ case PubKeyAlgoElGamal:
+ return writeMPIs(w, pk.p, pk.g, pk.y)
+ case PubKeyAlgoECDSA:
+ return pk.ec.serialize(w)
+ case PubKeyAlgoECDH:
+ if err = pk.ec.serialize(w); err != nil {
+ return
+ }
+ return pk.ecdh.serialize(w)
+ }
+ return errors.InvalidArgumentError("bad public-key algorithm")
+}
+
+// CanSign returns true iff this public key can generate signatures
+func (pk *PublicKey) CanSign() bool {
+ return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly && pk.PubKeyAlgo != PubKeyAlgoElGamal
+}
+
+// VerifySignature returns nil iff sig is a valid signature, made by this
+// public key, of the data hashed into signed. signed is mutated by this call.
+func (pk *PublicKey) VerifySignature(signed hash.Hash, sig *Signature) (err error) {
+ if !pk.CanSign() {
+ return errors.InvalidArgumentError("public key cannot generate signatures")
+ }
+
+ signed.Write(sig.HashSuffix)
+ hashBytes := signed.Sum(nil)
+
+ if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] {
+ return errors.SignatureError("hash tag doesn't match")
+ }
+
+ if pk.PubKeyAlgo != sig.PubKeyAlgo {
+ return errors.InvalidArgumentError("public key and signature use different algorithms")
+ }
+
+ switch pk.PubKeyAlgo {
+ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
+ rsaPublicKey, _ := pk.PublicKey.(*rsa.PublicKey)
+ err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes)
+ if err != nil {
+ return errors.SignatureError("RSA verification failure")
+ }
+ return nil
+ case PubKeyAlgoDSA:
+ dsaPublicKey, _ := pk.PublicKey.(*dsa.PublicKey)
+ // Need to truncate hashBytes to match FIPS 186-3 section 4.6.
+ subgroupSize := (dsaPublicKey.Q.BitLen() + 7) / 8
+ if len(hashBytes) > subgroupSize {
+ hashBytes = hashBytes[:subgroupSize]
+ }
+ if !dsa.Verify(dsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.DSASigR.bytes), new(big.Int).SetBytes(sig.DSASigS.bytes)) {
+ return errors.SignatureError("DSA verification failure")
+ }
+ return nil
+ case PubKeyAlgoECDSA:
+ ecdsaPublicKey := pk.PublicKey.(*ecdsa.PublicKey)
+ if !ecdsa.Verify(ecdsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.ECDSASigR.bytes), new(big.Int).SetBytes(sig.ECDSASigS.bytes)) {
+ return errors.SignatureError("ECDSA verification failure")
+ }
+ return nil
+ default:
+ return errors.SignatureError("Unsupported public key algorithm used in signature")
+ }
+}
+
+// VerifySignatureV3 returns nil iff sig is a valid signature, made by this
+// public key, of the data hashed into signed. signed is mutated by this call.
+func (pk *PublicKey) VerifySignatureV3(signed hash.Hash, sig *SignatureV3) (err error) {
+ if !pk.CanSign() {
+ return errors.InvalidArgumentError("public key cannot generate signatures")
+ }
+
+ suffix := make([]byte, 5)
+ suffix[0] = byte(sig.SigType)
+ binary.BigEndian.PutUint32(suffix[1:], uint32(sig.CreationTime.Unix()))
+ signed.Write(suffix)
+ hashBytes := signed.Sum(nil)
+
+ if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] {
+ return errors.SignatureError("hash tag doesn't match")
+ }
+
+ if pk.PubKeyAlgo != sig.PubKeyAlgo {
+ return errors.InvalidArgumentError("public key and signature use different algorithms")
+ }
+
+ switch pk.PubKeyAlgo {
+ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
+ rsaPublicKey := pk.PublicKey.(*rsa.PublicKey)
+ if err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes); err != nil {
+ return errors.SignatureError("RSA verification failure")
+ }
+ return
+ case PubKeyAlgoDSA:
+ dsaPublicKey := pk.PublicKey.(*dsa.PublicKey)
+ // Need to truncate hashBytes to match FIPS 186-3 section 4.6.
+ subgroupSize := (dsaPublicKey.Q.BitLen() + 7) / 8
+ if len(hashBytes) > subgroupSize {
+ hashBytes = hashBytes[:subgroupSize]
+ }
+ if !dsa.Verify(dsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.DSASigR.bytes), new(big.Int).SetBytes(sig.DSASigS.bytes)) {
+ return errors.SignatureError("DSA verification failure")
+ }
+ return nil
+ default:
+ panic("shouldn't happen")
+ }
+}
+
+// keySignatureHash returns a Hash of the message that needs to be signed for
+// pk to assert a subkey relationship to signed.
+func keySignatureHash(pk, signed signingKey, hashFunc crypto.Hash) (h hash.Hash, err error) {
+ if !hashFunc.Available() {
+ return nil, errors.UnsupportedError("hash function")
+ }
+ h = hashFunc.New()
+
+ // RFC 4880, section 5.2.4
+ pk.SerializeSignaturePrefix(h)
+ pk.serializeWithoutHeaders(h)
+ signed.SerializeSignaturePrefix(h)
+ signed.serializeWithoutHeaders(h)
+ return
+}
+
+// VerifyKeySignature returns nil iff sig is a valid signature, made by this
+// public key, of signed.
+func (pk *PublicKey) VerifyKeySignature(signed *PublicKey, sig *Signature) error {
+ h, err := keySignatureHash(pk, signed, sig.Hash)
+ if err != nil {
+ return err
+ }
+ if err = pk.VerifySignature(h, sig); err != nil {
+ return err
+ }
+
+ if sig.FlagSign {
+ // Signing subkeys must be cross-signed. See
+ // https://www.gnupg.org/faq/subkey-cross-certify.html.
+ if sig.EmbeddedSignature == nil {
+ return errors.StructuralError("signing subkey is missing cross-signature")
+ }
+ // Verify the cross-signature. This is calculated over the same
+ // data as the main signature, so we cannot just recursively
+ // call signed.VerifyKeySignature(...)
+ if h, err = keySignatureHash(pk, signed, sig.EmbeddedSignature.Hash); err != nil {
+ return errors.StructuralError("error while hashing for cross-signature: " + err.Error())
+ }
+ if err := signed.VerifySignature(h, sig.EmbeddedSignature); err != nil {
+ return errors.StructuralError("error while verifying cross-signature: " + err.Error())
+ }
+ }
+
+ return nil
+}
+
+func keyRevocationHash(pk signingKey, hashFunc crypto.Hash) (h hash.Hash, err error) {
+ if !hashFunc.Available() {
+ return nil, errors.UnsupportedError("hash function")
+ }
+ h = hashFunc.New()
+
+ // RFC 4880, section 5.2.4
+ pk.SerializeSignaturePrefix(h)
+ pk.serializeWithoutHeaders(h)
+
+ return
+}
+
+// VerifyRevocationSignature returns nil iff sig is a valid signature, made by this
+// public key.
+func (pk *PublicKey) VerifyRevocationSignature(sig *Signature) (err error) {
+ h, err := keyRevocationHash(pk, sig.Hash)
+ if err != nil {
+ return err
+ }
+ return pk.VerifySignature(h, sig)
+}
+
+// userIdSignatureHash returns a Hash of the message that needs to be signed
+// to assert that pk is a valid key for id.
+func userIdSignatureHash(id string, pk *PublicKey, hashFunc crypto.Hash) (h hash.Hash, err error) {
+ if !hashFunc.Available() {
+ return nil, errors.UnsupportedError("hash function")
+ }
+ h = hashFunc.New()
+
+ // RFC 4880, section 5.2.4
+ pk.SerializeSignaturePrefix(h)
+ pk.serializeWithoutHeaders(h)
+
+ var buf [5]byte
+ buf[0] = 0xb4
+ buf[1] = byte(len(id) >> 24)
+ buf[2] = byte(len(id) >> 16)
+ buf[3] = byte(len(id) >> 8)
+ buf[4] = byte(len(id))
+ h.Write(buf[:])
+ h.Write([]byte(id))
+
+ return
+}
+
+// VerifyUserIdSignature returns nil iff sig is a valid signature, made by this
+// public key, that id is the identity of pub.
+func (pk *PublicKey) VerifyUserIdSignature(id string, pub *PublicKey, sig *Signature) (err error) {
+ h, err := userIdSignatureHash(id, pub, sig.Hash)
+ if err != nil {
+ return err
+ }
+ return pk.VerifySignature(h, sig)
+}
+
+// VerifyUserIdSignatureV3 returns nil iff sig is a valid signature, made by this
+// public key, that id is the identity of pub.
+func (pk *PublicKey) VerifyUserIdSignatureV3(id string, pub *PublicKey, sig *SignatureV3) (err error) {
+ h, err := userIdSignatureV3Hash(id, pub, sig.Hash)
+ if err != nil {
+ return err
+ }
+ return pk.VerifySignatureV3(h, sig)
+}
+
+// KeyIdString returns the public key's fingerprint in capital hex
+// (e.g. "6C7EE1B8621CC013").
+func (pk *PublicKey) KeyIdString() string {
+ return fmt.Sprintf("%X", pk.Fingerprint[12:20])
+}
+
+// KeyIdShortString returns the short form of public key's fingerprint
+// in capital hex, as shown by gpg --list-keys (e.g. "621CC013").
+func (pk *PublicKey) KeyIdShortString() string {
+ return fmt.Sprintf("%X", pk.Fingerprint[16:20])
+}
+
+// A parsedMPI is used to store the contents of a big integer, along with the
+// bit length that was specified in the original input. This allows the MPI to
+// be reserialized exactly.
+type parsedMPI struct {
+ bytes []byte
+ bitLength uint16
+}
+
+// writeMPIs is a utility function for serializing several big integers to the
+// given Writer.
+func writeMPIs(w io.Writer, mpis ...parsedMPI) (err error) {
+ for _, mpi := range mpis {
+ err = writeMPI(w, mpi.bitLength, mpi.bytes)
+ if err != nil {
+ return
+ }
+ }
+ return
+}
+
+// BitLength returns the bit length for the given public key.
+func (pk *PublicKey) BitLength() (bitLength uint16, err error) {
+ switch pk.PubKeyAlgo {
+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
+ bitLength = pk.n.bitLength
+ case PubKeyAlgoDSA:
+ bitLength = pk.p.bitLength
+ case PubKeyAlgoElGamal:
+ bitLength = pk.p.bitLength
+ default:
+ err = errors.InvalidArgumentError("bad public-key algorithm")
+ }
+ return
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/public_key_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/public_key_test.go
new file mode 100644
index 000000000..7ad7d9185
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/public_key_test.go
@@ -0,0 +1,202 @@
+// Copyright 2011 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 packet
+
+import (
+ "bytes"
+ "encoding/hex"
+ "testing"
+ "time"
+)
+
+var pubKeyTests = []struct {
+ hexData string
+ hexFingerprint string
+ creationTime time.Time
+ pubKeyAlgo PublicKeyAlgorithm
+ keyId uint64
+ keyIdString string
+ keyIdShort string
+}{
+ {rsaPkDataHex, rsaFingerprintHex, time.Unix(0x4d3c5c10, 0), PubKeyAlgoRSA, 0xa34d7e18c20c31bb, "A34D7E18C20C31BB", "C20C31BB"},
+ {dsaPkDataHex, dsaFingerprintHex, time.Unix(0x4d432f89, 0), PubKeyAlgoDSA, 0x8e8fbe54062f19ed, "8E8FBE54062F19ED", "062F19ED"},
+ {ecdsaPkDataHex, ecdsaFingerprintHex, time.Unix(0x5071c294, 0), PubKeyAlgoECDSA, 0x43fe956c542ca00b, "43FE956C542CA00B", "542CA00B"},
+}
+
+func TestPublicKeyRead(t *testing.T) {
+ for i, test := range pubKeyTests {
+ packet, err := Read(readerFromHex(test.hexData))
+ if err != nil {
+ t.Errorf("#%d: Read error: %s", i, err)
+ continue
+ }
+ pk, ok := packet.(*PublicKey)
+ if !ok {
+ t.Errorf("#%d: failed to parse, got: %#v", i, packet)
+ continue
+ }
+ if pk.PubKeyAlgo != test.pubKeyAlgo {
+ t.Errorf("#%d: bad public key algorithm got:%x want:%x", i, pk.PubKeyAlgo, test.pubKeyAlgo)
+ }
+ if !pk.CreationTime.Equal(test.creationTime) {
+ t.Errorf("#%d: bad creation time got:%v want:%v", i, pk.CreationTime, test.creationTime)
+ }
+ expectedFingerprint, _ := hex.DecodeString(test.hexFingerprint)
+ if !bytes.Equal(expectedFingerprint, pk.Fingerprint[:]) {
+ t.Errorf("#%d: bad fingerprint got:%x want:%x", i, pk.Fingerprint[:], expectedFingerprint)
+ }
+ if pk.KeyId != test.keyId {
+ t.Errorf("#%d: bad keyid got:%x want:%x", i, pk.KeyId, test.keyId)
+ }
+ if g, e := pk.KeyIdString(), test.keyIdString; g != e {
+ t.Errorf("#%d: bad KeyIdString got:%q want:%q", i, g, e)
+ }
+ if g, e := pk.KeyIdShortString(), test.keyIdShort; g != e {
+ t.Errorf("#%d: bad KeyIdShortString got:%q want:%q", i, g, e)
+ }
+ }
+}
+
+func TestPublicKeySerialize(t *testing.T) {
+ for i, test := range pubKeyTests {
+ packet, err := Read(readerFromHex(test.hexData))
+ if err != nil {
+ t.Errorf("#%d: Read error: %s", i, err)
+ continue
+ }
+ pk, ok := packet.(*PublicKey)
+ if !ok {
+ t.Errorf("#%d: failed to parse, got: %#v", i, packet)
+ continue
+ }
+ serializeBuf := bytes.NewBuffer(nil)
+ err = pk.Serialize(serializeBuf)
+ if err != nil {
+ t.Errorf("#%d: failed to serialize: %s", i, err)
+ continue
+ }
+
+ packet, err = Read(serializeBuf)
+ if err != nil {
+ t.Errorf("#%d: Read error (from serialized data): %s", i, err)
+ continue
+ }
+ pk, ok = packet.(*PublicKey)
+ if !ok {
+ t.Errorf("#%d: failed to parse serialized data, got: %#v", i, packet)
+ continue
+ }
+ }
+}
+
+func TestEcc384Serialize(t *testing.T) {
+ r := readerFromHex(ecc384PubHex)
+ var w bytes.Buffer
+ for i := 0; i < 2; i++ {
+ // Public key
+ p, err := Read(r)
+ if err != nil {
+ t.Error(err)
+ }
+ pubkey := p.(*PublicKey)
+ if !bytes.Equal(pubkey.ec.oid, []byte{0x2b, 0x81, 0x04, 0x00, 0x22}) {
+ t.Errorf("Unexpected pubkey OID: %x", pubkey.ec.oid)
+ }
+ if !bytes.Equal(pubkey.ec.p.bytes[:5], []byte{0x04, 0xf6, 0xb8, 0xc5, 0xac}) {
+ t.Errorf("Unexpected pubkey P[:5]: %x", pubkey.ec.p.bytes)
+ }
+ if pubkey.KeyId != 0x098033880F54719F {
+ t.Errorf("Unexpected pubkey ID: %x", pubkey.KeyId)
+ }
+ err = pubkey.Serialize(&w)
+ if err != nil {
+ t.Error(err)
+ }
+ // User ID
+ p, err = Read(r)
+ if err != nil {
+ t.Error(err)
+ }
+ uid := p.(*UserId)
+ if uid.Id != "ec_dsa_dh_384 <openpgp@brainhub.org>" {
+ t.Error("Unexpected UID:", uid.Id)
+ }
+ err = uid.Serialize(&w)
+ if err != nil {
+ t.Error(err)
+ }
+ // User ID Sig
+ p, err = Read(r)
+ if err != nil {
+ t.Error(err)
+ }
+ uidSig := p.(*Signature)
+ err = pubkey.VerifyUserIdSignature(uid.Id, pubkey, uidSig)
+ if err != nil {
+ t.Error(err, ": UID")
+ }
+ err = uidSig.Serialize(&w)
+ if err != nil {
+ t.Error(err)
+ }
+ // Subkey
+ p, err = Read(r)
+ if err != nil {
+ t.Error(err)
+ }
+ subkey := p.(*PublicKey)
+ if !bytes.Equal(subkey.ec.oid, []byte{0x2b, 0x81, 0x04, 0x00, 0x22}) {
+ t.Errorf("Unexpected subkey OID: %x", subkey.ec.oid)
+ }
+ if !bytes.Equal(subkey.ec.p.bytes[:5], []byte{0x04, 0x2f, 0xaa, 0x84, 0x02}) {
+ t.Errorf("Unexpected subkey P[:5]: %x", subkey.ec.p.bytes)
+ }
+ if subkey.ecdh.KdfHash != 0x09 {
+ t.Error("Expected KDF hash function SHA384 (0x09), got", subkey.ecdh.KdfHash)
+ }
+ if subkey.ecdh.KdfAlgo != 0x09 {
+ t.Error("Expected KDF symmetric alg AES256 (0x09), got", subkey.ecdh.KdfAlgo)
+ }
+ if subkey.KeyId != 0xAA8B938F9A201946 {
+ t.Errorf("Unexpected subkey ID: %x", subkey.KeyId)
+ }
+ err = subkey.Serialize(&w)
+ if err != nil {
+ t.Error(err)
+ }
+ // Subkey Sig
+ p, err = Read(r)
+ if err != nil {
+ t.Error(err)
+ }
+ subkeySig := p.(*Signature)
+ err = pubkey.VerifyKeySignature(subkey, subkeySig)
+ if err != nil {
+ t.Error(err)
+ }
+ err = subkeySig.Serialize(&w)
+ if err != nil {
+ t.Error(err)
+ }
+ // Now read back what we've written again
+ r = bytes.NewBuffer(w.Bytes())
+ w.Reset()
+ }
+}
+
+const rsaFingerprintHex = "5fb74b1d03b1e3cb31bc2f8aa34d7e18c20c31bb"
+
+const rsaPkDataHex = "988d044d3c5c10010400b1d13382944bd5aba23a4312968b5095d14f947f600eb478e14a6fcb16b0e0cac764884909c020bc495cfcc39a935387c661507bdb236a0612fb582cac3af9b29cc2c8c70090616c41b662f4da4c1201e195472eb7f4ae1ccbcbf9940fe21d985e379a5563dde5b9a23d35f1cfaa5790da3b79db26f23695107bfaca8e7b5bcd0011010001"
+
+const dsaFingerprintHex = "eece4c094db002103714c63c8e8fbe54062f19ed"
+
+const dsaPkDataHex = "9901a2044d432f89110400cd581334f0d7a1e1bdc8b9d6d8c0baf68793632735d2bb0903224cbaa1dfbf35a60ee7a13b92643421e1eb41aa8d79bea19a115a677f6b8ba3c7818ce53a6c2a24a1608bd8b8d6e55c5090cbde09dd26e356267465ae25e69ec8bdd57c7bbb2623e4d73336f73a0a9098f7f16da2e25252130fd694c0e8070c55a812a423ae7f00a0ebf50e70c2f19c3520a551bd4b08d30f23530d3d03ff7d0bf4a53a64a09dc5e6e6e35854b7d70c882b0c60293401958b1bd9e40abec3ea05ba87cf64899299d4bd6aa7f459c201d3fbbd6c82004bdc5e8a9eb8082d12054cc90fa9d4ec251a843236a588bf49552441817436c4f43326966fe85447d4e6d0acf8fa1ef0f014730770603ad7634c3088dc52501c237328417c31c89ed70400b2f1a98b0bf42f11fefc430704bebbaa41d9f355600c3facee1e490f64208e0e094ea55e3a598a219a58500bf78ac677b670a14f4e47e9cf8eab4f368cc1ddcaa18cc59309d4cc62dd4f680e73e6cc3e1ce87a84d0925efbcb26c575c093fc42eecf45135fabf6403a25c2016e1774c0484e440a18319072c617cc97ac0a3bb0"
+
+const ecdsaFingerprintHex = "9892270b38b8980b05c8d56d43fe956c542ca00b"
+
+const ecdsaPkDataHex = "9893045071c29413052b8104002304230401f4867769cedfa52c325018896245443968e52e51d0c2df8d939949cb5b330f2921711fbee1c9b9dddb95d15cb0255e99badeddda7cc23d9ddcaacbc290969b9f24019375d61c2e4e3b36953a28d8b2bc95f78c3f1d592fb24499be348656a7b17e3963187b4361afe497bc5f9f81213f04069f8e1fb9e6a6290ae295ca1a92b894396cb4"
+
+// Source: https://sites.google.com/site/brainhub/pgpecckeys#TOC-ECC-NIST-P-384-key
+const ecc384PubHex = `99006f044d53059213052b81040022030304f6b8c5aced5b84ef9f4a209db2e4a9dfb70d28cb8c10ecd57674a9fa5a67389942b62d5e51367df4c7bfd3f8e500feecf07ed265a621a8ebbbe53e947ec78c677eba143bd1533c2b350e1c29f82313e1e1108eba063be1e64b10e6950e799c2db42465635f6473615f64685f333834203c6f70656e70677040627261696e6875622e6f72673e8900cb04101309005305024d530592301480000000002000077072656665727265642d656d61696c2d656e636f64696e67407067702e636f6d7067706d696d65040b090807021901051b03000000021602051e010000000415090a08000a0910098033880f54719fca2b0180aa37350968bd5f115afd8ce7bc7b103822152dbff06d0afcda835329510905b98cb469ba208faab87c7412b799e7b633017f58364ea480e8a1a3f253a0c5f22c446e8be9a9fce6210136ee30811abbd49139de28b5bdf8dc36d06ae748579e9ff503b90073044d53059212052b810400220303042faa84024a20b6735c4897efa5bfb41bf85b7eefeab5ca0cb9ffc8ea04a46acb25534a577694f9e25340a4ab5223a9dd1eda530c8aa2e6718db10d7e672558c7736fe09369ea5739a2a3554bf16d41faa50562f11c6d39bbd5dffb6b9a9ec9180301090989008404181309000c05024d530592051b0c000000000a0910098033880f54719f80970180eee7a6d8fcee41ee4f9289df17f9bcf9d955dca25c583b94336f3a2b2d4986dc5cf417b8d2dc86f741a9e1a6d236c0e3017d1c76575458a0cfb93ae8a2b274fcc65ceecd7a91eec83656ba13219969f06945b48c56bd04152c3a0553c5f2f4bd1267`
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/public_key_v3.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/public_key_v3.go
new file mode 100644
index 000000000..5daf7b6cf
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/public_key_v3.go
@@ -0,0 +1,279 @@
+// Copyright 2013 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 packet
+
+import (
+ "crypto"
+ "crypto/md5"
+ "crypto/rsa"
+ "encoding/binary"
+ "fmt"
+ "hash"
+ "io"
+ "math/big"
+ "strconv"
+ "time"
+
+ "golang.org/x/crypto/openpgp/errors"
+)
+
+// PublicKeyV3 represents older, version 3 public keys. These keys are less secure and
+// should not be used for signing or encrypting. They are supported here only for
+// parsing version 3 key material and validating signatures.
+// See RFC 4880, section 5.5.2.
+type PublicKeyV3 struct {
+ CreationTime time.Time
+ DaysToExpire uint16
+ PubKeyAlgo PublicKeyAlgorithm
+ PublicKey *rsa.PublicKey
+ Fingerprint [16]byte
+ KeyId uint64
+ IsSubkey bool
+
+ n, e parsedMPI
+}
+
+// newRSAPublicKeyV3 returns a PublicKey that wraps the given rsa.PublicKey.
+// Included here for testing purposes only. RFC 4880, section 5.5.2:
+// "an implementation MUST NOT generate a V3 key, but MAY accept it."
+func newRSAPublicKeyV3(creationTime time.Time, pub *rsa.PublicKey) *PublicKeyV3 {
+ pk := &PublicKeyV3{
+ CreationTime: creationTime,
+ PublicKey: pub,
+ n: fromBig(pub.N),
+ e: fromBig(big.NewInt(int64(pub.E))),
+ }
+
+ pk.setFingerPrintAndKeyId()
+ return pk
+}
+
+func (pk *PublicKeyV3) parse(r io.Reader) (err error) {
+ // RFC 4880, section 5.5.2
+ var buf [8]byte
+ if _, err = readFull(r, buf[:]); err != nil {
+ return
+ }
+ if buf[0] < 2 || buf[0] > 3 {
+ return errors.UnsupportedError("public key version")
+ }
+ pk.CreationTime = time.Unix(int64(uint32(buf[1])<<24|uint32(buf[2])<<16|uint32(buf[3])<<8|uint32(buf[4])), 0)
+ pk.DaysToExpire = binary.BigEndian.Uint16(buf[5:7])
+ pk.PubKeyAlgo = PublicKeyAlgorithm(buf[7])
+ switch pk.PubKeyAlgo {
+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
+ err = pk.parseRSA(r)
+ default:
+ err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo)))
+ }
+ if err != nil {
+ return
+ }
+
+ pk.setFingerPrintAndKeyId()
+ return
+}
+
+func (pk *PublicKeyV3) setFingerPrintAndKeyId() {
+ // RFC 4880, section 12.2
+ fingerPrint := md5.New()
+ fingerPrint.Write(pk.n.bytes)
+ fingerPrint.Write(pk.e.bytes)
+ fingerPrint.Sum(pk.Fingerprint[:0])
+ pk.KeyId = binary.BigEndian.Uint64(pk.n.bytes[len(pk.n.bytes)-8:])
+}
+
+// parseRSA parses RSA public key material from the given Reader. See RFC 4880,
+// section 5.5.2.
+func (pk *PublicKeyV3) parseRSA(r io.Reader) (err error) {
+ if pk.n.bytes, pk.n.bitLength, err = readMPI(r); err != nil {
+ return
+ }
+ if pk.e.bytes, pk.e.bitLength, err = readMPI(r); err != nil {
+ return
+ }
+
+ // RFC 4880 Section 12.2 requires the low 8 bytes of the
+ // modulus to form the key id.
+ if len(pk.n.bytes) < 8 {
+ return errors.StructuralError("v3 public key modulus is too short")
+ }
+ if len(pk.e.bytes) > 3 {
+ err = errors.UnsupportedError("large public exponent")
+ return
+ }
+ rsa := &rsa.PublicKey{N: new(big.Int).SetBytes(pk.n.bytes)}
+ for i := 0; i < len(pk.e.bytes); i++ {
+ rsa.E <<= 8
+ rsa.E |= int(pk.e.bytes[i])
+ }
+ pk.PublicKey = rsa
+ return
+}
+
+// SerializeSignaturePrefix writes the prefix for this public key to the given Writer.
+// The prefix is used when calculating a signature over this public key. See
+// RFC 4880, section 5.2.4.
+func (pk *PublicKeyV3) SerializeSignaturePrefix(w io.Writer) {
+ var pLength uint16
+ switch pk.PubKeyAlgo {
+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
+ pLength += 2 + uint16(len(pk.n.bytes))
+ pLength += 2 + uint16(len(pk.e.bytes))
+ default:
+ panic("unknown public key algorithm")
+ }
+ pLength += 6
+ w.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)})
+ return
+}
+
+func (pk *PublicKeyV3) Serialize(w io.Writer) (err error) {
+ length := 8 // 8 byte header
+
+ switch pk.PubKeyAlgo {
+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
+ length += 2 + len(pk.n.bytes)
+ length += 2 + len(pk.e.bytes)
+ default:
+ panic("unknown public key algorithm")
+ }
+
+ packetType := packetTypePublicKey
+ if pk.IsSubkey {
+ packetType = packetTypePublicSubkey
+ }
+ if err = serializeHeader(w, packetType, length); err != nil {
+ return
+ }
+ return pk.serializeWithoutHeaders(w)
+}
+
+// serializeWithoutHeaders marshals the PublicKey to w in the form of an
+// OpenPGP public key packet, not including the packet header.
+func (pk *PublicKeyV3) serializeWithoutHeaders(w io.Writer) (err error) {
+ var buf [8]byte
+ // Version 3
+ buf[0] = 3
+ // Creation time
+ t := uint32(pk.CreationTime.Unix())
+ buf[1] = byte(t >> 24)
+ buf[2] = byte(t >> 16)
+ buf[3] = byte(t >> 8)
+ buf[4] = byte(t)
+ // Days to expire
+ buf[5] = byte(pk.DaysToExpire >> 8)
+ buf[6] = byte(pk.DaysToExpire)
+ // Public key algorithm
+ buf[7] = byte(pk.PubKeyAlgo)
+
+ if _, err = w.Write(buf[:]); err != nil {
+ return
+ }
+
+ switch pk.PubKeyAlgo {
+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
+ return writeMPIs(w, pk.n, pk.e)
+ }
+ return errors.InvalidArgumentError("bad public-key algorithm")
+}
+
+// CanSign returns true iff this public key can generate signatures
+func (pk *PublicKeyV3) CanSign() bool {
+ return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly
+}
+
+// VerifySignatureV3 returns nil iff sig is a valid signature, made by this
+// public key, of the data hashed into signed. signed is mutated by this call.
+func (pk *PublicKeyV3) VerifySignatureV3(signed hash.Hash, sig *SignatureV3) (err error) {
+ if !pk.CanSign() {
+ return errors.InvalidArgumentError("public key cannot generate signatures")
+ }
+
+ suffix := make([]byte, 5)
+ suffix[0] = byte(sig.SigType)
+ binary.BigEndian.PutUint32(suffix[1:], uint32(sig.CreationTime.Unix()))
+ signed.Write(suffix)
+ hashBytes := signed.Sum(nil)
+
+ if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] {
+ return errors.SignatureError("hash tag doesn't match")
+ }
+
+ if pk.PubKeyAlgo != sig.PubKeyAlgo {
+ return errors.InvalidArgumentError("public key and signature use different algorithms")
+ }
+
+ switch pk.PubKeyAlgo {
+ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
+ if err = rsa.VerifyPKCS1v15(pk.PublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes); err != nil {
+ return errors.SignatureError("RSA verification failure")
+ }
+ return
+ default:
+ // V3 public keys only support RSA.
+ panic("shouldn't happen")
+ }
+}
+
+// VerifyUserIdSignatureV3 returns nil iff sig is a valid signature, made by this
+// public key, that id is the identity of pub.
+func (pk *PublicKeyV3) VerifyUserIdSignatureV3(id string, pub *PublicKeyV3, sig *SignatureV3) (err error) {
+ h, err := userIdSignatureV3Hash(id, pk, sig.Hash)
+ if err != nil {
+ return err
+ }
+ return pk.VerifySignatureV3(h, sig)
+}
+
+// VerifyKeySignatureV3 returns nil iff sig is a valid signature, made by this
+// public key, of signed.
+func (pk *PublicKeyV3) VerifyKeySignatureV3(signed *PublicKeyV3, sig *SignatureV3) (err error) {
+ h, err := keySignatureHash(pk, signed, sig.Hash)
+ if err != nil {
+ return err
+ }
+ return pk.VerifySignatureV3(h, sig)
+}
+
+// userIdSignatureV3Hash returns a Hash of the message that needs to be signed
+// to assert that pk is a valid key for id.
+func userIdSignatureV3Hash(id string, pk signingKey, hfn crypto.Hash) (h hash.Hash, err error) {
+ if !hfn.Available() {
+ return nil, errors.UnsupportedError("hash function")
+ }
+ h = hfn.New()
+
+ // RFC 4880, section 5.2.4
+ pk.SerializeSignaturePrefix(h)
+ pk.serializeWithoutHeaders(h)
+
+ h.Write([]byte(id))
+
+ return
+}
+
+// KeyIdString returns the public key's fingerprint in capital hex
+// (e.g. "6C7EE1B8621CC013").
+func (pk *PublicKeyV3) KeyIdString() string {
+ return fmt.Sprintf("%X", pk.KeyId)
+}
+
+// KeyIdShortString returns the short form of public key's fingerprint
+// in capital hex, as shown by gpg --list-keys (e.g. "621CC013").
+func (pk *PublicKeyV3) KeyIdShortString() string {
+ return fmt.Sprintf("%X", pk.KeyId&0xFFFFFFFF)
+}
+
+// BitLength returns the bit length for the given public key.
+func (pk *PublicKeyV3) BitLength() (bitLength uint16, err error) {
+ switch pk.PubKeyAlgo {
+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
+ bitLength = pk.n.bitLength
+ default:
+ err = errors.InvalidArgumentError("bad public-key algorithm")
+ }
+ return
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/public_key_v3_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/public_key_v3_test.go
new file mode 100644
index 000000000..e06405904
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/public_key_v3_test.go
@@ -0,0 +1,82 @@
+// Copyright 2013 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 packet
+
+import (
+ "bytes"
+ "encoding/hex"
+ "testing"
+ "time"
+)
+
+var pubKeyV3Test = struct {
+ hexFingerprint string
+ creationTime time.Time
+ pubKeyAlgo PublicKeyAlgorithm
+ keyId uint64
+ keyIdString string
+ keyIdShort string
+}{
+ "103BECF5BD1E837C89D19E98487767F7",
+ time.Unix(779753634, 0),
+ PubKeyAlgoRSA,
+ 0xDE0F188A5DA5E3C9,
+ "DE0F188A5DA5E3C9",
+ "5DA5E3C9"}
+
+func TestPublicKeyV3Read(t *testing.T) {
+ i, test := 0, pubKeyV3Test
+ packet, err := Read(v3KeyReader(t))
+ if err != nil {
+ t.Fatalf("#%d: Read error: %s", i, err)
+ }
+ pk, ok := packet.(*PublicKeyV3)
+ if !ok {
+ t.Fatalf("#%d: failed to parse, got: %#v", i, packet)
+ }
+ if pk.PubKeyAlgo != test.pubKeyAlgo {
+ t.Errorf("#%d: bad public key algorithm got:%x want:%x", i, pk.PubKeyAlgo, test.pubKeyAlgo)
+ }
+ if !pk.CreationTime.Equal(test.creationTime) {
+ t.Errorf("#%d: bad creation time got:%v want:%v", i, pk.CreationTime, test.creationTime)
+ }
+ expectedFingerprint, _ := hex.DecodeString(test.hexFingerprint)
+ if !bytes.Equal(expectedFingerprint, pk.Fingerprint[:]) {
+ t.Errorf("#%d: bad fingerprint got:%x want:%x", i, pk.Fingerprint[:], expectedFingerprint)
+ }
+ if pk.KeyId != test.keyId {
+ t.Errorf("#%d: bad keyid got:%x want:%x", i, pk.KeyId, test.keyId)
+ }
+ if g, e := pk.KeyIdString(), test.keyIdString; g != e {
+ t.Errorf("#%d: bad KeyIdString got:%q want:%q", i, g, e)
+ }
+ if g, e := pk.KeyIdShortString(), test.keyIdShort; g != e {
+ t.Errorf("#%d: bad KeyIdShortString got:%q want:%q", i, g, e)
+ }
+}
+
+func TestPublicKeyV3Serialize(t *testing.T) {
+ //for i, test := range pubKeyV3Tests {
+ i := 0
+ packet, err := Read(v3KeyReader(t))
+ if err != nil {
+ t.Fatalf("#%d: Read error: %s", i, err)
+ }
+ pk, ok := packet.(*PublicKeyV3)
+ if !ok {
+ t.Fatalf("#%d: failed to parse, got: %#v", i, packet)
+ }
+ var serializeBuf bytes.Buffer
+ if err = pk.Serialize(&serializeBuf); err != nil {
+ t.Fatalf("#%d: failed to serialize: %s", i, err)
+ }
+
+ if packet, err = Read(bytes.NewBuffer(serializeBuf.Bytes())); err != nil {
+ t.Fatalf("#%d: Read error (from serialized data): %s", i, err)
+ }
+ if pk, ok = packet.(*PublicKeyV3); !ok {
+ t.Fatalf("#%d: failed to parse serialized data, got: %#v", i, packet)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/reader.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/reader.go
new file mode 100644
index 000000000..34bc7c613
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/reader.go
@@ -0,0 +1,76 @@
+// Copyright 2011 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 packet
+
+import (
+ "golang.org/x/crypto/openpgp/errors"
+ "io"
+)
+
+// Reader reads packets from an io.Reader and allows packets to be 'unread' so
+// that they result from the next call to Next.
+type Reader struct {
+ q []Packet
+ readers []io.Reader
+}
+
+// New io.Readers are pushed when a compressed or encrypted packet is processed
+// and recursively treated as a new source of packets. However, a carefully
+// crafted packet can trigger an infinite recursive sequence of packets. See
+// http://mumble.net/~campbell/misc/pgp-quine
+// https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2013-4402
+// This constant limits the number of recursive packets that may be pushed.
+const maxReaders = 32
+
+// Next returns the most recently unread Packet, or reads another packet from
+// the top-most io.Reader. Unknown packet types are skipped.
+func (r *Reader) Next() (p Packet, err error) {
+ if len(r.q) > 0 {
+ p = r.q[len(r.q)-1]
+ r.q = r.q[:len(r.q)-1]
+ return
+ }
+
+ for len(r.readers) > 0 {
+ p, err = Read(r.readers[len(r.readers)-1])
+ if err == nil {
+ return
+ }
+ if err == io.EOF {
+ r.readers = r.readers[:len(r.readers)-1]
+ continue
+ }
+ if _, ok := err.(errors.UnknownPacketTypeError); !ok {
+ return nil, err
+ }
+ }
+
+ return nil, io.EOF
+}
+
+// Push causes the Reader to start reading from a new io.Reader. When an EOF
+// error is seen from the new io.Reader, it is popped and the Reader continues
+// to read from the next most recent io.Reader. Push returns a StructuralError
+// if pushing the reader would exceed the maximum recursion level, otherwise it
+// returns nil.
+func (r *Reader) Push(reader io.Reader) (err error) {
+ if len(r.readers) >= maxReaders {
+ return errors.StructuralError("too many layers of packets")
+ }
+ r.readers = append(r.readers, reader)
+ return nil
+}
+
+// Unread causes the given Packet to be returned from the next call to Next.
+func (r *Reader) Unread(p Packet) {
+ r.q = append(r.q, p)
+}
+
+func NewReader(r io.Reader) *Reader {
+ return &Reader{
+ q: nil,
+ readers: []io.Reader{r},
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/signature.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/signature.go
new file mode 100644
index 000000000..6ce0cbedb
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/signature.go
@@ -0,0 +1,731 @@
+// Copyright 2011 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 packet
+
+import (
+ "bytes"
+ "crypto"
+ "crypto/dsa"
+ "crypto/ecdsa"
+ "encoding/asn1"
+ "encoding/binary"
+ "hash"
+ "io"
+ "math/big"
+ "strconv"
+ "time"
+
+ "golang.org/x/crypto/openpgp/errors"
+ "golang.org/x/crypto/openpgp/s2k"
+)
+
+const (
+ // See RFC 4880, section 5.2.3.21 for details.
+ KeyFlagCertify = 1 << iota
+ KeyFlagSign
+ KeyFlagEncryptCommunications
+ KeyFlagEncryptStorage
+)
+
+// Signature represents a signature. See RFC 4880, section 5.2.
+type Signature struct {
+ SigType SignatureType
+ PubKeyAlgo PublicKeyAlgorithm
+ Hash crypto.Hash
+
+ // HashSuffix is extra data that is hashed in after the signed data.
+ HashSuffix []byte
+ // HashTag contains the first two bytes of the hash for fast rejection
+ // of bad signed data.
+ HashTag [2]byte
+ CreationTime time.Time
+
+ RSASignature parsedMPI
+ DSASigR, DSASigS parsedMPI
+ ECDSASigR, ECDSASigS parsedMPI
+
+ // rawSubpackets contains the unparsed subpackets, in order.
+ rawSubpackets []outputSubpacket
+
+ // The following are optional so are nil when not included in the
+ // signature.
+
+ SigLifetimeSecs, KeyLifetimeSecs *uint32
+ PreferredSymmetric, PreferredHash, PreferredCompression []uint8
+ IssuerKeyId *uint64
+ IsPrimaryId *bool
+
+ // FlagsValid is set if any flags were given. See RFC 4880, section
+ // 5.2.3.21 for details.
+ FlagsValid bool
+ FlagCertify, FlagSign, FlagEncryptCommunications, FlagEncryptStorage bool
+
+ // RevocationReason is set if this signature has been revoked.
+ // See RFC 4880, section 5.2.3.23 for details.
+ RevocationReason *uint8
+ RevocationReasonText string
+
+ // MDC is set if this signature has a feature packet that indicates
+ // support for MDC subpackets.
+ MDC bool
+
+ // EmbeddedSignature, if non-nil, is a signature of the parent key, by
+ // this key. This prevents an attacker from claiming another's signing
+ // subkey as their own.
+ EmbeddedSignature *Signature
+
+ outSubpackets []outputSubpacket
+}
+
+func (sig *Signature) parse(r io.Reader) (err error) {
+ // RFC 4880, section 5.2.3
+ var buf [5]byte
+ _, err = readFull(r, buf[:1])
+ if err != nil {
+ return
+ }
+ if buf[0] != 4 {
+ err = errors.UnsupportedError("signature packet version " + strconv.Itoa(int(buf[0])))
+ return
+ }
+
+ _, err = readFull(r, buf[:5])
+ if err != nil {
+ return
+ }
+ sig.SigType = SignatureType(buf[0])
+ sig.PubKeyAlgo = PublicKeyAlgorithm(buf[1])
+ switch sig.PubKeyAlgo {
+ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA:
+ default:
+ err = errors.UnsupportedError("public key algorithm " + strconv.Itoa(int(sig.PubKeyAlgo)))
+ return
+ }
+
+ var ok bool
+ sig.Hash, ok = s2k.HashIdToHash(buf[2])
+ if !ok {
+ return errors.UnsupportedError("hash function " + strconv.Itoa(int(buf[2])))
+ }
+
+ hashedSubpacketsLength := int(buf[3])<<8 | int(buf[4])
+ l := 6 + hashedSubpacketsLength
+ sig.HashSuffix = make([]byte, l+6)
+ sig.HashSuffix[0] = 4
+ copy(sig.HashSuffix[1:], buf[:5])
+ hashedSubpackets := sig.HashSuffix[6:l]
+ _, err = readFull(r, hashedSubpackets)
+ if err != nil {
+ return
+ }
+ // See RFC 4880, section 5.2.4
+ trailer := sig.HashSuffix[l:]
+ trailer[0] = 4
+ trailer[1] = 0xff
+ trailer[2] = uint8(l >> 24)
+ trailer[3] = uint8(l >> 16)
+ trailer[4] = uint8(l >> 8)
+ trailer[5] = uint8(l)
+
+ err = parseSignatureSubpackets(sig, hashedSubpackets, true)
+ if err != nil {
+ return
+ }
+
+ _, err = readFull(r, buf[:2])
+ if err != nil {
+ return
+ }
+ unhashedSubpacketsLength := int(buf[0])<<8 | int(buf[1])
+ unhashedSubpackets := make([]byte, unhashedSubpacketsLength)
+ _, err = readFull(r, unhashedSubpackets)
+ if err != nil {
+ return
+ }
+ err = parseSignatureSubpackets(sig, unhashedSubpackets, false)
+ if err != nil {
+ return
+ }
+
+ _, err = readFull(r, sig.HashTag[:2])
+ if err != nil {
+ return
+ }
+
+ switch sig.PubKeyAlgo {
+ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
+ sig.RSASignature.bytes, sig.RSASignature.bitLength, err = readMPI(r)
+ case PubKeyAlgoDSA:
+ sig.DSASigR.bytes, sig.DSASigR.bitLength, err = readMPI(r)
+ if err == nil {
+ sig.DSASigS.bytes, sig.DSASigS.bitLength, err = readMPI(r)
+ }
+ case PubKeyAlgoECDSA:
+ sig.ECDSASigR.bytes, sig.ECDSASigR.bitLength, err = readMPI(r)
+ if err == nil {
+ sig.ECDSASigS.bytes, sig.ECDSASigS.bitLength, err = readMPI(r)
+ }
+ default:
+ panic("unreachable")
+ }
+ return
+}
+
+// parseSignatureSubpackets parses subpackets of the main signature packet. See
+// RFC 4880, section 5.2.3.1.
+func parseSignatureSubpackets(sig *Signature, subpackets []byte, isHashed bool) (err error) {
+ for len(subpackets) > 0 {
+ subpackets, err = parseSignatureSubpacket(sig, subpackets, isHashed)
+ if err != nil {
+ return
+ }
+ }
+
+ if sig.CreationTime.IsZero() {
+ err = errors.StructuralError("no creation time in signature")
+ }
+
+ return
+}
+
+type signatureSubpacketType uint8
+
+const (
+ creationTimeSubpacket signatureSubpacketType = 2
+ signatureExpirationSubpacket signatureSubpacketType = 3
+ keyExpirationSubpacket signatureSubpacketType = 9
+ prefSymmetricAlgosSubpacket signatureSubpacketType = 11
+ issuerSubpacket signatureSubpacketType = 16
+ prefHashAlgosSubpacket signatureSubpacketType = 21
+ prefCompressionSubpacket signatureSubpacketType = 22
+ primaryUserIdSubpacket signatureSubpacketType = 25
+ keyFlagsSubpacket signatureSubpacketType = 27
+ reasonForRevocationSubpacket signatureSubpacketType = 29
+ featuresSubpacket signatureSubpacketType = 30
+ embeddedSignatureSubpacket signatureSubpacketType = 32
+)
+
+// parseSignatureSubpacket parses a single subpacket. len(subpacket) is >= 1.
+func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (rest []byte, err error) {
+ // RFC 4880, section 5.2.3.1
+ var (
+ length uint32
+ packetType signatureSubpacketType
+ isCritical bool
+ )
+ switch {
+ case subpacket[0] < 192:
+ length = uint32(subpacket[0])
+ subpacket = subpacket[1:]
+ case subpacket[0] < 255:
+ if len(subpacket) < 2 {
+ goto Truncated
+ }
+ length = uint32(subpacket[0]-192)<<8 + uint32(subpacket[1]) + 192
+ subpacket = subpacket[2:]
+ default:
+ if len(subpacket) < 5 {
+ goto Truncated
+ }
+ length = uint32(subpacket[1])<<24 |
+ uint32(subpacket[2])<<16 |
+ uint32(subpacket[3])<<8 |
+ uint32(subpacket[4])
+ subpacket = subpacket[5:]
+ }
+ if length > uint32(len(subpacket)) {
+ goto Truncated
+ }
+ rest = subpacket[length:]
+ subpacket = subpacket[:length]
+ if len(subpacket) == 0 {
+ err = errors.StructuralError("zero length signature subpacket")
+ return
+ }
+ packetType = signatureSubpacketType(subpacket[0] & 0x7f)
+ isCritical = subpacket[0]&0x80 == 0x80
+ subpacket = subpacket[1:]
+ sig.rawSubpackets = append(sig.rawSubpackets, outputSubpacket{isHashed, packetType, isCritical, subpacket})
+ switch packetType {
+ case creationTimeSubpacket:
+ if !isHashed {
+ err = errors.StructuralError("signature creation time in non-hashed area")
+ return
+ }
+ if len(subpacket) != 4 {
+ err = errors.StructuralError("signature creation time not four bytes")
+ return
+ }
+ t := binary.BigEndian.Uint32(subpacket)
+ sig.CreationTime = time.Unix(int64(t), 0)
+ case signatureExpirationSubpacket:
+ // Signature expiration time, section 5.2.3.10
+ if !isHashed {
+ return
+ }
+ if len(subpacket) != 4 {
+ err = errors.StructuralError("expiration subpacket with bad length")
+ return
+ }
+ sig.SigLifetimeSecs = new(uint32)
+ *sig.SigLifetimeSecs = binary.BigEndian.Uint32(subpacket)
+ case keyExpirationSubpacket:
+ // Key expiration time, section 5.2.3.6
+ if !isHashed {
+ return
+ }
+ if len(subpacket) != 4 {
+ err = errors.StructuralError("key expiration subpacket with bad length")
+ return
+ }
+ sig.KeyLifetimeSecs = new(uint32)
+ *sig.KeyLifetimeSecs = binary.BigEndian.Uint32(subpacket)
+ case prefSymmetricAlgosSubpacket:
+ // Preferred symmetric algorithms, section 5.2.3.7
+ if !isHashed {
+ return
+ }
+ sig.PreferredSymmetric = make([]byte, len(subpacket))
+ copy(sig.PreferredSymmetric, subpacket)
+ case issuerSubpacket:
+ // Issuer, section 5.2.3.5
+ if len(subpacket) != 8 {
+ err = errors.StructuralError("issuer subpacket with bad length")
+ return
+ }
+ sig.IssuerKeyId = new(uint64)
+ *sig.IssuerKeyId = binary.BigEndian.Uint64(subpacket)
+ case prefHashAlgosSubpacket:
+ // Preferred hash algorithms, section 5.2.3.8
+ if !isHashed {
+ return
+ }
+ sig.PreferredHash = make([]byte, len(subpacket))
+ copy(sig.PreferredHash, subpacket)
+ case prefCompressionSubpacket:
+ // Preferred compression algorithms, section 5.2.3.9
+ if !isHashed {
+ return
+ }
+ sig.PreferredCompression = make([]byte, len(subpacket))
+ copy(sig.PreferredCompression, subpacket)
+ case primaryUserIdSubpacket:
+ // Primary User ID, section 5.2.3.19
+ if !isHashed {
+ return
+ }
+ if len(subpacket) != 1 {
+ err = errors.StructuralError("primary user id subpacket with bad length")
+ return
+ }
+ sig.IsPrimaryId = new(bool)
+ if subpacket[0] > 0 {
+ *sig.IsPrimaryId = true
+ }
+ case keyFlagsSubpacket:
+ // Key flags, section 5.2.3.21
+ if !isHashed {
+ return
+ }
+ if len(subpacket) == 0 {
+ err = errors.StructuralError("empty key flags subpacket")
+ return
+ }
+ sig.FlagsValid = true
+ if subpacket[0]&KeyFlagCertify != 0 {
+ sig.FlagCertify = true
+ }
+ if subpacket[0]&KeyFlagSign != 0 {
+ sig.FlagSign = true
+ }
+ if subpacket[0]&KeyFlagEncryptCommunications != 0 {
+ sig.FlagEncryptCommunications = true
+ }
+ if subpacket[0]&KeyFlagEncryptStorage != 0 {
+ sig.FlagEncryptStorage = true
+ }
+ case reasonForRevocationSubpacket:
+ // Reason For Revocation, section 5.2.3.23
+ if !isHashed {
+ return
+ }
+ if len(subpacket) == 0 {
+ err = errors.StructuralError("empty revocation reason subpacket")
+ return
+ }
+ sig.RevocationReason = new(uint8)
+ *sig.RevocationReason = subpacket[0]
+ sig.RevocationReasonText = string(subpacket[1:])
+ case featuresSubpacket:
+ // Features subpacket, section 5.2.3.24 specifies a very general
+ // mechanism for OpenPGP implementations to signal support for new
+ // features. In practice, the subpacket is used exclusively to
+ // indicate support for MDC-protected encryption.
+ sig.MDC = len(subpacket) >= 1 && subpacket[0]&1 == 1
+ case embeddedSignatureSubpacket:
+ // Only usage is in signatures that cross-certify
+ // signing subkeys. section 5.2.3.26 describes the
+ // format, with its usage described in section 11.1
+ if sig.EmbeddedSignature != nil {
+ err = errors.StructuralError("Cannot have multiple embedded signatures")
+ return
+ }
+ sig.EmbeddedSignature = new(Signature)
+ // Embedded signatures are required to be v4 signatures see
+ // section 12.1. However, we only parse v4 signatures in this
+ // file anyway.
+ if err := sig.EmbeddedSignature.parse(bytes.NewBuffer(subpacket)); err != nil {
+ return nil, err
+ }
+ if sigType := sig.EmbeddedSignature.SigType; sigType != SigTypePrimaryKeyBinding {
+ return nil, errors.StructuralError("cross-signature has unexpected type " + strconv.Itoa(int(sigType)))
+ }
+ default:
+ if isCritical {
+ err = errors.UnsupportedError("unknown critical signature subpacket type " + strconv.Itoa(int(packetType)))
+ return
+ }
+ }
+ return
+
+Truncated:
+ err = errors.StructuralError("signature subpacket truncated")
+ return
+}
+
+// subpacketLengthLength returns the length, in bytes, of an encoded length value.
+func subpacketLengthLength(length int) int {
+ if length < 192 {
+ return 1
+ }
+ if length < 16320 {
+ return 2
+ }
+ return 5
+}
+
+// serializeSubpacketLength marshals the given length into to.
+func serializeSubpacketLength(to []byte, length int) int {
+ // RFC 4880, Section 4.2.2.
+ if length < 192 {
+ to[0] = byte(length)
+ return 1
+ }
+ if length < 16320 {
+ length -= 192
+ to[0] = byte((length >> 8) + 192)
+ to[1] = byte(length)
+ return 2
+ }
+ to[0] = 255
+ to[1] = byte(length >> 24)
+ to[2] = byte(length >> 16)
+ to[3] = byte(length >> 8)
+ to[4] = byte(length)
+ return 5
+}
+
+// subpacketsLength returns the serialized length, in bytes, of the given
+// subpackets.
+func subpacketsLength(subpackets []outputSubpacket, hashed bool) (length int) {
+ for _, subpacket := range subpackets {
+ if subpacket.hashed == hashed {
+ length += subpacketLengthLength(len(subpacket.contents) + 1)
+ length += 1 // type byte
+ length += len(subpacket.contents)
+ }
+ }
+ return
+}
+
+// serializeSubpackets marshals the given subpackets into to.
+func serializeSubpackets(to []byte, subpackets []outputSubpacket, hashed bool) {
+ for _, subpacket := range subpackets {
+ if subpacket.hashed == hashed {
+ n := serializeSubpacketLength(to, len(subpacket.contents)+1)
+ to[n] = byte(subpacket.subpacketType)
+ to = to[1+n:]
+ n = copy(to, subpacket.contents)
+ to = to[n:]
+ }
+ }
+ return
+}
+
+// KeyExpired returns whether sig is a self-signature of a key that has
+// expired.
+func (sig *Signature) KeyExpired(currentTime time.Time) bool {
+ if sig.KeyLifetimeSecs == nil {
+ return false
+ }
+ expiry := sig.CreationTime.Add(time.Duration(*sig.KeyLifetimeSecs) * time.Second)
+ return currentTime.After(expiry)
+}
+
+// buildHashSuffix constructs the HashSuffix member of sig in preparation for signing.
+func (sig *Signature) buildHashSuffix() (err error) {
+ hashedSubpacketsLen := subpacketsLength(sig.outSubpackets, true)
+
+ var ok bool
+ l := 6 + hashedSubpacketsLen
+ sig.HashSuffix = make([]byte, l+6)
+ sig.HashSuffix[0] = 4
+ sig.HashSuffix[1] = uint8(sig.SigType)
+ sig.HashSuffix[2] = uint8(sig.PubKeyAlgo)
+ sig.HashSuffix[3], ok = s2k.HashToHashId(sig.Hash)
+ if !ok {
+ sig.HashSuffix = nil
+ return errors.InvalidArgumentError("hash cannot be represented in OpenPGP: " + strconv.Itoa(int(sig.Hash)))
+ }
+ sig.HashSuffix[4] = byte(hashedSubpacketsLen >> 8)
+ sig.HashSuffix[5] = byte(hashedSubpacketsLen)
+ serializeSubpackets(sig.HashSuffix[6:l], sig.outSubpackets, true)
+ trailer := sig.HashSuffix[l:]
+ trailer[0] = 4
+ trailer[1] = 0xff
+ trailer[2] = byte(l >> 24)
+ trailer[3] = byte(l >> 16)
+ trailer[4] = byte(l >> 8)
+ trailer[5] = byte(l)
+ return
+}
+
+func (sig *Signature) signPrepareHash(h hash.Hash) (digest []byte, err error) {
+ err = sig.buildHashSuffix()
+ if err != nil {
+ return
+ }
+
+ h.Write(sig.HashSuffix)
+ digest = h.Sum(nil)
+ copy(sig.HashTag[:], digest)
+ return
+}
+
+// Sign signs a message with a private key. The hash, h, must contain
+// the hash of the message to be signed and will be mutated by this function.
+// On success, the signature is stored in sig. Call Serialize to write it out.
+// If config is nil, sensible defaults will be used.
+func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err error) {
+ sig.outSubpackets = sig.buildSubpackets()
+ digest, err := sig.signPrepareHash(h)
+ if err != nil {
+ return
+ }
+
+ switch priv.PubKeyAlgo {
+ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
+ // supports both *rsa.PrivateKey and crypto.Signer
+ sig.RSASignature.bytes, err = priv.PrivateKey.(crypto.Signer).Sign(config.Random(), digest, sig.Hash)
+ sig.RSASignature.bitLength = uint16(8 * len(sig.RSASignature.bytes))
+ case PubKeyAlgoDSA:
+ dsaPriv := priv.PrivateKey.(*dsa.PrivateKey)
+
+ // Need to truncate hashBytes to match FIPS 186-3 section 4.6.
+ subgroupSize := (dsaPriv.Q.BitLen() + 7) / 8
+ if len(digest) > subgroupSize {
+ digest = digest[:subgroupSize]
+ }
+ r, s, err := dsa.Sign(config.Random(), dsaPriv, digest)
+ if err == nil {
+ sig.DSASigR.bytes = r.Bytes()
+ sig.DSASigR.bitLength = uint16(8 * len(sig.DSASigR.bytes))
+ sig.DSASigS.bytes = s.Bytes()
+ sig.DSASigS.bitLength = uint16(8 * len(sig.DSASigS.bytes))
+ }
+ case PubKeyAlgoECDSA:
+ var r, s *big.Int
+ if pk, ok := priv.PrivateKey.(*ecdsa.PrivateKey); ok {
+ // direct support, avoid asn1 wrapping/unwrapping
+ r, s, err = ecdsa.Sign(config.Random(), pk, digest)
+ } else {
+ var b []byte
+ b, err = priv.PrivateKey.(crypto.Signer).Sign(config.Random(), digest, nil)
+ if err == nil {
+ r, s, err = unwrapECDSASig(b)
+ }
+ }
+ if err == nil {
+ sig.ECDSASigR = fromBig(r)
+ sig.ECDSASigS = fromBig(s)
+ }
+ default:
+ err = errors.UnsupportedError("public key algorithm: " + strconv.Itoa(int(sig.PubKeyAlgo)))
+ }
+
+ return
+}
+
+// unwrapECDSASig parses the two integer components of an ASN.1-encoded ECDSA
+// signature.
+func unwrapECDSASig(b []byte) (r, s *big.Int, err error) {
+ var ecsdaSig struct {
+ R, S *big.Int
+ }
+ _, err = asn1.Unmarshal(b, &ecsdaSig)
+ if err != nil {
+ return
+ }
+ return ecsdaSig.R, ecsdaSig.S, nil
+}
+
+// SignUserId computes a signature from priv, asserting that pub is a valid
+// key for the identity id. On success, the signature is stored in sig. Call
+// Serialize to write it out.
+// If config is nil, sensible defaults will be used.
+func (sig *Signature) SignUserId(id string, pub *PublicKey, priv *PrivateKey, config *Config) error {
+ h, err := userIdSignatureHash(id, pub, sig.Hash)
+ if err != nil {
+ return err
+ }
+ return sig.Sign(h, priv, config)
+}
+
+// SignKey computes a signature from priv, asserting that pub is a subkey. On
+// success, the signature is stored in sig. Call Serialize to write it out.
+// If config is nil, sensible defaults will be used.
+func (sig *Signature) SignKey(pub *PublicKey, priv *PrivateKey, config *Config) error {
+ h, err := keySignatureHash(&priv.PublicKey, pub, sig.Hash)
+ if err != nil {
+ return err
+ }
+ return sig.Sign(h, priv, config)
+}
+
+// Serialize marshals sig to w. Sign, SignUserId or SignKey must have been
+// called first.
+func (sig *Signature) Serialize(w io.Writer) (err error) {
+ if len(sig.outSubpackets) == 0 {
+ sig.outSubpackets = sig.rawSubpackets
+ }
+ if sig.RSASignature.bytes == nil && sig.DSASigR.bytes == nil && sig.ECDSASigR.bytes == nil {
+ return errors.InvalidArgumentError("Signature: need to call Sign, SignUserId or SignKey before Serialize")
+ }
+
+ sigLength := 0
+ switch sig.PubKeyAlgo {
+ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
+ sigLength = 2 + len(sig.RSASignature.bytes)
+ case PubKeyAlgoDSA:
+ sigLength = 2 + len(sig.DSASigR.bytes)
+ sigLength += 2 + len(sig.DSASigS.bytes)
+ case PubKeyAlgoECDSA:
+ sigLength = 2 + len(sig.ECDSASigR.bytes)
+ sigLength += 2 + len(sig.ECDSASigS.bytes)
+ default:
+ panic("impossible")
+ }
+
+ unhashedSubpacketsLen := subpacketsLength(sig.outSubpackets, false)
+ length := len(sig.HashSuffix) - 6 /* trailer not included */ +
+ 2 /* length of unhashed subpackets */ + unhashedSubpacketsLen +
+ 2 /* hash tag */ + sigLength
+ err = serializeHeader(w, packetTypeSignature, length)
+ if err != nil {
+ return
+ }
+
+ _, err = w.Write(sig.HashSuffix[:len(sig.HashSuffix)-6])
+ if err != nil {
+ return
+ }
+
+ unhashedSubpackets := make([]byte, 2+unhashedSubpacketsLen)
+ unhashedSubpackets[0] = byte(unhashedSubpacketsLen >> 8)
+ unhashedSubpackets[1] = byte(unhashedSubpacketsLen)
+ serializeSubpackets(unhashedSubpackets[2:], sig.outSubpackets, false)
+
+ _, err = w.Write(unhashedSubpackets)
+ if err != nil {
+ return
+ }
+ _, err = w.Write(sig.HashTag[:])
+ if err != nil {
+ return
+ }
+
+ switch sig.PubKeyAlgo {
+ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
+ err = writeMPIs(w, sig.RSASignature)
+ case PubKeyAlgoDSA:
+ err = writeMPIs(w, sig.DSASigR, sig.DSASigS)
+ case PubKeyAlgoECDSA:
+ err = writeMPIs(w, sig.ECDSASigR, sig.ECDSASigS)
+ default:
+ panic("impossible")
+ }
+ return
+}
+
+// outputSubpacket represents a subpacket to be marshaled.
+type outputSubpacket struct {
+ hashed bool // true if this subpacket is in the hashed area.
+ subpacketType signatureSubpacketType
+ isCritical bool
+ contents []byte
+}
+
+func (sig *Signature) buildSubpackets() (subpackets []outputSubpacket) {
+ creationTime := make([]byte, 4)
+ binary.BigEndian.PutUint32(creationTime, uint32(sig.CreationTime.Unix()))
+ subpackets = append(subpackets, outputSubpacket{true, creationTimeSubpacket, false, creationTime})
+
+ if sig.IssuerKeyId != nil {
+ keyId := make([]byte, 8)
+ binary.BigEndian.PutUint64(keyId, *sig.IssuerKeyId)
+ subpackets = append(subpackets, outputSubpacket{true, issuerSubpacket, false, keyId})
+ }
+
+ if sig.SigLifetimeSecs != nil && *sig.SigLifetimeSecs != 0 {
+ sigLifetime := make([]byte, 4)
+ binary.BigEndian.PutUint32(sigLifetime, *sig.SigLifetimeSecs)
+ subpackets = append(subpackets, outputSubpacket{true, signatureExpirationSubpacket, true, sigLifetime})
+ }
+
+ // Key flags may only appear in self-signatures or certification signatures.
+
+ if sig.FlagsValid {
+ var flags byte
+ if sig.FlagCertify {
+ flags |= KeyFlagCertify
+ }
+ if sig.FlagSign {
+ flags |= KeyFlagSign
+ }
+ if sig.FlagEncryptCommunications {
+ flags |= KeyFlagEncryptCommunications
+ }
+ if sig.FlagEncryptStorage {
+ flags |= KeyFlagEncryptStorage
+ }
+ subpackets = append(subpackets, outputSubpacket{true, keyFlagsSubpacket, false, []byte{flags}})
+ }
+
+ // The following subpackets may only appear in self-signatures
+
+ if sig.KeyLifetimeSecs != nil && *sig.KeyLifetimeSecs != 0 {
+ keyLifetime := make([]byte, 4)
+ binary.BigEndian.PutUint32(keyLifetime, *sig.KeyLifetimeSecs)
+ subpackets = append(subpackets, outputSubpacket{true, keyExpirationSubpacket, true, keyLifetime})
+ }
+
+ if sig.IsPrimaryId != nil && *sig.IsPrimaryId {
+ subpackets = append(subpackets, outputSubpacket{true, primaryUserIdSubpacket, false, []byte{1}})
+ }
+
+ if len(sig.PreferredSymmetric) > 0 {
+ subpackets = append(subpackets, outputSubpacket{true, prefSymmetricAlgosSubpacket, false, sig.PreferredSymmetric})
+ }
+
+ if len(sig.PreferredHash) > 0 {
+ subpackets = append(subpackets, outputSubpacket{true, prefHashAlgosSubpacket, false, sig.PreferredHash})
+ }
+
+ if len(sig.PreferredCompression) > 0 {
+ subpackets = append(subpackets, outputSubpacket{true, prefCompressionSubpacket, false, sig.PreferredCompression})
+ }
+
+ return
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/signature_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/signature_test.go
new file mode 100644
index 000000000..56e761179
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/signature_test.go
@@ -0,0 +1,78 @@
+// Copyright 2011 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 packet
+
+import (
+ "bytes"
+ "crypto"
+ "encoding/hex"
+ "testing"
+)
+
+func TestSignatureRead(t *testing.T) {
+ packet, err := Read(readerFromHex(signatureDataHex))
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ sig, ok := packet.(*Signature)
+ if !ok || sig.SigType != SigTypeBinary || sig.PubKeyAlgo != PubKeyAlgoRSA || sig.Hash != crypto.SHA1 {
+ t.Errorf("failed to parse, got: %#v", packet)
+ }
+}
+
+func TestSignatureReserialize(t *testing.T) {
+ packet, _ := Read(readerFromHex(signatureDataHex))
+ sig := packet.(*Signature)
+ out := new(bytes.Buffer)
+ err := sig.Serialize(out)
+ if err != nil {
+ t.Errorf("error reserializing: %s", err)
+ return
+ }
+
+ expected, _ := hex.DecodeString(signatureDataHex)
+ if !bytes.Equal(expected, out.Bytes()) {
+ t.Errorf("output doesn't match input (got vs expected):\n%s\n%s", hex.Dump(out.Bytes()), hex.Dump(expected))
+ }
+}
+
+func TestSignUserId(t *testing.T) {
+ sig := &Signature{
+ SigType: SigTypeGenericCert,
+ PubKeyAlgo: PubKeyAlgoRSA,
+ Hash: 0, // invalid hash function
+ }
+
+ packet, err := Read(readerFromHex(rsaPkDataHex))
+ if err != nil {
+ t.Fatalf("failed to deserialize public key: %v", err)
+ }
+ pubKey := packet.(*PublicKey)
+
+ packet, err = Read(readerFromHex(privKeyRSAHex))
+ if err != nil {
+ t.Fatalf("failed to deserialize private key: %v", err)
+ }
+ privKey := packet.(*PrivateKey)
+
+ err = sig.SignUserId("", pubKey, privKey, nil)
+ if err == nil {
+ t.Errorf("did not receive an error when expected")
+ }
+
+ sig.Hash = crypto.SHA256
+ err = privKey.Decrypt([]byte("testing"))
+ if err != nil {
+ t.Fatalf("failed to decrypt private key: %v", err)
+ }
+
+ err = sig.SignUserId("", pubKey, privKey, nil)
+ if err != nil {
+ t.Errorf("failed to sign user id: %v", err)
+ }
+}
+
+const signatureDataHex = "c2c05c04000102000605024cb45112000a0910ab105c91af38fb158f8d07ff5596ea368c5efe015bed6e78348c0f033c931d5f2ce5db54ce7f2a7e4b4ad64db758d65a7a71773edeab7ba2a9e0908e6a94a1175edd86c1d843279f045b021a6971a72702fcbd650efc393c5474d5b59a15f96d2eaad4c4c426797e0dcca2803ef41c6ff234d403eec38f31d610c344c06f2401c262f0993b2e66cad8a81ebc4322c723e0d4ba09fe917e8777658307ad8329adacba821420741009dfe87f007759f0982275d028a392c6ed983a0d846f890b36148c7358bdb8a516007fac760261ecd06076813831a36d0459075d1befa245ae7f7fb103d92ca759e9498fe60ef8078a39a3beda510deea251ea9f0a7f0df6ef42060f20780360686f3e400e"
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/signature_v3.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/signature_v3.go
new file mode 100644
index 000000000..6edff8893
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/signature_v3.go
@@ -0,0 +1,146 @@
+// Copyright 2013 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 packet
+
+import (
+ "crypto"
+ "encoding/binary"
+ "fmt"
+ "io"
+ "strconv"
+ "time"
+
+ "golang.org/x/crypto/openpgp/errors"
+ "golang.org/x/crypto/openpgp/s2k"
+)
+
+// SignatureV3 represents older version 3 signatures. These signatures are less secure
+// than version 4 and should not be used to create new signatures. They are included
+// here for backwards compatibility to read and validate with older key material.
+// See RFC 4880, section 5.2.2.
+type SignatureV3 struct {
+ SigType SignatureType
+ CreationTime time.Time
+ IssuerKeyId uint64
+ PubKeyAlgo PublicKeyAlgorithm
+ Hash crypto.Hash
+ HashTag [2]byte
+
+ RSASignature parsedMPI
+ DSASigR, DSASigS parsedMPI
+}
+
+func (sig *SignatureV3) parse(r io.Reader) (err error) {
+ // RFC 4880, section 5.2.2
+ var buf [8]byte
+ if _, err = readFull(r, buf[:1]); err != nil {
+ return
+ }
+ if buf[0] < 2 || buf[0] > 3 {
+ err = errors.UnsupportedError("signature packet version " + strconv.Itoa(int(buf[0])))
+ return
+ }
+ if _, err = readFull(r, buf[:1]); err != nil {
+ return
+ }
+ if buf[0] != 5 {
+ err = errors.UnsupportedError(
+ "invalid hashed material length " + strconv.Itoa(int(buf[0])))
+ return
+ }
+
+ // Read hashed material: signature type + creation time
+ if _, err = readFull(r, buf[:5]); err != nil {
+ return
+ }
+ sig.SigType = SignatureType(buf[0])
+ t := binary.BigEndian.Uint32(buf[1:5])
+ sig.CreationTime = time.Unix(int64(t), 0)
+
+ // Eight-octet Key ID of signer.
+ if _, err = readFull(r, buf[:8]); err != nil {
+ return
+ }
+ sig.IssuerKeyId = binary.BigEndian.Uint64(buf[:])
+
+ // Public-key and hash algorithm
+ if _, err = readFull(r, buf[:2]); err != nil {
+ return
+ }
+ sig.PubKeyAlgo = PublicKeyAlgorithm(buf[0])
+ switch sig.PubKeyAlgo {
+ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA:
+ default:
+ err = errors.UnsupportedError("public key algorithm " + strconv.Itoa(int(sig.PubKeyAlgo)))
+ return
+ }
+ var ok bool
+ if sig.Hash, ok = s2k.HashIdToHash(buf[1]); !ok {
+ return errors.UnsupportedError("hash function " + strconv.Itoa(int(buf[2])))
+ }
+
+ // Two-octet field holding left 16 bits of signed hash value.
+ if _, err = readFull(r, sig.HashTag[:2]); err != nil {
+ return
+ }
+
+ switch sig.PubKeyAlgo {
+ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
+ sig.RSASignature.bytes, sig.RSASignature.bitLength, err = readMPI(r)
+ case PubKeyAlgoDSA:
+ if sig.DSASigR.bytes, sig.DSASigR.bitLength, err = readMPI(r); err != nil {
+ return
+ }
+ sig.DSASigS.bytes, sig.DSASigS.bitLength, err = readMPI(r)
+ default:
+ panic("unreachable")
+ }
+ return
+}
+
+// Serialize marshals sig to w. Sign, SignUserId or SignKey must have been
+// called first.
+func (sig *SignatureV3) Serialize(w io.Writer) (err error) {
+ buf := make([]byte, 8)
+
+ // Write the sig type and creation time
+ buf[0] = byte(sig.SigType)
+ binary.BigEndian.PutUint32(buf[1:5], uint32(sig.CreationTime.Unix()))
+ if _, err = w.Write(buf[:5]); err != nil {
+ return
+ }
+
+ // Write the issuer long key ID
+ binary.BigEndian.PutUint64(buf[:8], sig.IssuerKeyId)
+ if _, err = w.Write(buf[:8]); err != nil {
+ return
+ }
+
+ // Write public key algorithm, hash ID, and hash value
+ buf[0] = byte(sig.PubKeyAlgo)
+ hashId, ok := s2k.HashToHashId(sig.Hash)
+ if !ok {
+ return errors.UnsupportedError(fmt.Sprintf("hash function %v", sig.Hash))
+ }
+ buf[1] = hashId
+ copy(buf[2:4], sig.HashTag[:])
+ if _, err = w.Write(buf[:4]); err != nil {
+ return
+ }
+
+ if sig.RSASignature.bytes == nil && sig.DSASigR.bytes == nil {
+ return errors.InvalidArgumentError("Signature: need to call Sign, SignUserId or SignKey before Serialize")
+ }
+
+ switch sig.PubKeyAlgo {
+ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
+ err = writeMPIs(w, sig.RSASignature)
+ case PubKeyAlgoDSA:
+ err = writeMPIs(w, sig.DSASigR, sig.DSASigS)
+ default:
+ panic("impossible")
+ }
+ return
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/signature_v3_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/signature_v3_test.go
new file mode 100644
index 000000000..ad7b62ac1
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/signature_v3_test.go
@@ -0,0 +1,92 @@
+// Copyright 2013 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 packet
+
+import (
+ "bytes"
+ "crypto"
+ "encoding/hex"
+ "io"
+ "io/ioutil"
+ "testing"
+
+ "golang.org/x/crypto/openpgp/armor"
+)
+
+func TestSignatureV3Read(t *testing.T) {
+ r := v3KeyReader(t)
+ Read(r) // Skip public key
+ Read(r) // Skip uid
+ packet, err := Read(r) // Signature
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ sig, ok := packet.(*SignatureV3)
+ if !ok || sig.SigType != SigTypeGenericCert || sig.PubKeyAlgo != PubKeyAlgoRSA || sig.Hash != crypto.MD5 {
+ t.Errorf("failed to parse, got: %#v", packet)
+ }
+}
+
+func TestSignatureV3Reserialize(t *testing.T) {
+ r := v3KeyReader(t)
+ Read(r) // Skip public key
+ Read(r) // Skip uid
+ packet, err := Read(r)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ sig := packet.(*SignatureV3)
+ out := new(bytes.Buffer)
+ if err = sig.Serialize(out); err != nil {
+ t.Errorf("error reserializing: %s", err)
+ return
+ }
+ expected, err := ioutil.ReadAll(v3KeyReader(t))
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ expected = expected[4+141+4+39:] // See pgpdump offsets below, this is where the sig starts
+ if !bytes.Equal(expected, out.Bytes()) {
+ t.Errorf("output doesn't match input (got vs expected):\n%s\n%s", hex.Dump(out.Bytes()), hex.Dump(expected))
+ }
+}
+
+func v3KeyReader(t *testing.T) io.Reader {
+ armorBlock, err := armor.Decode(bytes.NewBufferString(keySigV3Armor))
+ if err != nil {
+ t.Fatalf("armor Decode failed: %v", err)
+ }
+ return armorBlock.Body
+}
+
+// keySigV3Armor is some V3 public key I found in an SKS dump.
+// Old: Public Key Packet(tag 6)(141 bytes)
+// Ver 4 - new
+// Public key creation time - Fri Sep 16 17:13:54 CDT 1994
+// Pub alg - unknown(pub 0)
+// Unknown public key(pub 0)
+// Old: User ID Packet(tag 13)(39 bytes)
+// User ID - Armin M. Warda <warda@nephilim.ruhr.de>
+// Old: Signature Packet(tag 2)(149 bytes)
+// Ver 4 - new
+// Sig type - unknown(05)
+// Pub alg - ElGamal Encrypt-Only(pub 16)
+// Hash alg - unknown(hash 46)
+// Hashed Sub: unknown(sub 81, critical)(1988 bytes)
+const keySigV3Armor = `-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: SKS 1.0.10
+
+mI0CLnoYogAAAQQA1qwA2SuJwfQ5bCQ6u5t20ulnOtY0gykf7YjiK4LiVeRBwHjGq7v30tGV
+5Qti7qqRW4Ww7CDCJc4sZMFnystucR2vLkXaSoNWoFm4Fg47NiisDdhDezHwbVPW6OpCFNSi
+ZAamtj4QAUBu8j4LswafrJqZqR9336/V3g8Yil2l48kABRG0J0FybWluIE0uIFdhcmRhIDx3
+YXJkYUBuZXBoaWxpbS5ydWhyLmRlPoiVAgUQLok2xwXR6zmeWEiZAQE/DgP/WgxPQh40/Po4
+gSkWZCDAjNdph7zexvAb0CcUWahcwiBIgg3U5ErCx9I5CNVA9U+s8bNrDZwgSIeBzp3KhWUx
+524uhGgm6ZUTOAIKA6CbV6pfqoLpJnRYvXYQU5mIWsNa99wcu2qu18OeEDnztb7aLA6Ra9OF
+YFCbq4EjXRoOrYM=
+=LPjs
+-----END PGP PUBLIC KEY BLOCK-----`
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted.go
new file mode 100644
index 000000000..744c2d2c4
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted.go
@@ -0,0 +1,155 @@
+// Copyright 2011 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 packet
+
+import (
+ "bytes"
+ "crypto/cipher"
+ "io"
+ "strconv"
+
+ "golang.org/x/crypto/openpgp/errors"
+ "golang.org/x/crypto/openpgp/s2k"
+)
+
+// This is the largest session key that we'll support. Since no 512-bit cipher
+// has even been seriously used, this is comfortably large.
+const maxSessionKeySizeInBytes = 64
+
+// SymmetricKeyEncrypted represents a passphrase protected session key. See RFC
+// 4880, section 5.3.
+type SymmetricKeyEncrypted struct {
+ CipherFunc CipherFunction
+ s2k func(out, in []byte)
+ encryptedKey []byte
+}
+
+const symmetricKeyEncryptedVersion = 4
+
+func (ske *SymmetricKeyEncrypted) parse(r io.Reader) error {
+ // RFC 4880, section 5.3.
+ var buf [2]byte
+ if _, err := readFull(r, buf[:]); err != nil {
+ return err
+ }
+ if buf[0] != symmetricKeyEncryptedVersion {
+ return errors.UnsupportedError("SymmetricKeyEncrypted version")
+ }
+ ske.CipherFunc = CipherFunction(buf[1])
+
+ if ske.CipherFunc.KeySize() == 0 {
+ return errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(buf[1])))
+ }
+
+ var err error
+ ske.s2k, err = s2k.Parse(r)
+ if err != nil {
+ return err
+ }
+
+ encryptedKey := make([]byte, maxSessionKeySizeInBytes)
+ // The session key may follow. We just have to try and read to find
+ // out. If it exists then we limit it to maxSessionKeySizeInBytes.
+ n, err := readFull(r, encryptedKey)
+ if err != nil && err != io.ErrUnexpectedEOF {
+ return err
+ }
+
+ if n != 0 {
+ if n == maxSessionKeySizeInBytes {
+ return errors.UnsupportedError("oversized encrypted session key")
+ }
+ ske.encryptedKey = encryptedKey[:n]
+ }
+
+ return nil
+}
+
+// Decrypt attempts to decrypt an encrypted session key and returns the key and
+// the cipher to use when decrypting a subsequent Symmetrically Encrypted Data
+// packet.
+func (ske *SymmetricKeyEncrypted) Decrypt(passphrase []byte) ([]byte, CipherFunction, error) {
+ key := make([]byte, ske.CipherFunc.KeySize())
+ ske.s2k(key, passphrase)
+
+ if len(ske.encryptedKey) == 0 {
+ return key, ske.CipherFunc, nil
+ }
+
+ // the IV is all zeros
+ iv := make([]byte, ske.CipherFunc.blockSize())
+ c := cipher.NewCFBDecrypter(ske.CipherFunc.new(key), iv)
+ plaintextKey := make([]byte, len(ske.encryptedKey))
+ c.XORKeyStream(plaintextKey, ske.encryptedKey)
+ cipherFunc := CipherFunction(plaintextKey[0])
+ if cipherFunc.blockSize() == 0 {
+ return nil, ske.CipherFunc, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(cipherFunc)))
+ }
+ plaintextKey = plaintextKey[1:]
+ if l, cipherKeySize := len(plaintextKey), cipherFunc.KeySize(); l != cipherFunc.KeySize() {
+ return nil, cipherFunc, errors.StructuralError("length of decrypted key (" + strconv.Itoa(l) + ") " +
+ "not equal to cipher keysize (" + strconv.Itoa(cipherKeySize) + ")")
+ }
+ return plaintextKey, cipherFunc, nil
+}
+
+// SerializeSymmetricKeyEncrypted serializes a symmetric key packet to w. The
+// packet contains a random session key, encrypted by a key derived from the
+// given passphrase. The session key is returned and must be passed to
+// SerializeSymmetricallyEncrypted.
+// If config is nil, sensible defaults will be used.
+func SerializeSymmetricKeyEncrypted(w io.Writer, passphrase []byte, config *Config) (key []byte, err error) {
+ cipherFunc := config.Cipher()
+ keySize := cipherFunc.KeySize()
+ if keySize == 0 {
+ return nil, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(cipherFunc)))
+ }
+
+ s2kBuf := new(bytes.Buffer)
+ keyEncryptingKey := make([]byte, keySize)
+ // s2k.Serialize salts and stretches the passphrase, and writes the
+ // resulting key to keyEncryptingKey and the s2k descriptor to s2kBuf.
+ err = s2k.Serialize(s2kBuf, keyEncryptingKey, config.Random(), passphrase, &s2k.Config{Hash: config.Hash(), S2KCount: config.PasswordHashIterations()})
+ if err != nil {
+ return
+ }
+ s2kBytes := s2kBuf.Bytes()
+
+ packetLength := 2 /* header */ + len(s2kBytes) + 1 /* cipher type */ + keySize
+ err = serializeHeader(w, packetTypeSymmetricKeyEncrypted, packetLength)
+ if err != nil {
+ return
+ }
+
+ var buf [2]byte
+ buf[0] = symmetricKeyEncryptedVersion
+ buf[1] = byte(cipherFunc)
+ _, err = w.Write(buf[:])
+ if err != nil {
+ return
+ }
+ _, err = w.Write(s2kBytes)
+ if err != nil {
+ return
+ }
+
+ sessionKey := make([]byte, keySize)
+ _, err = io.ReadFull(config.Random(), sessionKey)
+ if err != nil {
+ return
+ }
+ iv := make([]byte, cipherFunc.blockSize())
+ c := cipher.NewCFBEncrypter(cipherFunc.new(keyEncryptingKey), iv)
+ encryptedCipherAndKey := make([]byte, keySize+1)
+ c.XORKeyStream(encryptedCipherAndKey, buf[1:])
+ c.XORKeyStream(encryptedCipherAndKey[1:], sessionKey)
+ _, err = w.Write(encryptedCipherAndKey)
+ if err != nil {
+ return
+ }
+
+ key = sessionKey
+ return
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted_test.go
new file mode 100644
index 000000000..e1d52c122
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted_test.go
@@ -0,0 +1,117 @@
+// Copyright 2011 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 packet
+
+import (
+ "bytes"
+ "encoding/hex"
+ "io"
+ "io/ioutil"
+ "testing"
+)
+
+func TestSymmetricKeyEncrypted(t *testing.T) {
+ buf := readerFromHex(symmetricallyEncryptedHex)
+ packet, err := Read(buf)
+ if err != nil {
+ t.Errorf("failed to read SymmetricKeyEncrypted: %s", err)
+ return
+ }
+ ske, ok := packet.(*SymmetricKeyEncrypted)
+ if !ok {
+ t.Error("didn't find SymmetricKeyEncrypted packet")
+ return
+ }
+ key, cipherFunc, err := ske.Decrypt([]byte("password"))
+ if err != nil {
+ t.Error(err)
+ return
+ }
+
+ packet, err = Read(buf)
+ if err != nil {
+ t.Errorf("failed to read SymmetricallyEncrypted: %s", err)
+ return
+ }
+ se, ok := packet.(*SymmetricallyEncrypted)
+ if !ok {
+ t.Error("didn't find SymmetricallyEncrypted packet")
+ return
+ }
+ r, err := se.Decrypt(cipherFunc, key)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+
+ contents, err := ioutil.ReadAll(r)
+ if err != nil && err != io.EOF {
+ t.Error(err)
+ return
+ }
+
+ expectedContents, _ := hex.DecodeString(symmetricallyEncryptedContentsHex)
+ if !bytes.Equal(expectedContents, contents) {
+ t.Errorf("bad contents got:%x want:%x", contents, expectedContents)
+ }
+}
+
+const symmetricallyEncryptedHex = "8c0d04030302371a0b38d884f02060c91cf97c9973b8e58e028e9501708ccfe618fb92afef7fa2d80ddadd93cf"
+const symmetricallyEncryptedContentsHex = "cb1062004d14c4df636f6e74656e74732e0a"
+
+func TestSerializeSymmetricKeyEncryptedCiphers(t *testing.T) {
+ tests := [...]struct {
+ cipherFunc CipherFunction
+ name string
+ }{
+ {Cipher3DES, "Cipher3DES"},
+ {CipherCAST5, "CipherCAST5"},
+ {CipherAES128, "CipherAES128"},
+ {CipherAES192, "CipherAES192"},
+ {CipherAES256, "CipherAES256"},
+ }
+
+ for _, test := range tests {
+ var buf bytes.Buffer
+ passphrase := []byte("testing")
+ config := &Config{
+ DefaultCipher: test.cipherFunc,
+ }
+
+ key, err := SerializeSymmetricKeyEncrypted(&buf, passphrase, config)
+ if err != nil {
+ t.Errorf("cipher(%s) failed to serialize: %s", test.name, err)
+ continue
+ }
+
+ p, err := Read(&buf)
+ if err != nil {
+ t.Errorf("cipher(%s) failed to reparse: %s", test.name, err)
+ continue
+ }
+
+ ske, ok := p.(*SymmetricKeyEncrypted)
+ if !ok {
+ t.Errorf("cipher(%s) parsed a different packet type: %#v", test.name, p)
+ continue
+ }
+
+ if ske.CipherFunc != config.DefaultCipher {
+ t.Errorf("cipher(%s) SKE cipher function is %d (expected %d)", test.name, ske.CipherFunc, config.DefaultCipher)
+ }
+ parsedKey, parsedCipherFunc, err := ske.Decrypt(passphrase)
+ if err != nil {
+ t.Errorf("cipher(%s) failed to decrypt reparsed SKE: %s", test.name, err)
+ continue
+ }
+ if !bytes.Equal(key, parsedKey) {
+ t.Errorf("cipher(%s) keys don't match after Decrypt: %x (original) vs %x (parsed)", test.name, key, parsedKey)
+ }
+ if parsedCipherFunc != test.cipherFunc {
+ t.Errorf("cipher(%s) cipher function doesn't match after Decrypt: %d (original) vs %d (parsed)",
+ test.name, test.cipherFunc, parsedCipherFunc)
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go
new file mode 100644
index 000000000..6126030eb
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go
@@ -0,0 +1,290 @@
+// Copyright 2011 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 packet
+
+import (
+ "crypto/cipher"
+ "crypto/sha1"
+ "crypto/subtle"
+ "golang.org/x/crypto/openpgp/errors"
+ "hash"
+ "io"
+ "strconv"
+)
+
+// SymmetricallyEncrypted represents a symmetrically encrypted byte string. The
+// encrypted contents will consist of more OpenPGP packets. See RFC 4880,
+// sections 5.7 and 5.13.
+type SymmetricallyEncrypted struct {
+ MDC bool // true iff this is a type 18 packet and thus has an embedded MAC.
+ contents io.Reader
+ prefix []byte
+}
+
+const symmetricallyEncryptedVersion = 1
+
+func (se *SymmetricallyEncrypted) parse(r io.Reader) error {
+ if se.MDC {
+ // See RFC 4880, section 5.13.
+ var buf [1]byte
+ _, err := readFull(r, buf[:])
+ if err != nil {
+ return err
+ }
+ if buf[0] != symmetricallyEncryptedVersion {
+ return errors.UnsupportedError("unknown SymmetricallyEncrypted version")
+ }
+ }
+ se.contents = r
+ return nil
+}
+
+// Decrypt returns a ReadCloser, from which the decrypted contents of the
+// packet can be read. An incorrect key can, with high probability, be detected
+// immediately and this will result in a KeyIncorrect error being returned.
+func (se *SymmetricallyEncrypted) Decrypt(c CipherFunction, key []byte) (io.ReadCloser, error) {
+ keySize := c.KeySize()
+ if keySize == 0 {
+ return nil, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(c)))
+ }
+ if len(key) != keySize {
+ return nil, errors.InvalidArgumentError("SymmetricallyEncrypted: incorrect key length")
+ }
+
+ if se.prefix == nil {
+ se.prefix = make([]byte, c.blockSize()+2)
+ _, err := readFull(se.contents, se.prefix)
+ if err != nil {
+ return nil, err
+ }
+ } else if len(se.prefix) != c.blockSize()+2 {
+ return nil, errors.InvalidArgumentError("can't try ciphers with different block lengths")
+ }
+
+ ocfbResync := OCFBResync
+ if se.MDC {
+ // MDC packets use a different form of OCFB mode.
+ ocfbResync = OCFBNoResync
+ }
+
+ s := NewOCFBDecrypter(c.new(key), se.prefix, ocfbResync)
+ if s == nil {
+ return nil, errors.ErrKeyIncorrect
+ }
+
+ plaintext := cipher.StreamReader{S: s, R: se.contents}
+
+ if se.MDC {
+ // MDC packets have an embedded hash that we need to check.
+ h := sha1.New()
+ h.Write(se.prefix)
+ return &seMDCReader{in: plaintext, h: h}, nil
+ }
+
+ // Otherwise, we just need to wrap plaintext so that it's a valid ReadCloser.
+ return seReader{plaintext}, nil
+}
+
+// seReader wraps an io.Reader with a no-op Close method.
+type seReader struct {
+ in io.Reader
+}
+
+func (ser seReader) Read(buf []byte) (int, error) {
+ return ser.in.Read(buf)
+}
+
+func (ser seReader) Close() error {
+ return nil
+}
+
+const mdcTrailerSize = 1 /* tag byte */ + 1 /* length byte */ + sha1.Size
+
+// An seMDCReader wraps an io.Reader, maintains a running hash and keeps hold
+// of the most recent 22 bytes (mdcTrailerSize). Upon EOF, those bytes form an
+// MDC packet containing a hash of the previous contents which is checked
+// against the running hash. See RFC 4880, section 5.13.
+type seMDCReader struct {
+ in io.Reader
+ h hash.Hash
+ trailer [mdcTrailerSize]byte
+ scratch [mdcTrailerSize]byte
+ trailerUsed int
+ error bool
+ eof bool
+}
+
+func (ser *seMDCReader) Read(buf []byte) (n int, err error) {
+ if ser.error {
+ err = io.ErrUnexpectedEOF
+ return
+ }
+ if ser.eof {
+ err = io.EOF
+ return
+ }
+
+ // If we haven't yet filled the trailer buffer then we must do that
+ // first.
+ for ser.trailerUsed < mdcTrailerSize {
+ n, err = ser.in.Read(ser.trailer[ser.trailerUsed:])
+ ser.trailerUsed += n
+ if err == io.EOF {
+ if ser.trailerUsed != mdcTrailerSize {
+ n = 0
+ err = io.ErrUnexpectedEOF
+ ser.error = true
+ return
+ }
+ ser.eof = true
+ n = 0
+ return
+ }
+
+ if err != nil {
+ n = 0
+ return
+ }
+ }
+
+ // If it's a short read then we read into a temporary buffer and shift
+ // the data into the caller's buffer.
+ if len(buf) <= mdcTrailerSize {
+ n, err = readFull(ser.in, ser.scratch[:len(buf)])
+ copy(buf, ser.trailer[:n])
+ ser.h.Write(buf[:n])
+ copy(ser.trailer[:], ser.trailer[n:])
+ copy(ser.trailer[mdcTrailerSize-n:], ser.scratch[:])
+ if n < len(buf) {
+ ser.eof = true
+ err = io.EOF
+ }
+ return
+ }
+
+ n, err = ser.in.Read(buf[mdcTrailerSize:])
+ copy(buf, ser.trailer[:])
+ ser.h.Write(buf[:n])
+ copy(ser.trailer[:], buf[n:])
+
+ if err == io.EOF {
+ ser.eof = true
+ }
+ return
+}
+
+// This is a new-format packet tag byte for a type 19 (MDC) packet.
+const mdcPacketTagByte = byte(0x80) | 0x40 | 19
+
+func (ser *seMDCReader) Close() error {
+ if ser.error {
+ return errors.SignatureError("error during reading")
+ }
+
+ for !ser.eof {
+ // We haven't seen EOF so we need to read to the end
+ var buf [1024]byte
+ _, err := ser.Read(buf[:])
+ if err == io.EOF {
+ break
+ }
+ if err != nil {
+ return errors.SignatureError("error during reading")
+ }
+ }
+
+ if ser.trailer[0] != mdcPacketTagByte || ser.trailer[1] != sha1.Size {
+ return errors.SignatureError("MDC packet not found")
+ }
+ ser.h.Write(ser.trailer[:2])
+
+ final := ser.h.Sum(nil)
+ if subtle.ConstantTimeCompare(final, ser.trailer[2:]) != 1 {
+ return errors.SignatureError("hash mismatch")
+ }
+ return nil
+}
+
+// An seMDCWriter writes through to an io.WriteCloser while maintains a running
+// hash of the data written. On close, it emits an MDC packet containing the
+// running hash.
+type seMDCWriter struct {
+ w io.WriteCloser
+ h hash.Hash
+}
+
+func (w *seMDCWriter) Write(buf []byte) (n int, err error) {
+ w.h.Write(buf)
+ return w.w.Write(buf)
+}
+
+func (w *seMDCWriter) Close() (err error) {
+ var buf [mdcTrailerSize]byte
+
+ buf[0] = mdcPacketTagByte
+ buf[1] = sha1.Size
+ w.h.Write(buf[:2])
+ digest := w.h.Sum(nil)
+ copy(buf[2:], digest)
+
+ _, err = w.w.Write(buf[:])
+ if err != nil {
+ return
+ }
+ return w.w.Close()
+}
+
+// noOpCloser is like an ioutil.NopCloser, but for an io.Writer.
+type noOpCloser struct {
+ w io.Writer
+}
+
+func (c noOpCloser) Write(data []byte) (n int, err error) {
+ return c.w.Write(data)
+}
+
+func (c noOpCloser) Close() error {
+ return nil
+}
+
+// SerializeSymmetricallyEncrypted serializes a symmetrically encrypted packet
+// to w and returns a WriteCloser to which the to-be-encrypted packets can be
+// written.
+// If config is nil, sensible defaults will be used.
+func SerializeSymmetricallyEncrypted(w io.Writer, c CipherFunction, key []byte, config *Config) (contents io.WriteCloser, err error) {
+ if c.KeySize() != len(key) {
+ return nil, errors.InvalidArgumentError("SymmetricallyEncrypted.Serialize: bad key length")
+ }
+ writeCloser := noOpCloser{w}
+ ciphertext, err := serializeStreamHeader(writeCloser, packetTypeSymmetricallyEncryptedMDC)
+ if err != nil {
+ return
+ }
+
+ _, err = ciphertext.Write([]byte{symmetricallyEncryptedVersion})
+ if err != nil {
+ return
+ }
+
+ block := c.new(key)
+ blockSize := block.BlockSize()
+ iv := make([]byte, blockSize)
+ _, err = config.Random().Read(iv)
+ if err != nil {
+ return
+ }
+ s, prefix := NewOCFBEncrypter(block, iv, OCFBNoResync)
+ _, err = ciphertext.Write(prefix)
+ if err != nil {
+ return
+ }
+ plaintext := cipher.StreamWriter{S: s, W: ciphertext}
+
+ h := sha1.New()
+ h.Write(iv)
+ h.Write(iv[blockSize-2:])
+ contents = &seMDCWriter{w: plaintext, h: h}
+ return
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted_test.go
new file mode 100644
index 000000000..c5c00f7b9
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted_test.go
@@ -0,0 +1,123 @@
+// Copyright 2011 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 packet
+
+import (
+ "bytes"
+ "crypto/sha1"
+ "encoding/hex"
+ "golang.org/x/crypto/openpgp/errors"
+ "io"
+ "io/ioutil"
+ "testing"
+)
+
+// TestReader wraps a []byte and returns reads of a specific length.
+type testReader struct {
+ data []byte
+ stride int
+}
+
+func (t *testReader) Read(buf []byte) (n int, err error) {
+ n = t.stride
+ if n > len(t.data) {
+ n = len(t.data)
+ }
+ if n > len(buf) {
+ n = len(buf)
+ }
+ copy(buf, t.data)
+ t.data = t.data[n:]
+ if len(t.data) == 0 {
+ err = io.EOF
+ }
+ return
+}
+
+func testMDCReader(t *testing.T) {
+ mdcPlaintext, _ := hex.DecodeString(mdcPlaintextHex)
+
+ for stride := 1; stride < len(mdcPlaintext)/2; stride++ {
+ r := &testReader{data: mdcPlaintext, stride: stride}
+ mdcReader := &seMDCReader{in: r, h: sha1.New()}
+ body, err := ioutil.ReadAll(mdcReader)
+ if err != nil {
+ t.Errorf("stride: %d, error: %s", stride, err)
+ continue
+ }
+ if !bytes.Equal(body, mdcPlaintext[:len(mdcPlaintext)-22]) {
+ t.Errorf("stride: %d: bad contents %x", stride, body)
+ continue
+ }
+
+ err = mdcReader.Close()
+ if err != nil {
+ t.Errorf("stride: %d, error on Close: %s", stride, err)
+ }
+ }
+
+ mdcPlaintext[15] ^= 80
+
+ r := &testReader{data: mdcPlaintext, stride: 2}
+ mdcReader := &seMDCReader{in: r, h: sha1.New()}
+ _, err := ioutil.ReadAll(mdcReader)
+ if err != nil {
+ t.Errorf("corruption test, error: %s", err)
+ return
+ }
+ err = mdcReader.Close()
+ if err == nil {
+ t.Error("corruption: no error")
+ } else if _, ok := err.(*errors.SignatureError); !ok {
+ t.Errorf("corruption: expected SignatureError, got: %s", err)
+ }
+}
+
+const mdcPlaintextHex = "a302789c3b2d93c4e0eb9aba22283539b3203335af44a134afb800c849cb4c4de10200aff40b45d31432c80cb384299a0655966d6939dfdeed1dddf980"
+
+func TestSerialize(t *testing.T) {
+ buf := bytes.NewBuffer(nil)
+ c := CipherAES128
+ key := make([]byte, c.KeySize())
+
+ w, err := SerializeSymmetricallyEncrypted(buf, c, key, nil)
+ if err != nil {
+ t.Errorf("error from SerializeSymmetricallyEncrypted: %s", err)
+ return
+ }
+
+ contents := []byte("hello world\n")
+
+ w.Write(contents)
+ w.Close()
+
+ p, err := Read(buf)
+ if err != nil {
+ t.Errorf("error from Read: %s", err)
+ return
+ }
+
+ se, ok := p.(*SymmetricallyEncrypted)
+ if !ok {
+ t.Errorf("didn't read a *SymmetricallyEncrypted")
+ return
+ }
+
+ r, err := se.Decrypt(c, key)
+ if err != nil {
+ t.Errorf("error from Decrypt: %s", err)
+ return
+ }
+
+ contentsCopy := bytes.NewBuffer(nil)
+ _, err = io.Copy(contentsCopy, r)
+ if err != nil {
+ t.Errorf("error from io.Copy: %s", err)
+ return
+ }
+ if !bytes.Equal(contentsCopy.Bytes(), contents) {
+ t.Errorf("contents not equal got: %x want: %x", contentsCopy.Bytes(), contents)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/userattribute.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/userattribute.go
new file mode 100644
index 000000000..96a2b382a
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/userattribute.go
@@ -0,0 +1,91 @@
+// Copyright 2013 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 packet
+
+import (
+ "bytes"
+ "image"
+ "image/jpeg"
+ "io"
+ "io/ioutil"
+)
+
+const UserAttrImageSubpacket = 1
+
+// UserAttribute is capable of storing other types of data about a user
+// beyond name, email and a text comment. In practice, user attributes are typically used
+// to store a signed thumbnail photo JPEG image of the user.
+// See RFC 4880, section 5.12.
+type UserAttribute struct {
+ Contents []*OpaqueSubpacket
+}
+
+// NewUserAttributePhoto creates a user attribute packet
+// containing the given images.
+func NewUserAttributePhoto(photos ...image.Image) (uat *UserAttribute, err error) {
+ uat = new(UserAttribute)
+ for _, photo := range photos {
+ var buf bytes.Buffer
+ // RFC 4880, Section 5.12.1.
+ data := []byte{
+ 0x10, 0x00, // Little-endian image header length (16 bytes)
+ 0x01, // Image header version 1
+ 0x01, // JPEG
+ 0, 0, 0, 0, // 12 reserved octets, must be all zero.
+ 0, 0, 0, 0,
+ 0, 0, 0, 0}
+ if _, err = buf.Write(data); err != nil {
+ return
+ }
+ if err = jpeg.Encode(&buf, photo, nil); err != nil {
+ return
+ }
+ uat.Contents = append(uat.Contents, &OpaqueSubpacket{
+ SubType: UserAttrImageSubpacket,
+ Contents: buf.Bytes()})
+ }
+ return
+}
+
+// NewUserAttribute creates a new user attribute packet containing the given subpackets.
+func NewUserAttribute(contents ...*OpaqueSubpacket) *UserAttribute {
+ return &UserAttribute{Contents: contents}
+}
+
+func (uat *UserAttribute) parse(r io.Reader) (err error) {
+ // RFC 4880, section 5.13
+ b, err := ioutil.ReadAll(r)
+ if err != nil {
+ return
+ }
+ uat.Contents, err = OpaqueSubpackets(b)
+ return
+}
+
+// Serialize marshals the user attribute to w in the form of an OpenPGP packet, including
+// header.
+func (uat *UserAttribute) Serialize(w io.Writer) (err error) {
+ var buf bytes.Buffer
+ for _, sp := range uat.Contents {
+ sp.Serialize(&buf)
+ }
+ if err = serializeHeader(w, packetTypeUserAttribute, buf.Len()); err != nil {
+ return err
+ }
+ _, err = w.Write(buf.Bytes())
+ return
+}
+
+// ImageData returns zero or more byte slices, each containing
+// JPEG File Interchange Format (JFIF), for each photo in the
+// the user attribute packet.
+func (uat *UserAttribute) ImageData() (imageData [][]byte) {
+ for _, sp := range uat.Contents {
+ if sp.SubType == UserAttrImageSubpacket && len(sp.Contents) > 16 {
+ imageData = append(imageData, sp.Contents[16:])
+ }
+ }
+ return
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/userattribute_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/userattribute_test.go
new file mode 100644
index 000000000..13ca5143c
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/userattribute_test.go
@@ -0,0 +1,109 @@
+// Copyright 2011 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 packet
+
+import (
+ "bytes"
+ "encoding/base64"
+ "image/color"
+ "image/jpeg"
+ "testing"
+)
+
+func TestParseUserAttribute(t *testing.T) {
+ r := base64.NewDecoder(base64.StdEncoding, bytes.NewBufferString(userAttributePacket))
+ for i := 0; i < 2; i++ {
+ p, err := Read(r)
+ if err != nil {
+ t.Fatal(err)
+ }
+ uat := p.(*UserAttribute)
+ imgs := uat.ImageData()
+ if len(imgs) != 1 {
+ t.Errorf("Unexpected number of images in user attribute packet: %d", len(imgs))
+ }
+ if len(imgs[0]) != 3395 {
+ t.Errorf("Unexpected JPEG image size: %d", len(imgs[0]))
+ }
+ img, err := jpeg.Decode(bytes.NewBuffer(imgs[0]))
+ if err != nil {
+ t.Errorf("Error decoding JPEG image: %v", err)
+ }
+ // A pixel in my right eye.
+ pixel := color.NRGBAModel.Convert(img.At(56, 36))
+ ref := color.NRGBA{R: 157, G: 128, B: 124, A: 255}
+ if pixel != ref {
+ t.Errorf("Unexpected pixel color: %v", pixel)
+ }
+ w := bytes.NewBuffer(nil)
+ err = uat.Serialize(w)
+ if err != nil {
+ t.Errorf("Error writing user attribute: %v", err)
+ }
+ r = bytes.NewBuffer(w.Bytes())
+ }
+}
+
+const userAttributePacket = `
+0cyWzJQBEAABAQAAAAAAAAAAAAAAAP/Y/+AAEEpGSUYAAQIAAAEAAQAA/9sAQwAFAwQEBAMFBAQE
+BQUFBgcMCAcHBwcPCgsJDBEPEhIRDxEQExYcFxMUGhUQERghGBocHR8fHxMXIiQiHiQcHh8e/9sA
+QwEFBQUHBgcOCAgOHhQRFB4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4e
+Hh4eHh4eHh4e/8AAEQgAZABkAwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYH
+CAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHw
+JDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6
+g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk
+5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIB
+AgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEX
+GBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKT
+lJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX2
+9/j5+v/aAAwDAQACEQMRAD8A5uGP06VehQ4pIox04q5EnHSvAep+hIIl4zVuMHGPWmRrUWtalaaN
+pU2oXsgSGJSxPr6ClvoitErs0Itqjc7BQOpPAFYmrfEnwjojtHNqaXEynBjtx5hH4jj9a8B8d+Od
+W8UXZjWR4LJT+7t0Jwfc+prnIdO1CWZEW2mZ3HyDactXXDB3V5s8evm1namj6r0H4weCLtxG+ova
+ueP30RA/MV6not1bX0Ed1ZzxzwyDKvGwZSPqK+Ff+ES8R8t/ZV2oHUmM10Hgbxp4m8BatEfNnWBH
+/eWshOxx9Kmpg4te49RUM1kn+8Wh9zQ4P1FaMC7l465rjPh14y0fxnoseoaXOpfaPOgJ+eI98j09
+67W19M15bi4uzPSqTU480WXkjZkAyAR61DPE6OCSOalWRRgZxjvTb598sfU4FBwx5uY4T4feIm8P
+TeJbAgc65NIM+8cX+FFeLfF3Vr3SfiNrMFrMypJMJcDPUqP8KK+kpVFyLU+ar037SXqX4hxVpMY7
+1UhPpVlT2rybKx9smWYz3NeH/EDVLzxt40j8O6bITaQybPlbKkjq39K9O8fasdH8IahfKxWQRFIy
+Ou9uB/OuE/Z/0y3j1d9TuyoZCMs5xjuea1pLli5nn46q240l13PcfhN8EvDNtpcEl/CklyVBLuMk
+mvU/Dfwo0BL/AO13FjEDD/qyV7Vn+CvGPg8zRpJrVm8ikLtEg6+1ew2dxZ3EQaJgysuQPasH7eXW
+1zzsbVhT92kk/PsYieEND+zlPs6c/wCyAPyryH4wfCPRtW0u6j+xRLOxLxSoADkDpXY+MPjJ4c0S
+9k082d3O8ZKkxw5XI96ytK+IGk+IpFjRpod+Qq3C7QT6A1E6NenaXbqRg6rlLlqS0fRnxjpd1r/w
+w8afa7GWRPKbZLGeBKmeVNfZngLxNaeKfDdprVjxHcLlkJ5Vh1H5185/tDad9h8XOsqAw3Cb0cjq
+CfX61P8AsveKf7L8T3fhe5nxa3g324YniQdh9R/KuivTdSmp9TXB1/Z1nRlsfU249QBx1pWfcwI7
+Cq6u2Ovamb9rYz16V5x7Psz5q/aJhZfibcupIElvE3H+7j+lFbXx9szP45jlUfeso8/99OKK9elL
+3EeNVopzZVharCtxVRGGMk02S5JyFOB69zWTieypnL/GksfB+0cr9oQt69awPhPpD69Y3Ky3DWth
+CWluGU4LAdq3vibGs/g68BJygVxjrwRW5+ztoRv/AAs8EeCZnO/J/hzz/Kumi4wp3kePjlOdZKPY
+ml8Mvo6WM9ppi7J0EkQYMzkb1X0wW+bJHGACa+ivg14huZPCkjXUO6SImIYOQAP6UQ2sGneHmiWF
+CYoSAAuM8etXfhBpMr+EZ3SSNRcMx6ZxWdes6ytBGSwkMNFuo7pnP614Ut9Zn1C4uLySKcwObGFA
+Qnm4+XcR71h+CfDHiKCQWuv2YWFtw+bBZQD8rcE8n2Ney+GbGGQSM6I7xvtI681rXdp8hKRRp6t3
+FYPE1VDlsY1nQjWdl+J8w/tOeDZZ/AMd/EGefTHyxxyYjwfyODXg3waRh8UtEcFh+8Jb8FNfZPxh
+Ak8J6nbPIsiyW7LnseK+Ofh99ptPHFnf2lu0y2twGcKuSEPB/Q1WHk50miq1o14TXU+xop+On61H
+NMC6Nis1LgsAcUTSt1APFcXJZn0EqmhyvxA037friTYziBV6f7Tf40Vr3k4aXLx5OMZIzRXZB2ik
+efJXbPHJJcnaD9aN2R1qoGO8/WkuLlIV+YjdjpXSonQ5lTxfiTwzqCnkeQxx9BWx+zPrQsrBFYja
+zEfrXL6lfie3khcjY6lSPUGud+G3iA6FrY0uQ/KJsA9gCa0jSvFpnBi6tpKSPu++nsIfDFxeXciR
+qIicscY4rxTwB8RUkn1axsPEf2LTYx85kTGzqCUP8VcJ47+JOs+I0Hhq1njjt/ufIeSvq1VtE+Gs
+eoaUbSHUrkHdu3WtuX5Ix81XRh7OL5jirVpV5Whdn0F8C/iX4auVn0i612T7bASoe8wjTAd89K9g
+vtSt5NMa4t5lkRhgOh3Dn6V8aaz8KZrIR3OlQ6r56LySmSxxz06Vo/CHx34h0rxBP4XvJ5AjK2RP
+nEbAEj6ZxjPrWM6fMmoswqJxqJ1VZnqHxn1NLPwveqWHmNC2BnnNcD8DfDkGi+CH1m+ijN1qMzNA
+4GSIiAMf+hVxPxU8Tapc3c0F9MGCn5GU5BX0Pau3+HmrT3XgXSIJCBHDGdgAx1NYSpezha52Yauq
+1dya2Wh2onAIwTj1p0lxxWWLkhRyCKWa5O3ORXOos9KVQluZm83j0oqi84JyWH50Vdmc7ep43d3I
+t1Z2Iz2FYdxeSTsxyRnvTdVuDNcNluM9KrKcg817NOnZGNbEXdkNckjrXGeIIprPxFFdRHAlIwem
+COtdmxrG8Q2cd/ZNExw45RvQ1bVjim+dWNzw7eaTD4mN3dndCQCo6hmI5zXpj/Ea/wBHjkh0kwRW
+xXEfl4yTxXzXZalJDL9nuWKMmRnHcV2Hh3WreCyYXW2SWQhd5P3F6n+lS43d2cTm6d7Ox9EWPxH1
+ODQxPqWpCaSU/ukUc4z3/WvKW8UhviAdaMewYZG98gj9c1ymoa8LyWOJHwkTDaVPb0qpr+q2m6Nb
+cfvNo349az9mou9iZVXNWbub3jm98/Vza2ReV7lsJg/e3dsV654UR9N0K0sZP9ZDGFbHr3rzL4P+
+H7rXfEEWr3I3W1qf3IYdW9fwqDxf4k8UeH/G95p08kscHmk25dPlZT0we9YTj7SXKjpw1aNG8mj3
+FLv5ccU959ycnmvKPDnxB82YQarGsZPAlTp+IrvIr1ZIgySKwIyCOhFYTpyg9T0qWIhVV4svzPvf
+IdhgY4orPachj81FRdmtzxqdiZmJ9aQEgdqZcPtmbJ71DJcAZ5r20kkeXJtsfPIQDwPzrG1a+S3i
+LyHAHvmp7y7HOD1rlNdm+1T7Acovf3o+J2RMpezjzMvrob67pX9o2ShZlYgg/wAWKxZLLWLZ/Ke3
+mVh14yK9M+BMC3dre2ko3LHKCB7EV7EngeGQJdQ7HyBkMKS0djgq1W3c+XtK03U522RwzsTwNiEk
+ntXoHgf4calql9El/G8UZbLfLyfr7V9FeGvh+s+0Lbxxcglu2K1NW1nwN4Gk/wBLuI57tV5jjwzE
+/QVNS+0dWYRqNvXRFv4eeCodKsY1ggVIY1G3K4z714h+1Jqul3GpwaXYeXJLbzgyyrg4b+6D+HNb
+vjz436zq9m+naHF/ZdkeGfOZXH17V4Vqt2b29K+ZuOc5bnce5zWdPBShL2lTfojSeJhy+zp/NjVz
+1Bwa6DSfFGq6fbJFDKrov8DjPFcu97ZxsUe4jVhwVJ5Bpp1mwQiLewJPXacVq6fNpYyjOUXdHoKf
+EG8VQHsInbuVcgflRXnt5fIs2FYHgcgUVi8LG+xusdW/mN7U2KgEVkTzPt60UVfQ9eHxGHrV1MGi
+iD4V25x1qvdgLAMd6KK0pbHm4x++dp8FtUubLxJ5EIjMc+A4Za+qfD8pe1JZVOBmiinW3RyRPMfi
+R8QPE638+k2l6LK0Hylbddhb6nOa80mlkcmWR2kcnlnOSaKK7qCXKcNdu5narcSrAoBxvODWJIga
+VckjDdqKKwq/EaQ0gUdbjQ6mr7QGBUcd6tPBC6gtGpOOuKKKie5qn7qIpEXd0HSiiimSf//Z`
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/userid.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/userid.go
new file mode 100644
index 000000000..d6bea7d4a
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/userid.go
@@ -0,0 +1,160 @@
+// Copyright 2011 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 packet
+
+import (
+ "io"
+ "io/ioutil"
+ "strings"
+)
+
+// UserId contains text that is intended to represent the name and email
+// address of the key holder. See RFC 4880, section 5.11. By convention, this
+// takes the form "Full Name (Comment) <email@example.com>"
+type UserId struct {
+ Id string // By convention, this takes the form "Full Name (Comment) <email@example.com>" which is split out in the fields below.
+
+ Name, Comment, Email string
+}
+
+func hasInvalidCharacters(s string) bool {
+ for _, c := range s {
+ switch c {
+ case '(', ')', '<', '>', 0:
+ return true
+ }
+ }
+ return false
+}
+
+// NewUserId returns a UserId or nil if any of the arguments contain invalid
+// characters. The invalid characters are '\x00', '(', ')', '<' and '>'
+func NewUserId(name, comment, email string) *UserId {
+ // RFC 4880 doesn't deal with the structure of userid strings; the
+ // name, comment and email form is just a convention. However, there's
+ // no convention about escaping the metacharacters and GPG just refuses
+ // to create user ids where, say, the name contains a '('. We mirror
+ // this behaviour.
+
+ if hasInvalidCharacters(name) || hasInvalidCharacters(comment) || hasInvalidCharacters(email) {
+ return nil
+ }
+
+ uid := new(UserId)
+ uid.Name, uid.Comment, uid.Email = name, comment, email
+ uid.Id = name
+ if len(comment) > 0 {
+ if len(uid.Id) > 0 {
+ uid.Id += " "
+ }
+ uid.Id += "("
+ uid.Id += comment
+ uid.Id += ")"
+ }
+ if len(email) > 0 {
+ if len(uid.Id) > 0 {
+ uid.Id += " "
+ }
+ uid.Id += "<"
+ uid.Id += email
+ uid.Id += ">"
+ }
+ return uid
+}
+
+func (uid *UserId) parse(r io.Reader) (err error) {
+ // RFC 4880, section 5.11
+ b, err := ioutil.ReadAll(r)
+ if err != nil {
+ return
+ }
+ uid.Id = string(b)
+ uid.Name, uid.Comment, uid.Email = parseUserId(uid.Id)
+ return
+}
+
+// Serialize marshals uid to w in the form of an OpenPGP packet, including
+// header.
+func (uid *UserId) Serialize(w io.Writer) error {
+ err := serializeHeader(w, packetTypeUserId, len(uid.Id))
+ if err != nil {
+ return err
+ }
+ _, err = w.Write([]byte(uid.Id))
+ return err
+}
+
+// parseUserId extracts the name, comment and email from a user id string that
+// is formatted as "Full Name (Comment) <email@example.com>".
+func parseUserId(id string) (name, comment, email string) {
+ var n, c, e struct {
+ start, end int
+ }
+ var state int
+
+ for offset, rune := range id {
+ switch state {
+ case 0:
+ // Entering name
+ n.start = offset
+ state = 1
+ fallthrough
+ case 1:
+ // In name
+ if rune == '(' {
+ state = 2
+ n.end = offset
+ } else if rune == '<' {
+ state = 5
+ n.end = offset
+ }
+ case 2:
+ // Entering comment
+ c.start = offset
+ state = 3
+ fallthrough
+ case 3:
+ // In comment
+ if rune == ')' {
+ state = 4
+ c.end = offset
+ }
+ case 4:
+ // Between comment and email
+ if rune == '<' {
+ state = 5
+ }
+ case 5:
+ // Entering email
+ e.start = offset
+ state = 6
+ fallthrough
+ case 6:
+ // In email
+ if rune == '>' {
+ state = 7
+ e.end = offset
+ }
+ default:
+ // After email
+ }
+ }
+ switch state {
+ case 1:
+ // ended in the name
+ n.end = len(id)
+ case 3:
+ // ended in comment
+ c.end = len(id)
+ case 6:
+ // ended in email
+ e.end = len(id)
+ }
+
+ name = strings.TrimSpace(id[n.start:n.end])
+ comment = strings.TrimSpace(id[c.start:c.end])
+ email = strings.TrimSpace(id[e.start:e.end])
+ return
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/userid_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/userid_test.go
new file mode 100644
index 000000000..296819389
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/packet/userid_test.go
@@ -0,0 +1,87 @@
+// Copyright 2011 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 packet
+
+import (
+ "testing"
+)
+
+var userIdTests = []struct {
+ id string
+ name, comment, email string
+}{
+ {"", "", "", ""},
+ {"John Smith", "John Smith", "", ""},
+ {"John Smith ()", "John Smith", "", ""},
+ {"John Smith () <>", "John Smith", "", ""},
+ {"(comment", "", "comment", ""},
+ {"(comment)", "", "comment", ""},
+ {"<email", "", "", "email"},
+ {"<email> sdfk", "", "", "email"},
+ {" John Smith ( Comment ) asdkflj < email > lksdfj", "John Smith", "Comment", "email"},
+ {" John Smith < email > lksdfj", "John Smith", "", "email"},
+ {"(<foo", "", "<foo", ""},
+ {"René Descartes (العربي)", "René Descartes", "العربي", ""},
+}
+
+func TestParseUserId(t *testing.T) {
+ for i, test := range userIdTests {
+ name, comment, email := parseUserId(test.id)
+ if name != test.name {
+ t.Errorf("%d: name mismatch got:%s want:%s", i, name, test.name)
+ }
+ if comment != test.comment {
+ t.Errorf("%d: comment mismatch got:%s want:%s", i, comment, test.comment)
+ }
+ if email != test.email {
+ t.Errorf("%d: email mismatch got:%s want:%s", i, email, test.email)
+ }
+ }
+}
+
+var newUserIdTests = []struct {
+ name, comment, email, id string
+}{
+ {"foo", "", "", "foo"},
+ {"", "bar", "", "(bar)"},
+ {"", "", "baz", "<baz>"},
+ {"foo", "bar", "", "foo (bar)"},
+ {"foo", "", "baz", "foo <baz>"},
+ {"", "bar", "baz", "(bar) <baz>"},
+ {"foo", "bar", "baz", "foo (bar) <baz>"},
+}
+
+func TestNewUserId(t *testing.T) {
+ for i, test := range newUserIdTests {
+ uid := NewUserId(test.name, test.comment, test.email)
+ if uid == nil {
+ t.Errorf("#%d: returned nil", i)
+ continue
+ }
+ if uid.Id != test.id {
+ t.Errorf("#%d: got '%s', want '%s'", i, uid.Id, test.id)
+ }
+ }
+}
+
+var invalidNewUserIdTests = []struct {
+ name, comment, email string
+}{
+ {"foo(", "", ""},
+ {"foo<", "", ""},
+ {"", "bar)", ""},
+ {"", "bar<", ""},
+ {"", "", "baz>"},
+ {"", "", "baz)"},
+ {"", "", "baz\x00"},
+}
+
+func TestNewUserIdWithInvalidInput(t *testing.T) {
+ for i, test := range invalidNewUserIdTests {
+ if uid := NewUserId(test.name, test.comment, test.email); uid != nil {
+ t.Errorf("#%d: returned non-nil value: %#v", i, uid)
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/read.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/read.go
new file mode 100644
index 000000000..6ec664f44
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/read.go
@@ -0,0 +1,442 @@
+// Copyright 2011 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 openpgp implements high level operations on OpenPGP messages.
+package openpgp // import "golang.org/x/crypto/openpgp"
+
+import (
+ "crypto"
+ _ "crypto/sha256"
+ "hash"
+ "io"
+ "strconv"
+
+ "golang.org/x/crypto/openpgp/armor"
+ "golang.org/x/crypto/openpgp/errors"
+ "golang.org/x/crypto/openpgp/packet"
+)
+
+// SignatureType is the armor type for a PGP signature.
+var SignatureType = "PGP SIGNATURE"
+
+// readArmored reads an armored block with the given type.
+func readArmored(r io.Reader, expectedType string) (body io.Reader, err error) {
+ block, err := armor.Decode(r)
+ if err != nil {
+ return
+ }
+
+ if block.Type != expectedType {
+ return nil, errors.InvalidArgumentError("expected '" + expectedType + "', got: " + block.Type)
+ }
+
+ return block.Body, nil
+}
+
+// MessageDetails contains the result of parsing an OpenPGP encrypted and/or
+// signed message.
+type MessageDetails struct {
+ IsEncrypted bool // true if the message was encrypted.
+ EncryptedToKeyIds []uint64 // the list of recipient key ids.
+ IsSymmetricallyEncrypted bool // true if a passphrase could have decrypted the message.
+ DecryptedWith Key // the private key used to decrypt the message, if any.
+ IsSigned bool // true if the message is signed.
+ SignedByKeyId uint64 // the key id of the signer, if any.
+ SignedBy *Key // the key of the signer, if available.
+ LiteralData *packet.LiteralData // the metadata of the contents
+ UnverifiedBody io.Reader // the contents of the message.
+
+ // If IsSigned is true and SignedBy is non-zero then the signature will
+ // be verified as UnverifiedBody is read. The signature cannot be
+ // checked until the whole of UnverifiedBody is read so UnverifiedBody
+ // must be consumed until EOF before the data can be trusted. Even if a
+ // message isn't signed (or the signer is unknown) the data may contain
+ // an authentication code that is only checked once UnverifiedBody has
+ // been consumed. Once EOF has been seen, the following fields are
+ // valid. (An authentication code failure is reported as a
+ // SignatureError error when reading from UnverifiedBody.)
+ SignatureError error // nil if the signature is good.
+ Signature *packet.Signature // the signature packet itself, if v4 (default)
+ SignatureV3 *packet.SignatureV3 // the signature packet if it is a v2 or v3 signature
+
+ decrypted io.ReadCloser
+}
+
+// A PromptFunction is used as a callback by functions that may need to decrypt
+// a private key, or prompt for a passphrase. It is called with a list of
+// acceptable, encrypted private keys and a boolean that indicates whether a
+// passphrase is usable. It should either decrypt a private key or return a
+// passphrase to try. If the decrypted private key or given passphrase isn't
+// correct, the function will be called again, forever. Any error returned will
+// be passed up.
+type PromptFunction func(keys []Key, symmetric bool) ([]byte, error)
+
+// A keyEnvelopePair is used to store a private key with the envelope that
+// contains a symmetric key, encrypted with that key.
+type keyEnvelopePair struct {
+ key Key
+ encryptedKey *packet.EncryptedKey
+}
+
+// ReadMessage parses an OpenPGP message that may be signed and/or encrypted.
+// The given KeyRing should contain both public keys (for signature
+// verification) and, possibly encrypted, private keys for decrypting.
+// If config is nil, sensible defaults will be used.
+func ReadMessage(r io.Reader, keyring KeyRing, prompt PromptFunction, config *packet.Config) (md *MessageDetails, err error) {
+ var p packet.Packet
+
+ var symKeys []*packet.SymmetricKeyEncrypted
+ var pubKeys []keyEnvelopePair
+ var se *packet.SymmetricallyEncrypted
+
+ packets := packet.NewReader(r)
+ md = new(MessageDetails)
+ md.IsEncrypted = true
+
+ // The message, if encrypted, starts with a number of packets
+ // containing an encrypted decryption key. The decryption key is either
+ // encrypted to a public key, or with a passphrase. This loop
+ // collects these packets.
+ParsePackets:
+ for {
+ p, err = packets.Next()
+ if err != nil {
+ return nil, err
+ }
+ switch p := p.(type) {
+ case *packet.SymmetricKeyEncrypted:
+ // This packet contains the decryption key encrypted with a passphrase.
+ md.IsSymmetricallyEncrypted = true
+ symKeys = append(symKeys, p)
+ case *packet.EncryptedKey:
+ // This packet contains the decryption key encrypted to a public key.
+ md.EncryptedToKeyIds = append(md.EncryptedToKeyIds, p.KeyId)
+ switch p.Algo {
+ case packet.PubKeyAlgoRSA, packet.PubKeyAlgoRSAEncryptOnly, packet.PubKeyAlgoElGamal:
+ break
+ default:
+ continue
+ }
+ var keys []Key
+ if p.KeyId == 0 {
+ keys = keyring.DecryptionKeys()
+ } else {
+ keys = keyring.KeysById(p.KeyId)
+ }
+ for _, k := range keys {
+ pubKeys = append(pubKeys, keyEnvelopePair{k, p})
+ }
+ case *packet.SymmetricallyEncrypted:
+ se = p
+ break ParsePackets
+ case *packet.Compressed, *packet.LiteralData, *packet.OnePassSignature:
+ // This message isn't encrypted.
+ if len(symKeys) != 0 || len(pubKeys) != 0 {
+ return nil, errors.StructuralError("key material not followed by encrypted message")
+ }
+ packets.Unread(p)
+ return readSignedMessage(packets, nil, keyring)
+ }
+ }
+
+ var candidates []Key
+ var decrypted io.ReadCloser
+
+ // Now that we have the list of encrypted keys we need to decrypt at
+ // least one of them or, if we cannot, we need to call the prompt
+ // function so that it can decrypt a key or give us a passphrase.
+FindKey:
+ for {
+ // See if any of the keys already have a private key available
+ candidates = candidates[:0]
+ candidateFingerprints := make(map[string]bool)
+
+ for _, pk := range pubKeys {
+ if pk.key.PrivateKey == nil {
+ continue
+ }
+ if !pk.key.PrivateKey.Encrypted {
+ if len(pk.encryptedKey.Key) == 0 {
+ pk.encryptedKey.Decrypt(pk.key.PrivateKey, config)
+ }
+ if len(pk.encryptedKey.Key) == 0 {
+ continue
+ }
+ decrypted, err = se.Decrypt(pk.encryptedKey.CipherFunc, pk.encryptedKey.Key)
+ if err != nil && err != errors.ErrKeyIncorrect {
+ return nil, err
+ }
+ if decrypted != nil {
+ md.DecryptedWith = pk.key
+ break FindKey
+ }
+ } else {
+ fpr := string(pk.key.PublicKey.Fingerprint[:])
+ if v := candidateFingerprints[fpr]; v {
+ continue
+ }
+ candidates = append(candidates, pk.key)
+ candidateFingerprints[fpr] = true
+ }
+ }
+
+ if len(candidates) == 0 && len(symKeys) == 0 {
+ return nil, errors.ErrKeyIncorrect
+ }
+
+ if prompt == nil {
+ return nil, errors.ErrKeyIncorrect
+ }
+
+ passphrase, err := prompt(candidates, len(symKeys) != 0)
+ if err != nil {
+ return nil, err
+ }
+
+ // Try the symmetric passphrase first
+ if len(symKeys) != 0 && passphrase != nil {
+ for _, s := range symKeys {
+ key, cipherFunc, err := s.Decrypt(passphrase)
+ if err == nil {
+ decrypted, err = se.Decrypt(cipherFunc, key)
+ if err != nil && err != errors.ErrKeyIncorrect {
+ return nil, err
+ }
+ if decrypted != nil {
+ break FindKey
+ }
+ }
+
+ }
+ }
+ }
+
+ md.decrypted = decrypted
+ if err := packets.Push(decrypted); err != nil {
+ return nil, err
+ }
+ return readSignedMessage(packets, md, keyring)
+}
+
+// readSignedMessage reads a possibly signed message if mdin is non-zero then
+// that structure is updated and returned. Otherwise a fresh MessageDetails is
+// used.
+func readSignedMessage(packets *packet.Reader, mdin *MessageDetails, keyring KeyRing) (md *MessageDetails, err error) {
+ if mdin == nil {
+ mdin = new(MessageDetails)
+ }
+ md = mdin
+
+ var p packet.Packet
+ var h hash.Hash
+ var wrappedHash hash.Hash
+FindLiteralData:
+ for {
+ p, err = packets.Next()
+ if err != nil {
+ return nil, err
+ }
+ switch p := p.(type) {
+ case *packet.Compressed:
+ if err := packets.Push(p.Body); err != nil {
+ return nil, err
+ }
+ case *packet.OnePassSignature:
+ if !p.IsLast {
+ return nil, errors.UnsupportedError("nested signatures")
+ }
+
+ h, wrappedHash, err = hashForSignature(p.Hash, p.SigType)
+ if err != nil {
+ md = nil
+ return
+ }
+
+ md.IsSigned = true
+ md.SignedByKeyId = p.KeyId
+ keys := keyring.KeysByIdUsage(p.KeyId, packet.KeyFlagSign)
+ if len(keys) > 0 {
+ md.SignedBy = &keys[0]
+ }
+ case *packet.LiteralData:
+ md.LiteralData = p
+ break FindLiteralData
+ }
+ }
+
+ if md.SignedBy != nil {
+ md.UnverifiedBody = &signatureCheckReader{packets, h, wrappedHash, md}
+ } else if md.decrypted != nil {
+ md.UnverifiedBody = checkReader{md}
+ } else {
+ md.UnverifiedBody = md.LiteralData.Body
+ }
+
+ return md, nil
+}
+
+// hashForSignature returns a pair of hashes that can be used to verify a
+// signature. The signature may specify that the contents of the signed message
+// should be preprocessed (i.e. to normalize line endings). Thus this function
+// returns two hashes. The second should be used to hash the message itself and
+// performs any needed preprocessing.
+func hashForSignature(hashId crypto.Hash, sigType packet.SignatureType) (hash.Hash, hash.Hash, error) {
+ if !hashId.Available() {
+ return nil, nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hashId)))
+ }
+ h := hashId.New()
+
+ switch sigType {
+ case packet.SigTypeBinary:
+ return h, h, nil
+ case packet.SigTypeText:
+ return h, NewCanonicalTextHash(h), nil
+ }
+
+ return nil, nil, errors.UnsupportedError("unsupported signature type: " + strconv.Itoa(int(sigType)))
+}
+
+// checkReader wraps an io.Reader from a LiteralData packet. When it sees EOF
+// it closes the ReadCloser from any SymmetricallyEncrypted packet to trigger
+// MDC checks.
+type checkReader struct {
+ md *MessageDetails
+}
+
+func (cr checkReader) Read(buf []byte) (n int, err error) {
+ n, err = cr.md.LiteralData.Body.Read(buf)
+ if err == io.EOF {
+ mdcErr := cr.md.decrypted.Close()
+ if mdcErr != nil {
+ err = mdcErr
+ }
+ }
+ return
+}
+
+// signatureCheckReader wraps an io.Reader from a LiteralData packet and hashes
+// the data as it is read. When it sees an EOF from the underlying io.Reader
+// it parses and checks a trailing Signature packet and triggers any MDC checks.
+type signatureCheckReader struct {
+ packets *packet.Reader
+ h, wrappedHash hash.Hash
+ md *MessageDetails
+}
+
+func (scr *signatureCheckReader) Read(buf []byte) (n int, err error) {
+ n, err = scr.md.LiteralData.Body.Read(buf)
+ scr.wrappedHash.Write(buf[:n])
+ if err == io.EOF {
+ var p packet.Packet
+ p, scr.md.SignatureError = scr.packets.Next()
+ if scr.md.SignatureError != nil {
+ return
+ }
+
+ var ok bool
+ if scr.md.Signature, ok = p.(*packet.Signature); ok {
+ scr.md.SignatureError = scr.md.SignedBy.PublicKey.VerifySignature(scr.h, scr.md.Signature)
+ } else if scr.md.SignatureV3, ok = p.(*packet.SignatureV3); ok {
+ scr.md.SignatureError = scr.md.SignedBy.PublicKey.VerifySignatureV3(scr.h, scr.md.SignatureV3)
+ } else {
+ scr.md.SignatureError = errors.StructuralError("LiteralData not followed by Signature")
+ return
+ }
+
+ // The SymmetricallyEncrypted packet, if any, might have an
+ // unsigned hash of its own. In order to check this we need to
+ // close that Reader.
+ if scr.md.decrypted != nil {
+ mdcErr := scr.md.decrypted.Close()
+ if mdcErr != nil {
+ err = mdcErr
+ }
+ }
+ }
+ return
+}
+
+// CheckDetachedSignature takes a signed file and a detached signature and
+// returns the signer if the signature is valid. If the signer isn't known,
+// ErrUnknownIssuer is returned.
+func CheckDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signer *Entity, err error) {
+ var issuerKeyId uint64
+ var hashFunc crypto.Hash
+ var sigType packet.SignatureType
+ var keys []Key
+ var p packet.Packet
+
+ packets := packet.NewReader(signature)
+ for {
+ p, err = packets.Next()
+ if err == io.EOF {
+ return nil, errors.ErrUnknownIssuer
+ }
+ if err != nil {
+ return nil, err
+ }
+
+ switch sig := p.(type) {
+ case *packet.Signature:
+ if sig.IssuerKeyId == nil {
+ return nil, errors.StructuralError("signature doesn't have an issuer")
+ }
+ issuerKeyId = *sig.IssuerKeyId
+ hashFunc = sig.Hash
+ sigType = sig.SigType
+ case *packet.SignatureV3:
+ issuerKeyId = sig.IssuerKeyId
+ hashFunc = sig.Hash
+ sigType = sig.SigType
+ default:
+ return nil, errors.StructuralError("non signature packet found")
+ }
+
+ keys = keyring.KeysByIdUsage(issuerKeyId, packet.KeyFlagSign)
+ if len(keys) > 0 {
+ break
+ }
+ }
+
+ if len(keys) == 0 {
+ panic("unreachable")
+ }
+
+ h, wrappedHash, err := hashForSignature(hashFunc, sigType)
+ if err != nil {
+ return nil, err
+ }
+
+ if _, err := io.Copy(wrappedHash, signed); err != nil && err != io.EOF {
+ return nil, err
+ }
+
+ for _, key := range keys {
+ switch sig := p.(type) {
+ case *packet.Signature:
+ err = key.PublicKey.VerifySignature(h, sig)
+ case *packet.SignatureV3:
+ err = key.PublicKey.VerifySignatureV3(h, sig)
+ default:
+ panic("unreachable")
+ }
+
+ if err == nil {
+ return key.Entity, nil
+ }
+ }
+
+ return nil, err
+}
+
+// CheckArmoredDetachedSignature performs the same actions as
+// CheckDetachedSignature but expects the signature to be armored.
+func CheckArmoredDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signer *Entity, err error) {
+ body, err := readArmored(signature, SignatureType)
+ if err != nil {
+ return
+ }
+
+ return CheckDetachedSignature(keyring, signed, body)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/read_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/read_test.go
new file mode 100644
index 000000000..1fbfbac4c
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/read_test.go
@@ -0,0 +1,613 @@
+// Copyright 2011 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 openpgp
+
+import (
+ "bytes"
+ _ "crypto/sha512"
+ "encoding/hex"
+ "io"
+ "io/ioutil"
+ "strings"
+ "testing"
+
+ "golang.org/x/crypto/openpgp/armor"
+ "golang.org/x/crypto/openpgp/errors"
+)
+
+func readerFromHex(s string) io.Reader {
+ data, err := hex.DecodeString(s)
+ if err != nil {
+ panic("readerFromHex: bad input")
+ }
+ return bytes.NewBuffer(data)
+}
+
+func TestReadKeyRing(t *testing.T) {
+ kring, err := ReadKeyRing(readerFromHex(testKeys1And2Hex))
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ if len(kring) != 2 || uint32(kring[0].PrimaryKey.KeyId) != 0xC20C31BB || uint32(kring[1].PrimaryKey.KeyId) != 0x1E35246B {
+ t.Errorf("bad keyring: %#v", kring)
+ }
+}
+
+func TestRereadKeyRing(t *testing.T) {
+ kring, err := ReadKeyRing(readerFromHex(testKeys1And2Hex))
+ if err != nil {
+ t.Errorf("error in initial parse: %s", err)
+ return
+ }
+ out := new(bytes.Buffer)
+ err = kring[0].Serialize(out)
+ if err != nil {
+ t.Errorf("error in serialization: %s", err)
+ return
+ }
+ kring, err = ReadKeyRing(out)
+ if err != nil {
+ t.Errorf("error in second parse: %s", err)
+ return
+ }
+
+ if len(kring) != 1 || uint32(kring[0].PrimaryKey.KeyId) != 0xC20C31BB {
+ t.Errorf("bad keyring: %#v", kring)
+ }
+}
+
+func TestReadPrivateKeyRing(t *testing.T) {
+ kring, err := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex))
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ if len(kring) != 2 || uint32(kring[0].PrimaryKey.KeyId) != 0xC20C31BB || uint32(kring[1].PrimaryKey.KeyId) != 0x1E35246B || kring[0].PrimaryKey == nil {
+ t.Errorf("bad keyring: %#v", kring)
+ }
+}
+
+func TestReadDSAKey(t *testing.T) {
+ kring, err := ReadKeyRing(readerFromHex(dsaTestKeyHex))
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ if len(kring) != 1 || uint32(kring[0].PrimaryKey.KeyId) != 0x0CCC0360 {
+ t.Errorf("bad parse: %#v", kring)
+ }
+}
+
+func TestReadP256Key(t *testing.T) {
+ kring, err := ReadKeyRing(readerFromHex(p256TestKeyHex))
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ if len(kring) != 1 || uint32(kring[0].PrimaryKey.KeyId) != 0x5918513E {
+ t.Errorf("bad parse: %#v", kring)
+ }
+}
+
+func TestDSAHashTruncatation(t *testing.T) {
+ // dsaKeyWithSHA512 was generated with GnuPG and --cert-digest-algo
+ // SHA512 in order to require DSA hash truncation to verify correctly.
+ _, err := ReadKeyRing(readerFromHex(dsaKeyWithSHA512))
+ if err != nil {
+ t.Error(err)
+ }
+}
+
+func TestGetKeyById(t *testing.T) {
+ kring, _ := ReadKeyRing(readerFromHex(testKeys1And2Hex))
+
+ keys := kring.KeysById(0xa34d7e18c20c31bb)
+ if len(keys) != 1 || keys[0].Entity != kring[0] {
+ t.Errorf("bad result for 0xa34d7e18c20c31bb: %#v", keys)
+ }
+
+ keys = kring.KeysById(0xfd94408d4543314f)
+ if len(keys) != 1 || keys[0].Entity != kring[0] {
+ t.Errorf("bad result for 0xa34d7e18c20c31bb: %#v", keys)
+ }
+}
+
+func checkSignedMessage(t *testing.T, signedHex, expected string) {
+ kring, _ := ReadKeyRing(readerFromHex(testKeys1And2Hex))
+
+ md, err := ReadMessage(readerFromHex(signedHex), kring, nil, nil)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+
+ if !md.IsSigned || md.SignedByKeyId != 0xa34d7e18c20c31bb || md.SignedBy == nil || md.IsEncrypted || md.IsSymmetricallyEncrypted || len(md.EncryptedToKeyIds) != 0 || md.IsSymmetricallyEncrypted {
+ t.Errorf("bad MessageDetails: %#v", md)
+ }
+
+ contents, err := ioutil.ReadAll(md.UnverifiedBody)
+ if err != nil {
+ t.Errorf("error reading UnverifiedBody: %s", err)
+ }
+ if string(contents) != expected {
+ t.Errorf("bad UnverifiedBody got:%s want:%s", string(contents), expected)
+ }
+ if md.SignatureError != nil || md.Signature == nil {
+ t.Errorf("failed to validate: %s", md.SignatureError)
+ }
+}
+
+func TestSignedMessage(t *testing.T) {
+ checkSignedMessage(t, signedMessageHex, signedInput)
+}
+
+func TestTextSignedMessage(t *testing.T) {
+ checkSignedMessage(t, signedTextMessageHex, signedTextInput)
+}
+
+// The reader should detect "compressed quines", which are compressed
+// packets that expand into themselves and cause an infinite recursive
+// parsing loop.
+// The packet in this test case comes from Taylor R. Campbell at
+// http://mumble.net/~campbell/misc/pgp-quine/
+func TestCampbellQuine(t *testing.T) {
+ md, err := ReadMessage(readerFromHex(campbellQuine), nil, nil, nil)
+ if md != nil {
+ t.Errorf("Reading a compressed quine should not return any data: %#v", md)
+ }
+ structural, ok := err.(errors.StructuralError)
+ if !ok {
+ t.Fatalf("Unexpected class of error: %T", err)
+ }
+ if !strings.Contains(string(structural), "too many layers of packets") {
+ t.Fatalf("Unexpected error: %s", err)
+ }
+}
+
+var signedEncryptedMessageTests = []struct {
+ keyRingHex string
+ messageHex string
+ signedByKeyId uint64
+ encryptedToKeyId uint64
+}{
+ {
+ testKeys1And2PrivateHex,
+ signedEncryptedMessageHex,
+ 0xa34d7e18c20c31bb,
+ 0x2a67d68660df41c7,
+ },
+ {
+ dsaElGamalTestKeysHex,
+ signedEncryptedMessage2Hex,
+ 0x33af447ccd759b09,
+ 0xcf6a7abcd43e3673,
+ },
+}
+
+func TestSignedEncryptedMessage(t *testing.T) {
+ for i, test := range signedEncryptedMessageTests {
+ expected := "Signed and encrypted message\n"
+ kring, _ := ReadKeyRing(readerFromHex(test.keyRingHex))
+ prompt := func(keys []Key, symmetric bool) ([]byte, error) {
+ if symmetric {
+ t.Errorf("prompt: message was marked as symmetrically encrypted")
+ return nil, errors.ErrKeyIncorrect
+ }
+
+ if len(keys) == 0 {
+ t.Error("prompt: no keys requested")
+ return nil, errors.ErrKeyIncorrect
+ }
+
+ err := keys[0].PrivateKey.Decrypt([]byte("passphrase"))
+ if err != nil {
+ t.Errorf("prompt: error decrypting key: %s", err)
+ return nil, errors.ErrKeyIncorrect
+ }
+
+ return nil, nil
+ }
+
+ md, err := ReadMessage(readerFromHex(test.messageHex), kring, prompt, nil)
+ if err != nil {
+ t.Errorf("#%d: error reading message: %s", i, err)
+ return
+ }
+
+ if !md.IsSigned || md.SignedByKeyId != test.signedByKeyId || md.SignedBy == nil || !md.IsEncrypted || md.IsSymmetricallyEncrypted || len(md.EncryptedToKeyIds) == 0 || md.EncryptedToKeyIds[0] != test.encryptedToKeyId {
+ t.Errorf("#%d: bad MessageDetails: %#v", i, md)
+ }
+
+ contents, err := ioutil.ReadAll(md.UnverifiedBody)
+ if err != nil {
+ t.Errorf("#%d: error reading UnverifiedBody: %s", i, err)
+ }
+ if string(contents) != expected {
+ t.Errorf("#%d: bad UnverifiedBody got:%s want:%s", i, string(contents), expected)
+ }
+
+ if md.SignatureError != nil || md.Signature == nil {
+ t.Errorf("#%d: failed to validate: %s", i, md.SignatureError)
+ }
+ }
+}
+
+func TestUnspecifiedRecipient(t *testing.T) {
+ expected := "Recipient unspecified\n"
+ kring, _ := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex))
+
+ md, err := ReadMessage(readerFromHex(recipientUnspecifiedHex), kring, nil, nil)
+ if err != nil {
+ t.Errorf("error reading message: %s", err)
+ return
+ }
+
+ contents, err := ioutil.ReadAll(md.UnverifiedBody)
+ if err != nil {
+ t.Errorf("error reading UnverifiedBody: %s", err)
+ }
+ if string(contents) != expected {
+ t.Errorf("bad UnverifiedBody got:%s want:%s", string(contents), expected)
+ }
+}
+
+func TestSymmetricallyEncrypted(t *testing.T) {
+ firstTimeCalled := true
+
+ prompt := func(keys []Key, symmetric bool) ([]byte, error) {
+ if len(keys) != 0 {
+ t.Errorf("prompt: len(keys) = %d (want 0)", len(keys))
+ }
+
+ if !symmetric {
+ t.Errorf("symmetric is not set")
+ }
+
+ if firstTimeCalled {
+ firstTimeCalled = false
+ return []byte("wrongpassword"), nil
+ }
+
+ return []byte("password"), nil
+ }
+
+ md, err := ReadMessage(readerFromHex(symmetricallyEncryptedCompressedHex), nil, prompt, nil)
+ if err != nil {
+ t.Errorf("ReadMessage: %s", err)
+ return
+ }
+
+ contents, err := ioutil.ReadAll(md.UnverifiedBody)
+ if err != nil {
+ t.Errorf("ReadAll: %s", err)
+ }
+
+ expectedCreationTime := uint32(1295992998)
+ if md.LiteralData.Time != expectedCreationTime {
+ t.Errorf("LiteralData.Time is %d, want %d", md.LiteralData.Time, expectedCreationTime)
+ }
+
+ const expected = "Symmetrically encrypted.\n"
+ if string(contents) != expected {
+ t.Errorf("contents got: %s want: %s", string(contents), expected)
+ }
+}
+
+func testDetachedSignature(t *testing.T, kring KeyRing, signature io.Reader, sigInput, tag string, expectedSignerKeyId uint64) {
+ signed := bytes.NewBufferString(sigInput)
+ signer, err := CheckDetachedSignature(kring, signed, signature)
+ if err != nil {
+ t.Errorf("%s: signature error: %s", tag, err)
+ return
+ }
+ if signer == nil {
+ t.Errorf("%s: signer is nil", tag)
+ return
+ }
+ if signer.PrimaryKey.KeyId != expectedSignerKeyId {
+ t.Errorf("%s: wrong signer got:%x want:%x", tag, signer.PrimaryKey.KeyId, expectedSignerKeyId)
+ }
+}
+
+func TestDetachedSignature(t *testing.T) {
+ kring, _ := ReadKeyRing(readerFromHex(testKeys1And2Hex))
+ testDetachedSignature(t, kring, readerFromHex(detachedSignatureHex), signedInput, "binary", testKey1KeyId)
+ testDetachedSignature(t, kring, readerFromHex(detachedSignatureTextHex), signedInput, "text", testKey1KeyId)
+ testDetachedSignature(t, kring, readerFromHex(detachedSignatureV3TextHex), signedInput, "v3", testKey1KeyId)
+
+ incorrectSignedInput := signedInput + "X"
+ _, err := CheckDetachedSignature(kring, bytes.NewBufferString(incorrectSignedInput), readerFromHex(detachedSignatureHex))
+ if err == nil {
+ t.Fatal("CheckDetachedSignature returned without error for bad signature")
+ }
+ if err == errors.ErrUnknownIssuer {
+ t.Fatal("CheckDetachedSignature returned ErrUnknownIssuer when the signer was known, but the signature invalid")
+ }
+}
+
+func TestDetachedSignatureDSA(t *testing.T) {
+ kring, _ := ReadKeyRing(readerFromHex(dsaTestKeyHex))
+ testDetachedSignature(t, kring, readerFromHex(detachedSignatureDSAHex), signedInput, "binary", testKey3KeyId)
+}
+
+func TestMultipleSignaturePacketsDSA(t *testing.T) {
+ kring, _ := ReadKeyRing(readerFromHex(dsaTestKeyHex))
+ testDetachedSignature(t, kring, readerFromHex(missingHashFunctionHex+detachedSignatureDSAHex), signedInput, "binary", testKey3KeyId)
+}
+
+func TestDetachedSignatureP256(t *testing.T) {
+ kring, _ := ReadKeyRing(readerFromHex(p256TestKeyHex))
+ testDetachedSignature(t, kring, readerFromHex(detachedSignatureP256Hex), signedInput, "binary", testKeyP256KeyId)
+}
+
+func testHashFunctionError(t *testing.T, signatureHex string) {
+ kring, _ := ReadKeyRing(readerFromHex(testKeys1And2Hex))
+ _, err := CheckDetachedSignature(kring, nil, readerFromHex(signatureHex))
+ if err == nil {
+ t.Fatal("Packet with bad hash type was correctly parsed")
+ }
+ unsupported, ok := err.(errors.UnsupportedError)
+ if !ok {
+ t.Fatalf("Unexpected class of error: %s", err)
+ }
+ if !strings.Contains(string(unsupported), "hash ") {
+ t.Fatalf("Unexpected error: %s", err)
+ }
+}
+
+func TestUnknownHashFunction(t *testing.T) {
+ // unknownHashFunctionHex contains a signature packet with hash
+ // function type 153 (which isn't a real hash function id).
+ testHashFunctionError(t, unknownHashFunctionHex)
+}
+
+func TestMissingHashFunction(t *testing.T) {
+ // missingHashFunctionHex contains a signature packet that uses
+ // RIPEMD160, which isn't compiled in. Since that's the only signature
+ // packet we don't find any suitable packets and end up with ErrUnknownIssuer
+ kring, _ := ReadKeyRing(readerFromHex(testKeys1And2Hex))
+ _, err := CheckDetachedSignature(kring, nil, readerFromHex(missingHashFunctionHex))
+ if err == nil {
+ t.Fatal("Packet with missing hash type was correctly parsed")
+ }
+ if err != errors.ErrUnknownIssuer {
+ t.Fatalf("Unexpected class of error: %s", err)
+ }
+}
+
+func TestReadingArmoredPrivateKey(t *testing.T) {
+ el, err := ReadArmoredKeyRing(bytes.NewBufferString(armoredPrivateKeyBlock))
+ if err != nil {
+ t.Error(err)
+ }
+ if len(el) != 1 {
+ t.Errorf("got %d entities, wanted 1\n", len(el))
+ }
+}
+
+func TestReadingArmoredPublicKey(t *testing.T) {
+ el, err := ReadArmoredKeyRing(bytes.NewBufferString(e2ePublicKey))
+ if err != nil {
+ t.Error(err)
+ }
+ if len(el) != 1 {
+ t.Errorf("didn't get a valid entity")
+ }
+}
+
+func TestNoArmoredData(t *testing.T) {
+ _, err := ReadArmoredKeyRing(bytes.NewBufferString("foo"))
+ if _, ok := err.(errors.InvalidArgumentError); !ok {
+ t.Errorf("error was not an InvalidArgumentError: %s", err)
+ }
+}
+
+func testReadMessageError(t *testing.T, messageHex string) {
+ buf, err := hex.DecodeString(messageHex)
+ if err != nil {
+ t.Errorf("hex.DecodeString(): %v", err)
+ }
+
+ kr, err := ReadKeyRing(new(bytes.Buffer))
+ if err != nil {
+ t.Errorf("ReadKeyring(): %v", err)
+ }
+
+ _, err = ReadMessage(bytes.NewBuffer(buf), kr,
+ func([]Key, bool) ([]byte, error) {
+ return []byte("insecure"), nil
+ }, nil)
+
+ if err == nil {
+ t.Errorf("ReadMessage(): Unexpected nil error")
+ }
+}
+
+func TestIssue11503(t *testing.T) {
+ testReadMessageError(t, "8c040402000aa430aa8228b9248b01fc899a91197130303030")
+}
+
+func TestIssue11504(t *testing.T) {
+ testReadMessageError(t, "9303000130303030303030303030983002303030303030030000000130")
+}
+
+// TestSignatureV3Message tests the verification of V3 signature, generated
+// with a modern V4-style key. Some people have their clients set to generate
+// V3 signatures, so it's useful to be able to verify them.
+func TestSignatureV3Message(t *testing.T) {
+ sig, err := armor.Decode(strings.NewReader(signedMessageV3))
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ key, err := ReadArmoredKeyRing(strings.NewReader(keyV4forVerifyingSignedMessageV3))
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ md, err := ReadMessage(sig.Body, key, nil, nil)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+
+ _, err = ioutil.ReadAll(md.UnverifiedBody)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+
+ // We'll see a sig error here after reading in the UnverifiedBody above,
+ // if there was one to see.
+ if err = md.SignatureError; err != nil {
+ t.Error(err)
+ return
+ }
+
+ if md.SignatureV3 == nil {
+ t.Errorf("No available signature after checking signature")
+ return
+ }
+ if md.Signature != nil {
+ t.Errorf("Did not expect a signature V4 back")
+ return
+ }
+ return
+}
+
+const testKey1KeyId = 0xA34D7E18C20C31BB
+const testKey3KeyId = 0x338934250CCC0360
+const testKeyP256KeyId = 0xd44a2c495918513e
+
+const signedInput = "Signed message\nline 2\nline 3\n"
+const signedTextInput = "Signed message\r\nline 2\r\nline 3\r\n"
+
+const recipientUnspecifiedHex = "848c0300000000000000000103ff62d4d578d03cf40c3da998dfe216c074fa6ddec5e31c197c9666ba292830d91d18716a80f699f9d897389a90e6d62d0238f5f07a5248073c0f24920e4bc4a30c2d17ee4e0cae7c3d4aaa4e8dced50e3010a80ee692175fa0385f62ecca4b56ee6e9980aa3ec51b61b077096ac9e800edaf161268593eedb6cc7027ff5cb32745d250010d407a6221ae22ef18469b444f2822478c4d190b24d36371a95cb40087cdd42d9399c3d06a53c0673349bfb607927f20d1e122bde1e2bf3aa6cae6edf489629bcaa0689539ae3b718914d88ededc3b"
+
+const detachedSignatureHex = "889c04000102000605024d449cd1000a0910a34d7e18c20c31bb167603ff57718d09f28a519fdc7b5a68b6a3336da04df85e38c5cd5d5bd2092fa4629848a33d85b1729402a2aab39c3ac19f9d573f773cc62c264dc924c067a79dfd8a863ae06c7c8686120760749f5fd9b1e03a64d20a7df3446ddc8f0aeadeaeba7cbaee5c1e366d65b6a0c6cc749bcb912d2f15013f812795c2e29eb7f7b77f39ce77"
+
+const detachedSignatureTextHex = "889c04010102000605024d449d21000a0910a34d7e18c20c31bbc8c60400a24fbef7342603a41cb1165767bd18985d015fb72fe05db42db36cfb2f1d455967f1e491194fbf6cf88146222b23bf6ffbd50d17598d976a0417d3192ff9cc0034fd00f287b02e90418bbefe609484b09231e4e7a5f3562e199bf39909ab5276c4d37382fe088f6b5c3426fc1052865da8b3ab158672d58b6264b10823dc4b39"
+
+const detachedSignatureV3TextHex = "8900950305005255c25ca34d7e18c20c31bb0102bb3f04009f6589ef8a028d6e54f6eaf25432e590d31c3a41f4710897585e10c31e5e332c7f9f409af8512adceaff24d0da1474ab07aa7bce4f674610b010fccc5b579ae5eb00a127f272fb799f988ab8e4574c141da6dbfecfef7e6b2c478d9a3d2551ba741f260ee22bec762812f0053e05380bfdd55ad0f22d8cdf71b233fe51ae8a24"
+
+const detachedSignatureDSAHex = "884604001102000605024d6c4eac000a0910338934250ccc0360f18d00a087d743d6405ed7b87755476629600b8b694a39e900a0abff8126f46faf1547c1743c37b21b4ea15b8f83"
+
+const detachedSignatureP256Hex = "885e0400130a0006050256e5bb00000a0910d44a2c495918513edef001009841a4f792beb0befccb35c8838a6a87d9b936beaa86db6745ddc7b045eee0cf00fd1ac1f78306b17e965935dd3f8bae4587a76587e4af231efe19cc4011a8434817"
+
+const testKeys1And2Hex = "988d044d3c5c10010400b1d13382944bd5aba23a4312968b5095d14f947f600eb478e14a6fcb16b0e0cac764884909c020bc495cfcc39a935387c661507bdb236a0612fb582cac3af9b29cc2c8c70090616c41b662f4da4c1201e195472eb7f4ae1ccbcbf9940fe21d985e379a5563dde5b9a23d35f1cfaa5790da3b79db26f23695107bfaca8e7b5bcd0011010001b41054657374204b6579203120285253412988b804130102002205024d3c5c10021b03060b090807030206150802090a0b0416020301021e01021780000a0910a34d7e18c20c31bbb5b304009cc45fe610b641a2c146331be94dade0a396e73ca725e1b25c21708d9cab46ecca5ccebc23055879df8f99eea39b377962a400f2ebdc36a7c99c333d74aeba346315137c3ff9d0a09b0273299090343048afb8107cf94cbd1400e3026f0ccac7ecebbc4d78588eb3e478fe2754d3ca664bcf3eac96ca4a6b0c8d7df5102f60f6b0020003b88d044d3c5c10010400b201df61d67487301f11879d514f4248ade90c8f68c7af1284c161098de4c28c2850f1ec7b8e30f959793e571542ffc6532189409cb51c3d30dad78c4ad5165eda18b20d9826d8707d0f742e2ab492103a85bbd9ddf4f5720f6de7064feb0d39ee002219765bb07bcfb8b877f47abe270ddeda4f676108cecb6b9bb2ad484a4f0011010001889f04180102000905024d3c5c10021b0c000a0910a34d7e18c20c31bb1a03040085c8d62e16d05dc4e9dad64953c8a2eed8b6c12f92b1575eeaa6dcf7be9473dd5b24b37b6dffbb4e7c99ed1bd3cb11634be19b3e6e207bed7505c7ca111ccf47cb323bf1f8851eb6360e8034cbff8dd149993c959de89f8f77f38e7e98b8e3076323aa719328e2b408db5ec0d03936efd57422ba04f925cdc7b4c1af7590e40ab0020003988d044d3c5c33010400b488c3e5f83f4d561f317817538d9d0397981e9aef1321ca68ebfae1cf8b7d388e19f4b5a24a82e2fbbf1c6c26557a6c5845307a03d815756f564ac7325b02bc83e87d5480a8fae848f07cb891f2d51ce7df83dcafdc12324517c86d472cc0ee10d47a68fd1d9ae49a6c19bbd36d82af597a0d88cc9c49de9df4e696fc1f0b5d0011010001b42754657374204b6579203220285253412c20656e637279707465642070726976617465206b65792988b804130102002205024d3c5c33021b03060b090807030206150802090a0b0416020301021e01021780000a0910d4984f961e35246b98940400908a73b6a6169f700434f076c6c79015a49bee37130eaf23aaa3cfa9ce60bfe4acaa7bc95f1146ada5867e0079babb38804891f4f0b8ebca57a86b249dee786161a755b7a342e68ccf3f78ed6440a93a6626beb9a37aa66afcd4f888790cb4bb46d94a4ae3eb3d7d3e6b00f6bfec940303e89ec5b32a1eaaacce66497d539328b0020003b88d044d3c5c33010400a4e913f9442abcc7f1804ccab27d2f787ffa592077ca935a8bb23165bd8d57576acac647cc596b2c3f814518cc8c82953c7a4478f32e0cf645630a5ba38d9618ef2bc3add69d459ae3dece5cab778938d988239f8c5ae437807075e06c828019959c644ff05ef6a5a1dab72227c98e3a040b0cf219026640698d7a13d8538a570011010001889f04180102000905024d3c5c33021b0c000a0910d4984f961e35246b26c703ff7ee29ef53bc1ae1ead533c408fa136db508434e233d6e62be621e031e5940bbd4c08142aed0f82217e7c3e1ec8de574bc06ccf3c36633be41ad78a9eacd209f861cae7b064100758545cc9dd83db71806dc1cfd5fb9ae5c7474bba0c19c44034ae61bae5eca379383339dece94ff56ff7aa44a582f3e5c38f45763af577c0934b0020003"
+
+const testKeys1And2PrivateHex = "9501d8044d3c5c10010400b1d13382944bd5aba23a4312968b5095d14f947f600eb478e14a6fcb16b0e0cac764884909c020bc495cfcc39a935387c661507bdb236a0612fb582cac3af9b29cc2c8c70090616c41b662f4da4c1201e195472eb7f4ae1ccbcbf9940fe21d985e379a5563dde5b9a23d35f1cfaa5790da3b79db26f23695107bfaca8e7b5bcd00110100010003ff4d91393b9a8e3430b14d6209df42f98dc927425b881f1209f319220841273a802a97c7bdb8b3a7740b3ab5866c4d1d308ad0d3a79bd1e883aacf1ac92dfe720285d10d08752a7efe3c609b1d00f17f2805b217be53999a7da7e493bfc3e9618fd17018991b8128aea70a05dbce30e4fbe626aa45775fa255dd9177aabf4df7cf0200c1ded12566e4bc2bb590455e5becfb2e2c9796482270a943343a7835de41080582c2be3caf5981aa838140e97afa40ad652a0b544f83eb1833b0957dce26e47b0200eacd6046741e9ce2ec5beb6fb5e6335457844fb09477f83b050a96be7da043e17f3a9523567ed40e7a521f818813a8b8a72209f1442844843ccc7eb9805442570200bdafe0438d97ac36e773c7162028d65844c4d463e2420aa2228c6e50dc2743c3d6c72d0d782a5173fe7be2169c8a9f4ef8a7cf3e37165e8c61b89c346cdc6c1799d2b41054657374204b6579203120285253412988b804130102002205024d3c5c10021b03060b090807030206150802090a0b0416020301021e01021780000a0910a34d7e18c20c31bbb5b304009cc45fe610b641a2c146331be94dade0a396e73ca725e1b25c21708d9cab46ecca5ccebc23055879df8f99eea39b377962a400f2ebdc36a7c99c333d74aeba346315137c3ff9d0a09b0273299090343048afb8107cf94cbd1400e3026f0ccac7ecebbc4d78588eb3e478fe2754d3ca664bcf3eac96ca4a6b0c8d7df5102f60f6b00200009d01d8044d3c5c10010400b201df61d67487301f11879d514f4248ade90c8f68c7af1284c161098de4c28c2850f1ec7b8e30f959793e571542ffc6532189409cb51c3d30dad78c4ad5165eda18b20d9826d8707d0f742e2ab492103a85bbd9ddf4f5720f6de7064feb0d39ee002219765bb07bcfb8b877f47abe270ddeda4f676108cecb6b9bb2ad484a4f00110100010003fd17a7490c22a79c59281fb7b20f5e6553ec0c1637ae382e8adaea295f50241037f8997cf42c1ce26417e015091451b15424b2c59eb8d4161b0975630408e394d3b00f88d4b4e18e2cc85e8251d4753a27c639c83f5ad4a571c4f19d7cd460b9b73c25ade730c99df09637bd173d8e3e981ac64432078263bb6dc30d3e974150dd0200d0ee05be3d4604d2146fb0457f31ba17c057560785aa804e8ca5530a7cd81d3440d0f4ba6851efcfd3954b7e68908fc0ba47f7ac37bf559c6c168b70d3a7c8cd0200da1c677c4bce06a068070f2b3733b0a714e88d62aa3f9a26c6f5216d48d5c2b5624144f3807c0df30be66b3268eeeca4df1fbded58faf49fc95dc3c35f134f8b01fd1396b6c0fc1b6c4f0eb8f5e44b8eace1e6073e20d0b8bc5385f86f1cf3f050f66af789f3ef1fc107b7f4421e19e0349c730c68f0a226981f4e889054fdb4dc149e8e889f04180102000905024d3c5c10021b0c000a0910a34d7e18c20c31bb1a03040085c8d62e16d05dc4e9dad64953c8a2eed8b6c12f92b1575eeaa6dcf7be9473dd5b24b37b6dffbb4e7c99ed1bd3cb11634be19b3e6e207bed7505c7ca111ccf47cb323bf1f8851eb6360e8034cbff8dd149993c959de89f8f77f38e7e98b8e3076323aa719328e2b408db5ec0d03936efd57422ba04f925cdc7b4c1af7590e40ab00200009501fe044d3c5c33010400b488c3e5f83f4d561f317817538d9d0397981e9aef1321ca68ebfae1cf8b7d388e19f4b5a24a82e2fbbf1c6c26557a6c5845307a03d815756f564ac7325b02bc83e87d5480a8fae848f07cb891f2d51ce7df83dcafdc12324517c86d472cc0ee10d47a68fd1d9ae49a6c19bbd36d82af597a0d88cc9c49de9df4e696fc1f0b5d0011010001fe030302e9030f3c783e14856063f16938530e148bc57a7aa3f3e4f90df9dceccdc779bc0835e1ad3d006e4a8d7b36d08b8e0de5a0d947254ecfbd22037e6572b426bcfdc517796b224b0036ff90bc574b5509bede85512f2eefb520fb4b02aa523ba739bff424a6fe81c5041f253f8d757e69a503d3563a104d0d49e9e890b9d0c26f96b55b743883b472caa7050c4acfd4a21f875bdf1258d88bd61224d303dc9df77f743137d51e6d5246b88c406780528fd9a3e15bab5452e5b93970d9dcc79f48b38651b9f15bfbcf6da452837e9cc70683d1bdca94507870f743e4ad902005812488dd342f836e72869afd00ce1850eea4cfa53ce10e3608e13d3c149394ee3cbd0e23d018fcbcb6e2ec5a1a22972d1d462ca05355d0d290dd2751e550d5efb38c6c89686344df64852bf4ff86638708f644e8ec6bd4af9b50d8541cb91891a431326ab2e332faa7ae86cfb6e0540aa63160c1e5cdd5a4add518b303fff0a20117c6bc77f7cfbaf36b04c865c6c2b42754657374204b6579203220285253412c20656e637279707465642070726976617465206b65792988b804130102002205024d3c5c33021b03060b090807030206150802090a0b0416020301021e01021780000a0910d4984f961e35246b98940400908a73b6a6169f700434f076c6c79015a49bee37130eaf23aaa3cfa9ce60bfe4acaa7bc95f1146ada5867e0079babb38804891f4f0b8ebca57a86b249dee786161a755b7a342e68ccf3f78ed6440a93a6626beb9a37aa66afcd4f888790cb4bb46d94a4ae3eb3d7d3e6b00f6bfec940303e89ec5b32a1eaaacce66497d539328b00200009d01fe044d3c5c33010400a4e913f9442abcc7f1804ccab27d2f787ffa592077ca935a8bb23165bd8d57576acac647cc596b2c3f814518cc8c82953c7a4478f32e0cf645630a5ba38d9618ef2bc3add69d459ae3dece5cab778938d988239f8c5ae437807075e06c828019959c644ff05ef6a5a1dab72227c98e3a040b0cf219026640698d7a13d8538a570011010001fe030302e9030f3c783e148560f936097339ae381d63116efcf802ff8b1c9360767db5219cc987375702a4123fd8657d3e22700f23f95020d1b261eda5257e9a72f9a918e8ef22dd5b3323ae03bbc1923dd224db988cadc16acc04b120a9f8b7e84da9716c53e0334d7b66586ddb9014df604b41be1e960dcfcbc96f4ed150a1a0dd070b9eb14276b9b6be413a769a75b519a53d3ecc0c220e85cd91ca354d57e7344517e64b43b6e29823cbd87eae26e2b2e78e6dedfbb76e3e9f77bcb844f9a8932eb3db2c3f9e44316e6f5d60e9e2a56e46b72abe6b06dc9a31cc63f10023d1f5e12d2a3ee93b675c96f504af0001220991c88db759e231b3320dcedf814dcf723fd9857e3d72d66a0f2af26950b915abdf56c1596f46a325bf17ad4810d3535fb02a259b247ac3dbd4cc3ecf9c51b6c07cebb009c1506fba0a89321ec8683e3fd009a6e551d50243e2d5092fefb3321083a4bad91320dc624bd6b5dddf93553e3d53924c05bfebec1fb4bd47e89a1a889f04180102000905024d3c5c33021b0c000a0910d4984f961e35246b26c703ff7ee29ef53bc1ae1ead533c408fa136db508434e233d6e62be621e031e5940bbd4c08142aed0f82217e7c3e1ec8de574bc06ccf3c36633be41ad78a9eacd209f861cae7b064100758545cc9dd83db71806dc1cfd5fb9ae5c7474bba0c19c44034ae61bae5eca379383339dece94ff56ff7aa44a582f3e5c38f45763af577c0934b0020000"
+
+const dsaElGamalTestKeysHex = "9501e1044dfcb16a110400aa3e5c1a1f43dd28c2ffae8abf5cfce555ee874134d8ba0a0f7b868ce2214beddc74e5e1e21ded354a95d18acdaf69e5e342371a71fbb9093162e0c5f3427de413a7f2c157d83f5cd2f9d791256dc4f6f0e13f13c3302af27f2384075ab3021dff7a050e14854bbde0a1094174855fc02f0bae8e00a340d94a1f22b32e48485700a0cec672ac21258fb95f61de2ce1af74b2c4fa3e6703ff698edc9be22c02ae4d916e4fa223f819d46582c0516235848a77b577ea49018dcd5e9e15cff9dbb4663a1ae6dd7580fa40946d40c05f72814b0f88481207e6c0832c3bded4853ebba0a7e3bd8e8c66df33d5a537cd4acf946d1080e7a3dcea679cb2b11a72a33a2b6a9dc85f466ad2ddf4c3db6283fa645343286971e3dd700703fc0c4e290d45767f370831a90187e74e9972aae5bff488eeff7d620af0362bfb95c1a6c3413ab5d15a2e4139e5d07a54d72583914661ed6a87cce810be28a0aa8879a2dd39e52fb6fe800f4f181ac7e328f740cde3d09a05cecf9483e4cca4253e60d4429ffd679d9996a520012aad119878c941e3cf151459873bdfc2a9563472fe0303027a728f9feb3b864260a1babe83925ce794710cfd642ee4ae0e5b9d74cee49e9c67b6cd0ea5dfbb582132195a121356a1513e1bca73e5b80c58c7ccb4164453412f456c47616d616c2054657374204b65792031886204131102002205024dfcb16a021b03060b090807030206150802090a0b0416020301021e01021780000a091033af447ccd759b09fadd00a0b8fd6f5a790bad7e9f2dbb7632046dc4493588db009c087c6a9ba9f7f49fab221587a74788c00db4889ab00200009d0157044dfcb16a1004008dec3f9291205255ccff8c532318133a6840739dd68b03ba942676f9038612071447bf07d00d559c5c0875724ea16a4c774f80d8338b55fca691a0522e530e604215b467bbc9ccfd483a1da99d7bc2648b4318fdbd27766fc8bfad3fddb37c62b8ae7ccfe9577e9b8d1e77c1d417ed2c2ef02d52f4da11600d85d3229607943700030503ff506c94c87c8cab778e963b76cf63770f0a79bf48fb49d3b4e52234620fc9f7657f9f8d56c96a2b7c7826ae6b57ebb2221a3fe154b03b6637cea7e6d98e3e45d87cf8dc432f723d3d71f89c5192ac8d7290684d2c25ce55846a80c9a7823f6acd9bb29fa6cd71f20bc90eccfca20451d0c976e460e672b000df49466408d527affe0303027a728f9feb3b864260abd761730327bca2aaa4ea0525c175e92bf240682a0e83b226f97ecb2e935b62c9a133858ce31b271fa8eb41f6a1b3cd72a63025ce1a75ee4180dcc284884904181102000905024dfcb16a021b0c000a091033af447ccd759b09dd0b009e3c3e7296092c81bee5a19929462caaf2fff3ae26009e218c437a2340e7ea628149af1ec98ec091a43992b00200009501e1044dfcb1be1104009f61faa61aa43df75d128cbe53de528c4aec49ce9360c992e70c77072ad5623de0a3a6212771b66b39a30dad6781799e92608316900518ec01184a85d872365b7d2ba4bacfb5882ea3c2473d3750dc6178cc1cf82147fb58caa28b28e9f12f6d1efcb0534abed644156c91cca4ab78834268495160b2400bc422beb37d237c2300a0cac94911b6d493bda1e1fbc6feeca7cb7421d34b03fe22cec6ccb39675bb7b94a335c2b7be888fd3906a1125f33301d8aa6ec6ee6878f46f73961c8d57a3e9544d8ef2a2cbfd4d52da665b1266928cfe4cb347a58c412815f3b2d2369dec04b41ac9a71cc9547426d5ab941cccf3b18575637ccfb42df1a802df3cfe0a999f9e7109331170e3a221991bf868543960f8c816c28097e503fe319db10fb98049f3a57d7c80c420da66d56f3644371631fad3f0ff4040a19a4fedc2d07727a1b27576f75a4d28c47d8246f27071e12d7a8de62aad216ddbae6aa02efd6b8a3e2818cda48526549791ab277e447b3a36c57cefe9b592f5eab73959743fcc8e83cbefec03a329b55018b53eec196765ae40ef9e20521a603c551efe0303020950d53a146bf9c66034d00c23130cce95576a2ff78016ca471276e8227fb30b1ffbd92e61804fb0c3eff9e30b1a826ee8f3e4730b4d86273ca977b4164453412f456c47616d616c2054657374204b65792032886204131102002205024dfcb1be021b03060b090807030206150802090a0b0416020301021e01021780000a0910a86bf526325b21b22bd9009e34511620415c974750a20df5cb56b182f3b48e6600a0a9466cb1a1305a84953445f77d461593f1d42bc1b00200009d0157044dfcb1be1004009565a951da1ee87119d600c077198f1c1bceb0f7aa54552489298e41ff788fa8f0d43a69871f0f6f77ebdfb14a4260cf9fbeb65d5844b4272a1904dd95136d06c3da745dc46327dd44a0f16f60135914368c8039a34033862261806bb2c5ce1152e2840254697872c85441ccb7321431d75a747a4bfb1d2c66362b51ce76311700030503fc0ea76601c196768070b7365a200e6ddb09307f262d5f39eec467b5f5784e22abdf1aa49226f59ab37cb49969d8f5230ea65caf56015abda62604544ed526c5c522bf92bed178a078789f6c807b6d34885688024a5bed9e9f8c58d11d4b82487b44c5f470c5606806a0443b79cadb45e0f897a561a53f724e5349b9267c75ca17fe0303020950d53a146bf9c660bc5f4ce8f072465e2d2466434320c1e712272fafc20e342fe7608101580fa1a1a367e60486a7cd1246b7ef5586cf5e10b32762b710a30144f12dd17dd4884904181102000905024dfcb1be021b0c000a0910a86bf526325b21b2904c00a0b2b66b4b39ccffda1d10f3ea8d58f827e30a8b8e009f4255b2d8112a184e40cde43a34e8655ca7809370b0020000"
+
+const signedMessageHex = "a3019bc0cbccc0c4b8d8b74ee2108fe16ec6d3ca490cbe362d3f8333d3f352531472538b8b13d353b97232f352158c20943157c71c16064626063656269052062e4e01987e9b6fccff4b7df3a34c534b23e679cbec3bc0f8f6e64dfb4b55fe3f8efa9ce110ddb5cd79faf1d753c51aecfa669f7e7aa043436596cccc3359cb7dd6bbe9ecaa69e5989d9e57209571edc0b2fa7f57b9b79a64ee6e99ce1371395fee92fec2796f7b15a77c386ff668ee27f6d38f0baa6c438b561657377bf6acff3c5947befd7bf4c196252f1d6e5c524d0300"
+
+const signedTextMessageHex = "a3019bc0cbccc8c4b8d8b74ee2108fe16ec6d36a250cbece0c178233d3f352531472538b8b13d35379b97232f352158ca0b4312f57c71c1646462606365626906a062e4e019811591798ff99bf8afee860b0d8a8c2a85c3387e3bcf0bb3b17987f2bbcfab2aa526d930cbfd3d98757184df3995c9f3e7790e36e3e9779f06089d4c64e9e47dd6202cb6e9bc73c5d11bb59fbaf89d22d8dc7cf199ddf17af96e77c5f65f9bbed56f427bd8db7af37f6c9984bf9385efaf5f184f986fb3e6adb0ecfe35bbf92d16a7aa2a344fb0bc52fb7624f0200"
+
+const signedEncryptedMessageHex = "848c032a67d68660df41c70103ff5789d0de26b6a50c985a02a13131ca829c413a35d0e6fa8d6842599252162808ac7439c72151c8c6183e76923fe3299301414d0c25a2f06a2257db3839e7df0ec964773f6e4c4ac7ff3b48c444237166dd46ba8ff443a5410dc670cb486672fdbe7c9dfafb75b4fea83af3a204fe2a7dfa86bd20122b4f3d2646cbeecb8f7be8d2c03b018bd210b1d3791e1aba74b0f1034e122ab72e760492c192383cf5e20b5628bd043272d63df9b923f147eb6091cd897553204832aba48fec54aa447547bb16305a1024713b90e77fd0065f1918271947549205af3c74891af22ee0b56cd29bfec6d6e351901cd4ab3ece7c486f1e32a792d4e474aed98ee84b3f591c7dff37b64e0ecd68fd036d517e412dcadf85840ce184ad7921ad446c4ee28db80447aea1ca8d4f574db4d4e37688158ddd19e14ee2eab4873d46947d65d14a23e788d912cf9a19624ca7352469b72a83866b7c23cb5ace3deab3c7018061b0ba0f39ed2befe27163e5083cf9b8271e3e3d52cc7ad6e2a3bd81d4c3d7022f8d"
+
+const signedEncryptedMessage2Hex = "85010e03cf6a7abcd43e36731003fb057f5495b79db367e277cdbe4ab90d924ddee0c0381494112ff8c1238fb0184af35d1731573b01bc4c55ecacd2aafbe2003d36310487d1ecc9ac994f3fada7f9f7f5c3a64248ab7782906c82c6ff1303b69a84d9a9529c31ecafbcdb9ba87e05439897d87e8a2a3dec55e14df19bba7f7bd316291c002ae2efd24f83f9e3441203fc081c0c23dc3092a454ca8a082b27f631abf73aca341686982e8fbda7e0e7d863941d68f3de4a755c2964407f4b5e0477b3196b8c93d551dd23c8beef7d0f03fbb1b6066f78907faf4bf1677d8fcec72651124080e0b7feae6b476e72ab207d38d90b958759fdedfc3c6c35717c9dbfc979b3cfbbff0a76d24a5e57056bb88acbd2a901ef64bc6e4db02adc05b6250ff378de81dca18c1910ab257dff1b9771b85bb9bbe0a69f5989e6d1710a35e6dfcceb7d8fb5ccea8db3932b3d9ff3fe0d327597c68b3622aec8e3716c83a6c93f497543b459b58ba504ed6bcaa747d37d2ca746fe49ae0a6ce4a8b694234e941b5159ff8bd34b9023da2814076163b86f40eed7c9472f81b551452d5ab87004a373c0172ec87ea6ce42ccfa7dbdad66b745496c4873d8019e8c28d6b3"
+
+const symmetricallyEncryptedCompressedHex = "8c0d04030302eb4a03808145d0d260c92f714339e13de5a79881216431925bf67ee2898ea61815f07894cd0703c50d0a76ef64d482196f47a8bc729af9b80bb6"
+
+const dsaTestKeyHex = "9901a2044d6c49de110400cb5ce438cf9250907ac2ba5bf6547931270b89f7c4b53d9d09f4d0213a5ef2ec1f26806d3d259960f872a4a102ef1581ea3f6d6882d15134f21ef6a84de933cc34c47cc9106efe3bd84c6aec12e78523661e29bc1a61f0aab17fa58a627fd5fd33f5149153fbe8cd70edf3d963bc287ef875270ff14b5bfdd1bca4483793923b00a0fe46d76cb6e4cbdc568435cd5480af3266d610d303fe33ae8273f30a96d4d34f42fa28ce1112d425b2e3bf7ea553d526e2db6b9255e9dc7419045ce817214d1a0056dbc8d5289956a4b1b69f20f1105124096e6a438f41f2e2495923b0f34b70642607d45559595c7fe94d7fa85fc41bf7d68c1fd509ebeaa5f315f6059a446b9369c277597e4f474a9591535354c7e7f4fd98a08aa60400b130c24ff20bdfbf683313f5daebf1c9b34b3bdadfc77f2ddd72ee1fb17e56c473664bc21d66467655dd74b9005e3a2bacce446f1920cd7017231ae447b67036c9b431b8179deacd5120262d894c26bc015bffe3d827ba7087ad9b700d2ca1f6d16cc1786581e5dd065f293c31209300f9b0afcc3f7c08dd26d0a22d87580b4db41054657374204b65792033202844534129886204131102002205024d6c49de021b03060b090807030206150802090a0b0416020301021e01021780000a0910338934250ccc03607e0400a0bdb9193e8a6b96fc2dfc108ae848914b504481f100a09c4dc148cb693293a67af24dd40d2b13a9e36794"
+
+const dsaTestKeyPrivateHex = "9501bb044d6c49de110400cb5ce438cf9250907ac2ba5bf6547931270b89f7c4b53d9d09f4d0213a5ef2ec1f26806d3d259960f872a4a102ef1581ea3f6d6882d15134f21ef6a84de933cc34c47cc9106efe3bd84c6aec12e78523661e29bc1a61f0aab17fa58a627fd5fd33f5149153fbe8cd70edf3d963bc287ef875270ff14b5bfdd1bca4483793923b00a0fe46d76cb6e4cbdc568435cd5480af3266d610d303fe33ae8273f30a96d4d34f42fa28ce1112d425b2e3bf7ea553d526e2db6b9255e9dc7419045ce817214d1a0056dbc8d5289956a4b1b69f20f1105124096e6a438f41f2e2495923b0f34b70642607d45559595c7fe94d7fa85fc41bf7d68c1fd509ebeaa5f315f6059a446b9369c277597e4f474a9591535354c7e7f4fd98a08aa60400b130c24ff20bdfbf683313f5daebf1c9b34b3bdadfc77f2ddd72ee1fb17e56c473664bc21d66467655dd74b9005e3a2bacce446f1920cd7017231ae447b67036c9b431b8179deacd5120262d894c26bc015bffe3d827ba7087ad9b700d2ca1f6d16cc1786581e5dd065f293c31209300f9b0afcc3f7c08dd26d0a22d87580b4d00009f592e0619d823953577d4503061706843317e4fee083db41054657374204b65792033202844534129886204131102002205024d6c49de021b03060b090807030206150802090a0b0416020301021e01021780000a0910338934250ccc03607e0400a0bdb9193e8a6b96fc2dfc108ae848914b504481f100a09c4dc148cb693293a67af24dd40d2b13a9e36794"
+
+const p256TestKeyHex = "98520456e5b83813082a8648ce3d030107020304a2072cd6d21321266c758cc5b83fab0510f751cb8d91897cddb7047d8d6f185546e2107111b0a95cb8ef063c33245502af7a65f004d5919d93ee74eb71a66253b424502d3235362054657374204b6579203c696e76616c6964406578616d706c652e636f6d3e8879041313080021050256e5b838021b03050b09080702061508090a0b020416020301021e01021780000a0910d44a2c495918513e54e50100dfa64f97d9b47766fc1943c6314ba3f2b2a103d71ad286dc5b1efb96a345b0c80100dbc8150b54241f559da6ef4baacea6d31902b4f4b1bdc09b34bf0502334b7754b8560456e5b83812082a8648ce3d030107020304bfe3cea9cee13486f8d518aa487fecab451f25467d2bf08e58f63e5fa525d5482133e6a79299c274b068ef0be448152ad65cf11cf764348588ca4f6a0bcf22b6030108078861041813080009050256e5b838021b0c000a0910d44a2c495918513e4a4800ff49d589fa64024ad30be363a032e3a0e0e6f5db56ba4c73db850518bf0121b8f20100fd78e065f4c70ea5be9df319ea67e493b936fc78da834a71828043d3154af56e"
+
+const p256TestKeyPrivateHex = "94a50456e5b83813082a8648ce3d030107020304a2072cd6d21321266c758cc5b83fab0510f751cb8d91897cddb7047d8d6f185546e2107111b0a95cb8ef063c33245502af7a65f004d5919d93ee74eb71a66253fe070302f0c2bfb0b6c30f87ee1599472b8636477eab23ced13b271886a4b50ed34c9d8436af5af5b8f88921f0efba6ef8c37c459bbb88bc1c6a13bbd25c4ce9b1e97679569ee77645d469bf4b43de637f5561b424502d3235362054657374204b6579203c696e76616c6964406578616d706c652e636f6d3e8879041313080021050256e5b838021b03050b09080702061508090a0b020416020301021e01021780000a0910d44a2c495918513e54e50100dfa64f97d9b47766fc1943c6314ba3f2b2a103d71ad286dc5b1efb96a345b0c80100dbc8150b54241f559da6ef4baacea6d31902b4f4b1bdc09b34bf0502334b77549ca90456e5b83812082a8648ce3d030107020304bfe3cea9cee13486f8d518aa487fecab451f25467d2bf08e58f63e5fa525d5482133e6a79299c274b068ef0be448152ad65cf11cf764348588ca4f6a0bcf22b603010807fe0703027510012471a603cfee2968dce19f732721ddf03e966fd133b4e3c7a685b788705cbc46fb026dc94724b830c9edbaecd2fb2c662f23169516cacd1fe423f0475c364ecc10abcabcfd4bbbda1a36a1bd8861041813080009050256e5b838021b0c000a0910d44a2c495918513e4a4800ff49d589fa64024ad30be363a032e3a0e0e6f5db56ba4c73db850518bf0121b8f20100fd78e065f4c70ea5be9df319ea67e493b936fc78da834a71828043d3154af56e"
+
+const armoredPrivateKeyBlock = `-----BEGIN PGP PRIVATE KEY BLOCK-----
+Version: GnuPG v1.4.10 (GNU/Linux)
+
+lQHYBE2rFNoBBADFwqWQIW/DSqcB4yCQqnAFTJ27qS5AnB46ccAdw3u4Greeu3Bp
+idpoHdjULy7zSKlwR1EA873dO/k/e11Ml3dlAFUinWeejWaK2ugFP6JjiieSsrKn
+vWNicdCS4HTWn0X4sjl0ZiAygw6GNhqEQ3cpLeL0g8E9hnYzJKQ0LWJa0QARAQAB
+AAP/TB81EIo2VYNmTq0pK1ZXwUpxCrvAAIG3hwKjEzHcbQznsjNvPUihZ+NZQ6+X
+0HCfPAdPkGDCLCb6NavcSW+iNnLTrdDnSI6+3BbIONqWWdRDYJhqZCkqmG6zqSfL
+IdkJgCw94taUg5BWP/AAeQrhzjChvpMQTVKQL5mnuZbUCeMCAN5qrYMP2S9iKdnk
+VANIFj7656ARKt/nf4CBzxcpHTyB8+d2CtPDKCmlJP6vL8t58Jmih+kHJMvC0dzn
+gr5f5+sCAOOe5gt9e0am7AvQWhdbHVfJU0TQJx+m2OiCJAqGTB1nvtBLHdJnfdC9
+TnXXQ6ZXibqLyBies/xeY2sCKL5qtTMCAKnX9+9d/5yQxRyrQUHt1NYhaXZnJbHx
+q4ytu0eWz+5i68IYUSK69jJ1NWPM0T6SkqpB3KCAIv68VFm9PxqG1KmhSrQIVGVz
+dCBLZXmIuAQTAQIAIgUCTasU2gIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AA
+CgkQO9o98PRieSoLhgQAkLEZex02Qt7vGhZzMwuN0R22w3VwyYyjBx+fM3JFETy1
+ut4xcLJoJfIaF5ZS38UplgakHG0FQ+b49i8dMij0aZmDqGxrew1m4kBfjXw9B/v+
+eIqpODryb6cOSwyQFH0lQkXC040pjq9YqDsO5w0WYNXYKDnzRV0p4H1pweo2VDid
+AdgETasU2gEEAN46UPeWRqKHvA99arOxee38fBt2CI08iiWyI8T3J6ivtFGixSqV
+bRcPxYO/qLpVe5l84Nb3X71GfVXlc9hyv7CD6tcowL59hg1E/DC5ydI8K8iEpUmK
+/UnHdIY5h8/kqgGxkY/T/hgp5fRQgW1ZoZxLajVlMRZ8W4tFtT0DeA+JABEBAAEA
+A/0bE1jaaZKj6ndqcw86jd+QtD1SF+Cf21CWRNeLKnUds4FRRvclzTyUMuWPkUeX
+TaNNsUOFqBsf6QQ2oHUBBK4VCHffHCW4ZEX2cd6umz7mpHW6XzN4DECEzOVksXtc
+lUC1j4UB91DC/RNQqwX1IV2QLSwssVotPMPqhOi0ZLNY7wIA3n7DWKInxYZZ4K+6
+rQ+POsz6brEoRHwr8x6XlHenq1Oki855pSa1yXIARoTrSJkBtn5oI+f8AzrnN0BN
+oyeQAwIA/7E++3HDi5aweWrViiul9cd3rcsS0dEnksPhvS0ozCJiHsq/6GFmy7J8
+QSHZPteedBnZyNp5jR+H7cIfVN3KgwH/Skq4PsuPhDq5TKK6i8Pc1WW8MA6DXTdU
+nLkX7RGmMwjC0DBf7KWAlPjFaONAX3a8ndnz//fy1q7u2l9AZwrj1qa1iJ8EGAEC
+AAkFAk2rFNoCGwwACgkQO9o98PRieSo2/QP/WTzr4ioINVsvN1akKuekmEMI3LAp
+BfHwatufxxP1U+3Si/6YIk7kuPB9Hs+pRqCXzbvPRrI8NHZBmc8qIGthishdCYad
+AHcVnXjtxrULkQFGbGvhKURLvS9WnzD/m1K2zzwxzkPTzT9/Yf06O6Mal5AdugPL
+VrM0m72/jnpKo04=
+=zNCn
+-----END PGP PRIVATE KEY BLOCK-----`
+
+const e2ePublicKey = `-----BEGIN PGP PUBLIC KEY BLOCK-----
+Charset: UTF-8
+
+xv8AAABSBAAAAAATCCqGSM49AwEHAgME1LRoXSpOxtHXDUdmuvzchyg6005qIBJ4
+sfaSxX7QgH9RV2ONUhC+WiayCNADq+UMzuR/vunSr4aQffXvuGnR383/AAAAFDxk
+Z2lsQHlhaG9vLWluYy5jb20+wv8AAACGBBATCAA4/wAAAAWCVGvAG/8AAAACiwn/
+AAAACZC2VkQCOjdvYf8AAAAFlQgJCgv/AAAAA5YBAv8AAAACngEAAE1BAP0X8veD
+24IjmI5/C6ZAfVNXxgZZFhTAACFX75jUA3oD6AEAzoSwKf1aqH6oq62qhCN/pekX
++WAsVMBhNwzLpqtCRjLO/wAAAFYEAAAAABIIKoZIzj0DAQcCAwT50ain7vXiIRv8
+B1DO3x3cE/aattZ5sHNixJzRCXi2vQIA5QmOxZ6b5jjUekNbdHG3SZi1a2Ak5mfX
+fRxC/5VGAwEIB8L/AAAAZQQYEwgAGP8AAAAFglRrwBz/AAAACZC2VkQCOjdvYQAA
+FJAA9isX3xtGyMLYwp2F3nXm7QEdY5bq5VUcD/RJlj792VwA/1wH0pCzVLl4Q9F9
+ex7En5r7rHR5xwX82Msc+Rq9dSyO
+=7MrZ
+-----END PGP PUBLIC KEY BLOCK-----`
+
+const dsaKeyWithSHA512 = `9901a2044f04b07f110400db244efecc7316553ee08d179972aab87bb1214de7692593fcf5b6feb1c80fba268722dd464748539b85b81d574cd2d7ad0ca2444de4d849b8756bad7768c486c83a824f9bba4af773d11742bdfb4ac3b89ef8cc9452d4aad31a37e4b630d33927bff68e879284a1672659b8b298222fc68f370f3e24dccacc4a862442b9438b00a0ea444a24088dc23e26df7daf8f43cba3bffc4fe703fe3d6cd7fdca199d54ed8ae501c30e3ec7871ea9cdd4cf63cfe6fc82281d70a5b8bb493f922cd99fba5f088935596af087c8d818d5ec4d0b9afa7f070b3d7c1dd32a84fca08d8280b4890c8da1dde334de8e3cad8450eed2a4a4fcc2db7b8e5528b869a74a7f0189e11ef097ef1253582348de072bb07a9fa8ab838e993cef0ee203ff49298723e2d1f549b00559f886cd417a41692ce58d0ac1307dc71d85a8af21b0cf6eaa14baf2922d3a70389bedf17cc514ba0febbd107675a372fe84b90162a9e88b14d4b1c6be855b96b33fb198c46f058568817780435b6936167ebb3724b680f32bf27382ada2e37a879b3d9de2abe0c3f399350afd1ad438883f4791e2e3b4184453412068617368207472756e636174696f6e207465737488620413110a002205024f04b07f021b03060b090807030206150802090a0b0416020301021e01021780000a0910ef20e0cefca131581318009e2bf3bf047a44d75a9bacd00161ee04d435522397009a03a60d51bd8a568c6c021c8d7cf1be8d990d6417b0020003`
+
+const unknownHashFunctionHex = `8a00000040040001990006050253863c24000a09103b4fe6acc0b21f32ffff01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101`
+
+const missingHashFunctionHex = `8a00000040040001030006050253863c24000a09103b4fe6acc0b21f32ffff0101010101010101010101010101010101010101010101010101010101010101010101010101`
+
+const campbellQuine = `a0b001000300fcffa0b001000d00f2ff000300fcffa0b001000d00f2ff8270a01c00000500faff8270a01c00000500faff000500faff001400ebff8270a01c00000500faff000500faff001400ebff428821c400001400ebff428821c400001400ebff428821c400001400ebff428821c400001400ebff428821c400000000ffff000000ffff000b00f4ff428821c400000000ffff000000ffff000b00f4ff0233214c40000100feff000233214c40000100feff0000`
+
+const keyV4forVerifyingSignedMessageV3 = `-----BEGIN PGP PUBLIC KEY BLOCK-----
+Comment: GPGTools - https://gpgtools.org
+
+mI0EVfxoFQEEAMBIqmbDfYygcvP6Phr1wr1XI41IF7Qixqybs/foBF8qqblD9gIY
+BKpXjnBOtbkcVOJ0nljd3/sQIfH4E0vQwK5/4YRQSI59eKOqd6Fx+fWQOLG+uu6z
+tewpeCj9LLHvibx/Sc7VWRnrznia6ftrXxJ/wHMezSab3tnGC0YPVdGNABEBAAG0
+JEdvY3J5cHRvIFRlc3QgS2V5IDx0aGVtYXhAZ21haWwuY29tPoi5BBMBCgAjBQJV
+/GgVAhsDBwsJCAcDAgEGFQgCCQoLBBYCAwECHgECF4AACgkQeXnQmhdGW9PFVAP+
+K7TU0qX5ArvIONIxh/WAweyOk884c5cE8f+3NOPOOCRGyVy0FId5A7MmD5GOQh4H
+JseOZVEVCqlmngEvtHZb3U1VYtVGE5WZ+6rQhGsMcWP5qaT4soYwMBlSYxgYwQcx
+YhN9qOr292f9j2Y//TTIJmZT4Oa+lMxhWdqTfX+qMgG4jQRV/GgVAQQArhFSiij1
+b+hT3dnapbEU+23Z1yTu1DfF6zsxQ4XQWEV3eR8v+8mEDDNcz8oyyF56k6UQ3rXi
+UMTIwRDg4V6SbZmaFbZYCOwp/EmXJ3rfhm7z7yzXj2OFN22luuqbyVhuL7LRdB0M
+pxgmjXb4tTvfgKd26x34S+QqUJ7W6uprY4sAEQEAAYifBBgBCgAJBQJV/GgVAhsM
+AAoJEHl50JoXRlvT7y8D/02ckx4OMkKBZo7viyrBw0MLG92i+DC2bs35PooHR6zz
+786mitjOp5z2QWNLBvxC70S0qVfCIz8jKupO1J6rq6Z8CcbLF3qjm6h1omUBf8Nd
+EfXKD2/2HV6zMKVknnKzIEzauh+eCKS2CeJUSSSryap/QLVAjRnckaES/OsEWhNB
+=RZia
+-----END PGP PUBLIC KEY BLOCK-----
+`
+
+const signedMessageV3 = `-----BEGIN PGP MESSAGE-----
+Comment: GPGTools - https://gpgtools.org
+
+owGbwMvMwMVYWXlhlrhb9GXG03JJDKF/MtxDMjKLFYAoUaEktbhEITe1uDgxPVWP
+q5NhKjMrWAVcC9evD8z/bF/uWNjqtk/X3y5/38XGRQHm/57rrDRYuGnTw597Xqka
+uM3137/hH3Os+Jf2dc0fXOITKwJvXJvecPVs0ta+Vg7ZO1MLn8w58Xx+6L58mbka
+DGHyU9yTueZE8D+QF/Tz28Y78dqtF56R1VPn9Xw4uJqrWYdd7b3vIZ1V6R4Nh05d
+iT57d/OhWwA=
+=hG7R
+-----END PGP MESSAGE-----
+`
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/s2k/s2k.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/s2k/s2k.go
new file mode 100644
index 000000000..4b9a44ca2
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/s2k/s2k.go
@@ -0,0 +1,273 @@
+// Copyright 2011 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 s2k implements the various OpenPGP string-to-key transforms as
+// specified in RFC 4800 section 3.7.1.
+package s2k // import "golang.org/x/crypto/openpgp/s2k"
+
+import (
+ "crypto"
+ "hash"
+ "io"
+ "strconv"
+
+ "golang.org/x/crypto/openpgp/errors"
+)
+
+// Config collects configuration parameters for s2k key-stretching
+// transformatioms. A nil *Config is valid and results in all default
+// values. Currently, Config is used only by the Serialize function in
+// this package.
+type Config struct {
+ // Hash is the default hash function to be used. If
+ // nil, SHA1 is used.
+ Hash crypto.Hash
+ // S2KCount is only used for symmetric encryption. It
+ // determines the strength of the passphrase stretching when
+ // the said passphrase is hashed to produce a key. S2KCount
+ // should be between 1024 and 65011712, inclusive. If Config
+ // is nil or S2KCount is 0, the value 65536 used. Not all
+ // values in the above range can be represented. S2KCount will
+ // be rounded up to the next representable value if it cannot
+ // be encoded exactly. When set, it is strongly encrouraged to
+ // use a value that is at least 65536. See RFC 4880 Section
+ // 3.7.1.3.
+ S2KCount int
+}
+
+func (c *Config) hash() crypto.Hash {
+ if c == nil || uint(c.Hash) == 0 {
+ // SHA1 is the historical default in this package.
+ return crypto.SHA1
+ }
+
+ return c.Hash
+}
+
+func (c *Config) encodedCount() uint8 {
+ if c == nil || c.S2KCount == 0 {
+ return 96 // The common case. Correspoding to 65536
+ }
+
+ i := c.S2KCount
+ switch {
+ // Behave like GPG. Should we make 65536 the lowest value used?
+ case i < 1024:
+ i = 1024
+ case i > 65011712:
+ i = 65011712
+ }
+
+ return encodeCount(i)
+}
+
+// encodeCount converts an iterative "count" in the range 1024 to
+// 65011712, inclusive, to an encoded count. The return value is the
+// octet that is actually stored in the GPG file. encodeCount panics
+// if i is not in the above range (encodedCount above takes care to
+// pass i in the correct range). See RFC 4880 Section 3.7.7.1.
+func encodeCount(i int) uint8 {
+ if i < 1024 || i > 65011712 {
+ panic("count arg i outside the required range")
+ }
+
+ for encoded := 0; encoded < 256; encoded++ {
+ count := decodeCount(uint8(encoded))
+ if count >= i {
+ return uint8(encoded)
+ }
+ }
+
+ return 255
+}
+
+// decodeCount returns the s2k mode 3 iterative "count" corresponding to
+// the encoded octet c.
+func decodeCount(c uint8) int {
+ return (16 + int(c&15)) << (uint32(c>>4) + 6)
+}
+
+// Simple writes to out the result of computing the Simple S2K function (RFC
+// 4880, section 3.7.1.1) using the given hash and input passphrase.
+func Simple(out []byte, h hash.Hash, in []byte) {
+ Salted(out, h, in, nil)
+}
+
+var zero [1]byte
+
+// Salted writes to out the result of computing the Salted S2K function (RFC
+// 4880, section 3.7.1.2) using the given hash, input passphrase and salt.
+func Salted(out []byte, h hash.Hash, in []byte, salt []byte) {
+ done := 0
+ var digest []byte
+
+ for i := 0; done < len(out); i++ {
+ h.Reset()
+ for j := 0; j < i; j++ {
+ h.Write(zero[:])
+ }
+ h.Write(salt)
+ h.Write(in)
+ digest = h.Sum(digest[:0])
+ n := copy(out[done:], digest)
+ done += n
+ }
+}
+
+// Iterated writes to out the result of computing the Iterated and Salted S2K
+// function (RFC 4880, section 3.7.1.3) using the given hash, input passphrase,
+// salt and iteration count.
+func Iterated(out []byte, h hash.Hash, in []byte, salt []byte, count int) {
+ combined := make([]byte, len(in)+len(salt))
+ copy(combined, salt)
+ copy(combined[len(salt):], in)
+
+ if count < len(combined) {
+ count = len(combined)
+ }
+
+ done := 0
+ var digest []byte
+ for i := 0; done < len(out); i++ {
+ h.Reset()
+ for j := 0; j < i; j++ {
+ h.Write(zero[:])
+ }
+ written := 0
+ for written < count {
+ if written+len(combined) > count {
+ todo := count - written
+ h.Write(combined[:todo])
+ written = count
+ } else {
+ h.Write(combined)
+ written += len(combined)
+ }
+ }
+ digest = h.Sum(digest[:0])
+ n := copy(out[done:], digest)
+ done += n
+ }
+}
+
+// Parse reads a binary specification for a string-to-key transformation from r
+// and returns a function which performs that transform.
+func Parse(r io.Reader) (f func(out, in []byte), err error) {
+ var buf [9]byte
+
+ _, err = io.ReadFull(r, buf[:2])
+ if err != nil {
+ return
+ }
+
+ hash, ok := HashIdToHash(buf[1])
+ if !ok {
+ return nil, errors.UnsupportedError("hash for S2K function: " + strconv.Itoa(int(buf[1])))
+ }
+ if !hash.Available() {
+ return nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hash)))
+ }
+ h := hash.New()
+
+ switch buf[0] {
+ case 0:
+ f := func(out, in []byte) {
+ Simple(out, h, in)
+ }
+ return f, nil
+ case 1:
+ _, err = io.ReadFull(r, buf[:8])
+ if err != nil {
+ return
+ }
+ f := func(out, in []byte) {
+ Salted(out, h, in, buf[:8])
+ }
+ return f, nil
+ case 3:
+ _, err = io.ReadFull(r, buf[:9])
+ if err != nil {
+ return
+ }
+ count := decodeCount(buf[8])
+ f := func(out, in []byte) {
+ Iterated(out, h, in, buf[:8], count)
+ }
+ return f, nil
+ }
+
+ return nil, errors.UnsupportedError("S2K function")
+}
+
+// Serialize salts and stretches the given passphrase and writes the
+// resulting key into key. It also serializes an S2K descriptor to
+// w. The key stretching can be configured with c, which may be
+// nil. In that case, sensible defaults will be used.
+func Serialize(w io.Writer, key []byte, rand io.Reader, passphrase []byte, c *Config) error {
+ var buf [11]byte
+ buf[0] = 3 /* iterated and salted */
+ buf[1], _ = HashToHashId(c.hash())
+ salt := buf[2:10]
+ if _, err := io.ReadFull(rand, salt); err != nil {
+ return err
+ }
+ encodedCount := c.encodedCount()
+ count := decodeCount(encodedCount)
+ buf[10] = encodedCount
+ if _, err := w.Write(buf[:]); err != nil {
+ return err
+ }
+
+ Iterated(key, c.hash().New(), passphrase, salt, count)
+ return nil
+}
+
+// hashToHashIdMapping contains pairs relating OpenPGP's hash identifier with
+// Go's crypto.Hash type. See RFC 4880, section 9.4.
+var hashToHashIdMapping = []struct {
+ id byte
+ hash crypto.Hash
+ name string
+}{
+ {1, crypto.MD5, "MD5"},
+ {2, crypto.SHA1, "SHA1"},
+ {3, crypto.RIPEMD160, "RIPEMD160"},
+ {8, crypto.SHA256, "SHA256"},
+ {9, crypto.SHA384, "SHA384"},
+ {10, crypto.SHA512, "SHA512"},
+ {11, crypto.SHA224, "SHA224"},
+}
+
+// HashIdToHash returns a crypto.Hash which corresponds to the given OpenPGP
+// hash id.
+func HashIdToHash(id byte) (h crypto.Hash, ok bool) {
+ for _, m := range hashToHashIdMapping {
+ if m.id == id {
+ return m.hash, true
+ }
+ }
+ return 0, false
+}
+
+// HashIdToString returns the name of the hash function corresponding to the
+// given OpenPGP hash id.
+func HashIdToString(id byte) (name string, ok bool) {
+ for _, m := range hashToHashIdMapping {
+ if m.id == id {
+ return m.name, true
+ }
+ }
+
+ return "", false
+}
+
+// HashIdToHash returns an OpenPGP hash id which corresponds the given Hash.
+func HashToHashId(h crypto.Hash) (id byte, ok bool) {
+ for _, m := range hashToHashIdMapping {
+ if m.hash == h {
+ return m.id, true
+ }
+ }
+ return 0, false
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/s2k/s2k_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/s2k/s2k_test.go
new file mode 100644
index 000000000..183d26056
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/s2k/s2k_test.go
@@ -0,0 +1,137 @@
+// Copyright 2011 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 s2k
+
+import (
+ "bytes"
+ "crypto"
+ _ "crypto/md5"
+ "crypto/rand"
+ "crypto/sha1"
+ _ "crypto/sha256"
+ _ "crypto/sha512"
+ "encoding/hex"
+ "testing"
+
+ _ "golang.org/x/crypto/ripemd160"
+)
+
+var saltedTests = []struct {
+ in, out string
+}{
+ {"hello", "10295ac1"},
+ {"world", "ac587a5e"},
+ {"foo", "4dda8077"},
+ {"bar", "bd8aac6b9ea9cae04eae6a91c6133b58b5d9a61c14f355516ed9370456"},
+ {"x", "f1d3f289"},
+ {"xxxxxxxxxxxxxxxxxxxxxxx", "e00d7b45"},
+}
+
+func TestSalted(t *testing.T) {
+ h := sha1.New()
+ salt := [4]byte{1, 2, 3, 4}
+
+ for i, test := range saltedTests {
+ expected, _ := hex.DecodeString(test.out)
+ out := make([]byte, len(expected))
+ Salted(out, h, []byte(test.in), salt[:])
+ if !bytes.Equal(expected, out) {
+ t.Errorf("#%d, got: %x want: %x", i, out, expected)
+ }
+ }
+}
+
+var iteratedTests = []struct {
+ in, out string
+}{
+ {"hello", "83126105"},
+ {"world", "6fa317f9"},
+ {"foo", "8fbc35b9"},
+ {"bar", "2af5a99b54f093789fd657f19bd245af7604d0f6ae06f66602a46a08ae"},
+ {"x", "5a684dfe"},
+ {"xxxxxxxxxxxxxxxxxxxxxxx", "18955174"},
+}
+
+func TestIterated(t *testing.T) {
+ h := sha1.New()
+ salt := [4]byte{4, 3, 2, 1}
+
+ for i, test := range iteratedTests {
+ expected, _ := hex.DecodeString(test.out)
+ out := make([]byte, len(expected))
+ Iterated(out, h, []byte(test.in), salt[:], 31)
+ if !bytes.Equal(expected, out) {
+ t.Errorf("#%d, got: %x want: %x", i, out, expected)
+ }
+ }
+}
+
+var parseTests = []struct {
+ spec, in, out string
+}{
+ /* Simple with SHA1 */
+ {"0002", "hello", "aaf4c61d"},
+ /* Salted with SHA1 */
+ {"01020102030405060708", "hello", "f4f7d67e"},
+ /* Iterated with SHA1 */
+ {"03020102030405060708f1", "hello", "f2a57b7c"},
+}
+
+func TestParse(t *testing.T) {
+ for i, test := range parseTests {
+ spec, _ := hex.DecodeString(test.spec)
+ buf := bytes.NewBuffer(spec)
+ f, err := Parse(buf)
+ if err != nil {
+ t.Errorf("%d: Parse returned error: %s", i, err)
+ continue
+ }
+
+ expected, _ := hex.DecodeString(test.out)
+ out := make([]byte, len(expected))
+ f(out, []byte(test.in))
+ if !bytes.Equal(out, expected) {
+ t.Errorf("%d: output got: %x want: %x", i, out, expected)
+ }
+ if testing.Short() {
+ break
+ }
+ }
+}
+
+func TestSerialize(t *testing.T) {
+ hashes := []crypto.Hash{crypto.MD5, crypto.SHA1, crypto.RIPEMD160,
+ crypto.SHA256, crypto.SHA384, crypto.SHA512, crypto.SHA224}
+ testCounts := []int{-1, 0, 1024, 65536, 4063232, 65011712}
+ for _, h := range hashes {
+ for _, c := range testCounts {
+ testSerializeConfig(t, &Config{Hash: h, S2KCount: c})
+ }
+ }
+}
+
+func testSerializeConfig(t *testing.T, c *Config) {
+ t.Logf("Running testSerializeConfig() with config: %+v", c)
+
+ buf := bytes.NewBuffer(nil)
+ key := make([]byte, 16)
+ passphrase := []byte("testing")
+ err := Serialize(buf, key, rand.Reader, passphrase, c)
+ if err != nil {
+ t.Errorf("failed to serialize: %s", err)
+ return
+ }
+
+ f, err := Parse(buf)
+ if err != nil {
+ t.Errorf("failed to reparse: %s", err)
+ return
+ }
+ key2 := make([]byte, len(key))
+ f(key2, passphrase)
+ if !bytes.Equal(key2, key) {
+ t.Errorf("keys don't match: %x (serialied) vs %x (parsed)", key, key2)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/write.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/write.go
new file mode 100644
index 000000000..65a304cc8
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/write.go
@@ -0,0 +1,378 @@
+// Copyright 2011 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 openpgp
+
+import (
+ "crypto"
+ "hash"
+ "io"
+ "strconv"
+ "time"
+
+ "golang.org/x/crypto/openpgp/armor"
+ "golang.org/x/crypto/openpgp/errors"
+ "golang.org/x/crypto/openpgp/packet"
+ "golang.org/x/crypto/openpgp/s2k"
+)
+
+// DetachSign signs message with the private key from signer (which must
+// already have been decrypted) and writes the signature to w.
+// If config is nil, sensible defaults will be used.
+func DetachSign(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) error {
+ return detachSign(w, signer, message, packet.SigTypeBinary, config)
+}
+
+// ArmoredDetachSign signs message with the private key from signer (which
+// must already have been decrypted) and writes an armored signature to w.
+// If config is nil, sensible defaults will be used.
+func ArmoredDetachSign(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) (err error) {
+ return armoredDetachSign(w, signer, message, packet.SigTypeBinary, config)
+}
+
+// DetachSignText signs message (after canonicalising the line endings) with
+// the private key from signer (which must already have been decrypted) and
+// writes the signature to w.
+// If config is nil, sensible defaults will be used.
+func DetachSignText(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) error {
+ return detachSign(w, signer, message, packet.SigTypeText, config)
+}
+
+// ArmoredDetachSignText signs message (after canonicalising the line endings)
+// with the private key from signer (which must already have been decrypted)
+// and writes an armored signature to w.
+// If config is nil, sensible defaults will be used.
+func ArmoredDetachSignText(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) error {
+ return armoredDetachSign(w, signer, message, packet.SigTypeText, config)
+}
+
+func armoredDetachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.SignatureType, config *packet.Config) (err error) {
+ out, err := armor.Encode(w, SignatureType, nil)
+ if err != nil {
+ return
+ }
+ err = detachSign(out, signer, message, sigType, config)
+ if err != nil {
+ return
+ }
+ return out.Close()
+}
+
+func detachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.SignatureType, config *packet.Config) (err error) {
+ if signer.PrivateKey == nil {
+ return errors.InvalidArgumentError("signing key doesn't have a private key")
+ }
+ if signer.PrivateKey.Encrypted {
+ return errors.InvalidArgumentError("signing key is encrypted")
+ }
+
+ sig := new(packet.Signature)
+ sig.SigType = sigType
+ sig.PubKeyAlgo = signer.PrivateKey.PubKeyAlgo
+ sig.Hash = config.Hash()
+ sig.CreationTime = config.Now()
+ sig.IssuerKeyId = &signer.PrivateKey.KeyId
+
+ h, wrappedHash, err := hashForSignature(sig.Hash, sig.SigType)
+ if err != nil {
+ return
+ }
+ io.Copy(wrappedHash, message)
+
+ err = sig.Sign(h, signer.PrivateKey, config)
+ if err != nil {
+ return
+ }
+
+ return sig.Serialize(w)
+}
+
+// FileHints contains metadata about encrypted files. This metadata is, itself,
+// encrypted.
+type FileHints struct {
+ // IsBinary can be set to hint that the contents are binary data.
+ IsBinary bool
+ // FileName hints at the name of the file that should be written. It's
+ // truncated to 255 bytes if longer. It may be empty to suggest that the
+ // file should not be written to disk. It may be equal to "_CONSOLE" to
+ // suggest the data should not be written to disk.
+ FileName string
+ // ModTime contains the modification time of the file, or the zero time if not applicable.
+ ModTime time.Time
+}
+
+// SymmetricallyEncrypt acts like gpg -c: it encrypts a file with a passphrase.
+// The resulting WriteCloser must be closed after the contents of the file have
+// been written.
+// If config is nil, sensible defaults will be used.
+func SymmetricallyEncrypt(ciphertext io.Writer, passphrase []byte, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) {
+ if hints == nil {
+ hints = &FileHints{}
+ }
+
+ key, err := packet.SerializeSymmetricKeyEncrypted(ciphertext, passphrase, config)
+ if err != nil {
+ return
+ }
+ w, err := packet.SerializeSymmetricallyEncrypted(ciphertext, config.Cipher(), key, config)
+ if err != nil {
+ return
+ }
+
+ literaldata := w
+ if algo := config.Compression(); algo != packet.CompressionNone {
+ var compConfig *packet.CompressionConfig
+ if config != nil {
+ compConfig = config.CompressionConfig
+ }
+ literaldata, err = packet.SerializeCompressed(w, algo, compConfig)
+ if err != nil {
+ return
+ }
+ }
+
+ var epochSeconds uint32
+ if !hints.ModTime.IsZero() {
+ epochSeconds = uint32(hints.ModTime.Unix())
+ }
+ return packet.SerializeLiteral(literaldata, hints.IsBinary, hints.FileName, epochSeconds)
+}
+
+// intersectPreferences mutates and returns a prefix of a that contains only
+// the values in the intersection of a and b. The order of a is preserved.
+func intersectPreferences(a []uint8, b []uint8) (intersection []uint8) {
+ var j int
+ for _, v := range a {
+ for _, v2 := range b {
+ if v == v2 {
+ a[j] = v
+ j++
+ break
+ }
+ }
+ }
+
+ return a[:j]
+}
+
+func hashToHashId(h crypto.Hash) uint8 {
+ v, ok := s2k.HashToHashId(h)
+ if !ok {
+ panic("tried to convert unknown hash")
+ }
+ return v
+}
+
+// Encrypt encrypts a message to a number of recipients and, optionally, signs
+// it. hints contains optional information, that is also encrypted, that aids
+// the recipients in processing the message. The resulting WriteCloser must
+// be closed after the contents of the file have been written.
+// If config is nil, sensible defaults will be used.
+func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) {
+ var signer *packet.PrivateKey
+ if signed != nil {
+ signKey, ok := signed.signingKey(config.Now())
+ if !ok {
+ return nil, errors.InvalidArgumentError("no valid signing keys")
+ }
+ signer = signKey.PrivateKey
+ if signer == nil {
+ return nil, errors.InvalidArgumentError("no private key in signing key")
+ }
+ if signer.Encrypted {
+ return nil, errors.InvalidArgumentError("signing key must be decrypted")
+ }
+ }
+
+ // These are the possible ciphers that we'll use for the message.
+ candidateCiphers := []uint8{
+ uint8(packet.CipherAES128),
+ uint8(packet.CipherAES256),
+ uint8(packet.CipherCAST5),
+ }
+ // These are the possible hash functions that we'll use for the signature.
+ candidateHashes := []uint8{
+ hashToHashId(crypto.SHA256),
+ hashToHashId(crypto.SHA512),
+ hashToHashId(crypto.SHA1),
+ hashToHashId(crypto.RIPEMD160),
+ }
+ // In the event that a recipient doesn't specify any supported ciphers
+ // or hash functions, these are the ones that we assume that every
+ // implementation supports.
+ defaultCiphers := candidateCiphers[len(candidateCiphers)-1:]
+ defaultHashes := candidateHashes[len(candidateHashes)-1:]
+
+ encryptKeys := make([]Key, len(to))
+ for i := range to {
+ var ok bool
+ encryptKeys[i], ok = to[i].encryptionKey(config.Now())
+ if !ok {
+ return nil, errors.InvalidArgumentError("cannot encrypt a message to key id " + strconv.FormatUint(to[i].PrimaryKey.KeyId, 16) + " because it has no encryption keys")
+ }
+
+ sig := to[i].primaryIdentity().SelfSignature
+
+ preferredSymmetric := sig.PreferredSymmetric
+ if len(preferredSymmetric) == 0 {
+ preferredSymmetric = defaultCiphers
+ }
+ preferredHashes := sig.PreferredHash
+ if len(preferredHashes) == 0 {
+ preferredHashes = defaultHashes
+ }
+ candidateCiphers = intersectPreferences(candidateCiphers, preferredSymmetric)
+ candidateHashes = intersectPreferences(candidateHashes, preferredHashes)
+ }
+
+ if len(candidateCiphers) == 0 || len(candidateHashes) == 0 {
+ return nil, errors.InvalidArgumentError("cannot encrypt because recipient set shares no common algorithms")
+ }
+
+ cipher := packet.CipherFunction(candidateCiphers[0])
+ // If the cipher specified by config is a candidate, we'll use that.
+ configuredCipher := config.Cipher()
+ for _, c := range candidateCiphers {
+ cipherFunc := packet.CipherFunction(c)
+ if cipherFunc == configuredCipher {
+ cipher = cipherFunc
+ break
+ }
+ }
+
+ var hash crypto.Hash
+ for _, hashId := range candidateHashes {
+ if h, ok := s2k.HashIdToHash(hashId); ok && h.Available() {
+ hash = h
+ break
+ }
+ }
+
+ // If the hash specified by config is a candidate, we'll use that.
+ if configuredHash := config.Hash(); configuredHash.Available() {
+ for _, hashId := range candidateHashes {
+ if h, ok := s2k.HashIdToHash(hashId); ok && h == configuredHash {
+ hash = h
+ break
+ }
+ }
+ }
+
+ if hash == 0 {
+ hashId := candidateHashes[0]
+ name, ok := s2k.HashIdToString(hashId)
+ if !ok {
+ name = "#" + strconv.Itoa(int(hashId))
+ }
+ return nil, errors.InvalidArgumentError("cannot encrypt because no candidate hash functions are compiled in. (Wanted " + name + " in this case.)")
+ }
+
+ symKey := make([]byte, cipher.KeySize())
+ if _, err := io.ReadFull(config.Random(), symKey); err != nil {
+ return nil, err
+ }
+
+ for _, key := range encryptKeys {
+ if err := packet.SerializeEncryptedKey(ciphertext, key.PublicKey, cipher, symKey, config); err != nil {
+ return nil, err
+ }
+ }
+
+ encryptedData, err := packet.SerializeSymmetricallyEncrypted(ciphertext, cipher, symKey, config)
+ if err != nil {
+ return
+ }
+
+ if signer != nil {
+ ops := &packet.OnePassSignature{
+ SigType: packet.SigTypeBinary,
+ Hash: hash,
+ PubKeyAlgo: signer.PubKeyAlgo,
+ KeyId: signer.KeyId,
+ IsLast: true,
+ }
+ if err := ops.Serialize(encryptedData); err != nil {
+ return nil, err
+ }
+ }
+
+ if hints == nil {
+ hints = &FileHints{}
+ }
+
+ w := encryptedData
+ if signer != nil {
+ // If we need to write a signature packet after the literal
+ // data then we need to stop literalData from closing
+ // encryptedData.
+ w = noOpCloser{encryptedData}
+
+ }
+ var epochSeconds uint32
+ if !hints.ModTime.IsZero() {
+ epochSeconds = uint32(hints.ModTime.Unix())
+ }
+ literalData, err := packet.SerializeLiteral(w, hints.IsBinary, hints.FileName, epochSeconds)
+ if err != nil {
+ return nil, err
+ }
+
+ if signer != nil {
+ return signatureWriter{encryptedData, literalData, hash, hash.New(), signer, config}, nil
+ }
+ return literalData, nil
+}
+
+// signatureWriter hashes the contents of a message while passing it along to
+// literalData. When closed, it closes literalData, writes a signature packet
+// to encryptedData and then also closes encryptedData.
+type signatureWriter struct {
+ encryptedData io.WriteCloser
+ literalData io.WriteCloser
+ hashType crypto.Hash
+ h hash.Hash
+ signer *packet.PrivateKey
+ config *packet.Config
+}
+
+func (s signatureWriter) Write(data []byte) (int, error) {
+ s.h.Write(data)
+ return s.literalData.Write(data)
+}
+
+func (s signatureWriter) Close() error {
+ sig := &packet.Signature{
+ SigType: packet.SigTypeBinary,
+ PubKeyAlgo: s.signer.PubKeyAlgo,
+ Hash: s.hashType,
+ CreationTime: s.config.Now(),
+ IssuerKeyId: &s.signer.KeyId,
+ }
+
+ if err := sig.Sign(s.h, s.signer, s.config); err != nil {
+ return err
+ }
+ if err := s.literalData.Close(); err != nil {
+ return err
+ }
+ if err := sig.Serialize(s.encryptedData); err != nil {
+ return err
+ }
+ return s.encryptedData.Close()
+}
+
+// noOpCloser is like an ioutil.NopCloser, but for an io.Writer.
+// TODO: we have two of these in OpenPGP packages alone. This probably needs
+// to be promoted somewhere more common.
+type noOpCloser struct {
+ w io.Writer
+}
+
+func (c noOpCloser) Write(data []byte) (n int, err error) {
+ return c.w.Write(data)
+}
+
+func (c noOpCloser) Close() error {
+ return nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/write_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/write_test.go
new file mode 100644
index 000000000..f2d50a0cf
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/openpgp/write_test.go
@@ -0,0 +1,273 @@
+// Copyright 2011 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 openpgp
+
+import (
+ "bytes"
+ "io"
+ "io/ioutil"
+ "testing"
+ "time"
+
+ "golang.org/x/crypto/openpgp/packet"
+)
+
+func TestSignDetached(t *testing.T) {
+ kring, _ := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex))
+ out := bytes.NewBuffer(nil)
+ message := bytes.NewBufferString(signedInput)
+ err := DetachSign(out, kring[0], message, nil)
+ if err != nil {
+ t.Error(err)
+ }
+
+ testDetachedSignature(t, kring, out, signedInput, "check", testKey1KeyId)
+}
+
+func TestSignTextDetached(t *testing.T) {
+ kring, _ := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex))
+ out := bytes.NewBuffer(nil)
+ message := bytes.NewBufferString(signedInput)
+ err := DetachSignText(out, kring[0], message, nil)
+ if err != nil {
+ t.Error(err)
+ }
+
+ testDetachedSignature(t, kring, out, signedInput, "check", testKey1KeyId)
+}
+
+func TestSignDetachedDSA(t *testing.T) {
+ kring, _ := ReadKeyRing(readerFromHex(dsaTestKeyPrivateHex))
+ out := bytes.NewBuffer(nil)
+ message := bytes.NewBufferString(signedInput)
+ err := DetachSign(out, kring[0], message, nil)
+ if err != nil {
+ t.Error(err)
+ }
+
+ testDetachedSignature(t, kring, out, signedInput, "check", testKey3KeyId)
+}
+
+func TestSignDetachedP256(t *testing.T) {
+ kring, _ := ReadKeyRing(readerFromHex(p256TestKeyPrivateHex))
+ kring[0].PrivateKey.Decrypt([]byte("passphrase"))
+
+ out := bytes.NewBuffer(nil)
+ message := bytes.NewBufferString(signedInput)
+ err := DetachSign(out, kring[0], message, nil)
+ if err != nil {
+ t.Error(err)
+ }
+
+ testDetachedSignature(t, kring, out, signedInput, "check", testKeyP256KeyId)
+}
+
+func TestNewEntity(t *testing.T) {
+ if testing.Short() {
+ return
+ }
+
+ // Check bit-length with no config.
+ e, err := NewEntity("Test User", "test", "test@example.com", nil)
+ if err != nil {
+ t.Errorf("failed to create entity: %s", err)
+ return
+ }
+ bl, err := e.PrimaryKey.BitLength()
+ if err != nil {
+ t.Errorf("failed to find bit length: %s", err)
+ }
+ if int(bl) != defaultRSAKeyBits {
+ t.Errorf("BitLength %v, expected %v", int(bl), defaultRSAKeyBits)
+ }
+
+ // Check bit-length with a config.
+ cfg := &packet.Config{RSABits: 1024}
+ e, err = NewEntity("Test User", "test", "test@example.com", cfg)
+ if err != nil {
+ t.Errorf("failed to create entity: %s", err)
+ return
+ }
+ bl, err = e.PrimaryKey.BitLength()
+ if err != nil {
+ t.Errorf("failed to find bit length: %s", err)
+ }
+ if int(bl) != cfg.RSABits {
+ t.Errorf("BitLength %v, expected %v", bl, cfg.RSABits)
+ }
+
+ w := bytes.NewBuffer(nil)
+ if err := e.SerializePrivate(w, nil); err != nil {
+ t.Errorf("failed to serialize entity: %s", err)
+ return
+ }
+ serialized := w.Bytes()
+
+ el, err := ReadKeyRing(w)
+ if err != nil {
+ t.Errorf("failed to reparse entity: %s", err)
+ return
+ }
+
+ if len(el) != 1 {
+ t.Errorf("wrong number of entities found, got %d, want 1", len(el))
+ }
+
+ w = bytes.NewBuffer(nil)
+ if err := e.SerializePrivate(w, nil); err != nil {
+ t.Errorf("failed to serialize entity second time: %s", err)
+ return
+ }
+
+ if !bytes.Equal(w.Bytes(), serialized) {
+ t.Errorf("results differed")
+ }
+}
+
+func TestSymmetricEncryption(t *testing.T) {
+ buf := new(bytes.Buffer)
+ plaintext, err := SymmetricallyEncrypt(buf, []byte("testing"), nil, nil)
+ if err != nil {
+ t.Errorf("error writing headers: %s", err)
+ return
+ }
+ message := []byte("hello world\n")
+ _, err = plaintext.Write(message)
+ if err != nil {
+ t.Errorf("error writing to plaintext writer: %s", err)
+ }
+ err = plaintext.Close()
+ if err != nil {
+ t.Errorf("error closing plaintext writer: %s", err)
+ }
+
+ md, err := ReadMessage(buf, nil, func(keys []Key, symmetric bool) ([]byte, error) {
+ return []byte("testing"), nil
+ }, nil)
+ if err != nil {
+ t.Errorf("error rereading message: %s", err)
+ }
+ messageBuf := bytes.NewBuffer(nil)
+ _, err = io.Copy(messageBuf, md.UnverifiedBody)
+ if err != nil {
+ t.Errorf("error rereading message: %s", err)
+ }
+ if !bytes.Equal(message, messageBuf.Bytes()) {
+ t.Errorf("recovered message incorrect got '%s', want '%s'", messageBuf.Bytes(), message)
+ }
+}
+
+var testEncryptionTests = []struct {
+ keyRingHex string
+ isSigned bool
+}{
+ {
+ testKeys1And2PrivateHex,
+ false,
+ },
+ {
+ testKeys1And2PrivateHex,
+ true,
+ },
+ {
+ dsaElGamalTestKeysHex,
+ false,
+ },
+ {
+ dsaElGamalTestKeysHex,
+ true,
+ },
+}
+
+func TestEncryption(t *testing.T) {
+ for i, test := range testEncryptionTests {
+ kring, _ := ReadKeyRing(readerFromHex(test.keyRingHex))
+
+ passphrase := []byte("passphrase")
+ for _, entity := range kring {
+ if entity.PrivateKey != nil && entity.PrivateKey.Encrypted {
+ err := entity.PrivateKey.Decrypt(passphrase)
+ if err != nil {
+ t.Errorf("#%d: failed to decrypt key", i)
+ }
+ }
+ for _, subkey := range entity.Subkeys {
+ if subkey.PrivateKey != nil && subkey.PrivateKey.Encrypted {
+ err := subkey.PrivateKey.Decrypt(passphrase)
+ if err != nil {
+ t.Errorf("#%d: failed to decrypt subkey", i)
+ }
+ }
+ }
+ }
+
+ var signed *Entity
+ if test.isSigned {
+ signed = kring[0]
+ }
+
+ buf := new(bytes.Buffer)
+ w, err := Encrypt(buf, kring[:1], signed, nil /* no hints */, nil)
+ if err != nil {
+ t.Errorf("#%d: error in Encrypt: %s", i, err)
+ continue
+ }
+
+ const message = "testing"
+ _, err = w.Write([]byte(message))
+ if err != nil {
+ t.Errorf("#%d: error writing plaintext: %s", i, err)
+ continue
+ }
+ err = w.Close()
+ if err != nil {
+ t.Errorf("#%d: error closing WriteCloser: %s", i, err)
+ continue
+ }
+
+ md, err := ReadMessage(buf, kring, nil /* no prompt */, nil)
+ if err != nil {
+ t.Errorf("#%d: error reading message: %s", i, err)
+ continue
+ }
+
+ testTime, _ := time.Parse("2006-01-02", "2013-07-01")
+ if test.isSigned {
+ signKey, _ := kring[0].signingKey(testTime)
+ expectedKeyId := signKey.PublicKey.KeyId
+ if md.SignedByKeyId != expectedKeyId {
+ t.Errorf("#%d: message signed by wrong key id, got: %v, want: %v", i, *md.SignedBy, expectedKeyId)
+ }
+ if md.SignedBy == nil {
+ t.Errorf("#%d: failed to find the signing Entity", i)
+ }
+ }
+
+ plaintext, err := ioutil.ReadAll(md.UnverifiedBody)
+ if err != nil {
+ t.Errorf("#%d: error reading encrypted contents: %s", i, err)
+ continue
+ }
+
+ encryptKey, _ := kring[0].encryptionKey(testTime)
+ expectedKeyId := encryptKey.PublicKey.KeyId
+ if len(md.EncryptedToKeyIds) != 1 || md.EncryptedToKeyIds[0] != expectedKeyId {
+ t.Errorf("#%d: expected message to be encrypted to %v, but got %#v", i, expectedKeyId, md.EncryptedToKeyIds)
+ }
+
+ if string(plaintext) != message {
+ t.Errorf("#%d: got: %s, want: %s", i, string(plaintext), message)
+ }
+
+ if test.isSigned {
+ if md.SignatureError != nil {
+ t.Errorf("#%d: signature error: %s", i, md.SignatureError)
+ }
+ if md.Signature == nil {
+ t.Error("signature missing")
+ }
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/otr/libotr_test_helper.c b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/otr/libotr_test_helper.c
new file mode 100644
index 000000000..b3ca072d4
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/otr/libotr_test_helper.c
@@ -0,0 +1,197 @@
+// Copyright 2012 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.
+
+// This code can be compiled and used to test the otr package against libotr.
+// See otr_test.go.
+
+// +build ignore
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <proto.h>
+#include <message.h>
+#include <privkey.h>
+
+static int g_session_established = 0;
+
+OtrlPolicy policy(void *opdata, ConnContext *context) {
+ return OTRL_POLICY_ALWAYS;
+}
+
+int is_logged_in(void *opdata, const char *accountname, const char *protocol,
+ const char *recipient) {
+ return 1;
+}
+
+void inject_message(void *opdata, const char *accountname, const char *protocol,
+ const char *recipient, const char *message) {
+ printf("%s\n", message);
+ fflush(stdout);
+ fprintf(stderr, "libotr helper sent: %s\n", message);
+}
+
+void update_context_list(void *opdata) {}
+
+void new_fingerprint(void *opdata, OtrlUserState us, const char *accountname,
+ const char *protocol, const char *username,
+ unsigned char fingerprint[20]) {
+ fprintf(stderr, "NEW FINGERPRINT\n");
+ g_session_established = 1;
+}
+
+void write_fingerprints(void *opdata) {}
+
+void gone_secure(void *opdata, ConnContext *context) {}
+
+void gone_insecure(void *opdata, ConnContext *context) {}
+
+void still_secure(void *opdata, ConnContext *context, int is_reply) {}
+
+int max_message_size(void *opdata, ConnContext *context) { return 99999; }
+
+const char *account_name(void *opdata, const char *account,
+ const char *protocol) {
+ return "ACCOUNT";
+}
+
+void account_name_free(void *opdata, const char *account_name) {}
+
+const char *error_message(void *opdata, ConnContext *context,
+ OtrlErrorCode err_code) {
+ return "ERR";
+}
+
+void error_message_free(void *opdata, const char *msg) {}
+
+void resent_msg_prefix_free(void *opdata, const char *prefix) {}
+
+void handle_smp_event(void *opdata, OtrlSMPEvent smp_event,
+ ConnContext *context, unsigned short progress_event,
+ char *question) {}
+
+void handle_msg_event(void *opdata, OtrlMessageEvent msg_event,
+ ConnContext *context, const char *message,
+ gcry_error_t err) {
+ fprintf(stderr, "msg event: %d %s\n", msg_event, message);
+}
+
+OtrlMessageAppOps uiops = {
+ policy,
+ NULL,
+ is_logged_in,
+ inject_message,
+ update_context_list,
+ new_fingerprint,
+ write_fingerprints,
+ gone_secure,
+ gone_insecure,
+ still_secure,
+ max_message_size,
+ account_name,
+ account_name_free,
+ NULL, /* received_symkey */
+ error_message,
+ error_message_free,
+ NULL, /* resent_msg_prefix */
+ resent_msg_prefix_free,
+ handle_smp_event,
+ handle_msg_event,
+ NULL /* create_instag */,
+ NULL /* convert_msg */,
+ NULL /* convert_free */,
+ NULL /* timer_control */,
+};
+
+static const char kPrivateKeyData[] =
+ "(privkeys (account (name \"account\") (protocol proto) (private-key (dsa "
+ "(p "
+ "#00FC07ABCF0DC916AFF6E9AE47BEF60C7AB9B4D6B2469E436630E36F8A489BE812486A09F"
+ "30B71224508654940A835301ACC525A4FF133FC152CC53DCC59D65C30A54F1993FE13FE63E"
+ "5823D4C746DB21B90F9B9C00B49EC7404AB1D929BA7FBA12F2E45C6E0A651689750E8528AB"
+ "8C031D3561FECEE72EBB4A090D450A9B7A857#) (q "
+ "#00997BD266EF7B1F60A5C23F3A741F2AEFD07A2081#) (g "
+ "#535E360E8A95EBA46A4F7DE50AD6E9B2A6DB785A66B64EB9F20338D2A3E8FB0E94725848F"
+ "1AA6CC567CB83A1CC517EC806F2E92EAE71457E80B2210A189B91250779434B41FC8A8873F"
+ "6DB94BEA7D177F5D59E7E114EE10A49CFD9CEF88AE43387023B672927BA74B04EB6BBB5E57"
+ "597766A2F9CE3857D7ACE3E1E3BC1FC6F26#) (y "
+ "#0AC8670AD767D7A8D9D14CC1AC6744CD7D76F993B77FFD9E39DF01E5A6536EF65E775FCEF"
+ "2A983E2A19BD6415500F6979715D9FD1257E1FE2B6F5E1E74B333079E7C880D39868462A93"
+ "454B41877BE62E5EF0A041C2EE9C9E76BD1E12AE25D9628DECB097025DD625EF49C3258A1A"
+ "3C0FF501E3DC673B76D7BABF349009B6ECF#) (x "
+ "#14D0345A3562C480A039E3C72764F72D79043216#)))))\n";
+
+int main() {
+ OTRL_INIT;
+
+ // We have to write the private key information to a file because the libotr
+ // API demands a filename to read from.
+ const char *tmpdir = "/tmp";
+ if (getenv("TMP")) {
+ tmpdir = getenv("TMP");
+ }
+
+ char private_key_file[256];
+ snprintf(private_key_file, sizeof(private_key_file),
+ "%s/libotr_test_helper_privatekeys-XXXXXX", tmpdir);
+ int fd = mkstemp(private_key_file);
+ if (fd == -1) {
+ perror("creating temp file");
+ }
+ write(fd, kPrivateKeyData, sizeof(kPrivateKeyData) - 1);
+ close(fd);
+
+ OtrlUserState userstate = otrl_userstate_create();
+ otrl_privkey_read(userstate, private_key_file);
+ unlink(private_key_file);
+
+ fprintf(stderr, "libotr helper started\n");
+
+ char buf[4096];
+
+ for (;;) {
+ char *message = fgets(buf, sizeof(buf), stdin);
+ if (strlen(message) == 0) {
+ break;
+ }
+ message[strlen(message) - 1] = 0;
+ fprintf(stderr, "libotr helper got: %s\n", message);
+
+ char *newmessage = NULL;
+ OtrlTLV *tlvs;
+ int ignore_message = otrl_message_receiving(
+ userstate, &uiops, NULL, "account", "proto", "peer", message,
+ &newmessage, &tlvs, NULL, NULL, NULL);
+ if (tlvs) {
+ otrl_tlv_free(tlvs);
+ }
+
+ if (newmessage != NULL) {
+ fprintf(stderr, "libotr got: %s\n", newmessage);
+ otrl_message_free(newmessage);
+
+ gcry_error_t err;
+ char *newmessage = NULL;
+
+ err = otrl_message_sending(userstate, &uiops, NULL, "account", "proto",
+ "peer", 0, "test message", NULL, &newmessage,
+ OTRL_FRAGMENT_SEND_SKIP, NULL, NULL, NULL);
+ if (newmessage == NULL) {
+ fprintf(stderr, "libotr didn't encrypt message\n");
+ return 1;
+ }
+ write(1, newmessage, strlen(newmessage));
+ write(1, "\n", 1);
+ fprintf(stderr, "libotr sent: %s\n", newmessage);
+ otrl_message_free(newmessage);
+
+ g_session_established = 0;
+ write(1, "?OTRv2?\n", 8);
+ fprintf(stderr, "libotr sent: ?OTRv2\n");
+ }
+ }
+
+ return 0;
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/otr/otr.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/otr/otr.go
new file mode 100644
index 000000000..173b753db
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/otr/otr.go
@@ -0,0 +1,1415 @@
+// Copyright 2012 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 otr implements the Off The Record protocol as specified in
+// http://www.cypherpunks.ca/otr/Protocol-v2-3.1.0.html
+package otr // import "golang.org/x/crypto/otr"
+
+import (
+ "bytes"
+ "crypto/aes"
+ "crypto/cipher"
+ "crypto/dsa"
+ "crypto/hmac"
+ "crypto/rand"
+ "crypto/sha1"
+ "crypto/sha256"
+ "crypto/subtle"
+ "encoding/base64"
+ "encoding/hex"
+ "errors"
+ "hash"
+ "io"
+ "math/big"
+ "strconv"
+)
+
+// SecurityChange describes a change in the security state of a Conversation.
+type SecurityChange int
+
+const (
+ NoChange SecurityChange = iota
+ // NewKeys indicates that a key exchange has completed. This occurs
+ // when a conversation first becomes encrypted, and when the keys are
+ // renegotiated within an encrypted conversation.
+ NewKeys
+ // SMPSecretNeeded indicates that the peer has started an
+ // authentication and that we need to supply a secret. Call SMPQuestion
+ // to get the optional, human readable challenge and then Authenticate
+ // to supply the matching secret.
+ SMPSecretNeeded
+ // SMPComplete indicates that an authentication completed. The identity
+ // of the peer has now been confirmed.
+ SMPComplete
+ // SMPFailed indicates that an authentication failed.
+ SMPFailed
+ // ConversationEnded indicates that the peer ended the secure
+ // conversation.
+ ConversationEnded
+)
+
+// QueryMessage can be sent to a peer to start an OTR conversation.
+var QueryMessage = "?OTRv2?"
+
+// ErrorPrefix can be used to make an OTR error by appending an error message
+// to it.
+var ErrorPrefix = "?OTR Error:"
+
+var (
+ fragmentPartSeparator = []byte(",")
+ fragmentPrefix = []byte("?OTR,")
+ msgPrefix = []byte("?OTR:")
+ queryMarker = []byte("?OTR")
+)
+
+// isQuery attempts to parse an OTR query from msg and returns the greatest
+// common version, or 0 if msg is not an OTR query.
+func isQuery(msg []byte) (greatestCommonVersion int) {
+ pos := bytes.Index(msg, queryMarker)
+ if pos == -1 {
+ return 0
+ }
+ for i, c := range msg[pos+len(queryMarker):] {
+ if i == 0 {
+ if c == '?' {
+ // Indicates support for version 1, but we don't
+ // implement that.
+ continue
+ }
+
+ if c != 'v' {
+ // Invalid message
+ return 0
+ }
+
+ continue
+ }
+
+ if c == '?' {
+ // End of message
+ return
+ }
+
+ if c == ' ' || c == '\t' {
+ // Probably an invalid message
+ return 0
+ }
+
+ if c == '2' {
+ greatestCommonVersion = 2
+ }
+ }
+
+ return 0
+}
+
+const (
+ statePlaintext = iota
+ stateEncrypted
+ stateFinished
+)
+
+const (
+ authStateNone = iota
+ authStateAwaitingDHKey
+ authStateAwaitingRevealSig
+ authStateAwaitingSig
+)
+
+const (
+ msgTypeDHCommit = 2
+ msgTypeData = 3
+ msgTypeDHKey = 10
+ msgTypeRevealSig = 17
+ msgTypeSig = 18
+)
+
+const (
+ // If the requested fragment size is less than this, it will be ignored.
+ minFragmentSize = 18
+ // Messages are padded to a multiple of this number of bytes.
+ paddingGranularity = 256
+ // The number of bytes in a Diffie-Hellman private value (320-bits).
+ dhPrivateBytes = 40
+ // The number of bytes needed to represent an element of the DSA
+ // subgroup (160-bits).
+ dsaSubgroupBytes = 20
+ // The number of bytes of the MAC that are sent on the wire (160-bits).
+ macPrefixBytes = 20
+)
+
+// These are the global, common group parameters for OTR.
+var (
+ p *big.Int // group prime
+ g *big.Int // group generator
+ q *big.Int // group order
+ pMinus2 *big.Int
+)
+
+func init() {
+ p, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF", 16)
+ q, _ = new(big.Int).SetString("7FFFFFFFFFFFFFFFE487ED5110B4611A62633145C06E0E68948127044533E63A0105DF531D89CD9128A5043CC71A026EF7CA8CD9E69D218D98158536F92F8A1BA7F09AB6B6A8E122F242DABB312F3F637A262174D31BF6B585FFAE5B7A035BF6F71C35FDAD44CFD2D74F9208BE258FF324943328F6722D9EE1003E5C50B1DF82CC6D241B0E2AE9CD348B1FD47E9267AFC1B2AE91EE51D6CB0E3179AB1042A95DCF6A9483B84B4B36B3861AA7255E4C0278BA36046511B993FFFFFFFFFFFFFFFF", 16)
+ g = new(big.Int).SetInt64(2)
+ pMinus2 = new(big.Int).Sub(p, g)
+}
+
+// Conversation represents a relation with a peer. The zero value is a valid
+// Conversation, although PrivateKey must be set.
+//
+// When communicating with a peer, all inbound messages should be passed to
+// Conversation.Receive and all outbound messages to Conversation.Send. The
+// Conversation will take care of maintaining the encryption state and
+// negotiating encryption as needed.
+type Conversation struct {
+ // PrivateKey contains the private key to use to sign key exchanges.
+ PrivateKey *PrivateKey
+
+ // Rand can be set to override the entropy source. Otherwise,
+ // crypto/rand will be used.
+ Rand io.Reader
+ // If FragmentSize is set, all messages produced by Receive and Send
+ // will be fragmented into messages of, at most, this number of bytes.
+ FragmentSize int
+
+ // Once Receive has returned NewKeys once, the following fields are
+ // valid.
+ SSID [8]byte
+ TheirPublicKey PublicKey
+
+ state, authState int
+
+ r [16]byte
+ x, y *big.Int
+ gx, gy *big.Int
+ gxBytes []byte
+ digest [sha256.Size]byte
+
+ revealKeys, sigKeys akeKeys
+
+ myKeyId uint32
+ myCurrentDHPub *big.Int
+ myCurrentDHPriv *big.Int
+ myLastDHPub *big.Int
+ myLastDHPriv *big.Int
+
+ theirKeyId uint32
+ theirCurrentDHPub *big.Int
+ theirLastDHPub *big.Int
+
+ keySlots [4]keySlot
+
+ myCounter [8]byte
+ theirLastCtr [8]byte
+ oldMACs []byte
+
+ k, n int // fragment state
+ frag []byte
+
+ smp smpState
+}
+
+// A keySlot contains key material for a specific (their keyid, my keyid) pair.
+type keySlot struct {
+ // used is true if this slot is valid. If false, it's free for reuse.
+ used bool
+ theirKeyId uint32
+ myKeyId uint32
+ sendAESKey, recvAESKey []byte
+ sendMACKey, recvMACKey []byte
+ theirLastCtr [8]byte
+}
+
+// akeKeys are generated during key exchange. There's one set for the reveal
+// signature message and another for the signature message. In the protocol
+// spec the latter are indicated with a prime mark.
+type akeKeys struct {
+ c [16]byte
+ m1, m2 [32]byte
+}
+
+func (c *Conversation) rand() io.Reader {
+ if c.Rand != nil {
+ return c.Rand
+ }
+ return rand.Reader
+}
+
+func (c *Conversation) randMPI(buf []byte) *big.Int {
+ _, err := io.ReadFull(c.rand(), buf)
+ if err != nil {
+ panic("otr: short read from random source")
+ }
+
+ return new(big.Int).SetBytes(buf)
+}
+
+// tlv represents the type-length value from the protocol.
+type tlv struct {
+ typ, length uint16
+ data []byte
+}
+
+const (
+ tlvTypePadding = 0
+ tlvTypeDisconnected = 1
+ tlvTypeSMP1 = 2
+ tlvTypeSMP2 = 3
+ tlvTypeSMP3 = 4
+ tlvTypeSMP4 = 5
+ tlvTypeSMPAbort = 6
+ tlvTypeSMP1WithQuestion = 7
+)
+
+// Receive handles a message from a peer. It returns a human readable message,
+// an indicator of whether that message was encrypted, a hint about the
+// encryption state and zero or more messages to send back to the peer.
+// These messages do not need to be passed to Send before transmission.
+func (c *Conversation) Receive(in []byte) (out []byte, encrypted bool, change SecurityChange, toSend [][]byte, err error) {
+ if bytes.HasPrefix(in, fragmentPrefix) {
+ in, err = c.processFragment(in)
+ if in == nil || err != nil {
+ return
+ }
+ }
+
+ if bytes.HasPrefix(in, msgPrefix) && in[len(in)-1] == '.' {
+ in = in[len(msgPrefix) : len(in)-1]
+ } else if version := isQuery(in); version > 0 {
+ c.authState = authStateAwaitingDHKey
+ c.reset()
+ toSend = c.encode(c.generateDHCommit())
+ return
+ } else {
+ // plaintext message
+ out = in
+ return
+ }
+
+ msg := make([]byte, base64.StdEncoding.DecodedLen(len(in)))
+ msgLen, err := base64.StdEncoding.Decode(msg, in)
+ if err != nil {
+ err = errors.New("otr: invalid base64 encoding in message")
+ return
+ }
+ msg = msg[:msgLen]
+
+ // The first two bytes are the protocol version (2)
+ if len(msg) < 3 || msg[0] != 0 || msg[1] != 2 {
+ err = errors.New("otr: invalid OTR message")
+ return
+ }
+
+ msgType := int(msg[2])
+ msg = msg[3:]
+
+ switch msgType {
+ case msgTypeDHCommit:
+ switch c.authState {
+ case authStateNone:
+ c.authState = authStateAwaitingRevealSig
+ if err = c.processDHCommit(msg); err != nil {
+ return
+ }
+ c.reset()
+ toSend = c.encode(c.generateDHKey())
+ return
+ case authStateAwaitingDHKey:
+ // This is a 'SYN-crossing'. The greater digest wins.
+ var cmp int
+ if cmp, err = c.compareToDHCommit(msg); err != nil {
+ return
+ }
+ if cmp > 0 {
+ // We win. Retransmit DH commit.
+ toSend = c.encode(c.serializeDHCommit())
+ return
+ } else {
+ // They win. We forget about our DH commit.
+ c.authState = authStateAwaitingRevealSig
+ if err = c.processDHCommit(msg); err != nil {
+ return
+ }
+ c.reset()
+ toSend = c.encode(c.generateDHKey())
+ return
+ }
+ case authStateAwaitingRevealSig:
+ if err = c.processDHCommit(msg); err != nil {
+ return
+ }
+ toSend = c.encode(c.serializeDHKey())
+ case authStateAwaitingSig:
+ if err = c.processDHCommit(msg); err != nil {
+ return
+ }
+ c.reset()
+ toSend = c.encode(c.generateDHKey())
+ c.authState = authStateAwaitingRevealSig
+ default:
+ panic("bad state")
+ }
+ case msgTypeDHKey:
+ switch c.authState {
+ case authStateAwaitingDHKey:
+ var isSame bool
+ if isSame, err = c.processDHKey(msg); err != nil {
+ return
+ }
+ if isSame {
+ err = errors.New("otr: unexpected duplicate DH key")
+ return
+ }
+ toSend = c.encode(c.generateRevealSig())
+ c.authState = authStateAwaitingSig
+ case authStateAwaitingSig:
+ var isSame bool
+ if isSame, err = c.processDHKey(msg); err != nil {
+ return
+ }
+ if isSame {
+ toSend = c.encode(c.serializeDHKey())
+ }
+ }
+ case msgTypeRevealSig:
+ if c.authState != authStateAwaitingRevealSig {
+ return
+ }
+ if err = c.processRevealSig(msg); err != nil {
+ return
+ }
+ toSend = c.encode(c.generateSig())
+ c.authState = authStateNone
+ c.state = stateEncrypted
+ change = NewKeys
+ case msgTypeSig:
+ if c.authState != authStateAwaitingSig {
+ return
+ }
+ if err = c.processSig(msg); err != nil {
+ return
+ }
+ c.authState = authStateNone
+ c.state = stateEncrypted
+ change = NewKeys
+ case msgTypeData:
+ if c.state != stateEncrypted {
+ err = errors.New("otr: encrypted message received without encrypted session established")
+ return
+ }
+ var tlvs []tlv
+ out, tlvs, err = c.processData(msg)
+ encrypted = true
+
+ EachTLV:
+ for _, inTLV := range tlvs {
+ switch inTLV.typ {
+ case tlvTypeDisconnected:
+ change = ConversationEnded
+ c.state = stateFinished
+ break EachTLV
+ case tlvTypeSMP1, tlvTypeSMP2, tlvTypeSMP3, tlvTypeSMP4, tlvTypeSMPAbort, tlvTypeSMP1WithQuestion:
+ var reply tlv
+ var complete bool
+ reply, complete, err = c.processSMP(inTLV)
+ if err == smpSecretMissingError {
+ err = nil
+ change = SMPSecretNeeded
+ c.smp.saved = &inTLV
+ return
+ }
+ if err == smpFailureError {
+ err = nil
+ change = SMPFailed
+ } else if complete {
+ change = SMPComplete
+ }
+ if reply.typ != 0 {
+ toSend = c.encode(c.generateData(nil, &reply))
+ }
+ break EachTLV
+ default:
+ // skip unknown TLVs
+ }
+ }
+ default:
+ err = errors.New("otr: unknown message type " + strconv.Itoa(msgType))
+ }
+
+ return
+}
+
+// Send takes a human readable message from the local user, possibly encrypts
+// it and returns zero one or more messages to send to the peer.
+func (c *Conversation) Send(msg []byte) ([][]byte, error) {
+ switch c.state {
+ case statePlaintext:
+ return [][]byte{msg}, nil
+ case stateEncrypted:
+ return c.encode(c.generateData(msg, nil)), nil
+ case stateFinished:
+ return nil, errors.New("otr: cannot send message because secure conversation has finished")
+ }
+
+ return nil, errors.New("otr: cannot send message in current state")
+}
+
+// SMPQuestion returns the human readable challenge question from the peer.
+// It's only valid after Receive has returned SMPSecretNeeded.
+func (c *Conversation) SMPQuestion() string {
+ return c.smp.question
+}
+
+// Authenticate begins an authentication with the peer. Authentication involves
+// an optional challenge message and a shared secret. The authentication
+// proceeds until either Receive returns SMPComplete, SMPSecretNeeded (which
+// indicates that a new authentication is happening and thus this one was
+// aborted) or SMPFailed.
+func (c *Conversation) Authenticate(question string, mutualSecret []byte) (toSend [][]byte, err error) {
+ if c.state != stateEncrypted {
+ err = errors.New("otr: can't authenticate a peer without a secure conversation established")
+ return
+ }
+
+ if c.smp.saved != nil {
+ c.calcSMPSecret(mutualSecret, false /* they started it */)
+
+ var out tlv
+ var complete bool
+ out, complete, err = c.processSMP(*c.smp.saved)
+ if complete {
+ panic("SMP completed on the first message")
+ }
+ c.smp.saved = nil
+ if out.typ != 0 {
+ toSend = c.encode(c.generateData(nil, &out))
+ }
+ return
+ }
+
+ c.calcSMPSecret(mutualSecret, true /* we started it */)
+ outs := c.startSMP(question)
+ for _, out := range outs {
+ toSend = append(toSend, c.encode(c.generateData(nil, &out))...)
+ }
+ return
+}
+
+// End ends a secure conversation by generating a termination message for
+// the peer and switches to unencrypted communication.
+func (c *Conversation) End() (toSend [][]byte) {
+ switch c.state {
+ case statePlaintext:
+ return nil
+ case stateEncrypted:
+ c.state = statePlaintext
+ return c.encode(c.generateData(nil, &tlv{typ: tlvTypeDisconnected}))
+ case stateFinished:
+ c.state = statePlaintext
+ return nil
+ }
+ panic("unreachable")
+}
+
+// IsEncrypted returns true if a message passed to Send would be encrypted
+// before transmission. This result remains valid until the next call to
+// Receive or End, which may change the state of the Conversation.
+func (c *Conversation) IsEncrypted() bool {
+ return c.state == stateEncrypted
+}
+
+var fragmentError = errors.New("otr: invalid OTR fragment")
+
+// processFragment processes a fragmented OTR message and possibly returns a
+// complete message. Fragmented messages look like "?OTR,k,n,msg," where k is
+// the fragment number (starting from 1), n is the number of fragments in this
+// message and msg is a substring of the base64 encoded message.
+func (c *Conversation) processFragment(in []byte) (out []byte, err error) {
+ in = in[len(fragmentPrefix):] // remove "?OTR,"
+ parts := bytes.Split(in, fragmentPartSeparator)
+ if len(parts) != 4 || len(parts[3]) != 0 {
+ return nil, fragmentError
+ }
+
+ k, err := strconv.Atoi(string(parts[0]))
+ if err != nil {
+ return nil, fragmentError
+ }
+
+ n, err := strconv.Atoi(string(parts[1]))
+ if err != nil {
+ return nil, fragmentError
+ }
+
+ if k < 1 || n < 1 || k > n {
+ return nil, fragmentError
+ }
+
+ if k == 1 {
+ c.frag = append(c.frag[:0], parts[2]...)
+ c.k, c.n = k, n
+ } else if n == c.n && k == c.k+1 {
+ c.frag = append(c.frag, parts[2]...)
+ c.k++
+ } else {
+ c.frag = c.frag[:0]
+ c.n, c.k = 0, 0
+ }
+
+ if c.n > 0 && c.k == c.n {
+ c.n, c.k = 0, 0
+ return c.frag, nil
+ }
+
+ return nil, nil
+}
+
+func (c *Conversation) generateDHCommit() []byte {
+ _, err := io.ReadFull(c.rand(), c.r[:])
+ if err != nil {
+ panic("otr: short read from random source")
+ }
+
+ var xBytes [dhPrivateBytes]byte
+ c.x = c.randMPI(xBytes[:])
+ c.gx = new(big.Int).Exp(g, c.x, p)
+ c.gy = nil
+ c.gxBytes = appendMPI(nil, c.gx)
+
+ h := sha256.New()
+ h.Write(c.gxBytes)
+ h.Sum(c.digest[:0])
+
+ aesCipher, err := aes.NewCipher(c.r[:])
+ if err != nil {
+ panic(err.Error())
+ }
+
+ var iv [aes.BlockSize]byte
+ ctr := cipher.NewCTR(aesCipher, iv[:])
+ ctr.XORKeyStream(c.gxBytes, c.gxBytes)
+
+ return c.serializeDHCommit()
+}
+
+func (c *Conversation) serializeDHCommit() []byte {
+ var ret []byte
+ ret = appendU16(ret, 2) // protocol version
+ ret = append(ret, msgTypeDHCommit)
+ ret = appendData(ret, c.gxBytes)
+ ret = appendData(ret, c.digest[:])
+ return ret
+}
+
+func (c *Conversation) processDHCommit(in []byte) error {
+ var ok1, ok2 bool
+ c.gxBytes, in, ok1 = getData(in)
+ digest, in, ok2 := getData(in)
+ if !ok1 || !ok2 || len(in) > 0 {
+ return errors.New("otr: corrupt DH commit message")
+ }
+ copy(c.digest[:], digest)
+ return nil
+}
+
+func (c *Conversation) compareToDHCommit(in []byte) (int, error) {
+ _, in, ok1 := getData(in)
+ digest, in, ok2 := getData(in)
+ if !ok1 || !ok2 || len(in) > 0 {
+ return 0, errors.New("otr: corrupt DH commit message")
+ }
+ return bytes.Compare(c.digest[:], digest), nil
+}
+
+func (c *Conversation) generateDHKey() []byte {
+ var yBytes [dhPrivateBytes]byte
+ c.y = c.randMPI(yBytes[:])
+ c.gy = new(big.Int).Exp(g, c.y, p)
+ return c.serializeDHKey()
+}
+
+func (c *Conversation) serializeDHKey() []byte {
+ var ret []byte
+ ret = appendU16(ret, 2) // protocol version
+ ret = append(ret, msgTypeDHKey)
+ ret = appendMPI(ret, c.gy)
+ return ret
+}
+
+func (c *Conversation) processDHKey(in []byte) (isSame bool, err error) {
+ gy, in, ok := getMPI(in)
+ if !ok {
+ err = errors.New("otr: corrupt DH key message")
+ return
+ }
+ if gy.Cmp(g) < 0 || gy.Cmp(pMinus2) > 0 {
+ err = errors.New("otr: DH value out of range")
+ return
+ }
+ if c.gy != nil {
+ isSame = c.gy.Cmp(gy) == 0
+ return
+ }
+ c.gy = gy
+ return
+}
+
+func (c *Conversation) generateEncryptedSignature(keys *akeKeys, xFirst bool) ([]byte, []byte) {
+ var xb []byte
+ xb = c.PrivateKey.PublicKey.Serialize(xb)
+
+ var verifyData []byte
+ if xFirst {
+ verifyData = appendMPI(verifyData, c.gx)
+ verifyData = appendMPI(verifyData, c.gy)
+ } else {
+ verifyData = appendMPI(verifyData, c.gy)
+ verifyData = appendMPI(verifyData, c.gx)
+ }
+ verifyData = append(verifyData, xb...)
+ verifyData = appendU32(verifyData, c.myKeyId)
+
+ mac := hmac.New(sha256.New, keys.m1[:])
+ mac.Write(verifyData)
+ mb := mac.Sum(nil)
+
+ xb = appendU32(xb, c.myKeyId)
+ xb = append(xb, c.PrivateKey.Sign(c.rand(), mb)...)
+
+ aesCipher, err := aes.NewCipher(keys.c[:])
+ if err != nil {
+ panic(err.Error())
+ }
+ var iv [aes.BlockSize]byte
+ ctr := cipher.NewCTR(aesCipher, iv[:])
+ ctr.XORKeyStream(xb, xb)
+
+ mac = hmac.New(sha256.New, keys.m2[:])
+ encryptedSig := appendData(nil, xb)
+ mac.Write(encryptedSig)
+
+ return encryptedSig, mac.Sum(nil)
+}
+
+func (c *Conversation) generateRevealSig() []byte {
+ s := new(big.Int).Exp(c.gy, c.x, p)
+ c.calcAKEKeys(s)
+ c.myKeyId++
+
+ encryptedSig, mac := c.generateEncryptedSignature(&c.revealKeys, true /* gx comes first */)
+
+ c.myCurrentDHPub = c.gx
+ c.myCurrentDHPriv = c.x
+ c.rotateDHKeys()
+ incCounter(&c.myCounter)
+
+ var ret []byte
+ ret = appendU16(ret, 2)
+ ret = append(ret, msgTypeRevealSig)
+ ret = appendData(ret, c.r[:])
+ ret = append(ret, encryptedSig...)
+ ret = append(ret, mac[:20]...)
+ return ret
+}
+
+func (c *Conversation) processEncryptedSig(encryptedSig, theirMAC []byte, keys *akeKeys, xFirst bool) error {
+ mac := hmac.New(sha256.New, keys.m2[:])
+ mac.Write(appendData(nil, encryptedSig))
+ myMAC := mac.Sum(nil)[:20]
+
+ if len(myMAC) != len(theirMAC) || subtle.ConstantTimeCompare(myMAC, theirMAC) == 0 {
+ return errors.New("bad signature MAC in encrypted signature")
+ }
+
+ aesCipher, err := aes.NewCipher(keys.c[:])
+ if err != nil {
+ panic(err.Error())
+ }
+ var iv [aes.BlockSize]byte
+ ctr := cipher.NewCTR(aesCipher, iv[:])
+ ctr.XORKeyStream(encryptedSig, encryptedSig)
+
+ sig := encryptedSig
+ sig, ok1 := c.TheirPublicKey.Parse(sig)
+ keyId, sig, ok2 := getU32(sig)
+ if !ok1 || !ok2 {
+ return errors.New("otr: corrupt encrypted signature")
+ }
+
+ var verifyData []byte
+ if xFirst {
+ verifyData = appendMPI(verifyData, c.gx)
+ verifyData = appendMPI(verifyData, c.gy)
+ } else {
+ verifyData = appendMPI(verifyData, c.gy)
+ verifyData = appendMPI(verifyData, c.gx)
+ }
+ verifyData = c.TheirPublicKey.Serialize(verifyData)
+ verifyData = appendU32(verifyData, keyId)
+
+ mac = hmac.New(sha256.New, keys.m1[:])
+ mac.Write(verifyData)
+ mb := mac.Sum(nil)
+
+ sig, ok1 = c.TheirPublicKey.Verify(mb, sig)
+ if !ok1 {
+ return errors.New("bad signature in encrypted signature")
+ }
+ if len(sig) > 0 {
+ return errors.New("corrupt encrypted signature")
+ }
+
+ c.theirKeyId = keyId
+ zero(c.theirLastCtr[:])
+ return nil
+}
+
+func (c *Conversation) processRevealSig(in []byte) error {
+ r, in, ok1 := getData(in)
+ encryptedSig, in, ok2 := getData(in)
+ theirMAC := in
+ if !ok1 || !ok2 || len(theirMAC) != 20 {
+ return errors.New("otr: corrupt reveal signature message")
+ }
+
+ aesCipher, err := aes.NewCipher(r)
+ if err != nil {
+ return errors.New("otr: cannot create AES cipher from reveal signature message: " + err.Error())
+ }
+ var iv [aes.BlockSize]byte
+ ctr := cipher.NewCTR(aesCipher, iv[:])
+ ctr.XORKeyStream(c.gxBytes, c.gxBytes)
+ h := sha256.New()
+ h.Write(c.gxBytes)
+ digest := h.Sum(nil)
+ if len(digest) != len(c.digest) || subtle.ConstantTimeCompare(digest, c.digest[:]) == 0 {
+ return errors.New("otr: bad commit MAC in reveal signature message")
+ }
+ var rest []byte
+ c.gx, rest, ok1 = getMPI(c.gxBytes)
+ if !ok1 || len(rest) > 0 {
+ return errors.New("otr: gx corrupt after decryption")
+ }
+ if c.gx.Cmp(g) < 0 || c.gx.Cmp(pMinus2) > 0 {
+ return errors.New("otr: DH value out of range")
+ }
+ s := new(big.Int).Exp(c.gx, c.y, p)
+ c.calcAKEKeys(s)
+
+ if err := c.processEncryptedSig(encryptedSig, theirMAC, &c.revealKeys, true /* gx comes first */); err != nil {
+ return errors.New("otr: in reveal signature message: " + err.Error())
+ }
+
+ c.theirCurrentDHPub = c.gx
+ c.theirLastDHPub = nil
+
+ return nil
+}
+
+func (c *Conversation) generateSig() []byte {
+ c.myKeyId++
+
+ encryptedSig, mac := c.generateEncryptedSignature(&c.sigKeys, false /* gy comes first */)
+
+ c.myCurrentDHPub = c.gy
+ c.myCurrentDHPriv = c.y
+ c.rotateDHKeys()
+ incCounter(&c.myCounter)
+
+ var ret []byte
+ ret = appendU16(ret, 2)
+ ret = append(ret, msgTypeSig)
+ ret = append(ret, encryptedSig...)
+ ret = append(ret, mac[:macPrefixBytes]...)
+ return ret
+}
+
+func (c *Conversation) processSig(in []byte) error {
+ encryptedSig, in, ok1 := getData(in)
+ theirMAC := in
+ if !ok1 || len(theirMAC) != macPrefixBytes {
+ return errors.New("otr: corrupt signature message")
+ }
+
+ if err := c.processEncryptedSig(encryptedSig, theirMAC, &c.sigKeys, false /* gy comes first */); err != nil {
+ return errors.New("otr: in signature message: " + err.Error())
+ }
+
+ c.theirCurrentDHPub = c.gy
+ c.theirLastDHPub = nil
+
+ return nil
+}
+
+func (c *Conversation) rotateDHKeys() {
+ // evict slots using our retired key id
+ for i := range c.keySlots {
+ slot := &c.keySlots[i]
+ if slot.used && slot.myKeyId == c.myKeyId-1 {
+ slot.used = false
+ c.oldMACs = append(c.oldMACs, slot.recvMACKey...)
+ }
+ }
+
+ c.myLastDHPriv = c.myCurrentDHPriv
+ c.myLastDHPub = c.myCurrentDHPub
+
+ var xBytes [dhPrivateBytes]byte
+ c.myCurrentDHPriv = c.randMPI(xBytes[:])
+ c.myCurrentDHPub = new(big.Int).Exp(g, c.myCurrentDHPriv, p)
+ c.myKeyId++
+}
+
+func (c *Conversation) processData(in []byte) (out []byte, tlvs []tlv, err error) {
+ origIn := in
+ flags, in, ok1 := getU8(in)
+ theirKeyId, in, ok2 := getU32(in)
+ myKeyId, in, ok3 := getU32(in)
+ y, in, ok4 := getMPI(in)
+ counter, in, ok5 := getNBytes(in, 8)
+ encrypted, in, ok6 := getData(in)
+ macedData := origIn[:len(origIn)-len(in)]
+ theirMAC, in, ok7 := getNBytes(in, macPrefixBytes)
+ _, in, ok8 := getData(in)
+ if !ok1 || !ok2 || !ok3 || !ok4 || !ok5 || !ok6 || !ok7 || !ok8 || len(in) > 0 {
+ err = errors.New("otr: corrupt data message")
+ return
+ }
+
+ ignoreErrors := flags&1 != 0
+
+ slot, err := c.calcDataKeys(myKeyId, theirKeyId)
+ if err != nil {
+ if ignoreErrors {
+ err = nil
+ }
+ return
+ }
+
+ mac := hmac.New(sha1.New, slot.recvMACKey)
+ mac.Write([]byte{0, 2, 3})
+ mac.Write(macedData)
+ myMAC := mac.Sum(nil)
+ if len(myMAC) != len(theirMAC) || subtle.ConstantTimeCompare(myMAC, theirMAC) == 0 {
+ if !ignoreErrors {
+ err = errors.New("otr: bad MAC on data message")
+ }
+ return
+ }
+
+ if bytes.Compare(counter, slot.theirLastCtr[:]) <= 0 {
+ err = errors.New("otr: counter regressed")
+ return
+ }
+ copy(slot.theirLastCtr[:], counter)
+
+ var iv [aes.BlockSize]byte
+ copy(iv[:], counter)
+ aesCipher, err := aes.NewCipher(slot.recvAESKey)
+ if err != nil {
+ panic(err.Error())
+ }
+ ctr := cipher.NewCTR(aesCipher, iv[:])
+ ctr.XORKeyStream(encrypted, encrypted)
+ decrypted := encrypted
+
+ if myKeyId == c.myKeyId {
+ c.rotateDHKeys()
+ }
+ if theirKeyId == c.theirKeyId {
+ // evict slots using their retired key id
+ for i := range c.keySlots {
+ slot := &c.keySlots[i]
+ if slot.used && slot.theirKeyId == theirKeyId-1 {
+ slot.used = false
+ c.oldMACs = append(c.oldMACs, slot.recvMACKey...)
+ }
+ }
+
+ c.theirLastDHPub = c.theirCurrentDHPub
+ c.theirKeyId++
+ c.theirCurrentDHPub = y
+ }
+
+ if nulPos := bytes.IndexByte(decrypted, 0); nulPos >= 0 {
+ out = decrypted[:nulPos]
+ tlvData := decrypted[nulPos+1:]
+ for len(tlvData) > 0 {
+ var t tlv
+ var ok1, ok2, ok3 bool
+
+ t.typ, tlvData, ok1 = getU16(tlvData)
+ t.length, tlvData, ok2 = getU16(tlvData)
+ t.data, tlvData, ok3 = getNBytes(tlvData, int(t.length))
+ if !ok1 || !ok2 || !ok3 {
+ err = errors.New("otr: corrupt tlv data")
+ return
+ }
+ tlvs = append(tlvs, t)
+ }
+ } else {
+ out = decrypted
+ }
+
+ return
+}
+
+func (c *Conversation) generateData(msg []byte, extra *tlv) []byte {
+ slot, err := c.calcDataKeys(c.myKeyId-1, c.theirKeyId)
+ if err != nil {
+ panic("otr: failed to generate sending keys: " + err.Error())
+ }
+
+ var plaintext []byte
+ plaintext = append(plaintext, msg...)
+ plaintext = append(plaintext, 0)
+
+ padding := paddingGranularity - ((len(plaintext) + 4) % paddingGranularity)
+ plaintext = appendU16(plaintext, tlvTypePadding)
+ plaintext = appendU16(plaintext, uint16(padding))
+ for i := 0; i < padding; i++ {
+ plaintext = append(plaintext, 0)
+ }
+
+ if extra != nil {
+ plaintext = appendU16(plaintext, extra.typ)
+ plaintext = appendU16(plaintext, uint16(len(extra.data)))
+ plaintext = append(plaintext, extra.data...)
+ }
+
+ encrypted := make([]byte, len(plaintext))
+
+ var iv [aes.BlockSize]byte
+ copy(iv[:], c.myCounter[:])
+ aesCipher, err := aes.NewCipher(slot.sendAESKey)
+ if err != nil {
+ panic(err.Error())
+ }
+ ctr := cipher.NewCTR(aesCipher, iv[:])
+ ctr.XORKeyStream(encrypted, plaintext)
+
+ var ret []byte
+ ret = appendU16(ret, 2)
+ ret = append(ret, msgTypeData)
+ ret = append(ret, 0 /* flags */)
+ ret = appendU32(ret, c.myKeyId-1)
+ ret = appendU32(ret, c.theirKeyId)
+ ret = appendMPI(ret, c.myCurrentDHPub)
+ ret = append(ret, c.myCounter[:]...)
+ ret = appendData(ret, encrypted)
+
+ mac := hmac.New(sha1.New, slot.sendMACKey)
+ mac.Write(ret)
+ ret = append(ret, mac.Sum(nil)[:macPrefixBytes]...)
+ ret = appendData(ret, c.oldMACs)
+ c.oldMACs = nil
+ incCounter(&c.myCounter)
+
+ return ret
+}
+
+func incCounter(counter *[8]byte) {
+ for i := 7; i >= 0; i-- {
+ counter[i]++
+ if counter[i] > 0 {
+ break
+ }
+ }
+}
+
+// calcDataKeys computes the keys used to encrypt a data message given the key
+// IDs.
+func (c *Conversation) calcDataKeys(myKeyId, theirKeyId uint32) (slot *keySlot, err error) {
+ // Check for a cache hit.
+ for i := range c.keySlots {
+ slot = &c.keySlots[i]
+ if slot.used && slot.theirKeyId == theirKeyId && slot.myKeyId == myKeyId {
+ return
+ }
+ }
+
+ // Find an empty slot to write into.
+ slot = nil
+ for i := range c.keySlots {
+ if !c.keySlots[i].used {
+ slot = &c.keySlots[i]
+ break
+ }
+ }
+ if slot == nil {
+ return nil, errors.New("otr: internal error: no more key slots")
+ }
+
+ var myPriv, myPub, theirPub *big.Int
+
+ if myKeyId == c.myKeyId {
+ myPriv = c.myCurrentDHPriv
+ myPub = c.myCurrentDHPub
+ } else if myKeyId == c.myKeyId-1 {
+ myPriv = c.myLastDHPriv
+ myPub = c.myLastDHPub
+ } else {
+ err = errors.New("otr: peer requested keyid " + strconv.FormatUint(uint64(myKeyId), 10) + " when I'm on " + strconv.FormatUint(uint64(c.myKeyId), 10))
+ return
+ }
+
+ if theirKeyId == c.theirKeyId {
+ theirPub = c.theirCurrentDHPub
+ } else if theirKeyId == c.theirKeyId-1 && c.theirLastDHPub != nil {
+ theirPub = c.theirLastDHPub
+ } else {
+ err = errors.New("otr: peer requested keyid " + strconv.FormatUint(uint64(myKeyId), 10) + " when they're on " + strconv.FormatUint(uint64(c.myKeyId), 10))
+ return
+ }
+
+ var sendPrefixByte, recvPrefixByte [1]byte
+
+ if myPub.Cmp(theirPub) > 0 {
+ // we're the high end
+ sendPrefixByte[0], recvPrefixByte[0] = 1, 2
+ } else {
+ // we're the low end
+ sendPrefixByte[0], recvPrefixByte[0] = 2, 1
+ }
+
+ s := new(big.Int).Exp(theirPub, myPriv, p)
+ sBytes := appendMPI(nil, s)
+
+ h := sha1.New()
+ h.Write(sendPrefixByte[:])
+ h.Write(sBytes)
+ slot.sendAESKey = h.Sum(slot.sendAESKey[:0])[:16]
+
+ h.Reset()
+ h.Write(slot.sendAESKey)
+ slot.sendMACKey = h.Sum(slot.sendMACKey[:0])
+
+ h.Reset()
+ h.Write(recvPrefixByte[:])
+ h.Write(sBytes)
+ slot.recvAESKey = h.Sum(slot.recvAESKey[:0])[:16]
+
+ h.Reset()
+ h.Write(slot.recvAESKey)
+ slot.recvMACKey = h.Sum(slot.recvMACKey[:0])
+
+ slot.theirKeyId = theirKeyId
+ slot.myKeyId = myKeyId
+ slot.used = true
+
+ zero(slot.theirLastCtr[:])
+ return
+}
+
+func (c *Conversation) calcAKEKeys(s *big.Int) {
+ mpi := appendMPI(nil, s)
+ h := sha256.New()
+
+ var cBytes [32]byte
+ hashWithPrefix(c.SSID[:], 0, mpi, h)
+
+ hashWithPrefix(cBytes[:], 1, mpi, h)
+ copy(c.revealKeys.c[:], cBytes[:16])
+ copy(c.sigKeys.c[:], cBytes[16:])
+
+ hashWithPrefix(c.revealKeys.m1[:], 2, mpi, h)
+ hashWithPrefix(c.revealKeys.m2[:], 3, mpi, h)
+ hashWithPrefix(c.sigKeys.m1[:], 4, mpi, h)
+ hashWithPrefix(c.sigKeys.m2[:], 5, mpi, h)
+}
+
+func hashWithPrefix(out []byte, prefix byte, in []byte, h hash.Hash) {
+ h.Reset()
+ var p [1]byte
+ p[0] = prefix
+ h.Write(p[:])
+ h.Write(in)
+ if len(out) == h.Size() {
+ h.Sum(out[:0])
+ } else {
+ digest := h.Sum(nil)
+ copy(out, digest)
+ }
+}
+
+func (c *Conversation) encode(msg []byte) [][]byte {
+ b64 := make([]byte, base64.StdEncoding.EncodedLen(len(msg))+len(msgPrefix)+1)
+ base64.StdEncoding.Encode(b64[len(msgPrefix):], msg)
+ copy(b64, msgPrefix)
+ b64[len(b64)-1] = '.'
+
+ if c.FragmentSize < minFragmentSize || len(b64) <= c.FragmentSize {
+ // We can encode this in a single fragment.
+ return [][]byte{b64}
+ }
+
+ // We have to fragment this message.
+ var ret [][]byte
+ bytesPerFragment := c.FragmentSize - minFragmentSize
+ numFragments := (len(b64) + bytesPerFragment) / bytesPerFragment
+
+ for i := 0; i < numFragments; i++ {
+ frag := []byte("?OTR," + strconv.Itoa(i+1) + "," + strconv.Itoa(numFragments) + ",")
+ todo := bytesPerFragment
+ if todo > len(b64) {
+ todo = len(b64)
+ }
+ frag = append(frag, b64[:todo]...)
+ b64 = b64[todo:]
+ frag = append(frag, ',')
+ ret = append(ret, frag)
+ }
+
+ return ret
+}
+
+func (c *Conversation) reset() {
+ c.myKeyId = 0
+
+ for i := range c.keySlots {
+ c.keySlots[i].used = false
+ }
+}
+
+type PublicKey struct {
+ dsa.PublicKey
+}
+
+func (pk *PublicKey) Parse(in []byte) ([]byte, bool) {
+ var ok bool
+ var pubKeyType uint16
+
+ if pubKeyType, in, ok = getU16(in); !ok || pubKeyType != 0 {
+ return nil, false
+ }
+ if pk.P, in, ok = getMPI(in); !ok {
+ return nil, false
+ }
+ if pk.Q, in, ok = getMPI(in); !ok {
+ return nil, false
+ }
+ if pk.G, in, ok = getMPI(in); !ok {
+ return nil, false
+ }
+ if pk.Y, in, ok = getMPI(in); !ok {
+ return nil, false
+ }
+
+ return in, true
+}
+
+func (pk *PublicKey) Serialize(in []byte) []byte {
+ in = appendU16(in, 0)
+ in = appendMPI(in, pk.P)
+ in = appendMPI(in, pk.Q)
+ in = appendMPI(in, pk.G)
+ in = appendMPI(in, pk.Y)
+ return in
+}
+
+// Fingerprint returns the 20-byte, binary fingerprint of the PublicKey.
+func (pk *PublicKey) Fingerprint() []byte {
+ b := pk.Serialize(nil)
+ h := sha1.New()
+ h.Write(b[2:])
+ return h.Sum(nil)
+}
+
+func (pk *PublicKey) Verify(hashed, sig []byte) ([]byte, bool) {
+ if len(sig) != 2*dsaSubgroupBytes {
+ return nil, false
+ }
+ r := new(big.Int).SetBytes(sig[:dsaSubgroupBytes])
+ s := new(big.Int).SetBytes(sig[dsaSubgroupBytes:])
+ ok := dsa.Verify(&pk.PublicKey, hashed, r, s)
+ return sig[dsaSubgroupBytes*2:], ok
+}
+
+type PrivateKey struct {
+ PublicKey
+ dsa.PrivateKey
+}
+
+func (priv *PrivateKey) Sign(rand io.Reader, hashed []byte) []byte {
+ r, s, err := dsa.Sign(rand, &priv.PrivateKey, hashed)
+ if err != nil {
+ panic(err.Error())
+ }
+ rBytes := r.Bytes()
+ sBytes := s.Bytes()
+ if len(rBytes) > dsaSubgroupBytes || len(sBytes) > dsaSubgroupBytes {
+ panic("DSA signature too large")
+ }
+
+ out := make([]byte, 2*dsaSubgroupBytes)
+ copy(out[dsaSubgroupBytes-len(rBytes):], rBytes)
+ copy(out[len(out)-len(sBytes):], sBytes)
+ return out
+}
+
+func (priv *PrivateKey) Serialize(in []byte) []byte {
+ in = priv.PublicKey.Serialize(in)
+ in = appendMPI(in, priv.PrivateKey.X)
+ return in
+}
+
+func (priv *PrivateKey) Parse(in []byte) ([]byte, bool) {
+ in, ok := priv.PublicKey.Parse(in)
+ if !ok {
+ return in, ok
+ }
+ priv.PrivateKey.PublicKey = priv.PublicKey.PublicKey
+ priv.PrivateKey.X, in, ok = getMPI(in)
+ return in, ok
+}
+
+func (priv *PrivateKey) Generate(rand io.Reader) {
+ if err := dsa.GenerateParameters(&priv.PrivateKey.PublicKey.Parameters, rand, dsa.L1024N160); err != nil {
+ panic(err.Error())
+ }
+ if err := dsa.GenerateKey(&priv.PrivateKey, rand); err != nil {
+ panic(err.Error())
+ }
+ priv.PublicKey.PublicKey = priv.PrivateKey.PublicKey
+}
+
+func notHex(r rune) bool {
+ if r >= '0' && r <= '9' ||
+ r >= 'a' && r <= 'f' ||
+ r >= 'A' && r <= 'F' {
+ return false
+ }
+
+ return true
+}
+
+// Import parses the contents of a libotr private key file.
+func (priv *PrivateKey) Import(in []byte) bool {
+ mpiStart := []byte(" #")
+
+ mpis := make([]*big.Int, 5)
+
+ for i := 0; i < len(mpis); i++ {
+ start := bytes.Index(in, mpiStart)
+ if start == -1 {
+ return false
+ }
+ in = in[start+len(mpiStart):]
+ end := bytes.IndexFunc(in, notHex)
+ if end == -1 {
+ return false
+ }
+ hexBytes := in[:end]
+ in = in[end:]
+
+ if len(hexBytes)&1 != 0 {
+ return false
+ }
+
+ mpiBytes := make([]byte, len(hexBytes)/2)
+ if _, err := hex.Decode(mpiBytes, hexBytes); err != nil {
+ return false
+ }
+
+ mpis[i] = new(big.Int).SetBytes(mpiBytes)
+ }
+
+ for _, mpi := range mpis {
+ if mpi.Sign() <= 0 {
+ return false
+ }
+ }
+
+ priv.PrivateKey.P = mpis[0]
+ priv.PrivateKey.Q = mpis[1]
+ priv.PrivateKey.G = mpis[2]
+ priv.PrivateKey.Y = mpis[3]
+ priv.PrivateKey.X = mpis[4]
+ priv.PublicKey.PublicKey = priv.PrivateKey.PublicKey
+
+ a := new(big.Int).Exp(priv.PrivateKey.G, priv.PrivateKey.X, priv.PrivateKey.P)
+ return a.Cmp(priv.PrivateKey.Y) == 0
+}
+
+func getU8(in []byte) (uint8, []byte, bool) {
+ if len(in) < 1 {
+ return 0, in, false
+ }
+ return in[0], in[1:], true
+}
+
+func getU16(in []byte) (uint16, []byte, bool) {
+ if len(in) < 2 {
+ return 0, in, false
+ }
+ r := uint16(in[0])<<8 | uint16(in[1])
+ return r, in[2:], true
+}
+
+func getU32(in []byte) (uint32, []byte, bool) {
+ if len(in) < 4 {
+ return 0, in, false
+ }
+ r := uint32(in[0])<<24 | uint32(in[1])<<16 | uint32(in[2])<<8 | uint32(in[3])
+ return r, in[4:], true
+}
+
+func getMPI(in []byte) (*big.Int, []byte, bool) {
+ l, in, ok := getU32(in)
+ if !ok || uint32(len(in)) < l {
+ return nil, in, false
+ }
+ r := new(big.Int).SetBytes(in[:l])
+ return r, in[l:], true
+}
+
+func getData(in []byte) ([]byte, []byte, bool) {
+ l, in, ok := getU32(in)
+ if !ok || uint32(len(in)) < l {
+ return nil, in, false
+ }
+ return in[:l], in[l:], true
+}
+
+func getNBytes(in []byte, n int) ([]byte, []byte, bool) {
+ if len(in) < n {
+ return nil, in, false
+ }
+ return in[:n], in[n:], true
+}
+
+func appendU16(out []byte, v uint16) []byte {
+ out = append(out, byte(v>>8), byte(v))
+ return out
+}
+
+func appendU32(out []byte, v uint32) []byte {
+ out = append(out, byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
+ return out
+}
+
+func appendData(out, v []byte) []byte {
+ out = appendU32(out, uint32(len(v)))
+ out = append(out, v...)
+ return out
+}
+
+func appendMPI(out []byte, v *big.Int) []byte {
+ vBytes := v.Bytes()
+ out = appendU32(out, uint32(len(vBytes)))
+ out = append(out, vBytes...)
+ return out
+}
+
+func appendMPIs(out []byte, mpis ...*big.Int) []byte {
+ for _, mpi := range mpis {
+ out = appendMPI(out, mpi)
+ }
+ return out
+}
+
+func zero(b []byte) {
+ for i := range b {
+ b[i] = 0
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/otr/otr_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/otr/otr_test.go
new file mode 100644
index 000000000..cfcd062b2
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/otr/otr_test.go
@@ -0,0 +1,470 @@
+// Copyright 2012 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 otr
+
+import (
+ "bufio"
+ "bytes"
+ "crypto/rand"
+ "encoding/hex"
+ "math/big"
+ "os"
+ "os/exec"
+ "testing"
+)
+
+var isQueryTests = []struct {
+ msg string
+ expectedVersion int
+}{
+ {"foo", 0},
+ {"?OtR", 0},
+ {"?OtR?", 0},
+ {"?OTR?", 0},
+ {"?OTRv?", 0},
+ {"?OTRv1?", 0},
+ {"?OTR?v1?", 0},
+ {"?OTR?v?", 0},
+ {"?OTR?v2?", 2},
+ {"?OTRv2?", 2},
+ {"?OTRv23?", 2},
+ {"?OTRv23 ?", 0},
+}
+
+func TestIsQuery(t *testing.T) {
+ for i, test := range isQueryTests {
+ version := isQuery([]byte(test.msg))
+ if version != test.expectedVersion {
+ t.Errorf("#%d: got %d, want %d", i, version, test.expectedVersion)
+ }
+ }
+}
+
+var alicePrivateKeyHex = "000000000080c81c2cb2eb729b7e6fd48e975a932c638b3a9055478583afa46755683e30102447f6da2d8bec9f386bbb5da6403b0040fee8650b6ab2d7f32c55ab017ae9b6aec8c324ab5844784e9a80e194830d548fb7f09a0410df2c4d5c8bc2b3e9ad484e65412be689cf0834694e0839fb2954021521ffdffb8f5c32c14dbf2020b3ce7500000014da4591d58def96de61aea7b04a8405fe1609308d000000808ddd5cb0b9d66956e3dea5a915d9aba9d8a6e7053b74dadb2fc52f9fe4e5bcc487d2305485ed95fed026ad93f06ebb8c9e8baf693b7887132c7ffdd3b0f72f4002ff4ed56583ca7c54458f8c068ca3e8a4dfa309d1dd5d34e2a4b68e6f4338835e5e0fb4317c9e4c7e4806dafda3ef459cd563775a586dd91b1319f72621bf3f00000080b8147e74d8c45e6318c37731b8b33b984a795b3653c2cd1d65cc99efe097cb7eb2fa49569bab5aab6e8a1c261a27d0f7840a5e80b317e6683042b59b6dceca2879c6ffc877a465be690c15e4a42f9a7588e79b10faac11b1ce3741fcef7aba8ce05327a2c16d279ee1b3d77eb783fb10e3356caa25635331e26dd42b8396c4d00000001420bec691fea37ecea58a5c717142f0b804452f57"
+
+var aliceFingerprintHex = "0bb01c360424522e94ee9c346ce877a1a4288b2f"
+
+var bobPrivateKeyHex = "000000000080a5138eb3d3eb9c1d85716faecadb718f87d31aaed1157671d7fee7e488f95e8e0ba60ad449ec732710a7dec5190f7182af2e2f98312d98497221dff160fd68033dd4f3a33b7c078d0d9f66e26847e76ca7447d4bab35486045090572863d9e4454777f24d6706f63e02548dfec2d0a620af37bbc1d24f884708a212c343b480d00000014e9c58f0ea21a5e4dfd9f44b6a9f7f6a9961a8fa9000000803c4d111aebd62d3c50c2889d420a32cdf1e98b70affcc1fcf44d59cca2eb019f6b774ef88153fb9b9615441a5fe25ea2d11b74ce922ca0232bd81b3c0fcac2a95b20cb6e6c0c5c1ace2e26f65dc43c751af0edbb10d669890e8ab6beea91410b8b2187af1a8347627a06ecea7e0f772c28aae9461301e83884860c9b656c722f0000008065af8625a555ea0e008cd04743671a3cda21162e83af045725db2eb2bb52712708dc0cc1a84c08b3649b88a966974bde27d8612c2861792ec9f08786a246fcadd6d8d3a81a32287745f309238f47618c2bd7612cb8b02d940571e0f30b96420bcd462ff542901b46109b1e5ad6423744448d20a57818a8cbb1647d0fea3b664e0000001440f9f2eb554cb00d45a5826b54bfa419b6980e48"
+
+func TestKeySerialization(t *testing.T) {
+ var priv PrivateKey
+ alicePrivateKey, _ := hex.DecodeString(alicePrivateKeyHex)
+ rest, ok := priv.Parse(alicePrivateKey)
+ if !ok {
+ t.Error("failed to parse private key")
+ }
+ if len(rest) > 0 {
+ t.Error("data remaining after parsing private key")
+ }
+
+ out := priv.Serialize(nil)
+ if !bytes.Equal(alicePrivateKey, out) {
+ t.Errorf("serialization (%x) is not equal to original (%x)", out, alicePrivateKey)
+ }
+
+ aliceFingerprint, _ := hex.DecodeString(aliceFingerprintHex)
+ fingerprint := priv.PublicKey.Fingerprint()
+ if !bytes.Equal(aliceFingerprint, fingerprint) {
+ t.Errorf("fingerprint (%x) is not equal to expected value (%x)", fingerprint, aliceFingerprint)
+ }
+}
+
+const libOTRPrivateKey = `(privkeys
+ (account
+(name "foo@example.com")
+(protocol prpl-jabber)
+(private-key
+ (dsa
+ (p #00FC07ABCF0DC916AFF6E9AE47BEF60C7AB9B4D6B2469E436630E36F8A489BE812486A09F30B71224508654940A835301ACC525A4FF133FC152CC53DCC59D65C30A54F1993FE13FE63E5823D4C746DB21B90F9B9C00B49EC7404AB1D929BA7FBA12F2E45C6E0A651689750E8528AB8C031D3561FECEE72EBB4A090D450A9B7A857#)
+ (q #00997BD266EF7B1F60A5C23F3A741F2AEFD07A2081#)
+ (g #535E360E8A95EBA46A4F7DE50AD6E9B2A6DB785A66B64EB9F20338D2A3E8FB0E94725848F1AA6CC567CB83A1CC517EC806F2E92EAE71457E80B2210A189B91250779434B41FC8A8873F6DB94BEA7D177F5D59E7E114EE10A49CFD9CEF88AE43387023B672927BA74B04EB6BBB5E57597766A2F9CE3857D7ACE3E1E3BC1FC6F26#)
+ (y #0AC8670AD767D7A8D9D14CC1AC6744CD7D76F993B77FFD9E39DF01E5A6536EF65E775FCEF2A983E2A19BD6415500F6979715D9FD1257E1FE2B6F5E1E74B333079E7C880D39868462A93454B41877BE62E5EF0A041C2EE9C9E76BD1E12AE25D9628DECB097025DD625EF49C3258A1A3C0FF501E3DC673B76D7BABF349009B6ECF#)
+ (x #14D0345A3562C480A039E3C72764F72D79043216#)
+ )
+ )
+ )
+)`
+
+func TestParseLibOTRPrivateKey(t *testing.T) {
+ var priv PrivateKey
+
+ if !priv.Import([]byte(libOTRPrivateKey)) {
+ t.Fatalf("Failed to import sample private key")
+ }
+}
+
+func TestSignVerify(t *testing.T) {
+ var priv PrivateKey
+ alicePrivateKey, _ := hex.DecodeString(alicePrivateKeyHex)
+ _, ok := priv.Parse(alicePrivateKey)
+ if !ok {
+ t.Error("failed to parse private key")
+ }
+
+ var msg [32]byte
+ rand.Reader.Read(msg[:])
+
+ sig := priv.Sign(rand.Reader, msg[:])
+ rest, ok := priv.PublicKey.Verify(msg[:], sig)
+ if !ok {
+ t.Errorf("signature (%x) of %x failed to verify", sig, msg[:])
+ } else if len(rest) > 0 {
+ t.Error("signature data remains after verification")
+ }
+
+ sig[10] ^= 80
+ _, ok = priv.PublicKey.Verify(msg[:], sig)
+ if ok {
+ t.Errorf("corrupted signature (%x) of %x verified", sig, msg[:])
+ }
+}
+
+func setupConversation(t *testing.T) (alice, bob *Conversation) {
+ alicePrivateKey, _ := hex.DecodeString(alicePrivateKeyHex)
+ bobPrivateKey, _ := hex.DecodeString(bobPrivateKeyHex)
+
+ alice, bob = new(Conversation), new(Conversation)
+
+ alice.PrivateKey = new(PrivateKey)
+ bob.PrivateKey = new(PrivateKey)
+ alice.PrivateKey.Parse(alicePrivateKey)
+ bob.PrivateKey.Parse(bobPrivateKey)
+ alice.FragmentSize = 100
+ bob.FragmentSize = 100
+
+ if alice.IsEncrypted() {
+ t.Error("Alice believes that the conversation is secure before we've started")
+ }
+ if bob.IsEncrypted() {
+ t.Error("Bob believes that the conversation is secure before we've started")
+ }
+
+ performHandshake(t, alice, bob)
+ return alice, bob
+}
+
+func performHandshake(t *testing.T, alice, bob *Conversation) {
+ var alicesMessage, bobsMessage [][]byte
+ var out []byte
+ var aliceChange, bobChange SecurityChange
+ var err error
+ alicesMessage = append(alicesMessage, []byte(QueryMessage))
+
+ for round := 0; len(alicesMessage) > 0 || len(bobsMessage) > 0; round++ {
+ bobsMessage = nil
+ for i, msg := range alicesMessage {
+ out, _, bobChange, bobsMessage, err = bob.Receive(msg)
+ if len(out) > 0 {
+ t.Errorf("Bob generated output during key exchange, round %d, message %d", round, i)
+ }
+ if err != nil {
+ t.Fatalf("Bob returned an error, round %d, message %d (%x): %s", round, i, msg, err)
+ }
+ if len(bobsMessage) > 0 && i != len(alicesMessage)-1 {
+ t.Errorf("Bob produced output while processing a fragment, round %d, message %d", round, i)
+ }
+ }
+
+ alicesMessage = nil
+ for i, msg := range bobsMessage {
+ out, _, aliceChange, alicesMessage, err = alice.Receive(msg)
+ if len(out) > 0 {
+ t.Errorf("Alice generated output during key exchange, round %d, message %d", round, i)
+ }
+ if err != nil {
+ t.Fatalf("Alice returned an error, round %d, message %d (%x): %s", round, i, msg, err)
+ }
+ if len(alicesMessage) > 0 && i != len(bobsMessage)-1 {
+ t.Errorf("Alice produced output while processing a fragment, round %d, message %d", round, i)
+ }
+ }
+ }
+
+ if aliceChange != NewKeys {
+ t.Errorf("Alice terminated without signaling new keys")
+ }
+ if bobChange != NewKeys {
+ t.Errorf("Bob terminated without signaling new keys")
+ }
+
+ if !bytes.Equal(alice.SSID[:], bob.SSID[:]) {
+ t.Errorf("Session identifiers don't match. Alice has %x, Bob has %x", alice.SSID[:], bob.SSID[:])
+ }
+
+ if !alice.IsEncrypted() {
+ t.Error("Alice doesn't believe that the conversation is secure")
+ }
+ if !bob.IsEncrypted() {
+ t.Error("Bob doesn't believe that the conversation is secure")
+ }
+}
+
+const (
+ firstRoundTrip = iota
+ subsequentRoundTrip
+ noMACKeyCheck
+)
+
+func roundTrip(t *testing.T, alice, bob *Conversation, message []byte, macKeyCheck int) {
+ alicesMessage, err := alice.Send(message)
+ if err != nil {
+ t.Errorf("Error from Alice sending message: %s", err)
+ }
+
+ if len(alice.oldMACs) != 0 {
+ t.Errorf("Alice has not revealed all MAC keys")
+ }
+
+ for i, msg := range alicesMessage {
+ out, encrypted, _, _, err := bob.Receive(msg)
+
+ if err != nil {
+ t.Errorf("Error generated while processing test message: %s", err.Error())
+ }
+ if len(out) > 0 {
+ if i != len(alicesMessage)-1 {
+ t.Fatal("Bob produced a message while processing a fragment of Alice's")
+ }
+ if !encrypted {
+ t.Errorf("Message was not marked as encrypted")
+ }
+ if !bytes.Equal(out, message) {
+ t.Errorf("Message corrupted: got %x, want %x", out, message)
+ }
+ }
+ }
+
+ switch macKeyCheck {
+ case firstRoundTrip:
+ if len(bob.oldMACs) != 0 {
+ t.Errorf("Bob should not have MAC keys to reveal")
+ }
+ case subsequentRoundTrip:
+ if len(bob.oldMACs) != 40 {
+ t.Errorf("Bob has %d bytes of MAC keys to reveal, but should have 40", len(bob.oldMACs))
+ }
+ }
+
+ bobsMessage, err := bob.Send(message)
+ if err != nil {
+ t.Errorf("Error from Bob sending message: %s", err)
+ }
+
+ if len(bob.oldMACs) != 0 {
+ t.Errorf("Bob has not revealed all MAC keys")
+ }
+
+ for i, msg := range bobsMessage {
+ out, encrypted, _, _, err := alice.Receive(msg)
+
+ if err != nil {
+ t.Errorf("Error generated while processing test message: %s", err.Error())
+ }
+ if len(out) > 0 {
+ if i != len(bobsMessage)-1 {
+ t.Fatal("Alice produced a message while processing a fragment of Bob's")
+ }
+ if !encrypted {
+ t.Errorf("Message was not marked as encrypted")
+ }
+ if !bytes.Equal(out, message) {
+ t.Errorf("Message corrupted: got %x, want %x", out, message)
+ }
+ }
+ }
+
+ switch macKeyCheck {
+ case firstRoundTrip:
+ if len(alice.oldMACs) != 20 {
+ t.Errorf("Alice has %d bytes of MAC keys to reveal, but should have 20", len(alice.oldMACs))
+ }
+ case subsequentRoundTrip:
+ if len(alice.oldMACs) != 40 {
+ t.Errorf("Alice has %d bytes of MAC keys to reveal, but should have 40", len(alice.oldMACs))
+ }
+ }
+}
+
+func TestConversation(t *testing.T) {
+ alice, bob := setupConversation(t)
+
+ var testMessages = [][]byte{
+ []byte("hello"), []byte("bye"),
+ }
+
+ roundTripType := firstRoundTrip
+
+ for _, testMessage := range testMessages {
+ roundTrip(t, alice, bob, testMessage, roundTripType)
+ roundTripType = subsequentRoundTrip
+ }
+}
+
+func TestGoodSMP(t *testing.T) {
+ var alice, bob Conversation
+
+ alice.smp.secret = new(big.Int).SetInt64(42)
+ bob.smp.secret = alice.smp.secret
+
+ var alicesMessages, bobsMessages []tlv
+ var aliceComplete, bobComplete bool
+ var err error
+ var out tlv
+
+ alicesMessages = alice.startSMP("")
+ for round := 0; len(alicesMessages) > 0 || len(bobsMessages) > 0; round++ {
+ bobsMessages = bobsMessages[:0]
+ for i, msg := range alicesMessages {
+ out, bobComplete, err = bob.processSMP(msg)
+ if err != nil {
+ t.Errorf("Error from Bob in round %d: %s", round, err)
+ }
+ if bobComplete && i != len(alicesMessages)-1 {
+ t.Errorf("Bob returned a completed signal before processing all of Alice's messages in round %d", round)
+ }
+ if out.typ != 0 {
+ bobsMessages = append(bobsMessages, out)
+ }
+ }
+
+ alicesMessages = alicesMessages[:0]
+ for i, msg := range bobsMessages {
+ out, aliceComplete, err = alice.processSMP(msg)
+ if err != nil {
+ t.Errorf("Error from Alice in round %d: %s", round, err)
+ }
+ if aliceComplete && i != len(bobsMessages)-1 {
+ t.Errorf("Alice returned a completed signal before processing all of Bob's messages in round %d", round)
+ }
+ if out.typ != 0 {
+ alicesMessages = append(alicesMessages, out)
+ }
+ }
+ }
+
+ if !aliceComplete || !bobComplete {
+ t.Errorf("SMP completed without both sides reporting success: alice: %v, bob: %v\n", aliceComplete, bobComplete)
+ }
+}
+
+func TestBadSMP(t *testing.T) {
+ var alice, bob Conversation
+
+ alice.smp.secret = new(big.Int).SetInt64(42)
+ bob.smp.secret = new(big.Int).SetInt64(43)
+
+ var alicesMessages, bobsMessages []tlv
+
+ alicesMessages = alice.startSMP("")
+ for round := 0; len(alicesMessages) > 0 || len(bobsMessages) > 0; round++ {
+ bobsMessages = bobsMessages[:0]
+ for _, msg := range alicesMessages {
+ out, complete, _ := bob.processSMP(msg)
+ if complete {
+ t.Errorf("Bob signaled completion in round %d", round)
+ }
+ if out.typ != 0 {
+ bobsMessages = append(bobsMessages, out)
+ }
+ }
+
+ alicesMessages = alicesMessages[:0]
+ for _, msg := range bobsMessages {
+ out, complete, _ := alice.processSMP(msg)
+ if complete {
+ t.Errorf("Alice signaled completion in round %d", round)
+ }
+ if out.typ != 0 {
+ alicesMessages = append(alicesMessages, out)
+ }
+ }
+ }
+}
+
+func TestRehandshaking(t *testing.T) {
+ alice, bob := setupConversation(t)
+ roundTrip(t, alice, bob, []byte("test"), firstRoundTrip)
+ roundTrip(t, alice, bob, []byte("test 2"), subsequentRoundTrip)
+ roundTrip(t, alice, bob, []byte("test 3"), subsequentRoundTrip)
+ roundTrip(t, alice, bob, []byte("test 4"), subsequentRoundTrip)
+ roundTrip(t, alice, bob, []byte("test 5"), subsequentRoundTrip)
+ roundTrip(t, alice, bob, []byte("test 6"), subsequentRoundTrip)
+ roundTrip(t, alice, bob, []byte("test 7"), subsequentRoundTrip)
+ roundTrip(t, alice, bob, []byte("test 8"), subsequentRoundTrip)
+ performHandshake(t, alice, bob)
+ roundTrip(t, alice, bob, []byte("test"), noMACKeyCheck)
+ roundTrip(t, alice, bob, []byte("test 2"), noMACKeyCheck)
+}
+
+func TestAgainstLibOTR(t *testing.T) {
+ // This test requires otr.c.test to be built as /tmp/a.out.
+ // If enabled, this tests runs forever performing OTR handshakes in a
+ // loop.
+ return
+
+ alicePrivateKey, _ := hex.DecodeString(alicePrivateKeyHex)
+ var alice Conversation
+ alice.PrivateKey = new(PrivateKey)
+ alice.PrivateKey.Parse(alicePrivateKey)
+
+ cmd := exec.Command("/tmp/a.out")
+ cmd.Stderr = os.Stderr
+
+ out, err := cmd.StdinPipe()
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer out.Close()
+ stdout, err := cmd.StdoutPipe()
+ if err != nil {
+ t.Fatal(err)
+ }
+ in := bufio.NewReader(stdout)
+
+ if err := cmd.Start(); err != nil {
+ t.Fatal(err)
+ }
+
+ out.Write([]byte(QueryMessage))
+ out.Write([]byte("\n"))
+ var expectedText = []byte("test message")
+
+ for {
+ line, isPrefix, err := in.ReadLine()
+ if isPrefix {
+ t.Fatal("line from subprocess too long")
+ }
+ if err != nil {
+ t.Fatal(err)
+ }
+ text, encrypted, change, alicesMessage, err := alice.Receive(line)
+ if err != nil {
+ t.Fatal(err)
+ }
+ for _, msg := range alicesMessage {
+ out.Write(msg)
+ out.Write([]byte("\n"))
+ }
+ if change == NewKeys {
+ alicesMessage, err := alice.Send([]byte("Go -> libotr test message"))
+ if err != nil {
+ t.Fatalf("error sending message: %s", err.Error())
+ } else {
+ for _, msg := range alicesMessage {
+ out.Write(msg)
+ out.Write([]byte("\n"))
+ }
+ }
+ }
+ if len(text) > 0 {
+ if !bytes.Equal(text, expectedText) {
+ t.Fatalf("expected %x, but got %x", expectedText, text)
+ }
+ if !encrypted {
+ t.Fatal("message wasn't encrypted")
+ }
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/otr/smp.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/otr/smp.go
new file mode 100644
index 000000000..dc6de4ee0
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/otr/smp.go
@@ -0,0 +1,572 @@
+// Copyright 2012 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.
+
+// This file implements the Socialist Millionaires Protocol as described in
+// http://www.cypherpunks.ca/otr/Protocol-v2-3.1.0.html. The protocol
+// specification is required in order to understand this code and, where
+// possible, the variable names in the code match up with the spec.
+
+package otr
+
+import (
+ "bytes"
+ "crypto/sha256"
+ "errors"
+ "hash"
+ "math/big"
+)
+
+type smpFailure string
+
+func (s smpFailure) Error() string {
+ return string(s)
+}
+
+var smpFailureError = smpFailure("otr: SMP protocol failed")
+var smpSecretMissingError = smpFailure("otr: mutual secret needed")
+
+const smpVersion = 1
+
+const (
+ smpState1 = iota
+ smpState2
+ smpState3
+ smpState4
+)
+
+type smpState struct {
+ state int
+ a2, a3, b2, b3, pb, qb *big.Int
+ g2a, g3a *big.Int
+ g2, g3 *big.Int
+ g3b, papb, qaqb, ra *big.Int
+ saved *tlv
+ secret *big.Int
+ question string
+}
+
+func (c *Conversation) startSMP(question string) (tlvs []tlv) {
+ if c.smp.state != smpState1 {
+ tlvs = append(tlvs, c.generateSMPAbort())
+ }
+ tlvs = append(tlvs, c.generateSMP1(question))
+ c.smp.question = ""
+ c.smp.state = smpState2
+ return
+}
+
+func (c *Conversation) resetSMP() {
+ c.smp.state = smpState1
+ c.smp.secret = nil
+ c.smp.question = ""
+}
+
+func (c *Conversation) processSMP(in tlv) (out tlv, complete bool, err error) {
+ data := in.data
+
+ switch in.typ {
+ case tlvTypeSMPAbort:
+ if c.smp.state != smpState1 {
+ err = smpFailureError
+ }
+ c.resetSMP()
+ return
+ case tlvTypeSMP1WithQuestion:
+ // We preprocess this into a SMP1 message.
+ nulPos := bytes.IndexByte(data, 0)
+ if nulPos == -1 {
+ err = errors.New("otr: SMP message with question didn't contain a NUL byte")
+ return
+ }
+ c.smp.question = string(data[:nulPos])
+ data = data[nulPos+1:]
+ }
+
+ numMPIs, data, ok := getU32(data)
+ if !ok || numMPIs > 20 {
+ err = errors.New("otr: corrupt SMP message")
+ return
+ }
+
+ mpis := make([]*big.Int, numMPIs)
+ for i := range mpis {
+ var ok bool
+ mpis[i], data, ok = getMPI(data)
+ if !ok {
+ err = errors.New("otr: corrupt SMP message")
+ return
+ }
+ }
+
+ switch in.typ {
+ case tlvTypeSMP1, tlvTypeSMP1WithQuestion:
+ if c.smp.state != smpState1 {
+ c.resetSMP()
+ out = c.generateSMPAbort()
+ return
+ }
+ if c.smp.secret == nil {
+ err = smpSecretMissingError
+ return
+ }
+ if err = c.processSMP1(mpis); err != nil {
+ return
+ }
+ c.smp.state = smpState3
+ out = c.generateSMP2()
+ case tlvTypeSMP2:
+ if c.smp.state != smpState2 {
+ c.resetSMP()
+ out = c.generateSMPAbort()
+ return
+ }
+ if out, err = c.processSMP2(mpis); err != nil {
+ out = c.generateSMPAbort()
+ return
+ }
+ c.smp.state = smpState4
+ case tlvTypeSMP3:
+ if c.smp.state != smpState3 {
+ c.resetSMP()
+ out = c.generateSMPAbort()
+ return
+ }
+ if out, err = c.processSMP3(mpis); err != nil {
+ return
+ }
+ c.smp.state = smpState1
+ c.smp.secret = nil
+ complete = true
+ case tlvTypeSMP4:
+ if c.smp.state != smpState4 {
+ c.resetSMP()
+ out = c.generateSMPAbort()
+ return
+ }
+ if err = c.processSMP4(mpis); err != nil {
+ out = c.generateSMPAbort()
+ return
+ }
+ c.smp.state = smpState1
+ c.smp.secret = nil
+ complete = true
+ default:
+ panic("unknown SMP message")
+ }
+
+ return
+}
+
+func (c *Conversation) calcSMPSecret(mutualSecret []byte, weStarted bool) {
+ h := sha256.New()
+ h.Write([]byte{smpVersion})
+ if weStarted {
+ h.Write(c.PrivateKey.PublicKey.Fingerprint())
+ h.Write(c.TheirPublicKey.Fingerprint())
+ } else {
+ h.Write(c.TheirPublicKey.Fingerprint())
+ h.Write(c.PrivateKey.PublicKey.Fingerprint())
+ }
+ h.Write(c.SSID[:])
+ h.Write(mutualSecret)
+ c.smp.secret = new(big.Int).SetBytes(h.Sum(nil))
+}
+
+func (c *Conversation) generateSMP1(question string) tlv {
+ var randBuf [16]byte
+ c.smp.a2 = c.randMPI(randBuf[:])
+ c.smp.a3 = c.randMPI(randBuf[:])
+ g2a := new(big.Int).Exp(g, c.smp.a2, p)
+ g3a := new(big.Int).Exp(g, c.smp.a3, p)
+ h := sha256.New()
+
+ r2 := c.randMPI(randBuf[:])
+ r := new(big.Int).Exp(g, r2, p)
+ c2 := new(big.Int).SetBytes(hashMPIs(h, 1, r))
+ d2 := new(big.Int).Mul(c.smp.a2, c2)
+ d2.Sub(r2, d2)
+ d2.Mod(d2, q)
+ if d2.Sign() < 0 {
+ d2.Add(d2, q)
+ }
+
+ r3 := c.randMPI(randBuf[:])
+ r.Exp(g, r3, p)
+ c3 := new(big.Int).SetBytes(hashMPIs(h, 2, r))
+ d3 := new(big.Int).Mul(c.smp.a3, c3)
+ d3.Sub(r3, d3)
+ d3.Mod(d3, q)
+ if d3.Sign() < 0 {
+ d3.Add(d3, q)
+ }
+
+ var ret tlv
+ if len(question) > 0 {
+ ret.typ = tlvTypeSMP1WithQuestion
+ ret.data = append(ret.data, question...)
+ ret.data = append(ret.data, 0)
+ } else {
+ ret.typ = tlvTypeSMP1
+ }
+ ret.data = appendU32(ret.data, 6)
+ ret.data = appendMPIs(ret.data, g2a, c2, d2, g3a, c3, d3)
+ return ret
+}
+
+func (c *Conversation) processSMP1(mpis []*big.Int) error {
+ if len(mpis) != 6 {
+ return errors.New("otr: incorrect number of arguments in SMP1 message")
+ }
+ g2a := mpis[0]
+ c2 := mpis[1]
+ d2 := mpis[2]
+ g3a := mpis[3]
+ c3 := mpis[4]
+ d3 := mpis[5]
+ h := sha256.New()
+
+ r := new(big.Int).Exp(g, d2, p)
+ s := new(big.Int).Exp(g2a, c2, p)
+ r.Mul(r, s)
+ r.Mod(r, p)
+ t := new(big.Int).SetBytes(hashMPIs(h, 1, r))
+ if c2.Cmp(t) != 0 {
+ return errors.New("otr: ZKP c2 incorrect in SMP1 message")
+ }
+ r.Exp(g, d3, p)
+ s.Exp(g3a, c3, p)
+ r.Mul(r, s)
+ r.Mod(r, p)
+ t.SetBytes(hashMPIs(h, 2, r))
+ if c3.Cmp(t) != 0 {
+ return errors.New("otr: ZKP c3 incorrect in SMP1 message")
+ }
+
+ c.smp.g2a = g2a
+ c.smp.g3a = g3a
+ return nil
+}
+
+func (c *Conversation) generateSMP2() tlv {
+ var randBuf [16]byte
+ b2 := c.randMPI(randBuf[:])
+ c.smp.b3 = c.randMPI(randBuf[:])
+ r2 := c.randMPI(randBuf[:])
+ r3 := c.randMPI(randBuf[:])
+ r4 := c.randMPI(randBuf[:])
+ r5 := c.randMPI(randBuf[:])
+ r6 := c.randMPI(randBuf[:])
+
+ g2b := new(big.Int).Exp(g, b2, p)
+ g3b := new(big.Int).Exp(g, c.smp.b3, p)
+
+ r := new(big.Int).Exp(g, r2, p)
+ h := sha256.New()
+ c2 := new(big.Int).SetBytes(hashMPIs(h, 3, r))
+ d2 := new(big.Int).Mul(b2, c2)
+ d2.Sub(r2, d2)
+ d2.Mod(d2, q)
+ if d2.Sign() < 0 {
+ d2.Add(d2, q)
+ }
+
+ r.Exp(g, r3, p)
+ c3 := new(big.Int).SetBytes(hashMPIs(h, 4, r))
+ d3 := new(big.Int).Mul(c.smp.b3, c3)
+ d3.Sub(r3, d3)
+ d3.Mod(d3, q)
+ if d3.Sign() < 0 {
+ d3.Add(d3, q)
+ }
+
+ c.smp.g2 = new(big.Int).Exp(c.smp.g2a, b2, p)
+ c.smp.g3 = new(big.Int).Exp(c.smp.g3a, c.smp.b3, p)
+ c.smp.pb = new(big.Int).Exp(c.smp.g3, r4, p)
+ c.smp.qb = new(big.Int).Exp(g, r4, p)
+ r.Exp(c.smp.g2, c.smp.secret, p)
+ c.smp.qb.Mul(c.smp.qb, r)
+ c.smp.qb.Mod(c.smp.qb, p)
+
+ s := new(big.Int)
+ s.Exp(c.smp.g2, r6, p)
+ r.Exp(g, r5, p)
+ s.Mul(r, s)
+ s.Mod(s, p)
+ r.Exp(c.smp.g3, r5, p)
+ cp := new(big.Int).SetBytes(hashMPIs(h, 5, r, s))
+
+ // D5 = r5 - r4 cP mod q and D6 = r6 - y cP mod q
+
+ s.Mul(r4, cp)
+ r.Sub(r5, s)
+ d5 := new(big.Int).Mod(r, q)
+ if d5.Sign() < 0 {
+ d5.Add(d5, q)
+ }
+
+ s.Mul(c.smp.secret, cp)
+ r.Sub(r6, s)
+ d6 := new(big.Int).Mod(r, q)
+ if d6.Sign() < 0 {
+ d6.Add(d6, q)
+ }
+
+ var ret tlv
+ ret.typ = tlvTypeSMP2
+ ret.data = appendU32(ret.data, 11)
+ ret.data = appendMPIs(ret.data, g2b, c2, d2, g3b, c3, d3, c.smp.pb, c.smp.qb, cp, d5, d6)
+ return ret
+}
+
+func (c *Conversation) processSMP2(mpis []*big.Int) (out tlv, err error) {
+ if len(mpis) != 11 {
+ err = errors.New("otr: incorrect number of arguments in SMP2 message")
+ return
+ }
+ g2b := mpis[0]
+ c2 := mpis[1]
+ d2 := mpis[2]
+ g3b := mpis[3]
+ c3 := mpis[4]
+ d3 := mpis[5]
+ pb := mpis[6]
+ qb := mpis[7]
+ cp := mpis[8]
+ d5 := mpis[9]
+ d6 := mpis[10]
+ h := sha256.New()
+
+ r := new(big.Int).Exp(g, d2, p)
+ s := new(big.Int).Exp(g2b, c2, p)
+ r.Mul(r, s)
+ r.Mod(r, p)
+ s.SetBytes(hashMPIs(h, 3, r))
+ if c2.Cmp(s) != 0 {
+ err = errors.New("otr: ZKP c2 failed in SMP2 message")
+ return
+ }
+
+ r.Exp(g, d3, p)
+ s.Exp(g3b, c3, p)
+ r.Mul(r, s)
+ r.Mod(r, p)
+ s.SetBytes(hashMPIs(h, 4, r))
+ if c3.Cmp(s) != 0 {
+ err = errors.New("otr: ZKP c3 failed in SMP2 message")
+ return
+ }
+
+ c.smp.g2 = new(big.Int).Exp(g2b, c.smp.a2, p)
+ c.smp.g3 = new(big.Int).Exp(g3b, c.smp.a3, p)
+
+ r.Exp(g, d5, p)
+ s.Exp(c.smp.g2, d6, p)
+ r.Mul(r, s)
+ s.Exp(qb, cp, p)
+ r.Mul(r, s)
+ r.Mod(r, p)
+
+ s.Exp(c.smp.g3, d5, p)
+ t := new(big.Int).Exp(pb, cp, p)
+ s.Mul(s, t)
+ s.Mod(s, p)
+ t.SetBytes(hashMPIs(h, 5, s, r))
+ if cp.Cmp(t) != 0 {
+ err = errors.New("otr: ZKP cP failed in SMP2 message")
+ return
+ }
+
+ var randBuf [16]byte
+ r4 := c.randMPI(randBuf[:])
+ r5 := c.randMPI(randBuf[:])
+ r6 := c.randMPI(randBuf[:])
+ r7 := c.randMPI(randBuf[:])
+
+ pa := new(big.Int).Exp(c.smp.g3, r4, p)
+ r.Exp(c.smp.g2, c.smp.secret, p)
+ qa := new(big.Int).Exp(g, r4, p)
+ qa.Mul(qa, r)
+ qa.Mod(qa, p)
+
+ r.Exp(g, r5, p)
+ s.Exp(c.smp.g2, r6, p)
+ r.Mul(r, s)
+ r.Mod(r, p)
+
+ s.Exp(c.smp.g3, r5, p)
+ cp.SetBytes(hashMPIs(h, 6, s, r))
+
+ r.Mul(r4, cp)
+ d5 = new(big.Int).Sub(r5, r)
+ d5.Mod(d5, q)
+ if d5.Sign() < 0 {
+ d5.Add(d5, q)
+ }
+
+ r.Mul(c.smp.secret, cp)
+ d6 = new(big.Int).Sub(r6, r)
+ d6.Mod(d6, q)
+ if d6.Sign() < 0 {
+ d6.Add(d6, q)
+ }
+
+ r.ModInverse(qb, p)
+ qaqb := new(big.Int).Mul(qa, r)
+ qaqb.Mod(qaqb, p)
+
+ ra := new(big.Int).Exp(qaqb, c.smp.a3, p)
+ r.Exp(qaqb, r7, p)
+ s.Exp(g, r7, p)
+ cr := new(big.Int).SetBytes(hashMPIs(h, 7, s, r))
+
+ r.Mul(c.smp.a3, cr)
+ d7 := new(big.Int).Sub(r7, r)
+ d7.Mod(d7, q)
+ if d7.Sign() < 0 {
+ d7.Add(d7, q)
+ }
+
+ c.smp.g3b = g3b
+ c.smp.qaqb = qaqb
+
+ r.ModInverse(pb, p)
+ c.smp.papb = new(big.Int).Mul(pa, r)
+ c.smp.papb.Mod(c.smp.papb, p)
+ c.smp.ra = ra
+
+ out.typ = tlvTypeSMP3
+ out.data = appendU32(out.data, 8)
+ out.data = appendMPIs(out.data, pa, qa, cp, d5, d6, ra, cr, d7)
+ return
+}
+
+func (c *Conversation) processSMP3(mpis []*big.Int) (out tlv, err error) {
+ if len(mpis) != 8 {
+ err = errors.New("otr: incorrect number of arguments in SMP3 message")
+ return
+ }
+ pa := mpis[0]
+ qa := mpis[1]
+ cp := mpis[2]
+ d5 := mpis[3]
+ d6 := mpis[4]
+ ra := mpis[5]
+ cr := mpis[6]
+ d7 := mpis[7]
+ h := sha256.New()
+
+ r := new(big.Int).Exp(g, d5, p)
+ s := new(big.Int).Exp(c.smp.g2, d6, p)
+ r.Mul(r, s)
+ s.Exp(qa, cp, p)
+ r.Mul(r, s)
+ r.Mod(r, p)
+
+ s.Exp(c.smp.g3, d5, p)
+ t := new(big.Int).Exp(pa, cp, p)
+ s.Mul(s, t)
+ s.Mod(s, p)
+ t.SetBytes(hashMPIs(h, 6, s, r))
+ if t.Cmp(cp) != 0 {
+ err = errors.New("otr: ZKP cP failed in SMP3 message")
+ return
+ }
+
+ r.ModInverse(c.smp.qb, p)
+ qaqb := new(big.Int).Mul(qa, r)
+ qaqb.Mod(qaqb, p)
+
+ r.Exp(qaqb, d7, p)
+ s.Exp(ra, cr, p)
+ r.Mul(r, s)
+ r.Mod(r, p)
+
+ s.Exp(g, d7, p)
+ t.Exp(c.smp.g3a, cr, p)
+ s.Mul(s, t)
+ s.Mod(s, p)
+ t.SetBytes(hashMPIs(h, 7, s, r))
+ if t.Cmp(cr) != 0 {
+ err = errors.New("otr: ZKP cR failed in SMP3 message")
+ return
+ }
+
+ var randBuf [16]byte
+ r7 := c.randMPI(randBuf[:])
+ rb := new(big.Int).Exp(qaqb, c.smp.b3, p)
+
+ r.Exp(qaqb, r7, p)
+ s.Exp(g, r7, p)
+ cr = new(big.Int).SetBytes(hashMPIs(h, 8, s, r))
+
+ r.Mul(c.smp.b3, cr)
+ d7 = new(big.Int).Sub(r7, r)
+ d7.Mod(d7, q)
+ if d7.Sign() < 0 {
+ d7.Add(d7, q)
+ }
+
+ out.typ = tlvTypeSMP4
+ out.data = appendU32(out.data, 3)
+ out.data = appendMPIs(out.data, rb, cr, d7)
+
+ r.ModInverse(c.smp.pb, p)
+ r.Mul(pa, r)
+ r.Mod(r, p)
+ s.Exp(ra, c.smp.b3, p)
+ if r.Cmp(s) != 0 {
+ err = smpFailureError
+ }
+
+ return
+}
+
+func (c *Conversation) processSMP4(mpis []*big.Int) error {
+ if len(mpis) != 3 {
+ return errors.New("otr: incorrect number of arguments in SMP4 message")
+ }
+ rb := mpis[0]
+ cr := mpis[1]
+ d7 := mpis[2]
+ h := sha256.New()
+
+ r := new(big.Int).Exp(c.smp.qaqb, d7, p)
+ s := new(big.Int).Exp(rb, cr, p)
+ r.Mul(r, s)
+ r.Mod(r, p)
+
+ s.Exp(g, d7, p)
+ t := new(big.Int).Exp(c.smp.g3b, cr, p)
+ s.Mul(s, t)
+ s.Mod(s, p)
+ t.SetBytes(hashMPIs(h, 8, s, r))
+ if t.Cmp(cr) != 0 {
+ return errors.New("otr: ZKP cR failed in SMP4 message")
+ }
+
+ r.Exp(rb, c.smp.a3, p)
+ if r.Cmp(c.smp.papb) != 0 {
+ return smpFailureError
+ }
+
+ return nil
+}
+
+func (c *Conversation) generateSMPAbort() tlv {
+ return tlv{typ: tlvTypeSMPAbort}
+}
+
+func hashMPIs(h hash.Hash, magic byte, mpis ...*big.Int) []byte {
+ if h != nil {
+ h.Reset()
+ } else {
+ h = sha256.New()
+ }
+
+ h.Write([]byte{magic})
+ for _, mpi := range mpis {
+ h.Write(appendMPI(nil, mpi))
+ }
+ return h.Sum(nil)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pbkdf2/pbkdf2.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pbkdf2/pbkdf2.go
new file mode 100644
index 000000000..593f65300
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pbkdf2/pbkdf2.go
@@ -0,0 +1,77 @@
+// Copyright 2012 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 pbkdf2 implements the key derivation function PBKDF2 as defined in RFC
+2898 / PKCS #5 v2.0.
+
+A key derivation function is useful when encrypting data based on a password
+or any other not-fully-random data. It uses a pseudorandom function to derive
+a secure encryption key based on the password.
+
+While v2.0 of the standard defines only one pseudorandom function to use,
+HMAC-SHA1, the drafted v2.1 specification allows use of all five FIPS Approved
+Hash Functions SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512 for HMAC. To
+choose, you can pass the `New` functions from the different SHA packages to
+pbkdf2.Key.
+*/
+package pbkdf2 // import "golang.org/x/crypto/pbkdf2"
+
+import (
+ "crypto/hmac"
+ "hash"
+)
+
+// Key derives a key from the password, salt and iteration count, returning a
+// []byte of length keylen that can be used as cryptographic key. The key is
+// derived based on the method described as PBKDF2 with the HMAC variant using
+// the supplied hash function.
+//
+// For example, to use a HMAC-SHA-1 based PBKDF2 key derivation function, you
+// can get a derived key for e.g. AES-256 (which needs a 32-byte key) by
+// doing:
+//
+// dk := pbkdf2.Key([]byte("some password"), salt, 4096, 32, sha1.New)
+//
+// Remember to get a good random salt. At least 8 bytes is recommended by the
+// RFC.
+//
+// Using a higher iteration count will increase the cost of an exhaustive
+// search but will also make derivation proportionally slower.
+func Key(password, salt []byte, iter, keyLen int, h func() hash.Hash) []byte {
+ prf := hmac.New(h, password)
+ hashLen := prf.Size()
+ numBlocks := (keyLen + hashLen - 1) / hashLen
+
+ var buf [4]byte
+ dk := make([]byte, 0, numBlocks*hashLen)
+ U := make([]byte, hashLen)
+ for block := 1; block <= numBlocks; block++ {
+ // N.B.: || means concatenation, ^ means XOR
+ // for each block T_i = U_1 ^ U_2 ^ ... ^ U_iter
+ // U_1 = PRF(password, salt || uint(i))
+ prf.Reset()
+ prf.Write(salt)
+ buf[0] = byte(block >> 24)
+ buf[1] = byte(block >> 16)
+ buf[2] = byte(block >> 8)
+ buf[3] = byte(block)
+ prf.Write(buf[:4])
+ dk = prf.Sum(dk)
+ T := dk[len(dk)-hashLen:]
+ copy(U, T)
+
+ // U_n = PRF(password, U_(n-1))
+ for n := 2; n <= iter; n++ {
+ prf.Reset()
+ prf.Write(U)
+ U = U[:0]
+ U = prf.Sum(U)
+ for x := range U {
+ T[x] ^= U[x]
+ }
+ }
+ }
+ return dk[:keyLen]
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pbkdf2/pbkdf2_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pbkdf2/pbkdf2_test.go
new file mode 100644
index 000000000..137924061
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pbkdf2/pbkdf2_test.go
@@ -0,0 +1,157 @@
+// Copyright 2012 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 pbkdf2
+
+import (
+ "bytes"
+ "crypto/sha1"
+ "crypto/sha256"
+ "hash"
+ "testing"
+)
+
+type testVector struct {
+ password string
+ salt string
+ iter int
+ output []byte
+}
+
+// Test vectors from RFC 6070, http://tools.ietf.org/html/rfc6070
+var sha1TestVectors = []testVector{
+ {
+ "password",
+ "salt",
+ 1,
+ []byte{
+ 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71,
+ 0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06,
+ 0x2f, 0xe0, 0x37, 0xa6,
+ },
+ },
+ {
+ "password",
+ "salt",
+ 2,
+ []byte{
+ 0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c,
+ 0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0,
+ 0xd8, 0xde, 0x89, 0x57,
+ },
+ },
+ {
+ "password",
+ "salt",
+ 4096,
+ []byte{
+ 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a,
+ 0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0,
+ 0x65, 0xa4, 0x29, 0xc1,
+ },
+ },
+ // // This one takes too long
+ // {
+ // "password",
+ // "salt",
+ // 16777216,
+ // []byte{
+ // 0xee, 0xfe, 0x3d, 0x61, 0xcd, 0x4d, 0xa4, 0xe4,
+ // 0xe9, 0x94, 0x5b, 0x3d, 0x6b, 0xa2, 0x15, 0x8c,
+ // 0x26, 0x34, 0xe9, 0x84,
+ // },
+ // },
+ {
+ "passwordPASSWORDpassword",
+ "saltSALTsaltSALTsaltSALTsaltSALTsalt",
+ 4096,
+ []byte{
+ 0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b,
+ 0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a,
+ 0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70,
+ 0x38,
+ },
+ },
+ {
+ "pass\000word",
+ "sa\000lt",
+ 4096,
+ []byte{
+ 0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d,
+ 0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3,
+ },
+ },
+}
+
+// Test vectors from
+// http://stackoverflow.com/questions/5130513/pbkdf2-hmac-sha2-test-vectors
+var sha256TestVectors = []testVector{
+ {
+ "password",
+ "salt",
+ 1,
+ []byte{
+ 0x12, 0x0f, 0xb6, 0xcf, 0xfc, 0xf8, 0xb3, 0x2c,
+ 0x43, 0xe7, 0x22, 0x52, 0x56, 0xc4, 0xf8, 0x37,
+ 0xa8, 0x65, 0x48, 0xc9,
+ },
+ },
+ {
+ "password",
+ "salt",
+ 2,
+ []byte{
+ 0xae, 0x4d, 0x0c, 0x95, 0xaf, 0x6b, 0x46, 0xd3,
+ 0x2d, 0x0a, 0xdf, 0xf9, 0x28, 0xf0, 0x6d, 0xd0,
+ 0x2a, 0x30, 0x3f, 0x8e,
+ },
+ },
+ {
+ "password",
+ "salt",
+ 4096,
+ []byte{
+ 0xc5, 0xe4, 0x78, 0xd5, 0x92, 0x88, 0xc8, 0x41,
+ 0xaa, 0x53, 0x0d, 0xb6, 0x84, 0x5c, 0x4c, 0x8d,
+ 0x96, 0x28, 0x93, 0xa0,
+ },
+ },
+ {
+ "passwordPASSWORDpassword",
+ "saltSALTsaltSALTsaltSALTsaltSALTsalt",
+ 4096,
+ []byte{
+ 0x34, 0x8c, 0x89, 0xdb, 0xcb, 0xd3, 0x2b, 0x2f,
+ 0x32, 0xd8, 0x14, 0xb8, 0x11, 0x6e, 0x84, 0xcf,
+ 0x2b, 0x17, 0x34, 0x7e, 0xbc, 0x18, 0x00, 0x18,
+ 0x1c,
+ },
+ },
+ {
+ "pass\000word",
+ "sa\000lt",
+ 4096,
+ []byte{
+ 0x89, 0xb6, 0x9d, 0x05, 0x16, 0xf8, 0x29, 0x89,
+ 0x3c, 0x69, 0x62, 0x26, 0x65, 0x0a, 0x86, 0x87,
+ },
+ },
+}
+
+func testHash(t *testing.T, h func() hash.Hash, hashName string, vectors []testVector) {
+ for i, v := range vectors {
+ o := Key([]byte(v.password), []byte(v.salt), v.iter, len(v.output), h)
+ if !bytes.Equal(o, v.output) {
+ t.Errorf("%s %d: expected %x, got %x", hashName, i, v.output, o)
+ }
+ }
+}
+
+func TestWithHMACSHA1(t *testing.T) {
+ testHash(t, sha1.New, "SHA1", sha1TestVectors)
+}
+
+func TestWithHMACSHA256(t *testing.T) {
+ testHash(t, sha256.New, "SHA256", sha256TestVectors)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/bmp-string.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/bmp-string.go
new file mode 100644
index 000000000..233b8b62c
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/bmp-string.go
@@ -0,0 +1,50 @@
+// Copyright 2015 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 pkcs12
+
+import (
+ "errors"
+ "unicode/utf16"
+)
+
+// bmpString returns s encoded in UCS-2 with a zero terminator.
+func bmpString(s string) ([]byte, error) {
+ // References:
+ // https://tools.ietf.org/html/rfc7292#appendix-B.1
+ // https://en.wikipedia.org/wiki/Plane_(Unicode)#Basic_Multilingual_Plane
+ // - non-BMP characters are encoded in UTF 16 by using a surrogate pair of 16-bit codes
+ // EncodeRune returns 0xfffd if the rune does not need special encoding
+ // - the above RFC provides the info that BMPStrings are NULL terminated.
+
+ ret := make([]byte, 0, 2*len(s)+2)
+
+ for _, r := range s {
+ if t, _ := utf16.EncodeRune(r); t != 0xfffd {
+ return nil, errors.New("pkcs12: string contains characters that cannot be encoded in UCS-2")
+ }
+ ret = append(ret, byte(r/256), byte(r%256))
+ }
+
+ return append(ret, 0, 0), nil
+}
+
+func decodeBMPString(bmpString []byte) (string, error) {
+ if len(bmpString)%2 != 0 {
+ return "", errors.New("pkcs12: odd-length BMP string")
+ }
+
+ // strip terminator if present
+ if l := len(bmpString); l >= 2 && bmpString[l-1] == 0 && bmpString[l-2] == 0 {
+ bmpString = bmpString[:l-2]
+ }
+
+ s := make([]uint16, 0, len(bmpString)/2)
+ for len(bmpString) > 0 {
+ s = append(s, uint16(bmpString[0])<<8+uint16(bmpString[1]))
+ bmpString = bmpString[2:]
+ }
+
+ return string(utf16.Decode(s)), nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/bmp-string_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/bmp-string_test.go
new file mode 100644
index 000000000..7fca55f4e
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/bmp-string_test.go
@@ -0,0 +1,63 @@
+// Copyright 2015 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 pkcs12
+
+import (
+ "bytes"
+ "encoding/hex"
+ "testing"
+)
+
+var bmpStringTests = []struct {
+ in string
+ expectedHex string
+ shouldFail bool
+}{
+ {"", "0000", false},
+ // Example from https://tools.ietf.org/html/rfc7292#appendix-B.
+ {"Beavis", "0042006500610076006900730000", false},
+ // Some characters from the "Letterlike Symbols Unicode block".
+ {"\u2115 - Double-struck N", "21150020002d00200044006f00750062006c0065002d00730074007200750063006b0020004e0000", false},
+ // any character outside the BMP should trigger an error.
+ {"\U0001f000 East wind (Mahjong)", "", true},
+}
+
+func TestBMPString(t *testing.T) {
+ for i, test := range bmpStringTests {
+ expected, err := hex.DecodeString(test.expectedHex)
+ if err != nil {
+ t.Fatalf("#%d: failed to decode expectation", i)
+ }
+
+ out, err := bmpString(test.in)
+ if err == nil && test.shouldFail {
+ t.Errorf("#%d: expected to fail, but produced %x", i, out)
+ continue
+ }
+
+ if err != nil && !test.shouldFail {
+ t.Errorf("#%d: failed unexpectedly: %s", i, err)
+ continue
+ }
+
+ if !test.shouldFail {
+ if !bytes.Equal(out, expected) {
+ t.Errorf("#%d: expected %s, got %x", i, test.expectedHex, out)
+ continue
+ }
+
+ roundTrip, err := decodeBMPString(out)
+ if err != nil {
+ t.Errorf("#%d: decoding output gave an error: %s", i, err)
+ continue
+ }
+
+ if roundTrip != test.in {
+ t.Errorf("#%d: decoding output resulted in %q, but it should have been %q", i, roundTrip, test.in)
+ continue
+ }
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/crypto.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/crypto.go
new file mode 100644
index 000000000..484ca51b7
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/crypto.go
@@ -0,0 +1,131 @@
+// Copyright 2015 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 pkcs12
+
+import (
+ "bytes"
+ "crypto/cipher"
+ "crypto/des"
+ "crypto/x509/pkix"
+ "encoding/asn1"
+ "errors"
+
+ "golang.org/x/crypto/pkcs12/internal/rc2"
+)
+
+var (
+ oidPBEWithSHAAnd3KeyTripleDESCBC = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 1, 3})
+ oidPBEWithSHAAnd40BitRC2CBC = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 1, 6})
+)
+
+// pbeCipher is an abstraction of a PKCS#12 cipher.
+type pbeCipher interface {
+ // create returns a cipher.Block given a key.
+ create(key []byte) (cipher.Block, error)
+ // deriveKey returns a key derived from the given password and salt.
+ deriveKey(salt, password []byte, iterations int) []byte
+ // deriveKey returns an IV derived from the given password and salt.
+ deriveIV(salt, password []byte, iterations int) []byte
+}
+
+type shaWithTripleDESCBC struct{}
+
+func (shaWithTripleDESCBC) create(key []byte) (cipher.Block, error) {
+ return des.NewTripleDESCipher(key)
+}
+
+func (shaWithTripleDESCBC) deriveKey(salt, password []byte, iterations int) []byte {
+ return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 1, 24)
+}
+
+func (shaWithTripleDESCBC) deriveIV(salt, password []byte, iterations int) []byte {
+ return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 2, 8)
+}
+
+type shaWith40BitRC2CBC struct{}
+
+func (shaWith40BitRC2CBC) create(key []byte) (cipher.Block, error) {
+ return rc2.New(key, len(key)*8)
+}
+
+func (shaWith40BitRC2CBC) deriveKey(salt, password []byte, iterations int) []byte {
+ return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 1, 5)
+}
+
+func (shaWith40BitRC2CBC) deriveIV(salt, password []byte, iterations int) []byte {
+ return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 2, 8)
+}
+
+type pbeParams struct {
+ Salt []byte
+ Iterations int
+}
+
+func pbDecrypterFor(algorithm pkix.AlgorithmIdentifier, password []byte) (cipher.BlockMode, int, error) {
+ var cipherType pbeCipher
+
+ switch {
+ case algorithm.Algorithm.Equal(oidPBEWithSHAAnd3KeyTripleDESCBC):
+ cipherType = shaWithTripleDESCBC{}
+ case algorithm.Algorithm.Equal(oidPBEWithSHAAnd40BitRC2CBC):
+ cipherType = shaWith40BitRC2CBC{}
+ default:
+ return nil, 0, NotImplementedError("algorithm " + algorithm.Algorithm.String() + " is not supported")
+ }
+
+ var params pbeParams
+ if err := unmarshal(algorithm.Parameters.FullBytes, &params); err != nil {
+ return nil, 0, err
+ }
+
+ key := cipherType.deriveKey(params.Salt, password, params.Iterations)
+ iv := cipherType.deriveIV(params.Salt, password, params.Iterations)
+
+ block, err := cipherType.create(key)
+ if err != nil {
+ return nil, 0, err
+ }
+
+ return cipher.NewCBCDecrypter(block, iv), block.BlockSize(), nil
+}
+
+func pbDecrypt(info decryptable, password []byte) (decrypted []byte, err error) {
+ cbc, blockSize, err := pbDecrypterFor(info.Algorithm(), password)
+ if err != nil {
+ return nil, err
+ }
+
+ encrypted := info.Data()
+ if len(encrypted) == 0 {
+ return nil, errors.New("pkcs12: empty encrypted data")
+ }
+ if len(encrypted)%blockSize != 0 {
+ return nil, errors.New("pkcs12: input is not a multiple of the block size")
+ }
+ decrypted = make([]byte, len(encrypted))
+ cbc.CryptBlocks(decrypted, encrypted)
+
+ psLen := int(decrypted[len(decrypted)-1])
+ if psLen == 0 || psLen > blockSize {
+ return nil, ErrDecryption
+ }
+
+ if len(decrypted) < psLen {
+ return nil, ErrDecryption
+ }
+ ps := decrypted[len(decrypted)-psLen:]
+ decrypted = decrypted[:len(decrypted)-psLen]
+ if bytes.Compare(ps, bytes.Repeat([]byte{byte(psLen)}, psLen)) != 0 {
+ return nil, ErrDecryption
+ }
+
+ return
+}
+
+// decryptable abstracts an object that contains ciphertext.
+type decryptable interface {
+ Algorithm() pkix.AlgorithmIdentifier
+ Data() []byte
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/crypto_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/crypto_test.go
new file mode 100644
index 000000000..eb4dae8fc
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/crypto_test.go
@@ -0,0 +1,125 @@
+// Copyright 2015 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 pkcs12
+
+import (
+ "bytes"
+ "crypto/x509/pkix"
+ "encoding/asn1"
+ "testing"
+)
+
+var sha1WithTripleDES = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 1, 3})
+
+func TestPbDecrypterFor(t *testing.T) {
+ params, _ := asn1.Marshal(pbeParams{
+ Salt: []byte{1, 2, 3, 4, 5, 6, 7, 8},
+ Iterations: 2048,
+ })
+ alg := pkix.AlgorithmIdentifier{
+ Algorithm: asn1.ObjectIdentifier([]int{1, 2, 3}),
+ Parameters: asn1.RawValue{
+ FullBytes: params,
+ },
+ }
+
+ pass, _ := bmpString("Sesame open")
+
+ _, _, err := pbDecrypterFor(alg, pass)
+ if _, ok := err.(NotImplementedError); !ok {
+ t.Errorf("expected not implemented error, got: %T %s", err, err)
+ }
+
+ alg.Algorithm = sha1WithTripleDES
+ cbc, blockSize, err := pbDecrypterFor(alg, pass)
+ if err != nil {
+ t.Errorf("unexpected error from pbDecrypterFor %v", err)
+ }
+ if blockSize != 8 {
+ t.Errorf("unexpected block size %d, wanted 8", blockSize)
+ }
+
+ plaintext := []byte{1, 2, 3, 4, 5, 6, 7, 8}
+ expectedCiphertext := []byte{185, 73, 135, 249, 137, 1, 122, 247}
+ ciphertext := make([]byte, len(plaintext))
+ cbc.CryptBlocks(ciphertext, plaintext)
+
+ if bytes.Compare(ciphertext, expectedCiphertext) != 0 {
+ t.Errorf("bad ciphertext, got %x but wanted %x", ciphertext, expectedCiphertext)
+ }
+}
+
+var pbDecryptTests = []struct {
+ in []byte
+ expected []byte
+ expectedError error
+}{
+ {
+ []byte("\x33\x73\xf3\x9f\xda\x49\xae\xfc\xa0\x9a\xdf\x5a\x58\xa0\xea\x46"), // 7 padding bytes
+ []byte("A secret!"),
+ nil,
+ },
+ {
+ []byte("\x33\x73\xf3\x9f\xda\x49\xae\xfc\x96\x24\x2f\x71\x7e\x32\x3f\xe7"), // 8 padding bytes
+ []byte("A secret"),
+ nil,
+ },
+ {
+ []byte("\x35\x0c\xc0\x8d\xab\xa9\x5d\x30\x7f\x9a\xec\x6a\xd8\x9b\x9c\xd9"), // 9 padding bytes, incorrect
+ nil,
+ ErrDecryption,
+ },
+ {
+ []byte("\xb2\xf9\x6e\x06\x60\xae\x20\xcf\x08\xa0\x7b\xd9\x6b\x20\xef\x41"), // incorrect padding bytes: [ ... 0x04 0x02 ]
+ nil,
+ ErrDecryption,
+ },
+}
+
+func TestPbDecrypt(t *testing.T) {
+ for i, test := range pbDecryptTests {
+ decryptable := testDecryptable{
+ data: test.in,
+ algorithm: pkix.AlgorithmIdentifier{
+ Algorithm: sha1WithTripleDES,
+ Parameters: pbeParams{
+ Salt: []byte("\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8"),
+ Iterations: 4096,
+ }.RawASN1(),
+ },
+ }
+ password, _ := bmpString("sesame")
+
+ plaintext, err := pbDecrypt(decryptable, password)
+ if err != test.expectedError {
+ t.Errorf("#%d: got error %q, but wanted %q", i, err, test.expectedError)
+ continue
+ }
+
+ if !bytes.Equal(plaintext, test.expected) {
+ t.Errorf("#%d: got %x, but wanted %x", i, plaintext, test.expected)
+ }
+ }
+}
+
+type testDecryptable struct {
+ data []byte
+ algorithm pkix.AlgorithmIdentifier
+}
+
+func (d testDecryptable) Algorithm() pkix.AlgorithmIdentifier { return d.algorithm }
+func (d testDecryptable) Data() []byte { return d.data }
+
+func (params pbeParams) RawASN1() (raw asn1.RawValue) {
+ asn1Bytes, err := asn1.Marshal(params)
+ if err != nil {
+ panic(err)
+ }
+ _, err = asn1.Unmarshal(asn1Bytes, &raw)
+ if err != nil {
+ panic(err)
+ }
+ return
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/errors.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/errors.go
new file mode 100644
index 000000000..7377ce6fb
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/errors.go
@@ -0,0 +1,23 @@
+// Copyright 2015 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 pkcs12
+
+import "errors"
+
+var (
+ // ErrDecryption represents a failure to decrypt the input.
+ ErrDecryption = errors.New("pkcs12: decryption error, incorrect padding")
+
+ // ErrIncorrectPassword is returned when an incorrect password is detected.
+ // Usually, P12/PFX data is signed to be able to verify the password.
+ ErrIncorrectPassword = errors.New("pkcs12: decryption password incorrect")
+)
+
+// NotImplementedError indicates that the input is not currently supported.
+type NotImplementedError string
+
+func (e NotImplementedError) Error() string {
+ return "pkcs12: " + string(e)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/internal/rc2/bench_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/internal/rc2/bench_test.go
new file mode 100644
index 000000000..3347f338c
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/internal/rc2/bench_test.go
@@ -0,0 +1,27 @@
+// Copyright 2015 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 rc2
+
+import (
+ "testing"
+)
+
+func BenchmarkEncrypt(b *testing.B) {
+ r, _ := New([]byte{0, 0, 0, 0, 0, 0, 0, 0}, 64)
+ b.ResetTimer()
+ var src [8]byte
+ for i := 0; i < b.N; i++ {
+ r.Encrypt(src[:], src[:])
+ }
+}
+
+func BenchmarkDecrypt(b *testing.B) {
+ r, _ := New([]byte{0, 0, 0, 0, 0, 0, 0, 0}, 64)
+ b.ResetTimer()
+ var src [8]byte
+ for i := 0; i < b.N; i++ {
+ r.Decrypt(src[:], src[:])
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/internal/rc2/rc2.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/internal/rc2/rc2.go
new file mode 100644
index 000000000..8c7090258
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/internal/rc2/rc2.go
@@ -0,0 +1,274 @@
+// Copyright 2015 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 rc2 implements the RC2 cipher
+/*
+https://www.ietf.org/rfc/rfc2268.txt
+http://people.csail.mit.edu/rivest/pubs/KRRR98.pdf
+
+This code is licensed under the MIT license.
+*/
+package rc2
+
+import (
+ "crypto/cipher"
+ "encoding/binary"
+)
+
+// The rc2 block size in bytes
+const BlockSize = 8
+
+type rc2Cipher struct {
+ k [64]uint16
+}
+
+// New returns a new rc2 cipher with the given key and effective key length t1
+func New(key []byte, t1 int) (cipher.Block, error) {
+ // TODO(dgryski): error checking for key length
+ return &rc2Cipher{
+ k: expandKey(key, t1),
+ }, nil
+}
+
+func (*rc2Cipher) BlockSize() int { return BlockSize }
+
+var piTable = [256]byte{
+ 0xd9, 0x78, 0xf9, 0xc4, 0x19, 0xdd, 0xb5, 0xed, 0x28, 0xe9, 0xfd, 0x79, 0x4a, 0xa0, 0xd8, 0x9d,
+ 0xc6, 0x7e, 0x37, 0x83, 0x2b, 0x76, 0x53, 0x8e, 0x62, 0x4c, 0x64, 0x88, 0x44, 0x8b, 0xfb, 0xa2,
+ 0x17, 0x9a, 0x59, 0xf5, 0x87, 0xb3, 0x4f, 0x13, 0x61, 0x45, 0x6d, 0x8d, 0x09, 0x81, 0x7d, 0x32,
+ 0xbd, 0x8f, 0x40, 0xeb, 0x86, 0xb7, 0x7b, 0x0b, 0xf0, 0x95, 0x21, 0x22, 0x5c, 0x6b, 0x4e, 0x82,
+ 0x54, 0xd6, 0x65, 0x93, 0xce, 0x60, 0xb2, 0x1c, 0x73, 0x56, 0xc0, 0x14, 0xa7, 0x8c, 0xf1, 0xdc,
+ 0x12, 0x75, 0xca, 0x1f, 0x3b, 0xbe, 0xe4, 0xd1, 0x42, 0x3d, 0xd4, 0x30, 0xa3, 0x3c, 0xb6, 0x26,
+ 0x6f, 0xbf, 0x0e, 0xda, 0x46, 0x69, 0x07, 0x57, 0x27, 0xf2, 0x1d, 0x9b, 0xbc, 0x94, 0x43, 0x03,
+ 0xf8, 0x11, 0xc7, 0xf6, 0x90, 0xef, 0x3e, 0xe7, 0x06, 0xc3, 0xd5, 0x2f, 0xc8, 0x66, 0x1e, 0xd7,
+ 0x08, 0xe8, 0xea, 0xde, 0x80, 0x52, 0xee, 0xf7, 0x84, 0xaa, 0x72, 0xac, 0x35, 0x4d, 0x6a, 0x2a,
+ 0x96, 0x1a, 0xd2, 0x71, 0x5a, 0x15, 0x49, 0x74, 0x4b, 0x9f, 0xd0, 0x5e, 0x04, 0x18, 0xa4, 0xec,
+ 0xc2, 0xe0, 0x41, 0x6e, 0x0f, 0x51, 0xcb, 0xcc, 0x24, 0x91, 0xaf, 0x50, 0xa1, 0xf4, 0x70, 0x39,
+ 0x99, 0x7c, 0x3a, 0x85, 0x23, 0xb8, 0xb4, 0x7a, 0xfc, 0x02, 0x36, 0x5b, 0x25, 0x55, 0x97, 0x31,
+ 0x2d, 0x5d, 0xfa, 0x98, 0xe3, 0x8a, 0x92, 0xae, 0x05, 0xdf, 0x29, 0x10, 0x67, 0x6c, 0xba, 0xc9,
+ 0xd3, 0x00, 0xe6, 0xcf, 0xe1, 0x9e, 0xa8, 0x2c, 0x63, 0x16, 0x01, 0x3f, 0x58, 0xe2, 0x89, 0xa9,
+ 0x0d, 0x38, 0x34, 0x1b, 0xab, 0x33, 0xff, 0xb0, 0xbb, 0x48, 0x0c, 0x5f, 0xb9, 0xb1, 0xcd, 0x2e,
+ 0xc5, 0xf3, 0xdb, 0x47, 0xe5, 0xa5, 0x9c, 0x77, 0x0a, 0xa6, 0x20, 0x68, 0xfe, 0x7f, 0xc1, 0xad,
+}
+
+func expandKey(key []byte, t1 int) [64]uint16 {
+
+ l := make([]byte, 128)
+ copy(l, key)
+
+ var t = len(key)
+ var t8 = (t1 + 7) / 8
+ var tm = byte(255 % uint(1<<(8+uint(t1)-8*uint(t8))))
+
+ for i := len(key); i < 128; i++ {
+ l[i] = piTable[l[i-1]+l[uint8(i-t)]]
+ }
+
+ l[128-t8] = piTable[l[128-t8]&tm]
+
+ for i := 127 - t8; i >= 0; i-- {
+ l[i] = piTable[l[i+1]^l[i+t8]]
+ }
+
+ var k [64]uint16
+
+ for i := range k {
+ k[i] = uint16(l[2*i]) + uint16(l[2*i+1])*256
+ }
+
+ return k
+}
+
+func rotl16(x uint16, b uint) uint16 {
+ return (x >> (16 - b)) | (x << b)
+}
+
+func (c *rc2Cipher) Encrypt(dst, src []byte) {
+
+ r0 := binary.LittleEndian.Uint16(src[0:])
+ r1 := binary.LittleEndian.Uint16(src[2:])
+ r2 := binary.LittleEndian.Uint16(src[4:])
+ r3 := binary.LittleEndian.Uint16(src[6:])
+
+ var j int
+
+ for j <= 16 {
+ // mix r0
+ r0 = r0 + c.k[j] + (r3 & r2) + ((^r3) & r1)
+ r0 = rotl16(r0, 1)
+ j++
+
+ // mix r1
+ r1 = r1 + c.k[j] + (r0 & r3) + ((^r0) & r2)
+ r1 = rotl16(r1, 2)
+ j++
+
+ // mix r2
+ r2 = r2 + c.k[j] + (r1 & r0) + ((^r1) & r3)
+ r2 = rotl16(r2, 3)
+ j++
+
+ // mix r3
+ r3 = r3 + c.k[j] + (r2 & r1) + ((^r2) & r0)
+ r3 = rotl16(r3, 5)
+ j++
+
+ }
+
+ r0 = r0 + c.k[r3&63]
+ r1 = r1 + c.k[r0&63]
+ r2 = r2 + c.k[r1&63]
+ r3 = r3 + c.k[r2&63]
+
+ for j <= 40 {
+
+ // mix r0
+ r0 = r0 + c.k[j] + (r3 & r2) + ((^r3) & r1)
+ r0 = rotl16(r0, 1)
+ j++
+
+ // mix r1
+ r1 = r1 + c.k[j] + (r0 & r3) + ((^r0) & r2)
+ r1 = rotl16(r1, 2)
+ j++
+
+ // mix r2
+ r2 = r2 + c.k[j] + (r1 & r0) + ((^r1) & r3)
+ r2 = rotl16(r2, 3)
+ j++
+
+ // mix r3
+ r3 = r3 + c.k[j] + (r2 & r1) + ((^r2) & r0)
+ r3 = rotl16(r3, 5)
+ j++
+
+ }
+
+ r0 = r0 + c.k[r3&63]
+ r1 = r1 + c.k[r0&63]
+ r2 = r2 + c.k[r1&63]
+ r3 = r3 + c.k[r2&63]
+
+ for j <= 60 {
+
+ // mix r0
+ r0 = r0 + c.k[j] + (r3 & r2) + ((^r3) & r1)
+ r0 = rotl16(r0, 1)
+ j++
+
+ // mix r1
+ r1 = r1 + c.k[j] + (r0 & r3) + ((^r0) & r2)
+ r1 = rotl16(r1, 2)
+ j++
+
+ // mix r2
+ r2 = r2 + c.k[j] + (r1 & r0) + ((^r1) & r3)
+ r2 = rotl16(r2, 3)
+ j++
+
+ // mix r3
+ r3 = r3 + c.k[j] + (r2 & r1) + ((^r2) & r0)
+ r3 = rotl16(r3, 5)
+ j++
+ }
+
+ binary.LittleEndian.PutUint16(dst[0:], r0)
+ binary.LittleEndian.PutUint16(dst[2:], r1)
+ binary.LittleEndian.PutUint16(dst[4:], r2)
+ binary.LittleEndian.PutUint16(dst[6:], r3)
+}
+
+func (c *rc2Cipher) Decrypt(dst, src []byte) {
+
+ r0 := binary.LittleEndian.Uint16(src[0:])
+ r1 := binary.LittleEndian.Uint16(src[2:])
+ r2 := binary.LittleEndian.Uint16(src[4:])
+ r3 := binary.LittleEndian.Uint16(src[6:])
+
+ j := 63
+
+ for j >= 44 {
+ // unmix r3
+ r3 = rotl16(r3, 16-5)
+ r3 = r3 - c.k[j] - (r2 & r1) - ((^r2) & r0)
+ j--
+
+ // unmix r2
+ r2 = rotl16(r2, 16-3)
+ r2 = r2 - c.k[j] - (r1 & r0) - ((^r1) & r3)
+ j--
+
+ // unmix r1
+ r1 = rotl16(r1, 16-2)
+ r1 = r1 - c.k[j] - (r0 & r3) - ((^r0) & r2)
+ j--
+
+ // unmix r0
+ r0 = rotl16(r0, 16-1)
+ r0 = r0 - c.k[j] - (r3 & r2) - ((^r3) & r1)
+ j--
+ }
+
+ r3 = r3 - c.k[r2&63]
+ r2 = r2 - c.k[r1&63]
+ r1 = r1 - c.k[r0&63]
+ r0 = r0 - c.k[r3&63]
+
+ for j >= 20 {
+ // unmix r3
+ r3 = rotl16(r3, 16-5)
+ r3 = r3 - c.k[j] - (r2 & r1) - ((^r2) & r0)
+ j--
+
+ // unmix r2
+ r2 = rotl16(r2, 16-3)
+ r2 = r2 - c.k[j] - (r1 & r0) - ((^r1) & r3)
+ j--
+
+ // unmix r1
+ r1 = rotl16(r1, 16-2)
+ r1 = r1 - c.k[j] - (r0 & r3) - ((^r0) & r2)
+ j--
+
+ // unmix r0
+ r0 = rotl16(r0, 16-1)
+ r0 = r0 - c.k[j] - (r3 & r2) - ((^r3) & r1)
+ j--
+
+ }
+
+ r3 = r3 - c.k[r2&63]
+ r2 = r2 - c.k[r1&63]
+ r1 = r1 - c.k[r0&63]
+ r0 = r0 - c.k[r3&63]
+
+ for j >= 0 {
+
+ // unmix r3
+ r3 = rotl16(r3, 16-5)
+ r3 = r3 - c.k[j] - (r2 & r1) - ((^r2) & r0)
+ j--
+
+ // unmix r2
+ r2 = rotl16(r2, 16-3)
+ r2 = r2 - c.k[j] - (r1 & r0) - ((^r1) & r3)
+ j--
+
+ // unmix r1
+ r1 = rotl16(r1, 16-2)
+ r1 = r1 - c.k[j] - (r0 & r3) - ((^r0) & r2)
+ j--
+
+ // unmix r0
+ r0 = rotl16(r0, 16-1)
+ r0 = r0 - c.k[j] - (r3 & r2) - ((^r3) & r1)
+ j--
+
+ }
+
+ binary.LittleEndian.PutUint16(dst[0:], r0)
+ binary.LittleEndian.PutUint16(dst[2:], r1)
+ binary.LittleEndian.PutUint16(dst[4:], r2)
+ binary.LittleEndian.PutUint16(dst[6:], r3)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/internal/rc2/rc2_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/internal/rc2/rc2_test.go
new file mode 100644
index 000000000..8a49dfaf3
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/internal/rc2/rc2_test.go
@@ -0,0 +1,93 @@
+// Copyright 2015 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 rc2
+
+import (
+ "bytes"
+ "encoding/hex"
+ "testing"
+)
+
+func TestEncryptDecrypt(t *testing.T) {
+
+ // TODO(dgryski): add the rest of the test vectors from the RFC
+ var tests = []struct {
+ key string
+ plain string
+ cipher string
+ t1 int
+ }{
+ {
+ "0000000000000000",
+ "0000000000000000",
+ "ebb773f993278eff",
+ 63,
+ },
+ {
+ "ffffffffffffffff",
+ "ffffffffffffffff",
+ "278b27e42e2f0d49",
+ 64,
+ },
+ {
+ "3000000000000000",
+ "1000000000000001",
+ "30649edf9be7d2c2",
+ 64,
+ },
+ {
+ "88",
+ "0000000000000000",
+ "61a8a244adacccf0",
+ 64,
+ },
+ {
+ "88bca90e90875a",
+ "0000000000000000",
+ "6ccf4308974c267f",
+ 64,
+ },
+ {
+ "88bca90e90875a7f0f79c384627bafb2",
+ "0000000000000000",
+ "1a807d272bbe5db1",
+ 64,
+ },
+ {
+ "88bca90e90875a7f0f79c384627bafb2",
+ "0000000000000000",
+ "2269552ab0f85ca6",
+ 128,
+ },
+ {
+ "88bca90e90875a7f0f79c384627bafb216f80a6f85920584c42fceb0be255daf1e",
+ "0000000000000000",
+ "5b78d3a43dfff1f1",
+ 129,
+ },
+ }
+
+ for _, tt := range tests {
+ k, _ := hex.DecodeString(tt.key)
+ p, _ := hex.DecodeString(tt.plain)
+ c, _ := hex.DecodeString(tt.cipher)
+
+ b, _ := New(k, tt.t1)
+
+ var dst [8]byte
+
+ b.Encrypt(dst[:], p)
+
+ if !bytes.Equal(dst[:], c) {
+ t.Errorf("encrypt failed: got % 2x wanted % 2x\n", dst, c)
+ }
+
+ b.Decrypt(dst[:], c)
+
+ if !bytes.Equal(dst[:], p) {
+ t.Errorf("decrypt failed: got % 2x wanted % 2x\n", dst, p)
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/mac.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/mac.go
new file mode 100644
index 000000000..5f38aa7de
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/mac.go
@@ -0,0 +1,45 @@
+// Copyright 2015 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 pkcs12
+
+import (
+ "crypto/hmac"
+ "crypto/sha1"
+ "crypto/x509/pkix"
+ "encoding/asn1"
+)
+
+type macData struct {
+ Mac digestInfo
+ MacSalt []byte
+ Iterations int `asn1:"optional,default:1"`
+}
+
+// from PKCS#7:
+type digestInfo struct {
+ Algorithm pkix.AlgorithmIdentifier
+ Digest []byte
+}
+
+var (
+ oidSHA1 = asn1.ObjectIdentifier([]int{1, 3, 14, 3, 2, 26})
+)
+
+func verifyMac(macData *macData, message, password []byte) error {
+ if !macData.Mac.Algorithm.Algorithm.Equal(oidSHA1) {
+ return NotImplementedError("unknown digest algorithm: " + macData.Mac.Algorithm.Algorithm.String())
+ }
+
+ key := pbkdf(sha1Sum, 20, 64, macData.MacSalt, password, macData.Iterations, 3, 20)
+
+ mac := hmac.New(sha1.New, key)
+ mac.Write(message)
+ expectedMAC := mac.Sum(nil)
+
+ if !hmac.Equal(macData.Mac.Digest, expectedMAC) {
+ return ErrIncorrectPassword
+ }
+ return nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/mac_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/mac_test.go
new file mode 100644
index 000000000..1ed4ff21e
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/mac_test.go
@@ -0,0 +1,42 @@
+// Copyright 2015 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 pkcs12
+
+import (
+ "encoding/asn1"
+ "testing"
+)
+
+func TestVerifyMac(t *testing.T) {
+ td := macData{
+ Mac: digestInfo{
+ Digest: []byte{0x18, 0x20, 0x3d, 0xff, 0x1e, 0x16, 0xf4, 0x92, 0xf2, 0xaf, 0xc8, 0x91, 0xa9, 0xba, 0xd6, 0xca, 0x9d, 0xee, 0x51, 0x93},
+ },
+ MacSalt: []byte{1, 2, 3, 4, 5, 6, 7, 8},
+ Iterations: 2048,
+ }
+
+ message := []byte{11, 12, 13, 14, 15}
+ password, _ := bmpString("")
+
+ td.Mac.Algorithm.Algorithm = asn1.ObjectIdentifier([]int{1, 2, 3})
+ err := verifyMac(&td, message, password)
+ if _, ok := err.(NotImplementedError); !ok {
+ t.Errorf("err: %v", err)
+ }
+
+ td.Mac.Algorithm.Algorithm = asn1.ObjectIdentifier([]int{1, 3, 14, 3, 2, 26})
+ err = verifyMac(&td, message, password)
+ if err != ErrIncorrectPassword {
+ t.Errorf("Expected incorrect password, got err: %v", err)
+ }
+
+ password, _ = bmpString("Sesame open")
+ err = verifyMac(&td, message, password)
+ if err != nil {
+ t.Errorf("err: %v", err)
+ }
+
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/pbkdf.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/pbkdf.go
new file mode 100644
index 000000000..5c419d41e
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/pbkdf.go
@@ -0,0 +1,170 @@
+// Copyright 2015 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 pkcs12
+
+import (
+ "bytes"
+ "crypto/sha1"
+ "math/big"
+)
+
+var (
+ one = big.NewInt(1)
+)
+
+// sha1Sum returns the SHA-1 hash of in.
+func sha1Sum(in []byte) []byte {
+ sum := sha1.Sum(in)
+ return sum[:]
+}
+
+// fillWithRepeats returns v*ceiling(len(pattern) / v) bytes consisting of
+// repeats of pattern.
+func fillWithRepeats(pattern []byte, v int) []byte {
+ if len(pattern) == 0 {
+ return nil
+ }
+ outputLen := v * ((len(pattern) + v - 1) / v)
+ return bytes.Repeat(pattern, (outputLen+len(pattern)-1)/len(pattern))[:outputLen]
+}
+
+func pbkdf(hash func([]byte) []byte, u, v int, salt, password []byte, r int, ID byte, size int) (key []byte) {
+ // implementation of https://tools.ietf.org/html/rfc7292#appendix-B.2 , RFC text verbatim in comments
+
+ // Let H be a hash function built around a compression function f:
+
+ // Z_2^u x Z_2^v -> Z_2^u
+
+ // (that is, H has a chaining variable and output of length u bits, and
+ // the message input to the compression function of H is v bits). The
+ // values for u and v are as follows:
+
+ // HASH FUNCTION VALUE u VALUE v
+ // MD2, MD5 128 512
+ // SHA-1 160 512
+ // SHA-224 224 512
+ // SHA-256 256 512
+ // SHA-384 384 1024
+ // SHA-512 512 1024
+ // SHA-512/224 224 1024
+ // SHA-512/256 256 1024
+
+ // Furthermore, let r be the iteration count.
+
+ // We assume here that u and v are both multiples of 8, as are the
+ // lengths of the password and salt strings (which we denote by p and s,
+ // respectively) and the number n of pseudorandom bits required. In
+ // addition, u and v are of course non-zero.
+
+ // For information on security considerations for MD5 [19], see [25] and
+ // [1], and on those for MD2, see [18].
+
+ // The following procedure can be used to produce pseudorandom bits for
+ // a particular "purpose" that is identified by a byte called "ID".
+ // This standard specifies 3 different values for the ID byte:
+
+ // 1. If ID=1, then the pseudorandom bits being produced are to be used
+ // as key material for performing encryption or decryption.
+
+ // 2. If ID=2, then the pseudorandom bits being produced are to be used
+ // as an IV (Initial Value) for encryption or decryption.
+
+ // 3. If ID=3, then the pseudorandom bits being produced are to be used
+ // as an integrity key for MACing.
+
+ // 1. Construct a string, D (the "diversifier"), by concatenating v/8
+ // copies of ID.
+ var D []byte
+ for i := 0; i < v; i++ {
+ D = append(D, ID)
+ }
+
+ // 2. Concatenate copies of the salt together to create a string S of
+ // length v(ceiling(s/v)) bits (the final copy of the salt may be
+ // truncated to create S). Note that if the salt is the empty
+ // string, then so is S.
+
+ S := fillWithRepeats(salt, v)
+
+ // 3. Concatenate copies of the password together to create a string P
+ // of length v(ceiling(p/v)) bits (the final copy of the password
+ // may be truncated to create P). Note that if the password is the
+ // empty string, then so is P.
+
+ P := fillWithRepeats(password, v)
+
+ // 4. Set I=S||P to be the concatenation of S and P.
+ I := append(S, P...)
+
+ // 5. Set c=ceiling(n/u).
+ c := (size + u - 1) / u
+
+ // 6. For i=1, 2, ..., c, do the following:
+ A := make([]byte, c*20)
+ var IjBuf []byte
+ for i := 0; i < c; i++ {
+ // A. Set A2=H^r(D||I). (i.e., the r-th hash of D||1,
+ // H(H(H(... H(D||I))))
+ Ai := hash(append(D, I...))
+ for j := 1; j < r; j++ {
+ Ai = hash(Ai)
+ }
+ copy(A[i*20:], Ai[:])
+
+ if i < c-1 { // skip on last iteration
+ // B. Concatenate copies of Ai to create a string B of length v
+ // bits (the final copy of Ai may be truncated to create B).
+ var B []byte
+ for len(B) < v {
+ B = append(B, Ai[:]...)
+ }
+ B = B[:v]
+
+ // C. Treating I as a concatenation I_0, I_1, ..., I_(k-1) of v-bit
+ // blocks, where k=ceiling(s/v)+ceiling(p/v), modify I by
+ // setting I_j=(I_j+B+1) mod 2^v for each j.
+ {
+ Bbi := new(big.Int).SetBytes(B)
+ Ij := new(big.Int)
+
+ for j := 0; j < len(I)/v; j++ {
+ Ij.SetBytes(I[j*v : (j+1)*v])
+ Ij.Add(Ij, Bbi)
+ Ij.Add(Ij, one)
+ Ijb := Ij.Bytes()
+ // We expect Ijb to be exactly v bytes,
+ // if it is longer or shorter we must
+ // adjust it accordingly.
+ if len(Ijb) > v {
+ Ijb = Ijb[len(Ijb)-v:]
+ }
+ if len(Ijb) < v {
+ if IjBuf == nil {
+ IjBuf = make([]byte, v)
+ }
+ bytesShort := v - len(Ijb)
+ for i := 0; i < bytesShort; i++ {
+ IjBuf[i] = 0
+ }
+ copy(IjBuf[bytesShort:], Ijb)
+ Ijb = IjBuf
+ }
+ copy(I[j*v:(j+1)*v], Ijb)
+ }
+ }
+ }
+ }
+ // 7. Concatenate A_1, A_2, ..., A_c together to form a pseudorandom
+ // bit string, A.
+
+ // 8. Use the first n bits of A as the output of this entire process.
+ return A[:size]
+
+ // If the above process is being used to generate a DES key, the process
+ // should be used to create 64 random bits, and the key's parity bits
+ // should be set after the 64 bits have been produced. Similar concerns
+ // hold for 2-key and 3-key triple-DES keys, for CDMF keys, and for any
+ // similar keys with parity bits "built into them".
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/pbkdf_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/pbkdf_test.go
new file mode 100644
index 000000000..262037d7e
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/pbkdf_test.go
@@ -0,0 +1,34 @@
+// Copyright 2015 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 pkcs12
+
+import (
+ "bytes"
+ "testing"
+)
+
+func TestThatPBKDFWorksCorrectlyForLongKeys(t *testing.T) {
+ cipherInfo := shaWithTripleDESCBC{}
+
+ salt := []byte("\xff\xff\xff\xff\xff\xff\xff\xff")
+ password, _ := bmpString("sesame")
+ key := cipherInfo.deriveKey(salt, password, 2048)
+
+ if expected := []byte("\x7c\xd9\xfd\x3e\x2b\x3b\xe7\x69\x1a\x44\xe3\xbe\xf0\xf9\xea\x0f\xb9\xb8\x97\xd4\xe3\x25\xd9\xd1"); bytes.Compare(key, expected) != 0 {
+ t.Fatalf("expected key '%x', but found '%x'", expected, key)
+ }
+}
+
+func TestThatPBKDFHandlesLeadingZeros(t *testing.T) {
+ // This test triggers a case where I_j (in step 6C) ends up with leading zero
+ // byte, meaning that len(Ijb) < v (leading zeros get stripped by big.Int).
+ // This was previously causing bug whereby certain inputs would break the
+ // derivation and produce the wrong output.
+ key := pbkdf(sha1Sum, 20, 64, []byte("\xf3\x7e\x05\xb5\x18\x32\x4b\x4b"), []byte("\x00\x00"), 2048, 1, 24)
+ expected := []byte("\x00\xf7\x59\xff\x47\xd1\x4d\xd0\x36\x65\xd5\x94\x3c\xb3\xc4\xa3\x9a\x25\x55\xc0\x2a\xed\x66\xe1")
+ if bytes.Compare(key, expected) != 0 {
+ t.Fatalf("expected key '%x', but found '%x'", expected, key)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/pkcs12.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/pkcs12.go
new file mode 100644
index 000000000..eff9ad3a9
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/pkcs12.go
@@ -0,0 +1,346 @@
+// Copyright 2015 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 pkcs12 implements some of PKCS#12.
+//
+// This implementation is distilled from https://tools.ietf.org/html/rfc7292
+// and referenced documents. It is intended for decoding P12/PFX-stored
+// certificates and keys for use with the crypto/tls package.
+package pkcs12
+
+import (
+ "crypto/ecdsa"
+ "crypto/rsa"
+ "crypto/x509"
+ "crypto/x509/pkix"
+ "encoding/asn1"
+ "encoding/hex"
+ "encoding/pem"
+ "errors"
+)
+
+var (
+ oidDataContentType = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 7, 1})
+ oidEncryptedDataContentType = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 7, 6})
+
+ oidFriendlyName = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 9, 20})
+ oidLocalKeyID = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 9, 21})
+ oidMicrosoftCSPName = asn1.ObjectIdentifier([]int{1, 3, 6, 1, 4, 1, 311, 17, 1})
+)
+
+type pfxPdu struct {
+ Version int
+ AuthSafe contentInfo
+ MacData macData `asn1:"optional"`
+}
+
+type contentInfo struct {
+ ContentType asn1.ObjectIdentifier
+ Content asn1.RawValue `asn1:"tag:0,explicit,optional"`
+}
+
+type encryptedData struct {
+ Version int
+ EncryptedContentInfo encryptedContentInfo
+}
+
+type encryptedContentInfo struct {
+ ContentType asn1.ObjectIdentifier
+ ContentEncryptionAlgorithm pkix.AlgorithmIdentifier
+ EncryptedContent []byte `asn1:"tag:0,optional"`
+}
+
+func (i encryptedContentInfo) Algorithm() pkix.AlgorithmIdentifier {
+ return i.ContentEncryptionAlgorithm
+}
+
+func (i encryptedContentInfo) Data() []byte { return i.EncryptedContent }
+
+type safeBag struct {
+ Id asn1.ObjectIdentifier
+ Value asn1.RawValue `asn1:"tag:0,explicit"`
+ Attributes []pkcs12Attribute `asn1:"set,optional"`
+}
+
+type pkcs12Attribute struct {
+ Id asn1.ObjectIdentifier
+ Value asn1.RawValue `asn1:"set"`
+}
+
+type encryptedPrivateKeyInfo struct {
+ AlgorithmIdentifier pkix.AlgorithmIdentifier
+ EncryptedData []byte
+}
+
+func (i encryptedPrivateKeyInfo) Algorithm() pkix.AlgorithmIdentifier {
+ return i.AlgorithmIdentifier
+}
+
+func (i encryptedPrivateKeyInfo) Data() []byte {
+ return i.EncryptedData
+}
+
+// PEM block types
+const (
+ certificateType = "CERTIFICATE"
+ privateKeyType = "PRIVATE KEY"
+)
+
+// unmarshal calls asn1.Unmarshal, but also returns an error if there is any
+// trailing data after unmarshaling.
+func unmarshal(in []byte, out interface{}) error {
+ trailing, err := asn1.Unmarshal(in, out)
+ if err != nil {
+ return err
+ }
+ if len(trailing) != 0 {
+ return errors.New("pkcs12: trailing data found")
+ }
+ return nil
+}
+
+// ConvertToPEM converts all "safe bags" contained in pfxData to PEM blocks.
+func ToPEM(pfxData []byte, password string) ([]*pem.Block, error) {
+ encodedPassword, err := bmpString(password)
+ if err != nil {
+ return nil, ErrIncorrectPassword
+ }
+
+ bags, encodedPassword, err := getSafeContents(pfxData, encodedPassword)
+
+ if err != nil {
+ return nil, err
+ }
+
+ blocks := make([]*pem.Block, 0, len(bags))
+ for _, bag := range bags {
+ block, err := convertBag(&bag, encodedPassword)
+ if err != nil {
+ return nil, err
+ }
+ blocks = append(blocks, block)
+ }
+
+ return blocks, nil
+}
+
+func convertBag(bag *safeBag, password []byte) (*pem.Block, error) {
+ block := &pem.Block{
+ Headers: make(map[string]string),
+ }
+
+ for _, attribute := range bag.Attributes {
+ k, v, err := convertAttribute(&attribute)
+ if err != nil {
+ return nil, err
+ }
+ block.Headers[k] = v
+ }
+
+ switch {
+ case bag.Id.Equal(oidCertBag):
+ block.Type = certificateType
+ certsData, err := decodeCertBag(bag.Value.Bytes)
+ if err != nil {
+ return nil, err
+ }
+ block.Bytes = certsData
+ case bag.Id.Equal(oidPKCS8ShroundedKeyBag):
+ block.Type = privateKeyType
+
+ key, err := decodePkcs8ShroudedKeyBag(bag.Value.Bytes, password)
+ if err != nil {
+ return nil, err
+ }
+
+ switch key := key.(type) {
+ case *rsa.PrivateKey:
+ block.Bytes = x509.MarshalPKCS1PrivateKey(key)
+ case *ecdsa.PrivateKey:
+ block.Bytes, err = x509.MarshalECPrivateKey(key)
+ if err != nil {
+ return nil, err
+ }
+ default:
+ return nil, errors.New("found unknown private key type in PKCS#8 wrapping")
+ }
+ default:
+ return nil, errors.New("don't know how to convert a safe bag of type " + bag.Id.String())
+ }
+ return block, nil
+}
+
+func convertAttribute(attribute *pkcs12Attribute) (key, value string, err error) {
+ isString := false
+
+ switch {
+ case attribute.Id.Equal(oidFriendlyName):
+ key = "friendlyName"
+ isString = true
+ case attribute.Id.Equal(oidLocalKeyID):
+ key = "localKeyId"
+ case attribute.Id.Equal(oidMicrosoftCSPName):
+ // This key is chosen to match OpenSSL.
+ key = "Microsoft CSP Name"
+ isString = true
+ default:
+ return "", "", errors.New("pkcs12: unknown attribute with OID " + attribute.Id.String())
+ }
+
+ if isString {
+ if err := unmarshal(attribute.Value.Bytes, &attribute.Value); err != nil {
+ return "", "", err
+ }
+ if value, err = decodeBMPString(attribute.Value.Bytes); err != nil {
+ return "", "", err
+ }
+ } else {
+ var id []byte
+ if err := unmarshal(attribute.Value.Bytes, &id); err != nil {
+ return "", "", err
+ }
+ value = hex.EncodeToString(id)
+ }
+
+ return key, value, nil
+}
+
+// Decode extracts a certificate and private key from pfxData. This function
+// assumes that there is only one certificate and only one private key in the
+// pfxData.
+func Decode(pfxData []byte, password string) (privateKey interface{}, certificate *x509.Certificate, err error) {
+ encodedPassword, err := bmpString(password)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ bags, encodedPassword, err := getSafeContents(pfxData, encodedPassword)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ if len(bags) != 2 {
+ err = errors.New("pkcs12: expected exactly two safe bags in the PFX PDU")
+ return
+ }
+
+ for _, bag := range bags {
+ switch {
+ case bag.Id.Equal(oidCertBag):
+ if certificate != nil {
+ err = errors.New("pkcs12: expected exactly one certificate bag")
+ }
+
+ certsData, err := decodeCertBag(bag.Value.Bytes)
+ if err != nil {
+ return nil, nil, err
+ }
+ certs, err := x509.ParseCertificates(certsData)
+ if err != nil {
+ return nil, nil, err
+ }
+ if len(certs) != 1 {
+ err = errors.New("pkcs12: expected exactly one certificate in the certBag")
+ return nil, nil, err
+ }
+ certificate = certs[0]
+
+ case bag.Id.Equal(oidPKCS8ShroundedKeyBag):
+ if privateKey != nil {
+ err = errors.New("pkcs12: expected exactly one key bag")
+ }
+
+ if privateKey, err = decodePkcs8ShroudedKeyBag(bag.Value.Bytes, encodedPassword); err != nil {
+ return nil, nil, err
+ }
+ }
+ }
+
+ if certificate == nil {
+ return nil, nil, errors.New("pkcs12: certificate missing")
+ }
+ if privateKey == nil {
+ return nil, nil, errors.New("pkcs12: private key missing")
+ }
+
+ return
+}
+
+func getSafeContents(p12Data, password []byte) (bags []safeBag, updatedPassword []byte, err error) {
+ pfx := new(pfxPdu)
+ if err := unmarshal(p12Data, pfx); err != nil {
+ return nil, nil, errors.New("pkcs12: error reading P12 data: " + err.Error())
+ }
+
+ if pfx.Version != 3 {
+ return nil, nil, NotImplementedError("can only decode v3 PFX PDU's")
+ }
+
+ if !pfx.AuthSafe.ContentType.Equal(oidDataContentType) {
+ return nil, nil, NotImplementedError("only password-protected PFX is implemented")
+ }
+
+ // unmarshal the explicit bytes in the content for type 'data'
+ if err := unmarshal(pfx.AuthSafe.Content.Bytes, &pfx.AuthSafe.Content); err != nil {
+ return nil, nil, err
+ }
+
+ if len(pfx.MacData.Mac.Algorithm.Algorithm) == 0 {
+ return nil, nil, errors.New("pkcs12: no MAC in data")
+ }
+
+ if err := verifyMac(&pfx.MacData, pfx.AuthSafe.Content.Bytes, password); err != nil {
+ if err == ErrIncorrectPassword && len(password) == 2 && password[0] == 0 && password[1] == 0 {
+ // some implementations use an empty byte array
+ // for the empty string password try one more
+ // time with empty-empty password
+ password = nil
+ err = verifyMac(&pfx.MacData, pfx.AuthSafe.Content.Bytes, password)
+ }
+ if err != nil {
+ return nil, nil, err
+ }
+ }
+
+ var authenticatedSafe []contentInfo
+ if err := unmarshal(pfx.AuthSafe.Content.Bytes, &authenticatedSafe); err != nil {
+ return nil, nil, err
+ }
+
+ if len(authenticatedSafe) != 2 {
+ return nil, nil, NotImplementedError("expected exactly two items in the authenticated safe")
+ }
+
+ for _, ci := range authenticatedSafe {
+ var data []byte
+
+ switch {
+ case ci.ContentType.Equal(oidDataContentType):
+ if err := unmarshal(ci.Content.Bytes, &data); err != nil {
+ return nil, nil, err
+ }
+ case ci.ContentType.Equal(oidEncryptedDataContentType):
+ var encryptedData encryptedData
+ if err := unmarshal(ci.Content.Bytes, &encryptedData); err != nil {
+ return nil, nil, err
+ }
+ if encryptedData.Version != 0 {
+ return nil, nil, NotImplementedError("only version 0 of EncryptedData is supported")
+ }
+ if data, err = pbDecrypt(encryptedData.EncryptedContentInfo, password); err != nil {
+ return nil, nil, err
+ }
+ default:
+ return nil, nil, NotImplementedError("only data and encryptedData content types are supported in authenticated safe")
+ }
+
+ var safeContents []safeBag
+ if err := unmarshal(data, &safeContents); err != nil {
+ return nil, nil, err
+ }
+ bags = append(bags, safeContents...)
+ }
+
+ return bags, password, nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/pkcs12_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/pkcs12_test.go
new file mode 100644
index 000000000..14dd2a6c5
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/pkcs12_test.go
@@ -0,0 +1,138 @@
+// Copyright 2015 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 pkcs12
+
+import (
+ "crypto/rsa"
+ "crypto/tls"
+ "encoding/base64"
+ "encoding/pem"
+ "testing"
+)
+
+func TestPfx(t *testing.T) {
+ for commonName, base64P12 := range testdata {
+ p12, _ := base64.StdEncoding.DecodeString(base64P12)
+
+ priv, cert, err := Decode(p12, "")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if err := priv.(*rsa.PrivateKey).Validate(); err != nil {
+ t.Errorf("error while validating private key: %v", err)
+ }
+
+ if cert.Subject.CommonName != commonName {
+ t.Errorf("expected common name to be %q, but found %q", commonName, cert.Subject.CommonName)
+ }
+ }
+}
+
+func TestPEM(t *testing.T) {
+ for commonName, base64P12 := range testdata {
+ p12, _ := base64.StdEncoding.DecodeString(base64P12)
+
+ blocks, err := ToPEM(p12, "")
+ if err != nil {
+ t.Fatalf("error while converting to PEM: %s", err)
+ }
+
+ var pemData []byte
+ for _, b := range blocks {
+ pemData = append(pemData, pem.EncodeToMemory(b)...)
+ }
+
+ cert, err := tls.X509KeyPair(pemData, pemData)
+ if err != nil {
+ t.Errorf("err while converting to key pair: %v", err)
+ }
+ config := tls.Config{
+ Certificates: []tls.Certificate{cert},
+ }
+ config.BuildNameToCertificate()
+
+ if _, exists := config.NameToCertificate[commonName]; !exists {
+ t.Errorf("did not find our cert in PEM?: %v", config.NameToCertificate)
+ }
+ }
+}
+
+func ExampleToPEM() {
+ p12, _ := base64.StdEncoding.DecodeString(`MIIJzgIBAzCCCZQGCS ... CA+gwggPk==`)
+
+ blocks, err := ToPEM(p12, "password")
+ if err != nil {
+ panic(err)
+ }
+
+ var pemData []byte
+ for _, b := range blocks {
+ pemData = append(pemData, pem.EncodeToMemory(b)...)
+ }
+
+ // then use PEM data for tls to construct tls certificate:
+ cert, err := tls.X509KeyPair(pemData, pemData)
+ if err != nil {
+ panic(err)
+ }
+
+ config := &tls.Config{
+ Certificates: []tls.Certificate{cert},
+ }
+
+ _ = config
+}
+
+var testdata = map[string]string{
+ // 'null' password test case
+ "Windows Azure Tools": `MIIKDAIBAzCCCcwGCSqGSIb3DQEHAaCCCb0Eggm5MIIJtTCCBe4GCSqGSIb3DQEHAaCCBd8EggXbMIIF1zCCBdMGCyqGSIb3DQEMCgECoIIE7jCCBOowHAYKKoZIhvcNAQwBAzAOBAhStUNnlTGV+gICB9AEggTIJ81JIossF6boFWpPtkiQRPtI6DW6e9QD4/WvHAVrM2bKdpMzSMsCML5NyuddANTKHBVq00Jc9keqGNAqJPKkjhSUebzQFyhe0E1oI9T4zY5UKr/I8JclOeccH4QQnsySzYUG2SnniXnQ+JrG3juetli7EKth9h6jLc6xbubPadY5HMB3wL/eG/kJymiXwU2KQ9Mgd4X6jbcV+NNCE/8jbZHvSTCPeYTJIjxfeX61Sj5kFKUCzERbsnpyevhY3X0eYtEDezZQarvGmXtMMdzf8HJHkWRdk9VLDLgjk8uiJif/+X4FohZ37ig0CpgC2+dP4DGugaZZ51hb8tN9GeCKIsrmWogMXDIVd0OACBp/EjJVmFB6y0kUCXxUE0TZt0XA1tjAGJcjDUpBvTntZjPsnH/4ZySy+s2d9OOhJ6pzRQBRm360TzkFdSwk9DLiLdGfv4pwMMu/vNGBlqjP/1sQtj+jprJiD1sDbCl4AdQZVoMBQHadF2uSD4/o17XG/Ci0r2h6Htc2yvZMAbEY4zMjjIn2a+vqIxD6onexaek1R3zbkS9j19D6EN9EWn8xgz80YRCyW65znZk8xaIhhvlU/mg7sTxeyuqroBZNcq6uDaQTehDpyH7bY2l4zWRpoj10a6JfH2q5shYz8Y6UZC/kOTfuGqbZDNZWro/9pYquvNNW0M847E5t9bsf9VkAAMHRGBbWoVoU9VpI0UnoXSfvpOo+aXa2DSq5sHHUTVY7A9eov3z5IqT+pligx11xcs+YhDWcU8di3BTJisohKvv5Y8WSkm/rloiZd4ig269k0jTRk1olP/vCksPli4wKG2wdsd5o42nX1yL7mFfXocOANZbB+5qMkiwdyoQSk+Vq+C8nAZx2bbKhUq2MbrORGMzOe0Hh0x2a0PeObycN1Bpyv7Mp3ZI9h5hBnONKCnqMhtyQHUj/nNvbJUnDVYNfoOEqDiEqqEwB7YqWzAKz8KW0OIqdlM8uiQ4JqZZlFllnWJUfaiDrdFM3lYSnFQBkzeVlts6GpDOOBjCYd7dcCNS6kq6pZC6p6HN60Twu0JnurZD6RT7rrPkIGE8vAenFt4iGe/yF52fahCSY8Ws4K0UTwN7bAS+4xRHVCWvE8sMRZsRCHizb5laYsVrPZJhE6+hux6OBb6w8kwPYXc+ud5v6UxawUWgt6uPwl8mlAtU9Z7Miw4Nn/wtBkiLL/ke1UI1gqJtcQXgHxx6mzsjh41+nAgTvdbsSEyU6vfOmxGj3Rwc1eOrIhJUqn5YjOWfzzsz/D5DzWKmwXIwdspt1p+u+kol1N3f2wT9fKPnd/RGCb4g/1hc3Aju4DQYgGY782l89CEEdalpQ/35bQczMFk6Fje12HykakWEXd/bGm9Unh82gH84USiRpeOfQvBDYoqEyrY3zkFZzBjhDqa+jEcAj41tcGx47oSfDq3iVYCdL7HSIjtnyEktVXd7mISZLoMt20JACFcMw+mrbjlug+eU7o2GR7T+LwtOp/p4LZqyLa7oQJDwde1BNZtm3TCK2P1mW94QDL0nDUps5KLtr1DaZXEkRbjSJub2ZE9WqDHyU3KA8G84Tq/rN1IoNu/if45jacyPje1Npj9IftUZSP22nV7HMwZtwQ4P4MYHRMBMGCSqGSIb3DQEJFTEGBAQBAAAAMFsGCSqGSIb3DQEJFDFOHkwAewBCADQAQQA0AEYARQBCADAALQBBADEAOABBAC0ANAA0AEIAQgAtAEIANQBGADIALQA0ADkAMQBFAEYAMQA1ADIAQgBBADEANgB9MF0GCSsGAQQBgjcRATFQHk4ATQBpAGMAcgBvAHMAbwBmAHQAIABTAG8AZgB0AHcAYQByAGUAIABLAGUAeQAgAFMAdABvAHIAYQBnAGUAIABQAHIAbwB2AGkAZABlAHIwggO/BgkqhkiG9w0BBwagggOwMIIDrAIBADCCA6UGCSqGSIb3DQEHATAcBgoqhkiG9w0BDAEGMA4ECEBk5ZAYpu0WAgIH0ICCA3hik4mQFGpw9Ha8TQPtk+j2jwWdxfF0+sTk6S8PTsEfIhB7wPltjiCK92Uv2tCBQnodBUmatIfkpnRDEySmgmdglmOCzj204lWAMRs94PoALGn3JVBXbO1vIDCbAPOZ7Z0Hd0/1t2hmk8v3//QJGUg+qr59/4y/MuVfIg4qfkPcC2QSvYWcK3oTf6SFi5rv9B1IOWFgN5D0+C+x/9Lb/myPYX+rbOHrwtJ4W1fWKoz9g7wwmGFA9IJ2DYGuH8ifVFbDFT1Vcgsvs8arSX7oBsJVW0qrP7XkuDRe3EqCmKW7rBEwYrFznhxZcRDEpMwbFoSvgSIZ4XhFY9VKYglT+JpNH5iDceYEBOQL4vBLpxNUk3l5jKaBNxVa14AIBxq18bVHJ+STInhLhad4u10v/Xbx7wIL3f9DX1yLAkPrpBYbNHS2/ew6H/ySDJnoIDxkw2zZ4qJ+qUJZ1S0lbZVG+VT0OP5uF6tyOSpbMlcGkdl3z254n6MlCrTifcwkzscysDsgKXaYQw06rzrPW6RDub+t+hXzGny799fS9jhQMLDmOggaQ7+LA4oEZsfT89HLMWxJYDqjo3gIfjciV2mV54R684qLDS+AO09U49e6yEbwGlq8lpmO/pbXCbpGbB1b3EomcQbxdWxW2WEkkEd/VBn81K4M3obmywwXJkw+tPXDXfBmzzaqqCR+onMQ5ME1nMkY8ybnfoCc1bDIupjVWsEL2Wvq752RgI6KqzVNr1ew1IdqV5AWN2fOfek+0vi3Jd9FHF3hx8JMwjJL9dZsETV5kHtYJtE7wJ23J68BnCt2eI0GEuwXcCf5EdSKN/xXCTlIokc4Qk/gzRdIZsvcEJ6B1lGovKG54X4IohikqTjiepjbsMWj38yxDmK3mtENZ9ci8FPfbbvIEcOCZIinuY3qFUlRSbx7VUerEoV1IP3clUwexVQo4lHFee2jd7ocWsdSqSapW7OWUupBtDzRkqVhE7tGria+i1W2d6YLlJ21QTjyapWJehAMO637OdbJCCzDs1cXbodRRE7bsP492ocJy8OX66rKdhYbg8srSFNKdb3pF3UDNbN9jhI/t8iagRhNBhlQtTr1me2E/c86Q18qcRXl4bcXTt6acgCeffK6Y26LcVlrgjlD33AEYRRUeyC+rpxbT0aMjdFderlndKRIyG23mSp0HaUwNzAfMAcGBSsOAwIaBBRlviCbIyRrhIysg2dc/KbLFTc2vQQUg4rfwHMM4IKYRD/fsd1x6dda+wQ=`,
+ // empty string password test case
+ "testing@example.com": `MIIJzgIBAzCCCZQGCSqGSIb3DQEHAaCCCYUEggmBMIIJfTCCA/cGCSqGSIb3DQEHBqCCA+gwggPk
+AgEAMIID3QYJKoZIhvcNAQcBMBwGCiqGSIb3DQEMAQYwDgQIIszfRGqcmPcCAggAgIIDsOZ9Eg1L
+s5Wx8JhYoV3HAL4aRnkAWvTYB5NISZOgSgIQTssmt/3A7134dibTmaT/93LikkL3cTKLnQzJ4wDf
+YZ1bprpVJvUqz+HFT79m27bP9zYXFrvxWBJbxjYKTSjQMgz+h8LAEpXXGajCmxMJ1oCOtdXkhhzc
+LdZN6SAYgtmtyFnCdMEDskSggGuLb3fw84QEJ/Sj6FAULXunW/CPaS7Ce0TMsKmNU/jfFWj3yXXw
+ro0kwjKiVLpVFlnBlHo2OoVU7hmkm59YpGhLgS7nxLD3n7nBroQ0ID1+8R01NnV9XLGoGzxMm1te
+6UyTCkr5mj+kEQ8EP1Ys7g/TC411uhVWySMt/rcpkx7Vz1r9kYEAzJpONAfr6cuEVkPKrxpq4Fh0
+2fzlKBky0i/hrfIEUmngh+ERHUb/Mtv/fkv1j5w9suESbhsMLLiCXAlsP1UWMX+3bNizi3WVMEts
+FM2k9byn+p8IUD/A8ULlE4kEaWeoc+2idkCNQkLGuIdGUXUFVm58se0auUkVRoRJx8x4CkMesT8j
+b1H831W66YRWoEwwDQp2kK1lA2vQXxdVHWlFevMNxJeromLzj3ayiaFrfByeUXhR2S+Hpm+c0yNR
+4UVU9WED2kacsZcpRm9nlEa5sr28mri5JdBrNa/K02OOhvKCxr5ZGmbOVzUQKla2z4w+Ku9k8POm
+dfDNU/fGx1b5hcFWtghXe3msWVsSJrQihnN6q1ughzNiYZlJUGcHdZDRtiWwCFI0bR8h/Dmg9uO9
+4rawQQrjIRT7B8yF3UbkZyAqs8Ppb1TsMeNPHh1rxEfGVQknh/48ouJYsmtbnzugTUt3mJCXXiL+
+XcPMV6bBVAUu4aaVKSmg9+yJtY4/VKv10iw88ktv29fViIdBe3t6l/oPuvQgbQ8dqf4T8w0l/uKZ
+9lS1Na9jfT1vCoS7F5TRi+tmyj1vL5kr/amEIW6xKEP6oeAMvCMtbPAzVEj38zdJ1R22FfuIBxkh
+f0Zl7pdVbmzRxl/SBx9iIBJSqAvcXItiT0FIj8HxQ+0iZKqMQMiBuNWJf5pYOLWGrIyntCWwHuaQ
+wrx0sTGuEL9YXLEAsBDrsvzLkx/56E4INGZFrH8G7HBdW6iGqb22IMI4GHltYSyBRKbB0gadYTyv
+abPEoqww8o7/85aPSzOTJ/53ozD438Q+d0u9SyDuOb60SzCD/zPuCEd78YgtXJwBYTuUNRT27FaM
+3LGMX8Hz+6yPNRnmnA2XKPn7dx/IlaqAjIs8MIIFfgYJKoZIhvcNAQcBoIIFbwSCBWswggVnMIIF
+YwYLKoZIhvcNAQwKAQKgggTuMIIE6jAcBgoqhkiG9w0BDAEDMA4ECJr0cClYqOlcAgIIAASCBMhe
+OQSiP2s0/46ONXcNeVAkz2ksW3u/+qorhSiskGZ0b3dFa1hhgBU2Q7JVIkc4Hf7OXaT1eVQ8oqND
+uhqsNz83/kqYo70+LS8Hocj49jFgWAKrf/yQkdyP1daHa2yzlEw4mkpqOfnIORQHvYCa8nEApspZ
+wVu8y6WVuLHKU67mel7db2xwstQp7PRuSAYqGjTfAylElog8ASdaqqYbYIrCXucF8iF9oVgmb/Qo
+xrXshJ9aSLO4MuXlTPELmWgj07AXKSb90FKNihE+y0bWb9LPVFY1Sly3AX9PfrtkSXIZwqW3phpv
+MxGxQl/R6mr1z+hlTfY9Wdpb5vlKXPKA0L0Rt8d2pOesylFi6esJoS01QgP1kJILjbrV731kvDc0
+Jsd+Oxv4BMwA7ClG8w1EAOInc/GrV1MWFGw/HeEqj3CZ/l/0jv9bwkbVeVCiIhoL6P6lVx9pXq4t
+KZ0uKg/tk5TVJmG2vLcMLvezD0Yk3G2ZOMrywtmskrwoF7oAUpO9e87szoH6fEvUZlkDkPVW1NV4
+cZk3DBSQiuA3VOOg8qbo/tx/EE3H59P0axZWno2GSB0wFPWd1aj+b//tJEJHaaNR6qPRj4IWj9ru
+Qbc8eRAcVWleHg8uAehSvUXlFpyMQREyrnpvMGddpiTC8N4UMrrBRhV7+UbCOWhxPCbItnInBqgl
+1JpSZIP7iUtsIMdu3fEC2cdbXMTRul+4rdzUR7F9OaezV3jjvcAbDvgbK1CpyC+MJ1Mxm/iTgk9V
+iUArydhlR8OniN84GyGYoYCW9O/KUwb6ASmeFOu/msx8x6kAsSQHIkKqMKv0TUR3kZnkxUvdpBGP
+KTl4YCTvNGX4dYALBqrAETRDhua2KVBD/kEttDHwBNVbN2xi81+Mc7ml461aADfk0c66R/m2sjHB
+2tN9+wG12OIWFQjL6wF/UfJMYamxx2zOOExiId29Opt57uYiNVLOO4ourPewHPeH0u8Gz35aero7
+lkt7cZAe1Q0038JUuE/QGlnK4lESK9UkSIQAjSaAlTsrcfwtQxB2EjoOoLhwH5mvxUEmcNGNnXUc
+9xj3M5BD3zBz3Ft7G3YMMDwB1+zC2l+0UG0MGVjMVaeoy32VVNvxgX7jk22OXG1iaOB+PY9kdk+O
+X+52BGSf/rD6X0EnqY7XuRPkMGgjtpZeAYxRQnFtCZgDY4wYheuxqSSpdF49yNczSPLkgB3CeCfS
++9NTKN7aC6hBbmW/8yYh6OvSiCEwY0lFS/T+7iaVxr1loE4zI1y/FFp4Pe1qfLlLttVlkygga2UU
+SCunTQ8UB/M5IXWKkhMOO11dP4niWwb39Y7pCWpau7mwbXOKfRPX96cgHnQJK5uG+BesDD1oYnX0
+6frN7FOnTSHKruRIwuI8KnOQ/I+owmyz71wiv5LMQt+yM47UrEjB/EZa5X8dpEwOZvkdqL7utcyo
+l0XH5kWMXdW856LL/FYftAqJIDAmtX1TXF/rbP6mPyN/IlDC0gjP84Uzd/a2UyTIWr+wk49Ek3vQ
+/uDamq6QrwAxVmNh5Tset5Vhpc1e1kb7mRMZIzxSP8JcTuYd45oFKi98I8YjvueHVZce1g7OudQP
+SbFQoJvdT46iBg1TTatlltpOiH2mFaxWVS0xYjAjBgkqhkiG9w0BCRUxFgQUdA9eVqvETX4an/c8
+p8SsTugkit8wOwYJKoZIhvcNAQkUMS4eLABGAHIAaQBlAG4AZABsAHkAIABuAGEAbQBlACAAZgBv
+AHIAIABjAGUAcgB0MDEwITAJBgUrDgMCGgUABBRFsNz3Zd1O1GI8GTuFwCWuDOjEEwQIuBEfIcAy
+HQ8CAggA`,
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/safebags.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/safebags.go
new file mode 100644
index 000000000..def1f7b98
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/pkcs12/safebags.go
@@ -0,0 +1,57 @@
+// Copyright 2015 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 pkcs12
+
+import (
+ "crypto/x509"
+ "encoding/asn1"
+ "errors"
+)
+
+var (
+ // see https://tools.ietf.org/html/rfc7292#appendix-D
+ oidCertTypeX509Certificate = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 9, 22, 1})
+ oidPKCS8ShroundedKeyBag = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 10, 1, 2})
+ oidCertBag = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 10, 1, 3})
+)
+
+type certBag struct {
+ Id asn1.ObjectIdentifier
+ Data []byte `asn1:"tag:0,explicit"`
+}
+
+func decodePkcs8ShroudedKeyBag(asn1Data, password []byte) (privateKey interface{}, err error) {
+ pkinfo := new(encryptedPrivateKeyInfo)
+ if err = unmarshal(asn1Data, pkinfo); err != nil {
+ return nil, errors.New("pkcs12: error decoding PKCS#8 shrouded key bag: " + err.Error())
+ }
+
+ pkData, err := pbDecrypt(pkinfo, password)
+ if err != nil {
+ return nil, errors.New("pkcs12: error decrypting PKCS#8 shrouded key bag: " + err.Error())
+ }
+
+ ret := new(asn1.RawValue)
+ if err = unmarshal(pkData, ret); err != nil {
+ return nil, errors.New("pkcs12: error unmarshaling decrypted private key: " + err.Error())
+ }
+
+ if privateKey, err = x509.ParsePKCS8PrivateKey(pkData); err != nil {
+ return nil, errors.New("pkcs12: error parsing PKCS#8 private key: " + err.Error())
+ }
+
+ return privateKey, nil
+}
+
+func decodeCertBag(asn1Data []byte) (x509Certificates []byte, err error) {
+ bag := new(certBag)
+ if err := unmarshal(asn1Data, bag); err != nil {
+ return nil, errors.New("pkcs12: error decoding cert bag: " + err.Error())
+ }
+ if !bag.Id.Equal(oidCertTypeX509Certificate) {
+ return nil, NotImplementedError("only X509 certificates are supported")
+ }
+ return bag.Data, nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/poly1305/poly1305.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/poly1305/poly1305.go
new file mode 100644
index 000000000..f562fa571
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/poly1305/poly1305.go
@@ -0,0 +1,33 @@
+// Copyright 2012 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 poly1305 implements Poly1305 one-time message authentication code as
+specified in https://cr.yp.to/mac/poly1305-20050329.pdf.
+
+Poly1305 is a fast, one-time authentication function. It is infeasible for an
+attacker to generate an authenticator for a message without the key. However, a
+key must only be used for a single message. Authenticating two different
+messages with the same key allows an attacker to forge authenticators for other
+messages with the same key.
+
+Poly1305 was originally coupled with AES in order to make Poly1305-AES. AES was
+used with a fixed key in order to generate one-time keys from an nonce.
+However, in this package AES isn't used and the one-time key is specified
+directly.
+*/
+package poly1305 // import "golang.org/x/crypto/poly1305"
+
+import "crypto/subtle"
+
+// TagSize is the size, in bytes, of a poly1305 authenticator.
+const TagSize = 16
+
+// Verify returns true if mac is a valid authenticator for m with the given
+// key.
+func Verify(mac *[16]byte, m []byte, key *[32]byte) bool {
+ var tmp [16]byte
+ Sum(&tmp, m, key)
+ return subtle.ConstantTimeCompare(tmp[:], mac[:]) == 1
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/poly1305/poly1305_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/poly1305/poly1305_test.go
new file mode 100644
index 000000000..017027fe6
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/poly1305/poly1305_test.go
@@ -0,0 +1,159 @@
+// Copyright 2012 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 poly1305
+
+import (
+ "bytes"
+ "encoding/hex"
+ "flag"
+ "testing"
+ "unsafe"
+)
+
+var stressFlag = flag.Bool("stress", false, "run slow stress tests")
+
+var testData = []struct {
+ in, k, correct []byte
+}{
+ {
+ []byte("Hello world!"),
+ []byte("this is 32-byte key for Poly1305"),
+ []byte{0xa6, 0xf7, 0x45, 0x00, 0x8f, 0x81, 0xc9, 0x16, 0xa2, 0x0d, 0xcc, 0x74, 0xee, 0xf2, 0xb2, 0xf0},
+ },
+ {
+ make([]byte, 32),
+ []byte("this is 32-byte key for Poly1305"),
+ []byte{0x49, 0xec, 0x78, 0x09, 0x0e, 0x48, 0x1e, 0xc6, 0xc2, 0x6b, 0x33, 0xb9, 0x1c, 0xcc, 0x03, 0x07},
+ },
+ {
+ make([]byte, 2007),
+ []byte("this is 32-byte key for Poly1305"),
+ []byte{0xda, 0x84, 0xbc, 0xab, 0x02, 0x67, 0x6c, 0x38, 0xcd, 0xb0, 0x15, 0x60, 0x42, 0x74, 0xc2, 0xaa},
+ },
+ {
+ make([]byte, 2007),
+ make([]byte, 32),
+ make([]byte, 16),
+ },
+ {
+ // This test triggers an edge-case. See https://go-review.googlesource.com/#/c/30101/.
+ []byte{0x81, 0xd8, 0xb2, 0xe4, 0x6a, 0x25, 0x21, 0x3b, 0x58, 0xfe, 0xe4, 0x21, 0x3a, 0x2a, 0x28, 0xe9, 0x21, 0xc1, 0x2a, 0x96, 0x32, 0x51, 0x6d, 0x3b, 0x73, 0x27, 0x27, 0x27, 0xbe, 0xcf, 0x21, 0x29},
+ []byte{0x3b, 0x3a, 0x29, 0xe9, 0x3b, 0x21, 0x3a, 0x5c, 0x5c, 0x3b, 0x3b, 0x05, 0x3a, 0x3a, 0x8c, 0x0d},
+ []byte{0x6d, 0xc1, 0x8b, 0x8c, 0x34, 0x4c, 0xd7, 0x99, 0x27, 0x11, 0x8b, 0xbe, 0x84, 0xb7, 0xf3, 0x14},
+ },
+ {
+ // This test generates a result of (2^130-1) % (2^130-5).
+ []byte{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ },
+ []byte{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ []byte{4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ },
+ {
+ // This test generates a result of (2^130-6) % (2^130-5).
+ []byte{
+ 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ },
+ []byte{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ []byte{0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ },
+ {
+ // This test generates a result of (2^130-5) % (2^130-5).
+ []byte{
+ 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ },
+ []byte{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ },
+}
+
+func testSum(t *testing.T, unaligned bool) {
+ var out [16]byte
+ var key [32]byte
+
+ for i, v := range testData {
+ in := v.in
+ if unaligned {
+ in = unalignBytes(in)
+ }
+ copy(key[:], v.k)
+ Sum(&out, in, &key)
+ if !bytes.Equal(out[:], v.correct) {
+ t.Errorf("%d: expected %x, got %x", i, v.correct, out[:])
+ }
+ }
+}
+
+func TestBurnin(t *testing.T) {
+ // This test can be used to sanity-check significant changes. It can
+ // take about many minutes to run, even on fast machines. It's disabled
+ // by default.
+ if !*stressFlag {
+ t.Skip("skipping without -stress")
+ }
+
+ var key [32]byte
+ var input [25]byte
+ var output [16]byte
+
+ for i := range key {
+ key[i] = 1
+ }
+ for i := range input {
+ input[i] = 2
+ }
+
+ for i := uint64(0); i < 1e10; i++ {
+ Sum(&output, input[:], &key)
+ copy(key[0:], output[:])
+ copy(key[16:], output[:])
+ copy(input[:], output[:])
+ copy(input[16:], output[:])
+ }
+
+ const expected = "5e3b866aea0b636d240c83c428f84bfa"
+ if got := hex.EncodeToString(output[:]); got != expected {
+ t.Errorf("expected %s, got %s", expected, got)
+ }
+}
+
+func TestSum(t *testing.T) { testSum(t, false) }
+func TestSumUnaligned(t *testing.T) { testSum(t, true) }
+
+func benchmark(b *testing.B, size int, unaligned bool) {
+ var out [16]byte
+ var key [32]byte
+ in := make([]byte, size)
+ if unaligned {
+ in = unalignBytes(in)
+ }
+ b.SetBytes(int64(len(in)))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ Sum(&out, in, &key)
+ }
+}
+
+func Benchmark64(b *testing.B) { benchmark(b, 64, false) }
+func Benchmark1K(b *testing.B) { benchmark(b, 1024, false) }
+func Benchmark64Unaligned(b *testing.B) { benchmark(b, 64, true) }
+func Benchmark1KUnaligned(b *testing.B) { benchmark(b, 1024, true) }
+
+func unalignBytes(in []byte) []byte {
+ out := make([]byte, len(in)+1)
+ if uintptr(unsafe.Pointer(&out[0]))&(unsafe.Alignof(uint32(0))-1) == 0 {
+ out = out[1:]
+ } else {
+ out = out[:len(in)]
+ }
+ copy(out, in)
+ return out
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/poly1305/sum_amd64.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/poly1305/sum_amd64.go
new file mode 100644
index 000000000..4dd72fe79
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/poly1305/sum_amd64.go
@@ -0,0 +1,22 @@
+// Copyright 2012 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.
+
+// +build amd64,!gccgo,!appengine
+
+package poly1305
+
+// This function is implemented in sum_amd64.s
+//go:noescape
+func poly1305(out *[16]byte, m *byte, mlen uint64, key *[32]byte)
+
+// Sum generates an authenticator for m using a one-time key and puts the
+// 16-byte result into out. Authenticating two different messages with the same
+// key allows an attacker to forge messages at will.
+func Sum(out *[16]byte, m []byte, key *[32]byte) {
+ var mPtr *byte
+ if len(m) > 0 {
+ mPtr = &m[0]
+ }
+ poly1305(out, mPtr, uint64(len(m)), key)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/poly1305/sum_amd64.s b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/poly1305/sum_amd64.s
new file mode 100644
index 000000000..2edae6382
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/poly1305/sum_amd64.s
@@ -0,0 +1,125 @@
+// Copyright 2012 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.
+
+// +build amd64,!gccgo,!appengine
+
+#include "textflag.h"
+
+#define POLY1305_ADD(msg, h0, h1, h2) \
+ ADDQ 0(msg), h0; \
+ ADCQ 8(msg), h1; \
+ ADCQ $1, h2; \
+ LEAQ 16(msg), msg
+
+#define POLY1305_MUL(h0, h1, h2, r0, r1, t0, t1, t2, t3) \
+ MOVQ r0, AX; \
+ MULQ h0; \
+ MOVQ AX, t0; \
+ MOVQ DX, t1; \
+ MOVQ r0, AX; \
+ MULQ h1; \
+ ADDQ AX, t1; \
+ ADCQ $0, DX; \
+ MOVQ r0, t2; \
+ IMULQ h2, t2; \
+ ADDQ DX, t2; \
+ \
+ MOVQ r1, AX; \
+ MULQ h0; \
+ ADDQ AX, t1; \
+ ADCQ $0, DX; \
+ MOVQ DX, h0; \
+ MOVQ r1, t3; \
+ IMULQ h2, t3; \
+ MOVQ r1, AX; \
+ MULQ h1; \
+ ADDQ AX, t2; \
+ ADCQ DX, t3; \
+ ADDQ h0, t2; \
+ ADCQ $0, t3; \
+ \
+ MOVQ t0, h0; \
+ MOVQ t1, h1; \
+ MOVQ t2, h2; \
+ ANDQ $3, h2; \
+ MOVQ t2, t0; \
+ ANDQ $0xFFFFFFFFFFFFFFFC, t0; \
+ ADDQ t0, h0; \
+ ADCQ t3, h1; \
+ ADCQ $0, h2; \
+ SHRQ $2, t3, t2; \
+ SHRQ $2, t3; \
+ ADDQ t2, h0; \
+ ADCQ t3, h1; \
+ ADCQ $0, h2
+
+DATA ·poly1305Mask<>+0x00(SB)/8, $0x0FFFFFFC0FFFFFFF
+DATA ·poly1305Mask<>+0x08(SB)/8, $0x0FFFFFFC0FFFFFFC
+GLOBL ·poly1305Mask<>(SB), RODATA, $16
+
+// func poly1305(out *[16]byte, m *byte, mlen uint64, key *[32]key)
+TEXT ·poly1305(SB), $0-32
+ MOVQ out+0(FP), DI
+ MOVQ m+8(FP), SI
+ MOVQ mlen+16(FP), R15
+ MOVQ key+24(FP), AX
+
+ MOVQ 0(AX), R11
+ MOVQ 8(AX), R12
+ ANDQ ·poly1305Mask<>(SB), R11 // r0
+ ANDQ ·poly1305Mask<>+8(SB), R12 // r1
+ XORQ R8, R8 // h0
+ XORQ R9, R9 // h1
+ XORQ R10, R10 // h2
+
+ CMPQ R15, $16
+ JB bytes_between_0_and_15
+
+loop:
+ POLY1305_ADD(SI, R8, R9, R10)
+
+multiply:
+ POLY1305_MUL(R8, R9, R10, R11, R12, BX, CX, R13, R14)
+ SUBQ $16, R15
+ CMPQ R15, $16
+ JAE loop
+
+bytes_between_0_and_15:
+ TESTQ R15, R15
+ JZ done
+ MOVQ $1, BX
+ XORQ CX, CX
+ XORQ R13, R13
+ ADDQ R15, SI
+
+flush_buffer:
+ SHLQ $8, BX, CX
+ SHLQ $8, BX
+ MOVB -1(SI), R13
+ XORQ R13, BX
+ DECQ SI
+ DECQ R15
+ JNZ flush_buffer
+
+ ADDQ BX, R8
+ ADCQ CX, R9
+ ADCQ $0, R10
+ MOVQ $16, R15
+ JMP multiply
+
+done:
+ MOVQ R8, AX
+ MOVQ R9, BX
+ SUBQ $0xFFFFFFFFFFFFFFFB, AX
+ SBBQ $0xFFFFFFFFFFFFFFFF, BX
+ SBBQ $3, R10
+ CMOVQCS R8, AX
+ CMOVQCS R9, BX
+ MOVQ key+24(FP), R8
+ ADDQ 16(R8), AX
+ ADCQ 24(R8), BX
+
+ MOVQ AX, 0(DI)
+ MOVQ BX, 8(DI)
+ RET
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/poly1305/sum_arm.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/poly1305/sum_arm.go
new file mode 100644
index 000000000..5dc321c2f
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/poly1305/sum_arm.go
@@ -0,0 +1,22 @@
+// Copyright 2015 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.
+
+// +build arm,!gccgo,!appengine,!nacl
+
+package poly1305
+
+// This function is implemented in sum_arm.s
+//go:noescape
+func poly1305_auth_armv6(out *[16]byte, m *byte, mlen uint32, key *[32]byte)
+
+// Sum generates an authenticator for m using a one-time key and puts the
+// 16-byte result into out. Authenticating two different messages with the same
+// key allows an attacker to forge messages at will.
+func Sum(out *[16]byte, m []byte, key *[32]byte) {
+ var mPtr *byte
+ if len(m) > 0 {
+ mPtr = &m[0]
+ }
+ poly1305_auth_armv6(out, mPtr, uint32(len(m)), key)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/poly1305/sum_arm.s b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/poly1305/sum_arm.s
new file mode 100644
index 000000000..f70b4ac48
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/poly1305/sum_arm.s
@@ -0,0 +1,427 @@
+// Copyright 2015 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.
+
+// +build arm,!gccgo,!appengine,!nacl
+
+#include "textflag.h"
+
+// This code was translated into a form compatible with 5a from the public
+// domain source by Andrew Moon: github.com/floodyberry/poly1305-opt/blob/master/app/extensions/poly1305.
+
+DATA ·poly1305_init_constants_armv6<>+0x00(SB)/4, $0x3ffffff
+DATA ·poly1305_init_constants_armv6<>+0x04(SB)/4, $0x3ffff03
+DATA ·poly1305_init_constants_armv6<>+0x08(SB)/4, $0x3ffc0ff
+DATA ·poly1305_init_constants_armv6<>+0x0c(SB)/4, $0x3f03fff
+DATA ·poly1305_init_constants_armv6<>+0x10(SB)/4, $0x00fffff
+GLOBL ·poly1305_init_constants_armv6<>(SB), 8, $20
+
+// Warning: the linker may use R11 to synthesize certain instructions. Please
+// take care and verify that no synthetic instructions use it.
+
+TEXT poly1305_init_ext_armv6<>(SB), NOSPLIT, $0
+ // Needs 16 bytes of stack and 64 bytes of space pointed to by R0. (It
+ // might look like it's only 60 bytes of space but the final four bytes
+ // will be written by another function.) We need to skip over four
+ // bytes of stack because that's saving the value of 'g'.
+ ADD $4, R13, R8
+ MOVM.IB [R4-R7], (R8)
+ MOVM.IA.W (R1), [R2-R5]
+ MOVW $·poly1305_init_constants_armv6<>(SB), R7
+ MOVW R2, R8
+ MOVW R2>>26, R9
+ MOVW R3>>20, g
+ MOVW R4>>14, R11
+ MOVW R5>>8, R12
+ ORR R3<<6, R9, R9
+ ORR R4<<12, g, g
+ ORR R5<<18, R11, R11
+ MOVM.IA (R7), [R2-R6]
+ AND R8, R2, R2
+ AND R9, R3, R3
+ AND g, R4, R4
+ AND R11, R5, R5
+ AND R12, R6, R6
+ MOVM.IA.W [R2-R6], (R0)
+ EOR R2, R2, R2
+ EOR R3, R3, R3
+ EOR R4, R4, R4
+ EOR R5, R5, R5
+ EOR R6, R6, R6
+ MOVM.IA.W [R2-R6], (R0)
+ MOVM.IA.W (R1), [R2-R5]
+ MOVM.IA [R2-R6], (R0)
+ ADD $20, R13, R0
+ MOVM.DA (R0), [R4-R7]
+ RET
+
+#define MOVW_UNALIGNED(Rsrc, Rdst, Rtmp, offset) \
+ MOVBU (offset+0)(Rsrc), Rtmp; \
+ MOVBU Rtmp, (offset+0)(Rdst); \
+ MOVBU (offset+1)(Rsrc), Rtmp; \
+ MOVBU Rtmp, (offset+1)(Rdst); \
+ MOVBU (offset+2)(Rsrc), Rtmp; \
+ MOVBU Rtmp, (offset+2)(Rdst); \
+ MOVBU (offset+3)(Rsrc), Rtmp; \
+ MOVBU Rtmp, (offset+3)(Rdst)
+
+TEXT poly1305_blocks_armv6<>(SB), NOSPLIT, $0
+ // Needs 24 bytes of stack for saved registers and then 88 bytes of
+ // scratch space after that. We assume that 24 bytes at (R13) have
+ // already been used: four bytes for the link register saved in the
+ // prelude of poly1305_auth_armv6, four bytes for saving the value of g
+ // in that function and 16 bytes of scratch space used around
+ // poly1305_finish_ext_armv6_skip1.
+ ADD $24, R13, R12
+ MOVM.IB [R4-R8, R14], (R12)
+ MOVW R0, 88(R13)
+ MOVW R1, 92(R13)
+ MOVW R2, 96(R13)
+ MOVW R1, R14
+ MOVW R2, R12
+ MOVW 56(R0), R8
+ WORD $0xe1180008 // TST R8, R8 not working see issue 5921
+ EOR R6, R6, R6
+ MOVW.EQ $(1<<24), R6
+ MOVW R6, 84(R13)
+ ADD $116, R13, g
+ MOVM.IA (R0), [R0-R9]
+ MOVM.IA [R0-R4], (g)
+ CMP $16, R12
+ BLO poly1305_blocks_armv6_done
+
+poly1305_blocks_armv6_mainloop:
+ WORD $0xe31e0003 // TST R14, #3 not working see issue 5921
+ BEQ poly1305_blocks_armv6_mainloop_aligned
+ ADD $100, R13, g
+ MOVW_UNALIGNED(R14, g, R0, 0)
+ MOVW_UNALIGNED(R14, g, R0, 4)
+ MOVW_UNALIGNED(R14, g, R0, 8)
+ MOVW_UNALIGNED(R14, g, R0, 12)
+ MOVM.IA (g), [R0-R3]
+ ADD $16, R14
+ B poly1305_blocks_armv6_mainloop_loaded
+
+poly1305_blocks_armv6_mainloop_aligned:
+ MOVM.IA.W (R14), [R0-R3]
+
+poly1305_blocks_armv6_mainloop_loaded:
+ MOVW R0>>26, g
+ MOVW R1>>20, R11
+ MOVW R2>>14, R12
+ MOVW R14, 92(R13)
+ MOVW R3>>8, R4
+ ORR R1<<6, g, g
+ ORR R2<<12, R11, R11
+ ORR R3<<18, R12, R12
+ BIC $0xfc000000, R0, R0
+ BIC $0xfc000000, g, g
+ MOVW 84(R13), R3
+ BIC $0xfc000000, R11, R11
+ BIC $0xfc000000, R12, R12
+ ADD R0, R5, R5
+ ADD g, R6, R6
+ ORR R3, R4, R4
+ ADD R11, R7, R7
+ ADD $116, R13, R14
+ ADD R12, R8, R8
+ ADD R4, R9, R9
+ MOVM.IA (R14), [R0-R4]
+ MULLU R4, R5, (R11, g)
+ MULLU R3, R5, (R14, R12)
+ MULALU R3, R6, (R11, g)
+ MULALU R2, R6, (R14, R12)
+ MULALU R2, R7, (R11, g)
+ MULALU R1, R7, (R14, R12)
+ ADD R4<<2, R4, R4
+ ADD R3<<2, R3, R3
+ MULALU R1, R8, (R11, g)
+ MULALU R0, R8, (R14, R12)
+ MULALU R0, R9, (R11, g)
+ MULALU R4, R9, (R14, R12)
+ MOVW g, 76(R13)
+ MOVW R11, 80(R13)
+ MOVW R12, 68(R13)
+ MOVW R14, 72(R13)
+ MULLU R2, R5, (R11, g)
+ MULLU R1, R5, (R14, R12)
+ MULALU R1, R6, (R11, g)
+ MULALU R0, R6, (R14, R12)
+ MULALU R0, R7, (R11, g)
+ MULALU R4, R7, (R14, R12)
+ ADD R2<<2, R2, R2
+ ADD R1<<2, R1, R1
+ MULALU R4, R8, (R11, g)
+ MULALU R3, R8, (R14, R12)
+ MULALU R3, R9, (R11, g)
+ MULALU R2, R9, (R14, R12)
+ MOVW g, 60(R13)
+ MOVW R11, 64(R13)
+ MOVW R12, 52(R13)
+ MOVW R14, 56(R13)
+ MULLU R0, R5, (R11, g)
+ MULALU R4, R6, (R11, g)
+ MULALU R3, R7, (R11, g)
+ MULALU R2, R8, (R11, g)
+ MULALU R1, R9, (R11, g)
+ ADD $52, R13, R0
+ MOVM.IA (R0), [R0-R7]
+ MOVW g>>26, R12
+ MOVW R4>>26, R14
+ ORR R11<<6, R12, R12
+ ORR R5<<6, R14, R14
+ BIC $0xfc000000, g, g
+ BIC $0xfc000000, R4, R4
+ ADD.S R12, R0, R0
+ ADC $0, R1, R1
+ ADD.S R14, R6, R6
+ ADC $0, R7, R7
+ MOVW R0>>26, R12
+ MOVW R6>>26, R14
+ ORR R1<<6, R12, R12
+ ORR R7<<6, R14, R14
+ BIC $0xfc000000, R0, R0
+ BIC $0xfc000000, R6, R6
+ ADD R14<<2, R14, R14
+ ADD.S R12, R2, R2
+ ADC $0, R3, R3
+ ADD R14, g, g
+ MOVW R2>>26, R12
+ MOVW g>>26, R14
+ ORR R3<<6, R12, R12
+ BIC $0xfc000000, g, R5
+ BIC $0xfc000000, R2, R7
+ ADD R12, R4, R4
+ ADD R14, R0, R0
+ MOVW R4>>26, R12
+ BIC $0xfc000000, R4, R8
+ ADD R12, R6, R9
+ MOVW 96(R13), R12
+ MOVW 92(R13), R14
+ MOVW R0, R6
+ CMP $32, R12
+ SUB $16, R12, R12
+ MOVW R12, 96(R13)
+ BHS poly1305_blocks_armv6_mainloop
+
+poly1305_blocks_armv6_done:
+ MOVW 88(R13), R12
+ MOVW R5, 20(R12)
+ MOVW R6, 24(R12)
+ MOVW R7, 28(R12)
+ MOVW R8, 32(R12)
+ MOVW R9, 36(R12)
+ ADD $48, R13, R0
+ MOVM.DA (R0), [R4-R8, R14]
+ RET
+
+#define MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp) \
+ MOVBU.P 1(Rsrc), Rtmp; \
+ MOVBU.P Rtmp, 1(Rdst); \
+ MOVBU.P 1(Rsrc), Rtmp; \
+ MOVBU.P Rtmp, 1(Rdst)
+
+#define MOVWP_UNALIGNED(Rsrc, Rdst, Rtmp) \
+ MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp); \
+ MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp)
+
+// func poly1305_auth_armv6(out *[16]byte, m *byte, mlen uint32, key *[32]key)
+TEXT ·poly1305_auth_armv6(SB), $196-16
+ // The value 196, just above, is the sum of 64 (the size of the context
+ // structure) and 132 (the amount of stack needed).
+ //
+ // At this point, the stack pointer (R13) has been moved down. It
+ // points to the saved link register and there's 196 bytes of free
+ // space above it.
+ //
+ // The stack for this function looks like:
+ //
+ // +---------------------
+ // |
+ // | 64 bytes of context structure
+ // |
+ // +---------------------
+ // |
+ // | 112 bytes for poly1305_blocks_armv6
+ // |
+ // +---------------------
+ // | 16 bytes of final block, constructed at
+ // | poly1305_finish_ext_armv6_skip8
+ // +---------------------
+ // | four bytes of saved 'g'
+ // +---------------------
+ // | lr, saved by prelude <- R13 points here
+ // +---------------------
+ MOVW g, 4(R13)
+
+ MOVW out+0(FP), R4
+ MOVW m+4(FP), R5
+ MOVW mlen+8(FP), R6
+ MOVW key+12(FP), R7
+
+ ADD $136, R13, R0 // 136 = 4 + 4 + 16 + 112
+ MOVW R7, R1
+
+ // poly1305_init_ext_armv6 will write to the stack from R13+4, but
+ // that's ok because none of the other values have been written yet.
+ BL poly1305_init_ext_armv6<>(SB)
+ BIC.S $15, R6, R2
+ BEQ poly1305_auth_armv6_noblocks
+ ADD $136, R13, R0
+ MOVW R5, R1
+ ADD R2, R5, R5
+ SUB R2, R6, R6
+ BL poly1305_blocks_armv6<>(SB)
+
+poly1305_auth_armv6_noblocks:
+ ADD $136, R13, R0
+ MOVW R5, R1
+ MOVW R6, R2
+ MOVW R4, R3
+
+ MOVW R0, R5
+ MOVW R1, R6
+ MOVW R2, R7
+ MOVW R3, R8
+ AND.S R2, R2, R2
+ BEQ poly1305_finish_ext_armv6_noremaining
+ EOR R0, R0
+ ADD $8, R13, R9 // 8 = offset to 16 byte scratch space
+ MOVW R0, (R9)
+ MOVW R0, 4(R9)
+ MOVW R0, 8(R9)
+ MOVW R0, 12(R9)
+ WORD $0xe3110003 // TST R1, #3 not working see issue 5921
+ BEQ poly1305_finish_ext_armv6_aligned
+ WORD $0xe3120008 // TST R2, #8 not working see issue 5921
+ BEQ poly1305_finish_ext_armv6_skip8
+ MOVWP_UNALIGNED(R1, R9, g)
+ MOVWP_UNALIGNED(R1, R9, g)
+
+poly1305_finish_ext_armv6_skip8:
+ WORD $0xe3120004 // TST $4, R2 not working see issue 5921
+ BEQ poly1305_finish_ext_armv6_skip4
+ MOVWP_UNALIGNED(R1, R9, g)
+
+poly1305_finish_ext_armv6_skip4:
+ WORD $0xe3120002 // TST $2, R2 not working see issue 5921
+ BEQ poly1305_finish_ext_armv6_skip2
+ MOVHUP_UNALIGNED(R1, R9, g)
+ B poly1305_finish_ext_armv6_skip2
+
+poly1305_finish_ext_armv6_aligned:
+ WORD $0xe3120008 // TST R2, #8 not working see issue 5921
+ BEQ poly1305_finish_ext_armv6_skip8_aligned
+ MOVM.IA.W (R1), [g-R11]
+ MOVM.IA.W [g-R11], (R9)
+
+poly1305_finish_ext_armv6_skip8_aligned:
+ WORD $0xe3120004 // TST $4, R2 not working see issue 5921
+ BEQ poly1305_finish_ext_armv6_skip4_aligned
+ MOVW.P 4(R1), g
+ MOVW.P g, 4(R9)
+
+poly1305_finish_ext_armv6_skip4_aligned:
+ WORD $0xe3120002 // TST $2, R2 not working see issue 5921
+ BEQ poly1305_finish_ext_armv6_skip2
+ MOVHU.P 2(R1), g
+ MOVH.P g, 2(R9)
+
+poly1305_finish_ext_armv6_skip2:
+ WORD $0xe3120001 // TST $1, R2 not working see issue 5921
+ BEQ poly1305_finish_ext_armv6_skip1
+ MOVBU.P 1(R1), g
+ MOVBU.P g, 1(R9)
+
+poly1305_finish_ext_armv6_skip1:
+ MOVW $1, R11
+ MOVBU R11, 0(R9)
+ MOVW R11, 56(R5)
+ MOVW R5, R0
+ ADD $8, R13, R1
+ MOVW $16, R2
+ BL poly1305_blocks_armv6<>(SB)
+
+poly1305_finish_ext_armv6_noremaining:
+ MOVW 20(R5), R0
+ MOVW 24(R5), R1
+ MOVW 28(R5), R2
+ MOVW 32(R5), R3
+ MOVW 36(R5), R4
+ MOVW R4>>26, R12
+ BIC $0xfc000000, R4, R4
+ ADD R12<<2, R12, R12
+ ADD R12, R0, R0
+ MOVW R0>>26, R12
+ BIC $0xfc000000, R0, R0
+ ADD R12, R1, R1
+ MOVW R1>>26, R12
+ BIC $0xfc000000, R1, R1
+ ADD R12, R2, R2
+ MOVW R2>>26, R12
+ BIC $0xfc000000, R2, R2
+ ADD R12, R3, R3
+ MOVW R3>>26, R12
+ BIC $0xfc000000, R3, R3
+ ADD R12, R4, R4
+ ADD $5, R0, R6
+ MOVW R6>>26, R12
+ BIC $0xfc000000, R6, R6
+ ADD R12, R1, R7
+ MOVW R7>>26, R12
+ BIC $0xfc000000, R7, R7
+ ADD R12, R2, g
+ MOVW g>>26, R12
+ BIC $0xfc000000, g, g
+ ADD R12, R3, R11
+ MOVW $-(1<<26), R12
+ ADD R11>>26, R12, R12
+ BIC $0xfc000000, R11, R11
+ ADD R12, R4, R9
+ MOVW R9>>31, R12
+ SUB $1, R12
+ AND R12, R6, R6
+ AND R12, R7, R7
+ AND R12, g, g
+ AND R12, R11, R11
+ AND R12, R9, R9
+ MVN R12, R12
+ AND R12, R0, R0
+ AND R12, R1, R1
+ AND R12, R2, R2
+ AND R12, R3, R3
+ AND R12, R4, R4
+ ORR R6, R0, R0
+ ORR R7, R1, R1
+ ORR g, R2, R2
+ ORR R11, R3, R3
+ ORR R9, R4, R4
+ ORR R1<<26, R0, R0
+ MOVW R1>>6, R1
+ ORR R2<<20, R1, R1
+ MOVW R2>>12, R2
+ ORR R3<<14, R2, R2
+ MOVW R3>>18, R3
+ ORR R4<<8, R3, R3
+ MOVW 40(R5), R6
+ MOVW 44(R5), R7
+ MOVW 48(R5), g
+ MOVW 52(R5), R11
+ ADD.S R6, R0, R0
+ ADC.S R7, R1, R1
+ ADC.S g, R2, R2
+ ADC.S R11, R3, R3
+ MOVM.IA [R0-R3], (R8)
+ MOVW R5, R12
+ EOR R0, R0, R0
+ EOR R1, R1, R1
+ EOR R2, R2, R2
+ EOR R3, R3, R3
+ EOR R4, R4, R4
+ EOR R5, R5, R5
+ EOR R6, R6, R6
+ EOR R7, R7, R7
+ MOVM.IA.W [R0-R7], (R12)
+ MOVM.IA [R0-R7], (R12)
+ MOVW 4(R13), g
+ RET
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/poly1305/sum_ref.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/poly1305/sum_ref.go
new file mode 100644
index 000000000..b2805a5ca
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/poly1305/sum_ref.go
@@ -0,0 +1,141 @@
+// Copyright 2012 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.
+
+// +build !amd64,!arm gccgo appengine nacl
+
+package poly1305
+
+import "encoding/binary"
+
+// Sum generates an authenticator for msg using a one-time key and puts the
+// 16-byte result into out. Authenticating two different messages with the same
+// key allows an attacker to forge messages at will.
+func Sum(out *[TagSize]byte, msg []byte, key *[32]byte) {
+ var (
+ h0, h1, h2, h3, h4 uint32 // the hash accumulators
+ r0, r1, r2, r3, r4 uint64 // the r part of the key
+ )
+
+ r0 = uint64(binary.LittleEndian.Uint32(key[0:]) & 0x3ffffff)
+ r1 = uint64((binary.LittleEndian.Uint32(key[3:]) >> 2) & 0x3ffff03)
+ r2 = uint64((binary.LittleEndian.Uint32(key[6:]) >> 4) & 0x3ffc0ff)
+ r3 = uint64((binary.LittleEndian.Uint32(key[9:]) >> 6) & 0x3f03fff)
+ r4 = uint64((binary.LittleEndian.Uint32(key[12:]) >> 8) & 0x00fffff)
+
+ R1, R2, R3, R4 := r1*5, r2*5, r3*5, r4*5
+
+ for len(msg) >= TagSize {
+ // h += msg
+ h0 += binary.LittleEndian.Uint32(msg[0:]) & 0x3ffffff
+ h1 += (binary.LittleEndian.Uint32(msg[3:]) >> 2) & 0x3ffffff
+ h2 += (binary.LittleEndian.Uint32(msg[6:]) >> 4) & 0x3ffffff
+ h3 += (binary.LittleEndian.Uint32(msg[9:]) >> 6) & 0x3ffffff
+ h4 += (binary.LittleEndian.Uint32(msg[12:]) >> 8) | (1 << 24)
+
+ // h *= r
+ d0 := (uint64(h0) * r0) + (uint64(h1) * R4) + (uint64(h2) * R3) + (uint64(h3) * R2) + (uint64(h4) * R1)
+ d1 := (d0 >> 26) + (uint64(h0) * r1) + (uint64(h1) * r0) + (uint64(h2) * R4) + (uint64(h3) * R3) + (uint64(h4) * R2)
+ d2 := (d1 >> 26) + (uint64(h0) * r2) + (uint64(h1) * r1) + (uint64(h2) * r0) + (uint64(h3) * R4) + (uint64(h4) * R3)
+ d3 := (d2 >> 26) + (uint64(h0) * r3) + (uint64(h1) * r2) + (uint64(h2) * r1) + (uint64(h3) * r0) + (uint64(h4) * R4)
+ d4 := (d3 >> 26) + (uint64(h0) * r4) + (uint64(h1) * r3) + (uint64(h2) * r2) + (uint64(h3) * r1) + (uint64(h4) * r0)
+
+ // h %= p
+ h0 = uint32(d0) & 0x3ffffff
+ h1 = uint32(d1) & 0x3ffffff
+ h2 = uint32(d2) & 0x3ffffff
+ h3 = uint32(d3) & 0x3ffffff
+ h4 = uint32(d4) & 0x3ffffff
+
+ h0 += uint32(d4>>26) * 5
+ h1 += h0 >> 26
+ h0 = h0 & 0x3ffffff
+
+ msg = msg[TagSize:]
+ }
+
+ if len(msg) > 0 {
+ var block [TagSize]byte
+ off := copy(block[:], msg)
+ block[off] = 0x01
+
+ // h += msg
+ h0 += binary.LittleEndian.Uint32(block[0:]) & 0x3ffffff
+ h1 += (binary.LittleEndian.Uint32(block[3:]) >> 2) & 0x3ffffff
+ h2 += (binary.LittleEndian.Uint32(block[6:]) >> 4) & 0x3ffffff
+ h3 += (binary.LittleEndian.Uint32(block[9:]) >> 6) & 0x3ffffff
+ h4 += (binary.LittleEndian.Uint32(block[12:]) >> 8)
+
+ // h *= r
+ d0 := (uint64(h0) * r0) + (uint64(h1) * R4) + (uint64(h2) * R3) + (uint64(h3) * R2) + (uint64(h4) * R1)
+ d1 := (d0 >> 26) + (uint64(h0) * r1) + (uint64(h1) * r0) + (uint64(h2) * R4) + (uint64(h3) * R3) + (uint64(h4) * R2)
+ d2 := (d1 >> 26) + (uint64(h0) * r2) + (uint64(h1) * r1) + (uint64(h2) * r0) + (uint64(h3) * R4) + (uint64(h4) * R3)
+ d3 := (d2 >> 26) + (uint64(h0) * r3) + (uint64(h1) * r2) + (uint64(h2) * r1) + (uint64(h3) * r0) + (uint64(h4) * R4)
+ d4 := (d3 >> 26) + (uint64(h0) * r4) + (uint64(h1) * r3) + (uint64(h2) * r2) + (uint64(h3) * r1) + (uint64(h4) * r0)
+
+ // h %= p
+ h0 = uint32(d0) & 0x3ffffff
+ h1 = uint32(d1) & 0x3ffffff
+ h2 = uint32(d2) & 0x3ffffff
+ h3 = uint32(d3) & 0x3ffffff
+ h4 = uint32(d4) & 0x3ffffff
+
+ h0 += uint32(d4>>26) * 5
+ h1 += h0 >> 26
+ h0 = h0 & 0x3ffffff
+ }
+
+ // h %= p reduction
+ h2 += h1 >> 26
+ h1 &= 0x3ffffff
+ h3 += h2 >> 26
+ h2 &= 0x3ffffff
+ h4 += h3 >> 26
+ h3 &= 0x3ffffff
+ h0 += 5 * (h4 >> 26)
+ h4 &= 0x3ffffff
+ h1 += h0 >> 26
+ h0 &= 0x3ffffff
+
+ // h - p
+ t0 := h0 + 5
+ t1 := h1 + (t0 >> 26)
+ t2 := h2 + (t1 >> 26)
+ t3 := h3 + (t2 >> 26)
+ t4 := h4 + (t3 >> 26) - (1 << 26)
+ t0 &= 0x3ffffff
+ t1 &= 0x3ffffff
+ t2 &= 0x3ffffff
+ t3 &= 0x3ffffff
+
+ // select h if h < p else h - p
+ t_mask := (t4 >> 31) - 1
+ h_mask := ^t_mask
+ h0 = (h0 & h_mask) | (t0 & t_mask)
+ h1 = (h1 & h_mask) | (t1 & t_mask)
+ h2 = (h2 & h_mask) | (t2 & t_mask)
+ h3 = (h3 & h_mask) | (t3 & t_mask)
+ h4 = (h4 & h_mask) | (t4 & t_mask)
+
+ // h %= 2^128
+ h0 |= h1 << 26
+ h1 = ((h1 >> 6) | (h2 << 20))
+ h2 = ((h2 >> 12) | (h3 << 14))
+ h3 = ((h3 >> 18) | (h4 << 8))
+
+ // s: the s part of the key
+ // tag = (h + s) % (2^128)
+ t := uint64(h0) + uint64(binary.LittleEndian.Uint32(key[16:]))
+ h0 = uint32(t)
+ t = uint64(h1) + uint64(binary.LittleEndian.Uint32(key[20:])) + (t >> 32)
+ h1 = uint32(t)
+ t = uint64(h2) + uint64(binary.LittleEndian.Uint32(key[24:])) + (t >> 32)
+ h2 = uint32(t)
+ t = uint64(h3) + uint64(binary.LittleEndian.Uint32(key[28:])) + (t >> 32)
+ h3 = uint32(t)
+
+ binary.LittleEndian.PutUint32(out[0:], h0)
+ binary.LittleEndian.PutUint32(out[4:], h1)
+ binary.LittleEndian.PutUint32(out[8:], h2)
+ binary.LittleEndian.PutUint32(out[12:], h3)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ripemd160/ripemd160.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ripemd160/ripemd160.go
new file mode 100644
index 000000000..6c6e84236
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ripemd160/ripemd160.go
@@ -0,0 +1,120 @@
+// Copyright 2010 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 ripemd160 implements the RIPEMD-160 hash algorithm.
+package ripemd160 // import "golang.org/x/crypto/ripemd160"
+
+// RIPEMD-160 is designed by by Hans Dobbertin, Antoon Bosselaers, and Bart
+// Preneel with specifications available at:
+// http://homes.esat.kuleuven.be/~cosicart/pdf/AB-9601/AB-9601.pdf.
+
+import (
+ "crypto"
+ "hash"
+)
+
+func init() {
+ crypto.RegisterHash(crypto.RIPEMD160, New)
+}
+
+// The size of the checksum in bytes.
+const Size = 20
+
+// The block size of the hash algorithm in bytes.
+const BlockSize = 64
+
+const (
+ _s0 = 0x67452301
+ _s1 = 0xefcdab89
+ _s2 = 0x98badcfe
+ _s3 = 0x10325476
+ _s4 = 0xc3d2e1f0
+)
+
+// digest represents the partial evaluation of a checksum.
+type digest struct {
+ s [5]uint32 // running context
+ x [BlockSize]byte // temporary buffer
+ nx int // index into x
+ tc uint64 // total count of bytes processed
+}
+
+func (d *digest) Reset() {
+ d.s[0], d.s[1], d.s[2], d.s[3], d.s[4] = _s0, _s1, _s2, _s3, _s4
+ d.nx = 0
+ d.tc = 0
+}
+
+// New returns a new hash.Hash computing the checksum.
+func New() hash.Hash {
+ result := new(digest)
+ result.Reset()
+ return result
+}
+
+func (d *digest) Size() int { return Size }
+
+func (d *digest) BlockSize() int { return BlockSize }
+
+func (d *digest) Write(p []byte) (nn int, err error) {
+ nn = len(p)
+ d.tc += uint64(nn)
+ if d.nx > 0 {
+ n := len(p)
+ if n > BlockSize-d.nx {
+ n = BlockSize - d.nx
+ }
+ for i := 0; i < n; i++ {
+ d.x[d.nx+i] = p[i]
+ }
+ d.nx += n
+ if d.nx == BlockSize {
+ _Block(d, d.x[0:])
+ d.nx = 0
+ }
+ p = p[n:]
+ }
+ n := _Block(d, p)
+ p = p[n:]
+ if len(p) > 0 {
+ d.nx = copy(d.x[:], p)
+ }
+ return
+}
+
+func (d0 *digest) Sum(in []byte) []byte {
+ // Make a copy of d0 so that caller can keep writing and summing.
+ d := *d0
+
+ // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64.
+ tc := d.tc
+ var tmp [64]byte
+ tmp[0] = 0x80
+ if tc%64 < 56 {
+ d.Write(tmp[0 : 56-tc%64])
+ } else {
+ d.Write(tmp[0 : 64+56-tc%64])
+ }
+
+ // Length in bits.
+ tc <<= 3
+ for i := uint(0); i < 8; i++ {
+ tmp[i] = byte(tc >> (8 * i))
+ }
+ d.Write(tmp[0:8])
+
+ if d.nx != 0 {
+ panic("d.nx != 0")
+ }
+
+ var digest [Size]byte
+ for i, s := range d.s {
+ digest[i*4] = byte(s)
+ digest[i*4+1] = byte(s >> 8)
+ digest[i*4+2] = byte(s >> 16)
+ digest[i*4+3] = byte(s >> 24)
+ }
+
+ return append(in, digest[:]...)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ripemd160/ripemd160_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ripemd160/ripemd160_test.go
new file mode 100644
index 000000000..5df1b2593
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ripemd160/ripemd160_test.go
@@ -0,0 +1,64 @@
+// Copyright 2010 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 ripemd160
+
+// Test vectors are from:
+// http://homes.esat.kuleuven.be/~bosselae/ripemd160.html
+
+import (
+ "fmt"
+ "io"
+ "testing"
+)
+
+type mdTest struct {
+ out string
+ in string
+}
+
+var vectors = [...]mdTest{
+ {"9c1185a5c5e9fc54612808977ee8f548b2258d31", ""},
+ {"0bdc9d2d256b3ee9daae347be6f4dc835a467ffe", "a"},
+ {"8eb208f7e05d987a9b044a8e98c6b087f15a0bfc", "abc"},
+ {"5d0689ef49d2fae572b881b123a85ffa21595f36", "message digest"},
+ {"f71c27109c692c1b56bbdceb5b9d2865b3708dbc", "abcdefghijklmnopqrstuvwxyz"},
+ {"12a053384a9c0c88e405a06c27dcf49ada62eb2b", "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"},
+ {"b0e20b6e3116640286ed3a87a5713079b21f5189", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"},
+ {"9b752e45573d4b39f4dbd3323cab82bf63326bfb", "12345678901234567890123456789012345678901234567890123456789012345678901234567890"},
+}
+
+func TestVectors(t *testing.T) {
+ for i := 0; i < len(vectors); i++ {
+ tv := vectors[i]
+ md := New()
+ for j := 0; j < 3; j++ {
+ if j < 2 {
+ io.WriteString(md, tv.in)
+ } else {
+ io.WriteString(md, tv.in[0:len(tv.in)/2])
+ md.Sum(nil)
+ io.WriteString(md, tv.in[len(tv.in)/2:])
+ }
+ s := fmt.Sprintf("%x", md.Sum(nil))
+ if s != tv.out {
+ t.Fatalf("RIPEMD-160[%d](%s) = %s, expected %s", j, tv.in, s, tv.out)
+ }
+ md.Reset()
+ }
+ }
+}
+
+func TestMillionA(t *testing.T) {
+ md := New()
+ for i := 0; i < 100000; i++ {
+ io.WriteString(md, "aaaaaaaaaa")
+ }
+ out := "52783243c1697bdbe16d37f97f68f08325dc1528"
+ s := fmt.Sprintf("%x", md.Sum(nil))
+ if s != out {
+ t.Fatalf("RIPEMD-160 (1 million 'a') = %s, expected %s", s, out)
+ }
+ md.Reset()
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ripemd160/ripemd160block.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ripemd160/ripemd160block.go
new file mode 100644
index 000000000..7bc8e6c48
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ripemd160/ripemd160block.go
@@ -0,0 +1,161 @@
+// Copyright 2010 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.
+
+// RIPEMD-160 block step.
+// In its own file so that a faster assembly or C version
+// can be substituted easily.
+
+package ripemd160
+
+// work buffer indices and roll amounts for one line
+var _n = [80]uint{
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8,
+ 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12,
+ 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2,
+ 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13,
+}
+
+var _r = [80]uint{
+ 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8,
+ 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12,
+ 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5,
+ 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12,
+ 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6,
+}
+
+// same for the other parallel one
+var n_ = [80]uint{
+ 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12,
+ 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2,
+ 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13,
+ 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14,
+ 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11,
+}
+
+var r_ = [80]uint{
+ 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6,
+ 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11,
+ 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5,
+ 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8,
+ 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11,
+}
+
+func _Block(md *digest, p []byte) int {
+ n := 0
+ var x [16]uint32
+ var alpha, beta uint32
+ for len(p) >= BlockSize {
+ a, b, c, d, e := md.s[0], md.s[1], md.s[2], md.s[3], md.s[4]
+ aa, bb, cc, dd, ee := a, b, c, d, e
+ j := 0
+ for i := 0; i < 16; i++ {
+ x[i] = uint32(p[j]) | uint32(p[j+1])<<8 | uint32(p[j+2])<<16 | uint32(p[j+3])<<24
+ j += 4
+ }
+
+ // round 1
+ i := 0
+ for i < 16 {
+ alpha = a + (b ^ c ^ d) + x[_n[i]]
+ s := _r[i]
+ alpha = (alpha<<s | alpha>>(32-s)) + e
+ beta = c<<10 | c>>22
+ a, b, c, d, e = e, alpha, b, beta, d
+
+ // parallel line
+ alpha = aa + (bb ^ (cc | ^dd)) + x[n_[i]] + 0x50a28be6
+ s = r_[i]
+ alpha = (alpha<<s | alpha>>(32-s)) + ee
+ beta = cc<<10 | cc>>22
+ aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd
+
+ i++
+ }
+
+ // round 2
+ for i < 32 {
+ alpha = a + (b&c | ^b&d) + x[_n[i]] + 0x5a827999
+ s := _r[i]
+ alpha = (alpha<<s | alpha>>(32-s)) + e
+ beta = c<<10 | c>>22
+ a, b, c, d, e = e, alpha, b, beta, d
+
+ // parallel line
+ alpha = aa + (bb&dd | cc&^dd) + x[n_[i]] + 0x5c4dd124
+ s = r_[i]
+ alpha = (alpha<<s | alpha>>(32-s)) + ee
+ beta = cc<<10 | cc>>22
+ aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd
+
+ i++
+ }
+
+ // round 3
+ for i < 48 {
+ alpha = a + (b | ^c ^ d) + x[_n[i]] + 0x6ed9eba1
+ s := _r[i]
+ alpha = (alpha<<s | alpha>>(32-s)) + e
+ beta = c<<10 | c>>22
+ a, b, c, d, e = e, alpha, b, beta, d
+
+ // parallel line
+ alpha = aa + (bb | ^cc ^ dd) + x[n_[i]] + 0x6d703ef3
+ s = r_[i]
+ alpha = (alpha<<s | alpha>>(32-s)) + ee
+ beta = cc<<10 | cc>>22
+ aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd
+
+ i++
+ }
+
+ // round 4
+ for i < 64 {
+ alpha = a + (b&d | c&^d) + x[_n[i]] + 0x8f1bbcdc
+ s := _r[i]
+ alpha = (alpha<<s | alpha>>(32-s)) + e
+ beta = c<<10 | c>>22
+ a, b, c, d, e = e, alpha, b, beta, d
+
+ // parallel line
+ alpha = aa + (bb&cc | ^bb&dd) + x[n_[i]] + 0x7a6d76e9
+ s = r_[i]
+ alpha = (alpha<<s | alpha>>(32-s)) + ee
+ beta = cc<<10 | cc>>22
+ aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd
+
+ i++
+ }
+
+ // round 5
+ for i < 80 {
+ alpha = a + (b ^ (c | ^d)) + x[_n[i]] + 0xa953fd4e
+ s := _r[i]
+ alpha = (alpha<<s | alpha>>(32-s)) + e
+ beta = c<<10 | c>>22
+ a, b, c, d, e = e, alpha, b, beta, d
+
+ // parallel line
+ alpha = aa + (bb ^ cc ^ dd) + x[n_[i]]
+ s = r_[i]
+ alpha = (alpha<<s | alpha>>(32-s)) + ee
+ beta = cc<<10 | cc>>22
+ aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd
+
+ i++
+ }
+
+ // combine results
+ dd += c + md.s[1]
+ md.s[1] = md.s[2] + d + ee
+ md.s[2] = md.s[3] + e + aa
+ md.s[3] = md.s[4] + a + bb
+ md.s[4] = md.s[0] + b + cc
+ md.s[0] = dd
+
+ p = p[BlockSize:]
+ n += BlockSize
+ }
+ return n
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/salsa20/salsa/hsalsa20.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/salsa20/salsa/hsalsa20.go
new file mode 100644
index 000000000..4c96147c8
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/salsa20/salsa/hsalsa20.go
@@ -0,0 +1,144 @@
+// Copyright 2012 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 salsa provides low-level access to functions in the Salsa family.
+package salsa // import "golang.org/x/crypto/salsa20/salsa"
+
+// Sigma is the Salsa20 constant for 256-bit keys.
+var Sigma = [16]byte{'e', 'x', 'p', 'a', 'n', 'd', ' ', '3', '2', '-', 'b', 'y', 't', 'e', ' ', 'k'}
+
+// HSalsa20 applies the HSalsa20 core function to a 16-byte input in, 32-byte
+// key k, and 16-byte constant c, and puts the result into the 32-byte array
+// out.
+func HSalsa20(out *[32]byte, in *[16]byte, k *[32]byte, c *[16]byte) {
+ x0 := uint32(c[0]) | uint32(c[1])<<8 | uint32(c[2])<<16 | uint32(c[3])<<24
+ x1 := uint32(k[0]) | uint32(k[1])<<8 | uint32(k[2])<<16 | uint32(k[3])<<24
+ x2 := uint32(k[4]) | uint32(k[5])<<8 | uint32(k[6])<<16 | uint32(k[7])<<24
+ x3 := uint32(k[8]) | uint32(k[9])<<8 | uint32(k[10])<<16 | uint32(k[11])<<24
+ x4 := uint32(k[12]) | uint32(k[13])<<8 | uint32(k[14])<<16 | uint32(k[15])<<24
+ x5 := uint32(c[4]) | uint32(c[5])<<8 | uint32(c[6])<<16 | uint32(c[7])<<24
+ x6 := uint32(in[0]) | uint32(in[1])<<8 | uint32(in[2])<<16 | uint32(in[3])<<24
+ x7 := uint32(in[4]) | uint32(in[5])<<8 | uint32(in[6])<<16 | uint32(in[7])<<24
+ x8 := uint32(in[8]) | uint32(in[9])<<8 | uint32(in[10])<<16 | uint32(in[11])<<24
+ x9 := uint32(in[12]) | uint32(in[13])<<8 | uint32(in[14])<<16 | uint32(in[15])<<24
+ x10 := uint32(c[8]) | uint32(c[9])<<8 | uint32(c[10])<<16 | uint32(c[11])<<24
+ x11 := uint32(k[16]) | uint32(k[17])<<8 | uint32(k[18])<<16 | uint32(k[19])<<24
+ x12 := uint32(k[20]) | uint32(k[21])<<8 | uint32(k[22])<<16 | uint32(k[23])<<24
+ x13 := uint32(k[24]) | uint32(k[25])<<8 | uint32(k[26])<<16 | uint32(k[27])<<24
+ x14 := uint32(k[28]) | uint32(k[29])<<8 | uint32(k[30])<<16 | uint32(k[31])<<24
+ x15 := uint32(c[12]) | uint32(c[13])<<8 | uint32(c[14])<<16 | uint32(c[15])<<24
+
+ for i := 0; i < 20; i += 2 {
+ u := x0 + x12
+ x4 ^= u<<7 | u>>(32-7)
+ u = x4 + x0
+ x8 ^= u<<9 | u>>(32-9)
+ u = x8 + x4
+ x12 ^= u<<13 | u>>(32-13)
+ u = x12 + x8
+ x0 ^= u<<18 | u>>(32-18)
+
+ u = x5 + x1
+ x9 ^= u<<7 | u>>(32-7)
+ u = x9 + x5
+ x13 ^= u<<9 | u>>(32-9)
+ u = x13 + x9
+ x1 ^= u<<13 | u>>(32-13)
+ u = x1 + x13
+ x5 ^= u<<18 | u>>(32-18)
+
+ u = x10 + x6
+ x14 ^= u<<7 | u>>(32-7)
+ u = x14 + x10
+ x2 ^= u<<9 | u>>(32-9)
+ u = x2 + x14
+ x6 ^= u<<13 | u>>(32-13)
+ u = x6 + x2
+ x10 ^= u<<18 | u>>(32-18)
+
+ u = x15 + x11
+ x3 ^= u<<7 | u>>(32-7)
+ u = x3 + x15
+ x7 ^= u<<9 | u>>(32-9)
+ u = x7 + x3
+ x11 ^= u<<13 | u>>(32-13)
+ u = x11 + x7
+ x15 ^= u<<18 | u>>(32-18)
+
+ u = x0 + x3
+ x1 ^= u<<7 | u>>(32-7)
+ u = x1 + x0
+ x2 ^= u<<9 | u>>(32-9)
+ u = x2 + x1
+ x3 ^= u<<13 | u>>(32-13)
+ u = x3 + x2
+ x0 ^= u<<18 | u>>(32-18)
+
+ u = x5 + x4
+ x6 ^= u<<7 | u>>(32-7)
+ u = x6 + x5
+ x7 ^= u<<9 | u>>(32-9)
+ u = x7 + x6
+ x4 ^= u<<13 | u>>(32-13)
+ u = x4 + x7
+ x5 ^= u<<18 | u>>(32-18)
+
+ u = x10 + x9
+ x11 ^= u<<7 | u>>(32-7)
+ u = x11 + x10
+ x8 ^= u<<9 | u>>(32-9)
+ u = x8 + x11
+ x9 ^= u<<13 | u>>(32-13)
+ u = x9 + x8
+ x10 ^= u<<18 | u>>(32-18)
+
+ u = x15 + x14
+ x12 ^= u<<7 | u>>(32-7)
+ u = x12 + x15
+ x13 ^= u<<9 | u>>(32-9)
+ u = x13 + x12
+ x14 ^= u<<13 | u>>(32-13)
+ u = x14 + x13
+ x15 ^= u<<18 | u>>(32-18)
+ }
+ out[0] = byte(x0)
+ out[1] = byte(x0 >> 8)
+ out[2] = byte(x0 >> 16)
+ out[3] = byte(x0 >> 24)
+
+ out[4] = byte(x5)
+ out[5] = byte(x5 >> 8)
+ out[6] = byte(x5 >> 16)
+ out[7] = byte(x5 >> 24)
+
+ out[8] = byte(x10)
+ out[9] = byte(x10 >> 8)
+ out[10] = byte(x10 >> 16)
+ out[11] = byte(x10 >> 24)
+
+ out[12] = byte(x15)
+ out[13] = byte(x15 >> 8)
+ out[14] = byte(x15 >> 16)
+ out[15] = byte(x15 >> 24)
+
+ out[16] = byte(x6)
+ out[17] = byte(x6 >> 8)
+ out[18] = byte(x6 >> 16)
+ out[19] = byte(x6 >> 24)
+
+ out[20] = byte(x7)
+ out[21] = byte(x7 >> 8)
+ out[22] = byte(x7 >> 16)
+ out[23] = byte(x7 >> 24)
+
+ out[24] = byte(x8)
+ out[25] = byte(x8 >> 8)
+ out[26] = byte(x8 >> 16)
+ out[27] = byte(x8 >> 24)
+
+ out[28] = byte(x9)
+ out[29] = byte(x9 >> 8)
+ out[30] = byte(x9 >> 16)
+ out[31] = byte(x9 >> 24)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/salsa20/salsa/salsa2020_amd64.s b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/salsa20/salsa/salsa2020_amd64.s
new file mode 100644
index 000000000..22afbdcad
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/salsa20/salsa/salsa2020_amd64.s
@@ -0,0 +1,889 @@
+// Copyright 2012 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.
+
+// +build amd64,!appengine,!gccgo
+
+// This code was translated into a form compatible with 6a from the public
+// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html
+
+// func salsa2020XORKeyStream(out, in *byte, n uint64, nonce, key *byte)
+// This needs up to 64 bytes at 360(SP); hence the non-obvious frame size.
+TEXT ·salsa2020XORKeyStream(SB),0,$456-40 // frame = 424 + 32 byte alignment
+ MOVQ out+0(FP),DI
+ MOVQ in+8(FP),SI
+ MOVQ n+16(FP),DX
+ MOVQ nonce+24(FP),CX
+ MOVQ key+32(FP),R8
+
+ MOVQ SP,R12
+ MOVQ SP,R9
+ ADDQ $31, R9
+ ANDQ $~31, R9
+ MOVQ R9, SP
+
+ MOVQ DX,R9
+ MOVQ CX,DX
+ MOVQ R8,R10
+ CMPQ R9,$0
+ JBE DONE
+ START:
+ MOVL 20(R10),CX
+ MOVL 0(R10),R8
+ MOVL 0(DX),AX
+ MOVL 16(R10),R11
+ MOVL CX,0(SP)
+ MOVL R8, 4 (SP)
+ MOVL AX, 8 (SP)
+ MOVL R11, 12 (SP)
+ MOVL 8(DX),CX
+ MOVL 24(R10),R8
+ MOVL 4(R10),AX
+ MOVL 4(DX),R11
+ MOVL CX,16(SP)
+ MOVL R8, 20 (SP)
+ MOVL AX, 24 (SP)
+ MOVL R11, 28 (SP)
+ MOVL 12(DX),CX
+ MOVL 12(R10),DX
+ MOVL 28(R10),R8
+ MOVL 8(R10),AX
+ MOVL DX,32(SP)
+ MOVL CX, 36 (SP)
+ MOVL R8, 40 (SP)
+ MOVL AX, 44 (SP)
+ MOVQ $1634760805,DX
+ MOVQ $857760878,CX
+ MOVQ $2036477234,R8
+ MOVQ $1797285236,AX
+ MOVL DX,48(SP)
+ MOVL CX, 52 (SP)
+ MOVL R8, 56 (SP)
+ MOVL AX, 60 (SP)
+ CMPQ R9,$256
+ JB BYTESBETWEEN1AND255
+ MOVOA 48(SP),X0
+ PSHUFL $0X55,X0,X1
+ PSHUFL $0XAA,X0,X2
+ PSHUFL $0XFF,X0,X3
+ PSHUFL $0X00,X0,X0
+ MOVOA X1,64(SP)
+ MOVOA X2,80(SP)
+ MOVOA X3,96(SP)
+ MOVOA X0,112(SP)
+ MOVOA 0(SP),X0
+ PSHUFL $0XAA,X0,X1
+ PSHUFL $0XFF,X0,X2
+ PSHUFL $0X00,X0,X3
+ PSHUFL $0X55,X0,X0
+ MOVOA X1,128(SP)
+ MOVOA X2,144(SP)
+ MOVOA X3,160(SP)
+ MOVOA X0,176(SP)
+ MOVOA 16(SP),X0
+ PSHUFL $0XFF,X0,X1
+ PSHUFL $0X55,X0,X2
+ PSHUFL $0XAA,X0,X0
+ MOVOA X1,192(SP)
+ MOVOA X2,208(SP)
+ MOVOA X0,224(SP)
+ MOVOA 32(SP),X0
+ PSHUFL $0X00,X0,X1
+ PSHUFL $0XAA,X0,X2
+ PSHUFL $0XFF,X0,X0
+ MOVOA X1,240(SP)
+ MOVOA X2,256(SP)
+ MOVOA X0,272(SP)
+ BYTESATLEAST256:
+ MOVL 16(SP),DX
+ MOVL 36 (SP),CX
+ MOVL DX,288(SP)
+ MOVL CX,304(SP)
+ ADDQ $1,DX
+ SHLQ $32,CX
+ ADDQ CX,DX
+ MOVQ DX,CX
+ SHRQ $32,CX
+ MOVL DX, 292 (SP)
+ MOVL CX, 308 (SP)
+ ADDQ $1,DX
+ SHLQ $32,CX
+ ADDQ CX,DX
+ MOVQ DX,CX
+ SHRQ $32,CX
+ MOVL DX, 296 (SP)
+ MOVL CX, 312 (SP)
+ ADDQ $1,DX
+ SHLQ $32,CX
+ ADDQ CX,DX
+ MOVQ DX,CX
+ SHRQ $32,CX
+ MOVL DX, 300 (SP)
+ MOVL CX, 316 (SP)
+ ADDQ $1,DX
+ SHLQ $32,CX
+ ADDQ CX,DX
+ MOVQ DX,CX
+ SHRQ $32,CX
+ MOVL DX,16(SP)
+ MOVL CX, 36 (SP)
+ MOVQ R9,352(SP)
+ MOVQ $20,DX
+ MOVOA 64(SP),X0
+ MOVOA 80(SP),X1
+ MOVOA 96(SP),X2
+ MOVOA 256(SP),X3
+ MOVOA 272(SP),X4
+ MOVOA 128(SP),X5
+ MOVOA 144(SP),X6
+ MOVOA 176(SP),X7
+ MOVOA 192(SP),X8
+ MOVOA 208(SP),X9
+ MOVOA 224(SP),X10
+ MOVOA 304(SP),X11
+ MOVOA 112(SP),X12
+ MOVOA 160(SP),X13
+ MOVOA 240(SP),X14
+ MOVOA 288(SP),X15
+ MAINLOOP1:
+ MOVOA X1,320(SP)
+ MOVOA X2,336(SP)
+ MOVOA X13,X1
+ PADDL X12,X1
+ MOVOA X1,X2
+ PSLLL $7,X1
+ PXOR X1,X14
+ PSRLL $25,X2
+ PXOR X2,X14
+ MOVOA X7,X1
+ PADDL X0,X1
+ MOVOA X1,X2
+ PSLLL $7,X1
+ PXOR X1,X11
+ PSRLL $25,X2
+ PXOR X2,X11
+ MOVOA X12,X1
+ PADDL X14,X1
+ MOVOA X1,X2
+ PSLLL $9,X1
+ PXOR X1,X15
+ PSRLL $23,X2
+ PXOR X2,X15
+ MOVOA X0,X1
+ PADDL X11,X1
+ MOVOA X1,X2
+ PSLLL $9,X1
+ PXOR X1,X9
+ PSRLL $23,X2
+ PXOR X2,X9
+ MOVOA X14,X1
+ PADDL X15,X1
+ MOVOA X1,X2
+ PSLLL $13,X1
+ PXOR X1,X13
+ PSRLL $19,X2
+ PXOR X2,X13
+ MOVOA X11,X1
+ PADDL X9,X1
+ MOVOA X1,X2
+ PSLLL $13,X1
+ PXOR X1,X7
+ PSRLL $19,X2
+ PXOR X2,X7
+ MOVOA X15,X1
+ PADDL X13,X1
+ MOVOA X1,X2
+ PSLLL $18,X1
+ PXOR X1,X12
+ PSRLL $14,X2
+ PXOR X2,X12
+ MOVOA 320(SP),X1
+ MOVOA X12,320(SP)
+ MOVOA X9,X2
+ PADDL X7,X2
+ MOVOA X2,X12
+ PSLLL $18,X2
+ PXOR X2,X0
+ PSRLL $14,X12
+ PXOR X12,X0
+ MOVOA X5,X2
+ PADDL X1,X2
+ MOVOA X2,X12
+ PSLLL $7,X2
+ PXOR X2,X3
+ PSRLL $25,X12
+ PXOR X12,X3
+ MOVOA 336(SP),X2
+ MOVOA X0,336(SP)
+ MOVOA X6,X0
+ PADDL X2,X0
+ MOVOA X0,X12
+ PSLLL $7,X0
+ PXOR X0,X4
+ PSRLL $25,X12
+ PXOR X12,X4
+ MOVOA X1,X0
+ PADDL X3,X0
+ MOVOA X0,X12
+ PSLLL $9,X0
+ PXOR X0,X10
+ PSRLL $23,X12
+ PXOR X12,X10
+ MOVOA X2,X0
+ PADDL X4,X0
+ MOVOA X0,X12
+ PSLLL $9,X0
+ PXOR X0,X8
+ PSRLL $23,X12
+ PXOR X12,X8
+ MOVOA X3,X0
+ PADDL X10,X0
+ MOVOA X0,X12
+ PSLLL $13,X0
+ PXOR X0,X5
+ PSRLL $19,X12
+ PXOR X12,X5
+ MOVOA X4,X0
+ PADDL X8,X0
+ MOVOA X0,X12
+ PSLLL $13,X0
+ PXOR X0,X6
+ PSRLL $19,X12
+ PXOR X12,X6
+ MOVOA X10,X0
+ PADDL X5,X0
+ MOVOA X0,X12
+ PSLLL $18,X0
+ PXOR X0,X1
+ PSRLL $14,X12
+ PXOR X12,X1
+ MOVOA 320(SP),X0
+ MOVOA X1,320(SP)
+ MOVOA X4,X1
+ PADDL X0,X1
+ MOVOA X1,X12
+ PSLLL $7,X1
+ PXOR X1,X7
+ PSRLL $25,X12
+ PXOR X12,X7
+ MOVOA X8,X1
+ PADDL X6,X1
+ MOVOA X1,X12
+ PSLLL $18,X1
+ PXOR X1,X2
+ PSRLL $14,X12
+ PXOR X12,X2
+ MOVOA 336(SP),X12
+ MOVOA X2,336(SP)
+ MOVOA X14,X1
+ PADDL X12,X1
+ MOVOA X1,X2
+ PSLLL $7,X1
+ PXOR X1,X5
+ PSRLL $25,X2
+ PXOR X2,X5
+ MOVOA X0,X1
+ PADDL X7,X1
+ MOVOA X1,X2
+ PSLLL $9,X1
+ PXOR X1,X10
+ PSRLL $23,X2
+ PXOR X2,X10
+ MOVOA X12,X1
+ PADDL X5,X1
+ MOVOA X1,X2
+ PSLLL $9,X1
+ PXOR X1,X8
+ PSRLL $23,X2
+ PXOR X2,X8
+ MOVOA X7,X1
+ PADDL X10,X1
+ MOVOA X1,X2
+ PSLLL $13,X1
+ PXOR X1,X4
+ PSRLL $19,X2
+ PXOR X2,X4
+ MOVOA X5,X1
+ PADDL X8,X1
+ MOVOA X1,X2
+ PSLLL $13,X1
+ PXOR X1,X14
+ PSRLL $19,X2
+ PXOR X2,X14
+ MOVOA X10,X1
+ PADDL X4,X1
+ MOVOA X1,X2
+ PSLLL $18,X1
+ PXOR X1,X0
+ PSRLL $14,X2
+ PXOR X2,X0
+ MOVOA 320(SP),X1
+ MOVOA X0,320(SP)
+ MOVOA X8,X0
+ PADDL X14,X0
+ MOVOA X0,X2
+ PSLLL $18,X0
+ PXOR X0,X12
+ PSRLL $14,X2
+ PXOR X2,X12
+ MOVOA X11,X0
+ PADDL X1,X0
+ MOVOA X0,X2
+ PSLLL $7,X0
+ PXOR X0,X6
+ PSRLL $25,X2
+ PXOR X2,X6
+ MOVOA 336(SP),X2
+ MOVOA X12,336(SP)
+ MOVOA X3,X0
+ PADDL X2,X0
+ MOVOA X0,X12
+ PSLLL $7,X0
+ PXOR X0,X13
+ PSRLL $25,X12
+ PXOR X12,X13
+ MOVOA X1,X0
+ PADDL X6,X0
+ MOVOA X0,X12
+ PSLLL $9,X0
+ PXOR X0,X15
+ PSRLL $23,X12
+ PXOR X12,X15
+ MOVOA X2,X0
+ PADDL X13,X0
+ MOVOA X0,X12
+ PSLLL $9,X0
+ PXOR X0,X9
+ PSRLL $23,X12
+ PXOR X12,X9
+ MOVOA X6,X0
+ PADDL X15,X0
+ MOVOA X0,X12
+ PSLLL $13,X0
+ PXOR X0,X11
+ PSRLL $19,X12
+ PXOR X12,X11
+ MOVOA X13,X0
+ PADDL X9,X0
+ MOVOA X0,X12
+ PSLLL $13,X0
+ PXOR X0,X3
+ PSRLL $19,X12
+ PXOR X12,X3
+ MOVOA X15,X0
+ PADDL X11,X0
+ MOVOA X0,X12
+ PSLLL $18,X0
+ PXOR X0,X1
+ PSRLL $14,X12
+ PXOR X12,X1
+ MOVOA X9,X0
+ PADDL X3,X0
+ MOVOA X0,X12
+ PSLLL $18,X0
+ PXOR X0,X2
+ PSRLL $14,X12
+ PXOR X12,X2
+ MOVOA 320(SP),X12
+ MOVOA 336(SP),X0
+ SUBQ $2,DX
+ JA MAINLOOP1
+ PADDL 112(SP),X12
+ PADDL 176(SP),X7
+ PADDL 224(SP),X10
+ PADDL 272(SP),X4
+ MOVD X12,DX
+ MOVD X7,CX
+ MOVD X10,R8
+ MOVD X4,R9
+ PSHUFL $0X39,X12,X12
+ PSHUFL $0X39,X7,X7
+ PSHUFL $0X39,X10,X10
+ PSHUFL $0X39,X4,X4
+ XORL 0(SI),DX
+ XORL 4(SI),CX
+ XORL 8(SI),R8
+ XORL 12(SI),R9
+ MOVL DX,0(DI)
+ MOVL CX,4(DI)
+ MOVL R8,8(DI)
+ MOVL R9,12(DI)
+ MOVD X12,DX
+ MOVD X7,CX
+ MOVD X10,R8
+ MOVD X4,R9
+ PSHUFL $0X39,X12,X12
+ PSHUFL $0X39,X7,X7
+ PSHUFL $0X39,X10,X10
+ PSHUFL $0X39,X4,X4
+ XORL 64(SI),DX
+ XORL 68(SI),CX
+ XORL 72(SI),R8
+ XORL 76(SI),R9
+ MOVL DX,64(DI)
+ MOVL CX,68(DI)
+ MOVL R8,72(DI)
+ MOVL R9,76(DI)
+ MOVD X12,DX
+ MOVD X7,CX
+ MOVD X10,R8
+ MOVD X4,R9
+ PSHUFL $0X39,X12,X12
+ PSHUFL $0X39,X7,X7
+ PSHUFL $0X39,X10,X10
+ PSHUFL $0X39,X4,X4
+ XORL 128(SI),DX
+ XORL 132(SI),CX
+ XORL 136(SI),R8
+ XORL 140(SI),R9
+ MOVL DX,128(DI)
+ MOVL CX,132(DI)
+ MOVL R8,136(DI)
+ MOVL R9,140(DI)
+ MOVD X12,DX
+ MOVD X7,CX
+ MOVD X10,R8
+ MOVD X4,R9
+ XORL 192(SI),DX
+ XORL 196(SI),CX
+ XORL 200(SI),R8
+ XORL 204(SI),R9
+ MOVL DX,192(DI)
+ MOVL CX,196(DI)
+ MOVL R8,200(DI)
+ MOVL R9,204(DI)
+ PADDL 240(SP),X14
+ PADDL 64(SP),X0
+ PADDL 128(SP),X5
+ PADDL 192(SP),X8
+ MOVD X14,DX
+ MOVD X0,CX
+ MOVD X5,R8
+ MOVD X8,R9
+ PSHUFL $0X39,X14,X14
+ PSHUFL $0X39,X0,X0
+ PSHUFL $0X39,X5,X5
+ PSHUFL $0X39,X8,X8
+ XORL 16(SI),DX
+ XORL 20(SI),CX
+ XORL 24(SI),R8
+ XORL 28(SI),R9
+ MOVL DX,16(DI)
+ MOVL CX,20(DI)
+ MOVL R8,24(DI)
+ MOVL R9,28(DI)
+ MOVD X14,DX
+ MOVD X0,CX
+ MOVD X5,R8
+ MOVD X8,R9
+ PSHUFL $0X39,X14,X14
+ PSHUFL $0X39,X0,X0
+ PSHUFL $0X39,X5,X5
+ PSHUFL $0X39,X8,X8
+ XORL 80(SI),DX
+ XORL 84(SI),CX
+ XORL 88(SI),R8
+ XORL 92(SI),R9
+ MOVL DX,80(DI)
+ MOVL CX,84(DI)
+ MOVL R8,88(DI)
+ MOVL R9,92(DI)
+ MOVD X14,DX
+ MOVD X0,CX
+ MOVD X5,R8
+ MOVD X8,R9
+ PSHUFL $0X39,X14,X14
+ PSHUFL $0X39,X0,X0
+ PSHUFL $0X39,X5,X5
+ PSHUFL $0X39,X8,X8
+ XORL 144(SI),DX
+ XORL 148(SI),CX
+ XORL 152(SI),R8
+ XORL 156(SI),R9
+ MOVL DX,144(DI)
+ MOVL CX,148(DI)
+ MOVL R8,152(DI)
+ MOVL R9,156(DI)
+ MOVD X14,DX
+ MOVD X0,CX
+ MOVD X5,R8
+ MOVD X8,R9
+ XORL 208(SI),DX
+ XORL 212(SI),CX
+ XORL 216(SI),R8
+ XORL 220(SI),R9
+ MOVL DX,208(DI)
+ MOVL CX,212(DI)
+ MOVL R8,216(DI)
+ MOVL R9,220(DI)
+ PADDL 288(SP),X15
+ PADDL 304(SP),X11
+ PADDL 80(SP),X1
+ PADDL 144(SP),X6
+ MOVD X15,DX
+ MOVD X11,CX
+ MOVD X1,R8
+ MOVD X6,R9
+ PSHUFL $0X39,X15,X15
+ PSHUFL $0X39,X11,X11
+ PSHUFL $0X39,X1,X1
+ PSHUFL $0X39,X6,X6
+ XORL 32(SI),DX
+ XORL 36(SI),CX
+ XORL 40(SI),R8
+ XORL 44(SI),R9
+ MOVL DX,32(DI)
+ MOVL CX,36(DI)
+ MOVL R8,40(DI)
+ MOVL R9,44(DI)
+ MOVD X15,DX
+ MOVD X11,CX
+ MOVD X1,R8
+ MOVD X6,R9
+ PSHUFL $0X39,X15,X15
+ PSHUFL $0X39,X11,X11
+ PSHUFL $0X39,X1,X1
+ PSHUFL $0X39,X6,X6
+ XORL 96(SI),DX
+ XORL 100(SI),CX
+ XORL 104(SI),R8
+ XORL 108(SI),R9
+ MOVL DX,96(DI)
+ MOVL CX,100(DI)
+ MOVL R8,104(DI)
+ MOVL R9,108(DI)
+ MOVD X15,DX
+ MOVD X11,CX
+ MOVD X1,R8
+ MOVD X6,R9
+ PSHUFL $0X39,X15,X15
+ PSHUFL $0X39,X11,X11
+ PSHUFL $0X39,X1,X1
+ PSHUFL $0X39,X6,X6
+ XORL 160(SI),DX
+ XORL 164(SI),CX
+ XORL 168(SI),R8
+ XORL 172(SI),R9
+ MOVL DX,160(DI)
+ MOVL CX,164(DI)
+ MOVL R8,168(DI)
+ MOVL R9,172(DI)
+ MOVD X15,DX
+ MOVD X11,CX
+ MOVD X1,R8
+ MOVD X6,R9
+ XORL 224(SI),DX
+ XORL 228(SI),CX
+ XORL 232(SI),R8
+ XORL 236(SI),R9
+ MOVL DX,224(DI)
+ MOVL CX,228(DI)
+ MOVL R8,232(DI)
+ MOVL R9,236(DI)
+ PADDL 160(SP),X13
+ PADDL 208(SP),X9
+ PADDL 256(SP),X3
+ PADDL 96(SP),X2
+ MOVD X13,DX
+ MOVD X9,CX
+ MOVD X3,R8
+ MOVD X2,R9
+ PSHUFL $0X39,X13,X13
+ PSHUFL $0X39,X9,X9
+ PSHUFL $0X39,X3,X3
+ PSHUFL $0X39,X2,X2
+ XORL 48(SI),DX
+ XORL 52(SI),CX
+ XORL 56(SI),R8
+ XORL 60(SI),R9
+ MOVL DX,48(DI)
+ MOVL CX,52(DI)
+ MOVL R8,56(DI)
+ MOVL R9,60(DI)
+ MOVD X13,DX
+ MOVD X9,CX
+ MOVD X3,R8
+ MOVD X2,R9
+ PSHUFL $0X39,X13,X13
+ PSHUFL $0X39,X9,X9
+ PSHUFL $0X39,X3,X3
+ PSHUFL $0X39,X2,X2
+ XORL 112(SI),DX
+ XORL 116(SI),CX
+ XORL 120(SI),R8
+ XORL 124(SI),R9
+ MOVL DX,112(DI)
+ MOVL CX,116(DI)
+ MOVL R8,120(DI)
+ MOVL R9,124(DI)
+ MOVD X13,DX
+ MOVD X9,CX
+ MOVD X3,R8
+ MOVD X2,R9
+ PSHUFL $0X39,X13,X13
+ PSHUFL $0X39,X9,X9
+ PSHUFL $0X39,X3,X3
+ PSHUFL $0X39,X2,X2
+ XORL 176(SI),DX
+ XORL 180(SI),CX
+ XORL 184(SI),R8
+ XORL 188(SI),R9
+ MOVL DX,176(DI)
+ MOVL CX,180(DI)
+ MOVL R8,184(DI)
+ MOVL R9,188(DI)
+ MOVD X13,DX
+ MOVD X9,CX
+ MOVD X3,R8
+ MOVD X2,R9
+ XORL 240(SI),DX
+ XORL 244(SI),CX
+ XORL 248(SI),R8
+ XORL 252(SI),R9
+ MOVL DX,240(DI)
+ MOVL CX,244(DI)
+ MOVL R8,248(DI)
+ MOVL R9,252(DI)
+ MOVQ 352(SP),R9
+ SUBQ $256,R9
+ ADDQ $256,SI
+ ADDQ $256,DI
+ CMPQ R9,$256
+ JAE BYTESATLEAST256
+ CMPQ R9,$0
+ JBE DONE
+ BYTESBETWEEN1AND255:
+ CMPQ R9,$64
+ JAE NOCOPY
+ MOVQ DI,DX
+ LEAQ 360(SP),DI
+ MOVQ R9,CX
+ REP; MOVSB
+ LEAQ 360(SP),DI
+ LEAQ 360(SP),SI
+ NOCOPY:
+ MOVQ R9,352(SP)
+ MOVOA 48(SP),X0
+ MOVOA 0(SP),X1
+ MOVOA 16(SP),X2
+ MOVOA 32(SP),X3
+ MOVOA X1,X4
+ MOVQ $20,CX
+ MAINLOOP2:
+ PADDL X0,X4
+ MOVOA X0,X5
+ MOVOA X4,X6
+ PSLLL $7,X4
+ PSRLL $25,X6
+ PXOR X4,X3
+ PXOR X6,X3
+ PADDL X3,X5
+ MOVOA X3,X4
+ MOVOA X5,X6
+ PSLLL $9,X5
+ PSRLL $23,X6
+ PXOR X5,X2
+ PSHUFL $0X93,X3,X3
+ PXOR X6,X2
+ PADDL X2,X4
+ MOVOA X2,X5
+ MOVOA X4,X6
+ PSLLL $13,X4
+ PSRLL $19,X6
+ PXOR X4,X1
+ PSHUFL $0X4E,X2,X2
+ PXOR X6,X1
+ PADDL X1,X5
+ MOVOA X3,X4
+ MOVOA X5,X6
+ PSLLL $18,X5
+ PSRLL $14,X6
+ PXOR X5,X0
+ PSHUFL $0X39,X1,X1
+ PXOR X6,X0
+ PADDL X0,X4
+ MOVOA X0,X5
+ MOVOA X4,X6
+ PSLLL $7,X4
+ PSRLL $25,X6
+ PXOR X4,X1
+ PXOR X6,X1
+ PADDL X1,X5
+ MOVOA X1,X4
+ MOVOA X5,X6
+ PSLLL $9,X5
+ PSRLL $23,X6
+ PXOR X5,X2
+ PSHUFL $0X93,X1,X1
+ PXOR X6,X2
+ PADDL X2,X4
+ MOVOA X2,X5
+ MOVOA X4,X6
+ PSLLL $13,X4
+ PSRLL $19,X6
+ PXOR X4,X3
+ PSHUFL $0X4E,X2,X2
+ PXOR X6,X3
+ PADDL X3,X5
+ MOVOA X1,X4
+ MOVOA X5,X6
+ PSLLL $18,X5
+ PSRLL $14,X6
+ PXOR X5,X0
+ PSHUFL $0X39,X3,X3
+ PXOR X6,X0
+ PADDL X0,X4
+ MOVOA X0,X5
+ MOVOA X4,X6
+ PSLLL $7,X4
+ PSRLL $25,X6
+ PXOR X4,X3
+ PXOR X6,X3
+ PADDL X3,X5
+ MOVOA X3,X4
+ MOVOA X5,X6
+ PSLLL $9,X5
+ PSRLL $23,X6
+ PXOR X5,X2
+ PSHUFL $0X93,X3,X3
+ PXOR X6,X2
+ PADDL X2,X4
+ MOVOA X2,X5
+ MOVOA X4,X6
+ PSLLL $13,X4
+ PSRLL $19,X6
+ PXOR X4,X1
+ PSHUFL $0X4E,X2,X2
+ PXOR X6,X1
+ PADDL X1,X5
+ MOVOA X3,X4
+ MOVOA X5,X6
+ PSLLL $18,X5
+ PSRLL $14,X6
+ PXOR X5,X0
+ PSHUFL $0X39,X1,X1
+ PXOR X6,X0
+ PADDL X0,X4
+ MOVOA X0,X5
+ MOVOA X4,X6
+ PSLLL $7,X4
+ PSRLL $25,X6
+ PXOR X4,X1
+ PXOR X6,X1
+ PADDL X1,X5
+ MOVOA X1,X4
+ MOVOA X5,X6
+ PSLLL $9,X5
+ PSRLL $23,X6
+ PXOR X5,X2
+ PSHUFL $0X93,X1,X1
+ PXOR X6,X2
+ PADDL X2,X4
+ MOVOA X2,X5
+ MOVOA X4,X6
+ PSLLL $13,X4
+ PSRLL $19,X6
+ PXOR X4,X3
+ PSHUFL $0X4E,X2,X2
+ PXOR X6,X3
+ SUBQ $4,CX
+ PADDL X3,X5
+ MOVOA X1,X4
+ MOVOA X5,X6
+ PSLLL $18,X5
+ PXOR X7,X7
+ PSRLL $14,X6
+ PXOR X5,X0
+ PSHUFL $0X39,X3,X3
+ PXOR X6,X0
+ JA MAINLOOP2
+ PADDL 48(SP),X0
+ PADDL 0(SP),X1
+ PADDL 16(SP),X2
+ PADDL 32(SP),X3
+ MOVD X0,CX
+ MOVD X1,R8
+ MOVD X2,R9
+ MOVD X3,AX
+ PSHUFL $0X39,X0,X0
+ PSHUFL $0X39,X1,X1
+ PSHUFL $0X39,X2,X2
+ PSHUFL $0X39,X3,X3
+ XORL 0(SI),CX
+ XORL 48(SI),R8
+ XORL 32(SI),R9
+ XORL 16(SI),AX
+ MOVL CX,0(DI)
+ MOVL R8,48(DI)
+ MOVL R9,32(DI)
+ MOVL AX,16(DI)
+ MOVD X0,CX
+ MOVD X1,R8
+ MOVD X2,R9
+ MOVD X3,AX
+ PSHUFL $0X39,X0,X0
+ PSHUFL $0X39,X1,X1
+ PSHUFL $0X39,X2,X2
+ PSHUFL $0X39,X3,X3
+ XORL 20(SI),CX
+ XORL 4(SI),R8
+ XORL 52(SI),R9
+ XORL 36(SI),AX
+ MOVL CX,20(DI)
+ MOVL R8,4(DI)
+ MOVL R9,52(DI)
+ MOVL AX,36(DI)
+ MOVD X0,CX
+ MOVD X1,R8
+ MOVD X2,R9
+ MOVD X3,AX
+ PSHUFL $0X39,X0,X0
+ PSHUFL $0X39,X1,X1
+ PSHUFL $0X39,X2,X2
+ PSHUFL $0X39,X3,X3
+ XORL 40(SI),CX
+ XORL 24(SI),R8
+ XORL 8(SI),R9
+ XORL 56(SI),AX
+ MOVL CX,40(DI)
+ MOVL R8,24(DI)
+ MOVL R9,8(DI)
+ MOVL AX,56(DI)
+ MOVD X0,CX
+ MOVD X1,R8
+ MOVD X2,R9
+ MOVD X3,AX
+ XORL 60(SI),CX
+ XORL 44(SI),R8
+ XORL 28(SI),R9
+ XORL 12(SI),AX
+ MOVL CX,60(DI)
+ MOVL R8,44(DI)
+ MOVL R9,28(DI)
+ MOVL AX,12(DI)
+ MOVQ 352(SP),R9
+ MOVL 16(SP),CX
+ MOVL 36 (SP),R8
+ ADDQ $1,CX
+ SHLQ $32,R8
+ ADDQ R8,CX
+ MOVQ CX,R8
+ SHRQ $32,R8
+ MOVL CX,16(SP)
+ MOVL R8, 36 (SP)
+ CMPQ R9,$64
+ JA BYTESATLEAST65
+ JAE BYTESATLEAST64
+ MOVQ DI,SI
+ MOVQ DX,DI
+ MOVQ R9,CX
+ REP; MOVSB
+ BYTESATLEAST64:
+ DONE:
+ MOVQ R12,SP
+ RET
+ BYTESATLEAST65:
+ SUBQ $64,R9
+ ADDQ $64,DI
+ ADDQ $64,SI
+ JMP BYTESBETWEEN1AND255
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/salsa20/salsa/salsa208.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/salsa20/salsa/salsa208.go
new file mode 100644
index 000000000..9bfc0927c
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/salsa20/salsa/salsa208.go
@@ -0,0 +1,199 @@
+// Copyright 2012 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 salsa
+
+// Core208 applies the Salsa20/8 core function to the 64-byte array in and puts
+// the result into the 64-byte array out. The input and output may be the same array.
+func Core208(out *[64]byte, in *[64]byte) {
+ j0 := uint32(in[0]) | uint32(in[1])<<8 | uint32(in[2])<<16 | uint32(in[3])<<24
+ j1 := uint32(in[4]) | uint32(in[5])<<8 | uint32(in[6])<<16 | uint32(in[7])<<24
+ j2 := uint32(in[8]) | uint32(in[9])<<8 | uint32(in[10])<<16 | uint32(in[11])<<24
+ j3 := uint32(in[12]) | uint32(in[13])<<8 | uint32(in[14])<<16 | uint32(in[15])<<24
+ j4 := uint32(in[16]) | uint32(in[17])<<8 | uint32(in[18])<<16 | uint32(in[19])<<24
+ j5 := uint32(in[20]) | uint32(in[21])<<8 | uint32(in[22])<<16 | uint32(in[23])<<24
+ j6 := uint32(in[24]) | uint32(in[25])<<8 | uint32(in[26])<<16 | uint32(in[27])<<24
+ j7 := uint32(in[28]) | uint32(in[29])<<8 | uint32(in[30])<<16 | uint32(in[31])<<24
+ j8 := uint32(in[32]) | uint32(in[33])<<8 | uint32(in[34])<<16 | uint32(in[35])<<24
+ j9 := uint32(in[36]) | uint32(in[37])<<8 | uint32(in[38])<<16 | uint32(in[39])<<24
+ j10 := uint32(in[40]) | uint32(in[41])<<8 | uint32(in[42])<<16 | uint32(in[43])<<24
+ j11 := uint32(in[44]) | uint32(in[45])<<8 | uint32(in[46])<<16 | uint32(in[47])<<24
+ j12 := uint32(in[48]) | uint32(in[49])<<8 | uint32(in[50])<<16 | uint32(in[51])<<24
+ j13 := uint32(in[52]) | uint32(in[53])<<8 | uint32(in[54])<<16 | uint32(in[55])<<24
+ j14 := uint32(in[56]) | uint32(in[57])<<8 | uint32(in[58])<<16 | uint32(in[59])<<24
+ j15 := uint32(in[60]) | uint32(in[61])<<8 | uint32(in[62])<<16 | uint32(in[63])<<24
+
+ x0, x1, x2, x3, x4, x5, x6, x7, x8 := j0, j1, j2, j3, j4, j5, j6, j7, j8
+ x9, x10, x11, x12, x13, x14, x15 := j9, j10, j11, j12, j13, j14, j15
+
+ for i := 0; i < 8; i += 2 {
+ u := x0 + x12
+ x4 ^= u<<7 | u>>(32-7)
+ u = x4 + x0
+ x8 ^= u<<9 | u>>(32-9)
+ u = x8 + x4
+ x12 ^= u<<13 | u>>(32-13)
+ u = x12 + x8
+ x0 ^= u<<18 | u>>(32-18)
+
+ u = x5 + x1
+ x9 ^= u<<7 | u>>(32-7)
+ u = x9 + x5
+ x13 ^= u<<9 | u>>(32-9)
+ u = x13 + x9
+ x1 ^= u<<13 | u>>(32-13)
+ u = x1 + x13
+ x5 ^= u<<18 | u>>(32-18)
+
+ u = x10 + x6
+ x14 ^= u<<7 | u>>(32-7)
+ u = x14 + x10
+ x2 ^= u<<9 | u>>(32-9)
+ u = x2 + x14
+ x6 ^= u<<13 | u>>(32-13)
+ u = x6 + x2
+ x10 ^= u<<18 | u>>(32-18)
+
+ u = x15 + x11
+ x3 ^= u<<7 | u>>(32-7)
+ u = x3 + x15
+ x7 ^= u<<9 | u>>(32-9)
+ u = x7 + x3
+ x11 ^= u<<13 | u>>(32-13)
+ u = x11 + x7
+ x15 ^= u<<18 | u>>(32-18)
+
+ u = x0 + x3
+ x1 ^= u<<7 | u>>(32-7)
+ u = x1 + x0
+ x2 ^= u<<9 | u>>(32-9)
+ u = x2 + x1
+ x3 ^= u<<13 | u>>(32-13)
+ u = x3 + x2
+ x0 ^= u<<18 | u>>(32-18)
+
+ u = x5 + x4
+ x6 ^= u<<7 | u>>(32-7)
+ u = x6 + x5
+ x7 ^= u<<9 | u>>(32-9)
+ u = x7 + x6
+ x4 ^= u<<13 | u>>(32-13)
+ u = x4 + x7
+ x5 ^= u<<18 | u>>(32-18)
+
+ u = x10 + x9
+ x11 ^= u<<7 | u>>(32-7)
+ u = x11 + x10
+ x8 ^= u<<9 | u>>(32-9)
+ u = x8 + x11
+ x9 ^= u<<13 | u>>(32-13)
+ u = x9 + x8
+ x10 ^= u<<18 | u>>(32-18)
+
+ u = x15 + x14
+ x12 ^= u<<7 | u>>(32-7)
+ u = x12 + x15
+ x13 ^= u<<9 | u>>(32-9)
+ u = x13 + x12
+ x14 ^= u<<13 | u>>(32-13)
+ u = x14 + x13
+ x15 ^= u<<18 | u>>(32-18)
+ }
+ x0 += j0
+ x1 += j1
+ x2 += j2
+ x3 += j3
+ x4 += j4
+ x5 += j5
+ x6 += j6
+ x7 += j7
+ x8 += j8
+ x9 += j9
+ x10 += j10
+ x11 += j11
+ x12 += j12
+ x13 += j13
+ x14 += j14
+ x15 += j15
+
+ out[0] = byte(x0)
+ out[1] = byte(x0 >> 8)
+ out[2] = byte(x0 >> 16)
+ out[3] = byte(x0 >> 24)
+
+ out[4] = byte(x1)
+ out[5] = byte(x1 >> 8)
+ out[6] = byte(x1 >> 16)
+ out[7] = byte(x1 >> 24)
+
+ out[8] = byte(x2)
+ out[9] = byte(x2 >> 8)
+ out[10] = byte(x2 >> 16)
+ out[11] = byte(x2 >> 24)
+
+ out[12] = byte(x3)
+ out[13] = byte(x3 >> 8)
+ out[14] = byte(x3 >> 16)
+ out[15] = byte(x3 >> 24)
+
+ out[16] = byte(x4)
+ out[17] = byte(x4 >> 8)
+ out[18] = byte(x4 >> 16)
+ out[19] = byte(x4 >> 24)
+
+ out[20] = byte(x5)
+ out[21] = byte(x5 >> 8)
+ out[22] = byte(x5 >> 16)
+ out[23] = byte(x5 >> 24)
+
+ out[24] = byte(x6)
+ out[25] = byte(x6 >> 8)
+ out[26] = byte(x6 >> 16)
+ out[27] = byte(x6 >> 24)
+
+ out[28] = byte(x7)
+ out[29] = byte(x7 >> 8)
+ out[30] = byte(x7 >> 16)
+ out[31] = byte(x7 >> 24)
+
+ out[32] = byte(x8)
+ out[33] = byte(x8 >> 8)
+ out[34] = byte(x8 >> 16)
+ out[35] = byte(x8 >> 24)
+
+ out[36] = byte(x9)
+ out[37] = byte(x9 >> 8)
+ out[38] = byte(x9 >> 16)
+ out[39] = byte(x9 >> 24)
+
+ out[40] = byte(x10)
+ out[41] = byte(x10 >> 8)
+ out[42] = byte(x10 >> 16)
+ out[43] = byte(x10 >> 24)
+
+ out[44] = byte(x11)
+ out[45] = byte(x11 >> 8)
+ out[46] = byte(x11 >> 16)
+ out[47] = byte(x11 >> 24)
+
+ out[48] = byte(x12)
+ out[49] = byte(x12 >> 8)
+ out[50] = byte(x12 >> 16)
+ out[51] = byte(x12 >> 24)
+
+ out[52] = byte(x13)
+ out[53] = byte(x13 >> 8)
+ out[54] = byte(x13 >> 16)
+ out[55] = byte(x13 >> 24)
+
+ out[56] = byte(x14)
+ out[57] = byte(x14 >> 8)
+ out[58] = byte(x14 >> 16)
+ out[59] = byte(x14 >> 24)
+
+ out[60] = byte(x15)
+ out[61] = byte(x15 >> 8)
+ out[62] = byte(x15 >> 16)
+ out[63] = byte(x15 >> 24)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.go
new file mode 100644
index 000000000..f9269c384
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.go
@@ -0,0 +1,24 @@
+// Copyright 2012 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.
+
+// +build amd64,!appengine,!gccgo
+
+package salsa
+
+// This function is implemented in salsa2020_amd64.s.
+
+//go:noescape
+
+func salsa2020XORKeyStream(out, in *byte, n uint64, nonce, key *byte)
+
+// XORKeyStream crypts bytes from in to out using the given key and counters.
+// In and out must overlap entirely or not at all. Counter
+// contains the raw salsa20 counter bytes (both nonce and block counter).
+func XORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) {
+ if len(in) == 0 {
+ return
+ }
+ _ = out[len(in)-1]
+ salsa2020XORKeyStream(&out[0], &in[0], uint64(len(in)), &counter[0], &key[0])
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_ref.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_ref.go
new file mode 100644
index 000000000..22126d17c
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_ref.go
@@ -0,0 +1,234 @@
+// Copyright 2012 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.
+
+// +build !amd64 appengine gccgo
+
+package salsa
+
+const rounds = 20
+
+// core applies the Salsa20 core function to 16-byte input in, 32-byte key k,
+// and 16-byte constant c, and puts the result into 64-byte array out.
+func core(out *[64]byte, in *[16]byte, k *[32]byte, c *[16]byte) {
+ j0 := uint32(c[0]) | uint32(c[1])<<8 | uint32(c[2])<<16 | uint32(c[3])<<24
+ j1 := uint32(k[0]) | uint32(k[1])<<8 | uint32(k[2])<<16 | uint32(k[3])<<24
+ j2 := uint32(k[4]) | uint32(k[5])<<8 | uint32(k[6])<<16 | uint32(k[7])<<24
+ j3 := uint32(k[8]) | uint32(k[9])<<8 | uint32(k[10])<<16 | uint32(k[11])<<24
+ j4 := uint32(k[12]) | uint32(k[13])<<8 | uint32(k[14])<<16 | uint32(k[15])<<24
+ j5 := uint32(c[4]) | uint32(c[5])<<8 | uint32(c[6])<<16 | uint32(c[7])<<24
+ j6 := uint32(in[0]) | uint32(in[1])<<8 | uint32(in[2])<<16 | uint32(in[3])<<24
+ j7 := uint32(in[4]) | uint32(in[5])<<8 | uint32(in[6])<<16 | uint32(in[7])<<24
+ j8 := uint32(in[8]) | uint32(in[9])<<8 | uint32(in[10])<<16 | uint32(in[11])<<24
+ j9 := uint32(in[12]) | uint32(in[13])<<8 | uint32(in[14])<<16 | uint32(in[15])<<24
+ j10 := uint32(c[8]) | uint32(c[9])<<8 | uint32(c[10])<<16 | uint32(c[11])<<24
+ j11 := uint32(k[16]) | uint32(k[17])<<8 | uint32(k[18])<<16 | uint32(k[19])<<24
+ j12 := uint32(k[20]) | uint32(k[21])<<8 | uint32(k[22])<<16 | uint32(k[23])<<24
+ j13 := uint32(k[24]) | uint32(k[25])<<8 | uint32(k[26])<<16 | uint32(k[27])<<24
+ j14 := uint32(k[28]) | uint32(k[29])<<8 | uint32(k[30])<<16 | uint32(k[31])<<24
+ j15 := uint32(c[12]) | uint32(c[13])<<8 | uint32(c[14])<<16 | uint32(c[15])<<24
+
+ x0, x1, x2, x3, x4, x5, x6, x7, x8 := j0, j1, j2, j3, j4, j5, j6, j7, j8
+ x9, x10, x11, x12, x13, x14, x15 := j9, j10, j11, j12, j13, j14, j15
+
+ for i := 0; i < rounds; i += 2 {
+ u := x0 + x12
+ x4 ^= u<<7 | u>>(32-7)
+ u = x4 + x0
+ x8 ^= u<<9 | u>>(32-9)
+ u = x8 + x4
+ x12 ^= u<<13 | u>>(32-13)
+ u = x12 + x8
+ x0 ^= u<<18 | u>>(32-18)
+
+ u = x5 + x1
+ x9 ^= u<<7 | u>>(32-7)
+ u = x9 + x5
+ x13 ^= u<<9 | u>>(32-9)
+ u = x13 + x9
+ x1 ^= u<<13 | u>>(32-13)
+ u = x1 + x13
+ x5 ^= u<<18 | u>>(32-18)
+
+ u = x10 + x6
+ x14 ^= u<<7 | u>>(32-7)
+ u = x14 + x10
+ x2 ^= u<<9 | u>>(32-9)
+ u = x2 + x14
+ x6 ^= u<<13 | u>>(32-13)
+ u = x6 + x2
+ x10 ^= u<<18 | u>>(32-18)
+
+ u = x15 + x11
+ x3 ^= u<<7 | u>>(32-7)
+ u = x3 + x15
+ x7 ^= u<<9 | u>>(32-9)
+ u = x7 + x3
+ x11 ^= u<<13 | u>>(32-13)
+ u = x11 + x7
+ x15 ^= u<<18 | u>>(32-18)
+
+ u = x0 + x3
+ x1 ^= u<<7 | u>>(32-7)
+ u = x1 + x0
+ x2 ^= u<<9 | u>>(32-9)
+ u = x2 + x1
+ x3 ^= u<<13 | u>>(32-13)
+ u = x3 + x2
+ x0 ^= u<<18 | u>>(32-18)
+
+ u = x5 + x4
+ x6 ^= u<<7 | u>>(32-7)
+ u = x6 + x5
+ x7 ^= u<<9 | u>>(32-9)
+ u = x7 + x6
+ x4 ^= u<<13 | u>>(32-13)
+ u = x4 + x7
+ x5 ^= u<<18 | u>>(32-18)
+
+ u = x10 + x9
+ x11 ^= u<<7 | u>>(32-7)
+ u = x11 + x10
+ x8 ^= u<<9 | u>>(32-9)
+ u = x8 + x11
+ x9 ^= u<<13 | u>>(32-13)
+ u = x9 + x8
+ x10 ^= u<<18 | u>>(32-18)
+
+ u = x15 + x14
+ x12 ^= u<<7 | u>>(32-7)
+ u = x12 + x15
+ x13 ^= u<<9 | u>>(32-9)
+ u = x13 + x12
+ x14 ^= u<<13 | u>>(32-13)
+ u = x14 + x13
+ x15 ^= u<<18 | u>>(32-18)
+ }
+ x0 += j0
+ x1 += j1
+ x2 += j2
+ x3 += j3
+ x4 += j4
+ x5 += j5
+ x6 += j6
+ x7 += j7
+ x8 += j8
+ x9 += j9
+ x10 += j10
+ x11 += j11
+ x12 += j12
+ x13 += j13
+ x14 += j14
+ x15 += j15
+
+ out[0] = byte(x0)
+ out[1] = byte(x0 >> 8)
+ out[2] = byte(x0 >> 16)
+ out[3] = byte(x0 >> 24)
+
+ out[4] = byte(x1)
+ out[5] = byte(x1 >> 8)
+ out[6] = byte(x1 >> 16)
+ out[7] = byte(x1 >> 24)
+
+ out[8] = byte(x2)
+ out[9] = byte(x2 >> 8)
+ out[10] = byte(x2 >> 16)
+ out[11] = byte(x2 >> 24)
+
+ out[12] = byte(x3)
+ out[13] = byte(x3 >> 8)
+ out[14] = byte(x3 >> 16)
+ out[15] = byte(x3 >> 24)
+
+ out[16] = byte(x4)
+ out[17] = byte(x4 >> 8)
+ out[18] = byte(x4 >> 16)
+ out[19] = byte(x4 >> 24)
+
+ out[20] = byte(x5)
+ out[21] = byte(x5 >> 8)
+ out[22] = byte(x5 >> 16)
+ out[23] = byte(x5 >> 24)
+
+ out[24] = byte(x6)
+ out[25] = byte(x6 >> 8)
+ out[26] = byte(x6 >> 16)
+ out[27] = byte(x6 >> 24)
+
+ out[28] = byte(x7)
+ out[29] = byte(x7 >> 8)
+ out[30] = byte(x7 >> 16)
+ out[31] = byte(x7 >> 24)
+
+ out[32] = byte(x8)
+ out[33] = byte(x8 >> 8)
+ out[34] = byte(x8 >> 16)
+ out[35] = byte(x8 >> 24)
+
+ out[36] = byte(x9)
+ out[37] = byte(x9 >> 8)
+ out[38] = byte(x9 >> 16)
+ out[39] = byte(x9 >> 24)
+
+ out[40] = byte(x10)
+ out[41] = byte(x10 >> 8)
+ out[42] = byte(x10 >> 16)
+ out[43] = byte(x10 >> 24)
+
+ out[44] = byte(x11)
+ out[45] = byte(x11 >> 8)
+ out[46] = byte(x11 >> 16)
+ out[47] = byte(x11 >> 24)
+
+ out[48] = byte(x12)
+ out[49] = byte(x12 >> 8)
+ out[50] = byte(x12 >> 16)
+ out[51] = byte(x12 >> 24)
+
+ out[52] = byte(x13)
+ out[53] = byte(x13 >> 8)
+ out[54] = byte(x13 >> 16)
+ out[55] = byte(x13 >> 24)
+
+ out[56] = byte(x14)
+ out[57] = byte(x14 >> 8)
+ out[58] = byte(x14 >> 16)
+ out[59] = byte(x14 >> 24)
+
+ out[60] = byte(x15)
+ out[61] = byte(x15 >> 8)
+ out[62] = byte(x15 >> 16)
+ out[63] = byte(x15 >> 24)
+}
+
+// XORKeyStream crypts bytes from in to out using the given key and counters.
+// In and out must overlap entirely or not at all. Counter
+// contains the raw salsa20 counter bytes (both nonce and block counter).
+func XORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) {
+ var block [64]byte
+ var counterCopy [16]byte
+ copy(counterCopy[:], counter[:])
+
+ for len(in) >= 64 {
+ core(&block, &counterCopy, key, &Sigma)
+ for i, x := range block {
+ out[i] = in[i] ^ x
+ }
+ u := uint32(1)
+ for i := 8; i < 16; i++ {
+ u += uint32(counterCopy[i])
+ counterCopy[i] = byte(u)
+ u >>= 8
+ }
+ in = in[64:]
+ out = out[64:]
+ }
+
+ if len(in) > 0 {
+ core(&block, &counterCopy, key, &Sigma)
+ for i, v := range in {
+ out[i] = v ^ block[i]
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/salsa20/salsa/salsa_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/salsa20/salsa/salsa_test.go
new file mode 100644
index 000000000..f67e94eba
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/salsa20/salsa/salsa_test.go
@@ -0,0 +1,54 @@
+// Copyright 2012 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 salsa
+
+import "testing"
+
+func TestCore208(t *testing.T) {
+ in := [64]byte{
+ 0x7e, 0x87, 0x9a, 0x21, 0x4f, 0x3e, 0xc9, 0x86,
+ 0x7c, 0xa9, 0x40, 0xe6, 0x41, 0x71, 0x8f, 0x26,
+ 0xba, 0xee, 0x55, 0x5b, 0x8c, 0x61, 0xc1, 0xb5,
+ 0x0d, 0xf8, 0x46, 0x11, 0x6d, 0xcd, 0x3b, 0x1d,
+ 0xee, 0x24, 0xf3, 0x19, 0xdf, 0x9b, 0x3d, 0x85,
+ 0x14, 0x12, 0x1e, 0x4b, 0x5a, 0xc5, 0xaa, 0x32,
+ 0x76, 0x02, 0x1d, 0x29, 0x09, 0xc7, 0x48, 0x29,
+ 0xed, 0xeb, 0xc6, 0x8d, 0xb8, 0xb8, 0xc2, 0x5e}
+
+ out := [64]byte{
+ 0xa4, 0x1f, 0x85, 0x9c, 0x66, 0x08, 0xcc, 0x99,
+ 0x3b, 0x81, 0xca, 0xcb, 0x02, 0x0c, 0xef, 0x05,
+ 0x04, 0x4b, 0x21, 0x81, 0xa2, 0xfd, 0x33, 0x7d,
+ 0xfd, 0x7b, 0x1c, 0x63, 0x96, 0x68, 0x2f, 0x29,
+ 0xb4, 0x39, 0x31, 0x68, 0xe3, 0xc9, 0xe6, 0xbc,
+ 0xfe, 0x6b, 0xc5, 0xb7, 0xa0, 0x6d, 0x96, 0xba,
+ 0xe4, 0x24, 0xcc, 0x10, 0x2c, 0x91, 0x74, 0x5c,
+ 0x24, 0xad, 0x67, 0x3d, 0xc7, 0x61, 0x8f, 0x81,
+ }
+
+ Core208(&in, &in)
+ if in != out {
+ t.Errorf("expected %x, got %x", out, in)
+ }
+}
+
+func TestOutOfBoundsWrite(t *testing.T) {
+ // encrypted "0123456789"
+ cipherText := []byte{170, 166, 196, 104, 175, 121, 68, 44, 174, 51}
+ var counter [16]byte
+ var key [32]byte
+ want := "abcdefghij"
+ plainText := []byte(want)
+ defer func() {
+ err := recover()
+ if err == nil {
+ t.Error("XORKeyStream expected to panic on len(dst) < len(src), but didn't")
+ }
+ if plainText[3] == '3' {
+ t.Errorf("XORKeyStream did out of bounds write, want %v, got %v", want, string(plainText))
+ }
+ }()
+ XORKeyStream(plainText[:3], cipherText, &counter, &key)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/salsa20/salsa20.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/salsa20/salsa20.go
new file mode 100644
index 000000000..0ee62485a
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/salsa20/salsa20.go
@@ -0,0 +1,54 @@
+// Copyright 2012 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 salsa20 implements the Salsa20 stream cipher as specified in https://cr.yp.to/snuffle/spec.pdf.
+
+Salsa20 differs from many other stream ciphers in that it is message orientated
+rather than byte orientated. Keystream blocks are not preserved between calls,
+therefore each side must encrypt/decrypt data with the same segmentation.
+
+Another aspect of this difference is that part of the counter is exposed as
+a nonce in each call. Encrypting two different messages with the same (key,
+nonce) pair leads to trivial plaintext recovery. This is analogous to
+encrypting two different messages with the same key with a traditional stream
+cipher.
+
+This package also implements XSalsa20: a version of Salsa20 with a 24-byte
+nonce as specified in https://cr.yp.to/snuffle/xsalsa-20081128.pdf. Simply
+passing a 24-byte slice as the nonce triggers XSalsa20.
+*/
+package salsa20 // import "golang.org/x/crypto/salsa20"
+
+// TODO(agl): implement XORKeyStream12 and XORKeyStream8 - the reduced round variants of Salsa20.
+
+import (
+ "golang.org/x/crypto/salsa20/salsa"
+)
+
+// XORKeyStream crypts bytes from in to out using the given key and nonce.
+// In and out must overlap entirely or not at all. Nonce must
+// be either 8 or 24 bytes long.
+func XORKeyStream(out, in []byte, nonce []byte, key *[32]byte) {
+ if len(out) < len(in) {
+ in = in[:len(out)]
+ }
+
+ var subNonce [16]byte
+
+ if len(nonce) == 24 {
+ var subKey [32]byte
+ var hNonce [16]byte
+ copy(hNonce[:], nonce[:16])
+ salsa.HSalsa20(&subKey, &hNonce, key, &salsa.Sigma)
+ copy(subNonce[:], nonce[16:])
+ key = &subKey
+ } else if len(nonce) == 8 {
+ copy(subNonce[:], nonce[:])
+ } else {
+ panic("salsa20: nonce must be 8 or 24 bytes")
+ }
+
+ salsa.XORKeyStream(out, in, &subNonce, key)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/salsa20/salsa20_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/salsa20/salsa20_test.go
new file mode 100644
index 000000000..0ef3328eb
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/salsa20/salsa20_test.go
@@ -0,0 +1,139 @@
+// Copyright 2012 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 salsa20
+
+import (
+ "bytes"
+ "encoding/hex"
+ "testing"
+)
+
+func fromHex(s string) []byte {
+ ret, err := hex.DecodeString(s)
+ if err != nil {
+ panic(err)
+ }
+ return ret
+}
+
+// testVectors was taken from set 6 of the ECRYPT test vectors:
+// http://www.ecrypt.eu.org/stream/svn/viewcvs.cgi/ecrypt/trunk/submissions/salsa20/full/verified.test-vectors?logsort=rev&rev=210&view=markup
+var testVectors = []struct {
+ key []byte
+ iv []byte
+ numBytes int
+ xor []byte
+}{
+ {
+ fromHex("0053A6F94C9FF24598EB3E91E4378ADD3083D6297CCF2275C81B6EC11467BA0D"),
+ fromHex("0D74DB42A91077DE"),
+ 131072,
+ fromHex("C349B6A51A3EC9B712EAED3F90D8BCEE69B7628645F251A996F55260C62EF31FD6C6B0AEA94E136C9D984AD2DF3578F78E457527B03A0450580DD874F63B1AB9"),
+ },
+ {
+ fromHex("0558ABFE51A4F74A9DF04396E93C8FE23588DB2E81D4277ACD2073C6196CBF12"),
+ fromHex("167DE44BB21980E7"),
+ 131072,
+ fromHex("C3EAAF32836BACE32D04E1124231EF47E101367D6305413A0EEB07C60698A2876E4D031870A739D6FFDDD208597AFF0A47AC17EDB0167DD67EBA84F1883D4DFD"),
+ },
+ {
+ fromHex("0A5DB00356A9FC4FA2F5489BEE4194E73A8DE03386D92C7FD22578CB1E71C417"),
+ fromHex("1F86ED54BB2289F0"),
+ 131072,
+ fromHex("3CD23C3DC90201ACC0CF49B440B6C417F0DC8D8410A716D5314C059E14B1A8D9A9FB8EA3D9C8DAE12B21402F674AA95C67B1FC514E994C9D3F3A6E41DFF5BBA6"),
+ },
+ {
+ fromHex("0F62B5085BAE0154A7FA4DA0F34699EC3F92E5388BDE3184D72A7DD02376C91C"),
+ fromHex("288FF65DC42B92F9"),
+ 131072,
+ fromHex("E00EBCCD70D69152725F9987982178A2E2E139C7BCBE04CA8A0E99E318D9AB76F988C8549F75ADD790BA4F81C176DA653C1A043F11A958E169B6D2319F4EEC1A"),
+ },
+}
+
+func TestSalsa20(t *testing.T) {
+ var inBuf, outBuf []byte
+ var key [32]byte
+
+ for i, test := range testVectors {
+ if test.numBytes%64 != 0 {
+ t.Errorf("#%d: numBytes is not a multiple of 64", i)
+ continue
+ }
+
+ if test.numBytes > len(inBuf) {
+ inBuf = make([]byte, test.numBytes)
+ outBuf = make([]byte, test.numBytes)
+ }
+ in := inBuf[:test.numBytes]
+ out := outBuf[:test.numBytes]
+ copy(key[:], test.key)
+ XORKeyStream(out, in, test.iv, &key)
+
+ var xor [64]byte
+ for len(out) > 0 {
+ for i := 0; i < 64; i++ {
+ xor[i] ^= out[i]
+ }
+ out = out[64:]
+ }
+
+ if !bytes.Equal(xor[:], test.xor) {
+ t.Errorf("#%d: bad result", i)
+ }
+ }
+}
+
+var xSalsa20TestData = []struct {
+ in, nonce, key, out []byte
+}{
+ {
+ []byte("Hello world!"),
+ []byte("24-byte nonce for xsalsa"),
+ []byte("this is 32-byte key for xsalsa20"),
+ []byte{0x00, 0x2d, 0x45, 0x13, 0x84, 0x3f, 0xc2, 0x40, 0xc4, 0x01, 0xe5, 0x41},
+ },
+ {
+ make([]byte, 64),
+ []byte("24-byte nonce for xsalsa"),
+ []byte("this is 32-byte key for xsalsa20"),
+ []byte{0x48, 0x48, 0x29, 0x7f, 0xeb, 0x1f, 0xb5, 0x2f, 0xb6,
+ 0x6d, 0x81, 0x60, 0x9b, 0xd5, 0x47, 0xfa, 0xbc, 0xbe, 0x70,
+ 0x26, 0xed, 0xc8, 0xb5, 0xe5, 0xe4, 0x49, 0xd0, 0x88, 0xbf,
+ 0xa6, 0x9c, 0x08, 0x8f, 0x5d, 0x8d, 0xa1, 0xd7, 0x91, 0x26,
+ 0x7c, 0x2c, 0x19, 0x5a, 0x7f, 0x8c, 0xae, 0x9c, 0x4b, 0x40,
+ 0x50, 0xd0, 0x8c, 0xe6, 0xd3, 0xa1, 0x51, 0xec, 0x26, 0x5f,
+ 0x3a, 0x58, 0xe4, 0x76, 0x48},
+ },
+}
+
+func TestXSalsa20(t *testing.T) {
+ var key [32]byte
+
+ for i, test := range xSalsa20TestData {
+ out := make([]byte, len(test.in))
+ copy(key[:], test.key)
+ XORKeyStream(out, test.in, test.nonce, &key)
+ if !bytes.Equal(out, test.out) {
+ t.Errorf("%d: expected %x, got %x", i, test.out, out)
+ }
+ }
+}
+
+var (
+ keyArray [32]byte
+ key = &keyArray
+ nonce [8]byte
+ msg = make([]byte, 1<<10)
+)
+
+func BenchmarkXOR1K(b *testing.B) {
+ b.StopTimer()
+ out := make([]byte, 1024)
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ XORKeyStream(out, msg[:1024], nonce[:], key)
+ }
+ b.SetBytes(1024)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/scrypt/example_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/scrypt/example_test.go
new file mode 100644
index 000000000..6736479b1
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/scrypt/example_test.go
@@ -0,0 +1,26 @@
+// 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 scrypt_test
+
+import (
+ "encoding/base64"
+ "fmt"
+ "log"
+
+ "golang.org/x/crypto/scrypt"
+)
+
+func Example() {
+ // DO NOT use this salt value; generate your own random salt. 8 bytes is
+ // a good length.
+ salt := []byte{0xc8, 0x28, 0xf2, 0x58, 0xa7, 0x6a, 0xad, 0x7b}
+
+ dk, err := scrypt.Key([]byte("some password"), salt, 1<<15, 8, 1, 32)
+ if err != nil {
+ log.Fatal(err)
+ }
+ fmt.Println(base64.StdEncoding.EncodeToString(dk))
+ // Output: lGnMz8io0AUkfzn6Pls1qX20Vs7PGN6sbYQ2TQgY12M=
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/scrypt/scrypt.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/scrypt/scrypt.go
new file mode 100644
index 000000000..ff28aaef6
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/scrypt/scrypt.go
@@ -0,0 +1,244 @@
+// Copyright 2012 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 scrypt implements the scrypt key derivation function as defined in
+// Colin Percival's paper "Stronger Key Derivation via Sequential Memory-Hard
+// Functions" (https://www.tarsnap.com/scrypt/scrypt.pdf).
+package scrypt // import "golang.org/x/crypto/scrypt"
+
+import (
+ "crypto/sha256"
+ "errors"
+
+ "golang.org/x/crypto/pbkdf2"
+)
+
+const maxInt = int(^uint(0) >> 1)
+
+// blockCopy copies n numbers from src into dst.
+func blockCopy(dst, src []uint32, n int) {
+ copy(dst, src[:n])
+}
+
+// blockXOR XORs numbers from dst with n numbers from src.
+func blockXOR(dst, src []uint32, n int) {
+ for i, v := range src[:n] {
+ dst[i] ^= v
+ }
+}
+
+// salsaXOR applies Salsa20/8 to the XOR of 16 numbers from tmp and in,
+// and puts the result into both both tmp and out.
+func salsaXOR(tmp *[16]uint32, in, out []uint32) {
+ w0 := tmp[0] ^ in[0]
+ w1 := tmp[1] ^ in[1]
+ w2 := tmp[2] ^ in[2]
+ w3 := tmp[3] ^ in[3]
+ w4 := tmp[4] ^ in[4]
+ w5 := tmp[5] ^ in[5]
+ w6 := tmp[6] ^ in[6]
+ w7 := tmp[7] ^ in[7]
+ w8 := tmp[8] ^ in[8]
+ w9 := tmp[9] ^ in[9]
+ w10 := tmp[10] ^ in[10]
+ w11 := tmp[11] ^ in[11]
+ w12 := tmp[12] ^ in[12]
+ w13 := tmp[13] ^ in[13]
+ w14 := tmp[14] ^ in[14]
+ w15 := tmp[15] ^ in[15]
+
+ x0, x1, x2, x3, x4, x5, x6, x7, x8 := w0, w1, w2, w3, w4, w5, w6, w7, w8
+ x9, x10, x11, x12, x13, x14, x15 := w9, w10, w11, w12, w13, w14, w15
+
+ for i := 0; i < 8; i += 2 {
+ u := x0 + x12
+ x4 ^= u<<7 | u>>(32-7)
+ u = x4 + x0
+ x8 ^= u<<9 | u>>(32-9)
+ u = x8 + x4
+ x12 ^= u<<13 | u>>(32-13)
+ u = x12 + x8
+ x0 ^= u<<18 | u>>(32-18)
+
+ u = x5 + x1
+ x9 ^= u<<7 | u>>(32-7)
+ u = x9 + x5
+ x13 ^= u<<9 | u>>(32-9)
+ u = x13 + x9
+ x1 ^= u<<13 | u>>(32-13)
+ u = x1 + x13
+ x5 ^= u<<18 | u>>(32-18)
+
+ u = x10 + x6
+ x14 ^= u<<7 | u>>(32-7)
+ u = x14 + x10
+ x2 ^= u<<9 | u>>(32-9)
+ u = x2 + x14
+ x6 ^= u<<13 | u>>(32-13)
+ u = x6 + x2
+ x10 ^= u<<18 | u>>(32-18)
+
+ u = x15 + x11
+ x3 ^= u<<7 | u>>(32-7)
+ u = x3 + x15
+ x7 ^= u<<9 | u>>(32-9)
+ u = x7 + x3
+ x11 ^= u<<13 | u>>(32-13)
+ u = x11 + x7
+ x15 ^= u<<18 | u>>(32-18)
+
+ u = x0 + x3
+ x1 ^= u<<7 | u>>(32-7)
+ u = x1 + x0
+ x2 ^= u<<9 | u>>(32-9)
+ u = x2 + x1
+ x3 ^= u<<13 | u>>(32-13)
+ u = x3 + x2
+ x0 ^= u<<18 | u>>(32-18)
+
+ u = x5 + x4
+ x6 ^= u<<7 | u>>(32-7)
+ u = x6 + x5
+ x7 ^= u<<9 | u>>(32-9)
+ u = x7 + x6
+ x4 ^= u<<13 | u>>(32-13)
+ u = x4 + x7
+ x5 ^= u<<18 | u>>(32-18)
+
+ u = x10 + x9
+ x11 ^= u<<7 | u>>(32-7)
+ u = x11 + x10
+ x8 ^= u<<9 | u>>(32-9)
+ u = x8 + x11
+ x9 ^= u<<13 | u>>(32-13)
+ u = x9 + x8
+ x10 ^= u<<18 | u>>(32-18)
+
+ u = x15 + x14
+ x12 ^= u<<7 | u>>(32-7)
+ u = x12 + x15
+ x13 ^= u<<9 | u>>(32-9)
+ u = x13 + x12
+ x14 ^= u<<13 | u>>(32-13)
+ u = x14 + x13
+ x15 ^= u<<18 | u>>(32-18)
+ }
+ x0 += w0
+ x1 += w1
+ x2 += w2
+ x3 += w3
+ x4 += w4
+ x5 += w5
+ x6 += w6
+ x7 += w7
+ x8 += w8
+ x9 += w9
+ x10 += w10
+ x11 += w11
+ x12 += w12
+ x13 += w13
+ x14 += w14
+ x15 += w15
+
+ out[0], tmp[0] = x0, x0
+ out[1], tmp[1] = x1, x1
+ out[2], tmp[2] = x2, x2
+ out[3], tmp[3] = x3, x3
+ out[4], tmp[4] = x4, x4
+ out[5], tmp[5] = x5, x5
+ out[6], tmp[6] = x6, x6
+ out[7], tmp[7] = x7, x7
+ out[8], tmp[8] = x8, x8
+ out[9], tmp[9] = x9, x9
+ out[10], tmp[10] = x10, x10
+ out[11], tmp[11] = x11, x11
+ out[12], tmp[12] = x12, x12
+ out[13], tmp[13] = x13, x13
+ out[14], tmp[14] = x14, x14
+ out[15], tmp[15] = x15, x15
+}
+
+func blockMix(tmp *[16]uint32, in, out []uint32, r int) {
+ blockCopy(tmp[:], in[(2*r-1)*16:], 16)
+ for i := 0; i < 2*r; i += 2 {
+ salsaXOR(tmp, in[i*16:], out[i*8:])
+ salsaXOR(tmp, in[i*16+16:], out[i*8+r*16:])
+ }
+}
+
+func integer(b []uint32, r int) uint64 {
+ j := (2*r - 1) * 16
+ return uint64(b[j]) | uint64(b[j+1])<<32
+}
+
+func smix(b []byte, r, N int, v, xy []uint32) {
+ var tmp [16]uint32
+ x := xy
+ y := xy[32*r:]
+
+ j := 0
+ for i := 0; i < 32*r; i++ {
+ x[i] = uint32(b[j]) | uint32(b[j+1])<<8 | uint32(b[j+2])<<16 | uint32(b[j+3])<<24
+ j += 4
+ }
+ for i := 0; i < N; i += 2 {
+ blockCopy(v[i*(32*r):], x, 32*r)
+ blockMix(&tmp, x, y, r)
+
+ blockCopy(v[(i+1)*(32*r):], y, 32*r)
+ blockMix(&tmp, y, x, r)
+ }
+ for i := 0; i < N; i += 2 {
+ j := int(integer(x, r) & uint64(N-1))
+ blockXOR(x, v[j*(32*r):], 32*r)
+ blockMix(&tmp, x, y, r)
+
+ j = int(integer(y, r) & uint64(N-1))
+ blockXOR(y, v[j*(32*r):], 32*r)
+ blockMix(&tmp, y, x, r)
+ }
+ j = 0
+ for _, v := range x[:32*r] {
+ b[j+0] = byte(v >> 0)
+ b[j+1] = byte(v >> 8)
+ b[j+2] = byte(v >> 16)
+ b[j+3] = byte(v >> 24)
+ j += 4
+ }
+}
+
+// Key derives a key from the password, salt, and cost parameters, returning
+// a byte slice of length keyLen that can be used as cryptographic key.
+//
+// N is a CPU/memory cost parameter, which must be a power of two greater than 1.
+// r and p must satisfy r * p < 2³⁰. If the parameters do not satisfy the
+// limits, the function returns a nil byte slice and an error.
+//
+// For example, you can get a derived key for e.g. AES-256 (which needs a
+// 32-byte key) by doing:
+//
+// dk, err := scrypt.Key([]byte("some password"), salt, 16384, 8, 1, 32)
+//
+// The recommended parameters for interactive logins as of 2017 are N=32768, r=8
+// and p=1. The parameters N, r, and p should be increased as memory latency and
+// CPU parallelism increases; consider setting N to the highest power of 2 you
+// can derive within 100 milliseconds. Remember to get a good random salt.
+func Key(password, salt []byte, N, r, p, keyLen int) ([]byte, error) {
+ if N <= 1 || N&(N-1) != 0 {
+ return nil, errors.New("scrypt: N must be > 1 and a power of 2")
+ }
+ if uint64(r)*uint64(p) >= 1<<30 || r > maxInt/128/p || r > maxInt/256 || N > maxInt/128/r {
+ return nil, errors.New("scrypt: parameters are too large")
+ }
+
+ xy := make([]uint32, 64*r)
+ v := make([]uint32, 32*N*r)
+ b := pbkdf2.Key(password, salt, 1, p*128*r, sha256.New)
+
+ for i := 0; i < p; i++ {
+ smix(b[i*128*r:], r, N, v, xy)
+ }
+
+ return pbkdf2.Key(password, b, 1, keyLen, sha256.New), nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/scrypt/scrypt_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/scrypt/scrypt_test.go
new file mode 100644
index 000000000..766ed8d90
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/scrypt/scrypt_test.go
@@ -0,0 +1,162 @@
+// Copyright 2012 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 scrypt
+
+import (
+ "bytes"
+ "testing"
+)
+
+type testVector struct {
+ password string
+ salt string
+ N, r, p int
+ output []byte
+}
+
+var good = []testVector{
+ {
+ "password",
+ "salt",
+ 2, 10, 10,
+ []byte{
+ 0x48, 0x2c, 0x85, 0x8e, 0x22, 0x90, 0x55, 0xe6, 0x2f,
+ 0x41, 0xe0, 0xec, 0x81, 0x9a, 0x5e, 0xe1, 0x8b, 0xdb,
+ 0x87, 0x25, 0x1a, 0x53, 0x4f, 0x75, 0xac, 0xd9, 0x5a,
+ 0xc5, 0xe5, 0xa, 0xa1, 0x5f,
+ },
+ },
+ {
+ "password",
+ "salt",
+ 16, 100, 100,
+ []byte{
+ 0x88, 0xbd, 0x5e, 0xdb, 0x52, 0xd1, 0xdd, 0x0, 0x18,
+ 0x87, 0x72, 0xad, 0x36, 0x17, 0x12, 0x90, 0x22, 0x4e,
+ 0x74, 0x82, 0x95, 0x25, 0xb1, 0x8d, 0x73, 0x23, 0xa5,
+ 0x7f, 0x91, 0x96, 0x3c, 0x37,
+ },
+ },
+ {
+ "this is a long \000 password",
+ "and this is a long \000 salt",
+ 16384, 8, 1,
+ []byte{
+ 0xc3, 0xf1, 0x82, 0xee, 0x2d, 0xec, 0x84, 0x6e, 0x70,
+ 0xa6, 0x94, 0x2f, 0xb5, 0x29, 0x98, 0x5a, 0x3a, 0x09,
+ 0x76, 0x5e, 0xf0, 0x4c, 0x61, 0x29, 0x23, 0xb1, 0x7f,
+ 0x18, 0x55, 0x5a, 0x37, 0x07, 0x6d, 0xeb, 0x2b, 0x98,
+ 0x30, 0xd6, 0x9d, 0xe5, 0x49, 0x26, 0x51, 0xe4, 0x50,
+ 0x6a, 0xe5, 0x77, 0x6d, 0x96, 0xd4, 0x0f, 0x67, 0xaa,
+ 0xee, 0x37, 0xe1, 0x77, 0x7b, 0x8a, 0xd5, 0xc3, 0x11,
+ 0x14, 0x32, 0xbb, 0x3b, 0x6f, 0x7e, 0x12, 0x64, 0x40,
+ 0x18, 0x79, 0xe6, 0x41, 0xae,
+ },
+ },
+ {
+ "p",
+ "s",
+ 2, 1, 1,
+ []byte{
+ 0x48, 0xb0, 0xd2, 0xa8, 0xa3, 0x27, 0x26, 0x11, 0x98,
+ 0x4c, 0x50, 0xeb, 0xd6, 0x30, 0xaf, 0x52,
+ },
+ },
+
+ {
+ "",
+ "",
+ 16, 1, 1,
+ []byte{
+ 0x77, 0xd6, 0x57, 0x62, 0x38, 0x65, 0x7b, 0x20, 0x3b,
+ 0x19, 0xca, 0x42, 0xc1, 0x8a, 0x04, 0x97, 0xf1, 0x6b,
+ 0x48, 0x44, 0xe3, 0x07, 0x4a, 0xe8, 0xdf, 0xdf, 0xfa,
+ 0x3f, 0xed, 0xe2, 0x14, 0x42, 0xfc, 0xd0, 0x06, 0x9d,
+ 0xed, 0x09, 0x48, 0xf8, 0x32, 0x6a, 0x75, 0x3a, 0x0f,
+ 0xc8, 0x1f, 0x17, 0xe8, 0xd3, 0xe0, 0xfb, 0x2e, 0x0d,
+ 0x36, 0x28, 0xcf, 0x35, 0xe2, 0x0c, 0x38, 0xd1, 0x89,
+ 0x06,
+ },
+ },
+ {
+ "password",
+ "NaCl",
+ 1024, 8, 16,
+ []byte{
+ 0xfd, 0xba, 0xbe, 0x1c, 0x9d, 0x34, 0x72, 0x00, 0x78,
+ 0x56, 0xe7, 0x19, 0x0d, 0x01, 0xe9, 0xfe, 0x7c, 0x6a,
+ 0xd7, 0xcb, 0xc8, 0x23, 0x78, 0x30, 0xe7, 0x73, 0x76,
+ 0x63, 0x4b, 0x37, 0x31, 0x62, 0x2e, 0xaf, 0x30, 0xd9,
+ 0x2e, 0x22, 0xa3, 0x88, 0x6f, 0xf1, 0x09, 0x27, 0x9d,
+ 0x98, 0x30, 0xda, 0xc7, 0x27, 0xaf, 0xb9, 0x4a, 0x83,
+ 0xee, 0x6d, 0x83, 0x60, 0xcb, 0xdf, 0xa2, 0xcc, 0x06,
+ 0x40,
+ },
+ },
+ {
+ "pleaseletmein", "SodiumChloride",
+ 16384, 8, 1,
+ []byte{
+ 0x70, 0x23, 0xbd, 0xcb, 0x3a, 0xfd, 0x73, 0x48, 0x46,
+ 0x1c, 0x06, 0xcd, 0x81, 0xfd, 0x38, 0xeb, 0xfd, 0xa8,
+ 0xfb, 0xba, 0x90, 0x4f, 0x8e, 0x3e, 0xa9, 0xb5, 0x43,
+ 0xf6, 0x54, 0x5d, 0xa1, 0xf2, 0xd5, 0x43, 0x29, 0x55,
+ 0x61, 0x3f, 0x0f, 0xcf, 0x62, 0xd4, 0x97, 0x05, 0x24,
+ 0x2a, 0x9a, 0xf9, 0xe6, 0x1e, 0x85, 0xdc, 0x0d, 0x65,
+ 0x1e, 0x40, 0xdf, 0xcf, 0x01, 0x7b, 0x45, 0x57, 0x58,
+ 0x87,
+ },
+ },
+ /*
+ // Disabled: needs 1 GiB RAM and takes too long for a simple test.
+ {
+ "pleaseletmein", "SodiumChloride",
+ 1048576, 8, 1,
+ []byte{
+ 0x21, 0x01, 0xcb, 0x9b, 0x6a, 0x51, 0x1a, 0xae, 0xad,
+ 0xdb, 0xbe, 0x09, 0xcf, 0x70, 0xf8, 0x81, 0xec, 0x56,
+ 0x8d, 0x57, 0x4a, 0x2f, 0xfd, 0x4d, 0xab, 0xe5, 0xee,
+ 0x98, 0x20, 0xad, 0xaa, 0x47, 0x8e, 0x56, 0xfd, 0x8f,
+ 0x4b, 0xa5, 0xd0, 0x9f, 0xfa, 0x1c, 0x6d, 0x92, 0x7c,
+ 0x40, 0xf4, 0xc3, 0x37, 0x30, 0x40, 0x49, 0xe8, 0xa9,
+ 0x52, 0xfb, 0xcb, 0xf4, 0x5c, 0x6f, 0xa7, 0x7a, 0x41,
+ 0xa4,
+ },
+ },
+ */
+}
+
+var bad = []testVector{
+ {"p", "s", 0, 1, 1, nil}, // N == 0
+ {"p", "s", 1, 1, 1, nil}, // N == 1
+ {"p", "s", 7, 8, 1, nil}, // N is not power of 2
+ {"p", "s", 16, maxInt / 2, maxInt / 2, nil}, // p * r too large
+}
+
+func TestKey(t *testing.T) {
+ for i, v := range good {
+ k, err := Key([]byte(v.password), []byte(v.salt), v.N, v.r, v.p, len(v.output))
+ if err != nil {
+ t.Errorf("%d: got unexpected error: %s", i, err)
+ }
+ if !bytes.Equal(k, v.output) {
+ t.Errorf("%d: expected %x, got %x", i, v.output, k)
+ }
+ }
+ for i, v := range bad {
+ _, err := Key([]byte(v.password), []byte(v.salt), v.N, v.r, v.p, 32)
+ if err == nil {
+ t.Errorf("%d: expected error, got nil", i)
+ }
+ }
+}
+
+var sink []byte
+
+func BenchmarkKey(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ sink, _ = Key([]byte("password"), []byte("salt"), 1<<15, 8, 1, 64)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/doc.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/doc.go
new file mode 100644
index 000000000..a0ee3ae72
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/doc.go
@@ -0,0 +1,66 @@
+// Copyright 2014 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 sha3 implements the SHA-3 fixed-output-length hash functions and
+// the SHAKE variable-output-length hash functions defined by FIPS-202.
+//
+// Both types of hash function use the "sponge" construction and the Keccak
+// permutation. For a detailed specification see http://keccak.noekeon.org/
+//
+//
+// Guidance
+//
+// If you aren't sure what function you need, use SHAKE256 with at least 64
+// bytes of output. The SHAKE instances are faster than the SHA3 instances;
+// the latter have to allocate memory to conform to the hash.Hash interface.
+//
+// If you need a secret-key MAC (message authentication code), prepend the
+// secret key to the input, hash with SHAKE256 and read at least 32 bytes of
+// output.
+//
+//
+// Security strengths
+//
+// The SHA3-x (x equals 224, 256, 384, or 512) functions have a security
+// strength against preimage attacks of x bits. Since they only produce "x"
+// bits of output, their collision-resistance is only "x/2" bits.
+//
+// The SHAKE-256 and -128 functions have a generic security strength of 256 and
+// 128 bits against all attacks, provided that at least 2x bits of their output
+// is used. Requesting more than 64 or 32 bytes of output, respectively, does
+// not increase the collision-resistance of the SHAKE functions.
+//
+//
+// The sponge construction
+//
+// A sponge builds a pseudo-random function from a public pseudo-random
+// permutation, by applying the permutation to a state of "rate + capacity"
+// bytes, but hiding "capacity" of the bytes.
+//
+// A sponge starts out with a zero state. To hash an input using a sponge, up
+// to "rate" bytes of the input are XORed into the sponge's state. The sponge
+// is then "full" and the permutation is applied to "empty" it. This process is
+// repeated until all the input has been "absorbed". The input is then padded.
+// The digest is "squeezed" from the sponge in the same way, except that output
+// output is copied out instead of input being XORed in.
+//
+// A sponge is parameterized by its generic security strength, which is equal
+// to half its capacity; capacity + rate is equal to the permutation's width.
+// Since the KeccakF-1600 permutation is 1600 bits (200 bytes) wide, this means
+// that the security strength of a sponge instance is equal to (1600 - bitrate) / 2.
+//
+//
+// Recommendations
+//
+// The SHAKE functions are recommended for most new uses. They can produce
+// output of arbitrary length. SHAKE256, with an output length of at least
+// 64 bytes, provides 256-bit security against all attacks. The Keccak team
+// recommends it for most applications upgrading from SHA2-512. (NIST chose a
+// much stronger, but much slower, sponge instance for SHA3-512.)
+//
+// The SHA-3 functions are "drop-in" replacements for the SHA-2 functions.
+// They produce output of the same length, with the same security strengths
+// against all attacks. This means, in particular, that SHA3-256 only has
+// 128-bit collision resistance, because its output length is 32 bytes.
+package sha3 // import "golang.org/x/crypto/sha3"
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/hashes.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/hashes.go
new file mode 100644
index 000000000..2b51cf4e9
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/hashes.go
@@ -0,0 +1,65 @@
+// Copyright 2014 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 sha3
+
+// This file provides functions for creating instances of the SHA-3
+// and SHAKE hash functions, as well as utility functions for hashing
+// bytes.
+
+import (
+ "hash"
+)
+
+// New224 creates a new SHA3-224 hash.
+// Its generic security strength is 224 bits against preimage attacks,
+// and 112 bits against collision attacks.
+func New224() hash.Hash { return &state{rate: 144, outputLen: 28, dsbyte: 0x06} }
+
+// New256 creates a new SHA3-256 hash.
+// Its generic security strength is 256 bits against preimage attacks,
+// and 128 bits against collision attacks.
+func New256() hash.Hash { return &state{rate: 136, outputLen: 32, dsbyte: 0x06} }
+
+// New384 creates a new SHA3-384 hash.
+// Its generic security strength is 384 bits against preimage attacks,
+// and 192 bits against collision attacks.
+func New384() hash.Hash { return &state{rate: 104, outputLen: 48, dsbyte: 0x06} }
+
+// New512 creates a new SHA3-512 hash.
+// Its generic security strength is 512 bits against preimage attacks,
+// and 256 bits against collision attacks.
+func New512() hash.Hash { return &state{rate: 72, outputLen: 64, dsbyte: 0x06} }
+
+// Sum224 returns the SHA3-224 digest of the data.
+func Sum224(data []byte) (digest [28]byte) {
+ h := New224()
+ h.Write(data)
+ h.Sum(digest[:0])
+ return
+}
+
+// Sum256 returns the SHA3-256 digest of the data.
+func Sum256(data []byte) (digest [32]byte) {
+ h := New256()
+ h.Write(data)
+ h.Sum(digest[:0])
+ return
+}
+
+// Sum384 returns the SHA3-384 digest of the data.
+func Sum384(data []byte) (digest [48]byte) {
+ h := New384()
+ h.Write(data)
+ h.Sum(digest[:0])
+ return
+}
+
+// Sum512 returns the SHA3-512 digest of the data.
+func Sum512(data []byte) (digest [64]byte) {
+ h := New512()
+ h.Write(data)
+ h.Sum(digest[:0])
+ return
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/keccakf.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/keccakf.go
new file mode 100644
index 000000000..46d03ed38
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/keccakf.go
@@ -0,0 +1,412 @@
+// Copyright 2014 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.
+
+// +build !amd64 appengine gccgo
+
+package sha3
+
+// rc stores the round constants for use in the ι step.
+var rc = [24]uint64{
+ 0x0000000000000001,
+ 0x0000000000008082,
+ 0x800000000000808A,
+ 0x8000000080008000,
+ 0x000000000000808B,
+ 0x0000000080000001,
+ 0x8000000080008081,
+ 0x8000000000008009,
+ 0x000000000000008A,
+ 0x0000000000000088,
+ 0x0000000080008009,
+ 0x000000008000000A,
+ 0x000000008000808B,
+ 0x800000000000008B,
+ 0x8000000000008089,
+ 0x8000000000008003,
+ 0x8000000000008002,
+ 0x8000000000000080,
+ 0x000000000000800A,
+ 0x800000008000000A,
+ 0x8000000080008081,
+ 0x8000000000008080,
+ 0x0000000080000001,
+ 0x8000000080008008,
+}
+
+// keccakF1600 applies the Keccak permutation to a 1600b-wide
+// state represented as a slice of 25 uint64s.
+func keccakF1600(a *[25]uint64) {
+ // Implementation translated from Keccak-inplace.c
+ // in the keccak reference code.
+ var t, bc0, bc1, bc2, bc3, bc4, d0, d1, d2, d3, d4 uint64
+
+ for i := 0; i < 24; i += 4 {
+ // Combines the 5 steps in each round into 2 steps.
+ // Unrolls 4 rounds per loop and spreads some steps across rounds.
+
+ // Round 1
+ bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20]
+ bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21]
+ bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22]
+ bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23]
+ bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24]
+ d0 = bc4 ^ (bc1<<1 | bc1>>63)
+ d1 = bc0 ^ (bc2<<1 | bc2>>63)
+ d2 = bc1 ^ (bc3<<1 | bc3>>63)
+ d3 = bc2 ^ (bc4<<1 | bc4>>63)
+ d4 = bc3 ^ (bc0<<1 | bc0>>63)
+
+ bc0 = a[0] ^ d0
+ t = a[6] ^ d1
+ bc1 = t<<44 | t>>(64-44)
+ t = a[12] ^ d2
+ bc2 = t<<43 | t>>(64-43)
+ t = a[18] ^ d3
+ bc3 = t<<21 | t>>(64-21)
+ t = a[24] ^ d4
+ bc4 = t<<14 | t>>(64-14)
+ a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i]
+ a[6] = bc1 ^ (bc3 &^ bc2)
+ a[12] = bc2 ^ (bc4 &^ bc3)
+ a[18] = bc3 ^ (bc0 &^ bc4)
+ a[24] = bc4 ^ (bc1 &^ bc0)
+
+ t = a[10] ^ d0
+ bc2 = t<<3 | t>>(64-3)
+ t = a[16] ^ d1
+ bc3 = t<<45 | t>>(64-45)
+ t = a[22] ^ d2
+ bc4 = t<<61 | t>>(64-61)
+ t = a[3] ^ d3
+ bc0 = t<<28 | t>>(64-28)
+ t = a[9] ^ d4
+ bc1 = t<<20 | t>>(64-20)
+ a[10] = bc0 ^ (bc2 &^ bc1)
+ a[16] = bc1 ^ (bc3 &^ bc2)
+ a[22] = bc2 ^ (bc4 &^ bc3)
+ a[3] = bc3 ^ (bc0 &^ bc4)
+ a[9] = bc4 ^ (bc1 &^ bc0)
+
+ t = a[20] ^ d0
+ bc4 = t<<18 | t>>(64-18)
+ t = a[1] ^ d1
+ bc0 = t<<1 | t>>(64-1)
+ t = a[7] ^ d2
+ bc1 = t<<6 | t>>(64-6)
+ t = a[13] ^ d3
+ bc2 = t<<25 | t>>(64-25)
+ t = a[19] ^ d4
+ bc3 = t<<8 | t>>(64-8)
+ a[20] = bc0 ^ (bc2 &^ bc1)
+ a[1] = bc1 ^ (bc3 &^ bc2)
+ a[7] = bc2 ^ (bc4 &^ bc3)
+ a[13] = bc3 ^ (bc0 &^ bc4)
+ a[19] = bc4 ^ (bc1 &^ bc0)
+
+ t = a[5] ^ d0
+ bc1 = t<<36 | t>>(64-36)
+ t = a[11] ^ d1
+ bc2 = t<<10 | t>>(64-10)
+ t = a[17] ^ d2
+ bc3 = t<<15 | t>>(64-15)
+ t = a[23] ^ d3
+ bc4 = t<<56 | t>>(64-56)
+ t = a[4] ^ d4
+ bc0 = t<<27 | t>>(64-27)
+ a[5] = bc0 ^ (bc2 &^ bc1)
+ a[11] = bc1 ^ (bc3 &^ bc2)
+ a[17] = bc2 ^ (bc4 &^ bc3)
+ a[23] = bc3 ^ (bc0 &^ bc4)
+ a[4] = bc4 ^ (bc1 &^ bc0)
+
+ t = a[15] ^ d0
+ bc3 = t<<41 | t>>(64-41)
+ t = a[21] ^ d1
+ bc4 = t<<2 | t>>(64-2)
+ t = a[2] ^ d2
+ bc0 = t<<62 | t>>(64-62)
+ t = a[8] ^ d3
+ bc1 = t<<55 | t>>(64-55)
+ t = a[14] ^ d4
+ bc2 = t<<39 | t>>(64-39)
+ a[15] = bc0 ^ (bc2 &^ bc1)
+ a[21] = bc1 ^ (bc3 &^ bc2)
+ a[2] = bc2 ^ (bc4 &^ bc3)
+ a[8] = bc3 ^ (bc0 &^ bc4)
+ a[14] = bc4 ^ (bc1 &^ bc0)
+
+ // Round 2
+ bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20]
+ bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21]
+ bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22]
+ bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23]
+ bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24]
+ d0 = bc4 ^ (bc1<<1 | bc1>>63)
+ d1 = bc0 ^ (bc2<<1 | bc2>>63)
+ d2 = bc1 ^ (bc3<<1 | bc3>>63)
+ d3 = bc2 ^ (bc4<<1 | bc4>>63)
+ d4 = bc3 ^ (bc0<<1 | bc0>>63)
+
+ bc0 = a[0] ^ d0
+ t = a[16] ^ d1
+ bc1 = t<<44 | t>>(64-44)
+ t = a[7] ^ d2
+ bc2 = t<<43 | t>>(64-43)
+ t = a[23] ^ d3
+ bc3 = t<<21 | t>>(64-21)
+ t = a[14] ^ d4
+ bc4 = t<<14 | t>>(64-14)
+ a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i+1]
+ a[16] = bc1 ^ (bc3 &^ bc2)
+ a[7] = bc2 ^ (bc4 &^ bc3)
+ a[23] = bc3 ^ (bc0 &^ bc4)
+ a[14] = bc4 ^ (bc1 &^ bc0)
+
+ t = a[20] ^ d0
+ bc2 = t<<3 | t>>(64-3)
+ t = a[11] ^ d1
+ bc3 = t<<45 | t>>(64-45)
+ t = a[2] ^ d2
+ bc4 = t<<61 | t>>(64-61)
+ t = a[18] ^ d3
+ bc0 = t<<28 | t>>(64-28)
+ t = a[9] ^ d4
+ bc1 = t<<20 | t>>(64-20)
+ a[20] = bc0 ^ (bc2 &^ bc1)
+ a[11] = bc1 ^ (bc3 &^ bc2)
+ a[2] = bc2 ^ (bc4 &^ bc3)
+ a[18] = bc3 ^ (bc0 &^ bc4)
+ a[9] = bc4 ^ (bc1 &^ bc0)
+
+ t = a[15] ^ d0
+ bc4 = t<<18 | t>>(64-18)
+ t = a[6] ^ d1
+ bc0 = t<<1 | t>>(64-1)
+ t = a[22] ^ d2
+ bc1 = t<<6 | t>>(64-6)
+ t = a[13] ^ d3
+ bc2 = t<<25 | t>>(64-25)
+ t = a[4] ^ d4
+ bc3 = t<<8 | t>>(64-8)
+ a[15] = bc0 ^ (bc2 &^ bc1)
+ a[6] = bc1 ^ (bc3 &^ bc2)
+ a[22] = bc2 ^ (bc4 &^ bc3)
+ a[13] = bc3 ^ (bc0 &^ bc4)
+ a[4] = bc4 ^ (bc1 &^ bc0)
+
+ t = a[10] ^ d0
+ bc1 = t<<36 | t>>(64-36)
+ t = a[1] ^ d1
+ bc2 = t<<10 | t>>(64-10)
+ t = a[17] ^ d2
+ bc3 = t<<15 | t>>(64-15)
+ t = a[8] ^ d3
+ bc4 = t<<56 | t>>(64-56)
+ t = a[24] ^ d4
+ bc0 = t<<27 | t>>(64-27)
+ a[10] = bc0 ^ (bc2 &^ bc1)
+ a[1] = bc1 ^ (bc3 &^ bc2)
+ a[17] = bc2 ^ (bc4 &^ bc3)
+ a[8] = bc3 ^ (bc0 &^ bc4)
+ a[24] = bc4 ^ (bc1 &^ bc0)
+
+ t = a[5] ^ d0
+ bc3 = t<<41 | t>>(64-41)
+ t = a[21] ^ d1
+ bc4 = t<<2 | t>>(64-2)
+ t = a[12] ^ d2
+ bc0 = t<<62 | t>>(64-62)
+ t = a[3] ^ d3
+ bc1 = t<<55 | t>>(64-55)
+ t = a[19] ^ d4
+ bc2 = t<<39 | t>>(64-39)
+ a[5] = bc0 ^ (bc2 &^ bc1)
+ a[21] = bc1 ^ (bc3 &^ bc2)
+ a[12] = bc2 ^ (bc4 &^ bc3)
+ a[3] = bc3 ^ (bc0 &^ bc4)
+ a[19] = bc4 ^ (bc1 &^ bc0)
+
+ // Round 3
+ bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20]
+ bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21]
+ bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22]
+ bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23]
+ bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24]
+ d0 = bc4 ^ (bc1<<1 | bc1>>63)
+ d1 = bc0 ^ (bc2<<1 | bc2>>63)
+ d2 = bc1 ^ (bc3<<1 | bc3>>63)
+ d3 = bc2 ^ (bc4<<1 | bc4>>63)
+ d4 = bc3 ^ (bc0<<1 | bc0>>63)
+
+ bc0 = a[0] ^ d0
+ t = a[11] ^ d1
+ bc1 = t<<44 | t>>(64-44)
+ t = a[22] ^ d2
+ bc2 = t<<43 | t>>(64-43)
+ t = a[8] ^ d3
+ bc3 = t<<21 | t>>(64-21)
+ t = a[19] ^ d4
+ bc4 = t<<14 | t>>(64-14)
+ a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i+2]
+ a[11] = bc1 ^ (bc3 &^ bc2)
+ a[22] = bc2 ^ (bc4 &^ bc3)
+ a[8] = bc3 ^ (bc0 &^ bc4)
+ a[19] = bc4 ^ (bc1 &^ bc0)
+
+ t = a[15] ^ d0
+ bc2 = t<<3 | t>>(64-3)
+ t = a[1] ^ d1
+ bc3 = t<<45 | t>>(64-45)
+ t = a[12] ^ d2
+ bc4 = t<<61 | t>>(64-61)
+ t = a[23] ^ d3
+ bc0 = t<<28 | t>>(64-28)
+ t = a[9] ^ d4
+ bc1 = t<<20 | t>>(64-20)
+ a[15] = bc0 ^ (bc2 &^ bc1)
+ a[1] = bc1 ^ (bc3 &^ bc2)
+ a[12] = bc2 ^ (bc4 &^ bc3)
+ a[23] = bc3 ^ (bc0 &^ bc4)
+ a[9] = bc4 ^ (bc1 &^ bc0)
+
+ t = a[5] ^ d0
+ bc4 = t<<18 | t>>(64-18)
+ t = a[16] ^ d1
+ bc0 = t<<1 | t>>(64-1)
+ t = a[2] ^ d2
+ bc1 = t<<6 | t>>(64-6)
+ t = a[13] ^ d3
+ bc2 = t<<25 | t>>(64-25)
+ t = a[24] ^ d4
+ bc3 = t<<8 | t>>(64-8)
+ a[5] = bc0 ^ (bc2 &^ bc1)
+ a[16] = bc1 ^ (bc3 &^ bc2)
+ a[2] = bc2 ^ (bc4 &^ bc3)
+ a[13] = bc3 ^ (bc0 &^ bc4)
+ a[24] = bc4 ^ (bc1 &^ bc0)
+
+ t = a[20] ^ d0
+ bc1 = t<<36 | t>>(64-36)
+ t = a[6] ^ d1
+ bc2 = t<<10 | t>>(64-10)
+ t = a[17] ^ d2
+ bc3 = t<<15 | t>>(64-15)
+ t = a[3] ^ d3
+ bc4 = t<<56 | t>>(64-56)
+ t = a[14] ^ d4
+ bc0 = t<<27 | t>>(64-27)
+ a[20] = bc0 ^ (bc2 &^ bc1)
+ a[6] = bc1 ^ (bc3 &^ bc2)
+ a[17] = bc2 ^ (bc4 &^ bc3)
+ a[3] = bc3 ^ (bc0 &^ bc4)
+ a[14] = bc4 ^ (bc1 &^ bc0)
+
+ t = a[10] ^ d0
+ bc3 = t<<41 | t>>(64-41)
+ t = a[21] ^ d1
+ bc4 = t<<2 | t>>(64-2)
+ t = a[7] ^ d2
+ bc0 = t<<62 | t>>(64-62)
+ t = a[18] ^ d3
+ bc1 = t<<55 | t>>(64-55)
+ t = a[4] ^ d4
+ bc2 = t<<39 | t>>(64-39)
+ a[10] = bc0 ^ (bc2 &^ bc1)
+ a[21] = bc1 ^ (bc3 &^ bc2)
+ a[7] = bc2 ^ (bc4 &^ bc3)
+ a[18] = bc3 ^ (bc0 &^ bc4)
+ a[4] = bc4 ^ (bc1 &^ bc0)
+
+ // Round 4
+ bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20]
+ bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21]
+ bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22]
+ bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23]
+ bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24]
+ d0 = bc4 ^ (bc1<<1 | bc1>>63)
+ d1 = bc0 ^ (bc2<<1 | bc2>>63)
+ d2 = bc1 ^ (bc3<<1 | bc3>>63)
+ d3 = bc2 ^ (bc4<<1 | bc4>>63)
+ d4 = bc3 ^ (bc0<<1 | bc0>>63)
+
+ bc0 = a[0] ^ d0
+ t = a[1] ^ d1
+ bc1 = t<<44 | t>>(64-44)
+ t = a[2] ^ d2
+ bc2 = t<<43 | t>>(64-43)
+ t = a[3] ^ d3
+ bc3 = t<<21 | t>>(64-21)
+ t = a[4] ^ d4
+ bc4 = t<<14 | t>>(64-14)
+ a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i+3]
+ a[1] = bc1 ^ (bc3 &^ bc2)
+ a[2] = bc2 ^ (bc4 &^ bc3)
+ a[3] = bc3 ^ (bc0 &^ bc4)
+ a[4] = bc4 ^ (bc1 &^ bc0)
+
+ t = a[5] ^ d0
+ bc2 = t<<3 | t>>(64-3)
+ t = a[6] ^ d1
+ bc3 = t<<45 | t>>(64-45)
+ t = a[7] ^ d2
+ bc4 = t<<61 | t>>(64-61)
+ t = a[8] ^ d3
+ bc0 = t<<28 | t>>(64-28)
+ t = a[9] ^ d4
+ bc1 = t<<20 | t>>(64-20)
+ a[5] = bc0 ^ (bc2 &^ bc1)
+ a[6] = bc1 ^ (bc3 &^ bc2)
+ a[7] = bc2 ^ (bc4 &^ bc3)
+ a[8] = bc3 ^ (bc0 &^ bc4)
+ a[9] = bc4 ^ (bc1 &^ bc0)
+
+ t = a[10] ^ d0
+ bc4 = t<<18 | t>>(64-18)
+ t = a[11] ^ d1
+ bc0 = t<<1 | t>>(64-1)
+ t = a[12] ^ d2
+ bc1 = t<<6 | t>>(64-6)
+ t = a[13] ^ d3
+ bc2 = t<<25 | t>>(64-25)
+ t = a[14] ^ d4
+ bc3 = t<<8 | t>>(64-8)
+ a[10] = bc0 ^ (bc2 &^ bc1)
+ a[11] = bc1 ^ (bc3 &^ bc2)
+ a[12] = bc2 ^ (bc4 &^ bc3)
+ a[13] = bc3 ^ (bc0 &^ bc4)
+ a[14] = bc4 ^ (bc1 &^ bc0)
+
+ t = a[15] ^ d0
+ bc1 = t<<36 | t>>(64-36)
+ t = a[16] ^ d1
+ bc2 = t<<10 | t>>(64-10)
+ t = a[17] ^ d2
+ bc3 = t<<15 | t>>(64-15)
+ t = a[18] ^ d3
+ bc4 = t<<56 | t>>(64-56)
+ t = a[19] ^ d4
+ bc0 = t<<27 | t>>(64-27)
+ a[15] = bc0 ^ (bc2 &^ bc1)
+ a[16] = bc1 ^ (bc3 &^ bc2)
+ a[17] = bc2 ^ (bc4 &^ bc3)
+ a[18] = bc3 ^ (bc0 &^ bc4)
+ a[19] = bc4 ^ (bc1 &^ bc0)
+
+ t = a[20] ^ d0
+ bc3 = t<<41 | t>>(64-41)
+ t = a[21] ^ d1
+ bc4 = t<<2 | t>>(64-2)
+ t = a[22] ^ d2
+ bc0 = t<<62 | t>>(64-62)
+ t = a[23] ^ d3
+ bc1 = t<<55 | t>>(64-55)
+ t = a[24] ^ d4
+ bc2 = t<<39 | t>>(64-39)
+ a[20] = bc0 ^ (bc2 &^ bc1)
+ a[21] = bc1 ^ (bc3 &^ bc2)
+ a[22] = bc2 ^ (bc4 &^ bc3)
+ a[23] = bc3 ^ (bc0 &^ bc4)
+ a[24] = bc4 ^ (bc1 &^ bc0)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/keccakf_amd64.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/keccakf_amd64.go
new file mode 100644
index 000000000..788679585
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/keccakf_amd64.go
@@ -0,0 +1,13 @@
+// Copyright 2015 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.
+
+// +build amd64,!appengine,!gccgo
+
+package sha3
+
+// This function is implemented in keccakf_amd64.s.
+
+//go:noescape
+
+func keccakF1600(a *[25]uint64)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/keccakf_amd64.s b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/keccakf_amd64.s
new file mode 100644
index 000000000..f88533acc
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/keccakf_amd64.s
@@ -0,0 +1,390 @@
+// Copyright 2015 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.
+
+// +build amd64,!appengine,!gccgo
+
+// This code was translated into a form compatible with 6a from the public
+// domain sources at https://github.com/gvanas/KeccakCodePackage
+
+// Offsets in state
+#define _ba (0*8)
+#define _be (1*8)
+#define _bi (2*8)
+#define _bo (3*8)
+#define _bu (4*8)
+#define _ga (5*8)
+#define _ge (6*8)
+#define _gi (7*8)
+#define _go (8*8)
+#define _gu (9*8)
+#define _ka (10*8)
+#define _ke (11*8)
+#define _ki (12*8)
+#define _ko (13*8)
+#define _ku (14*8)
+#define _ma (15*8)
+#define _me (16*8)
+#define _mi (17*8)
+#define _mo (18*8)
+#define _mu (19*8)
+#define _sa (20*8)
+#define _se (21*8)
+#define _si (22*8)
+#define _so (23*8)
+#define _su (24*8)
+
+// Temporary registers
+#define rT1 AX
+
+// Round vars
+#define rpState DI
+#define rpStack SP
+
+#define rDa BX
+#define rDe CX
+#define rDi DX
+#define rDo R8
+#define rDu R9
+
+#define rBa R10
+#define rBe R11
+#define rBi R12
+#define rBo R13
+#define rBu R14
+
+#define rCa SI
+#define rCe BP
+#define rCi rBi
+#define rCo rBo
+#define rCu R15
+
+#define MOVQ_RBI_RCE MOVQ rBi, rCe
+#define XORQ_RT1_RCA XORQ rT1, rCa
+#define XORQ_RT1_RCE XORQ rT1, rCe
+#define XORQ_RBA_RCU XORQ rBa, rCu
+#define XORQ_RBE_RCU XORQ rBe, rCu
+#define XORQ_RDU_RCU XORQ rDu, rCu
+#define XORQ_RDA_RCA XORQ rDa, rCa
+#define XORQ_RDE_RCE XORQ rDe, rCe
+
+#define mKeccakRound(iState, oState, rc, B_RBI_RCE, G_RT1_RCA, G_RT1_RCE, G_RBA_RCU, K_RT1_RCA, K_RT1_RCE, K_RBA_RCU, M_RT1_RCA, M_RT1_RCE, M_RBE_RCU, S_RDU_RCU, S_RDA_RCA, S_RDE_RCE) \
+ /* Prepare round */ \
+ MOVQ rCe, rDa; \
+ ROLQ $1, rDa; \
+ \
+ MOVQ _bi(iState), rCi; \
+ XORQ _gi(iState), rDi; \
+ XORQ rCu, rDa; \
+ XORQ _ki(iState), rCi; \
+ XORQ _mi(iState), rDi; \
+ XORQ rDi, rCi; \
+ \
+ MOVQ rCi, rDe; \
+ ROLQ $1, rDe; \
+ \
+ MOVQ _bo(iState), rCo; \
+ XORQ _go(iState), rDo; \
+ XORQ rCa, rDe; \
+ XORQ _ko(iState), rCo; \
+ XORQ _mo(iState), rDo; \
+ XORQ rDo, rCo; \
+ \
+ MOVQ rCo, rDi; \
+ ROLQ $1, rDi; \
+ \
+ MOVQ rCu, rDo; \
+ XORQ rCe, rDi; \
+ ROLQ $1, rDo; \
+ \
+ MOVQ rCa, rDu; \
+ XORQ rCi, rDo; \
+ ROLQ $1, rDu; \
+ \
+ /* Result b */ \
+ MOVQ _ba(iState), rBa; \
+ MOVQ _ge(iState), rBe; \
+ XORQ rCo, rDu; \
+ MOVQ _ki(iState), rBi; \
+ MOVQ _mo(iState), rBo; \
+ MOVQ _su(iState), rBu; \
+ XORQ rDe, rBe; \
+ ROLQ $44, rBe; \
+ XORQ rDi, rBi; \
+ XORQ rDa, rBa; \
+ ROLQ $43, rBi; \
+ \
+ MOVQ rBe, rCa; \
+ MOVQ rc, rT1; \
+ ORQ rBi, rCa; \
+ XORQ rBa, rT1; \
+ XORQ rT1, rCa; \
+ MOVQ rCa, _ba(oState); \
+ \
+ XORQ rDu, rBu; \
+ ROLQ $14, rBu; \
+ MOVQ rBa, rCu; \
+ ANDQ rBe, rCu; \
+ XORQ rBu, rCu; \
+ MOVQ rCu, _bu(oState); \
+ \
+ XORQ rDo, rBo; \
+ ROLQ $21, rBo; \
+ MOVQ rBo, rT1; \
+ ANDQ rBu, rT1; \
+ XORQ rBi, rT1; \
+ MOVQ rT1, _bi(oState); \
+ \
+ NOTQ rBi; \
+ ORQ rBa, rBu; \
+ ORQ rBo, rBi; \
+ XORQ rBo, rBu; \
+ XORQ rBe, rBi; \
+ MOVQ rBu, _bo(oState); \
+ MOVQ rBi, _be(oState); \
+ B_RBI_RCE; \
+ \
+ /* Result g */ \
+ MOVQ _gu(iState), rBe; \
+ XORQ rDu, rBe; \
+ MOVQ _ka(iState), rBi; \
+ ROLQ $20, rBe; \
+ XORQ rDa, rBi; \
+ ROLQ $3, rBi; \
+ MOVQ _bo(iState), rBa; \
+ MOVQ rBe, rT1; \
+ ORQ rBi, rT1; \
+ XORQ rDo, rBa; \
+ MOVQ _me(iState), rBo; \
+ MOVQ _si(iState), rBu; \
+ ROLQ $28, rBa; \
+ XORQ rBa, rT1; \
+ MOVQ rT1, _ga(oState); \
+ G_RT1_RCA; \
+ \
+ XORQ rDe, rBo; \
+ ROLQ $45, rBo; \
+ MOVQ rBi, rT1; \
+ ANDQ rBo, rT1; \
+ XORQ rBe, rT1; \
+ MOVQ rT1, _ge(oState); \
+ G_RT1_RCE; \
+ \
+ XORQ rDi, rBu; \
+ ROLQ $61, rBu; \
+ MOVQ rBu, rT1; \
+ ORQ rBa, rT1; \
+ XORQ rBo, rT1; \
+ MOVQ rT1, _go(oState); \
+ \
+ ANDQ rBe, rBa; \
+ XORQ rBu, rBa; \
+ MOVQ rBa, _gu(oState); \
+ NOTQ rBu; \
+ G_RBA_RCU; \
+ \
+ ORQ rBu, rBo; \
+ XORQ rBi, rBo; \
+ MOVQ rBo, _gi(oState); \
+ \
+ /* Result k */ \
+ MOVQ _be(iState), rBa; \
+ MOVQ _gi(iState), rBe; \
+ MOVQ _ko(iState), rBi; \
+ MOVQ _mu(iState), rBo; \
+ MOVQ _sa(iState), rBu; \
+ XORQ rDi, rBe; \
+ ROLQ $6, rBe; \
+ XORQ rDo, rBi; \
+ ROLQ $25, rBi; \
+ MOVQ rBe, rT1; \
+ ORQ rBi, rT1; \
+ XORQ rDe, rBa; \
+ ROLQ $1, rBa; \
+ XORQ rBa, rT1; \
+ MOVQ rT1, _ka(oState); \
+ K_RT1_RCA; \
+ \
+ XORQ rDu, rBo; \
+ ROLQ $8, rBo; \
+ MOVQ rBi, rT1; \
+ ANDQ rBo, rT1; \
+ XORQ rBe, rT1; \
+ MOVQ rT1, _ke(oState); \
+ K_RT1_RCE; \
+ \
+ XORQ rDa, rBu; \
+ ROLQ $18, rBu; \
+ NOTQ rBo; \
+ MOVQ rBo, rT1; \
+ ANDQ rBu, rT1; \
+ XORQ rBi, rT1; \
+ MOVQ rT1, _ki(oState); \
+ \
+ MOVQ rBu, rT1; \
+ ORQ rBa, rT1; \
+ XORQ rBo, rT1; \
+ MOVQ rT1, _ko(oState); \
+ \
+ ANDQ rBe, rBa; \
+ XORQ rBu, rBa; \
+ MOVQ rBa, _ku(oState); \
+ K_RBA_RCU; \
+ \
+ /* Result m */ \
+ MOVQ _ga(iState), rBe; \
+ XORQ rDa, rBe; \
+ MOVQ _ke(iState), rBi; \
+ ROLQ $36, rBe; \
+ XORQ rDe, rBi; \
+ MOVQ _bu(iState), rBa; \
+ ROLQ $10, rBi; \
+ MOVQ rBe, rT1; \
+ MOVQ _mi(iState), rBo; \
+ ANDQ rBi, rT1; \
+ XORQ rDu, rBa; \
+ MOVQ _so(iState), rBu; \
+ ROLQ $27, rBa; \
+ XORQ rBa, rT1; \
+ MOVQ rT1, _ma(oState); \
+ M_RT1_RCA; \
+ \
+ XORQ rDi, rBo; \
+ ROLQ $15, rBo; \
+ MOVQ rBi, rT1; \
+ ORQ rBo, rT1; \
+ XORQ rBe, rT1; \
+ MOVQ rT1, _me(oState); \
+ M_RT1_RCE; \
+ \
+ XORQ rDo, rBu; \
+ ROLQ $56, rBu; \
+ NOTQ rBo; \
+ MOVQ rBo, rT1; \
+ ORQ rBu, rT1; \
+ XORQ rBi, rT1; \
+ MOVQ rT1, _mi(oState); \
+ \
+ ORQ rBa, rBe; \
+ XORQ rBu, rBe; \
+ MOVQ rBe, _mu(oState); \
+ \
+ ANDQ rBa, rBu; \
+ XORQ rBo, rBu; \
+ MOVQ rBu, _mo(oState); \
+ M_RBE_RCU; \
+ \
+ /* Result s */ \
+ MOVQ _bi(iState), rBa; \
+ MOVQ _go(iState), rBe; \
+ MOVQ _ku(iState), rBi; \
+ XORQ rDi, rBa; \
+ MOVQ _ma(iState), rBo; \
+ ROLQ $62, rBa; \
+ XORQ rDo, rBe; \
+ MOVQ _se(iState), rBu; \
+ ROLQ $55, rBe; \
+ \
+ XORQ rDu, rBi; \
+ MOVQ rBa, rDu; \
+ XORQ rDe, rBu; \
+ ROLQ $2, rBu; \
+ ANDQ rBe, rDu; \
+ XORQ rBu, rDu; \
+ MOVQ rDu, _su(oState); \
+ \
+ ROLQ $39, rBi; \
+ S_RDU_RCU; \
+ NOTQ rBe; \
+ XORQ rDa, rBo; \
+ MOVQ rBe, rDa; \
+ ANDQ rBi, rDa; \
+ XORQ rBa, rDa; \
+ MOVQ rDa, _sa(oState); \
+ S_RDA_RCA; \
+ \
+ ROLQ $41, rBo; \
+ MOVQ rBi, rDe; \
+ ORQ rBo, rDe; \
+ XORQ rBe, rDe; \
+ MOVQ rDe, _se(oState); \
+ S_RDE_RCE; \
+ \
+ MOVQ rBo, rDi; \
+ MOVQ rBu, rDo; \
+ ANDQ rBu, rDi; \
+ ORQ rBa, rDo; \
+ XORQ rBi, rDi; \
+ XORQ rBo, rDo; \
+ MOVQ rDi, _si(oState); \
+ MOVQ rDo, _so(oState) \
+
+// func keccakF1600(state *[25]uint64)
+TEXT ·keccakF1600(SB), 0, $200-8
+ MOVQ state+0(FP), rpState
+
+ // Convert the user state into an internal state
+ NOTQ _be(rpState)
+ NOTQ _bi(rpState)
+ NOTQ _go(rpState)
+ NOTQ _ki(rpState)
+ NOTQ _mi(rpState)
+ NOTQ _sa(rpState)
+
+ // Execute the KeccakF permutation
+ MOVQ _ba(rpState), rCa
+ MOVQ _be(rpState), rCe
+ MOVQ _bu(rpState), rCu
+
+ XORQ _ga(rpState), rCa
+ XORQ _ge(rpState), rCe
+ XORQ _gu(rpState), rCu
+
+ XORQ _ka(rpState), rCa
+ XORQ _ke(rpState), rCe
+ XORQ _ku(rpState), rCu
+
+ XORQ _ma(rpState), rCa
+ XORQ _me(rpState), rCe
+ XORQ _mu(rpState), rCu
+
+ XORQ _sa(rpState), rCa
+ XORQ _se(rpState), rCe
+ MOVQ _si(rpState), rDi
+ MOVQ _so(rpState), rDo
+ XORQ _su(rpState), rCu
+
+ mKeccakRound(rpState, rpStack, $0x0000000000000001, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
+ mKeccakRound(rpStack, rpState, $0x0000000000008082, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
+ mKeccakRound(rpState, rpStack, $0x800000000000808a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
+ mKeccakRound(rpStack, rpState, $0x8000000080008000, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
+ mKeccakRound(rpState, rpStack, $0x000000000000808b, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
+ mKeccakRound(rpStack, rpState, $0x0000000080000001, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
+ mKeccakRound(rpState, rpStack, $0x8000000080008081, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
+ mKeccakRound(rpStack, rpState, $0x8000000000008009, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
+ mKeccakRound(rpState, rpStack, $0x000000000000008a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
+ mKeccakRound(rpStack, rpState, $0x0000000000000088, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
+ mKeccakRound(rpState, rpStack, $0x0000000080008009, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
+ mKeccakRound(rpStack, rpState, $0x000000008000000a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
+ mKeccakRound(rpState, rpStack, $0x000000008000808b, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
+ mKeccakRound(rpStack, rpState, $0x800000000000008b, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
+ mKeccakRound(rpState, rpStack, $0x8000000000008089, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
+ mKeccakRound(rpStack, rpState, $0x8000000000008003, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
+ mKeccakRound(rpState, rpStack, $0x8000000000008002, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
+ mKeccakRound(rpStack, rpState, $0x8000000000000080, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
+ mKeccakRound(rpState, rpStack, $0x000000000000800a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
+ mKeccakRound(rpStack, rpState, $0x800000008000000a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
+ mKeccakRound(rpState, rpStack, $0x8000000080008081, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
+ mKeccakRound(rpStack, rpState, $0x8000000000008080, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
+ mKeccakRound(rpState, rpStack, $0x0000000080000001, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
+ mKeccakRound(rpStack, rpState, $0x8000000080008008, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP)
+
+ // Revert the internal state to the user state
+ NOTQ _be(rpState)
+ NOTQ _bi(rpState)
+ NOTQ _go(rpState)
+ NOTQ _ki(rpState)
+ NOTQ _mi(rpState)
+ NOTQ _sa(rpState)
+
+ RET
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/register.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/register.go
new file mode 100644
index 000000000..3cf6a22e0
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/register.go
@@ -0,0 +1,18 @@
+// Copyright 2014 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.
+
+// +build go1.4
+
+package sha3
+
+import (
+ "crypto"
+)
+
+func init() {
+ crypto.RegisterHash(crypto.SHA3_224, New224)
+ crypto.RegisterHash(crypto.SHA3_256, New256)
+ crypto.RegisterHash(crypto.SHA3_384, New384)
+ crypto.RegisterHash(crypto.SHA3_512, New512)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/sha3.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/sha3.go
new file mode 100644
index 000000000..b12a35c87
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/sha3.go
@@ -0,0 +1,192 @@
+// Copyright 2014 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 sha3
+
+// spongeDirection indicates the direction bytes are flowing through the sponge.
+type spongeDirection int
+
+const (
+ // spongeAbsorbing indicates that the sponge is absorbing input.
+ spongeAbsorbing spongeDirection = iota
+ // spongeSqueezing indicates that the sponge is being squeezed.
+ spongeSqueezing
+)
+
+const (
+ // maxRate is the maximum size of the internal buffer. SHAKE-256
+ // currently needs the largest buffer.
+ maxRate = 168
+)
+
+type state struct {
+ // Generic sponge components.
+ a [25]uint64 // main state of the hash
+ buf []byte // points into storage
+ rate int // the number of bytes of state to use
+
+ // dsbyte contains the "domain separation" bits and the first bit of
+ // the padding. Sections 6.1 and 6.2 of [1] separate the outputs of the
+ // SHA-3 and SHAKE functions by appending bitstrings to the message.
+ // Using a little-endian bit-ordering convention, these are "01" for SHA-3
+ // and "1111" for SHAKE, or 00000010b and 00001111b, respectively. Then the
+ // padding rule from section 5.1 is applied to pad the message to a multiple
+ // of the rate, which involves adding a "1" bit, zero or more "0" bits, and
+ // a final "1" bit. We merge the first "1" bit from the padding into dsbyte,
+ // giving 00000110b (0x06) and 00011111b (0x1f).
+ // [1] http://csrc.nist.gov/publications/drafts/fips-202/fips_202_draft.pdf
+ // "Draft FIPS 202: SHA-3 Standard: Permutation-Based Hash and
+ // Extendable-Output Functions (May 2014)"
+ dsbyte byte
+ storage [maxRate]byte
+
+ // Specific to SHA-3 and SHAKE.
+ outputLen int // the default output size in bytes
+ state spongeDirection // whether the sponge is absorbing or squeezing
+}
+
+// BlockSize returns the rate of sponge underlying this hash function.
+func (d *state) BlockSize() int { return d.rate }
+
+// Size returns the output size of the hash function in bytes.
+func (d *state) Size() int { return d.outputLen }
+
+// Reset clears the internal state by zeroing the sponge state and
+// the byte buffer, and setting Sponge.state to absorbing.
+func (d *state) Reset() {
+ // Zero the permutation's state.
+ for i := range d.a {
+ d.a[i] = 0
+ }
+ d.state = spongeAbsorbing
+ d.buf = d.storage[:0]
+}
+
+func (d *state) clone() *state {
+ ret := *d
+ if ret.state == spongeAbsorbing {
+ ret.buf = ret.storage[:len(ret.buf)]
+ } else {
+ ret.buf = ret.storage[d.rate-cap(d.buf) : d.rate]
+ }
+
+ return &ret
+}
+
+// permute applies the KeccakF-1600 permutation. It handles
+// any input-output buffering.
+func (d *state) permute() {
+ switch d.state {
+ case spongeAbsorbing:
+ // If we're absorbing, we need to xor the input into the state
+ // before applying the permutation.
+ xorIn(d, d.buf)
+ d.buf = d.storage[:0]
+ keccakF1600(&d.a)
+ case spongeSqueezing:
+ // If we're squeezing, we need to apply the permutatin before
+ // copying more output.
+ keccakF1600(&d.a)
+ d.buf = d.storage[:d.rate]
+ copyOut(d, d.buf)
+ }
+}
+
+// pads appends the domain separation bits in dsbyte, applies
+// the multi-bitrate 10..1 padding rule, and permutes the state.
+func (d *state) padAndPermute(dsbyte byte) {
+ if d.buf == nil {
+ d.buf = d.storage[:0]
+ }
+ // Pad with this instance's domain-separator bits. We know that there's
+ // at least one byte of space in d.buf because, if it were full,
+ // permute would have been called to empty it. dsbyte also contains the
+ // first one bit for the padding. See the comment in the state struct.
+ d.buf = append(d.buf, dsbyte)
+ zerosStart := len(d.buf)
+ d.buf = d.storage[:d.rate]
+ for i := zerosStart; i < d.rate; i++ {
+ d.buf[i] = 0
+ }
+ // This adds the final one bit for the padding. Because of the way that
+ // bits are numbered from the LSB upwards, the final bit is the MSB of
+ // the last byte.
+ d.buf[d.rate-1] ^= 0x80
+ // Apply the permutation
+ d.permute()
+ d.state = spongeSqueezing
+ d.buf = d.storage[:d.rate]
+ copyOut(d, d.buf)
+}
+
+// Write absorbs more data into the hash's state. It produces an error
+// if more data is written to the ShakeHash after writing
+func (d *state) Write(p []byte) (written int, err error) {
+ if d.state != spongeAbsorbing {
+ panic("sha3: write to sponge after read")
+ }
+ if d.buf == nil {
+ d.buf = d.storage[:0]
+ }
+ written = len(p)
+
+ for len(p) > 0 {
+ if len(d.buf) == 0 && len(p) >= d.rate {
+ // The fast path; absorb a full "rate" bytes of input and apply the permutation.
+ xorIn(d, p[:d.rate])
+ p = p[d.rate:]
+ keccakF1600(&d.a)
+ } else {
+ // The slow path; buffer the input until we can fill the sponge, and then xor it in.
+ todo := d.rate - len(d.buf)
+ if todo > len(p) {
+ todo = len(p)
+ }
+ d.buf = append(d.buf, p[:todo]...)
+ p = p[todo:]
+
+ // If the sponge is full, apply the permutation.
+ if len(d.buf) == d.rate {
+ d.permute()
+ }
+ }
+ }
+
+ return
+}
+
+// Read squeezes an arbitrary number of bytes from the sponge.
+func (d *state) Read(out []byte) (n int, err error) {
+ // If we're still absorbing, pad and apply the permutation.
+ if d.state == spongeAbsorbing {
+ d.padAndPermute(d.dsbyte)
+ }
+
+ n = len(out)
+
+ // Now, do the squeezing.
+ for len(out) > 0 {
+ n := copy(out, d.buf)
+ d.buf = d.buf[n:]
+ out = out[n:]
+
+ // Apply the permutation if we've squeezed the sponge dry.
+ if len(d.buf) == 0 {
+ d.permute()
+ }
+ }
+
+ return
+}
+
+// Sum applies padding to the hash state and then squeezes out the desired
+// number of output bytes.
+func (d *state) Sum(in []byte) []byte {
+ // Make a copy of the original hash so that caller can keep writing
+ // and summing.
+ dup := d.clone()
+ hash := make([]byte, dup.outputLen)
+ dup.Read(hash)
+ return append(in, hash...)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/sha3_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/sha3_test.go
new file mode 100644
index 000000000..312e8f907
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/sha3_test.go
@@ -0,0 +1,311 @@
+// Copyright 2014 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 sha3
+
+// Tests include all the ShortMsgKATs provided by the Keccak team at
+// https://github.com/gvanas/KeccakCodePackage
+//
+// They only include the zero-bit case of the bitwise testvectors
+// published by NIST in the draft of FIPS-202.
+
+import (
+ "bytes"
+ "compress/flate"
+ "encoding/hex"
+ "encoding/json"
+ "fmt"
+ "hash"
+ "os"
+ "strings"
+ "testing"
+)
+
+const (
+ testString = "brekeccakkeccak koax koax"
+ katFilename = "testdata/keccakKats.json.deflate"
+)
+
+// Internal-use instances of SHAKE used to test against KATs.
+func newHashShake128() hash.Hash {
+ return &state{rate: 168, dsbyte: 0x1f, outputLen: 512}
+}
+func newHashShake256() hash.Hash {
+ return &state{rate: 136, dsbyte: 0x1f, outputLen: 512}
+}
+
+// testDigests contains functions returning hash.Hash instances
+// with output-length equal to the KAT length for both SHA-3 and
+// SHAKE instances.
+var testDigests = map[string]func() hash.Hash{
+ "SHA3-224": New224,
+ "SHA3-256": New256,
+ "SHA3-384": New384,
+ "SHA3-512": New512,
+ "SHAKE128": newHashShake128,
+ "SHAKE256": newHashShake256,
+}
+
+// testShakes contains functions that return ShakeHash instances for
+// testing the ShakeHash-specific interface.
+var testShakes = map[string]func() ShakeHash{
+ "SHAKE128": NewShake128,
+ "SHAKE256": NewShake256,
+}
+
+// decodeHex converts a hex-encoded string into a raw byte string.
+func decodeHex(s string) []byte {
+ b, err := hex.DecodeString(s)
+ if err != nil {
+ panic(err)
+ }
+ return b
+}
+
+// structs used to marshal JSON test-cases.
+type KeccakKats struct {
+ Kats map[string][]struct {
+ Digest string `json:"digest"`
+ Length int64 `json:"length"`
+ Message string `json:"message"`
+ }
+}
+
+func testUnalignedAndGeneric(t *testing.T, testf func(impl string)) {
+ xorInOrig, copyOutOrig := xorIn, copyOut
+ xorIn, copyOut = xorInGeneric, copyOutGeneric
+ testf("generic")
+ if xorImplementationUnaligned != "generic" {
+ xorIn, copyOut = xorInUnaligned, copyOutUnaligned
+ testf("unaligned")
+ }
+ xorIn, copyOut = xorInOrig, copyOutOrig
+}
+
+// TestKeccakKats tests the SHA-3 and Shake implementations against all the
+// ShortMsgKATs from https://github.com/gvanas/KeccakCodePackage
+// (The testvectors are stored in keccakKats.json.deflate due to their length.)
+func TestKeccakKats(t *testing.T) {
+ testUnalignedAndGeneric(t, func(impl string) {
+ // Read the KATs.
+ deflated, err := os.Open(katFilename)
+ if err != nil {
+ t.Errorf("error opening %s: %s", katFilename, err)
+ }
+ file := flate.NewReader(deflated)
+ dec := json.NewDecoder(file)
+ var katSet KeccakKats
+ err = dec.Decode(&katSet)
+ if err != nil {
+ t.Errorf("error decoding KATs: %s", err)
+ }
+
+ // Do the KATs.
+ for functionName, kats := range katSet.Kats {
+ d := testDigests[functionName]()
+ for _, kat := range kats {
+ d.Reset()
+ in, err := hex.DecodeString(kat.Message)
+ if err != nil {
+ t.Errorf("error decoding KAT: %s", err)
+ }
+ d.Write(in[:kat.Length/8])
+ got := strings.ToUpper(hex.EncodeToString(d.Sum(nil)))
+ if got != kat.Digest {
+ t.Errorf("function=%s, implementation=%s, length=%d\nmessage:\n %s\ngot:\n %s\nwanted:\n %s",
+ functionName, impl, kat.Length, kat.Message, got, kat.Digest)
+ t.Logf("wanted %+v", kat)
+ t.FailNow()
+ }
+ continue
+ }
+ }
+ })
+}
+
+// TestUnalignedWrite tests that writing data in an arbitrary pattern with
+// small input buffers.
+func testUnalignedWrite(t *testing.T) {
+ testUnalignedAndGeneric(t, func(impl string) {
+ buf := sequentialBytes(0x10000)
+ for alg, df := range testDigests {
+ d := df()
+ d.Reset()
+ d.Write(buf)
+ want := d.Sum(nil)
+ d.Reset()
+ for i := 0; i < len(buf); {
+ // Cycle through offsets which make a 137 byte sequence.
+ // Because 137 is prime this sequence should exercise all corner cases.
+ offsets := [17]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1}
+ for _, j := range offsets {
+ if v := len(buf) - i; v < j {
+ j = v
+ }
+ d.Write(buf[i : i+j])
+ i += j
+ }
+ }
+ got := d.Sum(nil)
+ if !bytes.Equal(got, want) {
+ t.Errorf("Unaligned writes, implementation=%s, alg=%s\ngot %q, want %q", impl, alg, got, want)
+ }
+ }
+ })
+}
+
+// TestAppend checks that appending works when reallocation is necessary.
+func TestAppend(t *testing.T) {
+ testUnalignedAndGeneric(t, func(impl string) {
+ d := New224()
+
+ for capacity := 2; capacity <= 66; capacity += 64 {
+ // The first time around the loop, Sum will have to reallocate.
+ // The second time, it will not.
+ buf := make([]byte, 2, capacity)
+ d.Reset()
+ d.Write([]byte{0xcc})
+ buf = d.Sum(buf)
+ expected := "0000DF70ADC49B2E76EEE3A6931B93FA41841C3AF2CDF5B32A18B5478C39"
+ if got := strings.ToUpper(hex.EncodeToString(buf)); got != expected {
+ t.Errorf("got %s, want %s", got, expected)
+ }
+ }
+ })
+}
+
+// TestAppendNoRealloc tests that appending works when no reallocation is necessary.
+func TestAppendNoRealloc(t *testing.T) {
+ testUnalignedAndGeneric(t, func(impl string) {
+ buf := make([]byte, 1, 200)
+ d := New224()
+ d.Write([]byte{0xcc})
+ buf = d.Sum(buf)
+ expected := "00DF70ADC49B2E76EEE3A6931B93FA41841C3AF2CDF5B32A18B5478C39"
+ if got := strings.ToUpper(hex.EncodeToString(buf)); got != expected {
+ t.Errorf("%s: got %s, want %s", impl, got, expected)
+ }
+ })
+}
+
+// TestSqueezing checks that squeezing the full output a single time produces
+// the same output as repeatedly squeezing the instance.
+func TestSqueezing(t *testing.T) {
+ testUnalignedAndGeneric(t, func(impl string) {
+ for functionName, newShakeHash := range testShakes {
+ d0 := newShakeHash()
+ d0.Write([]byte(testString))
+ ref := make([]byte, 32)
+ d0.Read(ref)
+
+ d1 := newShakeHash()
+ d1.Write([]byte(testString))
+ var multiple []byte
+ for _ = range ref {
+ one := make([]byte, 1)
+ d1.Read(one)
+ multiple = append(multiple, one...)
+ }
+ if !bytes.Equal(ref, multiple) {
+ t.Errorf("%s (%s): squeezing %d bytes one at a time failed", functionName, impl, len(ref))
+ }
+ }
+ })
+}
+
+// sequentialBytes produces a buffer of size consecutive bytes 0x00, 0x01, ..., used for testing.
+func sequentialBytes(size int) []byte {
+ result := make([]byte, size)
+ for i := range result {
+ result[i] = byte(i)
+ }
+ return result
+}
+
+// BenchmarkPermutationFunction measures the speed of the permutation function
+// with no input data.
+func BenchmarkPermutationFunction(b *testing.B) {
+ b.SetBytes(int64(200))
+ var lanes [25]uint64
+ for i := 0; i < b.N; i++ {
+ keccakF1600(&lanes)
+ }
+}
+
+// benchmarkHash tests the speed to hash num buffers of buflen each.
+func benchmarkHash(b *testing.B, h hash.Hash, size, num int) {
+ b.StopTimer()
+ h.Reset()
+ data := sequentialBytes(size)
+ b.SetBytes(int64(size * num))
+ b.StartTimer()
+
+ var state []byte
+ for i := 0; i < b.N; i++ {
+ for j := 0; j < num; j++ {
+ h.Write(data)
+ }
+ state = h.Sum(state[:0])
+ }
+ b.StopTimer()
+ h.Reset()
+}
+
+// benchmarkShake is specialized to the Shake instances, which don't
+// require a copy on reading output.
+func benchmarkShake(b *testing.B, h ShakeHash, size, num int) {
+ b.StopTimer()
+ h.Reset()
+ data := sequentialBytes(size)
+ d := make([]byte, 32)
+
+ b.SetBytes(int64(size * num))
+ b.StartTimer()
+
+ for i := 0; i < b.N; i++ {
+ h.Reset()
+ for j := 0; j < num; j++ {
+ h.Write(data)
+ }
+ h.Read(d)
+ }
+}
+
+func BenchmarkSha3_512_MTU(b *testing.B) { benchmarkHash(b, New512(), 1350, 1) }
+func BenchmarkSha3_384_MTU(b *testing.B) { benchmarkHash(b, New384(), 1350, 1) }
+func BenchmarkSha3_256_MTU(b *testing.B) { benchmarkHash(b, New256(), 1350, 1) }
+func BenchmarkSha3_224_MTU(b *testing.B) { benchmarkHash(b, New224(), 1350, 1) }
+
+func BenchmarkShake128_MTU(b *testing.B) { benchmarkShake(b, NewShake128(), 1350, 1) }
+func BenchmarkShake256_MTU(b *testing.B) { benchmarkShake(b, NewShake256(), 1350, 1) }
+func BenchmarkShake256_16x(b *testing.B) { benchmarkShake(b, NewShake256(), 16, 1024) }
+func BenchmarkShake256_1MiB(b *testing.B) { benchmarkShake(b, NewShake256(), 1024, 1024) }
+
+func BenchmarkSha3_512_1MiB(b *testing.B) { benchmarkHash(b, New512(), 1024, 1024) }
+
+func Example_sum() {
+ buf := []byte("some data to hash")
+ // A hash needs to be 64 bytes long to have 256-bit collision resistance.
+ h := make([]byte, 64)
+ // Compute a 64-byte hash of buf and put it in h.
+ ShakeSum256(h, buf)
+ fmt.Printf("%x\n", h)
+ // Output: 0f65fe41fc353e52c55667bb9e2b27bfcc8476f2c413e9437d272ee3194a4e3146d05ec04a25d16b8f577c19b82d16b1424c3e022e783d2b4da98de3658d363d
+}
+
+func Example_mac() {
+ k := []byte("this is a secret key; you should generate a strong random key that's at least 32 bytes long")
+ buf := []byte("and this is some data to authenticate")
+ // A MAC with 32 bytes of output has 256-bit security strength -- if you use at least a 32-byte-long key.
+ h := make([]byte, 32)
+ d := NewShake256()
+ // Write the key into the hash.
+ d.Write(k)
+ // Now write the data.
+ d.Write(buf)
+ // Read 32 bytes of output from the hash into h.
+ d.Read(h)
+ fmt.Printf("%x\n", h)
+ // Output: 78de2974bd2711d5549ffd32b753ef0f5fa80a0db2556db60f0987eb8a9218ff
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/shake.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/shake.go
new file mode 100644
index 000000000..841f9860f
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/shake.go
@@ -0,0 +1,60 @@
+// Copyright 2014 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 sha3
+
+// This file defines the ShakeHash interface, and provides
+// functions for creating SHAKE instances, as well as utility
+// functions for hashing bytes to arbitrary-length output.
+
+import (
+ "io"
+)
+
+// ShakeHash defines the interface to hash functions that
+// support arbitrary-length output.
+type ShakeHash interface {
+ // Write absorbs more data into the hash's state. It panics if input is
+ // written to it after output has been read from it.
+ io.Writer
+
+ // Read reads more output from the hash; reading affects the hash's
+ // state. (ShakeHash.Read is thus very different from Hash.Sum)
+ // It never returns an error.
+ io.Reader
+
+ // Clone returns a copy of the ShakeHash in its current state.
+ Clone() ShakeHash
+
+ // Reset resets the ShakeHash to its initial state.
+ Reset()
+}
+
+func (d *state) Clone() ShakeHash {
+ return d.clone()
+}
+
+// NewShake128 creates a new SHAKE128 variable-output-length ShakeHash.
+// Its generic security strength is 128 bits against all attacks if at
+// least 32 bytes of its output are used.
+func NewShake128() ShakeHash { return &state{rate: 168, dsbyte: 0x1f} }
+
+// NewShake256 creates a new SHAKE128 variable-output-length ShakeHash.
+// Its generic security strength is 256 bits against all attacks if
+// at least 64 bytes of its output are used.
+func NewShake256() ShakeHash { return &state{rate: 136, dsbyte: 0x1f} }
+
+// ShakeSum128 writes an arbitrary-length digest of data into hash.
+func ShakeSum128(hash, data []byte) {
+ h := NewShake128()
+ h.Write(data)
+ h.Read(hash)
+}
+
+// ShakeSum256 writes an arbitrary-length digest of data into hash.
+func ShakeSum256(hash, data []byte) {
+ h := NewShake256()
+ h.Write(data)
+ h.Read(hash)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/testdata/keccakKats.json.deflate b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/testdata/keccakKats.json.deflate
new file mode 100644
index 000000000..62e85ae24
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/testdata/keccakKats.json.deflate
Binary files differ
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/xor.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/xor.go
new file mode 100644
index 000000000..46a0d63a6
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/xor.go
@@ -0,0 +1,16 @@
+// Copyright 2015 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.
+
+// +build !amd64,!386,!ppc64le appengine
+
+package sha3
+
+var (
+ xorIn = xorInGeneric
+ copyOut = copyOutGeneric
+ xorInUnaligned = xorInGeneric
+ copyOutUnaligned = copyOutGeneric
+)
+
+const xorImplementationUnaligned = "generic"
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/xor_generic.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/xor_generic.go
new file mode 100644
index 000000000..fd35f02ef
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/xor_generic.go
@@ -0,0 +1,28 @@
+// Copyright 2015 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 sha3
+
+import "encoding/binary"
+
+// xorInGeneric xors the bytes in buf into the state; it
+// makes no non-portable assumptions about memory layout
+// or alignment.
+func xorInGeneric(d *state, buf []byte) {
+ n := len(buf) / 8
+
+ for i := 0; i < n; i++ {
+ a := binary.LittleEndian.Uint64(buf)
+ d.a[i] ^= a
+ buf = buf[8:]
+ }
+}
+
+// copyOutGeneric copies ulint64s to a byte buffer.
+func copyOutGeneric(d *state, b []byte) {
+ for i := 0; len(b) >= 8; i++ {
+ binary.LittleEndian.PutUint64(b, d.a[i])
+ b = b[8:]
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/xor_unaligned.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/xor_unaligned.go
new file mode 100644
index 000000000..929a486a7
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/sha3/xor_unaligned.go
@@ -0,0 +1,58 @@
+// Copyright 2015 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.
+
+// +build amd64 386 ppc64le
+// +build !appengine
+
+package sha3
+
+import "unsafe"
+
+func xorInUnaligned(d *state, buf []byte) {
+ bw := (*[maxRate / 8]uint64)(unsafe.Pointer(&buf[0]))
+ n := len(buf)
+ if n >= 72 {
+ d.a[0] ^= bw[0]
+ d.a[1] ^= bw[1]
+ d.a[2] ^= bw[2]
+ d.a[3] ^= bw[3]
+ d.a[4] ^= bw[4]
+ d.a[5] ^= bw[5]
+ d.a[6] ^= bw[6]
+ d.a[7] ^= bw[7]
+ d.a[8] ^= bw[8]
+ }
+ if n >= 104 {
+ d.a[9] ^= bw[9]
+ d.a[10] ^= bw[10]
+ d.a[11] ^= bw[11]
+ d.a[12] ^= bw[12]
+ }
+ if n >= 136 {
+ d.a[13] ^= bw[13]
+ d.a[14] ^= bw[14]
+ d.a[15] ^= bw[15]
+ d.a[16] ^= bw[16]
+ }
+ if n >= 144 {
+ d.a[17] ^= bw[17]
+ }
+ if n >= 168 {
+ d.a[18] ^= bw[18]
+ d.a[19] ^= bw[19]
+ d.a[20] ^= bw[20]
+ }
+}
+
+func copyOutUnaligned(d *state, buf []byte) {
+ ab := (*[maxRate]uint8)(unsafe.Pointer(&d.a[0]))
+ copy(buf, ab[:])
+}
+
+var (
+ xorIn = xorInUnaligned
+ copyOut = copyOutUnaligned
+)
+
+const xorImplementationUnaligned = "unaligned"
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/agent/client.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/agent/client.go
new file mode 100644
index 000000000..dce7682fa
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/agent/client.go
@@ -0,0 +1,683 @@
+// Copyright 2012 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 agent implements the ssh-agent protocol, and provides both
+// a client and a server. The client can talk to a standard ssh-agent
+// that uses UNIX sockets, and one could implement an alternative
+// ssh-agent process using the sample server.
+//
+// References:
+// [PROTOCOL.agent]: http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.agent?rev=HEAD
+package agent // import "golang.org/x/crypto/ssh/agent"
+
+import (
+ "bytes"
+ "crypto/dsa"
+ "crypto/ecdsa"
+ "crypto/elliptic"
+ "crypto/rsa"
+ "encoding/base64"
+ "encoding/binary"
+ "errors"
+ "fmt"
+ "io"
+ "math/big"
+ "sync"
+
+ "golang.org/x/crypto/ed25519"
+ "golang.org/x/crypto/ssh"
+)
+
+// Agent represents the capabilities of an ssh-agent.
+type Agent interface {
+ // List returns the identities known to the agent.
+ List() ([]*Key, error)
+
+ // Sign has the agent sign the data using a protocol 2 key as defined
+ // in [PROTOCOL.agent] section 2.6.2.
+ Sign(key ssh.PublicKey, data []byte) (*ssh.Signature, error)
+
+ // Add adds a private key to the agent.
+ Add(key AddedKey) error
+
+ // Remove removes all identities with the given public key.
+ Remove(key ssh.PublicKey) error
+
+ // RemoveAll removes all identities.
+ RemoveAll() error
+
+ // Lock locks the agent. Sign and Remove will fail, and List will empty an empty list.
+ Lock(passphrase []byte) error
+
+ // Unlock undoes the effect of Lock
+ Unlock(passphrase []byte) error
+
+ // Signers returns signers for all the known keys.
+ Signers() ([]ssh.Signer, error)
+}
+
+// ConstraintExtension describes an optional constraint defined by users.
+type ConstraintExtension struct {
+ // ExtensionName consist of a UTF-8 string suffixed by the
+ // implementation domain following the naming scheme defined
+ // in Section 4.2 of [RFC4251], e.g. "foo@example.com".
+ ExtensionName string
+ // ExtensionDetails contains the actual content of the extended
+ // constraint.
+ ExtensionDetails []byte
+}
+
+// AddedKey describes an SSH key to be added to an Agent.
+type AddedKey struct {
+ // PrivateKey must be a *rsa.PrivateKey, *dsa.PrivateKey or
+ // *ecdsa.PrivateKey, which will be inserted into the agent.
+ PrivateKey interface{}
+ // Certificate, if not nil, is communicated to the agent and will be
+ // stored with the key.
+ Certificate *ssh.Certificate
+ // Comment is an optional, free-form string.
+ Comment string
+ // LifetimeSecs, if not zero, is the number of seconds that the
+ // agent will store the key for.
+ LifetimeSecs uint32
+ // ConfirmBeforeUse, if true, requests that the agent confirm with the
+ // user before each use of this key.
+ ConfirmBeforeUse bool
+ // ConstraintExtensions are the experimental or private-use constraints
+ // defined by users.
+ ConstraintExtensions []ConstraintExtension
+}
+
+// See [PROTOCOL.agent], section 3.
+const (
+ agentRequestV1Identities = 1
+ agentRemoveAllV1Identities = 9
+
+ // 3.2 Requests from client to agent for protocol 2 key operations
+ agentAddIdentity = 17
+ agentRemoveIdentity = 18
+ agentRemoveAllIdentities = 19
+ agentAddIdConstrained = 25
+
+ // 3.3 Key-type independent requests from client to agent
+ agentAddSmartcardKey = 20
+ agentRemoveSmartcardKey = 21
+ agentLock = 22
+ agentUnlock = 23
+ agentAddSmartcardKeyConstrained = 26
+
+ // 3.7 Key constraint identifiers
+ agentConstrainLifetime = 1
+ agentConstrainConfirm = 2
+ agentConstrainExtension = 3
+)
+
+// maxAgentResponseBytes is the maximum agent reply size that is accepted. This
+// is a sanity check, not a limit in the spec.
+const maxAgentResponseBytes = 16 << 20
+
+// Agent messages:
+// These structures mirror the wire format of the corresponding ssh agent
+// messages found in [PROTOCOL.agent].
+
+// 3.4 Generic replies from agent to client
+const agentFailure = 5
+
+type failureAgentMsg struct{}
+
+const agentSuccess = 6
+
+type successAgentMsg struct{}
+
+// See [PROTOCOL.agent], section 2.5.2.
+const agentRequestIdentities = 11
+
+type requestIdentitiesAgentMsg struct{}
+
+// See [PROTOCOL.agent], section 2.5.2.
+const agentIdentitiesAnswer = 12
+
+type identitiesAnswerAgentMsg struct {
+ NumKeys uint32 `sshtype:"12"`
+ Keys []byte `ssh:"rest"`
+}
+
+// See [PROTOCOL.agent], section 2.6.2.
+const agentSignRequest = 13
+
+type signRequestAgentMsg struct {
+ KeyBlob []byte `sshtype:"13"`
+ Data []byte
+ Flags uint32
+}
+
+// See [PROTOCOL.agent], section 2.6.2.
+
+// 3.6 Replies from agent to client for protocol 2 key operations
+const agentSignResponse = 14
+
+type signResponseAgentMsg struct {
+ SigBlob []byte `sshtype:"14"`
+}
+
+type publicKey struct {
+ Format string
+ Rest []byte `ssh:"rest"`
+}
+
+// 3.7 Key constraint identifiers
+type constrainLifetimeAgentMsg struct {
+ LifetimeSecs uint32 `sshtype:"1"`
+}
+
+type constrainExtensionAgentMsg struct {
+ ExtensionName string `sshtype:"3"`
+ ExtensionDetails []byte
+
+ // Rest is a field used for parsing, not part of message
+ Rest []byte `ssh:"rest"`
+}
+
+// Key represents a protocol 2 public key as defined in
+// [PROTOCOL.agent], section 2.5.2.
+type Key struct {
+ Format string
+ Blob []byte
+ Comment string
+}
+
+func clientErr(err error) error {
+ return fmt.Errorf("agent: client error: %v", err)
+}
+
+// String returns the storage form of an agent key with the format, base64
+// encoded serialized key, and the comment if it is not empty.
+func (k *Key) String() string {
+ s := string(k.Format) + " " + base64.StdEncoding.EncodeToString(k.Blob)
+
+ if k.Comment != "" {
+ s += " " + k.Comment
+ }
+
+ return s
+}
+
+// Type returns the public key type.
+func (k *Key) Type() string {
+ return k.Format
+}
+
+// Marshal returns key blob to satisfy the ssh.PublicKey interface.
+func (k *Key) Marshal() []byte {
+ return k.Blob
+}
+
+// Verify satisfies the ssh.PublicKey interface.
+func (k *Key) Verify(data []byte, sig *ssh.Signature) error {
+ pubKey, err := ssh.ParsePublicKey(k.Blob)
+ if err != nil {
+ return fmt.Errorf("agent: bad public key: %v", err)
+ }
+ return pubKey.Verify(data, sig)
+}
+
+type wireKey struct {
+ Format string
+ Rest []byte `ssh:"rest"`
+}
+
+func parseKey(in []byte) (out *Key, rest []byte, err error) {
+ var record struct {
+ Blob []byte
+ Comment string
+ Rest []byte `ssh:"rest"`
+ }
+
+ if err := ssh.Unmarshal(in, &record); err != nil {
+ return nil, nil, err
+ }
+
+ var wk wireKey
+ if err := ssh.Unmarshal(record.Blob, &wk); err != nil {
+ return nil, nil, err
+ }
+
+ return &Key{
+ Format: wk.Format,
+ Blob: record.Blob,
+ Comment: record.Comment,
+ }, record.Rest, nil
+}
+
+// client is a client for an ssh-agent process.
+type client struct {
+ // conn is typically a *net.UnixConn
+ conn io.ReadWriter
+ // mu is used to prevent concurrent access to the agent
+ mu sync.Mutex
+}
+
+// NewClient returns an Agent that talks to an ssh-agent process over
+// the given connection.
+func NewClient(rw io.ReadWriter) Agent {
+ return &client{conn: rw}
+}
+
+// call sends an RPC to the agent. On success, the reply is
+// unmarshaled into reply and replyType is set to the first byte of
+// the reply, which contains the type of the message.
+func (c *client) call(req []byte) (reply interface{}, err error) {
+ c.mu.Lock()
+ defer c.mu.Unlock()
+
+ msg := make([]byte, 4+len(req))
+ binary.BigEndian.PutUint32(msg, uint32(len(req)))
+ copy(msg[4:], req)
+ if _, err = c.conn.Write(msg); err != nil {
+ return nil, clientErr(err)
+ }
+
+ var respSizeBuf [4]byte
+ if _, err = io.ReadFull(c.conn, respSizeBuf[:]); err != nil {
+ return nil, clientErr(err)
+ }
+ respSize := binary.BigEndian.Uint32(respSizeBuf[:])
+ if respSize > maxAgentResponseBytes {
+ return nil, clientErr(err)
+ }
+
+ buf := make([]byte, respSize)
+ if _, err = io.ReadFull(c.conn, buf); err != nil {
+ return nil, clientErr(err)
+ }
+ reply, err = unmarshal(buf)
+ if err != nil {
+ return nil, clientErr(err)
+ }
+ return reply, err
+}
+
+func (c *client) simpleCall(req []byte) error {
+ resp, err := c.call(req)
+ if err != nil {
+ return err
+ }
+ if _, ok := resp.(*successAgentMsg); ok {
+ return nil
+ }
+ return errors.New("agent: failure")
+}
+
+func (c *client) RemoveAll() error {
+ return c.simpleCall([]byte{agentRemoveAllIdentities})
+}
+
+func (c *client) Remove(key ssh.PublicKey) error {
+ req := ssh.Marshal(&agentRemoveIdentityMsg{
+ KeyBlob: key.Marshal(),
+ })
+ return c.simpleCall(req)
+}
+
+func (c *client) Lock(passphrase []byte) error {
+ req := ssh.Marshal(&agentLockMsg{
+ Passphrase: passphrase,
+ })
+ return c.simpleCall(req)
+}
+
+func (c *client) Unlock(passphrase []byte) error {
+ req := ssh.Marshal(&agentUnlockMsg{
+ Passphrase: passphrase,
+ })
+ return c.simpleCall(req)
+}
+
+// List returns the identities known to the agent.
+func (c *client) List() ([]*Key, error) {
+ // see [PROTOCOL.agent] section 2.5.2.
+ req := []byte{agentRequestIdentities}
+
+ msg, err := c.call(req)
+ if err != nil {
+ return nil, err
+ }
+
+ switch msg := msg.(type) {
+ case *identitiesAnswerAgentMsg:
+ if msg.NumKeys > maxAgentResponseBytes/8 {
+ return nil, errors.New("agent: too many keys in agent reply")
+ }
+ keys := make([]*Key, msg.NumKeys)
+ data := msg.Keys
+ for i := uint32(0); i < msg.NumKeys; i++ {
+ var key *Key
+ var err error
+ if key, data, err = parseKey(data); err != nil {
+ return nil, err
+ }
+ keys[i] = key
+ }
+ return keys, nil
+ case *failureAgentMsg:
+ return nil, errors.New("agent: failed to list keys")
+ }
+ panic("unreachable")
+}
+
+// Sign has the agent sign the data using a protocol 2 key as defined
+// in [PROTOCOL.agent] section 2.6.2.
+func (c *client) Sign(key ssh.PublicKey, data []byte) (*ssh.Signature, error) {
+ req := ssh.Marshal(signRequestAgentMsg{
+ KeyBlob: key.Marshal(),
+ Data: data,
+ })
+
+ msg, err := c.call(req)
+ if err != nil {
+ return nil, err
+ }
+
+ switch msg := msg.(type) {
+ case *signResponseAgentMsg:
+ var sig ssh.Signature
+ if err := ssh.Unmarshal(msg.SigBlob, &sig); err != nil {
+ return nil, err
+ }
+
+ return &sig, nil
+ case *failureAgentMsg:
+ return nil, errors.New("agent: failed to sign challenge")
+ }
+ panic("unreachable")
+}
+
+// unmarshal parses an agent message in packet, returning the parsed
+// form and the message type of packet.
+func unmarshal(packet []byte) (interface{}, error) {
+ if len(packet) < 1 {
+ return nil, errors.New("agent: empty packet")
+ }
+ var msg interface{}
+ switch packet[0] {
+ case agentFailure:
+ return new(failureAgentMsg), nil
+ case agentSuccess:
+ return new(successAgentMsg), nil
+ case agentIdentitiesAnswer:
+ msg = new(identitiesAnswerAgentMsg)
+ case agentSignResponse:
+ msg = new(signResponseAgentMsg)
+ case agentV1IdentitiesAnswer:
+ msg = new(agentV1IdentityMsg)
+ default:
+ return nil, fmt.Errorf("agent: unknown type tag %d", packet[0])
+ }
+ if err := ssh.Unmarshal(packet, msg); err != nil {
+ return nil, err
+ }
+ return msg, nil
+}
+
+type rsaKeyMsg struct {
+ Type string `sshtype:"17|25"`
+ N *big.Int
+ E *big.Int
+ D *big.Int
+ Iqmp *big.Int // IQMP = Inverse Q Mod P
+ P *big.Int
+ Q *big.Int
+ Comments string
+ Constraints []byte `ssh:"rest"`
+}
+
+type dsaKeyMsg struct {
+ Type string `sshtype:"17|25"`
+ P *big.Int
+ Q *big.Int
+ G *big.Int
+ Y *big.Int
+ X *big.Int
+ Comments string
+ Constraints []byte `ssh:"rest"`
+}
+
+type ecdsaKeyMsg struct {
+ Type string `sshtype:"17|25"`
+ Curve string
+ KeyBytes []byte
+ D *big.Int
+ Comments string
+ Constraints []byte `ssh:"rest"`
+}
+
+type ed25519KeyMsg struct {
+ Type string `sshtype:"17|25"`
+ Pub []byte
+ Priv []byte
+ Comments string
+ Constraints []byte `ssh:"rest"`
+}
+
+// Insert adds a private key to the agent.
+func (c *client) insertKey(s interface{}, comment string, constraints []byte) error {
+ var req []byte
+ switch k := s.(type) {
+ case *rsa.PrivateKey:
+ if len(k.Primes) != 2 {
+ return fmt.Errorf("agent: unsupported RSA key with %d primes", len(k.Primes))
+ }
+ k.Precompute()
+ req = ssh.Marshal(rsaKeyMsg{
+ Type: ssh.KeyAlgoRSA,
+ N: k.N,
+ E: big.NewInt(int64(k.E)),
+ D: k.D,
+ Iqmp: k.Precomputed.Qinv,
+ P: k.Primes[0],
+ Q: k.Primes[1],
+ Comments: comment,
+ Constraints: constraints,
+ })
+ case *dsa.PrivateKey:
+ req = ssh.Marshal(dsaKeyMsg{
+ Type: ssh.KeyAlgoDSA,
+ P: k.P,
+ Q: k.Q,
+ G: k.G,
+ Y: k.Y,
+ X: k.X,
+ Comments: comment,
+ Constraints: constraints,
+ })
+ case *ecdsa.PrivateKey:
+ nistID := fmt.Sprintf("nistp%d", k.Params().BitSize)
+ req = ssh.Marshal(ecdsaKeyMsg{
+ Type: "ecdsa-sha2-" + nistID,
+ Curve: nistID,
+ KeyBytes: elliptic.Marshal(k.Curve, k.X, k.Y),
+ D: k.D,
+ Comments: comment,
+ Constraints: constraints,
+ })
+ case *ed25519.PrivateKey:
+ req = ssh.Marshal(ed25519KeyMsg{
+ Type: ssh.KeyAlgoED25519,
+ Pub: []byte(*k)[32:],
+ Priv: []byte(*k),
+ Comments: comment,
+ Constraints: constraints,
+ })
+ default:
+ return fmt.Errorf("agent: unsupported key type %T", s)
+ }
+
+ // if constraints are present then the message type needs to be changed.
+ if len(constraints) != 0 {
+ req[0] = agentAddIdConstrained
+ }
+
+ resp, err := c.call(req)
+ if err != nil {
+ return err
+ }
+ if _, ok := resp.(*successAgentMsg); ok {
+ return nil
+ }
+ return errors.New("agent: failure")
+}
+
+type rsaCertMsg struct {
+ Type string `sshtype:"17|25"`
+ CertBytes []byte
+ D *big.Int
+ Iqmp *big.Int // IQMP = Inverse Q Mod P
+ P *big.Int
+ Q *big.Int
+ Comments string
+ Constraints []byte `ssh:"rest"`
+}
+
+type dsaCertMsg struct {
+ Type string `sshtype:"17|25"`
+ CertBytes []byte
+ X *big.Int
+ Comments string
+ Constraints []byte `ssh:"rest"`
+}
+
+type ecdsaCertMsg struct {
+ Type string `sshtype:"17|25"`
+ CertBytes []byte
+ D *big.Int
+ Comments string
+ Constraints []byte `ssh:"rest"`
+}
+
+type ed25519CertMsg struct {
+ Type string `sshtype:"17|25"`
+ CertBytes []byte
+ Pub []byte
+ Priv []byte
+ Comments string
+ Constraints []byte `ssh:"rest"`
+}
+
+// Add adds a private key to the agent. If a certificate is given,
+// that certificate is added instead as public key.
+func (c *client) Add(key AddedKey) error {
+ var constraints []byte
+
+ if secs := key.LifetimeSecs; secs != 0 {
+ constraints = append(constraints, ssh.Marshal(constrainLifetimeAgentMsg{secs})...)
+ }
+
+ if key.ConfirmBeforeUse {
+ constraints = append(constraints, agentConstrainConfirm)
+ }
+
+ if cert := key.Certificate; cert == nil {
+ return c.insertKey(key.PrivateKey, key.Comment, constraints)
+ } else {
+ return c.insertCert(key.PrivateKey, cert, key.Comment, constraints)
+ }
+}
+
+func (c *client) insertCert(s interface{}, cert *ssh.Certificate, comment string, constraints []byte) error {
+ var req []byte
+ switch k := s.(type) {
+ case *rsa.PrivateKey:
+ if len(k.Primes) != 2 {
+ return fmt.Errorf("agent: unsupported RSA key with %d primes", len(k.Primes))
+ }
+ k.Precompute()
+ req = ssh.Marshal(rsaCertMsg{
+ Type: cert.Type(),
+ CertBytes: cert.Marshal(),
+ D: k.D,
+ Iqmp: k.Precomputed.Qinv,
+ P: k.Primes[0],
+ Q: k.Primes[1],
+ Comments: comment,
+ Constraints: constraints,
+ })
+ case *dsa.PrivateKey:
+ req = ssh.Marshal(dsaCertMsg{
+ Type: cert.Type(),
+ CertBytes: cert.Marshal(),
+ X: k.X,
+ Comments: comment,
+ Constraints: constraints,
+ })
+ case *ecdsa.PrivateKey:
+ req = ssh.Marshal(ecdsaCertMsg{
+ Type: cert.Type(),
+ CertBytes: cert.Marshal(),
+ D: k.D,
+ Comments: comment,
+ Constraints: constraints,
+ })
+ case *ed25519.PrivateKey:
+ req = ssh.Marshal(ed25519CertMsg{
+ Type: cert.Type(),
+ CertBytes: cert.Marshal(),
+ Pub: []byte(*k)[32:],
+ Priv: []byte(*k),
+ Comments: comment,
+ Constraints: constraints,
+ })
+ default:
+ return fmt.Errorf("agent: unsupported key type %T", s)
+ }
+
+ // if constraints are present then the message type needs to be changed.
+ if len(constraints) != 0 {
+ req[0] = agentAddIdConstrained
+ }
+
+ signer, err := ssh.NewSignerFromKey(s)
+ if err != nil {
+ return err
+ }
+ if bytes.Compare(cert.Key.Marshal(), signer.PublicKey().Marshal()) != 0 {
+ return errors.New("agent: signer and cert have different public key")
+ }
+
+ resp, err := c.call(req)
+ if err != nil {
+ return err
+ }
+ if _, ok := resp.(*successAgentMsg); ok {
+ return nil
+ }
+ return errors.New("agent: failure")
+}
+
+// Signers provides a callback for client authentication.
+func (c *client) Signers() ([]ssh.Signer, error) {
+ keys, err := c.List()
+ if err != nil {
+ return nil, err
+ }
+
+ var result []ssh.Signer
+ for _, k := range keys {
+ result = append(result, &agentKeyringSigner{c, k})
+ }
+ return result, nil
+}
+
+type agentKeyringSigner struct {
+ agent *client
+ pub ssh.PublicKey
+}
+
+func (s *agentKeyringSigner) PublicKey() ssh.PublicKey {
+ return s.pub
+}
+
+func (s *agentKeyringSigner) Sign(rand io.Reader, data []byte) (*ssh.Signature, error) {
+ // The agent has its own entropy source, so the rand argument is ignored.
+ return s.agent.Sign(s.pub, data)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/agent/client_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/agent/client_test.go
new file mode 100644
index 000000000..266fd6d40
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/agent/client_test.go
@@ -0,0 +1,379 @@
+// Copyright 2012 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 agent
+
+import (
+ "bytes"
+ "crypto/rand"
+ "errors"
+ "net"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "strconv"
+ "testing"
+ "time"
+
+ "golang.org/x/crypto/ssh"
+)
+
+// startOpenSSHAgent executes ssh-agent, and returns an Agent interface to it.
+func startOpenSSHAgent(t *testing.T) (client Agent, socket string, cleanup func()) {
+ if testing.Short() {
+ // ssh-agent is not always available, and the key
+ // types supported vary by platform.
+ t.Skip("skipping test due to -short")
+ }
+
+ bin, err := exec.LookPath("ssh-agent")
+ if err != nil {
+ t.Skip("could not find ssh-agent")
+ }
+
+ cmd := exec.Command(bin, "-s")
+ out, err := cmd.Output()
+ if err != nil {
+ t.Fatalf("cmd.Output: %v", err)
+ }
+
+ /* Output looks like:
+
+ SSH_AUTH_SOCK=/tmp/ssh-P65gpcqArqvH/agent.15541; export SSH_AUTH_SOCK;
+ SSH_AGENT_PID=15542; export SSH_AGENT_PID;
+ echo Agent pid 15542;
+ */
+ fields := bytes.Split(out, []byte(";"))
+ line := bytes.SplitN(fields[0], []byte("="), 2)
+ line[0] = bytes.TrimLeft(line[0], "\n")
+ if string(line[0]) != "SSH_AUTH_SOCK" {
+ t.Fatalf("could not find key SSH_AUTH_SOCK in %q", fields[0])
+ }
+ socket = string(line[1])
+
+ line = bytes.SplitN(fields[2], []byte("="), 2)
+ line[0] = bytes.TrimLeft(line[0], "\n")
+ if string(line[0]) != "SSH_AGENT_PID" {
+ t.Fatalf("could not find key SSH_AGENT_PID in %q", fields[2])
+ }
+ pidStr := line[1]
+ pid, err := strconv.Atoi(string(pidStr))
+ if err != nil {
+ t.Fatalf("Atoi(%q): %v", pidStr, err)
+ }
+
+ conn, err := net.Dial("unix", string(socket))
+ if err != nil {
+ t.Fatalf("net.Dial: %v", err)
+ }
+
+ ac := NewClient(conn)
+ return ac, socket, func() {
+ proc, _ := os.FindProcess(pid)
+ if proc != nil {
+ proc.Kill()
+ }
+ conn.Close()
+ os.RemoveAll(filepath.Dir(socket))
+ }
+}
+
+// startKeyringAgent uses Keyring to simulate a ssh-agent Server and returns a client.
+func startKeyringAgent(t *testing.T) (client Agent, cleanup func()) {
+ c1, c2, err := netPipe()
+ if err != nil {
+ t.Fatalf("netPipe: %v", err)
+ }
+ go ServeAgent(NewKeyring(), c2)
+
+ return NewClient(c1), func() {
+ c1.Close()
+ c2.Close()
+ }
+}
+
+func testOpenSSHAgent(t *testing.T, key interface{}, cert *ssh.Certificate, lifetimeSecs uint32) {
+ agent, _, cleanup := startOpenSSHAgent(t)
+ defer cleanup()
+
+ testAgentInterface(t, agent, key, cert, lifetimeSecs)
+}
+
+func testKeyringAgent(t *testing.T, key interface{}, cert *ssh.Certificate, lifetimeSecs uint32) {
+ agent, cleanup := startKeyringAgent(t)
+ defer cleanup()
+
+ testAgentInterface(t, agent, key, cert, lifetimeSecs)
+}
+
+func testAgentInterface(t *testing.T, agent Agent, key interface{}, cert *ssh.Certificate, lifetimeSecs uint32) {
+ signer, err := ssh.NewSignerFromKey(key)
+ if err != nil {
+ t.Fatalf("NewSignerFromKey(%T): %v", key, err)
+ }
+ // The agent should start up empty.
+ if keys, err := agent.List(); err != nil {
+ t.Fatalf("RequestIdentities: %v", err)
+ } else if len(keys) > 0 {
+ t.Fatalf("got %d keys, want 0: %v", len(keys), keys)
+ }
+
+ // Attempt to insert the key, with certificate if specified.
+ var pubKey ssh.PublicKey
+ if cert != nil {
+ err = agent.Add(AddedKey{
+ PrivateKey: key,
+ Certificate: cert,
+ Comment: "comment",
+ LifetimeSecs: lifetimeSecs,
+ })
+ pubKey = cert
+ } else {
+ err = agent.Add(AddedKey{PrivateKey: key, Comment: "comment", LifetimeSecs: lifetimeSecs})
+ pubKey = signer.PublicKey()
+ }
+ if err != nil {
+ t.Fatalf("insert(%T): %v", key, err)
+ }
+
+ // Did the key get inserted successfully?
+ if keys, err := agent.List(); err != nil {
+ t.Fatalf("List: %v", err)
+ } else if len(keys) != 1 {
+ t.Fatalf("got %v, want 1 key", keys)
+ } else if keys[0].Comment != "comment" {
+ t.Fatalf("key comment: got %v, want %v", keys[0].Comment, "comment")
+ } else if !bytes.Equal(keys[0].Blob, pubKey.Marshal()) {
+ t.Fatalf("key mismatch")
+ }
+
+ // Can the agent make a valid signature?
+ data := []byte("hello")
+ sig, err := agent.Sign(pubKey, data)
+ if err != nil {
+ t.Fatalf("Sign(%s): %v", pubKey.Type(), err)
+ }
+
+ if err := pubKey.Verify(data, sig); err != nil {
+ t.Fatalf("Verify(%s): %v", pubKey.Type(), err)
+ }
+
+ // If the key has a lifetime, is it removed when it should be?
+ if lifetimeSecs > 0 {
+ time.Sleep(time.Second*time.Duration(lifetimeSecs) + 100*time.Millisecond)
+ keys, err := agent.List()
+ if err != nil {
+ t.Fatalf("List: %v", err)
+ }
+ if len(keys) > 0 {
+ t.Fatalf("key not expired")
+ }
+ }
+
+}
+
+func TestAgent(t *testing.T) {
+ for _, keyType := range []string{"rsa", "dsa", "ecdsa", "ed25519"} {
+ testOpenSSHAgent(t, testPrivateKeys[keyType], nil, 0)
+ testKeyringAgent(t, testPrivateKeys[keyType], nil, 0)
+ }
+}
+
+func TestCert(t *testing.T) {
+ cert := &ssh.Certificate{
+ Key: testPublicKeys["rsa"],
+ ValidBefore: ssh.CertTimeInfinity,
+ CertType: ssh.UserCert,
+ }
+ cert.SignCert(rand.Reader, testSigners["ecdsa"])
+
+ testOpenSSHAgent(t, testPrivateKeys["rsa"], cert, 0)
+ testKeyringAgent(t, testPrivateKeys["rsa"], cert, 0)
+}
+
+// netPipe is analogous to net.Pipe, but it uses a real net.Conn, and
+// therefore is buffered (net.Pipe deadlocks if both sides start with
+// a write.)
+func netPipe() (net.Conn, net.Conn, error) {
+ listener, err := net.Listen("tcp", "127.0.0.1:0")
+ if err != nil {
+ listener, err = net.Listen("tcp", "[::1]:0")
+ if err != nil {
+ return nil, nil, err
+ }
+ }
+ defer listener.Close()
+ c1, err := net.Dial("tcp", listener.Addr().String())
+ if err != nil {
+ return nil, nil, err
+ }
+
+ c2, err := listener.Accept()
+ if err != nil {
+ c1.Close()
+ return nil, nil, err
+ }
+
+ return c1, c2, nil
+}
+
+func TestAuth(t *testing.T) {
+ agent, _, cleanup := startOpenSSHAgent(t)
+ defer cleanup()
+
+ a, b, err := netPipe()
+ if err != nil {
+ t.Fatalf("netPipe: %v", err)
+ }
+
+ defer a.Close()
+ defer b.Close()
+
+ if err := agent.Add(AddedKey{PrivateKey: testPrivateKeys["rsa"], Comment: "comment"}); err != nil {
+ t.Errorf("Add: %v", err)
+ }
+
+ serverConf := ssh.ServerConfig{}
+ serverConf.AddHostKey(testSigners["rsa"])
+ serverConf.PublicKeyCallback = func(c ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
+ if bytes.Equal(key.Marshal(), testPublicKeys["rsa"].Marshal()) {
+ return nil, nil
+ }
+
+ return nil, errors.New("pubkey rejected")
+ }
+
+ go func() {
+ conn, _, _, err := ssh.NewServerConn(a, &serverConf)
+ if err != nil {
+ t.Fatalf("Server: %v", err)
+ }
+ conn.Close()
+ }()
+
+ conf := ssh.ClientConfig{
+ HostKeyCallback: ssh.InsecureIgnoreHostKey(),
+ }
+ conf.Auth = append(conf.Auth, ssh.PublicKeysCallback(agent.Signers))
+ conn, _, _, err := ssh.NewClientConn(b, "", &conf)
+ if err != nil {
+ t.Fatalf("NewClientConn: %v", err)
+ }
+ conn.Close()
+}
+
+func TestLockOpenSSHAgent(t *testing.T) {
+ agent, _, cleanup := startOpenSSHAgent(t)
+ defer cleanup()
+ testLockAgent(agent, t)
+}
+
+func TestLockKeyringAgent(t *testing.T) {
+ agent, cleanup := startKeyringAgent(t)
+ defer cleanup()
+ testLockAgent(agent, t)
+}
+
+func testLockAgent(agent Agent, t *testing.T) {
+ if err := agent.Add(AddedKey{PrivateKey: testPrivateKeys["rsa"], Comment: "comment 1"}); err != nil {
+ t.Errorf("Add: %v", err)
+ }
+ if err := agent.Add(AddedKey{PrivateKey: testPrivateKeys["dsa"], Comment: "comment dsa"}); err != nil {
+ t.Errorf("Add: %v", err)
+ }
+ if keys, err := agent.List(); err != nil {
+ t.Errorf("List: %v", err)
+ } else if len(keys) != 2 {
+ t.Errorf("Want 2 keys, got %v", keys)
+ }
+
+ passphrase := []byte("secret")
+ if err := agent.Lock(passphrase); err != nil {
+ t.Errorf("Lock: %v", err)
+ }
+
+ if keys, err := agent.List(); err != nil {
+ t.Errorf("List: %v", err)
+ } else if len(keys) != 0 {
+ t.Errorf("Want 0 keys, got %v", keys)
+ }
+
+ signer, _ := ssh.NewSignerFromKey(testPrivateKeys["rsa"])
+ if _, err := agent.Sign(signer.PublicKey(), []byte("hello")); err == nil {
+ t.Fatalf("Sign did not fail")
+ }
+
+ if err := agent.Remove(signer.PublicKey()); err == nil {
+ t.Fatalf("Remove did not fail")
+ }
+
+ if err := agent.RemoveAll(); err == nil {
+ t.Fatalf("RemoveAll did not fail")
+ }
+
+ if err := agent.Unlock(nil); err == nil {
+ t.Errorf("Unlock with wrong passphrase succeeded")
+ }
+ if err := agent.Unlock(passphrase); err != nil {
+ t.Errorf("Unlock: %v", err)
+ }
+
+ if err := agent.Remove(signer.PublicKey()); err != nil {
+ t.Fatalf("Remove: %v", err)
+ }
+
+ if keys, err := agent.List(); err != nil {
+ t.Errorf("List: %v", err)
+ } else if len(keys) != 1 {
+ t.Errorf("Want 1 keys, got %v", keys)
+ }
+}
+
+func testOpenSSHAgentLifetime(t *testing.T) {
+ agent, _, cleanup := startOpenSSHAgent(t)
+ defer cleanup()
+ testAgentLifetime(t, agent)
+}
+
+func testKeyringAgentLifetime(t *testing.T) {
+ agent, cleanup := startKeyringAgent(t)
+ defer cleanup()
+ testAgentLifetime(t, agent)
+}
+
+func testAgentLifetime(t *testing.T, agent Agent) {
+ for _, keyType := range []string{"rsa", "dsa", "ecdsa"} {
+ // Add private keys to the agent.
+ err := agent.Add(AddedKey{
+ PrivateKey: testPrivateKeys[keyType],
+ Comment: "comment",
+ LifetimeSecs: 1,
+ })
+ if err != nil {
+ t.Fatalf("add: %v", err)
+ }
+ // Add certs to the agent.
+ cert := &ssh.Certificate{
+ Key: testPublicKeys[keyType],
+ ValidBefore: ssh.CertTimeInfinity,
+ CertType: ssh.UserCert,
+ }
+ cert.SignCert(rand.Reader, testSigners[keyType])
+ err = agent.Add(AddedKey{
+ PrivateKey: testPrivateKeys[keyType],
+ Certificate: cert,
+ Comment: "comment",
+ LifetimeSecs: 1,
+ })
+ if err != nil {
+ t.Fatalf("add: %v", err)
+ }
+ }
+ time.Sleep(1100 * time.Millisecond)
+ if keys, err := agent.List(); err != nil {
+ t.Errorf("List: %v", err)
+ } else if len(keys) != 0 {
+ t.Errorf("Want 0 keys, got %v", len(keys))
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/agent/example_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/agent/example_test.go
new file mode 100644
index 000000000..85562253e
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/agent/example_test.go
@@ -0,0 +1,41 @@
+// 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.
+
+package agent_test
+
+import (
+ "log"
+ "net"
+ "os"
+
+ "golang.org/x/crypto/ssh"
+ "golang.org/x/crypto/ssh/agent"
+)
+
+func ExampleClientAgent() {
+ // ssh-agent has a UNIX socket under $SSH_AUTH_SOCK
+ socket := os.Getenv("SSH_AUTH_SOCK")
+ conn, err := net.Dial("unix", socket)
+ if err != nil {
+ log.Fatalf("net.Dial: %v", err)
+ }
+ agentClient := agent.NewClient(conn)
+ config := &ssh.ClientConfig{
+ User: "username",
+ Auth: []ssh.AuthMethod{
+ // Use a callback rather than PublicKeys
+ // so we only consult the agent once the remote server
+ // wants it.
+ ssh.PublicKeysCallback(agentClient.Signers),
+ },
+ HostKeyCallback: ssh.InsecureIgnoreHostKey(),
+ }
+
+ sshc, err := ssh.Dial("tcp", "localhost:22", config)
+ if err != nil {
+ log.Fatalf("Dial: %v", err)
+ }
+ // .. use sshc
+ sshc.Close()
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/agent/forward.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/agent/forward.go
new file mode 100644
index 000000000..fd24ba900
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/agent/forward.go
@@ -0,0 +1,103 @@
+// Copyright 2014 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 agent
+
+import (
+ "errors"
+ "io"
+ "net"
+ "sync"
+
+ "golang.org/x/crypto/ssh"
+)
+
+// RequestAgentForwarding sets up agent forwarding for the session.
+// ForwardToAgent or ForwardToRemote should be called to route
+// the authentication requests.
+func RequestAgentForwarding(session *ssh.Session) error {
+ ok, err := session.SendRequest("auth-agent-req@openssh.com", true, nil)
+ if err != nil {
+ return err
+ }
+ if !ok {
+ return errors.New("forwarding request denied")
+ }
+ return nil
+}
+
+// ForwardToAgent routes authentication requests to the given keyring.
+func ForwardToAgent(client *ssh.Client, keyring Agent) error {
+ channels := client.HandleChannelOpen(channelType)
+ if channels == nil {
+ return errors.New("agent: already have handler for " + channelType)
+ }
+
+ go func() {
+ for ch := range channels {
+ channel, reqs, err := ch.Accept()
+ if err != nil {
+ continue
+ }
+ go ssh.DiscardRequests(reqs)
+ go func() {
+ ServeAgent(keyring, channel)
+ channel.Close()
+ }()
+ }
+ }()
+ return nil
+}
+
+const channelType = "auth-agent@openssh.com"
+
+// ForwardToRemote routes authentication requests to the ssh-agent
+// process serving on the given unix socket.
+func ForwardToRemote(client *ssh.Client, addr string) error {
+ channels := client.HandleChannelOpen(channelType)
+ if channels == nil {
+ return errors.New("agent: already have handler for " + channelType)
+ }
+ conn, err := net.Dial("unix", addr)
+ if err != nil {
+ return err
+ }
+ conn.Close()
+
+ go func() {
+ for ch := range channels {
+ channel, reqs, err := ch.Accept()
+ if err != nil {
+ continue
+ }
+ go ssh.DiscardRequests(reqs)
+ go forwardUnixSocket(channel, addr)
+ }
+ }()
+ return nil
+}
+
+func forwardUnixSocket(channel ssh.Channel, addr string) {
+ conn, err := net.Dial("unix", addr)
+ if err != nil {
+ return
+ }
+
+ var wg sync.WaitGroup
+ wg.Add(2)
+ go func() {
+ io.Copy(conn, channel)
+ conn.(*net.UnixConn).CloseWrite()
+ wg.Done()
+ }()
+ go func() {
+ io.Copy(channel, conn)
+ channel.CloseWrite()
+ wg.Done()
+ }()
+
+ wg.Wait()
+ conn.Close()
+ channel.Close()
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/agent/keyring.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/agent/keyring.go
new file mode 100644
index 000000000..a6ba06ab3
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/agent/keyring.go
@@ -0,0 +1,215 @@
+// Copyright 2014 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 agent
+
+import (
+ "bytes"
+ "crypto/rand"
+ "crypto/subtle"
+ "errors"
+ "fmt"
+ "sync"
+ "time"
+
+ "golang.org/x/crypto/ssh"
+)
+
+type privKey struct {
+ signer ssh.Signer
+ comment string
+ expire *time.Time
+}
+
+type keyring struct {
+ mu sync.Mutex
+ keys []privKey
+
+ locked bool
+ passphrase []byte
+}
+
+var errLocked = errors.New("agent: locked")
+
+// NewKeyring returns an Agent that holds keys in memory. It is safe
+// for concurrent use by multiple goroutines.
+func NewKeyring() Agent {
+ return &keyring{}
+}
+
+// RemoveAll removes all identities.
+func (r *keyring) RemoveAll() error {
+ r.mu.Lock()
+ defer r.mu.Unlock()
+ if r.locked {
+ return errLocked
+ }
+
+ r.keys = nil
+ return nil
+}
+
+// removeLocked does the actual key removal. The caller must already be holding the
+// keyring mutex.
+func (r *keyring) removeLocked(want []byte) error {
+ found := false
+ for i := 0; i < len(r.keys); {
+ if bytes.Equal(r.keys[i].signer.PublicKey().Marshal(), want) {
+ found = true
+ r.keys[i] = r.keys[len(r.keys)-1]
+ r.keys = r.keys[:len(r.keys)-1]
+ continue
+ } else {
+ i++
+ }
+ }
+
+ if !found {
+ return errors.New("agent: key not found")
+ }
+ return nil
+}
+
+// Remove removes all identities with the given public key.
+func (r *keyring) Remove(key ssh.PublicKey) error {
+ r.mu.Lock()
+ defer r.mu.Unlock()
+ if r.locked {
+ return errLocked
+ }
+
+ return r.removeLocked(key.Marshal())
+}
+
+// Lock locks the agent. Sign and Remove will fail, and List will return an empty list.
+func (r *keyring) Lock(passphrase []byte) error {
+ r.mu.Lock()
+ defer r.mu.Unlock()
+ if r.locked {
+ return errLocked
+ }
+
+ r.locked = true
+ r.passphrase = passphrase
+ return nil
+}
+
+// Unlock undoes the effect of Lock
+func (r *keyring) Unlock(passphrase []byte) error {
+ r.mu.Lock()
+ defer r.mu.Unlock()
+ if !r.locked {
+ return errors.New("agent: not locked")
+ }
+ if len(passphrase) != len(r.passphrase) || 1 != subtle.ConstantTimeCompare(passphrase, r.passphrase) {
+ return fmt.Errorf("agent: incorrect passphrase")
+ }
+
+ r.locked = false
+ r.passphrase = nil
+ return nil
+}
+
+// expireKeysLocked removes expired keys from the keyring. If a key was added
+// with a lifetimesecs contraint and seconds >= lifetimesecs seconds have
+// ellapsed, it is removed. The caller *must* be holding the keyring mutex.
+func (r *keyring) expireKeysLocked() {
+ for _, k := range r.keys {
+ if k.expire != nil && time.Now().After(*k.expire) {
+ r.removeLocked(k.signer.PublicKey().Marshal())
+ }
+ }
+}
+
+// List returns the identities known to the agent.
+func (r *keyring) List() ([]*Key, error) {
+ r.mu.Lock()
+ defer r.mu.Unlock()
+ if r.locked {
+ // section 2.7: locked agents return empty.
+ return nil, nil
+ }
+
+ r.expireKeysLocked()
+ var ids []*Key
+ for _, k := range r.keys {
+ pub := k.signer.PublicKey()
+ ids = append(ids, &Key{
+ Format: pub.Type(),
+ Blob: pub.Marshal(),
+ Comment: k.comment})
+ }
+ return ids, nil
+}
+
+// Insert adds a private key to the keyring. If a certificate
+// is given, that certificate is added as public key. Note that
+// any constraints given are ignored.
+func (r *keyring) Add(key AddedKey) error {
+ r.mu.Lock()
+ defer r.mu.Unlock()
+ if r.locked {
+ return errLocked
+ }
+ signer, err := ssh.NewSignerFromKey(key.PrivateKey)
+
+ if err != nil {
+ return err
+ }
+
+ if cert := key.Certificate; cert != nil {
+ signer, err = ssh.NewCertSigner(cert, signer)
+ if err != nil {
+ return err
+ }
+ }
+
+ p := privKey{
+ signer: signer,
+ comment: key.Comment,
+ }
+
+ if key.LifetimeSecs > 0 {
+ t := time.Now().Add(time.Duration(key.LifetimeSecs) * time.Second)
+ p.expire = &t
+ }
+
+ r.keys = append(r.keys, p)
+
+ return nil
+}
+
+// Sign returns a signature for the data.
+func (r *keyring) Sign(key ssh.PublicKey, data []byte) (*ssh.Signature, error) {
+ r.mu.Lock()
+ defer r.mu.Unlock()
+ if r.locked {
+ return nil, errLocked
+ }
+
+ r.expireKeysLocked()
+ wanted := key.Marshal()
+ for _, k := range r.keys {
+ if bytes.Equal(k.signer.PublicKey().Marshal(), wanted) {
+ return k.signer.Sign(rand.Reader, data)
+ }
+ }
+ return nil, errors.New("not found")
+}
+
+// Signers returns signers for all the known keys.
+func (r *keyring) Signers() ([]ssh.Signer, error) {
+ r.mu.Lock()
+ defer r.mu.Unlock()
+ if r.locked {
+ return nil, errLocked
+ }
+
+ r.expireKeysLocked()
+ s := make([]ssh.Signer, 0, len(r.keys))
+ for _, k := range r.keys {
+ s = append(s, k.signer)
+ }
+ return s, nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/agent/keyring_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/agent/keyring_test.go
new file mode 100644
index 000000000..e5d50e7e0
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/agent/keyring_test.go
@@ -0,0 +1,76 @@
+// Copyright 2015 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 agent
+
+import "testing"
+
+func addTestKey(t *testing.T, a Agent, keyName string) {
+ err := a.Add(AddedKey{
+ PrivateKey: testPrivateKeys[keyName],
+ Comment: keyName,
+ })
+ if err != nil {
+ t.Fatalf("failed to add key %q: %v", keyName, err)
+ }
+}
+
+func removeTestKey(t *testing.T, a Agent, keyName string) {
+ err := a.Remove(testPublicKeys[keyName])
+ if err != nil {
+ t.Fatalf("failed to remove key %q: %v", keyName, err)
+ }
+}
+
+func validateListedKeys(t *testing.T, a Agent, expectedKeys []string) {
+ listedKeys, err := a.List()
+ if err != nil {
+ t.Fatalf("failed to list keys: %v", err)
+ return
+ }
+ actualKeys := make(map[string]bool)
+ for _, key := range listedKeys {
+ actualKeys[key.Comment] = true
+ }
+
+ matchedKeys := make(map[string]bool)
+ for _, expectedKey := range expectedKeys {
+ if !actualKeys[expectedKey] {
+ t.Fatalf("expected key %q, but was not found", expectedKey)
+ } else {
+ matchedKeys[expectedKey] = true
+ }
+ }
+
+ for actualKey := range actualKeys {
+ if !matchedKeys[actualKey] {
+ t.Fatalf("key %q was found, but was not expected", actualKey)
+ }
+ }
+}
+
+func TestKeyringAddingAndRemoving(t *testing.T) {
+ keyNames := []string{"dsa", "ecdsa", "rsa", "user"}
+
+ // add all test private keys
+ k := NewKeyring()
+ for _, keyName := range keyNames {
+ addTestKey(t, k, keyName)
+ }
+ validateListedKeys(t, k, keyNames)
+
+ // remove a key in the middle
+ keyToRemove := keyNames[1]
+ keyNames = append(keyNames[:1], keyNames[2:]...)
+
+ removeTestKey(t, k, keyToRemove)
+ validateListedKeys(t, k, keyNames)
+
+ // remove all keys
+ err := k.RemoveAll()
+ if err != nil {
+ t.Fatalf("failed to remove all keys: %v", err)
+ }
+ validateListedKeys(t, k, []string{})
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/agent/server.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/agent/server.go
new file mode 100644
index 000000000..321e48a26
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/agent/server.go
@@ -0,0 +1,523 @@
+// Copyright 2012 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 agent
+
+import (
+ "crypto/dsa"
+ "crypto/ecdsa"
+ "crypto/elliptic"
+ "crypto/rsa"
+ "encoding/binary"
+ "errors"
+ "fmt"
+ "io"
+ "log"
+ "math/big"
+
+ "golang.org/x/crypto/ed25519"
+ "golang.org/x/crypto/ssh"
+)
+
+// Server wraps an Agent and uses it to implement the agent side of
+// the SSH-agent, wire protocol.
+type server struct {
+ agent Agent
+}
+
+func (s *server) processRequestBytes(reqData []byte) []byte {
+ rep, err := s.processRequest(reqData)
+ if err != nil {
+ if err != errLocked {
+ // TODO(hanwen): provide better logging interface?
+ log.Printf("agent %d: %v", reqData[0], err)
+ }
+ return []byte{agentFailure}
+ }
+
+ if err == nil && rep == nil {
+ return []byte{agentSuccess}
+ }
+
+ return ssh.Marshal(rep)
+}
+
+func marshalKey(k *Key) []byte {
+ var record struct {
+ Blob []byte
+ Comment string
+ }
+ record.Blob = k.Marshal()
+ record.Comment = k.Comment
+
+ return ssh.Marshal(&record)
+}
+
+// See [PROTOCOL.agent], section 2.5.1.
+const agentV1IdentitiesAnswer = 2
+
+type agentV1IdentityMsg struct {
+ Numkeys uint32 `sshtype:"2"`
+}
+
+type agentRemoveIdentityMsg struct {
+ KeyBlob []byte `sshtype:"18"`
+}
+
+type agentLockMsg struct {
+ Passphrase []byte `sshtype:"22"`
+}
+
+type agentUnlockMsg struct {
+ Passphrase []byte `sshtype:"23"`
+}
+
+func (s *server) processRequest(data []byte) (interface{}, error) {
+ switch data[0] {
+ case agentRequestV1Identities:
+ return &agentV1IdentityMsg{0}, nil
+
+ case agentRemoveAllV1Identities:
+ return nil, nil
+
+ case agentRemoveIdentity:
+ var req agentRemoveIdentityMsg
+ if err := ssh.Unmarshal(data, &req); err != nil {
+ return nil, err
+ }
+
+ var wk wireKey
+ if err := ssh.Unmarshal(req.KeyBlob, &wk); err != nil {
+ return nil, err
+ }
+
+ return nil, s.agent.Remove(&Key{Format: wk.Format, Blob: req.KeyBlob})
+
+ case agentRemoveAllIdentities:
+ return nil, s.agent.RemoveAll()
+
+ case agentLock:
+ var req agentLockMsg
+ if err := ssh.Unmarshal(data, &req); err != nil {
+ return nil, err
+ }
+
+ return nil, s.agent.Lock(req.Passphrase)
+
+ case agentUnlock:
+ var req agentUnlockMsg
+ if err := ssh.Unmarshal(data, &req); err != nil {
+ return nil, err
+ }
+ return nil, s.agent.Unlock(req.Passphrase)
+
+ case agentSignRequest:
+ var req signRequestAgentMsg
+ if err := ssh.Unmarshal(data, &req); err != nil {
+ return nil, err
+ }
+
+ var wk wireKey
+ if err := ssh.Unmarshal(req.KeyBlob, &wk); err != nil {
+ return nil, err
+ }
+
+ k := &Key{
+ Format: wk.Format,
+ Blob: req.KeyBlob,
+ }
+
+ sig, err := s.agent.Sign(k, req.Data) // TODO(hanwen): flags.
+ if err != nil {
+ return nil, err
+ }
+ return &signResponseAgentMsg{SigBlob: ssh.Marshal(sig)}, nil
+
+ case agentRequestIdentities:
+ keys, err := s.agent.List()
+ if err != nil {
+ return nil, err
+ }
+
+ rep := identitiesAnswerAgentMsg{
+ NumKeys: uint32(len(keys)),
+ }
+ for _, k := range keys {
+ rep.Keys = append(rep.Keys, marshalKey(k)...)
+ }
+ return rep, nil
+
+ case agentAddIdConstrained, agentAddIdentity:
+ return nil, s.insertIdentity(data)
+ }
+
+ return nil, fmt.Errorf("unknown opcode %d", data[0])
+}
+
+func parseConstraints(constraints []byte) (lifetimeSecs uint32, confirmBeforeUse bool, extensions []ConstraintExtension, err error) {
+ for len(constraints) != 0 {
+ switch constraints[0] {
+ case agentConstrainLifetime:
+ lifetimeSecs = binary.BigEndian.Uint32(constraints[1:5])
+ constraints = constraints[5:]
+ case agentConstrainConfirm:
+ confirmBeforeUse = true
+ constraints = constraints[1:]
+ case agentConstrainExtension:
+ var msg constrainExtensionAgentMsg
+ if err = ssh.Unmarshal(constraints, &msg); err != nil {
+ return 0, false, nil, err
+ }
+ extensions = append(extensions, ConstraintExtension{
+ ExtensionName: msg.ExtensionName,
+ ExtensionDetails: msg.ExtensionDetails,
+ })
+ constraints = msg.Rest
+ default:
+ return 0, false, nil, fmt.Errorf("unknown constraint type: %d", constraints[0])
+ }
+ }
+ return
+}
+
+func setConstraints(key *AddedKey, constraintBytes []byte) error {
+ lifetimeSecs, confirmBeforeUse, constraintExtensions, err := parseConstraints(constraintBytes)
+ if err != nil {
+ return err
+ }
+
+ key.LifetimeSecs = lifetimeSecs
+ key.ConfirmBeforeUse = confirmBeforeUse
+ key.ConstraintExtensions = constraintExtensions
+ return nil
+}
+
+func parseRSAKey(req []byte) (*AddedKey, error) {
+ var k rsaKeyMsg
+ if err := ssh.Unmarshal(req, &k); err != nil {
+ return nil, err
+ }
+ if k.E.BitLen() > 30 {
+ return nil, errors.New("agent: RSA public exponent too large")
+ }
+ priv := &rsa.PrivateKey{
+ PublicKey: rsa.PublicKey{
+ E: int(k.E.Int64()),
+ N: k.N,
+ },
+ D: k.D,
+ Primes: []*big.Int{k.P, k.Q},
+ }
+ priv.Precompute()
+
+ addedKey := &AddedKey{PrivateKey: priv, Comment: k.Comments}
+ if err := setConstraints(addedKey, k.Constraints); err != nil {
+ return nil, err
+ }
+ return addedKey, nil
+}
+
+func parseEd25519Key(req []byte) (*AddedKey, error) {
+ var k ed25519KeyMsg
+ if err := ssh.Unmarshal(req, &k); err != nil {
+ return nil, err
+ }
+ priv := ed25519.PrivateKey(k.Priv)
+
+ addedKey := &AddedKey{PrivateKey: &priv, Comment: k.Comments}
+ if err := setConstraints(addedKey, k.Constraints); err != nil {
+ return nil, err
+ }
+ return addedKey, nil
+}
+
+func parseDSAKey(req []byte) (*AddedKey, error) {
+ var k dsaKeyMsg
+ if err := ssh.Unmarshal(req, &k); err != nil {
+ return nil, err
+ }
+ priv := &dsa.PrivateKey{
+ PublicKey: dsa.PublicKey{
+ Parameters: dsa.Parameters{
+ P: k.P,
+ Q: k.Q,
+ G: k.G,
+ },
+ Y: k.Y,
+ },
+ X: k.X,
+ }
+
+ addedKey := &AddedKey{PrivateKey: priv, Comment: k.Comments}
+ if err := setConstraints(addedKey, k.Constraints); err != nil {
+ return nil, err
+ }
+ return addedKey, nil
+}
+
+func unmarshalECDSA(curveName string, keyBytes []byte, privScalar *big.Int) (priv *ecdsa.PrivateKey, err error) {
+ priv = &ecdsa.PrivateKey{
+ D: privScalar,
+ }
+
+ switch curveName {
+ case "nistp256":
+ priv.Curve = elliptic.P256()
+ case "nistp384":
+ priv.Curve = elliptic.P384()
+ case "nistp521":
+ priv.Curve = elliptic.P521()
+ default:
+ return nil, fmt.Errorf("agent: unknown curve %q", curveName)
+ }
+
+ priv.X, priv.Y = elliptic.Unmarshal(priv.Curve, keyBytes)
+ if priv.X == nil || priv.Y == nil {
+ return nil, errors.New("agent: point not on curve")
+ }
+
+ return priv, nil
+}
+
+func parseEd25519Cert(req []byte) (*AddedKey, error) {
+ var k ed25519CertMsg
+ if err := ssh.Unmarshal(req, &k); err != nil {
+ return nil, err
+ }
+ pubKey, err := ssh.ParsePublicKey(k.CertBytes)
+ if err != nil {
+ return nil, err
+ }
+ priv := ed25519.PrivateKey(k.Priv)
+ cert, ok := pubKey.(*ssh.Certificate)
+ if !ok {
+ return nil, errors.New("agent: bad ED25519 certificate")
+ }
+
+ addedKey := &AddedKey{PrivateKey: &priv, Certificate: cert, Comment: k.Comments}
+ if err := setConstraints(addedKey, k.Constraints); err != nil {
+ return nil, err
+ }
+ return addedKey, nil
+}
+
+func parseECDSAKey(req []byte) (*AddedKey, error) {
+ var k ecdsaKeyMsg
+ if err := ssh.Unmarshal(req, &k); err != nil {
+ return nil, err
+ }
+
+ priv, err := unmarshalECDSA(k.Curve, k.KeyBytes, k.D)
+ if err != nil {
+ return nil, err
+ }
+
+ addedKey := &AddedKey{PrivateKey: priv, Comment: k.Comments}
+ if err := setConstraints(addedKey, k.Constraints); err != nil {
+ return nil, err
+ }
+ return addedKey, nil
+}
+
+func parseRSACert(req []byte) (*AddedKey, error) {
+ var k rsaCertMsg
+ if err := ssh.Unmarshal(req, &k); err != nil {
+ return nil, err
+ }
+
+ pubKey, err := ssh.ParsePublicKey(k.CertBytes)
+ if err != nil {
+ return nil, err
+ }
+
+ cert, ok := pubKey.(*ssh.Certificate)
+ if !ok {
+ return nil, errors.New("agent: bad RSA certificate")
+ }
+
+ // An RSA publickey as marshaled by rsaPublicKey.Marshal() in keys.go
+ var rsaPub struct {
+ Name string
+ E *big.Int
+ N *big.Int
+ }
+ if err := ssh.Unmarshal(cert.Key.Marshal(), &rsaPub); err != nil {
+ return nil, fmt.Errorf("agent: Unmarshal failed to parse public key: %v", err)
+ }
+
+ if rsaPub.E.BitLen() > 30 {
+ return nil, errors.New("agent: RSA public exponent too large")
+ }
+
+ priv := rsa.PrivateKey{
+ PublicKey: rsa.PublicKey{
+ E: int(rsaPub.E.Int64()),
+ N: rsaPub.N,
+ },
+ D: k.D,
+ Primes: []*big.Int{k.Q, k.P},
+ }
+ priv.Precompute()
+
+ addedKey := &AddedKey{PrivateKey: &priv, Certificate: cert, Comment: k.Comments}
+ if err := setConstraints(addedKey, k.Constraints); err != nil {
+ return nil, err
+ }
+ return addedKey, nil
+}
+
+func parseDSACert(req []byte) (*AddedKey, error) {
+ var k dsaCertMsg
+ if err := ssh.Unmarshal(req, &k); err != nil {
+ return nil, err
+ }
+ pubKey, err := ssh.ParsePublicKey(k.CertBytes)
+ if err != nil {
+ return nil, err
+ }
+ cert, ok := pubKey.(*ssh.Certificate)
+ if !ok {
+ return nil, errors.New("agent: bad DSA certificate")
+ }
+
+ // A DSA publickey as marshaled by dsaPublicKey.Marshal() in keys.go
+ var w struct {
+ Name string
+ P, Q, G, Y *big.Int
+ }
+ if err := ssh.Unmarshal(cert.Key.Marshal(), &w); err != nil {
+ return nil, fmt.Errorf("agent: Unmarshal failed to parse public key: %v", err)
+ }
+
+ priv := &dsa.PrivateKey{
+ PublicKey: dsa.PublicKey{
+ Parameters: dsa.Parameters{
+ P: w.P,
+ Q: w.Q,
+ G: w.G,
+ },
+ Y: w.Y,
+ },
+ X: k.X,
+ }
+
+ addedKey := &AddedKey{PrivateKey: priv, Certificate: cert, Comment: k.Comments}
+ if err := setConstraints(addedKey, k.Constraints); err != nil {
+ return nil, err
+ }
+ return addedKey, nil
+}
+
+func parseECDSACert(req []byte) (*AddedKey, error) {
+ var k ecdsaCertMsg
+ if err := ssh.Unmarshal(req, &k); err != nil {
+ return nil, err
+ }
+
+ pubKey, err := ssh.ParsePublicKey(k.CertBytes)
+ if err != nil {
+ return nil, err
+ }
+ cert, ok := pubKey.(*ssh.Certificate)
+ if !ok {
+ return nil, errors.New("agent: bad ECDSA certificate")
+ }
+
+ // An ECDSA publickey as marshaled by ecdsaPublicKey.Marshal() in keys.go
+ var ecdsaPub struct {
+ Name string
+ ID string
+ Key []byte
+ }
+ if err := ssh.Unmarshal(cert.Key.Marshal(), &ecdsaPub); err != nil {
+ return nil, err
+ }
+
+ priv, err := unmarshalECDSA(ecdsaPub.ID, ecdsaPub.Key, k.D)
+ if err != nil {
+ return nil, err
+ }
+
+ addedKey := &AddedKey{PrivateKey: priv, Certificate: cert, Comment: k.Comments}
+ if err := setConstraints(addedKey, k.Constraints); err != nil {
+ return nil, err
+ }
+ return addedKey, nil
+}
+
+func (s *server) insertIdentity(req []byte) error {
+ var record struct {
+ Type string `sshtype:"17|25"`
+ Rest []byte `ssh:"rest"`
+ }
+
+ if err := ssh.Unmarshal(req, &record); err != nil {
+ return err
+ }
+
+ var addedKey *AddedKey
+ var err error
+
+ switch record.Type {
+ case ssh.KeyAlgoRSA:
+ addedKey, err = parseRSAKey(req)
+ case ssh.KeyAlgoDSA:
+ addedKey, err = parseDSAKey(req)
+ case ssh.KeyAlgoECDSA256, ssh.KeyAlgoECDSA384, ssh.KeyAlgoECDSA521:
+ addedKey, err = parseECDSAKey(req)
+ case ssh.KeyAlgoED25519:
+ addedKey, err = parseEd25519Key(req)
+ case ssh.CertAlgoRSAv01:
+ addedKey, err = parseRSACert(req)
+ case ssh.CertAlgoDSAv01:
+ addedKey, err = parseDSACert(req)
+ case ssh.CertAlgoECDSA256v01, ssh.CertAlgoECDSA384v01, ssh.CertAlgoECDSA521v01:
+ addedKey, err = parseECDSACert(req)
+ case ssh.CertAlgoED25519v01:
+ addedKey, err = parseEd25519Cert(req)
+ default:
+ return fmt.Errorf("agent: not implemented: %q", record.Type)
+ }
+
+ if err != nil {
+ return err
+ }
+ return s.agent.Add(*addedKey)
+}
+
+// ServeAgent serves the agent protocol on the given connection. It
+// returns when an I/O error occurs.
+func ServeAgent(agent Agent, c io.ReadWriter) error {
+ s := &server{agent}
+
+ var length [4]byte
+ for {
+ if _, err := io.ReadFull(c, length[:]); err != nil {
+ return err
+ }
+ l := binary.BigEndian.Uint32(length[:])
+ if l > maxAgentResponseBytes {
+ // We also cap requests.
+ return fmt.Errorf("agent: request too large: %d", l)
+ }
+
+ req := make([]byte, l)
+ if _, err := io.ReadFull(c, req); err != nil {
+ return err
+ }
+
+ repData := s.processRequestBytes(req)
+ if len(repData) > maxAgentResponseBytes {
+ return fmt.Errorf("agent: reply too large: %d bytes", len(repData))
+ }
+
+ binary.BigEndian.PutUint32(length[:], uint32(len(repData)))
+ if _, err := c.Write(length[:]); err != nil {
+ return err
+ }
+ if _, err := c.Write(repData); err != nil {
+ return err
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/agent/server_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/agent/server_test.go
new file mode 100644
index 000000000..038018ebb
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/agent/server_test.go
@@ -0,0 +1,259 @@
+// Copyright 2012 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 agent
+
+import (
+ "crypto"
+ "crypto/rand"
+ "fmt"
+ pseudorand "math/rand"
+ "reflect"
+ "strings"
+ "testing"
+
+ "golang.org/x/crypto/ssh"
+)
+
+func TestServer(t *testing.T) {
+ c1, c2, err := netPipe()
+ if err != nil {
+ t.Fatalf("netPipe: %v", err)
+ }
+ defer c1.Close()
+ defer c2.Close()
+ client := NewClient(c1)
+
+ go ServeAgent(NewKeyring(), c2)
+
+ testAgentInterface(t, client, testPrivateKeys["rsa"], nil, 0)
+}
+
+func TestLockServer(t *testing.T) {
+ testLockAgent(NewKeyring(), t)
+}
+
+func TestSetupForwardAgent(t *testing.T) {
+ a, b, err := netPipe()
+ if err != nil {
+ t.Fatalf("netPipe: %v", err)
+ }
+
+ defer a.Close()
+ defer b.Close()
+
+ _, socket, cleanup := startOpenSSHAgent(t)
+ defer cleanup()
+
+ serverConf := ssh.ServerConfig{
+ NoClientAuth: true,
+ }
+ serverConf.AddHostKey(testSigners["rsa"])
+ incoming := make(chan *ssh.ServerConn, 1)
+ go func() {
+ conn, _, _, err := ssh.NewServerConn(a, &serverConf)
+ if err != nil {
+ t.Fatalf("Server: %v", err)
+ }
+ incoming <- conn
+ }()
+
+ conf := ssh.ClientConfig{
+ HostKeyCallback: ssh.InsecureIgnoreHostKey(),
+ }
+ conn, chans, reqs, err := ssh.NewClientConn(b, "", &conf)
+ if err != nil {
+ t.Fatalf("NewClientConn: %v", err)
+ }
+ client := ssh.NewClient(conn, chans, reqs)
+
+ if err := ForwardToRemote(client, socket); err != nil {
+ t.Fatalf("SetupForwardAgent: %v", err)
+ }
+
+ server := <-incoming
+ ch, reqs, err := server.OpenChannel(channelType, nil)
+ if err != nil {
+ t.Fatalf("OpenChannel(%q): %v", channelType, err)
+ }
+ go ssh.DiscardRequests(reqs)
+
+ agentClient := NewClient(ch)
+ testAgentInterface(t, agentClient, testPrivateKeys["rsa"], nil, 0)
+ conn.Close()
+}
+
+func TestV1ProtocolMessages(t *testing.T) {
+ c1, c2, err := netPipe()
+ if err != nil {
+ t.Fatalf("netPipe: %v", err)
+ }
+ defer c1.Close()
+ defer c2.Close()
+ c := NewClient(c1)
+
+ go ServeAgent(NewKeyring(), c2)
+
+ testV1ProtocolMessages(t, c.(*client))
+}
+
+func testV1ProtocolMessages(t *testing.T, c *client) {
+ reply, err := c.call([]byte{agentRequestV1Identities})
+ if err != nil {
+ t.Fatalf("v1 request all failed: %v", err)
+ }
+ if msg, ok := reply.(*agentV1IdentityMsg); !ok || msg.Numkeys != 0 {
+ t.Fatalf("invalid request all response: %#v", reply)
+ }
+
+ reply, err = c.call([]byte{agentRemoveAllV1Identities})
+ if err != nil {
+ t.Fatalf("v1 remove all failed: %v", err)
+ }
+ if _, ok := reply.(*successAgentMsg); !ok {
+ t.Fatalf("invalid remove all response: %#v", reply)
+ }
+}
+
+func verifyKey(sshAgent Agent) error {
+ keys, err := sshAgent.List()
+ if err != nil {
+ return fmt.Errorf("listing keys: %v", err)
+ }
+
+ if len(keys) != 1 {
+ return fmt.Errorf("bad number of keys found. expected 1, got %d", len(keys))
+ }
+
+ buf := make([]byte, 128)
+ if _, err := rand.Read(buf); err != nil {
+ return fmt.Errorf("rand: %v", err)
+ }
+
+ sig, err := sshAgent.Sign(keys[0], buf)
+ if err != nil {
+ return fmt.Errorf("sign: %v", err)
+ }
+
+ if err := keys[0].Verify(buf, sig); err != nil {
+ return fmt.Errorf("verify: %v", err)
+ }
+ return nil
+}
+
+func addKeyToAgent(key crypto.PrivateKey) error {
+ sshAgent := NewKeyring()
+ if err := sshAgent.Add(AddedKey{PrivateKey: key}); err != nil {
+ return fmt.Errorf("add: %v", err)
+ }
+ return verifyKey(sshAgent)
+}
+
+func TestKeyTypes(t *testing.T) {
+ for k, v := range testPrivateKeys {
+ if err := addKeyToAgent(v); err != nil {
+ t.Errorf("error adding key type %s, %v", k, err)
+ }
+ if err := addCertToAgentSock(v, nil); err != nil {
+ t.Errorf("error adding key type %s, %v", k, err)
+ }
+ }
+}
+
+func addCertToAgentSock(key crypto.PrivateKey, cert *ssh.Certificate) error {
+ a, b, err := netPipe()
+ if err != nil {
+ return err
+ }
+ agentServer := NewKeyring()
+ go ServeAgent(agentServer, a)
+
+ agentClient := NewClient(b)
+ if err := agentClient.Add(AddedKey{PrivateKey: key, Certificate: cert}); err != nil {
+ return fmt.Errorf("add: %v", err)
+ }
+ return verifyKey(agentClient)
+}
+
+func addCertToAgent(key crypto.PrivateKey, cert *ssh.Certificate) error {
+ sshAgent := NewKeyring()
+ if err := sshAgent.Add(AddedKey{PrivateKey: key, Certificate: cert}); err != nil {
+ return fmt.Errorf("add: %v", err)
+ }
+ return verifyKey(sshAgent)
+}
+
+func TestCertTypes(t *testing.T) {
+ for keyType, key := range testPublicKeys {
+ cert := &ssh.Certificate{
+ ValidPrincipals: []string{"gopher1"},
+ ValidAfter: 0,
+ ValidBefore: ssh.CertTimeInfinity,
+ Key: key,
+ Serial: 1,
+ CertType: ssh.UserCert,
+ SignatureKey: testPublicKeys["rsa"],
+ Permissions: ssh.Permissions{
+ CriticalOptions: map[string]string{},
+ Extensions: map[string]string{},
+ },
+ }
+ if err := cert.SignCert(rand.Reader, testSigners["rsa"]); err != nil {
+ t.Fatalf("signcert: %v", err)
+ }
+ if err := addCertToAgent(testPrivateKeys[keyType], cert); err != nil {
+ t.Fatalf("%v", err)
+ }
+ if err := addCertToAgentSock(testPrivateKeys[keyType], cert); err != nil {
+ t.Fatalf("%v", err)
+ }
+ }
+}
+
+func TestParseConstraints(t *testing.T) {
+ // Test LifetimeSecs
+ var msg = constrainLifetimeAgentMsg{pseudorand.Uint32()}
+ lifetimeSecs, _, _, err := parseConstraints(ssh.Marshal(msg))
+ if err != nil {
+ t.Fatalf("parseConstraints: %v", err)
+ }
+ if lifetimeSecs != msg.LifetimeSecs {
+ t.Errorf("got lifetime %v, want %v", lifetimeSecs, msg.LifetimeSecs)
+ }
+
+ // Test ConfirmBeforeUse
+ _, confirmBeforeUse, _, err := parseConstraints([]byte{agentConstrainConfirm})
+ if err != nil {
+ t.Fatalf("%v", err)
+ }
+ if !confirmBeforeUse {
+ t.Error("got comfirmBeforeUse == false")
+ }
+
+ // Test ConstraintExtensions
+ var data []byte
+ var expect []ConstraintExtension
+ for i := 0; i < 10; i++ {
+ var ext = ConstraintExtension{
+ ExtensionName: fmt.Sprintf("name%d", i),
+ ExtensionDetails: []byte(fmt.Sprintf("details: %d", i)),
+ }
+ expect = append(expect, ext)
+ data = append(data, agentConstrainExtension)
+ data = append(data, ssh.Marshal(ext)...)
+ }
+ _, _, extensions, err := parseConstraints(data)
+ if err != nil {
+ t.Fatalf("%v", err)
+ }
+ if !reflect.DeepEqual(expect, extensions) {
+ t.Errorf("got extension %v, want %v", extensions, expect)
+ }
+
+ // Test Unknown Constraint
+ _, _, _, err = parseConstraints([]byte{128})
+ if err == nil || !strings.Contains(err.Error(), "unknown constraint") {
+ t.Errorf("unexpected error: %v", err)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/agent/testdata_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/agent/testdata_test.go
new file mode 100644
index 000000000..cc42a87cb
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/agent/testdata_test.go
@@ -0,0 +1,64 @@
+// Copyright 2014 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.
+
+// IMPLEMENTATION NOTE: To avoid a package loop, this file is in three places:
+// ssh/, ssh/agent, and ssh/test/. It should be kept in sync across all three
+// instances.
+
+package agent
+
+import (
+ "crypto/rand"
+ "fmt"
+
+ "golang.org/x/crypto/ssh"
+ "golang.org/x/crypto/ssh/testdata"
+)
+
+var (
+ testPrivateKeys map[string]interface{}
+ testSigners map[string]ssh.Signer
+ testPublicKeys map[string]ssh.PublicKey
+)
+
+func init() {
+ var err error
+
+ n := len(testdata.PEMBytes)
+ testPrivateKeys = make(map[string]interface{}, n)
+ testSigners = make(map[string]ssh.Signer, n)
+ testPublicKeys = make(map[string]ssh.PublicKey, n)
+ for t, k := range testdata.PEMBytes {
+ testPrivateKeys[t], err = ssh.ParseRawPrivateKey(k)
+ if err != nil {
+ panic(fmt.Sprintf("Unable to parse test key %s: %v", t, err))
+ }
+ testSigners[t], err = ssh.NewSignerFromKey(testPrivateKeys[t])
+ if err != nil {
+ panic(fmt.Sprintf("Unable to create signer for test key %s: %v", t, err))
+ }
+ testPublicKeys[t] = testSigners[t].PublicKey()
+ }
+
+ // Create a cert and sign it for use in tests.
+ testCert := &ssh.Certificate{
+ Nonce: []byte{}, // To pass reflect.DeepEqual after marshal & parse, this must be non-nil
+ ValidPrincipals: []string{"gopher1", "gopher2"}, // increases test coverage
+ ValidAfter: 0, // unix epoch
+ ValidBefore: ssh.CertTimeInfinity, // The end of currently representable time.
+ Reserved: []byte{}, // To pass reflect.DeepEqual after marshal & parse, this must be non-nil
+ Key: testPublicKeys["ecdsa"],
+ SignatureKey: testPublicKeys["rsa"],
+ Permissions: ssh.Permissions{
+ CriticalOptions: map[string]string{},
+ Extensions: map[string]string{},
+ },
+ }
+ testCert.SignCert(rand.Reader, testSigners["rsa"])
+ testPrivateKeys["cert"] = testPrivateKeys["ecdsa"]
+ testSigners["cert"], err = ssh.NewCertSigner(testCert, testSigners["ecdsa"])
+ if err != nil {
+ panic(fmt.Sprintf("Unable to create certificate signer: %v", err))
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/benchmark_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/benchmark_test.go
new file mode 100644
index 000000000..d9f7eb9b6
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/benchmark_test.go
@@ -0,0 +1,122 @@
+// Copyright 2013 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 ssh
+
+import (
+ "errors"
+ "io"
+ "net"
+ "testing"
+)
+
+type server struct {
+ *ServerConn
+ chans <-chan NewChannel
+}
+
+func newServer(c net.Conn, conf *ServerConfig) (*server, error) {
+ sconn, chans, reqs, err := NewServerConn(c, conf)
+ if err != nil {
+ return nil, err
+ }
+ go DiscardRequests(reqs)
+ return &server{sconn, chans}, nil
+}
+
+func (s *server) Accept() (NewChannel, error) {
+ n, ok := <-s.chans
+ if !ok {
+ return nil, io.EOF
+ }
+ return n, nil
+}
+
+func sshPipe() (Conn, *server, error) {
+ c1, c2, err := netPipe()
+ if err != nil {
+ return nil, nil, err
+ }
+
+ clientConf := ClientConfig{
+ User: "user",
+ }
+ serverConf := ServerConfig{
+ NoClientAuth: true,
+ }
+ serverConf.AddHostKey(testSigners["ecdsa"])
+ done := make(chan *server, 1)
+ go func() {
+ server, err := newServer(c2, &serverConf)
+ if err != nil {
+ done <- nil
+ }
+ done <- server
+ }()
+
+ client, _, reqs, err := NewClientConn(c1, "", &clientConf)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ server := <-done
+ if server == nil {
+ return nil, nil, errors.New("server handshake failed.")
+ }
+ go DiscardRequests(reqs)
+
+ return client, server, nil
+}
+
+func BenchmarkEndToEnd(b *testing.B) {
+ b.StopTimer()
+
+ client, server, err := sshPipe()
+ if err != nil {
+ b.Fatalf("sshPipe: %v", err)
+ }
+
+ defer client.Close()
+ defer server.Close()
+
+ size := (1 << 20)
+ input := make([]byte, size)
+ output := make([]byte, size)
+ b.SetBytes(int64(size))
+ done := make(chan int, 1)
+
+ go func() {
+ newCh, err := server.Accept()
+ if err != nil {
+ b.Fatalf("Client: %v", err)
+ }
+ ch, incoming, err := newCh.Accept()
+ go DiscardRequests(incoming)
+ for i := 0; i < b.N; i++ {
+ if _, err := io.ReadFull(ch, output); err != nil {
+ b.Fatalf("ReadFull: %v", err)
+ }
+ }
+ ch.Close()
+ done <- 1
+ }()
+
+ ch, in, err := client.OpenChannel("speed", nil)
+ if err != nil {
+ b.Fatalf("OpenChannel: %v", err)
+ }
+ go DiscardRequests(in)
+
+ b.ResetTimer()
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ if _, err := ch.Write(input); err != nil {
+ b.Fatalf("WriteFull: %v", err)
+ }
+ }
+ ch.Close()
+ b.StopTimer()
+
+ <-done
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/buffer.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/buffer.go
new file mode 100644
index 000000000..1ab07d078
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/buffer.go
@@ -0,0 +1,97 @@
+// Copyright 2012 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 ssh
+
+import (
+ "io"
+ "sync"
+)
+
+// buffer provides a linked list buffer for data exchange
+// between producer and consumer. Theoretically the buffer is
+// of unlimited capacity as it does no allocation of its own.
+type buffer struct {
+ // protects concurrent access to head, tail and closed
+ *sync.Cond
+
+ head *element // the buffer that will be read first
+ tail *element // the buffer that will be read last
+
+ closed bool
+}
+
+// An element represents a single link in a linked list.
+type element struct {
+ buf []byte
+ next *element
+}
+
+// newBuffer returns an empty buffer that is not closed.
+func newBuffer() *buffer {
+ e := new(element)
+ b := &buffer{
+ Cond: newCond(),
+ head: e,
+ tail: e,
+ }
+ return b
+}
+
+// write makes buf available for Read to receive.
+// buf must not be modified after the call to write.
+func (b *buffer) write(buf []byte) {
+ b.Cond.L.Lock()
+ e := &element{buf: buf}
+ b.tail.next = e
+ b.tail = e
+ b.Cond.Signal()
+ b.Cond.L.Unlock()
+}
+
+// eof closes the buffer. Reads from the buffer once all
+// the data has been consumed will receive io.EOF.
+func (b *buffer) eof() {
+ b.Cond.L.Lock()
+ b.closed = true
+ b.Cond.Signal()
+ b.Cond.L.Unlock()
+}
+
+// Read reads data from the internal buffer in buf. Reads will block
+// if no data is available, or until the buffer is closed.
+func (b *buffer) Read(buf []byte) (n int, err error) {
+ b.Cond.L.Lock()
+ defer b.Cond.L.Unlock()
+
+ for len(buf) > 0 {
+ // if there is data in b.head, copy it
+ if len(b.head.buf) > 0 {
+ r := copy(buf, b.head.buf)
+ buf, b.head.buf = buf[r:], b.head.buf[r:]
+ n += r
+ continue
+ }
+ // if there is a next buffer, make it the head
+ if len(b.head.buf) == 0 && b.head != b.tail {
+ b.head = b.head.next
+ continue
+ }
+
+ // if at least one byte has been copied, return
+ if n > 0 {
+ break
+ }
+
+ // if nothing was read, and there is nothing outstanding
+ // check to see if the buffer is closed.
+ if b.closed {
+ err = io.EOF
+ break
+ }
+ // out of buffers, wait for producer
+ b.Cond.Wait()
+ }
+ return
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/buffer_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/buffer_test.go
new file mode 100644
index 000000000..d5781cb3d
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/buffer_test.go
@@ -0,0 +1,87 @@
+// Copyright 2011 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 ssh
+
+import (
+ "io"
+ "testing"
+)
+
+var alphabet = []byte("abcdefghijklmnopqrstuvwxyz")
+
+func TestBufferReadwrite(t *testing.T) {
+ b := newBuffer()
+ b.write(alphabet[:10])
+ r, _ := b.Read(make([]byte, 10))
+ if r != 10 {
+ t.Fatalf("Expected written == read == 10, written: 10, read %d", r)
+ }
+
+ b = newBuffer()
+ b.write(alphabet[:5])
+ r, _ = b.Read(make([]byte, 10))
+ if r != 5 {
+ t.Fatalf("Expected written == read == 5, written: 5, read %d", r)
+ }
+
+ b = newBuffer()
+ b.write(alphabet[:10])
+ r, _ = b.Read(make([]byte, 5))
+ if r != 5 {
+ t.Fatalf("Expected written == 10, read == 5, written: 10, read %d", r)
+ }
+
+ b = newBuffer()
+ b.write(alphabet[:5])
+ b.write(alphabet[5:15])
+ r, _ = b.Read(make([]byte, 10))
+ r2, _ := b.Read(make([]byte, 10))
+ if r != 10 || r2 != 5 || 15 != r+r2 {
+ t.Fatal("Expected written == read == 15")
+ }
+}
+
+func TestBufferClose(t *testing.T) {
+ b := newBuffer()
+ b.write(alphabet[:10])
+ b.eof()
+ _, err := b.Read(make([]byte, 5))
+ if err != nil {
+ t.Fatal("expected read of 5 to not return EOF")
+ }
+ b = newBuffer()
+ b.write(alphabet[:10])
+ b.eof()
+ r, err := b.Read(make([]byte, 5))
+ r2, err2 := b.Read(make([]byte, 10))
+ if r != 5 || r2 != 5 || err != nil || err2 != nil {
+ t.Fatal("expected reads of 5 and 5")
+ }
+
+ b = newBuffer()
+ b.write(alphabet[:10])
+ b.eof()
+ r, err = b.Read(make([]byte, 5))
+ r2, err2 = b.Read(make([]byte, 10))
+ r3, err3 := b.Read(make([]byte, 10))
+ if r != 5 || r2 != 5 || r3 != 0 || err != nil || err2 != nil || err3 != io.EOF {
+ t.Fatal("expected reads of 5 and 5 and 0, with EOF")
+ }
+
+ b = newBuffer()
+ b.write(make([]byte, 5))
+ b.write(make([]byte, 10))
+ b.eof()
+ r, err = b.Read(make([]byte, 9))
+ r2, err2 = b.Read(make([]byte, 3))
+ r3, err3 = b.Read(make([]byte, 3))
+ r4, err4 := b.Read(make([]byte, 10))
+ if err != nil || err2 != nil || err3 != nil || err4 != io.EOF {
+ t.Fatalf("Expected EOF on forth read only, err=%v, err2=%v, err3=%v, err4=%v", err, err2, err3, err4)
+ }
+ if r != 9 || r2 != 3 || r3 != 3 || r4 != 0 {
+ t.Fatal("Expected written == read == 15", r, r2, r3, r4)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/certs.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/certs.go
new file mode 100644
index 000000000..b1f022078
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/certs.go
@@ -0,0 +1,519 @@
+// Copyright 2012 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 ssh
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "io"
+ "net"
+ "sort"
+ "time"
+)
+
+// These constants from [PROTOCOL.certkeys] represent the algorithm names
+// for certificate types supported by this package.
+const (
+ CertAlgoRSAv01 = "ssh-rsa-cert-v01@openssh.com"
+ CertAlgoDSAv01 = "ssh-dss-cert-v01@openssh.com"
+ CertAlgoECDSA256v01 = "ecdsa-sha2-nistp256-cert-v01@openssh.com"
+ CertAlgoECDSA384v01 = "ecdsa-sha2-nistp384-cert-v01@openssh.com"
+ CertAlgoECDSA521v01 = "ecdsa-sha2-nistp521-cert-v01@openssh.com"
+ CertAlgoED25519v01 = "ssh-ed25519-cert-v01@openssh.com"
+)
+
+// Certificate types distinguish between host and user
+// certificates. The values can be set in the CertType field of
+// Certificate.
+const (
+ UserCert = 1
+ HostCert = 2
+)
+
+// Signature represents a cryptographic signature.
+type Signature struct {
+ Format string
+ Blob []byte
+}
+
+// CertTimeInfinity can be used for OpenSSHCertV01.ValidBefore to indicate that
+// a certificate does not expire.
+const CertTimeInfinity = 1<<64 - 1
+
+// An Certificate represents an OpenSSH certificate as defined in
+// [PROTOCOL.certkeys]?rev=1.8.
+type Certificate struct {
+ Nonce []byte
+ Key PublicKey
+ Serial uint64
+ CertType uint32
+ KeyId string
+ ValidPrincipals []string
+ ValidAfter uint64
+ ValidBefore uint64
+ Permissions
+ Reserved []byte
+ SignatureKey PublicKey
+ Signature *Signature
+}
+
+// genericCertData holds the key-independent part of the certificate data.
+// Overall, certificates contain an nonce, public key fields and
+// key-independent fields.
+type genericCertData struct {
+ Serial uint64
+ CertType uint32
+ KeyId string
+ ValidPrincipals []byte
+ ValidAfter uint64
+ ValidBefore uint64
+ CriticalOptions []byte
+ Extensions []byte
+ Reserved []byte
+ SignatureKey []byte
+ Signature []byte
+}
+
+func marshalStringList(namelist []string) []byte {
+ var to []byte
+ for _, name := range namelist {
+ s := struct{ N string }{name}
+ to = append(to, Marshal(&s)...)
+ }
+ return to
+}
+
+type optionsTuple struct {
+ Key string
+ Value []byte
+}
+
+type optionsTupleValue struct {
+ Value string
+}
+
+// serialize a map of critical options or extensions
+// issue #10569 - per [PROTOCOL.certkeys] and SSH implementation,
+// we need two length prefixes for a non-empty string value
+func marshalTuples(tups map[string]string) []byte {
+ keys := make([]string, 0, len(tups))
+ for key := range tups {
+ keys = append(keys, key)
+ }
+ sort.Strings(keys)
+
+ var ret []byte
+ for _, key := range keys {
+ s := optionsTuple{Key: key}
+ if value := tups[key]; len(value) > 0 {
+ s.Value = Marshal(&optionsTupleValue{value})
+ }
+ ret = append(ret, Marshal(&s)...)
+ }
+ return ret
+}
+
+// issue #10569 - per [PROTOCOL.certkeys] and SSH implementation,
+// we need two length prefixes for a non-empty option value
+func parseTuples(in []byte) (map[string]string, error) {
+ tups := map[string]string{}
+ var lastKey string
+ var haveLastKey bool
+
+ for len(in) > 0 {
+ var key, val, extra []byte
+ var ok bool
+
+ if key, in, ok = parseString(in); !ok {
+ return nil, errShortRead
+ }
+ keyStr := string(key)
+ // according to [PROTOCOL.certkeys], the names must be in
+ // lexical order.
+ if haveLastKey && keyStr <= lastKey {
+ return nil, fmt.Errorf("ssh: certificate options are not in lexical order")
+ }
+ lastKey, haveLastKey = keyStr, true
+ // the next field is a data field, which if non-empty has a string embedded
+ if val, in, ok = parseString(in); !ok {
+ return nil, errShortRead
+ }
+ if len(val) > 0 {
+ val, extra, ok = parseString(val)
+ if !ok {
+ return nil, errShortRead
+ }
+ if len(extra) > 0 {
+ return nil, fmt.Errorf("ssh: unexpected trailing data after certificate option value")
+ }
+ tups[keyStr] = string(val)
+ } else {
+ tups[keyStr] = ""
+ }
+ }
+ return tups, nil
+}
+
+func parseCert(in []byte, privAlgo string) (*Certificate, error) {
+ nonce, rest, ok := parseString(in)
+ if !ok {
+ return nil, errShortRead
+ }
+
+ key, rest, err := parsePubKey(rest, privAlgo)
+ if err != nil {
+ return nil, err
+ }
+
+ var g genericCertData
+ if err := Unmarshal(rest, &g); err != nil {
+ return nil, err
+ }
+
+ c := &Certificate{
+ Nonce: nonce,
+ Key: key,
+ Serial: g.Serial,
+ CertType: g.CertType,
+ KeyId: g.KeyId,
+ ValidAfter: g.ValidAfter,
+ ValidBefore: g.ValidBefore,
+ }
+
+ for principals := g.ValidPrincipals; len(principals) > 0; {
+ principal, rest, ok := parseString(principals)
+ if !ok {
+ return nil, errShortRead
+ }
+ c.ValidPrincipals = append(c.ValidPrincipals, string(principal))
+ principals = rest
+ }
+
+ c.CriticalOptions, err = parseTuples(g.CriticalOptions)
+ if err != nil {
+ return nil, err
+ }
+ c.Extensions, err = parseTuples(g.Extensions)
+ if err != nil {
+ return nil, err
+ }
+ c.Reserved = g.Reserved
+ k, err := ParsePublicKey(g.SignatureKey)
+ if err != nil {
+ return nil, err
+ }
+
+ c.SignatureKey = k
+ c.Signature, rest, ok = parseSignatureBody(g.Signature)
+ if !ok || len(rest) > 0 {
+ return nil, errors.New("ssh: signature parse error")
+ }
+
+ return c, nil
+}
+
+type openSSHCertSigner struct {
+ pub *Certificate
+ signer Signer
+}
+
+// NewCertSigner returns a Signer that signs with the given Certificate, whose
+// private key is held by signer. It returns an error if the public key in cert
+// doesn't match the key used by signer.
+func NewCertSigner(cert *Certificate, signer Signer) (Signer, error) {
+ if bytes.Compare(cert.Key.Marshal(), signer.PublicKey().Marshal()) != 0 {
+ return nil, errors.New("ssh: signer and cert have different public key")
+ }
+
+ return &openSSHCertSigner{cert, signer}, nil
+}
+
+func (s *openSSHCertSigner) Sign(rand io.Reader, data []byte) (*Signature, error) {
+ return s.signer.Sign(rand, data)
+}
+
+func (s *openSSHCertSigner) PublicKey() PublicKey {
+ return s.pub
+}
+
+const sourceAddressCriticalOption = "source-address"
+
+// CertChecker does the work of verifying a certificate. Its methods
+// can be plugged into ClientConfig.HostKeyCallback and
+// ServerConfig.PublicKeyCallback. For the CertChecker to work,
+// minimally, the IsAuthority callback should be set.
+type CertChecker struct {
+ // SupportedCriticalOptions lists the CriticalOptions that the
+ // server application layer understands. These are only used
+ // for user certificates.
+ SupportedCriticalOptions []string
+
+ // IsUserAuthority should return true if the key is recognized as an
+ // authority for the given user certificate. This allows for
+ // certificates to be signed by other certificates. This must be set
+ // if this CertChecker will be checking user certificates.
+ IsUserAuthority func(auth PublicKey) bool
+
+ // IsHostAuthority should report whether the key is recognized as
+ // an authority for this host. This allows for certificates to be
+ // signed by other keys, and for those other keys to only be valid
+ // signers for particular hostnames. This must be set if this
+ // CertChecker will be checking host certificates.
+ IsHostAuthority func(auth PublicKey, address string) bool
+
+ // Clock is used for verifying time stamps. If nil, time.Now
+ // is used.
+ Clock func() time.Time
+
+ // UserKeyFallback is called when CertChecker.Authenticate encounters a
+ // public key that is not a certificate. It must implement validation
+ // of user keys or else, if nil, all such keys are rejected.
+ UserKeyFallback func(conn ConnMetadata, key PublicKey) (*Permissions, error)
+
+ // HostKeyFallback is called when CertChecker.CheckHostKey encounters a
+ // public key that is not a certificate. It must implement host key
+ // validation or else, if nil, all such keys are rejected.
+ HostKeyFallback HostKeyCallback
+
+ // IsRevoked is called for each certificate so that revocation checking
+ // can be implemented. It should return true if the given certificate
+ // is revoked and false otherwise. If nil, no certificates are
+ // considered to have been revoked.
+ IsRevoked func(cert *Certificate) bool
+}
+
+// CheckHostKey checks a host key certificate. This method can be
+// plugged into ClientConfig.HostKeyCallback.
+func (c *CertChecker) CheckHostKey(addr string, remote net.Addr, key PublicKey) error {
+ cert, ok := key.(*Certificate)
+ if !ok {
+ if c.HostKeyFallback != nil {
+ return c.HostKeyFallback(addr, remote, key)
+ }
+ return errors.New("ssh: non-certificate host key")
+ }
+ if cert.CertType != HostCert {
+ return fmt.Errorf("ssh: certificate presented as a host key has type %d", cert.CertType)
+ }
+ if !c.IsHostAuthority(cert.SignatureKey, addr) {
+ return fmt.Errorf("ssh: no authorities for hostname: %v", addr)
+ }
+
+ hostname, _, err := net.SplitHostPort(addr)
+ if err != nil {
+ return err
+ }
+
+ // Pass hostname only as principal for host certificates (consistent with OpenSSH)
+ return c.CheckCert(hostname, cert)
+}
+
+// Authenticate checks a user certificate. Authenticate can be used as
+// a value for ServerConfig.PublicKeyCallback.
+func (c *CertChecker) Authenticate(conn ConnMetadata, pubKey PublicKey) (*Permissions, error) {
+ cert, ok := pubKey.(*Certificate)
+ if !ok {
+ if c.UserKeyFallback != nil {
+ return c.UserKeyFallback(conn, pubKey)
+ }
+ return nil, errors.New("ssh: normal key pairs not accepted")
+ }
+
+ if cert.CertType != UserCert {
+ return nil, fmt.Errorf("ssh: cert has type %d", cert.CertType)
+ }
+ if !c.IsUserAuthority(cert.SignatureKey) {
+ return nil, fmt.Errorf("ssh: certificate signed by unrecognized authority")
+ }
+
+ if err := c.CheckCert(conn.User(), cert); err != nil {
+ return nil, err
+ }
+
+ return &cert.Permissions, nil
+}
+
+// CheckCert checks CriticalOptions, ValidPrincipals, revocation, timestamp and
+// the signature of the certificate.
+func (c *CertChecker) CheckCert(principal string, cert *Certificate) error {
+ if c.IsRevoked != nil && c.IsRevoked(cert) {
+ return fmt.Errorf("ssh: certicate serial %d revoked", cert.Serial)
+ }
+
+ for opt, _ := range cert.CriticalOptions {
+ // sourceAddressCriticalOption will be enforced by
+ // serverAuthenticate
+ if opt == sourceAddressCriticalOption {
+ continue
+ }
+
+ found := false
+ for _, supp := range c.SupportedCriticalOptions {
+ if supp == opt {
+ found = true
+ break
+ }
+ }
+ if !found {
+ return fmt.Errorf("ssh: unsupported critical option %q in certificate", opt)
+ }
+ }
+
+ if len(cert.ValidPrincipals) > 0 {
+ // By default, certs are valid for all users/hosts.
+ found := false
+ for _, p := range cert.ValidPrincipals {
+ if p == principal {
+ found = true
+ break
+ }
+ }
+ if !found {
+ return fmt.Errorf("ssh: principal %q not in the set of valid principals for given certificate: %q", principal, cert.ValidPrincipals)
+ }
+ }
+
+ clock := c.Clock
+ if clock == nil {
+ clock = time.Now
+ }
+
+ unixNow := clock().Unix()
+ if after := int64(cert.ValidAfter); after < 0 || unixNow < int64(cert.ValidAfter) {
+ return fmt.Errorf("ssh: cert is not yet valid")
+ }
+ if before := int64(cert.ValidBefore); cert.ValidBefore != uint64(CertTimeInfinity) && (unixNow >= before || before < 0) {
+ return fmt.Errorf("ssh: cert has expired")
+ }
+ if err := cert.SignatureKey.Verify(cert.bytesForSigning(), cert.Signature); err != nil {
+ return fmt.Errorf("ssh: certificate signature does not verify")
+ }
+
+ return nil
+}
+
+// SignCert sets c.SignatureKey to the authority's public key and stores a
+// Signature, by authority, in the certificate.
+func (c *Certificate) SignCert(rand io.Reader, authority Signer) error {
+ c.Nonce = make([]byte, 32)
+ if _, err := io.ReadFull(rand, c.Nonce); err != nil {
+ return err
+ }
+ c.SignatureKey = authority.PublicKey()
+
+ sig, err := authority.Sign(rand, c.bytesForSigning())
+ if err != nil {
+ return err
+ }
+ c.Signature = sig
+ return nil
+}
+
+var certAlgoNames = map[string]string{
+ KeyAlgoRSA: CertAlgoRSAv01,
+ KeyAlgoDSA: CertAlgoDSAv01,
+ KeyAlgoECDSA256: CertAlgoECDSA256v01,
+ KeyAlgoECDSA384: CertAlgoECDSA384v01,
+ KeyAlgoECDSA521: CertAlgoECDSA521v01,
+ KeyAlgoED25519: CertAlgoED25519v01,
+}
+
+// certToPrivAlgo returns the underlying algorithm for a certificate algorithm.
+// Panics if a non-certificate algorithm is passed.
+func certToPrivAlgo(algo string) string {
+ for privAlgo, pubAlgo := range certAlgoNames {
+ if pubAlgo == algo {
+ return privAlgo
+ }
+ }
+ panic("unknown cert algorithm")
+}
+
+func (cert *Certificate) bytesForSigning() []byte {
+ c2 := *cert
+ c2.Signature = nil
+ out := c2.Marshal()
+ // Drop trailing signature length.
+ return out[:len(out)-4]
+}
+
+// Marshal serializes c into OpenSSH's wire format. It is part of the
+// PublicKey interface.
+func (c *Certificate) Marshal() []byte {
+ generic := genericCertData{
+ Serial: c.Serial,
+ CertType: c.CertType,
+ KeyId: c.KeyId,
+ ValidPrincipals: marshalStringList(c.ValidPrincipals),
+ ValidAfter: uint64(c.ValidAfter),
+ ValidBefore: uint64(c.ValidBefore),
+ CriticalOptions: marshalTuples(c.CriticalOptions),
+ Extensions: marshalTuples(c.Extensions),
+ Reserved: c.Reserved,
+ SignatureKey: c.SignatureKey.Marshal(),
+ }
+ if c.Signature != nil {
+ generic.Signature = Marshal(c.Signature)
+ }
+ genericBytes := Marshal(&generic)
+ keyBytes := c.Key.Marshal()
+ _, keyBytes, _ = parseString(keyBytes)
+ prefix := Marshal(&struct {
+ Name string
+ Nonce []byte
+ Key []byte `ssh:"rest"`
+ }{c.Type(), c.Nonce, keyBytes})
+
+ result := make([]byte, 0, len(prefix)+len(genericBytes))
+ result = append(result, prefix...)
+ result = append(result, genericBytes...)
+ return result
+}
+
+// Type returns the key name. It is part of the PublicKey interface.
+func (c *Certificate) Type() string {
+ algo, ok := certAlgoNames[c.Key.Type()]
+ if !ok {
+ panic("unknown cert key type " + c.Key.Type())
+ }
+ return algo
+}
+
+// Verify verifies a signature against the certificate's public
+// key. It is part of the PublicKey interface.
+func (c *Certificate) Verify(data []byte, sig *Signature) error {
+ return c.Key.Verify(data, sig)
+}
+
+func parseSignatureBody(in []byte) (out *Signature, rest []byte, ok bool) {
+ format, in, ok := parseString(in)
+ if !ok {
+ return
+ }
+
+ out = &Signature{
+ Format: string(format),
+ }
+
+ if out.Blob, in, ok = parseString(in); !ok {
+ return
+ }
+
+ return out, in, ok
+}
+
+func parseSignature(in []byte) (out *Signature, rest []byte, ok bool) {
+ sigBytes, rest, ok := parseString(in)
+ if !ok {
+ return
+ }
+
+ out, trailing, ok := parseSignatureBody(sigBytes)
+ if !ok || len(trailing) > 0 {
+ return nil, nil, false
+ }
+ return
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/certs_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/certs_test.go
new file mode 100644
index 000000000..0200531f4
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/certs_test.go
@@ -0,0 +1,222 @@
+// Copyright 2013 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 ssh
+
+import (
+ "bytes"
+ "crypto/rand"
+ "reflect"
+ "testing"
+ "time"
+)
+
+// Cert generated by ssh-keygen 6.0p1 Debian-4.
+// % ssh-keygen -s ca-key -I test user-key
+const exampleSSHCert = `ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgb1srW/W3ZDjYAO45xLYAwzHBDLsJ4Ux6ICFIkTjb1LEAAAADAQABAAAAYQCkoR51poH0wE8w72cqSB8Sszx+vAhzcMdCO0wqHTj7UNENHWEXGrU0E0UQekD7U+yhkhtoyjbPOVIP7hNa6aRk/ezdh/iUnCIt4Jt1v3Z1h1P+hA4QuYFMHNB+rmjPwAcAAAAAAAAAAAAAAAEAAAAEdGVzdAAAAAAAAAAAAAAAAP//////////AAAAAAAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAAHcAAAAHc3NoLXJzYQAAAAMBAAEAAABhANFS2kaktpSGc+CcmEKPyw9mJC4nZKxHKTgLVZeaGbFZOvJTNzBspQHdy7Q1uKSfktxpgjZnksiu/tFF9ngyY2KFoc+U88ya95IZUycBGCUbBQ8+bhDtw/icdDGQD5WnUwAAAG8AAAAHc3NoLXJzYQAAAGC8Y9Z2LQKhIhxf52773XaWrXdxP0t3GBVo4A10vUWiYoAGepr6rQIoGGXFxT4B9Gp+nEBJjOwKDXPrAevow0T9ca8gZN+0ykbhSrXLE5Ao48rqr3zP4O1/9P7e6gp0gw8=`
+
+func TestParseCert(t *testing.T) {
+ authKeyBytes := []byte(exampleSSHCert)
+
+ key, _, _, rest, err := ParseAuthorizedKey(authKeyBytes)
+ if err != nil {
+ t.Fatalf("ParseAuthorizedKey: %v", err)
+ }
+ if len(rest) > 0 {
+ t.Errorf("rest: got %q, want empty", rest)
+ }
+
+ if _, ok := key.(*Certificate); !ok {
+ t.Fatalf("got %v (%T), want *Certificate", key, key)
+ }
+
+ marshaled := MarshalAuthorizedKey(key)
+ // Before comparison, remove the trailing newline that
+ // MarshalAuthorizedKey adds.
+ marshaled = marshaled[:len(marshaled)-1]
+ if !bytes.Equal(authKeyBytes, marshaled) {
+ t.Errorf("marshaled certificate does not match original: got %q, want %q", marshaled, authKeyBytes)
+ }
+}
+
+// Cert generated by ssh-keygen OpenSSH_6.8p1 OS X 10.10.3
+// % ssh-keygen -s ca -I testcert -O source-address=192.168.1.0/24 -O force-command=/bin/sleep user.pub
+// user.pub key: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDACh1rt2DXfV3hk6fszSQcQ/rueMId0kVD9U7nl8cfEnFxqOCrNT92g4laQIGl2mn8lsGZfTLg8ksHq3gkvgO3oo/0wHy4v32JeBOHTsN5AL4gfHNEhWeWb50ev47hnTsRIt9P4dxogeUo/hTu7j9+s9lLpEQXCvq6xocXQt0j8MV9qZBBXFLXVT3cWIkSqOdwt/5ZBg+1GSrc7WfCXVWgTk4a20uPMuJPxU4RQwZW6X3+O8Pqo8C3cW0OzZRFP6gUYUKUsTI5WntlS+LAxgw1mZNsozFGdbiOPRnEryE3SRldh9vjDR3tin1fGpA5P7+CEB/bqaXtG3V+F2OkqaMN
+// Critical Options:
+// force-command /bin/sleep
+// source-address 192.168.1.0/24
+// Extensions:
+// permit-X11-forwarding
+// permit-agent-forwarding
+// permit-port-forwarding
+// permit-pty
+// permit-user-rc
+const exampleSSHCertWithOptions = `ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgDyysCJY0XrO1n03EeRRoITnTPdjENFmWDs9X58PP3VUAAAADAQABAAABAQDACh1rt2DXfV3hk6fszSQcQ/rueMId0kVD9U7nl8cfEnFxqOCrNT92g4laQIGl2mn8lsGZfTLg8ksHq3gkvgO3oo/0wHy4v32JeBOHTsN5AL4gfHNEhWeWb50ev47hnTsRIt9P4dxogeUo/hTu7j9+s9lLpEQXCvq6xocXQt0j8MV9qZBBXFLXVT3cWIkSqOdwt/5ZBg+1GSrc7WfCXVWgTk4a20uPMuJPxU4RQwZW6X3+O8Pqo8C3cW0OzZRFP6gUYUKUsTI5WntlS+LAxgw1mZNsozFGdbiOPRnEryE3SRldh9vjDR3tin1fGpA5P7+CEB/bqaXtG3V+F2OkqaMNAAAAAAAAAAAAAAABAAAACHRlc3RjZXJ0AAAAAAAAAAAAAAAA//////////8AAABLAAAADWZvcmNlLWNvbW1hbmQAAAAOAAAACi9iaW4vc2xlZXAAAAAOc291cmNlLWFkZHJlc3MAAAASAAAADjE5Mi4xNjguMS4wLzI0AAAAggAAABVwZXJtaXQtWDExLWZvcndhcmRpbmcAAAAAAAAAF3Blcm1pdC1hZ2VudC1mb3J3YXJkaW5nAAAAAAAAABZwZXJtaXQtcG9ydC1mb3J3YXJkaW5nAAAAAAAAAApwZXJtaXQtcHR5AAAAAAAAAA5wZXJtaXQtdXNlci1yYwAAAAAAAAAAAAABFwAAAAdzc2gtcnNhAAAAAwEAAQAAAQEAwU+c5ui5A8+J/CFpjW8wCa52bEODA808WWQDCSuTG/eMXNf59v9Y8Pk0F1E9dGCosSNyVcB/hacUrc6He+i97+HJCyKavBsE6GDxrjRyxYqAlfcOXi/IVmaUGiO8OQ39d4GHrjToInKvExSUeleQyH4Y4/e27T/pILAqPFL3fyrvMLT5qU9QyIt6zIpa7GBP5+urouNavMprV3zsfIqNBbWypinOQAw823a5wN+zwXnhZrgQiHZ/USG09Y6k98y1dTVz8YHlQVR4D3lpTAsKDKJ5hCH9WU4fdf+lU8OyNGaJ/vz0XNqxcToe1l4numLTnaoSuH89pHryjqurB7lJKwAAAQ8AAAAHc3NoLXJzYQAAAQCaHvUIoPL1zWUHIXLvu96/HU1s/i4CAW2IIEuGgxCUCiFj6vyTyYtgxQxcmbfZf6eaITlS6XJZa7Qq4iaFZh75C1DXTX8labXhRSD4E2t//AIP9MC1rtQC5xo6FmbQ+BoKcDskr+mNACcbRSxs3IL3bwCfWDnIw2WbVox9ZdcthJKk4UoCW4ix4QwdHw7zlddlz++fGEEVhmTbll1SUkycGApPFBsAYRTMupUJcYPIeReBI/m8XfkoMk99bV8ZJQTAd7OekHY2/48Ff53jLmyDjP7kNw1F8OaPtkFs6dGJXta4krmaekPy87j+35In5hFj7yoOqvSbmYUkeX70/GGQ`
+
+func TestParseCertWithOptions(t *testing.T) {
+ opts := map[string]string{
+ "source-address": "192.168.1.0/24",
+ "force-command": "/bin/sleep",
+ }
+ exts := map[string]string{
+ "permit-X11-forwarding": "",
+ "permit-agent-forwarding": "",
+ "permit-port-forwarding": "",
+ "permit-pty": "",
+ "permit-user-rc": "",
+ }
+ authKeyBytes := []byte(exampleSSHCertWithOptions)
+
+ key, _, _, rest, err := ParseAuthorizedKey(authKeyBytes)
+ if err != nil {
+ t.Fatalf("ParseAuthorizedKey: %v", err)
+ }
+ if len(rest) > 0 {
+ t.Errorf("rest: got %q, want empty", rest)
+ }
+ cert, ok := key.(*Certificate)
+ if !ok {
+ t.Fatalf("got %v (%T), want *Certificate", key, key)
+ }
+ if !reflect.DeepEqual(cert.CriticalOptions, opts) {
+ t.Errorf("unexpected critical options - got %v, want %v", cert.CriticalOptions, opts)
+ }
+ if !reflect.DeepEqual(cert.Extensions, exts) {
+ t.Errorf("unexpected Extensions - got %v, want %v", cert.Extensions, exts)
+ }
+ marshaled := MarshalAuthorizedKey(key)
+ // Before comparison, remove the trailing newline that
+ // MarshalAuthorizedKey adds.
+ marshaled = marshaled[:len(marshaled)-1]
+ if !bytes.Equal(authKeyBytes, marshaled) {
+ t.Errorf("marshaled certificate does not match original: got %q, want %q", marshaled, authKeyBytes)
+ }
+}
+
+func TestValidateCert(t *testing.T) {
+ key, _, _, _, err := ParseAuthorizedKey([]byte(exampleSSHCert))
+ if err != nil {
+ t.Fatalf("ParseAuthorizedKey: %v", err)
+ }
+ validCert, ok := key.(*Certificate)
+ if !ok {
+ t.Fatalf("got %v (%T), want *Certificate", key, key)
+ }
+ checker := CertChecker{}
+ checker.IsUserAuthority = func(k PublicKey) bool {
+ return bytes.Equal(k.Marshal(), validCert.SignatureKey.Marshal())
+ }
+
+ if err := checker.CheckCert("user", validCert); err != nil {
+ t.Errorf("Unable to validate certificate: %v", err)
+ }
+ invalidCert := &Certificate{
+ Key: testPublicKeys["rsa"],
+ SignatureKey: testPublicKeys["ecdsa"],
+ ValidBefore: CertTimeInfinity,
+ Signature: &Signature{},
+ }
+ if err := checker.CheckCert("user", invalidCert); err == nil {
+ t.Error("Invalid cert signature passed validation")
+ }
+}
+
+func TestValidateCertTime(t *testing.T) {
+ cert := Certificate{
+ ValidPrincipals: []string{"user"},
+ Key: testPublicKeys["rsa"],
+ ValidAfter: 50,
+ ValidBefore: 100,
+ }
+
+ cert.SignCert(rand.Reader, testSigners["ecdsa"])
+
+ for ts, ok := range map[int64]bool{
+ 25: false,
+ 50: true,
+ 99: true,
+ 100: false,
+ 125: false,
+ } {
+ checker := CertChecker{
+ Clock: func() time.Time { return time.Unix(ts, 0) },
+ }
+ checker.IsUserAuthority = func(k PublicKey) bool {
+ return bytes.Equal(k.Marshal(),
+ testPublicKeys["ecdsa"].Marshal())
+ }
+
+ if v := checker.CheckCert("user", &cert); (v == nil) != ok {
+ t.Errorf("Authenticate(%d): %v", ts, v)
+ }
+ }
+}
+
+// TODO(hanwen): tests for
+//
+// host keys:
+// * fallbacks
+
+func TestHostKeyCert(t *testing.T) {
+ cert := &Certificate{
+ ValidPrincipals: []string{"hostname", "hostname.domain", "otherhost"},
+ Key: testPublicKeys["rsa"],
+ ValidBefore: CertTimeInfinity,
+ CertType: HostCert,
+ }
+ cert.SignCert(rand.Reader, testSigners["ecdsa"])
+
+ checker := &CertChecker{
+ IsHostAuthority: func(p PublicKey, addr string) bool {
+ return addr == "hostname:22" && bytes.Equal(testPublicKeys["ecdsa"].Marshal(), p.Marshal())
+ },
+ }
+
+ certSigner, err := NewCertSigner(cert, testSigners["rsa"])
+ if err != nil {
+ t.Errorf("NewCertSigner: %v", err)
+ }
+
+ for _, test := range []struct {
+ addr string
+ succeed bool
+ }{
+ {addr: "hostname:22", succeed: true},
+ {addr: "otherhost:22", succeed: false}, // The certificate is valid for 'otherhost' as hostname, but we only recognize the authority of the signer for the address 'hostname:22'
+ {addr: "lasthost:22", succeed: false},
+ } {
+ c1, c2, err := netPipe()
+ if err != nil {
+ t.Fatalf("netPipe: %v", err)
+ }
+ defer c1.Close()
+ defer c2.Close()
+
+ errc := make(chan error)
+
+ go func() {
+ conf := ServerConfig{
+ NoClientAuth: true,
+ }
+ conf.AddHostKey(certSigner)
+ _, _, _, err := NewServerConn(c1, &conf)
+ errc <- err
+ }()
+
+ config := &ClientConfig{
+ User: "user",
+ HostKeyCallback: checker.CheckHostKey,
+ }
+ _, _, _, err = NewClientConn(c2, test.addr, config)
+
+ if (err == nil) != test.succeed {
+ t.Fatalf("NewClientConn(%q): %v", test.addr, err)
+ }
+
+ err = <-errc
+ if (err == nil) != test.succeed {
+ t.Fatalf("NewServerConn(%q): %v", test.addr, err)
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/channel.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/channel.go
new file mode 100644
index 000000000..195530ea0
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/channel.go
@@ -0,0 +1,633 @@
+// Copyright 2011 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 ssh
+
+import (
+ "encoding/binary"
+ "errors"
+ "fmt"
+ "io"
+ "log"
+ "sync"
+)
+
+const (
+ minPacketLength = 9
+ // channelMaxPacket contains the maximum number of bytes that will be
+ // sent in a single packet. As per RFC 4253, section 6.1, 32k is also
+ // the minimum.
+ channelMaxPacket = 1 << 15
+ // We follow OpenSSH here.
+ channelWindowSize = 64 * channelMaxPacket
+)
+
+// NewChannel represents an incoming request to a channel. It must either be
+// accepted for use by calling Accept, or rejected by calling Reject.
+type NewChannel interface {
+ // Accept accepts the channel creation request. It returns the Channel
+ // and a Go channel containing SSH requests. The Go channel must be
+ // serviced otherwise the Channel will hang.
+ Accept() (Channel, <-chan *Request, error)
+
+ // Reject rejects the channel creation request. After calling
+ // this, no other methods on the Channel may be called.
+ Reject(reason RejectionReason, message string) error
+
+ // ChannelType returns the type of the channel, as supplied by the
+ // client.
+ ChannelType() string
+
+ // ExtraData returns the arbitrary payload for this channel, as supplied
+ // by the client. This data is specific to the channel type.
+ ExtraData() []byte
+}
+
+// A Channel is an ordered, reliable, flow-controlled, duplex stream
+// that is multiplexed over an SSH connection.
+type Channel interface {
+ // Read reads up to len(data) bytes from the channel.
+ Read(data []byte) (int, error)
+
+ // Write writes len(data) bytes to the channel.
+ Write(data []byte) (int, error)
+
+ // Close signals end of channel use. No data may be sent after this
+ // call.
+ Close() error
+
+ // CloseWrite signals the end of sending in-band
+ // data. Requests may still be sent, and the other side may
+ // still send data
+ CloseWrite() error
+
+ // SendRequest sends a channel request. If wantReply is true,
+ // it will wait for a reply and return the result as a
+ // boolean, otherwise the return value will be false. Channel
+ // requests are out-of-band messages so they may be sent even
+ // if the data stream is closed or blocked by flow control.
+ // If the channel is closed before a reply is returned, io.EOF
+ // is returned.
+ SendRequest(name string, wantReply bool, payload []byte) (bool, error)
+
+ // Stderr returns an io.ReadWriter that writes to this channel
+ // with the extended data type set to stderr. Stderr may
+ // safely be read and written from a different goroutine than
+ // Read and Write respectively.
+ Stderr() io.ReadWriter
+}
+
+// Request is a request sent outside of the normal stream of
+// data. Requests can either be specific to an SSH channel, or they
+// can be global.
+type Request struct {
+ Type string
+ WantReply bool
+ Payload []byte
+
+ ch *channel
+ mux *mux
+}
+
+// Reply sends a response to a request. It must be called for all requests
+// where WantReply is true and is a no-op otherwise. The payload argument is
+// ignored for replies to channel-specific requests.
+func (r *Request) Reply(ok bool, payload []byte) error {
+ if !r.WantReply {
+ return nil
+ }
+
+ if r.ch == nil {
+ return r.mux.ackRequest(ok, payload)
+ }
+
+ return r.ch.ackRequest(ok)
+}
+
+// RejectionReason is an enumeration used when rejecting channel creation
+// requests. See RFC 4254, section 5.1.
+type RejectionReason uint32
+
+const (
+ Prohibited RejectionReason = iota + 1
+ ConnectionFailed
+ UnknownChannelType
+ ResourceShortage
+)
+
+// String converts the rejection reason to human readable form.
+func (r RejectionReason) String() string {
+ switch r {
+ case Prohibited:
+ return "administratively prohibited"
+ case ConnectionFailed:
+ return "connect failed"
+ case UnknownChannelType:
+ return "unknown channel type"
+ case ResourceShortage:
+ return "resource shortage"
+ }
+ return fmt.Sprintf("unknown reason %d", int(r))
+}
+
+func min(a uint32, b int) uint32 {
+ if a < uint32(b) {
+ return a
+ }
+ return uint32(b)
+}
+
+type channelDirection uint8
+
+const (
+ channelInbound channelDirection = iota
+ channelOutbound
+)
+
+// channel is an implementation of the Channel interface that works
+// with the mux class.
+type channel struct {
+ // R/O after creation
+ chanType string
+ extraData []byte
+ localId, remoteId uint32
+
+ // maxIncomingPayload and maxRemotePayload are the maximum
+ // payload sizes of normal and extended data packets for
+ // receiving and sending, respectively. The wire packet will
+ // be 9 or 13 bytes larger (excluding encryption overhead).
+ maxIncomingPayload uint32
+ maxRemotePayload uint32
+
+ mux *mux
+
+ // decided is set to true if an accept or reject message has been sent
+ // (for outbound channels) or received (for inbound channels).
+ decided bool
+
+ // direction contains either channelOutbound, for channels created
+ // locally, or channelInbound, for channels created by the peer.
+ direction channelDirection
+
+ // Pending internal channel messages.
+ msg chan interface{}
+
+ // Since requests have no ID, there can be only one request
+ // with WantReply=true outstanding. This lock is held by a
+ // goroutine that has such an outgoing request pending.
+ sentRequestMu sync.Mutex
+
+ incomingRequests chan *Request
+
+ sentEOF bool
+
+ // thread-safe data
+ remoteWin window
+ pending *buffer
+ extPending *buffer
+
+ // windowMu protects myWindow, the flow-control window.
+ windowMu sync.Mutex
+ myWindow uint32
+
+ // writeMu serializes calls to mux.conn.writePacket() and
+ // protects sentClose and packetPool. This mutex must be
+ // different from windowMu, as writePacket can block if there
+ // is a key exchange pending.
+ writeMu sync.Mutex
+ sentClose bool
+
+ // packetPool has a buffer for each extended channel ID to
+ // save allocations during writes.
+ packetPool map[uint32][]byte
+}
+
+// writePacket sends a packet. If the packet is a channel close, it updates
+// sentClose. This method takes the lock c.writeMu.
+func (c *channel) writePacket(packet []byte) error {
+ c.writeMu.Lock()
+ if c.sentClose {
+ c.writeMu.Unlock()
+ return io.EOF
+ }
+ c.sentClose = (packet[0] == msgChannelClose)
+ err := c.mux.conn.writePacket(packet)
+ c.writeMu.Unlock()
+ return err
+}
+
+func (c *channel) sendMessage(msg interface{}) error {
+ if debugMux {
+ log.Printf("send(%d): %#v", c.mux.chanList.offset, msg)
+ }
+
+ p := Marshal(msg)
+ binary.BigEndian.PutUint32(p[1:], c.remoteId)
+ return c.writePacket(p)
+}
+
+// WriteExtended writes data to a specific extended stream. These streams are
+// used, for example, for stderr.
+func (c *channel) WriteExtended(data []byte, extendedCode uint32) (n int, err error) {
+ if c.sentEOF {
+ return 0, io.EOF
+ }
+ // 1 byte message type, 4 bytes remoteId, 4 bytes data length
+ opCode := byte(msgChannelData)
+ headerLength := uint32(9)
+ if extendedCode > 0 {
+ headerLength += 4
+ opCode = msgChannelExtendedData
+ }
+
+ c.writeMu.Lock()
+ packet := c.packetPool[extendedCode]
+ // We don't remove the buffer from packetPool, so
+ // WriteExtended calls from different goroutines will be
+ // flagged as errors by the race detector.
+ c.writeMu.Unlock()
+
+ for len(data) > 0 {
+ space := min(c.maxRemotePayload, len(data))
+ if space, err = c.remoteWin.reserve(space); err != nil {
+ return n, err
+ }
+ if want := headerLength + space; uint32(cap(packet)) < want {
+ packet = make([]byte, want)
+ } else {
+ packet = packet[:want]
+ }
+
+ todo := data[:space]
+
+ packet[0] = opCode
+ binary.BigEndian.PutUint32(packet[1:], c.remoteId)
+ if extendedCode > 0 {
+ binary.BigEndian.PutUint32(packet[5:], uint32(extendedCode))
+ }
+ binary.BigEndian.PutUint32(packet[headerLength-4:], uint32(len(todo)))
+ copy(packet[headerLength:], todo)
+ if err = c.writePacket(packet); err != nil {
+ return n, err
+ }
+
+ n += len(todo)
+ data = data[len(todo):]
+ }
+
+ c.writeMu.Lock()
+ c.packetPool[extendedCode] = packet
+ c.writeMu.Unlock()
+
+ return n, err
+}
+
+func (c *channel) handleData(packet []byte) error {
+ headerLen := 9
+ isExtendedData := packet[0] == msgChannelExtendedData
+ if isExtendedData {
+ headerLen = 13
+ }
+ if len(packet) < headerLen {
+ // malformed data packet
+ return parseError(packet[0])
+ }
+
+ var extended uint32
+ if isExtendedData {
+ extended = binary.BigEndian.Uint32(packet[5:])
+ }
+
+ length := binary.BigEndian.Uint32(packet[headerLen-4 : headerLen])
+ if length == 0 {
+ return nil
+ }
+ if length > c.maxIncomingPayload {
+ // TODO(hanwen): should send Disconnect?
+ return errors.New("ssh: incoming packet exceeds maximum payload size")
+ }
+
+ data := packet[headerLen:]
+ if length != uint32(len(data)) {
+ return errors.New("ssh: wrong packet length")
+ }
+
+ c.windowMu.Lock()
+ if c.myWindow < length {
+ c.windowMu.Unlock()
+ // TODO(hanwen): should send Disconnect with reason?
+ return errors.New("ssh: remote side wrote too much")
+ }
+ c.myWindow -= length
+ c.windowMu.Unlock()
+
+ if extended == 1 {
+ c.extPending.write(data)
+ } else if extended > 0 {
+ // discard other extended data.
+ } else {
+ c.pending.write(data)
+ }
+ return nil
+}
+
+func (c *channel) adjustWindow(n uint32) error {
+ c.windowMu.Lock()
+ // Since myWindow is managed on our side, and can never exceed
+ // the initial window setting, we don't worry about overflow.
+ c.myWindow += uint32(n)
+ c.windowMu.Unlock()
+ return c.sendMessage(windowAdjustMsg{
+ AdditionalBytes: uint32(n),
+ })
+}
+
+func (c *channel) ReadExtended(data []byte, extended uint32) (n int, err error) {
+ switch extended {
+ case 1:
+ n, err = c.extPending.Read(data)
+ case 0:
+ n, err = c.pending.Read(data)
+ default:
+ return 0, fmt.Errorf("ssh: extended code %d unimplemented", extended)
+ }
+
+ if n > 0 {
+ err = c.adjustWindow(uint32(n))
+ // sendWindowAdjust can return io.EOF if the remote
+ // peer has closed the connection, however we want to
+ // defer forwarding io.EOF to the caller of Read until
+ // the buffer has been drained.
+ if n > 0 && err == io.EOF {
+ err = nil
+ }
+ }
+
+ return n, err
+}
+
+func (c *channel) close() {
+ c.pending.eof()
+ c.extPending.eof()
+ close(c.msg)
+ close(c.incomingRequests)
+ c.writeMu.Lock()
+ // This is not necessary for a normal channel teardown, but if
+ // there was another error, it is.
+ c.sentClose = true
+ c.writeMu.Unlock()
+ // Unblock writers.
+ c.remoteWin.close()
+}
+
+// responseMessageReceived is called when a success or failure message is
+// received on a channel to check that such a message is reasonable for the
+// given channel.
+func (c *channel) responseMessageReceived() error {
+ if c.direction == channelInbound {
+ return errors.New("ssh: channel response message received on inbound channel")
+ }
+ if c.decided {
+ return errors.New("ssh: duplicate response received for channel")
+ }
+ c.decided = true
+ return nil
+}
+
+func (c *channel) handlePacket(packet []byte) error {
+ switch packet[0] {
+ case msgChannelData, msgChannelExtendedData:
+ return c.handleData(packet)
+ case msgChannelClose:
+ c.sendMessage(channelCloseMsg{PeersId: c.remoteId})
+ c.mux.chanList.remove(c.localId)
+ c.close()
+ return nil
+ case msgChannelEOF:
+ // RFC 4254 is mute on how EOF affects dataExt messages but
+ // it is logical to signal EOF at the same time.
+ c.extPending.eof()
+ c.pending.eof()
+ return nil
+ }
+
+ decoded, err := decode(packet)
+ if err != nil {
+ return err
+ }
+
+ switch msg := decoded.(type) {
+ case *channelOpenFailureMsg:
+ if err := c.responseMessageReceived(); err != nil {
+ return err
+ }
+ c.mux.chanList.remove(msg.PeersId)
+ c.msg <- msg
+ case *channelOpenConfirmMsg:
+ if err := c.responseMessageReceived(); err != nil {
+ return err
+ }
+ if msg.MaxPacketSize < minPacketLength || msg.MaxPacketSize > 1<<31 {
+ return fmt.Errorf("ssh: invalid MaxPacketSize %d from peer", msg.MaxPacketSize)
+ }
+ c.remoteId = msg.MyId
+ c.maxRemotePayload = msg.MaxPacketSize
+ c.remoteWin.add(msg.MyWindow)
+ c.msg <- msg
+ case *windowAdjustMsg:
+ if !c.remoteWin.add(msg.AdditionalBytes) {
+ return fmt.Errorf("ssh: invalid window update for %d bytes", msg.AdditionalBytes)
+ }
+ case *channelRequestMsg:
+ req := Request{
+ Type: msg.Request,
+ WantReply: msg.WantReply,
+ Payload: msg.RequestSpecificData,
+ ch: c,
+ }
+
+ c.incomingRequests <- &req
+ default:
+ c.msg <- msg
+ }
+ return nil
+}
+
+func (m *mux) newChannel(chanType string, direction channelDirection, extraData []byte) *channel {
+ ch := &channel{
+ remoteWin: window{Cond: newCond()},
+ myWindow: channelWindowSize,
+ pending: newBuffer(),
+ extPending: newBuffer(),
+ direction: direction,
+ incomingRequests: make(chan *Request, chanSize),
+ msg: make(chan interface{}, chanSize),
+ chanType: chanType,
+ extraData: extraData,
+ mux: m,
+ packetPool: make(map[uint32][]byte),
+ }
+ ch.localId = m.chanList.add(ch)
+ return ch
+}
+
+var errUndecided = errors.New("ssh: must Accept or Reject channel")
+var errDecidedAlready = errors.New("ssh: can call Accept or Reject only once")
+
+type extChannel struct {
+ code uint32
+ ch *channel
+}
+
+func (e *extChannel) Write(data []byte) (n int, err error) {
+ return e.ch.WriteExtended(data, e.code)
+}
+
+func (e *extChannel) Read(data []byte) (n int, err error) {
+ return e.ch.ReadExtended(data, e.code)
+}
+
+func (c *channel) Accept() (Channel, <-chan *Request, error) {
+ if c.decided {
+ return nil, nil, errDecidedAlready
+ }
+ c.maxIncomingPayload = channelMaxPacket
+ confirm := channelOpenConfirmMsg{
+ PeersId: c.remoteId,
+ MyId: c.localId,
+ MyWindow: c.myWindow,
+ MaxPacketSize: c.maxIncomingPayload,
+ }
+ c.decided = true
+ if err := c.sendMessage(confirm); err != nil {
+ return nil, nil, err
+ }
+
+ return c, c.incomingRequests, nil
+}
+
+func (ch *channel) Reject(reason RejectionReason, message string) error {
+ if ch.decided {
+ return errDecidedAlready
+ }
+ reject := channelOpenFailureMsg{
+ PeersId: ch.remoteId,
+ Reason: reason,
+ Message: message,
+ Language: "en",
+ }
+ ch.decided = true
+ return ch.sendMessage(reject)
+}
+
+func (ch *channel) Read(data []byte) (int, error) {
+ if !ch.decided {
+ return 0, errUndecided
+ }
+ return ch.ReadExtended(data, 0)
+}
+
+func (ch *channel) Write(data []byte) (int, error) {
+ if !ch.decided {
+ return 0, errUndecided
+ }
+ return ch.WriteExtended(data, 0)
+}
+
+func (ch *channel) CloseWrite() error {
+ if !ch.decided {
+ return errUndecided
+ }
+ ch.sentEOF = true
+ return ch.sendMessage(channelEOFMsg{
+ PeersId: ch.remoteId})
+}
+
+func (ch *channel) Close() error {
+ if !ch.decided {
+ return errUndecided
+ }
+
+ return ch.sendMessage(channelCloseMsg{
+ PeersId: ch.remoteId})
+}
+
+// Extended returns an io.ReadWriter that sends and receives data on the given,
+// SSH extended stream. Such streams are used, for example, for stderr.
+func (ch *channel) Extended(code uint32) io.ReadWriter {
+ if !ch.decided {
+ return nil
+ }
+ return &extChannel{code, ch}
+}
+
+func (ch *channel) Stderr() io.ReadWriter {
+ return ch.Extended(1)
+}
+
+func (ch *channel) SendRequest(name string, wantReply bool, payload []byte) (bool, error) {
+ if !ch.decided {
+ return false, errUndecided
+ }
+
+ if wantReply {
+ ch.sentRequestMu.Lock()
+ defer ch.sentRequestMu.Unlock()
+ }
+
+ msg := channelRequestMsg{
+ PeersId: ch.remoteId,
+ Request: name,
+ WantReply: wantReply,
+ RequestSpecificData: payload,
+ }
+
+ if err := ch.sendMessage(msg); err != nil {
+ return false, err
+ }
+
+ if wantReply {
+ m, ok := (<-ch.msg)
+ if !ok {
+ return false, io.EOF
+ }
+ switch m.(type) {
+ case *channelRequestFailureMsg:
+ return false, nil
+ case *channelRequestSuccessMsg:
+ return true, nil
+ default:
+ return false, fmt.Errorf("ssh: unexpected response to channel request: %#v", m)
+ }
+ }
+
+ return false, nil
+}
+
+// ackRequest either sends an ack or nack to the channel request.
+func (ch *channel) ackRequest(ok bool) error {
+ if !ch.decided {
+ return errUndecided
+ }
+
+ var msg interface{}
+ if !ok {
+ msg = channelRequestFailureMsg{
+ PeersId: ch.remoteId,
+ }
+ } else {
+ msg = channelRequestSuccessMsg{
+ PeersId: ch.remoteId,
+ }
+ }
+ return ch.sendMessage(msg)
+}
+
+func (ch *channel) ChannelType() string {
+ return ch.chanType
+}
+
+func (ch *channel) ExtraData() []byte {
+ return ch.extraData
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/cipher.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/cipher.go
new file mode 100644
index 000000000..aed2b1f01
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/cipher.go
@@ -0,0 +1,629 @@
+// Copyright 2011 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 ssh
+
+import (
+ "crypto/aes"
+ "crypto/cipher"
+ "crypto/des"
+ "crypto/rc4"
+ "crypto/subtle"
+ "encoding/binary"
+ "errors"
+ "fmt"
+ "hash"
+ "io"
+ "io/ioutil"
+)
+
+const (
+ packetSizeMultiple = 16 // TODO(huin) this should be determined by the cipher.
+
+ // RFC 4253 section 6.1 defines a minimum packet size of 32768 that implementations
+ // MUST be able to process (plus a few more kilobytes for padding and mac). The RFC
+ // indicates implementations SHOULD be able to handle larger packet sizes, but then
+ // waffles on about reasonable limits.
+ //
+ // OpenSSH caps their maxPacket at 256kB so we choose to do
+ // the same. maxPacket is also used to ensure that uint32
+ // length fields do not overflow, so it should remain well
+ // below 4G.
+ maxPacket = 256 * 1024
+)
+
+// noneCipher implements cipher.Stream and provides no encryption. It is used
+// by the transport before the first key-exchange.
+type noneCipher struct{}
+
+func (c noneCipher) XORKeyStream(dst, src []byte) {
+ copy(dst, src)
+}
+
+func newAESCTR(key, iv []byte) (cipher.Stream, error) {
+ c, err := aes.NewCipher(key)
+ if err != nil {
+ return nil, err
+ }
+ return cipher.NewCTR(c, iv), nil
+}
+
+func newRC4(key, iv []byte) (cipher.Stream, error) {
+ return rc4.NewCipher(key)
+}
+
+type streamCipherMode struct {
+ keySize int
+ ivSize int
+ skip int
+ createFunc func(key, iv []byte) (cipher.Stream, error)
+}
+
+func (c *streamCipherMode) createStream(key, iv []byte) (cipher.Stream, error) {
+ if len(key) < c.keySize {
+ panic("ssh: key length too small for cipher")
+ }
+ if len(iv) < c.ivSize {
+ panic("ssh: iv too small for cipher")
+ }
+
+ stream, err := c.createFunc(key[:c.keySize], iv[:c.ivSize])
+ if err != nil {
+ return nil, err
+ }
+
+ var streamDump []byte
+ if c.skip > 0 {
+ streamDump = make([]byte, 512)
+ }
+
+ for remainingToDump := c.skip; remainingToDump > 0; {
+ dumpThisTime := remainingToDump
+ if dumpThisTime > len(streamDump) {
+ dumpThisTime = len(streamDump)
+ }
+ stream.XORKeyStream(streamDump[:dumpThisTime], streamDump[:dumpThisTime])
+ remainingToDump -= dumpThisTime
+ }
+
+ return stream, nil
+}
+
+// cipherModes documents properties of supported ciphers. Ciphers not included
+// are not supported and will not be negotiated, even if explicitly requested in
+// ClientConfig.Crypto.Ciphers.
+var cipherModes = map[string]*streamCipherMode{
+ // Ciphers from RFC4344, which introduced many CTR-based ciphers. Algorithms
+ // are defined in the order specified in the RFC.
+ "aes128-ctr": {16, aes.BlockSize, 0, newAESCTR},
+ "aes192-ctr": {24, aes.BlockSize, 0, newAESCTR},
+ "aes256-ctr": {32, aes.BlockSize, 0, newAESCTR},
+
+ // Ciphers from RFC4345, which introduces security-improved arcfour ciphers.
+ // They are defined in the order specified in the RFC.
+ "arcfour128": {16, 0, 1536, newRC4},
+ "arcfour256": {32, 0, 1536, newRC4},
+
+ // Cipher defined in RFC 4253, which describes SSH Transport Layer Protocol.
+ // Note that this cipher is not safe, as stated in RFC 4253: "Arcfour (and
+ // RC4) has problems with weak keys, and should be used with caution."
+ // RFC4345 introduces improved versions of Arcfour.
+ "arcfour": {16, 0, 0, newRC4},
+
+ // AES-GCM is not a stream cipher, so it is constructed with a
+ // special case. If we add any more non-stream ciphers, we
+ // should invest a cleaner way to do this.
+ gcmCipherID: {16, 12, 0, nil},
+
+ // CBC mode is insecure and so is not included in the default config.
+ // (See http://www.isg.rhul.ac.uk/~kp/SandPfinal.pdf). If absolutely
+ // needed, it's possible to specify a custom Config to enable it.
+ // You should expect that an active attacker can recover plaintext if
+ // you do.
+ aes128cbcID: {16, aes.BlockSize, 0, nil},
+
+ // 3des-cbc is insecure and is disabled by default.
+ tripledescbcID: {24, des.BlockSize, 0, nil},
+}
+
+// prefixLen is the length of the packet prefix that contains the packet length
+// and number of padding bytes.
+const prefixLen = 5
+
+// streamPacketCipher is a packetCipher using a stream cipher.
+type streamPacketCipher struct {
+ mac hash.Hash
+ cipher cipher.Stream
+ etm bool
+
+ // The following members are to avoid per-packet allocations.
+ prefix [prefixLen]byte
+ seqNumBytes [4]byte
+ padding [2 * packetSizeMultiple]byte
+ packetData []byte
+ macResult []byte
+}
+
+// readPacket reads and decrypt a single packet from the reader argument.
+func (s *streamPacketCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, error) {
+ if _, err := io.ReadFull(r, s.prefix[:]); err != nil {
+ return nil, err
+ }
+
+ var encryptedPaddingLength [1]byte
+ if s.mac != nil && s.etm {
+ copy(encryptedPaddingLength[:], s.prefix[4:5])
+ s.cipher.XORKeyStream(s.prefix[4:5], s.prefix[4:5])
+ } else {
+ s.cipher.XORKeyStream(s.prefix[:], s.prefix[:])
+ }
+
+ length := binary.BigEndian.Uint32(s.prefix[0:4])
+ paddingLength := uint32(s.prefix[4])
+
+ var macSize uint32
+ if s.mac != nil {
+ s.mac.Reset()
+ binary.BigEndian.PutUint32(s.seqNumBytes[:], seqNum)
+ s.mac.Write(s.seqNumBytes[:])
+ if s.etm {
+ s.mac.Write(s.prefix[:4])
+ s.mac.Write(encryptedPaddingLength[:])
+ } else {
+ s.mac.Write(s.prefix[:])
+ }
+ macSize = uint32(s.mac.Size())
+ }
+
+ if length <= paddingLength+1 {
+ return nil, errors.New("ssh: invalid packet length, packet too small")
+ }
+
+ if length > maxPacket {
+ return nil, errors.New("ssh: invalid packet length, packet too large")
+ }
+
+ // the maxPacket check above ensures that length-1+macSize
+ // does not overflow.
+ if uint32(cap(s.packetData)) < length-1+macSize {
+ s.packetData = make([]byte, length-1+macSize)
+ } else {
+ s.packetData = s.packetData[:length-1+macSize]
+ }
+
+ if _, err := io.ReadFull(r, s.packetData); err != nil {
+ return nil, err
+ }
+ mac := s.packetData[length-1:]
+ data := s.packetData[:length-1]
+
+ if s.mac != nil && s.etm {
+ s.mac.Write(data)
+ }
+
+ s.cipher.XORKeyStream(data, data)
+
+ if s.mac != nil {
+ if !s.etm {
+ s.mac.Write(data)
+ }
+ s.macResult = s.mac.Sum(s.macResult[:0])
+ if subtle.ConstantTimeCompare(s.macResult, mac) != 1 {
+ return nil, errors.New("ssh: MAC failure")
+ }
+ }
+
+ return s.packetData[:length-paddingLength-1], nil
+}
+
+// writePacket encrypts and sends a packet of data to the writer argument
+func (s *streamPacketCipher) writePacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error {
+ if len(packet) > maxPacket {
+ return errors.New("ssh: packet too large")
+ }
+
+ aadlen := 0
+ if s.mac != nil && s.etm {
+ // packet length is not encrypted for EtM modes
+ aadlen = 4
+ }
+
+ paddingLength := packetSizeMultiple - (prefixLen+len(packet)-aadlen)%packetSizeMultiple
+ if paddingLength < 4 {
+ paddingLength += packetSizeMultiple
+ }
+
+ length := len(packet) + 1 + paddingLength
+ binary.BigEndian.PutUint32(s.prefix[:], uint32(length))
+ s.prefix[4] = byte(paddingLength)
+ padding := s.padding[:paddingLength]
+ if _, err := io.ReadFull(rand, padding); err != nil {
+ return err
+ }
+
+ if s.mac != nil {
+ s.mac.Reset()
+ binary.BigEndian.PutUint32(s.seqNumBytes[:], seqNum)
+ s.mac.Write(s.seqNumBytes[:])
+
+ if s.etm {
+ // For EtM algorithms, the packet length must stay unencrypted,
+ // but the following data (padding length) must be encrypted
+ s.cipher.XORKeyStream(s.prefix[4:5], s.prefix[4:5])
+ }
+
+ s.mac.Write(s.prefix[:])
+
+ if !s.etm {
+ // For non-EtM algorithms, the algorithm is applied on unencrypted data
+ s.mac.Write(packet)
+ s.mac.Write(padding)
+ }
+ }
+
+ if !(s.mac != nil && s.etm) {
+ // For EtM algorithms, the padding length has already been encrypted
+ // and the packet length must remain unencrypted
+ s.cipher.XORKeyStream(s.prefix[:], s.prefix[:])
+ }
+
+ s.cipher.XORKeyStream(packet, packet)
+ s.cipher.XORKeyStream(padding, padding)
+
+ if s.mac != nil && s.etm {
+ // For EtM algorithms, packet and padding must be encrypted
+ s.mac.Write(packet)
+ s.mac.Write(padding)
+ }
+
+ if _, err := w.Write(s.prefix[:]); err != nil {
+ return err
+ }
+ if _, err := w.Write(packet); err != nil {
+ return err
+ }
+ if _, err := w.Write(padding); err != nil {
+ return err
+ }
+
+ if s.mac != nil {
+ s.macResult = s.mac.Sum(s.macResult[:0])
+ if _, err := w.Write(s.macResult); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+type gcmCipher struct {
+ aead cipher.AEAD
+ prefix [4]byte
+ iv []byte
+ buf []byte
+}
+
+func newGCMCipher(iv, key []byte) (packetCipher, error) {
+ c, err := aes.NewCipher(key)
+ if err != nil {
+ return nil, err
+ }
+
+ aead, err := cipher.NewGCM(c)
+ if err != nil {
+ return nil, err
+ }
+
+ return &gcmCipher{
+ aead: aead,
+ iv: iv,
+ }, nil
+}
+
+const gcmTagSize = 16
+
+func (c *gcmCipher) writePacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error {
+ // Pad out to multiple of 16 bytes. This is different from the
+ // stream cipher because that encrypts the length too.
+ padding := byte(packetSizeMultiple - (1+len(packet))%packetSizeMultiple)
+ if padding < 4 {
+ padding += packetSizeMultiple
+ }
+
+ length := uint32(len(packet) + int(padding) + 1)
+ binary.BigEndian.PutUint32(c.prefix[:], length)
+ if _, err := w.Write(c.prefix[:]); err != nil {
+ return err
+ }
+
+ if cap(c.buf) < int(length) {
+ c.buf = make([]byte, length)
+ } else {
+ c.buf = c.buf[:length]
+ }
+
+ c.buf[0] = padding
+ copy(c.buf[1:], packet)
+ if _, err := io.ReadFull(rand, c.buf[1+len(packet):]); err != nil {
+ return err
+ }
+ c.buf = c.aead.Seal(c.buf[:0], c.iv, c.buf, c.prefix[:])
+ if _, err := w.Write(c.buf); err != nil {
+ return err
+ }
+ c.incIV()
+
+ return nil
+}
+
+func (c *gcmCipher) incIV() {
+ for i := 4 + 7; i >= 4; i-- {
+ c.iv[i]++
+ if c.iv[i] != 0 {
+ break
+ }
+ }
+}
+
+func (c *gcmCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, error) {
+ if _, err := io.ReadFull(r, c.prefix[:]); err != nil {
+ return nil, err
+ }
+ length := binary.BigEndian.Uint32(c.prefix[:])
+ if length > maxPacket {
+ return nil, errors.New("ssh: max packet length exceeded.")
+ }
+
+ if cap(c.buf) < int(length+gcmTagSize) {
+ c.buf = make([]byte, length+gcmTagSize)
+ } else {
+ c.buf = c.buf[:length+gcmTagSize]
+ }
+
+ if _, err := io.ReadFull(r, c.buf); err != nil {
+ return nil, err
+ }
+
+ plain, err := c.aead.Open(c.buf[:0], c.iv, c.buf, c.prefix[:])
+ if err != nil {
+ return nil, err
+ }
+ c.incIV()
+
+ padding := plain[0]
+ if padding < 4 {
+ // padding is a byte, so it automatically satisfies
+ // the maximum size, which is 255.
+ return nil, fmt.Errorf("ssh: illegal padding %d", padding)
+ }
+
+ if int(padding+1) >= len(plain) {
+ return nil, fmt.Errorf("ssh: padding %d too large", padding)
+ }
+ plain = plain[1 : length-uint32(padding)]
+ return plain, nil
+}
+
+// cbcCipher implements aes128-cbc cipher defined in RFC 4253 section 6.1
+type cbcCipher struct {
+ mac hash.Hash
+ macSize uint32
+ decrypter cipher.BlockMode
+ encrypter cipher.BlockMode
+
+ // The following members are to avoid per-packet allocations.
+ seqNumBytes [4]byte
+ packetData []byte
+ macResult []byte
+
+ // Amount of data we should still read to hide which
+ // verification error triggered.
+ oracleCamouflage uint32
+}
+
+func newCBCCipher(c cipher.Block, iv, key, macKey []byte, algs directionAlgorithms) (packetCipher, error) {
+ cbc := &cbcCipher{
+ mac: macModes[algs.MAC].new(macKey),
+ decrypter: cipher.NewCBCDecrypter(c, iv),
+ encrypter: cipher.NewCBCEncrypter(c, iv),
+ packetData: make([]byte, 1024),
+ }
+ if cbc.mac != nil {
+ cbc.macSize = uint32(cbc.mac.Size())
+ }
+
+ return cbc, nil
+}
+
+func newAESCBCCipher(iv, key, macKey []byte, algs directionAlgorithms) (packetCipher, error) {
+ c, err := aes.NewCipher(key)
+ if err != nil {
+ return nil, err
+ }
+
+ cbc, err := newCBCCipher(c, iv, key, macKey, algs)
+ if err != nil {
+ return nil, err
+ }
+
+ return cbc, nil
+}
+
+func newTripleDESCBCCipher(iv, key, macKey []byte, algs directionAlgorithms) (packetCipher, error) {
+ c, err := des.NewTripleDESCipher(key)
+ if err != nil {
+ return nil, err
+ }
+
+ cbc, err := newCBCCipher(c, iv, key, macKey, algs)
+ if err != nil {
+ return nil, err
+ }
+
+ return cbc, nil
+}
+
+func maxUInt32(a, b int) uint32 {
+ if a > b {
+ return uint32(a)
+ }
+ return uint32(b)
+}
+
+const (
+ cbcMinPacketSizeMultiple = 8
+ cbcMinPacketSize = 16
+ cbcMinPaddingSize = 4
+)
+
+// cbcError represents a verification error that may leak information.
+type cbcError string
+
+func (e cbcError) Error() string { return string(e) }
+
+func (c *cbcCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, error) {
+ p, err := c.readPacketLeaky(seqNum, r)
+ if err != nil {
+ if _, ok := err.(cbcError); ok {
+ // Verification error: read a fixed amount of
+ // data, to make distinguishing between
+ // failing MAC and failing length check more
+ // difficult.
+ io.CopyN(ioutil.Discard, r, int64(c.oracleCamouflage))
+ }
+ }
+ return p, err
+}
+
+func (c *cbcCipher) readPacketLeaky(seqNum uint32, r io.Reader) ([]byte, error) {
+ blockSize := c.decrypter.BlockSize()
+
+ // Read the header, which will include some of the subsequent data in the
+ // case of block ciphers - this is copied back to the payload later.
+ // How many bytes of payload/padding will be read with this first read.
+ firstBlockLength := uint32((prefixLen + blockSize - 1) / blockSize * blockSize)
+ firstBlock := c.packetData[:firstBlockLength]
+ if _, err := io.ReadFull(r, firstBlock); err != nil {
+ return nil, err
+ }
+
+ c.oracleCamouflage = maxPacket + 4 + c.macSize - firstBlockLength
+
+ c.decrypter.CryptBlocks(firstBlock, firstBlock)
+ length := binary.BigEndian.Uint32(firstBlock[:4])
+ if length > maxPacket {
+ return nil, cbcError("ssh: packet too large")
+ }
+ if length+4 < maxUInt32(cbcMinPacketSize, blockSize) {
+ // The minimum size of a packet is 16 (or the cipher block size, whichever
+ // is larger) bytes.
+ return nil, cbcError("ssh: packet too small")
+ }
+ // The length of the packet (including the length field but not the MAC) must
+ // be a multiple of the block size or 8, whichever is larger.
+ if (length+4)%maxUInt32(cbcMinPacketSizeMultiple, blockSize) != 0 {
+ return nil, cbcError("ssh: invalid packet length multiple")
+ }
+
+ paddingLength := uint32(firstBlock[4])
+ if paddingLength < cbcMinPaddingSize || length <= paddingLength+1 {
+ return nil, cbcError("ssh: invalid packet length")
+ }
+
+ // Positions within the c.packetData buffer:
+ macStart := 4 + length
+ paddingStart := macStart - paddingLength
+
+ // Entire packet size, starting before length, ending at end of mac.
+ entirePacketSize := macStart + c.macSize
+
+ // Ensure c.packetData is large enough for the entire packet data.
+ if uint32(cap(c.packetData)) < entirePacketSize {
+ // Still need to upsize and copy, but this should be rare at runtime, only
+ // on upsizing the packetData buffer.
+ c.packetData = make([]byte, entirePacketSize)
+ copy(c.packetData, firstBlock)
+ } else {
+ c.packetData = c.packetData[:entirePacketSize]
+ }
+
+ if n, err := io.ReadFull(r, c.packetData[firstBlockLength:]); err != nil {
+ return nil, err
+ } else {
+ c.oracleCamouflage -= uint32(n)
+ }
+
+ remainingCrypted := c.packetData[firstBlockLength:macStart]
+ c.decrypter.CryptBlocks(remainingCrypted, remainingCrypted)
+
+ mac := c.packetData[macStart:]
+ if c.mac != nil {
+ c.mac.Reset()
+ binary.BigEndian.PutUint32(c.seqNumBytes[:], seqNum)
+ c.mac.Write(c.seqNumBytes[:])
+ c.mac.Write(c.packetData[:macStart])
+ c.macResult = c.mac.Sum(c.macResult[:0])
+ if subtle.ConstantTimeCompare(c.macResult, mac) != 1 {
+ return nil, cbcError("ssh: MAC failure")
+ }
+ }
+
+ return c.packetData[prefixLen:paddingStart], nil
+}
+
+func (c *cbcCipher) writePacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error {
+ effectiveBlockSize := maxUInt32(cbcMinPacketSizeMultiple, c.encrypter.BlockSize())
+
+ // Length of encrypted portion of the packet (header, payload, padding).
+ // Enforce minimum padding and packet size.
+ encLength := maxUInt32(prefixLen+len(packet)+cbcMinPaddingSize, cbcMinPaddingSize)
+ // Enforce block size.
+ encLength = (encLength + effectiveBlockSize - 1) / effectiveBlockSize * effectiveBlockSize
+
+ length := encLength - 4
+ paddingLength := int(length) - (1 + len(packet))
+
+ // Overall buffer contains: header, payload, padding, mac.
+ // Space for the MAC is reserved in the capacity but not the slice length.
+ bufferSize := encLength + c.macSize
+ if uint32(cap(c.packetData)) < bufferSize {
+ c.packetData = make([]byte, encLength, bufferSize)
+ } else {
+ c.packetData = c.packetData[:encLength]
+ }
+
+ p := c.packetData
+
+ // Packet header.
+ binary.BigEndian.PutUint32(p, length)
+ p = p[4:]
+ p[0] = byte(paddingLength)
+
+ // Payload.
+ p = p[1:]
+ copy(p, packet)
+
+ // Padding.
+ p = p[len(packet):]
+ if _, err := io.ReadFull(rand, p); err != nil {
+ return err
+ }
+
+ if c.mac != nil {
+ c.mac.Reset()
+ binary.BigEndian.PutUint32(c.seqNumBytes[:], seqNum)
+ c.mac.Write(c.seqNumBytes[:])
+ c.mac.Write(c.packetData)
+ // The MAC is now appended into the capacity reserved for it earlier.
+ c.packetData = c.mac.Sum(c.packetData)
+ }
+
+ c.encrypter.CryptBlocks(c.packetData[:encLength], c.packetData[:encLength])
+
+ if _, err := w.Write(c.packetData); err != nil {
+ return err
+ }
+
+ return nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/cipher_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/cipher_test.go
new file mode 100644
index 000000000..5cfa17a62
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/cipher_test.go
@@ -0,0 +1,129 @@
+// Copyright 2011 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 ssh
+
+import (
+ "bytes"
+ "crypto"
+ "crypto/aes"
+ "crypto/rand"
+ "testing"
+)
+
+func TestDefaultCiphersExist(t *testing.T) {
+ for _, cipherAlgo := range supportedCiphers {
+ if _, ok := cipherModes[cipherAlgo]; !ok {
+ t.Errorf("default cipher %q is unknown", cipherAlgo)
+ }
+ }
+}
+
+func TestPacketCiphers(t *testing.T) {
+ // Still test aes128cbc cipher although it's commented out.
+ cipherModes[aes128cbcID] = &streamCipherMode{16, aes.BlockSize, 0, nil}
+ defer delete(cipherModes, aes128cbcID)
+
+ for cipher := range cipherModes {
+ for mac := range macModes {
+ kr := &kexResult{Hash: crypto.SHA1}
+ algs := directionAlgorithms{
+ Cipher: cipher,
+ MAC: mac,
+ Compression: "none",
+ }
+ client, err := newPacketCipher(clientKeys, algs, kr)
+ if err != nil {
+ t.Errorf("newPacketCipher(client, %q, %q): %v", cipher, mac, err)
+ continue
+ }
+ server, err := newPacketCipher(clientKeys, algs, kr)
+ if err != nil {
+ t.Errorf("newPacketCipher(client, %q, %q): %v", cipher, mac, err)
+ continue
+ }
+
+ want := "bla bla"
+ input := []byte(want)
+ buf := &bytes.Buffer{}
+ if err := client.writePacket(0, buf, rand.Reader, input); err != nil {
+ t.Errorf("writePacket(%q, %q): %v", cipher, mac, err)
+ continue
+ }
+
+ packet, err := server.readPacket(0, buf)
+ if err != nil {
+ t.Errorf("readPacket(%q, %q): %v", cipher, mac, err)
+ continue
+ }
+
+ if string(packet) != want {
+ t.Errorf("roundtrip(%q, %q): got %q, want %q", cipher, mac, packet, want)
+ }
+ }
+ }
+}
+
+func TestCBCOracleCounterMeasure(t *testing.T) {
+ cipherModes[aes128cbcID] = &streamCipherMode{16, aes.BlockSize, 0, nil}
+ defer delete(cipherModes, aes128cbcID)
+
+ kr := &kexResult{Hash: crypto.SHA1}
+ algs := directionAlgorithms{
+ Cipher: aes128cbcID,
+ MAC: "hmac-sha1",
+ Compression: "none",
+ }
+ client, err := newPacketCipher(clientKeys, algs, kr)
+ if err != nil {
+ t.Fatalf("newPacketCipher(client): %v", err)
+ }
+
+ want := "bla bla"
+ input := []byte(want)
+ buf := &bytes.Buffer{}
+ if err := client.writePacket(0, buf, rand.Reader, input); err != nil {
+ t.Errorf("writePacket: %v", err)
+ }
+
+ packetSize := buf.Len()
+ buf.Write(make([]byte, 2*maxPacket))
+
+ // We corrupt each byte, but this usually will only test the
+ // 'packet too large' or 'MAC failure' cases.
+ lastRead := -1
+ for i := 0; i < packetSize; i++ {
+ server, err := newPacketCipher(clientKeys, algs, kr)
+ if err != nil {
+ t.Fatalf("newPacketCipher(client): %v", err)
+ }
+
+ fresh := &bytes.Buffer{}
+ fresh.Write(buf.Bytes())
+ fresh.Bytes()[i] ^= 0x01
+
+ before := fresh.Len()
+ _, err = server.readPacket(0, fresh)
+ if err == nil {
+ t.Errorf("corrupt byte %d: readPacket succeeded ", i)
+ continue
+ }
+ if _, ok := err.(cbcError); !ok {
+ t.Errorf("corrupt byte %d: got %v (%T), want cbcError", i, err, err)
+ continue
+ }
+
+ after := fresh.Len()
+ bytesRead := before - after
+ if bytesRead < maxPacket {
+ t.Errorf("corrupt byte %d: read %d bytes, want more than %d", i, bytesRead, maxPacket)
+ continue
+ }
+
+ if i > 0 && bytesRead != lastRead {
+ t.Errorf("corrupt byte %d: read %d bytes, want %d bytes read", i, bytesRead, lastRead)
+ }
+ lastRead = bytesRead
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/client.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/client.go
new file mode 100644
index 000000000..6fd199455
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/client.go
@@ -0,0 +1,278 @@
+// Copyright 2011 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 ssh
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "net"
+ "os"
+ "sync"
+ "time"
+)
+
+// Client implements a traditional SSH client that supports shells,
+// subprocesses, TCP port/streamlocal forwarding and tunneled dialing.
+type Client struct {
+ Conn
+
+ forwards forwardList // forwarded tcpip connections from the remote side
+ mu sync.Mutex
+ channelHandlers map[string]chan NewChannel
+}
+
+// HandleChannelOpen returns a channel on which NewChannel requests
+// for the given type are sent. If the type already is being handled,
+// nil is returned. The channel is closed when the connection is closed.
+func (c *Client) HandleChannelOpen(channelType string) <-chan NewChannel {
+ c.mu.Lock()
+ defer c.mu.Unlock()
+ if c.channelHandlers == nil {
+ // The SSH channel has been closed.
+ c := make(chan NewChannel)
+ close(c)
+ return c
+ }
+
+ ch := c.channelHandlers[channelType]
+ if ch != nil {
+ return nil
+ }
+
+ ch = make(chan NewChannel, chanSize)
+ c.channelHandlers[channelType] = ch
+ return ch
+}
+
+// NewClient creates a Client on top of the given connection.
+func NewClient(c Conn, chans <-chan NewChannel, reqs <-chan *Request) *Client {
+ conn := &Client{
+ Conn: c,
+ channelHandlers: make(map[string]chan NewChannel, 1),
+ }
+
+ go conn.handleGlobalRequests(reqs)
+ go conn.handleChannelOpens(chans)
+ go func() {
+ conn.Wait()
+ conn.forwards.closeAll()
+ }()
+ go conn.forwards.handleChannels(conn.HandleChannelOpen("forwarded-tcpip"))
+ go conn.forwards.handleChannels(conn.HandleChannelOpen("forwarded-streamlocal@openssh.com"))
+ return conn
+}
+
+// NewClientConn establishes an authenticated SSH connection using c
+// as the underlying transport. The Request and NewChannel channels
+// must be serviced or the connection will hang.
+func NewClientConn(c net.Conn, addr string, config *ClientConfig) (Conn, <-chan NewChannel, <-chan *Request, error) {
+ fullConf := *config
+ fullConf.SetDefaults()
+ if fullConf.HostKeyCallback == nil {
+ c.Close()
+ return nil, nil, nil, errors.New("ssh: must specify HostKeyCallback")
+ }
+
+ conn := &connection{
+ sshConn: sshConn{conn: c},
+ }
+
+ if err := conn.clientHandshake(addr, &fullConf); err != nil {
+ c.Close()
+ return nil, nil, nil, fmt.Errorf("ssh: handshake failed: %v", err)
+ }
+ conn.mux = newMux(conn.transport)
+ return conn, conn.mux.incomingChannels, conn.mux.incomingRequests, nil
+}
+
+// clientHandshake performs the client side key exchange. See RFC 4253 Section
+// 7.
+func (c *connection) clientHandshake(dialAddress string, config *ClientConfig) error {
+ if config.ClientVersion != "" {
+ c.clientVersion = []byte(config.ClientVersion)
+ } else {
+ c.clientVersion = []byte(packageVersion)
+ }
+ var err error
+ c.serverVersion, err = exchangeVersions(c.sshConn.conn, c.clientVersion)
+ if err != nil {
+ return err
+ }
+
+ c.transport = newClientTransport(
+ newTransport(c.sshConn.conn, config.Rand, true /* is client */),
+ c.clientVersion, c.serverVersion, config, dialAddress, c.sshConn.RemoteAddr())
+ if err := c.transport.waitSession(); err != nil {
+ return err
+ }
+
+ c.sessionID = c.transport.getSessionID()
+ return c.clientAuthenticate(config)
+}
+
+// verifyHostKeySignature verifies the host key obtained in the key
+// exchange.
+func verifyHostKeySignature(hostKey PublicKey, result *kexResult) error {
+ sig, rest, ok := parseSignatureBody(result.Signature)
+ if len(rest) > 0 || !ok {
+ return errors.New("ssh: signature parse error")
+ }
+
+ return hostKey.Verify(result.H, sig)
+}
+
+// NewSession opens a new Session for this client. (A session is a remote
+// execution of a program.)
+func (c *Client) NewSession() (*Session, error) {
+ ch, in, err := c.OpenChannel("session", nil)
+ if err != nil {
+ return nil, err
+ }
+ return newSession(ch, in)
+}
+
+func (c *Client) handleGlobalRequests(incoming <-chan *Request) {
+ for r := range incoming {
+ // This handles keepalive messages and matches
+ // the behaviour of OpenSSH.
+ r.Reply(false, nil)
+ }
+}
+
+// handleChannelOpens channel open messages from the remote side.
+func (c *Client) handleChannelOpens(in <-chan NewChannel) {
+ for ch := range in {
+ c.mu.Lock()
+ handler := c.channelHandlers[ch.ChannelType()]
+ c.mu.Unlock()
+
+ if handler != nil {
+ handler <- ch
+ } else {
+ ch.Reject(UnknownChannelType, fmt.Sprintf("unknown channel type: %v", ch.ChannelType()))
+ }
+ }
+
+ c.mu.Lock()
+ for _, ch := range c.channelHandlers {
+ close(ch)
+ }
+ c.channelHandlers = nil
+ c.mu.Unlock()
+}
+
+// Dial starts a client connection to the given SSH server. It is a
+// convenience function that connects to the given network address,
+// initiates the SSH handshake, and then sets up a Client. For access
+// to incoming channels and requests, use net.Dial with NewClientConn
+// instead.
+func Dial(network, addr string, config *ClientConfig) (*Client, error) {
+ conn, err := net.DialTimeout(network, addr, config.Timeout)
+ if err != nil {
+ return nil, err
+ }
+ c, chans, reqs, err := NewClientConn(conn, addr, config)
+ if err != nil {
+ return nil, err
+ }
+ return NewClient(c, chans, reqs), nil
+}
+
+// HostKeyCallback is the function type used for verifying server
+// keys. A HostKeyCallback must return nil if the host key is OK, or
+// an error to reject it. It receives the hostname as passed to Dial
+// or NewClientConn. The remote address is the RemoteAddr of the
+// net.Conn underlying the the SSH connection.
+type HostKeyCallback func(hostname string, remote net.Addr, key PublicKey) error
+
+// BannerCallback is the function type used for treat the banner sent by
+// the server. A BannerCallback receives the message sent by the remote server.
+type BannerCallback func(message string) error
+
+// A ClientConfig structure is used to configure a Client. It must not be
+// modified after having been passed to an SSH function.
+type ClientConfig struct {
+ // Config contains configuration that is shared between clients and
+ // servers.
+ Config
+
+ // User contains the username to authenticate as.
+ User string
+
+ // Auth contains possible authentication methods to use with the
+ // server. Only the first instance of a particular RFC 4252 method will
+ // be used during authentication.
+ Auth []AuthMethod
+
+ // HostKeyCallback is called during the cryptographic
+ // handshake to validate the server's host key. The client
+ // configuration must supply this callback for the connection
+ // to succeed. The functions InsecureIgnoreHostKey or
+ // FixedHostKey can be used for simplistic host key checks.
+ HostKeyCallback HostKeyCallback
+
+ // BannerCallback is called during the SSH dance to display a custom
+ // server's message. The client configuration can supply this callback to
+ // handle it as wished. The function BannerDisplayStderr can be used for
+ // simplistic display on Stderr.
+ BannerCallback BannerCallback
+
+ // ClientVersion contains the version identification string that will
+ // be used for the connection. If empty, a reasonable default is used.
+ ClientVersion string
+
+ // HostKeyAlgorithms lists the key types that the client will
+ // accept from the server as host key, in order of
+ // preference. If empty, a reasonable default is used. Any
+ // string returned from PublicKey.Type method may be used, or
+ // any of the CertAlgoXxxx and KeyAlgoXxxx constants.
+ HostKeyAlgorithms []string
+
+ // Timeout is the maximum amount of time for the TCP connection to establish.
+ //
+ // A Timeout of zero means no timeout.
+ Timeout time.Duration
+}
+
+// InsecureIgnoreHostKey returns a function that can be used for
+// ClientConfig.HostKeyCallback to accept any host key. It should
+// not be used for production code.
+func InsecureIgnoreHostKey() HostKeyCallback {
+ return func(hostname string, remote net.Addr, key PublicKey) error {
+ return nil
+ }
+}
+
+type fixedHostKey struct {
+ key PublicKey
+}
+
+func (f *fixedHostKey) check(hostname string, remote net.Addr, key PublicKey) error {
+ if f.key == nil {
+ return fmt.Errorf("ssh: required host key was nil")
+ }
+ if !bytes.Equal(key.Marshal(), f.key.Marshal()) {
+ return fmt.Errorf("ssh: host key mismatch")
+ }
+ return nil
+}
+
+// FixedHostKey returns a function for use in
+// ClientConfig.HostKeyCallback to accept only a specific host key.
+func FixedHostKey(key PublicKey) HostKeyCallback {
+ hk := &fixedHostKey{key}
+ return hk.check
+}
+
+// BannerDisplayStderr returns a function that can be used for
+// ClientConfig.BannerCallback to display banners on os.Stderr.
+func BannerDisplayStderr() BannerCallback {
+ return func(banner string) error {
+ _, err := os.Stderr.WriteString(banner)
+
+ return err
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/client_auth.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/client_auth.go
new file mode 100644
index 000000000..a1252cb9b
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/client_auth.go
@@ -0,0 +1,510 @@
+// Copyright 2011 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 ssh
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "io"
+)
+
+// clientAuthenticate authenticates with the remote server. See RFC 4252.
+func (c *connection) clientAuthenticate(config *ClientConfig) error {
+ // initiate user auth session
+ if err := c.transport.writePacket(Marshal(&serviceRequestMsg{serviceUserAuth})); err != nil {
+ return err
+ }
+ packet, err := c.transport.readPacket()
+ if err != nil {
+ return err
+ }
+ var serviceAccept serviceAcceptMsg
+ if err := Unmarshal(packet, &serviceAccept); err != nil {
+ return err
+ }
+
+ // during the authentication phase the client first attempts the "none" method
+ // then any untried methods suggested by the server.
+ tried := make(map[string]bool)
+ var lastMethods []string
+
+ sessionID := c.transport.getSessionID()
+ for auth := AuthMethod(new(noneAuth)); auth != nil; {
+ ok, methods, err := auth.auth(sessionID, config.User, c.transport, config.Rand)
+ if err != nil {
+ return err
+ }
+ if ok {
+ // success
+ return nil
+ }
+ tried[auth.method()] = true
+ if methods == nil {
+ methods = lastMethods
+ }
+ lastMethods = methods
+
+ auth = nil
+
+ findNext:
+ for _, a := range config.Auth {
+ candidateMethod := a.method()
+ if tried[candidateMethod] {
+ continue
+ }
+ for _, meth := range methods {
+ if meth == candidateMethod {
+ auth = a
+ break findNext
+ }
+ }
+ }
+ }
+ return fmt.Errorf("ssh: unable to authenticate, attempted methods %v, no supported methods remain", keys(tried))
+}
+
+func keys(m map[string]bool) []string {
+ s := make([]string, 0, len(m))
+
+ for key := range m {
+ s = append(s, key)
+ }
+ return s
+}
+
+// An AuthMethod represents an instance of an RFC 4252 authentication method.
+type AuthMethod interface {
+ // auth authenticates user over transport t.
+ // Returns true if authentication is successful.
+ // If authentication is not successful, a []string of alternative
+ // method names is returned. If the slice is nil, it will be ignored
+ // and the previous set of possible methods will be reused.
+ auth(session []byte, user string, p packetConn, rand io.Reader) (bool, []string, error)
+
+ // method returns the RFC 4252 method name.
+ method() string
+}
+
+// "none" authentication, RFC 4252 section 5.2.
+type noneAuth int
+
+func (n *noneAuth) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) {
+ if err := c.writePacket(Marshal(&userAuthRequestMsg{
+ User: user,
+ Service: serviceSSH,
+ Method: "none",
+ })); err != nil {
+ return false, nil, err
+ }
+
+ return handleAuthResponse(c)
+}
+
+func (n *noneAuth) method() string {
+ return "none"
+}
+
+// passwordCallback is an AuthMethod that fetches the password through
+// a function call, e.g. by prompting the user.
+type passwordCallback func() (password string, err error)
+
+func (cb passwordCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) {
+ type passwordAuthMsg struct {
+ User string `sshtype:"50"`
+ Service string
+ Method string
+ Reply bool
+ Password string
+ }
+
+ pw, err := cb()
+ // REVIEW NOTE: is there a need to support skipping a password attempt?
+ // The program may only find out that the user doesn't have a password
+ // when prompting.
+ if err != nil {
+ return false, nil, err
+ }
+
+ if err := c.writePacket(Marshal(&passwordAuthMsg{
+ User: user,
+ Service: serviceSSH,
+ Method: cb.method(),
+ Reply: false,
+ Password: pw,
+ })); err != nil {
+ return false, nil, err
+ }
+
+ return handleAuthResponse(c)
+}
+
+func (cb passwordCallback) method() string {
+ return "password"
+}
+
+// Password returns an AuthMethod using the given password.
+func Password(secret string) AuthMethod {
+ return passwordCallback(func() (string, error) { return secret, nil })
+}
+
+// PasswordCallback returns an AuthMethod that uses a callback for
+// fetching a password.
+func PasswordCallback(prompt func() (secret string, err error)) AuthMethod {
+ return passwordCallback(prompt)
+}
+
+type publickeyAuthMsg struct {
+ User string `sshtype:"50"`
+ Service string
+ Method string
+ // HasSig indicates to the receiver packet that the auth request is signed and
+ // should be used for authentication of the request.
+ HasSig bool
+ Algoname string
+ PubKey []byte
+ // Sig is tagged with "rest" so Marshal will exclude it during
+ // validateKey
+ Sig []byte `ssh:"rest"`
+}
+
+// publicKeyCallback is an AuthMethod that uses a set of key
+// pairs for authentication.
+type publicKeyCallback func() ([]Signer, error)
+
+func (cb publicKeyCallback) method() string {
+ return "publickey"
+}
+
+func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) {
+ // Authentication is performed by sending an enquiry to test if a key is
+ // acceptable to the remote. If the key is acceptable, the client will
+ // attempt to authenticate with the valid key. If not the client will repeat
+ // the process with the remaining keys.
+
+ signers, err := cb()
+ if err != nil {
+ return false, nil, err
+ }
+ var methods []string
+ for _, signer := range signers {
+ ok, err := validateKey(signer.PublicKey(), user, c)
+ if err != nil {
+ return false, nil, err
+ }
+ if !ok {
+ continue
+ }
+
+ pub := signer.PublicKey()
+ pubKey := pub.Marshal()
+ sign, err := signer.Sign(rand, buildDataSignedForAuth(session, userAuthRequestMsg{
+ User: user,
+ Service: serviceSSH,
+ Method: cb.method(),
+ }, []byte(pub.Type()), pubKey))
+ if err != nil {
+ return false, nil, err
+ }
+
+ // manually wrap the serialized signature in a string
+ s := Marshal(sign)
+ sig := make([]byte, stringLength(len(s)))
+ marshalString(sig, s)
+ msg := publickeyAuthMsg{
+ User: user,
+ Service: serviceSSH,
+ Method: cb.method(),
+ HasSig: true,
+ Algoname: pub.Type(),
+ PubKey: pubKey,
+ Sig: sig,
+ }
+ p := Marshal(&msg)
+ if err := c.writePacket(p); err != nil {
+ return false, nil, err
+ }
+ var success bool
+ success, methods, err = handleAuthResponse(c)
+ if err != nil {
+ return false, nil, err
+ }
+
+ // If authentication succeeds or the list of available methods does not
+ // contain the "publickey" method, do not attempt to authenticate with any
+ // other keys. According to RFC 4252 Section 7, the latter can occur when
+ // additional authentication methods are required.
+ if success || !containsMethod(methods, cb.method()) {
+ return success, methods, err
+ }
+ }
+
+ return false, methods, nil
+}
+
+func containsMethod(methods []string, method string) bool {
+ for _, m := range methods {
+ if m == method {
+ return true
+ }
+ }
+
+ return false
+}
+
+// validateKey validates the key provided is acceptable to the server.
+func validateKey(key PublicKey, user string, c packetConn) (bool, error) {
+ pubKey := key.Marshal()
+ msg := publickeyAuthMsg{
+ User: user,
+ Service: serviceSSH,
+ Method: "publickey",
+ HasSig: false,
+ Algoname: key.Type(),
+ PubKey: pubKey,
+ }
+ if err := c.writePacket(Marshal(&msg)); err != nil {
+ return false, err
+ }
+
+ return confirmKeyAck(key, c)
+}
+
+func confirmKeyAck(key PublicKey, c packetConn) (bool, error) {
+ pubKey := key.Marshal()
+ algoname := key.Type()
+
+ for {
+ packet, err := c.readPacket()
+ if err != nil {
+ return false, err
+ }
+ switch packet[0] {
+ case msgUserAuthBanner:
+ if err := handleBannerResponse(c, packet); err != nil {
+ return false, err
+ }
+ case msgUserAuthPubKeyOk:
+ var msg userAuthPubKeyOkMsg
+ if err := Unmarshal(packet, &msg); err != nil {
+ return false, err
+ }
+ if msg.Algo != algoname || !bytes.Equal(msg.PubKey, pubKey) {
+ return false, nil
+ }
+ return true, nil
+ case msgUserAuthFailure:
+ return false, nil
+ default:
+ return false, unexpectedMessageError(msgUserAuthSuccess, packet[0])
+ }
+ }
+}
+
+// PublicKeys returns an AuthMethod that uses the given key
+// pairs.
+func PublicKeys(signers ...Signer) AuthMethod {
+ return publicKeyCallback(func() ([]Signer, error) { return signers, nil })
+}
+
+// PublicKeysCallback returns an AuthMethod that runs the given
+// function to obtain a list of key pairs.
+func PublicKeysCallback(getSigners func() (signers []Signer, err error)) AuthMethod {
+ return publicKeyCallback(getSigners)
+}
+
+// handleAuthResponse returns whether the preceding authentication request succeeded
+// along with a list of remaining authentication methods to try next and
+// an error if an unexpected response was received.
+func handleAuthResponse(c packetConn) (bool, []string, error) {
+ for {
+ packet, err := c.readPacket()
+ if err != nil {
+ return false, nil, err
+ }
+
+ switch packet[0] {
+ case msgUserAuthBanner:
+ if err := handleBannerResponse(c, packet); err != nil {
+ return false, nil, err
+ }
+ case msgUserAuthFailure:
+ var msg userAuthFailureMsg
+ if err := Unmarshal(packet, &msg); err != nil {
+ return false, nil, err
+ }
+ return false, msg.Methods, nil
+ case msgUserAuthSuccess:
+ return true, nil, nil
+ default:
+ return false, nil, unexpectedMessageError(msgUserAuthSuccess, packet[0])
+ }
+ }
+}
+
+func handleBannerResponse(c packetConn, packet []byte) error {
+ var msg userAuthBannerMsg
+ if err := Unmarshal(packet, &msg); err != nil {
+ return err
+ }
+
+ transport, ok := c.(*handshakeTransport)
+ if !ok {
+ return nil
+ }
+
+ if transport.bannerCallback != nil {
+ return transport.bannerCallback(msg.Message)
+ }
+
+ return nil
+}
+
+// KeyboardInteractiveChallenge should print questions, optionally
+// disabling echoing (e.g. for passwords), and return all the answers.
+// Challenge may be called multiple times in a single session. After
+// successful authentication, the server may send a challenge with no
+// questions, for which the user and instruction messages should be
+// printed. RFC 4256 section 3.3 details how the UI should behave for
+// both CLI and GUI environments.
+type KeyboardInteractiveChallenge func(user, instruction string, questions []string, echos []bool) (answers []string, err error)
+
+// KeyboardInteractive returns an AuthMethod using a prompt/response
+// sequence controlled by the server.
+func KeyboardInteractive(challenge KeyboardInteractiveChallenge) AuthMethod {
+ return challenge
+}
+
+func (cb KeyboardInteractiveChallenge) method() string {
+ return "keyboard-interactive"
+}
+
+func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) {
+ type initiateMsg struct {
+ User string `sshtype:"50"`
+ Service string
+ Method string
+ Language string
+ Submethods string
+ }
+
+ if err := c.writePacket(Marshal(&initiateMsg{
+ User: user,
+ Service: serviceSSH,
+ Method: "keyboard-interactive",
+ })); err != nil {
+ return false, nil, err
+ }
+
+ for {
+ packet, err := c.readPacket()
+ if err != nil {
+ return false, nil, err
+ }
+
+ // like handleAuthResponse, but with less options.
+ switch packet[0] {
+ case msgUserAuthBanner:
+ if err := handleBannerResponse(c, packet); err != nil {
+ return false, nil, err
+ }
+ continue
+ case msgUserAuthInfoRequest:
+ // OK
+ case msgUserAuthFailure:
+ var msg userAuthFailureMsg
+ if err := Unmarshal(packet, &msg); err != nil {
+ return false, nil, err
+ }
+ return false, msg.Methods, nil
+ case msgUserAuthSuccess:
+ return true, nil, nil
+ default:
+ return false, nil, unexpectedMessageError(msgUserAuthInfoRequest, packet[0])
+ }
+
+ var msg userAuthInfoRequestMsg
+ if err := Unmarshal(packet, &msg); err != nil {
+ return false, nil, err
+ }
+
+ // Manually unpack the prompt/echo pairs.
+ rest := msg.Prompts
+ var prompts []string
+ var echos []bool
+ for i := 0; i < int(msg.NumPrompts); i++ {
+ prompt, r, ok := parseString(rest)
+ if !ok || len(r) == 0 {
+ return false, nil, errors.New("ssh: prompt format error")
+ }
+ prompts = append(prompts, string(prompt))
+ echos = append(echos, r[0] != 0)
+ rest = r[1:]
+ }
+
+ if len(rest) != 0 {
+ return false, nil, errors.New("ssh: extra data following keyboard-interactive pairs")
+ }
+
+ answers, err := cb(msg.User, msg.Instruction, prompts, echos)
+ if err != nil {
+ return false, nil, err
+ }
+
+ if len(answers) != len(prompts) {
+ return false, nil, errors.New("ssh: not enough answers from keyboard-interactive callback")
+ }
+ responseLength := 1 + 4
+ for _, a := range answers {
+ responseLength += stringLength(len(a))
+ }
+ serialized := make([]byte, responseLength)
+ p := serialized
+ p[0] = msgUserAuthInfoResponse
+ p = p[1:]
+ p = marshalUint32(p, uint32(len(answers)))
+ for _, a := range answers {
+ p = marshalString(p, []byte(a))
+ }
+
+ if err := c.writePacket(serialized); err != nil {
+ return false, nil, err
+ }
+ }
+}
+
+type retryableAuthMethod struct {
+ authMethod AuthMethod
+ maxTries int
+}
+
+func (r *retryableAuthMethod) auth(session []byte, user string, c packetConn, rand io.Reader) (ok bool, methods []string, err error) {
+ for i := 0; r.maxTries <= 0 || i < r.maxTries; i++ {
+ ok, methods, err = r.authMethod.auth(session, user, c, rand)
+ if ok || err != nil { // either success or error terminate
+ return ok, methods, err
+ }
+ }
+ return ok, methods, err
+}
+
+func (r *retryableAuthMethod) method() string {
+ return r.authMethod.method()
+}
+
+// RetryableAuthMethod is a decorator for other auth methods enabling them to
+// be retried up to maxTries before considering that AuthMethod itself failed.
+// If maxTries is <= 0, will retry indefinitely
+//
+// This is useful for interactive clients using challenge/response type
+// authentication (e.g. Keyboard-Interactive, Password, etc) where the user
+// could mistype their response resulting in the server issuing a
+// SSH_MSG_USERAUTH_FAILURE (rfc4252 #8 [password] and rfc4256 #3.4
+// [keyboard-interactive]); Without this decorator, the non-retryable
+// AuthMethod would be removed from future consideration, and never tried again
+// (and so the user would never be able to retry their entry).
+func RetryableAuthMethod(auth AuthMethod, maxTries int) AuthMethod {
+ return &retryableAuthMethod{authMethod: auth, maxTries: maxTries}
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/client_auth_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/client_auth_test.go
new file mode 100644
index 000000000..145b57a2b
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/client_auth_test.go
@@ -0,0 +1,628 @@
+// Copyright 2011 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 ssh
+
+import (
+ "bytes"
+ "crypto/rand"
+ "errors"
+ "fmt"
+ "os"
+ "strings"
+ "testing"
+)
+
+type keyboardInteractive map[string]string
+
+func (cr keyboardInteractive) Challenge(user string, instruction string, questions []string, echos []bool) ([]string, error) {
+ var answers []string
+ for _, q := range questions {
+ answers = append(answers, cr[q])
+ }
+ return answers, nil
+}
+
+// reused internally by tests
+var clientPassword = "tiger"
+
+// tryAuth runs a handshake with a given config against an SSH server
+// with config serverConfig
+func tryAuth(t *testing.T, config *ClientConfig) error {
+ c1, c2, err := netPipe()
+ if err != nil {
+ t.Fatalf("netPipe: %v", err)
+ }
+ defer c1.Close()
+ defer c2.Close()
+
+ certChecker := CertChecker{
+ IsUserAuthority: func(k PublicKey) bool {
+ return bytes.Equal(k.Marshal(), testPublicKeys["ecdsa"].Marshal())
+ },
+ UserKeyFallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) {
+ if conn.User() == "testuser" && bytes.Equal(key.Marshal(), testPublicKeys["rsa"].Marshal()) {
+ return nil, nil
+ }
+
+ return nil, fmt.Errorf("pubkey for %q not acceptable", conn.User())
+ },
+ IsRevoked: func(c *Certificate) bool {
+ return c.Serial == 666
+ },
+ }
+
+ serverConfig := &ServerConfig{
+ PasswordCallback: func(conn ConnMetadata, pass []byte) (*Permissions, error) {
+ if conn.User() == "testuser" && string(pass) == clientPassword {
+ return nil, nil
+ }
+ return nil, errors.New("password auth failed")
+ },
+ PublicKeyCallback: certChecker.Authenticate,
+ KeyboardInteractiveCallback: func(conn ConnMetadata, challenge KeyboardInteractiveChallenge) (*Permissions, error) {
+ ans, err := challenge("user",
+ "instruction",
+ []string{"question1", "question2"},
+ []bool{true, true})
+ if err != nil {
+ return nil, err
+ }
+ ok := conn.User() == "testuser" && ans[0] == "answer1" && ans[1] == "answer2"
+ if ok {
+ challenge("user", "motd", nil, nil)
+ return nil, nil
+ }
+ return nil, errors.New("keyboard-interactive failed")
+ },
+ }
+ serverConfig.AddHostKey(testSigners["rsa"])
+
+ go newServer(c1, serverConfig)
+ _, _, _, err = NewClientConn(c2, "", config)
+ return err
+}
+
+func TestClientAuthPublicKey(t *testing.T) {
+ config := &ClientConfig{
+ User: "testuser",
+ Auth: []AuthMethod{
+ PublicKeys(testSigners["rsa"]),
+ },
+ HostKeyCallback: InsecureIgnoreHostKey(),
+ }
+ if err := tryAuth(t, config); err != nil {
+ t.Fatalf("unable to dial remote side: %s", err)
+ }
+}
+
+func TestAuthMethodPassword(t *testing.T) {
+ config := &ClientConfig{
+ User: "testuser",
+ Auth: []AuthMethod{
+ Password(clientPassword),
+ },
+ HostKeyCallback: InsecureIgnoreHostKey(),
+ }
+
+ if err := tryAuth(t, config); err != nil {
+ t.Fatalf("unable to dial remote side: %s", err)
+ }
+}
+
+func TestAuthMethodFallback(t *testing.T) {
+ var passwordCalled bool
+ config := &ClientConfig{
+ User: "testuser",
+ Auth: []AuthMethod{
+ PublicKeys(testSigners["rsa"]),
+ PasswordCallback(
+ func() (string, error) {
+ passwordCalled = true
+ return "WRONG", nil
+ }),
+ },
+ HostKeyCallback: InsecureIgnoreHostKey(),
+ }
+
+ if err := tryAuth(t, config); err != nil {
+ t.Fatalf("unable to dial remote side: %s", err)
+ }
+
+ if passwordCalled {
+ t.Errorf("password auth tried before public-key auth.")
+ }
+}
+
+func TestAuthMethodWrongPassword(t *testing.T) {
+ config := &ClientConfig{
+ User: "testuser",
+ Auth: []AuthMethod{
+ Password("wrong"),
+ PublicKeys(testSigners["rsa"]),
+ },
+ HostKeyCallback: InsecureIgnoreHostKey(),
+ }
+
+ if err := tryAuth(t, config); err != nil {
+ t.Fatalf("unable to dial remote side: %s", err)
+ }
+}
+
+func TestAuthMethodKeyboardInteractive(t *testing.T) {
+ answers := keyboardInteractive(map[string]string{
+ "question1": "answer1",
+ "question2": "answer2",
+ })
+ config := &ClientConfig{
+ User: "testuser",
+ Auth: []AuthMethod{
+ KeyboardInteractive(answers.Challenge),
+ },
+ HostKeyCallback: InsecureIgnoreHostKey(),
+ }
+
+ if err := tryAuth(t, config); err != nil {
+ t.Fatalf("unable to dial remote side: %s", err)
+ }
+}
+
+func TestAuthMethodWrongKeyboardInteractive(t *testing.T) {
+ answers := keyboardInteractive(map[string]string{
+ "question1": "answer1",
+ "question2": "WRONG",
+ })
+ config := &ClientConfig{
+ User: "testuser",
+ Auth: []AuthMethod{
+ KeyboardInteractive(answers.Challenge),
+ },
+ }
+
+ if err := tryAuth(t, config); err == nil {
+ t.Fatalf("wrong answers should not have authenticated with KeyboardInteractive")
+ }
+}
+
+// the mock server will only authenticate ssh-rsa keys
+func TestAuthMethodInvalidPublicKey(t *testing.T) {
+ config := &ClientConfig{
+ User: "testuser",
+ Auth: []AuthMethod{
+ PublicKeys(testSigners["dsa"]),
+ },
+ }
+
+ if err := tryAuth(t, config); err == nil {
+ t.Fatalf("dsa private key should not have authenticated with rsa public key")
+ }
+}
+
+// the client should authenticate with the second key
+func TestAuthMethodRSAandDSA(t *testing.T) {
+ config := &ClientConfig{
+ User: "testuser",
+ Auth: []AuthMethod{
+ PublicKeys(testSigners["dsa"], testSigners["rsa"]),
+ },
+ HostKeyCallback: InsecureIgnoreHostKey(),
+ }
+ if err := tryAuth(t, config); err != nil {
+ t.Fatalf("client could not authenticate with rsa key: %v", err)
+ }
+}
+
+func TestClientHMAC(t *testing.T) {
+ for _, mac := range supportedMACs {
+ config := &ClientConfig{
+ User: "testuser",
+ Auth: []AuthMethod{
+ PublicKeys(testSigners["rsa"]),
+ },
+ Config: Config{
+ MACs: []string{mac},
+ },
+ HostKeyCallback: InsecureIgnoreHostKey(),
+ }
+ if err := tryAuth(t, config); err != nil {
+ t.Fatalf("client could not authenticate with mac algo %s: %v", mac, err)
+ }
+ }
+}
+
+// issue 4285.
+func TestClientUnsupportedCipher(t *testing.T) {
+ config := &ClientConfig{
+ User: "testuser",
+ Auth: []AuthMethod{
+ PublicKeys(),
+ },
+ Config: Config{
+ Ciphers: []string{"aes128-cbc"}, // not currently supported
+ },
+ }
+ if err := tryAuth(t, config); err == nil {
+ t.Errorf("expected no ciphers in common")
+ }
+}
+
+func TestClientUnsupportedKex(t *testing.T) {
+ if os.Getenv("GO_BUILDER_NAME") != "" {
+ t.Skip("skipping known-flaky test on the Go build dashboard; see golang.org/issue/15198")
+ }
+ config := &ClientConfig{
+ User: "testuser",
+ Auth: []AuthMethod{
+ PublicKeys(),
+ },
+ Config: Config{
+ KeyExchanges: []string{"diffie-hellman-group-exchange-sha256"}, // not currently supported
+ },
+ HostKeyCallback: InsecureIgnoreHostKey(),
+ }
+ if err := tryAuth(t, config); err == nil || !strings.Contains(err.Error(), "common algorithm") {
+ t.Errorf("got %v, expected 'common algorithm'", err)
+ }
+}
+
+func TestClientLoginCert(t *testing.T) {
+ cert := &Certificate{
+ Key: testPublicKeys["rsa"],
+ ValidBefore: CertTimeInfinity,
+ CertType: UserCert,
+ }
+ cert.SignCert(rand.Reader, testSigners["ecdsa"])
+ certSigner, err := NewCertSigner(cert, testSigners["rsa"])
+ if err != nil {
+ t.Fatalf("NewCertSigner: %v", err)
+ }
+
+ clientConfig := &ClientConfig{
+ User: "user",
+ HostKeyCallback: InsecureIgnoreHostKey(),
+ }
+ clientConfig.Auth = append(clientConfig.Auth, PublicKeys(certSigner))
+
+ // should succeed
+ if err := tryAuth(t, clientConfig); err != nil {
+ t.Errorf("cert login failed: %v", err)
+ }
+
+ // corrupted signature
+ cert.Signature.Blob[0]++
+ if err := tryAuth(t, clientConfig); err == nil {
+ t.Errorf("cert login passed with corrupted sig")
+ }
+
+ // revoked
+ cert.Serial = 666
+ cert.SignCert(rand.Reader, testSigners["ecdsa"])
+ if err := tryAuth(t, clientConfig); err == nil {
+ t.Errorf("revoked cert login succeeded")
+ }
+ cert.Serial = 1
+
+ // sign with wrong key
+ cert.SignCert(rand.Reader, testSigners["dsa"])
+ if err := tryAuth(t, clientConfig); err == nil {
+ t.Errorf("cert login passed with non-authoritative key")
+ }
+
+ // host cert
+ cert.CertType = HostCert
+ cert.SignCert(rand.Reader, testSigners["ecdsa"])
+ if err := tryAuth(t, clientConfig); err == nil {
+ t.Errorf("cert login passed with wrong type")
+ }
+ cert.CertType = UserCert
+
+ // principal specified
+ cert.ValidPrincipals = []string{"user"}
+ cert.SignCert(rand.Reader, testSigners["ecdsa"])
+ if err := tryAuth(t, clientConfig); err != nil {
+ t.Errorf("cert login failed: %v", err)
+ }
+
+ // wrong principal specified
+ cert.ValidPrincipals = []string{"fred"}
+ cert.SignCert(rand.Reader, testSigners["ecdsa"])
+ if err := tryAuth(t, clientConfig); err == nil {
+ t.Errorf("cert login passed with wrong principal")
+ }
+ cert.ValidPrincipals = nil
+
+ // added critical option
+ cert.CriticalOptions = map[string]string{"root-access": "yes"}
+ cert.SignCert(rand.Reader, testSigners["ecdsa"])
+ if err := tryAuth(t, clientConfig); err == nil {
+ t.Errorf("cert login passed with unrecognized critical option")
+ }
+
+ // allowed source address
+ cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42/24,::42/120"}
+ cert.SignCert(rand.Reader, testSigners["ecdsa"])
+ if err := tryAuth(t, clientConfig); err != nil {
+ t.Errorf("cert login with source-address failed: %v", err)
+ }
+
+ // disallowed source address
+ cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42,::42"}
+ cert.SignCert(rand.Reader, testSigners["ecdsa"])
+ if err := tryAuth(t, clientConfig); err == nil {
+ t.Errorf("cert login with source-address succeeded")
+ }
+}
+
+func testPermissionsPassing(withPermissions bool, t *testing.T) {
+ serverConfig := &ServerConfig{
+ PublicKeyCallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) {
+ if conn.User() == "nopermissions" {
+ return nil, nil
+ }
+ return &Permissions{}, nil
+ },
+ }
+ serverConfig.AddHostKey(testSigners["rsa"])
+
+ clientConfig := &ClientConfig{
+ Auth: []AuthMethod{
+ PublicKeys(testSigners["rsa"]),
+ },
+ HostKeyCallback: InsecureIgnoreHostKey(),
+ }
+ if withPermissions {
+ clientConfig.User = "permissions"
+ } else {
+ clientConfig.User = "nopermissions"
+ }
+
+ c1, c2, err := netPipe()
+ if err != nil {
+ t.Fatalf("netPipe: %v", err)
+ }
+ defer c1.Close()
+ defer c2.Close()
+
+ go NewClientConn(c2, "", clientConfig)
+ serverConn, err := newServer(c1, serverConfig)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if p := serverConn.Permissions; (p != nil) != withPermissions {
+ t.Fatalf("withPermissions is %t, but Permissions object is %#v", withPermissions, p)
+ }
+}
+
+func TestPermissionsPassing(t *testing.T) {
+ testPermissionsPassing(true, t)
+}
+
+func TestNoPermissionsPassing(t *testing.T) {
+ testPermissionsPassing(false, t)
+}
+
+func TestRetryableAuth(t *testing.T) {
+ n := 0
+ passwords := []string{"WRONG1", "WRONG2"}
+
+ config := &ClientConfig{
+ User: "testuser",
+ Auth: []AuthMethod{
+ RetryableAuthMethod(PasswordCallback(func() (string, error) {
+ p := passwords[n]
+ n++
+ return p, nil
+ }), 2),
+ PublicKeys(testSigners["rsa"]),
+ },
+ HostKeyCallback: InsecureIgnoreHostKey(),
+ }
+
+ if err := tryAuth(t, config); err != nil {
+ t.Fatalf("unable to dial remote side: %s", err)
+ }
+ if n != 2 {
+ t.Fatalf("Did not try all passwords")
+ }
+}
+
+func ExampleRetryableAuthMethod(t *testing.T) {
+ user := "testuser"
+ NumberOfPrompts := 3
+
+ // Normally this would be a callback that prompts the user to answer the
+ // provided questions
+ Cb := func(user, instruction string, questions []string, echos []bool) (answers []string, err error) {
+ return []string{"answer1", "answer2"}, nil
+ }
+
+ config := &ClientConfig{
+ HostKeyCallback: InsecureIgnoreHostKey(),
+ User: user,
+ Auth: []AuthMethod{
+ RetryableAuthMethod(KeyboardInteractiveChallenge(Cb), NumberOfPrompts),
+ },
+ }
+
+ if err := tryAuth(t, config); err != nil {
+ t.Fatalf("unable to dial remote side: %s", err)
+ }
+}
+
+// Test if username is received on server side when NoClientAuth is used
+func TestClientAuthNone(t *testing.T) {
+ user := "testuser"
+ serverConfig := &ServerConfig{
+ NoClientAuth: true,
+ }
+ serverConfig.AddHostKey(testSigners["rsa"])
+
+ clientConfig := &ClientConfig{
+ User: user,
+ HostKeyCallback: InsecureIgnoreHostKey(),
+ }
+
+ c1, c2, err := netPipe()
+ if err != nil {
+ t.Fatalf("netPipe: %v", err)
+ }
+ defer c1.Close()
+ defer c2.Close()
+
+ go NewClientConn(c2, "", clientConfig)
+ serverConn, err := newServer(c1, serverConfig)
+ if err != nil {
+ t.Fatalf("newServer: %v", err)
+ }
+ if serverConn.User() != user {
+ t.Fatalf("server: got %q, want %q", serverConn.User(), user)
+ }
+}
+
+// Test if authentication attempts are limited on server when MaxAuthTries is set
+func TestClientAuthMaxAuthTries(t *testing.T) {
+ user := "testuser"
+
+ serverConfig := &ServerConfig{
+ MaxAuthTries: 2,
+ PasswordCallback: func(conn ConnMetadata, pass []byte) (*Permissions, error) {
+ if conn.User() == "testuser" && string(pass) == "right" {
+ return nil, nil
+ }
+ return nil, errors.New("password auth failed")
+ },
+ }
+ serverConfig.AddHostKey(testSigners["rsa"])
+
+ expectedErr := fmt.Errorf("ssh: handshake failed: %v", &disconnectMsg{
+ Reason: 2,
+ Message: "too many authentication failures",
+ })
+
+ for tries := 2; tries < 4; tries++ {
+ n := tries
+ clientConfig := &ClientConfig{
+ User: user,
+ Auth: []AuthMethod{
+ RetryableAuthMethod(PasswordCallback(func() (string, error) {
+ n--
+ if n == 0 {
+ return "right", nil
+ }
+ return "wrong", nil
+ }), tries),
+ },
+ HostKeyCallback: InsecureIgnoreHostKey(),
+ }
+
+ c1, c2, err := netPipe()
+ if err != nil {
+ t.Fatalf("netPipe: %v", err)
+ }
+ defer c1.Close()
+ defer c2.Close()
+
+ go newServer(c1, serverConfig)
+ _, _, _, err = NewClientConn(c2, "", clientConfig)
+ if tries > 2 {
+ if err == nil {
+ t.Fatalf("client: got no error, want %s", expectedErr)
+ } else if err.Error() != expectedErr.Error() {
+ t.Fatalf("client: got %s, want %s", err, expectedErr)
+ }
+ } else {
+ if err != nil {
+ t.Fatalf("client: got %s, want no error", err)
+ }
+ }
+ }
+}
+
+// Test if authentication attempts are correctly limited on server
+// when more public keys are provided then MaxAuthTries
+func TestClientAuthMaxAuthTriesPublicKey(t *testing.T) {
+ signers := []Signer{}
+ for i := 0; i < 6; i++ {
+ signers = append(signers, testSigners["dsa"])
+ }
+
+ validConfig := &ClientConfig{
+ User: "testuser",
+ Auth: []AuthMethod{
+ PublicKeys(append([]Signer{testSigners["rsa"]}, signers...)...),
+ },
+ HostKeyCallback: InsecureIgnoreHostKey(),
+ }
+ if err := tryAuth(t, validConfig); err != nil {
+ t.Fatalf("unable to dial remote side: %s", err)
+ }
+
+ expectedErr := fmt.Errorf("ssh: handshake failed: %v", &disconnectMsg{
+ Reason: 2,
+ Message: "too many authentication failures",
+ })
+ invalidConfig := &ClientConfig{
+ User: "testuser",
+ Auth: []AuthMethod{
+ PublicKeys(append(signers, testSigners["rsa"])...),
+ },
+ HostKeyCallback: InsecureIgnoreHostKey(),
+ }
+ if err := tryAuth(t, invalidConfig); err == nil {
+ t.Fatalf("client: got no error, want %s", expectedErr)
+ } else if err.Error() != expectedErr.Error() {
+ t.Fatalf("client: got %s, want %s", err, expectedErr)
+ }
+}
+
+// Test whether authentication errors are being properly logged if all
+// authentication methods have been exhausted
+func TestClientAuthErrorList(t *testing.T) {
+ publicKeyErr := errors.New("This is an error from PublicKeyCallback")
+
+ clientConfig := &ClientConfig{
+ Auth: []AuthMethod{
+ PublicKeys(testSigners["rsa"]),
+ },
+ HostKeyCallback: InsecureIgnoreHostKey(),
+ }
+ serverConfig := &ServerConfig{
+ PublicKeyCallback: func(_ ConnMetadata, _ PublicKey) (*Permissions, error) {
+ return nil, publicKeyErr
+ },
+ }
+ serverConfig.AddHostKey(testSigners["rsa"])
+
+ c1, c2, err := netPipe()
+ if err != nil {
+ t.Fatalf("netPipe: %v", err)
+ }
+ defer c1.Close()
+ defer c2.Close()
+
+ go NewClientConn(c2, "", clientConfig)
+ _, err = newServer(c1, serverConfig)
+ if err == nil {
+ t.Fatal("newServer: got nil, expected errors")
+ }
+
+ authErrs, ok := err.(*ServerAuthError)
+ if !ok {
+ t.Fatalf("errors: got %T, want *ssh.ServerAuthError", err)
+ }
+ for i, e := range authErrs.Errors {
+ switch i {
+ case 0:
+ if e.Error() != "no auth passed yet" {
+ t.Fatalf("errors: got %v, want no auth passed yet", e.Error())
+ }
+ case 1:
+ if e != publicKeyErr {
+ t.Fatalf("errors: got %v, want %v", e, publicKeyErr)
+ }
+ default:
+ t.Fatalf("errors: got %v, expected 2 errors", authErrs.Errors)
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/client_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/client_test.go
new file mode 100644
index 000000000..9dbe04222
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/client_test.go
@@ -0,0 +1,119 @@
+// Copyright 2014 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 ssh
+
+import (
+ "net"
+ "strings"
+ "testing"
+)
+
+func testClientVersion(t *testing.T, config *ClientConfig, expected string) {
+ clientConn, serverConn := net.Pipe()
+ defer clientConn.Close()
+ receivedVersion := make(chan string, 1)
+ config.HostKeyCallback = InsecureIgnoreHostKey()
+ go func() {
+ version, err := readVersion(serverConn)
+ if err != nil {
+ receivedVersion <- ""
+ } else {
+ receivedVersion <- string(version)
+ }
+ serverConn.Close()
+ }()
+ NewClientConn(clientConn, "", config)
+ actual := <-receivedVersion
+ if actual != expected {
+ t.Fatalf("got %s; want %s", actual, expected)
+ }
+}
+
+func TestCustomClientVersion(t *testing.T) {
+ version := "Test-Client-Version-0.0"
+ testClientVersion(t, &ClientConfig{ClientVersion: version}, version)
+}
+
+func TestDefaultClientVersion(t *testing.T) {
+ testClientVersion(t, &ClientConfig{}, packageVersion)
+}
+
+func TestHostKeyCheck(t *testing.T) {
+ for _, tt := range []struct {
+ name string
+ wantError string
+ key PublicKey
+ }{
+ {"no callback", "must specify HostKeyCallback", nil},
+ {"correct key", "", testSigners["rsa"].PublicKey()},
+ {"mismatch", "mismatch", testSigners["ecdsa"].PublicKey()},
+ } {
+ c1, c2, err := netPipe()
+ if err != nil {
+ t.Fatalf("netPipe: %v", err)
+ }
+ defer c1.Close()
+ defer c2.Close()
+ serverConf := &ServerConfig{
+ NoClientAuth: true,
+ }
+ serverConf.AddHostKey(testSigners["rsa"])
+
+ go NewServerConn(c1, serverConf)
+ clientConf := ClientConfig{
+ User: "user",
+ }
+ if tt.key != nil {
+ clientConf.HostKeyCallback = FixedHostKey(tt.key)
+ }
+
+ _, _, _, err = NewClientConn(c2, "", &clientConf)
+ if err != nil {
+ if tt.wantError == "" || !strings.Contains(err.Error(), tt.wantError) {
+ t.Errorf("%s: got error %q, missing %q", tt.name, err.Error(), tt.wantError)
+ }
+ } else if tt.wantError != "" {
+ t.Errorf("%s: succeeded, but want error string %q", tt.name, tt.wantError)
+ }
+ }
+}
+
+func TestBannerCallback(t *testing.T) {
+ c1, c2, err := netPipe()
+ if err != nil {
+ t.Fatalf("netPipe: %v", err)
+ }
+ defer c1.Close()
+ defer c2.Close()
+
+ serverConf := &ServerConfig{
+ NoClientAuth: true,
+ BannerCallback: func(conn ConnMetadata) string {
+ return "Hello World"
+ },
+ }
+ serverConf.AddHostKey(testSigners["rsa"])
+ go NewServerConn(c1, serverConf)
+
+ var receivedBanner string
+ clientConf := ClientConfig{
+ User: "user",
+ HostKeyCallback: InsecureIgnoreHostKey(),
+ BannerCallback: func(message string) error {
+ receivedBanner = message
+ return nil
+ },
+ }
+
+ _, _, _, err = NewClientConn(c2, "", &clientConf)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ expected := "Hello World"
+ if receivedBanner != expected {
+ t.Fatalf("got %s; want %s", receivedBanner, expected)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/common.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/common.go
new file mode 100644
index 000000000..dc39e4d23
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/common.go
@@ -0,0 +1,373 @@
+// Copyright 2011 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 ssh
+
+import (
+ "crypto"
+ "crypto/rand"
+ "fmt"
+ "io"
+ "math"
+ "sync"
+
+ _ "crypto/sha1"
+ _ "crypto/sha256"
+ _ "crypto/sha512"
+)
+
+// These are string constants in the SSH protocol.
+const (
+ compressionNone = "none"
+ serviceUserAuth = "ssh-userauth"
+ serviceSSH = "ssh-connection"
+)
+
+// supportedCiphers specifies the supported ciphers in preference order.
+var supportedCiphers = []string{
+ "aes128-ctr", "aes192-ctr", "aes256-ctr",
+ "aes128-gcm@openssh.com",
+ "arcfour256", "arcfour128",
+}
+
+// supportedKexAlgos specifies the supported key-exchange algorithms in
+// preference order.
+var supportedKexAlgos = []string{
+ kexAlgoCurve25519SHA256,
+ // P384 and P521 are not constant-time yet, but since we don't
+ // reuse ephemeral keys, using them for ECDH should be OK.
+ kexAlgoECDH256, kexAlgoECDH384, kexAlgoECDH521,
+ kexAlgoDH14SHA1, kexAlgoDH1SHA1,
+}
+
+// supportedHostKeyAlgos specifies the supported host-key algorithms (i.e. methods
+// of authenticating servers) in preference order.
+var supportedHostKeyAlgos = []string{
+ CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01,
+ CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoED25519v01,
+
+ KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521,
+ KeyAlgoRSA, KeyAlgoDSA,
+
+ KeyAlgoED25519,
+}
+
+// supportedMACs specifies a default set of MAC algorithms in preference order.
+// This is based on RFC 4253, section 6.4, but with hmac-md5 variants removed
+// because they have reached the end of their useful life.
+var supportedMACs = []string{
+ "hmac-sha2-256-etm@openssh.com", "hmac-sha2-256", "hmac-sha1", "hmac-sha1-96",
+}
+
+var supportedCompressions = []string{compressionNone}
+
+// hashFuncs keeps the mapping of supported algorithms to their respective
+// hashes needed for signature verification.
+var hashFuncs = map[string]crypto.Hash{
+ KeyAlgoRSA: crypto.SHA1,
+ KeyAlgoDSA: crypto.SHA1,
+ KeyAlgoECDSA256: crypto.SHA256,
+ KeyAlgoECDSA384: crypto.SHA384,
+ KeyAlgoECDSA521: crypto.SHA512,
+ CertAlgoRSAv01: crypto.SHA1,
+ CertAlgoDSAv01: crypto.SHA1,
+ CertAlgoECDSA256v01: crypto.SHA256,
+ CertAlgoECDSA384v01: crypto.SHA384,
+ CertAlgoECDSA521v01: crypto.SHA512,
+}
+
+// unexpectedMessageError results when the SSH message that we received didn't
+// match what we wanted.
+func unexpectedMessageError(expected, got uint8) error {
+ return fmt.Errorf("ssh: unexpected message type %d (expected %d)", got, expected)
+}
+
+// parseError results from a malformed SSH message.
+func parseError(tag uint8) error {
+ return fmt.Errorf("ssh: parse error in message type %d", tag)
+}
+
+func findCommon(what string, client []string, server []string) (common string, err error) {
+ for _, c := range client {
+ for _, s := range server {
+ if c == s {
+ return c, nil
+ }
+ }
+ }
+ return "", fmt.Errorf("ssh: no common algorithm for %s; client offered: %v, server offered: %v", what, client, server)
+}
+
+type directionAlgorithms struct {
+ Cipher string
+ MAC string
+ Compression string
+}
+
+// rekeyBytes returns a rekeying intervals in bytes.
+func (a *directionAlgorithms) rekeyBytes() int64 {
+ // According to RFC4344 block ciphers should rekey after
+ // 2^(BLOCKSIZE/4) blocks. For all AES flavors BLOCKSIZE is
+ // 128.
+ switch a.Cipher {
+ case "aes128-ctr", "aes192-ctr", "aes256-ctr", gcmCipherID, aes128cbcID:
+ return 16 * (1 << 32)
+
+ }
+
+ // For others, stick with RFC4253 recommendation to rekey after 1 Gb of data.
+ return 1 << 30
+}
+
+type algorithms struct {
+ kex string
+ hostKey string
+ w directionAlgorithms
+ r directionAlgorithms
+}
+
+func findAgreedAlgorithms(clientKexInit, serverKexInit *kexInitMsg) (algs *algorithms, err error) {
+ result := &algorithms{}
+
+ result.kex, err = findCommon("key exchange", clientKexInit.KexAlgos, serverKexInit.KexAlgos)
+ if err != nil {
+ return
+ }
+
+ result.hostKey, err = findCommon("host key", clientKexInit.ServerHostKeyAlgos, serverKexInit.ServerHostKeyAlgos)
+ if err != nil {
+ return
+ }
+
+ result.w.Cipher, err = findCommon("client to server cipher", clientKexInit.CiphersClientServer, serverKexInit.CiphersClientServer)
+ if err != nil {
+ return
+ }
+
+ result.r.Cipher, err = findCommon("server to client cipher", clientKexInit.CiphersServerClient, serverKexInit.CiphersServerClient)
+ if err != nil {
+ return
+ }
+
+ result.w.MAC, err = findCommon("client to server MAC", clientKexInit.MACsClientServer, serverKexInit.MACsClientServer)
+ if err != nil {
+ return
+ }
+
+ result.r.MAC, err = findCommon("server to client MAC", clientKexInit.MACsServerClient, serverKexInit.MACsServerClient)
+ if err != nil {
+ return
+ }
+
+ result.w.Compression, err = findCommon("client to server compression", clientKexInit.CompressionClientServer, serverKexInit.CompressionClientServer)
+ if err != nil {
+ return
+ }
+
+ result.r.Compression, err = findCommon("server to client compression", clientKexInit.CompressionServerClient, serverKexInit.CompressionServerClient)
+ if err != nil {
+ return
+ }
+
+ return result, nil
+}
+
+// If rekeythreshold is too small, we can't make any progress sending
+// stuff.
+const minRekeyThreshold uint64 = 256
+
+// Config contains configuration data common to both ServerConfig and
+// ClientConfig.
+type Config struct {
+ // Rand provides the source of entropy for cryptographic
+ // primitives. If Rand is nil, the cryptographic random reader
+ // in package crypto/rand will be used.
+ Rand io.Reader
+
+ // The maximum number of bytes sent or received after which a
+ // new key is negotiated. It must be at least 256. If
+ // unspecified, a size suitable for the chosen cipher is used.
+ RekeyThreshold uint64
+
+ // The allowed key exchanges algorithms. If unspecified then a
+ // default set of algorithms is used.
+ KeyExchanges []string
+
+ // The allowed cipher algorithms. If unspecified then a sensible
+ // default is used.
+ Ciphers []string
+
+ // The allowed MAC algorithms. If unspecified then a sensible default
+ // is used.
+ MACs []string
+}
+
+// SetDefaults sets sensible values for unset fields in config. This is
+// exported for testing: Configs passed to SSH functions are copied and have
+// default values set automatically.
+func (c *Config) SetDefaults() {
+ if c.Rand == nil {
+ c.Rand = rand.Reader
+ }
+ if c.Ciphers == nil {
+ c.Ciphers = supportedCiphers
+ }
+ var ciphers []string
+ for _, c := range c.Ciphers {
+ if cipherModes[c] != nil {
+ // reject the cipher if we have no cipherModes definition
+ ciphers = append(ciphers, c)
+ }
+ }
+ c.Ciphers = ciphers
+
+ if c.KeyExchanges == nil {
+ c.KeyExchanges = supportedKexAlgos
+ }
+
+ if c.MACs == nil {
+ c.MACs = supportedMACs
+ }
+
+ if c.RekeyThreshold == 0 {
+ // cipher specific default
+ } else if c.RekeyThreshold < minRekeyThreshold {
+ c.RekeyThreshold = minRekeyThreshold
+ } else if c.RekeyThreshold >= math.MaxInt64 {
+ // Avoid weirdness if somebody uses -1 as a threshold.
+ c.RekeyThreshold = math.MaxInt64
+ }
+}
+
+// buildDataSignedForAuth returns the data that is signed in order to prove
+// possession of a private key. See RFC 4252, section 7.
+func buildDataSignedForAuth(sessionId []byte, req userAuthRequestMsg, algo, pubKey []byte) []byte {
+ data := struct {
+ Session []byte
+ Type byte
+ User string
+ Service string
+ Method string
+ Sign bool
+ Algo []byte
+ PubKey []byte
+ }{
+ sessionId,
+ msgUserAuthRequest,
+ req.User,
+ req.Service,
+ req.Method,
+ true,
+ algo,
+ pubKey,
+ }
+ return Marshal(data)
+}
+
+func appendU16(buf []byte, n uint16) []byte {
+ return append(buf, byte(n>>8), byte(n))
+}
+
+func appendU32(buf []byte, n uint32) []byte {
+ return append(buf, byte(n>>24), byte(n>>16), byte(n>>8), byte(n))
+}
+
+func appendU64(buf []byte, n uint64) []byte {
+ return append(buf,
+ byte(n>>56), byte(n>>48), byte(n>>40), byte(n>>32),
+ byte(n>>24), byte(n>>16), byte(n>>8), byte(n))
+}
+
+func appendInt(buf []byte, n int) []byte {
+ return appendU32(buf, uint32(n))
+}
+
+func appendString(buf []byte, s string) []byte {
+ buf = appendU32(buf, uint32(len(s)))
+ buf = append(buf, s...)
+ return buf
+}
+
+func appendBool(buf []byte, b bool) []byte {
+ if b {
+ return append(buf, 1)
+ }
+ return append(buf, 0)
+}
+
+// newCond is a helper to hide the fact that there is no usable zero
+// value for sync.Cond.
+func newCond() *sync.Cond { return sync.NewCond(new(sync.Mutex)) }
+
+// window represents the buffer available to clients
+// wishing to write to a channel.
+type window struct {
+ *sync.Cond
+ win uint32 // RFC 4254 5.2 says the window size can grow to 2^32-1
+ writeWaiters int
+ closed bool
+}
+
+// add adds win to the amount of window available
+// for consumers.
+func (w *window) add(win uint32) bool {
+ // a zero sized window adjust is a noop.
+ if win == 0 {
+ return true
+ }
+ w.L.Lock()
+ if w.win+win < win {
+ w.L.Unlock()
+ return false
+ }
+ w.win += win
+ // It is unusual that multiple goroutines would be attempting to reserve
+ // window space, but not guaranteed. Use broadcast to notify all waiters
+ // that additional window is available.
+ w.Broadcast()
+ w.L.Unlock()
+ return true
+}
+
+// close sets the window to closed, so all reservations fail
+// immediately.
+func (w *window) close() {
+ w.L.Lock()
+ w.closed = true
+ w.Broadcast()
+ w.L.Unlock()
+}
+
+// reserve reserves win from the available window capacity.
+// If no capacity remains, reserve will block. reserve may
+// return less than requested.
+func (w *window) reserve(win uint32) (uint32, error) {
+ var err error
+ w.L.Lock()
+ w.writeWaiters++
+ w.Broadcast()
+ for w.win == 0 && !w.closed {
+ w.Wait()
+ }
+ w.writeWaiters--
+ if w.win < win {
+ win = w.win
+ }
+ w.win -= win
+ if w.closed {
+ err = io.EOF
+ }
+ w.L.Unlock()
+ return win, err
+}
+
+// waitWriterBlocked waits until some goroutine is blocked for further
+// writes. It is used in tests only.
+func (w *window) waitWriterBlocked() {
+ w.Cond.L.Lock()
+ for w.writeWaiters == 0 {
+ w.Cond.Wait()
+ }
+ w.Cond.L.Unlock()
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/connection.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/connection.go
new file mode 100644
index 000000000..fd6b0681b
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/connection.go
@@ -0,0 +1,143 @@
+// Copyright 2013 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 ssh
+
+import (
+ "fmt"
+ "net"
+)
+
+// OpenChannelError is returned if the other side rejects an
+// OpenChannel request.
+type OpenChannelError struct {
+ Reason RejectionReason
+ Message string
+}
+
+func (e *OpenChannelError) Error() string {
+ return fmt.Sprintf("ssh: rejected: %s (%s)", e.Reason, e.Message)
+}
+
+// ConnMetadata holds metadata for the connection.
+type ConnMetadata interface {
+ // User returns the user ID for this connection.
+ User() string
+
+ // SessionID returns the session hash, also denoted by H.
+ SessionID() []byte
+
+ // ClientVersion returns the client's version string as hashed
+ // into the session ID.
+ ClientVersion() []byte
+
+ // ServerVersion returns the server's version string as hashed
+ // into the session ID.
+ ServerVersion() []byte
+
+ // RemoteAddr returns the remote address for this connection.
+ RemoteAddr() net.Addr
+
+ // LocalAddr returns the local address for this connection.
+ LocalAddr() net.Addr
+}
+
+// Conn represents an SSH connection for both server and client roles.
+// Conn is the basis for implementing an application layer, such
+// as ClientConn, which implements the traditional shell access for
+// clients.
+type Conn interface {
+ ConnMetadata
+
+ // SendRequest sends a global request, and returns the
+ // reply. If wantReply is true, it returns the response status
+ // and payload. See also RFC4254, section 4.
+ SendRequest(name string, wantReply bool, payload []byte) (bool, []byte, error)
+
+ // OpenChannel tries to open an channel. If the request is
+ // rejected, it returns *OpenChannelError. On success it returns
+ // the SSH Channel and a Go channel for incoming, out-of-band
+ // requests. The Go channel must be serviced, or the
+ // connection will hang.
+ OpenChannel(name string, data []byte) (Channel, <-chan *Request, error)
+
+ // Close closes the underlying network connection
+ Close() error
+
+ // Wait blocks until the connection has shut down, and returns the
+ // error causing the shutdown.
+ Wait() error
+
+ // TODO(hanwen): consider exposing:
+ // RequestKeyChange
+ // Disconnect
+}
+
+// DiscardRequests consumes and rejects all requests from the
+// passed-in channel.
+func DiscardRequests(in <-chan *Request) {
+ for req := range in {
+ if req.WantReply {
+ req.Reply(false, nil)
+ }
+ }
+}
+
+// A connection represents an incoming connection.
+type connection struct {
+ transport *handshakeTransport
+ sshConn
+
+ // The connection protocol.
+ *mux
+}
+
+func (c *connection) Close() error {
+ return c.sshConn.conn.Close()
+}
+
+// sshconn provides net.Conn metadata, but disallows direct reads and
+// writes.
+type sshConn struct {
+ conn net.Conn
+
+ user string
+ sessionID []byte
+ clientVersion []byte
+ serverVersion []byte
+}
+
+func dup(src []byte) []byte {
+ dst := make([]byte, len(src))
+ copy(dst, src)
+ return dst
+}
+
+func (c *sshConn) User() string {
+ return c.user
+}
+
+func (c *sshConn) RemoteAddr() net.Addr {
+ return c.conn.RemoteAddr()
+}
+
+func (c *sshConn) Close() error {
+ return c.conn.Close()
+}
+
+func (c *sshConn) LocalAddr() net.Addr {
+ return c.conn.LocalAddr()
+}
+
+func (c *sshConn) SessionID() []byte {
+ return dup(c.sessionID)
+}
+
+func (c *sshConn) ClientVersion() []byte {
+ return dup(c.clientVersion)
+}
+
+func (c *sshConn) ServerVersion() []byte {
+ return dup(c.serverVersion)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/doc.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/doc.go
new file mode 100644
index 000000000..67b7322c0
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/doc.go
@@ -0,0 +1,21 @@
+// Copyright 2011 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 ssh implements an SSH client and server.
+
+SSH is a transport security protocol, an authentication protocol and a
+family of application protocols. The most typical application level
+protocol is a remote shell and this is specifically implemented. However,
+the multiplexed nature of SSH is exposed to users that wish to support
+others.
+
+References:
+ [PROTOCOL.certkeys]: http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.certkeys?rev=HEAD
+ [SSH-PARAMETERS]: http://www.iana.org/assignments/ssh-parameters/ssh-parameters.xml#ssh-parameters-1
+
+This package does not fall under the stability promise of the Go language itself,
+so its API may be changed when pressing needs arise.
+*/
+package ssh // import "golang.org/x/crypto/ssh"
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/example_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/example_test.go
new file mode 100644
index 000000000..b910c7bf6
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/example_test.go
@@ -0,0 +1,320 @@
+// Copyright 2011 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 ssh_test
+
+import (
+ "bufio"
+ "bytes"
+ "fmt"
+ "io/ioutil"
+ "log"
+ "net"
+ "net/http"
+ "os"
+ "path/filepath"
+ "strings"
+
+ "golang.org/x/crypto/ssh"
+ "golang.org/x/crypto/ssh/terminal"
+)
+
+func ExampleNewServerConn() {
+ // Public key authentication is done by comparing
+ // the public key of a received connection
+ // with the entries in the authorized_keys file.
+ authorizedKeysBytes, err := ioutil.ReadFile("authorized_keys")
+ if err != nil {
+ log.Fatalf("Failed to load authorized_keys, err: %v", err)
+ }
+
+ authorizedKeysMap := map[string]bool{}
+ for len(authorizedKeysBytes) > 0 {
+ pubKey, _, _, rest, err := ssh.ParseAuthorizedKey(authorizedKeysBytes)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ authorizedKeysMap[string(pubKey.Marshal())] = true
+ authorizedKeysBytes = rest
+ }
+
+ // An SSH server is represented by a ServerConfig, which holds
+ // certificate details and handles authentication of ServerConns.
+ config := &ssh.ServerConfig{
+ // Remove to disable password auth.
+ PasswordCallback: func(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) {
+ // Should use constant-time compare (or better, salt+hash) in
+ // a production setting.
+ if c.User() == "testuser" && string(pass) == "tiger" {
+ return nil, nil
+ }
+ return nil, fmt.Errorf("password rejected for %q", c.User())
+ },
+
+ // Remove to disable public key auth.
+ PublicKeyCallback: func(c ssh.ConnMetadata, pubKey ssh.PublicKey) (*ssh.Permissions, error) {
+ if authorizedKeysMap[string(pubKey.Marshal())] {
+ return &ssh.Permissions{
+ // Record the public key used for authentication.
+ Extensions: map[string]string{
+ "pubkey-fp": ssh.FingerprintSHA256(pubKey),
+ },
+ }, nil
+ }
+ return nil, fmt.Errorf("unknown public key for %q", c.User())
+ },
+ }
+
+ privateBytes, err := ioutil.ReadFile("id_rsa")
+ if err != nil {
+ log.Fatal("Failed to load private key: ", err)
+ }
+
+ private, err := ssh.ParsePrivateKey(privateBytes)
+ if err != nil {
+ log.Fatal("Failed to parse private key: ", err)
+ }
+
+ config.AddHostKey(private)
+
+ // Once a ServerConfig has been configured, connections can be
+ // accepted.
+ listener, err := net.Listen("tcp", "0.0.0.0:2022")
+ if err != nil {
+ log.Fatal("failed to listen for connection: ", err)
+ }
+ nConn, err := listener.Accept()
+ if err != nil {
+ log.Fatal("failed to accept incoming connection: ", err)
+ }
+
+ // Before use, a handshake must be performed on the incoming
+ // net.Conn.
+ conn, chans, reqs, err := ssh.NewServerConn(nConn, config)
+ if err != nil {
+ log.Fatal("failed to handshake: ", err)
+ }
+ log.Printf("logged in with key %s", conn.Permissions.Extensions["pubkey-fp"])
+
+ // The incoming Request channel must be serviced.
+ go ssh.DiscardRequests(reqs)
+
+ // Service the incoming Channel channel.
+ for newChannel := range chans {
+ // Channels have a type, depending on the application level
+ // protocol intended. In the case of a shell, the type is
+ // "session" and ServerShell may be used to present a simple
+ // terminal interface.
+ if newChannel.ChannelType() != "session" {
+ newChannel.Reject(ssh.UnknownChannelType, "unknown channel type")
+ continue
+ }
+ channel, requests, err := newChannel.Accept()
+ if err != nil {
+ log.Fatalf("Could not accept channel: %v", err)
+ }
+
+ // Sessions have out-of-band requests such as "shell",
+ // "pty-req" and "env". Here we handle only the
+ // "shell" request.
+ go func(in <-chan *ssh.Request) {
+ for req := range in {
+ req.Reply(req.Type == "shell", nil)
+ }
+ }(requests)
+
+ term := terminal.NewTerminal(channel, "> ")
+
+ go func() {
+ defer channel.Close()
+ for {
+ line, err := term.ReadLine()
+ if err != nil {
+ break
+ }
+ fmt.Println(line)
+ }
+ }()
+ }
+}
+
+func ExampleHostKeyCheck() {
+ // Every client must provide a host key check. Here is a
+ // simple-minded parse of OpenSSH's known_hosts file
+ host := "hostname"
+ file, err := os.Open(filepath.Join(os.Getenv("HOME"), ".ssh", "known_hosts"))
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer file.Close()
+
+ scanner := bufio.NewScanner(file)
+ var hostKey ssh.PublicKey
+ for scanner.Scan() {
+ fields := strings.Split(scanner.Text(), " ")
+ if len(fields) != 3 {
+ continue
+ }
+ if strings.Contains(fields[0], host) {
+ var err error
+ hostKey, _, _, _, err = ssh.ParseAuthorizedKey(scanner.Bytes())
+ if err != nil {
+ log.Fatalf("error parsing %q: %v", fields[2], err)
+ }
+ break
+ }
+ }
+
+ if hostKey == nil {
+ log.Fatalf("no hostkey for %s", host)
+ }
+
+ config := ssh.ClientConfig{
+ User: os.Getenv("USER"),
+ HostKeyCallback: ssh.FixedHostKey(hostKey),
+ }
+
+ _, err = ssh.Dial("tcp", host+":22", &config)
+ log.Println(err)
+}
+
+func ExampleDial() {
+ var hostKey ssh.PublicKey
+ // An SSH client is represented with a ClientConn.
+ //
+ // To authenticate with the remote server you must pass at least one
+ // implementation of AuthMethod via the Auth field in ClientConfig,
+ // and provide a HostKeyCallback.
+ config := &ssh.ClientConfig{
+ User: "username",
+ Auth: []ssh.AuthMethod{
+ ssh.Password("yourpassword"),
+ },
+ HostKeyCallback: ssh.FixedHostKey(hostKey),
+ }
+ client, err := ssh.Dial("tcp", "yourserver.com:22", config)
+ if err != nil {
+ log.Fatal("Failed to dial: ", err)
+ }
+
+ // Each ClientConn can support multiple interactive sessions,
+ // represented by a Session.
+ session, err := client.NewSession()
+ if err != nil {
+ log.Fatal("Failed to create session: ", err)
+ }
+ defer session.Close()
+
+ // Once a Session is created, you can execute a single command on
+ // the remote side using the Run method.
+ var b bytes.Buffer
+ session.Stdout = &b
+ if err := session.Run("/usr/bin/whoami"); err != nil {
+ log.Fatal("Failed to run: " + err.Error())
+ }
+ fmt.Println(b.String())
+}
+
+func ExamplePublicKeys() {
+ var hostKey ssh.PublicKey
+ // A public key may be used to authenticate against the remote
+ // server by using an unencrypted PEM-encoded private key file.
+ //
+ // If you have an encrypted private key, the crypto/x509 package
+ // can be used to decrypt it.
+ key, err := ioutil.ReadFile("/home/user/.ssh/id_rsa")
+ if err != nil {
+ log.Fatalf("unable to read private key: %v", err)
+ }
+
+ // Create the Signer for this private key.
+ signer, err := ssh.ParsePrivateKey(key)
+ if err != nil {
+ log.Fatalf("unable to parse private key: %v", err)
+ }
+
+ config := &ssh.ClientConfig{
+ User: "user",
+ Auth: []ssh.AuthMethod{
+ // Use the PublicKeys method for remote authentication.
+ ssh.PublicKeys(signer),
+ },
+ HostKeyCallback: ssh.FixedHostKey(hostKey),
+ }
+
+ // Connect to the remote server and perform the SSH handshake.
+ client, err := ssh.Dial("tcp", "host.com:22", config)
+ if err != nil {
+ log.Fatalf("unable to connect: %v", err)
+ }
+ defer client.Close()
+}
+
+func ExampleClient_Listen() {
+ var hostKey ssh.PublicKey
+ config := &ssh.ClientConfig{
+ User: "username",
+ Auth: []ssh.AuthMethod{
+ ssh.Password("password"),
+ },
+ HostKeyCallback: ssh.FixedHostKey(hostKey),
+ }
+ // Dial your ssh server.
+ conn, err := ssh.Dial("tcp", "localhost:22", config)
+ if err != nil {
+ log.Fatal("unable to connect: ", err)
+ }
+ defer conn.Close()
+
+ // Request the remote side to open port 8080 on all interfaces.
+ l, err := conn.Listen("tcp", "0.0.0.0:8080")
+ if err != nil {
+ log.Fatal("unable to register tcp forward: ", err)
+ }
+ defer l.Close()
+
+ // Serve HTTP with your SSH server acting as a reverse proxy.
+ http.Serve(l, http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
+ fmt.Fprintf(resp, "Hello world!\n")
+ }))
+}
+
+func ExampleSession_RequestPty() {
+ var hostKey ssh.PublicKey
+ // Create client config
+ config := &ssh.ClientConfig{
+ User: "username",
+ Auth: []ssh.AuthMethod{
+ ssh.Password("password"),
+ },
+ HostKeyCallback: ssh.FixedHostKey(hostKey),
+ }
+ // Connect to ssh server
+ conn, err := ssh.Dial("tcp", "localhost:22", config)
+ if err != nil {
+ log.Fatal("unable to connect: ", err)
+ }
+ defer conn.Close()
+ // Create a session
+ session, err := conn.NewSession()
+ if err != nil {
+ log.Fatal("unable to create session: ", err)
+ }
+ defer session.Close()
+ // Set up terminal modes
+ modes := ssh.TerminalModes{
+ ssh.ECHO: 0, // disable echoing
+ ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud
+ ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud
+ }
+ // Request pseudo terminal
+ if err := session.RequestPty("xterm", 40, 80, modes); err != nil {
+ log.Fatal("request for pseudo terminal failed: ", err)
+ }
+ // Start remote shell
+ if err := session.Shell(); err != nil {
+ log.Fatal("failed to start shell: ", err)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/handshake.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/handshake.go
new file mode 100644
index 000000000..4f7912ecd
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/handshake.go
@@ -0,0 +1,646 @@
+// Copyright 2013 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 ssh
+
+import (
+ "crypto/rand"
+ "errors"
+ "fmt"
+ "io"
+ "log"
+ "net"
+ "sync"
+)
+
+// debugHandshake, if set, prints messages sent and received. Key
+// exchange messages are printed as if DH were used, so the debug
+// messages are wrong when using ECDH.
+const debugHandshake = false
+
+// chanSize sets the amount of buffering SSH connections. This is
+// primarily for testing: setting chanSize=0 uncovers deadlocks more
+// quickly.
+const chanSize = 16
+
+// keyingTransport is a packet based transport that supports key
+// changes. It need not be thread-safe. It should pass through
+// msgNewKeys in both directions.
+type keyingTransport interface {
+ packetConn
+
+ // prepareKeyChange sets up a key change. The key change for a
+ // direction will be effected if a msgNewKeys message is sent
+ // or received.
+ prepareKeyChange(*algorithms, *kexResult) error
+}
+
+// handshakeTransport implements rekeying on top of a keyingTransport
+// and offers a thread-safe writePacket() interface.
+type handshakeTransport struct {
+ conn keyingTransport
+ config *Config
+
+ serverVersion []byte
+ clientVersion []byte
+
+ // hostKeys is non-empty if we are the server. In that case,
+ // it contains all host keys that can be used to sign the
+ // connection.
+ hostKeys []Signer
+
+ // hostKeyAlgorithms is non-empty if we are the client. In that case,
+ // we accept these key types from the server as host key.
+ hostKeyAlgorithms []string
+
+ // On read error, incoming is closed, and readError is set.
+ incoming chan []byte
+ readError error
+
+ mu sync.Mutex
+ writeError error
+ sentInitPacket []byte
+ sentInitMsg *kexInitMsg
+ pendingPackets [][]byte // Used when a key exchange is in progress.
+
+ // If the read loop wants to schedule a kex, it pings this
+ // channel, and the write loop will send out a kex
+ // message.
+ requestKex chan struct{}
+
+ // If the other side requests or confirms a kex, its kexInit
+ // packet is sent here for the write loop to find it.
+ startKex chan *pendingKex
+
+ // data for host key checking
+ hostKeyCallback HostKeyCallback
+ dialAddress string
+ remoteAddr net.Addr
+
+ // bannerCallback is non-empty if we are the client and it has been set in
+ // ClientConfig. In that case it is called during the user authentication
+ // dance to handle a custom server's message.
+ bannerCallback BannerCallback
+
+ // Algorithms agreed in the last key exchange.
+ algorithms *algorithms
+
+ readPacketsLeft uint32
+ readBytesLeft int64
+
+ writePacketsLeft uint32
+ writeBytesLeft int64
+
+ // The session ID or nil if first kex did not complete yet.
+ sessionID []byte
+}
+
+type pendingKex struct {
+ otherInit []byte
+ done chan error
+}
+
+func newHandshakeTransport(conn keyingTransport, config *Config, clientVersion, serverVersion []byte) *handshakeTransport {
+ t := &handshakeTransport{
+ conn: conn,
+ serverVersion: serverVersion,
+ clientVersion: clientVersion,
+ incoming: make(chan []byte, chanSize),
+ requestKex: make(chan struct{}, 1),
+ startKex: make(chan *pendingKex, 1),
+
+ config: config,
+ }
+ t.resetReadThresholds()
+ t.resetWriteThresholds()
+
+ // We always start with a mandatory key exchange.
+ t.requestKex <- struct{}{}
+ return t
+}
+
+func newClientTransport(conn keyingTransport, clientVersion, serverVersion []byte, config *ClientConfig, dialAddr string, addr net.Addr) *handshakeTransport {
+ t := newHandshakeTransport(conn, &config.Config, clientVersion, serverVersion)
+ t.dialAddress = dialAddr
+ t.remoteAddr = addr
+ t.hostKeyCallback = config.HostKeyCallback
+ t.bannerCallback = config.BannerCallback
+ if config.HostKeyAlgorithms != nil {
+ t.hostKeyAlgorithms = config.HostKeyAlgorithms
+ } else {
+ t.hostKeyAlgorithms = supportedHostKeyAlgos
+ }
+ go t.readLoop()
+ go t.kexLoop()
+ return t
+}
+
+func newServerTransport(conn keyingTransport, clientVersion, serverVersion []byte, config *ServerConfig) *handshakeTransport {
+ t := newHandshakeTransport(conn, &config.Config, clientVersion, serverVersion)
+ t.hostKeys = config.hostKeys
+ go t.readLoop()
+ go t.kexLoop()
+ return t
+}
+
+func (t *handshakeTransport) getSessionID() []byte {
+ return t.sessionID
+}
+
+// waitSession waits for the session to be established. This should be
+// the first thing to call after instantiating handshakeTransport.
+func (t *handshakeTransport) waitSession() error {
+ p, err := t.readPacket()
+ if err != nil {
+ return err
+ }
+ if p[0] != msgNewKeys {
+ return fmt.Errorf("ssh: first packet should be msgNewKeys")
+ }
+
+ return nil
+}
+
+func (t *handshakeTransport) id() string {
+ if len(t.hostKeys) > 0 {
+ return "server"
+ }
+ return "client"
+}
+
+func (t *handshakeTransport) printPacket(p []byte, write bool) {
+ action := "got"
+ if write {
+ action = "sent"
+ }
+
+ if p[0] == msgChannelData || p[0] == msgChannelExtendedData {
+ log.Printf("%s %s data (packet %d bytes)", t.id(), action, len(p))
+ } else {
+ msg, err := decode(p)
+ log.Printf("%s %s %T %v (%v)", t.id(), action, msg, msg, err)
+ }
+}
+
+func (t *handshakeTransport) readPacket() ([]byte, error) {
+ p, ok := <-t.incoming
+ if !ok {
+ return nil, t.readError
+ }
+ return p, nil
+}
+
+func (t *handshakeTransport) readLoop() {
+ first := true
+ for {
+ p, err := t.readOnePacket(first)
+ first = false
+ if err != nil {
+ t.readError = err
+ close(t.incoming)
+ break
+ }
+ if p[0] == msgIgnore || p[0] == msgDebug {
+ continue
+ }
+ t.incoming <- p
+ }
+
+ // Stop writers too.
+ t.recordWriteError(t.readError)
+
+ // Unblock the writer should it wait for this.
+ close(t.startKex)
+
+ // Don't close t.requestKex; it's also written to from writePacket.
+}
+
+func (t *handshakeTransport) pushPacket(p []byte) error {
+ if debugHandshake {
+ t.printPacket(p, true)
+ }
+ return t.conn.writePacket(p)
+}
+
+func (t *handshakeTransport) getWriteError() error {
+ t.mu.Lock()
+ defer t.mu.Unlock()
+ return t.writeError
+}
+
+func (t *handshakeTransport) recordWriteError(err error) {
+ t.mu.Lock()
+ defer t.mu.Unlock()
+ if t.writeError == nil && err != nil {
+ t.writeError = err
+ }
+}
+
+func (t *handshakeTransport) requestKeyExchange() {
+ select {
+ case t.requestKex <- struct{}{}:
+ default:
+ // something already requested a kex, so do nothing.
+ }
+}
+
+func (t *handshakeTransport) resetWriteThresholds() {
+ t.writePacketsLeft = packetRekeyThreshold
+ if t.config.RekeyThreshold > 0 {
+ t.writeBytesLeft = int64(t.config.RekeyThreshold)
+ } else if t.algorithms != nil {
+ t.writeBytesLeft = t.algorithms.w.rekeyBytes()
+ } else {
+ t.writeBytesLeft = 1 << 30
+ }
+}
+
+func (t *handshakeTransport) kexLoop() {
+
+write:
+ for t.getWriteError() == nil {
+ var request *pendingKex
+ var sent bool
+
+ for request == nil || !sent {
+ var ok bool
+ select {
+ case request, ok = <-t.startKex:
+ if !ok {
+ break write
+ }
+ case <-t.requestKex:
+ break
+ }
+
+ if !sent {
+ if err := t.sendKexInit(); err != nil {
+ t.recordWriteError(err)
+ break
+ }
+ sent = true
+ }
+ }
+
+ if err := t.getWriteError(); err != nil {
+ if request != nil {
+ request.done <- err
+ }
+ break
+ }
+
+ // We're not servicing t.requestKex, but that is OK:
+ // we never block on sending to t.requestKex.
+
+ // We're not servicing t.startKex, but the remote end
+ // has just sent us a kexInitMsg, so it can't send
+ // another key change request, until we close the done
+ // channel on the pendingKex request.
+
+ err := t.enterKeyExchange(request.otherInit)
+
+ t.mu.Lock()
+ t.writeError = err
+ t.sentInitPacket = nil
+ t.sentInitMsg = nil
+
+ t.resetWriteThresholds()
+
+ // we have completed the key exchange. Since the
+ // reader is still blocked, it is safe to clear out
+ // the requestKex channel. This avoids the situation
+ // where: 1) we consumed our own request for the
+ // initial kex, and 2) the kex from the remote side
+ // caused another send on the requestKex channel,
+ clear:
+ for {
+ select {
+ case <-t.requestKex:
+ //
+ default:
+ break clear
+ }
+ }
+
+ request.done <- t.writeError
+
+ // kex finished. Push packets that we received while
+ // the kex was in progress. Don't look at t.startKex
+ // and don't increment writtenSinceKex: if we trigger
+ // another kex while we are still busy with the last
+ // one, things will become very confusing.
+ for _, p := range t.pendingPackets {
+ t.writeError = t.pushPacket(p)
+ if t.writeError != nil {
+ break
+ }
+ }
+ t.pendingPackets = t.pendingPackets[:0]
+ t.mu.Unlock()
+ }
+
+ // drain startKex channel. We don't service t.requestKex
+ // because nobody does blocking sends there.
+ go func() {
+ for init := range t.startKex {
+ init.done <- t.writeError
+ }
+ }()
+
+ // Unblock reader.
+ t.conn.Close()
+}
+
+// The protocol uses uint32 for packet counters, so we can't let them
+// reach 1<<32. We will actually read and write more packets than
+// this, though: the other side may send more packets, and after we
+// hit this limit on writing we will send a few more packets for the
+// key exchange itself.
+const packetRekeyThreshold = (1 << 31)
+
+func (t *handshakeTransport) resetReadThresholds() {
+ t.readPacketsLeft = packetRekeyThreshold
+ if t.config.RekeyThreshold > 0 {
+ t.readBytesLeft = int64(t.config.RekeyThreshold)
+ } else if t.algorithms != nil {
+ t.readBytesLeft = t.algorithms.r.rekeyBytes()
+ } else {
+ t.readBytesLeft = 1 << 30
+ }
+}
+
+func (t *handshakeTransport) readOnePacket(first bool) ([]byte, error) {
+ p, err := t.conn.readPacket()
+ if err != nil {
+ return nil, err
+ }
+
+ if t.readPacketsLeft > 0 {
+ t.readPacketsLeft--
+ } else {
+ t.requestKeyExchange()
+ }
+
+ if t.readBytesLeft > 0 {
+ t.readBytesLeft -= int64(len(p))
+ } else {
+ t.requestKeyExchange()
+ }
+
+ if debugHandshake {
+ t.printPacket(p, false)
+ }
+
+ if first && p[0] != msgKexInit {
+ return nil, fmt.Errorf("ssh: first packet should be msgKexInit")
+ }
+
+ if p[0] != msgKexInit {
+ return p, nil
+ }
+
+ firstKex := t.sessionID == nil
+
+ kex := pendingKex{
+ done: make(chan error, 1),
+ otherInit: p,
+ }
+ t.startKex <- &kex
+ err = <-kex.done
+
+ if debugHandshake {
+ log.Printf("%s exited key exchange (first %v), err %v", t.id(), firstKex, err)
+ }
+
+ if err != nil {
+ return nil, err
+ }
+
+ t.resetReadThresholds()
+
+ // By default, a key exchange is hidden from higher layers by
+ // translating it into msgIgnore.
+ successPacket := []byte{msgIgnore}
+ if firstKex {
+ // sendKexInit() for the first kex waits for
+ // msgNewKeys so the authentication process is
+ // guaranteed to happen over an encrypted transport.
+ successPacket = []byte{msgNewKeys}
+ }
+
+ return successPacket, nil
+}
+
+// sendKexInit sends a key change message.
+func (t *handshakeTransport) sendKexInit() error {
+ t.mu.Lock()
+ defer t.mu.Unlock()
+ if t.sentInitMsg != nil {
+ // kexInits may be sent either in response to the other side,
+ // or because our side wants to initiate a key change, so we
+ // may have already sent a kexInit. In that case, don't send a
+ // second kexInit.
+ return nil
+ }
+
+ msg := &kexInitMsg{
+ KexAlgos: t.config.KeyExchanges,
+ CiphersClientServer: t.config.Ciphers,
+ CiphersServerClient: t.config.Ciphers,
+ MACsClientServer: t.config.MACs,
+ MACsServerClient: t.config.MACs,
+ CompressionClientServer: supportedCompressions,
+ CompressionServerClient: supportedCompressions,
+ }
+ io.ReadFull(rand.Reader, msg.Cookie[:])
+
+ if len(t.hostKeys) > 0 {
+ for _, k := range t.hostKeys {
+ msg.ServerHostKeyAlgos = append(
+ msg.ServerHostKeyAlgos, k.PublicKey().Type())
+ }
+ } else {
+ msg.ServerHostKeyAlgos = t.hostKeyAlgorithms
+ }
+ packet := Marshal(msg)
+
+ // writePacket destroys the contents, so save a copy.
+ packetCopy := make([]byte, len(packet))
+ copy(packetCopy, packet)
+
+ if err := t.pushPacket(packetCopy); err != nil {
+ return err
+ }
+
+ t.sentInitMsg = msg
+ t.sentInitPacket = packet
+
+ return nil
+}
+
+func (t *handshakeTransport) writePacket(p []byte) error {
+ switch p[0] {
+ case msgKexInit:
+ return errors.New("ssh: only handshakeTransport can send kexInit")
+ case msgNewKeys:
+ return errors.New("ssh: only handshakeTransport can send newKeys")
+ }
+
+ t.mu.Lock()
+ defer t.mu.Unlock()
+ if t.writeError != nil {
+ return t.writeError
+ }
+
+ if t.sentInitMsg != nil {
+ // Copy the packet so the writer can reuse the buffer.
+ cp := make([]byte, len(p))
+ copy(cp, p)
+ t.pendingPackets = append(t.pendingPackets, cp)
+ return nil
+ }
+
+ if t.writeBytesLeft > 0 {
+ t.writeBytesLeft -= int64(len(p))
+ } else {
+ t.requestKeyExchange()
+ }
+
+ if t.writePacketsLeft > 0 {
+ t.writePacketsLeft--
+ } else {
+ t.requestKeyExchange()
+ }
+
+ if err := t.pushPacket(p); err != nil {
+ t.writeError = err
+ }
+
+ return nil
+}
+
+func (t *handshakeTransport) Close() error {
+ return t.conn.Close()
+}
+
+func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error {
+ if debugHandshake {
+ log.Printf("%s entered key exchange", t.id())
+ }
+
+ otherInit := &kexInitMsg{}
+ if err := Unmarshal(otherInitPacket, otherInit); err != nil {
+ return err
+ }
+
+ magics := handshakeMagics{
+ clientVersion: t.clientVersion,
+ serverVersion: t.serverVersion,
+ clientKexInit: otherInitPacket,
+ serverKexInit: t.sentInitPacket,
+ }
+
+ clientInit := otherInit
+ serverInit := t.sentInitMsg
+ if len(t.hostKeys) == 0 {
+ clientInit, serverInit = serverInit, clientInit
+
+ magics.clientKexInit = t.sentInitPacket
+ magics.serverKexInit = otherInitPacket
+ }
+
+ var err error
+ t.algorithms, err = findAgreedAlgorithms(clientInit, serverInit)
+ if err != nil {
+ return err
+ }
+
+ // We don't send FirstKexFollows, but we handle receiving it.
+ //
+ // RFC 4253 section 7 defines the kex and the agreement method for
+ // first_kex_packet_follows. It states that the guessed packet
+ // should be ignored if the "kex algorithm and/or the host
+ // key algorithm is guessed wrong (server and client have
+ // different preferred algorithm), or if any of the other
+ // algorithms cannot be agreed upon". The other algorithms have
+ // already been checked above so the kex algorithm and host key
+ // algorithm are checked here.
+ if otherInit.FirstKexFollows && (clientInit.KexAlgos[0] != serverInit.KexAlgos[0] || clientInit.ServerHostKeyAlgos[0] != serverInit.ServerHostKeyAlgos[0]) {
+ // other side sent a kex message for the wrong algorithm,
+ // which we have to ignore.
+ if _, err := t.conn.readPacket(); err != nil {
+ return err
+ }
+ }
+
+ kex, ok := kexAlgoMap[t.algorithms.kex]
+ if !ok {
+ return fmt.Errorf("ssh: unexpected key exchange algorithm %v", t.algorithms.kex)
+ }
+
+ var result *kexResult
+ if len(t.hostKeys) > 0 {
+ result, err = t.server(kex, t.algorithms, &magics)
+ } else {
+ result, err = t.client(kex, t.algorithms, &magics)
+ }
+
+ if err != nil {
+ return err
+ }
+
+ if t.sessionID == nil {
+ t.sessionID = result.H
+ }
+ result.SessionID = t.sessionID
+
+ if err := t.conn.prepareKeyChange(t.algorithms, result); err != nil {
+ return err
+ }
+ if err = t.conn.writePacket([]byte{msgNewKeys}); err != nil {
+ return err
+ }
+ if packet, err := t.conn.readPacket(); err != nil {
+ return err
+ } else if packet[0] != msgNewKeys {
+ return unexpectedMessageError(msgNewKeys, packet[0])
+ }
+
+ return nil
+}
+
+func (t *handshakeTransport) server(kex kexAlgorithm, algs *algorithms, magics *handshakeMagics) (*kexResult, error) {
+ var hostKey Signer
+ for _, k := range t.hostKeys {
+ if algs.hostKey == k.PublicKey().Type() {
+ hostKey = k
+ }
+ }
+
+ r, err := kex.Server(t.conn, t.config.Rand, magics, hostKey)
+ return r, err
+}
+
+func (t *handshakeTransport) client(kex kexAlgorithm, algs *algorithms, magics *handshakeMagics) (*kexResult, error) {
+ result, err := kex.Client(t.conn, t.config.Rand, magics)
+ if err != nil {
+ return nil, err
+ }
+
+ hostKey, err := ParsePublicKey(result.HostKey)
+ if err != nil {
+ return nil, err
+ }
+
+ if err := verifyHostKeySignature(hostKey, result); err != nil {
+ return nil, err
+ }
+
+ err = t.hostKeyCallback(t.dialAddress, t.remoteAddr, hostKey)
+ if err != nil {
+ return nil, err
+ }
+
+ return result, nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/handshake_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/handshake_test.go
new file mode 100644
index 000000000..91d493568
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/handshake_test.go
@@ -0,0 +1,559 @@
+// Copyright 2013 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 ssh
+
+import (
+ "bytes"
+ "crypto/rand"
+ "errors"
+ "fmt"
+ "io"
+ "net"
+ "reflect"
+ "runtime"
+ "strings"
+ "sync"
+ "testing"
+)
+
+type testChecker struct {
+ calls []string
+}
+
+func (t *testChecker) Check(dialAddr string, addr net.Addr, key PublicKey) error {
+ if dialAddr == "bad" {
+ return fmt.Errorf("dialAddr is bad")
+ }
+
+ if tcpAddr, ok := addr.(*net.TCPAddr); !ok || tcpAddr == nil {
+ return fmt.Errorf("testChecker: got %T want *net.TCPAddr", addr)
+ }
+
+ t.calls = append(t.calls, fmt.Sprintf("%s %v %s %x", dialAddr, addr, key.Type(), key.Marshal()))
+
+ return nil
+}
+
+// netPipe is analogous to net.Pipe, but it uses a real net.Conn, and
+// therefore is buffered (net.Pipe deadlocks if both sides start with
+// a write.)
+func netPipe() (net.Conn, net.Conn, error) {
+ listener, err := net.Listen("tcp", "127.0.0.1:0")
+ if err != nil {
+ listener, err = net.Listen("tcp", "[::1]:0")
+ if err != nil {
+ return nil, nil, err
+ }
+ }
+ defer listener.Close()
+ c1, err := net.Dial("tcp", listener.Addr().String())
+ if err != nil {
+ return nil, nil, err
+ }
+
+ c2, err := listener.Accept()
+ if err != nil {
+ c1.Close()
+ return nil, nil, err
+ }
+
+ return c1, c2, nil
+}
+
+// noiseTransport inserts ignore messages to check that the read loop
+// and the key exchange filters out these messages.
+type noiseTransport struct {
+ keyingTransport
+}
+
+func (t *noiseTransport) writePacket(p []byte) error {
+ ignore := []byte{msgIgnore}
+ if err := t.keyingTransport.writePacket(ignore); err != nil {
+ return err
+ }
+ debug := []byte{msgDebug, 1, 2, 3}
+ if err := t.keyingTransport.writePacket(debug); err != nil {
+ return err
+ }
+
+ return t.keyingTransport.writePacket(p)
+}
+
+func addNoiseTransport(t keyingTransport) keyingTransport {
+ return &noiseTransport{t}
+}
+
+// handshakePair creates two handshakeTransports connected with each
+// other. If the noise argument is true, both transports will try to
+// confuse the other side by sending ignore and debug messages.
+func handshakePair(clientConf *ClientConfig, addr string, noise bool) (client *handshakeTransport, server *handshakeTransport, err error) {
+ a, b, err := netPipe()
+ if err != nil {
+ return nil, nil, err
+ }
+
+ var trC, trS keyingTransport
+
+ trC = newTransport(a, rand.Reader, true)
+ trS = newTransport(b, rand.Reader, false)
+ if noise {
+ trC = addNoiseTransport(trC)
+ trS = addNoiseTransport(trS)
+ }
+ clientConf.SetDefaults()
+
+ v := []byte("version")
+ client = newClientTransport(trC, v, v, clientConf, addr, a.RemoteAddr())
+
+ serverConf := &ServerConfig{}
+ serverConf.AddHostKey(testSigners["ecdsa"])
+ serverConf.AddHostKey(testSigners["rsa"])
+ serverConf.SetDefaults()
+ server = newServerTransport(trS, v, v, serverConf)
+
+ if err := server.waitSession(); err != nil {
+ return nil, nil, fmt.Errorf("server.waitSession: %v", err)
+ }
+ if err := client.waitSession(); err != nil {
+ return nil, nil, fmt.Errorf("client.waitSession: %v", err)
+ }
+
+ return client, server, nil
+}
+
+func TestHandshakeBasic(t *testing.T) {
+ if runtime.GOOS == "plan9" {
+ t.Skip("see golang.org/issue/7237")
+ }
+
+ checker := &syncChecker{
+ waitCall: make(chan int, 10),
+ called: make(chan int, 10),
+ }
+
+ checker.waitCall <- 1
+ trC, trS, err := handshakePair(&ClientConfig{HostKeyCallback: checker.Check}, "addr", false)
+ if err != nil {
+ t.Fatalf("handshakePair: %v", err)
+ }
+
+ defer trC.Close()
+ defer trS.Close()
+
+ // Let first kex complete normally.
+ <-checker.called
+
+ clientDone := make(chan int, 0)
+ gotHalf := make(chan int, 0)
+ const N = 20
+
+ go func() {
+ defer close(clientDone)
+ // Client writes a bunch of stuff, and does a key
+ // change in the middle. This should not confuse the
+ // handshake in progress. We do this twice, so we test
+ // that the packet buffer is reset correctly.
+ for i := 0; i < N; i++ {
+ p := []byte{msgRequestSuccess, byte(i)}
+ if err := trC.writePacket(p); err != nil {
+ t.Fatalf("sendPacket: %v", err)
+ }
+ if (i % 10) == 5 {
+ <-gotHalf
+ // halfway through, we request a key change.
+ trC.requestKeyExchange()
+
+ // Wait until we can be sure the key
+ // change has really started before we
+ // write more.
+ <-checker.called
+ }
+ if (i % 10) == 7 {
+ // write some packets until the kex
+ // completes, to test buffering of
+ // packets.
+ checker.waitCall <- 1
+ }
+ }
+ }()
+
+ // Server checks that client messages come in cleanly
+ i := 0
+ err = nil
+ for ; i < N; i++ {
+ var p []byte
+ p, err = trS.readPacket()
+ if err != nil {
+ break
+ }
+ if (i % 10) == 5 {
+ gotHalf <- 1
+ }
+
+ want := []byte{msgRequestSuccess, byte(i)}
+ if bytes.Compare(p, want) != 0 {
+ t.Errorf("message %d: got %v, want %v", i, p, want)
+ }
+ }
+ <-clientDone
+ if err != nil && err != io.EOF {
+ t.Fatalf("server error: %v", err)
+ }
+ if i != N {
+ t.Errorf("received %d messages, want 10.", i)
+ }
+
+ close(checker.called)
+ if _, ok := <-checker.called; ok {
+ // If all went well, we registered exactly 2 key changes: one
+ // that establishes the session, and one that we requested
+ // additionally.
+ t.Fatalf("got another host key checks after 2 handshakes")
+ }
+}
+
+func TestForceFirstKex(t *testing.T) {
+ // like handshakePair, but must access the keyingTransport.
+ checker := &testChecker{}
+ clientConf := &ClientConfig{HostKeyCallback: checker.Check}
+ a, b, err := netPipe()
+ if err != nil {
+ t.Fatalf("netPipe: %v", err)
+ }
+
+ var trC, trS keyingTransport
+
+ trC = newTransport(a, rand.Reader, true)
+
+ // This is the disallowed packet:
+ trC.writePacket(Marshal(&serviceRequestMsg{serviceUserAuth}))
+
+ // Rest of the setup.
+ trS = newTransport(b, rand.Reader, false)
+ clientConf.SetDefaults()
+
+ v := []byte("version")
+ client := newClientTransport(trC, v, v, clientConf, "addr", a.RemoteAddr())
+
+ serverConf := &ServerConfig{}
+ serverConf.AddHostKey(testSigners["ecdsa"])
+ serverConf.AddHostKey(testSigners["rsa"])
+ serverConf.SetDefaults()
+ server := newServerTransport(trS, v, v, serverConf)
+
+ defer client.Close()
+ defer server.Close()
+
+ // We setup the initial key exchange, but the remote side
+ // tries to send serviceRequestMsg in cleartext, which is
+ // disallowed.
+
+ if err := server.waitSession(); err == nil {
+ t.Errorf("server first kex init should reject unexpected packet")
+ }
+}
+
+func TestHandshakeAutoRekeyWrite(t *testing.T) {
+ checker := &syncChecker{
+ called: make(chan int, 10),
+ waitCall: nil,
+ }
+ clientConf := &ClientConfig{HostKeyCallback: checker.Check}
+ clientConf.RekeyThreshold = 500
+ trC, trS, err := handshakePair(clientConf, "addr", false)
+ if err != nil {
+ t.Fatalf("handshakePair: %v", err)
+ }
+ defer trC.Close()
+ defer trS.Close()
+
+ input := make([]byte, 251)
+ input[0] = msgRequestSuccess
+
+ done := make(chan int, 1)
+ const numPacket = 5
+ go func() {
+ defer close(done)
+ j := 0
+ for ; j < numPacket; j++ {
+ if p, err := trS.readPacket(); err != nil {
+ break
+ } else if !bytes.Equal(input, p) {
+ t.Errorf("got packet type %d, want %d", p[0], input[0])
+ }
+ }
+
+ if j != numPacket {
+ t.Errorf("got %d, want 5 messages", j)
+ }
+ }()
+
+ <-checker.called
+
+ for i := 0; i < numPacket; i++ {
+ p := make([]byte, len(input))
+ copy(p, input)
+ if err := trC.writePacket(p); err != nil {
+ t.Errorf("writePacket: %v", err)
+ }
+ if i == 2 {
+ // Make sure the kex is in progress.
+ <-checker.called
+ }
+
+ }
+ <-done
+}
+
+type syncChecker struct {
+ waitCall chan int
+ called chan int
+}
+
+func (c *syncChecker) Check(dialAddr string, addr net.Addr, key PublicKey) error {
+ c.called <- 1
+ if c.waitCall != nil {
+ <-c.waitCall
+ }
+ return nil
+}
+
+func TestHandshakeAutoRekeyRead(t *testing.T) {
+ sync := &syncChecker{
+ called: make(chan int, 2),
+ waitCall: nil,
+ }
+ clientConf := &ClientConfig{
+ HostKeyCallback: sync.Check,
+ }
+ clientConf.RekeyThreshold = 500
+
+ trC, trS, err := handshakePair(clientConf, "addr", false)
+ if err != nil {
+ t.Fatalf("handshakePair: %v", err)
+ }
+ defer trC.Close()
+ defer trS.Close()
+
+ packet := make([]byte, 501)
+ packet[0] = msgRequestSuccess
+ if err := trS.writePacket(packet); err != nil {
+ t.Fatalf("writePacket: %v", err)
+ }
+
+ // While we read out the packet, a key change will be
+ // initiated.
+ done := make(chan int, 1)
+ go func() {
+ defer close(done)
+ if _, err := trC.readPacket(); err != nil {
+ t.Fatalf("readPacket(client): %v", err)
+ }
+
+ }()
+
+ <-done
+ <-sync.called
+}
+
+// errorKeyingTransport generates errors after a given number of
+// read/write operations.
+type errorKeyingTransport struct {
+ packetConn
+ readLeft, writeLeft int
+}
+
+func (n *errorKeyingTransport) prepareKeyChange(*algorithms, *kexResult) error {
+ return nil
+}
+
+func (n *errorKeyingTransport) getSessionID() []byte {
+ return nil
+}
+
+func (n *errorKeyingTransport) writePacket(packet []byte) error {
+ if n.writeLeft == 0 {
+ n.Close()
+ return errors.New("barf")
+ }
+
+ n.writeLeft--
+ return n.packetConn.writePacket(packet)
+}
+
+func (n *errorKeyingTransport) readPacket() ([]byte, error) {
+ if n.readLeft == 0 {
+ n.Close()
+ return nil, errors.New("barf")
+ }
+
+ n.readLeft--
+ return n.packetConn.readPacket()
+}
+
+func TestHandshakeErrorHandlingRead(t *testing.T) {
+ for i := 0; i < 20; i++ {
+ testHandshakeErrorHandlingN(t, i, -1, false)
+ }
+}
+
+func TestHandshakeErrorHandlingWrite(t *testing.T) {
+ for i := 0; i < 20; i++ {
+ testHandshakeErrorHandlingN(t, -1, i, false)
+ }
+}
+
+func TestHandshakeErrorHandlingReadCoupled(t *testing.T) {
+ for i := 0; i < 20; i++ {
+ testHandshakeErrorHandlingN(t, i, -1, true)
+ }
+}
+
+func TestHandshakeErrorHandlingWriteCoupled(t *testing.T) {
+ for i := 0; i < 20; i++ {
+ testHandshakeErrorHandlingN(t, -1, i, true)
+ }
+}
+
+// testHandshakeErrorHandlingN runs handshakes, injecting errors. If
+// handshakeTransport deadlocks, the go runtime will detect it and
+// panic.
+func testHandshakeErrorHandlingN(t *testing.T, readLimit, writeLimit int, coupled bool) {
+ msg := Marshal(&serviceRequestMsg{strings.Repeat("x", int(minRekeyThreshold)/4)})
+
+ a, b := memPipe()
+ defer a.Close()
+ defer b.Close()
+
+ key := testSigners["ecdsa"]
+ serverConf := Config{RekeyThreshold: minRekeyThreshold}
+ serverConf.SetDefaults()
+ serverConn := newHandshakeTransport(&errorKeyingTransport{a, readLimit, writeLimit}, &serverConf, []byte{'a'}, []byte{'b'})
+ serverConn.hostKeys = []Signer{key}
+ go serverConn.readLoop()
+ go serverConn.kexLoop()
+
+ clientConf := Config{RekeyThreshold: 10 * minRekeyThreshold}
+ clientConf.SetDefaults()
+ clientConn := newHandshakeTransport(&errorKeyingTransport{b, -1, -1}, &clientConf, []byte{'a'}, []byte{'b'})
+ clientConn.hostKeyAlgorithms = []string{key.PublicKey().Type()}
+ clientConn.hostKeyCallback = InsecureIgnoreHostKey()
+ go clientConn.readLoop()
+ go clientConn.kexLoop()
+
+ var wg sync.WaitGroup
+
+ for _, hs := range []packetConn{serverConn, clientConn} {
+ if !coupled {
+ wg.Add(2)
+ go func(c packetConn) {
+ for i := 0; ; i++ {
+ str := fmt.Sprintf("%08x", i) + strings.Repeat("x", int(minRekeyThreshold)/4-8)
+ err := c.writePacket(Marshal(&serviceRequestMsg{str}))
+ if err != nil {
+ break
+ }
+ }
+ wg.Done()
+ c.Close()
+ }(hs)
+ go func(c packetConn) {
+ for {
+ _, err := c.readPacket()
+ if err != nil {
+ break
+ }
+ }
+ wg.Done()
+ }(hs)
+ } else {
+ wg.Add(1)
+ go func(c packetConn) {
+ for {
+ _, err := c.readPacket()
+ if err != nil {
+ break
+ }
+ if err := c.writePacket(msg); err != nil {
+ break
+ }
+
+ }
+ wg.Done()
+ }(hs)
+ }
+ }
+ wg.Wait()
+}
+
+func TestDisconnect(t *testing.T) {
+ if runtime.GOOS == "plan9" {
+ t.Skip("see golang.org/issue/7237")
+ }
+ checker := &testChecker{}
+ trC, trS, err := handshakePair(&ClientConfig{HostKeyCallback: checker.Check}, "addr", false)
+ if err != nil {
+ t.Fatalf("handshakePair: %v", err)
+ }
+
+ defer trC.Close()
+ defer trS.Close()
+
+ trC.writePacket([]byte{msgRequestSuccess, 0, 0})
+ errMsg := &disconnectMsg{
+ Reason: 42,
+ Message: "such is life",
+ }
+ trC.writePacket(Marshal(errMsg))
+ trC.writePacket([]byte{msgRequestSuccess, 0, 0})
+
+ packet, err := trS.readPacket()
+ if err != nil {
+ t.Fatalf("readPacket 1: %v", err)
+ }
+ if packet[0] != msgRequestSuccess {
+ t.Errorf("got packet %v, want packet type %d", packet, msgRequestSuccess)
+ }
+
+ _, err = trS.readPacket()
+ if err == nil {
+ t.Errorf("readPacket 2 succeeded")
+ } else if !reflect.DeepEqual(err, errMsg) {
+ t.Errorf("got error %#v, want %#v", err, errMsg)
+ }
+
+ _, err = trS.readPacket()
+ if err == nil {
+ t.Errorf("readPacket 3 succeeded")
+ }
+}
+
+func TestHandshakeRekeyDefault(t *testing.T) {
+ clientConf := &ClientConfig{
+ Config: Config{
+ Ciphers: []string{"aes128-ctr"},
+ },
+ HostKeyCallback: InsecureIgnoreHostKey(),
+ }
+ trC, trS, err := handshakePair(clientConf, "addr", false)
+ if err != nil {
+ t.Fatalf("handshakePair: %v", err)
+ }
+ defer trC.Close()
+ defer trS.Close()
+
+ trC.writePacket([]byte{msgRequestSuccess, 0, 0})
+ trC.Close()
+
+ rgb := (1024 + trC.readBytesLeft) >> 30
+ wgb := (1024 + trC.writeBytesLeft) >> 30
+
+ if rgb != 64 {
+ t.Errorf("got rekey after %dG read, want 64G", rgb)
+ }
+ if wgb != 64 {
+ t.Errorf("got rekey after %dG write, want 64G", wgb)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/kex.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/kex.go
new file mode 100644
index 000000000..f91c2770e
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/kex.go
@@ -0,0 +1,540 @@
+// Copyright 2013 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 ssh
+
+import (
+ "crypto"
+ "crypto/ecdsa"
+ "crypto/elliptic"
+ "crypto/rand"
+ "crypto/subtle"
+ "errors"
+ "io"
+ "math/big"
+
+ "golang.org/x/crypto/curve25519"
+)
+
+const (
+ kexAlgoDH1SHA1 = "diffie-hellman-group1-sha1"
+ kexAlgoDH14SHA1 = "diffie-hellman-group14-sha1"
+ kexAlgoECDH256 = "ecdh-sha2-nistp256"
+ kexAlgoECDH384 = "ecdh-sha2-nistp384"
+ kexAlgoECDH521 = "ecdh-sha2-nistp521"
+ kexAlgoCurve25519SHA256 = "curve25519-sha256@libssh.org"
+)
+
+// kexResult captures the outcome of a key exchange.
+type kexResult struct {
+ // Session hash. See also RFC 4253, section 8.
+ H []byte
+
+ // Shared secret. See also RFC 4253, section 8.
+ K []byte
+
+ // Host key as hashed into H.
+ HostKey []byte
+
+ // Signature of H.
+ Signature []byte
+
+ // A cryptographic hash function that matches the security
+ // level of the key exchange algorithm. It is used for
+ // calculating H, and for deriving keys from H and K.
+ Hash crypto.Hash
+
+ // The session ID, which is the first H computed. This is used
+ // to derive key material inside the transport.
+ SessionID []byte
+}
+
+// handshakeMagics contains data that is always included in the
+// session hash.
+type handshakeMagics struct {
+ clientVersion, serverVersion []byte
+ clientKexInit, serverKexInit []byte
+}
+
+func (m *handshakeMagics) write(w io.Writer) {
+ writeString(w, m.clientVersion)
+ writeString(w, m.serverVersion)
+ writeString(w, m.clientKexInit)
+ writeString(w, m.serverKexInit)
+}
+
+// kexAlgorithm abstracts different key exchange algorithms.
+type kexAlgorithm interface {
+ // Server runs server-side key agreement, signing the result
+ // with a hostkey.
+ Server(p packetConn, rand io.Reader, magics *handshakeMagics, s Signer) (*kexResult, error)
+
+ // Client runs the client-side key agreement. Caller is
+ // responsible for verifying the host key signature.
+ Client(p packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error)
+}
+
+// dhGroup is a multiplicative group suitable for implementing Diffie-Hellman key agreement.
+type dhGroup struct {
+ g, p, pMinus1 *big.Int
+}
+
+func (group *dhGroup) diffieHellman(theirPublic, myPrivate *big.Int) (*big.Int, error) {
+ if theirPublic.Cmp(bigOne) <= 0 || theirPublic.Cmp(group.pMinus1) >= 0 {
+ return nil, errors.New("ssh: DH parameter out of bounds")
+ }
+ return new(big.Int).Exp(theirPublic, myPrivate, group.p), nil
+}
+
+func (group *dhGroup) Client(c packetConn, randSource io.Reader, magics *handshakeMagics) (*kexResult, error) {
+ hashFunc := crypto.SHA1
+
+ var x *big.Int
+ for {
+ var err error
+ if x, err = rand.Int(randSource, group.pMinus1); err != nil {
+ return nil, err
+ }
+ if x.Sign() > 0 {
+ break
+ }
+ }
+
+ X := new(big.Int).Exp(group.g, x, group.p)
+ kexDHInit := kexDHInitMsg{
+ X: X,
+ }
+ if err := c.writePacket(Marshal(&kexDHInit)); err != nil {
+ return nil, err
+ }
+
+ packet, err := c.readPacket()
+ if err != nil {
+ return nil, err
+ }
+
+ var kexDHReply kexDHReplyMsg
+ if err = Unmarshal(packet, &kexDHReply); err != nil {
+ return nil, err
+ }
+
+ kInt, err := group.diffieHellman(kexDHReply.Y, x)
+ if err != nil {
+ return nil, err
+ }
+
+ h := hashFunc.New()
+ magics.write(h)
+ writeString(h, kexDHReply.HostKey)
+ writeInt(h, X)
+ writeInt(h, kexDHReply.Y)
+ K := make([]byte, intLength(kInt))
+ marshalInt(K, kInt)
+ h.Write(K)
+
+ return &kexResult{
+ H: h.Sum(nil),
+ K: K,
+ HostKey: kexDHReply.HostKey,
+ Signature: kexDHReply.Signature,
+ Hash: crypto.SHA1,
+ }, nil
+}
+
+func (group *dhGroup) Server(c packetConn, randSource io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) {
+ hashFunc := crypto.SHA1
+ packet, err := c.readPacket()
+ if err != nil {
+ return
+ }
+ var kexDHInit kexDHInitMsg
+ if err = Unmarshal(packet, &kexDHInit); err != nil {
+ return
+ }
+
+ var y *big.Int
+ for {
+ if y, err = rand.Int(randSource, group.pMinus1); err != nil {
+ return
+ }
+ if y.Sign() > 0 {
+ break
+ }
+ }
+
+ Y := new(big.Int).Exp(group.g, y, group.p)
+ kInt, err := group.diffieHellman(kexDHInit.X, y)
+ if err != nil {
+ return nil, err
+ }
+
+ hostKeyBytes := priv.PublicKey().Marshal()
+
+ h := hashFunc.New()
+ magics.write(h)
+ writeString(h, hostKeyBytes)
+ writeInt(h, kexDHInit.X)
+ writeInt(h, Y)
+
+ K := make([]byte, intLength(kInt))
+ marshalInt(K, kInt)
+ h.Write(K)
+
+ H := h.Sum(nil)
+
+ // H is already a hash, but the hostkey signing will apply its
+ // own key-specific hash algorithm.
+ sig, err := signAndMarshal(priv, randSource, H)
+ if err != nil {
+ return nil, err
+ }
+
+ kexDHReply := kexDHReplyMsg{
+ HostKey: hostKeyBytes,
+ Y: Y,
+ Signature: sig,
+ }
+ packet = Marshal(&kexDHReply)
+
+ err = c.writePacket(packet)
+ return &kexResult{
+ H: H,
+ K: K,
+ HostKey: hostKeyBytes,
+ Signature: sig,
+ Hash: crypto.SHA1,
+ }, nil
+}
+
+// ecdh performs Elliptic Curve Diffie-Hellman key exchange as
+// described in RFC 5656, section 4.
+type ecdh struct {
+ curve elliptic.Curve
+}
+
+func (kex *ecdh) Client(c packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error) {
+ ephKey, err := ecdsa.GenerateKey(kex.curve, rand)
+ if err != nil {
+ return nil, err
+ }
+
+ kexInit := kexECDHInitMsg{
+ ClientPubKey: elliptic.Marshal(kex.curve, ephKey.PublicKey.X, ephKey.PublicKey.Y),
+ }
+
+ serialized := Marshal(&kexInit)
+ if err := c.writePacket(serialized); err != nil {
+ return nil, err
+ }
+
+ packet, err := c.readPacket()
+ if err != nil {
+ return nil, err
+ }
+
+ var reply kexECDHReplyMsg
+ if err = Unmarshal(packet, &reply); err != nil {
+ return nil, err
+ }
+
+ x, y, err := unmarshalECKey(kex.curve, reply.EphemeralPubKey)
+ if err != nil {
+ return nil, err
+ }
+
+ // generate shared secret
+ secret, _ := kex.curve.ScalarMult(x, y, ephKey.D.Bytes())
+
+ h := ecHash(kex.curve).New()
+ magics.write(h)
+ writeString(h, reply.HostKey)
+ writeString(h, kexInit.ClientPubKey)
+ writeString(h, reply.EphemeralPubKey)
+ K := make([]byte, intLength(secret))
+ marshalInt(K, secret)
+ h.Write(K)
+
+ return &kexResult{
+ H: h.Sum(nil),
+ K: K,
+ HostKey: reply.HostKey,
+ Signature: reply.Signature,
+ Hash: ecHash(kex.curve),
+ }, nil
+}
+
+// unmarshalECKey parses and checks an EC key.
+func unmarshalECKey(curve elliptic.Curve, pubkey []byte) (x, y *big.Int, err error) {
+ x, y = elliptic.Unmarshal(curve, pubkey)
+ if x == nil {
+ return nil, nil, errors.New("ssh: elliptic.Unmarshal failure")
+ }
+ if !validateECPublicKey(curve, x, y) {
+ return nil, nil, errors.New("ssh: public key not on curve")
+ }
+ return x, y, nil
+}
+
+// validateECPublicKey checks that the point is a valid public key for
+// the given curve. See [SEC1], 3.2.2
+func validateECPublicKey(curve elliptic.Curve, x, y *big.Int) bool {
+ if x.Sign() == 0 && y.Sign() == 0 {
+ return false
+ }
+
+ if x.Cmp(curve.Params().P) >= 0 {
+ return false
+ }
+
+ if y.Cmp(curve.Params().P) >= 0 {
+ return false
+ }
+
+ if !curve.IsOnCurve(x, y) {
+ return false
+ }
+
+ // We don't check if N * PubKey == 0, since
+ //
+ // - the NIST curves have cofactor = 1, so this is implicit.
+ // (We don't foresee an implementation that supports non NIST
+ // curves)
+ //
+ // - for ephemeral keys, we don't need to worry about small
+ // subgroup attacks.
+ return true
+}
+
+func (kex *ecdh) Server(c packetConn, rand io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) {
+ packet, err := c.readPacket()
+ if err != nil {
+ return nil, err
+ }
+
+ var kexECDHInit kexECDHInitMsg
+ if err = Unmarshal(packet, &kexECDHInit); err != nil {
+ return nil, err
+ }
+
+ clientX, clientY, err := unmarshalECKey(kex.curve, kexECDHInit.ClientPubKey)
+ if err != nil {
+ return nil, err
+ }
+
+ // We could cache this key across multiple users/multiple
+ // connection attempts, but the benefit is small. OpenSSH
+ // generates a new key for each incoming connection.
+ ephKey, err := ecdsa.GenerateKey(kex.curve, rand)
+ if err != nil {
+ return nil, err
+ }
+
+ hostKeyBytes := priv.PublicKey().Marshal()
+
+ serializedEphKey := elliptic.Marshal(kex.curve, ephKey.PublicKey.X, ephKey.PublicKey.Y)
+
+ // generate shared secret
+ secret, _ := kex.curve.ScalarMult(clientX, clientY, ephKey.D.Bytes())
+
+ h := ecHash(kex.curve).New()
+ magics.write(h)
+ writeString(h, hostKeyBytes)
+ writeString(h, kexECDHInit.ClientPubKey)
+ writeString(h, serializedEphKey)
+
+ K := make([]byte, intLength(secret))
+ marshalInt(K, secret)
+ h.Write(K)
+
+ H := h.Sum(nil)
+
+ // H is already a hash, but the hostkey signing will apply its
+ // own key-specific hash algorithm.
+ sig, err := signAndMarshal(priv, rand, H)
+ if err != nil {
+ return nil, err
+ }
+
+ reply := kexECDHReplyMsg{
+ EphemeralPubKey: serializedEphKey,
+ HostKey: hostKeyBytes,
+ Signature: sig,
+ }
+
+ serialized := Marshal(&reply)
+ if err := c.writePacket(serialized); err != nil {
+ return nil, err
+ }
+
+ return &kexResult{
+ H: H,
+ K: K,
+ HostKey: reply.HostKey,
+ Signature: sig,
+ Hash: ecHash(kex.curve),
+ }, nil
+}
+
+var kexAlgoMap = map[string]kexAlgorithm{}
+
+func init() {
+ // This is the group called diffie-hellman-group1-sha1 in RFC
+ // 4253 and Oakley Group 2 in RFC 2409.
+ p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF", 16)
+ kexAlgoMap[kexAlgoDH1SHA1] = &dhGroup{
+ g: new(big.Int).SetInt64(2),
+ p: p,
+ pMinus1: new(big.Int).Sub(p, bigOne),
+ }
+
+ // This is the group called diffie-hellman-group14-sha1 in RFC
+ // 4253 and Oakley Group 14 in RFC 3526.
+ p, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16)
+
+ kexAlgoMap[kexAlgoDH14SHA1] = &dhGroup{
+ g: new(big.Int).SetInt64(2),
+ p: p,
+ pMinus1: new(big.Int).Sub(p, bigOne),
+ }
+
+ kexAlgoMap[kexAlgoECDH521] = &ecdh{elliptic.P521()}
+ kexAlgoMap[kexAlgoECDH384] = &ecdh{elliptic.P384()}
+ kexAlgoMap[kexAlgoECDH256] = &ecdh{elliptic.P256()}
+ kexAlgoMap[kexAlgoCurve25519SHA256] = &curve25519sha256{}
+}
+
+// curve25519sha256 implements the curve25519-sha256@libssh.org key
+// agreement protocol, as described in
+// https://git.libssh.org/projects/libssh.git/tree/doc/curve25519-sha256@libssh.org.txt
+type curve25519sha256 struct{}
+
+type curve25519KeyPair struct {
+ priv [32]byte
+ pub [32]byte
+}
+
+func (kp *curve25519KeyPair) generate(rand io.Reader) error {
+ if _, err := io.ReadFull(rand, kp.priv[:]); err != nil {
+ return err
+ }
+ curve25519.ScalarBaseMult(&kp.pub, &kp.priv)
+ return nil
+}
+
+// curve25519Zeros is just an array of 32 zero bytes so that we have something
+// convenient to compare against in order to reject curve25519 points with the
+// wrong order.
+var curve25519Zeros [32]byte
+
+func (kex *curve25519sha256) Client(c packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error) {
+ var kp curve25519KeyPair
+ if err := kp.generate(rand); err != nil {
+ return nil, err
+ }
+ if err := c.writePacket(Marshal(&kexECDHInitMsg{kp.pub[:]})); err != nil {
+ return nil, err
+ }
+
+ packet, err := c.readPacket()
+ if err != nil {
+ return nil, err
+ }
+
+ var reply kexECDHReplyMsg
+ if err = Unmarshal(packet, &reply); err != nil {
+ return nil, err
+ }
+ if len(reply.EphemeralPubKey) != 32 {
+ return nil, errors.New("ssh: peer's curve25519 public value has wrong length")
+ }
+
+ var servPub, secret [32]byte
+ copy(servPub[:], reply.EphemeralPubKey)
+ curve25519.ScalarMult(&secret, &kp.priv, &servPub)
+ if subtle.ConstantTimeCompare(secret[:], curve25519Zeros[:]) == 1 {
+ return nil, errors.New("ssh: peer's curve25519 public value has wrong order")
+ }
+
+ h := crypto.SHA256.New()
+ magics.write(h)
+ writeString(h, reply.HostKey)
+ writeString(h, kp.pub[:])
+ writeString(h, reply.EphemeralPubKey)
+
+ kInt := new(big.Int).SetBytes(secret[:])
+ K := make([]byte, intLength(kInt))
+ marshalInt(K, kInt)
+ h.Write(K)
+
+ return &kexResult{
+ H: h.Sum(nil),
+ K: K,
+ HostKey: reply.HostKey,
+ Signature: reply.Signature,
+ Hash: crypto.SHA256,
+ }, nil
+}
+
+func (kex *curve25519sha256) Server(c packetConn, rand io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) {
+ packet, err := c.readPacket()
+ if err != nil {
+ return
+ }
+ var kexInit kexECDHInitMsg
+ if err = Unmarshal(packet, &kexInit); err != nil {
+ return
+ }
+
+ if len(kexInit.ClientPubKey) != 32 {
+ return nil, errors.New("ssh: peer's curve25519 public value has wrong length")
+ }
+
+ var kp curve25519KeyPair
+ if err := kp.generate(rand); err != nil {
+ return nil, err
+ }
+
+ var clientPub, secret [32]byte
+ copy(clientPub[:], kexInit.ClientPubKey)
+ curve25519.ScalarMult(&secret, &kp.priv, &clientPub)
+ if subtle.ConstantTimeCompare(secret[:], curve25519Zeros[:]) == 1 {
+ return nil, errors.New("ssh: peer's curve25519 public value has wrong order")
+ }
+
+ hostKeyBytes := priv.PublicKey().Marshal()
+
+ h := crypto.SHA256.New()
+ magics.write(h)
+ writeString(h, hostKeyBytes)
+ writeString(h, kexInit.ClientPubKey)
+ writeString(h, kp.pub[:])
+
+ kInt := new(big.Int).SetBytes(secret[:])
+ K := make([]byte, intLength(kInt))
+ marshalInt(K, kInt)
+ h.Write(K)
+
+ H := h.Sum(nil)
+
+ sig, err := signAndMarshal(priv, rand, H)
+ if err != nil {
+ return nil, err
+ }
+
+ reply := kexECDHReplyMsg{
+ EphemeralPubKey: kp.pub[:],
+ HostKey: hostKeyBytes,
+ Signature: sig,
+ }
+ if err := c.writePacket(Marshal(&reply)); err != nil {
+ return nil, err
+ }
+ return &kexResult{
+ H: H,
+ K: K,
+ HostKey: hostKeyBytes,
+ Signature: sig,
+ Hash: crypto.SHA256,
+ }, nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/kex_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/kex_test.go
new file mode 100644
index 000000000..12ca0acd3
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/kex_test.go
@@ -0,0 +1,50 @@
+// Copyright 2013 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 ssh
+
+// Key exchange tests.
+
+import (
+ "crypto/rand"
+ "reflect"
+ "testing"
+)
+
+func TestKexes(t *testing.T) {
+ type kexResultErr struct {
+ result *kexResult
+ err error
+ }
+
+ for name, kex := range kexAlgoMap {
+ a, b := memPipe()
+
+ s := make(chan kexResultErr, 1)
+ c := make(chan kexResultErr, 1)
+ var magics handshakeMagics
+ go func() {
+ r, e := kex.Client(a, rand.Reader, &magics)
+ a.Close()
+ c <- kexResultErr{r, e}
+ }()
+ go func() {
+ r, e := kex.Server(b, rand.Reader, &magics, testSigners["ecdsa"])
+ b.Close()
+ s <- kexResultErr{r, e}
+ }()
+
+ clientRes := <-c
+ serverRes := <-s
+ if clientRes.err != nil {
+ t.Errorf("client: %v", clientRes.err)
+ }
+ if serverRes.err != nil {
+ t.Errorf("server: %v", serverRes.err)
+ }
+ if !reflect.DeepEqual(clientRes.result, serverRes.result) {
+ t.Errorf("kex %q: mismatch %#v, %#v", name, clientRes.result, serverRes.result)
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/keys.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/keys.go
new file mode 100644
index 000000000..b682c1741
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/keys.go
@@ -0,0 +1,1031 @@
+// Copyright 2012 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 ssh
+
+import (
+ "bytes"
+ "crypto"
+ "crypto/dsa"
+ "crypto/ecdsa"
+ "crypto/elliptic"
+ "crypto/md5"
+ "crypto/rsa"
+ "crypto/sha256"
+ "crypto/x509"
+ "encoding/asn1"
+ "encoding/base64"
+ "encoding/hex"
+ "encoding/pem"
+ "errors"
+ "fmt"
+ "io"
+ "math/big"
+ "strings"
+
+ "golang.org/x/crypto/ed25519"
+)
+
+// These constants represent the algorithm names for key types supported by this
+// package.
+const (
+ KeyAlgoRSA = "ssh-rsa"
+ KeyAlgoDSA = "ssh-dss"
+ KeyAlgoECDSA256 = "ecdsa-sha2-nistp256"
+ KeyAlgoECDSA384 = "ecdsa-sha2-nistp384"
+ KeyAlgoECDSA521 = "ecdsa-sha2-nistp521"
+ KeyAlgoED25519 = "ssh-ed25519"
+)
+
+// parsePubKey parses a public key of the given algorithm.
+// Use ParsePublicKey for keys with prepended algorithm.
+func parsePubKey(in []byte, algo string) (pubKey PublicKey, rest []byte, err error) {
+ switch algo {
+ case KeyAlgoRSA:
+ return parseRSA(in)
+ case KeyAlgoDSA:
+ return parseDSA(in)
+ case KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521:
+ return parseECDSA(in)
+ case KeyAlgoED25519:
+ return parseED25519(in)
+ case CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoED25519v01:
+ cert, err := parseCert(in, certToPrivAlgo(algo))
+ if err != nil {
+ return nil, nil, err
+ }
+ return cert, nil, nil
+ }
+ return nil, nil, fmt.Errorf("ssh: unknown key algorithm: %v", algo)
+}
+
+// parseAuthorizedKey parses a public key in OpenSSH authorized_keys format
+// (see sshd(8) manual page) once the options and key type fields have been
+// removed.
+func parseAuthorizedKey(in []byte) (out PublicKey, comment string, err error) {
+ in = bytes.TrimSpace(in)
+
+ i := bytes.IndexAny(in, " \t")
+ if i == -1 {
+ i = len(in)
+ }
+ base64Key := in[:i]
+
+ key := make([]byte, base64.StdEncoding.DecodedLen(len(base64Key)))
+ n, err := base64.StdEncoding.Decode(key, base64Key)
+ if err != nil {
+ return nil, "", err
+ }
+ key = key[:n]
+ out, err = ParsePublicKey(key)
+ if err != nil {
+ return nil, "", err
+ }
+ comment = string(bytes.TrimSpace(in[i:]))
+ return out, comment, nil
+}
+
+// ParseKnownHosts parses an entry in the format of the known_hosts file.
+//
+// The known_hosts format is documented in the sshd(8) manual page. This
+// function will parse a single entry from in. On successful return, marker
+// will contain the optional marker value (i.e. "cert-authority" or "revoked")
+// or else be empty, hosts will contain the hosts that this entry matches,
+// pubKey will contain the public key and comment will contain any trailing
+// comment at the end of the line. See the sshd(8) manual page for the various
+// forms that a host string can take.
+//
+// The unparsed remainder of the input will be returned in rest. This function
+// can be called repeatedly to parse multiple entries.
+//
+// If no entries were found in the input then err will be io.EOF. Otherwise a
+// non-nil err value indicates a parse error.
+func ParseKnownHosts(in []byte) (marker string, hosts []string, pubKey PublicKey, comment string, rest []byte, err error) {
+ for len(in) > 0 {
+ end := bytes.IndexByte(in, '\n')
+ if end != -1 {
+ rest = in[end+1:]
+ in = in[:end]
+ } else {
+ rest = nil
+ }
+
+ end = bytes.IndexByte(in, '\r')
+ if end != -1 {
+ in = in[:end]
+ }
+
+ in = bytes.TrimSpace(in)
+ if len(in) == 0 || in[0] == '#' {
+ in = rest
+ continue
+ }
+
+ i := bytes.IndexAny(in, " \t")
+ if i == -1 {
+ in = rest
+ continue
+ }
+
+ // Strip out the beginning of the known_host key.
+ // This is either an optional marker or a (set of) hostname(s).
+ keyFields := bytes.Fields(in)
+ if len(keyFields) < 3 || len(keyFields) > 5 {
+ return "", nil, nil, "", nil, errors.New("ssh: invalid entry in known_hosts data")
+ }
+
+ // keyFields[0] is either "@cert-authority", "@revoked" or a comma separated
+ // list of hosts
+ marker := ""
+ if keyFields[0][0] == '@' {
+ marker = string(keyFields[0][1:])
+ keyFields = keyFields[1:]
+ }
+
+ hosts := string(keyFields[0])
+ // keyFields[1] contains the key type (e.g. “ssh-rsa”).
+ // However, that information is duplicated inside the
+ // base64-encoded key and so is ignored here.
+
+ key := bytes.Join(keyFields[2:], []byte(" "))
+ if pubKey, comment, err = parseAuthorizedKey(key); err != nil {
+ return "", nil, nil, "", nil, err
+ }
+
+ return marker, strings.Split(hosts, ","), pubKey, comment, rest, nil
+ }
+
+ return "", nil, nil, "", nil, io.EOF
+}
+
+// ParseAuthorizedKeys parses a public key from an authorized_keys
+// file used in OpenSSH according to the sshd(8) manual page.
+func ParseAuthorizedKey(in []byte) (out PublicKey, comment string, options []string, rest []byte, err error) {
+ for len(in) > 0 {
+ end := bytes.IndexByte(in, '\n')
+ if end != -1 {
+ rest = in[end+1:]
+ in = in[:end]
+ } else {
+ rest = nil
+ }
+
+ end = bytes.IndexByte(in, '\r')
+ if end != -1 {
+ in = in[:end]
+ }
+
+ in = bytes.TrimSpace(in)
+ if len(in) == 0 || in[0] == '#' {
+ in = rest
+ continue
+ }
+
+ i := bytes.IndexAny(in, " \t")
+ if i == -1 {
+ in = rest
+ continue
+ }
+
+ if out, comment, err = parseAuthorizedKey(in[i:]); err == nil {
+ return out, comment, options, rest, nil
+ }
+
+ // No key type recognised. Maybe there's an options field at
+ // the beginning.
+ var b byte
+ inQuote := false
+ var candidateOptions []string
+ optionStart := 0
+ for i, b = range in {
+ isEnd := !inQuote && (b == ' ' || b == '\t')
+ if (b == ',' && !inQuote) || isEnd {
+ if i-optionStart > 0 {
+ candidateOptions = append(candidateOptions, string(in[optionStart:i]))
+ }
+ optionStart = i + 1
+ }
+ if isEnd {
+ break
+ }
+ if b == '"' && (i == 0 || (i > 0 && in[i-1] != '\\')) {
+ inQuote = !inQuote
+ }
+ }
+ for i < len(in) && (in[i] == ' ' || in[i] == '\t') {
+ i++
+ }
+ if i == len(in) {
+ // Invalid line: unmatched quote
+ in = rest
+ continue
+ }
+
+ in = in[i:]
+ i = bytes.IndexAny(in, " \t")
+ if i == -1 {
+ in = rest
+ continue
+ }
+
+ if out, comment, err = parseAuthorizedKey(in[i:]); err == nil {
+ options = candidateOptions
+ return out, comment, options, rest, nil
+ }
+
+ in = rest
+ continue
+ }
+
+ return nil, "", nil, nil, errors.New("ssh: no key found")
+}
+
+// ParsePublicKey parses an SSH public key formatted for use in
+// the SSH wire protocol according to RFC 4253, section 6.6.
+func ParsePublicKey(in []byte) (out PublicKey, err error) {
+ algo, in, ok := parseString(in)
+ if !ok {
+ return nil, errShortRead
+ }
+ var rest []byte
+ out, rest, err = parsePubKey(in, string(algo))
+ if len(rest) > 0 {
+ return nil, errors.New("ssh: trailing junk in public key")
+ }
+
+ return out, err
+}
+
+// MarshalAuthorizedKey serializes key for inclusion in an OpenSSH
+// authorized_keys file. The return value ends with newline.
+func MarshalAuthorizedKey(key PublicKey) []byte {
+ b := &bytes.Buffer{}
+ b.WriteString(key.Type())
+ b.WriteByte(' ')
+ e := base64.NewEncoder(base64.StdEncoding, b)
+ e.Write(key.Marshal())
+ e.Close()
+ b.WriteByte('\n')
+ return b.Bytes()
+}
+
+// PublicKey is an abstraction of different types of public keys.
+type PublicKey interface {
+ // Type returns the key's type, e.g. "ssh-rsa".
+ Type() string
+
+ // Marshal returns the serialized key data in SSH wire format,
+ // with the name prefix.
+ Marshal() []byte
+
+ // Verify that sig is a signature on the given data using this
+ // key. This function will hash the data appropriately first.
+ Verify(data []byte, sig *Signature) error
+}
+
+// CryptoPublicKey, if implemented by a PublicKey,
+// returns the underlying crypto.PublicKey form of the key.
+type CryptoPublicKey interface {
+ CryptoPublicKey() crypto.PublicKey
+}
+
+// A Signer can create signatures that verify against a public key.
+type Signer interface {
+ // PublicKey returns an associated PublicKey instance.
+ PublicKey() PublicKey
+
+ // Sign returns raw signature for the given data. This method
+ // will apply the hash specified for the keytype to the data.
+ Sign(rand io.Reader, data []byte) (*Signature, error)
+}
+
+type rsaPublicKey rsa.PublicKey
+
+func (r *rsaPublicKey) Type() string {
+ return "ssh-rsa"
+}
+
+// parseRSA parses an RSA key according to RFC 4253, section 6.6.
+func parseRSA(in []byte) (out PublicKey, rest []byte, err error) {
+ var w struct {
+ E *big.Int
+ N *big.Int
+ Rest []byte `ssh:"rest"`
+ }
+ if err := Unmarshal(in, &w); err != nil {
+ return nil, nil, err
+ }
+
+ if w.E.BitLen() > 24 {
+ return nil, nil, errors.New("ssh: exponent too large")
+ }
+ e := w.E.Int64()
+ if e < 3 || e&1 == 0 {
+ return nil, nil, errors.New("ssh: incorrect exponent")
+ }
+
+ var key rsa.PublicKey
+ key.E = int(e)
+ key.N = w.N
+ return (*rsaPublicKey)(&key), w.Rest, nil
+}
+
+func (r *rsaPublicKey) Marshal() []byte {
+ e := new(big.Int).SetInt64(int64(r.E))
+ // RSA publickey struct layout should match the struct used by
+ // parseRSACert in the x/crypto/ssh/agent package.
+ wirekey := struct {
+ Name string
+ E *big.Int
+ N *big.Int
+ }{
+ KeyAlgoRSA,
+ e,
+ r.N,
+ }
+ return Marshal(&wirekey)
+}
+
+func (r *rsaPublicKey) Verify(data []byte, sig *Signature) error {
+ if sig.Format != r.Type() {
+ return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, r.Type())
+ }
+ h := crypto.SHA1.New()
+ h.Write(data)
+ digest := h.Sum(nil)
+ return rsa.VerifyPKCS1v15((*rsa.PublicKey)(r), crypto.SHA1, digest, sig.Blob)
+}
+
+func (r *rsaPublicKey) CryptoPublicKey() crypto.PublicKey {
+ return (*rsa.PublicKey)(r)
+}
+
+type dsaPublicKey dsa.PublicKey
+
+func (r *dsaPublicKey) Type() string {
+ return "ssh-dss"
+}
+
+func checkDSAParams(param *dsa.Parameters) error {
+ // SSH specifies FIPS 186-2, which only provided a single size
+ // (1024 bits) DSA key. FIPS 186-3 allows for larger key
+ // sizes, which would confuse SSH.
+ if l := param.P.BitLen(); l != 1024 {
+ return fmt.Errorf("ssh: unsupported DSA key size %d", l)
+ }
+
+ return nil
+}
+
+// parseDSA parses an DSA key according to RFC 4253, section 6.6.
+func parseDSA(in []byte) (out PublicKey, rest []byte, err error) {
+ var w struct {
+ P, Q, G, Y *big.Int
+ Rest []byte `ssh:"rest"`
+ }
+ if err := Unmarshal(in, &w); err != nil {
+ return nil, nil, err
+ }
+
+ param := dsa.Parameters{
+ P: w.P,
+ Q: w.Q,
+ G: w.G,
+ }
+ if err := checkDSAParams(&param); err != nil {
+ return nil, nil, err
+ }
+
+ key := &dsaPublicKey{
+ Parameters: param,
+ Y: w.Y,
+ }
+ return key, w.Rest, nil
+}
+
+func (k *dsaPublicKey) Marshal() []byte {
+ // DSA publickey struct layout should match the struct used by
+ // parseDSACert in the x/crypto/ssh/agent package.
+ w := struct {
+ Name string
+ P, Q, G, Y *big.Int
+ }{
+ k.Type(),
+ k.P,
+ k.Q,
+ k.G,
+ k.Y,
+ }
+
+ return Marshal(&w)
+}
+
+func (k *dsaPublicKey) Verify(data []byte, sig *Signature) error {
+ if sig.Format != k.Type() {
+ return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type())
+ }
+ h := crypto.SHA1.New()
+ h.Write(data)
+ digest := h.Sum(nil)
+
+ // Per RFC 4253, section 6.6,
+ // The value for 'dss_signature_blob' is encoded as a string containing
+ // r, followed by s (which are 160-bit integers, without lengths or
+ // padding, unsigned, and in network byte order).
+ // For DSS purposes, sig.Blob should be exactly 40 bytes in length.
+ if len(sig.Blob) != 40 {
+ return errors.New("ssh: DSA signature parse error")
+ }
+ r := new(big.Int).SetBytes(sig.Blob[:20])
+ s := new(big.Int).SetBytes(sig.Blob[20:])
+ if dsa.Verify((*dsa.PublicKey)(k), digest, r, s) {
+ return nil
+ }
+ return errors.New("ssh: signature did not verify")
+}
+
+func (k *dsaPublicKey) CryptoPublicKey() crypto.PublicKey {
+ return (*dsa.PublicKey)(k)
+}
+
+type dsaPrivateKey struct {
+ *dsa.PrivateKey
+}
+
+func (k *dsaPrivateKey) PublicKey() PublicKey {
+ return (*dsaPublicKey)(&k.PrivateKey.PublicKey)
+}
+
+func (k *dsaPrivateKey) Sign(rand io.Reader, data []byte) (*Signature, error) {
+ h := crypto.SHA1.New()
+ h.Write(data)
+ digest := h.Sum(nil)
+ r, s, err := dsa.Sign(rand, k.PrivateKey, digest)
+ if err != nil {
+ return nil, err
+ }
+
+ sig := make([]byte, 40)
+ rb := r.Bytes()
+ sb := s.Bytes()
+
+ copy(sig[20-len(rb):20], rb)
+ copy(sig[40-len(sb):], sb)
+
+ return &Signature{
+ Format: k.PublicKey().Type(),
+ Blob: sig,
+ }, nil
+}
+
+type ecdsaPublicKey ecdsa.PublicKey
+
+func (key *ecdsaPublicKey) Type() string {
+ return "ecdsa-sha2-" + key.nistID()
+}
+
+func (key *ecdsaPublicKey) nistID() string {
+ switch key.Params().BitSize {
+ case 256:
+ return "nistp256"
+ case 384:
+ return "nistp384"
+ case 521:
+ return "nistp521"
+ }
+ panic("ssh: unsupported ecdsa key size")
+}
+
+type ed25519PublicKey ed25519.PublicKey
+
+func (key ed25519PublicKey) Type() string {
+ return KeyAlgoED25519
+}
+
+func parseED25519(in []byte) (out PublicKey, rest []byte, err error) {
+ var w struct {
+ KeyBytes []byte
+ Rest []byte `ssh:"rest"`
+ }
+
+ if err := Unmarshal(in, &w); err != nil {
+ return nil, nil, err
+ }
+
+ key := ed25519.PublicKey(w.KeyBytes)
+
+ return (ed25519PublicKey)(key), w.Rest, nil
+}
+
+func (key ed25519PublicKey) Marshal() []byte {
+ w := struct {
+ Name string
+ KeyBytes []byte
+ }{
+ KeyAlgoED25519,
+ []byte(key),
+ }
+ return Marshal(&w)
+}
+
+func (key ed25519PublicKey) Verify(b []byte, sig *Signature) error {
+ if sig.Format != key.Type() {
+ return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, key.Type())
+ }
+
+ edKey := (ed25519.PublicKey)(key)
+ if ok := ed25519.Verify(edKey, b, sig.Blob); !ok {
+ return errors.New("ssh: signature did not verify")
+ }
+
+ return nil
+}
+
+func (k ed25519PublicKey) CryptoPublicKey() crypto.PublicKey {
+ return ed25519.PublicKey(k)
+}
+
+func supportedEllipticCurve(curve elliptic.Curve) bool {
+ return curve == elliptic.P256() || curve == elliptic.P384() || curve == elliptic.P521()
+}
+
+// ecHash returns the hash to match the given elliptic curve, see RFC
+// 5656, section 6.2.1
+func ecHash(curve elliptic.Curve) crypto.Hash {
+ bitSize := curve.Params().BitSize
+ switch {
+ case bitSize <= 256:
+ return crypto.SHA256
+ case bitSize <= 384:
+ return crypto.SHA384
+ }
+ return crypto.SHA512
+}
+
+// parseECDSA parses an ECDSA key according to RFC 5656, section 3.1.
+func parseECDSA(in []byte) (out PublicKey, rest []byte, err error) {
+ var w struct {
+ Curve string
+ KeyBytes []byte
+ Rest []byte `ssh:"rest"`
+ }
+
+ if err := Unmarshal(in, &w); err != nil {
+ return nil, nil, err
+ }
+
+ key := new(ecdsa.PublicKey)
+
+ switch w.Curve {
+ case "nistp256":
+ key.Curve = elliptic.P256()
+ case "nistp384":
+ key.Curve = elliptic.P384()
+ case "nistp521":
+ key.Curve = elliptic.P521()
+ default:
+ return nil, nil, errors.New("ssh: unsupported curve")
+ }
+
+ key.X, key.Y = elliptic.Unmarshal(key.Curve, w.KeyBytes)
+ if key.X == nil || key.Y == nil {
+ return nil, nil, errors.New("ssh: invalid curve point")
+ }
+ return (*ecdsaPublicKey)(key), w.Rest, nil
+}
+
+func (key *ecdsaPublicKey) Marshal() []byte {
+ // See RFC 5656, section 3.1.
+ keyBytes := elliptic.Marshal(key.Curve, key.X, key.Y)
+ // ECDSA publickey struct layout should match the struct used by
+ // parseECDSACert in the x/crypto/ssh/agent package.
+ w := struct {
+ Name string
+ ID string
+ Key []byte
+ }{
+ key.Type(),
+ key.nistID(),
+ keyBytes,
+ }
+
+ return Marshal(&w)
+}
+
+func (key *ecdsaPublicKey) Verify(data []byte, sig *Signature) error {
+ if sig.Format != key.Type() {
+ return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, key.Type())
+ }
+
+ h := ecHash(key.Curve).New()
+ h.Write(data)
+ digest := h.Sum(nil)
+
+ // Per RFC 5656, section 3.1.2,
+ // The ecdsa_signature_blob value has the following specific encoding:
+ // mpint r
+ // mpint s
+ var ecSig struct {
+ R *big.Int
+ S *big.Int
+ }
+
+ if err := Unmarshal(sig.Blob, &ecSig); err != nil {
+ return err
+ }
+
+ if ecdsa.Verify((*ecdsa.PublicKey)(key), digest, ecSig.R, ecSig.S) {
+ return nil
+ }
+ return errors.New("ssh: signature did not verify")
+}
+
+func (k *ecdsaPublicKey) CryptoPublicKey() crypto.PublicKey {
+ return (*ecdsa.PublicKey)(k)
+}
+
+// NewSignerFromKey takes an *rsa.PrivateKey, *dsa.PrivateKey,
+// *ecdsa.PrivateKey or any other crypto.Signer and returns a
+// corresponding Signer instance. ECDSA keys must use P-256, P-384 or
+// P-521. DSA keys must use parameter size L1024N160.
+func NewSignerFromKey(key interface{}) (Signer, error) {
+ switch key := key.(type) {
+ case crypto.Signer:
+ return NewSignerFromSigner(key)
+ case *dsa.PrivateKey:
+ return newDSAPrivateKey(key)
+ default:
+ return nil, fmt.Errorf("ssh: unsupported key type %T", key)
+ }
+}
+
+func newDSAPrivateKey(key *dsa.PrivateKey) (Signer, error) {
+ if err := checkDSAParams(&key.PublicKey.Parameters); err != nil {
+ return nil, err
+ }
+
+ return &dsaPrivateKey{key}, nil
+}
+
+type wrappedSigner struct {
+ signer crypto.Signer
+ pubKey PublicKey
+}
+
+// NewSignerFromSigner takes any crypto.Signer implementation and
+// returns a corresponding Signer interface. This can be used, for
+// example, with keys kept in hardware modules.
+func NewSignerFromSigner(signer crypto.Signer) (Signer, error) {
+ pubKey, err := NewPublicKey(signer.Public())
+ if err != nil {
+ return nil, err
+ }
+
+ return &wrappedSigner{signer, pubKey}, nil
+}
+
+func (s *wrappedSigner) PublicKey() PublicKey {
+ return s.pubKey
+}
+
+func (s *wrappedSigner) Sign(rand io.Reader, data []byte) (*Signature, error) {
+ var hashFunc crypto.Hash
+
+ switch key := s.pubKey.(type) {
+ case *rsaPublicKey, *dsaPublicKey:
+ hashFunc = crypto.SHA1
+ case *ecdsaPublicKey:
+ hashFunc = ecHash(key.Curve)
+ case ed25519PublicKey:
+ default:
+ return nil, fmt.Errorf("ssh: unsupported key type %T", key)
+ }
+
+ var digest []byte
+ if hashFunc != 0 {
+ h := hashFunc.New()
+ h.Write(data)
+ digest = h.Sum(nil)
+ } else {
+ digest = data
+ }
+
+ signature, err := s.signer.Sign(rand, digest, hashFunc)
+ if err != nil {
+ return nil, err
+ }
+
+ // crypto.Signer.Sign is expected to return an ASN.1-encoded signature
+ // for ECDSA and DSA, but that's not the encoding expected by SSH, so
+ // re-encode.
+ switch s.pubKey.(type) {
+ case *ecdsaPublicKey, *dsaPublicKey:
+ type asn1Signature struct {
+ R, S *big.Int
+ }
+ asn1Sig := new(asn1Signature)
+ _, err := asn1.Unmarshal(signature, asn1Sig)
+ if err != nil {
+ return nil, err
+ }
+
+ switch s.pubKey.(type) {
+ case *ecdsaPublicKey:
+ signature = Marshal(asn1Sig)
+
+ case *dsaPublicKey:
+ signature = make([]byte, 40)
+ r := asn1Sig.R.Bytes()
+ s := asn1Sig.S.Bytes()
+ copy(signature[20-len(r):20], r)
+ copy(signature[40-len(s):40], s)
+ }
+ }
+
+ return &Signature{
+ Format: s.pubKey.Type(),
+ Blob: signature,
+ }, nil
+}
+
+// NewPublicKey takes an *rsa.PublicKey, *dsa.PublicKey, *ecdsa.PublicKey,
+// or ed25519.PublicKey returns a corresponding PublicKey instance.
+// ECDSA keys must use P-256, P-384 or P-521.
+func NewPublicKey(key interface{}) (PublicKey, error) {
+ switch key := key.(type) {
+ case *rsa.PublicKey:
+ return (*rsaPublicKey)(key), nil
+ case *ecdsa.PublicKey:
+ if !supportedEllipticCurve(key.Curve) {
+ return nil, errors.New("ssh: only P-256, P-384 and P-521 EC keys are supported.")
+ }
+ return (*ecdsaPublicKey)(key), nil
+ case *dsa.PublicKey:
+ return (*dsaPublicKey)(key), nil
+ case ed25519.PublicKey:
+ return (ed25519PublicKey)(key), nil
+ default:
+ return nil, fmt.Errorf("ssh: unsupported key type %T", key)
+ }
+}
+
+// ParsePrivateKey returns a Signer from a PEM encoded private key. It supports
+// the same keys as ParseRawPrivateKey.
+func ParsePrivateKey(pemBytes []byte) (Signer, error) {
+ key, err := ParseRawPrivateKey(pemBytes)
+ if err != nil {
+ return nil, err
+ }
+
+ return NewSignerFromKey(key)
+}
+
+// ParsePrivateKeyWithPassphrase returns a Signer from a PEM encoded private
+// key and passphrase. It supports the same keys as
+// ParseRawPrivateKeyWithPassphrase.
+func ParsePrivateKeyWithPassphrase(pemBytes, passPhrase []byte) (Signer, error) {
+ key, err := ParseRawPrivateKeyWithPassphrase(pemBytes, passPhrase)
+ if err != nil {
+ return nil, err
+ }
+
+ return NewSignerFromKey(key)
+}
+
+// encryptedBlock tells whether a private key is
+// encrypted by examining its Proc-Type header
+// for a mention of ENCRYPTED
+// according to RFC 1421 Section 4.6.1.1.
+func encryptedBlock(block *pem.Block) bool {
+ return strings.Contains(block.Headers["Proc-Type"], "ENCRYPTED")
+}
+
+// ParseRawPrivateKey returns a private key from a PEM encoded private key. It
+// supports RSA (PKCS#1), DSA (OpenSSL), and ECDSA private keys.
+func ParseRawPrivateKey(pemBytes []byte) (interface{}, error) {
+ block, _ := pem.Decode(pemBytes)
+ if block == nil {
+ return nil, errors.New("ssh: no key found")
+ }
+
+ if encryptedBlock(block) {
+ return nil, errors.New("ssh: cannot decode encrypted private keys")
+ }
+
+ switch block.Type {
+ case "RSA PRIVATE KEY":
+ return x509.ParsePKCS1PrivateKey(block.Bytes)
+ case "EC PRIVATE KEY":
+ return x509.ParseECPrivateKey(block.Bytes)
+ case "DSA PRIVATE KEY":
+ return ParseDSAPrivateKey(block.Bytes)
+ case "OPENSSH PRIVATE KEY":
+ return parseOpenSSHPrivateKey(block.Bytes)
+ default:
+ return nil, fmt.Errorf("ssh: unsupported key type %q", block.Type)
+ }
+}
+
+// ParseRawPrivateKeyWithPassphrase returns a private key decrypted with
+// passphrase from a PEM encoded private key. If wrong passphrase, return
+// x509.IncorrectPasswordError.
+func ParseRawPrivateKeyWithPassphrase(pemBytes, passPhrase []byte) (interface{}, error) {
+ block, _ := pem.Decode(pemBytes)
+ if block == nil {
+ return nil, errors.New("ssh: no key found")
+ }
+ buf := block.Bytes
+
+ if encryptedBlock(block) {
+ if x509.IsEncryptedPEMBlock(block) {
+ var err error
+ buf, err = x509.DecryptPEMBlock(block, passPhrase)
+ if err != nil {
+ if err == x509.IncorrectPasswordError {
+ return nil, err
+ }
+ return nil, fmt.Errorf("ssh: cannot decode encrypted private keys: %v", err)
+ }
+ }
+ }
+
+ switch block.Type {
+ case "RSA PRIVATE KEY":
+ return x509.ParsePKCS1PrivateKey(buf)
+ case "EC PRIVATE KEY":
+ return x509.ParseECPrivateKey(buf)
+ case "DSA PRIVATE KEY":
+ return ParseDSAPrivateKey(buf)
+ case "OPENSSH PRIVATE KEY":
+ return parseOpenSSHPrivateKey(buf)
+ default:
+ return nil, fmt.Errorf("ssh: unsupported key type %q", block.Type)
+ }
+}
+
+// ParseDSAPrivateKey returns a DSA private key from its ASN.1 DER encoding, as
+// specified by the OpenSSL DSA man page.
+func ParseDSAPrivateKey(der []byte) (*dsa.PrivateKey, error) {
+ var k struct {
+ Version int
+ P *big.Int
+ Q *big.Int
+ G *big.Int
+ Pub *big.Int
+ Priv *big.Int
+ }
+ rest, err := asn1.Unmarshal(der, &k)
+ if err != nil {
+ return nil, errors.New("ssh: failed to parse DSA key: " + err.Error())
+ }
+ if len(rest) > 0 {
+ return nil, errors.New("ssh: garbage after DSA key")
+ }
+
+ return &dsa.PrivateKey{
+ PublicKey: dsa.PublicKey{
+ Parameters: dsa.Parameters{
+ P: k.P,
+ Q: k.Q,
+ G: k.G,
+ },
+ Y: k.Pub,
+ },
+ X: k.Priv,
+ }, nil
+}
+
+// Implemented based on the documentation at
+// https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key
+func parseOpenSSHPrivateKey(key []byte) (crypto.PrivateKey, error) {
+ magic := append([]byte("openssh-key-v1"), 0)
+ if !bytes.Equal(magic, key[0:len(magic)]) {
+ return nil, errors.New("ssh: invalid openssh private key format")
+ }
+ remaining := key[len(magic):]
+
+ var w struct {
+ CipherName string
+ KdfName string
+ KdfOpts string
+ NumKeys uint32
+ PubKey []byte
+ PrivKeyBlock []byte
+ }
+
+ if err := Unmarshal(remaining, &w); err != nil {
+ return nil, err
+ }
+
+ if w.KdfName != "none" || w.CipherName != "none" {
+ return nil, errors.New("ssh: cannot decode encrypted private keys")
+ }
+
+ pk1 := struct {
+ Check1 uint32
+ Check2 uint32
+ Keytype string
+ Rest []byte `ssh:"rest"`
+ }{}
+
+ if err := Unmarshal(w.PrivKeyBlock, &pk1); err != nil {
+ return nil, err
+ }
+
+ if pk1.Check1 != pk1.Check2 {
+ return nil, errors.New("ssh: checkint mismatch")
+ }
+
+ // we only handle ed25519 and rsa keys currently
+ switch pk1.Keytype {
+ case KeyAlgoRSA:
+ // https://github.com/openssh/openssh-portable/blob/master/sshkey.c#L2760-L2773
+ key := struct {
+ N *big.Int
+ E *big.Int
+ D *big.Int
+ Iqmp *big.Int
+ P *big.Int
+ Q *big.Int
+ Comment string
+ Pad []byte `ssh:"rest"`
+ }{}
+
+ if err := Unmarshal(pk1.Rest, &key); err != nil {
+ return nil, err
+ }
+
+ for i, b := range key.Pad {
+ if int(b) != i+1 {
+ return nil, errors.New("ssh: padding not as expected")
+ }
+ }
+
+ pk := &rsa.PrivateKey{
+ PublicKey: rsa.PublicKey{
+ N: key.N,
+ E: int(key.E.Int64()),
+ },
+ D: key.D,
+ Primes: []*big.Int{key.P, key.Q},
+ }
+
+ if err := pk.Validate(); err != nil {
+ return nil, err
+ }
+
+ pk.Precompute()
+
+ return pk, nil
+ case KeyAlgoED25519:
+ key := struct {
+ Pub []byte
+ Priv []byte
+ Comment string
+ Pad []byte `ssh:"rest"`
+ }{}
+
+ if err := Unmarshal(pk1.Rest, &key); err != nil {
+ return nil, err
+ }
+
+ if len(key.Priv) != ed25519.PrivateKeySize {
+ return nil, errors.New("ssh: private key unexpected length")
+ }
+
+ for i, b := range key.Pad {
+ if int(b) != i+1 {
+ return nil, errors.New("ssh: padding not as expected")
+ }
+ }
+
+ pk := ed25519.PrivateKey(make([]byte, ed25519.PrivateKeySize))
+ copy(pk, key.Priv)
+ return &pk, nil
+ default:
+ return nil, errors.New("ssh: unhandled key type")
+ }
+}
+
+// FingerprintLegacyMD5 returns the user presentation of the key's
+// fingerprint as described by RFC 4716 section 4.
+func FingerprintLegacyMD5(pubKey PublicKey) string {
+ md5sum := md5.Sum(pubKey.Marshal())
+ hexarray := make([]string, len(md5sum))
+ for i, c := range md5sum {
+ hexarray[i] = hex.EncodeToString([]byte{c})
+ }
+ return strings.Join(hexarray, ":")
+}
+
+// FingerprintSHA256 returns the user presentation of the key's
+// fingerprint as unpadded base64 encoded sha256 hash.
+// This format was introduced from OpenSSH 6.8.
+// https://www.openssh.com/txt/release-6.8
+// https://tools.ietf.org/html/rfc4648#section-3.2 (unpadded base64 encoding)
+func FingerprintSHA256(pubKey PublicKey) string {
+ sha256sum := sha256.Sum256(pubKey.Marshal())
+ hash := base64.RawStdEncoding.EncodeToString(sha256sum[:])
+ return "SHA256:" + hash
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/keys_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/keys_test.go
new file mode 100644
index 000000000..20ab954e2
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/keys_test.go
@@ -0,0 +1,500 @@
+// Copyright 2014 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 ssh
+
+import (
+ "bytes"
+ "crypto/dsa"
+ "crypto/ecdsa"
+ "crypto/elliptic"
+ "crypto/rand"
+ "crypto/rsa"
+ "crypto/x509"
+ "encoding/base64"
+ "fmt"
+ "reflect"
+ "strings"
+ "testing"
+
+ "golang.org/x/crypto/ed25519"
+ "golang.org/x/crypto/ssh/testdata"
+)
+
+func rawKey(pub PublicKey) interface{} {
+ switch k := pub.(type) {
+ case *rsaPublicKey:
+ return (*rsa.PublicKey)(k)
+ case *dsaPublicKey:
+ return (*dsa.PublicKey)(k)
+ case *ecdsaPublicKey:
+ return (*ecdsa.PublicKey)(k)
+ case ed25519PublicKey:
+ return (ed25519.PublicKey)(k)
+ case *Certificate:
+ return k
+ }
+ panic("unknown key type")
+}
+
+func TestKeyMarshalParse(t *testing.T) {
+ for _, priv := range testSigners {
+ pub := priv.PublicKey()
+ roundtrip, err := ParsePublicKey(pub.Marshal())
+ if err != nil {
+ t.Errorf("ParsePublicKey(%T): %v", pub, err)
+ }
+
+ k1 := rawKey(pub)
+ k2 := rawKey(roundtrip)
+
+ if !reflect.DeepEqual(k1, k2) {
+ t.Errorf("got %#v in roundtrip, want %#v", k2, k1)
+ }
+ }
+}
+
+func TestUnsupportedCurves(t *testing.T) {
+ raw, err := ecdsa.GenerateKey(elliptic.P224(), rand.Reader)
+ if err != nil {
+ t.Fatalf("GenerateKey: %v", err)
+ }
+
+ if _, err = NewSignerFromKey(raw); err == nil || !strings.Contains(err.Error(), "only P-256") {
+ t.Fatalf("NewPrivateKey should not succeed with P-224, got: %v", err)
+ }
+
+ if _, err = NewPublicKey(&raw.PublicKey); err == nil || !strings.Contains(err.Error(), "only P-256") {
+ t.Fatalf("NewPublicKey should not succeed with P-224, got: %v", err)
+ }
+}
+
+func TestNewPublicKey(t *testing.T) {
+ for _, k := range testSigners {
+ raw := rawKey(k.PublicKey())
+ // Skip certificates, as NewPublicKey does not support them.
+ if _, ok := raw.(*Certificate); ok {
+ continue
+ }
+ pub, err := NewPublicKey(raw)
+ if err != nil {
+ t.Errorf("NewPublicKey(%#v): %v", raw, err)
+ }
+ if !reflect.DeepEqual(k.PublicKey(), pub) {
+ t.Errorf("NewPublicKey(%#v) = %#v, want %#v", raw, pub, k.PublicKey())
+ }
+ }
+}
+
+func TestKeySignVerify(t *testing.T) {
+ for _, priv := range testSigners {
+ pub := priv.PublicKey()
+
+ data := []byte("sign me")
+ sig, err := priv.Sign(rand.Reader, data)
+ if err != nil {
+ t.Fatalf("Sign(%T): %v", priv, err)
+ }
+
+ if err := pub.Verify(data, sig); err != nil {
+ t.Errorf("publicKey.Verify(%T): %v", priv, err)
+ }
+ sig.Blob[5]++
+ if err := pub.Verify(data, sig); err == nil {
+ t.Errorf("publicKey.Verify on broken sig did not fail")
+ }
+ }
+}
+
+func TestParseRSAPrivateKey(t *testing.T) {
+ key := testPrivateKeys["rsa"]
+
+ rsa, ok := key.(*rsa.PrivateKey)
+ if !ok {
+ t.Fatalf("got %T, want *rsa.PrivateKey", rsa)
+ }
+
+ if err := rsa.Validate(); err != nil {
+ t.Errorf("Validate: %v", err)
+ }
+}
+
+func TestParseECPrivateKey(t *testing.T) {
+ key := testPrivateKeys["ecdsa"]
+
+ ecKey, ok := key.(*ecdsa.PrivateKey)
+ if !ok {
+ t.Fatalf("got %T, want *ecdsa.PrivateKey", ecKey)
+ }
+
+ if !validateECPublicKey(ecKey.Curve, ecKey.X, ecKey.Y) {
+ t.Fatalf("public key does not validate.")
+ }
+}
+
+// See Issue https://github.com/golang/go/issues/6650.
+func TestParseEncryptedPrivateKeysFails(t *testing.T) {
+ const wantSubstring = "encrypted"
+ for i, tt := range testdata.PEMEncryptedKeys {
+ _, err := ParsePrivateKey(tt.PEMBytes)
+ if err == nil {
+ t.Errorf("#%d key %s: ParsePrivateKey successfully parsed, expected an error", i, tt.Name)
+ continue
+ }
+
+ if !strings.Contains(err.Error(), wantSubstring) {
+ t.Errorf("#%d key %s: got error %q, want substring %q", i, tt.Name, err, wantSubstring)
+ }
+ }
+}
+
+// Parse encrypted private keys with passphrase
+func TestParseEncryptedPrivateKeysWithPassphrase(t *testing.T) {
+ data := []byte("sign me")
+ for _, tt := range testdata.PEMEncryptedKeys {
+ s, err := ParsePrivateKeyWithPassphrase(tt.PEMBytes, []byte(tt.EncryptionKey))
+ if err != nil {
+ t.Fatalf("ParsePrivateKeyWithPassphrase returned error: %s", err)
+ continue
+ }
+ sig, err := s.Sign(rand.Reader, data)
+ if err != nil {
+ t.Fatalf("dsa.Sign: %v", err)
+ }
+ if err := s.PublicKey().Verify(data, sig); err != nil {
+ t.Errorf("Verify failed: %v", err)
+ }
+ }
+
+ tt := testdata.PEMEncryptedKeys[0]
+ _, err := ParsePrivateKeyWithPassphrase(tt.PEMBytes, []byte("incorrect"))
+ if err != x509.IncorrectPasswordError {
+ t.Fatalf("got %v want IncorrectPasswordError", err)
+ }
+}
+
+func TestParseDSA(t *testing.T) {
+ // We actually exercise the ParsePrivateKey codepath here, as opposed to
+ // using the ParseRawPrivateKey+NewSignerFromKey path that testdata_test.go
+ // uses.
+ s, err := ParsePrivateKey(testdata.PEMBytes["dsa"])
+ if err != nil {
+ t.Fatalf("ParsePrivateKey returned error: %s", err)
+ }
+
+ data := []byte("sign me")
+ sig, err := s.Sign(rand.Reader, data)
+ if err != nil {
+ t.Fatalf("dsa.Sign: %v", err)
+ }
+
+ if err := s.PublicKey().Verify(data, sig); err != nil {
+ t.Errorf("Verify failed: %v", err)
+ }
+}
+
+// Tests for authorized_keys parsing.
+
+// getTestKey returns a public key, and its base64 encoding.
+func getTestKey() (PublicKey, string) {
+ k := testPublicKeys["rsa"]
+
+ b := &bytes.Buffer{}
+ e := base64.NewEncoder(base64.StdEncoding, b)
+ e.Write(k.Marshal())
+ e.Close()
+
+ return k, b.String()
+}
+
+func TestMarshalParsePublicKey(t *testing.T) {
+ pub, pubSerialized := getTestKey()
+ line := fmt.Sprintf("%s %s user@host", pub.Type(), pubSerialized)
+
+ authKeys := MarshalAuthorizedKey(pub)
+ actualFields := strings.Fields(string(authKeys))
+ if len(actualFields) == 0 {
+ t.Fatalf("failed authKeys: %v", authKeys)
+ }
+
+ // drop the comment
+ expectedFields := strings.Fields(line)[0:2]
+
+ if !reflect.DeepEqual(actualFields, expectedFields) {
+ t.Errorf("got %v, expected %v", actualFields, expectedFields)
+ }
+
+ actPub, _, _, _, err := ParseAuthorizedKey([]byte(line))
+ if err != nil {
+ t.Fatalf("cannot parse %v: %v", line, err)
+ }
+ if !reflect.DeepEqual(actPub, pub) {
+ t.Errorf("got %v, expected %v", actPub, pub)
+ }
+}
+
+type authResult struct {
+ pubKey PublicKey
+ options []string
+ comments string
+ rest string
+ ok bool
+}
+
+func testAuthorizedKeys(t *testing.T, authKeys []byte, expected []authResult) {
+ rest := authKeys
+ var values []authResult
+ for len(rest) > 0 {
+ var r authResult
+ var err error
+ r.pubKey, r.comments, r.options, rest, err = ParseAuthorizedKey(rest)
+ r.ok = (err == nil)
+ t.Log(err)
+ r.rest = string(rest)
+ values = append(values, r)
+ }
+
+ if !reflect.DeepEqual(values, expected) {
+ t.Errorf("got %#v, expected %#v", values, expected)
+ }
+}
+
+func TestAuthorizedKeyBasic(t *testing.T) {
+ pub, pubSerialized := getTestKey()
+ line := "ssh-rsa " + pubSerialized + " user@host"
+ testAuthorizedKeys(t, []byte(line),
+ []authResult{
+ {pub, nil, "user@host", "", true},
+ })
+}
+
+func TestAuth(t *testing.T) {
+ pub, pubSerialized := getTestKey()
+ authWithOptions := []string{
+ `# comments to ignore before any keys...`,
+ ``,
+ `env="HOME=/home/root",no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host`,
+ `# comments to ignore, along with a blank line`,
+ ``,
+ `env="HOME=/home/root2" ssh-rsa ` + pubSerialized + ` user2@host2`,
+ ``,
+ `# more comments, plus a invalid entry`,
+ `ssh-rsa data-that-will-not-parse user@host3`,
+ }
+ for _, eol := range []string{"\n", "\r\n"} {
+ authOptions := strings.Join(authWithOptions, eol)
+ rest2 := strings.Join(authWithOptions[3:], eol)
+ rest3 := strings.Join(authWithOptions[6:], eol)
+ testAuthorizedKeys(t, []byte(authOptions), []authResult{
+ {pub, []string{`env="HOME=/home/root"`, "no-port-forwarding"}, "user@host", rest2, true},
+ {pub, []string{`env="HOME=/home/root2"`}, "user2@host2", rest3, true},
+ {nil, nil, "", "", false},
+ })
+ }
+}
+
+func TestAuthWithQuotedSpaceInEnv(t *testing.T) {
+ pub, pubSerialized := getTestKey()
+ authWithQuotedSpaceInEnv := []byte(`env="HOME=/home/root dir",no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host`)
+ testAuthorizedKeys(t, []byte(authWithQuotedSpaceInEnv), []authResult{
+ {pub, []string{`env="HOME=/home/root dir"`, "no-port-forwarding"}, "user@host", "", true},
+ })
+}
+
+func TestAuthWithQuotedCommaInEnv(t *testing.T) {
+ pub, pubSerialized := getTestKey()
+ authWithQuotedCommaInEnv := []byte(`env="HOME=/home/root,dir",no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host`)
+ testAuthorizedKeys(t, []byte(authWithQuotedCommaInEnv), []authResult{
+ {pub, []string{`env="HOME=/home/root,dir"`, "no-port-forwarding"}, "user@host", "", true},
+ })
+}
+
+func TestAuthWithQuotedQuoteInEnv(t *testing.T) {
+ pub, pubSerialized := getTestKey()
+ authWithQuotedQuoteInEnv := []byte(`env="HOME=/home/\"root dir",no-port-forwarding` + "\t" + `ssh-rsa` + "\t" + pubSerialized + ` user@host`)
+ authWithDoubleQuotedQuote := []byte(`no-port-forwarding,env="HOME=/home/ \"root dir\"" ssh-rsa ` + pubSerialized + "\t" + `user@host`)
+ testAuthorizedKeys(t, []byte(authWithQuotedQuoteInEnv), []authResult{
+ {pub, []string{`env="HOME=/home/\"root dir"`, "no-port-forwarding"}, "user@host", "", true},
+ })
+
+ testAuthorizedKeys(t, []byte(authWithDoubleQuotedQuote), []authResult{
+ {pub, []string{"no-port-forwarding", `env="HOME=/home/ \"root dir\""`}, "user@host", "", true},
+ })
+}
+
+func TestAuthWithInvalidSpace(t *testing.T) {
+ _, pubSerialized := getTestKey()
+ authWithInvalidSpace := []byte(`env="HOME=/home/root dir", no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host
+#more to follow but still no valid keys`)
+ testAuthorizedKeys(t, []byte(authWithInvalidSpace), []authResult{
+ {nil, nil, "", "", false},
+ })
+}
+
+func TestAuthWithMissingQuote(t *testing.T) {
+ pub, pubSerialized := getTestKey()
+ authWithMissingQuote := []byte(`env="HOME=/home/root,no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host
+env="HOME=/home/root",shared-control ssh-rsa ` + pubSerialized + ` user@host`)
+
+ testAuthorizedKeys(t, []byte(authWithMissingQuote), []authResult{
+ {pub, []string{`env="HOME=/home/root"`, `shared-control`}, "user@host", "", true},
+ })
+}
+
+func TestInvalidEntry(t *testing.T) {
+ authInvalid := []byte(`ssh-rsa`)
+ _, _, _, _, err := ParseAuthorizedKey(authInvalid)
+ if err == nil {
+ t.Errorf("got valid entry for %q", authInvalid)
+ }
+}
+
+var knownHostsParseTests = []struct {
+ input string
+ err string
+
+ marker string
+ comment string
+ hosts []string
+ rest string
+}{
+ {
+ "",
+ "EOF",
+
+ "", "", nil, "",
+ },
+ {
+ "# Just a comment",
+ "EOF",
+
+ "", "", nil, "",
+ },
+ {
+ " \t ",
+ "EOF",
+
+ "", "", nil, "",
+ },
+ {
+ "localhost ssh-rsa {RSAPUB}",
+ "",
+
+ "", "", []string{"localhost"}, "",
+ },
+ {
+ "localhost\tssh-rsa {RSAPUB}",
+ "",
+
+ "", "", []string{"localhost"}, "",
+ },
+ {
+ "localhost\tssh-rsa {RSAPUB}\tcomment comment",
+ "",
+
+ "", "comment comment", []string{"localhost"}, "",
+ },
+ {
+ "localhost\tssh-rsa {RSAPUB}\tcomment comment\n",
+ "",
+
+ "", "comment comment", []string{"localhost"}, "",
+ },
+ {
+ "localhost\tssh-rsa {RSAPUB}\tcomment comment\r\n",
+ "",
+
+ "", "comment comment", []string{"localhost"}, "",
+ },
+ {
+ "localhost\tssh-rsa {RSAPUB}\tcomment comment\r\nnext line",
+ "",
+
+ "", "comment comment", []string{"localhost"}, "next line",
+ },
+ {
+ "localhost,[host2:123]\tssh-rsa {RSAPUB}\tcomment comment",
+ "",
+
+ "", "comment comment", []string{"localhost", "[host2:123]"}, "",
+ },
+ {
+ "@marker \tlocalhost,[host2:123]\tssh-rsa {RSAPUB}",
+ "",
+
+ "marker", "", []string{"localhost", "[host2:123]"}, "",
+ },
+ {
+ "@marker \tlocalhost,[host2:123]\tssh-rsa aabbccdd",
+ "short read",
+
+ "", "", nil, "",
+ },
+}
+
+func TestKnownHostsParsing(t *testing.T) {
+ rsaPub, rsaPubSerialized := getTestKey()
+
+ for i, test := range knownHostsParseTests {
+ var expectedKey PublicKey
+ const rsaKeyToken = "{RSAPUB}"
+
+ input := test.input
+ if strings.Contains(input, rsaKeyToken) {
+ expectedKey = rsaPub
+ input = strings.Replace(test.input, rsaKeyToken, rsaPubSerialized, -1)
+ }
+
+ marker, hosts, pubKey, comment, rest, err := ParseKnownHosts([]byte(input))
+ if err != nil {
+ if len(test.err) == 0 {
+ t.Errorf("#%d: unexpectedly failed with %q", i, err)
+ } else if !strings.Contains(err.Error(), test.err) {
+ t.Errorf("#%d: expected error containing %q, but got %q", i, test.err, err)
+ }
+ continue
+ } else if len(test.err) != 0 {
+ t.Errorf("#%d: succeeded but expected error including %q", i, test.err)
+ continue
+ }
+
+ if !reflect.DeepEqual(expectedKey, pubKey) {
+ t.Errorf("#%d: expected key %#v, but got %#v", i, expectedKey, pubKey)
+ }
+
+ if marker != test.marker {
+ t.Errorf("#%d: expected marker %q, but got %q", i, test.marker, marker)
+ }
+
+ if comment != test.comment {
+ t.Errorf("#%d: expected comment %q, but got %q", i, test.comment, comment)
+ }
+
+ if !reflect.DeepEqual(test.hosts, hosts) {
+ t.Errorf("#%d: expected hosts %#v, but got %#v", i, test.hosts, hosts)
+ }
+
+ if rest := string(rest); rest != test.rest {
+ t.Errorf("#%d: expected remaining input to be %q, but got %q", i, test.rest, rest)
+ }
+ }
+}
+
+func TestFingerprintLegacyMD5(t *testing.T) {
+ pub, _ := getTestKey()
+ fingerprint := FingerprintLegacyMD5(pub)
+ want := "fb:61:6d:1a:e3:f0:95:45:3c:a0:79:be:4a:93:63:66" // ssh-keygen -lf -E md5 rsa
+ if fingerprint != want {
+ t.Errorf("got fingerprint %q want %q", fingerprint, want)
+ }
+}
+
+func TestFingerprintSHA256(t *testing.T) {
+ pub, _ := getTestKey()
+ fingerprint := FingerprintSHA256(pub)
+ want := "SHA256:Anr3LjZK8YVpjrxu79myrW9Hrb/wpcMNpVvTq/RcBm8" // ssh-keygen -lf rsa
+ if fingerprint != want {
+ t.Errorf("got fingerprint %q want %q", fingerprint, want)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts.go
new file mode 100644
index 000000000..ea92b2983
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts.go
@@ -0,0 +1,546 @@
+// 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 knownhosts implements a parser for the OpenSSH
+// known_hosts host key database.
+package knownhosts
+
+import (
+ "bufio"
+ "bytes"
+ "crypto/hmac"
+ "crypto/rand"
+ "crypto/sha1"
+ "encoding/base64"
+ "errors"
+ "fmt"
+ "io"
+ "net"
+ "os"
+ "strings"
+
+ "golang.org/x/crypto/ssh"
+)
+
+// See the sshd manpage
+// (http://man.openbsd.org/sshd#SSH_KNOWN_HOSTS_FILE_FORMAT) for
+// background.
+
+type addr struct{ host, port string }
+
+func (a *addr) String() string {
+ h := a.host
+ if strings.Contains(h, ":") {
+ h = "[" + h + "]"
+ }
+ return h + ":" + a.port
+}
+
+type matcher interface {
+ match([]addr) bool
+}
+
+type hostPattern struct {
+ negate bool
+ addr addr
+}
+
+func (p *hostPattern) String() string {
+ n := ""
+ if p.negate {
+ n = "!"
+ }
+
+ return n + p.addr.String()
+}
+
+type hostPatterns []hostPattern
+
+func (ps hostPatterns) match(addrs []addr) bool {
+ matched := false
+ for _, p := range ps {
+ for _, a := range addrs {
+ m := p.match(a)
+ if !m {
+ continue
+ }
+ if p.negate {
+ return false
+ }
+ matched = true
+ }
+ }
+ return matched
+}
+
+// See
+// https://android.googlesource.com/platform/external/openssh/+/ab28f5495c85297e7a597c1ba62e996416da7c7e/addrmatch.c
+// The matching of * has no regard for separators, unlike filesystem globs
+func wildcardMatch(pat []byte, str []byte) bool {
+ for {
+ if len(pat) == 0 {
+ return len(str) == 0
+ }
+ if len(str) == 0 {
+ return false
+ }
+
+ if pat[0] == '*' {
+ if len(pat) == 1 {
+ return true
+ }
+
+ for j := range str {
+ if wildcardMatch(pat[1:], str[j:]) {
+ return true
+ }
+ }
+ return false
+ }
+
+ if pat[0] == '?' || pat[0] == str[0] {
+ pat = pat[1:]
+ str = str[1:]
+ } else {
+ return false
+ }
+ }
+}
+
+func (l *hostPattern) match(a addr) bool {
+ return wildcardMatch([]byte(l.addr.host), []byte(a.host)) && l.addr.port == a.port
+}
+
+type keyDBLine struct {
+ cert bool
+ matcher matcher
+ knownKey KnownKey
+}
+
+func serialize(k ssh.PublicKey) string {
+ return k.Type() + " " + base64.StdEncoding.EncodeToString(k.Marshal())
+}
+
+func (l *keyDBLine) match(addrs []addr) bool {
+ return l.matcher.match(addrs)
+}
+
+type hostKeyDB struct {
+ // Serialized version of revoked keys
+ revoked map[string]*KnownKey
+ lines []keyDBLine
+}
+
+func newHostKeyDB() *hostKeyDB {
+ db := &hostKeyDB{
+ revoked: make(map[string]*KnownKey),
+ }
+
+ return db
+}
+
+func keyEq(a, b ssh.PublicKey) bool {
+ return bytes.Equal(a.Marshal(), b.Marshal())
+}
+
+// IsAuthorityForHost can be used as a callback in ssh.CertChecker
+func (db *hostKeyDB) IsHostAuthority(remote ssh.PublicKey, address string) bool {
+ h, p, err := net.SplitHostPort(address)
+ if err != nil {
+ return false
+ }
+ a := addr{host: h, port: p}
+
+ for _, l := range db.lines {
+ if l.cert && keyEq(l.knownKey.Key, remote) && l.match([]addr{a}) {
+ return true
+ }
+ }
+ return false
+}
+
+// IsRevoked can be used as a callback in ssh.CertChecker
+func (db *hostKeyDB) IsRevoked(key *ssh.Certificate) bool {
+ _, ok := db.revoked[string(key.Marshal())]
+ return ok
+}
+
+const markerCert = "@cert-authority"
+const markerRevoked = "@revoked"
+
+func nextWord(line []byte) (string, []byte) {
+ i := bytes.IndexAny(line, "\t ")
+ if i == -1 {
+ return string(line), nil
+ }
+
+ return string(line[:i]), bytes.TrimSpace(line[i:])
+}
+
+func parseLine(line []byte) (marker, host string, key ssh.PublicKey, err error) {
+ if w, next := nextWord(line); w == markerCert || w == markerRevoked {
+ marker = w
+ line = next
+ }
+
+ host, line = nextWord(line)
+ if len(line) == 0 {
+ return "", "", nil, errors.New("knownhosts: missing host pattern")
+ }
+
+ // ignore the keytype as it's in the key blob anyway.
+ _, line = nextWord(line)
+ if len(line) == 0 {
+ return "", "", nil, errors.New("knownhosts: missing key type pattern")
+ }
+
+ keyBlob, _ := nextWord(line)
+
+ keyBytes, err := base64.StdEncoding.DecodeString(keyBlob)
+ if err != nil {
+ return "", "", nil, err
+ }
+ key, err = ssh.ParsePublicKey(keyBytes)
+ if err != nil {
+ return "", "", nil, err
+ }
+
+ return marker, host, key, nil
+}
+
+func (db *hostKeyDB) parseLine(line []byte, filename string, linenum int) error {
+ marker, pattern, key, err := parseLine(line)
+ if err != nil {
+ return err
+ }
+
+ if marker == markerRevoked {
+ db.revoked[string(key.Marshal())] = &KnownKey{
+ Key: key,
+ Filename: filename,
+ Line: linenum,
+ }
+
+ return nil
+ }
+
+ entry := keyDBLine{
+ cert: marker == markerCert,
+ knownKey: KnownKey{
+ Filename: filename,
+ Line: linenum,
+ Key: key,
+ },
+ }
+
+ if pattern[0] == '|' {
+ entry.matcher, err = newHashedHost(pattern)
+ } else {
+ entry.matcher, err = newHostnameMatcher(pattern)
+ }
+
+ if err != nil {
+ return err
+ }
+
+ db.lines = append(db.lines, entry)
+ return nil
+}
+
+func newHostnameMatcher(pattern string) (matcher, error) {
+ var hps hostPatterns
+ for _, p := range strings.Split(pattern, ",") {
+ if len(p) == 0 {
+ continue
+ }
+
+ var a addr
+ var negate bool
+ if p[0] == '!' {
+ negate = true
+ p = p[1:]
+ }
+
+ if len(p) == 0 {
+ return nil, errors.New("knownhosts: negation without following hostname")
+ }
+
+ var err error
+ if p[0] == '[' {
+ a.host, a.port, err = net.SplitHostPort(p)
+ if err != nil {
+ return nil, err
+ }
+ } else {
+ a.host, a.port, err = net.SplitHostPort(p)
+ if err != nil {
+ a.host = p
+ a.port = "22"
+ }
+ }
+ hps = append(hps, hostPattern{
+ negate: negate,
+ addr: a,
+ })
+ }
+ return hps, nil
+}
+
+// KnownKey represents a key declared in a known_hosts file.
+type KnownKey struct {
+ Key ssh.PublicKey
+ Filename string
+ Line int
+}
+
+func (k *KnownKey) String() string {
+ return fmt.Sprintf("%s:%d: %s", k.Filename, k.Line, serialize(k.Key))
+}
+
+// KeyError is returned if we did not find the key in the host key
+// database, or there was a mismatch. Typically, in batch
+// applications, this should be interpreted as failure. Interactive
+// applications can offer an interactive prompt to the user.
+type KeyError struct {
+ // Want holds the accepted host keys. For each key algorithm,
+ // there can be one hostkey. If Want is empty, the host is
+ // unknown. If Want is non-empty, there was a mismatch, which
+ // can signify a MITM attack.
+ Want []KnownKey
+}
+
+func (u *KeyError) Error() string {
+ if len(u.Want) == 0 {
+ return "knownhosts: key is unknown"
+ }
+ return "knownhosts: key mismatch"
+}
+
+// RevokedError is returned if we found a key that was revoked.
+type RevokedError struct {
+ Revoked KnownKey
+}
+
+func (r *RevokedError) Error() string {
+ return "knownhosts: key is revoked"
+}
+
+// check checks a key against the host database. This should not be
+// used for verifying certificates.
+func (db *hostKeyDB) check(address string, remote net.Addr, remoteKey ssh.PublicKey) error {
+ if revoked := db.revoked[string(remoteKey.Marshal())]; revoked != nil {
+ return &RevokedError{Revoked: *revoked}
+ }
+
+ host, port, err := net.SplitHostPort(remote.String())
+ if err != nil {
+ return fmt.Errorf("knownhosts: SplitHostPort(%s): %v", remote, err)
+ }
+
+ addrs := []addr{
+ {host, port},
+ }
+
+ if address != "" {
+ host, port, err := net.SplitHostPort(address)
+ if err != nil {
+ return fmt.Errorf("knownhosts: SplitHostPort(%s): %v", address, err)
+ }
+
+ addrs = append(addrs, addr{host, port})
+ }
+
+ return db.checkAddrs(addrs, remoteKey)
+}
+
+// checkAddrs checks if we can find the given public key for any of
+// the given addresses. If we only find an entry for the IP address,
+// or only the hostname, then this still succeeds.
+func (db *hostKeyDB) checkAddrs(addrs []addr, remoteKey ssh.PublicKey) error {
+ // TODO(hanwen): are these the right semantics? What if there
+ // is just a key for the IP address, but not for the
+ // hostname?
+
+ // Algorithm => key.
+ knownKeys := map[string]KnownKey{}
+ for _, l := range db.lines {
+ if l.match(addrs) {
+ typ := l.knownKey.Key.Type()
+ if _, ok := knownKeys[typ]; !ok {
+ knownKeys[typ] = l.knownKey
+ }
+ }
+ }
+
+ keyErr := &KeyError{}
+ for _, v := range knownKeys {
+ keyErr.Want = append(keyErr.Want, v)
+ }
+
+ // Unknown remote host.
+ if len(knownKeys) == 0 {
+ return keyErr
+ }
+
+ // If the remote host starts using a different, unknown key type, we
+ // also interpret that as a mismatch.
+ if known, ok := knownKeys[remoteKey.Type()]; !ok || !keyEq(known.Key, remoteKey) {
+ return keyErr
+ }
+
+ return nil
+}
+
+// The Read function parses file contents.
+func (db *hostKeyDB) Read(r io.Reader, filename string) error {
+ scanner := bufio.NewScanner(r)
+
+ lineNum := 0
+ for scanner.Scan() {
+ lineNum++
+ line := scanner.Bytes()
+ line = bytes.TrimSpace(line)
+ if len(line) == 0 || line[0] == '#' {
+ continue
+ }
+
+ if err := db.parseLine(line, filename, lineNum); err != nil {
+ return fmt.Errorf("knownhosts: %s:%d: %v", filename, lineNum, err)
+ }
+ }
+ return scanner.Err()
+}
+
+// New creates a host key callback from the given OpenSSH host key
+// files. The returned callback is for use in
+// ssh.ClientConfig.HostKeyCallback. Hashed hostnames are not supported.
+func New(files ...string) (ssh.HostKeyCallback, error) {
+ db := newHostKeyDB()
+ for _, fn := range files {
+ f, err := os.Open(fn)
+ if err != nil {
+ return nil, err
+ }
+ defer f.Close()
+ if err := db.Read(f, fn); err != nil {
+ return nil, err
+ }
+ }
+
+ var certChecker ssh.CertChecker
+ certChecker.IsHostAuthority = db.IsHostAuthority
+ certChecker.IsRevoked = db.IsRevoked
+ certChecker.HostKeyFallback = db.check
+
+ return certChecker.CheckHostKey, nil
+}
+
+// Normalize normalizes an address into the form used in known_hosts
+func Normalize(address string) string {
+ host, port, err := net.SplitHostPort(address)
+ if err != nil {
+ host = address
+ port = "22"
+ }
+ entry := host
+ if port != "22" {
+ entry = "[" + entry + "]:" + port
+ } else if strings.Contains(host, ":") && !strings.HasPrefix(host, "[") {
+ entry = "[" + entry + "]"
+ }
+ return entry
+}
+
+// Line returns a line to add append to the known_hosts files.
+func Line(addresses []string, key ssh.PublicKey) string {
+ var trimmed []string
+ for _, a := range addresses {
+ trimmed = append(trimmed, Normalize(a))
+ }
+
+ return strings.Join(trimmed, ",") + " " + serialize(key)
+}
+
+// HashHostname hashes the given hostname. The hostname is not
+// normalized before hashing.
+func HashHostname(hostname string) string {
+ // TODO(hanwen): check if we can safely normalize this always.
+ salt := make([]byte, sha1.Size)
+
+ _, err := rand.Read(salt)
+ if err != nil {
+ panic(fmt.Sprintf("crypto/rand failure %v", err))
+ }
+
+ hash := hashHost(hostname, salt)
+ return encodeHash(sha1HashType, salt, hash)
+}
+
+func decodeHash(encoded string) (hashType string, salt, hash []byte, err error) {
+ if len(encoded) == 0 || encoded[0] != '|' {
+ err = errors.New("knownhosts: hashed host must start with '|'")
+ return
+ }
+ components := strings.Split(encoded, "|")
+ if len(components) != 4 {
+ err = fmt.Errorf("knownhosts: got %d components, want 3", len(components))
+ return
+ }
+
+ hashType = components[1]
+ if salt, err = base64.StdEncoding.DecodeString(components[2]); err != nil {
+ return
+ }
+ if hash, err = base64.StdEncoding.DecodeString(components[3]); err != nil {
+ return
+ }
+ return
+}
+
+func encodeHash(typ string, salt []byte, hash []byte) string {
+ return strings.Join([]string{"",
+ typ,
+ base64.StdEncoding.EncodeToString(salt),
+ base64.StdEncoding.EncodeToString(hash),
+ }, "|")
+}
+
+// See https://android.googlesource.com/platform/external/openssh/+/ab28f5495c85297e7a597c1ba62e996416da7c7e/hostfile.c#120
+func hashHost(hostname string, salt []byte) []byte {
+ mac := hmac.New(sha1.New, salt)
+ mac.Write([]byte(hostname))
+ return mac.Sum(nil)
+}
+
+type hashedHost struct {
+ salt []byte
+ hash []byte
+}
+
+const sha1HashType = "1"
+
+func newHashedHost(encoded string) (*hashedHost, error) {
+ typ, salt, hash, err := decodeHash(encoded)
+ if err != nil {
+ return nil, err
+ }
+
+ // The type field seems for future algorithm agility, but it's
+ // actually hardcoded in openssh currently, see
+ // https://android.googlesource.com/platform/external/openssh/+/ab28f5495c85297e7a597c1ba62e996416da7c7e/hostfile.c#120
+ if typ != sha1HashType {
+ return nil, fmt.Errorf("knownhosts: got hash type %s, must be '1'", typ)
+ }
+
+ return &hashedHost{salt: salt, hash: hash}, nil
+}
+
+func (h *hashedHost) match(addrs []addr) bool {
+ for _, a := range addrs {
+ if bytes.Equal(hashHost(Normalize(a.String()), h.salt), h.hash) {
+ return true
+ }
+ }
+ return false
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts_test.go
new file mode 100644
index 000000000..be7cc0e80
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts_test.go
@@ -0,0 +1,329 @@
+// 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 knownhosts
+
+import (
+ "bytes"
+ "fmt"
+ "net"
+ "reflect"
+ "testing"
+
+ "golang.org/x/crypto/ssh"
+)
+
+const edKeyStr = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGBAarftlLeoyf+v+nVchEZII/vna2PCV8FaX4vsF5BX"
+const alternateEdKeyStr = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIXffBYeYL+WVzVru8npl5JHt2cjlr4ornFTWzoij9sx"
+const ecKeyStr = "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBNLCu01+wpXe3xB5olXCN4SqU2rQu0qjSRKJO4Bg+JRCPU+ENcgdA5srTU8xYDz/GEa4dzK5ldPw4J/gZgSXCMs="
+
+var ecKey, alternateEdKey, edKey ssh.PublicKey
+var testAddr = &net.TCPAddr{
+ IP: net.IP{198, 41, 30, 196},
+ Port: 22,
+}
+
+var testAddr6 = &net.TCPAddr{
+ IP: net.IP{198, 41, 30, 196,
+ 1, 2, 3, 4,
+ 1, 2, 3, 4,
+ 1, 2, 3, 4,
+ },
+ Port: 22,
+}
+
+func init() {
+ var err error
+ ecKey, _, _, _, err = ssh.ParseAuthorizedKey([]byte(ecKeyStr))
+ if err != nil {
+ panic(err)
+ }
+ edKey, _, _, _, err = ssh.ParseAuthorizedKey([]byte(edKeyStr))
+ if err != nil {
+ panic(err)
+ }
+ alternateEdKey, _, _, _, err = ssh.ParseAuthorizedKey([]byte(alternateEdKeyStr))
+ if err != nil {
+ panic(err)
+ }
+}
+
+func testDB(t *testing.T, s string) *hostKeyDB {
+ db := newHostKeyDB()
+ if err := db.Read(bytes.NewBufferString(s), "testdb"); err != nil {
+ t.Fatalf("Read: %v", err)
+ }
+
+ return db
+}
+
+func TestRevoked(t *testing.T) {
+ db := testDB(t, "\n\n@revoked * "+edKeyStr+"\n")
+ want := &RevokedError{
+ Revoked: KnownKey{
+ Key: edKey,
+ Filename: "testdb",
+ Line: 3,
+ },
+ }
+ if err := db.check("", &net.TCPAddr{
+ Port: 42,
+ }, edKey); err == nil {
+ t.Fatal("no error for revoked key")
+ } else if !reflect.DeepEqual(want, err) {
+ t.Fatalf("got %#v, want %#v", want, err)
+ }
+}
+
+func TestHostAuthority(t *testing.T) {
+ for _, m := range []struct {
+ authorityFor string
+ address string
+
+ good bool
+ }{
+ {authorityFor: "localhost", address: "localhost:22", good: true},
+ {authorityFor: "localhost", address: "localhost", good: false},
+ {authorityFor: "localhost", address: "localhost:1234", good: false},
+ {authorityFor: "[localhost]:1234", address: "localhost:1234", good: true},
+ {authorityFor: "[localhost]:1234", address: "localhost:22", good: false},
+ {authorityFor: "[localhost]:1234", address: "localhost", good: false},
+ } {
+ db := testDB(t, `@cert-authority `+m.authorityFor+` `+edKeyStr)
+ if ok := db.IsHostAuthority(db.lines[0].knownKey.Key, m.address); ok != m.good {
+ t.Errorf("IsHostAuthority: authority %s, address %s, wanted good = %v, got good = %v",
+ m.authorityFor, m.address, m.good, ok)
+ }
+ }
+}
+
+func TestBracket(t *testing.T) {
+ db := testDB(t, `[git.eclipse.org]:29418,[198.41.30.196]:29418 `+edKeyStr)
+
+ if err := db.check("git.eclipse.org:29418", &net.TCPAddr{
+ IP: net.IP{198, 41, 30, 196},
+ Port: 29418,
+ }, edKey); err != nil {
+ t.Errorf("got error %v, want none", err)
+ }
+
+ if err := db.check("git.eclipse.org:29419", &net.TCPAddr{
+ Port: 42,
+ }, edKey); err == nil {
+ t.Fatalf("no error for unknown address")
+ } else if ke, ok := err.(*KeyError); !ok {
+ t.Fatalf("got type %T, want *KeyError", err)
+ } else if len(ke.Want) > 0 {
+ t.Fatalf("got Want %v, want []", ke.Want)
+ }
+}
+
+func TestNewKeyType(t *testing.T) {
+ str := fmt.Sprintf("%s %s", testAddr, edKeyStr)
+ db := testDB(t, str)
+ if err := db.check("", testAddr, ecKey); err == nil {
+ t.Fatalf("no error for unknown address")
+ } else if ke, ok := err.(*KeyError); !ok {
+ t.Fatalf("got type %T, want *KeyError", err)
+ } else if len(ke.Want) == 0 {
+ t.Fatalf("got empty KeyError.Want")
+ }
+}
+
+func TestSameKeyType(t *testing.T) {
+ str := fmt.Sprintf("%s %s", testAddr, edKeyStr)
+ db := testDB(t, str)
+ if err := db.check("", testAddr, alternateEdKey); err == nil {
+ t.Fatalf("no error for unknown address")
+ } else if ke, ok := err.(*KeyError); !ok {
+ t.Fatalf("got type %T, want *KeyError", err)
+ } else if len(ke.Want) == 0 {
+ t.Fatalf("got empty KeyError.Want")
+ } else if got, want := ke.Want[0].Key.Marshal(), edKey.Marshal(); !bytes.Equal(got, want) {
+ t.Fatalf("got key %q, want %q", got, want)
+ }
+}
+
+func TestIPAddress(t *testing.T) {
+ str := fmt.Sprintf("%s %s", testAddr, edKeyStr)
+ db := testDB(t, str)
+ if err := db.check("", testAddr, edKey); err != nil {
+ t.Errorf("got error %q, want none", err)
+ }
+}
+
+func TestIPv6Address(t *testing.T) {
+ str := fmt.Sprintf("%s %s", testAddr6, edKeyStr)
+ db := testDB(t, str)
+
+ if err := db.check("", testAddr6, edKey); err != nil {
+ t.Errorf("got error %q, want none", err)
+ }
+}
+
+func TestBasic(t *testing.T) {
+ str := fmt.Sprintf("#comment\n\nserver.org,%s %s\notherhost %s", testAddr, edKeyStr, ecKeyStr)
+ db := testDB(t, str)
+ if err := db.check("server.org:22", testAddr, edKey); err != nil {
+ t.Errorf("got error %q, want none", err)
+ }
+
+ want := KnownKey{
+ Key: edKey,
+ Filename: "testdb",
+ Line: 3,
+ }
+ if err := db.check("server.org:22", testAddr, ecKey); err == nil {
+ t.Errorf("succeeded, want KeyError")
+ } else if ke, ok := err.(*KeyError); !ok {
+ t.Errorf("got %T, want *KeyError", err)
+ } else if len(ke.Want) != 1 {
+ t.Errorf("got %v, want 1 entry", ke)
+ } else if !reflect.DeepEqual(ke.Want[0], want) {
+ t.Errorf("got %v, want %v", ke.Want[0], want)
+ }
+}
+
+func TestNegate(t *testing.T) {
+ str := fmt.Sprintf("%s,!server.org %s", testAddr, edKeyStr)
+ db := testDB(t, str)
+ if err := db.check("server.org:22", testAddr, ecKey); err == nil {
+ t.Errorf("succeeded")
+ } else if ke, ok := err.(*KeyError); !ok {
+ t.Errorf("got error type %T, want *KeyError", err)
+ } else if len(ke.Want) != 0 {
+ t.Errorf("got expected keys %d (first of type %s), want []", len(ke.Want), ke.Want[0].Key.Type())
+ }
+}
+
+func TestWildcard(t *testing.T) {
+ str := fmt.Sprintf("server*.domain %s", edKeyStr)
+ db := testDB(t, str)
+
+ want := &KeyError{
+ Want: []KnownKey{{
+ Filename: "testdb",
+ Line: 1,
+ Key: edKey,
+ }},
+ }
+
+ got := db.check("server.domain:22", &net.TCPAddr{}, ecKey)
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("got %s, want %s", got, want)
+ }
+}
+
+func TestLine(t *testing.T) {
+ for in, want := range map[string]string{
+ "server.org": "server.org " + edKeyStr,
+ "server.org:22": "server.org " + edKeyStr,
+ "server.org:23": "[server.org]:23 " + edKeyStr,
+ "[c629:1ec4:102:304:102:304:102:304]:22": "[c629:1ec4:102:304:102:304:102:304] " + edKeyStr,
+ "[c629:1ec4:102:304:102:304:102:304]:23": "[c629:1ec4:102:304:102:304:102:304]:23 " + edKeyStr,
+ } {
+ if got := Line([]string{in}, edKey); got != want {
+ t.Errorf("Line(%q) = %q, want %q", in, got, want)
+ }
+ }
+}
+
+func TestWildcardMatch(t *testing.T) {
+ for _, c := range []struct {
+ pat, str string
+ want bool
+ }{
+ {"a?b", "abb", true},
+ {"ab", "abc", false},
+ {"abc", "ab", false},
+ {"a*b", "axxxb", true},
+ {"a*b", "axbxb", true},
+ {"a*b", "axbxbc", false},
+ {"a*?", "axbxc", true},
+ {"a*b*", "axxbxxxxxx", true},
+ {"a*b*c", "axxbxxxxxxc", true},
+ {"a*b*?", "axxbxxxxxxc", true},
+ {"a*b*z", "axxbxxbxxxz", true},
+ {"a*b*z", "axxbxxzxxxz", true},
+ {"a*b*z", "axxbxxzxxx", false},
+ } {
+ got := wildcardMatch([]byte(c.pat), []byte(c.str))
+ if got != c.want {
+ t.Errorf("wildcardMatch(%q, %q) = %v, want %v", c.pat, c.str, got, c.want)
+ }
+
+ }
+}
+
+// TODO(hanwen): test coverage for certificates.
+
+const testHostname = "hostname"
+
+// generated with keygen -H -f
+const encodedTestHostnameHash = "|1|IHXZvQMvTcZTUU29+2vXFgx8Frs=|UGccIWfRVDwilMBnA3WJoRAC75Y="
+
+func TestHostHash(t *testing.T) {
+ testHostHash(t, testHostname, encodedTestHostnameHash)
+}
+
+func TestHashList(t *testing.T) {
+ encoded := HashHostname(testHostname)
+ testHostHash(t, testHostname, encoded)
+}
+
+func testHostHash(t *testing.T, hostname, encoded string) {
+ typ, salt, hash, err := decodeHash(encoded)
+ if err != nil {
+ t.Fatalf("decodeHash: %v", err)
+ }
+
+ if got := encodeHash(typ, salt, hash); got != encoded {
+ t.Errorf("got encoding %s want %s", got, encoded)
+ }
+
+ if typ != sha1HashType {
+ t.Fatalf("got hash type %q, want %q", typ, sha1HashType)
+ }
+
+ got := hashHost(hostname, salt)
+ if !bytes.Equal(got, hash) {
+ t.Errorf("got hash %x want %x", got, hash)
+ }
+}
+
+func TestNormalize(t *testing.T) {
+ for in, want := range map[string]string{
+ "127.0.0.1:22": "127.0.0.1",
+ "[127.0.0.1]:22": "127.0.0.1",
+ "[127.0.0.1]:23": "[127.0.0.1]:23",
+ "127.0.0.1:23": "[127.0.0.1]:23",
+ "[a.b.c]:22": "a.b.c",
+ "[abcd:abcd:abcd:abcd]": "[abcd:abcd:abcd:abcd]",
+ "[abcd:abcd:abcd:abcd]:22": "[abcd:abcd:abcd:abcd]",
+ "[abcd:abcd:abcd:abcd]:23": "[abcd:abcd:abcd:abcd]:23",
+ } {
+ got := Normalize(in)
+ if got != want {
+ t.Errorf("Normalize(%q) = %q, want %q", in, got, want)
+ }
+ }
+}
+
+func TestHashedHostkeyCheck(t *testing.T) {
+ str := fmt.Sprintf("%s %s", HashHostname(testHostname), edKeyStr)
+ db := testDB(t, str)
+ if err := db.check(testHostname+":22", testAddr, edKey); err != nil {
+ t.Errorf("check(%s): %v", testHostname, err)
+ }
+ want := &KeyError{
+ Want: []KnownKey{{
+ Filename: "testdb",
+ Line: 1,
+ Key: edKey,
+ }},
+ }
+ if got := db.check(testHostname+":22", testAddr, alternateEdKey); !reflect.DeepEqual(got, want) {
+ t.Errorf("got error %v, want %v", got, want)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/mac.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/mac.go
new file mode 100644
index 000000000..c07a06285
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/mac.go
@@ -0,0 +1,61 @@
+// Copyright 2012 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 ssh
+
+// Message authentication support
+
+import (
+ "crypto/hmac"
+ "crypto/sha1"
+ "crypto/sha256"
+ "hash"
+)
+
+type macMode struct {
+ keySize int
+ etm bool
+ new func(key []byte) hash.Hash
+}
+
+// truncatingMAC wraps around a hash.Hash and truncates the output digest to
+// a given size.
+type truncatingMAC struct {
+ length int
+ hmac hash.Hash
+}
+
+func (t truncatingMAC) Write(data []byte) (int, error) {
+ return t.hmac.Write(data)
+}
+
+func (t truncatingMAC) Sum(in []byte) []byte {
+ out := t.hmac.Sum(in)
+ return out[:len(in)+t.length]
+}
+
+func (t truncatingMAC) Reset() {
+ t.hmac.Reset()
+}
+
+func (t truncatingMAC) Size() int {
+ return t.length
+}
+
+func (t truncatingMAC) BlockSize() int { return t.hmac.BlockSize() }
+
+var macModes = map[string]*macMode{
+ "hmac-sha2-256-etm@openssh.com": {32, true, func(key []byte) hash.Hash {
+ return hmac.New(sha256.New, key)
+ }},
+ "hmac-sha2-256": {32, false, func(key []byte) hash.Hash {
+ return hmac.New(sha256.New, key)
+ }},
+ "hmac-sha1": {20, false, func(key []byte) hash.Hash {
+ return hmac.New(sha1.New, key)
+ }},
+ "hmac-sha1-96": {20, false, func(key []byte) hash.Hash {
+ return truncatingMAC{12, hmac.New(sha1.New, key)}
+ }},
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/mempipe_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/mempipe_test.go
new file mode 100644
index 000000000..8697cd614
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/mempipe_test.go
@@ -0,0 +1,110 @@
+// Copyright 2013 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 ssh
+
+import (
+ "io"
+ "sync"
+ "testing"
+)
+
+// An in-memory packetConn. It is safe to call Close and writePacket
+// from different goroutines.
+type memTransport struct {
+ eof bool
+ pending [][]byte
+ write *memTransport
+ sync.Mutex
+ *sync.Cond
+}
+
+func (t *memTransport) readPacket() ([]byte, error) {
+ t.Lock()
+ defer t.Unlock()
+ for {
+ if len(t.pending) > 0 {
+ r := t.pending[0]
+ t.pending = t.pending[1:]
+ return r, nil
+ }
+ if t.eof {
+ return nil, io.EOF
+ }
+ t.Cond.Wait()
+ }
+}
+
+func (t *memTransport) closeSelf() error {
+ t.Lock()
+ defer t.Unlock()
+ if t.eof {
+ return io.EOF
+ }
+ t.eof = true
+ t.Cond.Broadcast()
+ return nil
+}
+
+func (t *memTransport) Close() error {
+ err := t.write.closeSelf()
+ t.closeSelf()
+ return err
+}
+
+func (t *memTransport) writePacket(p []byte) error {
+ t.write.Lock()
+ defer t.write.Unlock()
+ if t.write.eof {
+ return io.EOF
+ }
+ c := make([]byte, len(p))
+ copy(c, p)
+ t.write.pending = append(t.write.pending, c)
+ t.write.Cond.Signal()
+ return nil
+}
+
+func memPipe() (a, b packetConn) {
+ t1 := memTransport{}
+ t2 := memTransport{}
+ t1.write = &t2
+ t2.write = &t1
+ t1.Cond = sync.NewCond(&t1.Mutex)
+ t2.Cond = sync.NewCond(&t2.Mutex)
+ return &t1, &t2
+}
+
+func TestMemPipe(t *testing.T) {
+ a, b := memPipe()
+ if err := a.writePacket([]byte{42}); err != nil {
+ t.Fatalf("writePacket: %v", err)
+ }
+ if err := a.Close(); err != nil {
+ t.Fatal("Close: ", err)
+ }
+ p, err := b.readPacket()
+ if err != nil {
+ t.Fatal("readPacket: ", err)
+ }
+ if len(p) != 1 || p[0] != 42 {
+ t.Fatalf("got %v, want {42}", p)
+ }
+ p, err = b.readPacket()
+ if err != io.EOF {
+ t.Fatalf("got %v, %v, want EOF", p, err)
+ }
+}
+
+func TestDoubleClose(t *testing.T) {
+ a, _ := memPipe()
+ err := a.Close()
+ if err != nil {
+ t.Errorf("Close: %v", err)
+ }
+ err = a.Close()
+ if err != io.EOF {
+ t.Errorf("expect EOF on double close.")
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/messages.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/messages.go
new file mode 100644
index 000000000..c96e1bec5
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/messages.go
@@ -0,0 +1,766 @@
+// Copyright 2011 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 ssh
+
+import (
+ "bytes"
+ "encoding/binary"
+ "errors"
+ "fmt"
+ "io"
+ "math/big"
+ "reflect"
+ "strconv"
+ "strings"
+)
+
+// These are SSH message type numbers. They are scattered around several
+// documents but many were taken from [SSH-PARAMETERS].
+const (
+ msgIgnore = 2
+ msgUnimplemented = 3
+ msgDebug = 4
+ msgNewKeys = 21
+)
+
+// SSH messages:
+//
+// These structures mirror the wire format of the corresponding SSH messages.
+// They are marshaled using reflection with the marshal and unmarshal functions
+// in this file. The only wrinkle is that a final member of type []byte with a
+// ssh tag of "rest" receives the remainder of a packet when unmarshaling.
+
+// See RFC 4253, section 11.1.
+const msgDisconnect = 1
+
+// disconnectMsg is the message that signals a disconnect. It is also
+// the error type returned from mux.Wait()
+type disconnectMsg struct {
+ Reason uint32 `sshtype:"1"`
+ Message string
+ Language string
+}
+
+func (d *disconnectMsg) Error() string {
+ return fmt.Sprintf("ssh: disconnect, reason %d: %s", d.Reason, d.Message)
+}
+
+// See RFC 4253, section 7.1.
+const msgKexInit = 20
+
+type kexInitMsg struct {
+ Cookie [16]byte `sshtype:"20"`
+ KexAlgos []string
+ ServerHostKeyAlgos []string
+ CiphersClientServer []string
+ CiphersServerClient []string
+ MACsClientServer []string
+ MACsServerClient []string
+ CompressionClientServer []string
+ CompressionServerClient []string
+ LanguagesClientServer []string
+ LanguagesServerClient []string
+ FirstKexFollows bool
+ Reserved uint32
+}
+
+// See RFC 4253, section 8.
+
+// Diffie-Helman
+const msgKexDHInit = 30
+
+type kexDHInitMsg struct {
+ X *big.Int `sshtype:"30"`
+}
+
+const msgKexECDHInit = 30
+
+type kexECDHInitMsg struct {
+ ClientPubKey []byte `sshtype:"30"`
+}
+
+const msgKexECDHReply = 31
+
+type kexECDHReplyMsg struct {
+ HostKey []byte `sshtype:"31"`
+ EphemeralPubKey []byte
+ Signature []byte
+}
+
+const msgKexDHReply = 31
+
+type kexDHReplyMsg struct {
+ HostKey []byte `sshtype:"31"`
+ Y *big.Int
+ Signature []byte
+}
+
+// See RFC 4253, section 10.
+const msgServiceRequest = 5
+
+type serviceRequestMsg struct {
+ Service string `sshtype:"5"`
+}
+
+// See RFC 4253, section 10.
+const msgServiceAccept = 6
+
+type serviceAcceptMsg struct {
+ Service string `sshtype:"6"`
+}
+
+// See RFC 4252, section 5.
+const msgUserAuthRequest = 50
+
+type userAuthRequestMsg struct {
+ User string `sshtype:"50"`
+ Service string
+ Method string
+ Payload []byte `ssh:"rest"`
+}
+
+// Used for debug printouts of packets.
+type userAuthSuccessMsg struct {
+}
+
+// See RFC 4252, section 5.1
+const msgUserAuthFailure = 51
+
+type userAuthFailureMsg struct {
+ Methods []string `sshtype:"51"`
+ PartialSuccess bool
+}
+
+// See RFC 4252, section 5.1
+const msgUserAuthSuccess = 52
+
+// See RFC 4252, section 5.4
+const msgUserAuthBanner = 53
+
+type userAuthBannerMsg struct {
+ Message string `sshtype:"53"`
+ // unused, but required to allow message parsing
+ Language string
+}
+
+// See RFC 4256, section 3.2
+const msgUserAuthInfoRequest = 60
+const msgUserAuthInfoResponse = 61
+
+type userAuthInfoRequestMsg struct {
+ User string `sshtype:"60"`
+ Instruction string
+ DeprecatedLanguage string
+ NumPrompts uint32
+ Prompts []byte `ssh:"rest"`
+}
+
+// See RFC 4254, section 5.1.
+const msgChannelOpen = 90
+
+type channelOpenMsg struct {
+ ChanType string `sshtype:"90"`
+ PeersId uint32
+ PeersWindow uint32
+ MaxPacketSize uint32
+ TypeSpecificData []byte `ssh:"rest"`
+}
+
+const msgChannelExtendedData = 95
+const msgChannelData = 94
+
+// Used for debug print outs of packets.
+type channelDataMsg struct {
+ PeersId uint32 `sshtype:"94"`
+ Length uint32
+ Rest []byte `ssh:"rest"`
+}
+
+// See RFC 4254, section 5.1.
+const msgChannelOpenConfirm = 91
+
+type channelOpenConfirmMsg struct {
+ PeersId uint32 `sshtype:"91"`
+ MyId uint32
+ MyWindow uint32
+ MaxPacketSize uint32
+ TypeSpecificData []byte `ssh:"rest"`
+}
+
+// See RFC 4254, section 5.1.
+const msgChannelOpenFailure = 92
+
+type channelOpenFailureMsg struct {
+ PeersId uint32 `sshtype:"92"`
+ Reason RejectionReason
+ Message string
+ Language string
+}
+
+const msgChannelRequest = 98
+
+type channelRequestMsg struct {
+ PeersId uint32 `sshtype:"98"`
+ Request string
+ WantReply bool
+ RequestSpecificData []byte `ssh:"rest"`
+}
+
+// See RFC 4254, section 5.4.
+const msgChannelSuccess = 99
+
+type channelRequestSuccessMsg struct {
+ PeersId uint32 `sshtype:"99"`
+}
+
+// See RFC 4254, section 5.4.
+const msgChannelFailure = 100
+
+type channelRequestFailureMsg struct {
+ PeersId uint32 `sshtype:"100"`
+}
+
+// See RFC 4254, section 5.3
+const msgChannelClose = 97
+
+type channelCloseMsg struct {
+ PeersId uint32 `sshtype:"97"`
+}
+
+// See RFC 4254, section 5.3
+const msgChannelEOF = 96
+
+type channelEOFMsg struct {
+ PeersId uint32 `sshtype:"96"`
+}
+
+// See RFC 4254, section 4
+const msgGlobalRequest = 80
+
+type globalRequestMsg struct {
+ Type string `sshtype:"80"`
+ WantReply bool
+ Data []byte `ssh:"rest"`
+}
+
+// See RFC 4254, section 4
+const msgRequestSuccess = 81
+
+type globalRequestSuccessMsg struct {
+ Data []byte `ssh:"rest" sshtype:"81"`
+}
+
+// See RFC 4254, section 4
+const msgRequestFailure = 82
+
+type globalRequestFailureMsg struct {
+ Data []byte `ssh:"rest" sshtype:"82"`
+}
+
+// See RFC 4254, section 5.2
+const msgChannelWindowAdjust = 93
+
+type windowAdjustMsg struct {
+ PeersId uint32 `sshtype:"93"`
+ AdditionalBytes uint32
+}
+
+// See RFC 4252, section 7
+const msgUserAuthPubKeyOk = 60
+
+type userAuthPubKeyOkMsg struct {
+ Algo string `sshtype:"60"`
+ PubKey []byte
+}
+
+// typeTags returns the possible type bytes for the given reflect.Type, which
+// should be a struct. The possible values are separated by a '|' character.
+func typeTags(structType reflect.Type) (tags []byte) {
+ tagStr := structType.Field(0).Tag.Get("sshtype")
+
+ for _, tag := range strings.Split(tagStr, "|") {
+ i, err := strconv.Atoi(tag)
+ if err == nil {
+ tags = append(tags, byte(i))
+ }
+ }
+
+ return tags
+}
+
+func fieldError(t reflect.Type, field int, problem string) error {
+ if problem != "" {
+ problem = ": " + problem
+ }
+ return fmt.Errorf("ssh: unmarshal error for field %s of type %s%s", t.Field(field).Name, t.Name(), problem)
+}
+
+var errShortRead = errors.New("ssh: short read")
+
+// Unmarshal parses data in SSH wire format into a structure. The out
+// argument should be a pointer to struct. If the first member of the
+// struct has the "sshtype" tag set to a '|'-separated set of numbers
+// in decimal, the packet must start with one of those numbers. In
+// case of error, Unmarshal returns a ParseError or
+// UnexpectedMessageError.
+func Unmarshal(data []byte, out interface{}) error {
+ v := reflect.ValueOf(out).Elem()
+ structType := v.Type()
+ expectedTypes := typeTags(structType)
+
+ var expectedType byte
+ if len(expectedTypes) > 0 {
+ expectedType = expectedTypes[0]
+ }
+
+ if len(data) == 0 {
+ return parseError(expectedType)
+ }
+
+ if len(expectedTypes) > 0 {
+ goodType := false
+ for _, e := range expectedTypes {
+ if e > 0 && data[0] == e {
+ goodType = true
+ break
+ }
+ }
+ if !goodType {
+ return fmt.Errorf("ssh: unexpected message type %d (expected one of %v)", data[0], expectedTypes)
+ }
+ data = data[1:]
+ }
+
+ var ok bool
+ for i := 0; i < v.NumField(); i++ {
+ field := v.Field(i)
+ t := field.Type()
+ switch t.Kind() {
+ case reflect.Bool:
+ if len(data) < 1 {
+ return errShortRead
+ }
+ field.SetBool(data[0] != 0)
+ data = data[1:]
+ case reflect.Array:
+ if t.Elem().Kind() != reflect.Uint8 {
+ return fieldError(structType, i, "array of unsupported type")
+ }
+ if len(data) < t.Len() {
+ return errShortRead
+ }
+ for j, n := 0, t.Len(); j < n; j++ {
+ field.Index(j).Set(reflect.ValueOf(data[j]))
+ }
+ data = data[t.Len():]
+ case reflect.Uint64:
+ var u64 uint64
+ if u64, data, ok = parseUint64(data); !ok {
+ return errShortRead
+ }
+ field.SetUint(u64)
+ case reflect.Uint32:
+ var u32 uint32
+ if u32, data, ok = parseUint32(data); !ok {
+ return errShortRead
+ }
+ field.SetUint(uint64(u32))
+ case reflect.Uint8:
+ if len(data) < 1 {
+ return errShortRead
+ }
+ field.SetUint(uint64(data[0]))
+ data = data[1:]
+ case reflect.String:
+ var s []byte
+ if s, data, ok = parseString(data); !ok {
+ return fieldError(structType, i, "")
+ }
+ field.SetString(string(s))
+ case reflect.Slice:
+ switch t.Elem().Kind() {
+ case reflect.Uint8:
+ if structType.Field(i).Tag.Get("ssh") == "rest" {
+ field.Set(reflect.ValueOf(data))
+ data = nil
+ } else {
+ var s []byte
+ if s, data, ok = parseString(data); !ok {
+ return errShortRead
+ }
+ field.Set(reflect.ValueOf(s))
+ }
+ case reflect.String:
+ var nl []string
+ if nl, data, ok = parseNameList(data); !ok {
+ return errShortRead
+ }
+ field.Set(reflect.ValueOf(nl))
+ default:
+ return fieldError(structType, i, "slice of unsupported type")
+ }
+ case reflect.Ptr:
+ if t == bigIntType {
+ var n *big.Int
+ if n, data, ok = parseInt(data); !ok {
+ return errShortRead
+ }
+ field.Set(reflect.ValueOf(n))
+ } else {
+ return fieldError(structType, i, "pointer to unsupported type")
+ }
+ default:
+ return fieldError(structType, i, fmt.Sprintf("unsupported type: %v", t))
+ }
+ }
+
+ if len(data) != 0 {
+ return parseError(expectedType)
+ }
+
+ return nil
+}
+
+// Marshal serializes the message in msg to SSH wire format. The msg
+// argument should be a struct or pointer to struct. If the first
+// member has the "sshtype" tag set to a number in decimal, that
+// number is prepended to the result. If the last of member has the
+// "ssh" tag set to "rest", its contents are appended to the output.
+func Marshal(msg interface{}) []byte {
+ out := make([]byte, 0, 64)
+ return marshalStruct(out, msg)
+}
+
+func marshalStruct(out []byte, msg interface{}) []byte {
+ v := reflect.Indirect(reflect.ValueOf(msg))
+ msgTypes := typeTags(v.Type())
+ if len(msgTypes) > 0 {
+ out = append(out, msgTypes[0])
+ }
+
+ for i, n := 0, v.NumField(); i < n; i++ {
+ field := v.Field(i)
+ switch t := field.Type(); t.Kind() {
+ case reflect.Bool:
+ var v uint8
+ if field.Bool() {
+ v = 1
+ }
+ out = append(out, v)
+ case reflect.Array:
+ if t.Elem().Kind() != reflect.Uint8 {
+ panic(fmt.Sprintf("array of non-uint8 in field %d: %T", i, field.Interface()))
+ }
+ for j, l := 0, t.Len(); j < l; j++ {
+ out = append(out, uint8(field.Index(j).Uint()))
+ }
+ case reflect.Uint32:
+ out = appendU32(out, uint32(field.Uint()))
+ case reflect.Uint64:
+ out = appendU64(out, uint64(field.Uint()))
+ case reflect.Uint8:
+ out = append(out, uint8(field.Uint()))
+ case reflect.String:
+ s := field.String()
+ out = appendInt(out, len(s))
+ out = append(out, s...)
+ case reflect.Slice:
+ switch t.Elem().Kind() {
+ case reflect.Uint8:
+ if v.Type().Field(i).Tag.Get("ssh") != "rest" {
+ out = appendInt(out, field.Len())
+ }
+ out = append(out, field.Bytes()...)
+ case reflect.String:
+ offset := len(out)
+ out = appendU32(out, 0)
+ if n := field.Len(); n > 0 {
+ for j := 0; j < n; j++ {
+ f := field.Index(j)
+ if j != 0 {
+ out = append(out, ',')
+ }
+ out = append(out, f.String()...)
+ }
+ // overwrite length value
+ binary.BigEndian.PutUint32(out[offset:], uint32(len(out)-offset-4))
+ }
+ default:
+ panic(fmt.Sprintf("slice of unknown type in field %d: %T", i, field.Interface()))
+ }
+ case reflect.Ptr:
+ if t == bigIntType {
+ var n *big.Int
+ nValue := reflect.ValueOf(&n)
+ nValue.Elem().Set(field)
+ needed := intLength(n)
+ oldLength := len(out)
+
+ if cap(out)-len(out) < needed {
+ newOut := make([]byte, len(out), 2*(len(out)+needed))
+ copy(newOut, out)
+ out = newOut
+ }
+ out = out[:oldLength+needed]
+ marshalInt(out[oldLength:], n)
+ } else {
+ panic(fmt.Sprintf("pointer to unknown type in field %d: %T", i, field.Interface()))
+ }
+ }
+ }
+
+ return out
+}
+
+var bigOne = big.NewInt(1)
+
+func parseString(in []byte) (out, rest []byte, ok bool) {
+ if len(in) < 4 {
+ return
+ }
+ length := binary.BigEndian.Uint32(in)
+ in = in[4:]
+ if uint32(len(in)) < length {
+ return
+ }
+ out = in[:length]
+ rest = in[length:]
+ ok = true
+ return
+}
+
+var (
+ comma = []byte{','}
+ emptyNameList = []string{}
+)
+
+func parseNameList(in []byte) (out []string, rest []byte, ok bool) {
+ contents, rest, ok := parseString(in)
+ if !ok {
+ return
+ }
+ if len(contents) == 0 {
+ out = emptyNameList
+ return
+ }
+ parts := bytes.Split(contents, comma)
+ out = make([]string, len(parts))
+ for i, part := range parts {
+ out[i] = string(part)
+ }
+ return
+}
+
+func parseInt(in []byte) (out *big.Int, rest []byte, ok bool) {
+ contents, rest, ok := parseString(in)
+ if !ok {
+ return
+ }
+ out = new(big.Int)
+
+ if len(contents) > 0 && contents[0]&0x80 == 0x80 {
+ // This is a negative number
+ notBytes := make([]byte, len(contents))
+ for i := range notBytes {
+ notBytes[i] = ^contents[i]
+ }
+ out.SetBytes(notBytes)
+ out.Add(out, bigOne)
+ out.Neg(out)
+ } else {
+ // Positive number
+ out.SetBytes(contents)
+ }
+ ok = true
+ return
+}
+
+func parseUint32(in []byte) (uint32, []byte, bool) {
+ if len(in) < 4 {
+ return 0, nil, false
+ }
+ return binary.BigEndian.Uint32(in), in[4:], true
+}
+
+func parseUint64(in []byte) (uint64, []byte, bool) {
+ if len(in) < 8 {
+ return 0, nil, false
+ }
+ return binary.BigEndian.Uint64(in), in[8:], true
+}
+
+func intLength(n *big.Int) int {
+ length := 4 /* length bytes */
+ if n.Sign() < 0 {
+ nMinus1 := new(big.Int).Neg(n)
+ nMinus1.Sub(nMinus1, bigOne)
+ bitLen := nMinus1.BitLen()
+ if bitLen%8 == 0 {
+ // The number will need 0xff padding
+ length++
+ }
+ length += (bitLen + 7) / 8
+ } else if n.Sign() == 0 {
+ // A zero is the zero length string
+ } else {
+ bitLen := n.BitLen()
+ if bitLen%8 == 0 {
+ // The number will need 0x00 padding
+ length++
+ }
+ length += (bitLen + 7) / 8
+ }
+
+ return length
+}
+
+func marshalUint32(to []byte, n uint32) []byte {
+ binary.BigEndian.PutUint32(to, n)
+ return to[4:]
+}
+
+func marshalUint64(to []byte, n uint64) []byte {
+ binary.BigEndian.PutUint64(to, n)
+ return to[8:]
+}
+
+func marshalInt(to []byte, n *big.Int) []byte {
+ lengthBytes := to
+ to = to[4:]
+ length := 0
+
+ if n.Sign() < 0 {
+ // A negative number has to be converted to two's-complement
+ // form. So we'll subtract 1 and invert. If the
+ // most-significant-bit isn't set then we'll need to pad the
+ // beginning with 0xff in order to keep the number negative.
+ nMinus1 := new(big.Int).Neg(n)
+ nMinus1.Sub(nMinus1, bigOne)
+ bytes := nMinus1.Bytes()
+ for i := range bytes {
+ bytes[i] ^= 0xff
+ }
+ if len(bytes) == 0 || bytes[0]&0x80 == 0 {
+ to[0] = 0xff
+ to = to[1:]
+ length++
+ }
+ nBytes := copy(to, bytes)
+ to = to[nBytes:]
+ length += nBytes
+ } else if n.Sign() == 0 {
+ // A zero is the zero length string
+ } else {
+ bytes := n.Bytes()
+ if len(bytes) > 0 && bytes[0]&0x80 != 0 {
+ // We'll have to pad this with a 0x00 in order to
+ // stop it looking like a negative number.
+ to[0] = 0
+ to = to[1:]
+ length++
+ }
+ nBytes := copy(to, bytes)
+ to = to[nBytes:]
+ length += nBytes
+ }
+
+ lengthBytes[0] = byte(length >> 24)
+ lengthBytes[1] = byte(length >> 16)
+ lengthBytes[2] = byte(length >> 8)
+ lengthBytes[3] = byte(length)
+ return to
+}
+
+func writeInt(w io.Writer, n *big.Int) {
+ length := intLength(n)
+ buf := make([]byte, length)
+ marshalInt(buf, n)
+ w.Write(buf)
+}
+
+func writeString(w io.Writer, s []byte) {
+ var lengthBytes [4]byte
+ lengthBytes[0] = byte(len(s) >> 24)
+ lengthBytes[1] = byte(len(s) >> 16)
+ lengthBytes[2] = byte(len(s) >> 8)
+ lengthBytes[3] = byte(len(s))
+ w.Write(lengthBytes[:])
+ w.Write(s)
+}
+
+func stringLength(n int) int {
+ return 4 + n
+}
+
+func marshalString(to []byte, s []byte) []byte {
+ to[0] = byte(len(s) >> 24)
+ to[1] = byte(len(s) >> 16)
+ to[2] = byte(len(s) >> 8)
+ to[3] = byte(len(s))
+ to = to[4:]
+ copy(to, s)
+ return to[len(s):]
+}
+
+var bigIntType = reflect.TypeOf((*big.Int)(nil))
+
+// Decode a packet into its corresponding message.
+func decode(packet []byte) (interface{}, error) {
+ var msg interface{}
+ switch packet[0] {
+ case msgDisconnect:
+ msg = new(disconnectMsg)
+ case msgServiceRequest:
+ msg = new(serviceRequestMsg)
+ case msgServiceAccept:
+ msg = new(serviceAcceptMsg)
+ case msgKexInit:
+ msg = new(kexInitMsg)
+ case msgKexDHInit:
+ msg = new(kexDHInitMsg)
+ case msgKexDHReply:
+ msg = new(kexDHReplyMsg)
+ case msgUserAuthRequest:
+ msg = new(userAuthRequestMsg)
+ case msgUserAuthSuccess:
+ return new(userAuthSuccessMsg), nil
+ case msgUserAuthFailure:
+ msg = new(userAuthFailureMsg)
+ case msgUserAuthPubKeyOk:
+ msg = new(userAuthPubKeyOkMsg)
+ case msgGlobalRequest:
+ msg = new(globalRequestMsg)
+ case msgRequestSuccess:
+ msg = new(globalRequestSuccessMsg)
+ case msgRequestFailure:
+ msg = new(globalRequestFailureMsg)
+ case msgChannelOpen:
+ msg = new(channelOpenMsg)
+ case msgChannelData:
+ msg = new(channelDataMsg)
+ case msgChannelOpenConfirm:
+ msg = new(channelOpenConfirmMsg)
+ case msgChannelOpenFailure:
+ msg = new(channelOpenFailureMsg)
+ case msgChannelWindowAdjust:
+ msg = new(windowAdjustMsg)
+ case msgChannelEOF:
+ msg = new(channelEOFMsg)
+ case msgChannelClose:
+ msg = new(channelCloseMsg)
+ case msgChannelRequest:
+ msg = new(channelRequestMsg)
+ case msgChannelSuccess:
+ msg = new(channelRequestSuccessMsg)
+ case msgChannelFailure:
+ msg = new(channelRequestFailureMsg)
+ default:
+ return nil, unexpectedMessageError(0, packet[0])
+ }
+ if err := Unmarshal(packet, msg); err != nil {
+ return nil, err
+ }
+ return msg, nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/messages_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/messages_test.go
new file mode 100644
index 000000000..e79076412
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/messages_test.go
@@ -0,0 +1,288 @@
+// Copyright 2011 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 ssh
+
+import (
+ "bytes"
+ "math/big"
+ "math/rand"
+ "reflect"
+ "testing"
+ "testing/quick"
+)
+
+var intLengthTests = []struct {
+ val, length int
+}{
+ {0, 4 + 0},
+ {1, 4 + 1},
+ {127, 4 + 1},
+ {128, 4 + 2},
+ {-1, 4 + 1},
+}
+
+func TestIntLength(t *testing.T) {
+ for _, test := range intLengthTests {
+ v := new(big.Int).SetInt64(int64(test.val))
+ length := intLength(v)
+ if length != test.length {
+ t.Errorf("For %d, got length %d but expected %d", test.val, length, test.length)
+ }
+ }
+}
+
+type msgAllTypes struct {
+ Bool bool `sshtype:"21"`
+ Array [16]byte
+ Uint64 uint64
+ Uint32 uint32
+ Uint8 uint8
+ String string
+ Strings []string
+ Bytes []byte
+ Int *big.Int
+ Rest []byte `ssh:"rest"`
+}
+
+func (t *msgAllTypes) Generate(rand *rand.Rand, size int) reflect.Value {
+ m := &msgAllTypes{}
+ m.Bool = rand.Intn(2) == 1
+ randomBytes(m.Array[:], rand)
+ m.Uint64 = uint64(rand.Int63n(1<<63 - 1))
+ m.Uint32 = uint32(rand.Intn((1 << 31) - 1))
+ m.Uint8 = uint8(rand.Intn(1 << 8))
+ m.String = string(m.Array[:])
+ m.Strings = randomNameList(rand)
+ m.Bytes = m.Array[:]
+ m.Int = randomInt(rand)
+ m.Rest = m.Array[:]
+ return reflect.ValueOf(m)
+}
+
+func TestMarshalUnmarshal(t *testing.T) {
+ rand := rand.New(rand.NewSource(0))
+ iface := &msgAllTypes{}
+ ty := reflect.ValueOf(iface).Type()
+
+ n := 100
+ if testing.Short() {
+ n = 5
+ }
+ for j := 0; j < n; j++ {
+ v, ok := quick.Value(ty, rand)
+ if !ok {
+ t.Errorf("failed to create value")
+ break
+ }
+
+ m1 := v.Elem().Interface()
+ m2 := iface
+
+ marshaled := Marshal(m1)
+ if err := Unmarshal(marshaled, m2); err != nil {
+ t.Errorf("Unmarshal %#v: %s", m1, err)
+ break
+ }
+
+ if !reflect.DeepEqual(v.Interface(), m2) {
+ t.Errorf("got: %#v\nwant:%#v\n%x", m2, m1, marshaled)
+ break
+ }
+ }
+}
+
+func TestUnmarshalEmptyPacket(t *testing.T) {
+ var b []byte
+ var m channelRequestSuccessMsg
+ if err := Unmarshal(b, &m); err == nil {
+ t.Fatalf("unmarshal of empty slice succeeded")
+ }
+}
+
+func TestUnmarshalUnexpectedPacket(t *testing.T) {
+ type S struct {
+ I uint32 `sshtype:"43"`
+ S string
+ B bool
+ }
+
+ s := S{11, "hello", true}
+ packet := Marshal(s)
+ packet[0] = 42
+ roundtrip := S{}
+ err := Unmarshal(packet, &roundtrip)
+ if err == nil {
+ t.Fatal("expected error, not nil")
+ }
+}
+
+func TestMarshalPtr(t *testing.T) {
+ s := struct {
+ S string
+ }{"hello"}
+
+ m1 := Marshal(s)
+ m2 := Marshal(&s)
+ if !bytes.Equal(m1, m2) {
+ t.Errorf("got %q, want %q for marshaled pointer", m2, m1)
+ }
+}
+
+func TestBareMarshalUnmarshal(t *testing.T) {
+ type S struct {
+ I uint32
+ S string
+ B bool
+ }
+
+ s := S{42, "hello", true}
+ packet := Marshal(s)
+ roundtrip := S{}
+ Unmarshal(packet, &roundtrip)
+
+ if !reflect.DeepEqual(s, roundtrip) {
+ t.Errorf("got %#v, want %#v", roundtrip, s)
+ }
+}
+
+func TestBareMarshal(t *testing.T) {
+ type S2 struct {
+ I uint32
+ }
+ s := S2{42}
+ packet := Marshal(s)
+ i, rest, ok := parseUint32(packet)
+ if len(rest) > 0 || !ok {
+ t.Errorf("parseInt(%q): parse error", packet)
+ }
+ if i != s.I {
+ t.Errorf("got %d, want %d", i, s.I)
+ }
+}
+
+func TestUnmarshalShortKexInitPacket(t *testing.T) {
+ // This used to panic.
+ // Issue 11348
+ packet := []byte{0x14, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xff, 0xff, 0xff, 0xff}
+ kim := &kexInitMsg{}
+ if err := Unmarshal(packet, kim); err == nil {
+ t.Error("truncated packet unmarshaled without error")
+ }
+}
+
+func TestMarshalMultiTag(t *testing.T) {
+ var res struct {
+ A uint32 `sshtype:"1|2"`
+ }
+
+ good1 := struct {
+ A uint32 `sshtype:"1"`
+ }{
+ 1,
+ }
+ good2 := struct {
+ A uint32 `sshtype:"2"`
+ }{
+ 1,
+ }
+
+ if e := Unmarshal(Marshal(good1), &res); e != nil {
+ t.Errorf("error unmarshaling multipart tag: %v", e)
+ }
+
+ if e := Unmarshal(Marshal(good2), &res); e != nil {
+ t.Errorf("error unmarshaling multipart tag: %v", e)
+ }
+
+ bad1 := struct {
+ A uint32 `sshtype:"3"`
+ }{
+ 1,
+ }
+ if e := Unmarshal(Marshal(bad1), &res); e == nil {
+ t.Errorf("bad struct unmarshaled without error")
+ }
+}
+
+func randomBytes(out []byte, rand *rand.Rand) {
+ for i := 0; i < len(out); i++ {
+ out[i] = byte(rand.Int31())
+ }
+}
+
+func randomNameList(rand *rand.Rand) []string {
+ ret := make([]string, rand.Int31()&15)
+ for i := range ret {
+ s := make([]byte, 1+(rand.Int31()&15))
+ for j := range s {
+ s[j] = 'a' + uint8(rand.Int31()&15)
+ }
+ ret[i] = string(s)
+ }
+ return ret
+}
+
+func randomInt(rand *rand.Rand) *big.Int {
+ return new(big.Int).SetInt64(int64(int32(rand.Uint32())))
+}
+
+func (*kexInitMsg) Generate(rand *rand.Rand, size int) reflect.Value {
+ ki := &kexInitMsg{}
+ randomBytes(ki.Cookie[:], rand)
+ ki.KexAlgos = randomNameList(rand)
+ ki.ServerHostKeyAlgos = randomNameList(rand)
+ ki.CiphersClientServer = randomNameList(rand)
+ ki.CiphersServerClient = randomNameList(rand)
+ ki.MACsClientServer = randomNameList(rand)
+ ki.MACsServerClient = randomNameList(rand)
+ ki.CompressionClientServer = randomNameList(rand)
+ ki.CompressionServerClient = randomNameList(rand)
+ ki.LanguagesClientServer = randomNameList(rand)
+ ki.LanguagesServerClient = randomNameList(rand)
+ if rand.Int31()&1 == 1 {
+ ki.FirstKexFollows = true
+ }
+ return reflect.ValueOf(ki)
+}
+
+func (*kexDHInitMsg) Generate(rand *rand.Rand, size int) reflect.Value {
+ dhi := &kexDHInitMsg{}
+ dhi.X = randomInt(rand)
+ return reflect.ValueOf(dhi)
+}
+
+var (
+ _kexInitMsg = new(kexInitMsg).Generate(rand.New(rand.NewSource(0)), 10).Elem().Interface()
+ _kexDHInitMsg = new(kexDHInitMsg).Generate(rand.New(rand.NewSource(0)), 10).Elem().Interface()
+
+ _kexInit = Marshal(_kexInitMsg)
+ _kexDHInit = Marshal(_kexDHInitMsg)
+)
+
+func BenchmarkMarshalKexInitMsg(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ Marshal(_kexInitMsg)
+ }
+}
+
+func BenchmarkUnmarshalKexInitMsg(b *testing.B) {
+ m := new(kexInitMsg)
+ for i := 0; i < b.N; i++ {
+ Unmarshal(_kexInit, m)
+ }
+}
+
+func BenchmarkMarshalKexDHInitMsg(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ Marshal(_kexDHInitMsg)
+ }
+}
+
+func BenchmarkUnmarshalKexDHInitMsg(b *testing.B) {
+ m := new(kexDHInitMsg)
+ for i := 0; i < b.N; i++ {
+ Unmarshal(_kexDHInit, m)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/mux.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/mux.go
new file mode 100644
index 000000000..27a527c10
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/mux.go
@@ -0,0 +1,330 @@
+// Copyright 2013 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 ssh
+
+import (
+ "encoding/binary"
+ "fmt"
+ "io"
+ "log"
+ "sync"
+ "sync/atomic"
+)
+
+// debugMux, if set, causes messages in the connection protocol to be
+// logged.
+const debugMux = false
+
+// chanList is a thread safe channel list.
+type chanList struct {
+ // protects concurrent access to chans
+ sync.Mutex
+
+ // chans are indexed by the local id of the channel, which the
+ // other side should send in the PeersId field.
+ chans []*channel
+
+ // This is a debugging aid: it offsets all IDs by this
+ // amount. This helps distinguish otherwise identical
+ // server/client muxes
+ offset uint32
+}
+
+// Assigns a channel ID to the given channel.
+func (c *chanList) add(ch *channel) uint32 {
+ c.Lock()
+ defer c.Unlock()
+ for i := range c.chans {
+ if c.chans[i] == nil {
+ c.chans[i] = ch
+ return uint32(i) + c.offset
+ }
+ }
+ c.chans = append(c.chans, ch)
+ return uint32(len(c.chans)-1) + c.offset
+}
+
+// getChan returns the channel for the given ID.
+func (c *chanList) getChan(id uint32) *channel {
+ id -= c.offset
+
+ c.Lock()
+ defer c.Unlock()
+ if id < uint32(len(c.chans)) {
+ return c.chans[id]
+ }
+ return nil
+}
+
+func (c *chanList) remove(id uint32) {
+ id -= c.offset
+ c.Lock()
+ if id < uint32(len(c.chans)) {
+ c.chans[id] = nil
+ }
+ c.Unlock()
+}
+
+// dropAll forgets all channels it knows, returning them in a slice.
+func (c *chanList) dropAll() []*channel {
+ c.Lock()
+ defer c.Unlock()
+ var r []*channel
+
+ for _, ch := range c.chans {
+ if ch == nil {
+ continue
+ }
+ r = append(r, ch)
+ }
+ c.chans = nil
+ return r
+}
+
+// mux represents the state for the SSH connection protocol, which
+// multiplexes many channels onto a single packet transport.
+type mux struct {
+ conn packetConn
+ chanList chanList
+
+ incomingChannels chan NewChannel
+
+ globalSentMu sync.Mutex
+ globalResponses chan interface{}
+ incomingRequests chan *Request
+
+ errCond *sync.Cond
+ err error
+}
+
+// When debugging, each new chanList instantiation has a different
+// offset.
+var globalOff uint32
+
+func (m *mux) Wait() error {
+ m.errCond.L.Lock()
+ defer m.errCond.L.Unlock()
+ for m.err == nil {
+ m.errCond.Wait()
+ }
+ return m.err
+}
+
+// newMux returns a mux that runs over the given connection.
+func newMux(p packetConn) *mux {
+ m := &mux{
+ conn: p,
+ incomingChannels: make(chan NewChannel, chanSize),
+ globalResponses: make(chan interface{}, 1),
+ incomingRequests: make(chan *Request, chanSize),
+ errCond: newCond(),
+ }
+ if debugMux {
+ m.chanList.offset = atomic.AddUint32(&globalOff, 1)
+ }
+
+ go m.loop()
+ return m
+}
+
+func (m *mux) sendMessage(msg interface{}) error {
+ p := Marshal(msg)
+ if debugMux {
+ log.Printf("send global(%d): %#v", m.chanList.offset, msg)
+ }
+ return m.conn.writePacket(p)
+}
+
+func (m *mux) SendRequest(name string, wantReply bool, payload []byte) (bool, []byte, error) {
+ if wantReply {
+ m.globalSentMu.Lock()
+ defer m.globalSentMu.Unlock()
+ }
+
+ if err := m.sendMessage(globalRequestMsg{
+ Type: name,
+ WantReply: wantReply,
+ Data: payload,
+ }); err != nil {
+ return false, nil, err
+ }
+
+ if !wantReply {
+ return false, nil, nil
+ }
+
+ msg, ok := <-m.globalResponses
+ if !ok {
+ return false, nil, io.EOF
+ }
+ switch msg := msg.(type) {
+ case *globalRequestFailureMsg:
+ return false, msg.Data, nil
+ case *globalRequestSuccessMsg:
+ return true, msg.Data, nil
+ default:
+ return false, nil, fmt.Errorf("ssh: unexpected response to request: %#v", msg)
+ }
+}
+
+// ackRequest must be called after processing a global request that
+// has WantReply set.
+func (m *mux) ackRequest(ok bool, data []byte) error {
+ if ok {
+ return m.sendMessage(globalRequestSuccessMsg{Data: data})
+ }
+ return m.sendMessage(globalRequestFailureMsg{Data: data})
+}
+
+func (m *mux) Close() error {
+ return m.conn.Close()
+}
+
+// loop runs the connection machine. It will process packets until an
+// error is encountered. To synchronize on loop exit, use mux.Wait.
+func (m *mux) loop() {
+ var err error
+ for err == nil {
+ err = m.onePacket()
+ }
+
+ for _, ch := range m.chanList.dropAll() {
+ ch.close()
+ }
+
+ close(m.incomingChannels)
+ close(m.incomingRequests)
+ close(m.globalResponses)
+
+ m.conn.Close()
+
+ m.errCond.L.Lock()
+ m.err = err
+ m.errCond.Broadcast()
+ m.errCond.L.Unlock()
+
+ if debugMux {
+ log.Println("loop exit", err)
+ }
+}
+
+// onePacket reads and processes one packet.
+func (m *mux) onePacket() error {
+ packet, err := m.conn.readPacket()
+ if err != nil {
+ return err
+ }
+
+ if debugMux {
+ if packet[0] == msgChannelData || packet[0] == msgChannelExtendedData {
+ log.Printf("decoding(%d): data packet - %d bytes", m.chanList.offset, len(packet))
+ } else {
+ p, _ := decode(packet)
+ log.Printf("decoding(%d): %d %#v - %d bytes", m.chanList.offset, packet[0], p, len(packet))
+ }
+ }
+
+ switch packet[0] {
+ case msgChannelOpen:
+ return m.handleChannelOpen(packet)
+ case msgGlobalRequest, msgRequestSuccess, msgRequestFailure:
+ return m.handleGlobalPacket(packet)
+ }
+
+ // assume a channel packet.
+ if len(packet) < 5 {
+ return parseError(packet[0])
+ }
+ id := binary.BigEndian.Uint32(packet[1:])
+ ch := m.chanList.getChan(id)
+ if ch == nil {
+ return fmt.Errorf("ssh: invalid channel %d", id)
+ }
+
+ return ch.handlePacket(packet)
+}
+
+func (m *mux) handleGlobalPacket(packet []byte) error {
+ msg, err := decode(packet)
+ if err != nil {
+ return err
+ }
+
+ switch msg := msg.(type) {
+ case *globalRequestMsg:
+ m.incomingRequests <- &Request{
+ Type: msg.Type,
+ WantReply: msg.WantReply,
+ Payload: msg.Data,
+ mux: m,
+ }
+ case *globalRequestSuccessMsg, *globalRequestFailureMsg:
+ m.globalResponses <- msg
+ default:
+ panic(fmt.Sprintf("not a global message %#v", msg))
+ }
+
+ return nil
+}
+
+// handleChannelOpen schedules a channel to be Accept()ed.
+func (m *mux) handleChannelOpen(packet []byte) error {
+ var msg channelOpenMsg
+ if err := Unmarshal(packet, &msg); err != nil {
+ return err
+ }
+
+ if msg.MaxPacketSize < minPacketLength || msg.MaxPacketSize > 1<<31 {
+ failMsg := channelOpenFailureMsg{
+ PeersId: msg.PeersId,
+ Reason: ConnectionFailed,
+ Message: "invalid request",
+ Language: "en_US.UTF-8",
+ }
+ return m.sendMessage(failMsg)
+ }
+
+ c := m.newChannel(msg.ChanType, channelInbound, msg.TypeSpecificData)
+ c.remoteId = msg.PeersId
+ c.maxRemotePayload = msg.MaxPacketSize
+ c.remoteWin.add(msg.PeersWindow)
+ m.incomingChannels <- c
+ return nil
+}
+
+func (m *mux) OpenChannel(chanType string, extra []byte) (Channel, <-chan *Request, error) {
+ ch, err := m.openChannel(chanType, extra)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ return ch, ch.incomingRequests, nil
+}
+
+func (m *mux) openChannel(chanType string, extra []byte) (*channel, error) {
+ ch := m.newChannel(chanType, channelOutbound, extra)
+
+ ch.maxIncomingPayload = channelMaxPacket
+
+ open := channelOpenMsg{
+ ChanType: chanType,
+ PeersWindow: ch.myWindow,
+ MaxPacketSize: ch.maxIncomingPayload,
+ TypeSpecificData: extra,
+ PeersId: ch.localId,
+ }
+ if err := m.sendMessage(open); err != nil {
+ return nil, err
+ }
+
+ switch msg := (<-ch.msg).(type) {
+ case *channelOpenConfirmMsg:
+ return ch, nil
+ case *channelOpenFailureMsg:
+ return nil, &OpenChannelError{msg.Reason, msg.Message}
+ default:
+ return nil, fmt.Errorf("ssh: unexpected packet in response to channel open: %T", msg)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/mux_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/mux_test.go
new file mode 100644
index 000000000..25d2181d6
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/mux_test.go
@@ -0,0 +1,505 @@
+// Copyright 2013 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 ssh
+
+import (
+ "io"
+ "io/ioutil"
+ "sync"
+ "testing"
+)
+
+func muxPair() (*mux, *mux) {
+ a, b := memPipe()
+
+ s := newMux(a)
+ c := newMux(b)
+
+ return s, c
+}
+
+// Returns both ends of a channel, and the mux for the the 2nd
+// channel.
+func channelPair(t *testing.T) (*channel, *channel, *mux) {
+ c, s := muxPair()
+
+ res := make(chan *channel, 1)
+ go func() {
+ newCh, ok := <-s.incomingChannels
+ if !ok {
+ t.Fatalf("No incoming channel")
+ }
+ if newCh.ChannelType() != "chan" {
+ t.Fatalf("got type %q want chan", newCh.ChannelType())
+ }
+ ch, _, err := newCh.Accept()
+ if err != nil {
+ t.Fatalf("Accept %v", err)
+ }
+ res <- ch.(*channel)
+ }()
+
+ ch, err := c.openChannel("chan", nil)
+ if err != nil {
+ t.Fatalf("OpenChannel: %v", err)
+ }
+
+ return <-res, ch, c
+}
+
+// Test that stderr and stdout can be addressed from different
+// goroutines. This is intended for use with the race detector.
+func TestMuxChannelExtendedThreadSafety(t *testing.T) {
+ writer, reader, mux := channelPair(t)
+ defer writer.Close()
+ defer reader.Close()
+ defer mux.Close()
+
+ var wr, rd sync.WaitGroup
+ magic := "hello world"
+
+ wr.Add(2)
+ go func() {
+ io.WriteString(writer, magic)
+ wr.Done()
+ }()
+ go func() {
+ io.WriteString(writer.Stderr(), magic)
+ wr.Done()
+ }()
+
+ rd.Add(2)
+ go func() {
+ c, err := ioutil.ReadAll(reader)
+ if string(c) != magic {
+ t.Fatalf("stdout read got %q, want %q (error %s)", c, magic, err)
+ }
+ rd.Done()
+ }()
+ go func() {
+ c, err := ioutil.ReadAll(reader.Stderr())
+ if string(c) != magic {
+ t.Fatalf("stderr read got %q, want %q (error %s)", c, magic, err)
+ }
+ rd.Done()
+ }()
+
+ wr.Wait()
+ writer.CloseWrite()
+ rd.Wait()
+}
+
+func TestMuxReadWrite(t *testing.T) {
+ s, c, mux := channelPair(t)
+ defer s.Close()
+ defer c.Close()
+ defer mux.Close()
+
+ magic := "hello world"
+ magicExt := "hello stderr"
+ go func() {
+ _, err := s.Write([]byte(magic))
+ if err != nil {
+ t.Fatalf("Write: %v", err)
+ }
+ _, err = s.Extended(1).Write([]byte(magicExt))
+ if err != nil {
+ t.Fatalf("Write: %v", err)
+ }
+ err = s.Close()
+ if err != nil {
+ t.Fatalf("Close: %v", err)
+ }
+ }()
+
+ var buf [1024]byte
+ n, err := c.Read(buf[:])
+ if err != nil {
+ t.Fatalf("server Read: %v", err)
+ }
+ got := string(buf[:n])
+ if got != magic {
+ t.Fatalf("server: got %q want %q", got, magic)
+ }
+
+ n, err = c.Extended(1).Read(buf[:])
+ if err != nil {
+ t.Fatalf("server Read: %v", err)
+ }
+
+ got = string(buf[:n])
+ if got != magicExt {
+ t.Fatalf("server: got %q want %q", got, magic)
+ }
+}
+
+func TestMuxChannelOverflow(t *testing.T) {
+ reader, writer, mux := channelPair(t)
+ defer reader.Close()
+ defer writer.Close()
+ defer mux.Close()
+
+ wDone := make(chan int, 1)
+ go func() {
+ if _, err := writer.Write(make([]byte, channelWindowSize)); err != nil {
+ t.Errorf("could not fill window: %v", err)
+ }
+ writer.Write(make([]byte, 1))
+ wDone <- 1
+ }()
+ writer.remoteWin.waitWriterBlocked()
+
+ // Send 1 byte.
+ packet := make([]byte, 1+4+4+1)
+ packet[0] = msgChannelData
+ marshalUint32(packet[1:], writer.remoteId)
+ marshalUint32(packet[5:], uint32(1))
+ packet[9] = 42
+
+ if err := writer.mux.conn.writePacket(packet); err != nil {
+ t.Errorf("could not send packet")
+ }
+ if _, err := reader.SendRequest("hello", true, nil); err == nil {
+ t.Errorf("SendRequest succeeded.")
+ }
+ <-wDone
+}
+
+func TestMuxChannelCloseWriteUnblock(t *testing.T) {
+ reader, writer, mux := channelPair(t)
+ defer reader.Close()
+ defer writer.Close()
+ defer mux.Close()
+
+ wDone := make(chan int, 1)
+ go func() {
+ if _, err := writer.Write(make([]byte, channelWindowSize)); err != nil {
+ t.Errorf("could not fill window: %v", err)
+ }
+ if _, err := writer.Write(make([]byte, 1)); err != io.EOF {
+ t.Errorf("got %v, want EOF for unblock write", err)
+ }
+ wDone <- 1
+ }()
+
+ writer.remoteWin.waitWriterBlocked()
+ reader.Close()
+ <-wDone
+}
+
+func TestMuxConnectionCloseWriteUnblock(t *testing.T) {
+ reader, writer, mux := channelPair(t)
+ defer reader.Close()
+ defer writer.Close()
+ defer mux.Close()
+
+ wDone := make(chan int, 1)
+ go func() {
+ if _, err := writer.Write(make([]byte, channelWindowSize)); err != nil {
+ t.Errorf("could not fill window: %v", err)
+ }
+ if _, err := writer.Write(make([]byte, 1)); err != io.EOF {
+ t.Errorf("got %v, want EOF for unblock write", err)
+ }
+ wDone <- 1
+ }()
+
+ writer.remoteWin.waitWriterBlocked()
+ mux.Close()
+ <-wDone
+}
+
+func TestMuxReject(t *testing.T) {
+ client, server := muxPair()
+ defer server.Close()
+ defer client.Close()
+
+ go func() {
+ ch, ok := <-server.incomingChannels
+ if !ok {
+ t.Fatalf("Accept")
+ }
+ if ch.ChannelType() != "ch" || string(ch.ExtraData()) != "extra" {
+ t.Fatalf("unexpected channel: %q, %q", ch.ChannelType(), ch.ExtraData())
+ }
+ ch.Reject(RejectionReason(42), "message")
+ }()
+
+ ch, err := client.openChannel("ch", []byte("extra"))
+ if ch != nil {
+ t.Fatal("openChannel not rejected")
+ }
+
+ ocf, ok := err.(*OpenChannelError)
+ if !ok {
+ t.Errorf("got %#v want *OpenChannelError", err)
+ } else if ocf.Reason != 42 || ocf.Message != "message" {
+ t.Errorf("got %#v, want {Reason: 42, Message: %q}", ocf, "message")
+ }
+
+ want := "ssh: rejected: unknown reason 42 (message)"
+ if err.Error() != want {
+ t.Errorf("got %q, want %q", err.Error(), want)
+ }
+}
+
+func TestMuxChannelRequest(t *testing.T) {
+ client, server, mux := channelPair(t)
+ defer server.Close()
+ defer client.Close()
+ defer mux.Close()
+
+ var received int
+ var wg sync.WaitGroup
+ wg.Add(1)
+ go func() {
+ for r := range server.incomingRequests {
+ received++
+ r.Reply(r.Type == "yes", nil)
+ }
+ wg.Done()
+ }()
+ _, err := client.SendRequest("yes", false, nil)
+ if err != nil {
+ t.Fatalf("SendRequest: %v", err)
+ }
+ ok, err := client.SendRequest("yes", true, nil)
+ if err != nil {
+ t.Fatalf("SendRequest: %v", err)
+ }
+
+ if !ok {
+ t.Errorf("SendRequest(yes): %v", ok)
+
+ }
+
+ ok, err = client.SendRequest("no", true, nil)
+ if err != nil {
+ t.Fatalf("SendRequest: %v", err)
+ }
+ if ok {
+ t.Errorf("SendRequest(no): %v", ok)
+
+ }
+
+ client.Close()
+ wg.Wait()
+
+ if received != 3 {
+ t.Errorf("got %d requests, want %d", received, 3)
+ }
+}
+
+func TestMuxGlobalRequest(t *testing.T) {
+ clientMux, serverMux := muxPair()
+ defer serverMux.Close()
+ defer clientMux.Close()
+
+ var seen bool
+ go func() {
+ for r := range serverMux.incomingRequests {
+ seen = seen || r.Type == "peek"
+ if r.WantReply {
+ err := r.Reply(r.Type == "yes",
+ append([]byte(r.Type), r.Payload...))
+ if err != nil {
+ t.Errorf("AckRequest: %v", err)
+ }
+ }
+ }
+ }()
+
+ _, _, err := clientMux.SendRequest("peek", false, nil)
+ if err != nil {
+ t.Errorf("SendRequest: %v", err)
+ }
+
+ ok, data, err := clientMux.SendRequest("yes", true, []byte("a"))
+ if !ok || string(data) != "yesa" || err != nil {
+ t.Errorf("SendRequest(\"yes\", true, \"a\"): %v %v %v",
+ ok, data, err)
+ }
+ if ok, data, err := clientMux.SendRequest("yes", true, []byte("a")); !ok || string(data) != "yesa" || err != nil {
+ t.Errorf("SendRequest(\"yes\", true, \"a\"): %v %v %v",
+ ok, data, err)
+ }
+
+ if ok, data, err := clientMux.SendRequest("no", true, []byte("a")); ok || string(data) != "noa" || err != nil {
+ t.Errorf("SendRequest(\"no\", true, \"a\"): %v %v %v",
+ ok, data, err)
+ }
+
+ if !seen {
+ t.Errorf("never saw 'peek' request")
+ }
+}
+
+func TestMuxGlobalRequestUnblock(t *testing.T) {
+ clientMux, serverMux := muxPair()
+ defer serverMux.Close()
+ defer clientMux.Close()
+
+ result := make(chan error, 1)
+ go func() {
+ _, _, err := clientMux.SendRequest("hello", true, nil)
+ result <- err
+ }()
+
+ <-serverMux.incomingRequests
+ serverMux.conn.Close()
+ err := <-result
+
+ if err != io.EOF {
+ t.Errorf("want EOF, got %v", io.EOF)
+ }
+}
+
+func TestMuxChannelRequestUnblock(t *testing.T) {
+ a, b, connB := channelPair(t)
+ defer a.Close()
+ defer b.Close()
+ defer connB.Close()
+
+ result := make(chan error, 1)
+ go func() {
+ _, err := a.SendRequest("hello", true, nil)
+ result <- err
+ }()
+
+ <-b.incomingRequests
+ connB.conn.Close()
+ err := <-result
+
+ if err != io.EOF {
+ t.Errorf("want EOF, got %v", err)
+ }
+}
+
+func TestMuxCloseChannel(t *testing.T) {
+ r, w, mux := channelPair(t)
+ defer mux.Close()
+ defer r.Close()
+ defer w.Close()
+
+ result := make(chan error, 1)
+ go func() {
+ var b [1024]byte
+ _, err := r.Read(b[:])
+ result <- err
+ }()
+ if err := w.Close(); err != nil {
+ t.Errorf("w.Close: %v", err)
+ }
+
+ if _, err := w.Write([]byte("hello")); err != io.EOF {
+ t.Errorf("got err %v, want io.EOF after Close", err)
+ }
+
+ if err := <-result; err != io.EOF {
+ t.Errorf("got %v (%T), want io.EOF", err, err)
+ }
+}
+
+func TestMuxCloseWriteChannel(t *testing.T) {
+ r, w, mux := channelPair(t)
+ defer mux.Close()
+
+ result := make(chan error, 1)
+ go func() {
+ var b [1024]byte
+ _, err := r.Read(b[:])
+ result <- err
+ }()
+ if err := w.CloseWrite(); err != nil {
+ t.Errorf("w.CloseWrite: %v", err)
+ }
+
+ if _, err := w.Write([]byte("hello")); err != io.EOF {
+ t.Errorf("got err %v, want io.EOF after CloseWrite", err)
+ }
+
+ if err := <-result; err != io.EOF {
+ t.Errorf("got %v (%T), want io.EOF", err, err)
+ }
+}
+
+func TestMuxInvalidRecord(t *testing.T) {
+ a, b := muxPair()
+ defer a.Close()
+ defer b.Close()
+
+ packet := make([]byte, 1+4+4+1)
+ packet[0] = msgChannelData
+ marshalUint32(packet[1:], 29348723 /* invalid channel id */)
+ marshalUint32(packet[5:], 1)
+ packet[9] = 42
+
+ a.conn.writePacket(packet)
+ go a.SendRequest("hello", false, nil)
+ // 'a' wrote an invalid packet, so 'b' has exited.
+ req, ok := <-b.incomingRequests
+ if ok {
+ t.Errorf("got request %#v after receiving invalid packet", req)
+ }
+}
+
+func TestZeroWindowAdjust(t *testing.T) {
+ a, b, mux := channelPair(t)
+ defer a.Close()
+ defer b.Close()
+ defer mux.Close()
+
+ go func() {
+ io.WriteString(a, "hello")
+ // bogus adjust.
+ a.sendMessage(windowAdjustMsg{})
+ io.WriteString(a, "world")
+ a.Close()
+ }()
+
+ want := "helloworld"
+ c, _ := ioutil.ReadAll(b)
+ if string(c) != want {
+ t.Errorf("got %q want %q", c, want)
+ }
+}
+
+func TestMuxMaxPacketSize(t *testing.T) {
+ a, b, mux := channelPair(t)
+ defer a.Close()
+ defer b.Close()
+ defer mux.Close()
+
+ large := make([]byte, a.maxRemotePayload+1)
+ packet := make([]byte, 1+4+4+1+len(large))
+ packet[0] = msgChannelData
+ marshalUint32(packet[1:], a.remoteId)
+ marshalUint32(packet[5:], uint32(len(large)))
+ packet[9] = 42
+
+ if err := a.mux.conn.writePacket(packet); err != nil {
+ t.Errorf("could not send packet")
+ }
+
+ go a.SendRequest("hello", false, nil)
+
+ _, ok := <-b.incomingRequests
+ if ok {
+ t.Errorf("connection still alive after receiving large packet.")
+ }
+}
+
+// Don't ship code with debug=true.
+func TestDebug(t *testing.T) {
+ if debugMux {
+ t.Error("mux debug switched on")
+ }
+ if debugHandshake {
+ t.Error("handshake debug switched on")
+ }
+ if debugTransport {
+ t.Error("transport debug switched on")
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/server.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/server.go
new file mode 100644
index 000000000..148d2cb24
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/server.go
@@ -0,0 +1,580 @@
+// Copyright 2011 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 ssh
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "io"
+ "net"
+ "strings"
+)
+
+// The Permissions type holds fine-grained permissions that are
+// specific to a user or a specific authentication method for a user.
+// The Permissions value for a successful authentication attempt is
+// available in ServerConn, so it can be used to pass information from
+// the user-authentication phase to the application layer.
+type Permissions struct {
+ // CriticalOptions indicate restrictions to the default
+ // permissions, and are typically used in conjunction with
+ // user certificates. The standard for SSH certificates
+ // defines "force-command" (only allow the given command to
+ // execute) and "source-address" (only allow connections from
+ // the given address). The SSH package currently only enforces
+ // the "source-address" critical option. It is up to server
+ // implementations to enforce other critical options, such as
+ // "force-command", by checking them after the SSH handshake
+ // is successful. In general, SSH servers should reject
+ // connections that specify critical options that are unknown
+ // or not supported.
+ CriticalOptions map[string]string
+
+ // Extensions are extra functionality that the server may
+ // offer on authenticated connections. Lack of support for an
+ // extension does not preclude authenticating a user. Common
+ // extensions are "permit-agent-forwarding",
+ // "permit-X11-forwarding". The Go SSH library currently does
+ // not act on any extension, and it is up to server
+ // implementations to honor them. Extensions can be used to
+ // pass data from the authentication callbacks to the server
+ // application layer.
+ Extensions map[string]string
+}
+
+// ServerConfig holds server specific configuration data.
+type ServerConfig struct {
+ // Config contains configuration shared between client and server.
+ Config
+
+ hostKeys []Signer
+
+ // NoClientAuth is true if clients are allowed to connect without
+ // authenticating.
+ NoClientAuth bool
+
+ // MaxAuthTries specifies the maximum number of authentication attempts
+ // permitted per connection. If set to a negative number, the number of
+ // attempts are unlimited. If set to zero, the number of attempts are limited
+ // to 6.
+ MaxAuthTries int
+
+ // PasswordCallback, if non-nil, is called when a user
+ // attempts to authenticate using a password.
+ PasswordCallback func(conn ConnMetadata, password []byte) (*Permissions, error)
+
+ // PublicKeyCallback, if non-nil, is called when a client
+ // offers a public key for authentication. It must return a nil error
+ // if the given public key can be used to authenticate the
+ // given user. For example, see CertChecker.Authenticate. A
+ // call to this function does not guarantee that the key
+ // offered is in fact used to authenticate. To record any data
+ // depending on the public key, store it inside a
+ // Permissions.Extensions entry.
+ PublicKeyCallback func(conn ConnMetadata, key PublicKey) (*Permissions, error)
+
+ // KeyboardInteractiveCallback, if non-nil, is called when
+ // keyboard-interactive authentication is selected (RFC
+ // 4256). The client object's Challenge function should be
+ // used to query the user. The callback may offer multiple
+ // Challenge rounds. To avoid information leaks, the client
+ // should be presented a challenge even if the user is
+ // unknown.
+ KeyboardInteractiveCallback func(conn ConnMetadata, client KeyboardInteractiveChallenge) (*Permissions, error)
+
+ // AuthLogCallback, if non-nil, is called to log all authentication
+ // attempts.
+ AuthLogCallback func(conn ConnMetadata, method string, err error)
+
+ // ServerVersion is the version identification string to announce in
+ // the public handshake.
+ // If empty, a reasonable default is used.
+ // Note that RFC 4253 section 4.2 requires that this string start with
+ // "SSH-2.0-".
+ ServerVersion string
+
+ // BannerCallback, if present, is called and the return string is sent to
+ // the client after key exchange completed but before authentication.
+ BannerCallback func(conn ConnMetadata) string
+}
+
+// AddHostKey adds a private key as a host key. If an existing host
+// key exists with the same algorithm, it is overwritten. Each server
+// config must have at least one host key.
+func (s *ServerConfig) AddHostKey(key Signer) {
+ for i, k := range s.hostKeys {
+ if k.PublicKey().Type() == key.PublicKey().Type() {
+ s.hostKeys[i] = key
+ return
+ }
+ }
+
+ s.hostKeys = append(s.hostKeys, key)
+}
+
+// cachedPubKey contains the results of querying whether a public key is
+// acceptable for a user.
+type cachedPubKey struct {
+ user string
+ pubKeyData []byte
+ result error
+ perms *Permissions
+}
+
+const maxCachedPubKeys = 16
+
+// pubKeyCache caches tests for public keys. Since SSH clients
+// will query whether a public key is acceptable before attempting to
+// authenticate with it, we end up with duplicate queries for public
+// key validity. The cache only applies to a single ServerConn.
+type pubKeyCache struct {
+ keys []cachedPubKey
+}
+
+// get returns the result for a given user/algo/key tuple.
+func (c *pubKeyCache) get(user string, pubKeyData []byte) (cachedPubKey, bool) {
+ for _, k := range c.keys {
+ if k.user == user && bytes.Equal(k.pubKeyData, pubKeyData) {
+ return k, true
+ }
+ }
+ return cachedPubKey{}, false
+}
+
+// add adds the given tuple to the cache.
+func (c *pubKeyCache) add(candidate cachedPubKey) {
+ if len(c.keys) < maxCachedPubKeys {
+ c.keys = append(c.keys, candidate)
+ }
+}
+
+// ServerConn is an authenticated SSH connection, as seen from the
+// server
+type ServerConn struct {
+ Conn
+
+ // If the succeeding authentication callback returned a
+ // non-nil Permissions pointer, it is stored here.
+ Permissions *Permissions
+}
+
+// NewServerConn starts a new SSH server with c as the underlying
+// transport. It starts with a handshake and, if the handshake is
+// unsuccessful, it closes the connection and returns an error. The
+// Request and NewChannel channels must be serviced, or the connection
+// will hang.
+func NewServerConn(c net.Conn, config *ServerConfig) (*ServerConn, <-chan NewChannel, <-chan *Request, error) {
+ fullConf := *config
+ fullConf.SetDefaults()
+ if fullConf.MaxAuthTries == 0 {
+ fullConf.MaxAuthTries = 6
+ }
+
+ s := &connection{
+ sshConn: sshConn{conn: c},
+ }
+ perms, err := s.serverHandshake(&fullConf)
+ if err != nil {
+ c.Close()
+ return nil, nil, nil, err
+ }
+ return &ServerConn{s, perms}, s.mux.incomingChannels, s.mux.incomingRequests, nil
+}
+
+// signAndMarshal signs the data with the appropriate algorithm,
+// and serializes the result in SSH wire format.
+func signAndMarshal(k Signer, rand io.Reader, data []byte) ([]byte, error) {
+ sig, err := k.Sign(rand, data)
+ if err != nil {
+ return nil, err
+ }
+
+ return Marshal(sig), nil
+}
+
+// handshake performs key exchange and user authentication.
+func (s *connection) serverHandshake(config *ServerConfig) (*Permissions, error) {
+ if len(config.hostKeys) == 0 {
+ return nil, errors.New("ssh: server has no host keys")
+ }
+
+ if !config.NoClientAuth && config.PasswordCallback == nil && config.PublicKeyCallback == nil && config.KeyboardInteractiveCallback == nil {
+ return nil, errors.New("ssh: no authentication methods configured but NoClientAuth is also false")
+ }
+
+ if config.ServerVersion != "" {
+ s.serverVersion = []byte(config.ServerVersion)
+ } else {
+ s.serverVersion = []byte(packageVersion)
+ }
+ var err error
+ s.clientVersion, err = exchangeVersions(s.sshConn.conn, s.serverVersion)
+ if err != nil {
+ return nil, err
+ }
+
+ tr := newTransport(s.sshConn.conn, config.Rand, false /* not client */)
+ s.transport = newServerTransport(tr, s.clientVersion, s.serverVersion, config)
+
+ if err := s.transport.waitSession(); err != nil {
+ return nil, err
+ }
+
+ // We just did the key change, so the session ID is established.
+ s.sessionID = s.transport.getSessionID()
+
+ var packet []byte
+ if packet, err = s.transport.readPacket(); err != nil {
+ return nil, err
+ }
+
+ var serviceRequest serviceRequestMsg
+ if err = Unmarshal(packet, &serviceRequest); err != nil {
+ return nil, err
+ }
+ if serviceRequest.Service != serviceUserAuth {
+ return nil, errors.New("ssh: requested service '" + serviceRequest.Service + "' before authenticating")
+ }
+ serviceAccept := serviceAcceptMsg{
+ Service: serviceUserAuth,
+ }
+ if err := s.transport.writePacket(Marshal(&serviceAccept)); err != nil {
+ return nil, err
+ }
+
+ perms, err := s.serverAuthenticate(config)
+ if err != nil {
+ return nil, err
+ }
+ s.mux = newMux(s.transport)
+ return perms, err
+}
+
+func isAcceptableAlgo(algo string) bool {
+ switch algo {
+ case KeyAlgoRSA, KeyAlgoDSA, KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521, KeyAlgoED25519,
+ CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01:
+ return true
+ }
+ return false
+}
+
+func checkSourceAddress(addr net.Addr, sourceAddrs string) error {
+ if addr == nil {
+ return errors.New("ssh: no address known for client, but source-address match required")
+ }
+
+ tcpAddr, ok := addr.(*net.TCPAddr)
+ if !ok {
+ return fmt.Errorf("ssh: remote address %v is not an TCP address when checking source-address match", addr)
+ }
+
+ for _, sourceAddr := range strings.Split(sourceAddrs, ",") {
+ if allowedIP := net.ParseIP(sourceAddr); allowedIP != nil {
+ if allowedIP.Equal(tcpAddr.IP) {
+ return nil
+ }
+ } else {
+ _, ipNet, err := net.ParseCIDR(sourceAddr)
+ if err != nil {
+ return fmt.Errorf("ssh: error parsing source-address restriction %q: %v", sourceAddr, err)
+ }
+
+ if ipNet.Contains(tcpAddr.IP) {
+ return nil
+ }
+ }
+ }
+
+ return fmt.Errorf("ssh: remote address %v is not allowed because of source-address restriction", addr)
+}
+
+// ServerAuthError implements the error interface. It appends any authentication
+// errors that may occur, and is returned if all of the authentication methods
+// provided by the user failed to authenticate.
+type ServerAuthError struct {
+ // Errors contains authentication errors returned by the authentication
+ // callback methods.
+ Errors []error
+}
+
+func (l ServerAuthError) Error() string {
+ var errs []string
+ for _, err := range l.Errors {
+ errs = append(errs, err.Error())
+ }
+ return "[" + strings.Join(errs, ", ") + "]"
+}
+
+func (s *connection) serverAuthenticate(config *ServerConfig) (*Permissions, error) {
+ sessionID := s.transport.getSessionID()
+ var cache pubKeyCache
+ var perms *Permissions
+
+ authFailures := 0
+ var authErrs []error
+
+userAuthLoop:
+ for {
+ if authFailures >= config.MaxAuthTries && config.MaxAuthTries > 0 {
+ discMsg := &disconnectMsg{
+ Reason: 2,
+ Message: "too many authentication failures",
+ }
+
+ if err := s.transport.writePacket(Marshal(discMsg)); err != nil {
+ return nil, err
+ }
+
+ return nil, discMsg
+ }
+
+ var userAuthReq userAuthRequestMsg
+ if packet, err := s.transport.readPacket(); err != nil {
+ if err == io.EOF {
+ return nil, &ServerAuthError{Errors: authErrs}
+ }
+ return nil, err
+ } else if err = Unmarshal(packet, &userAuthReq); err != nil {
+ return nil, err
+ }
+
+ if userAuthReq.Service != serviceSSH {
+ return nil, errors.New("ssh: client attempted to negotiate for unknown service: " + userAuthReq.Service)
+ }
+
+ s.user = userAuthReq.User
+
+ if authFailures == 0 && config.BannerCallback != nil {
+ msg := config.BannerCallback(s)
+ if msg != "" {
+ bannerMsg := &userAuthBannerMsg{
+ Message: msg,
+ }
+ if err := s.transport.writePacket(Marshal(bannerMsg)); err != nil {
+ return nil, err
+ }
+ }
+ }
+
+ perms = nil
+ authErr := errors.New("no auth passed yet")
+
+ switch userAuthReq.Method {
+ case "none":
+ if config.NoClientAuth {
+ authErr = nil
+ }
+
+ // allow initial attempt of 'none' without penalty
+ if authFailures == 0 {
+ authFailures--
+ }
+ case "password":
+ if config.PasswordCallback == nil {
+ authErr = errors.New("ssh: password auth not configured")
+ break
+ }
+ payload := userAuthReq.Payload
+ if len(payload) < 1 || payload[0] != 0 {
+ return nil, parseError(msgUserAuthRequest)
+ }
+ payload = payload[1:]
+ password, payload, ok := parseString(payload)
+ if !ok || len(payload) > 0 {
+ return nil, parseError(msgUserAuthRequest)
+ }
+
+ perms, authErr = config.PasswordCallback(s, password)
+ case "keyboard-interactive":
+ if config.KeyboardInteractiveCallback == nil {
+ authErr = errors.New("ssh: keyboard-interactive auth not configubred")
+ break
+ }
+
+ prompter := &sshClientKeyboardInteractive{s}
+ perms, authErr = config.KeyboardInteractiveCallback(s, prompter.Challenge)
+ case "publickey":
+ if config.PublicKeyCallback == nil {
+ authErr = errors.New("ssh: publickey auth not configured")
+ break
+ }
+ payload := userAuthReq.Payload
+ if len(payload) < 1 {
+ return nil, parseError(msgUserAuthRequest)
+ }
+ isQuery := payload[0] == 0
+ payload = payload[1:]
+ algoBytes, payload, ok := parseString(payload)
+ if !ok {
+ return nil, parseError(msgUserAuthRequest)
+ }
+ algo := string(algoBytes)
+ if !isAcceptableAlgo(algo) {
+ authErr = fmt.Errorf("ssh: algorithm %q not accepted", algo)
+ break
+ }
+
+ pubKeyData, payload, ok := parseString(payload)
+ if !ok {
+ return nil, parseError(msgUserAuthRequest)
+ }
+
+ pubKey, err := ParsePublicKey(pubKeyData)
+ if err != nil {
+ return nil, err
+ }
+
+ candidate, ok := cache.get(s.user, pubKeyData)
+ if !ok {
+ candidate.user = s.user
+ candidate.pubKeyData = pubKeyData
+ candidate.perms, candidate.result = config.PublicKeyCallback(s, pubKey)
+ if candidate.result == nil && candidate.perms != nil && candidate.perms.CriticalOptions != nil && candidate.perms.CriticalOptions[sourceAddressCriticalOption] != "" {
+ candidate.result = checkSourceAddress(
+ s.RemoteAddr(),
+ candidate.perms.CriticalOptions[sourceAddressCriticalOption])
+ }
+ cache.add(candidate)
+ }
+
+ if isQuery {
+ // The client can query if the given public key
+ // would be okay.
+
+ if len(payload) > 0 {
+ return nil, parseError(msgUserAuthRequest)
+ }
+
+ if candidate.result == nil {
+ okMsg := userAuthPubKeyOkMsg{
+ Algo: algo,
+ PubKey: pubKeyData,
+ }
+ if err = s.transport.writePacket(Marshal(&okMsg)); err != nil {
+ return nil, err
+ }
+ continue userAuthLoop
+ }
+ authErr = candidate.result
+ } else {
+ sig, payload, ok := parseSignature(payload)
+ if !ok || len(payload) > 0 {
+ return nil, parseError(msgUserAuthRequest)
+ }
+ // Ensure the public key algo and signature algo
+ // are supported. Compare the private key
+ // algorithm name that corresponds to algo with
+ // sig.Format. This is usually the same, but
+ // for certs, the names differ.
+ if !isAcceptableAlgo(sig.Format) {
+ break
+ }
+ signedData := buildDataSignedForAuth(sessionID, userAuthReq, algoBytes, pubKeyData)
+
+ if err := pubKey.Verify(signedData, sig); err != nil {
+ return nil, err
+ }
+
+ authErr = candidate.result
+ perms = candidate.perms
+ }
+ default:
+ authErr = fmt.Errorf("ssh: unknown method %q", userAuthReq.Method)
+ }
+
+ authErrs = append(authErrs, authErr)
+
+ if config.AuthLogCallback != nil {
+ config.AuthLogCallback(s, userAuthReq.Method, authErr)
+ }
+
+ if authErr == nil {
+ break userAuthLoop
+ }
+
+ authFailures++
+
+ var failureMsg userAuthFailureMsg
+ if config.PasswordCallback != nil {
+ failureMsg.Methods = append(failureMsg.Methods, "password")
+ }
+ if config.PublicKeyCallback != nil {
+ failureMsg.Methods = append(failureMsg.Methods, "publickey")
+ }
+ if config.KeyboardInteractiveCallback != nil {
+ failureMsg.Methods = append(failureMsg.Methods, "keyboard-interactive")
+ }
+
+ if len(failureMsg.Methods) == 0 {
+ return nil, errors.New("ssh: no authentication methods configured but NoClientAuth is also false")
+ }
+
+ if err := s.transport.writePacket(Marshal(&failureMsg)); err != nil {
+ return nil, err
+ }
+ }
+
+ if err := s.transport.writePacket([]byte{msgUserAuthSuccess}); err != nil {
+ return nil, err
+ }
+ return perms, nil
+}
+
+// sshClientKeyboardInteractive implements a ClientKeyboardInteractive by
+// asking the client on the other side of a ServerConn.
+type sshClientKeyboardInteractive struct {
+ *connection
+}
+
+func (c *sshClientKeyboardInteractive) Challenge(user, instruction string, questions []string, echos []bool) (answers []string, err error) {
+ if len(questions) != len(echos) {
+ return nil, errors.New("ssh: echos and questions must have equal length")
+ }
+
+ var prompts []byte
+ for i := range questions {
+ prompts = appendString(prompts, questions[i])
+ prompts = appendBool(prompts, echos[i])
+ }
+
+ if err := c.transport.writePacket(Marshal(&userAuthInfoRequestMsg{
+ Instruction: instruction,
+ NumPrompts: uint32(len(questions)),
+ Prompts: prompts,
+ })); err != nil {
+ return nil, err
+ }
+
+ packet, err := c.transport.readPacket()
+ if err != nil {
+ return nil, err
+ }
+ if packet[0] != msgUserAuthInfoResponse {
+ return nil, unexpectedMessageError(msgUserAuthInfoResponse, packet[0])
+ }
+ packet = packet[1:]
+
+ n, packet, ok := parseUint32(packet)
+ if !ok || int(n) != len(questions) {
+ return nil, parseError(msgUserAuthInfoResponse)
+ }
+
+ for i := uint32(0); i < n; i++ {
+ ans, rest, ok := parseString(packet)
+ if !ok {
+ return nil, parseError(msgUserAuthInfoResponse)
+ }
+
+ answers = append(answers, string(ans))
+ packet = rest
+ }
+ if len(packet) != 0 {
+ return nil, errors.New("ssh: junk at end of message")
+ }
+
+ return answers, nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/session.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/session.go
new file mode 100644
index 000000000..cc06e03f5
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/session.go
@@ -0,0 +1,647 @@
+// Copyright 2011 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 ssh
+
+// Session implements an interactive session described in
+// "RFC 4254, section 6".
+
+import (
+ "bytes"
+ "encoding/binary"
+ "errors"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "sync"
+)
+
+type Signal string
+
+// POSIX signals as listed in RFC 4254 Section 6.10.
+const (
+ SIGABRT Signal = "ABRT"
+ SIGALRM Signal = "ALRM"
+ SIGFPE Signal = "FPE"
+ SIGHUP Signal = "HUP"
+ SIGILL Signal = "ILL"
+ SIGINT Signal = "INT"
+ SIGKILL Signal = "KILL"
+ SIGPIPE Signal = "PIPE"
+ SIGQUIT Signal = "QUIT"
+ SIGSEGV Signal = "SEGV"
+ SIGTERM Signal = "TERM"
+ SIGUSR1 Signal = "USR1"
+ SIGUSR2 Signal = "USR2"
+)
+
+var signals = map[Signal]int{
+ SIGABRT: 6,
+ SIGALRM: 14,
+ SIGFPE: 8,
+ SIGHUP: 1,
+ SIGILL: 4,
+ SIGINT: 2,
+ SIGKILL: 9,
+ SIGPIPE: 13,
+ SIGQUIT: 3,
+ SIGSEGV: 11,
+ SIGTERM: 15,
+}
+
+type TerminalModes map[uint8]uint32
+
+// POSIX terminal mode flags as listed in RFC 4254 Section 8.
+const (
+ tty_OP_END = 0
+ VINTR = 1
+ VQUIT = 2
+ VERASE = 3
+ VKILL = 4
+ VEOF = 5
+ VEOL = 6
+ VEOL2 = 7
+ VSTART = 8
+ VSTOP = 9
+ VSUSP = 10
+ VDSUSP = 11
+ VREPRINT = 12
+ VWERASE = 13
+ VLNEXT = 14
+ VFLUSH = 15
+ VSWTCH = 16
+ VSTATUS = 17
+ VDISCARD = 18
+ IGNPAR = 30
+ PARMRK = 31
+ INPCK = 32
+ ISTRIP = 33
+ INLCR = 34
+ IGNCR = 35
+ ICRNL = 36
+ IUCLC = 37
+ IXON = 38
+ IXANY = 39
+ IXOFF = 40
+ IMAXBEL = 41
+ ISIG = 50
+ ICANON = 51
+ XCASE = 52
+ ECHO = 53
+ ECHOE = 54
+ ECHOK = 55
+ ECHONL = 56
+ NOFLSH = 57
+ TOSTOP = 58
+ IEXTEN = 59
+ ECHOCTL = 60
+ ECHOKE = 61
+ PENDIN = 62
+ OPOST = 70
+ OLCUC = 71
+ ONLCR = 72
+ OCRNL = 73
+ ONOCR = 74
+ ONLRET = 75
+ CS7 = 90
+ CS8 = 91
+ PARENB = 92
+ PARODD = 93
+ TTY_OP_ISPEED = 128
+ TTY_OP_OSPEED = 129
+)
+
+// A Session represents a connection to a remote command or shell.
+type Session struct {
+ // Stdin specifies the remote process's standard input.
+ // If Stdin is nil, the remote process reads from an empty
+ // bytes.Buffer.
+ Stdin io.Reader
+
+ // Stdout and Stderr specify the remote process's standard
+ // output and error.
+ //
+ // If either is nil, Run connects the corresponding file
+ // descriptor to an instance of ioutil.Discard. There is a
+ // fixed amount of buffering that is shared for the two streams.
+ // If either blocks it may eventually cause the remote
+ // command to block.
+ Stdout io.Writer
+ Stderr io.Writer
+
+ ch Channel // the channel backing this session
+ started bool // true once Start, Run or Shell is invoked.
+ copyFuncs []func() error
+ errors chan error // one send per copyFunc
+
+ // true if pipe method is active
+ stdinpipe, stdoutpipe, stderrpipe bool
+
+ // stdinPipeWriter is non-nil if StdinPipe has not been called
+ // and Stdin was specified by the user; it is the write end of
+ // a pipe connecting Session.Stdin to the stdin channel.
+ stdinPipeWriter io.WriteCloser
+
+ exitStatus chan error
+}
+
+// SendRequest sends an out-of-band channel request on the SSH channel
+// underlying the session.
+func (s *Session) SendRequest(name string, wantReply bool, payload []byte) (bool, error) {
+ return s.ch.SendRequest(name, wantReply, payload)
+}
+
+func (s *Session) Close() error {
+ return s.ch.Close()
+}
+
+// RFC 4254 Section 6.4.
+type setenvRequest struct {
+ Name string
+ Value string
+}
+
+// Setenv sets an environment variable that will be applied to any
+// command executed by Shell or Run.
+func (s *Session) Setenv(name, value string) error {
+ msg := setenvRequest{
+ Name: name,
+ Value: value,
+ }
+ ok, err := s.ch.SendRequest("env", true, Marshal(&msg))
+ if err == nil && !ok {
+ err = errors.New("ssh: setenv failed")
+ }
+ return err
+}
+
+// RFC 4254 Section 6.2.
+type ptyRequestMsg struct {
+ Term string
+ Columns uint32
+ Rows uint32
+ Width uint32
+ Height uint32
+ Modelist string
+}
+
+// RequestPty requests the association of a pty with the session on the remote host.
+func (s *Session) RequestPty(term string, h, w int, termmodes TerminalModes) error {
+ var tm []byte
+ for k, v := range termmodes {
+ kv := struct {
+ Key byte
+ Val uint32
+ }{k, v}
+
+ tm = append(tm, Marshal(&kv)...)
+ }
+ tm = append(tm, tty_OP_END)
+ req := ptyRequestMsg{
+ Term: term,
+ Columns: uint32(w),
+ Rows: uint32(h),
+ Width: uint32(w * 8),
+ Height: uint32(h * 8),
+ Modelist: string(tm),
+ }
+ ok, err := s.ch.SendRequest("pty-req", true, Marshal(&req))
+ if err == nil && !ok {
+ err = errors.New("ssh: pty-req failed")
+ }
+ return err
+}
+
+// RFC 4254 Section 6.5.
+type subsystemRequestMsg struct {
+ Subsystem string
+}
+
+// RequestSubsystem requests the association of a subsystem with the session on the remote host.
+// A subsystem is a predefined command that runs in the background when the ssh session is initiated
+func (s *Session) RequestSubsystem(subsystem string) error {
+ msg := subsystemRequestMsg{
+ Subsystem: subsystem,
+ }
+ ok, err := s.ch.SendRequest("subsystem", true, Marshal(&msg))
+ if err == nil && !ok {
+ err = errors.New("ssh: subsystem request failed")
+ }
+ return err
+}
+
+// RFC 4254 Section 6.7.
+type ptyWindowChangeMsg struct {
+ Columns uint32
+ Rows uint32
+ Width uint32
+ Height uint32
+}
+
+// WindowChange informs the remote host about a terminal window dimension change to h rows and w columns.
+func (s *Session) WindowChange(h, w int) error {
+ req := ptyWindowChangeMsg{
+ Columns: uint32(w),
+ Rows: uint32(h),
+ Width: uint32(w * 8),
+ Height: uint32(h * 8),
+ }
+ _, err := s.ch.SendRequest("window-change", false, Marshal(&req))
+ return err
+}
+
+// RFC 4254 Section 6.9.
+type signalMsg struct {
+ Signal string
+}
+
+// Signal sends the given signal to the remote process.
+// sig is one of the SIG* constants.
+func (s *Session) Signal(sig Signal) error {
+ msg := signalMsg{
+ Signal: string(sig),
+ }
+
+ _, err := s.ch.SendRequest("signal", false, Marshal(&msg))
+ return err
+}
+
+// RFC 4254 Section 6.5.
+type execMsg struct {
+ Command string
+}
+
+// Start runs cmd on the remote host. Typically, the remote
+// server passes cmd to the shell for interpretation.
+// A Session only accepts one call to Run, Start or Shell.
+func (s *Session) Start(cmd string) error {
+ if s.started {
+ return errors.New("ssh: session already started")
+ }
+ req := execMsg{
+ Command: cmd,
+ }
+
+ ok, err := s.ch.SendRequest("exec", true, Marshal(&req))
+ if err == nil && !ok {
+ err = fmt.Errorf("ssh: command %v failed", cmd)
+ }
+ if err != nil {
+ return err
+ }
+ return s.start()
+}
+
+// Run runs cmd on the remote host. Typically, the remote
+// server passes cmd to the shell for interpretation.
+// A Session only accepts one call to Run, Start, Shell, Output,
+// or CombinedOutput.
+//
+// The returned error is nil if the command runs, has no problems
+// copying stdin, stdout, and stderr, and exits with a zero exit
+// status.
+//
+// If the remote server does not send an exit status, an error of type
+// *ExitMissingError is returned. If the command completes
+// unsuccessfully or is interrupted by a signal, the error is of type
+// *ExitError. Other error types may be returned for I/O problems.
+func (s *Session) Run(cmd string) error {
+ err := s.Start(cmd)
+ if err != nil {
+ return err
+ }
+ return s.Wait()
+}
+
+// Output runs cmd on the remote host and returns its standard output.
+func (s *Session) Output(cmd string) ([]byte, error) {
+ if s.Stdout != nil {
+ return nil, errors.New("ssh: Stdout already set")
+ }
+ var b bytes.Buffer
+ s.Stdout = &b
+ err := s.Run(cmd)
+ return b.Bytes(), err
+}
+
+type singleWriter struct {
+ b bytes.Buffer
+ mu sync.Mutex
+}
+
+func (w *singleWriter) Write(p []byte) (int, error) {
+ w.mu.Lock()
+ defer w.mu.Unlock()
+ return w.b.Write(p)
+}
+
+// CombinedOutput runs cmd on the remote host and returns its combined
+// standard output and standard error.
+func (s *Session) CombinedOutput(cmd string) ([]byte, error) {
+ if s.Stdout != nil {
+ return nil, errors.New("ssh: Stdout already set")
+ }
+ if s.Stderr != nil {
+ return nil, errors.New("ssh: Stderr already set")
+ }
+ var b singleWriter
+ s.Stdout = &b
+ s.Stderr = &b
+ err := s.Run(cmd)
+ return b.b.Bytes(), err
+}
+
+// Shell starts a login shell on the remote host. A Session only
+// accepts one call to Run, Start, Shell, Output, or CombinedOutput.
+func (s *Session) Shell() error {
+ if s.started {
+ return errors.New("ssh: session already started")
+ }
+
+ ok, err := s.ch.SendRequest("shell", true, nil)
+ if err == nil && !ok {
+ return errors.New("ssh: could not start shell")
+ }
+ if err != nil {
+ return err
+ }
+ return s.start()
+}
+
+func (s *Session) start() error {
+ s.started = true
+
+ type F func(*Session)
+ for _, setupFd := range []F{(*Session).stdin, (*Session).stdout, (*Session).stderr} {
+ setupFd(s)
+ }
+
+ s.errors = make(chan error, len(s.copyFuncs))
+ for _, fn := range s.copyFuncs {
+ go func(fn func() error) {
+ s.errors <- fn()
+ }(fn)
+ }
+ return nil
+}
+
+// Wait waits for the remote command to exit.
+//
+// The returned error is nil if the command runs, has no problems
+// copying stdin, stdout, and stderr, and exits with a zero exit
+// status.
+//
+// If the remote server does not send an exit status, an error of type
+// *ExitMissingError is returned. If the command completes
+// unsuccessfully or is interrupted by a signal, the error is of type
+// *ExitError. Other error types may be returned for I/O problems.
+func (s *Session) Wait() error {
+ if !s.started {
+ return errors.New("ssh: session not started")
+ }
+ waitErr := <-s.exitStatus
+
+ if s.stdinPipeWriter != nil {
+ s.stdinPipeWriter.Close()
+ }
+ var copyError error
+ for _ = range s.copyFuncs {
+ if err := <-s.errors; err != nil && copyError == nil {
+ copyError = err
+ }
+ }
+ if waitErr != nil {
+ return waitErr
+ }
+ return copyError
+}
+
+func (s *Session) wait(reqs <-chan *Request) error {
+ wm := Waitmsg{status: -1}
+ // Wait for msg channel to be closed before returning.
+ for msg := range reqs {
+ switch msg.Type {
+ case "exit-status":
+ wm.status = int(binary.BigEndian.Uint32(msg.Payload))
+ case "exit-signal":
+ var sigval struct {
+ Signal string
+ CoreDumped bool
+ Error string
+ Lang string
+ }
+ if err := Unmarshal(msg.Payload, &sigval); err != nil {
+ return err
+ }
+
+ // Must sanitize strings?
+ wm.signal = sigval.Signal
+ wm.msg = sigval.Error
+ wm.lang = sigval.Lang
+ default:
+ // This handles keepalives and matches
+ // OpenSSH's behaviour.
+ if msg.WantReply {
+ msg.Reply(false, nil)
+ }
+ }
+ }
+ if wm.status == 0 {
+ return nil
+ }
+ if wm.status == -1 {
+ // exit-status was never sent from server
+ if wm.signal == "" {
+ // signal was not sent either. RFC 4254
+ // section 6.10 recommends against this
+ // behavior, but it is allowed, so we let
+ // clients handle it.
+ return &ExitMissingError{}
+ }
+ wm.status = 128
+ if _, ok := signals[Signal(wm.signal)]; ok {
+ wm.status += signals[Signal(wm.signal)]
+ }
+ }
+
+ return &ExitError{wm}
+}
+
+// ExitMissingError is returned if a session is torn down cleanly, but
+// the server sends no confirmation of the exit status.
+type ExitMissingError struct{}
+
+func (e *ExitMissingError) Error() string {
+ return "wait: remote command exited without exit status or exit signal"
+}
+
+func (s *Session) stdin() {
+ if s.stdinpipe {
+ return
+ }
+ var stdin io.Reader
+ if s.Stdin == nil {
+ stdin = new(bytes.Buffer)
+ } else {
+ r, w := io.Pipe()
+ go func() {
+ _, err := io.Copy(w, s.Stdin)
+ w.CloseWithError(err)
+ }()
+ stdin, s.stdinPipeWriter = r, w
+ }
+ s.copyFuncs = append(s.copyFuncs, func() error {
+ _, err := io.Copy(s.ch, stdin)
+ if err1 := s.ch.CloseWrite(); err == nil && err1 != io.EOF {
+ err = err1
+ }
+ return err
+ })
+}
+
+func (s *Session) stdout() {
+ if s.stdoutpipe {
+ return
+ }
+ if s.Stdout == nil {
+ s.Stdout = ioutil.Discard
+ }
+ s.copyFuncs = append(s.copyFuncs, func() error {
+ _, err := io.Copy(s.Stdout, s.ch)
+ return err
+ })
+}
+
+func (s *Session) stderr() {
+ if s.stderrpipe {
+ return
+ }
+ if s.Stderr == nil {
+ s.Stderr = ioutil.Discard
+ }
+ s.copyFuncs = append(s.copyFuncs, func() error {
+ _, err := io.Copy(s.Stderr, s.ch.Stderr())
+ return err
+ })
+}
+
+// sessionStdin reroutes Close to CloseWrite.
+type sessionStdin struct {
+ io.Writer
+ ch Channel
+}
+
+func (s *sessionStdin) Close() error {
+ return s.ch.CloseWrite()
+}
+
+// StdinPipe returns a pipe that will be connected to the
+// remote command's standard input when the command starts.
+func (s *Session) StdinPipe() (io.WriteCloser, error) {
+ if s.Stdin != nil {
+ return nil, errors.New("ssh: Stdin already set")
+ }
+ if s.started {
+ return nil, errors.New("ssh: StdinPipe after process started")
+ }
+ s.stdinpipe = true
+ return &sessionStdin{s.ch, s.ch}, nil
+}
+
+// StdoutPipe returns a pipe that will be connected to the
+// remote command's standard output when the command starts.
+// There is a fixed amount of buffering that is shared between
+// stdout and stderr streams. If the StdoutPipe reader is
+// not serviced fast enough it may eventually cause the
+// remote command to block.
+func (s *Session) StdoutPipe() (io.Reader, error) {
+ if s.Stdout != nil {
+ return nil, errors.New("ssh: Stdout already set")
+ }
+ if s.started {
+ return nil, errors.New("ssh: StdoutPipe after process started")
+ }
+ s.stdoutpipe = true
+ return s.ch, nil
+}
+
+// StderrPipe returns a pipe that will be connected to the
+// remote command's standard error when the command starts.
+// There is a fixed amount of buffering that is shared between
+// stdout and stderr streams. If the StderrPipe reader is
+// not serviced fast enough it may eventually cause the
+// remote command to block.
+func (s *Session) StderrPipe() (io.Reader, error) {
+ if s.Stderr != nil {
+ return nil, errors.New("ssh: Stderr already set")
+ }
+ if s.started {
+ return nil, errors.New("ssh: StderrPipe after process started")
+ }
+ s.stderrpipe = true
+ return s.ch.Stderr(), nil
+}
+
+// newSession returns a new interactive session on the remote host.
+func newSession(ch Channel, reqs <-chan *Request) (*Session, error) {
+ s := &Session{
+ ch: ch,
+ }
+ s.exitStatus = make(chan error, 1)
+ go func() {
+ s.exitStatus <- s.wait(reqs)
+ }()
+
+ return s, nil
+}
+
+// An ExitError reports unsuccessful completion of a remote command.
+type ExitError struct {
+ Waitmsg
+}
+
+func (e *ExitError) Error() string {
+ return e.Waitmsg.String()
+}
+
+// Waitmsg stores the information about an exited remote command
+// as reported by Wait.
+type Waitmsg struct {
+ status int
+ signal string
+ msg string
+ lang string
+}
+
+// ExitStatus returns the exit status of the remote command.
+func (w Waitmsg) ExitStatus() int {
+ return w.status
+}
+
+// Signal returns the exit signal of the remote command if
+// it was terminated violently.
+func (w Waitmsg) Signal() string {
+ return w.signal
+}
+
+// Msg returns the exit message given by the remote command
+func (w Waitmsg) Msg() string {
+ return w.msg
+}
+
+// Lang returns the language tag. See RFC 3066
+func (w Waitmsg) Lang() string {
+ return w.lang
+}
+
+func (w Waitmsg) String() string {
+ str := fmt.Sprintf("Process exited with status %v", w.status)
+ if w.signal != "" {
+ str += fmt.Sprintf(" from signal %v", w.signal)
+ }
+ if w.msg != "" {
+ str += fmt.Sprintf(". Reason was: %v", w.msg)
+ }
+ return str
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/session_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/session_test.go
new file mode 100644
index 000000000..7dce6dd69
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/session_test.go
@@ -0,0 +1,774 @@
+// Copyright 2011 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 ssh
+
+// Session tests.
+
+import (
+ "bytes"
+ crypto_rand "crypto/rand"
+ "errors"
+ "io"
+ "io/ioutil"
+ "math/rand"
+ "net"
+ "testing"
+
+ "golang.org/x/crypto/ssh/terminal"
+)
+
+type serverType func(Channel, <-chan *Request, *testing.T)
+
+// dial constructs a new test server and returns a *ClientConn.
+func dial(handler serverType, t *testing.T) *Client {
+ c1, c2, err := netPipe()
+ if err != nil {
+ t.Fatalf("netPipe: %v", err)
+ }
+
+ go func() {
+ defer c1.Close()
+ conf := ServerConfig{
+ NoClientAuth: true,
+ }
+ conf.AddHostKey(testSigners["rsa"])
+
+ _, chans, reqs, err := NewServerConn(c1, &conf)
+ if err != nil {
+ t.Fatalf("Unable to handshake: %v", err)
+ }
+ go DiscardRequests(reqs)
+
+ for newCh := range chans {
+ if newCh.ChannelType() != "session" {
+ newCh.Reject(UnknownChannelType, "unknown channel type")
+ continue
+ }
+
+ ch, inReqs, err := newCh.Accept()
+ if err != nil {
+ t.Errorf("Accept: %v", err)
+ continue
+ }
+ go func() {
+ handler(ch, inReqs, t)
+ }()
+ }
+ }()
+
+ config := &ClientConfig{
+ User: "testuser",
+ HostKeyCallback: InsecureIgnoreHostKey(),
+ }
+
+ conn, chans, reqs, err := NewClientConn(c2, "", config)
+ if err != nil {
+ t.Fatalf("unable to dial remote side: %v", err)
+ }
+
+ return NewClient(conn, chans, reqs)
+}
+
+// Test a simple string is returned to session.Stdout.
+func TestSessionShell(t *testing.T) {
+ conn := dial(shellHandler, t)
+ defer conn.Close()
+ session, err := conn.NewSession()
+ if err != nil {
+ t.Fatalf("Unable to request new session: %v", err)
+ }
+ defer session.Close()
+ stdout := new(bytes.Buffer)
+ session.Stdout = stdout
+ if err := session.Shell(); err != nil {
+ t.Fatalf("Unable to execute command: %s", err)
+ }
+ if err := session.Wait(); err != nil {
+ t.Fatalf("Remote command did not exit cleanly: %v", err)
+ }
+ actual := stdout.String()
+ if actual != "golang" {
+ t.Fatalf("Remote shell did not return expected string: expected=golang, actual=%s", actual)
+ }
+}
+
+// TODO(dfc) add support for Std{in,err}Pipe when the Server supports it.
+
+// Test a simple string is returned via StdoutPipe.
+func TestSessionStdoutPipe(t *testing.T) {
+ conn := dial(shellHandler, t)
+ defer conn.Close()
+ session, err := conn.NewSession()
+ if err != nil {
+ t.Fatalf("Unable to request new session: %v", err)
+ }
+ defer session.Close()
+ stdout, err := session.StdoutPipe()
+ if err != nil {
+ t.Fatalf("Unable to request StdoutPipe(): %v", err)
+ }
+ var buf bytes.Buffer
+ if err := session.Shell(); err != nil {
+ t.Fatalf("Unable to execute command: %v", err)
+ }
+ done := make(chan bool, 1)
+ go func() {
+ if _, err := io.Copy(&buf, stdout); err != nil {
+ t.Errorf("Copy of stdout failed: %v", err)
+ }
+ done <- true
+ }()
+ if err := session.Wait(); err != nil {
+ t.Fatalf("Remote command did not exit cleanly: %v", err)
+ }
+ <-done
+ actual := buf.String()
+ if actual != "golang" {
+ t.Fatalf("Remote shell did not return expected string: expected=golang, actual=%s", actual)
+ }
+}
+
+// Test that a simple string is returned via the Output helper,
+// and that stderr is discarded.
+func TestSessionOutput(t *testing.T) {
+ conn := dial(fixedOutputHandler, t)
+ defer conn.Close()
+ session, err := conn.NewSession()
+ if err != nil {
+ t.Fatalf("Unable to request new session: %v", err)
+ }
+ defer session.Close()
+
+ buf, err := session.Output("") // cmd is ignored by fixedOutputHandler
+ if err != nil {
+ t.Error("Remote command did not exit cleanly:", err)
+ }
+ w := "this-is-stdout."
+ g := string(buf)
+ if g != w {
+ t.Error("Remote command did not return expected string:")
+ t.Logf("want %q", w)
+ t.Logf("got %q", g)
+ }
+}
+
+// Test that both stdout and stderr are returned
+// via the CombinedOutput helper.
+func TestSessionCombinedOutput(t *testing.T) {
+ conn := dial(fixedOutputHandler, t)
+ defer conn.Close()
+ session, err := conn.NewSession()
+ if err != nil {
+ t.Fatalf("Unable to request new session: %v", err)
+ }
+ defer session.Close()
+
+ buf, err := session.CombinedOutput("") // cmd is ignored by fixedOutputHandler
+ if err != nil {
+ t.Error("Remote command did not exit cleanly:", err)
+ }
+ const stdout = "this-is-stdout."
+ const stderr = "this-is-stderr."
+ g := string(buf)
+ if g != stdout+stderr && g != stderr+stdout {
+ t.Error("Remote command did not return expected string:")
+ t.Logf("want %q, or %q", stdout+stderr, stderr+stdout)
+ t.Logf("got %q", g)
+ }
+}
+
+// Test non-0 exit status is returned correctly.
+func TestExitStatusNonZero(t *testing.T) {
+ conn := dial(exitStatusNonZeroHandler, t)
+ defer conn.Close()
+ session, err := conn.NewSession()
+ if err != nil {
+ t.Fatalf("Unable to request new session: %v", err)
+ }
+ defer session.Close()
+ if err := session.Shell(); err != nil {
+ t.Fatalf("Unable to execute command: %v", err)
+ }
+ err = session.Wait()
+ if err == nil {
+ t.Fatalf("expected command to fail but it didn't")
+ }
+ e, ok := err.(*ExitError)
+ if !ok {
+ t.Fatalf("expected *ExitError but got %T", err)
+ }
+ if e.ExitStatus() != 15 {
+ t.Fatalf("expected command to exit with 15 but got %v", e.ExitStatus())
+ }
+}
+
+// Test 0 exit status is returned correctly.
+func TestExitStatusZero(t *testing.T) {
+ conn := dial(exitStatusZeroHandler, t)
+ defer conn.Close()
+ session, err := conn.NewSession()
+ if err != nil {
+ t.Fatalf("Unable to request new session: %v", err)
+ }
+ defer session.Close()
+
+ if err := session.Shell(); err != nil {
+ t.Fatalf("Unable to execute command: %v", err)
+ }
+ err = session.Wait()
+ if err != nil {
+ t.Fatalf("expected nil but got %v", err)
+ }
+}
+
+// Test exit signal and status are both returned correctly.
+func TestExitSignalAndStatus(t *testing.T) {
+ conn := dial(exitSignalAndStatusHandler, t)
+ defer conn.Close()
+ session, err := conn.NewSession()
+ if err != nil {
+ t.Fatalf("Unable to request new session: %v", err)
+ }
+ defer session.Close()
+ if err := session.Shell(); err != nil {
+ t.Fatalf("Unable to execute command: %v", err)
+ }
+ err = session.Wait()
+ if err == nil {
+ t.Fatalf("expected command to fail but it didn't")
+ }
+ e, ok := err.(*ExitError)
+ if !ok {
+ t.Fatalf("expected *ExitError but got %T", err)
+ }
+ if e.Signal() != "TERM" || e.ExitStatus() != 15 {
+ t.Fatalf("expected command to exit with signal TERM and status 15 but got signal %s and status %v", e.Signal(), e.ExitStatus())
+ }
+}
+
+// Test exit signal and status are both returned correctly.
+func TestKnownExitSignalOnly(t *testing.T) {
+ conn := dial(exitSignalHandler, t)
+ defer conn.Close()
+ session, err := conn.NewSession()
+ if err != nil {
+ t.Fatalf("Unable to request new session: %v", err)
+ }
+ defer session.Close()
+ if err := session.Shell(); err != nil {
+ t.Fatalf("Unable to execute command: %v", err)
+ }
+ err = session.Wait()
+ if err == nil {
+ t.Fatalf("expected command to fail but it didn't")
+ }
+ e, ok := err.(*ExitError)
+ if !ok {
+ t.Fatalf("expected *ExitError but got %T", err)
+ }
+ if e.Signal() != "TERM" || e.ExitStatus() != 143 {
+ t.Fatalf("expected command to exit with signal TERM and status 143 but got signal %s and status %v", e.Signal(), e.ExitStatus())
+ }
+}
+
+// Test exit signal and status are both returned correctly.
+func TestUnknownExitSignal(t *testing.T) {
+ conn := dial(exitSignalUnknownHandler, t)
+ defer conn.Close()
+ session, err := conn.NewSession()
+ if err != nil {
+ t.Fatalf("Unable to request new session: %v", err)
+ }
+ defer session.Close()
+ if err := session.Shell(); err != nil {
+ t.Fatalf("Unable to execute command: %v", err)
+ }
+ err = session.Wait()
+ if err == nil {
+ t.Fatalf("expected command to fail but it didn't")
+ }
+ e, ok := err.(*ExitError)
+ if !ok {
+ t.Fatalf("expected *ExitError but got %T", err)
+ }
+ if e.Signal() != "SYS" || e.ExitStatus() != 128 {
+ t.Fatalf("expected command to exit with signal SYS and status 128 but got signal %s and status %v", e.Signal(), e.ExitStatus())
+ }
+}
+
+func TestExitWithoutStatusOrSignal(t *testing.T) {
+ conn := dial(exitWithoutSignalOrStatus, t)
+ defer conn.Close()
+ session, err := conn.NewSession()
+ if err != nil {
+ t.Fatalf("Unable to request new session: %v", err)
+ }
+ defer session.Close()
+ if err := session.Shell(); err != nil {
+ t.Fatalf("Unable to execute command: %v", err)
+ }
+ err = session.Wait()
+ if err == nil {
+ t.Fatalf("expected command to fail but it didn't")
+ }
+ if _, ok := err.(*ExitMissingError); !ok {
+ t.Fatalf("got %T want *ExitMissingError", err)
+ }
+}
+
+// windowTestBytes is the number of bytes that we'll send to the SSH server.
+const windowTestBytes = 16000 * 200
+
+// TestServerWindow writes random data to the server. The server is expected to echo
+// the same data back, which is compared against the original.
+func TestServerWindow(t *testing.T) {
+ origBuf := bytes.NewBuffer(make([]byte, 0, windowTestBytes))
+ io.CopyN(origBuf, crypto_rand.Reader, windowTestBytes)
+ origBytes := origBuf.Bytes()
+
+ conn := dial(echoHandler, t)
+ defer conn.Close()
+ session, err := conn.NewSession()
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer session.Close()
+ result := make(chan []byte)
+
+ go func() {
+ defer close(result)
+ echoedBuf := bytes.NewBuffer(make([]byte, 0, windowTestBytes))
+ serverStdout, err := session.StdoutPipe()
+ if err != nil {
+ t.Errorf("StdoutPipe failed: %v", err)
+ return
+ }
+ n, err := copyNRandomly("stdout", echoedBuf, serverStdout, windowTestBytes)
+ if err != nil && err != io.EOF {
+ t.Errorf("Read only %d bytes from server, expected %d: %v", n, windowTestBytes, err)
+ }
+ result <- echoedBuf.Bytes()
+ }()
+
+ serverStdin, err := session.StdinPipe()
+ if err != nil {
+ t.Fatalf("StdinPipe failed: %v", err)
+ }
+ written, err := copyNRandomly("stdin", serverStdin, origBuf, windowTestBytes)
+ if err != nil {
+ t.Fatalf("failed to copy origBuf to serverStdin: %v", err)
+ }
+ if written != windowTestBytes {
+ t.Fatalf("Wrote only %d of %d bytes to server", written, windowTestBytes)
+ }
+
+ echoedBytes := <-result
+
+ if !bytes.Equal(origBytes, echoedBytes) {
+ t.Fatalf("Echoed buffer differed from original, orig %d, echoed %d", len(origBytes), len(echoedBytes))
+ }
+}
+
+// Verify the client can handle a keepalive packet from the server.
+func TestClientHandlesKeepalives(t *testing.T) {
+ conn := dial(channelKeepaliveSender, t)
+ defer conn.Close()
+ session, err := conn.NewSession()
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer session.Close()
+ if err := session.Shell(); err != nil {
+ t.Fatalf("Unable to execute command: %v", err)
+ }
+ err = session.Wait()
+ if err != nil {
+ t.Fatalf("expected nil but got: %v", err)
+ }
+}
+
+type exitStatusMsg struct {
+ Status uint32
+}
+
+type exitSignalMsg struct {
+ Signal string
+ CoreDumped bool
+ Errmsg string
+ Lang string
+}
+
+func handleTerminalRequests(in <-chan *Request) {
+ for req := range in {
+ ok := false
+ switch req.Type {
+ case "shell":
+ ok = true
+ if len(req.Payload) > 0 {
+ // We don't accept any commands, only the default shell.
+ ok = false
+ }
+ case "env":
+ ok = true
+ }
+ req.Reply(ok, nil)
+ }
+}
+
+func newServerShell(ch Channel, in <-chan *Request, prompt string) *terminal.Terminal {
+ term := terminal.NewTerminal(ch, prompt)
+ go handleTerminalRequests(in)
+ return term
+}
+
+func exitStatusZeroHandler(ch Channel, in <-chan *Request, t *testing.T) {
+ defer ch.Close()
+ // this string is returned to stdout
+ shell := newServerShell(ch, in, "> ")
+ readLine(shell, t)
+ sendStatus(0, ch, t)
+}
+
+func exitStatusNonZeroHandler(ch Channel, in <-chan *Request, t *testing.T) {
+ defer ch.Close()
+ shell := newServerShell(ch, in, "> ")
+ readLine(shell, t)
+ sendStatus(15, ch, t)
+}
+
+func exitSignalAndStatusHandler(ch Channel, in <-chan *Request, t *testing.T) {
+ defer ch.Close()
+ shell := newServerShell(ch, in, "> ")
+ readLine(shell, t)
+ sendStatus(15, ch, t)
+ sendSignal("TERM", ch, t)
+}
+
+func exitSignalHandler(ch Channel, in <-chan *Request, t *testing.T) {
+ defer ch.Close()
+ shell := newServerShell(ch, in, "> ")
+ readLine(shell, t)
+ sendSignal("TERM", ch, t)
+}
+
+func exitSignalUnknownHandler(ch Channel, in <-chan *Request, t *testing.T) {
+ defer ch.Close()
+ shell := newServerShell(ch, in, "> ")
+ readLine(shell, t)
+ sendSignal("SYS", ch, t)
+}
+
+func exitWithoutSignalOrStatus(ch Channel, in <-chan *Request, t *testing.T) {
+ defer ch.Close()
+ shell := newServerShell(ch, in, "> ")
+ readLine(shell, t)
+}
+
+func shellHandler(ch Channel, in <-chan *Request, t *testing.T) {
+ defer ch.Close()
+ // this string is returned to stdout
+ shell := newServerShell(ch, in, "golang")
+ readLine(shell, t)
+ sendStatus(0, ch, t)
+}
+
+// Ignores the command, writes fixed strings to stderr and stdout.
+// Strings are "this-is-stdout." and "this-is-stderr.".
+func fixedOutputHandler(ch Channel, in <-chan *Request, t *testing.T) {
+ defer ch.Close()
+ _, err := ch.Read(nil)
+
+ req, ok := <-in
+ if !ok {
+ t.Fatalf("error: expected channel request, got: %#v", err)
+ return
+ }
+
+ // ignore request, always send some text
+ req.Reply(true, nil)
+
+ _, err = io.WriteString(ch, "this-is-stdout.")
+ if err != nil {
+ t.Fatalf("error writing on server: %v", err)
+ }
+ _, err = io.WriteString(ch.Stderr(), "this-is-stderr.")
+ if err != nil {
+ t.Fatalf("error writing on server: %v", err)
+ }
+ sendStatus(0, ch, t)
+}
+
+func readLine(shell *terminal.Terminal, t *testing.T) {
+ if _, err := shell.ReadLine(); err != nil && err != io.EOF {
+ t.Errorf("unable to read line: %v", err)
+ }
+}
+
+func sendStatus(status uint32, ch Channel, t *testing.T) {
+ msg := exitStatusMsg{
+ Status: status,
+ }
+ if _, err := ch.SendRequest("exit-status", false, Marshal(&msg)); err != nil {
+ t.Errorf("unable to send status: %v", err)
+ }
+}
+
+func sendSignal(signal string, ch Channel, t *testing.T) {
+ sig := exitSignalMsg{
+ Signal: signal,
+ CoreDumped: false,
+ Errmsg: "Process terminated",
+ Lang: "en-GB-oed",
+ }
+ if _, err := ch.SendRequest("exit-signal", false, Marshal(&sig)); err != nil {
+ t.Errorf("unable to send signal: %v", err)
+ }
+}
+
+func discardHandler(ch Channel, t *testing.T) {
+ defer ch.Close()
+ io.Copy(ioutil.Discard, ch)
+}
+
+func echoHandler(ch Channel, in <-chan *Request, t *testing.T) {
+ defer ch.Close()
+ if n, err := copyNRandomly("echohandler", ch, ch, windowTestBytes); err != nil {
+ t.Errorf("short write, wrote %d, expected %d: %v ", n, windowTestBytes, err)
+ }
+}
+
+// copyNRandomly copies n bytes from src to dst. It uses a variable, and random,
+// buffer size to exercise more code paths.
+func copyNRandomly(title string, dst io.Writer, src io.Reader, n int) (int, error) {
+ var (
+ buf = make([]byte, 32*1024)
+ written int
+ remaining = n
+ )
+ for remaining > 0 {
+ l := rand.Intn(1 << 15)
+ if remaining < l {
+ l = remaining
+ }
+ nr, er := src.Read(buf[:l])
+ nw, ew := dst.Write(buf[:nr])
+ remaining -= nw
+ written += nw
+ if ew != nil {
+ return written, ew
+ }
+ if nr != nw {
+ return written, io.ErrShortWrite
+ }
+ if er != nil && er != io.EOF {
+ return written, er
+ }
+ }
+ return written, nil
+}
+
+func channelKeepaliveSender(ch Channel, in <-chan *Request, t *testing.T) {
+ defer ch.Close()
+ shell := newServerShell(ch, in, "> ")
+ readLine(shell, t)
+ if _, err := ch.SendRequest("keepalive@openssh.com", true, nil); err != nil {
+ t.Errorf("unable to send channel keepalive request: %v", err)
+ }
+ sendStatus(0, ch, t)
+}
+
+func TestClientWriteEOF(t *testing.T) {
+ conn := dial(simpleEchoHandler, t)
+ defer conn.Close()
+
+ session, err := conn.NewSession()
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer session.Close()
+ stdin, err := session.StdinPipe()
+ if err != nil {
+ t.Fatalf("StdinPipe failed: %v", err)
+ }
+ stdout, err := session.StdoutPipe()
+ if err != nil {
+ t.Fatalf("StdoutPipe failed: %v", err)
+ }
+
+ data := []byte(`0000`)
+ _, err = stdin.Write(data)
+ if err != nil {
+ t.Fatalf("Write failed: %v", err)
+ }
+ stdin.Close()
+
+ res, err := ioutil.ReadAll(stdout)
+ if err != nil {
+ t.Fatalf("Read failed: %v", err)
+ }
+
+ if !bytes.Equal(data, res) {
+ t.Fatalf("Read differed from write, wrote: %v, read: %v", data, res)
+ }
+}
+
+func simpleEchoHandler(ch Channel, in <-chan *Request, t *testing.T) {
+ defer ch.Close()
+ data, err := ioutil.ReadAll(ch)
+ if err != nil {
+ t.Errorf("handler read error: %v", err)
+ }
+ _, err = ch.Write(data)
+ if err != nil {
+ t.Errorf("handler write error: %v", err)
+ }
+}
+
+func TestSessionID(t *testing.T) {
+ c1, c2, err := netPipe()
+ if err != nil {
+ t.Fatalf("netPipe: %v", err)
+ }
+ defer c1.Close()
+ defer c2.Close()
+
+ serverID := make(chan []byte, 1)
+ clientID := make(chan []byte, 1)
+
+ serverConf := &ServerConfig{
+ NoClientAuth: true,
+ }
+ serverConf.AddHostKey(testSigners["ecdsa"])
+ clientConf := &ClientConfig{
+ HostKeyCallback: InsecureIgnoreHostKey(),
+ User: "user",
+ }
+
+ go func() {
+ conn, chans, reqs, err := NewServerConn(c1, serverConf)
+ if err != nil {
+ t.Fatalf("server handshake: %v", err)
+ }
+ serverID <- conn.SessionID()
+ go DiscardRequests(reqs)
+ for ch := range chans {
+ ch.Reject(Prohibited, "")
+ }
+ }()
+
+ go func() {
+ conn, chans, reqs, err := NewClientConn(c2, "", clientConf)
+ if err != nil {
+ t.Fatalf("client handshake: %v", err)
+ }
+ clientID <- conn.SessionID()
+ go DiscardRequests(reqs)
+ for ch := range chans {
+ ch.Reject(Prohibited, "")
+ }
+ }()
+
+ s := <-serverID
+ c := <-clientID
+ if bytes.Compare(s, c) != 0 {
+ t.Errorf("server session ID (%x) != client session ID (%x)", s, c)
+ } else if len(s) == 0 {
+ t.Errorf("client and server SessionID were empty.")
+ }
+}
+
+type noReadConn struct {
+ readSeen bool
+ net.Conn
+}
+
+func (c *noReadConn) Close() error {
+ return nil
+}
+
+func (c *noReadConn) Read(b []byte) (int, error) {
+ c.readSeen = true
+ return 0, errors.New("noReadConn error")
+}
+
+func TestInvalidServerConfiguration(t *testing.T) {
+ c1, c2, err := netPipe()
+ if err != nil {
+ t.Fatalf("netPipe: %v", err)
+ }
+ defer c1.Close()
+ defer c2.Close()
+
+ serveConn := noReadConn{Conn: c1}
+ serverConf := &ServerConfig{}
+
+ NewServerConn(&serveConn, serverConf)
+ if serveConn.readSeen {
+ t.Fatalf("NewServerConn attempted to Read() from Conn while configuration is missing host key")
+ }
+
+ serverConf.AddHostKey(testSigners["ecdsa"])
+
+ NewServerConn(&serveConn, serverConf)
+ if serveConn.readSeen {
+ t.Fatalf("NewServerConn attempted to Read() from Conn while configuration is missing authentication method")
+ }
+}
+
+func TestHostKeyAlgorithms(t *testing.T) {
+ serverConf := &ServerConfig{
+ NoClientAuth: true,
+ }
+ serverConf.AddHostKey(testSigners["rsa"])
+ serverConf.AddHostKey(testSigners["ecdsa"])
+
+ connect := func(clientConf *ClientConfig, want string) {
+ var alg string
+ clientConf.HostKeyCallback = func(h string, a net.Addr, key PublicKey) error {
+ alg = key.Type()
+ return nil
+ }
+ c1, c2, err := netPipe()
+ if err != nil {
+ t.Fatalf("netPipe: %v", err)
+ }
+ defer c1.Close()
+ defer c2.Close()
+
+ go NewServerConn(c1, serverConf)
+ _, _, _, err = NewClientConn(c2, "", clientConf)
+ if err != nil {
+ t.Fatalf("NewClientConn: %v", err)
+ }
+ if alg != want {
+ t.Errorf("selected key algorithm %s, want %s", alg, want)
+ }
+ }
+
+ // By default, we get the preferred algorithm, which is ECDSA 256.
+
+ clientConf := &ClientConfig{
+ HostKeyCallback: InsecureIgnoreHostKey(),
+ }
+ connect(clientConf, KeyAlgoECDSA256)
+
+ // Client asks for RSA explicitly.
+ clientConf.HostKeyAlgorithms = []string{KeyAlgoRSA}
+ connect(clientConf, KeyAlgoRSA)
+
+ c1, c2, err := netPipe()
+ if err != nil {
+ t.Fatalf("netPipe: %v", err)
+ }
+ defer c1.Close()
+ defer c2.Close()
+
+ go NewServerConn(c1, serverConf)
+ clientConf.HostKeyAlgorithms = []string{"nonexistent-hostkey-algo"}
+ _, _, _, err = NewClientConn(c2, "", clientConf)
+ if err == nil {
+ t.Fatal("succeeded connecting with unknown hostkey algorithm")
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/streamlocal.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/streamlocal.go
new file mode 100644
index 000000000..a2dccc64c
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/streamlocal.go
@@ -0,0 +1,115 @@
+package ssh
+
+import (
+ "errors"
+ "io"
+ "net"
+)
+
+// streamLocalChannelOpenDirectMsg is a struct used for SSH_MSG_CHANNEL_OPEN message
+// with "direct-streamlocal@openssh.com" string.
+//
+// See openssh-portable/PROTOCOL, section 2.4. connection: Unix domain socket forwarding
+// https://github.com/openssh/openssh-portable/blob/master/PROTOCOL#L235
+type streamLocalChannelOpenDirectMsg struct {
+ socketPath string
+ reserved0 string
+ reserved1 uint32
+}
+
+// forwardedStreamLocalPayload is a struct used for SSH_MSG_CHANNEL_OPEN message
+// with "forwarded-streamlocal@openssh.com" string.
+type forwardedStreamLocalPayload struct {
+ SocketPath string
+ Reserved0 string
+}
+
+// streamLocalChannelForwardMsg is a struct used for SSH2_MSG_GLOBAL_REQUEST message
+// with "streamlocal-forward@openssh.com"/"cancel-streamlocal-forward@openssh.com" string.
+type streamLocalChannelForwardMsg struct {
+ socketPath string
+}
+
+// ListenUnix is similar to ListenTCP but uses a Unix domain socket.
+func (c *Client) ListenUnix(socketPath string) (net.Listener, error) {
+ m := streamLocalChannelForwardMsg{
+ socketPath,
+ }
+ // send message
+ ok, _, err := c.SendRequest("streamlocal-forward@openssh.com", true, Marshal(&m))
+ if err != nil {
+ return nil, err
+ }
+ if !ok {
+ return nil, errors.New("ssh: streamlocal-forward@openssh.com request denied by peer")
+ }
+ ch := c.forwards.add(&net.UnixAddr{Name: socketPath, Net: "unix"})
+
+ return &unixListener{socketPath, c, ch}, nil
+}
+
+func (c *Client) dialStreamLocal(socketPath string) (Channel, error) {
+ msg := streamLocalChannelOpenDirectMsg{
+ socketPath: socketPath,
+ }
+ ch, in, err := c.OpenChannel("direct-streamlocal@openssh.com", Marshal(&msg))
+ if err != nil {
+ return nil, err
+ }
+ go DiscardRequests(in)
+ return ch, err
+}
+
+type unixListener struct {
+ socketPath string
+
+ conn *Client
+ in <-chan forward
+}
+
+// Accept waits for and returns the next connection to the listener.
+func (l *unixListener) Accept() (net.Conn, error) {
+ s, ok := <-l.in
+ if !ok {
+ return nil, io.EOF
+ }
+ ch, incoming, err := s.newCh.Accept()
+ if err != nil {
+ return nil, err
+ }
+ go DiscardRequests(incoming)
+
+ return &chanConn{
+ Channel: ch,
+ laddr: &net.UnixAddr{
+ Name: l.socketPath,
+ Net: "unix",
+ },
+ raddr: &net.UnixAddr{
+ Name: "@",
+ Net: "unix",
+ },
+ }, nil
+}
+
+// Close closes the listener.
+func (l *unixListener) Close() error {
+ // this also closes the listener.
+ l.conn.forwards.remove(&net.UnixAddr{Name: l.socketPath, Net: "unix"})
+ m := streamLocalChannelForwardMsg{
+ l.socketPath,
+ }
+ ok, _, err := l.conn.SendRequest("cancel-streamlocal-forward@openssh.com", true, Marshal(&m))
+ if err == nil && !ok {
+ err = errors.New("ssh: cancel-streamlocal-forward@openssh.com failed")
+ }
+ return err
+}
+
+// Addr returns the listener's network address.
+func (l *unixListener) Addr() net.Addr {
+ return &net.UnixAddr{
+ Name: l.socketPath,
+ Net: "unix",
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/tcpip.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/tcpip.go
new file mode 100644
index 000000000..acf17175d
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/tcpip.go
@@ -0,0 +1,465 @@
+// Copyright 2011 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 ssh
+
+import (
+ "errors"
+ "fmt"
+ "io"
+ "math/rand"
+ "net"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+)
+
+// Listen requests the remote peer open a listening socket on
+// addr. Incoming connections will be available by calling Accept on
+// the returned net.Listener. The listener must be serviced, or the
+// SSH connection may hang.
+// N must be "tcp", "tcp4", "tcp6", or "unix".
+func (c *Client) Listen(n, addr string) (net.Listener, error) {
+ switch n {
+ case "tcp", "tcp4", "tcp6":
+ laddr, err := net.ResolveTCPAddr(n, addr)
+ if err != nil {
+ return nil, err
+ }
+ return c.ListenTCP(laddr)
+ case "unix":
+ return c.ListenUnix(addr)
+ default:
+ return nil, fmt.Errorf("ssh: unsupported protocol: %s", n)
+ }
+}
+
+// Automatic port allocation is broken with OpenSSH before 6.0. See
+// also https://bugzilla.mindrot.org/show_bug.cgi?id=2017. In
+// particular, OpenSSH 5.9 sends a channelOpenMsg with port number 0,
+// rather than the actual port number. This means you can never open
+// two different listeners with auto allocated ports. We work around
+// this by trying explicit ports until we succeed.
+
+const openSSHPrefix = "OpenSSH_"
+
+var portRandomizer = rand.New(rand.NewSource(time.Now().UnixNano()))
+
+// isBrokenOpenSSHVersion returns true if the given version string
+// specifies a version of OpenSSH that is known to have a bug in port
+// forwarding.
+func isBrokenOpenSSHVersion(versionStr string) bool {
+ i := strings.Index(versionStr, openSSHPrefix)
+ if i < 0 {
+ return false
+ }
+ i += len(openSSHPrefix)
+ j := i
+ for ; j < len(versionStr); j++ {
+ if versionStr[j] < '0' || versionStr[j] > '9' {
+ break
+ }
+ }
+ version, _ := strconv.Atoi(versionStr[i:j])
+ return version < 6
+}
+
+// autoPortListenWorkaround simulates automatic port allocation by
+// trying random ports repeatedly.
+func (c *Client) autoPortListenWorkaround(laddr *net.TCPAddr) (net.Listener, error) {
+ var sshListener net.Listener
+ var err error
+ const tries = 10
+ for i := 0; i < tries; i++ {
+ addr := *laddr
+ addr.Port = 1024 + portRandomizer.Intn(60000)
+ sshListener, err = c.ListenTCP(&addr)
+ if err == nil {
+ laddr.Port = addr.Port
+ return sshListener, err
+ }
+ }
+ return nil, fmt.Errorf("ssh: listen on random port failed after %d tries: %v", tries, err)
+}
+
+// RFC 4254 7.1
+type channelForwardMsg struct {
+ addr string
+ rport uint32
+}
+
+// ListenTCP requests the remote peer open a listening socket
+// on laddr. Incoming connections will be available by calling
+// Accept on the returned net.Listener.
+func (c *Client) ListenTCP(laddr *net.TCPAddr) (net.Listener, error) {
+ if laddr.Port == 0 && isBrokenOpenSSHVersion(string(c.ServerVersion())) {
+ return c.autoPortListenWorkaround(laddr)
+ }
+
+ m := channelForwardMsg{
+ laddr.IP.String(),
+ uint32(laddr.Port),
+ }
+ // send message
+ ok, resp, err := c.SendRequest("tcpip-forward", true, Marshal(&m))
+ if err != nil {
+ return nil, err
+ }
+ if !ok {
+ return nil, errors.New("ssh: tcpip-forward request denied by peer")
+ }
+
+ // If the original port was 0, then the remote side will
+ // supply a real port number in the response.
+ if laddr.Port == 0 {
+ var p struct {
+ Port uint32
+ }
+ if err := Unmarshal(resp, &p); err != nil {
+ return nil, err
+ }
+ laddr.Port = int(p.Port)
+ }
+
+ // Register this forward, using the port number we obtained.
+ ch := c.forwards.add(laddr)
+
+ return &tcpListener{laddr, c, ch}, nil
+}
+
+// forwardList stores a mapping between remote
+// forward requests and the tcpListeners.
+type forwardList struct {
+ sync.Mutex
+ entries []forwardEntry
+}
+
+// forwardEntry represents an established mapping of a laddr on a
+// remote ssh server to a channel connected to a tcpListener.
+type forwardEntry struct {
+ laddr net.Addr
+ c chan forward
+}
+
+// forward represents an incoming forwarded tcpip connection. The
+// arguments to add/remove/lookup should be address as specified in
+// the original forward-request.
+type forward struct {
+ newCh NewChannel // the ssh client channel underlying this forward
+ raddr net.Addr // the raddr of the incoming connection
+}
+
+func (l *forwardList) add(addr net.Addr) chan forward {
+ l.Lock()
+ defer l.Unlock()
+ f := forwardEntry{
+ laddr: addr,
+ c: make(chan forward, 1),
+ }
+ l.entries = append(l.entries, f)
+ return f.c
+}
+
+// See RFC 4254, section 7.2
+type forwardedTCPPayload struct {
+ Addr string
+ Port uint32
+ OriginAddr string
+ OriginPort uint32
+}
+
+// parseTCPAddr parses the originating address from the remote into a *net.TCPAddr.
+func parseTCPAddr(addr string, port uint32) (*net.TCPAddr, error) {
+ if port == 0 || port > 65535 {
+ return nil, fmt.Errorf("ssh: port number out of range: %d", port)
+ }
+ ip := net.ParseIP(string(addr))
+ if ip == nil {
+ return nil, fmt.Errorf("ssh: cannot parse IP address %q", addr)
+ }
+ return &net.TCPAddr{IP: ip, Port: int(port)}, nil
+}
+
+func (l *forwardList) handleChannels(in <-chan NewChannel) {
+ for ch := range in {
+ var (
+ laddr net.Addr
+ raddr net.Addr
+ err error
+ )
+ switch channelType := ch.ChannelType(); channelType {
+ case "forwarded-tcpip":
+ var payload forwardedTCPPayload
+ if err = Unmarshal(ch.ExtraData(), &payload); err != nil {
+ ch.Reject(ConnectionFailed, "could not parse forwarded-tcpip payload: "+err.Error())
+ continue
+ }
+
+ // RFC 4254 section 7.2 specifies that incoming
+ // addresses should list the address, in string
+ // format. It is implied that this should be an IP
+ // address, as it would be impossible to connect to it
+ // otherwise.
+ laddr, err = parseTCPAddr(payload.Addr, payload.Port)
+ if err != nil {
+ ch.Reject(ConnectionFailed, err.Error())
+ continue
+ }
+ raddr, err = parseTCPAddr(payload.OriginAddr, payload.OriginPort)
+ if err != nil {
+ ch.Reject(ConnectionFailed, err.Error())
+ continue
+ }
+
+ case "forwarded-streamlocal@openssh.com":
+ var payload forwardedStreamLocalPayload
+ if err = Unmarshal(ch.ExtraData(), &payload); err != nil {
+ ch.Reject(ConnectionFailed, "could not parse forwarded-streamlocal@openssh.com payload: "+err.Error())
+ continue
+ }
+ laddr = &net.UnixAddr{
+ Name: payload.SocketPath,
+ Net: "unix",
+ }
+ raddr = &net.UnixAddr{
+ Name: "@",
+ Net: "unix",
+ }
+ default:
+ panic(fmt.Errorf("ssh: unknown channel type %s", channelType))
+ }
+ if ok := l.forward(laddr, raddr, ch); !ok {
+ // Section 7.2, implementations MUST reject spurious incoming
+ // connections.
+ ch.Reject(Prohibited, "no forward for address")
+ continue
+ }
+
+ }
+}
+
+// remove removes the forward entry, and the channel feeding its
+// listener.
+func (l *forwardList) remove(addr net.Addr) {
+ l.Lock()
+ defer l.Unlock()
+ for i, f := range l.entries {
+ if addr.Network() == f.laddr.Network() && addr.String() == f.laddr.String() {
+ l.entries = append(l.entries[:i], l.entries[i+1:]...)
+ close(f.c)
+ return
+ }
+ }
+}
+
+// closeAll closes and clears all forwards.
+func (l *forwardList) closeAll() {
+ l.Lock()
+ defer l.Unlock()
+ for _, f := range l.entries {
+ close(f.c)
+ }
+ l.entries = nil
+}
+
+func (l *forwardList) forward(laddr, raddr net.Addr, ch NewChannel) bool {
+ l.Lock()
+ defer l.Unlock()
+ for _, f := range l.entries {
+ if laddr.Network() == f.laddr.Network() && laddr.String() == f.laddr.String() {
+ f.c <- forward{newCh: ch, raddr: raddr}
+ return true
+ }
+ }
+ return false
+}
+
+type tcpListener struct {
+ laddr *net.TCPAddr
+
+ conn *Client
+ in <-chan forward
+}
+
+// Accept waits for and returns the next connection to the listener.
+func (l *tcpListener) Accept() (net.Conn, error) {
+ s, ok := <-l.in
+ if !ok {
+ return nil, io.EOF
+ }
+ ch, incoming, err := s.newCh.Accept()
+ if err != nil {
+ return nil, err
+ }
+ go DiscardRequests(incoming)
+
+ return &chanConn{
+ Channel: ch,
+ laddr: l.laddr,
+ raddr: s.raddr,
+ }, nil
+}
+
+// Close closes the listener.
+func (l *tcpListener) Close() error {
+ m := channelForwardMsg{
+ l.laddr.IP.String(),
+ uint32(l.laddr.Port),
+ }
+
+ // this also closes the listener.
+ l.conn.forwards.remove(l.laddr)
+ ok, _, err := l.conn.SendRequest("cancel-tcpip-forward", true, Marshal(&m))
+ if err == nil && !ok {
+ err = errors.New("ssh: cancel-tcpip-forward failed")
+ }
+ return err
+}
+
+// Addr returns the listener's network address.
+func (l *tcpListener) Addr() net.Addr {
+ return l.laddr
+}
+
+// Dial initiates a connection to the addr from the remote host.
+// The resulting connection has a zero LocalAddr() and RemoteAddr().
+func (c *Client) Dial(n, addr string) (net.Conn, error) {
+ var ch Channel
+ switch n {
+ case "tcp", "tcp4", "tcp6":
+ // Parse the address into host and numeric port.
+ host, portString, err := net.SplitHostPort(addr)
+ if err != nil {
+ return nil, err
+ }
+ port, err := strconv.ParseUint(portString, 10, 16)
+ if err != nil {
+ return nil, err
+ }
+ ch, err = c.dial(net.IPv4zero.String(), 0, host, int(port))
+ if err != nil {
+ return nil, err
+ }
+ // Use a zero address for local and remote address.
+ zeroAddr := &net.TCPAddr{
+ IP: net.IPv4zero,
+ Port: 0,
+ }
+ return &chanConn{
+ Channel: ch,
+ laddr: zeroAddr,
+ raddr: zeroAddr,
+ }, nil
+ case "unix":
+ var err error
+ ch, err = c.dialStreamLocal(addr)
+ if err != nil {
+ return nil, err
+ }
+ return &chanConn{
+ Channel: ch,
+ laddr: &net.UnixAddr{
+ Name: "@",
+ Net: "unix",
+ },
+ raddr: &net.UnixAddr{
+ Name: addr,
+ Net: "unix",
+ },
+ }, nil
+ default:
+ return nil, fmt.Errorf("ssh: unsupported protocol: %s", n)
+ }
+}
+
+// DialTCP connects to the remote address raddr on the network net,
+// which must be "tcp", "tcp4", or "tcp6". If laddr is not nil, it is used
+// as the local address for the connection.
+func (c *Client) DialTCP(n string, laddr, raddr *net.TCPAddr) (net.Conn, error) {
+ if laddr == nil {
+ laddr = &net.TCPAddr{
+ IP: net.IPv4zero,
+ Port: 0,
+ }
+ }
+ ch, err := c.dial(laddr.IP.String(), laddr.Port, raddr.IP.String(), raddr.Port)
+ if err != nil {
+ return nil, err
+ }
+ return &chanConn{
+ Channel: ch,
+ laddr: laddr,
+ raddr: raddr,
+ }, nil
+}
+
+// RFC 4254 7.2
+type channelOpenDirectMsg struct {
+ raddr string
+ rport uint32
+ laddr string
+ lport uint32
+}
+
+func (c *Client) dial(laddr string, lport int, raddr string, rport int) (Channel, error) {
+ msg := channelOpenDirectMsg{
+ raddr: raddr,
+ rport: uint32(rport),
+ laddr: laddr,
+ lport: uint32(lport),
+ }
+ ch, in, err := c.OpenChannel("direct-tcpip", Marshal(&msg))
+ if err != nil {
+ return nil, err
+ }
+ go DiscardRequests(in)
+ return ch, err
+}
+
+type tcpChan struct {
+ Channel // the backing channel
+}
+
+// chanConn fulfills the net.Conn interface without
+// the tcpChan having to hold laddr or raddr directly.
+type chanConn struct {
+ Channel
+ laddr, raddr net.Addr
+}
+
+// LocalAddr returns the local network address.
+func (t *chanConn) LocalAddr() net.Addr {
+ return t.laddr
+}
+
+// RemoteAddr returns the remote network address.
+func (t *chanConn) RemoteAddr() net.Addr {
+ return t.raddr
+}
+
+// SetDeadline sets the read and write deadlines associated
+// with the connection.
+func (t *chanConn) SetDeadline(deadline time.Time) error {
+ if err := t.SetReadDeadline(deadline); err != nil {
+ return err
+ }
+ return t.SetWriteDeadline(deadline)
+}
+
+// SetReadDeadline sets the read deadline.
+// A zero value for t means Read will not time out.
+// After the deadline, the error from Read will implement net.Error
+// with Timeout() == true.
+func (t *chanConn) SetReadDeadline(deadline time.Time) error {
+ // for compatibility with previous version,
+ // the error message contains "tcpChan"
+ return errors.New("ssh: tcpChan: deadline not supported")
+}
+
+// SetWriteDeadline exists to satisfy the net.Conn interface
+// but is not implemented by this type. It always returns an error.
+func (t *chanConn) SetWriteDeadline(deadline time.Time) error {
+ return errors.New("ssh: tcpChan: deadline not supported")
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/tcpip_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/tcpip_test.go
new file mode 100644
index 000000000..f1265cb49
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/tcpip_test.go
@@ -0,0 +1,20 @@
+// Copyright 2014 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 ssh
+
+import (
+ "testing"
+)
+
+func TestAutoPortListenBroken(t *testing.T) {
+ broken := "SSH-2.0-OpenSSH_5.9hh11"
+ works := "SSH-2.0-OpenSSH_6.1"
+ if !isBrokenOpenSSHVersion(broken) {
+ t.Errorf("version %q not marked as broken", broken)
+ }
+ if isBrokenOpenSSHVersion(works) {
+ t.Errorf("version %q marked as broken", works)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/terminal/terminal.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/terminal/terminal.go
new file mode 100644
index 000000000..18379a935
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/terminal/terminal.go
@@ -0,0 +1,951 @@
+// Copyright 2011 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 terminal
+
+import (
+ "bytes"
+ "io"
+ "sync"
+ "unicode/utf8"
+)
+
+// EscapeCodes contains escape sequences that can be written to the terminal in
+// order to achieve different styles of text.
+type EscapeCodes struct {
+ // Foreground colors
+ Black, Red, Green, Yellow, Blue, Magenta, Cyan, White []byte
+
+ // Reset all attributes
+ Reset []byte
+}
+
+var vt100EscapeCodes = EscapeCodes{
+ Black: []byte{keyEscape, '[', '3', '0', 'm'},
+ Red: []byte{keyEscape, '[', '3', '1', 'm'},
+ Green: []byte{keyEscape, '[', '3', '2', 'm'},
+ Yellow: []byte{keyEscape, '[', '3', '3', 'm'},
+ Blue: []byte{keyEscape, '[', '3', '4', 'm'},
+ Magenta: []byte{keyEscape, '[', '3', '5', 'm'},
+ Cyan: []byte{keyEscape, '[', '3', '6', 'm'},
+ White: []byte{keyEscape, '[', '3', '7', 'm'},
+
+ Reset: []byte{keyEscape, '[', '0', 'm'},
+}
+
+// Terminal contains the state for running a VT100 terminal that is capable of
+// reading lines of input.
+type Terminal struct {
+ // AutoCompleteCallback, if non-null, is called for each keypress with
+ // the full input line and the current position of the cursor (in
+ // bytes, as an index into |line|). If it returns ok=false, the key
+ // press is processed normally. Otherwise it returns a replacement line
+ // and the new cursor position.
+ AutoCompleteCallback func(line string, pos int, key rune) (newLine string, newPos int, ok bool)
+
+ // Escape contains a pointer to the escape codes for this terminal.
+ // It's always a valid pointer, although the escape codes themselves
+ // may be empty if the terminal doesn't support them.
+ Escape *EscapeCodes
+
+ // lock protects the terminal and the state in this object from
+ // concurrent processing of a key press and a Write() call.
+ lock sync.Mutex
+
+ c io.ReadWriter
+ prompt []rune
+
+ // line is the current line being entered.
+ line []rune
+ // pos is the logical position of the cursor in line
+ pos int
+ // echo is true if local echo is enabled
+ echo bool
+ // pasteActive is true iff there is a bracketed paste operation in
+ // progress.
+ pasteActive bool
+
+ // cursorX contains the current X value of the cursor where the left
+ // edge is 0. cursorY contains the row number where the first row of
+ // the current line is 0.
+ cursorX, cursorY int
+ // maxLine is the greatest value of cursorY so far.
+ maxLine int
+
+ termWidth, termHeight int
+
+ // outBuf contains the terminal data to be sent.
+ outBuf []byte
+ // remainder contains the remainder of any partial key sequences after
+ // a read. It aliases into inBuf.
+ remainder []byte
+ inBuf [256]byte
+
+ // history contains previously entered commands so that they can be
+ // accessed with the up and down keys.
+ history stRingBuffer
+ // historyIndex stores the currently accessed history entry, where zero
+ // means the immediately previous entry.
+ historyIndex int
+ // When navigating up and down the history it's possible to return to
+ // the incomplete, initial line. That value is stored in
+ // historyPending.
+ historyPending string
+}
+
+// NewTerminal runs a VT100 terminal on the given ReadWriter. If the ReadWriter is
+// a local terminal, that terminal must first have been put into raw mode.
+// prompt is a string that is written at the start of each input line (i.e.
+// "> ").
+func NewTerminal(c io.ReadWriter, prompt string) *Terminal {
+ return &Terminal{
+ Escape: &vt100EscapeCodes,
+ c: c,
+ prompt: []rune(prompt),
+ termWidth: 80,
+ termHeight: 24,
+ echo: true,
+ historyIndex: -1,
+ }
+}
+
+const (
+ keyCtrlD = 4
+ keyCtrlU = 21
+ keyEnter = '\r'
+ keyEscape = 27
+ keyBackspace = 127
+ keyUnknown = 0xd800 /* UTF-16 surrogate area */ + iota
+ keyUp
+ keyDown
+ keyLeft
+ keyRight
+ keyAltLeft
+ keyAltRight
+ keyHome
+ keyEnd
+ keyDeleteWord
+ keyDeleteLine
+ keyClearScreen
+ keyPasteStart
+ keyPasteEnd
+)
+
+var (
+ crlf = []byte{'\r', '\n'}
+ pasteStart = []byte{keyEscape, '[', '2', '0', '0', '~'}
+ pasteEnd = []byte{keyEscape, '[', '2', '0', '1', '~'}
+)
+
+// bytesToKey tries to parse a key sequence from b. If successful, it returns
+// the key and the remainder of the input. Otherwise it returns utf8.RuneError.
+func bytesToKey(b []byte, pasteActive bool) (rune, []byte) {
+ if len(b) == 0 {
+ return utf8.RuneError, nil
+ }
+
+ if !pasteActive {
+ switch b[0] {
+ case 1: // ^A
+ return keyHome, b[1:]
+ case 5: // ^E
+ return keyEnd, b[1:]
+ case 8: // ^H
+ return keyBackspace, b[1:]
+ case 11: // ^K
+ return keyDeleteLine, b[1:]
+ case 12: // ^L
+ return keyClearScreen, b[1:]
+ case 23: // ^W
+ return keyDeleteWord, b[1:]
+ }
+ }
+
+ if b[0] != keyEscape {
+ if !utf8.FullRune(b) {
+ return utf8.RuneError, b
+ }
+ r, l := utf8.DecodeRune(b)
+ return r, b[l:]
+ }
+
+ if !pasteActive && len(b) >= 3 && b[0] == keyEscape && b[1] == '[' {
+ switch b[2] {
+ case 'A':
+ return keyUp, b[3:]
+ case 'B':
+ return keyDown, b[3:]
+ case 'C':
+ return keyRight, b[3:]
+ case 'D':
+ return keyLeft, b[3:]
+ case 'H':
+ return keyHome, b[3:]
+ case 'F':
+ return keyEnd, b[3:]
+ }
+ }
+
+ if !pasteActive && len(b) >= 6 && b[0] == keyEscape && b[1] == '[' && b[2] == '1' && b[3] == ';' && b[4] == '3' {
+ switch b[5] {
+ case 'C':
+ return keyAltRight, b[6:]
+ case 'D':
+ return keyAltLeft, b[6:]
+ }
+ }
+
+ if !pasteActive && len(b) >= 6 && bytes.Equal(b[:6], pasteStart) {
+ return keyPasteStart, b[6:]
+ }
+
+ if pasteActive && len(b) >= 6 && bytes.Equal(b[:6], pasteEnd) {
+ return keyPasteEnd, b[6:]
+ }
+
+ // If we get here then we have a key that we don't recognise, or a
+ // partial sequence. It's not clear how one should find the end of a
+ // sequence without knowing them all, but it seems that [a-zA-Z~] only
+ // appears at the end of a sequence.
+ for i, c := range b[0:] {
+ if c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '~' {
+ return keyUnknown, b[i+1:]
+ }
+ }
+
+ return utf8.RuneError, b
+}
+
+// queue appends data to the end of t.outBuf
+func (t *Terminal) queue(data []rune) {
+ t.outBuf = append(t.outBuf, []byte(string(data))...)
+}
+
+var eraseUnderCursor = []rune{' ', keyEscape, '[', 'D'}
+var space = []rune{' '}
+
+func isPrintable(key rune) bool {
+ isInSurrogateArea := key >= 0xd800 && key <= 0xdbff
+ return key >= 32 && !isInSurrogateArea
+}
+
+// moveCursorToPos appends data to t.outBuf which will move the cursor to the
+// given, logical position in the text.
+func (t *Terminal) moveCursorToPos(pos int) {
+ if !t.echo {
+ return
+ }
+
+ x := visualLength(t.prompt) + pos
+ y := x / t.termWidth
+ x = x % t.termWidth
+
+ up := 0
+ if y < t.cursorY {
+ up = t.cursorY - y
+ }
+
+ down := 0
+ if y > t.cursorY {
+ down = y - t.cursorY
+ }
+
+ left := 0
+ if x < t.cursorX {
+ left = t.cursorX - x
+ }
+
+ right := 0
+ if x > t.cursorX {
+ right = x - t.cursorX
+ }
+
+ t.cursorX = x
+ t.cursorY = y
+ t.move(up, down, left, right)
+}
+
+func (t *Terminal) move(up, down, left, right int) {
+ movement := make([]rune, 3*(up+down+left+right))
+ m := movement
+ for i := 0; i < up; i++ {
+ m[0] = keyEscape
+ m[1] = '['
+ m[2] = 'A'
+ m = m[3:]
+ }
+ for i := 0; i < down; i++ {
+ m[0] = keyEscape
+ m[1] = '['
+ m[2] = 'B'
+ m = m[3:]
+ }
+ for i := 0; i < left; i++ {
+ m[0] = keyEscape
+ m[1] = '['
+ m[2] = 'D'
+ m = m[3:]
+ }
+ for i := 0; i < right; i++ {
+ m[0] = keyEscape
+ m[1] = '['
+ m[2] = 'C'
+ m = m[3:]
+ }
+
+ t.queue(movement)
+}
+
+func (t *Terminal) clearLineToRight() {
+ op := []rune{keyEscape, '[', 'K'}
+ t.queue(op)
+}
+
+const maxLineLength = 4096
+
+func (t *Terminal) setLine(newLine []rune, newPos int) {
+ if t.echo {
+ t.moveCursorToPos(0)
+ t.writeLine(newLine)
+ for i := len(newLine); i < len(t.line); i++ {
+ t.writeLine(space)
+ }
+ t.moveCursorToPos(newPos)
+ }
+ t.line = newLine
+ t.pos = newPos
+}
+
+func (t *Terminal) advanceCursor(places int) {
+ t.cursorX += places
+ t.cursorY += t.cursorX / t.termWidth
+ if t.cursorY > t.maxLine {
+ t.maxLine = t.cursorY
+ }
+ t.cursorX = t.cursorX % t.termWidth
+
+ if places > 0 && t.cursorX == 0 {
+ // Normally terminals will advance the current position
+ // when writing a character. But that doesn't happen
+ // for the last character in a line. However, when
+ // writing a character (except a new line) that causes
+ // a line wrap, the position will be advanced two
+ // places.
+ //
+ // So, if we are stopping at the end of a line, we
+ // need to write a newline so that our cursor can be
+ // advanced to the next line.
+ t.outBuf = append(t.outBuf, '\r', '\n')
+ }
+}
+
+func (t *Terminal) eraseNPreviousChars(n int) {
+ if n == 0 {
+ return
+ }
+
+ if t.pos < n {
+ n = t.pos
+ }
+ t.pos -= n
+ t.moveCursorToPos(t.pos)
+
+ copy(t.line[t.pos:], t.line[n+t.pos:])
+ t.line = t.line[:len(t.line)-n]
+ if t.echo {
+ t.writeLine(t.line[t.pos:])
+ for i := 0; i < n; i++ {
+ t.queue(space)
+ }
+ t.advanceCursor(n)
+ t.moveCursorToPos(t.pos)
+ }
+}
+
+// countToLeftWord returns then number of characters from the cursor to the
+// start of the previous word.
+func (t *Terminal) countToLeftWord() int {
+ if t.pos == 0 {
+ return 0
+ }
+
+ pos := t.pos - 1
+ for pos > 0 {
+ if t.line[pos] != ' ' {
+ break
+ }
+ pos--
+ }
+ for pos > 0 {
+ if t.line[pos] == ' ' {
+ pos++
+ break
+ }
+ pos--
+ }
+
+ return t.pos - pos
+}
+
+// countToRightWord returns then number of characters from the cursor to the
+// start of the next word.
+func (t *Terminal) countToRightWord() int {
+ pos := t.pos
+ for pos < len(t.line) {
+ if t.line[pos] == ' ' {
+ break
+ }
+ pos++
+ }
+ for pos < len(t.line) {
+ if t.line[pos] != ' ' {
+ break
+ }
+ pos++
+ }
+ return pos - t.pos
+}
+
+// visualLength returns the number of visible glyphs in s.
+func visualLength(runes []rune) int {
+ inEscapeSeq := false
+ length := 0
+
+ for _, r := range runes {
+ switch {
+ case inEscapeSeq:
+ if (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') {
+ inEscapeSeq = false
+ }
+ case r == '\x1b':
+ inEscapeSeq = true
+ default:
+ length++
+ }
+ }
+
+ return length
+}
+
+// handleKey processes the given key and, optionally, returns a line of text
+// that the user has entered.
+func (t *Terminal) handleKey(key rune) (line string, ok bool) {
+ if t.pasteActive && key != keyEnter {
+ t.addKeyToLine(key)
+ return
+ }
+
+ switch key {
+ case keyBackspace:
+ if t.pos == 0 {
+ return
+ }
+ t.eraseNPreviousChars(1)
+ case keyAltLeft:
+ // move left by a word.
+ t.pos -= t.countToLeftWord()
+ t.moveCursorToPos(t.pos)
+ case keyAltRight:
+ // move right by a word.
+ t.pos += t.countToRightWord()
+ t.moveCursorToPos(t.pos)
+ case keyLeft:
+ if t.pos == 0 {
+ return
+ }
+ t.pos--
+ t.moveCursorToPos(t.pos)
+ case keyRight:
+ if t.pos == len(t.line) {
+ return
+ }
+ t.pos++
+ t.moveCursorToPos(t.pos)
+ case keyHome:
+ if t.pos == 0 {
+ return
+ }
+ t.pos = 0
+ t.moveCursorToPos(t.pos)
+ case keyEnd:
+ if t.pos == len(t.line) {
+ return
+ }
+ t.pos = len(t.line)
+ t.moveCursorToPos(t.pos)
+ case keyUp:
+ entry, ok := t.history.NthPreviousEntry(t.historyIndex + 1)
+ if !ok {
+ return "", false
+ }
+ if t.historyIndex == -1 {
+ t.historyPending = string(t.line)
+ }
+ t.historyIndex++
+ runes := []rune(entry)
+ t.setLine(runes, len(runes))
+ case keyDown:
+ switch t.historyIndex {
+ case -1:
+ return
+ case 0:
+ runes := []rune(t.historyPending)
+ t.setLine(runes, len(runes))
+ t.historyIndex--
+ default:
+ entry, ok := t.history.NthPreviousEntry(t.historyIndex - 1)
+ if ok {
+ t.historyIndex--
+ runes := []rune(entry)
+ t.setLine(runes, len(runes))
+ }
+ }
+ case keyEnter:
+ t.moveCursorToPos(len(t.line))
+ t.queue([]rune("\r\n"))
+ line = string(t.line)
+ ok = true
+ t.line = t.line[:0]
+ t.pos = 0
+ t.cursorX = 0
+ t.cursorY = 0
+ t.maxLine = 0
+ case keyDeleteWord:
+ // Delete zero or more spaces and then one or more characters.
+ t.eraseNPreviousChars(t.countToLeftWord())
+ case keyDeleteLine:
+ // Delete everything from the current cursor position to the
+ // end of line.
+ for i := t.pos; i < len(t.line); i++ {
+ t.queue(space)
+ t.advanceCursor(1)
+ }
+ t.line = t.line[:t.pos]
+ t.moveCursorToPos(t.pos)
+ case keyCtrlD:
+ // Erase the character under the current position.
+ // The EOF case when the line is empty is handled in
+ // readLine().
+ if t.pos < len(t.line) {
+ t.pos++
+ t.eraseNPreviousChars(1)
+ }
+ case keyCtrlU:
+ t.eraseNPreviousChars(t.pos)
+ case keyClearScreen:
+ // Erases the screen and moves the cursor to the home position.
+ t.queue([]rune("\x1b[2J\x1b[H"))
+ t.queue(t.prompt)
+ t.cursorX, t.cursorY = 0, 0
+ t.advanceCursor(visualLength(t.prompt))
+ t.setLine(t.line, t.pos)
+ default:
+ if t.AutoCompleteCallback != nil {
+ prefix := string(t.line[:t.pos])
+ suffix := string(t.line[t.pos:])
+
+ t.lock.Unlock()
+ newLine, newPos, completeOk := t.AutoCompleteCallback(prefix+suffix, len(prefix), key)
+ t.lock.Lock()
+
+ if completeOk {
+ t.setLine([]rune(newLine), utf8.RuneCount([]byte(newLine)[:newPos]))
+ return
+ }
+ }
+ if !isPrintable(key) {
+ return
+ }
+ if len(t.line) == maxLineLength {
+ return
+ }
+ t.addKeyToLine(key)
+ }
+ return
+}
+
+// addKeyToLine inserts the given key at the current position in the current
+// line.
+func (t *Terminal) addKeyToLine(key rune) {
+ if len(t.line) == cap(t.line) {
+ newLine := make([]rune, len(t.line), 2*(1+len(t.line)))
+ copy(newLine, t.line)
+ t.line = newLine
+ }
+ t.line = t.line[:len(t.line)+1]
+ copy(t.line[t.pos+1:], t.line[t.pos:])
+ t.line[t.pos] = key
+ if t.echo {
+ t.writeLine(t.line[t.pos:])
+ }
+ t.pos++
+ t.moveCursorToPos(t.pos)
+}
+
+func (t *Terminal) writeLine(line []rune) {
+ for len(line) != 0 {
+ remainingOnLine := t.termWidth - t.cursorX
+ todo := len(line)
+ if todo > remainingOnLine {
+ todo = remainingOnLine
+ }
+ t.queue(line[:todo])
+ t.advanceCursor(visualLength(line[:todo]))
+ line = line[todo:]
+ }
+}
+
+// writeWithCRLF writes buf to w but replaces all occurrences of \n with \r\n.
+func writeWithCRLF(w io.Writer, buf []byte) (n int, err error) {
+ for len(buf) > 0 {
+ i := bytes.IndexByte(buf, '\n')
+ todo := len(buf)
+ if i >= 0 {
+ todo = i
+ }
+
+ var nn int
+ nn, err = w.Write(buf[:todo])
+ n += nn
+ if err != nil {
+ return n, err
+ }
+ buf = buf[todo:]
+
+ if i >= 0 {
+ if _, err = w.Write(crlf); err != nil {
+ return n, err
+ }
+ n += 1
+ buf = buf[1:]
+ }
+ }
+
+ return n, nil
+}
+
+func (t *Terminal) Write(buf []byte) (n int, err error) {
+ t.lock.Lock()
+ defer t.lock.Unlock()
+
+ if t.cursorX == 0 && t.cursorY == 0 {
+ // This is the easy case: there's nothing on the screen that we
+ // have to move out of the way.
+ return writeWithCRLF(t.c, buf)
+ }
+
+ // We have a prompt and possibly user input on the screen. We
+ // have to clear it first.
+ t.move(0 /* up */, 0 /* down */, t.cursorX /* left */, 0 /* right */)
+ t.cursorX = 0
+ t.clearLineToRight()
+
+ for t.cursorY > 0 {
+ t.move(1 /* up */, 0, 0, 0)
+ t.cursorY--
+ t.clearLineToRight()
+ }
+
+ if _, err = t.c.Write(t.outBuf); err != nil {
+ return
+ }
+ t.outBuf = t.outBuf[:0]
+
+ if n, err = writeWithCRLF(t.c, buf); err != nil {
+ return
+ }
+
+ t.writeLine(t.prompt)
+ if t.echo {
+ t.writeLine(t.line)
+ }
+
+ t.moveCursorToPos(t.pos)
+
+ if _, err = t.c.Write(t.outBuf); err != nil {
+ return
+ }
+ t.outBuf = t.outBuf[:0]
+ return
+}
+
+// ReadPassword temporarily changes the prompt and reads a password, without
+// echo, from the terminal.
+func (t *Terminal) ReadPassword(prompt string) (line string, err error) {
+ t.lock.Lock()
+ defer t.lock.Unlock()
+
+ oldPrompt := t.prompt
+ t.prompt = []rune(prompt)
+ t.echo = false
+
+ line, err = t.readLine()
+
+ t.prompt = oldPrompt
+ t.echo = true
+
+ return
+}
+
+// ReadLine returns a line of input from the terminal.
+func (t *Terminal) ReadLine() (line string, err error) {
+ t.lock.Lock()
+ defer t.lock.Unlock()
+
+ return t.readLine()
+}
+
+func (t *Terminal) readLine() (line string, err error) {
+ // t.lock must be held at this point
+
+ if t.cursorX == 0 && t.cursorY == 0 {
+ t.writeLine(t.prompt)
+ t.c.Write(t.outBuf)
+ t.outBuf = t.outBuf[:0]
+ }
+
+ lineIsPasted := t.pasteActive
+
+ for {
+ rest := t.remainder
+ lineOk := false
+ for !lineOk {
+ var key rune
+ key, rest = bytesToKey(rest, t.pasteActive)
+ if key == utf8.RuneError {
+ break
+ }
+ if !t.pasteActive {
+ if key == keyCtrlD {
+ if len(t.line) == 0 {
+ return "", io.EOF
+ }
+ }
+ if key == keyPasteStart {
+ t.pasteActive = true
+ if len(t.line) == 0 {
+ lineIsPasted = true
+ }
+ continue
+ }
+ } else if key == keyPasteEnd {
+ t.pasteActive = false
+ continue
+ }
+ if !t.pasteActive {
+ lineIsPasted = false
+ }
+ line, lineOk = t.handleKey(key)
+ }
+ if len(rest) > 0 {
+ n := copy(t.inBuf[:], rest)
+ t.remainder = t.inBuf[:n]
+ } else {
+ t.remainder = nil
+ }
+ t.c.Write(t.outBuf)
+ t.outBuf = t.outBuf[:0]
+ if lineOk {
+ if t.echo {
+ t.historyIndex = -1
+ t.history.Add(line)
+ }
+ if lineIsPasted {
+ err = ErrPasteIndicator
+ }
+ return
+ }
+
+ // t.remainder is a slice at the beginning of t.inBuf
+ // containing a partial key sequence
+ readBuf := t.inBuf[len(t.remainder):]
+ var n int
+
+ t.lock.Unlock()
+ n, err = t.c.Read(readBuf)
+ t.lock.Lock()
+
+ if err != nil {
+ return
+ }
+
+ t.remainder = t.inBuf[:n+len(t.remainder)]
+ }
+}
+
+// SetPrompt sets the prompt to be used when reading subsequent lines.
+func (t *Terminal) SetPrompt(prompt string) {
+ t.lock.Lock()
+ defer t.lock.Unlock()
+
+ t.prompt = []rune(prompt)
+}
+
+func (t *Terminal) clearAndRepaintLinePlusNPrevious(numPrevLines int) {
+ // Move cursor to column zero at the start of the line.
+ t.move(t.cursorY, 0, t.cursorX, 0)
+ t.cursorX, t.cursorY = 0, 0
+ t.clearLineToRight()
+ for t.cursorY < numPrevLines {
+ // Move down a line
+ t.move(0, 1, 0, 0)
+ t.cursorY++
+ t.clearLineToRight()
+ }
+ // Move back to beginning.
+ t.move(t.cursorY, 0, 0, 0)
+ t.cursorX, t.cursorY = 0, 0
+
+ t.queue(t.prompt)
+ t.advanceCursor(visualLength(t.prompt))
+ t.writeLine(t.line)
+ t.moveCursorToPos(t.pos)
+}
+
+func (t *Terminal) SetSize(width, height int) error {
+ t.lock.Lock()
+ defer t.lock.Unlock()
+
+ if width == 0 {
+ width = 1
+ }
+
+ oldWidth := t.termWidth
+ t.termWidth, t.termHeight = width, height
+
+ switch {
+ case width == oldWidth:
+ // If the width didn't change then nothing else needs to be
+ // done.
+ return nil
+ case len(t.line) == 0 && t.cursorX == 0 && t.cursorY == 0:
+ // If there is nothing on current line and no prompt printed,
+ // just do nothing
+ return nil
+ case width < oldWidth:
+ // Some terminals (e.g. xterm) will truncate lines that were
+ // too long when shinking. Others, (e.g. gnome-terminal) will
+ // attempt to wrap them. For the former, repainting t.maxLine
+ // works great, but that behaviour goes badly wrong in the case
+ // of the latter because they have doubled every full line.
+
+ // We assume that we are working on a terminal that wraps lines
+ // and adjust the cursor position based on every previous line
+ // wrapping and turning into two. This causes the prompt on
+ // xterms to move upwards, which isn't great, but it avoids a
+ // huge mess with gnome-terminal.
+ if t.cursorX >= t.termWidth {
+ t.cursorX = t.termWidth - 1
+ }
+ t.cursorY *= 2
+ t.clearAndRepaintLinePlusNPrevious(t.maxLine * 2)
+ case width > oldWidth:
+ // If the terminal expands then our position calculations will
+ // be wrong in the future because we think the cursor is
+ // |t.pos| chars into the string, but there will be a gap at
+ // the end of any wrapped line.
+ //
+ // But the position will actually be correct until we move, so
+ // we can move back to the beginning and repaint everything.
+ t.clearAndRepaintLinePlusNPrevious(t.maxLine)
+ }
+
+ _, err := t.c.Write(t.outBuf)
+ t.outBuf = t.outBuf[:0]
+ return err
+}
+
+type pasteIndicatorError struct{}
+
+func (pasteIndicatorError) Error() string {
+ return "terminal: ErrPasteIndicator not correctly handled"
+}
+
+// ErrPasteIndicator may be returned from ReadLine as the error, in addition
+// to valid line data. It indicates that bracketed paste mode is enabled and
+// that the returned line consists only of pasted data. Programs may wish to
+// interpret pasted data more literally than typed data.
+var ErrPasteIndicator = pasteIndicatorError{}
+
+// SetBracketedPasteMode requests that the terminal bracket paste operations
+// with markers. Not all terminals support this but, if it is supported, then
+// enabling this mode will stop any autocomplete callback from running due to
+// pastes. Additionally, any lines that are completely pasted will be returned
+// from ReadLine with the error set to ErrPasteIndicator.
+func (t *Terminal) SetBracketedPasteMode(on bool) {
+ if on {
+ io.WriteString(t.c, "\x1b[?2004h")
+ } else {
+ io.WriteString(t.c, "\x1b[?2004l")
+ }
+}
+
+// stRingBuffer is a ring buffer of strings.
+type stRingBuffer struct {
+ // entries contains max elements.
+ entries []string
+ max int
+ // head contains the index of the element most recently added to the ring.
+ head int
+ // size contains the number of elements in the ring.
+ size int
+}
+
+func (s *stRingBuffer) Add(a string) {
+ if s.entries == nil {
+ const defaultNumEntries = 100
+ s.entries = make([]string, defaultNumEntries)
+ s.max = defaultNumEntries
+ }
+
+ s.head = (s.head + 1) % s.max
+ s.entries[s.head] = a
+ if s.size < s.max {
+ s.size++
+ }
+}
+
+// NthPreviousEntry returns the value passed to the nth previous call to Add.
+// If n is zero then the immediately prior value is returned, if one, then the
+// next most recent, and so on. If such an element doesn't exist then ok is
+// false.
+func (s *stRingBuffer) NthPreviousEntry(n int) (value string, ok bool) {
+ if n >= s.size {
+ return "", false
+ }
+ index := s.head - n
+ if index < 0 {
+ index += s.max
+ }
+ return s.entries[index], true
+}
+
+// readPasswordLine reads from reader until it finds \n or io.EOF.
+// The slice returned does not include the \n.
+// readPasswordLine also ignores any \r it finds.
+func readPasswordLine(reader io.Reader) ([]byte, error) {
+ var buf [1]byte
+ var ret []byte
+
+ for {
+ n, err := reader.Read(buf[:])
+ if n > 0 {
+ switch buf[0] {
+ case '\n':
+ return ret, nil
+ case '\r':
+ // remove \r from passwords on Windows
+ default:
+ ret = append(ret, buf[0])
+ }
+ continue
+ }
+ if err != nil {
+ if err == io.EOF && len(ret) > 0 {
+ return ret, nil
+ }
+ return ret, err
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/terminal/terminal_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/terminal/terminal_test.go
new file mode 100644
index 000000000..901c72ab3
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/terminal/terminal_test.go
@@ -0,0 +1,350 @@
+// Copyright 2011 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 terminal
+
+import (
+ "bytes"
+ "io"
+ "os"
+ "testing"
+)
+
+type MockTerminal struct {
+ toSend []byte
+ bytesPerRead int
+ received []byte
+}
+
+func (c *MockTerminal) Read(data []byte) (n int, err error) {
+ n = len(data)
+ if n == 0 {
+ return
+ }
+ if n > len(c.toSend) {
+ n = len(c.toSend)
+ }
+ if n == 0 {
+ return 0, io.EOF
+ }
+ if c.bytesPerRead > 0 && n > c.bytesPerRead {
+ n = c.bytesPerRead
+ }
+ copy(data, c.toSend[:n])
+ c.toSend = c.toSend[n:]
+ return
+}
+
+func (c *MockTerminal) Write(data []byte) (n int, err error) {
+ c.received = append(c.received, data...)
+ return len(data), nil
+}
+
+func TestClose(t *testing.T) {
+ c := &MockTerminal{}
+ ss := NewTerminal(c, "> ")
+ line, err := ss.ReadLine()
+ if line != "" {
+ t.Errorf("Expected empty line but got: %s", line)
+ }
+ if err != io.EOF {
+ t.Errorf("Error should have been EOF but got: %s", err)
+ }
+}
+
+var keyPressTests = []struct {
+ in string
+ line string
+ err error
+ throwAwayLines int
+}{
+ {
+ err: io.EOF,
+ },
+ {
+ in: "\r",
+ line: "",
+ },
+ {
+ in: "foo\r",
+ line: "foo",
+ },
+ {
+ in: "a\x1b[Cb\r", // right
+ line: "ab",
+ },
+ {
+ in: "a\x1b[Db\r", // left
+ line: "ba",
+ },
+ {
+ in: "a\177b\r", // backspace
+ line: "b",
+ },
+ {
+ in: "\x1b[A\r", // up
+ },
+ {
+ in: "\x1b[B\r", // down
+ },
+ {
+ in: "line\x1b[A\x1b[B\r", // up then down
+ line: "line",
+ },
+ {
+ in: "line1\rline2\x1b[A\r", // recall previous line.
+ line: "line1",
+ throwAwayLines: 1,
+ },
+ {
+ // recall two previous lines and append.
+ in: "line1\rline2\rline3\x1b[A\x1b[Axxx\r",
+ line: "line1xxx",
+ throwAwayLines: 2,
+ },
+ {
+ // Ctrl-A to move to beginning of line followed by ^K to kill
+ // line.
+ in: "a b \001\013\r",
+ line: "",
+ },
+ {
+ // Ctrl-A to move to beginning of line, Ctrl-E to move to end,
+ // finally ^K to kill nothing.
+ in: "a b \001\005\013\r",
+ line: "a b ",
+ },
+ {
+ in: "\027\r",
+ line: "",
+ },
+ {
+ in: "a\027\r",
+ line: "",
+ },
+ {
+ in: "a \027\r",
+ line: "",
+ },
+ {
+ in: "a b\027\r",
+ line: "a ",
+ },
+ {
+ in: "a b \027\r",
+ line: "a ",
+ },
+ {
+ in: "one two thr\x1b[D\027\r",
+ line: "one two r",
+ },
+ {
+ in: "\013\r",
+ line: "",
+ },
+ {
+ in: "a\013\r",
+ line: "a",
+ },
+ {
+ in: "ab\x1b[D\013\r",
+ line: "a",
+ },
+ {
+ in: "Ξεσκεπάζω\r",
+ line: "Ξεσκεπάζω",
+ },
+ {
+ in: "£\r\x1b[A\177\r", // non-ASCII char, enter, up, backspace.
+ line: "",
+ throwAwayLines: 1,
+ },
+ {
+ in: "£\r££\x1b[A\x1b[B\177\r", // non-ASCII char, enter, 2x non-ASCII, up, down, backspace, enter.
+ line: "£",
+ throwAwayLines: 1,
+ },
+ {
+ // Ctrl-D at the end of the line should be ignored.
+ in: "a\004\r",
+ line: "a",
+ },
+ {
+ // a, b, left, Ctrl-D should erase the b.
+ in: "ab\x1b[D\004\r",
+ line: "a",
+ },
+ {
+ // a, b, c, d, left, left, ^U should erase to the beginning of
+ // the line.
+ in: "abcd\x1b[D\x1b[D\025\r",
+ line: "cd",
+ },
+ {
+ // Bracketed paste mode: control sequences should be returned
+ // verbatim in paste mode.
+ in: "abc\x1b[200~de\177f\x1b[201~\177\r",
+ line: "abcde\177",
+ },
+ {
+ // Enter in bracketed paste mode should still work.
+ in: "abc\x1b[200~d\refg\x1b[201~h\r",
+ line: "efgh",
+ throwAwayLines: 1,
+ },
+ {
+ // Lines consisting entirely of pasted data should be indicated as such.
+ in: "\x1b[200~a\r",
+ line: "a",
+ err: ErrPasteIndicator,
+ },
+}
+
+func TestKeyPresses(t *testing.T) {
+ for i, test := range keyPressTests {
+ for j := 1; j < len(test.in); j++ {
+ c := &MockTerminal{
+ toSend: []byte(test.in),
+ bytesPerRead: j,
+ }
+ ss := NewTerminal(c, "> ")
+ for k := 0; k < test.throwAwayLines; k++ {
+ _, err := ss.ReadLine()
+ if err != nil {
+ t.Errorf("Throwaway line %d from test %d resulted in error: %s", k, i, err)
+ }
+ }
+ line, err := ss.ReadLine()
+ if line != test.line {
+ t.Errorf("Line resulting from test %d (%d bytes per read) was '%s', expected '%s'", i, j, line, test.line)
+ break
+ }
+ if err != test.err {
+ t.Errorf("Error resulting from test %d (%d bytes per read) was '%v', expected '%v'", i, j, err, test.err)
+ break
+ }
+ }
+ }
+}
+
+func TestPasswordNotSaved(t *testing.T) {
+ c := &MockTerminal{
+ toSend: []byte("password\r\x1b[A\r"),
+ bytesPerRead: 1,
+ }
+ ss := NewTerminal(c, "> ")
+ pw, _ := ss.ReadPassword("> ")
+ if pw != "password" {
+ t.Fatalf("failed to read password, got %s", pw)
+ }
+ line, _ := ss.ReadLine()
+ if len(line) > 0 {
+ t.Fatalf("password was saved in history")
+ }
+}
+
+var setSizeTests = []struct {
+ width, height int
+}{
+ {40, 13},
+ {80, 24},
+ {132, 43},
+}
+
+func TestTerminalSetSize(t *testing.T) {
+ for _, setSize := range setSizeTests {
+ c := &MockTerminal{
+ toSend: []byte("password\r\x1b[A\r"),
+ bytesPerRead: 1,
+ }
+ ss := NewTerminal(c, "> ")
+ ss.SetSize(setSize.width, setSize.height)
+ pw, _ := ss.ReadPassword("Password: ")
+ if pw != "password" {
+ t.Fatalf("failed to read password, got %s", pw)
+ }
+ if string(c.received) != "Password: \r\n" {
+ t.Errorf("failed to set the temporary prompt expected %q, got %q", "Password: ", c.received)
+ }
+ }
+}
+
+func TestReadPasswordLineEnd(t *testing.T) {
+ var tests = []struct {
+ input string
+ want string
+ }{
+ {"\n", ""},
+ {"\r\n", ""},
+ {"test\r\n", "test"},
+ {"testtesttesttes\n", "testtesttesttes"},
+ {"testtesttesttes\r\n", "testtesttesttes"},
+ {"testtesttesttesttest\n", "testtesttesttesttest"},
+ {"testtesttesttesttest\r\n", "testtesttesttesttest"},
+ }
+ for _, test := range tests {
+ buf := new(bytes.Buffer)
+ if _, err := buf.WriteString(test.input); err != nil {
+ t.Fatal(err)
+ }
+
+ have, err := readPasswordLine(buf)
+ if err != nil {
+ t.Errorf("readPasswordLine(%q) failed: %v", test.input, err)
+ continue
+ }
+ if string(have) != test.want {
+ t.Errorf("readPasswordLine(%q) returns %q, but %q is expected", test.input, string(have), test.want)
+ continue
+ }
+
+ if _, err = buf.WriteString(test.input); err != nil {
+ t.Fatal(err)
+ }
+ have, err = readPasswordLine(buf)
+ if err != nil {
+ t.Errorf("readPasswordLine(%q) failed: %v", test.input, err)
+ continue
+ }
+ if string(have) != test.want {
+ t.Errorf("readPasswordLine(%q) returns %q, but %q is expected", test.input, string(have), test.want)
+ continue
+ }
+ }
+}
+
+func TestMakeRawState(t *testing.T) {
+ fd := int(os.Stdout.Fd())
+ if !IsTerminal(fd) {
+ t.Skip("stdout is not a terminal; skipping test")
+ }
+
+ st, err := GetState(fd)
+ if err != nil {
+ t.Fatalf("failed to get terminal state from GetState: %s", err)
+ }
+ defer Restore(fd, st)
+ raw, err := MakeRaw(fd)
+ if err != nil {
+ t.Fatalf("failed to get terminal state from MakeRaw: %s", err)
+ }
+
+ if *st != *raw {
+ t.Errorf("states do not match; was %v, expected %v", raw, st)
+ }
+}
+
+func TestOutputNewlines(t *testing.T) {
+ // \n should be changed to \r\n in terminal output.
+ buf := new(bytes.Buffer)
+ term := NewTerminal(buf, ">")
+
+ term.Write([]byte("1\n2\n"))
+ output := string(buf.Bytes())
+ const expected = "1\r\n2\r\n"
+
+ if output != expected {
+ t.Errorf("incorrect output: was %q, expected %q", output, expected)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/terminal/util.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/terminal/util.go
new file mode 100644
index 000000000..02dad484e
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/terminal/util.go
@@ -0,0 +1,116 @@
+// Copyright 2011 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.
+
+// +build darwin dragonfly freebsd linux,!appengine netbsd openbsd
+
+// Package terminal provides support functions for dealing with terminals, as
+// commonly found on UNIX systems.
+//
+// Putting a terminal into raw mode is the most common requirement:
+//
+// oldState, err := terminal.MakeRaw(0)
+// if err != nil {
+// panic(err)
+// }
+// defer terminal.Restore(0, oldState)
+package terminal // import "golang.org/x/crypto/ssh/terminal"
+
+import (
+ "golang.org/x/sys/unix"
+)
+
+// State contains the state of a terminal.
+type State struct {
+ termios unix.Termios
+}
+
+// IsTerminal returns true if the given file descriptor is a terminal.
+func IsTerminal(fd int) bool {
+ _, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
+ return err == nil
+}
+
+// MakeRaw put the terminal connected to the given file descriptor into raw
+// mode and returns the previous state of the terminal so that it can be
+// restored.
+func MakeRaw(fd int) (*State, error) {
+ termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
+ if err != nil {
+ return nil, err
+ }
+
+ oldState := State{termios: *termios}
+
+ // This attempts to replicate the behaviour documented for cfmakeraw in
+ // the termios(3) manpage.
+ termios.Iflag &^= unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON
+ termios.Oflag &^= unix.OPOST
+ termios.Lflag &^= unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN
+ termios.Cflag &^= unix.CSIZE | unix.PARENB
+ termios.Cflag |= unix.CS8
+ termios.Cc[unix.VMIN] = 1
+ termios.Cc[unix.VTIME] = 0
+ if err := unix.IoctlSetTermios(fd, ioctlWriteTermios, termios); err != nil {
+ return nil, err
+ }
+
+ return &oldState, nil
+}
+
+// GetState returns the current state of a terminal which may be useful to
+// restore the terminal after a signal.
+func GetState(fd int) (*State, error) {
+ termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
+ if err != nil {
+ return nil, err
+ }
+
+ return &State{termios: *termios}, nil
+}
+
+// Restore restores the terminal connected to the given file descriptor to a
+// previous state.
+func Restore(fd int, state *State) error {
+ return unix.IoctlSetTermios(fd, ioctlWriteTermios, &state.termios)
+}
+
+// GetSize returns the dimensions of the given terminal.
+func GetSize(fd int) (width, height int, err error) {
+ ws, err := unix.IoctlGetWinsize(fd, unix.TIOCGWINSZ)
+ if err != nil {
+ return -1, -1, err
+ }
+ return int(ws.Col), int(ws.Row), nil
+}
+
+// passwordReader is an io.Reader that reads from a specific file descriptor.
+type passwordReader int
+
+func (r passwordReader) Read(buf []byte) (int, error) {
+ return unix.Read(int(r), buf)
+}
+
+// ReadPassword reads a line of input from a terminal without local echo. This
+// is commonly used for inputting passwords and other sensitive data. The slice
+// returned does not include the \n.
+func ReadPassword(fd int) ([]byte, error) {
+ termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
+ if err != nil {
+ return nil, err
+ }
+
+ newState := *termios
+ newState.Lflag &^= unix.ECHO
+ newState.Lflag |= unix.ICANON | unix.ISIG
+ newState.Iflag |= unix.ICRNL
+ if err := unix.IoctlSetTermios(fd, ioctlWriteTermios, &newState); err != nil {
+ return nil, err
+ }
+
+ defer func() {
+ unix.IoctlSetTermios(fd, ioctlWriteTermios, termios)
+ }()
+
+ return readPasswordLine(passwordReader(fd))
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/terminal/util_bsd.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/terminal/util_bsd.go
new file mode 100644
index 000000000..cb23a5904
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/terminal/util_bsd.go
@@ -0,0 +1,12 @@
+// Copyright 2013 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.
+
+// +build darwin dragonfly freebsd netbsd openbsd
+
+package terminal
+
+import "golang.org/x/sys/unix"
+
+const ioctlReadTermios = unix.TIOCGETA
+const ioctlWriteTermios = unix.TIOCSETA
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/terminal/util_linux.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/terminal/util_linux.go
new file mode 100644
index 000000000..5fadfe8a1
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/terminal/util_linux.go
@@ -0,0 +1,10 @@
+// Copyright 2013 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 terminal
+
+import "golang.org/x/sys/unix"
+
+const ioctlReadTermios = unix.TCGETS
+const ioctlWriteTermios = unix.TCSETS
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/terminal/util_plan9.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/terminal/util_plan9.go
new file mode 100644
index 000000000..799f049f0
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/terminal/util_plan9.go
@@ -0,0 +1,58 @@
+// 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.
+
+// Package terminal provides support functions for dealing with terminals, as
+// commonly found on UNIX systems.
+//
+// Putting a terminal into raw mode is the most common requirement:
+//
+// oldState, err := terminal.MakeRaw(0)
+// if err != nil {
+// panic(err)
+// }
+// defer terminal.Restore(0, oldState)
+package terminal
+
+import (
+ "fmt"
+ "runtime"
+)
+
+type State struct{}
+
+// IsTerminal returns true if the given file descriptor is a terminal.
+func IsTerminal(fd int) bool {
+ return false
+}
+
+// MakeRaw put the terminal connected to the given file descriptor into raw
+// mode and returns the previous state of the terminal so that it can be
+// restored.
+func MakeRaw(fd int) (*State, error) {
+ return nil, fmt.Errorf("terminal: MakeRaw not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
+}
+
+// GetState returns the current state of a terminal which may be useful to
+// restore the terminal after a signal.
+func GetState(fd int) (*State, error) {
+ return nil, fmt.Errorf("terminal: GetState not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
+}
+
+// Restore restores the terminal connected to the given file descriptor to a
+// previous state.
+func Restore(fd int, state *State) error {
+ return fmt.Errorf("terminal: Restore not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
+}
+
+// GetSize returns the dimensions of the given terminal.
+func GetSize(fd int) (width, height int, err error) {
+ return 0, 0, fmt.Errorf("terminal: GetSize not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
+}
+
+// ReadPassword reads a line of input from a terminal without local echo. This
+// is commonly used for inputting passwords and other sensitive data. The slice
+// returned does not include the \n.
+func ReadPassword(fd int) ([]byte, error) {
+ return nil, fmt.Errorf("terminal: ReadPassword not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/terminal/util_solaris.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/terminal/util_solaris.go
new file mode 100644
index 000000000..a2e1b57dc
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/terminal/util_solaris.go
@@ -0,0 +1,128 @@
+// Copyright 2015 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.
+
+// +build solaris
+
+package terminal // import "golang.org/x/crypto/ssh/terminal"
+
+import (
+ "golang.org/x/sys/unix"
+ "io"
+ "syscall"
+)
+
+// State contains the state of a terminal.
+type State struct {
+ state *unix.Termios
+}
+
+// IsTerminal returns true if the given file descriptor is a terminal.
+func IsTerminal(fd int) bool {
+ _, err := unix.IoctlGetTermio(fd, unix.TCGETA)
+ return err == nil
+}
+
+// ReadPassword reads a line of input from a terminal without local echo. This
+// is commonly used for inputting passwords and other sensitive data. The slice
+// returned does not include the \n.
+func ReadPassword(fd int) ([]byte, error) {
+ // see also: http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libast/common/uwin/getpass.c
+ val, err := unix.IoctlGetTermios(fd, unix.TCGETS)
+ if err != nil {
+ return nil, err
+ }
+ oldState := *val
+
+ newState := oldState
+ newState.Lflag &^= syscall.ECHO
+ newState.Lflag |= syscall.ICANON | syscall.ISIG
+ newState.Iflag |= syscall.ICRNL
+ err = unix.IoctlSetTermios(fd, unix.TCSETS, &newState)
+ if err != nil {
+ return nil, err
+ }
+
+ defer unix.IoctlSetTermios(fd, unix.TCSETS, &oldState)
+
+ var buf [16]byte
+ var ret []byte
+ for {
+ n, err := syscall.Read(fd, buf[:])
+ if err != nil {
+ return nil, err
+ }
+ if n == 0 {
+ if len(ret) == 0 {
+ return nil, io.EOF
+ }
+ break
+ }
+ if buf[n-1] == '\n' {
+ n--
+ }
+ ret = append(ret, buf[:n]...)
+ if n < len(buf) {
+ break
+ }
+ }
+
+ return ret, nil
+}
+
+// MakeRaw puts the terminal connected to the given file descriptor into raw
+// mode and returns the previous state of the terminal so that it can be
+// restored.
+// see http://cr.illumos.org/~webrev/andy_js/1060/
+func MakeRaw(fd int) (*State, error) {
+ oldTermiosPtr, err := unix.IoctlGetTermios(fd, unix.TCGETS)
+ if err != nil {
+ return nil, err
+ }
+ oldTermios := *oldTermiosPtr
+
+ newTermios := oldTermios
+ newTermios.Iflag &^= syscall.IGNBRK | syscall.BRKINT | syscall.PARMRK | syscall.ISTRIP | syscall.INLCR | syscall.IGNCR | syscall.ICRNL | syscall.IXON
+ newTermios.Oflag &^= syscall.OPOST
+ newTermios.Lflag &^= syscall.ECHO | syscall.ECHONL | syscall.ICANON | syscall.ISIG | syscall.IEXTEN
+ newTermios.Cflag &^= syscall.CSIZE | syscall.PARENB
+ newTermios.Cflag |= syscall.CS8
+ newTermios.Cc[unix.VMIN] = 1
+ newTermios.Cc[unix.VTIME] = 0
+
+ if err := unix.IoctlSetTermios(fd, unix.TCSETS, &newTermios); err != nil {
+ return nil, err
+ }
+
+ return &State{
+ state: oldTermiosPtr,
+ }, nil
+}
+
+// Restore restores the terminal connected to the given file descriptor to a
+// previous state.
+func Restore(fd int, oldState *State) error {
+ return unix.IoctlSetTermios(fd, unix.TCSETS, oldState.state)
+}
+
+// GetState returns the current state of a terminal which may be useful to
+// restore the terminal after a signal.
+func GetState(fd int) (*State, error) {
+ oldTermiosPtr, err := unix.IoctlGetTermios(fd, unix.TCGETS)
+ if err != nil {
+ return nil, err
+ }
+
+ return &State{
+ state: oldTermiosPtr,
+ }, nil
+}
+
+// GetSize returns the dimensions of the given terminal.
+func GetSize(fd int) (width, height int, err error) {
+ ws, err := unix.IoctlGetWinsize(fd, unix.TIOCGWINSZ)
+ if err != nil {
+ return 0, 0, err
+ }
+ return int(ws.Col), int(ws.Row), nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/terminal/util_windows.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/terminal/util_windows.go
new file mode 100644
index 000000000..92944f3b4
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/terminal/util_windows.go
@@ -0,0 +1,97 @@
+// Copyright 2011 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.
+
+// +build windows
+
+// Package terminal provides support functions for dealing with terminals, as
+// commonly found on UNIX systems.
+//
+// Putting a terminal into raw mode is the most common requirement:
+//
+// oldState, err := terminal.MakeRaw(0)
+// if err != nil {
+// panic(err)
+// }
+// defer terminal.Restore(0, oldState)
+package terminal
+
+import (
+ "os"
+
+ "golang.org/x/sys/windows"
+)
+
+type State struct {
+ mode uint32
+}
+
+// IsTerminal returns true if the given file descriptor is a terminal.
+func IsTerminal(fd int) bool {
+ var st uint32
+ err := windows.GetConsoleMode(windows.Handle(fd), &st)
+ return err == nil
+}
+
+// MakeRaw put the terminal connected to the given file descriptor into raw
+// mode and returns the previous state of the terminal so that it can be
+// restored.
+func MakeRaw(fd int) (*State, error) {
+ var st uint32
+ if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil {
+ return nil, err
+ }
+ raw := st &^ (windows.ENABLE_ECHO_INPUT | windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT | windows.ENABLE_PROCESSED_OUTPUT)
+ if err := windows.SetConsoleMode(windows.Handle(fd), raw); err != nil {
+ return nil, err
+ }
+ return &State{st}, nil
+}
+
+// GetState returns the current state of a terminal which may be useful to
+// restore the terminal after a signal.
+func GetState(fd int) (*State, error) {
+ var st uint32
+ if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil {
+ return nil, err
+ }
+ return &State{st}, nil
+}
+
+// Restore restores the terminal connected to the given file descriptor to a
+// previous state.
+func Restore(fd int, state *State) error {
+ return windows.SetConsoleMode(windows.Handle(fd), state.mode)
+}
+
+// GetSize returns the dimensions of the given terminal.
+func GetSize(fd int) (width, height int, err error) {
+ var info windows.ConsoleScreenBufferInfo
+ if err := windows.GetConsoleScreenBufferInfo(windows.Handle(fd), &info); err != nil {
+ return 0, 0, err
+ }
+ return int(info.Size.X), int(info.Size.Y), nil
+}
+
+// ReadPassword reads a line of input from a terminal without local echo. This
+// is commonly used for inputting passwords and other sensitive data. The slice
+// returned does not include the \n.
+func ReadPassword(fd int) ([]byte, error) {
+ var st uint32
+ if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil {
+ return nil, err
+ }
+ old := st
+
+ st &^= (windows.ENABLE_ECHO_INPUT)
+ st |= (windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT | windows.ENABLE_PROCESSED_OUTPUT)
+ if err := windows.SetConsoleMode(windows.Handle(fd), st); err != nil {
+ return nil, err
+ }
+
+ defer func() {
+ windows.SetConsoleMode(windows.Handle(fd), old)
+ }()
+
+ return readPasswordLine(os.NewFile(uintptr(fd), "stdin"))
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/test/agent_unix_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/test/agent_unix_test.go
new file mode 100644
index 000000000..f481253c9
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/test/agent_unix_test.go
@@ -0,0 +1,59 @@
+// Copyright 2014 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.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd
+
+package test
+
+import (
+ "bytes"
+ "testing"
+
+ "golang.org/x/crypto/ssh"
+ "golang.org/x/crypto/ssh/agent"
+)
+
+func TestAgentForward(t *testing.T) {
+ server := newServer(t)
+ defer server.Shutdown()
+ conn := server.Dial(clientConfig())
+ defer conn.Close()
+
+ keyring := agent.NewKeyring()
+ if err := keyring.Add(agent.AddedKey{PrivateKey: testPrivateKeys["dsa"]}); err != nil {
+ t.Fatalf("Error adding key: %s", err)
+ }
+ if err := keyring.Add(agent.AddedKey{
+ PrivateKey: testPrivateKeys["dsa"],
+ ConfirmBeforeUse: true,
+ LifetimeSecs: 3600,
+ }); err != nil {
+ t.Fatalf("Error adding key with constraints: %s", err)
+ }
+ pub := testPublicKeys["dsa"]
+
+ sess, err := conn.NewSession()
+ if err != nil {
+ t.Fatalf("NewSession: %v", err)
+ }
+ if err := agent.RequestAgentForwarding(sess); err != nil {
+ t.Fatalf("RequestAgentForwarding: %v", err)
+ }
+
+ if err := agent.ForwardToAgent(conn, keyring); err != nil {
+ t.Fatalf("SetupForwardKeyring: %v", err)
+ }
+ out, err := sess.CombinedOutput("ssh-add -L")
+ if err != nil {
+ t.Fatalf("running ssh-add: %v, out %s", err, out)
+ }
+ key, _, _, _, err := ssh.ParseAuthorizedKey(out)
+ if err != nil {
+ t.Fatalf("ParseAuthorizedKey(%q): %v", out, err)
+ }
+
+ if !bytes.Equal(key.Marshal(), pub.Marshal()) {
+ t.Fatalf("got key %s, want %s", ssh.MarshalAuthorizedKey(key), ssh.MarshalAuthorizedKey(pub))
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/test/banner_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/test/banner_test.go
new file mode 100644
index 000000000..f1ad4697c
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/test/banner_test.go
@@ -0,0 +1,33 @@
+// Copyright 2014 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.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd
+
+package test
+
+import (
+ "testing"
+
+)
+
+func TestBannerCallbackAgainstOpenSSH(t *testing.T) {
+ server := newServer(t)
+ defer server.Shutdown()
+
+ clientConf := clientConfig()
+
+ var receivedBanner string
+ clientConf.BannerCallback = func(message string) error {
+ receivedBanner = message
+ return nil
+ }
+
+ conn := server.Dial(clientConf)
+ defer conn.Close()
+
+ expected := "Server Banner"
+ if receivedBanner != expected {
+ t.Fatalf("got %v; want %v", receivedBanner, expected)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/test/cert_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/test/cert_test.go
new file mode 100644
index 000000000..b231dd80c
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/test/cert_test.go
@@ -0,0 +1,77 @@
+// Copyright 2014 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.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd
+
+package test
+
+import (
+ "bytes"
+ "crypto/rand"
+ "testing"
+
+ "golang.org/x/crypto/ssh"
+)
+
+// Test both logging in with a cert, and also that the certificate presented by an OpenSSH host can be validated correctly
+func TestCertLogin(t *testing.T) {
+ s := newServer(t)
+ defer s.Shutdown()
+
+ // Use a key different from the default.
+ clientKey := testSigners["dsa"]
+ caAuthKey := testSigners["ecdsa"]
+ cert := &ssh.Certificate{
+ Key: clientKey.PublicKey(),
+ ValidPrincipals: []string{username()},
+ CertType: ssh.UserCert,
+ ValidBefore: ssh.CertTimeInfinity,
+ }
+ if err := cert.SignCert(rand.Reader, caAuthKey); err != nil {
+ t.Fatalf("SetSignature: %v", err)
+ }
+
+ certSigner, err := ssh.NewCertSigner(cert, clientKey)
+ if err != nil {
+ t.Fatalf("NewCertSigner: %v", err)
+ }
+
+ conf := &ssh.ClientConfig{
+ User: username(),
+ HostKeyCallback: (&ssh.CertChecker{
+ IsHostAuthority: func(pk ssh.PublicKey, addr string) bool {
+ return bytes.Equal(pk.Marshal(), testPublicKeys["ca"].Marshal())
+ },
+ }).CheckHostKey,
+ }
+ conf.Auth = append(conf.Auth, ssh.PublicKeys(certSigner))
+
+ for _, test := range []struct {
+ addr string
+ succeed bool
+ }{
+ {addr: "host.example.com:22", succeed: true},
+ {addr: "host.example.com:10000", succeed: true}, // non-standard port must be OK
+ {addr: "host.example.com", succeed: false}, // port must be specified
+ {addr: "host.ex4mple.com:22", succeed: false}, // wrong host
+ } {
+ client, err := s.TryDialWithAddr(conf, test.addr)
+
+ // Always close client if opened successfully
+ if err == nil {
+ client.Close()
+ }
+
+ // Now evaluate whether the test failed or passed
+ if test.succeed {
+ if err != nil {
+ t.Fatalf("TryDialWithAddr: %v", err)
+ }
+ } else {
+ if err == nil {
+ t.Fatalf("TryDialWithAddr, unexpected success")
+ }
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/test/dial_unix_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/test/dial_unix_test.go
new file mode 100644
index 000000000..091e48cc1
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/test/dial_unix_test.go
@@ -0,0 +1,128 @@
+// Copyright 2012 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.
+
+// +build !windows
+
+package test
+
+// direct-tcpip and direct-streamlocal functional tests
+
+import (
+ "fmt"
+ "io"
+ "io/ioutil"
+ "net"
+ "strings"
+ "testing"
+)
+
+type dialTester interface {
+ TestServerConn(t *testing.T, c net.Conn)
+ TestClientConn(t *testing.T, c net.Conn)
+}
+
+func testDial(t *testing.T, n, listenAddr string, x dialTester) {
+ server := newServer(t)
+ defer server.Shutdown()
+ sshConn := server.Dial(clientConfig())
+ defer sshConn.Close()
+
+ l, err := net.Listen(n, listenAddr)
+ if err != nil {
+ t.Fatalf("Listen: %v", err)
+ }
+ defer l.Close()
+
+ testData := fmt.Sprintf("hello from %s, %s", n, listenAddr)
+ go func() {
+ for {
+ c, err := l.Accept()
+ if err != nil {
+ break
+ }
+ x.TestServerConn(t, c)
+
+ io.WriteString(c, testData)
+ c.Close()
+ }
+ }()
+
+ conn, err := sshConn.Dial(n, l.Addr().String())
+ if err != nil {
+ t.Fatalf("Dial: %v", err)
+ }
+ x.TestClientConn(t, conn)
+ defer conn.Close()
+ b, err := ioutil.ReadAll(conn)
+ if err != nil {
+ t.Fatalf("ReadAll: %v", err)
+ }
+ t.Logf("got %q", string(b))
+ if string(b) != testData {
+ t.Fatalf("expected %q, got %q", testData, string(b))
+ }
+}
+
+type tcpDialTester struct {
+ listenAddr string
+}
+
+func (x *tcpDialTester) TestServerConn(t *testing.T, c net.Conn) {
+ host := strings.Split(x.listenAddr, ":")[0]
+ prefix := host + ":"
+ if !strings.HasPrefix(c.LocalAddr().String(), prefix) {
+ t.Fatalf("expected to start with %q, got %q", prefix, c.LocalAddr().String())
+ }
+ if !strings.HasPrefix(c.RemoteAddr().String(), prefix) {
+ t.Fatalf("expected to start with %q, got %q", prefix, c.RemoteAddr().String())
+ }
+}
+
+func (x *tcpDialTester) TestClientConn(t *testing.T, c net.Conn) {
+ // we use zero addresses. see *Client.Dial.
+ if c.LocalAddr().String() != "0.0.0.0:0" {
+ t.Fatalf("expected \"0.0.0.0:0\", got %q", c.LocalAddr().String())
+ }
+ if c.RemoteAddr().String() != "0.0.0.0:0" {
+ t.Fatalf("expected \"0.0.0.0:0\", got %q", c.RemoteAddr().String())
+ }
+}
+
+func TestDialTCP(t *testing.T) {
+ x := &tcpDialTester{
+ listenAddr: "127.0.0.1:0",
+ }
+ testDial(t, "tcp", x.listenAddr, x)
+}
+
+type unixDialTester struct {
+ listenAddr string
+}
+
+func (x *unixDialTester) TestServerConn(t *testing.T, c net.Conn) {
+ if c.LocalAddr().String() != x.listenAddr {
+ t.Fatalf("expected %q, got %q", x.listenAddr, c.LocalAddr().String())
+ }
+ if c.RemoteAddr().String() != "@" {
+ t.Fatalf("expected \"@\", got %q", c.RemoteAddr().String())
+ }
+}
+
+func (x *unixDialTester) TestClientConn(t *testing.T, c net.Conn) {
+ if c.RemoteAddr().String() != x.listenAddr {
+ t.Fatalf("expected %q, got %q", x.listenAddr, c.RemoteAddr().String())
+ }
+ if c.LocalAddr().String() != "@" {
+ t.Fatalf("expected \"@\", got %q", c.LocalAddr().String())
+ }
+}
+
+func TestDialUnix(t *testing.T) {
+ addr, cleanup := newTempSocket(t)
+ defer cleanup()
+ x := &unixDialTester{
+ listenAddr: addr,
+ }
+ testDial(t, "unix", x.listenAddr, x)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/test/doc.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/test/doc.go
new file mode 100644
index 000000000..3f9b3346d
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/test/doc.go
@@ -0,0 +1,7 @@
+// Copyright 2012 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.
+
+// This package contains integration tests for the
+// golang.org/x/crypto/ssh package.
+package test // import "golang.org/x/crypto/ssh/test"
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/test/forward_unix_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/test/forward_unix_test.go
new file mode 100644
index 000000000..ea8193780
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/test/forward_unix_test.go
@@ -0,0 +1,194 @@
+// Copyright 2012 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.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd
+
+package test
+
+import (
+ "bytes"
+ "io"
+ "io/ioutil"
+ "math/rand"
+ "net"
+ "testing"
+ "time"
+)
+
+type closeWriter interface {
+ CloseWrite() error
+}
+
+func testPortForward(t *testing.T, n, listenAddr string) {
+ server := newServer(t)
+ defer server.Shutdown()
+ conn := server.Dial(clientConfig())
+ defer conn.Close()
+
+ sshListener, err := conn.Listen(n, listenAddr)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ go func() {
+ sshConn, err := sshListener.Accept()
+ if err != nil {
+ t.Fatalf("listen.Accept failed: %v", err)
+ }
+
+ _, err = io.Copy(sshConn, sshConn)
+ if err != nil && err != io.EOF {
+ t.Fatalf("ssh client copy: %v", err)
+ }
+ sshConn.Close()
+ }()
+
+ forwardedAddr := sshListener.Addr().String()
+ netConn, err := net.Dial(n, forwardedAddr)
+ if err != nil {
+ t.Fatalf("net dial failed: %v", err)
+ }
+
+ readChan := make(chan []byte)
+ go func() {
+ data, _ := ioutil.ReadAll(netConn)
+ readChan <- data
+ }()
+
+ // Invent some data.
+ data := make([]byte, 100*1000)
+ for i := range data {
+ data[i] = byte(i % 255)
+ }
+
+ var sent []byte
+ for len(sent) < 1000*1000 {
+ // Send random sized chunks
+ m := rand.Intn(len(data))
+ n, err := netConn.Write(data[:m])
+ if err != nil {
+ break
+ }
+ sent = append(sent, data[:n]...)
+ }
+ if err := netConn.(closeWriter).CloseWrite(); err != nil {
+ t.Errorf("netConn.CloseWrite: %v", err)
+ }
+
+ read := <-readChan
+
+ if len(sent) != len(read) {
+ t.Fatalf("got %d bytes, want %d", len(read), len(sent))
+ }
+ if bytes.Compare(sent, read) != 0 {
+ t.Fatalf("read back data does not match")
+ }
+
+ if err := sshListener.Close(); err != nil {
+ t.Fatalf("sshListener.Close: %v", err)
+ }
+
+ // Check that the forward disappeared.
+ netConn, err = net.Dial(n, forwardedAddr)
+ if err == nil {
+ netConn.Close()
+ t.Errorf("still listening to %s after closing", forwardedAddr)
+ }
+}
+
+func TestPortForwardTCP(t *testing.T) {
+ testPortForward(t, "tcp", "localhost:0")
+}
+
+func TestPortForwardUnix(t *testing.T) {
+ addr, cleanup := newTempSocket(t)
+ defer cleanup()
+ testPortForward(t, "unix", addr)
+}
+
+func testAcceptClose(t *testing.T, n, listenAddr string) {
+ server := newServer(t)
+ defer server.Shutdown()
+ conn := server.Dial(clientConfig())
+
+ sshListener, err := conn.Listen(n, listenAddr)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ quit := make(chan error, 1)
+ go func() {
+ for {
+ c, err := sshListener.Accept()
+ if err != nil {
+ quit <- err
+ break
+ }
+ c.Close()
+ }
+ }()
+ sshListener.Close()
+
+ select {
+ case <-time.After(1 * time.Second):
+ t.Errorf("timeout: listener did not close.")
+ case err := <-quit:
+ t.Logf("quit as expected (error %v)", err)
+ }
+}
+
+func TestAcceptCloseTCP(t *testing.T) {
+ testAcceptClose(t, "tcp", "localhost:0")
+}
+
+func TestAcceptCloseUnix(t *testing.T) {
+ addr, cleanup := newTempSocket(t)
+ defer cleanup()
+ testAcceptClose(t, "unix", addr)
+}
+
+// Check that listeners exit if the underlying client transport dies.
+func testPortForwardConnectionClose(t *testing.T, n, listenAddr string) {
+ server := newServer(t)
+ defer server.Shutdown()
+ conn := server.Dial(clientConfig())
+
+ sshListener, err := conn.Listen(n, listenAddr)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ quit := make(chan error, 1)
+ go func() {
+ for {
+ c, err := sshListener.Accept()
+ if err != nil {
+ quit <- err
+ break
+ }
+ c.Close()
+ }
+ }()
+
+ // It would be even nicer if we closed the server side, but it
+ // is more involved as the fd for that side is dup()ed.
+ server.clientConn.Close()
+
+ select {
+ case <-time.After(1 * time.Second):
+ t.Errorf("timeout: listener did not close.")
+ case err := <-quit:
+ t.Logf("quit as expected (error %v)", err)
+ }
+}
+
+func TestPortForwardConnectionCloseTCP(t *testing.T) {
+ testPortForwardConnectionClose(t, "tcp", "localhost:0")
+}
+
+func TestPortForwardConnectionCloseUnix(t *testing.T) {
+ addr, cleanup := newTempSocket(t)
+ defer cleanup()
+ testPortForwardConnectionClose(t, "unix", addr)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/test/session_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/test/session_test.go
new file mode 100644
index 000000000..8238d9d90
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/test/session_test.go
@@ -0,0 +1,413 @@
+// Copyright 2012 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.
+
+// +build !windows
+
+package test
+
+// Session functional tests.
+
+import (
+ "bytes"
+ "errors"
+ "io"
+ "strings"
+ "testing"
+
+ "golang.org/x/crypto/ssh"
+)
+
+func TestRunCommandSuccess(t *testing.T) {
+ server := newServer(t)
+ defer server.Shutdown()
+ conn := server.Dial(clientConfig())
+ defer conn.Close()
+
+ session, err := conn.NewSession()
+ if err != nil {
+ t.Fatalf("session failed: %v", err)
+ }
+ defer session.Close()
+ err = session.Run("true")
+ if err != nil {
+ t.Fatalf("session failed: %v", err)
+ }
+}
+
+func TestHostKeyCheck(t *testing.T) {
+ server := newServer(t)
+ defer server.Shutdown()
+
+ conf := clientConfig()
+ hostDB := hostKeyDB()
+ conf.HostKeyCallback = hostDB.Check
+
+ // change the keys.
+ hostDB.keys[ssh.KeyAlgoRSA][25]++
+ hostDB.keys[ssh.KeyAlgoDSA][25]++
+ hostDB.keys[ssh.KeyAlgoECDSA256][25]++
+
+ conn, err := server.TryDial(conf)
+ if err == nil {
+ conn.Close()
+ t.Fatalf("dial should have failed.")
+ } else if !strings.Contains(err.Error(), "host key mismatch") {
+ t.Fatalf("'host key mismatch' not found in %v", err)
+ }
+}
+
+func TestRunCommandStdin(t *testing.T) {
+ server := newServer(t)
+ defer server.Shutdown()
+ conn := server.Dial(clientConfig())
+ defer conn.Close()
+
+ session, err := conn.NewSession()
+ if err != nil {
+ t.Fatalf("session failed: %v", err)
+ }
+ defer session.Close()
+
+ r, w := io.Pipe()
+ defer r.Close()
+ defer w.Close()
+ session.Stdin = r
+
+ err = session.Run("true")
+ if err != nil {
+ t.Fatalf("session failed: %v", err)
+ }
+}
+
+func TestRunCommandStdinError(t *testing.T) {
+ server := newServer(t)
+ defer server.Shutdown()
+ conn := server.Dial(clientConfig())
+ defer conn.Close()
+
+ session, err := conn.NewSession()
+ if err != nil {
+ t.Fatalf("session failed: %v", err)
+ }
+ defer session.Close()
+
+ r, w := io.Pipe()
+ defer r.Close()
+ session.Stdin = r
+ pipeErr := errors.New("closing write end of pipe")
+ w.CloseWithError(pipeErr)
+
+ err = session.Run("true")
+ if err != pipeErr {
+ t.Fatalf("expected %v, found %v", pipeErr, err)
+ }
+}
+
+func TestRunCommandFailed(t *testing.T) {
+ server := newServer(t)
+ defer server.Shutdown()
+ conn := server.Dial(clientConfig())
+ defer conn.Close()
+
+ session, err := conn.NewSession()
+ if err != nil {
+ t.Fatalf("session failed: %v", err)
+ }
+ defer session.Close()
+ err = session.Run(`bash -c "kill -9 $$"`)
+ if err == nil {
+ t.Fatalf("session succeeded: %v", err)
+ }
+}
+
+func TestRunCommandWeClosed(t *testing.T) {
+ server := newServer(t)
+ defer server.Shutdown()
+ conn := server.Dial(clientConfig())
+ defer conn.Close()
+
+ session, err := conn.NewSession()
+ if err != nil {
+ t.Fatalf("session failed: %v", err)
+ }
+ err = session.Shell()
+ if err != nil {
+ t.Fatalf("shell failed: %v", err)
+ }
+ err = session.Close()
+ if err != nil {
+ t.Fatalf("shell failed: %v", err)
+ }
+}
+
+func TestFuncLargeRead(t *testing.T) {
+ server := newServer(t)
+ defer server.Shutdown()
+ conn := server.Dial(clientConfig())
+ defer conn.Close()
+
+ session, err := conn.NewSession()
+ if err != nil {
+ t.Fatalf("unable to create new session: %s", err)
+ }
+
+ stdout, err := session.StdoutPipe()
+ if err != nil {
+ t.Fatalf("unable to acquire stdout pipe: %s", err)
+ }
+
+ err = session.Start("dd if=/dev/urandom bs=2048 count=1024")
+ if err != nil {
+ t.Fatalf("unable to execute remote command: %s", err)
+ }
+
+ buf := new(bytes.Buffer)
+ n, err := io.Copy(buf, stdout)
+ if err != nil {
+ t.Fatalf("error reading from remote stdout: %s", err)
+ }
+
+ if n != 2048*1024 {
+ t.Fatalf("Expected %d bytes but read only %d from remote command", 2048, n)
+ }
+}
+
+func TestKeyChange(t *testing.T) {
+ server := newServer(t)
+ defer server.Shutdown()
+ conf := clientConfig()
+ hostDB := hostKeyDB()
+ conf.HostKeyCallback = hostDB.Check
+ conf.RekeyThreshold = 1024
+ conn := server.Dial(conf)
+ defer conn.Close()
+
+ for i := 0; i < 4; i++ {
+ session, err := conn.NewSession()
+ if err != nil {
+ t.Fatalf("unable to create new session: %s", err)
+ }
+
+ stdout, err := session.StdoutPipe()
+ if err != nil {
+ t.Fatalf("unable to acquire stdout pipe: %s", err)
+ }
+
+ err = session.Start("dd if=/dev/urandom bs=1024 count=1")
+ if err != nil {
+ t.Fatalf("unable to execute remote command: %s", err)
+ }
+ buf := new(bytes.Buffer)
+ n, err := io.Copy(buf, stdout)
+ if err != nil {
+ t.Fatalf("error reading from remote stdout: %s", err)
+ }
+
+ want := int64(1024)
+ if n != want {
+ t.Fatalf("Expected %d bytes but read only %d from remote command", want, n)
+ }
+ }
+
+ if changes := hostDB.checkCount; changes < 4 {
+ t.Errorf("got %d key changes, want 4", changes)
+ }
+}
+
+func TestInvalidTerminalMode(t *testing.T) {
+ server := newServer(t)
+ defer server.Shutdown()
+ conn := server.Dial(clientConfig())
+ defer conn.Close()
+
+ session, err := conn.NewSession()
+ if err != nil {
+ t.Fatalf("session failed: %v", err)
+ }
+ defer session.Close()
+
+ if err = session.RequestPty("vt100", 80, 40, ssh.TerminalModes{255: 1984}); err == nil {
+ t.Fatalf("req-pty failed: successful request with invalid mode")
+ }
+}
+
+func TestValidTerminalMode(t *testing.T) {
+ server := newServer(t)
+ defer server.Shutdown()
+ conn := server.Dial(clientConfig())
+ defer conn.Close()
+
+ session, err := conn.NewSession()
+ if err != nil {
+ t.Fatalf("session failed: %v", err)
+ }
+ defer session.Close()
+
+ stdout, err := session.StdoutPipe()
+ if err != nil {
+ t.Fatalf("unable to acquire stdout pipe: %s", err)
+ }
+
+ stdin, err := session.StdinPipe()
+ if err != nil {
+ t.Fatalf("unable to acquire stdin pipe: %s", err)
+ }
+
+ tm := ssh.TerminalModes{ssh.ECHO: 0}
+ if err = session.RequestPty("xterm", 80, 40, tm); err != nil {
+ t.Fatalf("req-pty failed: %s", err)
+ }
+
+ err = session.Shell()
+ if err != nil {
+ t.Fatalf("session failed: %s", err)
+ }
+
+ stdin.Write([]byte("stty -a && exit\n"))
+
+ var buf bytes.Buffer
+ if _, err := io.Copy(&buf, stdout); err != nil {
+ t.Fatalf("reading failed: %s", err)
+ }
+
+ if sttyOutput := buf.String(); !strings.Contains(sttyOutput, "-echo ") {
+ t.Fatalf("terminal mode failure: expected -echo in stty output, got %s", sttyOutput)
+ }
+}
+
+func TestWindowChange(t *testing.T) {
+ server := newServer(t)
+ defer server.Shutdown()
+ conn := server.Dial(clientConfig())
+ defer conn.Close()
+
+ session, err := conn.NewSession()
+ if err != nil {
+ t.Fatalf("session failed: %v", err)
+ }
+ defer session.Close()
+
+ stdout, err := session.StdoutPipe()
+ if err != nil {
+ t.Fatalf("unable to acquire stdout pipe: %s", err)
+ }
+
+ stdin, err := session.StdinPipe()
+ if err != nil {
+ t.Fatalf("unable to acquire stdin pipe: %s", err)
+ }
+
+ tm := ssh.TerminalModes{ssh.ECHO: 0}
+ if err = session.RequestPty("xterm", 80, 40, tm); err != nil {
+ t.Fatalf("req-pty failed: %s", err)
+ }
+
+ if err := session.WindowChange(100, 100); err != nil {
+ t.Fatalf("window-change failed: %s", err)
+ }
+
+ err = session.Shell()
+ if err != nil {
+ t.Fatalf("session failed: %s", err)
+ }
+
+ stdin.Write([]byte("stty size && exit\n"))
+
+ var buf bytes.Buffer
+ if _, err := io.Copy(&buf, stdout); err != nil {
+ t.Fatalf("reading failed: %s", err)
+ }
+
+ if sttyOutput := buf.String(); !strings.Contains(sttyOutput, "100 100") {
+ t.Fatalf("terminal WindowChange failure: expected \"100 100\" stty output, got %s", sttyOutput)
+ }
+}
+
+func TestCiphers(t *testing.T) {
+ var config ssh.Config
+ config.SetDefaults()
+ cipherOrder := config.Ciphers
+ // These ciphers will not be tested when commented out in cipher.go it will
+ // fallback to the next available as per line 292.
+ cipherOrder = append(cipherOrder, "aes128-cbc", "3des-cbc")
+
+ for _, ciph := range cipherOrder {
+ server := newServer(t)
+ defer server.Shutdown()
+ conf := clientConfig()
+ conf.Ciphers = []string{ciph}
+ // Don't fail if sshd doesn't have the cipher.
+ conf.Ciphers = append(conf.Ciphers, cipherOrder...)
+ conn, err := server.TryDial(conf)
+ if err == nil {
+ conn.Close()
+ } else {
+ t.Fatalf("failed for cipher %q", ciph)
+ }
+ }
+}
+
+func TestMACs(t *testing.T) {
+ var config ssh.Config
+ config.SetDefaults()
+ macOrder := config.MACs
+
+ for _, mac := range macOrder {
+ server := newServer(t)
+ defer server.Shutdown()
+ conf := clientConfig()
+ conf.MACs = []string{mac}
+ // Don't fail if sshd doesn't have the MAC.
+ conf.MACs = append(conf.MACs, macOrder...)
+ if conn, err := server.TryDial(conf); err == nil {
+ conn.Close()
+ } else {
+ t.Fatalf("failed for MAC %q", mac)
+ }
+ }
+}
+
+func TestKeyExchanges(t *testing.T) {
+ var config ssh.Config
+ config.SetDefaults()
+ kexOrder := config.KeyExchanges
+ for _, kex := range kexOrder {
+ server := newServer(t)
+ defer server.Shutdown()
+ conf := clientConfig()
+ // Don't fail if sshd doesn't have the kex.
+ conf.KeyExchanges = append([]string{kex}, kexOrder...)
+ conn, err := server.TryDial(conf)
+ if err == nil {
+ conn.Close()
+ } else {
+ t.Errorf("failed for kex %q", kex)
+ }
+ }
+}
+
+func TestClientAuthAlgorithms(t *testing.T) {
+ for _, key := range []string{
+ "rsa",
+ "dsa",
+ "ecdsa",
+ "ed25519",
+ } {
+ server := newServer(t)
+ conf := clientConfig()
+ conf.SetDefaults()
+ conf.Auth = []ssh.AuthMethod{
+ ssh.PublicKeys(testSigners[key]),
+ }
+
+ conn, err := server.TryDial(conf)
+ if err == nil {
+ conn.Close()
+ } else {
+ t.Errorf("failed for key %q", key)
+ }
+
+ server.Shutdown()
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/test/test_unix_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/test/test_unix_test.go
new file mode 100644
index 000000000..6b1e0fff1
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/test/test_unix_test.go
@@ -0,0 +1,298 @@
+// Copyright 2012 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.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd plan9
+
+package test
+
+// functional test harness for unix.
+
+import (
+ "bytes"
+ "fmt"
+ "io/ioutil"
+ "log"
+ "net"
+ "os"
+ "os/exec"
+ "os/user"
+ "path/filepath"
+ "testing"
+ "text/template"
+
+ "golang.org/x/crypto/ssh"
+ "golang.org/x/crypto/ssh/testdata"
+)
+
+const sshd_config = `
+Protocol 2
+Banner {{.Dir}}/banner
+HostKey {{.Dir}}/id_rsa
+HostKey {{.Dir}}/id_dsa
+HostKey {{.Dir}}/id_ecdsa
+HostCertificate {{.Dir}}/id_rsa-cert.pub
+Pidfile {{.Dir}}/sshd.pid
+#UsePrivilegeSeparation no
+KeyRegenerationInterval 3600
+ServerKeyBits 768
+SyslogFacility AUTH
+LogLevel DEBUG2
+LoginGraceTime 120
+PermitRootLogin no
+StrictModes no
+RSAAuthentication yes
+PubkeyAuthentication yes
+AuthorizedKeysFile {{.Dir}}/authorized_keys
+TrustedUserCAKeys {{.Dir}}/id_ecdsa.pub
+IgnoreRhosts yes
+RhostsRSAAuthentication no
+HostbasedAuthentication no
+PubkeyAcceptedKeyTypes=*
+`
+
+var configTmpl = template.Must(template.New("").Parse(sshd_config))
+
+type server struct {
+ t *testing.T
+ cleanup func() // executed during Shutdown
+ configfile string
+ cmd *exec.Cmd
+ output bytes.Buffer // holds stderr from sshd process
+
+ // Client half of the network connection.
+ clientConn net.Conn
+}
+
+func username() string {
+ var username string
+ if user, err := user.Current(); err == nil {
+ username = user.Username
+ } else {
+ // user.Current() currently requires cgo. If an error is
+ // returned attempt to get the username from the environment.
+ log.Printf("user.Current: %v; falling back on $USER", err)
+ username = os.Getenv("USER")
+ }
+ if username == "" {
+ panic("Unable to get username")
+ }
+ return username
+}
+
+type storedHostKey struct {
+ // keys map from an algorithm string to binary key data.
+ keys map[string][]byte
+
+ // checkCount counts the Check calls. Used for testing
+ // rekeying.
+ checkCount int
+}
+
+func (k *storedHostKey) Add(key ssh.PublicKey) {
+ if k.keys == nil {
+ k.keys = map[string][]byte{}
+ }
+ k.keys[key.Type()] = key.Marshal()
+}
+
+func (k *storedHostKey) Check(addr string, remote net.Addr, key ssh.PublicKey) error {
+ k.checkCount++
+ algo := key.Type()
+
+ if k.keys == nil || bytes.Compare(key.Marshal(), k.keys[algo]) != 0 {
+ return fmt.Errorf("host key mismatch. Got %q, want %q", key, k.keys[algo])
+ }
+ return nil
+}
+
+func hostKeyDB() *storedHostKey {
+ keyChecker := &storedHostKey{}
+ keyChecker.Add(testPublicKeys["ecdsa"])
+ keyChecker.Add(testPublicKeys["rsa"])
+ keyChecker.Add(testPublicKeys["dsa"])
+ return keyChecker
+}
+
+func clientConfig() *ssh.ClientConfig {
+ config := &ssh.ClientConfig{
+ User: username(),
+ Auth: []ssh.AuthMethod{
+ ssh.PublicKeys(testSigners["user"]),
+ },
+ HostKeyCallback: hostKeyDB().Check,
+ HostKeyAlgorithms: []string{ // by default, don't allow certs as this affects the hostKeyDB checker
+ ssh.KeyAlgoECDSA256, ssh.KeyAlgoECDSA384, ssh.KeyAlgoECDSA521,
+ ssh.KeyAlgoRSA, ssh.KeyAlgoDSA,
+ ssh.KeyAlgoED25519,
+ },
+ }
+ return config
+}
+
+// unixConnection creates two halves of a connected net.UnixConn. It
+// is used for connecting the Go SSH client with sshd without opening
+// ports.
+func unixConnection() (*net.UnixConn, *net.UnixConn, error) {
+ dir, err := ioutil.TempDir("", "unixConnection")
+ if err != nil {
+ return nil, nil, err
+ }
+ defer os.Remove(dir)
+
+ addr := filepath.Join(dir, "ssh")
+ listener, err := net.Listen("unix", addr)
+ if err != nil {
+ return nil, nil, err
+ }
+ defer listener.Close()
+ c1, err := net.Dial("unix", addr)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ c2, err := listener.Accept()
+ if err != nil {
+ c1.Close()
+ return nil, nil, err
+ }
+
+ return c1.(*net.UnixConn), c2.(*net.UnixConn), nil
+}
+
+func (s *server) TryDial(config *ssh.ClientConfig) (*ssh.Client, error) {
+ return s.TryDialWithAddr(config, "")
+}
+
+// addr is the user specified host:port. While we don't actually dial it,
+// we need to know this for host key matching
+func (s *server) TryDialWithAddr(config *ssh.ClientConfig, addr string) (*ssh.Client, error) {
+ sshd, err := exec.LookPath("sshd")
+ if err != nil {
+ s.t.Skipf("skipping test: %v", err)
+ }
+
+ c1, c2, err := unixConnection()
+ if err != nil {
+ s.t.Fatalf("unixConnection: %v", err)
+ }
+
+ s.cmd = exec.Command(sshd, "-f", s.configfile, "-i", "-e")
+ f, err := c2.File()
+ if err != nil {
+ s.t.Fatalf("UnixConn.File: %v", err)
+ }
+ defer f.Close()
+ s.cmd.Stdin = f
+ s.cmd.Stdout = f
+ s.cmd.Stderr = &s.output
+ if err := s.cmd.Start(); err != nil {
+ s.t.Fail()
+ s.Shutdown()
+ s.t.Fatalf("s.cmd.Start: %v", err)
+ }
+ s.clientConn = c1
+ conn, chans, reqs, err := ssh.NewClientConn(c1, addr, config)
+ if err != nil {
+ return nil, err
+ }
+ return ssh.NewClient(conn, chans, reqs), nil
+}
+
+func (s *server) Dial(config *ssh.ClientConfig) *ssh.Client {
+ conn, err := s.TryDial(config)
+ if err != nil {
+ s.t.Fail()
+ s.Shutdown()
+ s.t.Fatalf("ssh.Client: %v", err)
+ }
+ return conn
+}
+
+func (s *server) Shutdown() {
+ if s.cmd != nil && s.cmd.Process != nil {
+ // Don't check for errors; if it fails it's most
+ // likely "os: process already finished", and we don't
+ // care about that. Use os.Interrupt, so child
+ // processes are killed too.
+ s.cmd.Process.Signal(os.Interrupt)
+ s.cmd.Wait()
+ }
+ if s.t.Failed() {
+ // log any output from sshd process
+ s.t.Logf("sshd: %s", s.output.String())
+ }
+ s.cleanup()
+}
+
+func writeFile(path string, contents []byte) {
+ f, err := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0600)
+ if err != nil {
+ panic(err)
+ }
+ defer f.Close()
+ if _, err := f.Write(contents); err != nil {
+ panic(err)
+ }
+}
+
+// newServer returns a new mock ssh server.
+func newServer(t *testing.T) *server {
+ if testing.Short() {
+ t.Skip("skipping test due to -short")
+ }
+ dir, err := ioutil.TempDir("", "sshtest")
+ if err != nil {
+ t.Fatal(err)
+ }
+ f, err := os.Create(filepath.Join(dir, "sshd_config"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ err = configTmpl.Execute(f, map[string]string{
+ "Dir": dir,
+ })
+ if err != nil {
+ t.Fatal(err)
+ }
+ f.Close()
+
+ writeFile(filepath.Join(dir, "banner"), []byte("Server Banner"))
+
+ for k, v := range testdata.PEMBytes {
+ filename := "id_" + k
+ writeFile(filepath.Join(dir, filename), v)
+ writeFile(filepath.Join(dir, filename+".pub"), ssh.MarshalAuthorizedKey(testPublicKeys[k]))
+ }
+
+ for k, v := range testdata.SSHCertificates {
+ filename := "id_" + k + "-cert.pub"
+ writeFile(filepath.Join(dir, filename), v)
+ }
+
+ var authkeys bytes.Buffer
+ for k, _ := range testdata.PEMBytes {
+ authkeys.Write(ssh.MarshalAuthorizedKey(testPublicKeys[k]))
+ }
+ writeFile(filepath.Join(dir, "authorized_keys"), authkeys.Bytes())
+
+ return &server{
+ t: t,
+ configfile: f.Name(),
+ cleanup: func() {
+ if err := os.RemoveAll(dir); err != nil {
+ t.Error(err)
+ }
+ },
+ }
+}
+
+func newTempSocket(t *testing.T) (string, func()) {
+ dir, err := ioutil.TempDir("", "socket")
+ if err != nil {
+ t.Fatal(err)
+ }
+ deferFunc := func() { os.RemoveAll(dir) }
+ addr := filepath.Join(dir, "sock")
+ return addr, deferFunc
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/test/testdata_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/test/testdata_test.go
new file mode 100644
index 000000000..a053f67ea
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/test/testdata_test.go
@@ -0,0 +1,64 @@
+// Copyright 2014 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.
+
+// IMPLEMENTATION NOTE: To avoid a package loop, this file is in three places:
+// ssh/, ssh/agent, and ssh/test/. It should be kept in sync across all three
+// instances.
+
+package test
+
+import (
+ "crypto/rand"
+ "fmt"
+
+ "golang.org/x/crypto/ssh"
+ "golang.org/x/crypto/ssh/testdata"
+)
+
+var (
+ testPrivateKeys map[string]interface{}
+ testSigners map[string]ssh.Signer
+ testPublicKeys map[string]ssh.PublicKey
+)
+
+func init() {
+ var err error
+
+ n := len(testdata.PEMBytes)
+ testPrivateKeys = make(map[string]interface{}, n)
+ testSigners = make(map[string]ssh.Signer, n)
+ testPublicKeys = make(map[string]ssh.PublicKey, n)
+ for t, k := range testdata.PEMBytes {
+ testPrivateKeys[t], err = ssh.ParseRawPrivateKey(k)
+ if err != nil {
+ panic(fmt.Sprintf("Unable to parse test key %s: %v", t, err))
+ }
+ testSigners[t], err = ssh.NewSignerFromKey(testPrivateKeys[t])
+ if err != nil {
+ panic(fmt.Sprintf("Unable to create signer for test key %s: %v", t, err))
+ }
+ testPublicKeys[t] = testSigners[t].PublicKey()
+ }
+
+ // Create a cert and sign it for use in tests.
+ testCert := &ssh.Certificate{
+ Nonce: []byte{}, // To pass reflect.DeepEqual after marshal & parse, this must be non-nil
+ ValidPrincipals: []string{"gopher1", "gopher2"}, // increases test coverage
+ ValidAfter: 0, // unix epoch
+ ValidBefore: ssh.CertTimeInfinity, // The end of currently representable time.
+ Reserved: []byte{}, // To pass reflect.DeepEqual after marshal & parse, this must be non-nil
+ Key: testPublicKeys["ecdsa"],
+ SignatureKey: testPublicKeys["rsa"],
+ Permissions: ssh.Permissions{
+ CriticalOptions: map[string]string{},
+ Extensions: map[string]string{},
+ },
+ }
+ testCert.SignCert(rand.Reader, testSigners["rsa"])
+ testPrivateKeys["cert"] = testPrivateKeys["ecdsa"]
+ testSigners["cert"], err = ssh.NewCertSigner(testCert, testSigners["ecdsa"])
+ if err != nil {
+ panic(fmt.Sprintf("Unable to create certificate signer: %v", err))
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/testdata/doc.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/testdata/doc.go
new file mode 100644
index 000000000..fcae47ca6
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/testdata/doc.go
@@ -0,0 +1,8 @@
+// Copyright 2014 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.
+
+// This package contains test data shared between the various subpackages of
+// the golang.org/x/crypto/ssh package. Under no circumstance should
+// this data be used for production code.
+package testdata // import "golang.org/x/crypto/ssh/testdata"
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/testdata/keys.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/testdata/keys.go
new file mode 100644
index 000000000..3b3d26c5b
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/testdata/keys.go
@@ -0,0 +1,177 @@
+// Copyright 2014 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 testdata
+
+var PEMBytes = map[string][]byte{
+ "dsa": []byte(`-----BEGIN DSA PRIVATE KEY-----
+MIIBuwIBAAKBgQD6PDSEyXiI9jfNs97WuM46MSDCYlOqWw80ajN16AohtBncs1YB
+lHk//dQOvCYOsYaE+gNix2jtoRjwXhDsc25/IqQbU1ahb7mB8/rsaILRGIbA5WH3
+EgFtJmXFovDz3if6F6TzvhFpHgJRmLYVR8cqsezL3hEZOvvs2iH7MorkxwIVAJHD
+nD82+lxh2fb4PMsIiaXudAsBAoGAQRf7Q/iaPRn43ZquUhd6WwvirqUj+tkIu6eV
+2nZWYmXLlqFQKEy4Tejl7Wkyzr2OSYvbXLzo7TNxLKoWor6ips0phYPPMyXld14r
+juhT24CrhOzuLMhDduMDi032wDIZG4Y+K7ElU8Oufn8Sj5Wge8r6ANmmVgmFfynr
+FhdYCngCgYEA3ucGJ93/Mx4q4eKRDxcWD3QzWyqpbRVRRV1Vmih9Ha/qC994nJFz
+DQIdjxDIT2Rk2AGzMqFEB68Zc3O+Wcsmz5eWWzEwFxaTwOGWTyDqsDRLm3fD+QYj
+nOwuxb0Kce+gWI8voWcqC9cyRm09jGzu2Ab3Bhtpg8JJ8L7gS3MRZK4CFEx4UAfY
+Fmsr0W6fHB9nhS4/UXM8
+-----END DSA PRIVATE KEY-----
+`),
+ "ecdsa": []byte(`-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEINGWx0zo6fhJ/0EAfrPzVFyFC9s18lBt3cRoEDhS3ARooAoGCCqGSM49
+AwEHoUQDQgAEi9Hdw6KvZcWxfg2IDhA7UkpDtzzt6ZqJXSsFdLd+Kx4S3Sx4cVO+
+6/ZOXRnPmNAlLUqjShUsUBBngG0u2fqEqA==
+-----END EC PRIVATE KEY-----
+`),
+ "rsa": []byte(`-----BEGIN RSA PRIVATE KEY-----
+MIICXAIBAAKBgQC8A6FGHDiWCSREAXCq6yBfNVr0xCVG2CzvktFNRpue+RXrGs/2
+a6ySEJQb3IYquw7HlJgu6fg3WIWhOmHCjfpG0PrL4CRwbqQ2LaPPXhJErWYejcD8
+Di00cF3677+G10KMZk9RXbmHtuBFZT98wxg8j+ZsBMqGM1+7yrWUvynswQIDAQAB
+AoGAJMCk5vqfSRzyXOTXLGIYCuR4Kj6pdsbNSeuuRGfYBeR1F2c/XdFAg7D/8s5R
+38p/Ih52/Ty5S8BfJtwtvgVY9ecf/JlU/rl/QzhG8/8KC0NG7KsyXklbQ7gJT8UT
+Ojmw5QpMk+rKv17ipDVkQQmPaj+gJXYNAHqImke5mm/K/h0CQQDciPmviQ+DOhOq
+2ZBqUfH8oXHgFmp7/6pXw80DpMIxgV3CwkxxIVx6a8lVH9bT/AFySJ6vXq4zTuV9
+6QmZcZzDAkEA2j/UXJPIs1fQ8z/6sONOkU/BjtoePFIWJlRxdN35cZjXnBraX5UR
+fFHkePv4YwqmXNqrBOvSu+w2WdSDci+IKwJAcsPRc/jWmsrJW1q3Ha0hSf/WG/Bu
+X7MPuXaKpP/DkzGoUmb8ks7yqj6XWnYkPNLjCc8izU5vRwIiyWBRf4mxMwJBAILa
+NDvRS0rjwt6lJGv7zPZoqDc65VfrK2aNyHx2PgFyzwrEOtuF57bu7pnvEIxpLTeM
+z26i6XVMeYXAWZMTloMCQBbpGgEERQpeUknLBqUHhg/wXF6+lFA+vEGnkY+Dwab2
+KCXFGd+SQ5GdUcEMe9isUH6DYj/6/yCDoFrXXmpQb+M=
+-----END RSA PRIVATE KEY-----
+`),
+ "ed25519": []byte(`-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
+QyNTUxOQAAACA+3f7hS7g5UWwXOGVTrMfhmxyrjqz7Sxxbx7I1j8DvvwAAAJhAFfkOQBX5
+DgAAAAtzc2gtZWQyNTUxOQAAACA+3f7hS7g5UWwXOGVTrMfhmxyrjqz7Sxxbx7I1j8Dvvw
+AAAEAaYmXltfW6nhRo3iWGglRB48lYq0z0Q3I3KyrdutEr6j7d/uFLuDlRbBc4ZVOsx+Gb
+HKuOrPtLHFvHsjWPwO+/AAAAE2dhcnRvbm1AZ2FydG9ubS14cHMBAg==
+-----END OPENSSH PRIVATE KEY-----
+`),
+ "rsa-openssh-format": []byte(`-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAlwAAAAdzc2gtcn
+NhAAAAAwEAAQAAAIEAwa48yfWFi3uIdqzuf9X7C2Zxfea/Iaaw0zIwHudpF8U92WVIiC5l
+oEuW1+OaVi3UWfIEjWMV1tHGysrHOwtwc34BPCJqJknUQO/KtDTBTJ4Pryhw1bWPC999Lz
+a+yrCTdNQYBzoROXKExZgPFh9pTMi5wqpHDuOQ2qZFIEI3lT0AAAIQWL0H31i9B98AAAAH
+c3NoLXJzYQAAAIEAwa48yfWFi3uIdqzuf9X7C2Zxfea/Iaaw0zIwHudpF8U92WVIiC5loE
+uW1+OaVi3UWfIEjWMV1tHGysrHOwtwc34BPCJqJknUQO/KtDTBTJ4Pryhw1bWPC999Lza+
+yrCTdNQYBzoROXKExZgPFh9pTMi5wqpHDuOQ2qZFIEI3lT0AAAADAQABAAAAgCThyTGsT4
+IARDxVMhWl6eiB2ZrgFgWSeJm/NOqtppWgOebsIqPMMg4UVuVFsl422/lE3RkPhVkjGXgE
+pWvZAdCnmLmApK8wK12vF334lZhZT7t3Z9EzJps88PWEHo7kguf285HcnUM7FlFeissJdk
+kXly34y7/3X/a6Tclm+iABAAAAQE0xR/KxZ39slwfMv64Rz7WKk1PPskaryI29aHE3mKHk
+pY2QA+P3QlrKxT/VWUMjHUbNNdYfJm48xu0SGNMRdKMAAABBAORh2NP/06JUV3J9W/2Hju
+X1ViJuqqcQnJPVzpgSL826EC2xwOECTqoY8uvFpUdD7CtpksIxNVqRIhuNOlz0lqEAAABB
+ANkaHTTaPojClO0dKJ/Zjs7pWOCGliebBYprQ/Y4r9QLBkC/XaWMS26gFIrjgC7D2Rv+rZ
+wSD0v0RcmkITP1ZR0AAAAYcHF1ZXJuYUBMdWNreUh5ZHJvLmxvY2FsAQID
+-----END OPENSSH PRIVATE KEY-----`),
+ "user": []byte(`-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEILYCAeq8f7V4vSSypRw7pxy8yz3V5W4qg8kSC3zJhqpQoAoGCCqGSM49
+AwEHoUQDQgAEYcO2xNKiRUYOLEHM7VYAp57HNyKbOdYtHD83Z4hzNPVC4tM5mdGD
+PLL8IEwvYu2wq+lpXfGQnNMbzYf9gspG0w==
+-----END EC PRIVATE KEY-----
+`),
+ "ca": []byte(`-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEAvg9dQ9IRG59lYJb+GESfKWTch4yBpr7Ydw1jkK6vvtrx9jLo
+5hkA8X6+ElRPRqTAZSlN5cBm6YCAcQIOsmXDUn6Oj1lVPQAoOjTBTvsjM3NjGhvv
+52kHTY0nsMsBeY9q5DTtlzmlYkVUq2a6Htgf2mNi01dIw5fJ7uTTo8EbNf7O0i3u
+c9a8P19HaZl5NKiWN4EIZkfB2WdXYRJCVBsGgQj3dE/GrEmH9QINq1A+GkNvK96u
+vZm8H1jjmuqzHplWa7lFeXcx8FTVTbVb/iJrZ2Lc/JvIPitKZWhqbR59yrGjpwEp
+Id7bo4WhO5L3OB0fSIJYvfu+o4WYnt4f3UzecwIDAQABAoIBABRD9yHgKErVuC2Q
+bA+SYZY8VvdtF/X7q4EmQFORDNRA7EPgMc03JU6awRGbQ8i4kHs46EFzPoXvWcKz
+AXYsO6N0Myc900Tp22A5d9NAHATEbPC/wdje7hRq1KyZONMJY9BphFv3nZbY5apR
+Dc90JBFZP5RhXjTc3n9GjvqLAKfFEKVmPRCvqxCOZunw6XR+SgIQLJo36nsIsbhW
+QUXIVaCI6cXMN8bRPm8EITdBNZu06Fpu4ZHm6VaxlXN9smERCDkgBSNXNWHKxmmA
+c3Glo2DByUr2/JFBOrLEe9fkYgr24KNCQkHVcSaFxEcZvTggr7StjKISVHlCNEaB
+7Q+kPoECgYEA3zE9FmvFGoQCU4g4Nl3dpQHs6kaAW8vJlrmq3xsireIuaJoa2HMe
+wYdIvgCnK9DIjyxd5OWnE4jXtAEYPsyGD32B5rSLQrRO96lgb3f4bESCLUb3Bsn/
+sdgeE3p1xZMA0B59htqCrvVgN9k8WxyevBxYl3/gSBm/p8OVH1RTW/ECgYEA2f9Z
+95OLj0KQHQtxQXf+I3VjhCw3LkLW39QZOXVI0QrCJfqqP7uxsJXH9NYX0l0GFTcR
+kRrlyoaSU1EGQosZh+n1MvplGBTkTSV47/bPsTzFpgK2NfEZuFm9RoWgltS+nYeH
+Y2k4mnAN3PhReCMwuprmJz8GRLsO3Cs2s2YylKMCgYEA2UX+uO/q7jgqZ5UJW+ue
+1H5+W0aMuFA3i7JtZEnvRaUVFqFGlwXin/WJ2+WY1++k/rPrJ+Rk9IBXtBUIvEGw
+FC5TIfsKQsJyyWgqx/jbbtJ2g4s8+W/1qfTAuqeRNOg5d2DnRDs90wJuS4//0JaY
+9HkHyVwkQyxFxhSA/AHEMJECgYA2MvyFR1O9bIk0D3I7GsA+xKLXa77Ua53MzIjw
+9i4CezBGDQpjCiFli/fI8am+jY5DnAtsDknvjoG24UAzLy5L0mk6IXMdB6SzYYut
+7ak5oahqW+Y9hxIj+XvLmtGQbphtxhJtLu35x75KoBpxSh6FZpmuTEccs31AVCYn
+eFM/DQKBgQDOPUwbLKqVi6ddFGgrV9MrWw+SWsDa43bPuyvYppMM3oqesvyaX1Dt
+qDvN7owaNxNM4OnfKcZr91z8YPVCFo4RbBif3DXRzjNNBlxEjHBtuMOikwvsmucN
+vIrbeEpjTiUMTEAr6PoTiVHjsfS8WAM6MDlF5M+2PNswDsBpa2yLgA==
+-----END RSA PRIVATE KEY-----
+`),
+}
+
+var SSHCertificates = map[string][]byte{
+ // The following are corresponding certificates for the private keys above, signed by the CA key
+ // Generated by the following commands:
+ //
+ // 1. Assumes "rsa" key above in file named "rsa", write out the public key to "rsa.pub":
+ // ssh-keygen -y -f rsa > rsa.pu
+ //
+ // 2. Assumes "ca" key above in file named "ca", sign a cert for "rsa.pub":
+ // ssh-keygen -s ca -h -n host.example.com -V +500w -I host.example.com-key rsa.pub
+ "rsa": []byte(`ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgLjYqmmuTSEmjVhSfLQphBSTJMLwIZhRgmpn8FHKLiEIAAAADAQABAAAAgQC8A6FGHDiWCSREAXCq6yBfNVr0xCVG2CzvktFNRpue+RXrGs/2a6ySEJQb3IYquw7HlJgu6fg3WIWhOmHCjfpG0PrL4CRwbqQ2LaPPXhJErWYejcD8Di00cF3677+G10KMZk9RXbmHtuBFZT98wxg8j+ZsBMqGM1+7yrWUvynswQAAAAAAAAAAAAAAAgAAABRob3N0LmV4YW1wbGUuY29tLWtleQAAABQAAAAQaG9zdC5leGFtcGxlLmNvbQAAAABZHN8UAAAAAGsjIYUAAAAAAAAAAAAAAAAAAAEXAAAAB3NzaC1yc2EAAAADAQABAAABAQC+D11D0hEbn2Vglv4YRJ8pZNyHjIGmvth3DWOQrq++2vH2MujmGQDxfr4SVE9GpMBlKU3lwGbpgIBxAg6yZcNSfo6PWVU9ACg6NMFO+yMzc2MaG+/naQdNjSewywF5j2rkNO2XOaViRVSrZroe2B/aY2LTV0jDl8nu5NOjwRs1/s7SLe5z1rw/X0dpmXk0qJY3gQhmR8HZZ1dhEkJUGwaBCPd0T8asSYf1Ag2rUD4aQ28r3q69mbwfWOOa6rMemVZruUV5dzHwVNVNtVv+ImtnYtz8m8g+K0plaGptHn3KsaOnASkh3tujhaE7kvc4HR9Igli9+76jhZie3h/dTN5zAAABDwAAAAdzc2gtcnNhAAABALeDea+60H6xJGhktAyosHaSY7AYzLocaqd8hJQjEIDifBwzoTlnBmcK9CxGhKuaoJFThdCLdaevCeOSuquh8HTkf+2ebZZc/G5T+2thPvPqmcuEcmMosWo+SIjYhbP3S6KD49aLC1X0kz8IBQeauFvURhkZ5ZjhA1L4aQYt9NjL73nqOl8PplRui+Ov5w8b4ldul4zOvYAFrzfcP6wnnXk3c1Zzwwf5wynD5jakO8GpYKBuhM7Z4crzkKSQjU3hla7xqgfomC5Gz4XbR2TNjcQiRrJQ0UlKtX3X3ObRCEhuvG0Kzjklhv+Ddw6txrhKjMjiSi/Yyius/AE8TmC1p4U= host.example.com
+`),
+}
+
+var PEMEncryptedKeys = []struct {
+ Name string
+ EncryptionKey string
+ PEMBytes []byte
+}{
+ 0: {
+ Name: "rsa-encrypted",
+ EncryptionKey: "r54-G0pher_t3st$",
+ PEMBytes: []byte(`-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-CBC,3E1714DE130BC5E81327F36564B05462
+
+MqW88sud4fnWk/Jk3fkjh7ydu51ZkHLN5qlQgA4SkAXORPPMj2XvqZOv1v2LOgUV
+dUevUn8PZK7a9zbZg4QShUSzwE5k6wdB7XKPyBgI39mJ79GBd2U4W3h6KT6jIdWA
+goQpluxkrzr2/X602IaxLEre97FT9mpKC6zxKCLvyFWVIP9n3OSFS47cTTXyFr+l
+7PdRhe60nn6jSBgUNk/Q1lAvEQ9fufdPwDYY93F1wyJ6lOr0F1+mzRrMbH67NyKs
+rG8J1Fa7cIIre7ueKIAXTIne7OAWqpU9UDgQatDtZTbvA7ciqGsSFgiwwW13N+Rr
+hN8MkODKs9cjtONxSKi05s206A3NDU6STtZ3KuPDjFE1gMJODotOuqSM+cxKfyFq
+wxpk/CHYCDdMAVBSwxb/vraOHamylL4uCHpJdBHypzf2HABt+lS8Su23uAmL87DR
+yvyCS/lmpuNTndef6qHPRkoW2EV3xqD3ovosGf7kgwGJUk2ZpCLVteqmYehKlZDK
+r/Jy+J26ooI2jIg9bjvD1PZq+Mv+2dQ1RlDrPG3PB+rEixw6vBaL9x3jatCd4ej7
+XG7lb3qO9xFpLsx89tkEcvpGR+broSpUJ6Mu5LBCVmrvqHjvnDhrZVz1brMiQtU9
+iMZbgXqDLXHd6ERWygk7OTU03u+l1gs+KGMfmS0h0ZYw6KGVLgMnsoxqd6cFSKNB
+8Ohk9ZTZGCiovlXBUepyu8wKat1k8YlHSfIHoRUJRhhcd7DrmojC+bcbMIZBU22T
+Pl2ftVRGtcQY23lYd0NNKfebF7ncjuLWQGy+vZW+7cgfI6wPIbfYfP6g7QAutk6W
+KQx0AoX5woZ6cNxtpIrymaVjSMRRBkKQrJKmRp3pC/lul5E5P2cueMs1fj4OHTbJ
+lAUv88ywr+R+mRgYQlFW/XQ653f6DT4t6+njfO9oBcPrQDASZel3LjXLpjjYG/N5
++BWnVexuJX9ika8HJiFl55oqaKb+WknfNhk5cPY+x7SDV9ywQeMiDZpr0ffeYAEP
+LlwwiWRDYpO+uwXHSFF3+JjWwjhs8m8g99iFb7U93yKgBB12dCEPPa2ZeH9wUHMJ
+sreYhNuq6f4iWWSXpzN45inQqtTi8jrJhuNLTT543ErW7DtntBO2rWMhff3aiXbn
+Uy3qzZM1nPbuCGuBmP9L2dJ3Z5ifDWB4JmOyWY4swTZGt9AVmUxMIKdZpRONx8vz
+I9u9nbVPGZBcou50Pa0qTLbkWsSL94MNXrARBxzhHC9Zs6XNEtwN7mOuii7uMkVc
+adrxgknBH1J1N+NX/eTKzUwJuPvDtA+Z5ILWNN9wpZT/7ed8zEnKHPNUexyeT5g3
+uw9z9jH7ffGxFYlx87oiVPHGOrCXYZYW5uoZE31SCBkbtNuffNRJRKIFeipmpJ3P
+7bpAG+kGHMelQH6b+5K1Qgsv4tpuSyKeTKpPFH9Av5nN4P1ZBm9N80tzbNWqjSJm
+S7rYdHnuNEVnUGnRmEUMmVuYZnNBEVN/fP2m2SEwXcP3Uh7TiYlcWw10ygaGmOr7
+MvMLGkYgQ4Utwnd98mtqa0jr0hK2TcOSFir3AqVvXN3XJj4cVULkrXe4Im1laWgp
+-----END RSA PRIVATE KEY-----
+`),
+ },
+
+ 1: {
+ Name: "dsa-encrypted",
+ EncryptionKey: "qG0pher-dsa_t3st$",
+ PEMBytes: []byte(`-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-CBC,7CE7A6E4A647DC01AF860210B15ADE3E
+
+hvnBpI99Hceq/55pYRdOzBLntIEis02JFNXuLEydWL+RJBFDn7tA+vXec0ERJd6J
+G8JXlSOAhmC2H4uK3q2xR8/Y3yL95n6OIcjvCBiLsV+o3jj1MYJmErxP6zRtq4w3
+JjIjGHWmaYFSxPKQ6e8fs74HEqaeMV9ONUoTtB+aISmgaBL15Fcoayg245dkBvVl
+h5Kqspe7yvOBmzA3zjRuxmSCqKJmasXM7mqs3vIrMxZE3XPo1/fWKcPuExgpVQoT
+HkJZEoIEIIPnPMwT2uYbFJSGgPJVMDT84xz7yvjCdhLmqrsXgs5Qw7Pw0i0c0BUJ
+b7fDJ2UhdiwSckWGmIhTLlJZzr8K+JpjCDlP+REYBI5meB7kosBnlvCEHdw2EJkH
+0QDc/2F4xlVrHOLbPRFyu1Oi2Gvbeoo9EsM/DThpd1hKAlb0sF5Y0y0d+owv0PnE
+R/4X3HWfIdOHsDUvJ8xVWZ4BZk9Zk9qol045DcFCehpr/3hslCrKSZHakLt9GI58
+vVQJ4L0aYp5nloLfzhViZtKJXRLkySMKdzYkIlNmW1oVGl7tce5UCNI8Nok4j6yn
+IiHM7GBn+0nJoKTXsOGMIBe3ulKlKVxLjEuk9yivh/8=
+-----END DSA PRIVATE KEY-----
+`),
+ },
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/testdata_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/testdata_test.go
new file mode 100644
index 000000000..2da8c79dc
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/testdata_test.go
@@ -0,0 +1,63 @@
+// Copyright 2014 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.
+
+// IMPLEMENTATION NOTE: To avoid a package loop, this file is in three places:
+// ssh/, ssh/agent, and ssh/test/. It should be kept in sync across all three
+// instances.
+
+package ssh
+
+import (
+ "crypto/rand"
+ "fmt"
+
+ "golang.org/x/crypto/ssh/testdata"
+)
+
+var (
+ testPrivateKeys map[string]interface{}
+ testSigners map[string]Signer
+ testPublicKeys map[string]PublicKey
+)
+
+func init() {
+ var err error
+
+ n := len(testdata.PEMBytes)
+ testPrivateKeys = make(map[string]interface{}, n)
+ testSigners = make(map[string]Signer, n)
+ testPublicKeys = make(map[string]PublicKey, n)
+ for t, k := range testdata.PEMBytes {
+ testPrivateKeys[t], err = ParseRawPrivateKey(k)
+ if err != nil {
+ panic(fmt.Sprintf("Unable to parse test key %s: %v", t, err))
+ }
+ testSigners[t], err = NewSignerFromKey(testPrivateKeys[t])
+ if err != nil {
+ panic(fmt.Sprintf("Unable to create signer for test key %s: %v", t, err))
+ }
+ testPublicKeys[t] = testSigners[t].PublicKey()
+ }
+
+ // Create a cert and sign it for use in tests.
+ testCert := &Certificate{
+ Nonce: []byte{}, // To pass reflect.DeepEqual after marshal & parse, this must be non-nil
+ ValidPrincipals: []string{"gopher1", "gopher2"}, // increases test coverage
+ ValidAfter: 0, // unix epoch
+ ValidBefore: CertTimeInfinity, // The end of currently representable time.
+ Reserved: []byte{}, // To pass reflect.DeepEqual after marshal & parse, this must be non-nil
+ Key: testPublicKeys["ecdsa"],
+ SignatureKey: testPublicKeys["rsa"],
+ Permissions: Permissions{
+ CriticalOptions: map[string]string{},
+ Extensions: map[string]string{},
+ },
+ }
+ testCert.SignCert(rand.Reader, testSigners["rsa"])
+ testPrivateKeys["cert"] = testPrivateKeys["ecdsa"]
+ testSigners["cert"], err = NewCertSigner(testCert, testSigners["ecdsa"])
+ if err != nil {
+ panic(fmt.Sprintf("Unable to create certificate signer: %v", err))
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/transport.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/transport.go
new file mode 100644
index 000000000..ab2b88765
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/transport.go
@@ -0,0 +1,375 @@
+// Copyright 2011 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 ssh
+
+import (
+ "bufio"
+ "errors"
+ "io"
+ "log"
+)
+
+// debugTransport if set, will print packet types as they go over the
+// wire. No message decoding is done, to minimize the impact on timing.
+const debugTransport = false
+
+const (
+ gcmCipherID = "aes128-gcm@openssh.com"
+ aes128cbcID = "aes128-cbc"
+ tripledescbcID = "3des-cbc"
+)
+
+// packetConn represents a transport that implements packet based
+// operations.
+type packetConn interface {
+ // Encrypt and send a packet of data to the remote peer.
+ writePacket(packet []byte) error
+
+ // Read a packet from the connection. The read is blocking,
+ // i.e. if error is nil, then the returned byte slice is
+ // always non-empty.
+ readPacket() ([]byte, error)
+
+ // Close closes the write-side of the connection.
+ Close() error
+}
+
+// transport is the keyingTransport that implements the SSH packet
+// protocol.
+type transport struct {
+ reader connectionState
+ writer connectionState
+
+ bufReader *bufio.Reader
+ bufWriter *bufio.Writer
+ rand io.Reader
+ isClient bool
+ io.Closer
+}
+
+// packetCipher represents a combination of SSH encryption/MAC
+// protocol. A single instance should be used for one direction only.
+type packetCipher interface {
+ // writePacket encrypts the packet and writes it to w. The
+ // contents of the packet are generally scrambled.
+ writePacket(seqnum uint32, w io.Writer, rand io.Reader, packet []byte) error
+
+ // readPacket reads and decrypts a packet of data. The
+ // returned packet may be overwritten by future calls of
+ // readPacket.
+ readPacket(seqnum uint32, r io.Reader) ([]byte, error)
+}
+
+// connectionState represents one side (read or write) of the
+// connection. This is necessary because each direction has its own
+// keys, and can even have its own algorithms
+type connectionState struct {
+ packetCipher
+ seqNum uint32
+ dir direction
+ pendingKeyChange chan packetCipher
+}
+
+// prepareKeyChange sets up key material for a keychange. The key changes in
+// both directions are triggered by reading and writing a msgNewKey packet
+// respectively.
+func (t *transport) prepareKeyChange(algs *algorithms, kexResult *kexResult) error {
+ if ciph, err := newPacketCipher(t.reader.dir, algs.r, kexResult); err != nil {
+ return err
+ } else {
+ t.reader.pendingKeyChange <- ciph
+ }
+
+ if ciph, err := newPacketCipher(t.writer.dir, algs.w, kexResult); err != nil {
+ return err
+ } else {
+ t.writer.pendingKeyChange <- ciph
+ }
+
+ return nil
+}
+
+func (t *transport) printPacket(p []byte, write bool) {
+ if len(p) == 0 {
+ return
+ }
+ who := "server"
+ if t.isClient {
+ who = "client"
+ }
+ what := "read"
+ if write {
+ what = "write"
+ }
+
+ log.Println(what, who, p[0])
+}
+
+// Read and decrypt next packet.
+func (t *transport) readPacket() (p []byte, err error) {
+ for {
+ p, err = t.reader.readPacket(t.bufReader)
+ if err != nil {
+ break
+ }
+ if len(p) == 0 || (p[0] != msgIgnore && p[0] != msgDebug) {
+ break
+ }
+ }
+ if debugTransport {
+ t.printPacket(p, false)
+ }
+
+ return p, err
+}
+
+func (s *connectionState) readPacket(r *bufio.Reader) ([]byte, error) {
+ packet, err := s.packetCipher.readPacket(s.seqNum, r)
+ s.seqNum++
+ if err == nil && len(packet) == 0 {
+ err = errors.New("ssh: zero length packet")
+ }
+
+ if len(packet) > 0 {
+ switch packet[0] {
+ case msgNewKeys:
+ select {
+ case cipher := <-s.pendingKeyChange:
+ s.packetCipher = cipher
+ default:
+ return nil, errors.New("ssh: got bogus newkeys message.")
+ }
+
+ case msgDisconnect:
+ // Transform a disconnect message into an
+ // error. Since this is lowest level at which
+ // we interpret message types, doing it here
+ // ensures that we don't have to handle it
+ // elsewhere.
+ var msg disconnectMsg
+ if err := Unmarshal(packet, &msg); err != nil {
+ return nil, err
+ }
+ return nil, &msg
+ }
+ }
+
+ // The packet may point to an internal buffer, so copy the
+ // packet out here.
+ fresh := make([]byte, len(packet))
+ copy(fresh, packet)
+
+ return fresh, err
+}
+
+func (t *transport) writePacket(packet []byte) error {
+ if debugTransport {
+ t.printPacket(packet, true)
+ }
+ return t.writer.writePacket(t.bufWriter, t.rand, packet)
+}
+
+func (s *connectionState) writePacket(w *bufio.Writer, rand io.Reader, packet []byte) error {
+ changeKeys := len(packet) > 0 && packet[0] == msgNewKeys
+
+ err := s.packetCipher.writePacket(s.seqNum, w, rand, packet)
+ if err != nil {
+ return err
+ }
+ if err = w.Flush(); err != nil {
+ return err
+ }
+ s.seqNum++
+ if changeKeys {
+ select {
+ case cipher := <-s.pendingKeyChange:
+ s.packetCipher = cipher
+ default:
+ panic("ssh: no key material for msgNewKeys")
+ }
+ }
+ return err
+}
+
+func newTransport(rwc io.ReadWriteCloser, rand io.Reader, isClient bool) *transport {
+ t := &transport{
+ bufReader: bufio.NewReader(rwc),
+ bufWriter: bufio.NewWriter(rwc),
+ rand: rand,
+ reader: connectionState{
+ packetCipher: &streamPacketCipher{cipher: noneCipher{}},
+ pendingKeyChange: make(chan packetCipher, 1),
+ },
+ writer: connectionState{
+ packetCipher: &streamPacketCipher{cipher: noneCipher{}},
+ pendingKeyChange: make(chan packetCipher, 1),
+ },
+ Closer: rwc,
+ }
+ t.isClient = isClient
+
+ if isClient {
+ t.reader.dir = serverKeys
+ t.writer.dir = clientKeys
+ } else {
+ t.reader.dir = clientKeys
+ t.writer.dir = serverKeys
+ }
+
+ return t
+}
+
+type direction struct {
+ ivTag []byte
+ keyTag []byte
+ macKeyTag []byte
+}
+
+var (
+ serverKeys = direction{[]byte{'B'}, []byte{'D'}, []byte{'F'}}
+ clientKeys = direction{[]byte{'A'}, []byte{'C'}, []byte{'E'}}
+)
+
+// generateKeys generates key material for IV, MAC and encryption.
+func generateKeys(d direction, algs directionAlgorithms, kex *kexResult) (iv, key, macKey []byte) {
+ cipherMode := cipherModes[algs.Cipher]
+ macMode := macModes[algs.MAC]
+
+ iv = make([]byte, cipherMode.ivSize)
+ key = make([]byte, cipherMode.keySize)
+ macKey = make([]byte, macMode.keySize)
+
+ generateKeyMaterial(iv, d.ivTag, kex)
+ generateKeyMaterial(key, d.keyTag, kex)
+ generateKeyMaterial(macKey, d.macKeyTag, kex)
+ return
+}
+
+// setupKeys sets the cipher and MAC keys from kex.K, kex.H and sessionId, as
+// described in RFC 4253, section 6.4. direction should either be serverKeys
+// (to setup server->client keys) or clientKeys (for client->server keys).
+func newPacketCipher(d direction, algs directionAlgorithms, kex *kexResult) (packetCipher, error) {
+ iv, key, macKey := generateKeys(d, algs, kex)
+
+ if algs.Cipher == gcmCipherID {
+ return newGCMCipher(iv, key)
+ }
+
+ if algs.Cipher == aes128cbcID {
+ return newAESCBCCipher(iv, key, macKey, algs)
+ }
+
+ if algs.Cipher == tripledescbcID {
+ return newTripleDESCBCCipher(iv, key, macKey, algs)
+ }
+
+ c := &streamPacketCipher{
+ mac: macModes[algs.MAC].new(macKey),
+ etm: macModes[algs.MAC].etm,
+ }
+ c.macResult = make([]byte, c.mac.Size())
+
+ var err error
+ c.cipher, err = cipherModes[algs.Cipher].createStream(key, iv)
+ if err != nil {
+ return nil, err
+ }
+
+ return c, nil
+}
+
+// generateKeyMaterial fills out with key material generated from tag, K, H
+// and sessionId, as specified in RFC 4253, section 7.2.
+func generateKeyMaterial(out, tag []byte, r *kexResult) {
+ var digestsSoFar []byte
+
+ h := r.Hash.New()
+ for len(out) > 0 {
+ h.Reset()
+ h.Write(r.K)
+ h.Write(r.H)
+
+ if len(digestsSoFar) == 0 {
+ h.Write(tag)
+ h.Write(r.SessionID)
+ } else {
+ h.Write(digestsSoFar)
+ }
+
+ digest := h.Sum(nil)
+ n := copy(out, digest)
+ out = out[n:]
+ if len(out) > 0 {
+ digestsSoFar = append(digestsSoFar, digest...)
+ }
+ }
+}
+
+const packageVersion = "SSH-2.0-Go"
+
+// Sends and receives a version line. The versionLine string should
+// be US ASCII, start with "SSH-2.0-", and should not include a
+// newline. exchangeVersions returns the other side's version line.
+func exchangeVersions(rw io.ReadWriter, versionLine []byte) (them []byte, err error) {
+ // Contrary to the RFC, we do not ignore lines that don't
+ // start with "SSH-2.0-" to make the library usable with
+ // nonconforming servers.
+ for _, c := range versionLine {
+ // The spec disallows non US-ASCII chars, and
+ // specifically forbids null chars.
+ if c < 32 {
+ return nil, errors.New("ssh: junk character in version line")
+ }
+ }
+ if _, err = rw.Write(append(versionLine, '\r', '\n')); err != nil {
+ return
+ }
+
+ them, err = readVersion(rw)
+ return them, err
+}
+
+// maxVersionStringBytes is the maximum number of bytes that we'll
+// accept as a version string. RFC 4253 section 4.2 limits this at 255
+// chars
+const maxVersionStringBytes = 255
+
+// Read version string as specified by RFC 4253, section 4.2.
+func readVersion(r io.Reader) ([]byte, error) {
+ versionString := make([]byte, 0, 64)
+ var ok bool
+ var buf [1]byte
+
+ for len(versionString) < maxVersionStringBytes {
+ _, err := io.ReadFull(r, buf[:])
+ if err != nil {
+ return nil, err
+ }
+ // The RFC says that the version should be terminated with \r\n
+ // but several SSH servers actually only send a \n.
+ if buf[0] == '\n' {
+ ok = true
+ break
+ }
+
+ // non ASCII chars are disallowed, but we are lenient,
+ // since Go doesn't use null-terminated strings.
+
+ // The RFC allows a comment after a space, however,
+ // all of it (version and comments) goes into the
+ // session hash.
+ versionString = append(versionString, buf[0])
+ }
+
+ if !ok {
+ return nil, errors.New("ssh: overflow reading version string")
+ }
+
+ // There might be a '\r' on the end which we should remove.
+ if len(versionString) > 0 && versionString[len(versionString)-1] == '\r' {
+ versionString = versionString[:len(versionString)-1]
+ }
+ return versionString, nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/transport_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/transport_test.go
new file mode 100644
index 000000000..92d83abf9
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/ssh/transport_test.go
@@ -0,0 +1,109 @@
+// Copyright 2011 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 ssh
+
+import (
+ "bytes"
+ "crypto/rand"
+ "encoding/binary"
+ "strings"
+ "testing"
+)
+
+func TestReadVersion(t *testing.T) {
+ longversion := strings.Repeat("SSH-2.0-bla", 50)[:253]
+ cases := map[string]string{
+ "SSH-2.0-bla\r\n": "SSH-2.0-bla",
+ "SSH-2.0-bla\n": "SSH-2.0-bla",
+ longversion + "\r\n": longversion,
+ }
+
+ for in, want := range cases {
+ result, err := readVersion(bytes.NewBufferString(in))
+ if err != nil {
+ t.Errorf("readVersion(%q): %s", in, err)
+ }
+ got := string(result)
+ if got != want {
+ t.Errorf("got %q, want %q", got, want)
+ }
+ }
+}
+
+func TestReadVersionError(t *testing.T) {
+ longversion := strings.Repeat("SSH-2.0-bla", 50)[:253]
+ cases := []string{
+ longversion + "too-long\r\n",
+ }
+ for _, in := range cases {
+ if _, err := readVersion(bytes.NewBufferString(in)); err == nil {
+ t.Errorf("readVersion(%q) should have failed", in)
+ }
+ }
+}
+
+func TestExchangeVersionsBasic(t *testing.T) {
+ v := "SSH-2.0-bla"
+ buf := bytes.NewBufferString(v + "\r\n")
+ them, err := exchangeVersions(buf, []byte("xyz"))
+ if err != nil {
+ t.Errorf("exchangeVersions: %v", err)
+ }
+
+ if want := "SSH-2.0-bla"; string(them) != want {
+ t.Errorf("got %q want %q for our version", them, want)
+ }
+}
+
+func TestExchangeVersions(t *testing.T) {
+ cases := []string{
+ "not\x000allowed",
+ "not allowed\n",
+ }
+ for _, c := range cases {
+ buf := bytes.NewBufferString("SSH-2.0-bla\r\n")
+ if _, err := exchangeVersions(buf, []byte(c)); err == nil {
+ t.Errorf("exchangeVersions(%q): should have failed", c)
+ }
+ }
+}
+
+type closerBuffer struct {
+ bytes.Buffer
+}
+
+func (b *closerBuffer) Close() error {
+ return nil
+}
+
+func TestTransportMaxPacketWrite(t *testing.T) {
+ buf := &closerBuffer{}
+ tr := newTransport(buf, rand.Reader, true)
+ huge := make([]byte, maxPacket+1)
+ err := tr.writePacket(huge)
+ if err == nil {
+ t.Errorf("transport accepted write for a huge packet.")
+ }
+}
+
+func TestTransportMaxPacketReader(t *testing.T) {
+ var header [5]byte
+ huge := make([]byte, maxPacket+128)
+ binary.BigEndian.PutUint32(header[0:], uint32(len(huge)))
+ // padding.
+ header[4] = 0
+
+ buf := &closerBuffer{}
+ buf.Write(header[:])
+ buf.Write(huge)
+
+ tr := newTransport(buf, rand.Reader, true)
+ _, err := tr.readPacket()
+ if err == nil {
+ t.Errorf("transport succeeded reading huge packet.")
+ } else if !strings.Contains(err.Error(), "large") {
+ t.Errorf("got %q, should mention %q", err.Error(), "large")
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/tea/cipher.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/tea/cipher.go
new file mode 100644
index 000000000..9c13d12a2
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/tea/cipher.go
@@ -0,0 +1,109 @@
+// Copyright 2015 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 tea implements the TEA algorithm, as defined in Needham and
+// Wheeler's 1994 technical report, “TEA, a Tiny Encryption Algorithm”. See
+// http://www.cix.co.uk/~klockstone/tea.pdf for details.
+
+package tea
+
+import (
+ "crypto/cipher"
+ "encoding/binary"
+ "errors"
+)
+
+const (
+ // BlockSize is the size of a TEA block, in bytes.
+ BlockSize = 8
+
+ // KeySize is the size of a TEA key, in bytes.
+ KeySize = 16
+
+ // delta is the TEA key schedule constant.
+ delta = 0x9e3779b9
+
+ // numRounds is the standard number of rounds in TEA.
+ numRounds = 64
+)
+
+// tea is an instance of the TEA cipher with a particular key.
+type tea struct {
+ key [16]byte
+ rounds int
+}
+
+// NewCipher returns an instance of the TEA cipher with the standard number of
+// rounds. The key argument must be 16 bytes long.
+func NewCipher(key []byte) (cipher.Block, error) {
+ return NewCipherWithRounds(key, numRounds)
+}
+
+// NewCipherWithRounds returns an instance of the TEA cipher with a given
+// number of rounds, which must be even. The key argument must be 16 bytes
+// long.
+func NewCipherWithRounds(key []byte, rounds int) (cipher.Block, error) {
+ if len(key) != 16 {
+ return nil, errors.New("tea: incorrect key size")
+ }
+
+ if rounds&1 != 0 {
+ return nil, errors.New("tea: odd number of rounds specified")
+ }
+
+ c := &tea{
+ rounds: rounds,
+ }
+ copy(c.key[:], key)
+
+ return c, nil
+}
+
+// BlockSize returns the TEA block size, which is eight bytes. It is necessary
+// to satisfy the Block interface in the package "crypto/cipher".
+func (*tea) BlockSize() int {
+ return BlockSize
+}
+
+// Encrypt encrypts the 8 byte buffer src using the key in t and stores the
+// result in dst. Note that for amounts of data larger than a block, it is not
+// safe to just call Encrypt on successive blocks; instead, use an encryption
+// mode like CBC (see crypto/cipher/cbc.go).
+func (t *tea) Encrypt(dst, src []byte) {
+ e := binary.BigEndian
+ v0, v1 := e.Uint32(src), e.Uint32(src[4:])
+ k0, k1, k2, k3 := e.Uint32(t.key[0:]), e.Uint32(t.key[4:]), e.Uint32(t.key[8:]), e.Uint32(t.key[12:])
+
+ sum := uint32(0)
+ delta := uint32(delta)
+
+ for i := 0; i < t.rounds/2; i++ {
+ sum += delta
+ v0 += ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1)
+ v1 += ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3)
+ }
+
+ e.PutUint32(dst, v0)
+ e.PutUint32(dst[4:], v1)
+}
+
+// Decrypt decrypts the 8 byte buffer src using the key in t and stores the
+// result in dst.
+func (t *tea) Decrypt(dst, src []byte) {
+ e := binary.BigEndian
+ v0, v1 := e.Uint32(src), e.Uint32(src[4:])
+ k0, k1, k2, k3 := e.Uint32(t.key[0:]), e.Uint32(t.key[4:]), e.Uint32(t.key[8:]), e.Uint32(t.key[12:])
+
+ delta := uint32(delta)
+ sum := delta * uint32(t.rounds/2) // in general, sum = delta * n
+
+ for i := 0; i < t.rounds/2; i++ {
+ v1 -= ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3)
+ v0 -= ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1)
+ sum -= delta
+ }
+
+ e.PutUint32(dst, v0)
+ e.PutUint32(dst[4:], v1)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/tea/tea_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/tea/tea_test.go
new file mode 100644
index 000000000..eb98d1e0e
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/tea/tea_test.go
@@ -0,0 +1,93 @@
+// Copyright 2015 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 tea
+
+import (
+ "bytes"
+ "testing"
+)
+
+// A sample test key for when we just want to initialize a cipher
+var testKey = []byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}
+
+// Test that the block size for tea is correct
+func TestBlocksize(t *testing.T) {
+ c, err := NewCipher(testKey)
+ if err != nil {
+ t.Fatalf("NewCipher returned error: %s", err)
+ }
+
+ if result := c.BlockSize(); result != BlockSize {
+ t.Errorf("cipher.BlockSize returned %d, but expected %d", result, BlockSize)
+ }
+}
+
+// Test that invalid key sizes return an error
+func TestInvalidKeySize(t *testing.T) {
+ var key [KeySize + 1]byte
+
+ if _, err := NewCipher(key[:]); err == nil {
+ t.Errorf("invalid key size %d didn't result in an error.", len(key))
+ }
+
+ if _, err := NewCipher(key[:KeySize-1]); err == nil {
+ t.Errorf("invalid key size %d didn't result in an error.", KeySize-1)
+ }
+}
+
+// Test Vectors
+type teaTest struct {
+ rounds int
+ key []byte
+ plaintext []byte
+ ciphertext []byte
+}
+
+var teaTests = []teaTest{
+ // These were sourced from https://github.com/froydnj/ironclad/blob/master/testing/test-vectors/tea.testvec
+ {
+ numRounds,
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0x41, 0xea, 0x3a, 0x0a, 0x94, 0xba, 0xa9, 0x40},
+ },
+ {
+ numRounds,
+ []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ []byte{0x31, 0x9b, 0xbe, 0xfb, 0x01, 0x6a, 0xbd, 0xb2},
+ },
+ {
+ 16,
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0xed, 0x28, 0x5d, 0xa1, 0x45, 0x5b, 0x33, 0xc1},
+ },
+}
+
+// Test encryption
+func TestCipherEncrypt(t *testing.T) {
+ // Test encryption with standard 64 rounds
+ for i, test := range teaTests {
+ c, err := NewCipherWithRounds(test.key, test.rounds)
+ if err != nil {
+ t.Fatalf("#%d: NewCipher returned error: %s", i, err)
+ }
+
+ var ciphertext [BlockSize]byte
+ c.Encrypt(ciphertext[:], test.plaintext)
+
+ if !bytes.Equal(ciphertext[:], test.ciphertext) {
+ t.Errorf("#%d: incorrect ciphertext. Got %x, wanted %x", i, ciphertext, test.ciphertext)
+ }
+
+ var plaintext2 [BlockSize]byte
+ c.Decrypt(plaintext2[:], ciphertext[:])
+
+ if !bytes.Equal(plaintext2[:], test.plaintext) {
+ t.Errorf("#%d: incorrect plaintext. Got %x, wanted %x", i, plaintext2, test.plaintext)
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/twofish/twofish.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/twofish/twofish.go
new file mode 100644
index 000000000..6db01fcf4
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/twofish/twofish.go
@@ -0,0 +1,342 @@
+// Copyright 2011 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 twofish implements Bruce Schneier's Twofish encryption algorithm.
+package twofish // import "golang.org/x/crypto/twofish"
+
+// Twofish is defined in https://www.schneier.com/paper-twofish-paper.pdf [TWOFISH]
+
+// This code is a port of the LibTom C implementation.
+// See http://libtom.org/?page=features&newsitems=5&whatfile=crypt.
+// LibTomCrypt is free for all purposes under the public domain.
+// It was heavily inspired by the go blowfish package.
+
+import "strconv"
+
+// BlockSize is the constant block size of Twofish.
+const BlockSize = 16
+
+const mdsPolynomial = 0x169 // x^8 + x^6 + x^5 + x^3 + 1, see [TWOFISH] 4.2
+const rsPolynomial = 0x14d // x^8 + x^6 + x^3 + x^2 + 1, see [TWOFISH] 4.3
+
+// A Cipher is an instance of Twofish encryption using a particular key.
+type Cipher struct {
+ s [4][256]uint32
+ k [40]uint32
+}
+
+type KeySizeError int
+
+func (k KeySizeError) Error() string {
+ return "crypto/twofish: invalid key size " + strconv.Itoa(int(k))
+}
+
+// NewCipher creates and returns a Cipher.
+// The key argument should be the Twofish key, 16, 24 or 32 bytes.
+func NewCipher(key []byte) (*Cipher, error) {
+ keylen := len(key)
+
+ if keylen != 16 && keylen != 24 && keylen != 32 {
+ return nil, KeySizeError(keylen)
+ }
+
+ // k is the number of 64 bit words in key
+ k := keylen / 8
+
+ // Create the S[..] words
+ var S [4 * 4]byte
+ for i := 0; i < k; i++ {
+ // Computes [y0 y1 y2 y3] = rs . [x0 x1 x2 x3 x4 x5 x6 x7]
+ for j, rsRow := range rs {
+ for k, rsVal := range rsRow {
+ S[4*i+j] ^= gfMult(key[8*i+k], rsVal, rsPolynomial)
+ }
+ }
+ }
+
+ // Calculate subkeys
+ c := new(Cipher)
+ var tmp [4]byte
+ for i := byte(0); i < 20; i++ {
+ // A = h(p * 2x, Me)
+ for j := range tmp {
+ tmp[j] = 2 * i
+ }
+ A := h(tmp[:], key, 0)
+
+ // B = rolc(h(p * (2x + 1), Mo), 8)
+ for j := range tmp {
+ tmp[j] = 2*i + 1
+ }
+ B := h(tmp[:], key, 1)
+ B = rol(B, 8)
+
+ c.k[2*i] = A + B
+
+ // K[2i+1] = (A + 2B) <<< 9
+ c.k[2*i+1] = rol(2*B+A, 9)
+ }
+
+ // Calculate sboxes
+ switch k {
+ case 2:
+ for i := range c.s[0] {
+ c.s[0][i] = mdsColumnMult(sbox[1][sbox[0][sbox[0][byte(i)]^S[0]]^S[4]], 0)
+ c.s[1][i] = mdsColumnMult(sbox[0][sbox[0][sbox[1][byte(i)]^S[1]]^S[5]], 1)
+ c.s[2][i] = mdsColumnMult(sbox[1][sbox[1][sbox[0][byte(i)]^S[2]]^S[6]], 2)
+ c.s[3][i] = mdsColumnMult(sbox[0][sbox[1][sbox[1][byte(i)]^S[3]]^S[7]], 3)
+ }
+ case 3:
+ for i := range c.s[0] {
+ c.s[0][i] = mdsColumnMult(sbox[1][sbox[0][sbox[0][sbox[1][byte(i)]^S[0]]^S[4]]^S[8]], 0)
+ c.s[1][i] = mdsColumnMult(sbox[0][sbox[0][sbox[1][sbox[1][byte(i)]^S[1]]^S[5]]^S[9]], 1)
+ c.s[2][i] = mdsColumnMult(sbox[1][sbox[1][sbox[0][sbox[0][byte(i)]^S[2]]^S[6]]^S[10]], 2)
+ c.s[3][i] = mdsColumnMult(sbox[0][sbox[1][sbox[1][sbox[0][byte(i)]^S[3]]^S[7]]^S[11]], 3)
+ }
+ default:
+ for i := range c.s[0] {
+ c.s[0][i] = mdsColumnMult(sbox[1][sbox[0][sbox[0][sbox[1][sbox[1][byte(i)]^S[0]]^S[4]]^S[8]]^S[12]], 0)
+ c.s[1][i] = mdsColumnMult(sbox[0][sbox[0][sbox[1][sbox[1][sbox[0][byte(i)]^S[1]]^S[5]]^S[9]]^S[13]], 1)
+ c.s[2][i] = mdsColumnMult(sbox[1][sbox[1][sbox[0][sbox[0][sbox[0][byte(i)]^S[2]]^S[6]]^S[10]]^S[14]], 2)
+ c.s[3][i] = mdsColumnMult(sbox[0][sbox[1][sbox[1][sbox[0][sbox[1][byte(i)]^S[3]]^S[7]]^S[11]]^S[15]], 3)
+ }
+ }
+
+ return c, nil
+}
+
+// BlockSize returns the Twofish block size, 16 bytes.
+func (c *Cipher) BlockSize() int { return BlockSize }
+
+// store32l stores src in dst in little-endian form.
+func store32l(dst []byte, src uint32) {
+ dst[0] = byte(src)
+ dst[1] = byte(src >> 8)
+ dst[2] = byte(src >> 16)
+ dst[3] = byte(src >> 24)
+ return
+}
+
+// load32l reads a little-endian uint32 from src.
+func load32l(src []byte) uint32 {
+ return uint32(src[0]) | uint32(src[1])<<8 | uint32(src[2])<<16 | uint32(src[3])<<24
+}
+
+// rol returns x after a left circular rotation of y bits.
+func rol(x, y uint32) uint32 {
+ return (x << (y & 31)) | (x >> (32 - (y & 31)))
+}
+
+// ror returns x after a right circular rotation of y bits.
+func ror(x, y uint32) uint32 {
+ return (x >> (y & 31)) | (x << (32 - (y & 31)))
+}
+
+// The RS matrix. See [TWOFISH] 4.3
+var rs = [4][8]byte{
+ {0x01, 0xA4, 0x55, 0x87, 0x5A, 0x58, 0xDB, 0x9E},
+ {0xA4, 0x56, 0x82, 0xF3, 0x1E, 0xC6, 0x68, 0xE5},
+ {0x02, 0xA1, 0xFC, 0xC1, 0x47, 0xAE, 0x3D, 0x19},
+ {0xA4, 0x55, 0x87, 0x5A, 0x58, 0xDB, 0x9E, 0x03},
+}
+
+// sbox tables
+var sbox = [2][256]byte{
+ {
+ 0xa9, 0x67, 0xb3, 0xe8, 0x04, 0xfd, 0xa3, 0x76, 0x9a, 0x92, 0x80, 0x78, 0xe4, 0xdd, 0xd1, 0x38,
+ 0x0d, 0xc6, 0x35, 0x98, 0x18, 0xf7, 0xec, 0x6c, 0x43, 0x75, 0x37, 0x26, 0xfa, 0x13, 0x94, 0x48,
+ 0xf2, 0xd0, 0x8b, 0x30, 0x84, 0x54, 0xdf, 0x23, 0x19, 0x5b, 0x3d, 0x59, 0xf3, 0xae, 0xa2, 0x82,
+ 0x63, 0x01, 0x83, 0x2e, 0xd9, 0x51, 0x9b, 0x7c, 0xa6, 0xeb, 0xa5, 0xbe, 0x16, 0x0c, 0xe3, 0x61,
+ 0xc0, 0x8c, 0x3a, 0xf5, 0x73, 0x2c, 0x25, 0x0b, 0xbb, 0x4e, 0x89, 0x6b, 0x53, 0x6a, 0xb4, 0xf1,
+ 0xe1, 0xe6, 0xbd, 0x45, 0xe2, 0xf4, 0xb6, 0x66, 0xcc, 0x95, 0x03, 0x56, 0xd4, 0x1c, 0x1e, 0xd7,
+ 0xfb, 0xc3, 0x8e, 0xb5, 0xe9, 0xcf, 0xbf, 0xba, 0xea, 0x77, 0x39, 0xaf, 0x33, 0xc9, 0x62, 0x71,
+ 0x81, 0x79, 0x09, 0xad, 0x24, 0xcd, 0xf9, 0xd8, 0xe5, 0xc5, 0xb9, 0x4d, 0x44, 0x08, 0x86, 0xe7,
+ 0xa1, 0x1d, 0xaa, 0xed, 0x06, 0x70, 0xb2, 0xd2, 0x41, 0x7b, 0xa0, 0x11, 0x31, 0xc2, 0x27, 0x90,
+ 0x20, 0xf6, 0x60, 0xff, 0x96, 0x5c, 0xb1, 0xab, 0x9e, 0x9c, 0x52, 0x1b, 0x5f, 0x93, 0x0a, 0xef,
+ 0x91, 0x85, 0x49, 0xee, 0x2d, 0x4f, 0x8f, 0x3b, 0x47, 0x87, 0x6d, 0x46, 0xd6, 0x3e, 0x69, 0x64,
+ 0x2a, 0xce, 0xcb, 0x2f, 0xfc, 0x97, 0x05, 0x7a, 0xac, 0x7f, 0xd5, 0x1a, 0x4b, 0x0e, 0xa7, 0x5a,
+ 0x28, 0x14, 0x3f, 0x29, 0x88, 0x3c, 0x4c, 0x02, 0xb8, 0xda, 0xb0, 0x17, 0x55, 0x1f, 0x8a, 0x7d,
+ 0x57, 0xc7, 0x8d, 0x74, 0xb7, 0xc4, 0x9f, 0x72, 0x7e, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34,
+ 0x6e, 0x50, 0xde, 0x68, 0x65, 0xbc, 0xdb, 0xf8, 0xc8, 0xa8, 0x2b, 0x40, 0xdc, 0xfe, 0x32, 0xa4,
+ 0xca, 0x10, 0x21, 0xf0, 0xd3, 0x5d, 0x0f, 0x00, 0x6f, 0x9d, 0x36, 0x42, 0x4a, 0x5e, 0xc1, 0xe0,
+ },
+ {
+ 0x75, 0xf3, 0xc6, 0xf4, 0xdb, 0x7b, 0xfb, 0xc8, 0x4a, 0xd3, 0xe6, 0x6b, 0x45, 0x7d, 0xe8, 0x4b,
+ 0xd6, 0x32, 0xd8, 0xfd, 0x37, 0x71, 0xf1, 0xe1, 0x30, 0x0f, 0xf8, 0x1b, 0x87, 0xfa, 0x06, 0x3f,
+ 0x5e, 0xba, 0xae, 0x5b, 0x8a, 0x00, 0xbc, 0x9d, 0x6d, 0xc1, 0xb1, 0x0e, 0x80, 0x5d, 0xd2, 0xd5,
+ 0xa0, 0x84, 0x07, 0x14, 0xb5, 0x90, 0x2c, 0xa3, 0xb2, 0x73, 0x4c, 0x54, 0x92, 0x74, 0x36, 0x51,
+ 0x38, 0xb0, 0xbd, 0x5a, 0xfc, 0x60, 0x62, 0x96, 0x6c, 0x42, 0xf7, 0x10, 0x7c, 0x28, 0x27, 0x8c,
+ 0x13, 0x95, 0x9c, 0xc7, 0x24, 0x46, 0x3b, 0x70, 0xca, 0xe3, 0x85, 0xcb, 0x11, 0xd0, 0x93, 0xb8,
+ 0xa6, 0x83, 0x20, 0xff, 0x9f, 0x77, 0xc3, 0xcc, 0x03, 0x6f, 0x08, 0xbf, 0x40, 0xe7, 0x2b, 0xe2,
+ 0x79, 0x0c, 0xaa, 0x82, 0x41, 0x3a, 0xea, 0xb9, 0xe4, 0x9a, 0xa4, 0x97, 0x7e, 0xda, 0x7a, 0x17,
+ 0x66, 0x94, 0xa1, 0x1d, 0x3d, 0xf0, 0xde, 0xb3, 0x0b, 0x72, 0xa7, 0x1c, 0xef, 0xd1, 0x53, 0x3e,
+ 0x8f, 0x33, 0x26, 0x5f, 0xec, 0x76, 0x2a, 0x49, 0x81, 0x88, 0xee, 0x21, 0xc4, 0x1a, 0xeb, 0xd9,
+ 0xc5, 0x39, 0x99, 0xcd, 0xad, 0x31, 0x8b, 0x01, 0x18, 0x23, 0xdd, 0x1f, 0x4e, 0x2d, 0xf9, 0x48,
+ 0x4f, 0xf2, 0x65, 0x8e, 0x78, 0x5c, 0x58, 0x19, 0x8d, 0xe5, 0x98, 0x57, 0x67, 0x7f, 0x05, 0x64,
+ 0xaf, 0x63, 0xb6, 0xfe, 0xf5, 0xb7, 0x3c, 0xa5, 0xce, 0xe9, 0x68, 0x44, 0xe0, 0x4d, 0x43, 0x69,
+ 0x29, 0x2e, 0xac, 0x15, 0x59, 0xa8, 0x0a, 0x9e, 0x6e, 0x47, 0xdf, 0x34, 0x35, 0x6a, 0xcf, 0xdc,
+ 0x22, 0xc9, 0xc0, 0x9b, 0x89, 0xd4, 0xed, 0xab, 0x12, 0xa2, 0x0d, 0x52, 0xbb, 0x02, 0x2f, 0xa9,
+ 0xd7, 0x61, 0x1e, 0xb4, 0x50, 0x04, 0xf6, 0xc2, 0x16, 0x25, 0x86, 0x56, 0x55, 0x09, 0xbe, 0x91,
+ },
+}
+
+// gfMult returns a·b in GF(2^8)/p
+func gfMult(a, b byte, p uint32) byte {
+ B := [2]uint32{0, uint32(b)}
+ P := [2]uint32{0, p}
+ var result uint32
+
+ // branchless GF multiplier
+ for i := 0; i < 7; i++ {
+ result ^= B[a&1]
+ a >>= 1
+ B[1] = P[B[1]>>7] ^ (B[1] << 1)
+ }
+ result ^= B[a&1]
+ return byte(result)
+}
+
+// mdsColumnMult calculates y{col} where [y0 y1 y2 y3] = MDS · [x0]
+func mdsColumnMult(in byte, col int) uint32 {
+ mul01 := in
+ mul5B := gfMult(in, 0x5B, mdsPolynomial)
+ mulEF := gfMult(in, 0xEF, mdsPolynomial)
+
+ switch col {
+ case 0:
+ return uint32(mul01) | uint32(mul5B)<<8 | uint32(mulEF)<<16 | uint32(mulEF)<<24
+ case 1:
+ return uint32(mulEF) | uint32(mulEF)<<8 | uint32(mul5B)<<16 | uint32(mul01)<<24
+ case 2:
+ return uint32(mul5B) | uint32(mulEF)<<8 | uint32(mul01)<<16 | uint32(mulEF)<<24
+ case 3:
+ return uint32(mul5B) | uint32(mul01)<<8 | uint32(mulEF)<<16 | uint32(mul5B)<<24
+ }
+
+ panic("unreachable")
+}
+
+// h implements the S-box generation function. See [TWOFISH] 4.3.5
+func h(in, key []byte, offset int) uint32 {
+ var y [4]byte
+ for x := range y {
+ y[x] = in[x]
+ }
+ switch len(key) / 8 {
+ case 4:
+ y[0] = sbox[1][y[0]] ^ key[4*(6+offset)+0]
+ y[1] = sbox[0][y[1]] ^ key[4*(6+offset)+1]
+ y[2] = sbox[0][y[2]] ^ key[4*(6+offset)+2]
+ y[3] = sbox[1][y[3]] ^ key[4*(6+offset)+3]
+ fallthrough
+ case 3:
+ y[0] = sbox[1][y[0]] ^ key[4*(4+offset)+0]
+ y[1] = sbox[1][y[1]] ^ key[4*(4+offset)+1]
+ y[2] = sbox[0][y[2]] ^ key[4*(4+offset)+2]
+ y[3] = sbox[0][y[3]] ^ key[4*(4+offset)+3]
+ fallthrough
+ case 2:
+ y[0] = sbox[1][sbox[0][sbox[0][y[0]]^key[4*(2+offset)+0]]^key[4*(0+offset)+0]]
+ y[1] = sbox[0][sbox[0][sbox[1][y[1]]^key[4*(2+offset)+1]]^key[4*(0+offset)+1]]
+ y[2] = sbox[1][sbox[1][sbox[0][y[2]]^key[4*(2+offset)+2]]^key[4*(0+offset)+2]]
+ y[3] = sbox[0][sbox[1][sbox[1][y[3]]^key[4*(2+offset)+3]]^key[4*(0+offset)+3]]
+ }
+ // [y0 y1 y2 y3] = MDS . [x0 x1 x2 x3]
+ var mdsMult uint32
+ for i := range y {
+ mdsMult ^= mdsColumnMult(y[i], i)
+ }
+ return mdsMult
+}
+
+// Encrypt encrypts a 16-byte block from src to dst, which may overlap.
+// Note that for amounts of data larger than a block,
+// it is not safe to just call Encrypt on successive blocks;
+// instead, use an encryption mode like CBC (see crypto/cipher/cbc.go).
+func (c *Cipher) Encrypt(dst, src []byte) {
+ S1 := c.s[0]
+ S2 := c.s[1]
+ S3 := c.s[2]
+ S4 := c.s[3]
+
+ // Load input
+ ia := load32l(src[0:4])
+ ib := load32l(src[4:8])
+ ic := load32l(src[8:12])
+ id := load32l(src[12:16])
+
+ // Pre-whitening
+ ia ^= c.k[0]
+ ib ^= c.k[1]
+ ic ^= c.k[2]
+ id ^= c.k[3]
+
+ for i := 0; i < 8; i++ {
+ k := c.k[8+i*4 : 12+i*4]
+ t2 := S2[byte(ib)] ^ S3[byte(ib>>8)] ^ S4[byte(ib>>16)] ^ S1[byte(ib>>24)]
+ t1 := S1[byte(ia)] ^ S2[byte(ia>>8)] ^ S3[byte(ia>>16)] ^ S4[byte(ia>>24)] + t2
+ ic = ror(ic^(t1+k[0]), 1)
+ id = rol(id, 1) ^ (t2 + t1 + k[1])
+
+ t2 = S2[byte(id)] ^ S3[byte(id>>8)] ^ S4[byte(id>>16)] ^ S1[byte(id>>24)]
+ t1 = S1[byte(ic)] ^ S2[byte(ic>>8)] ^ S3[byte(ic>>16)] ^ S4[byte(ic>>24)] + t2
+ ia = ror(ia^(t1+k[2]), 1)
+ ib = rol(ib, 1) ^ (t2 + t1 + k[3])
+ }
+
+ // Output with "undo last swap"
+ ta := ic ^ c.k[4]
+ tb := id ^ c.k[5]
+ tc := ia ^ c.k[6]
+ td := ib ^ c.k[7]
+
+ store32l(dst[0:4], ta)
+ store32l(dst[4:8], tb)
+ store32l(dst[8:12], tc)
+ store32l(dst[12:16], td)
+}
+
+// Decrypt decrypts a 16-byte block from src to dst, which may overlap.
+func (c *Cipher) Decrypt(dst, src []byte) {
+ S1 := c.s[0]
+ S2 := c.s[1]
+ S3 := c.s[2]
+ S4 := c.s[3]
+
+ // Load input
+ ta := load32l(src[0:4])
+ tb := load32l(src[4:8])
+ tc := load32l(src[8:12])
+ td := load32l(src[12:16])
+
+ // Undo undo final swap
+ ia := tc ^ c.k[6]
+ ib := td ^ c.k[7]
+ ic := ta ^ c.k[4]
+ id := tb ^ c.k[5]
+
+ for i := 8; i > 0; i-- {
+ k := c.k[4+i*4 : 8+i*4]
+ t2 := S2[byte(id)] ^ S3[byte(id>>8)] ^ S4[byte(id>>16)] ^ S1[byte(id>>24)]
+ t1 := S1[byte(ic)] ^ S2[byte(ic>>8)] ^ S3[byte(ic>>16)] ^ S4[byte(ic>>24)] + t2
+ ia = rol(ia, 1) ^ (t1 + k[2])
+ ib = ror(ib^(t2+t1+k[3]), 1)
+
+ t2 = S2[byte(ib)] ^ S3[byte(ib>>8)] ^ S4[byte(ib>>16)] ^ S1[byte(ib>>24)]
+ t1 = S1[byte(ia)] ^ S2[byte(ia>>8)] ^ S3[byte(ia>>16)] ^ S4[byte(ia>>24)] + t2
+ ic = rol(ic, 1) ^ (t1 + k[0])
+ id = ror(id^(t2+t1+k[1]), 1)
+ }
+
+ // Undo pre-whitening
+ ia ^= c.k[0]
+ ib ^= c.k[1]
+ ic ^= c.k[2]
+ id ^= c.k[3]
+
+ store32l(dst[0:4], ia)
+ store32l(dst[4:8], ib)
+ store32l(dst[8:12], ic)
+ store32l(dst[12:16], id)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/twofish/twofish_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/twofish/twofish_test.go
new file mode 100644
index 000000000..ed6a1a8fd
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/twofish/twofish_test.go
@@ -0,0 +1,129 @@
+// Copyright 2011 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 twofish
+
+import (
+ "bytes"
+ "testing"
+)
+
+var qbox = [2][4][16]byte{
+ {
+ {0x8, 0x1, 0x7, 0xD, 0x6, 0xF, 0x3, 0x2, 0x0, 0xB, 0x5, 0x9, 0xE, 0xC, 0xA, 0x4},
+ {0xE, 0xC, 0xB, 0x8, 0x1, 0x2, 0x3, 0x5, 0xF, 0x4, 0xA, 0x6, 0x7, 0x0, 0x9, 0xD},
+ {0xB, 0xA, 0x5, 0xE, 0x6, 0xD, 0x9, 0x0, 0xC, 0x8, 0xF, 0x3, 0x2, 0x4, 0x7, 0x1},
+ {0xD, 0x7, 0xF, 0x4, 0x1, 0x2, 0x6, 0xE, 0x9, 0xB, 0x3, 0x0, 0x8, 0x5, 0xC, 0xA},
+ },
+ {
+ {0x2, 0x8, 0xB, 0xD, 0xF, 0x7, 0x6, 0xE, 0x3, 0x1, 0x9, 0x4, 0x0, 0xA, 0xC, 0x5},
+ {0x1, 0xE, 0x2, 0xB, 0x4, 0xC, 0x3, 0x7, 0x6, 0xD, 0xA, 0x5, 0xF, 0x9, 0x0, 0x8},
+ {0x4, 0xC, 0x7, 0x5, 0x1, 0x6, 0x9, 0xA, 0x0, 0xE, 0xD, 0x8, 0x2, 0xB, 0x3, 0xF},
+ {0xB, 0x9, 0x5, 0x1, 0xC, 0x3, 0xD, 0xE, 0x6, 0x4, 0x7, 0xF, 0x2, 0x0, 0x8, 0xA},
+ },
+}
+
+// genSbox generates the variable sbox
+func genSbox(qi int, x byte) byte {
+ a0, b0 := x/16, x%16
+ for i := 0; i < 2; i++ {
+ a1 := a0 ^ b0
+ b1 := (a0 ^ ((b0 << 3) | (b0 >> 1)) ^ (a0 << 3)) & 15
+ a0 = qbox[qi][2*i][a1]
+ b0 = qbox[qi][2*i+1][b1]
+ }
+ return (b0 << 4) + a0
+}
+
+func TestSbox(t *testing.T) {
+ for n := range sbox {
+ for m := range sbox[n] {
+ if genSbox(n, byte(m)) != sbox[n][m] {
+ t.Errorf("#%d|%d: sbox value = %d want %d", n, m, sbox[n][m], genSbox(n, byte(m)))
+ }
+ }
+ }
+}
+
+var testVectors = []struct {
+ key []byte
+ dec []byte
+ enc []byte
+}{
+ // These tests are extracted from LibTom
+ {
+ []byte{0x9F, 0x58, 0x9F, 0x5C, 0xF6, 0x12, 0x2C, 0x32, 0xB6, 0xBF, 0xEC, 0x2F, 0x2A, 0xE8, 0xC3, 0x5A},
+ []byte{0xD4, 0x91, 0xDB, 0x16, 0xE7, 0xB1, 0xC3, 0x9E, 0x86, 0xCB, 0x08, 0x6B, 0x78, 0x9F, 0x54, 0x19},
+ []byte{0x01, 0x9F, 0x98, 0x09, 0xDE, 0x17, 0x11, 0x85, 0x8F, 0xAA, 0xC3, 0xA3, 0xBA, 0x20, 0xFB, 0xC3},
+ },
+ {
+ []byte{0x88, 0xB2, 0xB2, 0x70, 0x6B, 0x10, 0x5E, 0x36, 0xB4, 0x46, 0xBB, 0x6D, 0x73, 0x1A, 0x1E, 0x88,
+ 0xEF, 0xA7, 0x1F, 0x78, 0x89, 0x65, 0xBD, 0x44},
+ []byte{0x39, 0xDA, 0x69, 0xD6, 0xBA, 0x49, 0x97, 0xD5, 0x85, 0xB6, 0xDC, 0x07, 0x3C, 0xA3, 0x41, 0xB2},
+ []byte{0x18, 0x2B, 0x02, 0xD8, 0x14, 0x97, 0xEA, 0x45, 0xF9, 0xDA, 0xAC, 0xDC, 0x29, 0x19, 0x3A, 0x65},
+ },
+ {
+ []byte{0xD4, 0x3B, 0xB7, 0x55, 0x6E, 0xA3, 0x2E, 0x46, 0xF2, 0xA2, 0x82, 0xB7, 0xD4, 0x5B, 0x4E, 0x0D,
+ 0x57, 0xFF, 0x73, 0x9D, 0x4D, 0xC9, 0x2C, 0x1B, 0xD7, 0xFC, 0x01, 0x70, 0x0C, 0xC8, 0x21, 0x6F},
+ []byte{0x90, 0xAF, 0xE9, 0x1B, 0xB2, 0x88, 0x54, 0x4F, 0x2C, 0x32, 0xDC, 0x23, 0x9B, 0x26, 0x35, 0xE6},
+ []byte{0x6C, 0xB4, 0x56, 0x1C, 0x40, 0xBF, 0x0A, 0x97, 0x05, 0x93, 0x1C, 0xB6, 0xD4, 0x08, 0xE7, 0xFA},
+ },
+ // These tests are derived from https://www.schneier.com/code/ecb_ival.txt
+ {
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0x9F, 0x58, 0x9F, 0x5C, 0xF6, 0x12, 0x2C, 0x32, 0xB6, 0xBF, 0xEC, 0x2F, 0x2A, 0xE8, 0xC3, 0x5A},
+ },
+ {
+ []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ },
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0xCF, 0xD1, 0xD2, 0xE5, 0xA9, 0xBE, 0x9C, 0xDF, 0x50, 0x1F, 0x13, 0xB8, 0x92, 0xBD, 0x22, 0x48},
+ },
+ {
+ []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
+ },
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0x37, 0x52, 0x7B, 0xE0, 0x05, 0x23, 0x34, 0xB8, 0x9F, 0x0C, 0xFC, 0xCA, 0xE8, 0x7C, 0xFA, 0x20},
+ },
+}
+
+func TestCipher(t *testing.T) {
+ for n, tt := range testVectors {
+ // Test if the plaintext (dec) is encrypts to the given
+ // ciphertext (enc) using the given key. Test also if enc can
+ // be decrypted again into dec.
+ c, err := NewCipher(tt.key)
+ if err != nil {
+ t.Errorf("#%d: NewCipher: %v", n, err)
+ return
+ }
+
+ buf := make([]byte, 16)
+ c.Encrypt(buf, tt.dec)
+ if !bytes.Equal(buf, tt.enc) {
+ t.Errorf("#%d: encrypt = %x want %x", n, buf, tt.enc)
+ }
+ c.Decrypt(buf, tt.enc)
+ if !bytes.Equal(buf, tt.dec) {
+ t.Errorf("#%d: decrypt = %x want %x", n, buf, tt.dec)
+ }
+
+ // Test that 16 zero bytes, encrypted 1000 times then decrypted
+ // 1000 times results in zero bytes again.
+ zero := make([]byte, 16)
+ buf = make([]byte, 16)
+ for i := 0; i < 1000; i++ {
+ c.Encrypt(buf, buf)
+ }
+ for i := 0; i < 1000; i++ {
+ c.Decrypt(buf, buf)
+ }
+ if !bytes.Equal(buf, zero) {
+ t.Errorf("#%d: encrypt/decrypt 1000: have %x want %x", n, buf, zero)
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/xtea/block.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/xtea/block.go
new file mode 100644
index 000000000..bf5d24599
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/xtea/block.go
@@ -0,0 +1,66 @@
+// Copyright 2009 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.
+
+/*
+ Implementation adapted from Needham and Wheeler's paper:
+ http://www.cix.co.uk/~klockstone/xtea.pdf
+
+ A precalculated look up table is used during encryption/decryption for values that are based purely on the key.
+*/
+
+package xtea
+
+// XTEA is based on 64 rounds.
+const numRounds = 64
+
+// blockToUint32 reads an 8 byte slice into two uint32s.
+// The block is treated as big endian.
+func blockToUint32(src []byte) (uint32, uint32) {
+ r0 := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
+ r1 := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
+ return r0, r1
+}
+
+// uint32ToBlock writes two uint32s into an 8 byte data block.
+// Values are written as big endian.
+func uint32ToBlock(v0, v1 uint32, dst []byte) {
+ dst[0] = byte(v0 >> 24)
+ dst[1] = byte(v0 >> 16)
+ dst[2] = byte(v0 >> 8)
+ dst[3] = byte(v0)
+ dst[4] = byte(v1 >> 24)
+ dst[5] = byte(v1 >> 16)
+ dst[6] = byte(v1 >> 8)
+ dst[7] = byte(v1 >> 0)
+}
+
+// encryptBlock encrypts a single 8 byte block using XTEA.
+func encryptBlock(c *Cipher, dst, src []byte) {
+ v0, v1 := blockToUint32(src)
+
+ // Two rounds of XTEA applied per loop
+ for i := 0; i < numRounds; {
+ v0 += ((v1<<4 ^ v1>>5) + v1) ^ c.table[i]
+ i++
+ v1 += ((v0<<4 ^ v0>>5) + v0) ^ c.table[i]
+ i++
+ }
+
+ uint32ToBlock(v0, v1, dst)
+}
+
+// decryptBlock decrypt a single 8 byte block using XTEA.
+func decryptBlock(c *Cipher, dst, src []byte) {
+ v0, v1 := blockToUint32(src)
+
+ // Two rounds of XTEA applied per loop
+ for i := numRounds; i > 0; {
+ i--
+ v1 -= ((v0<<4 ^ v0>>5) + v0) ^ c.table[i]
+ i--
+ v0 -= ((v1<<4 ^ v1>>5) + v1) ^ c.table[i]
+ }
+
+ uint32ToBlock(v0, v1, dst)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/xtea/cipher.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/xtea/cipher.go
new file mode 100644
index 000000000..108b42635
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/xtea/cipher.go
@@ -0,0 +1,82 @@
+// Copyright 2009 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 xtea implements XTEA encryption, as defined in Needham and Wheeler's
+// 1997 technical report, "Tea extensions."
+package xtea // import "golang.org/x/crypto/xtea"
+
+// For details, see http://www.cix.co.uk/~klockstone/xtea.pdf
+
+import "strconv"
+
+// The XTEA block size in bytes.
+const BlockSize = 8
+
+// A Cipher is an instance of an XTEA cipher using a particular key.
+// table contains a series of precalculated values that are used each round.
+type Cipher struct {
+ table [64]uint32
+}
+
+type KeySizeError int
+
+func (k KeySizeError) Error() string {
+ return "crypto/xtea: invalid key size " + strconv.Itoa(int(k))
+}
+
+// NewCipher creates and returns a new Cipher.
+// The key argument should be the XTEA key.
+// XTEA only supports 128 bit (16 byte) keys.
+func NewCipher(key []byte) (*Cipher, error) {
+ k := len(key)
+ switch k {
+ default:
+ return nil, KeySizeError(k)
+ case 16:
+ break
+ }
+
+ c := new(Cipher)
+ initCipher(c, key)
+
+ return c, nil
+}
+
+// BlockSize returns the XTEA block size, 8 bytes.
+// It is necessary to satisfy the Block interface in the
+// package "crypto/cipher".
+func (c *Cipher) BlockSize() int { return BlockSize }
+
+// Encrypt encrypts the 8 byte buffer src using the key and stores the result in dst.
+// Note that for amounts of data larger than a block,
+// it is not safe to just call Encrypt on successive blocks;
+// instead, use an encryption mode like CBC (see crypto/cipher/cbc.go).
+func (c *Cipher) Encrypt(dst, src []byte) { encryptBlock(c, dst, src) }
+
+// Decrypt decrypts the 8 byte buffer src using the key k and stores the result in dst.
+func (c *Cipher) Decrypt(dst, src []byte) { decryptBlock(c, dst, src) }
+
+// initCipher initializes the cipher context by creating a look up table
+// of precalculated values that are based on the key.
+func initCipher(c *Cipher, key []byte) {
+ // Load the key into four uint32s
+ var k [4]uint32
+ for i := 0; i < len(k); i++ {
+ j := i << 2 // Multiply by 4
+ k[i] = uint32(key[j+0])<<24 | uint32(key[j+1])<<16 | uint32(key[j+2])<<8 | uint32(key[j+3])
+ }
+
+ // Precalculate the table
+ const delta = 0x9E3779B9
+ var sum uint32 = 0
+
+ // Two rounds of XTEA applied per loop
+ for i := 0; i < numRounds; {
+ c.table[i] = sum + k[sum&3]
+ i++
+ sum += delta
+ c.table[i] = sum + k[(sum>>11)&3]
+ i++
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/xtea/xtea_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/xtea/xtea_test.go
new file mode 100644
index 000000000..be711bf5a
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/xtea/xtea_test.go
@@ -0,0 +1,229 @@
+// Copyright 2009 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 xtea
+
+import (
+ "testing"
+)
+
+// A sample test key for when we just want to initialize a cipher
+var testKey = []byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}
+
+// Test that the block size for XTEA is correct
+func TestBlocksize(t *testing.T) {
+ if BlockSize != 8 {
+ t.Errorf("BlockSize constant - expected 8, got %d", BlockSize)
+ return
+ }
+
+ c, err := NewCipher(testKey)
+ if err != nil {
+ t.Errorf("NewCipher(%d bytes) = %s", len(testKey), err)
+ return
+ }
+
+ result := c.BlockSize()
+ if result != 8 {
+ t.Errorf("BlockSize function - expected 8, got %d", result)
+ return
+ }
+}
+
+// A series of test values to confirm that the Cipher.table array was initialized correctly
+var testTable = []uint32{
+ 0x00112233, 0x6B1568B8, 0xE28CE030, 0xC5089E2D, 0xC5089E2D, 0x1EFBD3A2, 0xA7845C2A, 0x78EF0917,
+ 0x78EF0917, 0x172682D0, 0x5B6AC714, 0x822AC955, 0x3DE68511, 0xDC1DFECA, 0x2062430E, 0x3611343F,
+ 0xF1CCEFFB, 0x900469B4, 0xD448ADF8, 0x2E3BE36D, 0xB6C46BF5, 0x994029F2, 0x994029F2, 0xF3335F67,
+ 0x6AAAD6DF, 0x4D2694DC, 0x4D2694DC, 0xEB5E0E95, 0x2FA252D9, 0x4551440A, 0x121E10D6, 0xB0558A8F,
+ 0xE388BDC3, 0x0A48C004, 0xC6047BC0, 0x643BF579, 0xA88039BD, 0x02736F32, 0x8AFBF7BA, 0x5C66A4A7,
+ 0x5C66A4A7, 0xC76AEB2C, 0x3EE262A4, 0x215E20A1, 0x215E20A1, 0x7B515616, 0x03D9DE9E, 0x1988CFCF,
+ 0xD5448B8B, 0x737C0544, 0xB7C04988, 0xDE804BC9, 0x9A3C0785, 0x3873813E, 0x7CB7C582, 0xD6AAFAF7,
+ 0x4E22726F, 0x309E306C, 0x309E306C, 0x8A9165E1, 0x1319EE69, 0xF595AC66, 0xF595AC66, 0x4F88E1DB,
+}
+
+// Test that the cipher context is initialized correctly
+func TestCipherInit(t *testing.T) {
+ c, err := NewCipher(testKey)
+ if err != nil {
+ t.Errorf("NewCipher(%d bytes) = %s", len(testKey), err)
+ return
+ }
+
+ for i := 0; i < len(c.table); i++ {
+ if c.table[i] != testTable[i] {
+ t.Errorf("NewCipher() failed to initialize Cipher.table[%d] correctly. Expected %08X, got %08X", i, testTable[i], c.table[i])
+ break
+ }
+ }
+}
+
+// Test that invalid key sizes return an error
+func TestInvalidKeySize(t *testing.T) {
+ // Test a long key
+ key := []byte{
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
+ }
+
+ _, err := NewCipher(key)
+ if err == nil {
+ t.Errorf("Invalid key size %d didn't result in an error.", len(key))
+ }
+
+ // Test a short key
+ key = []byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}
+
+ _, err = NewCipher(key)
+ if err == nil {
+ t.Errorf("Invalid key size %d didn't result in an error.", len(key))
+ }
+}
+
+// Test that we can correctly decode some bytes we have encoded
+func TestEncodeDecode(t *testing.T) {
+ original := []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}
+ input := original
+ output := make([]byte, BlockSize)
+
+ c, err := NewCipher(testKey)
+ if err != nil {
+ t.Errorf("NewCipher(%d bytes) = %s", len(testKey), err)
+ return
+ }
+
+ // Encrypt the input block
+ c.Encrypt(output, input)
+
+ // Check that the output does not match the input
+ differs := false
+ for i := 0; i < len(input); i++ {
+ if output[i] != input[i] {
+ differs = true
+ break
+ }
+ }
+ if differs == false {
+ t.Error("Cipher.Encrypt: Failed to encrypt the input block.")
+ return
+ }
+
+ // Decrypt the block we just encrypted
+ input = output
+ output = make([]byte, BlockSize)
+ c.Decrypt(output, input)
+
+ // Check that the output from decrypt matches our initial input
+ for i := 0; i < len(input); i++ {
+ if output[i] != original[i] {
+ t.Errorf("Decrypted byte %d differed. Expected %02X, got %02X\n", i, original[i], output[i])
+ return
+ }
+ }
+}
+
+// Test Vectors
+type CryptTest struct {
+ key []byte
+ plainText []byte
+ cipherText []byte
+}
+
+var CryptTests = []CryptTest{
+ // These were sourced from http://www.freemedialibrary.com/index.php/XTEA_test_vectors
+ {
+ []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f},
+ []byte{0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48},
+ []byte{0x49, 0x7d, 0xf3, 0xd0, 0x72, 0x61, 0x2c, 0xb5},
+ },
+ {
+ []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f},
+ []byte{0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41},
+ []byte{0xe7, 0x8f, 0x2d, 0x13, 0x74, 0x43, 0x41, 0xd8},
+ },
+ {
+ []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f},
+ []byte{0x5a, 0x5b, 0x6e, 0x27, 0x89, 0x48, 0xd7, 0x7f},
+ []byte{0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41},
+ },
+ {
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48},
+ []byte{0xa0, 0x39, 0x05, 0x89, 0xf8, 0xb8, 0xef, 0xa5},
+ },
+ {
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41},
+ []byte{0xed, 0x23, 0x37, 0x5a, 0x82, 0x1a, 0x8c, 0x2d},
+ },
+ {
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0x70, 0xe1, 0x22, 0x5d, 0x6e, 0x4e, 0x76, 0x55},
+ []byte{0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41},
+ },
+
+ // These vectors are from http://wiki.secondlife.com/wiki/XTEA_Strong_Encryption_Implementation#Bouncy_Castle_C.23_API
+ {
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0xDE, 0xE9, 0xD4, 0xD8, 0xF7, 0x13, 0x1E, 0xD9},
+ },
+ {
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08},
+ []byte{0x06, 0x5C, 0x1B, 0x89, 0x75, 0xC6, 0xA8, 0x16},
+ },
+ {
+ []byte{0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, 0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A},
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0x1F, 0xF9, 0xA0, 0x26, 0x1A, 0xC6, 0x42, 0x64},
+ },
+ {
+ []byte{0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, 0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A},
+ []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08},
+ []byte{0x8C, 0x67, 0x15, 0x5B, 0x2E, 0xF9, 0x1E, 0xAD},
+ },
+}
+
+// Test encryption
+func TestCipherEncrypt(t *testing.T) {
+ for i, tt := range CryptTests {
+ c, err := NewCipher(tt.key)
+ if err != nil {
+ t.Errorf("NewCipher(%d bytes), vector %d = %s", len(tt.key), i, err)
+ continue
+ }
+
+ out := make([]byte, len(tt.plainText))
+ c.Encrypt(out, tt.plainText)
+
+ for j := 0; j < len(out); j++ {
+ if out[j] != tt.cipherText[j] {
+ t.Errorf("Cipher.Encrypt %d: out[%d] = %02X, expected %02X", i, j, out[j], tt.cipherText[j])
+ break
+ }
+ }
+ }
+}
+
+// Test decryption
+func TestCipherDecrypt(t *testing.T) {
+ for i, tt := range CryptTests {
+ c, err := NewCipher(tt.key)
+ if err != nil {
+ t.Errorf("NewCipher(%d bytes), vector %d = %s", len(tt.key), i, err)
+ continue
+ }
+
+ out := make([]byte, len(tt.cipherText))
+ c.Decrypt(out, tt.cipherText)
+
+ for j := 0; j < len(out); j++ {
+ if out[j] != tt.plainText[j] {
+ t.Errorf("Cipher.Decrypt %d: out[%d] = %02X, expected %02X", i, j, out[j], tt.plainText[j])
+ break
+ }
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/xts/xts.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/xts/xts.go
new file mode 100644
index 000000000..92cbce99b
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/xts/xts.go
@@ -0,0 +1,137 @@
+// Copyright 2012 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 xts implements the XTS cipher mode as specified in IEEE P1619/D16.
+//
+// XTS mode is typically used for disk encryption, which presents a number of
+// novel problems that make more common modes inapplicable. The disk is
+// conceptually an array of sectors and we must be able to encrypt and decrypt
+// a sector in isolation. However, an attacker must not be able to transpose
+// two sectors of plaintext by transposing their ciphertext.
+//
+// XTS wraps a block cipher with Rogaway's XEX mode in order to build a
+// tweakable block cipher. This allows each sector to have a unique tweak and
+// effectively create a unique key for each sector.
+//
+// XTS does not provide any authentication. An attacker can manipulate the
+// ciphertext and randomise a block (16 bytes) of the plaintext.
+//
+// (Note: this package does not implement ciphertext-stealing so sectors must
+// be a multiple of 16 bytes.)
+package xts // import "golang.org/x/crypto/xts"
+
+import (
+ "crypto/cipher"
+ "encoding/binary"
+ "errors"
+)
+
+// Cipher contains an expanded key structure. It doesn't contain mutable state
+// and therefore can be used concurrently.
+type Cipher struct {
+ k1, k2 cipher.Block
+}
+
+// blockSize is the block size that the underlying cipher must have. XTS is
+// only defined for 16-byte ciphers.
+const blockSize = 16
+
+// NewCipher creates a Cipher given a function for creating the underlying
+// block cipher (which must have a block size of 16 bytes). The key must be
+// twice the length of the underlying cipher's key.
+func NewCipher(cipherFunc func([]byte) (cipher.Block, error), key []byte) (c *Cipher, err error) {
+ c = new(Cipher)
+ if c.k1, err = cipherFunc(key[:len(key)/2]); err != nil {
+ return
+ }
+ c.k2, err = cipherFunc(key[len(key)/2:])
+
+ if c.k1.BlockSize() != blockSize {
+ err = errors.New("xts: cipher does not have a block size of 16")
+ }
+
+ return
+}
+
+// Encrypt encrypts a sector of plaintext and puts the result into ciphertext.
+// Plaintext and ciphertext must overlap entirely or not at all.
+// Sectors must be a multiple of 16 bytes and less than 2²⁴ bytes.
+func (c *Cipher) Encrypt(ciphertext, plaintext []byte, sectorNum uint64) {
+ if len(ciphertext) < len(plaintext) {
+ panic("xts: ciphertext is smaller than plaintext")
+ }
+ if len(plaintext)%blockSize != 0 {
+ panic("xts: plaintext is not a multiple of the block size")
+ }
+
+ var tweak [blockSize]byte
+ binary.LittleEndian.PutUint64(tweak[:8], sectorNum)
+
+ c.k2.Encrypt(tweak[:], tweak[:])
+
+ for len(plaintext) > 0 {
+ for j := range tweak {
+ ciphertext[j] = plaintext[j] ^ tweak[j]
+ }
+ c.k1.Encrypt(ciphertext, ciphertext)
+ for j := range tweak {
+ ciphertext[j] ^= tweak[j]
+ }
+ plaintext = plaintext[blockSize:]
+ ciphertext = ciphertext[blockSize:]
+
+ mul2(&tweak)
+ }
+}
+
+// Decrypt decrypts a sector of ciphertext and puts the result into plaintext.
+// Plaintext and ciphertext must overlap entirely or not at all.
+// Sectors must be a multiple of 16 bytes and less than 2²⁴ bytes.
+func (c *Cipher) Decrypt(plaintext, ciphertext []byte, sectorNum uint64) {
+ if len(plaintext) < len(ciphertext) {
+ panic("xts: plaintext is smaller than ciphertext")
+ }
+ if len(ciphertext)%blockSize != 0 {
+ panic("xts: ciphertext is not a multiple of the block size")
+ }
+
+ var tweak [blockSize]byte
+ binary.LittleEndian.PutUint64(tweak[:8], sectorNum)
+
+ c.k2.Encrypt(tweak[:], tweak[:])
+
+ for len(ciphertext) > 0 {
+ for j := range tweak {
+ plaintext[j] = ciphertext[j] ^ tweak[j]
+ }
+ c.k1.Decrypt(plaintext, plaintext)
+ for j := range tweak {
+ plaintext[j] ^= tweak[j]
+ }
+ plaintext = plaintext[blockSize:]
+ ciphertext = ciphertext[blockSize:]
+
+ mul2(&tweak)
+ }
+}
+
+// mul2 multiplies tweak by 2 in GF(2¹²⁸) with an irreducible polynomial of
+// x¹²⁸ + x⁷ + x² + x + 1.
+func mul2(tweak *[blockSize]byte) {
+ var carryIn byte
+ for j := range tweak {
+ carryOut := tweak[j] >> 7
+ tweak[j] = (tweak[j] << 1) + carryIn
+ carryIn = carryOut
+ }
+ if carryIn != 0 {
+ // If we have a carry bit then we need to subtract a multiple
+ // of the irreducible polynomial (x¹²⁸ + x⁷ + x² + x + 1).
+ // By dropping the carry bit, we're subtracting the x^128 term
+ // so all that remains is to subtract x⁷ + x² + x + 1.
+ // Subtraction (and addition) in this representation is just
+ // XOR.
+ tweak[0] ^= 1<<7 | 1<<2 | 1<<1 | 1
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/xts/xts_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/xts/xts_test.go
new file mode 100644
index 000000000..96d3b6cbc
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/crypto/xts/xts_test.go
@@ -0,0 +1,105 @@
+// Copyright 2012 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 xts
+
+import (
+ "bytes"
+ "crypto/aes"
+ "encoding/hex"
+ "testing"
+)
+
+// These test vectors have been taken from IEEE P1619/D16, Annex B.
+var xtsTestVectors = []struct {
+ key string
+ sector uint64
+ plaintext string
+ ciphertext string
+}{
+ {
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ 0,
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "917cf69ebd68b2ec9b9fe9a3eadda692cd43d2f59598ed858c02c2652fbf922e",
+ }, {
+ "1111111111111111111111111111111122222222222222222222222222222222",
+ 0x3333333333,
+ "4444444444444444444444444444444444444444444444444444444444444444",
+ "c454185e6a16936e39334038acef838bfb186fff7480adc4289382ecd6d394f0",
+ }, {
+ "fffefdfcfbfaf9f8f7f6f5f4f3f2f1f022222222222222222222222222222222",
+ 0x3333333333,
+ "4444444444444444444444444444444444444444444444444444444444444444",
+ "af85336b597afc1a900b2eb21ec949d292df4c047e0b21532186a5971a227a89",
+ }, {
+ "2718281828459045235360287471352631415926535897932384626433832795",
+ 0,
+ "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
+ "27a7479befa1d476489f308cd4cfa6e2a96e4bbe3208ff25287dd3819616e89cc78cf7f5e543445f8333d8fa7f56000005279fa5d8b5e4ad40e736ddb4d35412328063fd2aab53e5ea1e0a9f332500a5df9487d07a5c92cc512c8866c7e860ce93fdf166a24912b422976146ae20ce846bb7dc9ba94a767aaef20c0d61ad02655ea92dc4c4e41a8952c651d33174be51a10c421110e6d81588ede82103a252d8a750e8768defffed9122810aaeb99f9172af82b604dc4b8e51bcb08235a6f4341332e4ca60482a4ba1a03b3e65008fc5da76b70bf1690db4eae29c5f1badd03c5ccf2a55d705ddcd86d449511ceb7ec30bf12b1fa35b913f9f747a8afd1b130e94bff94effd01a91735ca1726acd0b197c4e5b03393697e126826fb6bbde8ecc1e08298516e2c9ed03ff3c1b7860f6de76d4cecd94c8119855ef5297ca67e9f3e7ff72b1e99785ca0a7e7720c5b36dc6d72cac9574c8cbbc2f801e23e56fd344b07f22154beba0f08ce8891e643ed995c94d9a69c9f1b5f499027a78572aeebd74d20cc39881c213ee770b1010e4bea718846977ae119f7a023ab58cca0ad752afe656bb3c17256a9f6e9bf19fdd5a38fc82bbe872c5539edb609ef4f79c203ebb140f2e583cb2ad15b4aa5b655016a8449277dbd477ef2c8d6c017db738b18deb4a427d1923ce3ff262735779a418f20a282df920147beabe421ee5319d0568",
+ }, {
+ "2718281828459045235360287471352631415926535897932384626433832795",
+ 1,
+ "27a7479befa1d476489f308cd4cfa6e2a96e4bbe3208ff25287dd3819616e89cc78cf7f5e543445f8333d8fa7f56000005279fa5d8b5e4ad40e736ddb4d35412328063fd2aab53e5ea1e0a9f332500a5df9487d07a5c92cc512c8866c7e860ce93fdf166a24912b422976146ae20ce846bb7dc9ba94a767aaef20c0d61ad02655ea92dc4c4e41a8952c651d33174be51a10c421110e6d81588ede82103a252d8a750e8768defffed9122810aaeb99f9172af82b604dc4b8e51bcb08235a6f4341332e4ca60482a4ba1a03b3e65008fc5da76b70bf1690db4eae29c5f1badd03c5ccf2a55d705ddcd86d449511ceb7ec30bf12b1fa35b913f9f747a8afd1b130e94bff94effd01a91735ca1726acd0b197c4e5b03393697e126826fb6bbde8ecc1e08298516e2c9ed03ff3c1b7860f6de76d4cecd94c8119855ef5297ca67e9f3e7ff72b1e99785ca0a7e7720c5b36dc6d72cac9574c8cbbc2f801e23e56fd344b07f22154beba0f08ce8891e643ed995c94d9a69c9f1b5f499027a78572aeebd74d20cc39881c213ee770b1010e4bea718846977ae119f7a023ab58cca0ad752afe656bb3c17256a9f6e9bf19fdd5a38fc82bbe872c5539edb609ef4f79c203ebb140f2e583cb2ad15b4aa5b655016a8449277dbd477ef2c8d6c017db738b18deb4a427d1923ce3ff262735779a418f20a282df920147beabe421ee5319d0568",
+ "264d3ca8512194fec312c8c9891f279fefdd608d0c027b60483a3fa811d65ee59d52d9e40ec5672d81532b38b6b089ce951f0f9c35590b8b978d175213f329bb1c2fd30f2f7f30492a61a532a79f51d36f5e31a7c9a12c286082ff7d2394d18f783e1a8e72c722caaaa52d8f065657d2631fd25bfd8e5baad6e527d763517501c68c5edc3cdd55435c532d7125c8614deed9adaa3acade5888b87bef641c4c994c8091b5bcd387f3963fb5bc37aa922fbfe3df4e5b915e6eb514717bdd2a74079a5073f5c4bfd46adf7d282e7a393a52579d11a028da4d9cd9c77124f9648ee383b1ac763930e7162a8d37f350b2f74b8472cf09902063c6b32e8c2d9290cefbd7346d1c779a0df50edcde4531da07b099c638e83a755944df2aef1aa31752fd323dcb710fb4bfbb9d22b925bc3577e1b8949e729a90bbafeacf7f7879e7b1147e28ba0bae940db795a61b15ecf4df8db07b824bb062802cc98a9545bb2aaeed77cb3fc6db15dcd7d80d7d5bc406c4970a3478ada8899b329198eb61c193fb6275aa8ca340344a75a862aebe92eee1ce032fd950b47d7704a3876923b4ad62844bf4a09c4dbe8b4397184b7471360c9564880aedddb9baa4af2e75394b08cd32ff479c57a07d3eab5d54de5f9738b8d27f27a9f0ab11799d7b7ffefb2704c95c6ad12c39f1e867a4b7b1d7818a4b753dfd2a89ccb45e001a03a867b187f225dd",
+ }, {
+ "27182818284590452353602874713526624977572470936999595749669676273141592653589793238462643383279502884197169399375105820974944592",
+ 0xff,
+ "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
+ "1c3b3a102f770386e4836c99e370cf9bea00803f5e482357a4ae12d414a3e63b5d31e276f8fe4a8d66b317f9ac683f44680a86ac35adfc3345befecb4bb188fd5776926c49a3095eb108fd1098baec70aaa66999a72a82f27d848b21d4a741b0c5cd4d5fff9dac89aeba122961d03a757123e9870f8acf1000020887891429ca2a3e7a7d7df7b10355165c8b9a6d0a7de8b062c4500dc4cd120c0f7418dae3d0b5781c34803fa75421c790dfe1de1834f280d7667b327f6c8cd7557e12ac3a0f93ec05c52e0493ef31a12d3d9260f79a289d6a379bc70c50841473d1a8cc81ec583e9645e07b8d9670655ba5bbcfecc6dc3966380ad8fecb17b6ba02469a020a84e18e8f84252070c13e9f1f289be54fbc481457778f616015e1327a02b140f1505eb309326d68378f8374595c849d84f4c333ec4423885143cb47bd71c5edae9be69a2ffeceb1bec9de244fbe15992b11b77c040f12bd8f6a975a44a0f90c29a9abc3d4d893927284c58754cce294529f8614dcd2aba991925fedc4ae74ffac6e333b93eb4aff0479da9a410e4450e0dd7ae4c6e2910900575da401fc07059f645e8b7e9bfdef33943054ff84011493c27b3429eaedb4ed5376441a77ed43851ad77f16f541dfd269d50d6a5f14fb0aab1cbb4c1550be97f7ab4066193c4caa773dad38014bd2092fa755c824bb5e54c4f36ffda9fcea70b9c6e693e148c151",
+ },
+}
+
+func fromHex(s string) []byte {
+ ret, err := hex.DecodeString(s)
+ if err != nil {
+ panic("xts: invalid hex in test")
+ }
+ return ret
+}
+
+func TestXTS(t *testing.T) {
+ for i, test := range xtsTestVectors {
+ c, err := NewCipher(aes.NewCipher, fromHex(test.key))
+ if err != nil {
+ t.Errorf("#%d: failed to create cipher: %s", i, err)
+ continue
+ }
+ plaintext := fromHex(test.plaintext)
+ ciphertext := make([]byte, len(plaintext))
+ c.Encrypt(ciphertext, plaintext, test.sector)
+
+ expectedCiphertext := fromHex(test.ciphertext)
+ if !bytes.Equal(ciphertext, expectedCiphertext) {
+ t.Errorf("#%d: encrypted failed, got: %x, want: %x", i, ciphertext, expectedCiphertext)
+ continue
+ }
+
+ decrypted := make([]byte, len(ciphertext))
+ c.Decrypt(decrypted, ciphertext, test.sector)
+ if !bytes.Equal(decrypted, plaintext) {
+ t.Errorf("#%d: decryption failed, got: %x, want: %x", i, decrypted, plaintext)
+ }
+ }
+}
+
+func TestShorterCiphertext(t *testing.T) {
+ // Decrypt used to panic if the input was shorter than the output. See
+ // https://go-review.googlesource.com/c/39954/
+ c, err := NewCipher(aes.NewCipher, make([]byte, 32))
+ if err != nil {
+ t.Fatalf("NewCipher failed: %s", err)
+ }
+
+ plaintext := make([]byte, 32)
+ encrypted := make([]byte, 48)
+ decrypted := make([]byte, 48)
+
+ c.Encrypt(encrypted, plaintext, 0)
+ c.Decrypt(decrypted, encrypted[:len(plaintext)], 0)
+
+ if !bytes.Equal(plaintext, decrypted[:len(plaintext)]) {
+ t.Errorf("En/Decryption is not inverse")
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/.gitattributes b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/.gitattributes
new file mode 100644
index 000000000..d2f212e5d
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/.gitattributes
@@ -0,0 +1,10 @@
+# Treat all files in this repo as binary, with no git magic updating
+# line endings. Windows users contributing to Go will need to use a
+# modern version of git and editors capable of LF line endings.
+#
+# We'll prevent accidental CRLF line endings from entering the repo
+# via the git-review gofmt checks.
+#
+# See golang.org/issue/9281
+
+* -text
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/.gitignore b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/.gitignore
new file mode 100644
index 000000000..8339fd61d
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/.gitignore
@@ -0,0 +1,2 @@
+# Add no patterns to .hgignore except for files generated by the build.
+last-change
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/AUTHORS b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/AUTHORS
new file mode 100644
index 000000000..15167cd74
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/AUTHORS
@@ -0,0 +1,3 @@
+# This source code refers to The Go Authors for copyright purposes.
+# The master list of authors is in the main Go distribution,
+# visible at http://tip.golang.org/AUTHORS.
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/CONTRIBUTING.md b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/CONTRIBUTING.md
new file mode 100644
index 000000000..88dff59bc
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/CONTRIBUTING.md
@@ -0,0 +1,31 @@
+# Contributing to Go
+
+Go is an open source project.
+
+It is the work of hundreds of contributors. We appreciate your help!
+
+
+## Filing issues
+
+When [filing an issue](https://golang.org/issue/new), make sure to answer these five questions:
+
+1. What version of Go are you using (`go version`)?
+2. What operating system and processor architecture are you using?
+3. What did you do?
+4. What did you expect to see?
+5. What did you see instead?
+
+General questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker.
+The gophers there will answer or ask you to file an issue if you've tripped over a bug.
+
+## Contributing code
+
+Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html)
+before sending patches.
+
+**We do not accept GitHub pull requests**
+(we use [Gerrit](https://code.google.com/p/gerrit/) instead for code review).
+
+Unless otherwise noted, the Go source files are distributed under
+the BSD-style license found in the LICENSE file.
+
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/CONTRIBUTORS b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/CONTRIBUTORS
new file mode 100644
index 000000000..1c4577e96
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/CONTRIBUTORS
@@ -0,0 +1,3 @@
+# This source code was written by the Go contributors.
+# The master list of contributors is in the main Go distribution,
+# visible at http://tip.golang.org/CONTRIBUTORS.
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/LICENSE b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/LICENSE
new file mode 100644
index 000000000..6a66aea5e
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2009 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/PATENTS b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/PATENTS
new file mode 100644
index 000000000..733099041
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/PATENTS
@@ -0,0 +1,22 @@
+Additional IP Rights Grant (Patents)
+
+"This implementation" means the copyrightable works distributed by
+Google as part of the Go project.
+
+Google hereby grants to You a perpetual, worldwide, non-exclusive,
+no-charge, royalty-free, irrevocable (except as stated in this section)
+patent license to make, have made, use, offer to sell, sell, import,
+transfer and otherwise run, modify and propagate the contents of this
+implementation of Go, where such license applies only to those patent
+claims, both currently owned or controlled by Google and acquired in
+the future, licensable by Google that are necessarily infringed by this
+implementation of Go. This grant does not include claims that would be
+infringed only as a consequence of further modification of this
+implementation. If you or your agent or exclusive licensee institute or
+order or agree to the institution of patent litigation against any
+entity (including a cross-claim or counterclaim in a lawsuit) alleging
+that this implementation of Go or any code incorporated within this
+implementation of Go constitutes direct or contributory patent
+infringement, or inducement of patent infringement, then any patent
+rights granted to you under this License for this implementation of Go
+shall terminate as of the date such litigation is filed.
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/README.md b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/README.md
new file mode 100644
index 000000000..00a9b6eb2
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/README.md
@@ -0,0 +1,16 @@
+# Go Networking
+
+This repository holds supplementary Go networking libraries.
+
+## Download/Install
+
+The easiest way to install is to run `go get -u golang.org/x/net`. You can
+also manually git clone the repository to `$GOPATH/src/golang.org/x/net`.
+
+## Report Issues / Send Patches
+
+This repository uses Gerrit for code changes. To learn how to submit
+changes to this repository, see https://golang.org/doc/contribute.html.
+The main issue tracker for the net repository is located at
+https://github.com/golang/go/issues. Prefix your issue with "x/net:" in the
+subject line, so it is easy to find.
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/asm.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/asm.go
new file mode 100644
index 000000000..15e21b181
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/asm.go
@@ -0,0 +1,41 @@
+// 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.
+
+package bpf
+
+import "fmt"
+
+// Assemble converts insts into raw instructions suitable for loading
+// into a BPF virtual machine.
+//
+// Currently, no optimization is attempted, the assembled program flow
+// is exactly as provided.
+func Assemble(insts []Instruction) ([]RawInstruction, error) {
+ ret := make([]RawInstruction, len(insts))
+ var err error
+ for i, inst := range insts {
+ ret[i], err = inst.Assemble()
+ if err != nil {
+ return nil, fmt.Errorf("assembling instruction %d: %s", i+1, err)
+ }
+ }
+ return ret, nil
+}
+
+// Disassemble attempts to parse raw back into
+// Instructions. Unrecognized RawInstructions are assumed to be an
+// extension not implemented by this package, and are passed through
+// unchanged to the output. The allDecoded value reports whether insts
+// contains no RawInstructions.
+func Disassemble(raw []RawInstruction) (insts []Instruction, allDecoded bool) {
+ insts = make([]Instruction, len(raw))
+ allDecoded = true
+ for i, r := range raw {
+ insts[i] = r.Disassemble()
+ if _, ok := insts[i].(RawInstruction); ok {
+ allDecoded = false
+ }
+ }
+ return insts, allDecoded
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/constants.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/constants.go
new file mode 100644
index 000000000..b89ca3523
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/constants.go
@@ -0,0 +1,218 @@
+// 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.
+
+package bpf
+
+// A Register is a register of the BPF virtual machine.
+type Register uint16
+
+const (
+ // RegA is the accumulator register. RegA is always the
+ // destination register of ALU operations.
+ RegA Register = iota
+ // RegX is the indirection register, used by LoadIndirect
+ // operations.
+ RegX
+)
+
+// An ALUOp is an arithmetic or logic operation.
+type ALUOp uint16
+
+// ALU binary operation types.
+const (
+ ALUOpAdd ALUOp = iota << 4
+ ALUOpSub
+ ALUOpMul
+ ALUOpDiv
+ ALUOpOr
+ ALUOpAnd
+ ALUOpShiftLeft
+ ALUOpShiftRight
+ aluOpNeg // Not exported because it's the only unary ALU operation, and gets its own instruction type.
+ ALUOpMod
+ ALUOpXor
+)
+
+// A JumpTest is a comparison operator used in conditional jumps.
+type JumpTest uint16
+
+// Supported operators for conditional jumps.
+const (
+ // K == A
+ JumpEqual JumpTest = iota
+ // K != A
+ JumpNotEqual
+ // K > A
+ JumpGreaterThan
+ // K < A
+ JumpLessThan
+ // K >= A
+ JumpGreaterOrEqual
+ // K <= A
+ JumpLessOrEqual
+ // K & A != 0
+ JumpBitsSet
+ // K & A == 0
+ JumpBitsNotSet
+)
+
+// An Extension is a function call provided by the kernel that
+// performs advanced operations that are expensive or impossible
+// within the BPF virtual machine.
+//
+// Extensions are only implemented by the Linux kernel.
+//
+// TODO: should we prune this list? Some of these extensions seem
+// either broken or near-impossible to use correctly, whereas other
+// (len, random, ifindex) are quite useful.
+type Extension int
+
+// Extension functions available in the Linux kernel.
+const (
+ // extOffset is the negative maximum number of instructions used
+ // to load instructions by overloading the K argument.
+ extOffset = -0x1000
+ // ExtLen returns the length of the packet.
+ ExtLen Extension = 1
+ // ExtProto returns the packet's L3 protocol type.
+ ExtProto Extension = 0
+ // ExtType returns the packet's type (skb->pkt_type in the kernel)
+ //
+ // TODO: better documentation. How nice an API do we want to
+ // provide for these esoteric extensions?
+ ExtType Extension = 4
+ // ExtPayloadOffset returns the offset of the packet payload, or
+ // the first protocol header that the kernel does not know how to
+ // parse.
+ ExtPayloadOffset Extension = 52
+ // ExtInterfaceIndex returns the index of the interface on which
+ // the packet was received.
+ ExtInterfaceIndex Extension = 8
+ // ExtNetlinkAttr returns the netlink attribute of type X at
+ // offset A.
+ ExtNetlinkAttr Extension = 12
+ // ExtNetlinkAttrNested returns the nested netlink attribute of
+ // type X at offset A.
+ ExtNetlinkAttrNested Extension = 16
+ // ExtMark returns the packet's mark value.
+ ExtMark Extension = 20
+ // ExtQueue returns the packet's assigned hardware queue.
+ ExtQueue Extension = 24
+ // ExtLinkLayerType returns the packet's hardware address type
+ // (e.g. Ethernet, Infiniband).
+ ExtLinkLayerType Extension = 28
+ // ExtRXHash returns the packets receive hash.
+ //
+ // TODO: figure out what this rxhash actually is.
+ ExtRXHash Extension = 32
+ // ExtCPUID returns the ID of the CPU processing the current
+ // packet.
+ ExtCPUID Extension = 36
+ // ExtVLANTag returns the packet's VLAN tag.
+ ExtVLANTag Extension = 44
+ // ExtVLANTagPresent returns non-zero if the packet has a VLAN
+ // tag.
+ //
+ // TODO: I think this might be a lie: it reads bit 0x1000 of the
+ // VLAN header, which changed meaning in recent revisions of the
+ // spec - this extension may now return meaningless information.
+ ExtVLANTagPresent Extension = 48
+ // ExtVLANProto returns 0x8100 if the frame has a VLAN header,
+ // 0x88a8 if the frame has a "Q-in-Q" double VLAN header, or some
+ // other value if no VLAN information is present.
+ ExtVLANProto Extension = 60
+ // ExtRand returns a uniformly random uint32.
+ ExtRand Extension = 56
+)
+
+// The following gives names to various bit patterns used in opcode construction.
+
+const (
+ opMaskCls uint16 = 0x7
+ // opClsLoad masks
+ opMaskLoadDest = 0x01
+ opMaskLoadWidth = 0x18
+ opMaskLoadMode = 0xe0
+ // opClsALU
+ opMaskOperandSrc = 0x08
+ opMaskOperator = 0xf0
+ // opClsJump
+ opMaskJumpConst = 0x0f
+ opMaskJumpCond = 0xf0
+)
+
+const (
+ // +---------------+-----------------+---+---+---+
+ // | AddrMode (3b) | LoadWidth (2b) | 0 | 0 | 0 |
+ // +---------------+-----------------+---+---+---+
+ opClsLoadA uint16 = iota
+ // +---------------+-----------------+---+---+---+
+ // | AddrMode (3b) | LoadWidth (2b) | 0 | 0 | 1 |
+ // +---------------+-----------------+---+---+---+
+ opClsLoadX
+ // +---+---+---+---+---+---+---+---+
+ // | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
+ // +---+---+---+---+---+---+---+---+
+ opClsStoreA
+ // +---+---+---+---+---+---+---+---+
+ // | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
+ // +---+---+---+---+---+---+---+---+
+ opClsStoreX
+ // +---------------+-----------------+---+---+---+
+ // | Operator (4b) | OperandSrc (1b) | 1 | 0 | 0 |
+ // +---------------+-----------------+---+---+---+
+ opClsALU
+ // +-----------------------------+---+---+---+---+
+ // | TestOperator (4b) | 0 | 1 | 0 | 1 |
+ // +-----------------------------+---+---+---+---+
+ opClsJump
+ // +---+-------------------------+---+---+---+---+
+ // | 0 | 0 | 0 | RetSrc (1b) | 0 | 1 | 1 | 0 |
+ // +---+-------------------------+---+---+---+---+
+ opClsReturn
+ // +---+-------------------------+---+---+---+---+
+ // | 0 | 0 | 0 | TXAorTAX (1b) | 0 | 1 | 1 | 1 |
+ // +---+-------------------------+---+---+---+---+
+ opClsMisc
+)
+
+const (
+ opAddrModeImmediate uint16 = iota << 5
+ opAddrModeAbsolute
+ opAddrModeIndirect
+ opAddrModeScratch
+ opAddrModePacketLen // actually an extension, not an addressing mode.
+ opAddrModeMemShift
+)
+
+const (
+ opLoadWidth4 uint16 = iota << 3
+ opLoadWidth2
+ opLoadWidth1
+)
+
+// Operator defined by ALUOp*
+
+const (
+ opALUSrcConstant uint16 = iota << 3
+ opALUSrcX
+)
+
+const (
+ opJumpAlways = iota << 4
+ opJumpEqual
+ opJumpGT
+ opJumpGE
+ opJumpSet
+)
+
+const (
+ opRetSrcConstant uint16 = iota << 4
+ opRetSrcA
+)
+
+const (
+ opMiscTAX = 0x00
+ opMiscTXA = 0x80
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/doc.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/doc.go
new file mode 100644
index 000000000..ae62feb53
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/doc.go
@@ -0,0 +1,82 @@
+// 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.
+
+/*
+
+Package bpf implements marshaling and unmarshaling of programs for the
+Berkeley Packet Filter virtual machine, and provides a Go implementation
+of the virtual machine.
+
+BPF's main use is to specify a packet filter for network taps, so that
+the kernel doesn't have to expensively copy every packet it sees to
+userspace. However, it's been repurposed to other areas where running
+user code in-kernel is needed. For example, Linux's seccomp uses BPF
+to apply security policies to system calls. For simplicity, this
+documentation refers only to packets, but other uses of BPF have their
+own data payloads.
+
+BPF programs run in a restricted virtual machine. It has almost no
+access to kernel functions, and while conditional branches are
+allowed, they can only jump forwards, to guarantee that there are no
+infinite loops.
+
+The virtual machine
+
+The BPF VM is an accumulator machine. Its main register, called
+register A, is an implicit source and destination in all arithmetic
+and logic operations. The machine also has 16 scratch registers for
+temporary storage, and an indirection register (register X) for
+indirect memory access. All registers are 32 bits wide.
+
+Each run of a BPF program is given one packet, which is placed in the
+VM's read-only "main memory". LoadAbsolute and LoadIndirect
+instructions can fetch up to 32 bits at a time into register A for
+examination.
+
+The goal of a BPF program is to produce and return a verdict (uint32),
+which tells the kernel what to do with the packet. In the context of
+packet filtering, the returned value is the number of bytes of the
+packet to forward to userspace, or 0 to ignore the packet. Other
+contexts like seccomp define their own return values.
+
+In order to simplify programs, attempts to read past the end of the
+packet terminate the program execution with a verdict of 0 (ignore
+packet). This means that the vast majority of BPF programs don't need
+to do any explicit bounds checking.
+
+In addition to the bytes of the packet, some BPF programs have access
+to extensions, which are essentially calls to kernel utility
+functions. Currently, the only extensions supported by this package
+are the Linux packet filter extensions.
+
+Examples
+
+This packet filter selects all ARP packets.
+
+ bpf.Assemble([]bpf.Instruction{
+ // Load "EtherType" field from the ethernet header.
+ bpf.LoadAbsolute{Off: 12, Size: 2},
+ // Skip over the next instruction if EtherType is not ARP.
+ bpf.JumpIf{Cond: bpf.JumpNotEqual, Val: 0x0806, SkipTrue: 1},
+ // Verdict is "send up to 4k of the packet to userspace."
+ bpf.RetConstant{Val: 4096},
+ // Verdict is "ignore packet."
+ bpf.RetConstant{Val: 0},
+ })
+
+This packet filter captures a random 1% sample of traffic.
+
+ bpf.Assemble([]bpf.Instruction{
+ // Get a 32-bit random number from the Linux kernel.
+ bpf.LoadExtension{Num: bpf.ExtRand},
+ // 1% dice roll?
+ bpf.JumpIf{Cond: bpf.JumpLessThan, Val: 2^32/100, SkipFalse: 1},
+ // Capture.
+ bpf.RetConstant{Val: 4096},
+ // Ignore.
+ bpf.RetConstant{Val: 0},
+ })
+
+*/
+package bpf // import "golang.org/x/net/bpf"
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/instructions.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/instructions.go
new file mode 100644
index 000000000..3b4fd0891
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/instructions.go
@@ -0,0 +1,704 @@
+// 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.
+
+package bpf
+
+import "fmt"
+
+// An Instruction is one instruction executed by the BPF virtual
+// machine.
+type Instruction interface {
+ // Assemble assembles the Instruction into a RawInstruction.
+ Assemble() (RawInstruction, error)
+}
+
+// A RawInstruction is a raw BPF virtual machine instruction.
+type RawInstruction struct {
+ // Operation to execute.
+ Op uint16
+ // For conditional jump instructions, the number of instructions
+ // to skip if the condition is true/false.
+ Jt uint8
+ Jf uint8
+ // Constant parameter. The meaning depends on the Op.
+ K uint32
+}
+
+// Assemble implements the Instruction Assemble method.
+func (ri RawInstruction) Assemble() (RawInstruction, error) { return ri, nil }
+
+// Disassemble parses ri into an Instruction and returns it. If ri is
+// not recognized by this package, ri itself is returned.
+func (ri RawInstruction) Disassemble() Instruction {
+ switch ri.Op & opMaskCls {
+ case opClsLoadA, opClsLoadX:
+ reg := Register(ri.Op & opMaskLoadDest)
+ sz := 0
+ switch ri.Op & opMaskLoadWidth {
+ case opLoadWidth4:
+ sz = 4
+ case opLoadWidth2:
+ sz = 2
+ case opLoadWidth1:
+ sz = 1
+ default:
+ return ri
+ }
+ switch ri.Op & opMaskLoadMode {
+ case opAddrModeImmediate:
+ if sz != 4 {
+ return ri
+ }
+ return LoadConstant{Dst: reg, Val: ri.K}
+ case opAddrModeScratch:
+ if sz != 4 || ri.K > 15 {
+ return ri
+ }
+ return LoadScratch{Dst: reg, N: int(ri.K)}
+ case opAddrModeAbsolute:
+ if ri.K > extOffset+0xffffffff {
+ return LoadExtension{Num: Extension(-extOffset + ri.K)}
+ }
+ return LoadAbsolute{Size: sz, Off: ri.K}
+ case opAddrModeIndirect:
+ return LoadIndirect{Size: sz, Off: ri.K}
+ case opAddrModePacketLen:
+ if sz != 4 {
+ return ri
+ }
+ return LoadExtension{Num: ExtLen}
+ case opAddrModeMemShift:
+ return LoadMemShift{Off: ri.K}
+ default:
+ return ri
+ }
+
+ case opClsStoreA:
+ if ri.Op != opClsStoreA || ri.K > 15 {
+ return ri
+ }
+ return StoreScratch{Src: RegA, N: int(ri.K)}
+
+ case opClsStoreX:
+ if ri.Op != opClsStoreX || ri.K > 15 {
+ return ri
+ }
+ return StoreScratch{Src: RegX, N: int(ri.K)}
+
+ case opClsALU:
+ switch op := ALUOp(ri.Op & opMaskOperator); op {
+ case ALUOpAdd, ALUOpSub, ALUOpMul, ALUOpDiv, ALUOpOr, ALUOpAnd, ALUOpShiftLeft, ALUOpShiftRight, ALUOpMod, ALUOpXor:
+ if ri.Op&opMaskOperandSrc != 0 {
+ return ALUOpX{Op: op}
+ }
+ return ALUOpConstant{Op: op, Val: ri.K}
+ case aluOpNeg:
+ return NegateA{}
+ default:
+ return ri
+ }
+
+ case opClsJump:
+ if ri.Op&opMaskJumpConst != opClsJump {
+ return ri
+ }
+ switch ri.Op & opMaskJumpCond {
+ case opJumpAlways:
+ return Jump{Skip: ri.K}
+ case opJumpEqual:
+ if ri.Jt == 0 {
+ return JumpIf{
+ Cond: JumpNotEqual,
+ Val: ri.K,
+ SkipTrue: ri.Jf,
+ SkipFalse: 0,
+ }
+ }
+ return JumpIf{
+ Cond: JumpEqual,
+ Val: ri.K,
+ SkipTrue: ri.Jt,
+ SkipFalse: ri.Jf,
+ }
+ case opJumpGT:
+ if ri.Jt == 0 {
+ return JumpIf{
+ Cond: JumpLessOrEqual,
+ Val: ri.K,
+ SkipTrue: ri.Jf,
+ SkipFalse: 0,
+ }
+ }
+ return JumpIf{
+ Cond: JumpGreaterThan,
+ Val: ri.K,
+ SkipTrue: ri.Jt,
+ SkipFalse: ri.Jf,
+ }
+ case opJumpGE:
+ if ri.Jt == 0 {
+ return JumpIf{
+ Cond: JumpLessThan,
+ Val: ri.K,
+ SkipTrue: ri.Jf,
+ SkipFalse: 0,
+ }
+ }
+ return JumpIf{
+ Cond: JumpGreaterOrEqual,
+ Val: ri.K,
+ SkipTrue: ri.Jt,
+ SkipFalse: ri.Jf,
+ }
+ case opJumpSet:
+ return JumpIf{
+ Cond: JumpBitsSet,
+ Val: ri.K,
+ SkipTrue: ri.Jt,
+ SkipFalse: ri.Jf,
+ }
+ default:
+ return ri
+ }
+
+ case opClsReturn:
+ switch ri.Op {
+ case opClsReturn | opRetSrcA:
+ return RetA{}
+ case opClsReturn | opRetSrcConstant:
+ return RetConstant{Val: ri.K}
+ default:
+ return ri
+ }
+
+ case opClsMisc:
+ switch ri.Op {
+ case opClsMisc | opMiscTAX:
+ return TAX{}
+ case opClsMisc | opMiscTXA:
+ return TXA{}
+ default:
+ return ri
+ }
+
+ default:
+ panic("unreachable") // switch is exhaustive on the bit pattern
+ }
+}
+
+// LoadConstant loads Val into register Dst.
+type LoadConstant struct {
+ Dst Register
+ Val uint32
+}
+
+// Assemble implements the Instruction Assemble method.
+func (a LoadConstant) Assemble() (RawInstruction, error) {
+ return assembleLoad(a.Dst, 4, opAddrModeImmediate, a.Val)
+}
+
+// String returns the the instruction in assembler notation.
+func (a LoadConstant) String() string {
+ switch a.Dst {
+ case RegA:
+ return fmt.Sprintf("ld #%d", a.Val)
+ case RegX:
+ return fmt.Sprintf("ldx #%d", a.Val)
+ default:
+ return fmt.Sprintf("unknown instruction: %#v", a)
+ }
+}
+
+// LoadScratch loads scratch[N] into register Dst.
+type LoadScratch struct {
+ Dst Register
+ N int // 0-15
+}
+
+// Assemble implements the Instruction Assemble method.
+func (a LoadScratch) Assemble() (RawInstruction, error) {
+ if a.N < 0 || a.N > 15 {
+ return RawInstruction{}, fmt.Errorf("invalid scratch slot %d", a.N)
+ }
+ return assembleLoad(a.Dst, 4, opAddrModeScratch, uint32(a.N))
+}
+
+// String returns the the instruction in assembler notation.
+func (a LoadScratch) String() string {
+ switch a.Dst {
+ case RegA:
+ return fmt.Sprintf("ld M[%d]", a.N)
+ case RegX:
+ return fmt.Sprintf("ldx M[%d]", a.N)
+ default:
+ return fmt.Sprintf("unknown instruction: %#v", a)
+ }
+}
+
+// LoadAbsolute loads packet[Off:Off+Size] as an integer value into
+// register A.
+type LoadAbsolute struct {
+ Off uint32
+ Size int // 1, 2 or 4
+}
+
+// Assemble implements the Instruction Assemble method.
+func (a LoadAbsolute) Assemble() (RawInstruction, error) {
+ return assembleLoad(RegA, a.Size, opAddrModeAbsolute, a.Off)
+}
+
+// String returns the the instruction in assembler notation.
+func (a LoadAbsolute) String() string {
+ switch a.Size {
+ case 1: // byte
+ return fmt.Sprintf("ldb [%d]", a.Off)
+ case 2: // half word
+ return fmt.Sprintf("ldh [%d]", a.Off)
+ case 4: // word
+ if a.Off > extOffset+0xffffffff {
+ return LoadExtension{Num: Extension(a.Off + 0x1000)}.String()
+ }
+ return fmt.Sprintf("ld [%d]", a.Off)
+ default:
+ return fmt.Sprintf("unknown instruction: %#v", a)
+ }
+}
+
+// LoadIndirect loads packet[X+Off:X+Off+Size] as an integer value
+// into register A.
+type LoadIndirect struct {
+ Off uint32
+ Size int // 1, 2 or 4
+}
+
+// Assemble implements the Instruction Assemble method.
+func (a LoadIndirect) Assemble() (RawInstruction, error) {
+ return assembleLoad(RegA, a.Size, opAddrModeIndirect, a.Off)
+}
+
+// String returns the the instruction in assembler notation.
+func (a LoadIndirect) String() string {
+ switch a.Size {
+ case 1: // byte
+ return fmt.Sprintf("ldb [x + %d]", a.Off)
+ case 2: // half word
+ return fmt.Sprintf("ldh [x + %d]", a.Off)
+ case 4: // word
+ return fmt.Sprintf("ld [x + %d]", a.Off)
+ default:
+ return fmt.Sprintf("unknown instruction: %#v", a)
+ }
+}
+
+// LoadMemShift multiplies the first 4 bits of the byte at packet[Off]
+// by 4 and stores the result in register X.
+//
+// This instruction is mainly useful to load into X the length of an
+// IPv4 packet header in a single instruction, rather than have to do
+// the arithmetic on the header's first byte by hand.
+type LoadMemShift struct {
+ Off uint32
+}
+
+// Assemble implements the Instruction Assemble method.
+func (a LoadMemShift) Assemble() (RawInstruction, error) {
+ return assembleLoad(RegX, 1, opAddrModeMemShift, a.Off)
+}
+
+// String returns the the instruction in assembler notation.
+func (a LoadMemShift) String() string {
+ return fmt.Sprintf("ldx 4*([%d]&0xf)", a.Off)
+}
+
+// LoadExtension invokes a linux-specific extension and stores the
+// result in register A.
+type LoadExtension struct {
+ Num Extension
+}
+
+// Assemble implements the Instruction Assemble method.
+func (a LoadExtension) Assemble() (RawInstruction, error) {
+ if a.Num == ExtLen {
+ return assembleLoad(RegA, 4, opAddrModePacketLen, 0)
+ }
+ return assembleLoad(RegA, 4, opAddrModeAbsolute, uint32(extOffset+a.Num))
+}
+
+// String returns the the instruction in assembler notation.
+func (a LoadExtension) String() string {
+ switch a.Num {
+ case ExtLen:
+ return "ld #len"
+ case ExtProto:
+ return "ld #proto"
+ case ExtType:
+ return "ld #type"
+ case ExtPayloadOffset:
+ return "ld #poff"
+ case ExtInterfaceIndex:
+ return "ld #ifidx"
+ case ExtNetlinkAttr:
+ return "ld #nla"
+ case ExtNetlinkAttrNested:
+ return "ld #nlan"
+ case ExtMark:
+ return "ld #mark"
+ case ExtQueue:
+ return "ld #queue"
+ case ExtLinkLayerType:
+ return "ld #hatype"
+ case ExtRXHash:
+ return "ld #rxhash"
+ case ExtCPUID:
+ return "ld #cpu"
+ case ExtVLANTag:
+ return "ld #vlan_tci"
+ case ExtVLANTagPresent:
+ return "ld #vlan_avail"
+ case ExtVLANProto:
+ return "ld #vlan_tpid"
+ case ExtRand:
+ return "ld #rand"
+ default:
+ return fmt.Sprintf("unknown instruction: %#v", a)
+ }
+}
+
+// StoreScratch stores register Src into scratch[N].
+type StoreScratch struct {
+ Src Register
+ N int // 0-15
+}
+
+// Assemble implements the Instruction Assemble method.
+func (a StoreScratch) Assemble() (RawInstruction, error) {
+ if a.N < 0 || a.N > 15 {
+ return RawInstruction{}, fmt.Errorf("invalid scratch slot %d", a.N)
+ }
+ var op uint16
+ switch a.Src {
+ case RegA:
+ op = opClsStoreA
+ case RegX:
+ op = opClsStoreX
+ default:
+ return RawInstruction{}, fmt.Errorf("invalid source register %v", a.Src)
+ }
+
+ return RawInstruction{
+ Op: op,
+ K: uint32(a.N),
+ }, nil
+}
+
+// String returns the the instruction in assembler notation.
+func (a StoreScratch) String() string {
+ switch a.Src {
+ case RegA:
+ return fmt.Sprintf("st M[%d]", a.N)
+ case RegX:
+ return fmt.Sprintf("stx M[%d]", a.N)
+ default:
+ return fmt.Sprintf("unknown instruction: %#v", a)
+ }
+}
+
+// ALUOpConstant executes A = A <Op> Val.
+type ALUOpConstant struct {
+ Op ALUOp
+ Val uint32
+}
+
+// Assemble implements the Instruction Assemble method.
+func (a ALUOpConstant) Assemble() (RawInstruction, error) {
+ return RawInstruction{
+ Op: opClsALU | opALUSrcConstant | uint16(a.Op),
+ K: a.Val,
+ }, nil
+}
+
+// String returns the the instruction in assembler notation.
+func (a ALUOpConstant) String() string {
+ switch a.Op {
+ case ALUOpAdd:
+ return fmt.Sprintf("add #%d", a.Val)
+ case ALUOpSub:
+ return fmt.Sprintf("sub #%d", a.Val)
+ case ALUOpMul:
+ return fmt.Sprintf("mul #%d", a.Val)
+ case ALUOpDiv:
+ return fmt.Sprintf("div #%d", a.Val)
+ case ALUOpMod:
+ return fmt.Sprintf("mod #%d", a.Val)
+ case ALUOpAnd:
+ return fmt.Sprintf("and #%d", a.Val)
+ case ALUOpOr:
+ return fmt.Sprintf("or #%d", a.Val)
+ case ALUOpXor:
+ return fmt.Sprintf("xor #%d", a.Val)
+ case ALUOpShiftLeft:
+ return fmt.Sprintf("lsh #%d", a.Val)
+ case ALUOpShiftRight:
+ return fmt.Sprintf("rsh #%d", a.Val)
+ default:
+ return fmt.Sprintf("unknown instruction: %#v", a)
+ }
+}
+
+// ALUOpX executes A = A <Op> X
+type ALUOpX struct {
+ Op ALUOp
+}
+
+// Assemble implements the Instruction Assemble method.
+func (a ALUOpX) Assemble() (RawInstruction, error) {
+ return RawInstruction{
+ Op: opClsALU | opALUSrcX | uint16(a.Op),
+ }, nil
+}
+
+// String returns the the instruction in assembler notation.
+func (a ALUOpX) String() string {
+ switch a.Op {
+ case ALUOpAdd:
+ return "add x"
+ case ALUOpSub:
+ return "sub x"
+ case ALUOpMul:
+ return "mul x"
+ case ALUOpDiv:
+ return "div x"
+ case ALUOpMod:
+ return "mod x"
+ case ALUOpAnd:
+ return "and x"
+ case ALUOpOr:
+ return "or x"
+ case ALUOpXor:
+ return "xor x"
+ case ALUOpShiftLeft:
+ return "lsh x"
+ case ALUOpShiftRight:
+ return "rsh x"
+ default:
+ return fmt.Sprintf("unknown instruction: %#v", a)
+ }
+}
+
+// NegateA executes A = -A.
+type NegateA struct{}
+
+// Assemble implements the Instruction Assemble method.
+func (a NegateA) Assemble() (RawInstruction, error) {
+ return RawInstruction{
+ Op: opClsALU | uint16(aluOpNeg),
+ }, nil
+}
+
+// String returns the the instruction in assembler notation.
+func (a NegateA) String() string {
+ return fmt.Sprintf("neg")
+}
+
+// Jump skips the following Skip instructions in the program.
+type Jump struct {
+ Skip uint32
+}
+
+// Assemble implements the Instruction Assemble method.
+func (a Jump) Assemble() (RawInstruction, error) {
+ return RawInstruction{
+ Op: opClsJump | opJumpAlways,
+ K: a.Skip,
+ }, nil
+}
+
+// String returns the the instruction in assembler notation.
+func (a Jump) String() string {
+ return fmt.Sprintf("ja %d", a.Skip)
+}
+
+// JumpIf skips the following Skip instructions in the program if A
+// <Cond> Val is true.
+type JumpIf struct {
+ Cond JumpTest
+ Val uint32
+ SkipTrue uint8
+ SkipFalse uint8
+}
+
+// Assemble implements the Instruction Assemble method.
+func (a JumpIf) Assemble() (RawInstruction, error) {
+ var (
+ cond uint16
+ flip bool
+ )
+ switch a.Cond {
+ case JumpEqual:
+ cond = opJumpEqual
+ case JumpNotEqual:
+ cond, flip = opJumpEqual, true
+ case JumpGreaterThan:
+ cond = opJumpGT
+ case JumpLessThan:
+ cond, flip = opJumpGE, true
+ case JumpGreaterOrEqual:
+ cond = opJumpGE
+ case JumpLessOrEqual:
+ cond, flip = opJumpGT, true
+ case JumpBitsSet:
+ cond = opJumpSet
+ case JumpBitsNotSet:
+ cond, flip = opJumpSet, true
+ default:
+ return RawInstruction{}, fmt.Errorf("unknown JumpTest %v", a.Cond)
+ }
+ jt, jf := a.SkipTrue, a.SkipFalse
+ if flip {
+ jt, jf = jf, jt
+ }
+ return RawInstruction{
+ Op: opClsJump | cond,
+ Jt: jt,
+ Jf: jf,
+ K: a.Val,
+ }, nil
+}
+
+// String returns the the instruction in assembler notation.
+func (a JumpIf) String() string {
+ switch a.Cond {
+ // K == A
+ case JumpEqual:
+ return conditionalJump(a, "jeq", "jneq")
+ // K != A
+ case JumpNotEqual:
+ return fmt.Sprintf("jneq #%d,%d", a.Val, a.SkipTrue)
+ // K > A
+ case JumpGreaterThan:
+ return conditionalJump(a, "jgt", "jle")
+ // K < A
+ case JumpLessThan:
+ return fmt.Sprintf("jlt #%d,%d", a.Val, a.SkipTrue)
+ // K >= A
+ case JumpGreaterOrEqual:
+ return conditionalJump(a, "jge", "jlt")
+ // K <= A
+ case JumpLessOrEqual:
+ return fmt.Sprintf("jle #%d,%d", a.Val, a.SkipTrue)
+ // K & A != 0
+ case JumpBitsSet:
+ if a.SkipFalse > 0 {
+ return fmt.Sprintf("jset #%d,%d,%d", a.Val, a.SkipTrue, a.SkipFalse)
+ }
+ return fmt.Sprintf("jset #%d,%d", a.Val, a.SkipTrue)
+ // K & A == 0, there is no assembler instruction for JumpBitNotSet, use JumpBitSet and invert skips
+ case JumpBitsNotSet:
+ return JumpIf{Cond: JumpBitsSet, SkipTrue: a.SkipFalse, SkipFalse: a.SkipTrue, Val: a.Val}.String()
+ default:
+ return fmt.Sprintf("unknown instruction: %#v", a)
+ }
+}
+
+func conditionalJump(inst JumpIf, positiveJump, negativeJump string) string {
+ if inst.SkipTrue > 0 {
+ if inst.SkipFalse > 0 {
+ return fmt.Sprintf("%s #%d,%d,%d", positiveJump, inst.Val, inst.SkipTrue, inst.SkipFalse)
+ }
+ return fmt.Sprintf("%s #%d,%d", positiveJump, inst.Val, inst.SkipTrue)
+ }
+ return fmt.Sprintf("%s #%d,%d", negativeJump, inst.Val, inst.SkipFalse)
+}
+
+// RetA exits the BPF program, returning the value of register A.
+type RetA struct{}
+
+// Assemble implements the Instruction Assemble method.
+func (a RetA) Assemble() (RawInstruction, error) {
+ return RawInstruction{
+ Op: opClsReturn | opRetSrcA,
+ }, nil
+}
+
+// String returns the the instruction in assembler notation.
+func (a RetA) String() string {
+ return fmt.Sprintf("ret a")
+}
+
+// RetConstant exits the BPF program, returning a constant value.
+type RetConstant struct {
+ Val uint32
+}
+
+// Assemble implements the Instruction Assemble method.
+func (a RetConstant) Assemble() (RawInstruction, error) {
+ return RawInstruction{
+ Op: opClsReturn | opRetSrcConstant,
+ K: a.Val,
+ }, nil
+}
+
+// String returns the the instruction in assembler notation.
+func (a RetConstant) String() string {
+ return fmt.Sprintf("ret #%d", a.Val)
+}
+
+// TXA copies the value of register X to register A.
+type TXA struct{}
+
+// Assemble implements the Instruction Assemble method.
+func (a TXA) Assemble() (RawInstruction, error) {
+ return RawInstruction{
+ Op: opClsMisc | opMiscTXA,
+ }, nil
+}
+
+// String returns the the instruction in assembler notation.
+func (a TXA) String() string {
+ return fmt.Sprintf("txa")
+}
+
+// TAX copies the value of register A to register X.
+type TAX struct{}
+
+// Assemble implements the Instruction Assemble method.
+func (a TAX) Assemble() (RawInstruction, error) {
+ return RawInstruction{
+ Op: opClsMisc | opMiscTAX,
+ }, nil
+}
+
+// String returns the the instruction in assembler notation.
+func (a TAX) String() string {
+ return fmt.Sprintf("tax")
+}
+
+func assembleLoad(dst Register, loadSize int, mode uint16, k uint32) (RawInstruction, error) {
+ var (
+ cls uint16
+ sz uint16
+ )
+ switch dst {
+ case RegA:
+ cls = opClsLoadA
+ case RegX:
+ cls = opClsLoadX
+ default:
+ return RawInstruction{}, fmt.Errorf("invalid target register %v", dst)
+ }
+ switch loadSize {
+ case 1:
+ sz = opLoadWidth1
+ case 2:
+ sz = opLoadWidth2
+ case 4:
+ sz = opLoadWidth4
+ default:
+ return RawInstruction{}, fmt.Errorf("invalid load byte length %d", sz)
+ }
+ return RawInstruction{
+ Op: cls | sz | mode,
+ K: k,
+ }, nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/instructions_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/instructions_test.go
new file mode 100644
index 000000000..dde474aba
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/instructions_test.go
@@ -0,0 +1,525 @@
+// 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.
+
+package bpf
+
+import (
+ "fmt"
+ "io/ioutil"
+ "reflect"
+ "strconv"
+ "strings"
+ "testing"
+)
+
+// This is a direct translation of the program in
+// testdata/all_instructions.txt.
+var allInstructions = []Instruction{
+ LoadConstant{Dst: RegA, Val: 42},
+ LoadConstant{Dst: RegX, Val: 42},
+
+ LoadScratch{Dst: RegA, N: 3},
+ LoadScratch{Dst: RegX, N: 3},
+
+ LoadAbsolute{Off: 42, Size: 1},
+ LoadAbsolute{Off: 42, Size: 2},
+ LoadAbsolute{Off: 42, Size: 4},
+
+ LoadIndirect{Off: 42, Size: 1},
+ LoadIndirect{Off: 42, Size: 2},
+ LoadIndirect{Off: 42, Size: 4},
+
+ LoadMemShift{Off: 42},
+
+ LoadExtension{Num: ExtLen},
+ LoadExtension{Num: ExtProto},
+ LoadExtension{Num: ExtType},
+ LoadExtension{Num: ExtRand},
+
+ StoreScratch{Src: RegA, N: 3},
+ StoreScratch{Src: RegX, N: 3},
+
+ ALUOpConstant{Op: ALUOpAdd, Val: 42},
+ ALUOpConstant{Op: ALUOpSub, Val: 42},
+ ALUOpConstant{Op: ALUOpMul, Val: 42},
+ ALUOpConstant{Op: ALUOpDiv, Val: 42},
+ ALUOpConstant{Op: ALUOpOr, Val: 42},
+ ALUOpConstant{Op: ALUOpAnd, Val: 42},
+ ALUOpConstant{Op: ALUOpShiftLeft, Val: 42},
+ ALUOpConstant{Op: ALUOpShiftRight, Val: 42},
+ ALUOpConstant{Op: ALUOpMod, Val: 42},
+ ALUOpConstant{Op: ALUOpXor, Val: 42},
+
+ ALUOpX{Op: ALUOpAdd},
+ ALUOpX{Op: ALUOpSub},
+ ALUOpX{Op: ALUOpMul},
+ ALUOpX{Op: ALUOpDiv},
+ ALUOpX{Op: ALUOpOr},
+ ALUOpX{Op: ALUOpAnd},
+ ALUOpX{Op: ALUOpShiftLeft},
+ ALUOpX{Op: ALUOpShiftRight},
+ ALUOpX{Op: ALUOpMod},
+ ALUOpX{Op: ALUOpXor},
+
+ NegateA{},
+
+ Jump{Skip: 10},
+ JumpIf{Cond: JumpEqual, Val: 42, SkipTrue: 8, SkipFalse: 9},
+ JumpIf{Cond: JumpNotEqual, Val: 42, SkipTrue: 8},
+ JumpIf{Cond: JumpLessThan, Val: 42, SkipTrue: 7},
+ JumpIf{Cond: JumpLessOrEqual, Val: 42, SkipTrue: 6},
+ JumpIf{Cond: JumpGreaterThan, Val: 42, SkipTrue: 4, SkipFalse: 5},
+ JumpIf{Cond: JumpGreaterOrEqual, Val: 42, SkipTrue: 3, SkipFalse: 4},
+ JumpIf{Cond: JumpBitsSet, Val: 42, SkipTrue: 2, SkipFalse: 3},
+
+ TAX{},
+ TXA{},
+
+ RetA{},
+ RetConstant{Val: 42},
+}
+var allInstructionsExpected = "testdata/all_instructions.bpf"
+
+// Check that we produce the same output as the canonical bpf_asm
+// linux kernel tool.
+func TestInterop(t *testing.T) {
+ out, err := Assemble(allInstructions)
+ if err != nil {
+ t.Fatalf("assembly of allInstructions program failed: %s", err)
+ }
+ t.Logf("Assembled program is %d instructions long", len(out))
+
+ bs, err := ioutil.ReadFile(allInstructionsExpected)
+ if err != nil {
+ t.Fatalf("reading %s: %s", allInstructionsExpected, err)
+ }
+ // First statement is the number of statements, last statement is
+ // empty. We just ignore both and rely on slice length.
+ stmts := strings.Split(string(bs), ",")
+ if len(stmts)-2 != len(out) {
+ t.Fatalf("test program lengths don't match: %s has %d, Go implementation has %d", allInstructionsExpected, len(stmts)-2, len(allInstructions))
+ }
+
+ for i, stmt := range stmts[1 : len(stmts)-2] {
+ nums := strings.Split(stmt, " ")
+ if len(nums) != 4 {
+ t.Fatalf("malformed instruction %d in %s: %s", i+1, allInstructionsExpected, stmt)
+ }
+
+ actual := out[i]
+
+ op, err := strconv.ParseUint(nums[0], 10, 16)
+ if err != nil {
+ t.Fatalf("malformed opcode %s in instruction %d of %s", nums[0], i+1, allInstructionsExpected)
+ }
+ if actual.Op != uint16(op) {
+ t.Errorf("opcode mismatch on instruction %d (%#v): got 0x%02x, want 0x%02x", i+1, allInstructions[i], actual.Op, op)
+ }
+
+ jt, err := strconv.ParseUint(nums[1], 10, 8)
+ if err != nil {
+ t.Fatalf("malformed jt offset %s in instruction %d of %s", nums[1], i+1, allInstructionsExpected)
+ }
+ if actual.Jt != uint8(jt) {
+ t.Errorf("jt mismatch on instruction %d (%#v): got %d, want %d", i+1, allInstructions[i], actual.Jt, jt)
+ }
+
+ jf, err := strconv.ParseUint(nums[2], 10, 8)
+ if err != nil {
+ t.Fatalf("malformed jf offset %s in instruction %d of %s", nums[2], i+1, allInstructionsExpected)
+ }
+ if actual.Jf != uint8(jf) {
+ t.Errorf("jf mismatch on instruction %d (%#v): got %d, want %d", i+1, allInstructions[i], actual.Jf, jf)
+ }
+
+ k, err := strconv.ParseUint(nums[3], 10, 32)
+ if err != nil {
+ t.Fatalf("malformed constant %s in instruction %d of %s", nums[3], i+1, allInstructionsExpected)
+ }
+ if actual.K != uint32(k) {
+ t.Errorf("constant mismatch on instruction %d (%#v): got %d, want %d", i+1, allInstructions[i], actual.K, k)
+ }
+ }
+}
+
+// Check that assembly and disassembly match each other.
+func TestAsmDisasm(t *testing.T) {
+ prog1, err := Assemble(allInstructions)
+ if err != nil {
+ t.Fatalf("assembly of allInstructions program failed: %s", err)
+ }
+ t.Logf("Assembled program is %d instructions long", len(prog1))
+
+ got, allDecoded := Disassemble(prog1)
+ if !allDecoded {
+ t.Errorf("Disassemble(Assemble(allInstructions)) produced unrecognized instructions:")
+ for i, inst := range got {
+ if r, ok := inst.(RawInstruction); ok {
+ t.Logf(" insn %d, %#v --> %#v", i+1, allInstructions[i], r)
+ }
+ }
+ }
+
+ if len(allInstructions) != len(got) {
+ t.Fatalf("disassembly changed program size: %d insns before, %d insns after", len(allInstructions), len(got))
+ }
+ if !reflect.DeepEqual(allInstructions, got) {
+ t.Errorf("program mutated by disassembly:")
+ for i := range got {
+ if !reflect.DeepEqual(allInstructions[i], got[i]) {
+ t.Logf(" insn %d, s: %#v, p1: %#v, got: %#v", i+1, allInstructions[i], prog1[i], got[i])
+ }
+ }
+ }
+}
+
+type InvalidInstruction struct{}
+
+func (a InvalidInstruction) Assemble() (RawInstruction, error) {
+ return RawInstruction{}, fmt.Errorf("Invalid Instruction")
+}
+
+func (a InvalidInstruction) String() string {
+ return fmt.Sprintf("unknown instruction: %#v", a)
+}
+
+func TestString(t *testing.T) {
+ testCases := []struct {
+ instruction Instruction
+ assembler string
+ }{
+ {
+ instruction: LoadConstant{Dst: RegA, Val: 42},
+ assembler: "ld #42",
+ },
+ {
+ instruction: LoadConstant{Dst: RegX, Val: 42},
+ assembler: "ldx #42",
+ },
+ {
+ instruction: LoadConstant{Dst: 0xffff, Val: 42},
+ assembler: "unknown instruction: bpf.LoadConstant{Dst:0xffff, Val:0x2a}",
+ },
+ {
+ instruction: LoadScratch{Dst: RegA, N: 3},
+ assembler: "ld M[3]",
+ },
+ {
+ instruction: LoadScratch{Dst: RegX, N: 3},
+ assembler: "ldx M[3]",
+ },
+ {
+ instruction: LoadScratch{Dst: 0xffff, N: 3},
+ assembler: "unknown instruction: bpf.LoadScratch{Dst:0xffff, N:3}",
+ },
+ {
+ instruction: LoadAbsolute{Off: 42, Size: 1},
+ assembler: "ldb [42]",
+ },
+ {
+ instruction: LoadAbsolute{Off: 42, Size: 2},
+ assembler: "ldh [42]",
+ },
+ {
+ instruction: LoadAbsolute{Off: 42, Size: 4},
+ assembler: "ld [42]",
+ },
+ {
+ instruction: LoadAbsolute{Off: 42, Size: -1},
+ assembler: "unknown instruction: bpf.LoadAbsolute{Off:0x2a, Size:-1}",
+ },
+ {
+ instruction: LoadIndirect{Off: 42, Size: 1},
+ assembler: "ldb [x + 42]",
+ },
+ {
+ instruction: LoadIndirect{Off: 42, Size: 2},
+ assembler: "ldh [x + 42]",
+ },
+ {
+ instruction: LoadIndirect{Off: 42, Size: 4},
+ assembler: "ld [x + 42]",
+ },
+ {
+ instruction: LoadIndirect{Off: 42, Size: -1},
+ assembler: "unknown instruction: bpf.LoadIndirect{Off:0x2a, Size:-1}",
+ },
+ {
+ instruction: LoadMemShift{Off: 42},
+ assembler: "ldx 4*([42]&0xf)",
+ },
+ {
+ instruction: LoadExtension{Num: ExtLen},
+ assembler: "ld #len",
+ },
+ {
+ instruction: LoadExtension{Num: ExtProto},
+ assembler: "ld #proto",
+ },
+ {
+ instruction: LoadExtension{Num: ExtType},
+ assembler: "ld #type",
+ },
+ {
+ instruction: LoadExtension{Num: ExtPayloadOffset},
+ assembler: "ld #poff",
+ },
+ {
+ instruction: LoadExtension{Num: ExtInterfaceIndex},
+ assembler: "ld #ifidx",
+ },
+ {
+ instruction: LoadExtension{Num: ExtNetlinkAttr},
+ assembler: "ld #nla",
+ },
+ {
+ instruction: LoadExtension{Num: ExtNetlinkAttrNested},
+ assembler: "ld #nlan",
+ },
+ {
+ instruction: LoadExtension{Num: ExtMark},
+ assembler: "ld #mark",
+ },
+ {
+ instruction: LoadExtension{Num: ExtQueue},
+ assembler: "ld #queue",
+ },
+ {
+ instruction: LoadExtension{Num: ExtLinkLayerType},
+ assembler: "ld #hatype",
+ },
+ {
+ instruction: LoadExtension{Num: ExtRXHash},
+ assembler: "ld #rxhash",
+ },
+ {
+ instruction: LoadExtension{Num: ExtCPUID},
+ assembler: "ld #cpu",
+ },
+ {
+ instruction: LoadExtension{Num: ExtVLANTag},
+ assembler: "ld #vlan_tci",
+ },
+ {
+ instruction: LoadExtension{Num: ExtVLANTagPresent},
+ assembler: "ld #vlan_avail",
+ },
+ {
+ instruction: LoadExtension{Num: ExtVLANProto},
+ assembler: "ld #vlan_tpid",
+ },
+ {
+ instruction: LoadExtension{Num: ExtRand},
+ assembler: "ld #rand",
+ },
+ {
+ instruction: LoadAbsolute{Off: 0xfffff038, Size: 4},
+ assembler: "ld #rand",
+ },
+ {
+ instruction: LoadExtension{Num: 0xfff},
+ assembler: "unknown instruction: bpf.LoadExtension{Num:4095}",
+ },
+ {
+ instruction: StoreScratch{Src: RegA, N: 3},
+ assembler: "st M[3]",
+ },
+ {
+ instruction: StoreScratch{Src: RegX, N: 3},
+ assembler: "stx M[3]",
+ },
+ {
+ instruction: StoreScratch{Src: 0xffff, N: 3},
+ assembler: "unknown instruction: bpf.StoreScratch{Src:0xffff, N:3}",
+ },
+ {
+ instruction: ALUOpConstant{Op: ALUOpAdd, Val: 42},
+ assembler: "add #42",
+ },
+ {
+ instruction: ALUOpConstant{Op: ALUOpSub, Val: 42},
+ assembler: "sub #42",
+ },
+ {
+ instruction: ALUOpConstant{Op: ALUOpMul, Val: 42},
+ assembler: "mul #42",
+ },
+ {
+ instruction: ALUOpConstant{Op: ALUOpDiv, Val: 42},
+ assembler: "div #42",
+ },
+ {
+ instruction: ALUOpConstant{Op: ALUOpOr, Val: 42},
+ assembler: "or #42",
+ },
+ {
+ instruction: ALUOpConstant{Op: ALUOpAnd, Val: 42},
+ assembler: "and #42",
+ },
+ {
+ instruction: ALUOpConstant{Op: ALUOpShiftLeft, Val: 42},
+ assembler: "lsh #42",
+ },
+ {
+ instruction: ALUOpConstant{Op: ALUOpShiftRight, Val: 42},
+ assembler: "rsh #42",
+ },
+ {
+ instruction: ALUOpConstant{Op: ALUOpMod, Val: 42},
+ assembler: "mod #42",
+ },
+ {
+ instruction: ALUOpConstant{Op: ALUOpXor, Val: 42},
+ assembler: "xor #42",
+ },
+ {
+ instruction: ALUOpConstant{Op: 0xffff, Val: 42},
+ assembler: "unknown instruction: bpf.ALUOpConstant{Op:0xffff, Val:0x2a}",
+ },
+ {
+ instruction: ALUOpX{Op: ALUOpAdd},
+ assembler: "add x",
+ },
+ {
+ instruction: ALUOpX{Op: ALUOpSub},
+ assembler: "sub x",
+ },
+ {
+ instruction: ALUOpX{Op: ALUOpMul},
+ assembler: "mul x",
+ },
+ {
+ instruction: ALUOpX{Op: ALUOpDiv},
+ assembler: "div x",
+ },
+ {
+ instruction: ALUOpX{Op: ALUOpOr},
+ assembler: "or x",
+ },
+ {
+ instruction: ALUOpX{Op: ALUOpAnd},
+ assembler: "and x",
+ },
+ {
+ instruction: ALUOpX{Op: ALUOpShiftLeft},
+ assembler: "lsh x",
+ },
+ {
+ instruction: ALUOpX{Op: ALUOpShiftRight},
+ assembler: "rsh x",
+ },
+ {
+ instruction: ALUOpX{Op: ALUOpMod},
+ assembler: "mod x",
+ },
+ {
+ instruction: ALUOpX{Op: ALUOpXor},
+ assembler: "xor x",
+ },
+ {
+ instruction: ALUOpX{Op: 0xffff},
+ assembler: "unknown instruction: bpf.ALUOpX{Op:0xffff}",
+ },
+ {
+ instruction: NegateA{},
+ assembler: "neg",
+ },
+ {
+ instruction: Jump{Skip: 10},
+ assembler: "ja 10",
+ },
+ {
+ instruction: JumpIf{Cond: JumpEqual, Val: 42, SkipTrue: 8, SkipFalse: 9},
+ assembler: "jeq #42,8,9",
+ },
+ {
+ instruction: JumpIf{Cond: JumpEqual, Val: 42, SkipTrue: 8},
+ assembler: "jeq #42,8",
+ },
+ {
+ instruction: JumpIf{Cond: JumpEqual, Val: 42, SkipFalse: 8},
+ assembler: "jneq #42,8",
+ },
+ {
+ instruction: JumpIf{Cond: JumpNotEqual, Val: 42, SkipTrue: 8},
+ assembler: "jneq #42,8",
+ },
+ {
+ instruction: JumpIf{Cond: JumpLessThan, Val: 42, SkipTrue: 7},
+ assembler: "jlt #42,7",
+ },
+ {
+ instruction: JumpIf{Cond: JumpLessOrEqual, Val: 42, SkipTrue: 6},
+ assembler: "jle #42,6",
+ },
+ {
+ instruction: JumpIf{Cond: JumpGreaterThan, Val: 42, SkipTrue: 4, SkipFalse: 5},
+ assembler: "jgt #42,4,5",
+ },
+ {
+ instruction: JumpIf{Cond: JumpGreaterThan, Val: 42, SkipTrue: 4},
+ assembler: "jgt #42,4",
+ },
+ {
+ instruction: JumpIf{Cond: JumpGreaterOrEqual, Val: 42, SkipTrue: 3, SkipFalse: 4},
+ assembler: "jge #42,3,4",
+ },
+ {
+ instruction: JumpIf{Cond: JumpGreaterOrEqual, Val: 42, SkipTrue: 3},
+ assembler: "jge #42,3",
+ },
+ {
+ instruction: JumpIf{Cond: JumpBitsSet, Val: 42, SkipTrue: 2, SkipFalse: 3},
+ assembler: "jset #42,2,3",
+ },
+ {
+ instruction: JumpIf{Cond: JumpBitsSet, Val: 42, SkipTrue: 2},
+ assembler: "jset #42,2",
+ },
+ {
+ instruction: JumpIf{Cond: JumpBitsNotSet, Val: 42, SkipTrue: 2, SkipFalse: 3},
+ assembler: "jset #42,3,2",
+ },
+ {
+ instruction: JumpIf{Cond: JumpBitsNotSet, Val: 42, SkipTrue: 2},
+ assembler: "jset #42,0,2",
+ },
+ {
+ instruction: JumpIf{Cond: 0xffff, Val: 42, SkipTrue: 1, SkipFalse: 2},
+ assembler: "unknown instruction: bpf.JumpIf{Cond:0xffff, Val:0x2a, SkipTrue:0x1, SkipFalse:0x2}",
+ },
+ {
+ instruction: TAX{},
+ assembler: "tax",
+ },
+ {
+ instruction: TXA{},
+ assembler: "txa",
+ },
+ {
+ instruction: RetA{},
+ assembler: "ret a",
+ },
+ {
+ instruction: RetConstant{Val: 42},
+ assembler: "ret #42",
+ },
+ // Invalid instruction
+ {
+ instruction: InvalidInstruction{},
+ assembler: "unknown instruction: bpf.InvalidInstruction{}",
+ },
+ }
+
+ for _, testCase := range testCases {
+ if input, ok := testCase.instruction.(fmt.Stringer); ok {
+ got := input.String()
+ if got != testCase.assembler {
+ t.Errorf("String did not return expected assembler notation, expected: %s, got: %s", testCase.assembler, got)
+ }
+ } else {
+ t.Errorf("Instruction %#v is not a fmt.Stringer", testCase.instruction)
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/setter.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/setter.go
new file mode 100644
index 000000000..43e35f0ac
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/setter.go
@@ -0,0 +1,10 @@
+// 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 bpf
+
+// A Setter is a type which can attach a compiled BPF filter to itself.
+type Setter interface {
+ SetBPF(filter []RawInstruction) error
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/testdata/all_instructions.bpf b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/testdata/all_instructions.bpf
new file mode 100644
index 000000000..f87144064
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/testdata/all_instructions.bpf
@@ -0,0 +1 @@
+50,0 0 0 42,1 0 0 42,96 0 0 3,97 0 0 3,48 0 0 42,40 0 0 42,32 0 0 42,80 0 0 42,72 0 0 42,64 0 0 42,177 0 0 42,128 0 0 0,32 0 0 4294963200,32 0 0 4294963204,32 0 0 4294963256,2 0 0 3,3 0 0 3,4 0 0 42,20 0 0 42,36 0 0 42,52 0 0 42,68 0 0 42,84 0 0 42,100 0 0 42,116 0 0 42,148 0 0 42,164 0 0 42,12 0 0 0,28 0 0 0,44 0 0 0,60 0 0 0,76 0 0 0,92 0 0 0,108 0 0 0,124 0 0 0,156 0 0 0,172 0 0 0,132 0 0 0,5 0 0 10,21 8 9 42,21 0 8 42,53 0 7 42,37 0 6 42,37 4 5 42,53 3 4 42,69 2 3 42,7 0 0 0,135 0 0 0,22 0 0 0,6 0 0 0,
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/testdata/all_instructions.txt b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/testdata/all_instructions.txt
new file mode 100644
index 000000000..304550155
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/testdata/all_instructions.txt
@@ -0,0 +1,79 @@
+# This filter is compiled to all_instructions.bpf by the `bpf_asm`
+# tool, which can be found in the linux kernel source tree under
+# tools/net.
+
+# Load immediate
+ld #42
+ldx #42
+
+# Load scratch
+ld M[3]
+ldx M[3]
+
+# Load absolute
+ldb [42]
+ldh [42]
+ld [42]
+
+# Load indirect
+ldb [x + 42]
+ldh [x + 42]
+ld [x + 42]
+
+# Load IPv4 header length
+ldx 4*([42]&0xf)
+
+# Run extension function
+ld #len
+ld #proto
+ld #type
+ld #rand
+
+# Store scratch
+st M[3]
+stx M[3]
+
+# A <op> constant
+add #42
+sub #42
+mul #42
+div #42
+or #42
+and #42
+lsh #42
+rsh #42
+mod #42
+xor #42
+
+# A <op> X
+add x
+sub x
+mul x
+div x
+or x
+and x
+lsh x
+rsh x
+mod x
+xor x
+
+# !A
+neg
+
+# Jumps
+ja end
+jeq #42,prev,end
+jne #42,end
+jlt #42,end
+jle #42,end
+jgt #42,prev,end
+jge #42,prev,end
+jset #42,prev,end
+
+# Register transfers
+tax
+txa
+
+# Returns
+prev: ret a
+end: ret #42
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/vm.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/vm.go
new file mode 100644
index 000000000..4c656f1e1
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/vm.go
@@ -0,0 +1,140 @@
+// 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.
+
+package bpf
+
+import (
+ "errors"
+ "fmt"
+)
+
+// A VM is an emulated BPF virtual machine.
+type VM struct {
+ filter []Instruction
+}
+
+// NewVM returns a new VM using the input BPF program.
+func NewVM(filter []Instruction) (*VM, error) {
+ if len(filter) == 0 {
+ return nil, errors.New("one or more Instructions must be specified")
+ }
+
+ for i, ins := range filter {
+ check := len(filter) - (i + 1)
+ switch ins := ins.(type) {
+ // Check for out-of-bounds jumps in instructions
+ case Jump:
+ if check <= int(ins.Skip) {
+ return nil, fmt.Errorf("cannot jump %d instructions; jumping past program bounds", ins.Skip)
+ }
+ case JumpIf:
+ if check <= int(ins.SkipTrue) {
+ return nil, fmt.Errorf("cannot jump %d instructions in true case; jumping past program bounds", ins.SkipTrue)
+ }
+ if check <= int(ins.SkipFalse) {
+ return nil, fmt.Errorf("cannot jump %d instructions in false case; jumping past program bounds", ins.SkipFalse)
+ }
+ // Check for division or modulus by zero
+ case ALUOpConstant:
+ if ins.Val != 0 {
+ break
+ }
+
+ switch ins.Op {
+ case ALUOpDiv, ALUOpMod:
+ return nil, errors.New("cannot divide by zero using ALUOpConstant")
+ }
+ // Check for unknown extensions
+ case LoadExtension:
+ switch ins.Num {
+ case ExtLen:
+ default:
+ return nil, fmt.Errorf("extension %d not implemented", ins.Num)
+ }
+ }
+ }
+
+ // Make sure last instruction is a return instruction
+ switch filter[len(filter)-1].(type) {
+ case RetA, RetConstant:
+ default:
+ return nil, errors.New("BPF program must end with RetA or RetConstant")
+ }
+
+ // Though our VM works using disassembled instructions, we
+ // attempt to assemble the input filter anyway to ensure it is compatible
+ // with an operating system VM.
+ _, err := Assemble(filter)
+
+ return &VM{
+ filter: filter,
+ }, err
+}
+
+// Run runs the VM's BPF program against the input bytes.
+// Run returns the number of bytes accepted by the BPF program, and any errors
+// which occurred while processing the program.
+func (v *VM) Run(in []byte) (int, error) {
+ var (
+ // Registers of the virtual machine
+ regA uint32
+ regX uint32
+ regScratch [16]uint32
+
+ // OK is true if the program should continue processing the next
+ // instruction, or false if not, causing the loop to break
+ ok = true
+ )
+
+ // TODO(mdlayher): implement:
+ // - NegateA:
+ // - would require a change from uint32 registers to int32
+ // registers
+
+ // TODO(mdlayher): add interop tests that check signedness of ALU
+ // operations against kernel implementation, and make sure Go
+ // implementation matches behavior
+
+ for i := 0; i < len(v.filter) && ok; i++ {
+ ins := v.filter[i]
+
+ switch ins := ins.(type) {
+ case ALUOpConstant:
+ regA = aluOpConstant(ins, regA)
+ case ALUOpX:
+ regA, ok = aluOpX(ins, regA, regX)
+ case Jump:
+ i += int(ins.Skip)
+ case JumpIf:
+ jump := jumpIf(ins, regA)
+ i += jump
+ case LoadAbsolute:
+ regA, ok = loadAbsolute(ins, in)
+ case LoadConstant:
+ regA, regX = loadConstant(ins, regA, regX)
+ case LoadExtension:
+ regA = loadExtension(ins, in)
+ case LoadIndirect:
+ regA, ok = loadIndirect(ins, in, regX)
+ case LoadMemShift:
+ regX, ok = loadMemShift(ins, in)
+ case LoadScratch:
+ regA, regX = loadScratch(ins, regScratch, regA, regX)
+ case RetA:
+ return int(regA), nil
+ case RetConstant:
+ return int(ins.Val), nil
+ case StoreScratch:
+ regScratch = storeScratch(ins, regScratch, regA, regX)
+ case TAX:
+ regX = regA
+ case TXA:
+ regA = regX
+ default:
+ return 0, fmt.Errorf("unknown Instruction at index %d: %T", i, ins)
+ }
+ }
+
+ return 0, nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/vm_aluop_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/vm_aluop_test.go
new file mode 100644
index 000000000..16678244a
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/vm_aluop_test.go
@@ -0,0 +1,512 @@
+// 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.
+
+package bpf_test
+
+import (
+ "testing"
+
+ "golang.org/x/net/bpf"
+)
+
+func TestVMALUOpAdd(t *testing.T) {
+ vm, done, err := testVM(t, []bpf.Instruction{
+ bpf.LoadAbsolute{
+ Off: 8,
+ Size: 1,
+ },
+ bpf.ALUOpConstant{
+ Op: bpf.ALUOpAdd,
+ Val: 3,
+ },
+ bpf.RetA{},
+ })
+ if err != nil {
+ t.Fatalf("failed to load BPF program: %v", err)
+ }
+ defer done()
+
+ out, err := vm.Run([]byte{
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 8, 2, 3,
+ })
+ if err != nil {
+ t.Fatalf("unexpected error while running program: %v", err)
+ }
+ if want, got := 3, out; want != got {
+ t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
+ want, got)
+ }
+}
+
+func TestVMALUOpSub(t *testing.T) {
+ vm, done, err := testVM(t, []bpf.Instruction{
+ bpf.LoadAbsolute{
+ Off: 8,
+ Size: 1,
+ },
+ bpf.TAX{},
+ bpf.ALUOpX{
+ Op: bpf.ALUOpSub,
+ },
+ bpf.RetA{},
+ })
+ if err != nil {
+ t.Fatalf("failed to load BPF program: %v", err)
+ }
+ defer done()
+
+ out, err := vm.Run([]byte{
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 1, 2, 3,
+ })
+ if err != nil {
+ t.Fatalf("unexpected error while running program: %v", err)
+ }
+ if want, got := 0, out; want != got {
+ t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
+ want, got)
+ }
+}
+
+func TestVMALUOpMul(t *testing.T) {
+ vm, done, err := testVM(t, []bpf.Instruction{
+ bpf.LoadAbsolute{
+ Off: 8,
+ Size: 1,
+ },
+ bpf.ALUOpConstant{
+ Op: bpf.ALUOpMul,
+ Val: 2,
+ },
+ bpf.RetA{},
+ })
+ if err != nil {
+ t.Fatalf("failed to load BPF program: %v", err)
+ }
+ defer done()
+
+ out, err := vm.Run([]byte{
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 6, 2, 3, 4,
+ })
+ if err != nil {
+ t.Fatalf("unexpected error while running program: %v", err)
+ }
+ if want, got := 4, out; want != got {
+ t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
+ want, got)
+ }
+}
+
+func TestVMALUOpDiv(t *testing.T) {
+ vm, done, err := testVM(t, []bpf.Instruction{
+ bpf.LoadAbsolute{
+ Off: 8,
+ Size: 1,
+ },
+ bpf.ALUOpConstant{
+ Op: bpf.ALUOpDiv,
+ Val: 2,
+ },
+ bpf.RetA{},
+ })
+ if err != nil {
+ t.Fatalf("failed to load BPF program: %v", err)
+ }
+ defer done()
+
+ out, err := vm.Run([]byte{
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 20, 2, 3, 4,
+ })
+ if err != nil {
+ t.Fatalf("unexpected error while running program: %v", err)
+ }
+ if want, got := 2, out; want != got {
+ t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
+ want, got)
+ }
+}
+
+func TestVMALUOpDivByZeroALUOpConstant(t *testing.T) {
+ _, _, err := testVM(t, []bpf.Instruction{
+ bpf.ALUOpConstant{
+ Op: bpf.ALUOpDiv,
+ Val: 0,
+ },
+ bpf.RetA{},
+ })
+ if errStr(err) != "cannot divide by zero using ALUOpConstant" {
+ t.Fatalf("unexpected error: %v", err)
+ }
+}
+
+func TestVMALUOpDivByZeroALUOpX(t *testing.T) {
+ vm, done, err := testVM(t, []bpf.Instruction{
+ // Load byte 0 into X
+ bpf.LoadAbsolute{
+ Off: 8,
+ Size: 1,
+ },
+ bpf.TAX{},
+ // Load byte 1 into A
+ bpf.LoadAbsolute{
+ Off: 9,
+ Size: 1,
+ },
+ // Attempt to perform 1/0
+ bpf.ALUOpX{
+ Op: bpf.ALUOpDiv,
+ },
+ // Return 4 bytes if program does not terminate
+ bpf.LoadConstant{
+ Val: 12,
+ },
+ bpf.RetA{},
+ })
+ if err != nil {
+ t.Fatalf("failed to load BPF program: %v", err)
+ }
+ defer done()
+
+ out, err := vm.Run([]byte{
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0, 1, 3, 4,
+ })
+ if err != nil {
+ t.Fatalf("unexpected error while running program: %v", err)
+ }
+ if want, got := 0, out; want != got {
+ t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
+ want, got)
+ }
+}
+
+func TestVMALUOpOr(t *testing.T) {
+ vm, done, err := testVM(t, []bpf.Instruction{
+ bpf.LoadAbsolute{
+ Off: 8,
+ Size: 2,
+ },
+ bpf.ALUOpConstant{
+ Op: bpf.ALUOpOr,
+ Val: 0x01,
+ },
+ bpf.RetA{},
+ })
+ if err != nil {
+ t.Fatalf("failed to load BPF program: %v", err)
+ }
+ defer done()
+
+ out, err := vm.Run([]byte{
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x10, 0x03, 0x04,
+ 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0xff,
+ })
+ if err != nil {
+ t.Fatalf("unexpected error while running program: %v", err)
+ }
+ if want, got := 9, out; want != got {
+ t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
+ want, got)
+ }
+}
+
+func TestVMALUOpAnd(t *testing.T) {
+ vm, done, err := testVM(t, []bpf.Instruction{
+ bpf.LoadAbsolute{
+ Off: 8,
+ Size: 2,
+ },
+ bpf.ALUOpConstant{
+ Op: bpf.ALUOpAnd,
+ Val: 0x0019,
+ },
+ bpf.RetA{},
+ })
+ if err != nil {
+ t.Fatalf("failed to load BPF program: %v", err)
+ }
+ defer done()
+
+ out, err := vm.Run([]byte{
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0xaa, 0x09,
+ })
+ if err != nil {
+ t.Fatalf("unexpected error while running program: %v", err)
+ }
+ if want, got := 1, out; want != got {
+ t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
+ want, got)
+ }
+}
+
+func TestVMALUOpShiftLeft(t *testing.T) {
+ vm, done, err := testVM(t, []bpf.Instruction{
+ bpf.LoadAbsolute{
+ Off: 8,
+ Size: 1,
+ },
+ bpf.ALUOpConstant{
+ Op: bpf.ALUOpShiftLeft,
+ Val: 0x01,
+ },
+ bpf.JumpIf{
+ Cond: bpf.JumpEqual,
+ Val: 0x02,
+ SkipTrue: 1,
+ },
+ bpf.RetConstant{
+ Val: 0,
+ },
+ bpf.RetConstant{
+ Val: 9,
+ },
+ })
+ if err != nil {
+ t.Fatalf("failed to load BPF program: %v", err)
+ }
+ defer done()
+
+ out, err := vm.Run([]byte{
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0x01, 0xaa,
+ })
+ if err != nil {
+ t.Fatalf("unexpected error while running program: %v", err)
+ }
+ if want, got := 1, out; want != got {
+ t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
+ want, got)
+ }
+}
+
+func TestVMALUOpShiftRight(t *testing.T) {
+ vm, done, err := testVM(t, []bpf.Instruction{
+ bpf.LoadAbsolute{
+ Off: 8,
+ Size: 1,
+ },
+ bpf.ALUOpConstant{
+ Op: bpf.ALUOpShiftRight,
+ Val: 0x01,
+ },
+ bpf.JumpIf{
+ Cond: bpf.JumpEqual,
+ Val: 0x04,
+ SkipTrue: 1,
+ },
+ bpf.RetConstant{
+ Val: 0,
+ },
+ bpf.RetConstant{
+ Val: 9,
+ },
+ })
+ if err != nil {
+ t.Fatalf("failed to load BPF program: %v", err)
+ }
+ defer done()
+
+ out, err := vm.Run([]byte{
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0x08, 0xff, 0xff,
+ })
+ if err != nil {
+ t.Fatalf("unexpected error while running program: %v", err)
+ }
+ if want, got := 1, out; want != got {
+ t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
+ want, got)
+ }
+}
+
+func TestVMALUOpMod(t *testing.T) {
+ vm, done, err := testVM(t, []bpf.Instruction{
+ bpf.LoadAbsolute{
+ Off: 8,
+ Size: 1,
+ },
+ bpf.ALUOpConstant{
+ Op: bpf.ALUOpMod,
+ Val: 20,
+ },
+ bpf.RetA{},
+ })
+ if err != nil {
+ t.Fatalf("failed to load BPF program: %v", err)
+ }
+ defer done()
+
+ out, err := vm.Run([]byte{
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 30, 0, 0,
+ })
+ if err != nil {
+ t.Fatalf("unexpected error while running program: %v", err)
+ }
+ if want, got := 2, out; want != got {
+ t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
+ want, got)
+ }
+}
+
+func TestVMALUOpModByZeroALUOpConstant(t *testing.T) {
+ _, _, err := testVM(t, []bpf.Instruction{
+ bpf.LoadAbsolute{
+ Off: 8,
+ Size: 1,
+ },
+ bpf.ALUOpConstant{
+ Op: bpf.ALUOpMod,
+ Val: 0,
+ },
+ bpf.RetA{},
+ })
+ if errStr(err) != "cannot divide by zero using ALUOpConstant" {
+ t.Fatalf("unexpected error: %v", err)
+ }
+}
+
+func TestVMALUOpModByZeroALUOpX(t *testing.T) {
+ vm, done, err := testVM(t, []bpf.Instruction{
+ // Load byte 0 into X
+ bpf.LoadAbsolute{
+ Off: 8,
+ Size: 1,
+ },
+ bpf.TAX{},
+ // Load byte 1 into A
+ bpf.LoadAbsolute{
+ Off: 9,
+ Size: 1,
+ },
+ // Attempt to perform 1%0
+ bpf.ALUOpX{
+ Op: bpf.ALUOpMod,
+ },
+ // Return 4 bytes if program does not terminate
+ bpf.LoadConstant{
+ Val: 12,
+ },
+ bpf.RetA{},
+ })
+ if err != nil {
+ t.Fatalf("failed to load BPF program: %v", err)
+ }
+ defer done()
+
+ out, err := vm.Run([]byte{
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0, 1, 3, 4,
+ })
+ if err != nil {
+ t.Fatalf("unexpected error while running program: %v", err)
+ }
+ if want, got := 0, out; want != got {
+ t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
+ want, got)
+ }
+}
+
+func TestVMALUOpXor(t *testing.T) {
+ vm, done, err := testVM(t, []bpf.Instruction{
+ bpf.LoadAbsolute{
+ Off: 8,
+ Size: 1,
+ },
+ bpf.ALUOpConstant{
+ Op: bpf.ALUOpXor,
+ Val: 0x0a,
+ },
+ bpf.JumpIf{
+ Cond: bpf.JumpEqual,
+ Val: 0x01,
+ SkipTrue: 1,
+ },
+ bpf.RetConstant{
+ Val: 0,
+ },
+ bpf.RetConstant{
+ Val: 9,
+ },
+ })
+ if err != nil {
+ t.Fatalf("failed to load BPF program: %v", err)
+ }
+ defer done()
+
+ out, err := vm.Run([]byte{
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0x0b, 0x00, 0x00, 0x00,
+ })
+ if err != nil {
+ t.Fatalf("unexpected error while running program: %v", err)
+ }
+ if want, got := 1, out; want != got {
+ t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
+ want, got)
+ }
+}
+
+func TestVMALUOpUnknown(t *testing.T) {
+ vm, done, err := testVM(t, []bpf.Instruction{
+ bpf.LoadAbsolute{
+ Off: 8,
+ Size: 1,
+ },
+ bpf.ALUOpConstant{
+ Op: bpf.ALUOpAdd,
+ Val: 1,
+ },
+ // Verify that an unknown operation is a no-op
+ bpf.ALUOpConstant{
+ Op: 100,
+ },
+ bpf.JumpIf{
+ Cond: bpf.JumpEqual,
+ Val: 0x02,
+ SkipTrue: 1,
+ },
+ bpf.RetConstant{
+ Val: 0,
+ },
+ bpf.RetConstant{
+ Val: 9,
+ },
+ })
+ if err != nil {
+ t.Fatalf("failed to load BPF program: %v", err)
+ }
+ defer done()
+
+ out, err := vm.Run([]byte{
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 1,
+ })
+ if err != nil {
+ t.Fatalf("unexpected error while running program: %v", err)
+ }
+ if want, got := 1, out; want != got {
+ t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
+ want, got)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/vm_bpf_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/vm_bpf_test.go
new file mode 100644
index 000000000..77fa8fe4a
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/vm_bpf_test.go
@@ -0,0 +1,192 @@
+// 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.
+
+package bpf_test
+
+import (
+ "net"
+ "runtime"
+ "testing"
+ "time"
+
+ "golang.org/x/net/bpf"
+ "golang.org/x/net/ipv4"
+)
+
+// A virtualMachine is a BPF virtual machine which can process an
+// input packet against a BPF program and render a verdict.
+type virtualMachine interface {
+ Run(in []byte) (int, error)
+}
+
+// canUseOSVM indicates if the OS BPF VM is available on this platform.
+func canUseOSVM() bool {
+ // OS BPF VM can only be used on platforms where x/net/ipv4 supports
+ // attaching a BPF program to a socket.
+ switch runtime.GOOS {
+ case "linux":
+ return true
+ }
+
+ return false
+}
+
+// All BPF tests against both the Go VM and OS VM are assumed to
+// be used with a UDP socket. As a result, the entire contents
+// of a UDP datagram is sent through the BPF program, but only
+// the body after the UDP header will ever be returned in output.
+
+// testVM sets up a Go BPF VM, and if available, a native OS BPF VM
+// for integration testing.
+func testVM(t *testing.T, filter []bpf.Instruction) (virtualMachine, func(), error) {
+ goVM, err := bpf.NewVM(filter)
+ if err != nil {
+ // Some tests expect an error, so this error must be returned
+ // instead of fatally exiting the test
+ return nil, nil, err
+ }
+
+ mvm := &multiVirtualMachine{
+ goVM: goVM,
+
+ t: t,
+ }
+
+ // If available, add the OS VM for tests which verify that both the Go
+ // VM and OS VM have exactly the same output for the same input program
+ // and packet.
+ done := func() {}
+ if canUseOSVM() {
+ osVM, osVMDone := testOSVM(t, filter)
+ done = func() { osVMDone() }
+ mvm.osVM = osVM
+ }
+
+ return mvm, done, nil
+}
+
+// udpHeaderLen is the length of a UDP header.
+const udpHeaderLen = 8
+
+// A multiVirtualMachine is a virtualMachine which can call out to both the Go VM
+// and the native OS VM, if the OS VM is available.
+type multiVirtualMachine struct {
+ goVM virtualMachine
+ osVM virtualMachine
+
+ t *testing.T
+}
+
+func (mvm *multiVirtualMachine) Run(in []byte) (int, error) {
+ if len(in) < udpHeaderLen {
+ mvm.t.Fatalf("input must be at least length of UDP header (%d), got: %d",
+ udpHeaderLen, len(in))
+ }
+
+ // All tests have a UDP header as part of input, because the OS VM
+ // packets always will. For the Go VM, this output is trimmed before
+ // being sent back to tests.
+ goOut, goErr := mvm.goVM.Run(in)
+ if goOut >= udpHeaderLen {
+ goOut -= udpHeaderLen
+ }
+
+ // If Go output is larger than the size of the packet, packet filtering
+ // interop tests must trim the output bytes to the length of the packet.
+ // The BPF VM should not do this on its own, as other uses of it do
+ // not trim the output byte count.
+ trim := len(in) - udpHeaderLen
+ if goOut > trim {
+ goOut = trim
+ }
+
+ // When the OS VM is not available, process using the Go VM alone
+ if mvm.osVM == nil {
+ return goOut, goErr
+ }
+
+ // The OS VM will apply its own UDP header, so remove the pseudo header
+ // that the Go VM needs.
+ osOut, err := mvm.osVM.Run(in[udpHeaderLen:])
+ if err != nil {
+ mvm.t.Fatalf("error while running OS VM: %v", err)
+ }
+
+ // Verify both VMs return same number of bytes
+ var mismatch bool
+ if goOut != osOut {
+ mismatch = true
+ mvm.t.Logf("output byte count does not match:\n- go: %v\n- os: %v", goOut, osOut)
+ }
+
+ if mismatch {
+ mvm.t.Fatal("Go BPF and OS BPF packet outputs do not match")
+ }
+
+ return goOut, goErr
+}
+
+// An osVirtualMachine is a virtualMachine which uses the OS's BPF VM for
+// processing BPF programs.
+type osVirtualMachine struct {
+ l net.PacketConn
+ s net.Conn
+}
+
+// testOSVM creates a virtualMachine which uses the OS's BPF VM by injecting
+// packets into a UDP listener with a BPF program attached to it.
+func testOSVM(t *testing.T, filter []bpf.Instruction) (virtualMachine, func()) {
+ l, err := net.ListenPacket("udp4", "127.0.0.1:0")
+ if err != nil {
+ t.Fatalf("failed to open OS VM UDP listener: %v", err)
+ }
+
+ prog, err := bpf.Assemble(filter)
+ if err != nil {
+ t.Fatalf("failed to compile BPF program: %v", err)
+ }
+
+ p := ipv4.NewPacketConn(l)
+ if err = p.SetBPF(prog); err != nil {
+ t.Fatalf("failed to attach BPF program to listener: %v", err)
+ }
+
+ s, err := net.Dial("udp4", l.LocalAddr().String())
+ if err != nil {
+ t.Fatalf("failed to dial connection to listener: %v", err)
+ }
+
+ done := func() {
+ _ = s.Close()
+ _ = l.Close()
+ }
+
+ return &osVirtualMachine{
+ l: l,
+ s: s,
+ }, done
+}
+
+// Run sends the input bytes into the OS's BPF VM and returns its verdict.
+func (vm *osVirtualMachine) Run(in []byte) (int, error) {
+ go func() {
+ _, _ = vm.s.Write(in)
+ }()
+
+ vm.l.SetDeadline(time.Now().Add(50 * time.Millisecond))
+
+ var b [512]byte
+ n, _, err := vm.l.ReadFrom(b[:])
+ if err != nil {
+ // A timeout indicates that BPF filtered out the packet, and thus,
+ // no input should be returned.
+ if nerr, ok := err.(net.Error); ok && nerr.Timeout() {
+ return n, nil
+ }
+
+ return n, err
+ }
+
+ return n, nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/vm_extension_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/vm_extension_test.go
new file mode 100644
index 000000000..7a48c82f3
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/vm_extension_test.go
@@ -0,0 +1,49 @@
+// 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.
+
+package bpf_test
+
+import (
+ "testing"
+
+ "golang.org/x/net/bpf"
+)
+
+func TestVMLoadExtensionNotImplemented(t *testing.T) {
+ _, _, err := testVM(t, []bpf.Instruction{
+ bpf.LoadExtension{
+ Num: 100,
+ },
+ bpf.RetA{},
+ })
+ if errStr(err) != "extension 100 not implemented" {
+ t.Fatalf("unexpected error: %v", err)
+ }
+}
+
+func TestVMLoadExtensionExtLen(t *testing.T) {
+ vm, done, err := testVM(t, []bpf.Instruction{
+ bpf.LoadExtension{
+ Num: bpf.ExtLen,
+ },
+ bpf.RetA{},
+ })
+ if err != nil {
+ t.Fatalf("failed to load BPF program: %v", err)
+ }
+ defer done()
+
+ out, err := vm.Run([]byte{
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0, 1, 2, 3,
+ })
+ if err != nil {
+ t.Fatalf("unexpected error while running program: %v", err)
+ }
+ if want, got := 4, out; want != got {
+ t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
+ want, got)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/vm_instructions.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/vm_instructions.go
new file mode 100644
index 000000000..516f9462b
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/vm_instructions.go
@@ -0,0 +1,174 @@
+// 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.
+
+package bpf
+
+import (
+ "encoding/binary"
+ "fmt"
+)
+
+func aluOpConstant(ins ALUOpConstant, regA uint32) uint32 {
+ return aluOpCommon(ins.Op, regA, ins.Val)
+}
+
+func aluOpX(ins ALUOpX, regA uint32, regX uint32) (uint32, bool) {
+ // Guard against division or modulus by zero by terminating
+ // the program, as the OS BPF VM does
+ if regX == 0 {
+ switch ins.Op {
+ case ALUOpDiv, ALUOpMod:
+ return 0, false
+ }
+ }
+
+ return aluOpCommon(ins.Op, regA, regX), true
+}
+
+func aluOpCommon(op ALUOp, regA uint32, value uint32) uint32 {
+ switch op {
+ case ALUOpAdd:
+ return regA + value
+ case ALUOpSub:
+ return regA - value
+ case ALUOpMul:
+ return regA * value
+ case ALUOpDiv:
+ // Division by zero not permitted by NewVM and aluOpX checks
+ return regA / value
+ case ALUOpOr:
+ return regA | value
+ case ALUOpAnd:
+ return regA & value
+ case ALUOpShiftLeft:
+ return regA << value
+ case ALUOpShiftRight:
+ return regA >> value
+ case ALUOpMod:
+ // Modulus by zero not permitted by NewVM and aluOpX checks
+ return regA % value
+ case ALUOpXor:
+ return regA ^ value
+ default:
+ return regA
+ }
+}
+
+func jumpIf(ins JumpIf, value uint32) int {
+ var ok bool
+ inV := uint32(ins.Val)
+
+ switch ins.Cond {
+ case JumpEqual:
+ ok = value == inV
+ case JumpNotEqual:
+ ok = value != inV
+ case JumpGreaterThan:
+ ok = value > inV
+ case JumpLessThan:
+ ok = value < inV
+ case JumpGreaterOrEqual:
+ ok = value >= inV
+ case JumpLessOrEqual:
+ ok = value <= inV
+ case JumpBitsSet:
+ ok = (value & inV) != 0
+ case JumpBitsNotSet:
+ ok = (value & inV) == 0
+ }
+
+ if ok {
+ return int(ins.SkipTrue)
+ }
+
+ return int(ins.SkipFalse)
+}
+
+func loadAbsolute(ins LoadAbsolute, in []byte) (uint32, bool) {
+ offset := int(ins.Off)
+ size := int(ins.Size)
+
+ return loadCommon(in, offset, size)
+}
+
+func loadConstant(ins LoadConstant, regA uint32, regX uint32) (uint32, uint32) {
+ switch ins.Dst {
+ case RegA:
+ regA = ins.Val
+ case RegX:
+ regX = ins.Val
+ }
+
+ return regA, regX
+}
+
+func loadExtension(ins LoadExtension, in []byte) uint32 {
+ switch ins.Num {
+ case ExtLen:
+ return uint32(len(in))
+ default:
+ panic(fmt.Sprintf("unimplemented extension: %d", ins.Num))
+ }
+}
+
+func loadIndirect(ins LoadIndirect, in []byte, regX uint32) (uint32, bool) {
+ offset := int(ins.Off) + int(regX)
+ size := int(ins.Size)
+
+ return loadCommon(in, offset, size)
+}
+
+func loadMemShift(ins LoadMemShift, in []byte) (uint32, bool) {
+ offset := int(ins.Off)
+
+ if !inBounds(len(in), offset, 0) {
+ return 0, false
+ }
+
+ // Mask off high 4 bits and multiply low 4 bits by 4
+ return uint32(in[offset]&0x0f) * 4, true
+}
+
+func inBounds(inLen int, offset int, size int) bool {
+ return offset+size <= inLen
+}
+
+func loadCommon(in []byte, offset int, size int) (uint32, bool) {
+ if !inBounds(len(in), offset, size) {
+ return 0, false
+ }
+
+ switch size {
+ case 1:
+ return uint32(in[offset]), true
+ case 2:
+ return uint32(binary.BigEndian.Uint16(in[offset : offset+size])), true
+ case 4:
+ return uint32(binary.BigEndian.Uint32(in[offset : offset+size])), true
+ default:
+ panic(fmt.Sprintf("invalid load size: %d", size))
+ }
+}
+
+func loadScratch(ins LoadScratch, regScratch [16]uint32, regA uint32, regX uint32) (uint32, uint32) {
+ switch ins.Dst {
+ case RegA:
+ regA = regScratch[ins.N]
+ case RegX:
+ regX = regScratch[ins.N]
+ }
+
+ return regA, regX
+}
+
+func storeScratch(ins StoreScratch, regScratch [16]uint32, regA uint32, regX uint32) [16]uint32 {
+ switch ins.Src {
+ case RegA:
+ regScratch[ins.N] = regA
+ case RegX:
+ regScratch[ins.N] = regX
+ }
+
+ return regScratch
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/vm_jump_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/vm_jump_test.go
new file mode 100644
index 000000000..e0a3a988b
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/vm_jump_test.go
@@ -0,0 +1,380 @@
+// 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.
+
+package bpf_test
+
+import (
+ "testing"
+
+ "golang.org/x/net/bpf"
+)
+
+func TestVMJumpOne(t *testing.T) {
+ vm, done, err := testVM(t, []bpf.Instruction{
+ bpf.LoadAbsolute{
+ Off: 8,
+ Size: 1,
+ },
+ bpf.Jump{
+ Skip: 1,
+ },
+ bpf.RetConstant{
+ Val: 0,
+ },
+ bpf.RetConstant{
+ Val: 9,
+ },
+ })
+ if err != nil {
+ t.Fatalf("failed to load BPF program: %v", err)
+ }
+ defer done()
+
+ out, err := vm.Run([]byte{
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 1,
+ })
+ if err != nil {
+ t.Fatalf("unexpected error while running program: %v", err)
+ }
+ if want, got := 1, out; want != got {
+ t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
+ want, got)
+ }
+}
+
+func TestVMJumpOutOfProgram(t *testing.T) {
+ _, _, err := testVM(t, []bpf.Instruction{
+ bpf.Jump{
+ Skip: 1,
+ },
+ bpf.RetA{},
+ })
+ if errStr(err) != "cannot jump 1 instructions; jumping past program bounds" {
+ t.Fatalf("unexpected error: %v", err)
+ }
+}
+
+func TestVMJumpIfTrueOutOfProgram(t *testing.T) {
+ _, _, err := testVM(t, []bpf.Instruction{
+ bpf.JumpIf{
+ Cond: bpf.JumpEqual,
+ SkipTrue: 2,
+ },
+ bpf.RetA{},
+ })
+ if errStr(err) != "cannot jump 2 instructions in true case; jumping past program bounds" {
+ t.Fatalf("unexpected error: %v", err)
+ }
+}
+
+func TestVMJumpIfFalseOutOfProgram(t *testing.T) {
+ _, _, err := testVM(t, []bpf.Instruction{
+ bpf.JumpIf{
+ Cond: bpf.JumpEqual,
+ SkipFalse: 3,
+ },
+ bpf.RetA{},
+ })
+ if errStr(err) != "cannot jump 3 instructions in false case; jumping past program bounds" {
+ t.Fatalf("unexpected error: %v", err)
+ }
+}
+
+func TestVMJumpIfEqual(t *testing.T) {
+ vm, done, err := testVM(t, []bpf.Instruction{
+ bpf.LoadAbsolute{
+ Off: 8,
+ Size: 1,
+ },
+ bpf.JumpIf{
+ Cond: bpf.JumpEqual,
+ Val: 1,
+ SkipTrue: 1,
+ },
+ bpf.RetConstant{
+ Val: 0,
+ },
+ bpf.RetConstant{
+ Val: 9,
+ },
+ })
+ if err != nil {
+ t.Fatalf("failed to load BPF program: %v", err)
+ }
+ defer done()
+
+ out, err := vm.Run([]byte{
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 1,
+ })
+ if err != nil {
+ t.Fatalf("unexpected error while running program: %v", err)
+ }
+ if want, got := 1, out; want != got {
+ t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
+ want, got)
+ }
+}
+
+func TestVMJumpIfNotEqual(t *testing.T) {
+ vm, done, err := testVM(t, []bpf.Instruction{
+ bpf.LoadAbsolute{
+ Off: 8,
+ Size: 1,
+ },
+ bpf.JumpIf{
+ Cond: bpf.JumpNotEqual,
+ Val: 1,
+ SkipFalse: 1,
+ },
+ bpf.RetConstant{
+ Val: 0,
+ },
+ bpf.RetConstant{
+ Val: 9,
+ },
+ })
+ if err != nil {
+ t.Fatalf("failed to load BPF program: %v", err)
+ }
+ defer done()
+
+ out, err := vm.Run([]byte{
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 1,
+ })
+ if err != nil {
+ t.Fatalf("unexpected error while running program: %v", err)
+ }
+ if want, got := 1, out; want != got {
+ t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
+ want, got)
+ }
+}
+
+func TestVMJumpIfGreaterThan(t *testing.T) {
+ vm, done, err := testVM(t, []bpf.Instruction{
+ bpf.LoadAbsolute{
+ Off: 8,
+ Size: 4,
+ },
+ bpf.JumpIf{
+ Cond: bpf.JumpGreaterThan,
+ Val: 0x00010202,
+ SkipTrue: 1,
+ },
+ bpf.RetConstant{
+ Val: 0,
+ },
+ bpf.RetConstant{
+ Val: 12,
+ },
+ })
+ if err != nil {
+ t.Fatalf("failed to load BPF program: %v", err)
+ }
+ defer done()
+
+ out, err := vm.Run([]byte{
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0, 1, 2, 3,
+ })
+ if err != nil {
+ t.Fatalf("unexpected error while running program: %v", err)
+ }
+ if want, got := 4, out; want != got {
+ t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
+ want, got)
+ }
+}
+
+func TestVMJumpIfLessThan(t *testing.T) {
+ vm, done, err := testVM(t, []bpf.Instruction{
+ bpf.LoadAbsolute{
+ Off: 8,
+ Size: 4,
+ },
+ bpf.JumpIf{
+ Cond: bpf.JumpLessThan,
+ Val: 0xff010203,
+ SkipTrue: 1,
+ },
+ bpf.RetConstant{
+ Val: 0,
+ },
+ bpf.RetConstant{
+ Val: 12,
+ },
+ })
+ if err != nil {
+ t.Fatalf("failed to load BPF program: %v", err)
+ }
+ defer done()
+
+ out, err := vm.Run([]byte{
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0, 1, 2, 3,
+ })
+ if err != nil {
+ t.Fatalf("unexpected error while running program: %v", err)
+ }
+ if want, got := 4, out; want != got {
+ t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
+ want, got)
+ }
+}
+
+func TestVMJumpIfGreaterOrEqual(t *testing.T) {
+ vm, done, err := testVM(t, []bpf.Instruction{
+ bpf.LoadAbsolute{
+ Off: 8,
+ Size: 4,
+ },
+ bpf.JumpIf{
+ Cond: bpf.JumpGreaterOrEqual,
+ Val: 0x00010203,
+ SkipTrue: 1,
+ },
+ bpf.RetConstant{
+ Val: 0,
+ },
+ bpf.RetConstant{
+ Val: 12,
+ },
+ })
+ if err != nil {
+ t.Fatalf("failed to load BPF program: %v", err)
+ }
+ defer done()
+
+ out, err := vm.Run([]byte{
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0, 1, 2, 3,
+ })
+ if err != nil {
+ t.Fatalf("unexpected error while running program: %v", err)
+ }
+ if want, got := 4, out; want != got {
+ t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
+ want, got)
+ }
+}
+
+func TestVMJumpIfLessOrEqual(t *testing.T) {
+ vm, done, err := testVM(t, []bpf.Instruction{
+ bpf.LoadAbsolute{
+ Off: 8,
+ Size: 4,
+ },
+ bpf.JumpIf{
+ Cond: bpf.JumpLessOrEqual,
+ Val: 0xff010203,
+ SkipTrue: 1,
+ },
+ bpf.RetConstant{
+ Val: 0,
+ },
+ bpf.RetConstant{
+ Val: 12,
+ },
+ })
+ if err != nil {
+ t.Fatalf("failed to load BPF program: %v", err)
+ }
+ defer done()
+
+ out, err := vm.Run([]byte{
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0, 1, 2, 3,
+ })
+ if err != nil {
+ t.Fatalf("unexpected error while running program: %v", err)
+ }
+ if want, got := 4, out; want != got {
+ t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
+ want, got)
+ }
+}
+
+func TestVMJumpIfBitsSet(t *testing.T) {
+ vm, done, err := testVM(t, []bpf.Instruction{
+ bpf.LoadAbsolute{
+ Off: 8,
+ Size: 2,
+ },
+ bpf.JumpIf{
+ Cond: bpf.JumpBitsSet,
+ Val: 0x1122,
+ SkipTrue: 1,
+ },
+ bpf.RetConstant{
+ Val: 0,
+ },
+ bpf.RetConstant{
+ Val: 10,
+ },
+ })
+ if err != nil {
+ t.Fatalf("failed to load BPF program: %v", err)
+ }
+ defer done()
+
+ out, err := vm.Run([]byte{
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0x01, 0x02,
+ })
+ if err != nil {
+ t.Fatalf("unexpected error while running program: %v", err)
+ }
+ if want, got := 2, out; want != got {
+ t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
+ want, got)
+ }
+}
+
+func TestVMJumpIfBitsNotSet(t *testing.T) {
+ vm, done, err := testVM(t, []bpf.Instruction{
+ bpf.LoadAbsolute{
+ Off: 8,
+ Size: 2,
+ },
+ bpf.JumpIf{
+ Cond: bpf.JumpBitsNotSet,
+ Val: 0x1221,
+ SkipTrue: 1,
+ },
+ bpf.RetConstant{
+ Val: 0,
+ },
+ bpf.RetConstant{
+ Val: 10,
+ },
+ })
+ if err != nil {
+ t.Fatalf("failed to load BPF program: %v", err)
+ }
+ defer done()
+
+ out, err := vm.Run([]byte{
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0x01, 0x02,
+ })
+ if err != nil {
+ t.Fatalf("unexpected error while running program: %v", err)
+ }
+ if want, got := 2, out; want != got {
+ t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
+ want, got)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/vm_load_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/vm_load_test.go
new file mode 100644
index 000000000..04578b66b
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/vm_load_test.go
@@ -0,0 +1,246 @@
+// 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.
+
+package bpf_test
+
+import (
+ "net"
+ "testing"
+
+ "golang.org/x/net/bpf"
+ "golang.org/x/net/ipv4"
+)
+
+func TestVMLoadAbsoluteOffsetOutOfBounds(t *testing.T) {
+ vm, done, err := testVM(t, []bpf.Instruction{
+ bpf.LoadAbsolute{
+ Off: 100,
+ Size: 2,
+ },
+ bpf.RetA{},
+ })
+ if err != nil {
+ t.Fatalf("failed to load BPF program: %v", err)
+ }
+ defer done()
+
+ out, err := vm.Run([]byte{
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0, 1, 2, 3,
+ })
+ if err != nil {
+ t.Fatalf("unexpected error while running program: %v", err)
+ }
+ if want, got := 0, out; want != got {
+ t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
+ want, got)
+ }
+}
+
+func TestVMLoadAbsoluteOffsetPlusSizeOutOfBounds(t *testing.T) {
+ vm, done, err := testVM(t, []bpf.Instruction{
+ bpf.LoadAbsolute{
+ Off: 8,
+ Size: 2,
+ },
+ bpf.RetA{},
+ })
+ if err != nil {
+ t.Fatalf("failed to load BPF program: %v", err)
+ }
+ defer done()
+
+ out, err := vm.Run([]byte{
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0,
+ })
+ if err != nil {
+ t.Fatalf("unexpected error while running program: %v", err)
+ }
+ if want, got := 0, out; want != got {
+ t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
+ want, got)
+ }
+}
+
+func TestVMLoadAbsoluteBadInstructionSize(t *testing.T) {
+ _, _, err := testVM(t, []bpf.Instruction{
+ bpf.LoadAbsolute{
+ Size: 5,
+ },
+ bpf.RetA{},
+ })
+ if errStr(err) != "assembling instruction 1: invalid load byte length 0" {
+ t.Fatalf("unexpected error: %v", err)
+ }
+}
+
+func TestVMLoadConstantOK(t *testing.T) {
+ vm, done, err := testVM(t, []bpf.Instruction{
+ bpf.LoadConstant{
+ Dst: bpf.RegX,
+ Val: 9,
+ },
+ bpf.TXA{},
+ bpf.RetA{},
+ })
+ if err != nil {
+ t.Fatalf("failed to load BPF program: %v", err)
+ }
+ defer done()
+
+ out, err := vm.Run([]byte{
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0,
+ })
+ if err != nil {
+ t.Fatalf("unexpected error while running program: %v", err)
+ }
+ if want, got := 1, out; want != got {
+ t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
+ want, got)
+ }
+}
+
+func TestVMLoadIndirectOutOfBounds(t *testing.T) {
+ vm, done, err := testVM(t, []bpf.Instruction{
+ bpf.LoadIndirect{
+ Off: 100,
+ Size: 1,
+ },
+ bpf.RetA{},
+ })
+ if err != nil {
+ t.Fatalf("failed to load BPF program: %v", err)
+ }
+ defer done()
+
+ out, err := vm.Run([]byte{
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0,
+ })
+ if err != nil {
+ t.Fatalf("unexpected error while running program: %v", err)
+ }
+ if want, got := 0, out; want != got {
+ t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
+ want, got)
+ }
+}
+
+func TestVMLoadMemShiftOutOfBounds(t *testing.T) {
+ vm, done, err := testVM(t, []bpf.Instruction{
+ bpf.LoadMemShift{
+ Off: 100,
+ },
+ bpf.RetA{},
+ })
+ if err != nil {
+ t.Fatalf("failed to load BPF program: %v", err)
+ }
+ defer done()
+
+ out, err := vm.Run([]byte{
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0,
+ })
+ if err != nil {
+ t.Fatalf("unexpected error while running program: %v", err)
+ }
+ if want, got := 0, out; want != got {
+ t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
+ want, got)
+ }
+}
+
+const (
+ dhcp4Port = 53
+)
+
+func TestVMLoadMemShiftLoadIndirectNoResult(t *testing.T) {
+ vm, in, done := testDHCPv4(t)
+ defer done()
+
+ // Append mostly empty UDP header with incorrect DHCPv4 port
+ in = append(in, []byte{
+ 0, 0,
+ 0, dhcp4Port + 1,
+ 0, 0,
+ 0, 0,
+ }...)
+
+ out, err := vm.Run(in)
+ if err != nil {
+ t.Fatalf("unexpected error while running program: %v", err)
+ }
+ if want, got := 0, out; want != got {
+ t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
+ want, got)
+ }
+}
+
+func TestVMLoadMemShiftLoadIndirectOK(t *testing.T) {
+ vm, in, done := testDHCPv4(t)
+ defer done()
+
+ // Append mostly empty UDP header with correct DHCPv4 port
+ in = append(in, []byte{
+ 0, 0,
+ 0, dhcp4Port,
+ 0, 0,
+ 0, 0,
+ }...)
+
+ out, err := vm.Run(in)
+ if err != nil {
+ t.Fatalf("unexpected error while running program: %v", err)
+ }
+ if want, got := len(in)-8, out; want != got {
+ t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
+ want, got)
+ }
+}
+
+func testDHCPv4(t *testing.T) (virtualMachine, []byte, func()) {
+ // DHCPv4 test data courtesy of David Anderson:
+ // https://github.com/google/netboot/blob/master/dhcp4/conn_linux.go#L59-L70
+ vm, done, err := testVM(t, []bpf.Instruction{
+ // Load IPv4 packet length
+ bpf.LoadMemShift{Off: 8},
+ // Get UDP dport
+ bpf.LoadIndirect{Off: 8 + 2, Size: 2},
+ // Correct dport?
+ bpf.JumpIf{Cond: bpf.JumpEqual, Val: dhcp4Port, SkipFalse: 1},
+ // Accept
+ bpf.RetConstant{Val: 1500},
+ // Ignore
+ bpf.RetConstant{Val: 0},
+ })
+ if err != nil {
+ t.Fatalf("failed to load BPF program: %v", err)
+ }
+
+ // Minimal requirements to make a valid IPv4 header
+ h := &ipv4.Header{
+ Len: ipv4.HeaderLen,
+ Src: net.IPv4(192, 168, 1, 1),
+ Dst: net.IPv4(192, 168, 1, 2),
+ }
+ hb, err := h.Marshal()
+ if err != nil {
+ t.Fatalf("failed to marshal IPv4 header: %v", err)
+ }
+
+ hb = append([]byte{
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ }, hb...)
+
+ return vm, hb, done
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/vm_ret_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/vm_ret_test.go
new file mode 100644
index 000000000..2d86eae3e
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/vm_ret_test.go
@@ -0,0 +1,115 @@
+// 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.
+
+package bpf_test
+
+import (
+ "testing"
+
+ "golang.org/x/net/bpf"
+)
+
+func TestVMRetA(t *testing.T) {
+ vm, done, err := testVM(t, []bpf.Instruction{
+ bpf.LoadAbsolute{
+ Off: 8,
+ Size: 1,
+ },
+ bpf.RetA{},
+ })
+ if err != nil {
+ t.Fatalf("failed to load BPF program: %v", err)
+ }
+ defer done()
+
+ out, err := vm.Run([]byte{
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 9,
+ })
+ if err != nil {
+ t.Fatalf("unexpected error while running program: %v", err)
+ }
+ if want, got := 1, out; want != got {
+ t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
+ want, got)
+ }
+}
+
+func TestVMRetALargerThanInput(t *testing.T) {
+ vm, done, err := testVM(t, []bpf.Instruction{
+ bpf.LoadAbsolute{
+ Off: 8,
+ Size: 2,
+ },
+ bpf.RetA{},
+ })
+ if err != nil {
+ t.Fatalf("failed to load BPF program: %v", err)
+ }
+ defer done()
+
+ out, err := vm.Run([]byte{
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0, 255,
+ })
+ if err != nil {
+ t.Fatalf("unexpected error while running program: %v", err)
+ }
+ if want, got := 2, out; want != got {
+ t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
+ want, got)
+ }
+}
+
+func TestVMRetConstant(t *testing.T) {
+ vm, done, err := testVM(t, []bpf.Instruction{
+ bpf.RetConstant{
+ Val: 9,
+ },
+ })
+ if err != nil {
+ t.Fatalf("failed to load BPF program: %v", err)
+ }
+ defer done()
+
+ out, err := vm.Run([]byte{
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0, 1,
+ })
+ if err != nil {
+ t.Fatalf("unexpected error while running program: %v", err)
+ }
+ if want, got := 1, out; want != got {
+ t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
+ want, got)
+ }
+}
+
+func TestVMRetConstantLargerThanInput(t *testing.T) {
+ vm, done, err := testVM(t, []bpf.Instruction{
+ bpf.RetConstant{
+ Val: 16,
+ },
+ })
+ if err != nil {
+ t.Fatalf("failed to load BPF program: %v", err)
+ }
+ defer done()
+
+ out, err := vm.Run([]byte{
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0, 1,
+ })
+ if err != nil {
+ t.Fatalf("unexpected error while running program: %v", err)
+ }
+ if want, got := 2, out; want != got {
+ t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
+ want, got)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/vm_scratch_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/vm_scratch_test.go
new file mode 100644
index 000000000..e600e3c28
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/vm_scratch_test.go
@@ -0,0 +1,247 @@
+// 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.
+
+package bpf_test
+
+import (
+ "testing"
+
+ "golang.org/x/net/bpf"
+)
+
+func TestVMStoreScratchInvalidScratchRegisterTooSmall(t *testing.T) {
+ _, _, err := testVM(t, []bpf.Instruction{
+ bpf.StoreScratch{
+ Src: bpf.RegA,
+ N: -1,
+ },
+ bpf.RetA{},
+ })
+ if errStr(err) != "assembling instruction 1: invalid scratch slot -1" {
+ t.Fatalf("unexpected error: %v", err)
+ }
+}
+
+func TestVMStoreScratchInvalidScratchRegisterTooLarge(t *testing.T) {
+ _, _, err := testVM(t, []bpf.Instruction{
+ bpf.StoreScratch{
+ Src: bpf.RegA,
+ N: 16,
+ },
+ bpf.RetA{},
+ })
+ if errStr(err) != "assembling instruction 1: invalid scratch slot 16" {
+ t.Fatalf("unexpected error: %v", err)
+ }
+}
+
+func TestVMStoreScratchUnknownSourceRegister(t *testing.T) {
+ _, _, err := testVM(t, []bpf.Instruction{
+ bpf.StoreScratch{
+ Src: 100,
+ N: 0,
+ },
+ bpf.RetA{},
+ })
+ if errStr(err) != "assembling instruction 1: invalid source register 100" {
+ t.Fatalf("unexpected error: %v", err)
+ }
+}
+
+func TestVMLoadScratchInvalidScratchRegisterTooSmall(t *testing.T) {
+ _, _, err := testVM(t, []bpf.Instruction{
+ bpf.LoadScratch{
+ Dst: bpf.RegX,
+ N: -1,
+ },
+ bpf.RetA{},
+ })
+ if errStr(err) != "assembling instruction 1: invalid scratch slot -1" {
+ t.Fatalf("unexpected error: %v", err)
+ }
+}
+
+func TestVMLoadScratchInvalidScratchRegisterTooLarge(t *testing.T) {
+ _, _, err := testVM(t, []bpf.Instruction{
+ bpf.LoadScratch{
+ Dst: bpf.RegX,
+ N: 16,
+ },
+ bpf.RetA{},
+ })
+ if errStr(err) != "assembling instruction 1: invalid scratch slot 16" {
+ t.Fatalf("unexpected error: %v", err)
+ }
+}
+
+func TestVMLoadScratchUnknownDestinationRegister(t *testing.T) {
+ _, _, err := testVM(t, []bpf.Instruction{
+ bpf.LoadScratch{
+ Dst: 100,
+ N: 0,
+ },
+ bpf.RetA{},
+ })
+ if errStr(err) != "assembling instruction 1: invalid target register 100" {
+ t.Fatalf("unexpected error: %v", err)
+ }
+}
+
+func TestVMStoreScratchLoadScratchOneValue(t *testing.T) {
+ vm, done, err := testVM(t, []bpf.Instruction{
+ // Load byte 255
+ bpf.LoadAbsolute{
+ Off: 8,
+ Size: 1,
+ },
+ // Copy to X and store in scratch[0]
+ bpf.TAX{},
+ bpf.StoreScratch{
+ Src: bpf.RegX,
+ N: 0,
+ },
+ // Load byte 1
+ bpf.LoadAbsolute{
+ Off: 9,
+ Size: 1,
+ },
+ // Overwrite 1 with 255 from scratch[0]
+ bpf.LoadScratch{
+ Dst: bpf.RegA,
+ N: 0,
+ },
+ // Return 255
+ bpf.RetA{},
+ })
+ if err != nil {
+ t.Fatalf("failed to load BPF program: %v", err)
+ }
+ defer done()
+
+ out, err := vm.Run([]byte{
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 255, 1, 2,
+ })
+ if err != nil {
+ t.Fatalf("unexpected error while running program: %v", err)
+ }
+ if want, got := 3, out; want != got {
+ t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
+ want, got)
+ }
+}
+
+func TestVMStoreScratchLoadScratchMultipleValues(t *testing.T) {
+ vm, done, err := testVM(t, []bpf.Instruction{
+ // Load byte 10
+ bpf.LoadAbsolute{
+ Off: 8,
+ Size: 1,
+ },
+ // Store in scratch[0]
+ bpf.StoreScratch{
+ Src: bpf.RegA,
+ N: 0,
+ },
+ // Load byte 20
+ bpf.LoadAbsolute{
+ Off: 9,
+ Size: 1,
+ },
+ // Store in scratch[1]
+ bpf.StoreScratch{
+ Src: bpf.RegA,
+ N: 1,
+ },
+ // Load byte 30
+ bpf.LoadAbsolute{
+ Off: 10,
+ Size: 1,
+ },
+ // Store in scratch[2]
+ bpf.StoreScratch{
+ Src: bpf.RegA,
+ N: 2,
+ },
+ // Load byte 1
+ bpf.LoadAbsolute{
+ Off: 11,
+ Size: 1,
+ },
+ // Store in scratch[3]
+ bpf.StoreScratch{
+ Src: bpf.RegA,
+ N: 3,
+ },
+ // Load in byte 10 to X
+ bpf.LoadScratch{
+ Dst: bpf.RegX,
+ N: 0,
+ },
+ // Copy X -> A
+ bpf.TXA{},
+ // Verify value is 10
+ bpf.JumpIf{
+ Cond: bpf.JumpEqual,
+ Val: 10,
+ SkipTrue: 1,
+ },
+ // Fail test if incorrect
+ bpf.RetConstant{
+ Val: 0,
+ },
+ // Load in byte 20 to A
+ bpf.LoadScratch{
+ Dst: bpf.RegA,
+ N: 1,
+ },
+ // Verify value is 20
+ bpf.JumpIf{
+ Cond: bpf.JumpEqual,
+ Val: 20,
+ SkipTrue: 1,
+ },
+ // Fail test if incorrect
+ bpf.RetConstant{
+ Val: 0,
+ },
+ // Load in byte 30 to A
+ bpf.LoadScratch{
+ Dst: bpf.RegA,
+ N: 2,
+ },
+ // Verify value is 30
+ bpf.JumpIf{
+ Cond: bpf.JumpEqual,
+ Val: 30,
+ SkipTrue: 1,
+ },
+ // Fail test if incorrect
+ bpf.RetConstant{
+ Val: 0,
+ },
+ // Return first two bytes on success
+ bpf.RetConstant{
+ Val: 10,
+ },
+ })
+ if err != nil {
+ t.Fatalf("failed to load BPF program: %v", err)
+ }
+ defer done()
+
+ out, err := vm.Run([]byte{
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 10, 20, 30, 1,
+ })
+ if err != nil {
+ t.Fatalf("unexpected error while running program: %v", err)
+ }
+ if want, got := 2, out; want != got {
+ t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
+ want, got)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/vm_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/vm_test.go
new file mode 100644
index 000000000..6bd4dd5c3
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/bpf/vm_test.go
@@ -0,0 +1,144 @@
+// 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.
+
+package bpf_test
+
+import (
+ "fmt"
+ "testing"
+
+ "golang.org/x/net/bpf"
+)
+
+var _ bpf.Instruction = unknown{}
+
+type unknown struct{}
+
+func (unknown) Assemble() (bpf.RawInstruction, error) {
+ return bpf.RawInstruction{}, nil
+}
+
+func TestVMUnknownInstruction(t *testing.T) {
+ vm, done, err := testVM(t, []bpf.Instruction{
+ bpf.LoadConstant{
+ Dst: bpf.RegA,
+ Val: 100,
+ },
+ // Should terminate the program with an error immediately
+ unknown{},
+ bpf.RetA{},
+ })
+ if err != nil {
+ t.Fatalf("unexpected error: %v", err)
+ }
+ defer done()
+
+ _, err = vm.Run([]byte{
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x00,
+ })
+ if errStr(err) != "unknown Instruction at index 1: bpf_test.unknown" {
+ t.Fatalf("unexpected error while running program: %v", err)
+ }
+}
+
+func TestVMNoReturnInstruction(t *testing.T) {
+ _, _, err := testVM(t, []bpf.Instruction{
+ bpf.LoadConstant{
+ Dst: bpf.RegA,
+ Val: 1,
+ },
+ })
+ if errStr(err) != "BPF program must end with RetA or RetConstant" {
+ t.Fatalf("unexpected error: %v", err)
+ }
+}
+
+func TestVMNoInputInstructions(t *testing.T) {
+ _, _, err := testVM(t, []bpf.Instruction{})
+ if errStr(err) != "one or more Instructions must be specified" {
+ t.Fatalf("unexpected error: %v", err)
+ }
+}
+
+// ExampleNewVM demonstrates usage of a VM, using an Ethernet frame
+// as input and checking its EtherType to determine if it should be accepted.
+func ExampleNewVM() {
+ // Offset | Length | Comment
+ // -------------------------
+ // 00 | 06 | Ethernet destination MAC address
+ // 06 | 06 | Ethernet source MAC address
+ // 12 | 02 | Ethernet EtherType
+ const (
+ etOff = 12
+ etLen = 2
+
+ etARP = 0x0806
+ )
+
+ // Set up a VM to filter traffic based on if its EtherType
+ // matches the ARP EtherType.
+ vm, err := bpf.NewVM([]bpf.Instruction{
+ // Load EtherType value from Ethernet header
+ bpf.LoadAbsolute{
+ Off: etOff,
+ Size: etLen,
+ },
+ // If EtherType is equal to the ARP EtherType, jump to allow
+ // packet to be accepted
+ bpf.JumpIf{
+ Cond: bpf.JumpEqual,
+ Val: etARP,
+ SkipTrue: 1,
+ },
+ // EtherType does not match the ARP EtherType
+ bpf.RetConstant{
+ Val: 0,
+ },
+ // EtherType matches the ARP EtherType, accept up to 1500
+ // bytes of packet
+ bpf.RetConstant{
+ Val: 1500,
+ },
+ })
+ if err != nil {
+ panic(fmt.Sprintf("failed to load BPF program: %v", err))
+ }
+
+ // Create an Ethernet frame with the ARP EtherType for testing
+ frame := []byte{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
+ 0x08, 0x06,
+ // Payload omitted for brevity
+ }
+
+ // Run our VM's BPF program using the Ethernet frame as input
+ out, err := vm.Run(frame)
+ if err != nil {
+ panic(fmt.Sprintf("failed to accept Ethernet frame: %v", err))
+ }
+
+ // BPF VM can return a byte count greater than the number of input
+ // bytes, so trim the output to match the input byte length
+ if out > len(frame) {
+ out = len(frame)
+ }
+
+ fmt.Printf("out: %d bytes", out)
+
+ // Output:
+ // out: 14 bytes
+}
+
+// errStr returns the string representation of an error, or
+// "<nil>" if it is nil.
+func errStr(err error) string {
+ if err == nil {
+ return "<nil>"
+ }
+
+ return err.Error()
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/codereview.cfg b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/codereview.cfg
new file mode 100644
index 000000000..3f8b14b64
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/codereview.cfg
@@ -0,0 +1 @@
+issuerepo: golang/go
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/context/context.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/context/context.go
new file mode 100644
index 000000000..a3c021d3f
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/context/context.go
@@ -0,0 +1,56 @@
+// Copyright 2014 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 context defines the Context type, which carries deadlines,
+// cancelation signals, and other request-scoped values across API boundaries
+// and between processes.
+// As of Go 1.7 this package is available in the standard library under the
+// name context. https://golang.org/pkg/context.
+//
+// Incoming requests to a server should create a Context, and outgoing calls to
+// servers should accept a Context. The chain of function calls between must
+// propagate the Context, optionally replacing it with a modified copy created
+// using WithDeadline, WithTimeout, WithCancel, or WithValue.
+//
+// Programs that use Contexts should follow these rules to keep interfaces
+// consistent across packages and enable static analysis tools to check context
+// propagation:
+//
+// Do not store Contexts inside a struct type; instead, pass a Context
+// explicitly to each function that needs it. The Context should be the first
+// parameter, typically named ctx:
+//
+// func DoSomething(ctx context.Context, arg Arg) error {
+// // ... use ctx ...
+// }
+//
+// Do not pass a nil Context, even if a function permits it. Pass context.TODO
+// if you are unsure about which Context to use.
+//
+// Use context Values only for request-scoped data that transits processes and
+// APIs, not for passing optional parameters to functions.
+//
+// The same Context may be passed to functions running in different goroutines;
+// Contexts are safe for simultaneous use by multiple goroutines.
+//
+// See http://blog.golang.org/context for example code for a server that uses
+// Contexts.
+package context // import "golang.org/x/net/context"
+
+// Background returns a non-nil, empty Context. It is never canceled, has no
+// values, and has no deadline. It is typically used by the main function,
+// initialization, and tests, and as the top-level Context for incoming
+// requests.
+func Background() Context {
+ return background
+}
+
+// TODO returns a non-nil, empty Context. Code should use context.TODO when
+// it's unclear which Context to use or it is not yet available (because the
+// surrounding function has not yet been extended to accept a Context
+// parameter). TODO is recognized by static analysis tools that determine
+// whether Contexts are propagated correctly in a program.
+func TODO() Context {
+ return todo
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/context/context_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/context/context_test.go
new file mode 100644
index 000000000..62844131b
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/context/context_test.go
@@ -0,0 +1,583 @@
+// Copyright 2014 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.
+
+// +build !go1.7
+
+package context
+
+import (
+ "fmt"
+ "math/rand"
+ "runtime"
+ "strings"
+ "sync"
+ "testing"
+ "time"
+)
+
+// otherContext is a Context that's not one of the types defined in context.go.
+// This lets us test code paths that differ based on the underlying type of the
+// Context.
+type otherContext struct {
+ Context
+}
+
+func TestBackground(t *testing.T) {
+ c := Background()
+ if c == nil {
+ t.Fatalf("Background returned nil")
+ }
+ select {
+ case x := <-c.Done():
+ t.Errorf("<-c.Done() == %v want nothing (it should block)", x)
+ default:
+ }
+ if got, want := fmt.Sprint(c), "context.Background"; got != want {
+ t.Errorf("Background().String() = %q want %q", got, want)
+ }
+}
+
+func TestTODO(t *testing.T) {
+ c := TODO()
+ if c == nil {
+ t.Fatalf("TODO returned nil")
+ }
+ select {
+ case x := <-c.Done():
+ t.Errorf("<-c.Done() == %v want nothing (it should block)", x)
+ default:
+ }
+ if got, want := fmt.Sprint(c), "context.TODO"; got != want {
+ t.Errorf("TODO().String() = %q want %q", got, want)
+ }
+}
+
+func TestWithCancel(t *testing.T) {
+ c1, cancel := WithCancel(Background())
+
+ if got, want := fmt.Sprint(c1), "context.Background.WithCancel"; got != want {
+ t.Errorf("c1.String() = %q want %q", got, want)
+ }
+
+ o := otherContext{c1}
+ c2, _ := WithCancel(o)
+ contexts := []Context{c1, o, c2}
+
+ for i, c := range contexts {
+ if d := c.Done(); d == nil {
+ t.Errorf("c[%d].Done() == %v want non-nil", i, d)
+ }
+ if e := c.Err(); e != nil {
+ t.Errorf("c[%d].Err() == %v want nil", i, e)
+ }
+
+ select {
+ case x := <-c.Done():
+ t.Errorf("<-c.Done() == %v want nothing (it should block)", x)
+ default:
+ }
+ }
+
+ cancel()
+ time.Sleep(100 * time.Millisecond) // let cancelation propagate
+
+ for i, c := range contexts {
+ select {
+ case <-c.Done():
+ default:
+ t.Errorf("<-c[%d].Done() blocked, but shouldn't have", i)
+ }
+ if e := c.Err(); e != Canceled {
+ t.Errorf("c[%d].Err() == %v want %v", i, e, Canceled)
+ }
+ }
+}
+
+func TestParentFinishesChild(t *testing.T) {
+ // Context tree:
+ // parent -> cancelChild
+ // parent -> valueChild -> timerChild
+ parent, cancel := WithCancel(Background())
+ cancelChild, stop := WithCancel(parent)
+ defer stop()
+ valueChild := WithValue(parent, "key", "value")
+ timerChild, stop := WithTimeout(valueChild, 10000*time.Hour)
+ defer stop()
+
+ select {
+ case x := <-parent.Done():
+ t.Errorf("<-parent.Done() == %v want nothing (it should block)", x)
+ case x := <-cancelChild.Done():
+ t.Errorf("<-cancelChild.Done() == %v want nothing (it should block)", x)
+ case x := <-timerChild.Done():
+ t.Errorf("<-timerChild.Done() == %v want nothing (it should block)", x)
+ case x := <-valueChild.Done():
+ t.Errorf("<-valueChild.Done() == %v want nothing (it should block)", x)
+ default:
+ }
+
+ // The parent's children should contain the two cancelable children.
+ pc := parent.(*cancelCtx)
+ cc := cancelChild.(*cancelCtx)
+ tc := timerChild.(*timerCtx)
+ pc.mu.Lock()
+ if len(pc.children) != 2 || !pc.children[cc] || !pc.children[tc] {
+ t.Errorf("bad linkage: pc.children = %v, want %v and %v",
+ pc.children, cc, tc)
+ }
+ pc.mu.Unlock()
+
+ if p, ok := parentCancelCtx(cc.Context); !ok || p != pc {
+ t.Errorf("bad linkage: parentCancelCtx(cancelChild.Context) = %v, %v want %v, true", p, ok, pc)
+ }
+ if p, ok := parentCancelCtx(tc.Context); !ok || p != pc {
+ t.Errorf("bad linkage: parentCancelCtx(timerChild.Context) = %v, %v want %v, true", p, ok, pc)
+ }
+
+ cancel()
+
+ pc.mu.Lock()
+ if len(pc.children) != 0 {
+ t.Errorf("pc.cancel didn't clear pc.children = %v", pc.children)
+ }
+ pc.mu.Unlock()
+
+ // parent and children should all be finished.
+ check := func(ctx Context, name string) {
+ select {
+ case <-ctx.Done():
+ default:
+ t.Errorf("<-%s.Done() blocked, but shouldn't have", name)
+ }
+ if e := ctx.Err(); e != Canceled {
+ t.Errorf("%s.Err() == %v want %v", name, e, Canceled)
+ }
+ }
+ check(parent, "parent")
+ check(cancelChild, "cancelChild")
+ check(valueChild, "valueChild")
+ check(timerChild, "timerChild")
+
+ // WithCancel should return a canceled context on a canceled parent.
+ precanceledChild := WithValue(parent, "key", "value")
+ select {
+ case <-precanceledChild.Done():
+ default:
+ t.Errorf("<-precanceledChild.Done() blocked, but shouldn't have")
+ }
+ if e := precanceledChild.Err(); e != Canceled {
+ t.Errorf("precanceledChild.Err() == %v want %v", e, Canceled)
+ }
+}
+
+func TestChildFinishesFirst(t *testing.T) {
+ cancelable, stop := WithCancel(Background())
+ defer stop()
+ for _, parent := range []Context{Background(), cancelable} {
+ child, cancel := WithCancel(parent)
+
+ select {
+ case x := <-parent.Done():
+ t.Errorf("<-parent.Done() == %v want nothing (it should block)", x)
+ case x := <-child.Done():
+ t.Errorf("<-child.Done() == %v want nothing (it should block)", x)
+ default:
+ }
+
+ cc := child.(*cancelCtx)
+ pc, pcok := parent.(*cancelCtx) // pcok == false when parent == Background()
+ if p, ok := parentCancelCtx(cc.Context); ok != pcok || (ok && pc != p) {
+ t.Errorf("bad linkage: parentCancelCtx(cc.Context) = %v, %v want %v, %v", p, ok, pc, pcok)
+ }
+
+ if pcok {
+ pc.mu.Lock()
+ if len(pc.children) != 1 || !pc.children[cc] {
+ t.Errorf("bad linkage: pc.children = %v, cc = %v", pc.children, cc)
+ }
+ pc.mu.Unlock()
+ }
+
+ cancel()
+
+ if pcok {
+ pc.mu.Lock()
+ if len(pc.children) != 0 {
+ t.Errorf("child's cancel didn't remove self from pc.children = %v", pc.children)
+ }
+ pc.mu.Unlock()
+ }
+
+ // child should be finished.
+ select {
+ case <-child.Done():
+ default:
+ t.Errorf("<-child.Done() blocked, but shouldn't have")
+ }
+ if e := child.Err(); e != Canceled {
+ t.Errorf("child.Err() == %v want %v", e, Canceled)
+ }
+
+ // parent should not be finished.
+ select {
+ case x := <-parent.Done():
+ t.Errorf("<-parent.Done() == %v want nothing (it should block)", x)
+ default:
+ }
+ if e := parent.Err(); e != nil {
+ t.Errorf("parent.Err() == %v want nil", e)
+ }
+ }
+}
+
+func testDeadline(c Context, wait time.Duration, t *testing.T) {
+ select {
+ case <-time.After(wait):
+ t.Fatalf("context should have timed out")
+ case <-c.Done():
+ }
+ if e := c.Err(); e != DeadlineExceeded {
+ t.Errorf("c.Err() == %v want %v", e, DeadlineExceeded)
+ }
+}
+
+func TestDeadline(t *testing.T) {
+ t.Parallel()
+ const timeUnit = 500 * time.Millisecond
+ c, _ := WithDeadline(Background(), time.Now().Add(1*timeUnit))
+ if got, prefix := fmt.Sprint(c), "context.Background.WithDeadline("; !strings.HasPrefix(got, prefix) {
+ t.Errorf("c.String() = %q want prefix %q", got, prefix)
+ }
+ testDeadline(c, 2*timeUnit, t)
+
+ c, _ = WithDeadline(Background(), time.Now().Add(1*timeUnit))
+ o := otherContext{c}
+ testDeadline(o, 2*timeUnit, t)
+
+ c, _ = WithDeadline(Background(), time.Now().Add(1*timeUnit))
+ o = otherContext{c}
+ c, _ = WithDeadline(o, time.Now().Add(3*timeUnit))
+ testDeadline(c, 2*timeUnit, t)
+}
+
+func TestTimeout(t *testing.T) {
+ t.Parallel()
+ const timeUnit = 500 * time.Millisecond
+ c, _ := WithTimeout(Background(), 1*timeUnit)
+ if got, prefix := fmt.Sprint(c), "context.Background.WithDeadline("; !strings.HasPrefix(got, prefix) {
+ t.Errorf("c.String() = %q want prefix %q", got, prefix)
+ }
+ testDeadline(c, 2*timeUnit, t)
+
+ c, _ = WithTimeout(Background(), 1*timeUnit)
+ o := otherContext{c}
+ testDeadline(o, 2*timeUnit, t)
+
+ c, _ = WithTimeout(Background(), 1*timeUnit)
+ o = otherContext{c}
+ c, _ = WithTimeout(o, 3*timeUnit)
+ testDeadline(c, 2*timeUnit, t)
+}
+
+func TestCanceledTimeout(t *testing.T) {
+ t.Parallel()
+ const timeUnit = 500 * time.Millisecond
+ c, _ := WithTimeout(Background(), 2*timeUnit)
+ o := otherContext{c}
+ c, cancel := WithTimeout(o, 4*timeUnit)
+ cancel()
+ time.Sleep(1 * timeUnit) // let cancelation propagate
+ select {
+ case <-c.Done():
+ default:
+ t.Errorf("<-c.Done() blocked, but shouldn't have")
+ }
+ if e := c.Err(); e != Canceled {
+ t.Errorf("c.Err() == %v want %v", e, Canceled)
+ }
+}
+
+type key1 int
+type key2 int
+
+var k1 = key1(1)
+var k2 = key2(1) // same int as k1, different type
+var k3 = key2(3) // same type as k2, different int
+
+func TestValues(t *testing.T) {
+ check := func(c Context, nm, v1, v2, v3 string) {
+ if v, ok := c.Value(k1).(string); ok == (len(v1) == 0) || v != v1 {
+ t.Errorf(`%s.Value(k1).(string) = %q, %t want %q, %t`, nm, v, ok, v1, len(v1) != 0)
+ }
+ if v, ok := c.Value(k2).(string); ok == (len(v2) == 0) || v != v2 {
+ t.Errorf(`%s.Value(k2).(string) = %q, %t want %q, %t`, nm, v, ok, v2, len(v2) != 0)
+ }
+ if v, ok := c.Value(k3).(string); ok == (len(v3) == 0) || v != v3 {
+ t.Errorf(`%s.Value(k3).(string) = %q, %t want %q, %t`, nm, v, ok, v3, len(v3) != 0)
+ }
+ }
+
+ c0 := Background()
+ check(c0, "c0", "", "", "")
+
+ c1 := WithValue(Background(), k1, "c1k1")
+ check(c1, "c1", "c1k1", "", "")
+
+ if got, want := fmt.Sprint(c1), `context.Background.WithValue(1, "c1k1")`; got != want {
+ t.Errorf("c.String() = %q want %q", got, want)
+ }
+
+ c2 := WithValue(c1, k2, "c2k2")
+ check(c2, "c2", "c1k1", "c2k2", "")
+
+ c3 := WithValue(c2, k3, "c3k3")
+ check(c3, "c2", "c1k1", "c2k2", "c3k3")
+
+ c4 := WithValue(c3, k1, nil)
+ check(c4, "c4", "", "c2k2", "c3k3")
+
+ o0 := otherContext{Background()}
+ check(o0, "o0", "", "", "")
+
+ o1 := otherContext{WithValue(Background(), k1, "c1k1")}
+ check(o1, "o1", "c1k1", "", "")
+
+ o2 := WithValue(o1, k2, "o2k2")
+ check(o2, "o2", "c1k1", "o2k2", "")
+
+ o3 := otherContext{c4}
+ check(o3, "o3", "", "c2k2", "c3k3")
+
+ o4 := WithValue(o3, k3, nil)
+ check(o4, "o4", "", "c2k2", "")
+}
+
+func TestAllocs(t *testing.T) {
+ bg := Background()
+ for _, test := range []struct {
+ desc string
+ f func()
+ limit float64
+ gccgoLimit float64
+ }{
+ {
+ desc: "Background()",
+ f: func() { Background() },
+ limit: 0,
+ gccgoLimit: 0,
+ },
+ {
+ desc: fmt.Sprintf("WithValue(bg, %v, nil)", k1),
+ f: func() {
+ c := WithValue(bg, k1, nil)
+ c.Value(k1)
+ },
+ limit: 3,
+ gccgoLimit: 3,
+ },
+ {
+ desc: "WithTimeout(bg, 15*time.Millisecond)",
+ f: func() {
+ c, _ := WithTimeout(bg, 15*time.Millisecond)
+ <-c.Done()
+ },
+ limit: 8,
+ gccgoLimit: 16,
+ },
+ {
+ desc: "WithCancel(bg)",
+ f: func() {
+ c, cancel := WithCancel(bg)
+ cancel()
+ <-c.Done()
+ },
+ limit: 5,
+ gccgoLimit: 8,
+ },
+ {
+ desc: "WithTimeout(bg, 100*time.Millisecond)",
+ f: func() {
+ c, cancel := WithTimeout(bg, 100*time.Millisecond)
+ cancel()
+ <-c.Done()
+ },
+ limit: 8,
+ gccgoLimit: 25,
+ },
+ } {
+ limit := test.limit
+ if runtime.Compiler == "gccgo" {
+ // gccgo does not yet do escape analysis.
+ // TODO(iant): Remove this when gccgo does do escape analysis.
+ limit = test.gccgoLimit
+ }
+ if n := testing.AllocsPerRun(100, test.f); n > limit {
+ t.Errorf("%s allocs = %f want %d", test.desc, n, int(limit))
+ }
+ }
+}
+
+func TestSimultaneousCancels(t *testing.T) {
+ root, cancel := WithCancel(Background())
+ m := map[Context]CancelFunc{root: cancel}
+ q := []Context{root}
+ // Create a tree of contexts.
+ for len(q) != 0 && len(m) < 100 {
+ parent := q[0]
+ q = q[1:]
+ for i := 0; i < 4; i++ {
+ ctx, cancel := WithCancel(parent)
+ m[ctx] = cancel
+ q = append(q, ctx)
+ }
+ }
+ // Start all the cancels in a random order.
+ var wg sync.WaitGroup
+ wg.Add(len(m))
+ for _, cancel := range m {
+ go func(cancel CancelFunc) {
+ cancel()
+ wg.Done()
+ }(cancel)
+ }
+ // Wait on all the contexts in a random order.
+ for ctx := range m {
+ select {
+ case <-ctx.Done():
+ case <-time.After(1 * time.Second):
+ buf := make([]byte, 10<<10)
+ n := runtime.Stack(buf, true)
+ t.Fatalf("timed out waiting for <-ctx.Done(); stacks:\n%s", buf[:n])
+ }
+ }
+ // Wait for all the cancel functions to return.
+ done := make(chan struct{})
+ go func() {
+ wg.Wait()
+ close(done)
+ }()
+ select {
+ case <-done:
+ case <-time.After(1 * time.Second):
+ buf := make([]byte, 10<<10)
+ n := runtime.Stack(buf, true)
+ t.Fatalf("timed out waiting for cancel functions; stacks:\n%s", buf[:n])
+ }
+}
+
+func TestInterlockedCancels(t *testing.T) {
+ parent, cancelParent := WithCancel(Background())
+ child, cancelChild := WithCancel(parent)
+ go func() {
+ parent.Done()
+ cancelChild()
+ }()
+ cancelParent()
+ select {
+ case <-child.Done():
+ case <-time.After(1 * time.Second):
+ buf := make([]byte, 10<<10)
+ n := runtime.Stack(buf, true)
+ t.Fatalf("timed out waiting for child.Done(); stacks:\n%s", buf[:n])
+ }
+}
+
+func TestLayersCancel(t *testing.T) {
+ testLayers(t, time.Now().UnixNano(), false)
+}
+
+func TestLayersTimeout(t *testing.T) {
+ testLayers(t, time.Now().UnixNano(), true)
+}
+
+func testLayers(t *testing.T, seed int64, testTimeout bool) {
+ rand.Seed(seed)
+ errorf := func(format string, a ...interface{}) {
+ t.Errorf(fmt.Sprintf("seed=%d: %s", seed, format), a...)
+ }
+ const (
+ timeout = 200 * time.Millisecond
+ minLayers = 30
+ )
+ type value int
+ var (
+ vals []*value
+ cancels []CancelFunc
+ numTimers int
+ ctx = Background()
+ )
+ for i := 0; i < minLayers || numTimers == 0 || len(cancels) == 0 || len(vals) == 0; i++ {
+ switch rand.Intn(3) {
+ case 0:
+ v := new(value)
+ ctx = WithValue(ctx, v, v)
+ vals = append(vals, v)
+ case 1:
+ var cancel CancelFunc
+ ctx, cancel = WithCancel(ctx)
+ cancels = append(cancels, cancel)
+ case 2:
+ var cancel CancelFunc
+ ctx, cancel = WithTimeout(ctx, timeout)
+ cancels = append(cancels, cancel)
+ numTimers++
+ }
+ }
+ checkValues := func(when string) {
+ for _, key := range vals {
+ if val := ctx.Value(key).(*value); key != val {
+ errorf("%s: ctx.Value(%p) = %p want %p", when, key, val, key)
+ }
+ }
+ }
+ select {
+ case <-ctx.Done():
+ errorf("ctx should not be canceled yet")
+ default:
+ }
+ if s, prefix := fmt.Sprint(ctx), "context.Background."; !strings.HasPrefix(s, prefix) {
+ t.Errorf("ctx.String() = %q want prefix %q", s, prefix)
+ }
+ t.Log(ctx)
+ checkValues("before cancel")
+ if testTimeout {
+ select {
+ case <-ctx.Done():
+ case <-time.After(timeout + 100*time.Millisecond):
+ errorf("ctx should have timed out")
+ }
+ checkValues("after timeout")
+ } else {
+ cancel := cancels[rand.Intn(len(cancels))]
+ cancel()
+ select {
+ case <-ctx.Done():
+ default:
+ errorf("ctx should be canceled")
+ }
+ checkValues("after cancel")
+ }
+}
+
+func TestCancelRemoves(t *testing.T) {
+ checkChildren := func(when string, ctx Context, want int) {
+ if got := len(ctx.(*cancelCtx).children); got != want {
+ t.Errorf("%s: context has %d children, want %d", when, got, want)
+ }
+ }
+
+ ctx, _ := WithCancel(Background())
+ checkChildren("after creation", ctx, 0)
+ _, cancel := WithCancel(ctx)
+ checkChildren("with WithCancel child ", ctx, 1)
+ cancel()
+ checkChildren("after cancelling WithCancel child", ctx, 0)
+
+ ctx, _ = WithCancel(Background())
+ checkChildren("after creation", ctx, 0)
+ _, cancel = WithTimeout(ctx, 60*time.Minute)
+ checkChildren("with WithTimeout child ", ctx, 1)
+ cancel()
+ checkChildren("after cancelling WithTimeout child", ctx, 0)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go
new file mode 100644
index 000000000..606cf1f97
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go
@@ -0,0 +1,74 @@
+// 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.
+
+// +build go1.7
+
+// Package ctxhttp provides helper functions for performing context-aware HTTP requests.
+package ctxhttp // import "golang.org/x/net/context/ctxhttp"
+
+import (
+ "io"
+ "net/http"
+ "net/url"
+ "strings"
+
+ "golang.org/x/net/context"
+)
+
+// Do sends an HTTP request with the provided http.Client and returns
+// an HTTP response.
+//
+// If the client is nil, http.DefaultClient is used.
+//
+// The provided ctx must be non-nil. If it is canceled or times out,
+// ctx.Err() will be returned.
+func Do(ctx context.Context, client *http.Client, req *http.Request) (*http.Response, error) {
+ if client == nil {
+ client = http.DefaultClient
+ }
+ resp, err := client.Do(req.WithContext(ctx))
+ // If we got an error, and the context has been canceled,
+ // the context's error is probably more useful.
+ if err != nil {
+ select {
+ case <-ctx.Done():
+ err = ctx.Err()
+ default:
+ }
+ }
+ return resp, err
+}
+
+// Get issues a GET request via the Do function.
+func Get(ctx context.Context, client *http.Client, url string) (*http.Response, error) {
+ req, err := http.NewRequest("GET", url, nil)
+ if err != nil {
+ return nil, err
+ }
+ return Do(ctx, client, req)
+}
+
+// Head issues a HEAD request via the Do function.
+func Head(ctx context.Context, client *http.Client, url string) (*http.Response, error) {
+ req, err := http.NewRequest("HEAD", url, nil)
+ if err != nil {
+ return nil, err
+ }
+ return Do(ctx, client, req)
+}
+
+// Post issues a POST request via the Do function.
+func Post(ctx context.Context, client *http.Client, url string, bodyType string, body io.Reader) (*http.Response, error) {
+ req, err := http.NewRequest("POST", url, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header.Set("Content-Type", bodyType)
+ return Do(ctx, client, req)
+}
+
+// PostForm issues a POST request via the Do function.
+func PostForm(ctx context.Context, client *http.Client, url string, data url.Values) (*http.Response, error) {
+ return Post(ctx, client, url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode()))
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/context/ctxhttp/ctxhttp_17_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/context/ctxhttp/ctxhttp_17_test.go
new file mode 100644
index 000000000..72411b1b6
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/context/ctxhttp/ctxhttp_17_test.go
@@ -0,0 +1,29 @@
+// Copyright 2015 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.
+
+// +build !plan9,go1.7
+
+package ctxhttp
+
+import (
+ "io"
+ "net/http"
+ "net/http/httptest"
+ "testing"
+
+ "context"
+)
+
+func TestGo17Context(t *testing.T) {
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ io.WriteString(w, "ok")
+ }))
+ defer ts.Close()
+ ctx := context.Background()
+ resp, err := Get(ctx, http.DefaultClient, ts.URL)
+ if resp == nil || err != nil {
+ t.Fatalf("error received from client: %v %v", err, resp)
+ }
+ resp.Body.Close()
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/context/ctxhttp/ctxhttp_pre17.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/context/ctxhttp/ctxhttp_pre17.go
new file mode 100644
index 000000000..926870cc2
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/context/ctxhttp/ctxhttp_pre17.go
@@ -0,0 +1,147 @@
+// Copyright 2015 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.
+
+// +build !go1.7
+
+package ctxhttp // import "golang.org/x/net/context/ctxhttp"
+
+import (
+ "io"
+ "net/http"
+ "net/url"
+ "strings"
+
+ "golang.org/x/net/context"
+)
+
+func nop() {}
+
+var (
+ testHookContextDoneBeforeHeaders = nop
+ testHookDoReturned = nop
+ testHookDidBodyClose = nop
+)
+
+// Do sends an HTTP request with the provided http.Client and returns an HTTP response.
+// If the client is nil, http.DefaultClient is used.
+// If the context is canceled or times out, ctx.Err() will be returned.
+func Do(ctx context.Context, client *http.Client, req *http.Request) (*http.Response, error) {
+ if client == nil {
+ client = http.DefaultClient
+ }
+
+ // TODO(djd): Respect any existing value of req.Cancel.
+ cancel := make(chan struct{})
+ req.Cancel = cancel
+
+ type responseAndError struct {
+ resp *http.Response
+ err error
+ }
+ result := make(chan responseAndError, 1)
+
+ // Make local copies of test hooks closed over by goroutines below.
+ // Prevents data races in tests.
+ testHookDoReturned := testHookDoReturned
+ testHookDidBodyClose := testHookDidBodyClose
+
+ go func() {
+ resp, err := client.Do(req)
+ testHookDoReturned()
+ result <- responseAndError{resp, err}
+ }()
+
+ var resp *http.Response
+
+ select {
+ case <-ctx.Done():
+ testHookContextDoneBeforeHeaders()
+ close(cancel)
+ // Clean up after the goroutine calling client.Do:
+ go func() {
+ if r := <-result; r.resp != nil {
+ testHookDidBodyClose()
+ r.resp.Body.Close()
+ }
+ }()
+ return nil, ctx.Err()
+ case r := <-result:
+ var err error
+ resp, err = r.resp, r.err
+ if err != nil {
+ return resp, err
+ }
+ }
+
+ c := make(chan struct{})
+ go func() {
+ select {
+ case <-ctx.Done():
+ close(cancel)
+ case <-c:
+ // The response's Body is closed.
+ }
+ }()
+ resp.Body = &notifyingReader{resp.Body, c}
+
+ return resp, nil
+}
+
+// Get issues a GET request via the Do function.
+func Get(ctx context.Context, client *http.Client, url string) (*http.Response, error) {
+ req, err := http.NewRequest("GET", url, nil)
+ if err != nil {
+ return nil, err
+ }
+ return Do(ctx, client, req)
+}
+
+// Head issues a HEAD request via the Do function.
+func Head(ctx context.Context, client *http.Client, url string) (*http.Response, error) {
+ req, err := http.NewRequest("HEAD", url, nil)
+ if err != nil {
+ return nil, err
+ }
+ return Do(ctx, client, req)
+}
+
+// Post issues a POST request via the Do function.
+func Post(ctx context.Context, client *http.Client, url string, bodyType string, body io.Reader) (*http.Response, error) {
+ req, err := http.NewRequest("POST", url, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header.Set("Content-Type", bodyType)
+ return Do(ctx, client, req)
+}
+
+// PostForm issues a POST request via the Do function.
+func PostForm(ctx context.Context, client *http.Client, url string, data url.Values) (*http.Response, error) {
+ return Post(ctx, client, url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode()))
+}
+
+// notifyingReader is an io.ReadCloser that closes the notify channel after
+// Close is called or a Read fails on the underlying ReadCloser.
+type notifyingReader struct {
+ io.ReadCloser
+ notify chan<- struct{}
+}
+
+func (r *notifyingReader) Read(p []byte) (int, error) {
+ n, err := r.ReadCloser.Read(p)
+ if err != nil && r.notify != nil {
+ close(r.notify)
+ r.notify = nil
+ }
+ return n, err
+}
+
+func (r *notifyingReader) Close() error {
+ err := r.ReadCloser.Close()
+ if r.notify != nil {
+ close(r.notify)
+ r.notify = nil
+ }
+ return err
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/context/ctxhttp/ctxhttp_pre17_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/context/ctxhttp/ctxhttp_pre17_test.go
new file mode 100644
index 000000000..9159cf022
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/context/ctxhttp/ctxhttp_pre17_test.go
@@ -0,0 +1,79 @@
+// Copyright 2015 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.
+
+// +build !plan9,!go1.7
+
+package ctxhttp
+
+import (
+ "net"
+ "net/http"
+ "net/http/httptest"
+ "sync"
+ "testing"
+ "time"
+
+ "golang.org/x/net/context"
+)
+
+// golang.org/issue/14065
+func TestClosesResponseBodyOnCancel(t *testing.T) {
+ defer func() { testHookContextDoneBeforeHeaders = nop }()
+ defer func() { testHookDoReturned = nop }()
+ defer func() { testHookDidBodyClose = nop }()
+
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}))
+ defer ts.Close()
+
+ ctx, cancel := context.WithCancel(context.Background())
+
+ // closed when Do enters select case <-ctx.Done()
+ enteredDonePath := make(chan struct{})
+
+ testHookContextDoneBeforeHeaders = func() {
+ close(enteredDonePath)
+ }
+
+ testHookDoReturned = func() {
+ // We now have the result (the Flush'd headers) at least,
+ // so we can cancel the request.
+ cancel()
+
+ // But block the client.Do goroutine from sending
+ // until Do enters into the <-ctx.Done() path, since
+ // otherwise if both channels are readable, select
+ // picks a random one.
+ <-enteredDonePath
+ }
+
+ sawBodyClose := make(chan struct{})
+ testHookDidBodyClose = func() { close(sawBodyClose) }
+
+ tr := &http.Transport{}
+ defer tr.CloseIdleConnections()
+ c := &http.Client{Transport: tr}
+ req, _ := http.NewRequest("GET", ts.URL, nil)
+ _, doErr := Do(ctx, c, req)
+
+ select {
+ case <-sawBodyClose:
+ case <-time.After(5 * time.Second):
+ t.Fatal("timeout waiting for body to close")
+ }
+
+ if doErr != ctx.Err() {
+ t.Errorf("Do error = %v; want %v", doErr, ctx.Err())
+ }
+}
+
+type noteCloseConn struct {
+ net.Conn
+ onceClose sync.Once
+ closefn func()
+}
+
+func (c *noteCloseConn) Close() error {
+ c.onceClose.Do(c.closefn)
+ return c.Conn.Close()
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/context/ctxhttp/ctxhttp_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/context/ctxhttp/ctxhttp_test.go
new file mode 100644
index 000000000..1e4155180
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/context/ctxhttp/ctxhttp_test.go
@@ -0,0 +1,105 @@
+// Copyright 2015 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.
+
+// +build !plan9
+
+package ctxhttp
+
+import (
+ "io"
+ "io/ioutil"
+ "net/http"
+ "net/http/httptest"
+ "testing"
+ "time"
+
+ "golang.org/x/net/context"
+)
+
+const (
+ requestDuration = 100 * time.Millisecond
+ requestBody = "ok"
+)
+
+func okHandler(w http.ResponseWriter, r *http.Request) {
+ time.Sleep(requestDuration)
+ io.WriteString(w, requestBody)
+}
+
+func TestNoTimeout(t *testing.T) {
+ ts := httptest.NewServer(http.HandlerFunc(okHandler))
+ defer ts.Close()
+
+ ctx := context.Background()
+ res, err := Get(ctx, nil, ts.URL)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer res.Body.Close()
+ slurp, err := ioutil.ReadAll(res.Body)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if string(slurp) != requestBody {
+ t.Errorf("body = %q; want %q", slurp, requestBody)
+ }
+}
+
+func TestCancelBeforeHeaders(t *testing.T) {
+ ctx, cancel := context.WithCancel(context.Background())
+
+ blockServer := make(chan struct{})
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ cancel()
+ <-blockServer
+ io.WriteString(w, requestBody)
+ }))
+ defer ts.Close()
+ defer close(blockServer)
+
+ res, err := Get(ctx, nil, ts.URL)
+ if err == nil {
+ res.Body.Close()
+ t.Fatal("Get returned unexpected nil error")
+ }
+ if err != context.Canceled {
+ t.Errorf("err = %v; want %v", err, context.Canceled)
+ }
+}
+
+func TestCancelAfterHangingRequest(t *testing.T) {
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.WriteHeader(http.StatusOK)
+ w.(http.Flusher).Flush()
+ <-w.(http.CloseNotifier).CloseNotify()
+ }))
+ defer ts.Close()
+
+ ctx, cancel := context.WithCancel(context.Background())
+ resp, err := Get(ctx, nil, ts.URL)
+ if err != nil {
+ t.Fatalf("unexpected error in Get: %v", err)
+ }
+
+ // Cancel befer reading the body.
+ // Reading Request.Body should fail, since the request was
+ // canceled before anything was written.
+ cancel()
+
+ done := make(chan struct{})
+
+ go func() {
+ b, err := ioutil.ReadAll(resp.Body)
+ if len(b) != 0 || err == nil {
+ t.Errorf(`Read got (%q, %v); want ("", error)`, b, err)
+ }
+ close(done)
+ }()
+
+ select {
+ case <-time.After(1 * time.Second):
+ t.Errorf("Test timed out")
+ case <-done:
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/context/go17.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/context/go17.go
new file mode 100644
index 000000000..d20f52b7d
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/context/go17.go
@@ -0,0 +1,72 @@
+// 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.
+
+// +build go1.7
+
+package context
+
+import (
+ "context" // standard library's context, as of Go 1.7
+ "time"
+)
+
+var (
+ todo = context.TODO()
+ background = context.Background()
+)
+
+// Canceled is the error returned by Context.Err when the context is canceled.
+var Canceled = context.Canceled
+
+// DeadlineExceeded is the error returned by Context.Err when the context's
+// deadline passes.
+var DeadlineExceeded = context.DeadlineExceeded
+
+// WithCancel returns a copy of parent with a new Done channel. The returned
+// context's Done channel is closed when the returned cancel function is called
+// or when the parent context's Done channel is closed, whichever happens first.
+//
+// Canceling this context releases resources associated with it, so code should
+// call cancel as soon as the operations running in this Context complete.
+func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
+ ctx, f := context.WithCancel(parent)
+ return ctx, CancelFunc(f)
+}
+
+// WithDeadline returns a copy of the parent context with the deadline adjusted
+// to be no later than d. If the parent's deadline is already earlier than d,
+// WithDeadline(parent, d) is semantically equivalent to parent. The returned
+// context's Done channel is closed when the deadline expires, when the returned
+// cancel function is called, or when the parent context's Done channel is
+// closed, whichever happens first.
+//
+// Canceling this context releases resources associated with it, so code should
+// call cancel as soon as the operations running in this Context complete.
+func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) {
+ ctx, f := context.WithDeadline(parent, deadline)
+ return ctx, CancelFunc(f)
+}
+
+// WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)).
+//
+// Canceling this context releases resources associated with it, so code should
+// call cancel as soon as the operations running in this Context complete:
+//
+// func slowOperationWithTimeout(ctx context.Context) (Result, error) {
+// ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
+// defer cancel() // releases resources if slowOperation completes before timeout elapses
+// return slowOperation(ctx)
+// }
+func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
+ return WithDeadline(parent, time.Now().Add(timeout))
+}
+
+// WithValue returns a copy of parent in which the value associated with key is
+// val.
+//
+// Use context Values only for request-scoped data that transits processes and
+// APIs, not for passing optional parameters to functions.
+func WithValue(parent Context, key interface{}, val interface{}) Context {
+ return context.WithValue(parent, key, val)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/context/go19.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/context/go19.go
new file mode 100644
index 000000000..d88bd1db1
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/context/go19.go
@@ -0,0 +1,20 @@
+// 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.
+
+// +build go1.9
+
+package context
+
+import "context" // standard library's context, as of Go 1.7
+
+// A Context carries a deadline, a cancelation signal, and other values across
+// API boundaries.
+//
+// Context's methods may be called by multiple goroutines simultaneously.
+type Context = context.Context
+
+// A CancelFunc tells an operation to abandon its work.
+// A CancelFunc does not wait for the work to stop.
+// After the first call, subsequent calls to a CancelFunc do nothing.
+type CancelFunc = context.CancelFunc
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/context/pre_go17.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/context/pre_go17.go
new file mode 100644
index 000000000..0f35592df
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/context/pre_go17.go
@@ -0,0 +1,300 @@
+// Copyright 2014 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.
+
+// +build !go1.7
+
+package context
+
+import (
+ "errors"
+ "fmt"
+ "sync"
+ "time"
+)
+
+// An emptyCtx is never canceled, has no values, and has no deadline. It is not
+// struct{}, since vars of this type must have distinct addresses.
+type emptyCtx int
+
+func (*emptyCtx) Deadline() (deadline time.Time, ok bool) {
+ return
+}
+
+func (*emptyCtx) Done() <-chan struct{} {
+ return nil
+}
+
+func (*emptyCtx) Err() error {
+ return nil
+}
+
+func (*emptyCtx) Value(key interface{}) interface{} {
+ return nil
+}
+
+func (e *emptyCtx) String() string {
+ switch e {
+ case background:
+ return "context.Background"
+ case todo:
+ return "context.TODO"
+ }
+ return "unknown empty Context"
+}
+
+var (
+ background = new(emptyCtx)
+ todo = new(emptyCtx)
+)
+
+// Canceled is the error returned by Context.Err when the context is canceled.
+var Canceled = errors.New("context canceled")
+
+// DeadlineExceeded is the error returned by Context.Err when the context's
+// deadline passes.
+var DeadlineExceeded = errors.New("context deadline exceeded")
+
+// WithCancel returns a copy of parent with a new Done channel. The returned
+// context's Done channel is closed when the returned cancel function is called
+// or when the parent context's Done channel is closed, whichever happens first.
+//
+// Canceling this context releases resources associated with it, so code should
+// call cancel as soon as the operations running in this Context complete.
+func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
+ c := newCancelCtx(parent)
+ propagateCancel(parent, c)
+ return c, func() { c.cancel(true, Canceled) }
+}
+
+// newCancelCtx returns an initialized cancelCtx.
+func newCancelCtx(parent Context) *cancelCtx {
+ return &cancelCtx{
+ Context: parent,
+ done: make(chan struct{}),
+ }
+}
+
+// propagateCancel arranges for child to be canceled when parent is.
+func propagateCancel(parent Context, child canceler) {
+ if parent.Done() == nil {
+ return // parent is never canceled
+ }
+ if p, ok := parentCancelCtx(parent); ok {
+ p.mu.Lock()
+ if p.err != nil {
+ // parent has already been canceled
+ child.cancel(false, p.err)
+ } else {
+ if p.children == nil {
+ p.children = make(map[canceler]bool)
+ }
+ p.children[child] = true
+ }
+ p.mu.Unlock()
+ } else {
+ go func() {
+ select {
+ case <-parent.Done():
+ child.cancel(false, parent.Err())
+ case <-child.Done():
+ }
+ }()
+ }
+}
+
+// parentCancelCtx follows a chain of parent references until it finds a
+// *cancelCtx. This function understands how each of the concrete types in this
+// package represents its parent.
+func parentCancelCtx(parent Context) (*cancelCtx, bool) {
+ for {
+ switch c := parent.(type) {
+ case *cancelCtx:
+ return c, true
+ case *timerCtx:
+ return c.cancelCtx, true
+ case *valueCtx:
+ parent = c.Context
+ default:
+ return nil, false
+ }
+ }
+}
+
+// removeChild removes a context from its parent.
+func removeChild(parent Context, child canceler) {
+ p, ok := parentCancelCtx(parent)
+ if !ok {
+ return
+ }
+ p.mu.Lock()
+ if p.children != nil {
+ delete(p.children, child)
+ }
+ p.mu.Unlock()
+}
+
+// A canceler is a context type that can be canceled directly. The
+// implementations are *cancelCtx and *timerCtx.
+type canceler interface {
+ cancel(removeFromParent bool, err error)
+ Done() <-chan struct{}
+}
+
+// A cancelCtx can be canceled. When canceled, it also cancels any children
+// that implement canceler.
+type cancelCtx struct {
+ Context
+
+ done chan struct{} // closed by the first cancel call.
+
+ mu sync.Mutex
+ children map[canceler]bool // set to nil by the first cancel call
+ err error // set to non-nil by the first cancel call
+}
+
+func (c *cancelCtx) Done() <-chan struct{} {
+ return c.done
+}
+
+func (c *cancelCtx) Err() error {
+ c.mu.Lock()
+ defer c.mu.Unlock()
+ return c.err
+}
+
+func (c *cancelCtx) String() string {
+ return fmt.Sprintf("%v.WithCancel", c.Context)
+}
+
+// cancel closes c.done, cancels each of c's children, and, if
+// removeFromParent is true, removes c from its parent's children.
+func (c *cancelCtx) cancel(removeFromParent bool, err error) {
+ if err == nil {
+ panic("context: internal error: missing cancel error")
+ }
+ c.mu.Lock()
+ if c.err != nil {
+ c.mu.Unlock()
+ return // already canceled
+ }
+ c.err = err
+ close(c.done)
+ for child := range c.children {
+ // NOTE: acquiring the child's lock while holding parent's lock.
+ child.cancel(false, err)
+ }
+ c.children = nil
+ c.mu.Unlock()
+
+ if removeFromParent {
+ removeChild(c.Context, c)
+ }
+}
+
+// WithDeadline returns a copy of the parent context with the deadline adjusted
+// to be no later than d. If the parent's deadline is already earlier than d,
+// WithDeadline(parent, d) is semantically equivalent to parent. The returned
+// context's Done channel is closed when the deadline expires, when the returned
+// cancel function is called, or when the parent context's Done channel is
+// closed, whichever happens first.
+//
+// Canceling this context releases resources associated with it, so code should
+// call cancel as soon as the operations running in this Context complete.
+func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) {
+ if cur, ok := parent.Deadline(); ok && cur.Before(deadline) {
+ // The current deadline is already sooner than the new one.
+ return WithCancel(parent)
+ }
+ c := &timerCtx{
+ cancelCtx: newCancelCtx(parent),
+ deadline: deadline,
+ }
+ propagateCancel(parent, c)
+ d := deadline.Sub(time.Now())
+ if d <= 0 {
+ c.cancel(true, DeadlineExceeded) // deadline has already passed
+ return c, func() { c.cancel(true, Canceled) }
+ }
+ c.mu.Lock()
+ defer c.mu.Unlock()
+ if c.err == nil {
+ c.timer = time.AfterFunc(d, func() {
+ c.cancel(true, DeadlineExceeded)
+ })
+ }
+ return c, func() { c.cancel(true, Canceled) }
+}
+
+// A timerCtx carries a timer and a deadline. It embeds a cancelCtx to
+// implement Done and Err. It implements cancel by stopping its timer then
+// delegating to cancelCtx.cancel.
+type timerCtx struct {
+ *cancelCtx
+ timer *time.Timer // Under cancelCtx.mu.
+
+ deadline time.Time
+}
+
+func (c *timerCtx) Deadline() (deadline time.Time, ok bool) {
+ return c.deadline, true
+}
+
+func (c *timerCtx) String() string {
+ return fmt.Sprintf("%v.WithDeadline(%s [%s])", c.cancelCtx.Context, c.deadline, c.deadline.Sub(time.Now()))
+}
+
+func (c *timerCtx) cancel(removeFromParent bool, err error) {
+ c.cancelCtx.cancel(false, err)
+ if removeFromParent {
+ // Remove this timerCtx from its parent cancelCtx's children.
+ removeChild(c.cancelCtx.Context, c)
+ }
+ c.mu.Lock()
+ if c.timer != nil {
+ c.timer.Stop()
+ c.timer = nil
+ }
+ c.mu.Unlock()
+}
+
+// WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)).
+//
+// Canceling this context releases resources associated with it, so code should
+// call cancel as soon as the operations running in this Context complete:
+//
+// func slowOperationWithTimeout(ctx context.Context) (Result, error) {
+// ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
+// defer cancel() // releases resources if slowOperation completes before timeout elapses
+// return slowOperation(ctx)
+// }
+func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
+ return WithDeadline(parent, time.Now().Add(timeout))
+}
+
+// WithValue returns a copy of parent in which the value associated with key is
+// val.
+//
+// Use context Values only for request-scoped data that transits processes and
+// APIs, not for passing optional parameters to functions.
+func WithValue(parent Context, key interface{}, val interface{}) Context {
+ return &valueCtx{parent, key, val}
+}
+
+// A valueCtx carries a key-value pair. It implements Value for that key and
+// delegates all other calls to the embedded Context.
+type valueCtx struct {
+ Context
+ key, val interface{}
+}
+
+func (c *valueCtx) String() string {
+ return fmt.Sprintf("%v.WithValue(%#v, %#v)", c.Context, c.key, c.val)
+}
+
+func (c *valueCtx) Value(key interface{}) interface{} {
+ if c.key == key {
+ return c.val
+ }
+ return c.Context.Value(key)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/context/pre_go19.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/context/pre_go19.go
new file mode 100644
index 000000000..b105f80be
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/context/pre_go19.go
@@ -0,0 +1,109 @@
+// Copyright 2014 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.
+
+// +build !go1.9
+
+package context
+
+import "time"
+
+// A Context carries a deadline, a cancelation signal, and other values across
+// API boundaries.
+//
+// Context's methods may be called by multiple goroutines simultaneously.
+type Context interface {
+ // Deadline returns the time when work done on behalf of this context
+ // should be canceled. Deadline returns ok==false when no deadline is
+ // set. Successive calls to Deadline return the same results.
+ Deadline() (deadline time.Time, ok bool)
+
+ // Done returns a channel that's closed when work done on behalf of this
+ // context should be canceled. Done may return nil if this context can
+ // never be canceled. Successive calls to Done return the same value.
+ //
+ // WithCancel arranges for Done to be closed when cancel is called;
+ // WithDeadline arranges for Done to be closed when the deadline
+ // expires; WithTimeout arranges for Done to be closed when the timeout
+ // elapses.
+ //
+ // Done is provided for use in select statements:
+ //
+ // // Stream generates values with DoSomething and sends them to out
+ // // until DoSomething returns an error or ctx.Done is closed.
+ // func Stream(ctx context.Context, out chan<- Value) error {
+ // for {
+ // v, err := DoSomething(ctx)
+ // if err != nil {
+ // return err
+ // }
+ // select {
+ // case <-ctx.Done():
+ // return ctx.Err()
+ // case out <- v:
+ // }
+ // }
+ // }
+ //
+ // See http://blog.golang.org/pipelines for more examples of how to use
+ // a Done channel for cancelation.
+ Done() <-chan struct{}
+
+ // Err returns a non-nil error value after Done is closed. Err returns
+ // Canceled if the context was canceled or DeadlineExceeded if the
+ // context's deadline passed. No other values for Err are defined.
+ // After Done is closed, successive calls to Err return the same value.
+ Err() error
+
+ // Value returns the value associated with this context for key, or nil
+ // if no value is associated with key. Successive calls to Value with
+ // the same key returns the same result.
+ //
+ // Use context values only for request-scoped data that transits
+ // processes and API boundaries, not for passing optional parameters to
+ // functions.
+ //
+ // A key identifies a specific value in a Context. Functions that wish
+ // to store values in Context typically allocate a key in a global
+ // variable then use that key as the argument to context.WithValue and
+ // Context.Value. A key can be any type that supports equality;
+ // packages should define keys as an unexported type to avoid
+ // collisions.
+ //
+ // Packages that define a Context key should provide type-safe accessors
+ // for the values stores using that key:
+ //
+ // // Package user defines a User type that's stored in Contexts.
+ // package user
+ //
+ // import "golang.org/x/net/context"
+ //
+ // // User is the type of value stored in the Contexts.
+ // type User struct {...}
+ //
+ // // key is an unexported type for keys defined in this package.
+ // // This prevents collisions with keys defined in other packages.
+ // type key int
+ //
+ // // userKey is the key for user.User values in Contexts. It is
+ // // unexported; clients use user.NewContext and user.FromContext
+ // // instead of using this key directly.
+ // var userKey key = 0
+ //
+ // // NewContext returns a new Context that carries value u.
+ // func NewContext(ctx context.Context, u *User) context.Context {
+ // return context.WithValue(ctx, userKey, u)
+ // }
+ //
+ // // FromContext returns the User value stored in ctx, if any.
+ // func FromContext(ctx context.Context) (*User, bool) {
+ // u, ok := ctx.Value(userKey).(*User)
+ // return u, ok
+ // }
+ Value(key interface{}) interface{}
+}
+
+// A CancelFunc tells an operation to abandon its work.
+// A CancelFunc does not wait for the work to stop.
+// After the first call, subsequent calls to a CancelFunc do nothing.
+type CancelFunc func()
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/context/withtimeout_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/context/withtimeout_test.go
new file mode 100644
index 000000000..e6f56691d
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/context/withtimeout_test.go
@@ -0,0 +1,31 @@
+// Copyright 2014 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 context_test
+
+import (
+ "fmt"
+ "time"
+
+ "golang.org/x/net/context"
+)
+
+// This example passes a context with a timeout to tell a blocking function that
+// it should abandon its work after the timeout elapses.
+func ExampleWithTimeout() {
+ // Pass a context with a timeout to tell a blocking function that it
+ // should abandon its work after the timeout elapses.
+ ctx, cancel := context.WithTimeout(context.Background(), 50*time.Millisecond)
+ defer cancel()
+
+ select {
+ case <-time.After(1 * time.Second):
+ fmt.Println("overslept")
+ case <-ctx.Done():
+ fmt.Println(ctx.Err()) // prints "context deadline exceeded"
+ }
+
+ // Output:
+ // context deadline exceeded
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/dict/dict.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/dict/dict.go
new file mode 100644
index 000000000..93e65c03c
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/dict/dict.go
@@ -0,0 +1,210 @@
+// Copyright 2010 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 dict implements the Dictionary Server Protocol
+// as defined in RFC 2229.
+package dict // import "golang.org/x/net/dict"
+
+import (
+ "net/textproto"
+ "strconv"
+ "strings"
+)
+
+// A Client represents a client connection to a dictionary server.
+type Client struct {
+ text *textproto.Conn
+}
+
+// Dial returns a new client connected to a dictionary server at
+// addr on the given network.
+func Dial(network, addr string) (*Client, error) {
+ text, err := textproto.Dial(network, addr)
+ if err != nil {
+ return nil, err
+ }
+ _, _, err = text.ReadCodeLine(220)
+ if err != nil {
+ text.Close()
+ return nil, err
+ }
+ return &Client{text: text}, nil
+}
+
+// Close closes the connection to the dictionary server.
+func (c *Client) Close() error {
+ return c.text.Close()
+}
+
+// A Dict represents a dictionary available on the server.
+type Dict struct {
+ Name string // short name of dictionary
+ Desc string // long description
+}
+
+// Dicts returns a list of the dictionaries available on the server.
+func (c *Client) Dicts() ([]Dict, error) {
+ id, err := c.text.Cmd("SHOW DB")
+ if err != nil {
+ return nil, err
+ }
+
+ c.text.StartResponse(id)
+ defer c.text.EndResponse(id)
+
+ _, _, err = c.text.ReadCodeLine(110)
+ if err != nil {
+ return nil, err
+ }
+ lines, err := c.text.ReadDotLines()
+ if err != nil {
+ return nil, err
+ }
+ _, _, err = c.text.ReadCodeLine(250)
+
+ dicts := make([]Dict, len(lines))
+ for i := range dicts {
+ d := &dicts[i]
+ a, _ := fields(lines[i])
+ if len(a) < 2 {
+ return nil, textproto.ProtocolError("invalid dictionary: " + lines[i])
+ }
+ d.Name = a[0]
+ d.Desc = a[1]
+ }
+ return dicts, err
+}
+
+// A Defn represents a definition.
+type Defn struct {
+ Dict Dict // Dict where definition was found
+ Word string // Word being defined
+ Text []byte // Definition text, typically multiple lines
+}
+
+// Define requests the definition of the given word.
+// The argument dict names the dictionary to use,
+// the Name field of a Dict returned by Dicts.
+//
+// The special dictionary name "*" means to look in all the
+// server's dictionaries.
+// The special dictionary name "!" means to look in all the
+// server's dictionaries in turn, stopping after finding the word
+// in one of them.
+func (c *Client) Define(dict, word string) ([]*Defn, error) {
+ id, err := c.text.Cmd("DEFINE %s %q", dict, word)
+ if err != nil {
+ return nil, err
+ }
+
+ c.text.StartResponse(id)
+ defer c.text.EndResponse(id)
+
+ _, line, err := c.text.ReadCodeLine(150)
+ if err != nil {
+ return nil, err
+ }
+ a, _ := fields(line)
+ if len(a) < 1 {
+ return nil, textproto.ProtocolError("malformed response: " + line)
+ }
+ n, err := strconv.Atoi(a[0])
+ if err != nil {
+ return nil, textproto.ProtocolError("invalid definition count: " + a[0])
+ }
+ def := make([]*Defn, n)
+ for i := 0; i < n; i++ {
+ _, line, err = c.text.ReadCodeLine(151)
+ if err != nil {
+ return nil, err
+ }
+ a, _ := fields(line)
+ if len(a) < 3 {
+ // skip it, to keep protocol in sync
+ i--
+ n--
+ def = def[0:n]
+ continue
+ }
+ d := &Defn{Word: a[0], Dict: Dict{a[1], a[2]}}
+ d.Text, err = c.text.ReadDotBytes()
+ if err != nil {
+ return nil, err
+ }
+ def[i] = d
+ }
+ _, _, err = c.text.ReadCodeLine(250)
+ return def, err
+}
+
+// Fields returns the fields in s.
+// Fields are space separated unquoted words
+// or quoted with single or double quote.
+func fields(s string) ([]string, error) {
+ var v []string
+ i := 0
+ for {
+ for i < len(s) && (s[i] == ' ' || s[i] == '\t') {
+ i++
+ }
+ if i >= len(s) {
+ break
+ }
+ if s[i] == '"' || s[i] == '\'' {
+ q := s[i]
+ // quoted string
+ var j int
+ for j = i + 1; ; j++ {
+ if j >= len(s) {
+ return nil, textproto.ProtocolError("malformed quoted string")
+ }
+ if s[j] == '\\' {
+ j++
+ continue
+ }
+ if s[j] == q {
+ j++
+ break
+ }
+ }
+ v = append(v, unquote(s[i+1:j-1]))
+ i = j
+ } else {
+ // atom
+ var j int
+ for j = i; j < len(s); j++ {
+ if s[j] == ' ' || s[j] == '\t' || s[j] == '\\' || s[j] == '"' || s[j] == '\'' {
+ break
+ }
+ }
+ v = append(v, s[i:j])
+ i = j
+ }
+ if i < len(s) {
+ c := s[i]
+ if c != ' ' && c != '\t' {
+ return nil, textproto.ProtocolError("quotes not on word boundaries")
+ }
+ }
+ }
+ return v, nil
+}
+
+func unquote(s string) string {
+ if strings.Index(s, "\\") < 0 {
+ return s
+ }
+ b := []byte(s)
+ w := 0
+ for r := 0; r < len(b); r++ {
+ c := b[r]
+ if c == '\\' {
+ r++
+ c = b[r]
+ }
+ b[w] = c
+ w++
+ }
+ return string(b[0:w])
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/dns/dnsmessage/example_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/dns/dnsmessage/example_test.go
new file mode 100644
index 000000000..5415c2d3a
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/dns/dnsmessage/example_test.go
@@ -0,0 +1,132 @@
+// 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 dnsmessage_test
+
+import (
+ "fmt"
+ "net"
+ "strings"
+
+ "golang.org/x/net/dns/dnsmessage"
+)
+
+func mustNewName(name string) dnsmessage.Name {
+ n, err := dnsmessage.NewName(name)
+ if err != nil {
+ panic(err)
+ }
+ return n
+}
+
+func ExampleParser() {
+ msg := dnsmessage.Message{
+ Header: dnsmessage.Header{Response: true, Authoritative: true},
+ Questions: []dnsmessage.Question{
+ {
+ Name: mustNewName("foo.bar.example.com."),
+ Type: dnsmessage.TypeA,
+ Class: dnsmessage.ClassINET,
+ },
+ {
+ Name: mustNewName("bar.example.com."),
+ Type: dnsmessage.TypeA,
+ Class: dnsmessage.ClassINET,
+ },
+ },
+ Answers: []dnsmessage.Resource{
+ {
+ dnsmessage.ResourceHeader{
+ Name: mustNewName("foo.bar.example.com."),
+ Type: dnsmessage.TypeA,
+ Class: dnsmessage.ClassINET,
+ },
+ &dnsmessage.AResource{[4]byte{127, 0, 0, 1}},
+ },
+ {
+ dnsmessage.ResourceHeader{
+ Name: mustNewName("bar.example.com."),
+ Type: dnsmessage.TypeA,
+ Class: dnsmessage.ClassINET,
+ },
+ &dnsmessage.AResource{[4]byte{127, 0, 0, 2}},
+ },
+ },
+ }
+
+ buf, err := msg.Pack()
+ if err != nil {
+ panic(err)
+ }
+
+ wantName := "bar.example.com."
+
+ var p dnsmessage.Parser
+ if _, err := p.Start(buf); err != nil {
+ panic(err)
+ }
+
+ for {
+ q, err := p.Question()
+ if err == dnsmessage.ErrSectionDone {
+ break
+ }
+ if err != nil {
+ panic(err)
+ }
+
+ if q.Name.String() != wantName {
+ continue
+ }
+
+ fmt.Println("Found question for name", wantName)
+ if err := p.SkipAllQuestions(); err != nil {
+ panic(err)
+ }
+ break
+ }
+
+ var gotIPs []net.IP
+ for {
+ h, err := p.AnswerHeader()
+ if err == dnsmessage.ErrSectionDone {
+ break
+ }
+ if err != nil {
+ panic(err)
+ }
+
+ if (h.Type != dnsmessage.TypeA && h.Type != dnsmessage.TypeAAAA) || h.Class != dnsmessage.ClassINET {
+ continue
+ }
+
+ if !strings.EqualFold(h.Name.String(), wantName) {
+ if err := p.SkipAnswer(); err != nil {
+ panic(err)
+ }
+ continue
+ }
+
+ switch h.Type {
+ case dnsmessage.TypeA:
+ r, err := p.AResource()
+ if err != nil {
+ panic(err)
+ }
+ gotIPs = append(gotIPs, r.A[:])
+ case dnsmessage.TypeAAAA:
+ r, err := p.AAAAResource()
+ if err != nil {
+ panic(err)
+ }
+ gotIPs = append(gotIPs, r.AAAA[:])
+ }
+ }
+
+ fmt.Printf("Found A/AAAA records for name %s: %v\n", wantName, gotIPs)
+
+ // Output:
+ // Found question for name bar.example.com.
+ // Found A/AAAA records for name bar.example.com.: [127.0.0.2]
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/dns/dnsmessage/message.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/dns/dnsmessage/message.go
new file mode 100644
index 000000000..c7244b782
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/dns/dnsmessage/message.go
@@ -0,0 +1,2001 @@
+// Copyright 2009 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 provides a mostly RFC 1035 compliant implementation of
+// DNS message packing and unpacking.
+//
+// This implementation is designed to minimize heap allocations and avoid
+// unnecessary packing and unpacking as much as possible.
+package dnsmessage
+
+import (
+ "errors"
+)
+
+// Packet formats
+
+// A Type is a type of DNS request and response.
+type Type uint16
+
+// A Class is a type of network.
+type Class uint16
+
+// An OpCode is a DNS operation code.
+type OpCode uint16
+
+// An RCode is a DNS response status code.
+type RCode uint16
+
+// Wire constants.
+const (
+ // ResourceHeader.Type and Question.Type
+ TypeA Type = 1
+ TypeNS Type = 2
+ TypeCNAME Type = 5
+ TypeSOA Type = 6
+ TypePTR Type = 12
+ TypeMX Type = 15
+ TypeTXT Type = 16
+ TypeAAAA Type = 28
+ TypeSRV Type = 33
+
+ // Question.Type
+ TypeWKS Type = 11
+ TypeHINFO Type = 13
+ TypeMINFO Type = 14
+ TypeAXFR Type = 252
+ TypeALL Type = 255
+
+ // ResourceHeader.Class and Question.Class
+ ClassINET Class = 1
+ ClassCSNET Class = 2
+ ClassCHAOS Class = 3
+ ClassHESIOD Class = 4
+
+ // Question.Class
+ ClassANY Class = 255
+
+ // Message.Rcode
+ RCodeSuccess RCode = 0
+ RCodeFormatError RCode = 1
+ RCodeServerFailure RCode = 2
+ RCodeNameError RCode = 3
+ RCodeNotImplemented RCode = 4
+ RCodeRefused RCode = 5
+)
+
+var (
+ // ErrNotStarted indicates that the prerequisite information isn't
+ // available yet because the previous records haven't been appropriately
+ // parsed, skipped or finished.
+ ErrNotStarted = errors.New("parsing/packing of this type isn't available yet")
+
+ // ErrSectionDone indicated that all records in the section have been
+ // parsed or finished.
+ ErrSectionDone = errors.New("parsing/packing of this section has completed")
+
+ errBaseLen = errors.New("insufficient data for base length type")
+ errCalcLen = errors.New("insufficient data for calculated length type")
+ errReserved = errors.New("segment prefix is reserved")
+ errTooManyPtr = errors.New("too many pointers (>10)")
+ errInvalidPtr = errors.New("invalid pointer")
+ errNilResouceBody = errors.New("nil resource body")
+ errResourceLen = errors.New("insufficient data for resource body length")
+ errSegTooLong = errors.New("segment length too long")
+ errZeroSegLen = errors.New("zero length segment")
+ errResTooLong = errors.New("resource length too long")
+ errTooManyQuestions = errors.New("too many Questions to pack (>65535)")
+ errTooManyAnswers = errors.New("too many Answers to pack (>65535)")
+ errTooManyAuthorities = errors.New("too many Authorities to pack (>65535)")
+ errTooManyAdditionals = errors.New("too many Additionals to pack (>65535)")
+ errNonCanonicalName = errors.New("name is not in canonical format (it must end with a .)")
+)
+
+// Internal constants.
+const (
+ // packStartingCap is the default initial buffer size allocated during
+ // packing.
+ //
+ // The starting capacity doesn't matter too much, but most DNS responses
+ // Will be <= 512 bytes as it is the limit for DNS over UDP.
+ packStartingCap = 512
+
+ // uint16Len is the length (in bytes) of a uint16.
+ uint16Len = 2
+
+ // uint32Len is the length (in bytes) of a uint32.
+ uint32Len = 4
+
+ // headerLen is the length (in bytes) of a DNS header.
+ //
+ // A header is comprised of 6 uint16s and no padding.
+ headerLen = 6 * uint16Len
+)
+
+type nestedError struct {
+ // s is the current level's error message.
+ s string
+
+ // err is the nested error.
+ err error
+}
+
+// nestedError implements error.Error.
+func (e *nestedError) Error() string {
+ return e.s + ": " + e.err.Error()
+}
+
+// Header is a representation of a DNS message header.
+type Header struct {
+ ID uint16
+ Response bool
+ OpCode OpCode
+ Authoritative bool
+ Truncated bool
+ RecursionDesired bool
+ RecursionAvailable bool
+ RCode RCode
+}
+
+func (m *Header) pack() (id uint16, bits uint16) {
+ id = m.ID
+ bits = uint16(m.OpCode)<<11 | uint16(m.RCode)
+ if m.RecursionAvailable {
+ bits |= headerBitRA
+ }
+ if m.RecursionDesired {
+ bits |= headerBitRD
+ }
+ if m.Truncated {
+ bits |= headerBitTC
+ }
+ if m.Authoritative {
+ bits |= headerBitAA
+ }
+ if m.Response {
+ bits |= headerBitQR
+ }
+ return
+}
+
+// Message is a representation of a DNS message.
+type Message struct {
+ Header
+ Questions []Question
+ Answers []Resource
+ Authorities []Resource
+ Additionals []Resource
+}
+
+type section uint8
+
+const (
+ sectionNotStarted section = iota
+ sectionHeader
+ sectionQuestions
+ sectionAnswers
+ sectionAuthorities
+ sectionAdditionals
+ sectionDone
+
+ headerBitQR = 1 << 15 // query/response (response=1)
+ headerBitAA = 1 << 10 // authoritative
+ headerBitTC = 1 << 9 // truncated
+ headerBitRD = 1 << 8 // recursion desired
+ headerBitRA = 1 << 7 // recursion available
+)
+
+var sectionNames = map[section]string{
+ sectionHeader: "header",
+ sectionQuestions: "Question",
+ sectionAnswers: "Answer",
+ sectionAuthorities: "Authority",
+ sectionAdditionals: "Additional",
+}
+
+// header is the wire format for a DNS message header.
+type header struct {
+ id uint16
+ bits uint16
+ questions uint16
+ answers uint16
+ authorities uint16
+ additionals uint16
+}
+
+func (h *header) count(sec section) uint16 {
+ switch sec {
+ case sectionQuestions:
+ return h.questions
+ case sectionAnswers:
+ return h.answers
+ case sectionAuthorities:
+ return h.authorities
+ case sectionAdditionals:
+ return h.additionals
+ }
+ return 0
+}
+
+func (h *header) pack(msg []byte) []byte {
+ msg = packUint16(msg, h.id)
+ msg = packUint16(msg, h.bits)
+ msg = packUint16(msg, h.questions)
+ msg = packUint16(msg, h.answers)
+ msg = packUint16(msg, h.authorities)
+ return packUint16(msg, h.additionals)
+}
+
+func (h *header) unpack(msg []byte, off int) (int, error) {
+ newOff := off
+ var err error
+ if h.id, newOff, err = unpackUint16(msg, newOff); err != nil {
+ return off, &nestedError{"id", err}
+ }
+ if h.bits, newOff, err = unpackUint16(msg, newOff); err != nil {
+ return off, &nestedError{"bits", err}
+ }
+ if h.questions, newOff, err = unpackUint16(msg, newOff); err != nil {
+ return off, &nestedError{"questions", err}
+ }
+ if h.answers, newOff, err = unpackUint16(msg, newOff); err != nil {
+ return off, &nestedError{"answers", err}
+ }
+ if h.authorities, newOff, err = unpackUint16(msg, newOff); err != nil {
+ return off, &nestedError{"authorities", err}
+ }
+ if h.additionals, newOff, err = unpackUint16(msg, newOff); err != nil {
+ return off, &nestedError{"additionals", err}
+ }
+ return newOff, nil
+}
+
+func (h *header) header() Header {
+ return Header{
+ ID: h.id,
+ Response: (h.bits & headerBitQR) != 0,
+ OpCode: OpCode(h.bits>>11) & 0xF,
+ Authoritative: (h.bits & headerBitAA) != 0,
+ Truncated: (h.bits & headerBitTC) != 0,
+ RecursionDesired: (h.bits & headerBitRD) != 0,
+ RecursionAvailable: (h.bits & headerBitRA) != 0,
+ RCode: RCode(h.bits & 0xF),
+ }
+}
+
+// A Resource is a DNS resource record.
+type Resource struct {
+ Header ResourceHeader
+ Body ResourceBody
+}
+
+// A ResourceBody is a DNS resource record minus the header.
+type ResourceBody interface {
+ // pack packs a Resource except for its header.
+ pack(msg []byte, compression map[string]int) ([]byte, error)
+
+ // realType returns the actual type of the Resource. This is used to
+ // fill in the header Type field.
+ realType() Type
+}
+
+func (r *Resource) pack(msg []byte, compression map[string]int) ([]byte, error) {
+ if r.Body == nil {
+ return msg, errNilResouceBody
+ }
+ oldMsg := msg
+ r.Header.Type = r.Body.realType()
+ msg, length, err := r.Header.pack(msg, compression)
+ if err != nil {
+ return msg, &nestedError{"ResourceHeader", err}
+ }
+ preLen := len(msg)
+ msg, err = r.Body.pack(msg, compression)
+ if err != nil {
+ return msg, &nestedError{"content", err}
+ }
+ if err := r.Header.fixLen(msg, length, preLen); err != nil {
+ return oldMsg, err
+ }
+ return msg, nil
+}
+
+// A Parser allows incrementally parsing a DNS message.
+//
+// When parsing is started, the Header is parsed. Next, each Question can be
+// either parsed or skipped. Alternatively, all Questions can be skipped at
+// once. When all Questions have been parsed, attempting to parse Questions
+// will return (nil, nil) and attempting to skip Questions will return
+// (true, nil). After all Questions have been either parsed or skipped, all
+// Answers, Authorities and Additionals can be either parsed or skipped in the
+// same way, and each type of Resource must be fully parsed or skipped before
+// proceeding to the next type of Resource.
+//
+// Note that there is no requirement to fully skip or parse the message.
+type Parser struct {
+ msg []byte
+ header header
+
+ section section
+ off int
+ index int
+ resHeaderValid bool
+ resHeader ResourceHeader
+}
+
+// Start parses the header and enables the parsing of Questions.
+func (p *Parser) Start(msg []byte) (Header, error) {
+ if p.msg != nil {
+ *p = Parser{}
+ }
+ p.msg = msg
+ var err error
+ if p.off, err = p.header.unpack(msg, 0); err != nil {
+ return Header{}, &nestedError{"unpacking header", err}
+ }
+ p.section = sectionQuestions
+ return p.header.header(), nil
+}
+
+func (p *Parser) checkAdvance(sec section) error {
+ if p.section < sec {
+ return ErrNotStarted
+ }
+ if p.section > sec {
+ return ErrSectionDone
+ }
+ p.resHeaderValid = false
+ if p.index == int(p.header.count(sec)) {
+ p.index = 0
+ p.section++
+ return ErrSectionDone
+ }
+ return nil
+}
+
+func (p *Parser) resource(sec section) (Resource, error) {
+ var r Resource
+ var err error
+ r.Header, err = p.resourceHeader(sec)
+ if err != nil {
+ return r, err
+ }
+ p.resHeaderValid = false
+ r.Body, p.off, err = unpackResourceBody(p.msg, p.off, r.Header)
+ if err != nil {
+ return Resource{}, &nestedError{"unpacking " + sectionNames[sec], err}
+ }
+ p.index++
+ return r, nil
+}
+
+func (p *Parser) resourceHeader(sec section) (ResourceHeader, error) {
+ if p.resHeaderValid {
+ return p.resHeader, nil
+ }
+ if err := p.checkAdvance(sec); err != nil {
+ return ResourceHeader{}, err
+ }
+ var hdr ResourceHeader
+ off, err := hdr.unpack(p.msg, p.off)
+ if err != nil {
+ return ResourceHeader{}, err
+ }
+ p.resHeaderValid = true
+ p.resHeader = hdr
+ p.off = off
+ return hdr, nil
+}
+
+func (p *Parser) skipResource(sec section) error {
+ if p.resHeaderValid {
+ newOff := p.off + int(p.resHeader.Length)
+ if newOff > len(p.msg) {
+ return errResourceLen
+ }
+ p.off = newOff
+ p.resHeaderValid = false
+ p.index++
+ return nil
+ }
+ if err := p.checkAdvance(sec); err != nil {
+ return err
+ }
+ var err error
+ p.off, err = skipResource(p.msg, p.off)
+ if err != nil {
+ return &nestedError{"skipping: " + sectionNames[sec], err}
+ }
+ p.index++
+ return nil
+}
+
+// Question parses a single Question.
+func (p *Parser) Question() (Question, error) {
+ if err := p.checkAdvance(sectionQuestions); err != nil {
+ return Question{}, err
+ }
+ var name Name
+ off, err := name.unpack(p.msg, p.off)
+ if err != nil {
+ return Question{}, &nestedError{"unpacking Question.Name", err}
+ }
+ typ, off, err := unpackType(p.msg, off)
+ if err != nil {
+ return Question{}, &nestedError{"unpacking Question.Type", err}
+ }
+ class, off, err := unpackClass(p.msg, off)
+ if err != nil {
+ return Question{}, &nestedError{"unpacking Question.Class", err}
+ }
+ p.off = off
+ p.index++
+ return Question{name, typ, class}, nil
+}
+
+// AllQuestions parses all Questions.
+func (p *Parser) AllQuestions() ([]Question, error) {
+ qs := make([]Question, 0, p.header.questions)
+ for {
+ q, err := p.Question()
+ if err == ErrSectionDone {
+ return qs, nil
+ }
+ if err != nil {
+ return nil, err
+ }
+ qs = append(qs, q)
+ }
+}
+
+// SkipQuestion skips a single Question.
+func (p *Parser) SkipQuestion() error {
+ if err := p.checkAdvance(sectionQuestions); err != nil {
+ return err
+ }
+ off, err := skipName(p.msg, p.off)
+ if err != nil {
+ return &nestedError{"skipping Question Name", err}
+ }
+ if off, err = skipType(p.msg, off); err != nil {
+ return &nestedError{"skipping Question Type", err}
+ }
+ if off, err = skipClass(p.msg, off); err != nil {
+ return &nestedError{"skipping Question Class", err}
+ }
+ p.off = off
+ p.index++
+ return nil
+}
+
+// SkipAllQuestions skips all Questions.
+func (p *Parser) SkipAllQuestions() error {
+ for {
+ if err := p.SkipQuestion(); err == ErrSectionDone {
+ return nil
+ } else if err != nil {
+ return err
+ }
+ }
+}
+
+// AnswerHeader parses a single Answer ResourceHeader.
+func (p *Parser) AnswerHeader() (ResourceHeader, error) {
+ return p.resourceHeader(sectionAnswers)
+}
+
+// Answer parses a single Answer Resource.
+func (p *Parser) Answer() (Resource, error) {
+ return p.resource(sectionAnswers)
+}
+
+// AllAnswers parses all Answer Resources.
+func (p *Parser) AllAnswers() ([]Resource, error) {
+ as := make([]Resource, 0, p.header.answers)
+ for {
+ a, err := p.Answer()
+ if err == ErrSectionDone {
+ return as, nil
+ }
+ if err != nil {
+ return nil, err
+ }
+ as = append(as, a)
+ }
+}
+
+// SkipAnswer skips a single Answer Resource.
+func (p *Parser) SkipAnswer() error {
+ return p.skipResource(sectionAnswers)
+}
+
+// SkipAllAnswers skips all Answer Resources.
+func (p *Parser) SkipAllAnswers() error {
+ for {
+ if err := p.SkipAnswer(); err == ErrSectionDone {
+ return nil
+ } else if err != nil {
+ return err
+ }
+ }
+}
+
+// AuthorityHeader parses a single Authority ResourceHeader.
+func (p *Parser) AuthorityHeader() (ResourceHeader, error) {
+ return p.resourceHeader(sectionAuthorities)
+}
+
+// Authority parses a single Authority Resource.
+func (p *Parser) Authority() (Resource, error) {
+ return p.resource(sectionAuthorities)
+}
+
+// AllAuthorities parses all Authority Resources.
+func (p *Parser) AllAuthorities() ([]Resource, error) {
+ as := make([]Resource, 0, p.header.authorities)
+ for {
+ a, err := p.Authority()
+ if err == ErrSectionDone {
+ return as, nil
+ }
+ if err != nil {
+ return nil, err
+ }
+ as = append(as, a)
+ }
+}
+
+// SkipAuthority skips a single Authority Resource.
+func (p *Parser) SkipAuthority() error {
+ return p.skipResource(sectionAuthorities)
+}
+
+// SkipAllAuthorities skips all Authority Resources.
+func (p *Parser) SkipAllAuthorities() error {
+ for {
+ if err := p.SkipAuthority(); err == ErrSectionDone {
+ return nil
+ } else if err != nil {
+ return err
+ }
+ }
+}
+
+// AdditionalHeader parses a single Additional ResourceHeader.
+func (p *Parser) AdditionalHeader() (ResourceHeader, error) {
+ return p.resourceHeader(sectionAdditionals)
+}
+
+// Additional parses a single Additional Resource.
+func (p *Parser) Additional() (Resource, error) {
+ return p.resource(sectionAdditionals)
+}
+
+// AllAdditionals parses all Additional Resources.
+func (p *Parser) AllAdditionals() ([]Resource, error) {
+ as := make([]Resource, 0, p.header.additionals)
+ for {
+ a, err := p.Additional()
+ if err == ErrSectionDone {
+ return as, nil
+ }
+ if err != nil {
+ return nil, err
+ }
+ as = append(as, a)
+ }
+}
+
+// SkipAdditional skips a single Additional Resource.
+func (p *Parser) SkipAdditional() error {
+ return p.skipResource(sectionAdditionals)
+}
+
+// SkipAllAdditionals skips all Additional Resources.
+func (p *Parser) SkipAllAdditionals() error {
+ for {
+ if err := p.SkipAdditional(); err == ErrSectionDone {
+ return nil
+ } else if err != nil {
+ return err
+ }
+ }
+}
+
+// CNAMEResource parses a single CNAMEResource.
+//
+// One of the XXXHeader methods must have been called before calling this
+// method.
+func (p *Parser) CNAMEResource() (CNAMEResource, error) {
+ if !p.resHeaderValid || p.resHeader.Type != TypeCNAME {
+ return CNAMEResource{}, ErrNotStarted
+ }
+ r, err := unpackCNAMEResource(p.msg, p.off)
+ if err != nil {
+ return CNAMEResource{}, err
+ }
+ p.off += int(p.resHeader.Length)
+ p.resHeaderValid = false
+ p.index++
+ return r, nil
+}
+
+// MXResource parses a single MXResource.
+//
+// One of the XXXHeader methods must have been called before calling this
+// method.
+func (p *Parser) MXResource() (MXResource, error) {
+ if !p.resHeaderValid || p.resHeader.Type != TypeMX {
+ return MXResource{}, ErrNotStarted
+ }
+ r, err := unpackMXResource(p.msg, p.off)
+ if err != nil {
+ return MXResource{}, err
+ }
+ p.off += int(p.resHeader.Length)
+ p.resHeaderValid = false
+ p.index++
+ return r, nil
+}
+
+// NSResource parses a single NSResource.
+//
+// One of the XXXHeader methods must have been called before calling this
+// method.
+func (p *Parser) NSResource() (NSResource, error) {
+ if !p.resHeaderValid || p.resHeader.Type != TypeNS {
+ return NSResource{}, ErrNotStarted
+ }
+ r, err := unpackNSResource(p.msg, p.off)
+ if err != nil {
+ return NSResource{}, err
+ }
+ p.off += int(p.resHeader.Length)
+ p.resHeaderValid = false
+ p.index++
+ return r, nil
+}
+
+// PTRResource parses a single PTRResource.
+//
+// One of the XXXHeader methods must have been called before calling this
+// method.
+func (p *Parser) PTRResource() (PTRResource, error) {
+ if !p.resHeaderValid || p.resHeader.Type != TypePTR {
+ return PTRResource{}, ErrNotStarted
+ }
+ r, err := unpackPTRResource(p.msg, p.off)
+ if err != nil {
+ return PTRResource{}, err
+ }
+ p.off += int(p.resHeader.Length)
+ p.resHeaderValid = false
+ p.index++
+ return r, nil
+}
+
+// SOAResource parses a single SOAResource.
+//
+// One of the XXXHeader methods must have been called before calling this
+// method.
+func (p *Parser) SOAResource() (SOAResource, error) {
+ if !p.resHeaderValid || p.resHeader.Type != TypeSOA {
+ return SOAResource{}, ErrNotStarted
+ }
+ r, err := unpackSOAResource(p.msg, p.off)
+ if err != nil {
+ return SOAResource{}, err
+ }
+ p.off += int(p.resHeader.Length)
+ p.resHeaderValid = false
+ p.index++
+ return r, nil
+}
+
+// TXTResource parses a single TXTResource.
+//
+// One of the XXXHeader methods must have been called before calling this
+// method.
+func (p *Parser) TXTResource() (TXTResource, error) {
+ if !p.resHeaderValid || p.resHeader.Type != TypeTXT {
+ return TXTResource{}, ErrNotStarted
+ }
+ r, err := unpackTXTResource(p.msg, p.off, p.resHeader.Length)
+ if err != nil {
+ return TXTResource{}, err
+ }
+ p.off += int(p.resHeader.Length)
+ p.resHeaderValid = false
+ p.index++
+ return r, nil
+}
+
+// SRVResource parses a single SRVResource.
+//
+// One of the XXXHeader methods must have been called before calling this
+// method.
+func (p *Parser) SRVResource() (SRVResource, error) {
+ if !p.resHeaderValid || p.resHeader.Type != TypeSRV {
+ return SRVResource{}, ErrNotStarted
+ }
+ r, err := unpackSRVResource(p.msg, p.off)
+ if err != nil {
+ return SRVResource{}, err
+ }
+ p.off += int(p.resHeader.Length)
+ p.resHeaderValid = false
+ p.index++
+ return r, nil
+}
+
+// AResource parses a single AResource.
+//
+// One of the XXXHeader methods must have been called before calling this
+// method.
+func (p *Parser) AResource() (AResource, error) {
+ if !p.resHeaderValid || p.resHeader.Type != TypeA {
+ return AResource{}, ErrNotStarted
+ }
+ r, err := unpackAResource(p.msg, p.off)
+ if err != nil {
+ return AResource{}, err
+ }
+ p.off += int(p.resHeader.Length)
+ p.resHeaderValid = false
+ p.index++
+ return r, nil
+}
+
+// AAAAResource parses a single AAAAResource.
+//
+// One of the XXXHeader methods must have been called before calling this
+// method.
+func (p *Parser) AAAAResource() (AAAAResource, error) {
+ if !p.resHeaderValid || p.resHeader.Type != TypeAAAA {
+ return AAAAResource{}, ErrNotStarted
+ }
+ r, err := unpackAAAAResource(p.msg, p.off)
+ if err != nil {
+ return AAAAResource{}, err
+ }
+ p.off += int(p.resHeader.Length)
+ p.resHeaderValid = false
+ p.index++
+ return r, nil
+}
+
+// Unpack parses a full Message.
+func (m *Message) Unpack(msg []byte) error {
+ var p Parser
+ var err error
+ if m.Header, err = p.Start(msg); err != nil {
+ return err
+ }
+ if m.Questions, err = p.AllQuestions(); err != nil {
+ return err
+ }
+ if m.Answers, err = p.AllAnswers(); err != nil {
+ return err
+ }
+ if m.Authorities, err = p.AllAuthorities(); err != nil {
+ return err
+ }
+ if m.Additionals, err = p.AllAdditionals(); err != nil {
+ return err
+ }
+ return nil
+}
+
+// Pack packs a full Message.
+func (m *Message) Pack() ([]byte, error) {
+ return m.AppendPack(make([]byte, 0, packStartingCap))
+}
+
+// AppendPack is like Pack but appends the full Message to b and returns the
+// extended buffer.
+func (m *Message) AppendPack(b []byte) ([]byte, error) {
+ // Validate the lengths. It is very unlikely that anyone will try to
+ // pack more than 65535 of any particular type, but it is possible and
+ // we should fail gracefully.
+ if len(m.Questions) > int(^uint16(0)) {
+ return nil, errTooManyQuestions
+ }
+ if len(m.Answers) > int(^uint16(0)) {
+ return nil, errTooManyAnswers
+ }
+ if len(m.Authorities) > int(^uint16(0)) {
+ return nil, errTooManyAuthorities
+ }
+ if len(m.Additionals) > int(^uint16(0)) {
+ return nil, errTooManyAdditionals
+ }
+
+ var h header
+ h.id, h.bits = m.Header.pack()
+
+ h.questions = uint16(len(m.Questions))
+ h.answers = uint16(len(m.Answers))
+ h.authorities = uint16(len(m.Authorities))
+ h.additionals = uint16(len(m.Additionals))
+
+ msg := h.pack(b)
+
+ // RFC 1035 allows (but does not require) compression for packing. RFC
+ // 1035 requires unpacking implementations to support compression, so
+ // unconditionally enabling it is fine.
+ //
+ // DNS lookups are typically done over UDP, and RFC 1035 states that UDP
+ // DNS packets can be a maximum of 512 bytes long. Without compression,
+ // many DNS response packets are over this limit, so enabling
+ // compression will help ensure compliance.
+ compression := map[string]int{}
+
+ for i := range m.Questions {
+ var err error
+ if msg, err = m.Questions[i].pack(msg, compression); err != nil {
+ return nil, &nestedError{"packing Question", err}
+ }
+ }
+ for i := range m.Answers {
+ var err error
+ if msg, err = m.Answers[i].pack(msg, compression); err != nil {
+ return nil, &nestedError{"packing Answer", err}
+ }
+ }
+ for i := range m.Authorities {
+ var err error
+ if msg, err = m.Authorities[i].pack(msg, compression); err != nil {
+ return nil, &nestedError{"packing Authority", err}
+ }
+ }
+ for i := range m.Additionals {
+ var err error
+ if msg, err = m.Additionals[i].pack(msg, compression); err != nil {
+ return nil, &nestedError{"packing Additional", err}
+ }
+ }
+
+ return msg, nil
+}
+
+// A Builder allows incrementally packing a DNS message.
+type Builder struct {
+ msg []byte
+ header header
+ section section
+ compression map[string]int
+}
+
+// Start initializes the builder.
+//
+// buf is optional (nil is fine), but if provided, Start takes ownership of buf.
+func (b *Builder) Start(buf []byte, h Header) {
+ b.StartWithoutCompression(buf, h)
+ b.compression = map[string]int{}
+}
+
+// StartWithoutCompression initializes the builder with compression disabled.
+//
+// This avoids compression related allocations, but can result in larger message
+// sizes. Be careful with this mode as it can cause messages to exceed the UDP
+// size limit.
+//
+// buf is optional (nil is fine), but if provided, Start takes ownership of buf.
+func (b *Builder) StartWithoutCompression(buf []byte, h Header) {
+ *b = Builder{msg: buf}
+ b.header.id, b.header.bits = h.pack()
+ if cap(b.msg) < headerLen {
+ b.msg = make([]byte, 0, packStartingCap)
+ }
+ b.msg = b.msg[:headerLen]
+ b.section = sectionHeader
+}
+
+func (b *Builder) startCheck(s section) error {
+ if b.section <= sectionNotStarted {
+ return ErrNotStarted
+ }
+ if b.section > s {
+ return ErrSectionDone
+ }
+ return nil
+}
+
+// StartQuestions prepares the builder for packing Questions.
+func (b *Builder) StartQuestions() error {
+ if err := b.startCheck(sectionQuestions); err != nil {
+ return err
+ }
+ b.section = sectionQuestions
+ return nil
+}
+
+// StartAnswers prepares the builder for packing Answers.
+func (b *Builder) StartAnswers() error {
+ if err := b.startCheck(sectionAnswers); err != nil {
+ return err
+ }
+ b.section = sectionAnswers
+ return nil
+}
+
+// StartAuthorities prepares the builder for packing Authorities.
+func (b *Builder) StartAuthorities() error {
+ if err := b.startCheck(sectionAuthorities); err != nil {
+ return err
+ }
+ b.section = sectionAuthorities
+ return nil
+}
+
+// StartAdditionals prepares the builder for packing Additionals.
+func (b *Builder) StartAdditionals() error {
+ if err := b.startCheck(sectionAdditionals); err != nil {
+ return err
+ }
+ b.section = sectionAdditionals
+ return nil
+}
+
+func (b *Builder) incrementSectionCount() error {
+ var count *uint16
+ var err error
+ switch b.section {
+ case sectionQuestions:
+ count = &b.header.questions
+ err = errTooManyQuestions
+ case sectionAnswers:
+ count = &b.header.answers
+ err = errTooManyAnswers
+ case sectionAuthorities:
+ count = &b.header.authorities
+ err = errTooManyAuthorities
+ case sectionAdditionals:
+ count = &b.header.additionals
+ err = errTooManyAdditionals
+ }
+ if *count == ^uint16(0) {
+ return err
+ }
+ *count++
+ return nil
+}
+
+// Question adds a single Question.
+func (b *Builder) Question(q Question) error {
+ if b.section < sectionQuestions {
+ return ErrNotStarted
+ }
+ if b.section > sectionQuestions {
+ return ErrSectionDone
+ }
+ msg, err := q.pack(b.msg, b.compression)
+ if err != nil {
+ return err
+ }
+ if err := b.incrementSectionCount(); err != nil {
+ return err
+ }
+ b.msg = msg
+ return nil
+}
+
+func (b *Builder) checkResourceSection() error {
+ if b.section < sectionAnswers {
+ return ErrNotStarted
+ }
+ if b.section > sectionAdditionals {
+ return ErrSectionDone
+ }
+ return nil
+}
+
+// CNAMEResource adds a single CNAMEResource.
+func (b *Builder) CNAMEResource(h ResourceHeader, r CNAMEResource) error {
+ if err := b.checkResourceSection(); err != nil {
+ return err
+ }
+ h.Type = r.realType()
+ msg, length, err := h.pack(b.msg, b.compression)
+ if err != nil {
+ return &nestedError{"ResourceHeader", err}
+ }
+ preLen := len(msg)
+ if msg, err = r.pack(msg, b.compression); err != nil {
+ return &nestedError{"CNAMEResource body", err}
+ }
+ if err := h.fixLen(msg, length, preLen); err != nil {
+ return err
+ }
+ if err := b.incrementSectionCount(); err != nil {
+ return err
+ }
+ b.msg = msg
+ return nil
+}
+
+// MXResource adds a single MXResource.
+func (b *Builder) MXResource(h ResourceHeader, r MXResource) error {
+ if err := b.checkResourceSection(); err != nil {
+ return err
+ }
+ h.Type = r.realType()
+ msg, length, err := h.pack(b.msg, b.compression)
+ if err != nil {
+ return &nestedError{"ResourceHeader", err}
+ }
+ preLen := len(msg)
+ if msg, err = r.pack(msg, b.compression); err != nil {
+ return &nestedError{"MXResource body", err}
+ }
+ if err := h.fixLen(msg, length, preLen); err != nil {
+ return err
+ }
+ if err := b.incrementSectionCount(); err != nil {
+ return err
+ }
+ b.msg = msg
+ return nil
+}
+
+// NSResource adds a single NSResource.
+func (b *Builder) NSResource(h ResourceHeader, r NSResource) error {
+ if err := b.checkResourceSection(); err != nil {
+ return err
+ }
+ h.Type = r.realType()
+ msg, length, err := h.pack(b.msg, b.compression)
+ if err != nil {
+ return &nestedError{"ResourceHeader", err}
+ }
+ preLen := len(msg)
+ if msg, err = r.pack(msg, b.compression); err != nil {
+ return &nestedError{"NSResource body", err}
+ }
+ if err := h.fixLen(msg, length, preLen); err != nil {
+ return err
+ }
+ if err := b.incrementSectionCount(); err != nil {
+ return err
+ }
+ b.msg = msg
+ return nil
+}
+
+// PTRResource adds a single PTRResource.
+func (b *Builder) PTRResource(h ResourceHeader, r PTRResource) error {
+ if err := b.checkResourceSection(); err != nil {
+ return err
+ }
+ h.Type = r.realType()
+ msg, length, err := h.pack(b.msg, b.compression)
+ if err != nil {
+ return &nestedError{"ResourceHeader", err}
+ }
+ preLen := len(msg)
+ if msg, err = r.pack(msg, b.compression); err != nil {
+ return &nestedError{"PTRResource body", err}
+ }
+ if err := h.fixLen(msg, length, preLen); err != nil {
+ return err
+ }
+ if err := b.incrementSectionCount(); err != nil {
+ return err
+ }
+ b.msg = msg
+ return nil
+}
+
+// SOAResource adds a single SOAResource.
+func (b *Builder) SOAResource(h ResourceHeader, r SOAResource) error {
+ if err := b.checkResourceSection(); err != nil {
+ return err
+ }
+ h.Type = r.realType()
+ msg, length, err := h.pack(b.msg, b.compression)
+ if err != nil {
+ return &nestedError{"ResourceHeader", err}
+ }
+ preLen := len(msg)
+ if msg, err = r.pack(msg, b.compression); err != nil {
+ return &nestedError{"SOAResource body", err}
+ }
+ if err := h.fixLen(msg, length, preLen); err != nil {
+ return err
+ }
+ if err := b.incrementSectionCount(); err != nil {
+ return err
+ }
+ b.msg = msg
+ return nil
+}
+
+// TXTResource adds a single TXTResource.
+func (b *Builder) TXTResource(h ResourceHeader, r TXTResource) error {
+ if err := b.checkResourceSection(); err != nil {
+ return err
+ }
+ h.Type = r.realType()
+ msg, length, err := h.pack(b.msg, b.compression)
+ if err != nil {
+ return &nestedError{"ResourceHeader", err}
+ }
+ preLen := len(msg)
+ if msg, err = r.pack(msg, b.compression); err != nil {
+ return &nestedError{"TXTResource body", err}
+ }
+ if err := h.fixLen(msg, length, preLen); err != nil {
+ return err
+ }
+ if err := b.incrementSectionCount(); err != nil {
+ return err
+ }
+ b.msg = msg
+ return nil
+}
+
+// SRVResource adds a single SRVResource.
+func (b *Builder) SRVResource(h ResourceHeader, r SRVResource) error {
+ if err := b.checkResourceSection(); err != nil {
+ return err
+ }
+ h.Type = r.realType()
+ msg, length, err := h.pack(b.msg, b.compression)
+ if err != nil {
+ return &nestedError{"ResourceHeader", err}
+ }
+ preLen := len(msg)
+ if msg, err = r.pack(msg, b.compression); err != nil {
+ return &nestedError{"SRVResource body", err}
+ }
+ if err := h.fixLen(msg, length, preLen); err != nil {
+ return err
+ }
+ if err := b.incrementSectionCount(); err != nil {
+ return err
+ }
+ b.msg = msg
+ return nil
+}
+
+// AResource adds a single AResource.
+func (b *Builder) AResource(h ResourceHeader, r AResource) error {
+ if err := b.checkResourceSection(); err != nil {
+ return err
+ }
+ h.Type = r.realType()
+ msg, length, err := h.pack(b.msg, b.compression)
+ if err != nil {
+ return &nestedError{"ResourceHeader", err}
+ }
+ preLen := len(msg)
+ if msg, err = r.pack(msg, b.compression); err != nil {
+ return &nestedError{"AResource body", err}
+ }
+ if err := h.fixLen(msg, length, preLen); err != nil {
+ return err
+ }
+ if err := b.incrementSectionCount(); err != nil {
+ return err
+ }
+ b.msg = msg
+ return nil
+}
+
+// AAAAResource adds a single AAAAResource.
+func (b *Builder) AAAAResource(h ResourceHeader, r AAAAResource) error {
+ if err := b.checkResourceSection(); err != nil {
+ return err
+ }
+ h.Type = r.realType()
+ msg, length, err := h.pack(b.msg, b.compression)
+ if err != nil {
+ return &nestedError{"ResourceHeader", err}
+ }
+ preLen := len(msg)
+ if msg, err = r.pack(msg, b.compression); err != nil {
+ return &nestedError{"AAAAResource body", err}
+ }
+ if err := h.fixLen(msg, length, preLen); err != nil {
+ return err
+ }
+ if err := b.incrementSectionCount(); err != nil {
+ return err
+ }
+ b.msg = msg
+ return nil
+}
+
+// Finish ends message building and generates a binary packet.
+func (b *Builder) Finish() ([]byte, error) {
+ if b.section < sectionHeader {
+ return nil, ErrNotStarted
+ }
+ b.section = sectionDone
+ b.header.pack(b.msg[:0])
+ return b.msg, nil
+}
+
+// A ResourceHeader is the header of a DNS resource record. There are
+// many types of DNS resource records, but they all share the same header.
+type ResourceHeader struct {
+ // Name is the domain name for which this resource record pertains.
+ Name Name
+
+ // Type is the type of DNS resource record.
+ //
+ // This field will be set automatically during packing.
+ Type Type
+
+ // Class is the class of network to which this DNS resource record
+ // pertains.
+ Class Class
+
+ // TTL is the length of time (measured in seconds) which this resource
+ // record is valid for (time to live). All Resources in a set should
+ // have the same TTL (RFC 2181 Section 5.2).
+ TTL uint32
+
+ // Length is the length of data in the resource record after the header.
+ //
+ // This field will be set automatically during packing.
+ Length uint16
+}
+
+// pack packs all of the fields in a ResourceHeader except for the length. The
+// length bytes are returned as a slice so they can be filled in after the rest
+// of the Resource has been packed.
+func (h *ResourceHeader) pack(oldMsg []byte, compression map[string]int) (msg []byte, length []byte, err error) {
+ msg = oldMsg
+ if msg, err = h.Name.pack(msg, compression); err != nil {
+ return oldMsg, nil, &nestedError{"Name", err}
+ }
+ msg = packType(msg, h.Type)
+ msg = packClass(msg, h.Class)
+ msg = packUint32(msg, h.TTL)
+ lenBegin := len(msg)
+ msg = packUint16(msg, h.Length)
+ return msg, msg[lenBegin : lenBegin+uint16Len], nil
+}
+
+func (h *ResourceHeader) unpack(msg []byte, off int) (int, error) {
+ newOff := off
+ var err error
+ if newOff, err = h.Name.unpack(msg, newOff); err != nil {
+ return off, &nestedError{"Name", err}
+ }
+ if h.Type, newOff, err = unpackType(msg, newOff); err != nil {
+ return off, &nestedError{"Type", err}
+ }
+ if h.Class, newOff, err = unpackClass(msg, newOff); err != nil {
+ return off, &nestedError{"Class", err}
+ }
+ if h.TTL, newOff, err = unpackUint32(msg, newOff); err != nil {
+ return off, &nestedError{"TTL", err}
+ }
+ if h.Length, newOff, err = unpackUint16(msg, newOff); err != nil {
+ return off, &nestedError{"Length", err}
+ }
+ return newOff, nil
+}
+
+func (h *ResourceHeader) fixLen(msg []byte, length []byte, preLen int) error {
+ conLen := len(msg) - preLen
+ if conLen > int(^uint16(0)) {
+ return errResTooLong
+ }
+
+ // Fill in the length now that we know how long the content is.
+ packUint16(length[:0], uint16(conLen))
+ h.Length = uint16(conLen)
+
+ return nil
+}
+
+func skipResource(msg []byte, off int) (int, error) {
+ newOff, err := skipName(msg, off)
+ if err != nil {
+ return off, &nestedError{"Name", err}
+ }
+ if newOff, err = skipType(msg, newOff); err != nil {
+ return off, &nestedError{"Type", err}
+ }
+ if newOff, err = skipClass(msg, newOff); err != nil {
+ return off, &nestedError{"Class", err}
+ }
+ if newOff, err = skipUint32(msg, newOff); err != nil {
+ return off, &nestedError{"TTL", err}
+ }
+ length, newOff, err := unpackUint16(msg, newOff)
+ if err != nil {
+ return off, &nestedError{"Length", err}
+ }
+ if newOff += int(length); newOff > len(msg) {
+ return off, errResourceLen
+ }
+ return newOff, nil
+}
+
+func packUint16(msg []byte, field uint16) []byte {
+ return append(msg, byte(field>>8), byte(field))
+}
+
+func unpackUint16(msg []byte, off int) (uint16, int, error) {
+ if off+uint16Len > len(msg) {
+ return 0, off, errBaseLen
+ }
+ return uint16(msg[off])<<8 | uint16(msg[off+1]), off + uint16Len, nil
+}
+
+func skipUint16(msg []byte, off int) (int, error) {
+ if off+uint16Len > len(msg) {
+ return off, errBaseLen
+ }
+ return off + uint16Len, nil
+}
+
+func packType(msg []byte, field Type) []byte {
+ return packUint16(msg, uint16(field))
+}
+
+func unpackType(msg []byte, off int) (Type, int, error) {
+ t, o, err := unpackUint16(msg, off)
+ return Type(t), o, err
+}
+
+func skipType(msg []byte, off int) (int, error) {
+ return skipUint16(msg, off)
+}
+
+func packClass(msg []byte, field Class) []byte {
+ return packUint16(msg, uint16(field))
+}
+
+func unpackClass(msg []byte, off int) (Class, int, error) {
+ c, o, err := unpackUint16(msg, off)
+ return Class(c), o, err
+}
+
+func skipClass(msg []byte, off int) (int, error) {
+ return skipUint16(msg, off)
+}
+
+func packUint32(msg []byte, field uint32) []byte {
+ return append(
+ msg,
+ byte(field>>24),
+ byte(field>>16),
+ byte(field>>8),
+ byte(field),
+ )
+}
+
+func unpackUint32(msg []byte, off int) (uint32, int, error) {
+ if off+uint32Len > len(msg) {
+ return 0, off, errBaseLen
+ }
+ v := uint32(msg[off])<<24 | uint32(msg[off+1])<<16 | uint32(msg[off+2])<<8 | uint32(msg[off+3])
+ return v, off + uint32Len, nil
+}
+
+func skipUint32(msg []byte, off int) (int, error) {
+ if off+uint32Len > len(msg) {
+ return off, errBaseLen
+ }
+ return off + uint32Len, nil
+}
+
+func packText(msg []byte, field string) []byte {
+ for len(field) > 0 {
+ l := len(field)
+ if l > 255 {
+ l = 255
+ }
+ msg = append(msg, byte(l))
+ msg = append(msg, field[:l]...)
+ field = field[l:]
+ }
+ return msg
+}
+
+func unpackText(msg []byte, off int) (string, int, error) {
+ if off >= len(msg) {
+ return "", off, errBaseLen
+ }
+ beginOff := off + 1
+ endOff := beginOff + int(msg[off])
+ if endOff > len(msg) {
+ return "", off, errCalcLen
+ }
+ return string(msg[beginOff:endOff]), endOff, nil
+}
+
+func skipText(msg []byte, off int) (int, error) {
+ if off >= len(msg) {
+ return off, errBaseLen
+ }
+ endOff := off + 1 + int(msg[off])
+ if endOff > len(msg) {
+ return off, errCalcLen
+ }
+ return endOff, nil
+}
+
+func packBytes(msg []byte, field []byte) []byte {
+ return append(msg, field...)
+}
+
+func unpackBytes(msg []byte, off int, field []byte) (int, error) {
+ newOff := off + len(field)
+ if newOff > len(msg) {
+ return off, errBaseLen
+ }
+ copy(field, msg[off:newOff])
+ return newOff, nil
+}
+
+func skipBytes(msg []byte, off int, field []byte) (int, error) {
+ newOff := off + len(field)
+ if newOff > len(msg) {
+ return off, errBaseLen
+ }
+ return newOff, nil
+}
+
+const nameLen = 255
+
+// A Name is a non-encoded domain name. It is used instead of strings to avoid
+// allocations.
+type Name struct {
+ Data [nameLen]byte
+ Length uint8
+}
+
+// NewName creates a new Name from a string.
+func NewName(name string) (Name, error) {
+ if len([]byte(name)) > nameLen {
+ return Name{}, errCalcLen
+ }
+ n := Name{Length: uint8(len(name))}
+ copy(n.Data[:], []byte(name))
+ return n, nil
+}
+
+func (n Name) String() string {
+ return string(n.Data[:n.Length])
+}
+
+// pack packs a domain name.
+//
+// Domain names are a sequence of counted strings split at the dots. They end
+// with a zero-length string. Compression can be used to reuse domain suffixes.
+//
+// The compression map will be updated with new domain suffixes. If compression
+// is nil, compression will not be used.
+func (n *Name) pack(msg []byte, compression map[string]int) ([]byte, error) {
+ oldMsg := msg
+
+ // Add a trailing dot to canonicalize name.
+ if n.Length == 0 || n.Data[n.Length-1] != '.' {
+ return oldMsg, errNonCanonicalName
+ }
+
+ // Allow root domain.
+ if n.Data[0] == '.' && n.Length == 1 {
+ return append(msg, 0), nil
+ }
+
+ // Emit sequence of counted strings, chopping at dots.
+ for i, begin := 0, 0; i < int(n.Length); i++ {
+ // Check for the end of the segment.
+ if n.Data[i] == '.' {
+ // The two most significant bits have special meaning.
+ // It isn't allowed for segments to be long enough to
+ // need them.
+ if i-begin >= 1<<6 {
+ return oldMsg, errSegTooLong
+ }
+
+ // Segments must have a non-zero length.
+ if i-begin == 0 {
+ return oldMsg, errZeroSegLen
+ }
+
+ msg = append(msg, byte(i-begin))
+
+ for j := begin; j < i; j++ {
+ msg = append(msg, n.Data[j])
+ }
+
+ begin = i + 1
+ continue
+ }
+
+ // We can only compress domain suffixes starting with a new
+ // segment. A pointer is two bytes with the two most significant
+ // bits set to 1 to indicate that it is a pointer.
+ if (i == 0 || n.Data[i-1] == '.') && compression != nil {
+ if ptr, ok := compression[string(n.Data[i:])]; ok {
+ // Hit. Emit a pointer instead of the rest of
+ // the domain.
+ return append(msg, byte(ptr>>8|0xC0), byte(ptr)), nil
+ }
+
+ // Miss. Add the suffix to the compression table if the
+ // offset can be stored in the available 14 bytes.
+ if len(msg) <= int(^uint16(0)>>2) {
+ compression[string(n.Data[i:])] = len(msg)
+ }
+ }
+ }
+ return append(msg, 0), nil
+}
+
+// unpack unpacks a domain name.
+func (n *Name) unpack(msg []byte, off int) (int, error) {
+ // currOff is the current working offset.
+ currOff := off
+
+ // newOff is the offset where the next record will start. Pointers lead
+ // to data that belongs to other names and thus doesn't count towards to
+ // the usage of this name.
+ newOff := off
+
+ // ptr is the number of pointers followed.
+ var ptr int
+
+ // Name is a slice representation of the name data.
+ name := n.Data[:0]
+
+Loop:
+ for {
+ if currOff >= len(msg) {
+ return off, errBaseLen
+ }
+ c := int(msg[currOff])
+ currOff++
+ switch c & 0xC0 {
+ case 0x00: // String segment
+ if c == 0x00 {
+ // A zero length signals the end of the name.
+ break Loop
+ }
+ endOff := currOff + c
+ if endOff > len(msg) {
+ return off, errCalcLen
+ }
+ name = append(name, msg[currOff:endOff]...)
+ name = append(name, '.')
+ currOff = endOff
+ case 0xC0: // Pointer
+ if currOff >= len(msg) {
+ return off, errInvalidPtr
+ }
+ c1 := msg[currOff]
+ currOff++
+ if ptr == 0 {
+ newOff = currOff
+ }
+ // Don't follow too many pointers, maybe there's a loop.
+ if ptr++; ptr > 10 {
+ return off, errTooManyPtr
+ }
+ currOff = (c^0xC0)<<8 | int(c1)
+ default:
+ // Prefixes 0x80 and 0x40 are reserved.
+ return off, errReserved
+ }
+ }
+ if len(name) == 0 {
+ name = append(name, '.')
+ }
+ if len(name) > len(n.Data) {
+ return off, errCalcLen
+ }
+ n.Length = uint8(len(name))
+ if ptr == 0 {
+ newOff = currOff
+ }
+ return newOff, nil
+}
+
+func skipName(msg []byte, off int) (int, error) {
+ // newOff is the offset where the next record will start. Pointers lead
+ // to data that belongs to other names and thus doesn't count towards to
+ // the usage of this name.
+ newOff := off
+
+Loop:
+ for {
+ if newOff >= len(msg) {
+ return off, errBaseLen
+ }
+ c := int(msg[newOff])
+ newOff++
+ switch c & 0xC0 {
+ case 0x00:
+ if c == 0x00 {
+ // A zero length signals the end of the name.
+ break Loop
+ }
+ // literal string
+ newOff += c
+ if newOff > len(msg) {
+ return off, errCalcLen
+ }
+ case 0xC0:
+ // Pointer to somewhere else in msg.
+
+ // Pointers are two bytes.
+ newOff++
+
+ // Don't follow the pointer as the data here has ended.
+ break Loop
+ default:
+ // Prefixes 0x80 and 0x40 are reserved.
+ return off, errReserved
+ }
+ }
+
+ return newOff, nil
+}
+
+// A Question is a DNS query.
+type Question struct {
+ Name Name
+ Type Type
+ Class Class
+}
+
+func (q *Question) pack(msg []byte, compression map[string]int) ([]byte, error) {
+ msg, err := q.Name.pack(msg, compression)
+ if err != nil {
+ return msg, &nestedError{"Name", err}
+ }
+ msg = packType(msg, q.Type)
+ return packClass(msg, q.Class), nil
+}
+
+func unpackResourceBody(msg []byte, off int, hdr ResourceHeader) (ResourceBody, int, error) {
+ var (
+ r ResourceBody
+ err error
+ name string
+ )
+ switch hdr.Type {
+ case TypeA:
+ var rb AResource
+ rb, err = unpackAResource(msg, off)
+ r = &rb
+ name = "A"
+ case TypeNS:
+ var rb NSResource
+ rb, err = unpackNSResource(msg, off)
+ r = &rb
+ name = "NS"
+ case TypeCNAME:
+ var rb CNAMEResource
+ rb, err = unpackCNAMEResource(msg, off)
+ r = &rb
+ name = "CNAME"
+ case TypeSOA:
+ var rb SOAResource
+ rb, err = unpackSOAResource(msg, off)
+ r = &rb
+ name = "SOA"
+ case TypePTR:
+ var rb PTRResource
+ rb, err = unpackPTRResource(msg, off)
+ r = &rb
+ name = "PTR"
+ case TypeMX:
+ var rb MXResource
+ rb, err = unpackMXResource(msg, off)
+ r = &rb
+ name = "MX"
+ case TypeTXT:
+ var rb TXTResource
+ rb, err = unpackTXTResource(msg, off, hdr.Length)
+ r = &rb
+ name = "TXT"
+ case TypeAAAA:
+ var rb AAAAResource
+ rb, err = unpackAAAAResource(msg, off)
+ r = &rb
+ name = "AAAA"
+ case TypeSRV:
+ var rb SRVResource
+ rb, err = unpackSRVResource(msg, off)
+ r = &rb
+ name = "SRV"
+ }
+ if err != nil {
+ return nil, off, &nestedError{name + " record", err}
+ }
+ if r == nil {
+ return nil, off, errors.New("invalid resource type: " + string(hdr.Type+'0'))
+ }
+ return r, off + int(hdr.Length), nil
+}
+
+// A CNAMEResource is a CNAME Resource record.
+type CNAMEResource struct {
+ CNAME Name
+}
+
+func (r *CNAMEResource) realType() Type {
+ return TypeCNAME
+}
+
+func (r *CNAMEResource) pack(msg []byte, compression map[string]int) ([]byte, error) {
+ return r.CNAME.pack(msg, compression)
+}
+
+func unpackCNAMEResource(msg []byte, off int) (CNAMEResource, error) {
+ var cname Name
+ if _, err := cname.unpack(msg, off); err != nil {
+ return CNAMEResource{}, err
+ }
+ return CNAMEResource{cname}, nil
+}
+
+// An MXResource is an MX Resource record.
+type MXResource struct {
+ Pref uint16
+ MX Name
+}
+
+func (r *MXResource) realType() Type {
+ return TypeMX
+}
+
+func (r *MXResource) pack(msg []byte, compression map[string]int) ([]byte, error) {
+ oldMsg := msg
+ msg = packUint16(msg, r.Pref)
+ msg, err := r.MX.pack(msg, compression)
+ if err != nil {
+ return oldMsg, &nestedError{"MXResource.MX", err}
+ }
+ return msg, nil
+}
+
+func unpackMXResource(msg []byte, off int) (MXResource, error) {
+ pref, off, err := unpackUint16(msg, off)
+ if err != nil {
+ return MXResource{}, &nestedError{"Pref", err}
+ }
+ var mx Name
+ if _, err := mx.unpack(msg, off); err != nil {
+ return MXResource{}, &nestedError{"MX", err}
+ }
+ return MXResource{pref, mx}, nil
+}
+
+// An NSResource is an NS Resource record.
+type NSResource struct {
+ NS Name
+}
+
+func (r *NSResource) realType() Type {
+ return TypeNS
+}
+
+func (r *NSResource) pack(msg []byte, compression map[string]int) ([]byte, error) {
+ return r.NS.pack(msg, compression)
+}
+
+func unpackNSResource(msg []byte, off int) (NSResource, error) {
+ var ns Name
+ if _, err := ns.unpack(msg, off); err != nil {
+ return NSResource{}, err
+ }
+ return NSResource{ns}, nil
+}
+
+// A PTRResource is a PTR Resource record.
+type PTRResource struct {
+ PTR Name
+}
+
+func (r *PTRResource) realType() Type {
+ return TypePTR
+}
+
+func (r *PTRResource) pack(msg []byte, compression map[string]int) ([]byte, error) {
+ return r.PTR.pack(msg, compression)
+}
+
+func unpackPTRResource(msg []byte, off int) (PTRResource, error) {
+ var ptr Name
+ if _, err := ptr.unpack(msg, off); err != nil {
+ return PTRResource{}, err
+ }
+ return PTRResource{ptr}, nil
+}
+
+// An SOAResource is an SOA Resource record.
+type SOAResource struct {
+ NS Name
+ MBox Name
+ Serial uint32
+ Refresh uint32
+ Retry uint32
+ Expire uint32
+
+ // MinTTL the is the default TTL of Resources records which did not
+ // contain a TTL value and the TTL of negative responses. (RFC 2308
+ // Section 4)
+ MinTTL uint32
+}
+
+func (r *SOAResource) realType() Type {
+ return TypeSOA
+}
+
+func (r *SOAResource) pack(msg []byte, compression map[string]int) ([]byte, error) {
+ oldMsg := msg
+ msg, err := r.NS.pack(msg, compression)
+ if err != nil {
+ return oldMsg, &nestedError{"SOAResource.NS", err}
+ }
+ msg, err = r.MBox.pack(msg, compression)
+ if err != nil {
+ return oldMsg, &nestedError{"SOAResource.MBox", err}
+ }
+ msg = packUint32(msg, r.Serial)
+ msg = packUint32(msg, r.Refresh)
+ msg = packUint32(msg, r.Retry)
+ msg = packUint32(msg, r.Expire)
+ return packUint32(msg, r.MinTTL), nil
+}
+
+func unpackSOAResource(msg []byte, off int) (SOAResource, error) {
+ var ns Name
+ off, err := ns.unpack(msg, off)
+ if err != nil {
+ return SOAResource{}, &nestedError{"NS", err}
+ }
+ var mbox Name
+ if off, err = mbox.unpack(msg, off); err != nil {
+ return SOAResource{}, &nestedError{"MBox", err}
+ }
+ serial, off, err := unpackUint32(msg, off)
+ if err != nil {
+ return SOAResource{}, &nestedError{"Serial", err}
+ }
+ refresh, off, err := unpackUint32(msg, off)
+ if err != nil {
+ return SOAResource{}, &nestedError{"Refresh", err}
+ }
+ retry, off, err := unpackUint32(msg, off)
+ if err != nil {
+ return SOAResource{}, &nestedError{"Retry", err}
+ }
+ expire, off, err := unpackUint32(msg, off)
+ if err != nil {
+ return SOAResource{}, &nestedError{"Expire", err}
+ }
+ minTTL, _, err := unpackUint32(msg, off)
+ if err != nil {
+ return SOAResource{}, &nestedError{"MinTTL", err}
+ }
+ return SOAResource{ns, mbox, serial, refresh, retry, expire, minTTL}, nil
+}
+
+// A TXTResource is a TXT Resource record.
+type TXTResource struct {
+ Txt string // Not a domain name.
+}
+
+func (r *TXTResource) realType() Type {
+ return TypeTXT
+}
+
+func (r *TXTResource) pack(msg []byte, compression map[string]int) ([]byte, error) {
+ return packText(msg, r.Txt), nil
+}
+
+func unpackTXTResource(msg []byte, off int, length uint16) (TXTResource, error) {
+ var txt string
+ for n := uint16(0); n < length; {
+ var t string
+ var err error
+ if t, off, err = unpackText(msg, off); err != nil {
+ return TXTResource{}, &nestedError{"text", err}
+ }
+ // Check if we got too many bytes.
+ if length-n < uint16(len(t))+1 {
+ return TXTResource{}, errCalcLen
+ }
+ n += uint16(len(t)) + 1
+ txt += t
+ }
+ return TXTResource{txt}, nil
+}
+
+// An SRVResource is an SRV Resource record.
+type SRVResource struct {
+ Priority uint16
+ Weight uint16
+ Port uint16
+ Target Name // Not compressed as per RFC 2782.
+}
+
+func (r *SRVResource) realType() Type {
+ return TypeSRV
+}
+
+func (r *SRVResource) pack(msg []byte, compression map[string]int) ([]byte, error) {
+ oldMsg := msg
+ msg = packUint16(msg, r.Priority)
+ msg = packUint16(msg, r.Weight)
+ msg = packUint16(msg, r.Port)
+ msg, err := r.Target.pack(msg, nil)
+ if err != nil {
+ return oldMsg, &nestedError{"SRVResource.Target", err}
+ }
+ return msg, nil
+}
+
+func unpackSRVResource(msg []byte, off int) (SRVResource, error) {
+ priority, off, err := unpackUint16(msg, off)
+ if err != nil {
+ return SRVResource{}, &nestedError{"Priority", err}
+ }
+ weight, off, err := unpackUint16(msg, off)
+ if err != nil {
+ return SRVResource{}, &nestedError{"Weight", err}
+ }
+ port, off, err := unpackUint16(msg, off)
+ if err != nil {
+ return SRVResource{}, &nestedError{"Port", err}
+ }
+ var target Name
+ if _, err := target.unpack(msg, off); err != nil {
+ return SRVResource{}, &nestedError{"Target", err}
+ }
+ return SRVResource{priority, weight, port, target}, nil
+}
+
+// An AResource is an A Resource record.
+type AResource struct {
+ A [4]byte
+}
+
+func (r *AResource) realType() Type {
+ return TypeA
+}
+
+func (r *AResource) pack(msg []byte, compression map[string]int) ([]byte, error) {
+ return packBytes(msg, r.A[:]), nil
+}
+
+func unpackAResource(msg []byte, off int) (AResource, error) {
+ var a [4]byte
+ if _, err := unpackBytes(msg, off, a[:]); err != nil {
+ return AResource{}, err
+ }
+ return AResource{a}, nil
+}
+
+// An AAAAResource is an AAAA Resource record.
+type AAAAResource struct {
+ AAAA [16]byte
+}
+
+func (r *AAAAResource) realType() Type {
+ return TypeAAAA
+}
+
+func (r *AAAAResource) pack(msg []byte, compression map[string]int) ([]byte, error) {
+ return packBytes(msg, r.AAAA[:]), nil
+}
+
+func unpackAAAAResource(msg []byte, off int) (AAAAResource, error) {
+ var aaaa [16]byte
+ if _, err := unpackBytes(msg, off, aaaa[:]); err != nil {
+ return AAAAResource{}, err
+ }
+ return AAAAResource{aaaa}, nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/dns/dnsmessage/message_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/dns/dnsmessage/message_test.go
new file mode 100644
index 000000000..2bb763420
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/dns/dnsmessage/message_test.go
@@ -0,0 +1,1141 @@
+// Copyright 2009 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 (
+ "bytes"
+ "fmt"
+ "reflect"
+ "testing"
+)
+
+func mustNewName(name string) Name {
+ n, err := NewName(name)
+ if err != nil {
+ panic(err)
+ }
+ return n
+}
+
+func (m *Message) String() string {
+ s := fmt.Sprintf("Message: %#v\n", &m.Header)
+ if len(m.Questions) > 0 {
+ s += "-- Questions\n"
+ for _, q := range m.Questions {
+ s += fmt.Sprintf("%#v\n", q)
+ }
+ }
+ if len(m.Answers) > 0 {
+ s += "-- Answers\n"
+ for _, a := range m.Answers {
+ s += fmt.Sprintf("%#v\n", a)
+ }
+ }
+ if len(m.Authorities) > 0 {
+ s += "-- Authorities\n"
+ for _, ns := range m.Authorities {
+ s += fmt.Sprintf("%#v\n", ns)
+ }
+ }
+ if len(m.Additionals) > 0 {
+ s += "-- Additionals\n"
+ for _, e := range m.Additionals {
+ s += fmt.Sprintf("%#v\n", e)
+ }
+ }
+ return s
+}
+
+func TestNameString(t *testing.T) {
+ want := "foo"
+ name := mustNewName(want)
+ if got := fmt.Sprint(name); got != want {
+ t.Errorf("got fmt.Sprint(%#v) = %s, want = %s", name, got, want)
+ }
+}
+
+func TestQuestionPackUnpack(t *testing.T) {
+ want := Question{
+ Name: mustNewName("."),
+ Type: TypeA,
+ Class: ClassINET,
+ }
+ buf, err := want.pack(make([]byte, 1, 50), map[string]int{})
+ if err != nil {
+ t.Fatal("Packing failed:", err)
+ }
+ var p Parser
+ p.msg = buf
+ p.header.questions = 1
+ p.section = sectionQuestions
+ p.off = 1
+ got, err := p.Question()
+ if err != nil {
+ t.Fatalf("Unpacking failed: %v\n%s", err, string(buf[1:]))
+ }
+ if p.off != len(buf) {
+ t.Errorf("Unpacked different amount than packed: got n = %d, want = %d", p.off, len(buf))
+ }
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("Got = %+v, want = %+v", got, want)
+ }
+}
+
+func TestName(t *testing.T) {
+ tests := []string{
+ "",
+ ".",
+ "google..com",
+ "google.com",
+ "google..com.",
+ "google.com.",
+ ".google.com.",
+ "www..google.com.",
+ "www.google.com.",
+ }
+
+ for _, test := range tests {
+ n, err := NewName(test)
+ if err != nil {
+ t.Errorf("Creating name for %q: %v", test, err)
+ continue
+ }
+ if ns := n.String(); ns != test {
+ t.Errorf("Got %#v.String() = %q, want = %q", n, ns, test)
+ continue
+ }
+ }
+}
+
+func TestNamePackUnpack(t *testing.T) {
+ tests := []struct {
+ in string
+ want string
+ err error
+ }{
+ {"", "", errNonCanonicalName},
+ {".", ".", nil},
+ {"google..com", "", errNonCanonicalName},
+ {"google.com", "", errNonCanonicalName},
+ {"google..com.", "", errZeroSegLen},
+ {"google.com.", "google.com.", nil},
+ {".google.com.", "", errZeroSegLen},
+ {"www..google.com.", "", errZeroSegLen},
+ {"www.google.com.", "www.google.com.", nil},
+ }
+
+ for _, test := range tests {
+ in := mustNewName(test.in)
+ want := mustNewName(test.want)
+ buf, err := in.pack(make([]byte, 0, 30), map[string]int{})
+ if err != test.err {
+ t.Errorf("Packing of %q: got err = %v, want err = %v", test.in, err, test.err)
+ continue
+ }
+ if test.err != nil {
+ continue
+ }
+ var got Name
+ n, err := got.unpack(buf, 0)
+ if err != nil {
+ t.Errorf("Unpacking for %q failed: %v", test.in, err)
+ continue
+ }
+ if n != len(buf) {
+ t.Errorf(
+ "Unpacked different amount than packed for %q: got n = %d, want = %d",
+ test.in,
+ n,
+ len(buf),
+ )
+ }
+ if got != want {
+ t.Errorf("Unpacking packing of %q: got = %#v, want = %#v", test.in, got, want)
+ }
+ }
+}
+
+func checkErrorPrefix(err error, prefix string) bool {
+ e, ok := err.(*nestedError)
+ return ok && e.s == prefix
+}
+
+func TestHeaderUnpackError(t *testing.T) {
+ wants := []string{
+ "id",
+ "bits",
+ "questions",
+ "answers",
+ "authorities",
+ "additionals",
+ }
+ var buf []byte
+ var h header
+ for _, want := range wants {
+ n, err := h.unpack(buf, 0)
+ if n != 0 || !checkErrorPrefix(err, want) {
+ t.Errorf("got h.unpack([%d]byte, 0) = %d, %v, want = 0, %s", len(buf), n, err, want)
+ }
+ buf = append(buf, 0, 0)
+ }
+}
+
+func TestParserStart(t *testing.T) {
+ const want = "unpacking header"
+ var p Parser
+ for i := 0; i <= 1; i++ {
+ _, err := p.Start([]byte{})
+ if !checkErrorPrefix(err, want) {
+ t.Errorf("got p.Start(nil) = _, %v, want = _, %s", err, want)
+ }
+ }
+}
+
+func TestResourceNotStarted(t *testing.T) {
+ tests := []struct {
+ name string
+ fn func(*Parser) error
+ }{
+ {"CNAMEResource", func(p *Parser) error { _, err := p.CNAMEResource(); return err }},
+ {"MXResource", func(p *Parser) error { _, err := p.MXResource(); return err }},
+ {"NSResource", func(p *Parser) error { _, err := p.NSResource(); return err }},
+ {"PTRResource", func(p *Parser) error { _, err := p.PTRResource(); return err }},
+ {"SOAResource", func(p *Parser) error { _, err := p.SOAResource(); return err }},
+ {"TXTResource", func(p *Parser) error { _, err := p.TXTResource(); return err }},
+ {"SRVResource", func(p *Parser) error { _, err := p.SRVResource(); return err }},
+ {"AResource", func(p *Parser) error { _, err := p.AResource(); return err }},
+ {"AAAAResource", func(p *Parser) error { _, err := p.AAAAResource(); return err }},
+ }
+
+ for _, test := range tests {
+ if err := test.fn(&Parser{}); err != ErrNotStarted {
+ t.Errorf("got _, %v = p.%s(), want = _, %v", err, test.name, ErrNotStarted)
+ }
+ }
+}
+
+func TestDNSPackUnpack(t *testing.T) {
+ wants := []Message{
+ {
+ Questions: []Question{
+ {
+ Name: mustNewName("."),
+ Type: TypeAAAA,
+ Class: ClassINET,
+ },
+ },
+ Answers: []Resource{},
+ Authorities: []Resource{},
+ Additionals: []Resource{},
+ },
+ largeTestMsg(),
+ }
+ for i, want := range wants {
+ b, err := want.Pack()
+ if err != nil {
+ t.Fatalf("%d: packing failed: %v", i, err)
+ }
+ var got Message
+ err = got.Unpack(b)
+ if err != nil {
+ t.Fatalf("%d: unpacking failed: %v", i, err)
+ }
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("%d: got = %+v, want = %+v", i, &got, &want)
+ }
+ }
+}
+
+func TestSkipAll(t *testing.T) {
+ msg := largeTestMsg()
+ buf, err := msg.Pack()
+ if err != nil {
+ t.Fatal("Packing large test message:", err)
+ }
+ var p Parser
+ if _, err := p.Start(buf); err != nil {
+ t.Fatal(err)
+ }
+
+ tests := []struct {
+ name string
+ f func() error
+ }{
+ {"SkipAllQuestions", p.SkipAllQuestions},
+ {"SkipAllAnswers", p.SkipAllAnswers},
+ {"SkipAllAuthorities", p.SkipAllAuthorities},
+ {"SkipAllAdditionals", p.SkipAllAdditionals},
+ }
+ for _, test := range tests {
+ for i := 1; i <= 3; i++ {
+ if err := test.f(); err != nil {
+ t.Errorf("Call #%d to %s(): %v", i, test.name, err)
+ }
+ }
+ }
+}
+
+func TestSkipEach(t *testing.T) {
+ msg := smallTestMsg()
+
+ buf, err := msg.Pack()
+ if err != nil {
+ t.Fatal("Packing test message:", err)
+ }
+ var p Parser
+ if _, err := p.Start(buf); err != nil {
+ t.Fatal(err)
+ }
+
+ tests := []struct {
+ name string
+ f func() error
+ }{
+ {"SkipQuestion", p.SkipQuestion},
+ {"SkipAnswer", p.SkipAnswer},
+ {"SkipAuthority", p.SkipAuthority},
+ {"SkipAdditional", p.SkipAdditional},
+ }
+ for _, test := range tests {
+ if err := test.f(); err != nil {
+ t.Errorf("First call: got %s() = %v, want = %v", test.name, err, nil)
+ }
+ if err := test.f(); err != ErrSectionDone {
+ t.Errorf("Second call: got %s() = %v, want = %v", test.name, err, ErrSectionDone)
+ }
+ }
+}
+
+func TestSkipAfterRead(t *testing.T) {
+ msg := smallTestMsg()
+
+ buf, err := msg.Pack()
+ if err != nil {
+ t.Fatal("Packing test message:", err)
+ }
+ var p Parser
+ if _, err := p.Start(buf); err != nil {
+ t.Fatal(err)
+ }
+
+ tests := []struct {
+ name string
+ skip func() error
+ read func() error
+ }{
+ {"Question", p.SkipQuestion, func() error { _, err := p.Question(); return err }},
+ {"Answer", p.SkipAnswer, func() error { _, err := p.Answer(); return err }},
+ {"Authority", p.SkipAuthority, func() error { _, err := p.Authority(); return err }},
+ {"Additional", p.SkipAdditional, func() error { _, err := p.Additional(); return err }},
+ }
+ for _, test := range tests {
+ if err := test.read(); err != nil {
+ t.Errorf("Got %s() = _, %v, want = _, %v", test.name, err, nil)
+ }
+ if err := test.skip(); err != ErrSectionDone {
+ t.Errorf("Got Skip%s() = %v, want = %v", test.name, err, ErrSectionDone)
+ }
+ }
+}
+
+func TestSkipNotStarted(t *testing.T) {
+ var p Parser
+
+ tests := []struct {
+ name string
+ f func() error
+ }{
+ {"SkipAllQuestions", p.SkipAllQuestions},
+ {"SkipAllAnswers", p.SkipAllAnswers},
+ {"SkipAllAuthorities", p.SkipAllAuthorities},
+ {"SkipAllAdditionals", p.SkipAllAdditionals},
+ }
+ for _, test := range tests {
+ if err := test.f(); err != ErrNotStarted {
+ t.Errorf("Got %s() = %v, want = %v", test.name, err, ErrNotStarted)
+ }
+ }
+}
+
+func TestTooManyRecords(t *testing.T) {
+ const recs = int(^uint16(0)) + 1
+ tests := []struct {
+ name string
+ msg Message
+ want error
+ }{
+ {
+ "Questions",
+ Message{
+ Questions: make([]Question, recs),
+ },
+ errTooManyQuestions,
+ },
+ {
+ "Answers",
+ Message{
+ Answers: make([]Resource, recs),
+ },
+ errTooManyAnswers,
+ },
+ {
+ "Authorities",
+ Message{
+ Authorities: make([]Resource, recs),
+ },
+ errTooManyAuthorities,
+ },
+ {
+ "Additionals",
+ Message{
+ Additionals: make([]Resource, recs),
+ },
+ errTooManyAdditionals,
+ },
+ }
+
+ for _, test := range tests {
+ if _, got := test.msg.Pack(); got != test.want {
+ t.Errorf("Packing %d %s: got = %v, want = %v", recs, test.name, got, test.want)
+ }
+ }
+}
+
+func TestVeryLongTxt(t *testing.T) {
+ want := Resource{
+ ResourceHeader{
+ Name: mustNewName("foo.bar.example.com."),
+ Type: TypeTXT,
+ Class: ClassINET,
+ },
+ &TXTResource{loremIpsum},
+ }
+ buf, err := want.pack(make([]byte, 0, 8000), map[string]int{})
+ if err != nil {
+ t.Fatal("Packing failed:", err)
+ }
+ var got Resource
+ off, err := got.Header.unpack(buf, 0)
+ if err != nil {
+ t.Fatal("Unpacking ResourceHeader failed:", err)
+ }
+ body, n, err := unpackResourceBody(buf, off, got.Header)
+ if err != nil {
+ t.Fatal("Unpacking failed:", err)
+ }
+ got.Body = body
+ if n != len(buf) {
+ t.Errorf("Unpacked different amount than packed: got n = %d, want = %d", n, len(buf))
+ }
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("Got = %#v, want = %#v", got, want)
+ }
+}
+
+func TestStartError(t *testing.T) {
+ tests := []struct {
+ name string
+ fn func(*Builder) error
+ }{
+ {"Questions", func(b *Builder) error { return b.StartQuestions() }},
+ {"Answers", func(b *Builder) error { return b.StartAnswers() }},
+ {"Authorities", func(b *Builder) error { return b.StartAuthorities() }},
+ {"Additionals", func(b *Builder) error { return b.StartAdditionals() }},
+ }
+
+ envs := []struct {
+ name string
+ fn func() *Builder
+ want error
+ }{
+ {"sectionNotStarted", func() *Builder { return &Builder{section: sectionNotStarted} }, ErrNotStarted},
+ {"sectionDone", func() *Builder { return &Builder{section: sectionDone} }, ErrSectionDone},
+ }
+
+ for _, env := range envs {
+ for _, test := range tests {
+ if got := test.fn(env.fn()); got != env.want {
+ t.Errorf("got Builder{%s}.Start%s = %v, want = %v", env.name, test.name, got, env.want)
+ }
+ }
+ }
+}
+
+func TestBuilderResourceError(t *testing.T) {
+ tests := []struct {
+ name string
+ fn func(*Builder) error
+ }{
+ {"CNAMEResource", func(b *Builder) error { return b.CNAMEResource(ResourceHeader{}, CNAMEResource{}) }},
+ {"MXResource", func(b *Builder) error { return b.MXResource(ResourceHeader{}, MXResource{}) }},
+ {"NSResource", func(b *Builder) error { return b.NSResource(ResourceHeader{}, NSResource{}) }},
+ {"PTRResource", func(b *Builder) error { return b.PTRResource(ResourceHeader{}, PTRResource{}) }},
+ {"SOAResource", func(b *Builder) error { return b.SOAResource(ResourceHeader{}, SOAResource{}) }},
+ {"TXTResource", func(b *Builder) error { return b.TXTResource(ResourceHeader{}, TXTResource{}) }},
+ {"SRVResource", func(b *Builder) error { return b.SRVResource(ResourceHeader{}, SRVResource{}) }},
+ {"AResource", func(b *Builder) error { return b.AResource(ResourceHeader{}, AResource{}) }},
+ {"AAAAResource", func(b *Builder) error { return b.AAAAResource(ResourceHeader{}, AAAAResource{}) }},
+ }
+
+ envs := []struct {
+ name string
+ fn func() *Builder
+ want error
+ }{
+ {"sectionNotStarted", func() *Builder { return &Builder{section: sectionNotStarted} }, ErrNotStarted},
+ {"sectionHeader", func() *Builder { return &Builder{section: sectionHeader} }, ErrNotStarted},
+ {"sectionQuestions", func() *Builder { return &Builder{section: sectionQuestions} }, ErrNotStarted},
+ {"sectionDone", func() *Builder { return &Builder{section: sectionDone} }, ErrSectionDone},
+ }
+
+ for _, env := range envs {
+ for _, test := range tests {
+ if got := test.fn(env.fn()); got != env.want {
+ t.Errorf("got Builder{%s}.%s = %v, want = %v", env.name, test.name, got, env.want)
+ }
+ }
+ }
+}
+
+func TestFinishError(t *testing.T) {
+ var b Builder
+ want := ErrNotStarted
+ if _, got := b.Finish(); got != want {
+ t.Errorf("got Builder{}.Finish() = %v, want = %v", got, want)
+ }
+}
+
+func TestBuilder(t *testing.T) {
+ msg := largeTestMsg()
+ want, err := msg.Pack()
+ if err != nil {
+ t.Fatal("Packing without builder:", err)
+ }
+
+ var b Builder
+ b.Start(nil, msg.Header)
+
+ if err := b.StartQuestions(); err != nil {
+ t.Fatal("b.StartQuestions():", err)
+ }
+ for _, q := range msg.Questions {
+ if err := b.Question(q); err != nil {
+ t.Fatalf("b.Question(%#v): %v", q, err)
+ }
+ }
+
+ if err := b.StartAnswers(); err != nil {
+ t.Fatal("b.StartAnswers():", err)
+ }
+ for _, a := range msg.Answers {
+ switch a.Header.Type {
+ case TypeA:
+ if err := b.AResource(a.Header, *a.Body.(*AResource)); err != nil {
+ t.Fatalf("b.AResource(%#v): %v", a, err)
+ }
+ case TypeNS:
+ if err := b.NSResource(a.Header, *a.Body.(*NSResource)); err != nil {
+ t.Fatalf("b.NSResource(%#v): %v", a, err)
+ }
+ case TypeCNAME:
+ if err := b.CNAMEResource(a.Header, *a.Body.(*CNAMEResource)); err != nil {
+ t.Fatalf("b.CNAMEResource(%#v): %v", a, err)
+ }
+ case TypeSOA:
+ if err := b.SOAResource(a.Header, *a.Body.(*SOAResource)); err != nil {
+ t.Fatalf("b.SOAResource(%#v): %v", a, err)
+ }
+ case TypePTR:
+ if err := b.PTRResource(a.Header, *a.Body.(*PTRResource)); err != nil {
+ t.Fatalf("b.PTRResource(%#v): %v", a, err)
+ }
+ case TypeMX:
+ if err := b.MXResource(a.Header, *a.Body.(*MXResource)); err != nil {
+ t.Fatalf("b.MXResource(%#v): %v", a, err)
+ }
+ case TypeTXT:
+ if err := b.TXTResource(a.Header, *a.Body.(*TXTResource)); err != nil {
+ t.Fatalf("b.TXTResource(%#v): %v", a, err)
+ }
+ case TypeAAAA:
+ if err := b.AAAAResource(a.Header, *a.Body.(*AAAAResource)); err != nil {
+ t.Fatalf("b.AAAAResource(%#v): %v", a, err)
+ }
+ case TypeSRV:
+ if err := b.SRVResource(a.Header, *a.Body.(*SRVResource)); err != nil {
+ t.Fatalf("b.SRVResource(%#v): %v", a, err)
+ }
+ }
+ }
+
+ if err := b.StartAuthorities(); err != nil {
+ t.Fatal("b.StartAuthorities():", err)
+ }
+ for _, a := range msg.Authorities {
+ if err := b.NSResource(a.Header, *a.Body.(*NSResource)); err != nil {
+ t.Fatalf("b.NSResource(%#v): %v", a, err)
+ }
+ }
+
+ if err := b.StartAdditionals(); err != nil {
+ t.Fatal("b.StartAdditionals():", err)
+ }
+ for _, a := range msg.Additionals {
+ if err := b.TXTResource(a.Header, *a.Body.(*TXTResource)); err != nil {
+ t.Fatalf("b.TXTResource(%#v): %v", a, err)
+ }
+ }
+
+ got, err := b.Finish()
+ if err != nil {
+ t.Fatal("b.Finish():", err)
+ }
+ if !bytes.Equal(got, want) {
+ t.Fatalf("Got from Builder: %#v\nwant = %#v", got, want)
+ }
+}
+
+func TestResourcePack(t *testing.T) {
+ for _, tt := range []struct {
+ m Message
+ err error
+ }{
+ {
+ Message{
+ Questions: []Question{
+ {
+ Name: mustNewName("."),
+ Type: TypeAAAA,
+ Class: ClassINET,
+ },
+ },
+ Answers: []Resource{{ResourceHeader{}, nil}},
+ },
+ &nestedError{"packing Answer", errNilResouceBody},
+ },
+ {
+ Message{
+ Questions: []Question{
+ {
+ Name: mustNewName("."),
+ Type: TypeAAAA,
+ Class: ClassINET,
+ },
+ },
+ Authorities: []Resource{{ResourceHeader{}, (*NSResource)(nil)}},
+ },
+ &nestedError{"packing Authority",
+ &nestedError{"ResourceHeader",
+ &nestedError{"Name", errNonCanonicalName},
+ },
+ },
+ },
+ {
+ Message{
+ Questions: []Question{
+ {
+ Name: mustNewName("."),
+ Type: TypeA,
+ Class: ClassINET,
+ },
+ },
+ Additionals: []Resource{{ResourceHeader{}, nil}},
+ },
+ &nestedError{"packing Additional", errNilResouceBody},
+ },
+ } {
+ _, err := tt.m.Pack()
+ if !reflect.DeepEqual(err, tt.err) {
+ t.Errorf("got %v for %v; want %v", err, tt.m, tt.err)
+ }
+ }
+}
+
+func BenchmarkParsing(b *testing.B) {
+ b.ReportAllocs()
+
+ name := mustNewName("foo.bar.example.com.")
+ msg := Message{
+ Header: Header{Response: true, Authoritative: true},
+ Questions: []Question{
+ {
+ Name: name,
+ Type: TypeA,
+ Class: ClassINET,
+ },
+ },
+ Answers: []Resource{
+ {
+ ResourceHeader{
+ Name: name,
+ Class: ClassINET,
+ },
+ &AResource{[4]byte{}},
+ },
+ {
+ ResourceHeader{
+ Name: name,
+ Class: ClassINET,
+ },
+ &AAAAResource{[16]byte{}},
+ },
+ {
+ ResourceHeader{
+ Name: name,
+ Class: ClassINET,
+ },
+ &CNAMEResource{name},
+ },
+ {
+ ResourceHeader{
+ Name: name,
+ Class: ClassINET,
+ },
+ &NSResource{name},
+ },
+ },
+ }
+
+ buf, err := msg.Pack()
+ if err != nil {
+ b.Fatal("msg.Pack():", err)
+ }
+
+ for i := 0; i < b.N; i++ {
+ var p Parser
+ if _, err := p.Start(buf); err != nil {
+ b.Fatal("p.Start(buf):", err)
+ }
+
+ for {
+ _, err := p.Question()
+ if err == ErrSectionDone {
+ break
+ }
+ if err != nil {
+ b.Fatal("p.Question():", err)
+ }
+ }
+
+ for {
+ h, err := p.AnswerHeader()
+ if err == ErrSectionDone {
+ break
+ }
+ if err != nil {
+ panic(err)
+ }
+
+ switch h.Type {
+ case TypeA:
+ if _, err := p.AResource(); err != nil {
+ b.Fatal("p.AResource():", err)
+ }
+ case TypeAAAA:
+ if _, err := p.AAAAResource(); err != nil {
+ b.Fatal("p.AAAAResource():", err)
+ }
+ case TypeCNAME:
+ if _, err := p.CNAMEResource(); err != nil {
+ b.Fatal("p.CNAMEResource():", err)
+ }
+ case TypeNS:
+ if _, err := p.NSResource(); err != nil {
+ b.Fatal("p.NSResource():", err)
+ }
+ default:
+ b.Fatalf("unknown type: %T", h)
+ }
+ }
+ }
+}
+
+func BenchmarkBuilding(b *testing.B) {
+ b.ReportAllocs()
+
+ name := mustNewName("foo.bar.example.com.")
+ buf := make([]byte, 0, packStartingCap)
+
+ for i := 0; i < b.N; i++ {
+ var bld Builder
+ bld.StartWithoutCompression(buf, Header{Response: true, Authoritative: true})
+
+ if err := bld.StartQuestions(); err != nil {
+ b.Fatal("bld.StartQuestions():", err)
+ }
+ q := Question{
+ Name: name,
+ Type: TypeA,
+ Class: ClassINET,
+ }
+ if err := bld.Question(q); err != nil {
+ b.Fatalf("bld.Question(%+v): %v", q, err)
+ }
+
+ hdr := ResourceHeader{
+ Name: name,
+ Class: ClassINET,
+ }
+ if err := bld.StartAnswers(); err != nil {
+ b.Fatal("bld.StartQuestions():", err)
+ }
+
+ ar := AResource{[4]byte{}}
+ if err := bld.AResource(hdr, ar); err != nil {
+ b.Fatalf("bld.AResource(%+v, %+v): %v", hdr, ar, err)
+ }
+
+ aaar := AAAAResource{[16]byte{}}
+ if err := bld.AAAAResource(hdr, aaar); err != nil {
+ b.Fatalf("bld.AAAAResource(%+v, %+v): %v", hdr, aaar, err)
+ }
+
+ cnr := CNAMEResource{name}
+ if err := bld.CNAMEResource(hdr, cnr); err != nil {
+ b.Fatalf("bld.CNAMEResource(%+v, %+v): %v", hdr, cnr, err)
+ }
+
+ nsr := NSResource{name}
+ if err := bld.NSResource(hdr, nsr); err != nil {
+ b.Fatalf("bld.NSResource(%+v, %+v): %v", hdr, nsr, err)
+ }
+
+ if _, err := bld.Finish(); err != nil {
+ b.Fatal("bld.Finish():", err)
+ }
+ }
+}
+
+func smallTestMsg() Message {
+ name := mustNewName("example.com.")
+ return Message{
+ Header: Header{Response: true, Authoritative: true},
+ Questions: []Question{
+ {
+ Name: name,
+ Type: TypeA,
+ Class: ClassINET,
+ },
+ },
+ Answers: []Resource{
+ {
+ ResourceHeader{
+ Name: name,
+ Type: TypeA,
+ Class: ClassINET,
+ },
+ &AResource{[4]byte{127, 0, 0, 1}},
+ },
+ },
+ Authorities: []Resource{
+ {
+ ResourceHeader{
+ Name: name,
+ Type: TypeA,
+ Class: ClassINET,
+ },
+ &AResource{[4]byte{127, 0, 0, 1}},
+ },
+ },
+ Additionals: []Resource{
+ {
+ ResourceHeader{
+ Name: name,
+ Type: TypeA,
+ Class: ClassINET,
+ },
+ &AResource{[4]byte{127, 0, 0, 1}},
+ },
+ },
+ }
+}
+
+func BenchmarkPack(b *testing.B) {
+ msg := largeTestMsg()
+
+ b.ReportAllocs()
+
+ for i := 0; i < b.N; i++ {
+ if _, err := msg.Pack(); err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+func BenchmarkAppendPack(b *testing.B) {
+ msg := largeTestMsg()
+ buf := make([]byte, 0, packStartingCap)
+
+ b.ReportAllocs()
+
+ for i := 0; i < b.N; i++ {
+ if _, err := msg.AppendPack(buf[:0]); err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+func largeTestMsg() Message {
+ name := mustNewName("foo.bar.example.com.")
+ return Message{
+ Header: Header{Response: true, Authoritative: true},
+ Questions: []Question{
+ {
+ Name: name,
+ Type: TypeA,
+ Class: ClassINET,
+ },
+ },
+ Answers: []Resource{
+ {
+ ResourceHeader{
+ Name: name,
+ Type: TypeA,
+ Class: ClassINET,
+ },
+ &AResource{[4]byte{127, 0, 0, 1}},
+ },
+ {
+ ResourceHeader{
+ Name: name,
+ Type: TypeA,
+ Class: ClassINET,
+ },
+ &AResource{[4]byte{127, 0, 0, 2}},
+ },
+ {
+ ResourceHeader{
+ Name: name,
+ Type: TypeAAAA,
+ Class: ClassINET,
+ },
+ &AAAAResource{[16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}},
+ },
+ {
+ ResourceHeader{
+ Name: name,
+ Type: TypeCNAME,
+ Class: ClassINET,
+ },
+ &CNAMEResource{mustNewName("alias.example.com.")},
+ },
+ {
+ ResourceHeader{
+ Name: name,
+ Type: TypeSOA,
+ Class: ClassINET,
+ },
+ &SOAResource{
+ NS: mustNewName("ns1.example.com."),
+ MBox: mustNewName("mb.example.com."),
+ Serial: 1,
+ Refresh: 2,
+ Retry: 3,
+ Expire: 4,
+ MinTTL: 5,
+ },
+ },
+ {
+ ResourceHeader{
+ Name: name,
+ Type: TypePTR,
+ Class: ClassINET,
+ },
+ &PTRResource{mustNewName("ptr.example.com.")},
+ },
+ {
+ ResourceHeader{
+ Name: name,
+ Type: TypeMX,
+ Class: ClassINET,
+ },
+ &MXResource{
+ 7,
+ mustNewName("mx.example.com."),
+ },
+ },
+ {
+ ResourceHeader{
+ Name: name,
+ Type: TypeSRV,
+ Class: ClassINET,
+ },
+ &SRVResource{
+ 8,
+ 9,
+ 11,
+ mustNewName("srv.example.com."),
+ },
+ },
+ },
+ Authorities: []Resource{
+ {
+ ResourceHeader{
+ Name: name,
+ Type: TypeNS,
+ Class: ClassINET,
+ },
+ &NSResource{mustNewName("ns1.example.com.")},
+ },
+ {
+ ResourceHeader{
+ Name: name,
+ Type: TypeNS,
+ Class: ClassINET,
+ },
+ &NSResource{mustNewName("ns2.example.com.")},
+ },
+ },
+ Additionals: []Resource{
+ {
+ ResourceHeader{
+ Name: name,
+ Type: TypeTXT,
+ Class: ClassINET,
+ },
+ &TXTResource{"So Long, and Thanks for All the Fish"},
+ },
+ {
+ ResourceHeader{
+ Name: name,
+ Type: TypeTXT,
+ Class: ClassINET,
+ },
+ &TXTResource{"Hamster Huey and the Gooey Kablooie"},
+ },
+ },
+ }
+}
+
+const loremIpsum = `
+Lorem ipsum dolor sit amet, nec enim antiopam id, an ullum choro
+nonumes qui, pro eu debet honestatis mediocritatem. No alia enim eos,
+magna signiferumque ex vis. Mei no aperiri dissentias, cu vel quas
+regione. Malorum quaeque vim ut, eum cu semper aliquid invidunt, ei
+nam ipsum assentior.
+
+Nostrum appellantur usu no, vis ex probatus adipiscing. Cu usu illum
+facilis eleifend. Iusto conceptam complectitur vim id. Tale omnesque
+no usu, ei oblique sadipscing vim. At nullam voluptua usu, mei laudem
+reformidans et. Qui ei eros porro reformidans, ius suas veritus
+torquatos ex. Mea te facer alterum consequat.
+
+Soleat torquatos democritum sed et, no mea congue appareat, facer
+aliquam nec in. Has te ipsum tritani. At justo dicta option nec, movet
+phaedrum ad nam. Ea detracto verterem liberavisse has, delectus
+suscipiantur in mei. Ex nam meliore complectitur. Ut nam omnis
+honestatis quaerendum, ea mea nihil affert detracto, ad vix rebum
+mollis.
+
+Ut epicurei praesent neglegentur pri, prima fuisset intellegebat ad
+vim. An habemus comprehensam usu, at enim dignissim pro. Eam reque
+vivendum adipisci ea. Vel ne odio choro minimum. Sea admodum
+dissentiet ex. Mundi tamquam evertitur ius cu. Homero postea iisque ut
+pro, vel ne saepe senserit consetetur.
+
+Nulla utamur facilisis ius ea, in viderer diceret pertinax eum. Mei no
+enim quodsi facilisi, ex sed aeterno appareat mediocritatem, eum
+sententiae deterruisset ut. At suas timeam euismod cum, offendit
+appareat interpretaris ne vix. Vel ea civibus albucius, ex vim quidam
+accusata intellegebat, noluisse instructior sea id. Nec te nonumes
+habemus appellantur, quis dignissim vituperata eu nam.
+
+At vix apeirian patrioque vituperatoribus, an usu agam assum. Debet
+iisque an mea. Per eu dicant ponderum accommodare. Pri alienum
+placerat senserit an, ne eum ferri abhorreant vituperatoribus. Ut mea
+eligendi disputationi. Ius no tation everti impedit, ei magna quidam
+mediocritatem pri.
+
+Legendos perpetua iracundia ne usu, no ius ullum epicurei intellegam,
+ad modus epicuri lucilius eam. In unum quaerendum usu. Ne diam paulo
+has, ea veri virtute sed. Alia honestatis conclusionemque mea eu, ut
+iudico albucius his.
+
+Usu essent probatus eu, sed omnis dolor delicatissimi ex. No qui augue
+dissentias dissentiet. Laudem recteque no usu, vel an velit noluisse,
+an sed utinam eirmod appetere. Ne mea fuisset inimicus ocurreret. At
+vis dicant abhorreant, utinam forensibus nec ne, mei te docendi
+consequat. Brute inermis persecuti cum id. Ut ipsum munere propriae
+usu, dicit graeco disputando id has.
+
+Eros dolore quaerendum nam ei. Timeam ornatus inciderint pro id. Nec
+torquatos sadipscing ei, ancillae molestie per in. Malis principes duo
+ea, usu liber postulant ei.
+
+Graece timeam voluptatibus eu eam. Alia probatus quo no, ea scripta
+feugiat duo. Congue option meliore ex qui, noster invenire appellantur
+ea vel. Eu exerci legendos vel. Consetetur repudiandae vim ut. Vix an
+probo minimum, et nam illud falli tempor.
+
+Cum dico signiferumque eu. Sed ut regione maiorum, id veritus insolens
+tacimates vix. Eu mel sint tamquam lucilius, duo no oporteat
+tacimates. Atqui augue concludaturque vix ei, id mel utroque menandri.
+
+Ad oratio blandit aliquando pro. Vis et dolorum rationibus
+philosophia, ad cum nulla molestie. Hinc fuisset adversarium eum et,
+ne qui nisl verear saperet, vel te quaestio forensibus. Per odio
+option delenit an. Alii placerat has no, in pri nihil platonem
+cotidieque. Est ut elit copiosae scaevola, debet tollit maluisset sea
+an.
+
+Te sea hinc debet pericula, liber ridens fabulas cu sed, quem mutat
+accusam mea et. Elitr labitur albucius et pri, an labore feugait mel.
+Velit zril melius usu ea. Ad stet putent interpretaris qui. Mel no
+error volumus scripserit. In pro paulo iudico, quo ei dolorem
+verterem, affert fabellas dissentiet ea vix.
+
+Vis quot deserunt te. Error aliquid detraxit eu usu, vis alia eruditi
+salutatus cu. Est nostrud bonorum an, ei usu alii salutatus. Vel at
+nisl primis, eum ex aperiri noluisse reformidans. Ad veri velit
+utroque vis, ex equidem detraxit temporibus has.
+
+Inermis appareat usu ne. Eros placerat periculis mea ad, in dictas
+pericula pro. Errem postulant at usu, ea nec amet ornatus mentitum. Ad
+mazim graeco eum, vel ex percipit volutpat iudicabit, sit ne delicata
+interesset. Mel sapientem prodesset abhorreant et, oblique suscipit
+eam id.
+
+An maluisset disputando mea, vidit mnesarchum pri et. Malis insolens
+inciderint no sea. Ea persius maluisset vix, ne vim appellantur
+instructior, consul quidam definiebas pri id. Cum integre feugiat
+pericula in, ex sed persius similique, mel ne natum dicit percipitur.
+
+Primis discere ne pri, errem putent definitionem at vis. Ei mel dolore
+neglegentur, mei tincidunt percipitur ei. Pro ad simul integre
+rationibus. Eu vel alii honestatis definitiones, mea no nonumy
+reprehendunt.
+
+Dicta appareat legendos est cu. Eu vel congue dicunt omittam, no vix
+adhuc minimum constituam, quot noluisse id mel. Eu quot sale mutat
+duo, ex nisl munere invenire duo. Ne nec ullum utamur. Pro alterum
+debitis nostrum no, ut vel aliquid vivendo.
+
+Aliquip fierent praesent quo ne, id sit audiam recusabo delicatissimi.
+Usu postulant incorrupte cu. At pro dicit tibique intellegam, cibo
+dolore impedit id eam, et aeque feugait assentior has. Quando sensibus
+nec ex. Possit sensibus pri ad, unum mutat periculis cu vix.
+
+Mundi tibique vix te, duo simul partiendo qualisque id, est at vidit
+sonet tempor. No per solet aeterno deseruisse. Petentium salutandi
+definiebas pri cu. Munere vivendum est in. Ei justo congue eligendi
+vis, modus offendit omittantur te mel.
+
+Integre voluptaria in qui, sit habemus tractatos constituam no. Utinam
+melius conceptam est ne, quo in minimum apeirian delicata, ut ius
+porro recusabo. Dicant expetenda vix no, ludus scripserit sed ex, eu
+his modo nostro. Ut etiam sonet his, quodsi inciderint philosophia te
+per. Nullam lobortis eu cum, vix an sonet efficiendi repudiandae. Vis
+ad idque fabellas intellegebat.
+
+Eum commodo senserit conclusionemque ex. Sed forensibus sadipscing ut,
+mei in facer delicata periculis, sea ne hinc putent cetero. Nec ne
+alia corpora invenire, alia prima soleat te cum. Eleifend posidonium
+nam at.
+
+Dolorum indoctum cu quo, ex dolor legendos recteque eam, cu pri zril
+discere. Nec civibus officiis dissentiunt ex, est te liber ludus
+elaboraret. Cum ea fabellas invenire. Ex vim nostrud eripuit
+comprehensam, nam te inermis delectus, saepe inermis senserit.
+`
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/atom/atom.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/atom/atom.go
new file mode 100644
index 000000000..cd0a8ac15
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/atom/atom.go
@@ -0,0 +1,78 @@
+// Copyright 2012 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 atom provides integer codes (also known as atoms) for a fixed set of
+// frequently occurring HTML strings: tag names and attribute keys such as "p"
+// and "id".
+//
+// Sharing an atom's name between all elements with the same tag can result in
+// fewer string allocations when tokenizing and parsing HTML. Integer
+// comparisons are also generally faster than string comparisons.
+//
+// The value of an atom's particular code is not guaranteed to stay the same
+// between versions of this package. Neither is any ordering guaranteed:
+// whether atom.H1 < atom.H2 may also change. The codes are not guaranteed to
+// be dense. The only guarantees are that e.g. looking up "div" will yield
+// atom.Div, calling atom.Div.String will return "div", and atom.Div != 0.
+package atom // import "golang.org/x/net/html/atom"
+
+// Atom is an integer code for a string. The zero value maps to "".
+type Atom uint32
+
+// String returns the atom's name.
+func (a Atom) String() string {
+ start := uint32(a >> 8)
+ n := uint32(a & 0xff)
+ if start+n > uint32(len(atomText)) {
+ return ""
+ }
+ return atomText[start : start+n]
+}
+
+func (a Atom) string() string {
+ return atomText[a>>8 : a>>8+a&0xff]
+}
+
+// fnv computes the FNV hash with an arbitrary starting value h.
+func fnv(h uint32, s []byte) uint32 {
+ for i := range s {
+ h ^= uint32(s[i])
+ h *= 16777619
+ }
+ return h
+}
+
+func match(s string, t []byte) bool {
+ for i, c := range t {
+ if s[i] != c {
+ return false
+ }
+ }
+ return true
+}
+
+// Lookup returns the atom whose name is s. It returns zero if there is no
+// such atom. The lookup is case sensitive.
+func Lookup(s []byte) Atom {
+ if len(s) == 0 || len(s) > maxAtomLen {
+ return 0
+ }
+ h := fnv(hash0, s)
+ if a := table[h&uint32(len(table)-1)]; int(a&0xff) == len(s) && match(a.string(), s) {
+ return a
+ }
+ if a := table[(h>>16)&uint32(len(table)-1)]; int(a&0xff) == len(s) && match(a.string(), s) {
+ return a
+ }
+ return 0
+}
+
+// String returns a string whose contents are equal to s. In that sense, it is
+// equivalent to string(s) but may be more efficient.
+func String(s []byte) string {
+ if a := Lookup(s); a != 0 {
+ return a.String()
+ }
+ return string(s)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/atom/atom_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/atom/atom_test.go
new file mode 100644
index 000000000..6e33704dd
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/atom/atom_test.go
@@ -0,0 +1,109 @@
+// Copyright 2012 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 atom
+
+import (
+ "sort"
+ "testing"
+)
+
+func TestKnown(t *testing.T) {
+ for _, s := range testAtomList {
+ if atom := Lookup([]byte(s)); atom.String() != s {
+ t.Errorf("Lookup(%q) = %#x (%q)", s, uint32(atom), atom.String())
+ }
+ }
+}
+
+func TestHits(t *testing.T) {
+ for _, a := range table {
+ if a == 0 {
+ continue
+ }
+ got := Lookup([]byte(a.String()))
+ if got != a {
+ t.Errorf("Lookup(%q) = %#x, want %#x", a.String(), uint32(got), uint32(a))
+ }
+ }
+}
+
+func TestMisses(t *testing.T) {
+ testCases := []string{
+ "",
+ "\x00",
+ "\xff",
+ "A",
+ "DIV",
+ "Div",
+ "dIV",
+ "aa",
+ "a\x00",
+ "ab",
+ "abb",
+ "abbr0",
+ "abbr ",
+ " abbr",
+ " a",
+ "acceptcharset",
+ "acceptCharset",
+ "accept_charset",
+ "h0",
+ "h1h2",
+ "h7",
+ "onClick",
+ "λ",
+ // The following string has the same hash (0xa1d7fab7) as "onmouseover".
+ "\x00\x00\x00\x00\x00\x50\x18\xae\x38\xd0\xb7",
+ }
+ for _, tc := range testCases {
+ got := Lookup([]byte(tc))
+ if got != 0 {
+ t.Errorf("Lookup(%q): got %d, want 0", tc, got)
+ }
+ }
+}
+
+func TestForeignObject(t *testing.T) {
+ const (
+ afo = Foreignobject
+ afO = ForeignObject
+ sfo = "foreignobject"
+ sfO = "foreignObject"
+ )
+ if got := Lookup([]byte(sfo)); got != afo {
+ t.Errorf("Lookup(%q): got %#v, want %#v", sfo, got, afo)
+ }
+ if got := Lookup([]byte(sfO)); got != afO {
+ t.Errorf("Lookup(%q): got %#v, want %#v", sfO, got, afO)
+ }
+ if got := afo.String(); got != sfo {
+ t.Errorf("Atom(%#v).String(): got %q, want %q", afo, got, sfo)
+ }
+ if got := afO.String(); got != sfO {
+ t.Errorf("Atom(%#v).String(): got %q, want %q", afO, got, sfO)
+ }
+}
+
+func BenchmarkLookup(b *testing.B) {
+ sortedTable := make([]string, 0, len(table))
+ for _, a := range table {
+ if a != 0 {
+ sortedTable = append(sortedTable, a.String())
+ }
+ }
+ sort.Strings(sortedTable)
+
+ x := make([][]byte, 1000)
+ for i := range x {
+ x[i] = []byte(sortedTable[i%len(sortedTable)])
+ }
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ for _, s := range x {
+ Lookup(s)
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/atom/gen.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/atom/gen.go
new file mode 100644
index 000000000..cc5dc5dbc
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/atom/gen.go
@@ -0,0 +1,709 @@
+// Copyright 2012 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.
+
+// +build ignore
+
+//go:generate go run gen.go
+//go:generate go run gen.go -test
+
+package main
+
+import (
+ "bytes"
+ "flag"
+ "fmt"
+ "go/format"
+ "io/ioutil"
+ "math/rand"
+ "os"
+ "sort"
+ "strings"
+)
+
+// identifier converts s to a Go exported identifier.
+// It converts "div" to "Div" and "accept-charset" to "AcceptCharset".
+func identifier(s string) string {
+ b := make([]byte, 0, len(s))
+ cap := true
+ for _, c := range s {
+ if c == '-' {
+ cap = true
+ continue
+ }
+ if cap && 'a' <= c && c <= 'z' {
+ c -= 'a' - 'A'
+ }
+ cap = false
+ b = append(b, byte(c))
+ }
+ return string(b)
+}
+
+var test = flag.Bool("test", false, "generate table_test.go")
+
+func genFile(name string, buf *bytes.Buffer) {
+ b, err := format.Source(buf.Bytes())
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+ if err := ioutil.WriteFile(name, b, 0644); err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+}
+
+func main() {
+ flag.Parse()
+
+ var all []string
+ all = append(all, elements...)
+ all = append(all, attributes...)
+ all = append(all, eventHandlers...)
+ all = append(all, extra...)
+ sort.Strings(all)
+
+ // uniq - lists have dups
+ w := 0
+ for _, s := range all {
+ if w == 0 || all[w-1] != s {
+ all[w] = s
+ w++
+ }
+ }
+ all = all[:w]
+
+ if *test {
+ var buf bytes.Buffer
+ fmt.Fprintln(&buf, "// Code generated by go generate gen.go; DO NOT EDIT.\n")
+ fmt.Fprintln(&buf, "//go:generate go run gen.go -test\n")
+ fmt.Fprintln(&buf, "package atom\n")
+ fmt.Fprintln(&buf, "var testAtomList = []string{")
+ for _, s := range all {
+ fmt.Fprintf(&buf, "\t%q,\n", s)
+ }
+ fmt.Fprintln(&buf, "}")
+
+ genFile("table_test.go", &buf)
+ return
+ }
+
+ // Find hash that minimizes table size.
+ var best *table
+ for i := 0; i < 1000000; i++ {
+ if best != nil && 1<<(best.k-1) < len(all) {
+ break
+ }
+ h := rand.Uint32()
+ for k := uint(0); k <= 16; k++ {
+ if best != nil && k >= best.k {
+ break
+ }
+ var t table
+ if t.init(h, k, all) {
+ best = &t
+ break
+ }
+ }
+ }
+ if best == nil {
+ fmt.Fprintf(os.Stderr, "failed to construct string table\n")
+ os.Exit(1)
+ }
+
+ // Lay out strings, using overlaps when possible.
+ layout := append([]string{}, all...)
+
+ // Remove strings that are substrings of other strings
+ for changed := true; changed; {
+ changed = false
+ for i, s := range layout {
+ if s == "" {
+ continue
+ }
+ for j, t := range layout {
+ if i != j && t != "" && strings.Contains(s, t) {
+ changed = true
+ layout[j] = ""
+ }
+ }
+ }
+ }
+
+ // Join strings where one suffix matches another prefix.
+ for {
+ // Find best i, j, k such that layout[i][len-k:] == layout[j][:k],
+ // maximizing overlap length k.
+ besti := -1
+ bestj := -1
+ bestk := 0
+ for i, s := range layout {
+ if s == "" {
+ continue
+ }
+ for j, t := range layout {
+ if i == j {
+ continue
+ }
+ for k := bestk + 1; k <= len(s) && k <= len(t); k++ {
+ if s[len(s)-k:] == t[:k] {
+ besti = i
+ bestj = j
+ bestk = k
+ }
+ }
+ }
+ }
+ if bestk > 0 {
+ layout[besti] += layout[bestj][bestk:]
+ layout[bestj] = ""
+ continue
+ }
+ break
+ }
+
+ text := strings.Join(layout, "")
+
+ atom := map[string]uint32{}
+ for _, s := range all {
+ off := strings.Index(text, s)
+ if off < 0 {
+ panic("lost string " + s)
+ }
+ atom[s] = uint32(off<<8 | len(s))
+ }
+
+ var buf bytes.Buffer
+ // Generate the Go code.
+ fmt.Fprintln(&buf, "// Code generated by go generate gen.go; DO NOT EDIT.\n")
+ fmt.Fprintln(&buf, "//go:generate go run gen.go\n")
+ fmt.Fprintln(&buf, "package atom\n\nconst (")
+
+ // compute max len
+ maxLen := 0
+ for _, s := range all {
+ if maxLen < len(s) {
+ maxLen = len(s)
+ }
+ fmt.Fprintf(&buf, "\t%s Atom = %#x\n", identifier(s), atom[s])
+ }
+ fmt.Fprintln(&buf, ")\n")
+
+ fmt.Fprintf(&buf, "const hash0 = %#x\n\n", best.h0)
+ fmt.Fprintf(&buf, "const maxAtomLen = %d\n\n", maxLen)
+
+ fmt.Fprintf(&buf, "var table = [1<<%d]Atom{\n", best.k)
+ for i, s := range best.tab {
+ if s == "" {
+ continue
+ }
+ fmt.Fprintf(&buf, "\t%#x: %#x, // %s\n", i, atom[s], s)
+ }
+ fmt.Fprintf(&buf, "}\n")
+ datasize := (1 << best.k) * 4
+
+ fmt.Fprintln(&buf, "const atomText =")
+ textsize := len(text)
+ for len(text) > 60 {
+ fmt.Fprintf(&buf, "\t%q +\n", text[:60])
+ text = text[60:]
+ }
+ fmt.Fprintf(&buf, "\t%q\n\n", text)
+
+ genFile("table.go", &buf)
+
+ fmt.Fprintf(os.Stdout, "%d atoms; %d string bytes + %d tables = %d total data\n", len(all), textsize, datasize, textsize+datasize)
+}
+
+type byLen []string
+
+func (x byLen) Less(i, j int) bool { return len(x[i]) > len(x[j]) }
+func (x byLen) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
+func (x byLen) Len() int { return len(x) }
+
+// fnv computes the FNV hash with an arbitrary starting value h.
+func fnv(h uint32, s string) uint32 {
+ for i := 0; i < len(s); i++ {
+ h ^= uint32(s[i])
+ h *= 16777619
+ }
+ return h
+}
+
+// A table represents an attempt at constructing the lookup table.
+// The lookup table uses cuckoo hashing, meaning that each string
+// can be found in one of two positions.
+type table struct {
+ h0 uint32
+ k uint
+ mask uint32
+ tab []string
+}
+
+// hash returns the two hashes for s.
+func (t *table) hash(s string) (h1, h2 uint32) {
+ h := fnv(t.h0, s)
+ h1 = h & t.mask
+ h2 = (h >> 16) & t.mask
+ return
+}
+
+// init initializes the table with the given parameters.
+// h0 is the initial hash value,
+// k is the number of bits of hash value to use, and
+// x is the list of strings to store in the table.
+// init returns false if the table cannot be constructed.
+func (t *table) init(h0 uint32, k uint, x []string) bool {
+ t.h0 = h0
+ t.k = k
+ t.tab = make([]string, 1<<k)
+ t.mask = 1<<k - 1
+ for _, s := range x {
+ if !t.insert(s) {
+ return false
+ }
+ }
+ return true
+}
+
+// insert inserts s in the table.
+func (t *table) insert(s string) bool {
+ h1, h2 := t.hash(s)
+ if t.tab[h1] == "" {
+ t.tab[h1] = s
+ return true
+ }
+ if t.tab[h2] == "" {
+ t.tab[h2] = s
+ return true
+ }
+ if t.push(h1, 0) {
+ t.tab[h1] = s
+ return true
+ }
+ if t.push(h2, 0) {
+ t.tab[h2] = s
+ return true
+ }
+ return false
+}
+
+// push attempts to push aside the entry in slot i.
+func (t *table) push(i uint32, depth int) bool {
+ if depth > len(t.tab) {
+ return false
+ }
+ s := t.tab[i]
+ h1, h2 := t.hash(s)
+ j := h1 + h2 - i
+ if t.tab[j] != "" && !t.push(j, depth+1) {
+ return false
+ }
+ t.tab[j] = s
+ return true
+}
+
+// The lists of element names and attribute keys were taken from
+// https://html.spec.whatwg.org/multipage/indices.html#index
+// as of the "HTML Living Standard - Last Updated 18 September 2017" version.
+
+// "command", "keygen" and "menuitem" have been removed from the spec,
+// but are kept here for backwards compatibility.
+var elements = []string{
+ "a",
+ "abbr",
+ "address",
+ "area",
+ "article",
+ "aside",
+ "audio",
+ "b",
+ "base",
+ "bdi",
+ "bdo",
+ "blockquote",
+ "body",
+ "br",
+ "button",
+ "canvas",
+ "caption",
+ "cite",
+ "code",
+ "col",
+ "colgroup",
+ "command",
+ "data",
+ "datalist",
+ "dd",
+ "del",
+ "details",
+ "dfn",
+ "dialog",
+ "div",
+ "dl",
+ "dt",
+ "em",
+ "embed",
+ "fieldset",
+ "figcaption",
+ "figure",
+ "footer",
+ "form",
+ "h1",
+ "h2",
+ "h3",
+ "h4",
+ "h5",
+ "h6",
+ "head",
+ "header",
+ "hgroup",
+ "hr",
+ "html",
+ "i",
+ "iframe",
+ "img",
+ "input",
+ "ins",
+ "kbd",
+ "keygen",
+ "label",
+ "legend",
+ "li",
+ "link",
+ "main",
+ "map",
+ "mark",
+ "menu",
+ "menuitem",
+ "meta",
+ "meter",
+ "nav",
+ "noscript",
+ "object",
+ "ol",
+ "optgroup",
+ "option",
+ "output",
+ "p",
+ "param",
+ "picture",
+ "pre",
+ "progress",
+ "q",
+ "rp",
+ "rt",
+ "ruby",
+ "s",
+ "samp",
+ "script",
+ "section",
+ "select",
+ "slot",
+ "small",
+ "source",
+ "span",
+ "strong",
+ "style",
+ "sub",
+ "summary",
+ "sup",
+ "table",
+ "tbody",
+ "td",
+ "template",
+ "textarea",
+ "tfoot",
+ "th",
+ "thead",
+ "time",
+ "title",
+ "tr",
+ "track",
+ "u",
+ "ul",
+ "var",
+ "video",
+ "wbr",
+}
+
+// https://html.spec.whatwg.org/multipage/indices.html#attributes-3
+//
+// "challenge", "command", "contextmenu", "dropzone", "icon", "keytype", "mediagroup",
+// "radiogroup", "spellcheck", "scoped", "seamless", "sortable" and "sorted" have been removed from the spec,
+// but are kept here for backwards compatibility.
+var attributes = []string{
+ "abbr",
+ "accept",
+ "accept-charset",
+ "accesskey",
+ "action",
+ "allowfullscreen",
+ "allowpaymentrequest",
+ "allowusermedia",
+ "alt",
+ "as",
+ "async",
+ "autocomplete",
+ "autofocus",
+ "autoplay",
+ "challenge",
+ "charset",
+ "checked",
+ "cite",
+ "class",
+ "color",
+ "cols",
+ "colspan",
+ "command",
+ "content",
+ "contenteditable",
+ "contextmenu",
+ "controls",
+ "coords",
+ "crossorigin",
+ "data",
+ "datetime",
+ "default",
+ "defer",
+ "dir",
+ "dirname",
+ "disabled",
+ "download",
+ "draggable",
+ "dropzone",
+ "enctype",
+ "for",
+ "form",
+ "formaction",
+ "formenctype",
+ "formmethod",
+ "formnovalidate",
+ "formtarget",
+ "headers",
+ "height",
+ "hidden",
+ "high",
+ "href",
+ "hreflang",
+ "http-equiv",
+ "icon",
+ "id",
+ "inputmode",
+ "integrity",
+ "is",
+ "ismap",
+ "itemid",
+ "itemprop",
+ "itemref",
+ "itemscope",
+ "itemtype",
+ "keytype",
+ "kind",
+ "label",
+ "lang",
+ "list",
+ "loop",
+ "low",
+ "manifest",
+ "max",
+ "maxlength",
+ "media",
+ "mediagroup",
+ "method",
+ "min",
+ "minlength",
+ "multiple",
+ "muted",
+ "name",
+ "nomodule",
+ "nonce",
+ "novalidate",
+ "open",
+ "optimum",
+ "pattern",
+ "ping",
+ "placeholder",
+ "playsinline",
+ "poster",
+ "preload",
+ "radiogroup",
+ "readonly",
+ "referrerpolicy",
+ "rel",
+ "required",
+ "reversed",
+ "rows",
+ "rowspan",
+ "sandbox",
+ "spellcheck",
+ "scope",
+ "scoped",
+ "seamless",
+ "selected",
+ "shape",
+ "size",
+ "sizes",
+ "sortable",
+ "sorted",
+ "slot",
+ "span",
+ "spellcheck",
+ "src",
+ "srcdoc",
+ "srclang",
+ "srcset",
+ "start",
+ "step",
+ "style",
+ "tabindex",
+ "target",
+ "title",
+ "translate",
+ "type",
+ "typemustmatch",
+ "updateviacache",
+ "usemap",
+ "value",
+ "width",
+ "workertype",
+ "wrap",
+}
+
+// "onautocomplete", "onautocompleteerror", "onmousewheel",
+// "onshow" and "onsort" have been removed from the spec,
+// but are kept here for backwards compatibility.
+var eventHandlers = []string{
+ "onabort",
+ "onautocomplete",
+ "onautocompleteerror",
+ "onauxclick",
+ "onafterprint",
+ "onbeforeprint",
+ "onbeforeunload",
+ "onblur",
+ "oncancel",
+ "oncanplay",
+ "oncanplaythrough",
+ "onchange",
+ "onclick",
+ "onclose",
+ "oncontextmenu",
+ "oncopy",
+ "oncuechange",
+ "oncut",
+ "ondblclick",
+ "ondrag",
+ "ondragend",
+ "ondragenter",
+ "ondragexit",
+ "ondragleave",
+ "ondragover",
+ "ondragstart",
+ "ondrop",
+ "ondurationchange",
+ "onemptied",
+ "onended",
+ "onerror",
+ "onfocus",
+ "onhashchange",
+ "oninput",
+ "oninvalid",
+ "onkeydown",
+ "onkeypress",
+ "onkeyup",
+ "onlanguagechange",
+ "onload",
+ "onloadeddata",
+ "onloadedmetadata",
+ "onloadend",
+ "onloadstart",
+ "onmessage",
+ "onmessageerror",
+ "onmousedown",
+ "onmouseenter",
+ "onmouseleave",
+ "onmousemove",
+ "onmouseout",
+ "onmouseover",
+ "onmouseup",
+ "onmousewheel",
+ "onwheel",
+ "onoffline",
+ "ononline",
+ "onpagehide",
+ "onpageshow",
+ "onpaste",
+ "onpause",
+ "onplay",
+ "onplaying",
+ "onpopstate",
+ "onprogress",
+ "onratechange",
+ "onreset",
+ "onresize",
+ "onrejectionhandled",
+ "onscroll",
+ "onsecuritypolicyviolation",
+ "onseeked",
+ "onseeking",
+ "onselect",
+ "onshow",
+ "onsort",
+ "onstalled",
+ "onstorage",
+ "onsubmit",
+ "onsuspend",
+ "ontimeupdate",
+ "ontoggle",
+ "onunhandledrejection",
+ "onunload",
+ "onvolumechange",
+ "onwaiting",
+}
+
+// extra are ad-hoc values not covered by any of the lists above.
+var extra = []string{
+ "align",
+ "annotation",
+ "annotation-xml",
+ "applet",
+ "basefont",
+ "bgsound",
+ "big",
+ "blink",
+ "center",
+ "color",
+ "desc",
+ "face",
+ "font",
+ "foreignObject", // HTML is case-insensitive, but SVG-embedded-in-HTML is case-sensitive.
+ "foreignobject",
+ "frame",
+ "frameset",
+ "image",
+ "isindex",
+ "listing",
+ "malignmark",
+ "marquee",
+ "math",
+ "mglyph",
+ "mi",
+ "mn",
+ "mo",
+ "ms",
+ "mtext",
+ "nobr",
+ "noembed",
+ "noframes",
+ "plaintext",
+ "prompt",
+ "public",
+ "spacer",
+ "strike",
+ "svg",
+ "system",
+ "tt",
+ "xmp",
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/atom/table.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/atom/table.go
new file mode 100644
index 000000000..f74018ece
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/atom/table.go
@@ -0,0 +1,777 @@
+// Code generated by go generate gen.go; DO NOT EDIT.
+
+//go:generate go run gen.go
+
+package atom
+
+const (
+ A Atom = 0x1
+ Abbr Atom = 0x4
+ Accept Atom = 0x1a06
+ AcceptCharset Atom = 0x1a0e
+ Accesskey Atom = 0x2c09
+ Action Atom = 0x25a06
+ Address Atom = 0x6ed07
+ Align Atom = 0x6d405
+ Allowfullscreen Atom = 0x1f00f
+ Allowpaymentrequest Atom = 0x6913
+ Allowusermedia Atom = 0x850e
+ Alt Atom = 0xb003
+ Annotation Atom = 0x1b90a
+ AnnotationXml Atom = 0x1b90e
+ Applet Atom = 0x30106
+ Area Atom = 0x34a04
+ Article Atom = 0x3f007
+ As Atom = 0xb902
+ Aside Atom = 0xc105
+ Async Atom = 0xb905
+ Audio Atom = 0xcf05
+ Autocomplete Atom = 0x2600c
+ Autofocus Atom = 0xeb09
+ Autoplay Atom = 0x10608
+ B Atom = 0x101
+ Base Atom = 0x11504
+ Basefont Atom = 0x11508
+ Bdi Atom = 0x16103
+ Bdo Atom = 0x13403
+ Bgsound Atom = 0x14707
+ Big Atom = 0x15903
+ Blink Atom = 0x15c05
+ Blockquote Atom = 0x1680a
+ Body Atom = 0x2804
+ Br Atom = 0x202
+ Button Atom = 0x17206
+ Canvas Atom = 0xbd06
+ Caption Atom = 0x21907
+ Center Atom = 0x20806
+ Challenge Atom = 0x28309
+ Charset Atom = 0x2107
+ Checked Atom = 0x46d07
+ Cite Atom = 0x55804
+ Class Atom = 0x5b905
+ Code Atom = 0x19004
+ Col Atom = 0x19703
+ Colgroup Atom = 0x19708
+ Color Atom = 0x1af05
+ Cols Atom = 0x1b404
+ Colspan Atom = 0x1b407
+ Command Atom = 0x1c707
+ Content Atom = 0x57f07
+ Contenteditable Atom = 0x57f0f
+ Contextmenu Atom = 0x3740b
+ Controls Atom = 0x1ce08
+ Coords Atom = 0x1da06
+ Crossorigin Atom = 0x1e30b
+ Data Atom = 0x49904
+ Datalist Atom = 0x49908
+ Datetime Atom = 0x2a008
+ Dd Atom = 0x2bf02
+ Default Atom = 0xc407
+ Defer Atom = 0x19205
+ Del Atom = 0x44603
+ Desc Atom = 0x55504
+ Details Atom = 0x4607
+ Dfn Atom = 0x5f03
+ Dialog Atom = 0x16206
+ Dir Atom = 0xa303
+ Dirname Atom = 0xa307
+ Disabled Atom = 0x14d08
+ Div Atom = 0x15403
+ Dl Atom = 0x5e202
+ Download Atom = 0x45708
+ Draggable Atom = 0x18309
+ Dropzone Atom = 0x3f908
+ Dt Atom = 0x64702
+ Em Atom = 0x4202
+ Embed Atom = 0x4205
+ Enctype Atom = 0x27507
+ Face Atom = 0x20604
+ Fieldset Atom = 0x20e08
+ Figcaption Atom = 0x2160a
+ Figure Atom = 0x23006
+ Font Atom = 0x11904
+ Footer Atom = 0xb306
+ For Atom = 0x23c03
+ ForeignObject Atom = 0x23c0d
+ Foreignobject Atom = 0x2490d
+ Form Atom = 0x25604
+ Formaction Atom = 0x2560a
+ Formenctype Atom = 0x2710b
+ Formmethod Atom = 0x28c0a
+ Formnovalidate Atom = 0x2960e
+ Formtarget Atom = 0x2a80a
+ Frame Atom = 0x5705
+ Frameset Atom = 0x5708
+ H1 Atom = 0x14502
+ H2 Atom = 0x2c602
+ H3 Atom = 0x2f502
+ H4 Atom = 0x33902
+ H5 Atom = 0x34302
+ H6 Atom = 0x64902
+ Head Atom = 0x32504
+ Header Atom = 0x32506
+ Headers Atom = 0x32507
+ Height Atom = 0x12c06
+ Hgroup Atom = 0x2b206
+ Hidden Atom = 0x2bd06
+ High Atom = 0x2c304
+ Hr Atom = 0x14002
+ Href Atom = 0x2c804
+ Hreflang Atom = 0x2c808
+ Html Atom = 0x13004
+ HttpEquiv Atom = 0x2d00a
+ I Atom = 0x601
+ Icon Atom = 0x57e04
+ Id Atom = 0xc302
+ Iframe Atom = 0x2e406
+ Image Atom = 0x2ea05
+ Img Atom = 0x2ef03
+ Input Atom = 0x43f05
+ Inputmode Atom = 0x43f09
+ Ins Atom = 0x1ec03
+ Integrity Atom = 0x22709
+ Is Atom = 0x14e02
+ Isindex Atom = 0x2f707
+ Ismap Atom = 0x2fe05
+ Itemid Atom = 0x37f06
+ Itemprop Atom = 0x55908
+ Itemref Atom = 0x3c107
+ Itemscope Atom = 0x66d09
+ Itemtype Atom = 0x30708
+ Kbd Atom = 0x16003
+ Keygen Atom = 0x3206
+ Keytype Atom = 0x7e07
+ Kind Atom = 0x18004
+ Label Atom = 0xda05
+ Lang Atom = 0x2cc04
+ Legend Atom = 0x18a06
+ Li Atom = 0x11102
+ Link Atom = 0x15d04
+ List Atom = 0x49d04
+ Listing Atom = 0x49d07
+ Loop Atom = 0xde04
+ Low Atom = 0x6b03
+ Main Atom = 0x1004
+ Malignmark Atom = 0x6d30a
+ Manifest Atom = 0x30f08
+ Map Atom = 0x30003
+ Mark Atom = 0x6d904
+ Marquee Atom = 0x31b07
+ Math Atom = 0x32204
+ Max Atom = 0x33103
+ Maxlength Atom = 0x33109
+ Media Atom = 0x8e05
+ Mediagroup Atom = 0x8e0a
+ Menu Atom = 0x37b04
+ Menuitem Atom = 0x37b08
+ Meta Atom = 0x4ac04
+ Meter Atom = 0xa805
+ Method Atom = 0x29006
+ Mglyph Atom = 0x2f006
+ Mi Atom = 0x33b02
+ Min Atom = 0x33b03
+ Minlength Atom = 0x33b09
+ Mn Atom = 0x29902
+ Mo Atom = 0x6302
+ Ms Atom = 0x67002
+ Mtext Atom = 0x34505
+ Multiple Atom = 0x35308
+ Muted Atom = 0x35b05
+ Name Atom = 0xa604
+ Nav Atom = 0x1303
+ Nobr Atom = 0x3704
+ Noembed Atom = 0x4007
+ Noframes Atom = 0x5508
+ Nomodule Atom = 0x6108
+ Nonce Atom = 0x56205
+ Noscript Atom = 0x1fe08
+ Novalidate Atom = 0x29a0a
+ Object Atom = 0x25006
+ Ol Atom = 0x10102
+ Onabort Atom = 0x17607
+ Onafterprint Atom = 0x21e0c
+ Onautocomplete Atom = 0x25e0e
+ Onautocompleteerror Atom = 0x25e13
+ Onauxclick Atom = 0x61b0a
+ Onbeforeprint Atom = 0x69a0d
+ Onbeforeunload Atom = 0x6e10e
+ Onblur Atom = 0x5c206
+ Oncancel Atom = 0xd308
+ Oncanplay Atom = 0x13609
+ Oncanplaythrough Atom = 0x13610
+ Onchange Atom = 0x40f08
+ Onclick Atom = 0x2dd07
+ Onclose Atom = 0x36007
+ Oncontextmenu Atom = 0x3720d
+ Oncopy Atom = 0x38506
+ Oncuechange Atom = 0x38b0b
+ Oncut Atom = 0x39605
+ Ondblclick Atom = 0x39b0a
+ Ondrag Atom = 0x3a506
+ Ondragend Atom = 0x3a509
+ Ondragenter Atom = 0x3ae0b
+ Ondragexit Atom = 0x3b90a
+ Ondragleave Atom = 0x3d30b
+ Ondragover Atom = 0x3de0a
+ Ondragstart Atom = 0x3e80b
+ Ondrop Atom = 0x3f706
+ Ondurationchange Atom = 0x40710
+ Onemptied Atom = 0x3fe09
+ Onended Atom = 0x41707
+ Onerror Atom = 0x41e07
+ Onfocus Atom = 0x42507
+ Onhashchange Atom = 0x4310c
+ Oninput Atom = 0x43d07
+ Oninvalid Atom = 0x44909
+ Onkeydown Atom = 0x45209
+ Onkeypress Atom = 0x45f0a
+ Onkeyup Atom = 0x47407
+ Onlanguagechange Atom = 0x48110
+ Onload Atom = 0x49106
+ Onloadeddata Atom = 0x4910c
+ Onloadedmetadata Atom = 0x4a410
+ Onloadend Atom = 0x4ba09
+ Onloadstart Atom = 0x4c30b
+ Onmessage Atom = 0x4ce09
+ Onmessageerror Atom = 0x4ce0e
+ Onmousedown Atom = 0x4dc0b
+ Onmouseenter Atom = 0x4e70c
+ Onmouseleave Atom = 0x4f30c
+ Onmousemove Atom = 0x4ff0b
+ Onmouseout Atom = 0x50a0a
+ Onmouseover Atom = 0x5170b
+ Onmouseup Atom = 0x52209
+ Onmousewheel Atom = 0x5300c
+ Onoffline Atom = 0x53c09
+ Ononline Atom = 0x54508
+ Onpagehide Atom = 0x54d0a
+ Onpageshow Atom = 0x5670a
+ Onpaste Atom = 0x57307
+ Onpause Atom = 0x58e07
+ Onplay Atom = 0x59806
+ Onplaying Atom = 0x59809
+ Onpopstate Atom = 0x5a10a
+ Onprogress Atom = 0x5ab0a
+ Onratechange Atom = 0x5c80c
+ Onrejectionhandled Atom = 0x5d412
+ Onreset Atom = 0x5e607
+ Onresize Atom = 0x5ed08
+ Onscroll Atom = 0x5fc08
+ Onsecuritypolicyviolation Atom = 0x60419
+ Onseeked Atom = 0x62508
+ Onseeking Atom = 0x62d09
+ Onselect Atom = 0x63608
+ Onshow Atom = 0x64006
+ Onsort Atom = 0x64b06
+ Onstalled Atom = 0x65509
+ Onstorage Atom = 0x65e09
+ Onsubmit Atom = 0x66708
+ Onsuspend Atom = 0x67709
+ Ontimeupdate Atom = 0x11a0c
+ Ontoggle Atom = 0x68008
+ Onunhandledrejection Atom = 0x68814
+ Onunload Atom = 0x6a708
+ Onvolumechange Atom = 0x6af0e
+ Onwaiting Atom = 0x6bd09
+ Onwheel Atom = 0x6c607
+ Open Atom = 0x55f04
+ Optgroup Atom = 0xe008
+ Optimum Atom = 0x6cd07
+ Option Atom = 0x6dd06
+ Output Atom = 0x51106
+ P Atom = 0xc01
+ Param Atom = 0xc05
+ Pattern Atom = 0x4f07
+ Picture Atom = 0x9707
+ Ping Atom = 0xe704
+ Placeholder Atom = 0xfb0b
+ Plaintext Atom = 0x19e09
+ Playsinline Atom = 0x10a0b
+ Poster Atom = 0x2b706
+ Pre Atom = 0x46403
+ Preload Atom = 0x47a07
+ Progress Atom = 0x5ad08
+ Prompt Atom = 0x52a06
+ Public Atom = 0x57a06
+ Q Atom = 0x7701
+ Radiogroup Atom = 0x30a
+ Readonly Atom = 0x34b08
+ Referrerpolicy Atom = 0x3c50e
+ Rel Atom = 0x47b03
+ Required Atom = 0x23408
+ Reversed Atom = 0x9c08
+ Rows Atom = 0x3a04
+ Rowspan Atom = 0x3a07
+ Rp Atom = 0x22402
+ Rt Atom = 0x17b02
+ Ruby Atom = 0xac04
+ S Atom = 0x2501
+ Samp Atom = 0x4c04
+ Sandbox Atom = 0xf307
+ Scope Atom = 0x67105
+ Scoped Atom = 0x67106
+ Script Atom = 0x20006
+ Seamless Atom = 0x36508
+ Section Atom = 0x5bd07
+ Select Atom = 0x63806
+ Selected Atom = 0x63808
+ Shape Atom = 0x1d505
+ Size Atom = 0x5f104
+ Sizes Atom = 0x5f105
+ Slot Atom = 0x1df04
+ Small Atom = 0x1ee05
+ Sortable Atom = 0x64d08
+ Sorted Atom = 0x32b06
+ Source Atom = 0x36c06
+ Spacer Atom = 0x42b06
+ Span Atom = 0x3d04
+ Spellcheck Atom = 0x4680a
+ Src Atom = 0x5b403
+ Srcdoc Atom = 0x5b406
+ Srclang Atom = 0x5f507
+ Srcset Atom = 0x6f306
+ Start Atom = 0x3ee05
+ Step Atom = 0x57704
+ Strike Atom = 0x7a06
+ Strong Atom = 0x31506
+ Style Atom = 0x6f905
+ Sub Atom = 0x66903
+ Summary Atom = 0x6fe07
+ Sup Atom = 0x70503
+ Svg Atom = 0x70803
+ System Atom = 0x70b06
+ Tabindex Atom = 0x4b208
+ Table Atom = 0x58905
+ Target Atom = 0x2ac06
+ Tbody Atom = 0x2705
+ Td Atom = 0x5e02
+ Template Atom = 0x70e08
+ Textarea Atom = 0x34608
+ Tfoot Atom = 0xb205
+ Th Atom = 0x13f02
+ Thead Atom = 0x32405
+ Time Atom = 0x11c04
+ Title Atom = 0xca05
+ Tr Atom = 0x7402
+ Track Atom = 0x17c05
+ Translate Atom = 0x1a609
+ Tt Atom = 0x5102
+ Type Atom = 0x8104
+ Typemustmatch Atom = 0x2780d
+ U Atom = 0xb01
+ Ul Atom = 0x6602
+ Updateviacache Atom = 0x1200e
+ Usemap Atom = 0x59206
+ Value Atom = 0x1505
+ Var Atom = 0x15603
+ Video Atom = 0x2d905
+ Wbr Atom = 0x57003
+ Width Atom = 0x64505
+ Workertype Atom = 0x7160a
+ Wrap Atom = 0x72004
+ Xmp Atom = 0xf903
+)
+
+const hash0 = 0x81cdf10e
+
+const maxAtomLen = 25
+
+var table = [1 << 9]Atom{
+ 0x1: 0x8e0a, // mediagroup
+ 0x2: 0x2cc04, // lang
+ 0x4: 0x2c09, // accesskey
+ 0x5: 0x5708, // frameset
+ 0x7: 0x63608, // onselect
+ 0x8: 0x70b06, // system
+ 0xa: 0x64505, // width
+ 0xc: 0x2710b, // formenctype
+ 0xd: 0x10102, // ol
+ 0xe: 0x38b0b, // oncuechange
+ 0x10: 0x13403, // bdo
+ 0x11: 0xcf05, // audio
+ 0x12: 0x18309, // draggable
+ 0x14: 0x2d905, // video
+ 0x15: 0x29902, // mn
+ 0x16: 0x37b04, // menu
+ 0x17: 0x2b706, // poster
+ 0x19: 0xb306, // footer
+ 0x1a: 0x29006, // method
+ 0x1b: 0x2a008, // datetime
+ 0x1c: 0x17607, // onabort
+ 0x1d: 0x1200e, // updateviacache
+ 0x1e: 0xb905, // async
+ 0x1f: 0x49106, // onload
+ 0x21: 0xd308, // oncancel
+ 0x22: 0x62508, // onseeked
+ 0x23: 0x2ea05, // image
+ 0x24: 0x5d412, // onrejectionhandled
+ 0x26: 0x15d04, // link
+ 0x27: 0x51106, // output
+ 0x28: 0x32504, // head
+ 0x29: 0x4f30c, // onmouseleave
+ 0x2a: 0x57307, // onpaste
+ 0x2b: 0x59809, // onplaying
+ 0x2c: 0x1b407, // colspan
+ 0x2f: 0x1af05, // color
+ 0x30: 0x5f104, // size
+ 0x31: 0x2d00a, // http-equiv
+ 0x33: 0x601, // i
+ 0x34: 0x54d0a, // onpagehide
+ 0x35: 0x68814, // onunhandledrejection
+ 0x37: 0x41e07, // onerror
+ 0x3a: 0x11508, // basefont
+ 0x3f: 0x1303, // nav
+ 0x40: 0x18004, // kind
+ 0x41: 0x34b08, // readonly
+ 0x42: 0x2f006, // mglyph
+ 0x44: 0x11102, // li
+ 0x46: 0x2bd06, // hidden
+ 0x47: 0x70803, // svg
+ 0x48: 0x57704, // step
+ 0x49: 0x22709, // integrity
+ 0x4a: 0x57a06, // public
+ 0x4c: 0x19703, // col
+ 0x4d: 0x1680a, // blockquote
+ 0x4e: 0x34302, // h5
+ 0x50: 0x5ad08, // progress
+ 0x51: 0x5f105, // sizes
+ 0x52: 0x33902, // h4
+ 0x56: 0x32405, // thead
+ 0x57: 0x7e07, // keytype
+ 0x58: 0x5ab0a, // onprogress
+ 0x59: 0x43f09, // inputmode
+ 0x5a: 0x3a509, // ondragend
+ 0x5d: 0x39605, // oncut
+ 0x5e: 0x42b06, // spacer
+ 0x5f: 0x19708, // colgroup
+ 0x62: 0x14e02, // is
+ 0x65: 0xb902, // as
+ 0x66: 0x53c09, // onoffline
+ 0x67: 0x32b06, // sorted
+ 0x69: 0x48110, // onlanguagechange
+ 0x6c: 0x4310c, // onhashchange
+ 0x6d: 0xa604, // name
+ 0x6e: 0xb205, // tfoot
+ 0x6f: 0x55504, // desc
+ 0x70: 0x33103, // max
+ 0x72: 0x1da06, // coords
+ 0x73: 0x2f502, // h3
+ 0x74: 0x6e10e, // onbeforeunload
+ 0x75: 0x3a04, // rows
+ 0x76: 0x63806, // select
+ 0x77: 0xa805, // meter
+ 0x78: 0x37f06, // itemid
+ 0x79: 0x5300c, // onmousewheel
+ 0x7a: 0x5b406, // srcdoc
+ 0x7d: 0x17c05, // track
+ 0x7f: 0x30708, // itemtype
+ 0x82: 0x6302, // mo
+ 0x83: 0x40f08, // onchange
+ 0x84: 0x32507, // headers
+ 0x85: 0x5c80c, // onratechange
+ 0x86: 0x60419, // onsecuritypolicyviolation
+ 0x88: 0x49908, // datalist
+ 0x89: 0x4dc0b, // onmousedown
+ 0x8a: 0x1df04, // slot
+ 0x8b: 0x4a410, // onloadedmetadata
+ 0x8c: 0x1a06, // accept
+ 0x8d: 0x25006, // object
+ 0x91: 0x6af0e, // onvolumechange
+ 0x92: 0x2107, // charset
+ 0x93: 0x25e13, // onautocompleteerror
+ 0x94: 0x6913, // allowpaymentrequest
+ 0x95: 0x2804, // body
+ 0x96: 0xc407, // default
+ 0x97: 0x63808, // selected
+ 0x98: 0x20604, // face
+ 0x99: 0x1d505, // shape
+ 0x9b: 0x68008, // ontoggle
+ 0x9e: 0x64702, // dt
+ 0x9f: 0x6d904, // mark
+ 0xa1: 0xb01, // u
+ 0xa4: 0x6a708, // onunload
+ 0xa5: 0xde04, // loop
+ 0xa6: 0x14d08, // disabled
+ 0xaa: 0x41707, // onended
+ 0xab: 0x6d30a, // malignmark
+ 0xad: 0x67709, // onsuspend
+ 0xae: 0x34505, // mtext
+ 0xaf: 0x64b06, // onsort
+ 0xb0: 0x55908, // itemprop
+ 0xb3: 0x66d09, // itemscope
+ 0xb4: 0x15c05, // blink
+ 0xb6: 0x3a506, // ondrag
+ 0xb7: 0x6602, // ul
+ 0xb8: 0x25604, // form
+ 0xb9: 0xf307, // sandbox
+ 0xba: 0x5705, // frame
+ 0xbb: 0x1505, // value
+ 0xbc: 0x65e09, // onstorage
+ 0xc0: 0x17b02, // rt
+ 0xc2: 0x202, // br
+ 0xc3: 0x20e08, // fieldset
+ 0xc4: 0x2780d, // typemustmatch
+ 0xc5: 0x6108, // nomodule
+ 0xc6: 0x4007, // noembed
+ 0xc7: 0x69a0d, // onbeforeprint
+ 0xc8: 0x17206, // button
+ 0xc9: 0x2dd07, // onclick
+ 0xca: 0x6fe07, // summary
+ 0xcd: 0xac04, // ruby
+ 0xce: 0x5b905, // class
+ 0xcf: 0x3e80b, // ondragstart
+ 0xd0: 0x21907, // caption
+ 0xd4: 0x850e, // allowusermedia
+ 0xd5: 0x4c30b, // onloadstart
+ 0xd9: 0x15403, // div
+ 0xda: 0x49d04, // list
+ 0xdb: 0x32204, // math
+ 0xdc: 0x43f05, // input
+ 0xdf: 0x3de0a, // ondragover
+ 0xe0: 0x2c602, // h2
+ 0xe2: 0x19e09, // plaintext
+ 0xe4: 0x4e70c, // onmouseenter
+ 0xe7: 0x46d07, // checked
+ 0xe8: 0x46403, // pre
+ 0xea: 0x35308, // multiple
+ 0xeb: 0x16103, // bdi
+ 0xec: 0x33109, // maxlength
+ 0xed: 0x7701, // q
+ 0xee: 0x61b0a, // onauxclick
+ 0xf0: 0x57003, // wbr
+ 0xf2: 0x11504, // base
+ 0xf3: 0x6dd06, // option
+ 0xf5: 0x40710, // ondurationchange
+ 0xf7: 0x5508, // noframes
+ 0xf9: 0x3f908, // dropzone
+ 0xfb: 0x67105, // scope
+ 0xfc: 0x9c08, // reversed
+ 0xfd: 0x3ae0b, // ondragenter
+ 0xfe: 0x3ee05, // start
+ 0xff: 0xf903, // xmp
+ 0x100: 0x5f507, // srclang
+ 0x101: 0x2ef03, // img
+ 0x104: 0x101, // b
+ 0x105: 0x23c03, // for
+ 0x106: 0xc105, // aside
+ 0x107: 0x43d07, // oninput
+ 0x108: 0x34a04, // area
+ 0x109: 0x28c0a, // formmethod
+ 0x10a: 0x72004, // wrap
+ 0x10c: 0x22402, // rp
+ 0x10d: 0x45f0a, // onkeypress
+ 0x10e: 0x5102, // tt
+ 0x110: 0x33b02, // mi
+ 0x111: 0x35b05, // muted
+ 0x112: 0xb003, // alt
+ 0x113: 0x19004, // code
+ 0x114: 0x4202, // em
+ 0x115: 0x3b90a, // ondragexit
+ 0x117: 0x3d04, // span
+ 0x119: 0x30f08, // manifest
+ 0x11a: 0x37b08, // menuitem
+ 0x11b: 0x57f07, // content
+ 0x11d: 0x6bd09, // onwaiting
+ 0x11f: 0x4ba09, // onloadend
+ 0x121: 0x3720d, // oncontextmenu
+ 0x123: 0x5c206, // onblur
+ 0x124: 0x3f007, // article
+ 0x125: 0xa303, // dir
+ 0x126: 0xe704, // ping
+ 0x127: 0x23408, // required
+ 0x128: 0x44909, // oninvalid
+ 0x129: 0x6d405, // align
+ 0x12b: 0x57e04, // icon
+ 0x12c: 0x64902, // h6
+ 0x12d: 0x1b404, // cols
+ 0x12e: 0x2160a, // figcaption
+ 0x12f: 0x45209, // onkeydown
+ 0x130: 0x66708, // onsubmit
+ 0x131: 0x13609, // oncanplay
+ 0x132: 0x70503, // sup
+ 0x133: 0xc01, // p
+ 0x135: 0x3fe09, // onemptied
+ 0x136: 0x38506, // oncopy
+ 0x137: 0x55804, // cite
+ 0x138: 0x39b0a, // ondblclick
+ 0x13a: 0x4ff0b, // onmousemove
+ 0x13c: 0x66903, // sub
+ 0x13d: 0x47b03, // rel
+ 0x13e: 0xe008, // optgroup
+ 0x142: 0x3a07, // rowspan
+ 0x143: 0x36c06, // source
+ 0x144: 0x1fe08, // noscript
+ 0x145: 0x55f04, // open
+ 0x146: 0x1ec03, // ins
+ 0x147: 0x23c0d, // foreignObject
+ 0x148: 0x5a10a, // onpopstate
+ 0x14a: 0x27507, // enctype
+ 0x14b: 0x25e0e, // onautocomplete
+ 0x14c: 0x34608, // textarea
+ 0x14e: 0x2600c, // autocomplete
+ 0x14f: 0x14002, // hr
+ 0x150: 0x1ce08, // controls
+ 0x151: 0xc302, // id
+ 0x153: 0x21e0c, // onafterprint
+ 0x155: 0x2490d, // foreignobject
+ 0x156: 0x31b07, // marquee
+ 0x157: 0x58e07, // onpause
+ 0x158: 0x5e202, // dl
+ 0x159: 0x12c06, // height
+ 0x15a: 0x33b03, // min
+ 0x15b: 0xa307, // dirname
+ 0x15c: 0x1a609, // translate
+ 0x15d: 0x13004, // html
+ 0x15e: 0x33b09, // minlength
+ 0x15f: 0x47a07, // preload
+ 0x160: 0x70e08, // template
+ 0x161: 0x3d30b, // ondragleave
+ 0x164: 0x5b403, // src
+ 0x165: 0x31506, // strong
+ 0x167: 0x4c04, // samp
+ 0x168: 0x6ed07, // address
+ 0x169: 0x54508, // ononline
+ 0x16b: 0xfb0b, // placeholder
+ 0x16c: 0x2ac06, // target
+ 0x16d: 0x1ee05, // small
+ 0x16e: 0x6c607, // onwheel
+ 0x16f: 0x1b90a, // annotation
+ 0x170: 0x4680a, // spellcheck
+ 0x171: 0x4607, // details
+ 0x172: 0xbd06, // canvas
+ 0x173: 0xeb09, // autofocus
+ 0x174: 0xc05, // param
+ 0x176: 0x45708, // download
+ 0x177: 0x44603, // del
+ 0x178: 0x36007, // onclose
+ 0x179: 0x16003, // kbd
+ 0x17a: 0x30106, // applet
+ 0x17b: 0x2c804, // href
+ 0x17c: 0x5ed08, // onresize
+ 0x17e: 0x4910c, // onloadeddata
+ 0x180: 0x7402, // tr
+ 0x181: 0x2a80a, // formtarget
+ 0x182: 0xca05, // title
+ 0x183: 0x6f905, // style
+ 0x184: 0x7a06, // strike
+ 0x185: 0x59206, // usemap
+ 0x186: 0x2e406, // iframe
+ 0x187: 0x1004, // main
+ 0x189: 0x9707, // picture
+ 0x18c: 0x2fe05, // ismap
+ 0x18e: 0x49904, // data
+ 0x18f: 0xda05, // label
+ 0x191: 0x3c50e, // referrerpolicy
+ 0x192: 0x13f02, // th
+ 0x194: 0x52a06, // prompt
+ 0x195: 0x5bd07, // section
+ 0x197: 0x6cd07, // optimum
+ 0x198: 0x2c304, // high
+ 0x199: 0x14502, // h1
+ 0x19a: 0x65509, // onstalled
+ 0x19b: 0x15603, // var
+ 0x19c: 0x11c04, // time
+ 0x19e: 0x67002, // ms
+ 0x19f: 0x32506, // header
+ 0x1a0: 0x4ce09, // onmessage
+ 0x1a1: 0x56205, // nonce
+ 0x1a2: 0x2560a, // formaction
+ 0x1a3: 0x20806, // center
+ 0x1a4: 0x3704, // nobr
+ 0x1a5: 0x58905, // table
+ 0x1a6: 0x49d07, // listing
+ 0x1a7: 0x18a06, // legend
+ 0x1a9: 0x28309, // challenge
+ 0x1aa: 0x23006, // figure
+ 0x1ab: 0x8e05, // media
+ 0x1ae: 0x8104, // type
+ 0x1af: 0x11904, // font
+ 0x1b0: 0x4ce0e, // onmessageerror
+ 0x1b1: 0x36508, // seamless
+ 0x1b2: 0x5f03, // dfn
+ 0x1b3: 0x19205, // defer
+ 0x1b4: 0x6b03, // low
+ 0x1b5: 0x62d09, // onseeking
+ 0x1b6: 0x5170b, // onmouseover
+ 0x1b7: 0x29a0a, // novalidate
+ 0x1b8: 0x7160a, // workertype
+ 0x1ba: 0x3c107, // itemref
+ 0x1bd: 0x1, // a
+ 0x1be: 0x30003, // map
+ 0x1bf: 0x11a0c, // ontimeupdate
+ 0x1c0: 0x14707, // bgsound
+ 0x1c1: 0x3206, // keygen
+ 0x1c2: 0x2705, // tbody
+ 0x1c5: 0x64006, // onshow
+ 0x1c7: 0x2501, // s
+ 0x1c8: 0x4f07, // pattern
+ 0x1cc: 0x13610, // oncanplaythrough
+ 0x1ce: 0x2bf02, // dd
+ 0x1cf: 0x6f306, // srcset
+ 0x1d0: 0x15903, // big
+ 0x1d2: 0x64d08, // sortable
+ 0x1d3: 0x47407, // onkeyup
+ 0x1d5: 0x59806, // onplay
+ 0x1d7: 0x4ac04, // meta
+ 0x1d8: 0x3f706, // ondrop
+ 0x1da: 0x5fc08, // onscroll
+ 0x1db: 0x1e30b, // crossorigin
+ 0x1dc: 0x5670a, // onpageshow
+ 0x1dd: 0x4, // abbr
+ 0x1de: 0x5e02, // td
+ 0x1df: 0x57f0f, // contenteditable
+ 0x1e0: 0x25a06, // action
+ 0x1e1: 0x10a0b, // playsinline
+ 0x1e2: 0x42507, // onfocus
+ 0x1e3: 0x2c808, // hreflang
+ 0x1e5: 0x50a0a, // onmouseout
+ 0x1e6: 0x5e607, // onreset
+ 0x1e7: 0x10608, // autoplay
+ 0x1ea: 0x67106, // scoped
+ 0x1ec: 0x30a, // radiogroup
+ 0x1ee: 0x3740b, // contextmenu
+ 0x1ef: 0x52209, // onmouseup
+ 0x1f1: 0x2b206, // hgroup
+ 0x1f2: 0x1f00f, // allowfullscreen
+ 0x1f3: 0x4b208, // tabindex
+ 0x1f6: 0x2f707, // isindex
+ 0x1f7: 0x1a0e, // accept-charset
+ 0x1f8: 0x2960e, // formnovalidate
+ 0x1fb: 0x1b90e, // annotation-xml
+ 0x1fc: 0x4205, // embed
+ 0x1fd: 0x20006, // script
+ 0x1fe: 0x16206, // dialog
+ 0x1ff: 0x1c707, // command
+}
+
+const atomText = "abbradiogrouparamainavalueaccept-charsetbodyaccesskeygenobro" +
+ "wspanoembedetailsampatternoframesetdfnomoduleallowpaymentreq" +
+ "uestrikeytypeallowusermediagroupictureversedirnameterubyaltf" +
+ "ooterasyncanvasidefaultitleaudioncancelabelooptgroupingautof" +
+ "ocusandboxmplaceholderautoplaysinlinebasefontimeupdateviacac" +
+ "heightmlbdoncanplaythrough1bgsoundisabledivarbigblinkbdialog" +
+ "blockquotebuttonabortrackindraggablegendcodefercolgrouplaint" +
+ "extranslatecolorcolspannotation-xmlcommandcontrolshapecoords" +
+ "lotcrossoriginsmallowfullscreenoscriptfacenterfieldsetfigcap" +
+ "tionafterprintegrityfigurequiredforeignObjectforeignobjectfo" +
+ "rmactionautocompleteerrorformenctypemustmatchallengeformmeth" +
+ "odformnovalidatetimeformtargethgrouposterhiddenhigh2hreflang" +
+ "http-equivideonclickiframeimageimglyph3isindexismappletitemt" +
+ "ypemanifestrongmarqueematheadersortedmaxlength4minlength5mte" +
+ "xtareadonlymultiplemutedoncloseamlessourceoncontextmenuitemi" +
+ "doncopyoncuechangeoncutondblclickondragendondragenterondrage" +
+ "xitemreferrerpolicyondragleaveondragoverondragstarticleondro" +
+ "pzonemptiedondurationchangeonendedonerroronfocuspaceronhashc" +
+ "hangeoninputmodeloninvalidonkeydownloadonkeypresspellchecked" +
+ "onkeyupreloadonlanguagechangeonloadeddatalistingonloadedmeta" +
+ "databindexonloadendonloadstartonmessageerroronmousedownonmou" +
+ "seenteronmouseleaveonmousemoveonmouseoutputonmouseoveronmous" +
+ "eupromptonmousewheelonofflineononlineonpagehidescitempropeno" +
+ "nceonpageshowbronpastepublicontenteditableonpausemaponplayin" +
+ "gonpopstateonprogressrcdoclassectionbluronratechangeonreject" +
+ "ionhandledonresetonresizesrclangonscrollonsecuritypolicyviol" +
+ "ationauxclickonseekedonseekingonselectedonshowidth6onsortabl" +
+ "eonstalledonstorageonsubmitemscopedonsuspendontoggleonunhand" +
+ "ledrejectionbeforeprintonunloadonvolumechangeonwaitingonwhee" +
+ "loptimumalignmarkoptionbeforeunloaddressrcsetstylesummarysup" +
+ "svgsystemplateworkertypewrap"
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/atom/table_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/atom/table_test.go
new file mode 100644
index 000000000..16891054f
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/atom/table_test.go
@@ -0,0 +1,373 @@
+// Code generated by go generate gen.go; DO NOT EDIT.
+
+//go:generate go run gen.go -test
+
+package atom
+
+var testAtomList = []string{
+ "a",
+ "abbr",
+ "accept",
+ "accept-charset",
+ "accesskey",
+ "action",
+ "address",
+ "align",
+ "allowfullscreen",
+ "allowpaymentrequest",
+ "allowusermedia",
+ "alt",
+ "annotation",
+ "annotation-xml",
+ "applet",
+ "area",
+ "article",
+ "as",
+ "aside",
+ "async",
+ "audio",
+ "autocomplete",
+ "autofocus",
+ "autoplay",
+ "b",
+ "base",
+ "basefont",
+ "bdi",
+ "bdo",
+ "bgsound",
+ "big",
+ "blink",
+ "blockquote",
+ "body",
+ "br",
+ "button",
+ "canvas",
+ "caption",
+ "center",
+ "challenge",
+ "charset",
+ "checked",
+ "cite",
+ "class",
+ "code",
+ "col",
+ "colgroup",
+ "color",
+ "cols",
+ "colspan",
+ "command",
+ "content",
+ "contenteditable",
+ "contextmenu",
+ "controls",
+ "coords",
+ "crossorigin",
+ "data",
+ "datalist",
+ "datetime",
+ "dd",
+ "default",
+ "defer",
+ "del",
+ "desc",
+ "details",
+ "dfn",
+ "dialog",
+ "dir",
+ "dirname",
+ "disabled",
+ "div",
+ "dl",
+ "download",
+ "draggable",
+ "dropzone",
+ "dt",
+ "em",
+ "embed",
+ "enctype",
+ "face",
+ "fieldset",
+ "figcaption",
+ "figure",
+ "font",
+ "footer",
+ "for",
+ "foreignObject",
+ "foreignobject",
+ "form",
+ "formaction",
+ "formenctype",
+ "formmethod",
+ "formnovalidate",
+ "formtarget",
+ "frame",
+ "frameset",
+ "h1",
+ "h2",
+ "h3",
+ "h4",
+ "h5",
+ "h6",
+ "head",
+ "header",
+ "headers",
+ "height",
+ "hgroup",
+ "hidden",
+ "high",
+ "hr",
+ "href",
+ "hreflang",
+ "html",
+ "http-equiv",
+ "i",
+ "icon",
+ "id",
+ "iframe",
+ "image",
+ "img",
+ "input",
+ "inputmode",
+ "ins",
+ "integrity",
+ "is",
+ "isindex",
+ "ismap",
+ "itemid",
+ "itemprop",
+ "itemref",
+ "itemscope",
+ "itemtype",
+ "kbd",
+ "keygen",
+ "keytype",
+ "kind",
+ "label",
+ "lang",
+ "legend",
+ "li",
+ "link",
+ "list",
+ "listing",
+ "loop",
+ "low",
+ "main",
+ "malignmark",
+ "manifest",
+ "map",
+ "mark",
+ "marquee",
+ "math",
+ "max",
+ "maxlength",
+ "media",
+ "mediagroup",
+ "menu",
+ "menuitem",
+ "meta",
+ "meter",
+ "method",
+ "mglyph",
+ "mi",
+ "min",
+ "minlength",
+ "mn",
+ "mo",
+ "ms",
+ "mtext",
+ "multiple",
+ "muted",
+ "name",
+ "nav",
+ "nobr",
+ "noembed",
+ "noframes",
+ "nomodule",
+ "nonce",
+ "noscript",
+ "novalidate",
+ "object",
+ "ol",
+ "onabort",
+ "onafterprint",
+ "onautocomplete",
+ "onautocompleteerror",
+ "onauxclick",
+ "onbeforeprint",
+ "onbeforeunload",
+ "onblur",
+ "oncancel",
+ "oncanplay",
+ "oncanplaythrough",
+ "onchange",
+ "onclick",
+ "onclose",
+ "oncontextmenu",
+ "oncopy",
+ "oncuechange",
+ "oncut",
+ "ondblclick",
+ "ondrag",
+ "ondragend",
+ "ondragenter",
+ "ondragexit",
+ "ondragleave",
+ "ondragover",
+ "ondragstart",
+ "ondrop",
+ "ondurationchange",
+ "onemptied",
+ "onended",
+ "onerror",
+ "onfocus",
+ "onhashchange",
+ "oninput",
+ "oninvalid",
+ "onkeydown",
+ "onkeypress",
+ "onkeyup",
+ "onlanguagechange",
+ "onload",
+ "onloadeddata",
+ "onloadedmetadata",
+ "onloadend",
+ "onloadstart",
+ "onmessage",
+ "onmessageerror",
+ "onmousedown",
+ "onmouseenter",
+ "onmouseleave",
+ "onmousemove",
+ "onmouseout",
+ "onmouseover",
+ "onmouseup",
+ "onmousewheel",
+ "onoffline",
+ "ononline",
+ "onpagehide",
+ "onpageshow",
+ "onpaste",
+ "onpause",
+ "onplay",
+ "onplaying",
+ "onpopstate",
+ "onprogress",
+ "onratechange",
+ "onrejectionhandled",
+ "onreset",
+ "onresize",
+ "onscroll",
+ "onsecuritypolicyviolation",
+ "onseeked",
+ "onseeking",
+ "onselect",
+ "onshow",
+ "onsort",
+ "onstalled",
+ "onstorage",
+ "onsubmit",
+ "onsuspend",
+ "ontimeupdate",
+ "ontoggle",
+ "onunhandledrejection",
+ "onunload",
+ "onvolumechange",
+ "onwaiting",
+ "onwheel",
+ "open",
+ "optgroup",
+ "optimum",
+ "option",
+ "output",
+ "p",
+ "param",
+ "pattern",
+ "picture",
+ "ping",
+ "placeholder",
+ "plaintext",
+ "playsinline",
+ "poster",
+ "pre",
+ "preload",
+ "progress",
+ "prompt",
+ "public",
+ "q",
+ "radiogroup",
+ "readonly",
+ "referrerpolicy",
+ "rel",
+ "required",
+ "reversed",
+ "rows",
+ "rowspan",
+ "rp",
+ "rt",
+ "ruby",
+ "s",
+ "samp",
+ "sandbox",
+ "scope",
+ "scoped",
+ "script",
+ "seamless",
+ "section",
+ "select",
+ "selected",
+ "shape",
+ "size",
+ "sizes",
+ "slot",
+ "small",
+ "sortable",
+ "sorted",
+ "source",
+ "spacer",
+ "span",
+ "spellcheck",
+ "src",
+ "srcdoc",
+ "srclang",
+ "srcset",
+ "start",
+ "step",
+ "strike",
+ "strong",
+ "style",
+ "sub",
+ "summary",
+ "sup",
+ "svg",
+ "system",
+ "tabindex",
+ "table",
+ "target",
+ "tbody",
+ "td",
+ "template",
+ "textarea",
+ "tfoot",
+ "th",
+ "thead",
+ "time",
+ "title",
+ "tr",
+ "track",
+ "translate",
+ "tt",
+ "type",
+ "typemustmatch",
+ "u",
+ "ul",
+ "updateviacache",
+ "usemap",
+ "value",
+ "var",
+ "video",
+ "wbr",
+ "width",
+ "workertype",
+ "wrap",
+ "xmp",
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/charset.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/charset.go
new file mode 100644
index 000000000..13bed1599
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/charset.go
@@ -0,0 +1,257 @@
+// Copyright 2013 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 charset provides common text encodings for HTML documents.
+//
+// The mapping from encoding labels to encodings is defined at
+// https://encoding.spec.whatwg.org/.
+package charset // import "golang.org/x/net/html/charset"
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "mime"
+ "strings"
+ "unicode/utf8"
+
+ "golang.org/x/net/html"
+ "golang.org/x/text/encoding"
+ "golang.org/x/text/encoding/charmap"
+ "golang.org/x/text/encoding/htmlindex"
+ "golang.org/x/text/transform"
+)
+
+// Lookup returns the encoding with the specified label, and its canonical
+// name. It returns nil and the empty string if label is not one of the
+// standard encodings for HTML. Matching is case-insensitive and ignores
+// leading and trailing whitespace. Encoders will use HTML escape sequences for
+// runes that are not supported by the character set.
+func Lookup(label string) (e encoding.Encoding, name string) {
+ e, err := htmlindex.Get(label)
+ if err != nil {
+ return nil, ""
+ }
+ name, _ = htmlindex.Name(e)
+ return &htmlEncoding{e}, name
+}
+
+type htmlEncoding struct{ encoding.Encoding }
+
+func (h *htmlEncoding) NewEncoder() *encoding.Encoder {
+ // HTML requires a non-terminating legacy encoder. We use HTML escapes to
+ // substitute unsupported code points.
+ return encoding.HTMLEscapeUnsupported(h.Encoding.NewEncoder())
+}
+
+// DetermineEncoding determines the encoding of an HTML document by examining
+// up to the first 1024 bytes of content and the declared Content-Type.
+//
+// See http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html#determining-the-character-encoding
+func DetermineEncoding(content []byte, contentType string) (e encoding.Encoding, name string, certain bool) {
+ if len(content) > 1024 {
+ content = content[:1024]
+ }
+
+ for _, b := range boms {
+ if bytes.HasPrefix(content, b.bom) {
+ e, name = Lookup(b.enc)
+ return e, name, true
+ }
+ }
+
+ if _, params, err := mime.ParseMediaType(contentType); err == nil {
+ if cs, ok := params["charset"]; ok {
+ if e, name = Lookup(cs); e != nil {
+ return e, name, true
+ }
+ }
+ }
+
+ if len(content) > 0 {
+ e, name = prescan(content)
+ if e != nil {
+ return e, name, false
+ }
+ }
+
+ // Try to detect UTF-8.
+ // First eliminate any partial rune at the end.
+ for i := len(content) - 1; i >= 0 && i > len(content)-4; i-- {
+ b := content[i]
+ if b < 0x80 {
+ break
+ }
+ if utf8.RuneStart(b) {
+ content = content[:i]
+ break
+ }
+ }
+ hasHighBit := false
+ for _, c := range content {
+ if c >= 0x80 {
+ hasHighBit = true
+ break
+ }
+ }
+ if hasHighBit && utf8.Valid(content) {
+ return encoding.Nop, "utf-8", false
+ }
+
+ // TODO: change default depending on user's locale?
+ return charmap.Windows1252, "windows-1252", false
+}
+
+// NewReader returns an io.Reader that converts the content of r to UTF-8.
+// It calls DetermineEncoding to find out what r's encoding is.
+func NewReader(r io.Reader, contentType string) (io.Reader, error) {
+ preview := make([]byte, 1024)
+ n, err := io.ReadFull(r, preview)
+ switch {
+ case err == io.ErrUnexpectedEOF:
+ preview = preview[:n]
+ r = bytes.NewReader(preview)
+ case err != nil:
+ return nil, err
+ default:
+ r = io.MultiReader(bytes.NewReader(preview), r)
+ }
+
+ if e, _, _ := DetermineEncoding(preview, contentType); e != encoding.Nop {
+ r = transform.NewReader(r, e.NewDecoder())
+ }
+ return r, nil
+}
+
+// NewReaderLabel returns a reader that converts from the specified charset to
+// UTF-8. It uses Lookup to find the encoding that corresponds to label, and
+// returns an error if Lookup returns nil. It is suitable for use as
+// encoding/xml.Decoder's CharsetReader function.
+func NewReaderLabel(label string, input io.Reader) (io.Reader, error) {
+ e, _ := Lookup(label)
+ if e == nil {
+ return nil, fmt.Errorf("unsupported charset: %q", label)
+ }
+ return transform.NewReader(input, e.NewDecoder()), nil
+}
+
+func prescan(content []byte) (e encoding.Encoding, name string) {
+ z := html.NewTokenizer(bytes.NewReader(content))
+ for {
+ switch z.Next() {
+ case html.ErrorToken:
+ return nil, ""
+
+ case html.StartTagToken, html.SelfClosingTagToken:
+ tagName, hasAttr := z.TagName()
+ if !bytes.Equal(tagName, []byte("meta")) {
+ continue
+ }
+ attrList := make(map[string]bool)
+ gotPragma := false
+
+ const (
+ dontKnow = iota
+ doNeedPragma
+ doNotNeedPragma
+ )
+ needPragma := dontKnow
+
+ name = ""
+ e = nil
+ for hasAttr {
+ var key, val []byte
+ key, val, hasAttr = z.TagAttr()
+ ks := string(key)
+ if attrList[ks] {
+ continue
+ }
+ attrList[ks] = true
+ for i, c := range val {
+ if 'A' <= c && c <= 'Z' {
+ val[i] = c + 0x20
+ }
+ }
+
+ switch ks {
+ case "http-equiv":
+ if bytes.Equal(val, []byte("content-type")) {
+ gotPragma = true
+ }
+
+ case "content":
+ if e == nil {
+ name = fromMetaElement(string(val))
+ if name != "" {
+ e, name = Lookup(name)
+ if e != nil {
+ needPragma = doNeedPragma
+ }
+ }
+ }
+
+ case "charset":
+ e, name = Lookup(string(val))
+ needPragma = doNotNeedPragma
+ }
+ }
+
+ if needPragma == dontKnow || needPragma == doNeedPragma && !gotPragma {
+ continue
+ }
+
+ if strings.HasPrefix(name, "utf-16") {
+ name = "utf-8"
+ e = encoding.Nop
+ }
+
+ if e != nil {
+ return e, name
+ }
+ }
+ }
+}
+
+func fromMetaElement(s string) string {
+ for s != "" {
+ csLoc := strings.Index(s, "charset")
+ if csLoc == -1 {
+ return ""
+ }
+ s = s[csLoc+len("charset"):]
+ s = strings.TrimLeft(s, " \t\n\f\r")
+ if !strings.HasPrefix(s, "=") {
+ continue
+ }
+ s = s[1:]
+ s = strings.TrimLeft(s, " \t\n\f\r")
+ if s == "" {
+ return ""
+ }
+ if q := s[0]; q == '"' || q == '\'' {
+ s = s[1:]
+ closeQuote := strings.IndexRune(s, rune(q))
+ if closeQuote == -1 {
+ return ""
+ }
+ return s[:closeQuote]
+ }
+
+ end := strings.IndexAny(s, "; \t\n\f\r")
+ if end == -1 {
+ end = len(s)
+ }
+ return s[:end]
+ }
+ return ""
+}
+
+var boms = []struct {
+ bom []byte
+ enc string
+}{
+ {[]byte{0xfe, 0xff}, "utf-16be"},
+ {[]byte{0xff, 0xfe}, "utf-16le"},
+ {[]byte{0xef, 0xbb, 0xbf}, "utf-8"},
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/charset_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/charset_test.go
new file mode 100644
index 000000000..e4e7d86bf
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/charset_test.go
@@ -0,0 +1,237 @@
+// Copyright 2013 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 charset
+
+import (
+ "bytes"
+ "encoding/xml"
+ "io/ioutil"
+ "runtime"
+ "strings"
+ "testing"
+
+ "golang.org/x/text/transform"
+)
+
+func transformString(t transform.Transformer, s string) (string, error) {
+ r := transform.NewReader(strings.NewReader(s), t)
+ b, err := ioutil.ReadAll(r)
+ return string(b), err
+}
+
+type testCase struct {
+ utf8, other, otherEncoding string
+}
+
+// testCases for encoding and decoding.
+var testCases = []testCase{
+ {"Résumé", "Résumé", "utf8"},
+ {"Résumé", "R\xe9sum\xe9", "latin1"},
+ {"これは漢字です。", "S0\x8c0o0\"oW[g0Y0\x020", "UTF-16LE"},
+ {"これは漢字です。", "0S0\x8c0oo\"[W0g0Y0\x02", "UTF-16BE"},
+ {"Hello, world", "Hello, world", "ASCII"},
+ {"Gdańsk", "Gda\xf1sk", "ISO-8859-2"},
+ {"Ââ Čč Đđ Ŋŋ Õõ Šš Žž Åå Ää", "\xc2\xe2 \xc8\xe8 \xa9\xb9 \xaf\xbf \xd5\xf5 \xaa\xba \xac\xbc \xc5\xe5 \xc4\xe4", "ISO-8859-10"},
+ {"สำหรับ", "\xca\xd3\xcb\xc3\u047a", "ISO-8859-11"},
+ {"latviešu", "latvie\xf0u", "ISO-8859-13"},
+ {"Seònaid", "Se\xf2naid", "ISO-8859-14"},
+ {"€1 is cheap", "\xa41 is cheap", "ISO-8859-15"},
+ {"românește", "rom\xe2ne\xbate", "ISO-8859-16"},
+ {"nutraĵo", "nutra\xbco", "ISO-8859-3"},
+ {"Kalâdlit", "Kal\xe2dlit", "ISO-8859-4"},
+ {"русский", "\xe0\xe3\xe1\xe1\xda\xd8\xd9", "ISO-8859-5"},
+ {"ελληνικά", "\xe5\xeb\xeb\xe7\xed\xe9\xea\xdc", "ISO-8859-7"},
+ {"Kağan", "Ka\xf0an", "ISO-8859-9"},
+ {"Résumé", "R\x8esum\x8e", "macintosh"},
+ {"Gdańsk", "Gda\xf1sk", "windows-1250"},
+ {"русский", "\xf0\xf3\xf1\xf1\xea\xe8\xe9", "windows-1251"},
+ {"Résumé", "R\xe9sum\xe9", "windows-1252"},
+ {"ελληνικά", "\xe5\xeb\xeb\xe7\xed\xe9\xea\xdc", "windows-1253"},
+ {"Kağan", "Ka\xf0an", "windows-1254"},
+ {"עִבְרִית", "\xf2\xc4\xe1\xc0\xf8\xc4\xe9\xfa", "windows-1255"},
+ {"العربية", "\xc7\xe1\xda\xd1\xc8\xed\xc9", "windows-1256"},
+ {"latviešu", "latvie\xf0u", "windows-1257"},
+ {"Việt", "Vi\xea\xf2t", "windows-1258"},
+ {"สำหรับ", "\xca\xd3\xcb\xc3\u047a", "windows-874"},
+ {"русский", "\xd2\xd5\xd3\xd3\xcb\xc9\xca", "KOI8-R"},
+ {"українська", "\xd5\xcb\xd2\xc1\xa7\xce\xd3\xd8\xcb\xc1", "KOI8-U"},
+ {"Hello 常用國字標準字體表", "Hello \xb1`\xa5\u03b0\xea\xa6r\xbc\u0437\u01e6r\xc5\xe9\xaa\xed", "big5"},
+ {"Hello 常用國字標準字體表", "Hello \xb3\xa3\xd3\xc3\x87\xf8\xd7\xd6\x98\xcb\x9c\xca\xd7\xd6\xf3\x77\xb1\xed", "gbk"},
+ {"Hello 常用國字標準字體表", "Hello \xb3\xa3\xd3\xc3\x87\xf8\xd7\xd6\x98\xcb\x9c\xca\xd7\xd6\xf3\x77\xb1\xed", "gb18030"},
+ {"עִבְרִית", "\x81\x30\xfb\x30\x81\x30\xf6\x34\x81\x30\xf9\x33\x81\x30\xf6\x30\x81\x30\xfb\x36\x81\x30\xf6\x34\x81\x30\xfa\x31\x81\x30\xfb\x38", "gb18030"},
+ {"㧯", "\x82\x31\x89\x38", "gb18030"},
+ {"これは漢字です。", "\x82\xb1\x82\xea\x82\xcd\x8a\xbf\x8e\x9a\x82\xc5\x82\xb7\x81B", "SJIS"},
+ {"Hello, 世界!", "Hello, \x90\xa2\x8aE!", "SJIS"},
+ {"イウエオカ", "\xb2\xb3\xb4\xb5\xb6", "SJIS"},
+ {"これは漢字です。", "\xa4\xb3\xa4\xec\xa4\u03f4\xc1\xbb\xfa\xa4\u01e4\xb9\xa1\xa3", "EUC-JP"},
+ {"Hello, 世界!", "Hello, \x1b$B@$3&\x1b(B!", "ISO-2022-JP"},
+ {"다음과 같은 조건을 따라야 합니다: 저작자표시", "\xb4\xd9\xc0\xbd\xb0\xfa \xb0\xb0\xc0\xba \xc1\xb6\xb0\xc7\xc0\xbb \xb5\xfb\xb6\xf3\xbe\xdf \xc7մϴ\xd9: \xc0\xfa\xc0\xdb\xc0\xdaǥ\xbd\xc3", "EUC-KR"},
+}
+
+func TestDecode(t *testing.T) {
+ testCases := append(testCases, []testCase{
+ // Replace multi-byte maximum subpart of ill-formed subsequence with
+ // single replacement character (WhatWG requirement).
+ {"Rés\ufffdumé", "Rés\xe1\x80umé", "utf8"},
+ }...)
+ for _, tc := range testCases {
+ e, _ := Lookup(tc.otherEncoding)
+ if e == nil {
+ t.Errorf("%s: not found", tc.otherEncoding)
+ continue
+ }
+ s, err := transformString(e.NewDecoder(), tc.other)
+ if err != nil {
+ t.Errorf("%s: decode %q: %v", tc.otherEncoding, tc.other, err)
+ continue
+ }
+ if s != tc.utf8 {
+ t.Errorf("%s: got %q, want %q", tc.otherEncoding, s, tc.utf8)
+ }
+ }
+}
+
+func TestEncode(t *testing.T) {
+ testCases := append(testCases, []testCase{
+ // Use Go-style replacement.
+ {"Rés\xe1\x80umé", "Rés\ufffd\ufffdumé", "utf8"},
+ // U+0144 LATIN SMALL LETTER N WITH ACUTE not supported by encoding.
+ {"Gdańsk", "Gda&#324;sk", "ISO-8859-11"},
+ {"\ufffd", "&#65533;", "ISO-8859-11"},
+ {"a\xe1\x80b", "a&#65533;&#65533;b", "ISO-8859-11"},
+ }...)
+ for _, tc := range testCases {
+ e, _ := Lookup(tc.otherEncoding)
+ if e == nil {
+ t.Errorf("%s: not found", tc.otherEncoding)
+ continue
+ }
+ s, err := transformString(e.NewEncoder(), tc.utf8)
+ if err != nil {
+ t.Errorf("%s: encode %q: %s", tc.otherEncoding, tc.utf8, err)
+ continue
+ }
+ if s != tc.other {
+ t.Errorf("%s: got %q, want %q", tc.otherEncoding, s, tc.other)
+ }
+ }
+}
+
+var sniffTestCases = []struct {
+ filename, declared, want string
+}{
+ {"HTTP-charset.html", "text/html; charset=iso-8859-15", "iso-8859-15"},
+ {"UTF-16LE-BOM.html", "", "utf-16le"},
+ {"UTF-16BE-BOM.html", "", "utf-16be"},
+ {"meta-content-attribute.html", "text/html", "iso-8859-15"},
+ {"meta-charset-attribute.html", "text/html", "iso-8859-15"},
+ {"No-encoding-declaration.html", "text/html", "utf-8"},
+ {"HTTP-vs-UTF-8-BOM.html", "text/html; charset=iso-8859-15", "utf-8"},
+ {"HTTP-vs-meta-content.html", "text/html; charset=iso-8859-15", "iso-8859-15"},
+ {"HTTP-vs-meta-charset.html", "text/html; charset=iso-8859-15", "iso-8859-15"},
+ {"UTF-8-BOM-vs-meta-content.html", "text/html", "utf-8"},
+ {"UTF-8-BOM-vs-meta-charset.html", "text/html", "utf-8"},
+}
+
+func TestSniff(t *testing.T) {
+ switch runtime.GOOS {
+ case "nacl": // platforms that don't permit direct file system access
+ t.Skipf("not supported on %q", runtime.GOOS)
+ }
+
+ for _, tc := range sniffTestCases {
+ content, err := ioutil.ReadFile("testdata/" + tc.filename)
+ if err != nil {
+ t.Errorf("%s: error reading file: %v", tc.filename, err)
+ continue
+ }
+
+ _, name, _ := DetermineEncoding(content, tc.declared)
+ if name != tc.want {
+ t.Errorf("%s: got %q, want %q", tc.filename, name, tc.want)
+ continue
+ }
+ }
+}
+
+func TestReader(t *testing.T) {
+ switch runtime.GOOS {
+ case "nacl": // platforms that don't permit direct file system access
+ t.Skipf("not supported on %q", runtime.GOOS)
+ }
+
+ for _, tc := range sniffTestCases {
+ content, err := ioutil.ReadFile("testdata/" + tc.filename)
+ if err != nil {
+ t.Errorf("%s: error reading file: %v", tc.filename, err)
+ continue
+ }
+
+ r, err := NewReader(bytes.NewReader(content), tc.declared)
+ if err != nil {
+ t.Errorf("%s: error creating reader: %v", tc.filename, err)
+ continue
+ }
+
+ got, err := ioutil.ReadAll(r)
+ if err != nil {
+ t.Errorf("%s: error reading from charset.NewReader: %v", tc.filename, err)
+ continue
+ }
+
+ e, _ := Lookup(tc.want)
+ want, err := ioutil.ReadAll(transform.NewReader(bytes.NewReader(content), e.NewDecoder()))
+ if err != nil {
+ t.Errorf("%s: error decoding with hard-coded charset name: %v", tc.filename, err)
+ continue
+ }
+
+ if !bytes.Equal(got, want) {
+ t.Errorf("%s: got %q, want %q", tc.filename, got, want)
+ continue
+ }
+ }
+}
+
+var metaTestCases = []struct {
+ meta, want string
+}{
+ {"", ""},
+ {"text/html", ""},
+ {"text/html; charset utf-8", ""},
+ {"text/html; charset=latin-2", "latin-2"},
+ {"text/html; charset; charset = utf-8", "utf-8"},
+ {`charset="big5"`, "big5"},
+ {"charset='shift_jis'", "shift_jis"},
+}
+
+func TestFromMeta(t *testing.T) {
+ for _, tc := range metaTestCases {
+ got := fromMetaElement(tc.meta)
+ if got != tc.want {
+ t.Errorf("%q: got %q, want %q", tc.meta, got, tc.want)
+ }
+ }
+}
+
+func TestXML(t *testing.T) {
+ const s = "<?xml version=\"1.0\" encoding=\"windows-1252\"?><a><Word>r\xe9sum\xe9</Word></a>"
+
+ d := xml.NewDecoder(strings.NewReader(s))
+ d.CharsetReader = NewReaderLabel
+
+ var a struct {
+ Word string
+ }
+ err := d.Decode(&a)
+ if err != nil {
+ t.Fatalf("Decode: %v", err)
+ }
+
+ want := "résumé"
+ if a.Word != want {
+ t.Errorf("got %q, want %q", a.Word, want)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/testdata/HTTP-charset.html b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/testdata/HTTP-charset.html
new file mode 100644
index 000000000..9915fa0ee
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/testdata/HTTP-charset.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+ <title>HTTP charset</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream'>
+<link rel="stylesheet" type="text/css" href="./generatedtests.css">
+<script src="http://w3c-test.org/resources/testharness.js"></script>
+<script src="http://w3c-test.org/resources/testharnessreport.js"></script>
+<meta name='flags' content='http'>
+<meta name="assert" content="The character encoding of a page can be set using the HTTP header charset declaration.">
+<style type='text/css'>
+.test div { width: 50px; }</style>
+<link rel="stylesheet" type="text/css" href="the-input-byte-stream/support/encodingtests-15.css">
+</head>
+<body>
+<p class='title'>HTTP charset</p>
+
+
+<div id='log'></div>
+
+
+<div class='test'><div id='box' class='ýäè'>&#xA0;</div></div>
+
+
+
+
+
+<div class='description'>
+<p class="assertion" title="Assertion">The character encoding of a page can be set using the HTTP header charset declaration.</p>
+<div class="notes"><p><p>The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector <code>.test div.&#x00C3;&#x0153;&#x00C3;&#x20AC;&#x00C3;&#x0161;</code>. This matches the sequence of bytes above when they are interpreted as ISO 8859-15. If the class name matches the selector then the test will pass.</p><p>The only character encoding declaration for this HTML file is in the HTTP header, which sets the encoding to ISO 8859-15.</p></p>
+</div>
+</div>
+<div class="nexttest"><div><a href="generate?test=the-input-byte-stream-003">Next test</a></div><div class="doctype">HTML5</div>
+<p class="jump">the-input-byte-stream-001<br /><a href="/International/tests/html5/the-input-byte-stream/results-basics#basics" target="_blank">Result summary &amp; related tests</a><br /><a href="http://w3c-test.org/framework/details/i18n-html5/the-input-byte-stream-001" target="_blank">Detailed results for this test</a><br/> <a href="http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream" target="_blank">Link to spec</a></p>
+<div class='prereq'>Assumptions: <ul><li>The default encoding for the browser you are testing is not set to ISO 8859-15.</li>
+ <li>The test is read from a server that supports HTTP.</li></ul></div>
+</div>
+<script>
+test(function() {
+assert_equals(document.getElementById('box').offsetWidth, 100);
+}, " ");
+</script>
+
+</body>
+</html>
+
+
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/testdata/HTTP-vs-UTF-8-BOM.html b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/testdata/HTTP-vs-UTF-8-BOM.html
new file mode 100644
index 000000000..26e5d8b4e
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/testdata/HTTP-vs-UTF-8-BOM.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+ <title>HTTP vs UTF-8 BOM</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream'>
+<link rel="stylesheet" type="text/css" href="./generatedtests.css">
+<script src="http://w3c-test.org/resources/testharness.js"></script>
+<script src="http://w3c-test.org/resources/testharnessreport.js"></script>
+<meta name='flags' content='http'>
+<meta name="assert" content="A character encoding set in the HTTP header has lower precedence than the UTF-8 signature.">
+<style type='text/css'>
+.test div { width: 50px; }</style>
+<link rel="stylesheet" type="text/css" href="the-input-byte-stream/support/encodingtests-utf8.css">
+</head>
+<body>
+<p class='title'>HTTP vs UTF-8 BOM</p>
+
+
+<div id='log'></div>
+
+
+<div class='test'><div id='box' class='ýäè'>&#xA0;</div></div>
+
+
+
+
+
+<div class='description'>
+<p class="assertion" title="Assertion">A character encoding set in the HTTP header has lower precedence than the UTF-8 signature.</p>
+<div class="notes"><p><p>The HTTP header attempts to set the character encoding to ISO 8859-15. The page starts with a UTF-8 signature.</p><p>The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector <code>.test div.&#x00FD;&#x00E4;&#x00E8;</code>. This matches the sequence of bytes above when they are interpreted as UTF-8. If the class name matches the selector then the test will pass.</p><p>If the test is unsuccessful, the characters &#x00EF;&#x00BB;&#x00BF; should appear at the top of the page. These represent the bytes that make up the UTF-8 signature when encountered in the ISO 8859-15 encoding.</p></p>
+</div>
+</div>
+<div class="nexttest"><div><a href="generate?test=the-input-byte-stream-022">Next test</a></div><div class="doctype">HTML5</div>
+<p class="jump">the-input-byte-stream-034<br /><a href="/International/tests/html5/the-input-byte-stream/results-basics#precedence" target="_blank">Result summary &amp; related tests</a><br /><a href="http://w3c-test.org/framework/details/i18n-html5/the-input-byte-stream-034" target="_blank">Detailed results for this test</a><br/> <a href="http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream" target="_blank">Link to spec</a></p>
+<div class='prereq'>Assumptions: <ul><li>The default encoding for the browser you are testing is not set to ISO 8859-15.</li>
+ <li>The test is read from a server that supports HTTP.</li></ul></div>
+</div>
+<script>
+test(function() {
+assert_equals(document.getElementById('box').offsetWidth, 100);
+}, " ");
+</script>
+
+</body>
+</html>
+
+
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/testdata/HTTP-vs-meta-charset.html b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/testdata/HTTP-vs-meta-charset.html
new file mode 100644
index 000000000..2f07e9515
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/testdata/HTTP-vs-meta-charset.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+ <meta charset="iso-8859-1" > <title>HTTP vs meta charset</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream'>
+<link rel="stylesheet" type="text/css" href="./generatedtests.css">
+<script src="http://w3c-test.org/resources/testharness.js"></script>
+<script src="http://w3c-test.org/resources/testharnessreport.js"></script>
+<meta name='flags' content='http'>
+<meta name="assert" content="The HTTP header has a higher precedence than an encoding declaration in a meta charset attribute.">
+<style type='text/css'>
+.test div { width: 50px; }.test div { width: 90px; }
+</style>
+<link rel="stylesheet" type="text/css" href="the-input-byte-stream/support/encodingtests-15.css">
+</head>
+<body>
+<p class='title'>HTTP vs meta charset</p>
+
+
+<div id='log'></div>
+
+
+<div class='test'><div id='box' class='ýäè'>&#xA0;</div></div>
+
+
+
+
+
+<div class='description'>
+<p class="assertion" title="Assertion">The HTTP header has a higher precedence than an encoding declaration in a meta charset attribute.</p>
+<div class="notes"><p><p>The HTTP header attempts to set the character encoding to ISO 8859-15. The page contains an encoding declaration in a meta charset attribute that attempts to set the character encoding to ISO 8859-1.</p><p>The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector <code>.test div.&#x00C3;&#x0153;&#x00C3;&#x20AC;&#x00C3;&#x0161;</code>. This matches the sequence of bytes above when they are interpreted as ISO 8859-15. If the class name matches the selector then the test will pass.</p></p>
+</div>
+</div>
+<div class="nexttest"><div><a href="generate?test=the-input-byte-stream-037">Next test</a></div><div class="doctype">HTML5</div>
+<p class="jump">the-input-byte-stream-018<br /><a href="/International/tests/html5/the-input-byte-stream/results-basics#precedence" target="_blank">Result summary &amp; related tests</a><br /><a href="http://w3c-test.org/framework/details/i18n-html5/the-input-byte-stream-018" target="_blank">Detailed results for this test</a><br/> <a href="http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream" target="_blank">Link to spec</a></p>
+<div class='prereq'>Assumptions: <ul><li>The default encoding for the browser you are testing is not set to ISO 8859-15.</li>
+ <li>The test is read from a server that supports HTTP.</li></ul></div>
+</div>
+<script>
+test(function() {
+assert_equals(document.getElementById('box').offsetWidth, 100);
+}, " ");
+</script>
+
+</body>
+</html>
+
+
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/testdata/HTTP-vs-meta-content.html b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/testdata/HTTP-vs-meta-content.html
new file mode 100644
index 000000000..6853cddec
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/testdata/HTTP-vs-meta-content.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+ <meta http-equiv="content-type" content="text/html;charset=iso-8859-1" > <title>HTTP vs meta content</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream'>
+<link rel="stylesheet" type="text/css" href="./generatedtests.css">
+<script src="http://w3c-test.org/resources/testharness.js"></script>
+<script src="http://w3c-test.org/resources/testharnessreport.js"></script>
+<meta name='flags' content='http'>
+<meta name="assert" content="The HTTP header has a higher precedence than an encoding declaration in a meta content attribute.">
+<style type='text/css'>
+.test div { width: 50px; }.test div { width: 90px; }
+</style>
+<link rel="stylesheet" type="text/css" href="the-input-byte-stream/support/encodingtests-15.css">
+</head>
+<body>
+<p class='title'>HTTP vs meta content</p>
+
+
+<div id='log'></div>
+
+
+<div class='test'><div id='box' class='ýäè'>&#xA0;</div></div>
+
+
+
+
+
+<div class='description'>
+<p class="assertion" title="Assertion">The HTTP header has a higher precedence than an encoding declaration in a meta content attribute.</p>
+<div class="notes"><p><p>The HTTP header attempts to set the character encoding to ISO 8859-15. The page contains an encoding declaration in a meta content attribute that attempts to set the character encoding to ISO 8859-1.</p><p>The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector <code>.test div.&#x00C3;&#x0153;&#x00C3;&#x20AC;&#x00C3;&#x0161;</code>. This matches the sequence of bytes above when they are interpreted as ISO 8859-15. If the class name matches the selector then the test will pass.</p></p>
+</div>
+</div>
+<div class="nexttest"><div><a href="generate?test=the-input-byte-stream-018">Next test</a></div><div class="doctype">HTML5</div>
+<p class="jump">the-input-byte-stream-016<br /><a href="/International/tests/html5/the-input-byte-stream/results-basics#precedence" target="_blank">Result summary &amp; related tests</a><br /><a href="http://w3c-test.org/framework/details/i18n-html5/the-input-byte-stream-016" target="_blank">Detailed results for this test</a><br/> <a href="http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream" target="_blank">Link to spec</a></p>
+<div class='prereq'>Assumptions: <ul><li>The default encoding for the browser you are testing is not set to ISO 8859-15.</li>
+ <li>The test is read from a server that supports HTTP.</li></ul></div>
+</div>
+<script>
+test(function() {
+assert_equals(document.getElementById('box').offsetWidth, 100);
+}, " ");
+</script>
+
+</body>
+</html>
+
+
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/testdata/No-encoding-declaration.html b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/testdata/No-encoding-declaration.html
new file mode 100644
index 000000000..612e26c6c
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/testdata/No-encoding-declaration.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+ <title>No encoding declaration</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream'>
+<link rel="stylesheet" type="text/css" href="./generatedtests.css">
+<script src="http://w3c-test.org/resources/testharness.js"></script>
+<script src="http://w3c-test.org/resources/testharnessreport.js"></script>
+<meta name='flags' content='http'>
+<meta name="assert" content="A page with no encoding information in HTTP, BOM, XML declaration or meta element will be treated as UTF-8.">
+<style type='text/css'>
+.test div { width: 50px; }</style>
+<link rel="stylesheet" type="text/css" href="the-input-byte-stream/support/encodingtests-utf8.css">
+</head>
+<body>
+<p class='title'>No encoding declaration</p>
+
+
+<div id='log'></div>
+
+
+<div class='test'><div id='box' class='ýäè'>&#xA0;</div></div>
+
+
+
+
+
+<div class='description'>
+<p class="assertion" title="Assertion">A page with no encoding information in HTTP, BOM, XML declaration or meta element will be treated as UTF-8.</p>
+<div class="notes"><p><p>The test on this page contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector <code>.test div.&#x00FD;&#x00E4;&#x00E8;</code>. This matches the sequence of bytes above when they are interpreted as UTF-8. If the class name matches the selector then the test will pass.</p></p>
+</div>
+</div>
+<div class="nexttest"><div><a href="generate?test=the-input-byte-stream-034">Next test</a></div><div class="doctype">HTML5</div>
+<p class="jump">the-input-byte-stream-015<br /><a href="/International/tests/html5/the-input-byte-stream/results-basics#basics" target="_blank">Result summary &amp; related tests</a><br /><a href="http://w3c-test.org/framework/details/i18n-html5/the-input-byte-stream-015" target="_blank">Detailed results for this test</a><br/> <a href="http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream" target="_blank">Link to spec</a></p>
+<div class='prereq'>Assumptions: <ul><li>The test is read from a server that supports HTTP.</li></ul></div>
+</div>
+<script>
+test(function() {
+assert_equals(document.getElementById('box').offsetWidth, 100);
+}, " ");
+</script>
+
+</body>
+</html>
+
+
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/testdata/README b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/testdata/README
new file mode 100644
index 000000000..38ef0f9f1
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/testdata/README
@@ -0,0 +1,9 @@
+These test cases come from
+http://www.w3.org/International/tests/repository/html5/the-input-byte-stream/results-basics
+
+Distributed under both the W3C Test Suite License
+(http://www.w3.org/Consortium/Legal/2008/04-testsuite-license)
+and the W3C 3-clause BSD License
+(http://www.w3.org/Consortium/Legal/2008/03-bsd-license).
+To contribute to a W3C Test Suite, see the policies and contribution
+forms (http://www.w3.org/2004/10/27-testcases).
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/testdata/UTF-16BE-BOM.html b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/testdata/UTF-16BE-BOM.html
new file mode 100644
index 000000000..3abf7a934
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/testdata/UTF-16BE-BOM.html
Binary files differ
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/testdata/UTF-16LE-BOM.html b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/testdata/UTF-16LE-BOM.html
new file mode 100644
index 000000000..76254c980
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/testdata/UTF-16LE-BOM.html
Binary files differ
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/testdata/UTF-8-BOM-vs-meta-charset.html b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/testdata/UTF-8-BOM-vs-meta-charset.html
new file mode 100644
index 000000000..83de43338
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/testdata/UTF-8-BOM-vs-meta-charset.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+ <meta charset="iso-8859-15"> <title>UTF-8 BOM vs meta charset</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream'>
+<link rel="stylesheet" type="text/css" href="./generatedtests.css">
+<script src="http://w3c-test.org/resources/testharness.js"></script>
+<script src="http://w3c-test.org/resources/testharnessreport.js"></script>
+<meta name='flags' content='http'>
+<meta name="assert" content="A page with a UTF-8 BOM will be recognized as UTF-8 even if the meta charset attribute declares a different encoding.">
+<style type='text/css'>
+.test div { width: 50px; }.test div { width: 90px; }
+</style>
+<link rel="stylesheet" type="text/css" href="the-input-byte-stream/support/encodingtests-utf8.css">
+</head>
+<body>
+<p class='title'>UTF-8 BOM vs meta charset</p>
+
+
+<div id='log'></div>
+
+
+<div class='test'><div id='box' class='ýäè'>&#xA0;</div></div>
+
+
+
+
+
+<div class='description'>
+<p class="assertion" title="Assertion">A page with a UTF-8 BOM will be recognized as UTF-8 even if the meta charset attribute declares a different encoding.</p>
+<div class="notes"><p><p>The page contains an encoding declaration in a meta charset attribute that attempts to set the character encoding to ISO 8859-15, but the file starts with a UTF-8 signature.</p><p>The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector <code>.test div.&#x00FD;&#x00E4;&#x00E8;</code>. This matches the sequence of bytes above when they are interpreted as UTF-8. If the class name matches the selector then the test will pass.</p></p>
+</div>
+</div>
+<div class="nexttest"><div><a href="generate?test=the-input-byte-stream-024">Next test</a></div><div class="doctype">HTML5</div>
+<p class="jump">the-input-byte-stream-038<br /><a href="/International/tests/html5/the-input-byte-stream/results-basics#precedence" target="_blank">Result summary &amp; related tests</a><br /><a href="http://w3c-test.org/framework/details/i18n-html5/the-input-byte-stream-038" target="_blank">Detailed results for this test</a><br/> <a href="http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream" target="_blank">Link to spec</a></p>
+<div class='prereq'>Assumptions: <ul><li>The default encoding for the browser you are testing is not set to ISO 8859-15.</li>
+ <li>The test is read from a server that supports HTTP.</li></ul></div>
+</div>
+<script>
+test(function() {
+assert_equals(document.getElementById('box').offsetWidth, 100);
+}, " ");
+</script>
+
+</body>
+</html>
+
+
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/testdata/UTF-8-BOM-vs-meta-content.html b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/testdata/UTF-8-BOM-vs-meta-content.html
new file mode 100644
index 000000000..501aac2d6
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/testdata/UTF-8-BOM-vs-meta-content.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+ <meta http-equiv="content-type" content="text/html; charset=iso-8859-15"> <title>UTF-8 BOM vs meta content</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream'>
+<link rel="stylesheet" type="text/css" href="./generatedtests.css">
+<script src="http://w3c-test.org/resources/testharness.js"></script>
+<script src="http://w3c-test.org/resources/testharnessreport.js"></script>
+<meta name='flags' content='http'>
+<meta name="assert" content="A page with a UTF-8 BOM will be recognized as UTF-8 even if the meta content attribute declares a different encoding.">
+<style type='text/css'>
+.test div { width: 50px; }</style>
+<link rel="stylesheet" type="text/css" href="the-input-byte-stream/support/encodingtests-utf8.css">
+</head>
+<body>
+<p class='title'>UTF-8 BOM vs meta content</p>
+
+
+<div id='log'></div>
+
+
+<div class='test'><div id='box' class='ýäè'>&#xA0;</div></div>
+
+
+
+
+
+<div class='description'>
+<p class="assertion" title="Assertion">A page with a UTF-8 BOM will be recognized as UTF-8 even if the meta content attribute declares a different encoding.</p>
+<div class="notes"><p><p>The page contains an encoding declaration in a meta content attribute that attempts to set the character encoding to ISO 8859-15, but the file starts with a UTF-8 signature.</p><p>The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector <code>.test div.&#x00FD;&#x00E4;&#x00E8;</code>. This matches the sequence of bytes above when they are interpreted as UTF-8. If the class name matches the selector then the test will pass.</p></p>
+</div>
+</div>
+<div class="nexttest"><div><a href="generate?test=the-input-byte-stream-038">Next test</a></div><div class="doctype">HTML5</div>
+<p class="jump">the-input-byte-stream-037<br /><a href="/International/tests/html5/the-input-byte-stream/results-basics#precedence" target="_blank">Result summary &amp; related tests</a><br /><a href="http://w3c-test.org/framework/details/i18n-html5/the-input-byte-stream-037" target="_blank">Detailed results for this test</a><br/> <a href="http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream" target="_blank">Link to spec</a></p>
+<div class='prereq'>Assumptions: <ul><li>The default encoding for the browser you are testing is not set to ISO 8859-15.</li>
+ <li>The test is read from a server that supports HTTP.</li></ul></div>
+</div>
+<script>
+test(function() {
+assert_equals(document.getElementById('box').offsetWidth, 100);
+}, " ");
+</script>
+
+</body>
+</html>
+
+
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/testdata/meta-charset-attribute.html b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/testdata/meta-charset-attribute.html
new file mode 100644
index 000000000..2d7d25aba
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/testdata/meta-charset-attribute.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+ <meta charset="iso-8859-15"> <title>meta charset attribute</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream'>
+<link rel="stylesheet" type="text/css" href="./generatedtests.css">
+<script src="http://w3c-test.org/resources/testharness.js"></script>
+<script src="http://w3c-test.org/resources/testharnessreport.js"></script>
+<meta name='flags' content='http'>
+<meta name="assert" content="The character encoding of the page can be set by a meta element with charset attribute.">
+<style type='text/css'>
+.test div { width: 50px; }</style>
+<link rel="stylesheet" type="text/css" href="the-input-byte-stream/support/encodingtests-15.css">
+</head>
+<body>
+<p class='title'>meta charset attribute</p>
+
+
+<div id='log'></div>
+
+
+<div class='test'><div id='box' class='ýäè'>&#xA0;</div></div>
+
+
+
+
+
+<div class='description'>
+<p class="assertion" title="Assertion">The character encoding of the page can be set by a meta element with charset attribute.</p>
+<div class="notes"><p><p>The only character encoding declaration for this HTML file is in the charset attribute of the meta element, which declares the encoding to be ISO 8859-15.</p><p>The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector <code>.test div.&#x00C3;&#x0153;&#x00C3;&#x20AC;&#x00C3;&#x0161;</code>. This matches the sequence of bytes above when they are interpreted as ISO 8859-15. If the class name matches the selector then the test will pass.</p></p>
+</div>
+</div>
+<div class="nexttest"><div><a href="generate?test=the-input-byte-stream-015">Next test</a></div><div class="doctype">HTML5</div>
+<p class="jump">the-input-byte-stream-009<br /><a href="/International/tests/html5/the-input-byte-stream/results-basics#basics" target="_blank">Result summary &amp; related tests</a><br /><a href="http://w3c-test.org/framework/details/i18n-html5/the-input-byte-stream-009" target="_blank">Detailed results for this test</a><br/> <a href="http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream" target="_blank">Link to spec</a></p>
+<div class='prereq'>Assumptions: <ul><li>The default encoding for the browser you are testing is not set to ISO 8859-15.</li>
+ <li>The test is read from a server that supports HTTP.</li></ul></div>
+</div>
+<script>
+test(function() {
+assert_equals(document.getElementById('box').offsetWidth, 100);
+}, " ");
+</script>
+
+</body>
+</html>
+
+
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/testdata/meta-content-attribute.html b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/testdata/meta-content-attribute.html
new file mode 100644
index 000000000..1c3f228e7
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/charset/testdata/meta-content-attribute.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+ <meta http-equiv="content-type" content="text/html; charset=iso-8859-15"> <title>meta content attribute</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream'>
+<link rel="stylesheet" type="text/css" href="./generatedtests.css">
+<script src="http://w3c-test.org/resources/testharness.js"></script>
+<script src="http://w3c-test.org/resources/testharnessreport.js"></script>
+<meta name='flags' content='http'>
+<meta name="assert" content="The character encoding of the page can be set by a meta element with http-equiv and content attributes.">
+<style type='text/css'>
+.test div { width: 50px; }</style>
+<link rel="stylesheet" type="text/css" href="the-input-byte-stream/support/encodingtests-15.css">
+</head>
+<body>
+<p class='title'>meta content attribute</p>
+
+
+<div id='log'></div>
+
+
+<div class='test'><div id='box' class='ýäè'>&#xA0;</div></div>
+
+
+
+
+
+<div class='description'>
+<p class="assertion" title="Assertion">The character encoding of the page can be set by a meta element with http-equiv and content attributes.</p>
+<div class="notes"><p><p>The only character encoding declaration for this HTML file is in the content attribute of the meta element, which declares the encoding to be ISO 8859-15.</p><p>The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector <code>.test div.&#x00C3;&#x0153;&#x00C3;&#x20AC;&#x00C3;&#x0161;</code>. This matches the sequence of bytes above when they are interpreted as ISO 8859-15. If the class name matches the selector then the test will pass.</p></p>
+</div>
+</div>
+<div class="nexttest"><div><a href="generate?test=the-input-byte-stream-009">Next test</a></div><div class="doctype">HTML5</div>
+<p class="jump">the-input-byte-stream-007<br /><a href="/International/tests/html5/the-input-byte-stream/results-basics#basics" target="_blank">Result summary &amp; related tests</a><br /><a href="http://w3c-test.org/framework/details/i18n-html5/the-input-byte-stream-007" target="_blank">Detailed results for this test</a><br/> <a href="http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream" target="_blank">Link to spec</a></p>
+<div class='prereq'>Assumptions: <ul><li>The default encoding for the browser you are testing is not set to ISO 8859-15.</li>
+ <li>The test is read from a server that supports HTTP.</li></ul></div>
+</div>
+<script>
+test(function() {
+assert_equals(document.getElementById('box').offsetWidth, 100);
+}, " ");
+</script>
+
+</body>
+</html>
+
+
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/const.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/const.go
new file mode 100644
index 000000000..b37e62124
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/const.go
@@ -0,0 +1,104 @@
+// Copyright 2011 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 html
+
+// Section 12.2.3.2 of the HTML5 specification says "The following elements
+// have varying levels of special parsing rules".
+// https://html.spec.whatwg.org/multipage/syntax.html#the-stack-of-open-elements
+var isSpecialElementMap = map[string]bool{
+ "address": true,
+ "applet": true,
+ "area": true,
+ "article": true,
+ "aside": true,
+ "base": true,
+ "basefont": true,
+ "bgsound": true,
+ "blockquote": true,
+ "body": true,
+ "br": true,
+ "button": true,
+ "caption": true,
+ "center": true,
+ "col": true,
+ "colgroup": true,
+ "dd": true,
+ "details": true,
+ "dir": true,
+ "div": true,
+ "dl": true,
+ "dt": true,
+ "embed": true,
+ "fieldset": true,
+ "figcaption": true,
+ "figure": true,
+ "footer": true,
+ "form": true,
+ "frame": true,
+ "frameset": true,
+ "h1": true,
+ "h2": true,
+ "h3": true,
+ "h4": true,
+ "h5": true,
+ "h6": true,
+ "head": true,
+ "header": true,
+ "hgroup": true,
+ "hr": true,
+ "html": true,
+ "iframe": true,
+ "img": true,
+ "input": true,
+ "isindex": true, // The 'isindex' element has been removed, but keep it for backwards compatibility.
+ "keygen": true,
+ "li": true,
+ "link": true,
+ "listing": true,
+ "main": true,
+ "marquee": true,
+ "menu": true,
+ "meta": true,
+ "nav": true,
+ "noembed": true,
+ "noframes": true,
+ "noscript": true,
+ "object": true,
+ "ol": true,
+ "p": true,
+ "param": true,
+ "plaintext": true,
+ "pre": true,
+ "script": true,
+ "section": true,
+ "select": true,
+ "source": true,
+ "style": true,
+ "summary": true,
+ "table": true,
+ "tbody": true,
+ "td": true,
+ "template": true,
+ "textarea": true,
+ "tfoot": true,
+ "th": true,
+ "thead": true,
+ "title": true,
+ "tr": true,
+ "track": true,
+ "ul": true,
+ "wbr": true,
+ "xmp": true,
+}
+
+func isSpecialElement(element *Node) bool {
+ switch element.Namespace {
+ case "", "html":
+ return isSpecialElementMap[element.Data]
+ case "svg":
+ return element.Data == "foreignObject"
+ }
+ return false
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/doc.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/doc.go
new file mode 100644
index 000000000..822ed42a0
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/doc.go
@@ -0,0 +1,106 @@
+// Copyright 2010 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 html implements an HTML5-compliant tokenizer and parser.
+
+Tokenization is done by creating a Tokenizer for an io.Reader r. It is the
+caller's responsibility to ensure that r provides UTF-8 encoded HTML.
+
+ z := html.NewTokenizer(r)
+
+Given a Tokenizer z, the HTML is tokenized by repeatedly calling z.Next(),
+which parses the next token and returns its type, or an error:
+
+ for {
+ tt := z.Next()
+ if tt == html.ErrorToken {
+ // ...
+ return ...
+ }
+ // Process the current token.
+ }
+
+There are two APIs for retrieving the current token. The high-level API is to
+call Token; the low-level API is to call Text or TagName / TagAttr. Both APIs
+allow optionally calling Raw after Next but before Token, Text, TagName, or
+TagAttr. In EBNF notation, the valid call sequence per token is:
+
+ Next {Raw} [ Token | Text | TagName {TagAttr} ]
+
+Token returns an independent data structure that completely describes a token.
+Entities (such as "&lt;") are unescaped, tag names and attribute keys are
+lower-cased, and attributes are collected into a []Attribute. For example:
+
+ for {
+ if z.Next() == html.ErrorToken {
+ // Returning io.EOF indicates success.
+ return z.Err()
+ }
+ emitToken(z.Token())
+ }
+
+The low-level API performs fewer allocations and copies, but the contents of
+the []byte values returned by Text, TagName and TagAttr may change on the next
+call to Next. For example, to extract an HTML page's anchor text:
+
+ depth := 0
+ for {
+ tt := z.Next()
+ switch tt {
+ case html.ErrorToken:
+ return z.Err()
+ case html.TextToken:
+ if depth > 0 {
+ // emitBytes should copy the []byte it receives,
+ // if it doesn't process it immediately.
+ emitBytes(z.Text())
+ }
+ case html.StartTagToken, html.EndTagToken:
+ tn, _ := z.TagName()
+ if len(tn) == 1 && tn[0] == 'a' {
+ if tt == html.StartTagToken {
+ depth++
+ } else {
+ depth--
+ }
+ }
+ }
+ }
+
+Parsing is done by calling Parse with an io.Reader, which returns the root of
+the parse tree (the document element) as a *Node. It is the caller's
+responsibility to ensure that the Reader provides UTF-8 encoded HTML. For
+example, to process each anchor node in depth-first order:
+
+ doc, err := html.Parse(r)
+ if err != nil {
+ // ...
+ }
+ var f func(*html.Node)
+ f = func(n *html.Node) {
+ if n.Type == html.ElementNode && n.Data == "a" {
+ // Do something with n...
+ }
+ for c := n.FirstChild; c != nil; c = c.NextSibling {
+ f(c)
+ }
+ }
+ f(doc)
+
+The relevant specifications include:
+https://html.spec.whatwg.org/multipage/syntax.html and
+https://html.spec.whatwg.org/multipage/syntax.html#tokenization
+*/
+package html // import "golang.org/x/net/html"
+
+// The tokenization algorithm implemented by this package is not a line-by-line
+// transliteration of the relatively verbose state-machine in the WHATWG
+// specification. A more direct approach is used instead, where the program
+// counter implies the state, such as whether it is tokenizing a tag or a text
+// node. Specification compliance is verified by checking expected and actual
+// outputs over a test suite rather than aiming for algorithmic fidelity.
+
+// TODO(nigeltao): Does a DOM API belong in this package or a separate one?
+// TODO(nigeltao): How does parsing interact with a JavaScript engine?
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/doctype.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/doctype.go
new file mode 100644
index 000000000..c484e5a94
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/doctype.go
@@ -0,0 +1,156 @@
+// Copyright 2011 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 html
+
+import (
+ "strings"
+)
+
+// parseDoctype parses the data from a DoctypeToken into a name,
+// public identifier, and system identifier. It returns a Node whose Type
+// is DoctypeNode, whose Data is the name, and which has attributes
+// named "system" and "public" for the two identifiers if they were present.
+// quirks is whether the document should be parsed in "quirks mode".
+func parseDoctype(s string) (n *Node, quirks bool) {
+ n = &Node{Type: DoctypeNode}
+
+ // Find the name.
+ space := strings.IndexAny(s, whitespace)
+ if space == -1 {
+ space = len(s)
+ }
+ n.Data = s[:space]
+ // The comparison to "html" is case-sensitive.
+ if n.Data != "html" {
+ quirks = true
+ }
+ n.Data = strings.ToLower(n.Data)
+ s = strings.TrimLeft(s[space:], whitespace)
+
+ if len(s) < 6 {
+ // It can't start with "PUBLIC" or "SYSTEM".
+ // Ignore the rest of the string.
+ return n, quirks || s != ""
+ }
+
+ key := strings.ToLower(s[:6])
+ s = s[6:]
+ for key == "public" || key == "system" {
+ s = strings.TrimLeft(s, whitespace)
+ if s == "" {
+ break
+ }
+ quote := s[0]
+ if quote != '"' && quote != '\'' {
+ break
+ }
+ s = s[1:]
+ q := strings.IndexRune(s, rune(quote))
+ var id string
+ if q == -1 {
+ id = s
+ s = ""
+ } else {
+ id = s[:q]
+ s = s[q+1:]
+ }
+ n.Attr = append(n.Attr, Attribute{Key: key, Val: id})
+ if key == "public" {
+ key = "system"
+ } else {
+ key = ""
+ }
+ }
+
+ if key != "" || s != "" {
+ quirks = true
+ } else if len(n.Attr) > 0 {
+ if n.Attr[0].Key == "public" {
+ public := strings.ToLower(n.Attr[0].Val)
+ switch public {
+ case "-//w3o//dtd w3 html strict 3.0//en//", "-/w3d/dtd html 4.0 transitional/en", "html":
+ quirks = true
+ default:
+ for _, q := range quirkyIDs {
+ if strings.HasPrefix(public, q) {
+ quirks = true
+ break
+ }
+ }
+ }
+ // The following two public IDs only cause quirks mode if there is no system ID.
+ if len(n.Attr) == 1 && (strings.HasPrefix(public, "-//w3c//dtd html 4.01 frameset//") ||
+ strings.HasPrefix(public, "-//w3c//dtd html 4.01 transitional//")) {
+ quirks = true
+ }
+ }
+ if lastAttr := n.Attr[len(n.Attr)-1]; lastAttr.Key == "system" &&
+ strings.ToLower(lastAttr.Val) == "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd" {
+ quirks = true
+ }
+ }
+
+ return n, quirks
+}
+
+// quirkyIDs is a list of public doctype identifiers that cause a document
+// to be interpreted in quirks mode. The identifiers should be in lower case.
+var quirkyIDs = []string{
+ "+//silmaril//dtd html pro v0r11 19970101//",
+ "-//advasoft ltd//dtd html 3.0 aswedit + extensions//",
+ "-//as//dtd html 3.0 aswedit + extensions//",
+ "-//ietf//dtd html 2.0 level 1//",
+ "-//ietf//dtd html 2.0 level 2//",
+ "-//ietf//dtd html 2.0 strict level 1//",
+ "-//ietf//dtd html 2.0 strict level 2//",
+ "-//ietf//dtd html 2.0 strict//",
+ "-//ietf//dtd html 2.0//",
+ "-//ietf//dtd html 2.1e//",
+ "-//ietf//dtd html 3.0//",
+ "-//ietf//dtd html 3.2 final//",
+ "-//ietf//dtd html 3.2//",
+ "-//ietf//dtd html 3//",
+ "-//ietf//dtd html level 0//",
+ "-//ietf//dtd html level 1//",
+ "-//ietf//dtd html level 2//",
+ "-//ietf//dtd html level 3//",
+ "-//ietf//dtd html strict level 0//",
+ "-//ietf//dtd html strict level 1//",
+ "-//ietf//dtd html strict level 2//",
+ "-//ietf//dtd html strict level 3//",
+ "-//ietf//dtd html strict//",
+ "-//ietf//dtd html//",
+ "-//metrius//dtd metrius presentational//",
+ "-//microsoft//dtd internet explorer 2.0 html strict//",
+ "-//microsoft//dtd internet explorer 2.0 html//",
+ "-//microsoft//dtd internet explorer 2.0 tables//",
+ "-//microsoft//dtd internet explorer 3.0 html strict//",
+ "-//microsoft//dtd internet explorer 3.0 html//",
+ "-//microsoft//dtd internet explorer 3.0 tables//",
+ "-//netscape comm. corp.//dtd html//",
+ "-//netscape comm. corp.//dtd strict html//",
+ "-//o'reilly and associates//dtd html 2.0//",
+ "-//o'reilly and associates//dtd html extended 1.0//",
+ "-//o'reilly and associates//dtd html extended relaxed 1.0//",
+ "-//softquad software//dtd hotmetal pro 6.0::19990601::extensions to html 4.0//",
+ "-//softquad//dtd hotmetal pro 4.0::19971010::extensions to html 4.0//",
+ "-//spyglass//dtd html 2.0 extended//",
+ "-//sq//dtd html 2.0 hotmetal + extensions//",
+ "-//sun microsystems corp.//dtd hotjava html//",
+ "-//sun microsystems corp.//dtd hotjava strict html//",
+ "-//w3c//dtd html 3 1995-03-24//",
+ "-//w3c//dtd html 3.2 draft//",
+ "-//w3c//dtd html 3.2 final//",
+ "-//w3c//dtd html 3.2//",
+ "-//w3c//dtd html 3.2s draft//",
+ "-//w3c//dtd html 4.0 frameset//",
+ "-//w3c//dtd html 4.0 transitional//",
+ "-//w3c//dtd html experimental 19960712//",
+ "-//w3c//dtd html experimental 970421//",
+ "-//w3c//dtd w3 html//",
+ "-//w3o//dtd w3 html 3.0//",
+ "-//webtechs//dtd mozilla html 2.0//",
+ "-//webtechs//dtd mozilla html//",
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/entity.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/entity.go
new file mode 100644
index 000000000..a50c04c60
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/entity.go
@@ -0,0 +1,2253 @@
+// Copyright 2010 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 html
+
+// All entities that do not end with ';' are 6 or fewer bytes long.
+const longestEntityWithoutSemicolon = 6
+
+// entity is a map from HTML entity names to their values. The semicolon matters:
+// https://html.spec.whatwg.org/multipage/syntax.html#named-character-references
+// lists both "amp" and "amp;" as two separate entries.
+//
+// Note that the HTML5 list is larger than the HTML4 list at
+// http://www.w3.org/TR/html4/sgml/entities.html
+var entity = map[string]rune{
+ "AElig;": '\U000000C6',
+ "AMP;": '\U00000026',
+ "Aacute;": '\U000000C1',
+ "Abreve;": '\U00000102',
+ "Acirc;": '\U000000C2',
+ "Acy;": '\U00000410',
+ "Afr;": '\U0001D504',
+ "Agrave;": '\U000000C0',
+ "Alpha;": '\U00000391',
+ "Amacr;": '\U00000100',
+ "And;": '\U00002A53',
+ "Aogon;": '\U00000104',
+ "Aopf;": '\U0001D538',
+ "ApplyFunction;": '\U00002061',
+ "Aring;": '\U000000C5',
+ "Ascr;": '\U0001D49C',
+ "Assign;": '\U00002254',
+ "Atilde;": '\U000000C3',
+ "Auml;": '\U000000C4',
+ "Backslash;": '\U00002216',
+ "Barv;": '\U00002AE7',
+ "Barwed;": '\U00002306',
+ "Bcy;": '\U00000411',
+ "Because;": '\U00002235',
+ "Bernoullis;": '\U0000212C',
+ "Beta;": '\U00000392',
+ "Bfr;": '\U0001D505',
+ "Bopf;": '\U0001D539',
+ "Breve;": '\U000002D8',
+ "Bscr;": '\U0000212C',
+ "Bumpeq;": '\U0000224E',
+ "CHcy;": '\U00000427',
+ "COPY;": '\U000000A9',
+ "Cacute;": '\U00000106',
+ "Cap;": '\U000022D2',
+ "CapitalDifferentialD;": '\U00002145',
+ "Cayleys;": '\U0000212D',
+ "Ccaron;": '\U0000010C',
+ "Ccedil;": '\U000000C7',
+ "Ccirc;": '\U00000108',
+ "Cconint;": '\U00002230',
+ "Cdot;": '\U0000010A',
+ "Cedilla;": '\U000000B8',
+ "CenterDot;": '\U000000B7',
+ "Cfr;": '\U0000212D',
+ "Chi;": '\U000003A7',
+ "CircleDot;": '\U00002299',
+ "CircleMinus;": '\U00002296',
+ "CirclePlus;": '\U00002295',
+ "CircleTimes;": '\U00002297',
+ "ClockwiseContourIntegral;": '\U00002232',
+ "CloseCurlyDoubleQuote;": '\U0000201D',
+ "CloseCurlyQuote;": '\U00002019',
+ "Colon;": '\U00002237',
+ "Colone;": '\U00002A74',
+ "Congruent;": '\U00002261',
+ "Conint;": '\U0000222F',
+ "ContourIntegral;": '\U0000222E',
+ "Copf;": '\U00002102',
+ "Coproduct;": '\U00002210',
+ "CounterClockwiseContourIntegral;": '\U00002233',
+ "Cross;": '\U00002A2F',
+ "Cscr;": '\U0001D49E',
+ "Cup;": '\U000022D3',
+ "CupCap;": '\U0000224D',
+ "DD;": '\U00002145',
+ "DDotrahd;": '\U00002911',
+ "DJcy;": '\U00000402',
+ "DScy;": '\U00000405',
+ "DZcy;": '\U0000040F',
+ "Dagger;": '\U00002021',
+ "Darr;": '\U000021A1',
+ "Dashv;": '\U00002AE4',
+ "Dcaron;": '\U0000010E',
+ "Dcy;": '\U00000414',
+ "Del;": '\U00002207',
+ "Delta;": '\U00000394',
+ "Dfr;": '\U0001D507',
+ "DiacriticalAcute;": '\U000000B4',
+ "DiacriticalDot;": '\U000002D9',
+ "DiacriticalDoubleAcute;": '\U000002DD',
+ "DiacriticalGrave;": '\U00000060',
+ "DiacriticalTilde;": '\U000002DC',
+ "Diamond;": '\U000022C4',
+ "DifferentialD;": '\U00002146',
+ "Dopf;": '\U0001D53B',
+ "Dot;": '\U000000A8',
+ "DotDot;": '\U000020DC',
+ "DotEqual;": '\U00002250',
+ "DoubleContourIntegral;": '\U0000222F',
+ "DoubleDot;": '\U000000A8',
+ "DoubleDownArrow;": '\U000021D3',
+ "DoubleLeftArrow;": '\U000021D0',
+ "DoubleLeftRightArrow;": '\U000021D4',
+ "DoubleLeftTee;": '\U00002AE4',
+ "DoubleLongLeftArrow;": '\U000027F8',
+ "DoubleLongLeftRightArrow;": '\U000027FA',
+ "DoubleLongRightArrow;": '\U000027F9',
+ "DoubleRightArrow;": '\U000021D2',
+ "DoubleRightTee;": '\U000022A8',
+ "DoubleUpArrow;": '\U000021D1',
+ "DoubleUpDownArrow;": '\U000021D5',
+ "DoubleVerticalBar;": '\U00002225',
+ "DownArrow;": '\U00002193',
+ "DownArrowBar;": '\U00002913',
+ "DownArrowUpArrow;": '\U000021F5',
+ "DownBreve;": '\U00000311',
+ "DownLeftRightVector;": '\U00002950',
+ "DownLeftTeeVector;": '\U0000295E',
+ "DownLeftVector;": '\U000021BD',
+ "DownLeftVectorBar;": '\U00002956',
+ "DownRightTeeVector;": '\U0000295F',
+ "DownRightVector;": '\U000021C1',
+ "DownRightVectorBar;": '\U00002957',
+ "DownTee;": '\U000022A4',
+ "DownTeeArrow;": '\U000021A7',
+ "Downarrow;": '\U000021D3',
+ "Dscr;": '\U0001D49F',
+ "Dstrok;": '\U00000110',
+ "ENG;": '\U0000014A',
+ "ETH;": '\U000000D0',
+ "Eacute;": '\U000000C9',
+ "Ecaron;": '\U0000011A',
+ "Ecirc;": '\U000000CA',
+ "Ecy;": '\U0000042D',
+ "Edot;": '\U00000116',
+ "Efr;": '\U0001D508',
+ "Egrave;": '\U000000C8',
+ "Element;": '\U00002208',
+ "Emacr;": '\U00000112',
+ "EmptySmallSquare;": '\U000025FB',
+ "EmptyVerySmallSquare;": '\U000025AB',
+ "Eogon;": '\U00000118',
+ "Eopf;": '\U0001D53C',
+ "Epsilon;": '\U00000395',
+ "Equal;": '\U00002A75',
+ "EqualTilde;": '\U00002242',
+ "Equilibrium;": '\U000021CC',
+ "Escr;": '\U00002130',
+ "Esim;": '\U00002A73',
+ "Eta;": '\U00000397',
+ "Euml;": '\U000000CB',
+ "Exists;": '\U00002203',
+ "ExponentialE;": '\U00002147',
+ "Fcy;": '\U00000424',
+ "Ffr;": '\U0001D509',
+ "FilledSmallSquare;": '\U000025FC',
+ "FilledVerySmallSquare;": '\U000025AA',
+ "Fopf;": '\U0001D53D',
+ "ForAll;": '\U00002200',
+ "Fouriertrf;": '\U00002131',
+ "Fscr;": '\U00002131',
+ "GJcy;": '\U00000403',
+ "GT;": '\U0000003E',
+ "Gamma;": '\U00000393',
+ "Gammad;": '\U000003DC',
+ "Gbreve;": '\U0000011E',
+ "Gcedil;": '\U00000122',
+ "Gcirc;": '\U0000011C',
+ "Gcy;": '\U00000413',
+ "Gdot;": '\U00000120',
+ "Gfr;": '\U0001D50A',
+ "Gg;": '\U000022D9',
+ "Gopf;": '\U0001D53E',
+ "GreaterEqual;": '\U00002265',
+ "GreaterEqualLess;": '\U000022DB',
+ "GreaterFullEqual;": '\U00002267',
+ "GreaterGreater;": '\U00002AA2',
+ "GreaterLess;": '\U00002277',
+ "GreaterSlantEqual;": '\U00002A7E',
+ "GreaterTilde;": '\U00002273',
+ "Gscr;": '\U0001D4A2',
+ "Gt;": '\U0000226B',
+ "HARDcy;": '\U0000042A',
+ "Hacek;": '\U000002C7',
+ "Hat;": '\U0000005E',
+ "Hcirc;": '\U00000124',
+ "Hfr;": '\U0000210C',
+ "HilbertSpace;": '\U0000210B',
+ "Hopf;": '\U0000210D',
+ "HorizontalLine;": '\U00002500',
+ "Hscr;": '\U0000210B',
+ "Hstrok;": '\U00000126',
+ "HumpDownHump;": '\U0000224E',
+ "HumpEqual;": '\U0000224F',
+ "IEcy;": '\U00000415',
+ "IJlig;": '\U00000132',
+ "IOcy;": '\U00000401',
+ "Iacute;": '\U000000CD',
+ "Icirc;": '\U000000CE',
+ "Icy;": '\U00000418',
+ "Idot;": '\U00000130',
+ "Ifr;": '\U00002111',
+ "Igrave;": '\U000000CC',
+ "Im;": '\U00002111',
+ "Imacr;": '\U0000012A',
+ "ImaginaryI;": '\U00002148',
+ "Implies;": '\U000021D2',
+ "Int;": '\U0000222C',
+ "Integral;": '\U0000222B',
+ "Intersection;": '\U000022C2',
+ "InvisibleComma;": '\U00002063',
+ "InvisibleTimes;": '\U00002062',
+ "Iogon;": '\U0000012E',
+ "Iopf;": '\U0001D540',
+ "Iota;": '\U00000399',
+ "Iscr;": '\U00002110',
+ "Itilde;": '\U00000128',
+ "Iukcy;": '\U00000406',
+ "Iuml;": '\U000000CF',
+ "Jcirc;": '\U00000134',
+ "Jcy;": '\U00000419',
+ "Jfr;": '\U0001D50D',
+ "Jopf;": '\U0001D541',
+ "Jscr;": '\U0001D4A5',
+ "Jsercy;": '\U00000408',
+ "Jukcy;": '\U00000404',
+ "KHcy;": '\U00000425',
+ "KJcy;": '\U0000040C',
+ "Kappa;": '\U0000039A',
+ "Kcedil;": '\U00000136',
+ "Kcy;": '\U0000041A',
+ "Kfr;": '\U0001D50E',
+ "Kopf;": '\U0001D542',
+ "Kscr;": '\U0001D4A6',
+ "LJcy;": '\U00000409',
+ "LT;": '\U0000003C',
+ "Lacute;": '\U00000139',
+ "Lambda;": '\U0000039B',
+ "Lang;": '\U000027EA',
+ "Laplacetrf;": '\U00002112',
+ "Larr;": '\U0000219E',
+ "Lcaron;": '\U0000013D',
+ "Lcedil;": '\U0000013B',
+ "Lcy;": '\U0000041B',
+ "LeftAngleBracket;": '\U000027E8',
+ "LeftArrow;": '\U00002190',
+ "LeftArrowBar;": '\U000021E4',
+ "LeftArrowRightArrow;": '\U000021C6',
+ "LeftCeiling;": '\U00002308',
+ "LeftDoubleBracket;": '\U000027E6',
+ "LeftDownTeeVector;": '\U00002961',
+ "LeftDownVector;": '\U000021C3',
+ "LeftDownVectorBar;": '\U00002959',
+ "LeftFloor;": '\U0000230A',
+ "LeftRightArrow;": '\U00002194',
+ "LeftRightVector;": '\U0000294E',
+ "LeftTee;": '\U000022A3',
+ "LeftTeeArrow;": '\U000021A4',
+ "LeftTeeVector;": '\U0000295A',
+ "LeftTriangle;": '\U000022B2',
+ "LeftTriangleBar;": '\U000029CF',
+ "LeftTriangleEqual;": '\U000022B4',
+ "LeftUpDownVector;": '\U00002951',
+ "LeftUpTeeVector;": '\U00002960',
+ "LeftUpVector;": '\U000021BF',
+ "LeftUpVectorBar;": '\U00002958',
+ "LeftVector;": '\U000021BC',
+ "LeftVectorBar;": '\U00002952',
+ "Leftarrow;": '\U000021D0',
+ "Leftrightarrow;": '\U000021D4',
+ "LessEqualGreater;": '\U000022DA',
+ "LessFullEqual;": '\U00002266',
+ "LessGreater;": '\U00002276',
+ "LessLess;": '\U00002AA1',
+ "LessSlantEqual;": '\U00002A7D',
+ "LessTilde;": '\U00002272',
+ "Lfr;": '\U0001D50F',
+ "Ll;": '\U000022D8',
+ "Lleftarrow;": '\U000021DA',
+ "Lmidot;": '\U0000013F',
+ "LongLeftArrow;": '\U000027F5',
+ "LongLeftRightArrow;": '\U000027F7',
+ "LongRightArrow;": '\U000027F6',
+ "Longleftarrow;": '\U000027F8',
+ "Longleftrightarrow;": '\U000027FA',
+ "Longrightarrow;": '\U000027F9',
+ "Lopf;": '\U0001D543',
+ "LowerLeftArrow;": '\U00002199',
+ "LowerRightArrow;": '\U00002198',
+ "Lscr;": '\U00002112',
+ "Lsh;": '\U000021B0',
+ "Lstrok;": '\U00000141',
+ "Lt;": '\U0000226A',
+ "Map;": '\U00002905',
+ "Mcy;": '\U0000041C',
+ "MediumSpace;": '\U0000205F',
+ "Mellintrf;": '\U00002133',
+ "Mfr;": '\U0001D510',
+ "MinusPlus;": '\U00002213',
+ "Mopf;": '\U0001D544',
+ "Mscr;": '\U00002133',
+ "Mu;": '\U0000039C',
+ "NJcy;": '\U0000040A',
+ "Nacute;": '\U00000143',
+ "Ncaron;": '\U00000147',
+ "Ncedil;": '\U00000145',
+ "Ncy;": '\U0000041D',
+ "NegativeMediumSpace;": '\U0000200B',
+ "NegativeThickSpace;": '\U0000200B',
+ "NegativeThinSpace;": '\U0000200B',
+ "NegativeVeryThinSpace;": '\U0000200B',
+ "NestedGreaterGreater;": '\U0000226B',
+ "NestedLessLess;": '\U0000226A',
+ "NewLine;": '\U0000000A',
+ "Nfr;": '\U0001D511',
+ "NoBreak;": '\U00002060',
+ "NonBreakingSpace;": '\U000000A0',
+ "Nopf;": '\U00002115',
+ "Not;": '\U00002AEC',
+ "NotCongruent;": '\U00002262',
+ "NotCupCap;": '\U0000226D',
+ "NotDoubleVerticalBar;": '\U00002226',
+ "NotElement;": '\U00002209',
+ "NotEqual;": '\U00002260',
+ "NotExists;": '\U00002204',
+ "NotGreater;": '\U0000226F',
+ "NotGreaterEqual;": '\U00002271',
+ "NotGreaterLess;": '\U00002279',
+ "NotGreaterTilde;": '\U00002275',
+ "NotLeftTriangle;": '\U000022EA',
+ "NotLeftTriangleEqual;": '\U000022EC',
+ "NotLess;": '\U0000226E',
+ "NotLessEqual;": '\U00002270',
+ "NotLessGreater;": '\U00002278',
+ "NotLessTilde;": '\U00002274',
+ "NotPrecedes;": '\U00002280',
+ "NotPrecedesSlantEqual;": '\U000022E0',
+ "NotReverseElement;": '\U0000220C',
+ "NotRightTriangle;": '\U000022EB',
+ "NotRightTriangleEqual;": '\U000022ED',
+ "NotSquareSubsetEqual;": '\U000022E2',
+ "NotSquareSupersetEqual;": '\U000022E3',
+ "NotSubsetEqual;": '\U00002288',
+ "NotSucceeds;": '\U00002281',
+ "NotSucceedsSlantEqual;": '\U000022E1',
+ "NotSupersetEqual;": '\U00002289',
+ "NotTilde;": '\U00002241',
+ "NotTildeEqual;": '\U00002244',
+ "NotTildeFullEqual;": '\U00002247',
+ "NotTildeTilde;": '\U00002249',
+ "NotVerticalBar;": '\U00002224',
+ "Nscr;": '\U0001D4A9',
+ "Ntilde;": '\U000000D1',
+ "Nu;": '\U0000039D',
+ "OElig;": '\U00000152',
+ "Oacute;": '\U000000D3',
+ "Ocirc;": '\U000000D4',
+ "Ocy;": '\U0000041E',
+ "Odblac;": '\U00000150',
+ "Ofr;": '\U0001D512',
+ "Ograve;": '\U000000D2',
+ "Omacr;": '\U0000014C',
+ "Omega;": '\U000003A9',
+ "Omicron;": '\U0000039F',
+ "Oopf;": '\U0001D546',
+ "OpenCurlyDoubleQuote;": '\U0000201C',
+ "OpenCurlyQuote;": '\U00002018',
+ "Or;": '\U00002A54',
+ "Oscr;": '\U0001D4AA',
+ "Oslash;": '\U000000D8',
+ "Otilde;": '\U000000D5',
+ "Otimes;": '\U00002A37',
+ "Ouml;": '\U000000D6',
+ "OverBar;": '\U0000203E',
+ "OverBrace;": '\U000023DE',
+ "OverBracket;": '\U000023B4',
+ "OverParenthesis;": '\U000023DC',
+ "PartialD;": '\U00002202',
+ "Pcy;": '\U0000041F',
+ "Pfr;": '\U0001D513',
+ "Phi;": '\U000003A6',
+ "Pi;": '\U000003A0',
+ "PlusMinus;": '\U000000B1',
+ "Poincareplane;": '\U0000210C',
+ "Popf;": '\U00002119',
+ "Pr;": '\U00002ABB',
+ "Precedes;": '\U0000227A',
+ "PrecedesEqual;": '\U00002AAF',
+ "PrecedesSlantEqual;": '\U0000227C',
+ "PrecedesTilde;": '\U0000227E',
+ "Prime;": '\U00002033',
+ "Product;": '\U0000220F',
+ "Proportion;": '\U00002237',
+ "Proportional;": '\U0000221D',
+ "Pscr;": '\U0001D4AB',
+ "Psi;": '\U000003A8',
+ "QUOT;": '\U00000022',
+ "Qfr;": '\U0001D514',
+ "Qopf;": '\U0000211A',
+ "Qscr;": '\U0001D4AC',
+ "RBarr;": '\U00002910',
+ "REG;": '\U000000AE',
+ "Racute;": '\U00000154',
+ "Rang;": '\U000027EB',
+ "Rarr;": '\U000021A0',
+ "Rarrtl;": '\U00002916',
+ "Rcaron;": '\U00000158',
+ "Rcedil;": '\U00000156',
+ "Rcy;": '\U00000420',
+ "Re;": '\U0000211C',
+ "ReverseElement;": '\U0000220B',
+ "ReverseEquilibrium;": '\U000021CB',
+ "ReverseUpEquilibrium;": '\U0000296F',
+ "Rfr;": '\U0000211C',
+ "Rho;": '\U000003A1',
+ "RightAngleBracket;": '\U000027E9',
+ "RightArrow;": '\U00002192',
+ "RightArrowBar;": '\U000021E5',
+ "RightArrowLeftArrow;": '\U000021C4',
+ "RightCeiling;": '\U00002309',
+ "RightDoubleBracket;": '\U000027E7',
+ "RightDownTeeVector;": '\U0000295D',
+ "RightDownVector;": '\U000021C2',
+ "RightDownVectorBar;": '\U00002955',
+ "RightFloor;": '\U0000230B',
+ "RightTee;": '\U000022A2',
+ "RightTeeArrow;": '\U000021A6',
+ "RightTeeVector;": '\U0000295B',
+ "RightTriangle;": '\U000022B3',
+ "RightTriangleBar;": '\U000029D0',
+ "RightTriangleEqual;": '\U000022B5',
+ "RightUpDownVector;": '\U0000294F',
+ "RightUpTeeVector;": '\U0000295C',
+ "RightUpVector;": '\U000021BE',
+ "RightUpVectorBar;": '\U00002954',
+ "RightVector;": '\U000021C0',
+ "RightVectorBar;": '\U00002953',
+ "Rightarrow;": '\U000021D2',
+ "Ropf;": '\U0000211D',
+ "RoundImplies;": '\U00002970',
+ "Rrightarrow;": '\U000021DB',
+ "Rscr;": '\U0000211B',
+ "Rsh;": '\U000021B1',
+ "RuleDelayed;": '\U000029F4',
+ "SHCHcy;": '\U00000429',
+ "SHcy;": '\U00000428',
+ "SOFTcy;": '\U0000042C',
+ "Sacute;": '\U0000015A',
+ "Sc;": '\U00002ABC',
+ "Scaron;": '\U00000160',
+ "Scedil;": '\U0000015E',
+ "Scirc;": '\U0000015C',
+ "Scy;": '\U00000421',
+ "Sfr;": '\U0001D516',
+ "ShortDownArrow;": '\U00002193',
+ "ShortLeftArrow;": '\U00002190',
+ "ShortRightArrow;": '\U00002192',
+ "ShortUpArrow;": '\U00002191',
+ "Sigma;": '\U000003A3',
+ "SmallCircle;": '\U00002218',
+ "Sopf;": '\U0001D54A',
+ "Sqrt;": '\U0000221A',
+ "Square;": '\U000025A1',
+ "SquareIntersection;": '\U00002293',
+ "SquareSubset;": '\U0000228F',
+ "SquareSubsetEqual;": '\U00002291',
+ "SquareSuperset;": '\U00002290',
+ "SquareSupersetEqual;": '\U00002292',
+ "SquareUnion;": '\U00002294',
+ "Sscr;": '\U0001D4AE',
+ "Star;": '\U000022C6',
+ "Sub;": '\U000022D0',
+ "Subset;": '\U000022D0',
+ "SubsetEqual;": '\U00002286',
+ "Succeeds;": '\U0000227B',
+ "SucceedsEqual;": '\U00002AB0',
+ "SucceedsSlantEqual;": '\U0000227D',
+ "SucceedsTilde;": '\U0000227F',
+ "SuchThat;": '\U0000220B',
+ "Sum;": '\U00002211',
+ "Sup;": '\U000022D1',
+ "Superset;": '\U00002283',
+ "SupersetEqual;": '\U00002287',
+ "Supset;": '\U000022D1',
+ "THORN;": '\U000000DE',
+ "TRADE;": '\U00002122',
+ "TSHcy;": '\U0000040B',
+ "TScy;": '\U00000426',
+ "Tab;": '\U00000009',
+ "Tau;": '\U000003A4',
+ "Tcaron;": '\U00000164',
+ "Tcedil;": '\U00000162',
+ "Tcy;": '\U00000422',
+ "Tfr;": '\U0001D517',
+ "Therefore;": '\U00002234',
+ "Theta;": '\U00000398',
+ "ThinSpace;": '\U00002009',
+ "Tilde;": '\U0000223C',
+ "TildeEqual;": '\U00002243',
+ "TildeFullEqual;": '\U00002245',
+ "TildeTilde;": '\U00002248',
+ "Topf;": '\U0001D54B',
+ "TripleDot;": '\U000020DB',
+ "Tscr;": '\U0001D4AF',
+ "Tstrok;": '\U00000166',
+ "Uacute;": '\U000000DA',
+ "Uarr;": '\U0000219F',
+ "Uarrocir;": '\U00002949',
+ "Ubrcy;": '\U0000040E',
+ "Ubreve;": '\U0000016C',
+ "Ucirc;": '\U000000DB',
+ "Ucy;": '\U00000423',
+ "Udblac;": '\U00000170',
+ "Ufr;": '\U0001D518',
+ "Ugrave;": '\U000000D9',
+ "Umacr;": '\U0000016A',
+ "UnderBar;": '\U0000005F',
+ "UnderBrace;": '\U000023DF',
+ "UnderBracket;": '\U000023B5',
+ "UnderParenthesis;": '\U000023DD',
+ "Union;": '\U000022C3',
+ "UnionPlus;": '\U0000228E',
+ "Uogon;": '\U00000172',
+ "Uopf;": '\U0001D54C',
+ "UpArrow;": '\U00002191',
+ "UpArrowBar;": '\U00002912',
+ "UpArrowDownArrow;": '\U000021C5',
+ "UpDownArrow;": '\U00002195',
+ "UpEquilibrium;": '\U0000296E',
+ "UpTee;": '\U000022A5',
+ "UpTeeArrow;": '\U000021A5',
+ "Uparrow;": '\U000021D1',
+ "Updownarrow;": '\U000021D5',
+ "UpperLeftArrow;": '\U00002196',
+ "UpperRightArrow;": '\U00002197',
+ "Upsi;": '\U000003D2',
+ "Upsilon;": '\U000003A5',
+ "Uring;": '\U0000016E',
+ "Uscr;": '\U0001D4B0',
+ "Utilde;": '\U00000168',
+ "Uuml;": '\U000000DC',
+ "VDash;": '\U000022AB',
+ "Vbar;": '\U00002AEB',
+ "Vcy;": '\U00000412',
+ "Vdash;": '\U000022A9',
+ "Vdashl;": '\U00002AE6',
+ "Vee;": '\U000022C1',
+ "Verbar;": '\U00002016',
+ "Vert;": '\U00002016',
+ "VerticalBar;": '\U00002223',
+ "VerticalLine;": '\U0000007C',
+ "VerticalSeparator;": '\U00002758',
+ "VerticalTilde;": '\U00002240',
+ "VeryThinSpace;": '\U0000200A',
+ "Vfr;": '\U0001D519',
+ "Vopf;": '\U0001D54D',
+ "Vscr;": '\U0001D4B1',
+ "Vvdash;": '\U000022AA',
+ "Wcirc;": '\U00000174',
+ "Wedge;": '\U000022C0',
+ "Wfr;": '\U0001D51A',
+ "Wopf;": '\U0001D54E',
+ "Wscr;": '\U0001D4B2',
+ "Xfr;": '\U0001D51B',
+ "Xi;": '\U0000039E',
+ "Xopf;": '\U0001D54F',
+ "Xscr;": '\U0001D4B3',
+ "YAcy;": '\U0000042F',
+ "YIcy;": '\U00000407',
+ "YUcy;": '\U0000042E',
+ "Yacute;": '\U000000DD',
+ "Ycirc;": '\U00000176',
+ "Ycy;": '\U0000042B',
+ "Yfr;": '\U0001D51C',
+ "Yopf;": '\U0001D550',
+ "Yscr;": '\U0001D4B4',
+ "Yuml;": '\U00000178',
+ "ZHcy;": '\U00000416',
+ "Zacute;": '\U00000179',
+ "Zcaron;": '\U0000017D',
+ "Zcy;": '\U00000417',
+ "Zdot;": '\U0000017B',
+ "ZeroWidthSpace;": '\U0000200B',
+ "Zeta;": '\U00000396',
+ "Zfr;": '\U00002128',
+ "Zopf;": '\U00002124',
+ "Zscr;": '\U0001D4B5',
+ "aacute;": '\U000000E1',
+ "abreve;": '\U00000103',
+ "ac;": '\U0000223E',
+ "acd;": '\U0000223F',
+ "acirc;": '\U000000E2',
+ "acute;": '\U000000B4',
+ "acy;": '\U00000430',
+ "aelig;": '\U000000E6',
+ "af;": '\U00002061',
+ "afr;": '\U0001D51E',
+ "agrave;": '\U000000E0',
+ "alefsym;": '\U00002135',
+ "aleph;": '\U00002135',
+ "alpha;": '\U000003B1',
+ "amacr;": '\U00000101',
+ "amalg;": '\U00002A3F',
+ "amp;": '\U00000026',
+ "and;": '\U00002227',
+ "andand;": '\U00002A55',
+ "andd;": '\U00002A5C',
+ "andslope;": '\U00002A58',
+ "andv;": '\U00002A5A',
+ "ang;": '\U00002220',
+ "ange;": '\U000029A4',
+ "angle;": '\U00002220',
+ "angmsd;": '\U00002221',
+ "angmsdaa;": '\U000029A8',
+ "angmsdab;": '\U000029A9',
+ "angmsdac;": '\U000029AA',
+ "angmsdad;": '\U000029AB',
+ "angmsdae;": '\U000029AC',
+ "angmsdaf;": '\U000029AD',
+ "angmsdag;": '\U000029AE',
+ "angmsdah;": '\U000029AF',
+ "angrt;": '\U0000221F',
+ "angrtvb;": '\U000022BE',
+ "angrtvbd;": '\U0000299D',
+ "angsph;": '\U00002222',
+ "angst;": '\U000000C5',
+ "angzarr;": '\U0000237C',
+ "aogon;": '\U00000105',
+ "aopf;": '\U0001D552',
+ "ap;": '\U00002248',
+ "apE;": '\U00002A70',
+ "apacir;": '\U00002A6F',
+ "ape;": '\U0000224A',
+ "apid;": '\U0000224B',
+ "apos;": '\U00000027',
+ "approx;": '\U00002248',
+ "approxeq;": '\U0000224A',
+ "aring;": '\U000000E5',
+ "ascr;": '\U0001D4B6',
+ "ast;": '\U0000002A',
+ "asymp;": '\U00002248',
+ "asympeq;": '\U0000224D',
+ "atilde;": '\U000000E3',
+ "auml;": '\U000000E4',
+ "awconint;": '\U00002233',
+ "awint;": '\U00002A11',
+ "bNot;": '\U00002AED',
+ "backcong;": '\U0000224C',
+ "backepsilon;": '\U000003F6',
+ "backprime;": '\U00002035',
+ "backsim;": '\U0000223D',
+ "backsimeq;": '\U000022CD',
+ "barvee;": '\U000022BD',
+ "barwed;": '\U00002305',
+ "barwedge;": '\U00002305',
+ "bbrk;": '\U000023B5',
+ "bbrktbrk;": '\U000023B6',
+ "bcong;": '\U0000224C',
+ "bcy;": '\U00000431',
+ "bdquo;": '\U0000201E',
+ "becaus;": '\U00002235',
+ "because;": '\U00002235',
+ "bemptyv;": '\U000029B0',
+ "bepsi;": '\U000003F6',
+ "bernou;": '\U0000212C',
+ "beta;": '\U000003B2',
+ "beth;": '\U00002136',
+ "between;": '\U0000226C',
+ "bfr;": '\U0001D51F',
+ "bigcap;": '\U000022C2',
+ "bigcirc;": '\U000025EF',
+ "bigcup;": '\U000022C3',
+ "bigodot;": '\U00002A00',
+ "bigoplus;": '\U00002A01',
+ "bigotimes;": '\U00002A02',
+ "bigsqcup;": '\U00002A06',
+ "bigstar;": '\U00002605',
+ "bigtriangledown;": '\U000025BD',
+ "bigtriangleup;": '\U000025B3',
+ "biguplus;": '\U00002A04',
+ "bigvee;": '\U000022C1',
+ "bigwedge;": '\U000022C0',
+ "bkarow;": '\U0000290D',
+ "blacklozenge;": '\U000029EB',
+ "blacksquare;": '\U000025AA',
+ "blacktriangle;": '\U000025B4',
+ "blacktriangledown;": '\U000025BE',
+ "blacktriangleleft;": '\U000025C2',
+ "blacktriangleright;": '\U000025B8',
+ "blank;": '\U00002423',
+ "blk12;": '\U00002592',
+ "blk14;": '\U00002591',
+ "blk34;": '\U00002593',
+ "block;": '\U00002588',
+ "bnot;": '\U00002310',
+ "bopf;": '\U0001D553',
+ "bot;": '\U000022A5',
+ "bottom;": '\U000022A5',
+ "bowtie;": '\U000022C8',
+ "boxDL;": '\U00002557',
+ "boxDR;": '\U00002554',
+ "boxDl;": '\U00002556',
+ "boxDr;": '\U00002553',
+ "boxH;": '\U00002550',
+ "boxHD;": '\U00002566',
+ "boxHU;": '\U00002569',
+ "boxHd;": '\U00002564',
+ "boxHu;": '\U00002567',
+ "boxUL;": '\U0000255D',
+ "boxUR;": '\U0000255A',
+ "boxUl;": '\U0000255C',
+ "boxUr;": '\U00002559',
+ "boxV;": '\U00002551',
+ "boxVH;": '\U0000256C',
+ "boxVL;": '\U00002563',
+ "boxVR;": '\U00002560',
+ "boxVh;": '\U0000256B',
+ "boxVl;": '\U00002562',
+ "boxVr;": '\U0000255F',
+ "boxbox;": '\U000029C9',
+ "boxdL;": '\U00002555',
+ "boxdR;": '\U00002552',
+ "boxdl;": '\U00002510',
+ "boxdr;": '\U0000250C',
+ "boxh;": '\U00002500',
+ "boxhD;": '\U00002565',
+ "boxhU;": '\U00002568',
+ "boxhd;": '\U0000252C',
+ "boxhu;": '\U00002534',
+ "boxminus;": '\U0000229F',
+ "boxplus;": '\U0000229E',
+ "boxtimes;": '\U000022A0',
+ "boxuL;": '\U0000255B',
+ "boxuR;": '\U00002558',
+ "boxul;": '\U00002518',
+ "boxur;": '\U00002514',
+ "boxv;": '\U00002502',
+ "boxvH;": '\U0000256A',
+ "boxvL;": '\U00002561',
+ "boxvR;": '\U0000255E',
+ "boxvh;": '\U0000253C',
+ "boxvl;": '\U00002524',
+ "boxvr;": '\U0000251C',
+ "bprime;": '\U00002035',
+ "breve;": '\U000002D8',
+ "brvbar;": '\U000000A6',
+ "bscr;": '\U0001D4B7',
+ "bsemi;": '\U0000204F',
+ "bsim;": '\U0000223D',
+ "bsime;": '\U000022CD',
+ "bsol;": '\U0000005C',
+ "bsolb;": '\U000029C5',
+ "bsolhsub;": '\U000027C8',
+ "bull;": '\U00002022',
+ "bullet;": '\U00002022',
+ "bump;": '\U0000224E',
+ "bumpE;": '\U00002AAE',
+ "bumpe;": '\U0000224F',
+ "bumpeq;": '\U0000224F',
+ "cacute;": '\U00000107',
+ "cap;": '\U00002229',
+ "capand;": '\U00002A44',
+ "capbrcup;": '\U00002A49',
+ "capcap;": '\U00002A4B',
+ "capcup;": '\U00002A47',
+ "capdot;": '\U00002A40',
+ "caret;": '\U00002041',
+ "caron;": '\U000002C7',
+ "ccaps;": '\U00002A4D',
+ "ccaron;": '\U0000010D',
+ "ccedil;": '\U000000E7',
+ "ccirc;": '\U00000109',
+ "ccups;": '\U00002A4C',
+ "ccupssm;": '\U00002A50',
+ "cdot;": '\U0000010B',
+ "cedil;": '\U000000B8',
+ "cemptyv;": '\U000029B2',
+ "cent;": '\U000000A2',
+ "centerdot;": '\U000000B7',
+ "cfr;": '\U0001D520',
+ "chcy;": '\U00000447',
+ "check;": '\U00002713',
+ "checkmark;": '\U00002713',
+ "chi;": '\U000003C7',
+ "cir;": '\U000025CB',
+ "cirE;": '\U000029C3',
+ "circ;": '\U000002C6',
+ "circeq;": '\U00002257',
+ "circlearrowleft;": '\U000021BA',
+ "circlearrowright;": '\U000021BB',
+ "circledR;": '\U000000AE',
+ "circledS;": '\U000024C8',
+ "circledast;": '\U0000229B',
+ "circledcirc;": '\U0000229A',
+ "circleddash;": '\U0000229D',
+ "cire;": '\U00002257',
+ "cirfnint;": '\U00002A10',
+ "cirmid;": '\U00002AEF',
+ "cirscir;": '\U000029C2',
+ "clubs;": '\U00002663',
+ "clubsuit;": '\U00002663',
+ "colon;": '\U0000003A',
+ "colone;": '\U00002254',
+ "coloneq;": '\U00002254',
+ "comma;": '\U0000002C',
+ "commat;": '\U00000040',
+ "comp;": '\U00002201',
+ "compfn;": '\U00002218',
+ "complement;": '\U00002201',
+ "complexes;": '\U00002102',
+ "cong;": '\U00002245',
+ "congdot;": '\U00002A6D',
+ "conint;": '\U0000222E',
+ "copf;": '\U0001D554',
+ "coprod;": '\U00002210',
+ "copy;": '\U000000A9',
+ "copysr;": '\U00002117',
+ "crarr;": '\U000021B5',
+ "cross;": '\U00002717',
+ "cscr;": '\U0001D4B8',
+ "csub;": '\U00002ACF',
+ "csube;": '\U00002AD1',
+ "csup;": '\U00002AD0',
+ "csupe;": '\U00002AD2',
+ "ctdot;": '\U000022EF',
+ "cudarrl;": '\U00002938',
+ "cudarrr;": '\U00002935',
+ "cuepr;": '\U000022DE',
+ "cuesc;": '\U000022DF',
+ "cularr;": '\U000021B6',
+ "cularrp;": '\U0000293D',
+ "cup;": '\U0000222A',
+ "cupbrcap;": '\U00002A48',
+ "cupcap;": '\U00002A46',
+ "cupcup;": '\U00002A4A',
+ "cupdot;": '\U0000228D',
+ "cupor;": '\U00002A45',
+ "curarr;": '\U000021B7',
+ "curarrm;": '\U0000293C',
+ "curlyeqprec;": '\U000022DE',
+ "curlyeqsucc;": '\U000022DF',
+ "curlyvee;": '\U000022CE',
+ "curlywedge;": '\U000022CF',
+ "curren;": '\U000000A4',
+ "curvearrowleft;": '\U000021B6',
+ "curvearrowright;": '\U000021B7',
+ "cuvee;": '\U000022CE',
+ "cuwed;": '\U000022CF',
+ "cwconint;": '\U00002232',
+ "cwint;": '\U00002231',
+ "cylcty;": '\U0000232D',
+ "dArr;": '\U000021D3',
+ "dHar;": '\U00002965',
+ "dagger;": '\U00002020',
+ "daleth;": '\U00002138',
+ "darr;": '\U00002193',
+ "dash;": '\U00002010',
+ "dashv;": '\U000022A3',
+ "dbkarow;": '\U0000290F',
+ "dblac;": '\U000002DD',
+ "dcaron;": '\U0000010F',
+ "dcy;": '\U00000434',
+ "dd;": '\U00002146',
+ "ddagger;": '\U00002021',
+ "ddarr;": '\U000021CA',
+ "ddotseq;": '\U00002A77',
+ "deg;": '\U000000B0',
+ "delta;": '\U000003B4',
+ "demptyv;": '\U000029B1',
+ "dfisht;": '\U0000297F',
+ "dfr;": '\U0001D521',
+ "dharl;": '\U000021C3',
+ "dharr;": '\U000021C2',
+ "diam;": '\U000022C4',
+ "diamond;": '\U000022C4',
+ "diamondsuit;": '\U00002666',
+ "diams;": '\U00002666',
+ "die;": '\U000000A8',
+ "digamma;": '\U000003DD',
+ "disin;": '\U000022F2',
+ "div;": '\U000000F7',
+ "divide;": '\U000000F7',
+ "divideontimes;": '\U000022C7',
+ "divonx;": '\U000022C7',
+ "djcy;": '\U00000452',
+ "dlcorn;": '\U0000231E',
+ "dlcrop;": '\U0000230D',
+ "dollar;": '\U00000024',
+ "dopf;": '\U0001D555',
+ "dot;": '\U000002D9',
+ "doteq;": '\U00002250',
+ "doteqdot;": '\U00002251',
+ "dotminus;": '\U00002238',
+ "dotplus;": '\U00002214',
+ "dotsquare;": '\U000022A1',
+ "doublebarwedge;": '\U00002306',
+ "downarrow;": '\U00002193',
+ "downdownarrows;": '\U000021CA',
+ "downharpoonleft;": '\U000021C3',
+ "downharpoonright;": '\U000021C2',
+ "drbkarow;": '\U00002910',
+ "drcorn;": '\U0000231F',
+ "drcrop;": '\U0000230C',
+ "dscr;": '\U0001D4B9',
+ "dscy;": '\U00000455',
+ "dsol;": '\U000029F6',
+ "dstrok;": '\U00000111',
+ "dtdot;": '\U000022F1',
+ "dtri;": '\U000025BF',
+ "dtrif;": '\U000025BE',
+ "duarr;": '\U000021F5',
+ "duhar;": '\U0000296F',
+ "dwangle;": '\U000029A6',
+ "dzcy;": '\U0000045F',
+ "dzigrarr;": '\U000027FF',
+ "eDDot;": '\U00002A77',
+ "eDot;": '\U00002251',
+ "eacute;": '\U000000E9',
+ "easter;": '\U00002A6E',
+ "ecaron;": '\U0000011B',
+ "ecir;": '\U00002256',
+ "ecirc;": '\U000000EA',
+ "ecolon;": '\U00002255',
+ "ecy;": '\U0000044D',
+ "edot;": '\U00000117',
+ "ee;": '\U00002147',
+ "efDot;": '\U00002252',
+ "efr;": '\U0001D522',
+ "eg;": '\U00002A9A',
+ "egrave;": '\U000000E8',
+ "egs;": '\U00002A96',
+ "egsdot;": '\U00002A98',
+ "el;": '\U00002A99',
+ "elinters;": '\U000023E7',
+ "ell;": '\U00002113',
+ "els;": '\U00002A95',
+ "elsdot;": '\U00002A97',
+ "emacr;": '\U00000113',
+ "empty;": '\U00002205',
+ "emptyset;": '\U00002205',
+ "emptyv;": '\U00002205',
+ "emsp;": '\U00002003',
+ "emsp13;": '\U00002004',
+ "emsp14;": '\U00002005',
+ "eng;": '\U0000014B',
+ "ensp;": '\U00002002',
+ "eogon;": '\U00000119',
+ "eopf;": '\U0001D556',
+ "epar;": '\U000022D5',
+ "eparsl;": '\U000029E3',
+ "eplus;": '\U00002A71',
+ "epsi;": '\U000003B5',
+ "epsilon;": '\U000003B5',
+ "epsiv;": '\U000003F5',
+ "eqcirc;": '\U00002256',
+ "eqcolon;": '\U00002255',
+ "eqsim;": '\U00002242',
+ "eqslantgtr;": '\U00002A96',
+ "eqslantless;": '\U00002A95',
+ "equals;": '\U0000003D',
+ "equest;": '\U0000225F',
+ "equiv;": '\U00002261',
+ "equivDD;": '\U00002A78',
+ "eqvparsl;": '\U000029E5',
+ "erDot;": '\U00002253',
+ "erarr;": '\U00002971',
+ "escr;": '\U0000212F',
+ "esdot;": '\U00002250',
+ "esim;": '\U00002242',
+ "eta;": '\U000003B7',
+ "eth;": '\U000000F0',
+ "euml;": '\U000000EB',
+ "euro;": '\U000020AC',
+ "excl;": '\U00000021',
+ "exist;": '\U00002203',
+ "expectation;": '\U00002130',
+ "exponentiale;": '\U00002147',
+ "fallingdotseq;": '\U00002252',
+ "fcy;": '\U00000444',
+ "female;": '\U00002640',
+ "ffilig;": '\U0000FB03',
+ "fflig;": '\U0000FB00',
+ "ffllig;": '\U0000FB04',
+ "ffr;": '\U0001D523',
+ "filig;": '\U0000FB01',
+ "flat;": '\U0000266D',
+ "fllig;": '\U0000FB02',
+ "fltns;": '\U000025B1',
+ "fnof;": '\U00000192',
+ "fopf;": '\U0001D557',
+ "forall;": '\U00002200',
+ "fork;": '\U000022D4',
+ "forkv;": '\U00002AD9',
+ "fpartint;": '\U00002A0D',
+ "frac12;": '\U000000BD',
+ "frac13;": '\U00002153',
+ "frac14;": '\U000000BC',
+ "frac15;": '\U00002155',
+ "frac16;": '\U00002159',
+ "frac18;": '\U0000215B',
+ "frac23;": '\U00002154',
+ "frac25;": '\U00002156',
+ "frac34;": '\U000000BE',
+ "frac35;": '\U00002157',
+ "frac38;": '\U0000215C',
+ "frac45;": '\U00002158',
+ "frac56;": '\U0000215A',
+ "frac58;": '\U0000215D',
+ "frac78;": '\U0000215E',
+ "frasl;": '\U00002044',
+ "frown;": '\U00002322',
+ "fscr;": '\U0001D4BB',
+ "gE;": '\U00002267',
+ "gEl;": '\U00002A8C',
+ "gacute;": '\U000001F5',
+ "gamma;": '\U000003B3',
+ "gammad;": '\U000003DD',
+ "gap;": '\U00002A86',
+ "gbreve;": '\U0000011F',
+ "gcirc;": '\U0000011D',
+ "gcy;": '\U00000433',
+ "gdot;": '\U00000121',
+ "ge;": '\U00002265',
+ "gel;": '\U000022DB',
+ "geq;": '\U00002265',
+ "geqq;": '\U00002267',
+ "geqslant;": '\U00002A7E',
+ "ges;": '\U00002A7E',
+ "gescc;": '\U00002AA9',
+ "gesdot;": '\U00002A80',
+ "gesdoto;": '\U00002A82',
+ "gesdotol;": '\U00002A84',
+ "gesles;": '\U00002A94',
+ "gfr;": '\U0001D524',
+ "gg;": '\U0000226B',
+ "ggg;": '\U000022D9',
+ "gimel;": '\U00002137',
+ "gjcy;": '\U00000453',
+ "gl;": '\U00002277',
+ "glE;": '\U00002A92',
+ "gla;": '\U00002AA5',
+ "glj;": '\U00002AA4',
+ "gnE;": '\U00002269',
+ "gnap;": '\U00002A8A',
+ "gnapprox;": '\U00002A8A',
+ "gne;": '\U00002A88',
+ "gneq;": '\U00002A88',
+ "gneqq;": '\U00002269',
+ "gnsim;": '\U000022E7',
+ "gopf;": '\U0001D558',
+ "grave;": '\U00000060',
+ "gscr;": '\U0000210A',
+ "gsim;": '\U00002273',
+ "gsime;": '\U00002A8E',
+ "gsiml;": '\U00002A90',
+ "gt;": '\U0000003E',
+ "gtcc;": '\U00002AA7',
+ "gtcir;": '\U00002A7A',
+ "gtdot;": '\U000022D7',
+ "gtlPar;": '\U00002995',
+ "gtquest;": '\U00002A7C',
+ "gtrapprox;": '\U00002A86',
+ "gtrarr;": '\U00002978',
+ "gtrdot;": '\U000022D7',
+ "gtreqless;": '\U000022DB',
+ "gtreqqless;": '\U00002A8C',
+ "gtrless;": '\U00002277',
+ "gtrsim;": '\U00002273',
+ "hArr;": '\U000021D4',
+ "hairsp;": '\U0000200A',
+ "half;": '\U000000BD',
+ "hamilt;": '\U0000210B',
+ "hardcy;": '\U0000044A',
+ "harr;": '\U00002194',
+ "harrcir;": '\U00002948',
+ "harrw;": '\U000021AD',
+ "hbar;": '\U0000210F',
+ "hcirc;": '\U00000125',
+ "hearts;": '\U00002665',
+ "heartsuit;": '\U00002665',
+ "hellip;": '\U00002026',
+ "hercon;": '\U000022B9',
+ "hfr;": '\U0001D525',
+ "hksearow;": '\U00002925',
+ "hkswarow;": '\U00002926',
+ "hoarr;": '\U000021FF',
+ "homtht;": '\U0000223B',
+ "hookleftarrow;": '\U000021A9',
+ "hookrightarrow;": '\U000021AA',
+ "hopf;": '\U0001D559',
+ "horbar;": '\U00002015',
+ "hscr;": '\U0001D4BD',
+ "hslash;": '\U0000210F',
+ "hstrok;": '\U00000127',
+ "hybull;": '\U00002043',
+ "hyphen;": '\U00002010',
+ "iacute;": '\U000000ED',
+ "ic;": '\U00002063',
+ "icirc;": '\U000000EE',
+ "icy;": '\U00000438',
+ "iecy;": '\U00000435',
+ "iexcl;": '\U000000A1',
+ "iff;": '\U000021D4',
+ "ifr;": '\U0001D526',
+ "igrave;": '\U000000EC',
+ "ii;": '\U00002148',
+ "iiiint;": '\U00002A0C',
+ "iiint;": '\U0000222D',
+ "iinfin;": '\U000029DC',
+ "iiota;": '\U00002129',
+ "ijlig;": '\U00000133',
+ "imacr;": '\U0000012B',
+ "image;": '\U00002111',
+ "imagline;": '\U00002110',
+ "imagpart;": '\U00002111',
+ "imath;": '\U00000131',
+ "imof;": '\U000022B7',
+ "imped;": '\U000001B5',
+ "in;": '\U00002208',
+ "incare;": '\U00002105',
+ "infin;": '\U0000221E',
+ "infintie;": '\U000029DD',
+ "inodot;": '\U00000131',
+ "int;": '\U0000222B',
+ "intcal;": '\U000022BA',
+ "integers;": '\U00002124',
+ "intercal;": '\U000022BA',
+ "intlarhk;": '\U00002A17',
+ "intprod;": '\U00002A3C',
+ "iocy;": '\U00000451',
+ "iogon;": '\U0000012F',
+ "iopf;": '\U0001D55A',
+ "iota;": '\U000003B9',
+ "iprod;": '\U00002A3C',
+ "iquest;": '\U000000BF',
+ "iscr;": '\U0001D4BE',
+ "isin;": '\U00002208',
+ "isinE;": '\U000022F9',
+ "isindot;": '\U000022F5',
+ "isins;": '\U000022F4',
+ "isinsv;": '\U000022F3',
+ "isinv;": '\U00002208',
+ "it;": '\U00002062',
+ "itilde;": '\U00000129',
+ "iukcy;": '\U00000456',
+ "iuml;": '\U000000EF',
+ "jcirc;": '\U00000135',
+ "jcy;": '\U00000439',
+ "jfr;": '\U0001D527',
+ "jmath;": '\U00000237',
+ "jopf;": '\U0001D55B',
+ "jscr;": '\U0001D4BF',
+ "jsercy;": '\U00000458',
+ "jukcy;": '\U00000454',
+ "kappa;": '\U000003BA',
+ "kappav;": '\U000003F0',
+ "kcedil;": '\U00000137',
+ "kcy;": '\U0000043A',
+ "kfr;": '\U0001D528',
+ "kgreen;": '\U00000138',
+ "khcy;": '\U00000445',
+ "kjcy;": '\U0000045C',
+ "kopf;": '\U0001D55C',
+ "kscr;": '\U0001D4C0',
+ "lAarr;": '\U000021DA',
+ "lArr;": '\U000021D0',
+ "lAtail;": '\U0000291B',
+ "lBarr;": '\U0000290E',
+ "lE;": '\U00002266',
+ "lEg;": '\U00002A8B',
+ "lHar;": '\U00002962',
+ "lacute;": '\U0000013A',
+ "laemptyv;": '\U000029B4',
+ "lagran;": '\U00002112',
+ "lambda;": '\U000003BB',
+ "lang;": '\U000027E8',
+ "langd;": '\U00002991',
+ "langle;": '\U000027E8',
+ "lap;": '\U00002A85',
+ "laquo;": '\U000000AB',
+ "larr;": '\U00002190',
+ "larrb;": '\U000021E4',
+ "larrbfs;": '\U0000291F',
+ "larrfs;": '\U0000291D',
+ "larrhk;": '\U000021A9',
+ "larrlp;": '\U000021AB',
+ "larrpl;": '\U00002939',
+ "larrsim;": '\U00002973',
+ "larrtl;": '\U000021A2',
+ "lat;": '\U00002AAB',
+ "latail;": '\U00002919',
+ "late;": '\U00002AAD',
+ "lbarr;": '\U0000290C',
+ "lbbrk;": '\U00002772',
+ "lbrace;": '\U0000007B',
+ "lbrack;": '\U0000005B',
+ "lbrke;": '\U0000298B',
+ "lbrksld;": '\U0000298F',
+ "lbrkslu;": '\U0000298D',
+ "lcaron;": '\U0000013E',
+ "lcedil;": '\U0000013C',
+ "lceil;": '\U00002308',
+ "lcub;": '\U0000007B',
+ "lcy;": '\U0000043B',
+ "ldca;": '\U00002936',
+ "ldquo;": '\U0000201C',
+ "ldquor;": '\U0000201E',
+ "ldrdhar;": '\U00002967',
+ "ldrushar;": '\U0000294B',
+ "ldsh;": '\U000021B2',
+ "le;": '\U00002264',
+ "leftarrow;": '\U00002190',
+ "leftarrowtail;": '\U000021A2',
+ "leftharpoondown;": '\U000021BD',
+ "leftharpoonup;": '\U000021BC',
+ "leftleftarrows;": '\U000021C7',
+ "leftrightarrow;": '\U00002194',
+ "leftrightarrows;": '\U000021C6',
+ "leftrightharpoons;": '\U000021CB',
+ "leftrightsquigarrow;": '\U000021AD',
+ "leftthreetimes;": '\U000022CB',
+ "leg;": '\U000022DA',
+ "leq;": '\U00002264',
+ "leqq;": '\U00002266',
+ "leqslant;": '\U00002A7D',
+ "les;": '\U00002A7D',
+ "lescc;": '\U00002AA8',
+ "lesdot;": '\U00002A7F',
+ "lesdoto;": '\U00002A81',
+ "lesdotor;": '\U00002A83',
+ "lesges;": '\U00002A93',
+ "lessapprox;": '\U00002A85',
+ "lessdot;": '\U000022D6',
+ "lesseqgtr;": '\U000022DA',
+ "lesseqqgtr;": '\U00002A8B',
+ "lessgtr;": '\U00002276',
+ "lesssim;": '\U00002272',
+ "lfisht;": '\U0000297C',
+ "lfloor;": '\U0000230A',
+ "lfr;": '\U0001D529',
+ "lg;": '\U00002276',
+ "lgE;": '\U00002A91',
+ "lhard;": '\U000021BD',
+ "lharu;": '\U000021BC',
+ "lharul;": '\U0000296A',
+ "lhblk;": '\U00002584',
+ "ljcy;": '\U00000459',
+ "ll;": '\U0000226A',
+ "llarr;": '\U000021C7',
+ "llcorner;": '\U0000231E',
+ "llhard;": '\U0000296B',
+ "lltri;": '\U000025FA',
+ "lmidot;": '\U00000140',
+ "lmoust;": '\U000023B0',
+ "lmoustache;": '\U000023B0',
+ "lnE;": '\U00002268',
+ "lnap;": '\U00002A89',
+ "lnapprox;": '\U00002A89',
+ "lne;": '\U00002A87',
+ "lneq;": '\U00002A87',
+ "lneqq;": '\U00002268',
+ "lnsim;": '\U000022E6',
+ "loang;": '\U000027EC',
+ "loarr;": '\U000021FD',
+ "lobrk;": '\U000027E6',
+ "longleftarrow;": '\U000027F5',
+ "longleftrightarrow;": '\U000027F7',
+ "longmapsto;": '\U000027FC',
+ "longrightarrow;": '\U000027F6',
+ "looparrowleft;": '\U000021AB',
+ "looparrowright;": '\U000021AC',
+ "lopar;": '\U00002985',
+ "lopf;": '\U0001D55D',
+ "loplus;": '\U00002A2D',
+ "lotimes;": '\U00002A34',
+ "lowast;": '\U00002217',
+ "lowbar;": '\U0000005F',
+ "loz;": '\U000025CA',
+ "lozenge;": '\U000025CA',
+ "lozf;": '\U000029EB',
+ "lpar;": '\U00000028',
+ "lparlt;": '\U00002993',
+ "lrarr;": '\U000021C6',
+ "lrcorner;": '\U0000231F',
+ "lrhar;": '\U000021CB',
+ "lrhard;": '\U0000296D',
+ "lrm;": '\U0000200E',
+ "lrtri;": '\U000022BF',
+ "lsaquo;": '\U00002039',
+ "lscr;": '\U0001D4C1',
+ "lsh;": '\U000021B0',
+ "lsim;": '\U00002272',
+ "lsime;": '\U00002A8D',
+ "lsimg;": '\U00002A8F',
+ "lsqb;": '\U0000005B',
+ "lsquo;": '\U00002018',
+ "lsquor;": '\U0000201A',
+ "lstrok;": '\U00000142',
+ "lt;": '\U0000003C',
+ "ltcc;": '\U00002AA6',
+ "ltcir;": '\U00002A79',
+ "ltdot;": '\U000022D6',
+ "lthree;": '\U000022CB',
+ "ltimes;": '\U000022C9',
+ "ltlarr;": '\U00002976',
+ "ltquest;": '\U00002A7B',
+ "ltrPar;": '\U00002996',
+ "ltri;": '\U000025C3',
+ "ltrie;": '\U000022B4',
+ "ltrif;": '\U000025C2',
+ "lurdshar;": '\U0000294A',
+ "luruhar;": '\U00002966',
+ "mDDot;": '\U0000223A',
+ "macr;": '\U000000AF',
+ "male;": '\U00002642',
+ "malt;": '\U00002720',
+ "maltese;": '\U00002720',
+ "map;": '\U000021A6',
+ "mapsto;": '\U000021A6',
+ "mapstodown;": '\U000021A7',
+ "mapstoleft;": '\U000021A4',
+ "mapstoup;": '\U000021A5',
+ "marker;": '\U000025AE',
+ "mcomma;": '\U00002A29',
+ "mcy;": '\U0000043C',
+ "mdash;": '\U00002014',
+ "measuredangle;": '\U00002221',
+ "mfr;": '\U0001D52A',
+ "mho;": '\U00002127',
+ "micro;": '\U000000B5',
+ "mid;": '\U00002223',
+ "midast;": '\U0000002A',
+ "midcir;": '\U00002AF0',
+ "middot;": '\U000000B7',
+ "minus;": '\U00002212',
+ "minusb;": '\U0000229F',
+ "minusd;": '\U00002238',
+ "minusdu;": '\U00002A2A',
+ "mlcp;": '\U00002ADB',
+ "mldr;": '\U00002026',
+ "mnplus;": '\U00002213',
+ "models;": '\U000022A7',
+ "mopf;": '\U0001D55E',
+ "mp;": '\U00002213',
+ "mscr;": '\U0001D4C2',
+ "mstpos;": '\U0000223E',
+ "mu;": '\U000003BC',
+ "multimap;": '\U000022B8',
+ "mumap;": '\U000022B8',
+ "nLeftarrow;": '\U000021CD',
+ "nLeftrightarrow;": '\U000021CE',
+ "nRightarrow;": '\U000021CF',
+ "nVDash;": '\U000022AF',
+ "nVdash;": '\U000022AE',
+ "nabla;": '\U00002207',
+ "nacute;": '\U00000144',
+ "nap;": '\U00002249',
+ "napos;": '\U00000149',
+ "napprox;": '\U00002249',
+ "natur;": '\U0000266E',
+ "natural;": '\U0000266E',
+ "naturals;": '\U00002115',
+ "nbsp;": '\U000000A0',
+ "ncap;": '\U00002A43',
+ "ncaron;": '\U00000148',
+ "ncedil;": '\U00000146',
+ "ncong;": '\U00002247',
+ "ncup;": '\U00002A42',
+ "ncy;": '\U0000043D',
+ "ndash;": '\U00002013',
+ "ne;": '\U00002260',
+ "neArr;": '\U000021D7',
+ "nearhk;": '\U00002924',
+ "nearr;": '\U00002197',
+ "nearrow;": '\U00002197',
+ "nequiv;": '\U00002262',
+ "nesear;": '\U00002928',
+ "nexist;": '\U00002204',
+ "nexists;": '\U00002204',
+ "nfr;": '\U0001D52B',
+ "nge;": '\U00002271',
+ "ngeq;": '\U00002271',
+ "ngsim;": '\U00002275',
+ "ngt;": '\U0000226F',
+ "ngtr;": '\U0000226F',
+ "nhArr;": '\U000021CE',
+ "nharr;": '\U000021AE',
+ "nhpar;": '\U00002AF2',
+ "ni;": '\U0000220B',
+ "nis;": '\U000022FC',
+ "nisd;": '\U000022FA',
+ "niv;": '\U0000220B',
+ "njcy;": '\U0000045A',
+ "nlArr;": '\U000021CD',
+ "nlarr;": '\U0000219A',
+ "nldr;": '\U00002025',
+ "nle;": '\U00002270',
+ "nleftarrow;": '\U0000219A',
+ "nleftrightarrow;": '\U000021AE',
+ "nleq;": '\U00002270',
+ "nless;": '\U0000226E',
+ "nlsim;": '\U00002274',
+ "nlt;": '\U0000226E',
+ "nltri;": '\U000022EA',
+ "nltrie;": '\U000022EC',
+ "nmid;": '\U00002224',
+ "nopf;": '\U0001D55F',
+ "not;": '\U000000AC',
+ "notin;": '\U00002209',
+ "notinva;": '\U00002209',
+ "notinvb;": '\U000022F7',
+ "notinvc;": '\U000022F6',
+ "notni;": '\U0000220C',
+ "notniva;": '\U0000220C',
+ "notnivb;": '\U000022FE',
+ "notnivc;": '\U000022FD',
+ "npar;": '\U00002226',
+ "nparallel;": '\U00002226',
+ "npolint;": '\U00002A14',
+ "npr;": '\U00002280',
+ "nprcue;": '\U000022E0',
+ "nprec;": '\U00002280',
+ "nrArr;": '\U000021CF',
+ "nrarr;": '\U0000219B',
+ "nrightarrow;": '\U0000219B',
+ "nrtri;": '\U000022EB',
+ "nrtrie;": '\U000022ED',
+ "nsc;": '\U00002281',
+ "nsccue;": '\U000022E1',
+ "nscr;": '\U0001D4C3',
+ "nshortmid;": '\U00002224',
+ "nshortparallel;": '\U00002226',
+ "nsim;": '\U00002241',
+ "nsime;": '\U00002244',
+ "nsimeq;": '\U00002244',
+ "nsmid;": '\U00002224',
+ "nspar;": '\U00002226',
+ "nsqsube;": '\U000022E2',
+ "nsqsupe;": '\U000022E3',
+ "nsub;": '\U00002284',
+ "nsube;": '\U00002288',
+ "nsubseteq;": '\U00002288',
+ "nsucc;": '\U00002281',
+ "nsup;": '\U00002285',
+ "nsupe;": '\U00002289',
+ "nsupseteq;": '\U00002289',
+ "ntgl;": '\U00002279',
+ "ntilde;": '\U000000F1',
+ "ntlg;": '\U00002278',
+ "ntriangleleft;": '\U000022EA',
+ "ntrianglelefteq;": '\U000022EC',
+ "ntriangleright;": '\U000022EB',
+ "ntrianglerighteq;": '\U000022ED',
+ "nu;": '\U000003BD',
+ "num;": '\U00000023',
+ "numero;": '\U00002116',
+ "numsp;": '\U00002007',
+ "nvDash;": '\U000022AD',
+ "nvHarr;": '\U00002904',
+ "nvdash;": '\U000022AC',
+ "nvinfin;": '\U000029DE',
+ "nvlArr;": '\U00002902',
+ "nvrArr;": '\U00002903',
+ "nwArr;": '\U000021D6',
+ "nwarhk;": '\U00002923',
+ "nwarr;": '\U00002196',
+ "nwarrow;": '\U00002196',
+ "nwnear;": '\U00002927',
+ "oS;": '\U000024C8',
+ "oacute;": '\U000000F3',
+ "oast;": '\U0000229B',
+ "ocir;": '\U0000229A',
+ "ocirc;": '\U000000F4',
+ "ocy;": '\U0000043E',
+ "odash;": '\U0000229D',
+ "odblac;": '\U00000151',
+ "odiv;": '\U00002A38',
+ "odot;": '\U00002299',
+ "odsold;": '\U000029BC',
+ "oelig;": '\U00000153',
+ "ofcir;": '\U000029BF',
+ "ofr;": '\U0001D52C',
+ "ogon;": '\U000002DB',
+ "ograve;": '\U000000F2',
+ "ogt;": '\U000029C1',
+ "ohbar;": '\U000029B5',
+ "ohm;": '\U000003A9',
+ "oint;": '\U0000222E',
+ "olarr;": '\U000021BA',
+ "olcir;": '\U000029BE',
+ "olcross;": '\U000029BB',
+ "oline;": '\U0000203E',
+ "olt;": '\U000029C0',
+ "omacr;": '\U0000014D',
+ "omega;": '\U000003C9',
+ "omicron;": '\U000003BF',
+ "omid;": '\U000029B6',
+ "ominus;": '\U00002296',
+ "oopf;": '\U0001D560',
+ "opar;": '\U000029B7',
+ "operp;": '\U000029B9',
+ "oplus;": '\U00002295',
+ "or;": '\U00002228',
+ "orarr;": '\U000021BB',
+ "ord;": '\U00002A5D',
+ "order;": '\U00002134',
+ "orderof;": '\U00002134',
+ "ordf;": '\U000000AA',
+ "ordm;": '\U000000BA',
+ "origof;": '\U000022B6',
+ "oror;": '\U00002A56',
+ "orslope;": '\U00002A57',
+ "orv;": '\U00002A5B',
+ "oscr;": '\U00002134',
+ "oslash;": '\U000000F8',
+ "osol;": '\U00002298',
+ "otilde;": '\U000000F5',
+ "otimes;": '\U00002297',
+ "otimesas;": '\U00002A36',
+ "ouml;": '\U000000F6',
+ "ovbar;": '\U0000233D',
+ "par;": '\U00002225',
+ "para;": '\U000000B6',
+ "parallel;": '\U00002225',
+ "parsim;": '\U00002AF3',
+ "parsl;": '\U00002AFD',
+ "part;": '\U00002202',
+ "pcy;": '\U0000043F',
+ "percnt;": '\U00000025',
+ "period;": '\U0000002E',
+ "permil;": '\U00002030',
+ "perp;": '\U000022A5',
+ "pertenk;": '\U00002031',
+ "pfr;": '\U0001D52D',
+ "phi;": '\U000003C6',
+ "phiv;": '\U000003D5',
+ "phmmat;": '\U00002133',
+ "phone;": '\U0000260E',
+ "pi;": '\U000003C0',
+ "pitchfork;": '\U000022D4',
+ "piv;": '\U000003D6',
+ "planck;": '\U0000210F',
+ "planckh;": '\U0000210E',
+ "plankv;": '\U0000210F',
+ "plus;": '\U0000002B',
+ "plusacir;": '\U00002A23',
+ "plusb;": '\U0000229E',
+ "pluscir;": '\U00002A22',
+ "plusdo;": '\U00002214',
+ "plusdu;": '\U00002A25',
+ "pluse;": '\U00002A72',
+ "plusmn;": '\U000000B1',
+ "plussim;": '\U00002A26',
+ "plustwo;": '\U00002A27',
+ "pm;": '\U000000B1',
+ "pointint;": '\U00002A15',
+ "popf;": '\U0001D561',
+ "pound;": '\U000000A3',
+ "pr;": '\U0000227A',
+ "prE;": '\U00002AB3',
+ "prap;": '\U00002AB7',
+ "prcue;": '\U0000227C',
+ "pre;": '\U00002AAF',
+ "prec;": '\U0000227A',
+ "precapprox;": '\U00002AB7',
+ "preccurlyeq;": '\U0000227C',
+ "preceq;": '\U00002AAF',
+ "precnapprox;": '\U00002AB9',
+ "precneqq;": '\U00002AB5',
+ "precnsim;": '\U000022E8',
+ "precsim;": '\U0000227E',
+ "prime;": '\U00002032',
+ "primes;": '\U00002119',
+ "prnE;": '\U00002AB5',
+ "prnap;": '\U00002AB9',
+ "prnsim;": '\U000022E8',
+ "prod;": '\U0000220F',
+ "profalar;": '\U0000232E',
+ "profline;": '\U00002312',
+ "profsurf;": '\U00002313',
+ "prop;": '\U0000221D',
+ "propto;": '\U0000221D',
+ "prsim;": '\U0000227E',
+ "prurel;": '\U000022B0',
+ "pscr;": '\U0001D4C5',
+ "psi;": '\U000003C8',
+ "puncsp;": '\U00002008',
+ "qfr;": '\U0001D52E',
+ "qint;": '\U00002A0C',
+ "qopf;": '\U0001D562',
+ "qprime;": '\U00002057',
+ "qscr;": '\U0001D4C6',
+ "quaternions;": '\U0000210D',
+ "quatint;": '\U00002A16',
+ "quest;": '\U0000003F',
+ "questeq;": '\U0000225F',
+ "quot;": '\U00000022',
+ "rAarr;": '\U000021DB',
+ "rArr;": '\U000021D2',
+ "rAtail;": '\U0000291C',
+ "rBarr;": '\U0000290F',
+ "rHar;": '\U00002964',
+ "racute;": '\U00000155',
+ "radic;": '\U0000221A',
+ "raemptyv;": '\U000029B3',
+ "rang;": '\U000027E9',
+ "rangd;": '\U00002992',
+ "range;": '\U000029A5',
+ "rangle;": '\U000027E9',
+ "raquo;": '\U000000BB',
+ "rarr;": '\U00002192',
+ "rarrap;": '\U00002975',
+ "rarrb;": '\U000021E5',
+ "rarrbfs;": '\U00002920',
+ "rarrc;": '\U00002933',
+ "rarrfs;": '\U0000291E',
+ "rarrhk;": '\U000021AA',
+ "rarrlp;": '\U000021AC',
+ "rarrpl;": '\U00002945',
+ "rarrsim;": '\U00002974',
+ "rarrtl;": '\U000021A3',
+ "rarrw;": '\U0000219D',
+ "ratail;": '\U0000291A',
+ "ratio;": '\U00002236',
+ "rationals;": '\U0000211A',
+ "rbarr;": '\U0000290D',
+ "rbbrk;": '\U00002773',
+ "rbrace;": '\U0000007D',
+ "rbrack;": '\U0000005D',
+ "rbrke;": '\U0000298C',
+ "rbrksld;": '\U0000298E',
+ "rbrkslu;": '\U00002990',
+ "rcaron;": '\U00000159',
+ "rcedil;": '\U00000157',
+ "rceil;": '\U00002309',
+ "rcub;": '\U0000007D',
+ "rcy;": '\U00000440',
+ "rdca;": '\U00002937',
+ "rdldhar;": '\U00002969',
+ "rdquo;": '\U0000201D',
+ "rdquor;": '\U0000201D',
+ "rdsh;": '\U000021B3',
+ "real;": '\U0000211C',
+ "realine;": '\U0000211B',
+ "realpart;": '\U0000211C',
+ "reals;": '\U0000211D',
+ "rect;": '\U000025AD',
+ "reg;": '\U000000AE',
+ "rfisht;": '\U0000297D',
+ "rfloor;": '\U0000230B',
+ "rfr;": '\U0001D52F',
+ "rhard;": '\U000021C1',
+ "rharu;": '\U000021C0',
+ "rharul;": '\U0000296C',
+ "rho;": '\U000003C1',
+ "rhov;": '\U000003F1',
+ "rightarrow;": '\U00002192',
+ "rightarrowtail;": '\U000021A3',
+ "rightharpoondown;": '\U000021C1',
+ "rightharpoonup;": '\U000021C0',
+ "rightleftarrows;": '\U000021C4',
+ "rightleftharpoons;": '\U000021CC',
+ "rightrightarrows;": '\U000021C9',
+ "rightsquigarrow;": '\U0000219D',
+ "rightthreetimes;": '\U000022CC',
+ "ring;": '\U000002DA',
+ "risingdotseq;": '\U00002253',
+ "rlarr;": '\U000021C4',
+ "rlhar;": '\U000021CC',
+ "rlm;": '\U0000200F',
+ "rmoust;": '\U000023B1',
+ "rmoustache;": '\U000023B1',
+ "rnmid;": '\U00002AEE',
+ "roang;": '\U000027ED',
+ "roarr;": '\U000021FE',
+ "robrk;": '\U000027E7',
+ "ropar;": '\U00002986',
+ "ropf;": '\U0001D563',
+ "roplus;": '\U00002A2E',
+ "rotimes;": '\U00002A35',
+ "rpar;": '\U00000029',
+ "rpargt;": '\U00002994',
+ "rppolint;": '\U00002A12',
+ "rrarr;": '\U000021C9',
+ "rsaquo;": '\U0000203A',
+ "rscr;": '\U0001D4C7',
+ "rsh;": '\U000021B1',
+ "rsqb;": '\U0000005D',
+ "rsquo;": '\U00002019',
+ "rsquor;": '\U00002019',
+ "rthree;": '\U000022CC',
+ "rtimes;": '\U000022CA',
+ "rtri;": '\U000025B9',
+ "rtrie;": '\U000022B5',
+ "rtrif;": '\U000025B8',
+ "rtriltri;": '\U000029CE',
+ "ruluhar;": '\U00002968',
+ "rx;": '\U0000211E',
+ "sacute;": '\U0000015B',
+ "sbquo;": '\U0000201A',
+ "sc;": '\U0000227B',
+ "scE;": '\U00002AB4',
+ "scap;": '\U00002AB8',
+ "scaron;": '\U00000161',
+ "sccue;": '\U0000227D',
+ "sce;": '\U00002AB0',
+ "scedil;": '\U0000015F',
+ "scirc;": '\U0000015D',
+ "scnE;": '\U00002AB6',
+ "scnap;": '\U00002ABA',
+ "scnsim;": '\U000022E9',
+ "scpolint;": '\U00002A13',
+ "scsim;": '\U0000227F',
+ "scy;": '\U00000441',
+ "sdot;": '\U000022C5',
+ "sdotb;": '\U000022A1',
+ "sdote;": '\U00002A66',
+ "seArr;": '\U000021D8',
+ "searhk;": '\U00002925',
+ "searr;": '\U00002198',
+ "searrow;": '\U00002198',
+ "sect;": '\U000000A7',
+ "semi;": '\U0000003B',
+ "seswar;": '\U00002929',
+ "setminus;": '\U00002216',
+ "setmn;": '\U00002216',
+ "sext;": '\U00002736',
+ "sfr;": '\U0001D530',
+ "sfrown;": '\U00002322',
+ "sharp;": '\U0000266F',
+ "shchcy;": '\U00000449',
+ "shcy;": '\U00000448',
+ "shortmid;": '\U00002223',
+ "shortparallel;": '\U00002225',
+ "shy;": '\U000000AD',
+ "sigma;": '\U000003C3',
+ "sigmaf;": '\U000003C2',
+ "sigmav;": '\U000003C2',
+ "sim;": '\U0000223C',
+ "simdot;": '\U00002A6A',
+ "sime;": '\U00002243',
+ "simeq;": '\U00002243',
+ "simg;": '\U00002A9E',
+ "simgE;": '\U00002AA0',
+ "siml;": '\U00002A9D',
+ "simlE;": '\U00002A9F',
+ "simne;": '\U00002246',
+ "simplus;": '\U00002A24',
+ "simrarr;": '\U00002972',
+ "slarr;": '\U00002190',
+ "smallsetminus;": '\U00002216',
+ "smashp;": '\U00002A33',
+ "smeparsl;": '\U000029E4',
+ "smid;": '\U00002223',
+ "smile;": '\U00002323',
+ "smt;": '\U00002AAA',
+ "smte;": '\U00002AAC',
+ "softcy;": '\U0000044C',
+ "sol;": '\U0000002F',
+ "solb;": '\U000029C4',
+ "solbar;": '\U0000233F',
+ "sopf;": '\U0001D564',
+ "spades;": '\U00002660',
+ "spadesuit;": '\U00002660',
+ "spar;": '\U00002225',
+ "sqcap;": '\U00002293',
+ "sqcup;": '\U00002294',
+ "sqsub;": '\U0000228F',
+ "sqsube;": '\U00002291',
+ "sqsubset;": '\U0000228F',
+ "sqsubseteq;": '\U00002291',
+ "sqsup;": '\U00002290',
+ "sqsupe;": '\U00002292',
+ "sqsupset;": '\U00002290',
+ "sqsupseteq;": '\U00002292',
+ "squ;": '\U000025A1',
+ "square;": '\U000025A1',
+ "squarf;": '\U000025AA',
+ "squf;": '\U000025AA',
+ "srarr;": '\U00002192',
+ "sscr;": '\U0001D4C8',
+ "ssetmn;": '\U00002216',
+ "ssmile;": '\U00002323',
+ "sstarf;": '\U000022C6',
+ "star;": '\U00002606',
+ "starf;": '\U00002605',
+ "straightepsilon;": '\U000003F5',
+ "straightphi;": '\U000003D5',
+ "strns;": '\U000000AF',
+ "sub;": '\U00002282',
+ "subE;": '\U00002AC5',
+ "subdot;": '\U00002ABD',
+ "sube;": '\U00002286',
+ "subedot;": '\U00002AC3',
+ "submult;": '\U00002AC1',
+ "subnE;": '\U00002ACB',
+ "subne;": '\U0000228A',
+ "subplus;": '\U00002ABF',
+ "subrarr;": '\U00002979',
+ "subset;": '\U00002282',
+ "subseteq;": '\U00002286',
+ "subseteqq;": '\U00002AC5',
+ "subsetneq;": '\U0000228A',
+ "subsetneqq;": '\U00002ACB',
+ "subsim;": '\U00002AC7',
+ "subsub;": '\U00002AD5',
+ "subsup;": '\U00002AD3',
+ "succ;": '\U0000227B',
+ "succapprox;": '\U00002AB8',
+ "succcurlyeq;": '\U0000227D',
+ "succeq;": '\U00002AB0',
+ "succnapprox;": '\U00002ABA',
+ "succneqq;": '\U00002AB6',
+ "succnsim;": '\U000022E9',
+ "succsim;": '\U0000227F',
+ "sum;": '\U00002211',
+ "sung;": '\U0000266A',
+ "sup;": '\U00002283',
+ "sup1;": '\U000000B9',
+ "sup2;": '\U000000B2',
+ "sup3;": '\U000000B3',
+ "supE;": '\U00002AC6',
+ "supdot;": '\U00002ABE',
+ "supdsub;": '\U00002AD8',
+ "supe;": '\U00002287',
+ "supedot;": '\U00002AC4',
+ "suphsol;": '\U000027C9',
+ "suphsub;": '\U00002AD7',
+ "suplarr;": '\U0000297B',
+ "supmult;": '\U00002AC2',
+ "supnE;": '\U00002ACC',
+ "supne;": '\U0000228B',
+ "supplus;": '\U00002AC0',
+ "supset;": '\U00002283',
+ "supseteq;": '\U00002287',
+ "supseteqq;": '\U00002AC6',
+ "supsetneq;": '\U0000228B',
+ "supsetneqq;": '\U00002ACC',
+ "supsim;": '\U00002AC8',
+ "supsub;": '\U00002AD4',
+ "supsup;": '\U00002AD6',
+ "swArr;": '\U000021D9',
+ "swarhk;": '\U00002926',
+ "swarr;": '\U00002199',
+ "swarrow;": '\U00002199',
+ "swnwar;": '\U0000292A',
+ "szlig;": '\U000000DF',
+ "target;": '\U00002316',
+ "tau;": '\U000003C4',
+ "tbrk;": '\U000023B4',
+ "tcaron;": '\U00000165',
+ "tcedil;": '\U00000163',
+ "tcy;": '\U00000442',
+ "tdot;": '\U000020DB',
+ "telrec;": '\U00002315',
+ "tfr;": '\U0001D531',
+ "there4;": '\U00002234',
+ "therefore;": '\U00002234',
+ "theta;": '\U000003B8',
+ "thetasym;": '\U000003D1',
+ "thetav;": '\U000003D1',
+ "thickapprox;": '\U00002248',
+ "thicksim;": '\U0000223C',
+ "thinsp;": '\U00002009',
+ "thkap;": '\U00002248',
+ "thksim;": '\U0000223C',
+ "thorn;": '\U000000FE',
+ "tilde;": '\U000002DC',
+ "times;": '\U000000D7',
+ "timesb;": '\U000022A0',
+ "timesbar;": '\U00002A31',
+ "timesd;": '\U00002A30',
+ "tint;": '\U0000222D',
+ "toea;": '\U00002928',
+ "top;": '\U000022A4',
+ "topbot;": '\U00002336',
+ "topcir;": '\U00002AF1',
+ "topf;": '\U0001D565',
+ "topfork;": '\U00002ADA',
+ "tosa;": '\U00002929',
+ "tprime;": '\U00002034',
+ "trade;": '\U00002122',
+ "triangle;": '\U000025B5',
+ "triangledown;": '\U000025BF',
+ "triangleleft;": '\U000025C3',
+ "trianglelefteq;": '\U000022B4',
+ "triangleq;": '\U0000225C',
+ "triangleright;": '\U000025B9',
+ "trianglerighteq;": '\U000022B5',
+ "tridot;": '\U000025EC',
+ "trie;": '\U0000225C',
+ "triminus;": '\U00002A3A',
+ "triplus;": '\U00002A39',
+ "trisb;": '\U000029CD',
+ "tritime;": '\U00002A3B',
+ "trpezium;": '\U000023E2',
+ "tscr;": '\U0001D4C9',
+ "tscy;": '\U00000446',
+ "tshcy;": '\U0000045B',
+ "tstrok;": '\U00000167',
+ "twixt;": '\U0000226C',
+ "twoheadleftarrow;": '\U0000219E',
+ "twoheadrightarrow;": '\U000021A0',
+ "uArr;": '\U000021D1',
+ "uHar;": '\U00002963',
+ "uacute;": '\U000000FA',
+ "uarr;": '\U00002191',
+ "ubrcy;": '\U0000045E',
+ "ubreve;": '\U0000016D',
+ "ucirc;": '\U000000FB',
+ "ucy;": '\U00000443',
+ "udarr;": '\U000021C5',
+ "udblac;": '\U00000171',
+ "udhar;": '\U0000296E',
+ "ufisht;": '\U0000297E',
+ "ufr;": '\U0001D532',
+ "ugrave;": '\U000000F9',
+ "uharl;": '\U000021BF',
+ "uharr;": '\U000021BE',
+ "uhblk;": '\U00002580',
+ "ulcorn;": '\U0000231C',
+ "ulcorner;": '\U0000231C',
+ "ulcrop;": '\U0000230F',
+ "ultri;": '\U000025F8',
+ "umacr;": '\U0000016B',
+ "uml;": '\U000000A8',
+ "uogon;": '\U00000173',
+ "uopf;": '\U0001D566',
+ "uparrow;": '\U00002191',
+ "updownarrow;": '\U00002195',
+ "upharpoonleft;": '\U000021BF',
+ "upharpoonright;": '\U000021BE',
+ "uplus;": '\U0000228E',
+ "upsi;": '\U000003C5',
+ "upsih;": '\U000003D2',
+ "upsilon;": '\U000003C5',
+ "upuparrows;": '\U000021C8',
+ "urcorn;": '\U0000231D',
+ "urcorner;": '\U0000231D',
+ "urcrop;": '\U0000230E',
+ "uring;": '\U0000016F',
+ "urtri;": '\U000025F9',
+ "uscr;": '\U0001D4CA',
+ "utdot;": '\U000022F0',
+ "utilde;": '\U00000169',
+ "utri;": '\U000025B5',
+ "utrif;": '\U000025B4',
+ "uuarr;": '\U000021C8',
+ "uuml;": '\U000000FC',
+ "uwangle;": '\U000029A7',
+ "vArr;": '\U000021D5',
+ "vBar;": '\U00002AE8',
+ "vBarv;": '\U00002AE9',
+ "vDash;": '\U000022A8',
+ "vangrt;": '\U0000299C',
+ "varepsilon;": '\U000003F5',
+ "varkappa;": '\U000003F0',
+ "varnothing;": '\U00002205',
+ "varphi;": '\U000003D5',
+ "varpi;": '\U000003D6',
+ "varpropto;": '\U0000221D',
+ "varr;": '\U00002195',
+ "varrho;": '\U000003F1',
+ "varsigma;": '\U000003C2',
+ "vartheta;": '\U000003D1',
+ "vartriangleleft;": '\U000022B2',
+ "vartriangleright;": '\U000022B3',
+ "vcy;": '\U00000432',
+ "vdash;": '\U000022A2',
+ "vee;": '\U00002228',
+ "veebar;": '\U000022BB',
+ "veeeq;": '\U0000225A',
+ "vellip;": '\U000022EE',
+ "verbar;": '\U0000007C',
+ "vert;": '\U0000007C',
+ "vfr;": '\U0001D533',
+ "vltri;": '\U000022B2',
+ "vopf;": '\U0001D567',
+ "vprop;": '\U0000221D',
+ "vrtri;": '\U000022B3',
+ "vscr;": '\U0001D4CB',
+ "vzigzag;": '\U0000299A',
+ "wcirc;": '\U00000175',
+ "wedbar;": '\U00002A5F',
+ "wedge;": '\U00002227',
+ "wedgeq;": '\U00002259',
+ "weierp;": '\U00002118',
+ "wfr;": '\U0001D534',
+ "wopf;": '\U0001D568',
+ "wp;": '\U00002118',
+ "wr;": '\U00002240',
+ "wreath;": '\U00002240',
+ "wscr;": '\U0001D4CC',
+ "xcap;": '\U000022C2',
+ "xcirc;": '\U000025EF',
+ "xcup;": '\U000022C3',
+ "xdtri;": '\U000025BD',
+ "xfr;": '\U0001D535',
+ "xhArr;": '\U000027FA',
+ "xharr;": '\U000027F7',
+ "xi;": '\U000003BE',
+ "xlArr;": '\U000027F8',
+ "xlarr;": '\U000027F5',
+ "xmap;": '\U000027FC',
+ "xnis;": '\U000022FB',
+ "xodot;": '\U00002A00',
+ "xopf;": '\U0001D569',
+ "xoplus;": '\U00002A01',
+ "xotime;": '\U00002A02',
+ "xrArr;": '\U000027F9',
+ "xrarr;": '\U000027F6',
+ "xscr;": '\U0001D4CD',
+ "xsqcup;": '\U00002A06',
+ "xuplus;": '\U00002A04',
+ "xutri;": '\U000025B3',
+ "xvee;": '\U000022C1',
+ "xwedge;": '\U000022C0',
+ "yacute;": '\U000000FD',
+ "yacy;": '\U0000044F',
+ "ycirc;": '\U00000177',
+ "ycy;": '\U0000044B',
+ "yen;": '\U000000A5',
+ "yfr;": '\U0001D536',
+ "yicy;": '\U00000457',
+ "yopf;": '\U0001D56A',
+ "yscr;": '\U0001D4CE',
+ "yucy;": '\U0000044E',
+ "yuml;": '\U000000FF',
+ "zacute;": '\U0000017A',
+ "zcaron;": '\U0000017E',
+ "zcy;": '\U00000437',
+ "zdot;": '\U0000017C',
+ "zeetrf;": '\U00002128',
+ "zeta;": '\U000003B6',
+ "zfr;": '\U0001D537',
+ "zhcy;": '\U00000436',
+ "zigrarr;": '\U000021DD',
+ "zopf;": '\U0001D56B',
+ "zscr;": '\U0001D4CF',
+ "zwj;": '\U0000200D',
+ "zwnj;": '\U0000200C',
+ "AElig": '\U000000C6',
+ "AMP": '\U00000026',
+ "Aacute": '\U000000C1',
+ "Acirc": '\U000000C2',
+ "Agrave": '\U000000C0',
+ "Aring": '\U000000C5',
+ "Atilde": '\U000000C3',
+ "Auml": '\U000000C4',
+ "COPY": '\U000000A9',
+ "Ccedil": '\U000000C7',
+ "ETH": '\U000000D0',
+ "Eacute": '\U000000C9',
+ "Ecirc": '\U000000CA',
+ "Egrave": '\U000000C8',
+ "Euml": '\U000000CB',
+ "GT": '\U0000003E',
+ "Iacute": '\U000000CD',
+ "Icirc": '\U000000CE',
+ "Igrave": '\U000000CC',
+ "Iuml": '\U000000CF',
+ "LT": '\U0000003C',
+ "Ntilde": '\U000000D1',
+ "Oacute": '\U000000D3',
+ "Ocirc": '\U000000D4',
+ "Ograve": '\U000000D2',
+ "Oslash": '\U000000D8',
+ "Otilde": '\U000000D5',
+ "Ouml": '\U000000D6',
+ "QUOT": '\U00000022',
+ "REG": '\U000000AE',
+ "THORN": '\U000000DE',
+ "Uacute": '\U000000DA',
+ "Ucirc": '\U000000DB',
+ "Ugrave": '\U000000D9',
+ "Uuml": '\U000000DC',
+ "Yacute": '\U000000DD',
+ "aacute": '\U000000E1',
+ "acirc": '\U000000E2',
+ "acute": '\U000000B4',
+ "aelig": '\U000000E6',
+ "agrave": '\U000000E0',
+ "amp": '\U00000026',
+ "aring": '\U000000E5',
+ "atilde": '\U000000E3',
+ "auml": '\U000000E4',
+ "brvbar": '\U000000A6',
+ "ccedil": '\U000000E7',
+ "cedil": '\U000000B8',
+ "cent": '\U000000A2',
+ "copy": '\U000000A9',
+ "curren": '\U000000A4',
+ "deg": '\U000000B0',
+ "divide": '\U000000F7',
+ "eacute": '\U000000E9',
+ "ecirc": '\U000000EA',
+ "egrave": '\U000000E8',
+ "eth": '\U000000F0',
+ "euml": '\U000000EB',
+ "frac12": '\U000000BD',
+ "frac14": '\U000000BC',
+ "frac34": '\U000000BE',
+ "gt": '\U0000003E',
+ "iacute": '\U000000ED',
+ "icirc": '\U000000EE',
+ "iexcl": '\U000000A1',
+ "igrave": '\U000000EC',
+ "iquest": '\U000000BF',
+ "iuml": '\U000000EF',
+ "laquo": '\U000000AB',
+ "lt": '\U0000003C',
+ "macr": '\U000000AF',
+ "micro": '\U000000B5',
+ "middot": '\U000000B7',
+ "nbsp": '\U000000A0',
+ "not": '\U000000AC',
+ "ntilde": '\U000000F1',
+ "oacute": '\U000000F3',
+ "ocirc": '\U000000F4',
+ "ograve": '\U000000F2',
+ "ordf": '\U000000AA',
+ "ordm": '\U000000BA',
+ "oslash": '\U000000F8',
+ "otilde": '\U000000F5',
+ "ouml": '\U000000F6',
+ "para": '\U000000B6',
+ "plusmn": '\U000000B1',
+ "pound": '\U000000A3',
+ "quot": '\U00000022',
+ "raquo": '\U000000BB',
+ "reg": '\U000000AE',
+ "sect": '\U000000A7',
+ "shy": '\U000000AD',
+ "sup1": '\U000000B9',
+ "sup2": '\U000000B2',
+ "sup3": '\U000000B3',
+ "szlig": '\U000000DF',
+ "thorn": '\U000000FE',
+ "times": '\U000000D7',
+ "uacute": '\U000000FA',
+ "ucirc": '\U000000FB',
+ "ugrave": '\U000000F9',
+ "uml": '\U000000A8',
+ "uuml": '\U000000FC',
+ "yacute": '\U000000FD',
+ "yen": '\U000000A5',
+ "yuml": '\U000000FF',
+}
+
+// HTML entities that are two unicode codepoints.
+var entity2 = map[string][2]rune{
+ // TODO(nigeltao): Handle replacements that are wider than their names.
+ // "nLt;": {'\u226A', '\u20D2'},
+ // "nGt;": {'\u226B', '\u20D2'},
+ "NotEqualTilde;": {'\u2242', '\u0338'},
+ "NotGreaterFullEqual;": {'\u2267', '\u0338'},
+ "NotGreaterGreater;": {'\u226B', '\u0338'},
+ "NotGreaterSlantEqual;": {'\u2A7E', '\u0338'},
+ "NotHumpDownHump;": {'\u224E', '\u0338'},
+ "NotHumpEqual;": {'\u224F', '\u0338'},
+ "NotLeftTriangleBar;": {'\u29CF', '\u0338'},
+ "NotLessLess;": {'\u226A', '\u0338'},
+ "NotLessSlantEqual;": {'\u2A7D', '\u0338'},
+ "NotNestedGreaterGreater;": {'\u2AA2', '\u0338'},
+ "NotNestedLessLess;": {'\u2AA1', '\u0338'},
+ "NotPrecedesEqual;": {'\u2AAF', '\u0338'},
+ "NotRightTriangleBar;": {'\u29D0', '\u0338'},
+ "NotSquareSubset;": {'\u228F', '\u0338'},
+ "NotSquareSuperset;": {'\u2290', '\u0338'},
+ "NotSubset;": {'\u2282', '\u20D2'},
+ "NotSucceedsEqual;": {'\u2AB0', '\u0338'},
+ "NotSucceedsTilde;": {'\u227F', '\u0338'},
+ "NotSuperset;": {'\u2283', '\u20D2'},
+ "ThickSpace;": {'\u205F', '\u200A'},
+ "acE;": {'\u223E', '\u0333'},
+ "bne;": {'\u003D', '\u20E5'},
+ "bnequiv;": {'\u2261', '\u20E5'},
+ "caps;": {'\u2229', '\uFE00'},
+ "cups;": {'\u222A', '\uFE00'},
+ "fjlig;": {'\u0066', '\u006A'},
+ "gesl;": {'\u22DB', '\uFE00'},
+ "gvertneqq;": {'\u2269', '\uFE00'},
+ "gvnE;": {'\u2269', '\uFE00'},
+ "lates;": {'\u2AAD', '\uFE00'},
+ "lesg;": {'\u22DA', '\uFE00'},
+ "lvertneqq;": {'\u2268', '\uFE00'},
+ "lvnE;": {'\u2268', '\uFE00'},
+ "nGg;": {'\u22D9', '\u0338'},
+ "nGtv;": {'\u226B', '\u0338'},
+ "nLl;": {'\u22D8', '\u0338'},
+ "nLtv;": {'\u226A', '\u0338'},
+ "nang;": {'\u2220', '\u20D2'},
+ "napE;": {'\u2A70', '\u0338'},
+ "napid;": {'\u224B', '\u0338'},
+ "nbump;": {'\u224E', '\u0338'},
+ "nbumpe;": {'\u224F', '\u0338'},
+ "ncongdot;": {'\u2A6D', '\u0338'},
+ "nedot;": {'\u2250', '\u0338'},
+ "nesim;": {'\u2242', '\u0338'},
+ "ngE;": {'\u2267', '\u0338'},
+ "ngeqq;": {'\u2267', '\u0338'},
+ "ngeqslant;": {'\u2A7E', '\u0338'},
+ "nges;": {'\u2A7E', '\u0338'},
+ "nlE;": {'\u2266', '\u0338'},
+ "nleqq;": {'\u2266', '\u0338'},
+ "nleqslant;": {'\u2A7D', '\u0338'},
+ "nles;": {'\u2A7D', '\u0338'},
+ "notinE;": {'\u22F9', '\u0338'},
+ "notindot;": {'\u22F5', '\u0338'},
+ "nparsl;": {'\u2AFD', '\u20E5'},
+ "npart;": {'\u2202', '\u0338'},
+ "npre;": {'\u2AAF', '\u0338'},
+ "npreceq;": {'\u2AAF', '\u0338'},
+ "nrarrc;": {'\u2933', '\u0338'},
+ "nrarrw;": {'\u219D', '\u0338'},
+ "nsce;": {'\u2AB0', '\u0338'},
+ "nsubE;": {'\u2AC5', '\u0338'},
+ "nsubset;": {'\u2282', '\u20D2'},
+ "nsubseteqq;": {'\u2AC5', '\u0338'},
+ "nsucceq;": {'\u2AB0', '\u0338'},
+ "nsupE;": {'\u2AC6', '\u0338'},
+ "nsupset;": {'\u2283', '\u20D2'},
+ "nsupseteqq;": {'\u2AC6', '\u0338'},
+ "nvap;": {'\u224D', '\u20D2'},
+ "nvge;": {'\u2265', '\u20D2'},
+ "nvgt;": {'\u003E', '\u20D2'},
+ "nvle;": {'\u2264', '\u20D2'},
+ "nvlt;": {'\u003C', '\u20D2'},
+ "nvltrie;": {'\u22B4', '\u20D2'},
+ "nvrtrie;": {'\u22B5', '\u20D2'},
+ "nvsim;": {'\u223C', '\u20D2'},
+ "race;": {'\u223D', '\u0331'},
+ "smtes;": {'\u2AAC', '\uFE00'},
+ "sqcaps;": {'\u2293', '\uFE00'},
+ "sqcups;": {'\u2294', '\uFE00'},
+ "varsubsetneq;": {'\u228A', '\uFE00'},
+ "varsubsetneqq;": {'\u2ACB', '\uFE00'},
+ "varsupsetneq;": {'\u228B', '\uFE00'},
+ "varsupsetneqq;": {'\u2ACC', '\uFE00'},
+ "vnsub;": {'\u2282', '\u20D2'},
+ "vnsup;": {'\u2283', '\u20D2'},
+ "vsubnE;": {'\u2ACB', '\uFE00'},
+ "vsubne;": {'\u228A', '\uFE00'},
+ "vsupnE;": {'\u2ACC', '\uFE00'},
+ "vsupne;": {'\u228B', '\uFE00'},
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/entity_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/entity_test.go
new file mode 100644
index 000000000..b53f866fa
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/entity_test.go
@@ -0,0 +1,29 @@
+// Copyright 2010 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 html
+
+import (
+ "testing"
+ "unicode/utf8"
+)
+
+func TestEntityLength(t *testing.T) {
+ // We verify that the length of UTF-8 encoding of each value is <= 1 + len(key).
+ // The +1 comes from the leading "&". This property implies that the length of
+ // unescaped text is <= the length of escaped text.
+ for k, v := range entity {
+ if 1+len(k) < utf8.RuneLen(v) {
+ t.Error("escaped entity &" + k + " is shorter than its UTF-8 encoding " + string(v))
+ }
+ if len(k) > longestEntityWithoutSemicolon && k[len(k)-1] != ';' {
+ t.Errorf("entity name %s is %d characters, but longestEntityWithoutSemicolon=%d", k, len(k), longestEntityWithoutSemicolon)
+ }
+ }
+ for k, v := range entity2 {
+ if 1+len(k) < utf8.RuneLen(v[0])+utf8.RuneLen(v[1]) {
+ t.Error("escaped entity &" + k + " is shorter than its UTF-8 encoding " + string(v[0]) + string(v[1]))
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/escape.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/escape.go
new file mode 100644
index 000000000..d85613962
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/escape.go
@@ -0,0 +1,258 @@
+// Copyright 2010 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 html
+
+import (
+ "bytes"
+ "strings"
+ "unicode/utf8"
+)
+
+// These replacements permit compatibility with old numeric entities that
+// assumed Windows-1252 encoding.
+// https://html.spec.whatwg.org/multipage/syntax.html#consume-a-character-reference
+var replacementTable = [...]rune{
+ '\u20AC', // First entry is what 0x80 should be replaced with.
+ '\u0081',
+ '\u201A',
+ '\u0192',
+ '\u201E',
+ '\u2026',
+ '\u2020',
+ '\u2021',
+ '\u02C6',
+ '\u2030',
+ '\u0160',
+ '\u2039',
+ '\u0152',
+ '\u008D',
+ '\u017D',
+ '\u008F',
+ '\u0090',
+ '\u2018',
+ '\u2019',
+ '\u201C',
+ '\u201D',
+ '\u2022',
+ '\u2013',
+ '\u2014',
+ '\u02DC',
+ '\u2122',
+ '\u0161',
+ '\u203A',
+ '\u0153',
+ '\u009D',
+ '\u017E',
+ '\u0178', // Last entry is 0x9F.
+ // 0x00->'\uFFFD' is handled programmatically.
+ // 0x0D->'\u000D' is a no-op.
+}
+
+// unescapeEntity reads an entity like "&lt;" from b[src:] and writes the
+// corresponding "<" to b[dst:], returning the incremented dst and src cursors.
+// Precondition: b[src] == '&' && dst <= src.
+// attribute should be true if parsing an attribute value.
+func unescapeEntity(b []byte, dst, src int, attribute bool) (dst1, src1 int) {
+ // https://html.spec.whatwg.org/multipage/syntax.html#consume-a-character-reference
+
+ // i starts at 1 because we already know that s[0] == '&'.
+ i, s := 1, b[src:]
+
+ if len(s) <= 1 {
+ b[dst] = b[src]
+ return dst + 1, src + 1
+ }
+
+ if s[i] == '#' {
+ if len(s) <= 3 { // We need to have at least "&#.".
+ b[dst] = b[src]
+ return dst + 1, src + 1
+ }
+ i++
+ c := s[i]
+ hex := false
+ if c == 'x' || c == 'X' {
+ hex = true
+ i++
+ }
+
+ x := '\x00'
+ for i < len(s) {
+ c = s[i]
+ i++
+ if hex {
+ if '0' <= c && c <= '9' {
+ x = 16*x + rune(c) - '0'
+ continue
+ } else if 'a' <= c && c <= 'f' {
+ x = 16*x + rune(c) - 'a' + 10
+ continue
+ } else if 'A' <= c && c <= 'F' {
+ x = 16*x + rune(c) - 'A' + 10
+ continue
+ }
+ } else if '0' <= c && c <= '9' {
+ x = 10*x + rune(c) - '0'
+ continue
+ }
+ if c != ';' {
+ i--
+ }
+ break
+ }
+
+ if i <= 3 { // No characters matched.
+ b[dst] = b[src]
+ return dst + 1, src + 1
+ }
+
+ if 0x80 <= x && x <= 0x9F {
+ // Replace characters from Windows-1252 with UTF-8 equivalents.
+ x = replacementTable[x-0x80]
+ } else if x == 0 || (0xD800 <= x && x <= 0xDFFF) || x > 0x10FFFF {
+ // Replace invalid characters with the replacement character.
+ x = '\uFFFD'
+ }
+
+ return dst + utf8.EncodeRune(b[dst:], x), src + i
+ }
+
+ // Consume the maximum number of characters possible, with the
+ // consumed characters matching one of the named references.
+
+ for i < len(s) {
+ c := s[i]
+ i++
+ // Lower-cased characters are more common in entities, so we check for them first.
+ if 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || '0' <= c && c <= '9' {
+ continue
+ }
+ if c != ';' {
+ i--
+ }
+ break
+ }
+
+ entityName := string(s[1:i])
+ if entityName == "" {
+ // No-op.
+ } else if attribute && entityName[len(entityName)-1] != ';' && len(s) > i && s[i] == '=' {
+ // No-op.
+ } else if x := entity[entityName]; x != 0 {
+ return dst + utf8.EncodeRune(b[dst:], x), src + i
+ } else if x := entity2[entityName]; x[0] != 0 {
+ dst1 := dst + utf8.EncodeRune(b[dst:], x[0])
+ return dst1 + utf8.EncodeRune(b[dst1:], x[1]), src + i
+ } else if !attribute {
+ maxLen := len(entityName) - 1
+ if maxLen > longestEntityWithoutSemicolon {
+ maxLen = longestEntityWithoutSemicolon
+ }
+ for j := maxLen; j > 1; j-- {
+ if x := entity[entityName[:j]]; x != 0 {
+ return dst + utf8.EncodeRune(b[dst:], x), src + j + 1
+ }
+ }
+ }
+
+ dst1, src1 = dst+i, src+i
+ copy(b[dst:dst1], b[src:src1])
+ return dst1, src1
+}
+
+// unescape unescapes b's entities in-place, so that "a&lt;b" becomes "a<b".
+// attribute should be true if parsing an attribute value.
+func unescape(b []byte, attribute bool) []byte {
+ for i, c := range b {
+ if c == '&' {
+ dst, src := unescapeEntity(b, i, i, attribute)
+ for src < len(b) {
+ c := b[src]
+ if c == '&' {
+ dst, src = unescapeEntity(b, dst, src, attribute)
+ } else {
+ b[dst] = c
+ dst, src = dst+1, src+1
+ }
+ }
+ return b[0:dst]
+ }
+ }
+ return b
+}
+
+// lower lower-cases the A-Z bytes in b in-place, so that "aBc" becomes "abc".
+func lower(b []byte) []byte {
+ for i, c := range b {
+ if 'A' <= c && c <= 'Z' {
+ b[i] = c + 'a' - 'A'
+ }
+ }
+ return b
+}
+
+const escapedChars = "&'<>\"\r"
+
+func escape(w writer, s string) error {
+ i := strings.IndexAny(s, escapedChars)
+ for i != -1 {
+ if _, err := w.WriteString(s[:i]); err != nil {
+ return err
+ }
+ var esc string
+ switch s[i] {
+ case '&':
+ esc = "&amp;"
+ case '\'':
+ // "&#39;" is shorter than "&apos;" and apos was not in HTML until HTML5.
+ esc = "&#39;"
+ case '<':
+ esc = "&lt;"
+ case '>':
+ esc = "&gt;"
+ case '"':
+ // "&#34;" is shorter than "&quot;".
+ esc = "&#34;"
+ case '\r':
+ esc = "&#13;"
+ default:
+ panic("unrecognized escape character")
+ }
+ s = s[i+1:]
+ if _, err := w.WriteString(esc); err != nil {
+ return err
+ }
+ i = strings.IndexAny(s, escapedChars)
+ }
+ _, err := w.WriteString(s)
+ return err
+}
+
+// EscapeString escapes special characters like "<" to become "&lt;". It
+// escapes only five such characters: <, >, &, ' and ".
+// UnescapeString(EscapeString(s)) == s always holds, but the converse isn't
+// always true.
+func EscapeString(s string) string {
+ if strings.IndexAny(s, escapedChars) == -1 {
+ return s
+ }
+ var buf bytes.Buffer
+ escape(&buf, s)
+ return buf.String()
+}
+
+// UnescapeString unescapes entities like "&lt;" to become "<". It unescapes a
+// larger range of entities than EscapeString escapes. For example, "&aacute;"
+// unescapes to "á", as does "&#225;" and "&xE1;".
+// UnescapeString(EscapeString(s)) == s always holds, but the converse isn't
+// always true.
+func UnescapeString(s string) string {
+ for _, c := range s {
+ if c == '&' {
+ return string(unescape([]byte(s), false))
+ }
+ }
+ return s
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/escape_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/escape_test.go
new file mode 100644
index 000000000..b405d4b4a
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/escape_test.go
@@ -0,0 +1,97 @@
+// Copyright 2013 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 html
+
+import "testing"
+
+type unescapeTest struct {
+ // A short description of the test case.
+ desc string
+ // The HTML text.
+ html string
+ // The unescaped text.
+ unescaped string
+}
+
+var unescapeTests = []unescapeTest{
+ // Handle no entities.
+ {
+ "copy",
+ "A\ttext\nstring",
+ "A\ttext\nstring",
+ },
+ // Handle simple named entities.
+ {
+ "simple",
+ "&amp; &gt; &lt;",
+ "& > <",
+ },
+ // Handle hitting the end of the string.
+ {
+ "stringEnd",
+ "&amp &amp",
+ "& &",
+ },
+ // Handle entities with two codepoints.
+ {
+ "multiCodepoint",
+ "text &gesl; blah",
+ "text \u22db\ufe00 blah",
+ },
+ // Handle decimal numeric entities.
+ {
+ "decimalEntity",
+ "Delta = &#916; ",
+ "Delta = Δ ",
+ },
+ // Handle hexadecimal numeric entities.
+ {
+ "hexadecimalEntity",
+ "Lambda = &#x3bb; = &#X3Bb ",
+ "Lambda = λ = λ ",
+ },
+ // Handle numeric early termination.
+ {
+ "numericEnds",
+ "&# &#x &#128;43 &copy = &#169f = &#xa9",
+ "&# &#x €43 © = ©f = ©",
+ },
+ // Handle numeric ISO-8859-1 entity replacements.
+ {
+ "numericReplacements",
+ "Footnote&#x87;",
+ "Footnote‡",
+ },
+}
+
+func TestUnescape(t *testing.T) {
+ for _, tt := range unescapeTests {
+ unescaped := UnescapeString(tt.html)
+ if unescaped != tt.unescaped {
+ t.Errorf("TestUnescape %s: want %q, got %q", tt.desc, tt.unescaped, unescaped)
+ }
+ }
+}
+
+func TestUnescapeEscape(t *testing.T) {
+ ss := []string{
+ ``,
+ `abc def`,
+ `a & b`,
+ `a&amp;b`,
+ `a &amp b`,
+ `&quot;`,
+ `"`,
+ `"<&>"`,
+ `&quot;&lt;&amp;&gt;&quot;`,
+ `3&5==1 && 0<1, "0&lt;1", a+acute=&aacute;`,
+ `The special characters are: <, >, &, ' and "`,
+ }
+ for _, s := range ss {
+ if got := UnescapeString(EscapeString(s)); got != s {
+ t.Errorf("got %q want %q", got, s)
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/example_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/example_test.go
new file mode 100644
index 000000000..0b06ed773
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/example_test.go
@@ -0,0 +1,40 @@
+// Copyright 2012 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.
+
+// This example demonstrates parsing HTML data and walking the resulting tree.
+package html_test
+
+import (
+ "fmt"
+ "log"
+ "strings"
+
+ "golang.org/x/net/html"
+)
+
+func ExampleParse() {
+ s := `<p>Links:</p><ul><li><a href="foo">Foo</a><li><a href="/bar/baz">BarBaz</a></ul>`
+ doc, err := html.Parse(strings.NewReader(s))
+ if err != nil {
+ log.Fatal(err)
+ }
+ var f func(*html.Node)
+ f = func(n *html.Node) {
+ if n.Type == html.ElementNode && n.Data == "a" {
+ for _, a := range n.Attr {
+ if a.Key == "href" {
+ fmt.Println(a.Val)
+ break
+ }
+ }
+ }
+ for c := n.FirstChild; c != nil; c = c.NextSibling {
+ f(c)
+ }
+ }
+ f(doc)
+ // Output:
+ // foo
+ // /bar/baz
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/foreign.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/foreign.go
new file mode 100644
index 000000000..d3b384409
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/foreign.go
@@ -0,0 +1,226 @@
+// Copyright 2011 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 html
+
+import (
+ "strings"
+)
+
+func adjustAttributeNames(aa []Attribute, nameMap map[string]string) {
+ for i := range aa {
+ if newName, ok := nameMap[aa[i].Key]; ok {
+ aa[i].Key = newName
+ }
+ }
+}
+
+func adjustForeignAttributes(aa []Attribute) {
+ for i, a := range aa {
+ if a.Key == "" || a.Key[0] != 'x' {
+ continue
+ }
+ switch a.Key {
+ case "xlink:actuate", "xlink:arcrole", "xlink:href", "xlink:role", "xlink:show",
+ "xlink:title", "xlink:type", "xml:base", "xml:lang", "xml:space", "xmlns:xlink":
+ j := strings.Index(a.Key, ":")
+ aa[i].Namespace = a.Key[:j]
+ aa[i].Key = a.Key[j+1:]
+ }
+ }
+}
+
+func htmlIntegrationPoint(n *Node) bool {
+ if n.Type != ElementNode {
+ return false
+ }
+ switch n.Namespace {
+ case "math":
+ if n.Data == "annotation-xml" {
+ for _, a := range n.Attr {
+ if a.Key == "encoding" {
+ val := strings.ToLower(a.Val)
+ if val == "text/html" || val == "application/xhtml+xml" {
+ return true
+ }
+ }
+ }
+ }
+ case "svg":
+ switch n.Data {
+ case "desc", "foreignObject", "title":
+ return true
+ }
+ }
+ return false
+}
+
+func mathMLTextIntegrationPoint(n *Node) bool {
+ if n.Namespace != "math" {
+ return false
+ }
+ switch n.Data {
+ case "mi", "mo", "mn", "ms", "mtext":
+ return true
+ }
+ return false
+}
+
+// Section 12.2.5.5.
+var breakout = map[string]bool{
+ "b": true,
+ "big": true,
+ "blockquote": true,
+ "body": true,
+ "br": true,
+ "center": true,
+ "code": true,
+ "dd": true,
+ "div": true,
+ "dl": true,
+ "dt": true,
+ "em": true,
+ "embed": true,
+ "h1": true,
+ "h2": true,
+ "h3": true,
+ "h4": true,
+ "h5": true,
+ "h6": true,
+ "head": true,
+ "hr": true,
+ "i": true,
+ "img": true,
+ "li": true,
+ "listing": true,
+ "menu": true,
+ "meta": true,
+ "nobr": true,
+ "ol": true,
+ "p": true,
+ "pre": true,
+ "ruby": true,
+ "s": true,
+ "small": true,
+ "span": true,
+ "strong": true,
+ "strike": true,
+ "sub": true,
+ "sup": true,
+ "table": true,
+ "tt": true,
+ "u": true,
+ "ul": true,
+ "var": true,
+}
+
+// Section 12.2.5.5.
+var svgTagNameAdjustments = map[string]string{
+ "altglyph": "altGlyph",
+ "altglyphdef": "altGlyphDef",
+ "altglyphitem": "altGlyphItem",
+ "animatecolor": "animateColor",
+ "animatemotion": "animateMotion",
+ "animatetransform": "animateTransform",
+ "clippath": "clipPath",
+ "feblend": "feBlend",
+ "fecolormatrix": "feColorMatrix",
+ "fecomponenttransfer": "feComponentTransfer",
+ "fecomposite": "feComposite",
+ "feconvolvematrix": "feConvolveMatrix",
+ "fediffuselighting": "feDiffuseLighting",
+ "fedisplacementmap": "feDisplacementMap",
+ "fedistantlight": "feDistantLight",
+ "feflood": "feFlood",
+ "fefunca": "feFuncA",
+ "fefuncb": "feFuncB",
+ "fefuncg": "feFuncG",
+ "fefuncr": "feFuncR",
+ "fegaussianblur": "feGaussianBlur",
+ "feimage": "feImage",
+ "femerge": "feMerge",
+ "femergenode": "feMergeNode",
+ "femorphology": "feMorphology",
+ "feoffset": "feOffset",
+ "fepointlight": "fePointLight",
+ "fespecularlighting": "feSpecularLighting",
+ "fespotlight": "feSpotLight",
+ "fetile": "feTile",
+ "feturbulence": "feTurbulence",
+ "foreignobject": "foreignObject",
+ "glyphref": "glyphRef",
+ "lineargradient": "linearGradient",
+ "radialgradient": "radialGradient",
+ "textpath": "textPath",
+}
+
+// Section 12.2.5.1
+var mathMLAttributeAdjustments = map[string]string{
+ "definitionurl": "definitionURL",
+}
+
+var svgAttributeAdjustments = map[string]string{
+ "attributename": "attributeName",
+ "attributetype": "attributeType",
+ "basefrequency": "baseFrequency",
+ "baseprofile": "baseProfile",
+ "calcmode": "calcMode",
+ "clippathunits": "clipPathUnits",
+ "contentscripttype": "contentScriptType",
+ "contentstyletype": "contentStyleType",
+ "diffuseconstant": "diffuseConstant",
+ "edgemode": "edgeMode",
+ "externalresourcesrequired": "externalResourcesRequired",
+ "filterres": "filterRes",
+ "filterunits": "filterUnits",
+ "glyphref": "glyphRef",
+ "gradienttransform": "gradientTransform",
+ "gradientunits": "gradientUnits",
+ "kernelmatrix": "kernelMatrix",
+ "kernelunitlength": "kernelUnitLength",
+ "keypoints": "keyPoints",
+ "keysplines": "keySplines",
+ "keytimes": "keyTimes",
+ "lengthadjust": "lengthAdjust",
+ "limitingconeangle": "limitingConeAngle",
+ "markerheight": "markerHeight",
+ "markerunits": "markerUnits",
+ "markerwidth": "markerWidth",
+ "maskcontentunits": "maskContentUnits",
+ "maskunits": "maskUnits",
+ "numoctaves": "numOctaves",
+ "pathlength": "pathLength",
+ "patterncontentunits": "patternContentUnits",
+ "patterntransform": "patternTransform",
+ "patternunits": "patternUnits",
+ "pointsatx": "pointsAtX",
+ "pointsaty": "pointsAtY",
+ "pointsatz": "pointsAtZ",
+ "preservealpha": "preserveAlpha",
+ "preserveaspectratio": "preserveAspectRatio",
+ "primitiveunits": "primitiveUnits",
+ "refx": "refX",
+ "refy": "refY",
+ "repeatcount": "repeatCount",
+ "repeatdur": "repeatDur",
+ "requiredextensions": "requiredExtensions",
+ "requiredfeatures": "requiredFeatures",
+ "specularconstant": "specularConstant",
+ "specularexponent": "specularExponent",
+ "spreadmethod": "spreadMethod",
+ "startoffset": "startOffset",
+ "stddeviation": "stdDeviation",
+ "stitchtiles": "stitchTiles",
+ "surfacescale": "surfaceScale",
+ "systemlanguage": "systemLanguage",
+ "tablevalues": "tableValues",
+ "targetx": "targetX",
+ "targety": "targetY",
+ "textlength": "textLength",
+ "viewbox": "viewBox",
+ "viewtarget": "viewTarget",
+ "xchannelselector": "xChannelSelector",
+ "ychannelselector": "yChannelSelector",
+ "zoomandpan": "zoomAndPan",
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/node.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/node.go
new file mode 100644
index 000000000..26b657aec
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/node.go
@@ -0,0 +1,193 @@
+// Copyright 2011 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 html
+
+import (
+ "golang.org/x/net/html/atom"
+)
+
+// A NodeType is the type of a Node.
+type NodeType uint32
+
+const (
+ ErrorNode NodeType = iota
+ TextNode
+ DocumentNode
+ ElementNode
+ CommentNode
+ DoctypeNode
+ scopeMarkerNode
+)
+
+// Section 12.2.3.3 says "scope markers are inserted when entering applet
+// elements, buttons, object elements, marquees, table cells, and table
+// captions, and are used to prevent formatting from 'leaking'".
+var scopeMarker = Node{Type: scopeMarkerNode}
+
+// A Node consists of a NodeType and some Data (tag name for element nodes,
+// content for text) and are part of a tree of Nodes. Element nodes may also
+// have a Namespace and contain a slice of Attributes. Data is unescaped, so
+// that it looks like "a<b" rather than "a&lt;b". For element nodes, DataAtom
+// is the atom for Data, or zero if Data is not a known tag name.
+//
+// An empty Namespace implies a "http://www.w3.org/1999/xhtml" namespace.
+// Similarly, "math" is short for "http://www.w3.org/1998/Math/MathML", and
+// "svg" is short for "http://www.w3.org/2000/svg".
+type Node struct {
+ Parent, FirstChild, LastChild, PrevSibling, NextSibling *Node
+
+ Type NodeType
+ DataAtom atom.Atom
+ Data string
+ Namespace string
+ Attr []Attribute
+}
+
+// InsertBefore inserts newChild as a child of n, immediately before oldChild
+// in the sequence of n's children. oldChild may be nil, in which case newChild
+// is appended to the end of n's children.
+//
+// It will panic if newChild already has a parent or siblings.
+func (n *Node) InsertBefore(newChild, oldChild *Node) {
+ if newChild.Parent != nil || newChild.PrevSibling != nil || newChild.NextSibling != nil {
+ panic("html: InsertBefore called for an attached child Node")
+ }
+ var prev, next *Node
+ if oldChild != nil {
+ prev, next = oldChild.PrevSibling, oldChild
+ } else {
+ prev = n.LastChild
+ }
+ if prev != nil {
+ prev.NextSibling = newChild
+ } else {
+ n.FirstChild = newChild
+ }
+ if next != nil {
+ next.PrevSibling = newChild
+ } else {
+ n.LastChild = newChild
+ }
+ newChild.Parent = n
+ newChild.PrevSibling = prev
+ newChild.NextSibling = next
+}
+
+// AppendChild adds a node c as a child of n.
+//
+// It will panic if c already has a parent or siblings.
+func (n *Node) AppendChild(c *Node) {
+ if c.Parent != nil || c.PrevSibling != nil || c.NextSibling != nil {
+ panic("html: AppendChild called for an attached child Node")
+ }
+ last := n.LastChild
+ if last != nil {
+ last.NextSibling = c
+ } else {
+ n.FirstChild = c
+ }
+ n.LastChild = c
+ c.Parent = n
+ c.PrevSibling = last
+}
+
+// RemoveChild removes a node c that is a child of n. Afterwards, c will have
+// no parent and no siblings.
+//
+// It will panic if c's parent is not n.
+func (n *Node) RemoveChild(c *Node) {
+ if c.Parent != n {
+ panic("html: RemoveChild called for a non-child Node")
+ }
+ if n.FirstChild == c {
+ n.FirstChild = c.NextSibling
+ }
+ if c.NextSibling != nil {
+ c.NextSibling.PrevSibling = c.PrevSibling
+ }
+ if n.LastChild == c {
+ n.LastChild = c.PrevSibling
+ }
+ if c.PrevSibling != nil {
+ c.PrevSibling.NextSibling = c.NextSibling
+ }
+ c.Parent = nil
+ c.PrevSibling = nil
+ c.NextSibling = nil
+}
+
+// reparentChildren reparents all of src's child nodes to dst.
+func reparentChildren(dst, src *Node) {
+ for {
+ child := src.FirstChild
+ if child == nil {
+ break
+ }
+ src.RemoveChild(child)
+ dst.AppendChild(child)
+ }
+}
+
+// clone returns a new node with the same type, data and attributes.
+// The clone has no parent, no siblings and no children.
+func (n *Node) clone() *Node {
+ m := &Node{
+ Type: n.Type,
+ DataAtom: n.DataAtom,
+ Data: n.Data,
+ Attr: make([]Attribute, len(n.Attr)),
+ }
+ copy(m.Attr, n.Attr)
+ return m
+}
+
+// nodeStack is a stack of nodes.
+type nodeStack []*Node
+
+// pop pops the stack. It will panic if s is empty.
+func (s *nodeStack) pop() *Node {
+ i := len(*s)
+ n := (*s)[i-1]
+ *s = (*s)[:i-1]
+ return n
+}
+
+// top returns the most recently pushed node, or nil if s is empty.
+func (s *nodeStack) top() *Node {
+ if i := len(*s); i > 0 {
+ return (*s)[i-1]
+ }
+ return nil
+}
+
+// index returns the index of the top-most occurrence of n in the stack, or -1
+// if n is not present.
+func (s *nodeStack) index(n *Node) int {
+ for i := len(*s) - 1; i >= 0; i-- {
+ if (*s)[i] == n {
+ return i
+ }
+ }
+ return -1
+}
+
+// insert inserts a node at the given index.
+func (s *nodeStack) insert(i int, n *Node) {
+ (*s) = append(*s, nil)
+ copy((*s)[i+1:], (*s)[i:])
+ (*s)[i] = n
+}
+
+// remove removes a node from the stack. It is a no-op if n is not present.
+func (s *nodeStack) remove(n *Node) {
+ i := s.index(n)
+ if i == -1 {
+ return
+ }
+ copy((*s)[i:], (*s)[i+1:])
+ j := len(*s) - 1
+ (*s)[j] = nil
+ *s = (*s)[:j]
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/node_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/node_test.go
new file mode 100644
index 000000000..471102f3a
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/node_test.go
@@ -0,0 +1,146 @@
+// Copyright 2010 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 html
+
+import (
+ "fmt"
+)
+
+// checkTreeConsistency checks that a node and its descendants are all
+// consistent in their parent/child/sibling relationships.
+func checkTreeConsistency(n *Node) error {
+ return checkTreeConsistency1(n, 0)
+}
+
+func checkTreeConsistency1(n *Node, depth int) error {
+ if depth == 1e4 {
+ return fmt.Errorf("html: tree looks like it contains a cycle")
+ }
+ if err := checkNodeConsistency(n); err != nil {
+ return err
+ }
+ for c := n.FirstChild; c != nil; c = c.NextSibling {
+ if err := checkTreeConsistency1(c, depth+1); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// checkNodeConsistency checks that a node's parent/child/sibling relationships
+// are consistent.
+func checkNodeConsistency(n *Node) error {
+ if n == nil {
+ return nil
+ }
+
+ nParent := 0
+ for p := n.Parent; p != nil; p = p.Parent {
+ nParent++
+ if nParent == 1e4 {
+ return fmt.Errorf("html: parent list looks like an infinite loop")
+ }
+ }
+
+ nForward := 0
+ for c := n.FirstChild; c != nil; c = c.NextSibling {
+ nForward++
+ if nForward == 1e6 {
+ return fmt.Errorf("html: forward list of children looks like an infinite loop")
+ }
+ if c.Parent != n {
+ return fmt.Errorf("html: inconsistent child/parent relationship")
+ }
+ }
+
+ nBackward := 0
+ for c := n.LastChild; c != nil; c = c.PrevSibling {
+ nBackward++
+ if nBackward == 1e6 {
+ return fmt.Errorf("html: backward list of children looks like an infinite loop")
+ }
+ if c.Parent != n {
+ return fmt.Errorf("html: inconsistent child/parent relationship")
+ }
+ }
+
+ if n.Parent != nil {
+ if n.Parent == n {
+ return fmt.Errorf("html: inconsistent parent relationship")
+ }
+ if n.Parent == n.FirstChild {
+ return fmt.Errorf("html: inconsistent parent/first relationship")
+ }
+ if n.Parent == n.LastChild {
+ return fmt.Errorf("html: inconsistent parent/last relationship")
+ }
+ if n.Parent == n.PrevSibling {
+ return fmt.Errorf("html: inconsistent parent/prev relationship")
+ }
+ if n.Parent == n.NextSibling {
+ return fmt.Errorf("html: inconsistent parent/next relationship")
+ }
+
+ parentHasNAsAChild := false
+ for c := n.Parent.FirstChild; c != nil; c = c.NextSibling {
+ if c == n {
+ parentHasNAsAChild = true
+ break
+ }
+ }
+ if !parentHasNAsAChild {
+ return fmt.Errorf("html: inconsistent parent/child relationship")
+ }
+ }
+
+ if n.PrevSibling != nil && n.PrevSibling.NextSibling != n {
+ return fmt.Errorf("html: inconsistent prev/next relationship")
+ }
+ if n.NextSibling != nil && n.NextSibling.PrevSibling != n {
+ return fmt.Errorf("html: inconsistent next/prev relationship")
+ }
+
+ if (n.FirstChild == nil) != (n.LastChild == nil) {
+ return fmt.Errorf("html: inconsistent first/last relationship")
+ }
+ if n.FirstChild != nil && n.FirstChild == n.LastChild {
+ // We have a sole child.
+ if n.FirstChild.PrevSibling != nil || n.FirstChild.NextSibling != nil {
+ return fmt.Errorf("html: inconsistent sole child's sibling relationship")
+ }
+ }
+
+ seen := map[*Node]bool{}
+
+ var last *Node
+ for c := n.FirstChild; c != nil; c = c.NextSibling {
+ if seen[c] {
+ return fmt.Errorf("html: inconsistent repeated child")
+ }
+ seen[c] = true
+ last = c
+ }
+ if last != n.LastChild {
+ return fmt.Errorf("html: inconsistent last relationship")
+ }
+
+ var first *Node
+ for c := n.LastChild; c != nil; c = c.PrevSibling {
+ if !seen[c] {
+ return fmt.Errorf("html: inconsistent missing child")
+ }
+ delete(seen, c)
+ first = c
+ }
+ if first != n.FirstChild {
+ return fmt.Errorf("html: inconsistent first relationship")
+ }
+
+ if len(seen) != 0 {
+ return fmt.Errorf("html: inconsistent forwards/backwards child list")
+ }
+
+ return nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/parse.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/parse.go
new file mode 100644
index 000000000..be4b2bf5a
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/parse.go
@@ -0,0 +1,2094 @@
+// Copyright 2010 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 html
+
+import (
+ "errors"
+ "fmt"
+ "io"
+ "strings"
+
+ a "golang.org/x/net/html/atom"
+)
+
+// A parser implements the HTML5 parsing algorithm:
+// https://html.spec.whatwg.org/multipage/syntax.html#tree-construction
+type parser struct {
+ // tokenizer provides the tokens for the parser.
+ tokenizer *Tokenizer
+ // tok is the most recently read token.
+ tok Token
+ // Self-closing tags like <hr/> are treated as start tags, except that
+ // hasSelfClosingToken is set while they are being processed.
+ hasSelfClosingToken bool
+ // doc is the document root element.
+ doc *Node
+ // The stack of open elements (section 12.2.3.2) and active formatting
+ // elements (section 12.2.3.3).
+ oe, afe nodeStack
+ // Element pointers (section 12.2.3.4).
+ head, form *Node
+ // Other parsing state flags (section 12.2.3.5).
+ scripting, framesetOK bool
+ // im is the current insertion mode.
+ im insertionMode
+ // originalIM is the insertion mode to go back to after completing a text
+ // or inTableText insertion mode.
+ originalIM insertionMode
+ // fosterParenting is whether new elements should be inserted according to
+ // the foster parenting rules (section 12.2.5.3).
+ fosterParenting bool
+ // quirks is whether the parser is operating in "quirks mode."
+ quirks bool
+ // fragment is whether the parser is parsing an HTML fragment.
+ fragment bool
+ // context is the context element when parsing an HTML fragment
+ // (section 12.4).
+ context *Node
+}
+
+func (p *parser) top() *Node {
+ if n := p.oe.top(); n != nil {
+ return n
+ }
+ return p.doc
+}
+
+// Stop tags for use in popUntil. These come from section 12.2.3.2.
+var (
+ defaultScopeStopTags = map[string][]a.Atom{
+ "": {a.Applet, a.Caption, a.Html, a.Table, a.Td, a.Th, a.Marquee, a.Object, a.Template},
+ "math": {a.AnnotationXml, a.Mi, a.Mn, a.Mo, a.Ms, a.Mtext},
+ "svg": {a.Desc, a.ForeignObject, a.Title},
+ }
+)
+
+type scope int
+
+const (
+ defaultScope scope = iota
+ listItemScope
+ buttonScope
+ tableScope
+ tableRowScope
+ tableBodyScope
+ selectScope
+)
+
+// popUntil pops the stack of open elements at the highest element whose tag
+// is in matchTags, provided there is no higher element in the scope's stop
+// tags (as defined in section 12.2.3.2). It returns whether or not there was
+// such an element. If there was not, popUntil leaves the stack unchanged.
+//
+// For example, the set of stop tags for table scope is: "html", "table". If
+// the stack was:
+// ["html", "body", "font", "table", "b", "i", "u"]
+// then popUntil(tableScope, "font") would return false, but
+// popUntil(tableScope, "i") would return true and the stack would become:
+// ["html", "body", "font", "table", "b"]
+//
+// If an element's tag is in both the stop tags and matchTags, then the stack
+// will be popped and the function returns true (provided, of course, there was
+// no higher element in the stack that was also in the stop tags). For example,
+// popUntil(tableScope, "table") returns true and leaves:
+// ["html", "body", "font"]
+func (p *parser) popUntil(s scope, matchTags ...a.Atom) bool {
+ if i := p.indexOfElementInScope(s, matchTags...); i != -1 {
+ p.oe = p.oe[:i]
+ return true
+ }
+ return false
+}
+
+// indexOfElementInScope returns the index in p.oe of the highest element whose
+// tag is in matchTags that is in scope. If no matching element is in scope, it
+// returns -1.
+func (p *parser) indexOfElementInScope(s scope, matchTags ...a.Atom) int {
+ for i := len(p.oe) - 1; i >= 0; i-- {
+ tagAtom := p.oe[i].DataAtom
+ if p.oe[i].Namespace == "" {
+ for _, t := range matchTags {
+ if t == tagAtom {
+ return i
+ }
+ }
+ switch s {
+ case defaultScope:
+ // No-op.
+ case listItemScope:
+ if tagAtom == a.Ol || tagAtom == a.Ul {
+ return -1
+ }
+ case buttonScope:
+ if tagAtom == a.Button {
+ return -1
+ }
+ case tableScope:
+ if tagAtom == a.Html || tagAtom == a.Table {
+ return -1
+ }
+ case selectScope:
+ if tagAtom != a.Optgroup && tagAtom != a.Option {
+ return -1
+ }
+ default:
+ panic("unreachable")
+ }
+ }
+ switch s {
+ case defaultScope, listItemScope, buttonScope:
+ for _, t := range defaultScopeStopTags[p.oe[i].Namespace] {
+ if t == tagAtom {
+ return -1
+ }
+ }
+ }
+ }
+ return -1
+}
+
+// elementInScope is like popUntil, except that it doesn't modify the stack of
+// open elements.
+func (p *parser) elementInScope(s scope, matchTags ...a.Atom) bool {
+ return p.indexOfElementInScope(s, matchTags...) != -1
+}
+
+// clearStackToContext pops elements off the stack of open elements until a
+// scope-defined element is found.
+func (p *parser) clearStackToContext(s scope) {
+ for i := len(p.oe) - 1; i >= 0; i-- {
+ tagAtom := p.oe[i].DataAtom
+ switch s {
+ case tableScope:
+ if tagAtom == a.Html || tagAtom == a.Table {
+ p.oe = p.oe[:i+1]
+ return
+ }
+ case tableRowScope:
+ if tagAtom == a.Html || tagAtom == a.Tr {
+ p.oe = p.oe[:i+1]
+ return
+ }
+ case tableBodyScope:
+ if tagAtom == a.Html || tagAtom == a.Tbody || tagAtom == a.Tfoot || tagAtom == a.Thead {
+ p.oe = p.oe[:i+1]
+ return
+ }
+ default:
+ panic("unreachable")
+ }
+ }
+}
+
+// generateImpliedEndTags pops nodes off the stack of open elements as long as
+// the top node has a tag name of dd, dt, li, option, optgroup, p, rp, or rt.
+// If exceptions are specified, nodes with that name will not be popped off.
+func (p *parser) generateImpliedEndTags(exceptions ...string) {
+ var i int
+loop:
+ for i = len(p.oe) - 1; i >= 0; i-- {
+ n := p.oe[i]
+ if n.Type == ElementNode {
+ switch n.DataAtom {
+ case a.Dd, a.Dt, a.Li, a.Option, a.Optgroup, a.P, a.Rp, a.Rt:
+ for _, except := range exceptions {
+ if n.Data == except {
+ break loop
+ }
+ }
+ continue
+ }
+ }
+ break
+ }
+
+ p.oe = p.oe[:i+1]
+}
+
+// addChild adds a child node n to the top element, and pushes n onto the stack
+// of open elements if it is an element node.
+func (p *parser) addChild(n *Node) {
+ if p.shouldFosterParent() {
+ p.fosterParent(n)
+ } else {
+ p.top().AppendChild(n)
+ }
+
+ if n.Type == ElementNode {
+ p.oe = append(p.oe, n)
+ }
+}
+
+// shouldFosterParent returns whether the next node to be added should be
+// foster parented.
+func (p *parser) shouldFosterParent() bool {
+ if p.fosterParenting {
+ switch p.top().DataAtom {
+ case a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr:
+ return true
+ }
+ }
+ return false
+}
+
+// fosterParent adds a child node according to the foster parenting rules.
+// Section 12.2.5.3, "foster parenting".
+func (p *parser) fosterParent(n *Node) {
+ var table, parent, prev *Node
+ var i int
+ for i = len(p.oe) - 1; i >= 0; i-- {
+ if p.oe[i].DataAtom == a.Table {
+ table = p.oe[i]
+ break
+ }
+ }
+
+ if table == nil {
+ // The foster parent is the html element.
+ parent = p.oe[0]
+ } else {
+ parent = table.Parent
+ }
+ if parent == nil {
+ parent = p.oe[i-1]
+ }
+
+ if table != nil {
+ prev = table.PrevSibling
+ } else {
+ prev = parent.LastChild
+ }
+ if prev != nil && prev.Type == TextNode && n.Type == TextNode {
+ prev.Data += n.Data
+ return
+ }
+
+ parent.InsertBefore(n, table)
+}
+
+// addText adds text to the preceding node if it is a text node, or else it
+// calls addChild with a new text node.
+func (p *parser) addText(text string) {
+ if text == "" {
+ return
+ }
+
+ if p.shouldFosterParent() {
+ p.fosterParent(&Node{
+ Type: TextNode,
+ Data: text,
+ })
+ return
+ }
+
+ t := p.top()
+ if n := t.LastChild; n != nil && n.Type == TextNode {
+ n.Data += text
+ return
+ }
+ p.addChild(&Node{
+ Type: TextNode,
+ Data: text,
+ })
+}
+
+// addElement adds a child element based on the current token.
+func (p *parser) addElement() {
+ p.addChild(&Node{
+ Type: ElementNode,
+ DataAtom: p.tok.DataAtom,
+ Data: p.tok.Data,
+ Attr: p.tok.Attr,
+ })
+}
+
+// Section 12.2.3.3.
+func (p *parser) addFormattingElement() {
+ tagAtom, attr := p.tok.DataAtom, p.tok.Attr
+ p.addElement()
+
+ // Implement the Noah's Ark clause, but with three per family instead of two.
+ identicalElements := 0
+findIdenticalElements:
+ for i := len(p.afe) - 1; i >= 0; i-- {
+ n := p.afe[i]
+ if n.Type == scopeMarkerNode {
+ break
+ }
+ if n.Type != ElementNode {
+ continue
+ }
+ if n.Namespace != "" {
+ continue
+ }
+ if n.DataAtom != tagAtom {
+ continue
+ }
+ if len(n.Attr) != len(attr) {
+ continue
+ }
+ compareAttributes:
+ for _, t0 := range n.Attr {
+ for _, t1 := range attr {
+ if t0.Key == t1.Key && t0.Namespace == t1.Namespace && t0.Val == t1.Val {
+ // Found a match for this attribute, continue with the next attribute.
+ continue compareAttributes
+ }
+ }
+ // If we get here, there is no attribute that matches a.
+ // Therefore the element is not identical to the new one.
+ continue findIdenticalElements
+ }
+
+ identicalElements++
+ if identicalElements >= 3 {
+ p.afe.remove(n)
+ }
+ }
+
+ p.afe = append(p.afe, p.top())
+}
+
+// Section 12.2.3.3.
+func (p *parser) clearActiveFormattingElements() {
+ for {
+ n := p.afe.pop()
+ if len(p.afe) == 0 || n.Type == scopeMarkerNode {
+ return
+ }
+ }
+}
+
+// Section 12.2.3.3.
+func (p *parser) reconstructActiveFormattingElements() {
+ n := p.afe.top()
+ if n == nil {
+ return
+ }
+ if n.Type == scopeMarkerNode || p.oe.index(n) != -1 {
+ return
+ }
+ i := len(p.afe) - 1
+ for n.Type != scopeMarkerNode && p.oe.index(n) == -1 {
+ if i == 0 {
+ i = -1
+ break
+ }
+ i--
+ n = p.afe[i]
+ }
+ for {
+ i++
+ clone := p.afe[i].clone()
+ p.addChild(clone)
+ p.afe[i] = clone
+ if i == len(p.afe)-1 {
+ break
+ }
+ }
+}
+
+// Section 12.2.4.
+func (p *parser) acknowledgeSelfClosingTag() {
+ p.hasSelfClosingToken = false
+}
+
+// An insertion mode (section 12.2.3.1) is the state transition function from
+// a particular state in the HTML5 parser's state machine. It updates the
+// parser's fields depending on parser.tok (where ErrorToken means EOF).
+// It returns whether the token was consumed.
+type insertionMode func(*parser) bool
+
+// setOriginalIM sets the insertion mode to return to after completing a text or
+// inTableText insertion mode.
+// Section 12.2.3.1, "using the rules for".
+func (p *parser) setOriginalIM() {
+ if p.originalIM != nil {
+ panic("html: bad parser state: originalIM was set twice")
+ }
+ p.originalIM = p.im
+}
+
+// Section 12.2.3.1, "reset the insertion mode".
+func (p *parser) resetInsertionMode() {
+ for i := len(p.oe) - 1; i >= 0; i-- {
+ n := p.oe[i]
+ if i == 0 && p.context != nil {
+ n = p.context
+ }
+
+ switch n.DataAtom {
+ case a.Select:
+ p.im = inSelectIM
+ case a.Td, a.Th:
+ p.im = inCellIM
+ case a.Tr:
+ p.im = inRowIM
+ case a.Tbody, a.Thead, a.Tfoot:
+ p.im = inTableBodyIM
+ case a.Caption:
+ p.im = inCaptionIM
+ case a.Colgroup:
+ p.im = inColumnGroupIM
+ case a.Table:
+ p.im = inTableIM
+ case a.Head:
+ p.im = inBodyIM
+ case a.Body:
+ p.im = inBodyIM
+ case a.Frameset:
+ p.im = inFramesetIM
+ case a.Html:
+ p.im = beforeHeadIM
+ default:
+ continue
+ }
+ return
+ }
+ p.im = inBodyIM
+}
+
+const whitespace = " \t\r\n\f"
+
+// Section 12.2.5.4.1.
+func initialIM(p *parser) bool {
+ switch p.tok.Type {
+ case TextToken:
+ p.tok.Data = strings.TrimLeft(p.tok.Data, whitespace)
+ if len(p.tok.Data) == 0 {
+ // It was all whitespace, so ignore it.
+ return true
+ }
+ case CommentToken:
+ p.doc.AppendChild(&Node{
+ Type: CommentNode,
+ Data: p.tok.Data,
+ })
+ return true
+ case DoctypeToken:
+ n, quirks := parseDoctype(p.tok.Data)
+ p.doc.AppendChild(n)
+ p.quirks = quirks
+ p.im = beforeHTMLIM
+ return true
+ }
+ p.quirks = true
+ p.im = beforeHTMLIM
+ return false
+}
+
+// Section 12.2.5.4.2.
+func beforeHTMLIM(p *parser) bool {
+ switch p.tok.Type {
+ case DoctypeToken:
+ // Ignore the token.
+ return true
+ case TextToken:
+ p.tok.Data = strings.TrimLeft(p.tok.Data, whitespace)
+ if len(p.tok.Data) == 0 {
+ // It was all whitespace, so ignore it.
+ return true
+ }
+ case StartTagToken:
+ if p.tok.DataAtom == a.Html {
+ p.addElement()
+ p.im = beforeHeadIM
+ return true
+ }
+ case EndTagToken:
+ switch p.tok.DataAtom {
+ case a.Head, a.Body, a.Html, a.Br:
+ p.parseImpliedToken(StartTagToken, a.Html, a.Html.String())
+ return false
+ default:
+ // Ignore the token.
+ return true
+ }
+ case CommentToken:
+ p.doc.AppendChild(&Node{
+ Type: CommentNode,
+ Data: p.tok.Data,
+ })
+ return true
+ }
+ p.parseImpliedToken(StartTagToken, a.Html, a.Html.String())
+ return false
+}
+
+// Section 12.2.5.4.3.
+func beforeHeadIM(p *parser) bool {
+ switch p.tok.Type {
+ case TextToken:
+ p.tok.Data = strings.TrimLeft(p.tok.Data, whitespace)
+ if len(p.tok.Data) == 0 {
+ // It was all whitespace, so ignore it.
+ return true
+ }
+ case StartTagToken:
+ switch p.tok.DataAtom {
+ case a.Head:
+ p.addElement()
+ p.head = p.top()
+ p.im = inHeadIM
+ return true
+ case a.Html:
+ return inBodyIM(p)
+ }
+ case EndTagToken:
+ switch p.tok.DataAtom {
+ case a.Head, a.Body, a.Html, a.Br:
+ p.parseImpliedToken(StartTagToken, a.Head, a.Head.String())
+ return false
+ default:
+ // Ignore the token.
+ return true
+ }
+ case CommentToken:
+ p.addChild(&Node{
+ Type: CommentNode,
+ Data: p.tok.Data,
+ })
+ return true
+ case DoctypeToken:
+ // Ignore the token.
+ return true
+ }
+
+ p.parseImpliedToken(StartTagToken, a.Head, a.Head.String())
+ return false
+}
+
+// Section 12.2.5.4.4.
+func inHeadIM(p *parser) bool {
+ switch p.tok.Type {
+ case TextToken:
+ s := strings.TrimLeft(p.tok.Data, whitespace)
+ if len(s) < len(p.tok.Data) {
+ // Add the initial whitespace to the current node.
+ p.addText(p.tok.Data[:len(p.tok.Data)-len(s)])
+ if s == "" {
+ return true
+ }
+ p.tok.Data = s
+ }
+ case StartTagToken:
+ switch p.tok.DataAtom {
+ case a.Html:
+ return inBodyIM(p)
+ case a.Base, a.Basefont, a.Bgsound, a.Command, a.Link, a.Meta:
+ p.addElement()
+ p.oe.pop()
+ p.acknowledgeSelfClosingTag()
+ return true
+ case a.Script, a.Title, a.Noscript, a.Noframes, a.Style:
+ p.addElement()
+ p.setOriginalIM()
+ p.im = textIM
+ return true
+ case a.Head:
+ // Ignore the token.
+ return true
+ }
+ case EndTagToken:
+ switch p.tok.DataAtom {
+ case a.Head:
+ n := p.oe.pop()
+ if n.DataAtom != a.Head {
+ panic("html: bad parser state: <head> element not found, in the in-head insertion mode")
+ }
+ p.im = afterHeadIM
+ return true
+ case a.Body, a.Html, a.Br:
+ p.parseImpliedToken(EndTagToken, a.Head, a.Head.String())
+ return false
+ default:
+ // Ignore the token.
+ return true
+ }
+ case CommentToken:
+ p.addChild(&Node{
+ Type: CommentNode,
+ Data: p.tok.Data,
+ })
+ return true
+ case DoctypeToken:
+ // Ignore the token.
+ return true
+ }
+
+ p.parseImpliedToken(EndTagToken, a.Head, a.Head.String())
+ return false
+}
+
+// Section 12.2.5.4.6.
+func afterHeadIM(p *parser) bool {
+ switch p.tok.Type {
+ case TextToken:
+ s := strings.TrimLeft(p.tok.Data, whitespace)
+ if len(s) < len(p.tok.Data) {
+ // Add the initial whitespace to the current node.
+ p.addText(p.tok.Data[:len(p.tok.Data)-len(s)])
+ if s == "" {
+ return true
+ }
+ p.tok.Data = s
+ }
+ case StartTagToken:
+ switch p.tok.DataAtom {
+ case a.Html:
+ return inBodyIM(p)
+ case a.Body:
+ p.addElement()
+ p.framesetOK = false
+ p.im = inBodyIM
+ return true
+ case a.Frameset:
+ p.addElement()
+ p.im = inFramesetIM
+ return true
+ case a.Base, a.Basefont, a.Bgsound, a.Link, a.Meta, a.Noframes, a.Script, a.Style, a.Title:
+ p.oe = append(p.oe, p.head)
+ defer p.oe.remove(p.head)
+ return inHeadIM(p)
+ case a.Head:
+ // Ignore the token.
+ return true
+ }
+ case EndTagToken:
+ switch p.tok.DataAtom {
+ case a.Body, a.Html, a.Br:
+ // Drop down to creating an implied <body> tag.
+ default:
+ // Ignore the token.
+ return true
+ }
+ case CommentToken:
+ p.addChild(&Node{
+ Type: CommentNode,
+ Data: p.tok.Data,
+ })
+ return true
+ case DoctypeToken:
+ // Ignore the token.
+ return true
+ }
+
+ p.parseImpliedToken(StartTagToken, a.Body, a.Body.String())
+ p.framesetOK = true
+ return false
+}
+
+// copyAttributes copies attributes of src not found on dst to dst.
+func copyAttributes(dst *Node, src Token) {
+ if len(src.Attr) == 0 {
+ return
+ }
+ attr := map[string]string{}
+ for _, t := range dst.Attr {
+ attr[t.Key] = t.Val
+ }
+ for _, t := range src.Attr {
+ if _, ok := attr[t.Key]; !ok {
+ dst.Attr = append(dst.Attr, t)
+ attr[t.Key] = t.Val
+ }
+ }
+}
+
+// Section 12.2.5.4.7.
+func inBodyIM(p *parser) bool {
+ switch p.tok.Type {
+ case TextToken:
+ d := p.tok.Data
+ switch n := p.oe.top(); n.DataAtom {
+ case a.Pre, a.Listing:
+ if n.FirstChild == nil {
+ // Ignore a newline at the start of a <pre> block.
+ if d != "" && d[0] == '\r' {
+ d = d[1:]
+ }
+ if d != "" && d[0] == '\n' {
+ d = d[1:]
+ }
+ }
+ }
+ d = strings.Replace(d, "\x00", "", -1)
+ if d == "" {
+ return true
+ }
+ p.reconstructActiveFormattingElements()
+ p.addText(d)
+ if p.framesetOK && strings.TrimLeft(d, whitespace) != "" {
+ // There were non-whitespace characters inserted.
+ p.framesetOK = false
+ }
+ case StartTagToken:
+ switch p.tok.DataAtom {
+ case a.Html:
+ copyAttributes(p.oe[0], p.tok)
+ case a.Base, a.Basefont, a.Bgsound, a.Command, a.Link, a.Meta, a.Noframes, a.Script, a.Style, a.Title:
+ return inHeadIM(p)
+ case a.Body:
+ if len(p.oe) >= 2 {
+ body := p.oe[1]
+ if body.Type == ElementNode && body.DataAtom == a.Body {
+ p.framesetOK = false
+ copyAttributes(body, p.tok)
+ }
+ }
+ case a.Frameset:
+ if !p.framesetOK || len(p.oe) < 2 || p.oe[1].DataAtom != a.Body {
+ // Ignore the token.
+ return true
+ }
+ body := p.oe[1]
+ if body.Parent != nil {
+ body.Parent.RemoveChild(body)
+ }
+ p.oe = p.oe[:1]
+ p.addElement()
+ p.im = inFramesetIM
+ return true
+ case a.Address, a.Article, a.Aside, a.Blockquote, a.Center, a.Details, a.Dir, a.Div, a.Dl, a.Fieldset, a.Figcaption, a.Figure, a.Footer, a.Header, a.Hgroup, a.Menu, a.Nav, a.Ol, a.P, a.Section, a.Summary, a.Ul:
+ p.popUntil(buttonScope, a.P)
+ p.addElement()
+ case a.H1, a.H2, a.H3, a.H4, a.H5, a.H6:
+ p.popUntil(buttonScope, a.P)
+ switch n := p.top(); n.DataAtom {
+ case a.H1, a.H2, a.H3, a.H4, a.H5, a.H6:
+ p.oe.pop()
+ }
+ p.addElement()
+ case a.Pre, a.Listing:
+ p.popUntil(buttonScope, a.P)
+ p.addElement()
+ // The newline, if any, will be dealt with by the TextToken case.
+ p.framesetOK = false
+ case a.Form:
+ if p.form == nil {
+ p.popUntil(buttonScope, a.P)
+ p.addElement()
+ p.form = p.top()
+ }
+ case a.Li:
+ p.framesetOK = false
+ for i := len(p.oe) - 1; i >= 0; i-- {
+ node := p.oe[i]
+ switch node.DataAtom {
+ case a.Li:
+ p.oe = p.oe[:i]
+ case a.Address, a.Div, a.P:
+ continue
+ default:
+ if !isSpecialElement(node) {
+ continue
+ }
+ }
+ break
+ }
+ p.popUntil(buttonScope, a.P)
+ p.addElement()
+ case a.Dd, a.Dt:
+ p.framesetOK = false
+ for i := len(p.oe) - 1; i >= 0; i-- {
+ node := p.oe[i]
+ switch node.DataAtom {
+ case a.Dd, a.Dt:
+ p.oe = p.oe[:i]
+ case a.Address, a.Div, a.P:
+ continue
+ default:
+ if !isSpecialElement(node) {
+ continue
+ }
+ }
+ break
+ }
+ p.popUntil(buttonScope, a.P)
+ p.addElement()
+ case a.Plaintext:
+ p.popUntil(buttonScope, a.P)
+ p.addElement()
+ case a.Button:
+ p.popUntil(defaultScope, a.Button)
+ p.reconstructActiveFormattingElements()
+ p.addElement()
+ p.framesetOK = false
+ case a.A:
+ for i := len(p.afe) - 1; i >= 0 && p.afe[i].Type != scopeMarkerNode; i-- {
+ if n := p.afe[i]; n.Type == ElementNode && n.DataAtom == a.A {
+ p.inBodyEndTagFormatting(a.A)
+ p.oe.remove(n)
+ p.afe.remove(n)
+ break
+ }
+ }
+ p.reconstructActiveFormattingElements()
+ p.addFormattingElement()
+ case a.B, a.Big, a.Code, a.Em, a.Font, a.I, a.S, a.Small, a.Strike, a.Strong, a.Tt, a.U:
+ p.reconstructActiveFormattingElements()
+ p.addFormattingElement()
+ case a.Nobr:
+ p.reconstructActiveFormattingElements()
+ if p.elementInScope(defaultScope, a.Nobr) {
+ p.inBodyEndTagFormatting(a.Nobr)
+ p.reconstructActiveFormattingElements()
+ }
+ p.addFormattingElement()
+ case a.Applet, a.Marquee, a.Object:
+ p.reconstructActiveFormattingElements()
+ p.addElement()
+ p.afe = append(p.afe, &scopeMarker)
+ p.framesetOK = false
+ case a.Table:
+ if !p.quirks {
+ p.popUntil(buttonScope, a.P)
+ }
+ p.addElement()
+ p.framesetOK = false
+ p.im = inTableIM
+ return true
+ case a.Area, a.Br, a.Embed, a.Img, a.Input, a.Keygen, a.Wbr:
+ p.reconstructActiveFormattingElements()
+ p.addElement()
+ p.oe.pop()
+ p.acknowledgeSelfClosingTag()
+ if p.tok.DataAtom == a.Input {
+ for _, t := range p.tok.Attr {
+ if t.Key == "type" {
+ if strings.ToLower(t.Val) == "hidden" {
+ // Skip setting framesetOK = false
+ return true
+ }
+ }
+ }
+ }
+ p.framesetOK = false
+ case a.Param, a.Source, a.Track:
+ p.addElement()
+ p.oe.pop()
+ p.acknowledgeSelfClosingTag()
+ case a.Hr:
+ p.popUntil(buttonScope, a.P)
+ p.addElement()
+ p.oe.pop()
+ p.acknowledgeSelfClosingTag()
+ p.framesetOK = false
+ case a.Image:
+ p.tok.DataAtom = a.Img
+ p.tok.Data = a.Img.String()
+ return false
+ case a.Isindex:
+ if p.form != nil {
+ // Ignore the token.
+ return true
+ }
+ action := ""
+ prompt := "This is a searchable index. Enter search keywords: "
+ attr := []Attribute{{Key: "name", Val: "isindex"}}
+ for _, t := range p.tok.Attr {
+ switch t.Key {
+ case "action":
+ action = t.Val
+ case "name":
+ // Ignore the attribute.
+ case "prompt":
+ prompt = t.Val
+ default:
+ attr = append(attr, t)
+ }
+ }
+ p.acknowledgeSelfClosingTag()
+ p.popUntil(buttonScope, a.P)
+ p.parseImpliedToken(StartTagToken, a.Form, a.Form.String())
+ if action != "" {
+ p.form.Attr = []Attribute{{Key: "action", Val: action}}
+ }
+ p.parseImpliedToken(StartTagToken, a.Hr, a.Hr.String())
+ p.parseImpliedToken(StartTagToken, a.Label, a.Label.String())
+ p.addText(prompt)
+ p.addChild(&Node{
+ Type: ElementNode,
+ DataAtom: a.Input,
+ Data: a.Input.String(),
+ Attr: attr,
+ })
+ p.oe.pop()
+ p.parseImpliedToken(EndTagToken, a.Label, a.Label.String())
+ p.parseImpliedToken(StartTagToken, a.Hr, a.Hr.String())
+ p.parseImpliedToken(EndTagToken, a.Form, a.Form.String())
+ case a.Textarea:
+ p.addElement()
+ p.setOriginalIM()
+ p.framesetOK = false
+ p.im = textIM
+ case a.Xmp:
+ p.popUntil(buttonScope, a.P)
+ p.reconstructActiveFormattingElements()
+ p.framesetOK = false
+ p.addElement()
+ p.setOriginalIM()
+ p.im = textIM
+ case a.Iframe:
+ p.framesetOK = false
+ p.addElement()
+ p.setOriginalIM()
+ p.im = textIM
+ case a.Noembed, a.Noscript:
+ p.addElement()
+ p.setOriginalIM()
+ p.im = textIM
+ case a.Select:
+ p.reconstructActiveFormattingElements()
+ p.addElement()
+ p.framesetOK = false
+ p.im = inSelectIM
+ return true
+ case a.Optgroup, a.Option:
+ if p.top().DataAtom == a.Option {
+ p.oe.pop()
+ }
+ p.reconstructActiveFormattingElements()
+ p.addElement()
+ case a.Rp, a.Rt:
+ if p.elementInScope(defaultScope, a.Ruby) {
+ p.generateImpliedEndTags()
+ }
+ p.addElement()
+ case a.Math, a.Svg:
+ p.reconstructActiveFormattingElements()
+ if p.tok.DataAtom == a.Math {
+ adjustAttributeNames(p.tok.Attr, mathMLAttributeAdjustments)
+ } else {
+ adjustAttributeNames(p.tok.Attr, svgAttributeAdjustments)
+ }
+ adjustForeignAttributes(p.tok.Attr)
+ p.addElement()
+ p.top().Namespace = p.tok.Data
+ if p.hasSelfClosingToken {
+ p.oe.pop()
+ p.acknowledgeSelfClosingTag()
+ }
+ return true
+ case a.Caption, a.Col, a.Colgroup, a.Frame, a.Head, a.Tbody, a.Td, a.Tfoot, a.Th, a.Thead, a.Tr:
+ // Ignore the token.
+ default:
+ p.reconstructActiveFormattingElements()
+ p.addElement()
+ }
+ case EndTagToken:
+ switch p.tok.DataAtom {
+ case a.Body:
+ if p.elementInScope(defaultScope, a.Body) {
+ p.im = afterBodyIM
+ }
+ case a.Html:
+ if p.elementInScope(defaultScope, a.Body) {
+ p.parseImpliedToken(EndTagToken, a.Body, a.Body.String())
+ return false
+ }
+ return true
+ case a.Address, a.Article, a.Aside, a.Blockquote, a.Button, a.Center, a.Details, a.Dir, a.Div, a.Dl, a.Fieldset, a.Figcaption, a.Figure, a.Footer, a.Header, a.Hgroup, a.Listing, a.Menu, a.Nav, a.Ol, a.Pre, a.Section, a.Summary, a.Ul:
+ p.popUntil(defaultScope, p.tok.DataAtom)
+ case a.Form:
+ node := p.form
+ p.form = nil
+ i := p.indexOfElementInScope(defaultScope, a.Form)
+ if node == nil || i == -1 || p.oe[i] != node {
+ // Ignore the token.
+ return true
+ }
+ p.generateImpliedEndTags()
+ p.oe.remove(node)
+ case a.P:
+ if !p.elementInScope(buttonScope, a.P) {
+ p.parseImpliedToken(StartTagToken, a.P, a.P.String())
+ }
+ p.popUntil(buttonScope, a.P)
+ case a.Li:
+ p.popUntil(listItemScope, a.Li)
+ case a.Dd, a.Dt:
+ p.popUntil(defaultScope, p.tok.DataAtom)
+ case a.H1, a.H2, a.H3, a.H4, a.H5, a.H6:
+ p.popUntil(defaultScope, a.H1, a.H2, a.H3, a.H4, a.H5, a.H6)
+ case a.A, a.B, a.Big, a.Code, a.Em, a.Font, a.I, a.Nobr, a.S, a.Small, a.Strike, a.Strong, a.Tt, a.U:
+ p.inBodyEndTagFormatting(p.tok.DataAtom)
+ case a.Applet, a.Marquee, a.Object:
+ if p.popUntil(defaultScope, p.tok.DataAtom) {
+ p.clearActiveFormattingElements()
+ }
+ case a.Br:
+ p.tok.Type = StartTagToken
+ return false
+ default:
+ p.inBodyEndTagOther(p.tok.DataAtom)
+ }
+ case CommentToken:
+ p.addChild(&Node{
+ Type: CommentNode,
+ Data: p.tok.Data,
+ })
+ }
+
+ return true
+}
+
+func (p *parser) inBodyEndTagFormatting(tagAtom a.Atom) {
+ // This is the "adoption agency" algorithm, described at
+ // https://html.spec.whatwg.org/multipage/syntax.html#adoptionAgency
+
+ // TODO: this is a fairly literal line-by-line translation of that algorithm.
+ // Once the code successfully parses the comprehensive test suite, we should
+ // refactor this code to be more idiomatic.
+
+ // Steps 1-4. The outer loop.
+ for i := 0; i < 8; i++ {
+ // Step 5. Find the formatting element.
+ var formattingElement *Node
+ for j := len(p.afe) - 1; j >= 0; j-- {
+ if p.afe[j].Type == scopeMarkerNode {
+ break
+ }
+ if p.afe[j].DataAtom == tagAtom {
+ formattingElement = p.afe[j]
+ break
+ }
+ }
+ if formattingElement == nil {
+ p.inBodyEndTagOther(tagAtom)
+ return
+ }
+ feIndex := p.oe.index(formattingElement)
+ if feIndex == -1 {
+ p.afe.remove(formattingElement)
+ return
+ }
+ if !p.elementInScope(defaultScope, tagAtom) {
+ // Ignore the tag.
+ return
+ }
+
+ // Steps 9-10. Find the furthest block.
+ var furthestBlock *Node
+ for _, e := range p.oe[feIndex:] {
+ if isSpecialElement(e) {
+ furthestBlock = e
+ break
+ }
+ }
+ if furthestBlock == nil {
+ e := p.oe.pop()
+ for e != formattingElement {
+ e = p.oe.pop()
+ }
+ p.afe.remove(e)
+ return
+ }
+
+ // Steps 11-12. Find the common ancestor and bookmark node.
+ commonAncestor := p.oe[feIndex-1]
+ bookmark := p.afe.index(formattingElement)
+
+ // Step 13. The inner loop. Find the lastNode to reparent.
+ lastNode := furthestBlock
+ node := furthestBlock
+ x := p.oe.index(node)
+ // Steps 13.1-13.2
+ for j := 0; j < 3; j++ {
+ // Step 13.3.
+ x--
+ node = p.oe[x]
+ // Step 13.4 - 13.5.
+ if p.afe.index(node) == -1 {
+ p.oe.remove(node)
+ continue
+ }
+ // Step 13.6.
+ if node == formattingElement {
+ break
+ }
+ // Step 13.7.
+ clone := node.clone()
+ p.afe[p.afe.index(node)] = clone
+ p.oe[p.oe.index(node)] = clone
+ node = clone
+ // Step 13.8.
+ if lastNode == furthestBlock {
+ bookmark = p.afe.index(node) + 1
+ }
+ // Step 13.9.
+ if lastNode.Parent != nil {
+ lastNode.Parent.RemoveChild(lastNode)
+ }
+ node.AppendChild(lastNode)
+ // Step 13.10.
+ lastNode = node
+ }
+
+ // Step 14. Reparent lastNode to the common ancestor,
+ // or for misnested table nodes, to the foster parent.
+ if lastNode.Parent != nil {
+ lastNode.Parent.RemoveChild(lastNode)
+ }
+ switch commonAncestor.DataAtom {
+ case a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr:
+ p.fosterParent(lastNode)
+ default:
+ commonAncestor.AppendChild(lastNode)
+ }
+
+ // Steps 15-17. Reparent nodes from the furthest block's children
+ // to a clone of the formatting element.
+ clone := formattingElement.clone()
+ reparentChildren(clone, furthestBlock)
+ furthestBlock.AppendChild(clone)
+
+ // Step 18. Fix up the list of active formatting elements.
+ if oldLoc := p.afe.index(formattingElement); oldLoc != -1 && oldLoc < bookmark {
+ // Move the bookmark with the rest of the list.
+ bookmark--
+ }
+ p.afe.remove(formattingElement)
+ p.afe.insert(bookmark, clone)
+
+ // Step 19. Fix up the stack of open elements.
+ p.oe.remove(formattingElement)
+ p.oe.insert(p.oe.index(furthestBlock)+1, clone)
+ }
+}
+
+// inBodyEndTagOther performs the "any other end tag" algorithm for inBodyIM.
+// "Any other end tag" handling from 12.2.5.5 The rules for parsing tokens in foreign content
+// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inforeign
+func (p *parser) inBodyEndTagOther(tagAtom a.Atom) {
+ for i := len(p.oe) - 1; i >= 0; i-- {
+ if p.oe[i].DataAtom == tagAtom {
+ p.oe = p.oe[:i]
+ break
+ }
+ if isSpecialElement(p.oe[i]) {
+ break
+ }
+ }
+}
+
+// Section 12.2.5.4.8.
+func textIM(p *parser) bool {
+ switch p.tok.Type {
+ case ErrorToken:
+ p.oe.pop()
+ case TextToken:
+ d := p.tok.Data
+ if n := p.oe.top(); n.DataAtom == a.Textarea && n.FirstChild == nil {
+ // Ignore a newline at the start of a <textarea> block.
+ if d != "" && d[0] == '\r' {
+ d = d[1:]
+ }
+ if d != "" && d[0] == '\n' {
+ d = d[1:]
+ }
+ }
+ if d == "" {
+ return true
+ }
+ p.addText(d)
+ return true
+ case EndTagToken:
+ p.oe.pop()
+ }
+ p.im = p.originalIM
+ p.originalIM = nil
+ return p.tok.Type == EndTagToken
+}
+
+// Section 12.2.5.4.9.
+func inTableIM(p *parser) bool {
+ switch p.tok.Type {
+ case ErrorToken:
+ // Stop parsing.
+ return true
+ case TextToken:
+ p.tok.Data = strings.Replace(p.tok.Data, "\x00", "", -1)
+ switch p.oe.top().DataAtom {
+ case a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr:
+ if strings.Trim(p.tok.Data, whitespace) == "" {
+ p.addText(p.tok.Data)
+ return true
+ }
+ }
+ case StartTagToken:
+ switch p.tok.DataAtom {
+ case a.Caption:
+ p.clearStackToContext(tableScope)
+ p.afe = append(p.afe, &scopeMarker)
+ p.addElement()
+ p.im = inCaptionIM
+ return true
+ case a.Colgroup:
+ p.clearStackToContext(tableScope)
+ p.addElement()
+ p.im = inColumnGroupIM
+ return true
+ case a.Col:
+ p.parseImpliedToken(StartTagToken, a.Colgroup, a.Colgroup.String())
+ return false
+ case a.Tbody, a.Tfoot, a.Thead:
+ p.clearStackToContext(tableScope)
+ p.addElement()
+ p.im = inTableBodyIM
+ return true
+ case a.Td, a.Th, a.Tr:
+ p.parseImpliedToken(StartTagToken, a.Tbody, a.Tbody.String())
+ return false
+ case a.Table:
+ if p.popUntil(tableScope, a.Table) {
+ p.resetInsertionMode()
+ return false
+ }
+ // Ignore the token.
+ return true
+ case a.Style, a.Script:
+ return inHeadIM(p)
+ case a.Input:
+ for _, t := range p.tok.Attr {
+ if t.Key == "type" && strings.ToLower(t.Val) == "hidden" {
+ p.addElement()
+ p.oe.pop()
+ return true
+ }
+ }
+ // Otherwise drop down to the default action.
+ case a.Form:
+ if p.form != nil {
+ // Ignore the token.
+ return true
+ }
+ p.addElement()
+ p.form = p.oe.pop()
+ case a.Select:
+ p.reconstructActiveFormattingElements()
+ switch p.top().DataAtom {
+ case a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr:
+ p.fosterParenting = true
+ }
+ p.addElement()
+ p.fosterParenting = false
+ p.framesetOK = false
+ p.im = inSelectInTableIM
+ return true
+ }
+ case EndTagToken:
+ switch p.tok.DataAtom {
+ case a.Table:
+ if p.popUntil(tableScope, a.Table) {
+ p.resetInsertionMode()
+ return true
+ }
+ // Ignore the token.
+ return true
+ case a.Body, a.Caption, a.Col, a.Colgroup, a.Html, a.Tbody, a.Td, a.Tfoot, a.Th, a.Thead, a.Tr:
+ // Ignore the token.
+ return true
+ }
+ case CommentToken:
+ p.addChild(&Node{
+ Type: CommentNode,
+ Data: p.tok.Data,
+ })
+ return true
+ case DoctypeToken:
+ // Ignore the token.
+ return true
+ }
+
+ p.fosterParenting = true
+ defer func() { p.fosterParenting = false }()
+
+ return inBodyIM(p)
+}
+
+// Section 12.2.5.4.11.
+func inCaptionIM(p *parser) bool {
+ switch p.tok.Type {
+ case StartTagToken:
+ switch p.tok.DataAtom {
+ case a.Caption, a.Col, a.Colgroup, a.Tbody, a.Td, a.Tfoot, a.Thead, a.Tr:
+ if p.popUntil(tableScope, a.Caption) {
+ p.clearActiveFormattingElements()
+ p.im = inTableIM
+ return false
+ } else {
+ // Ignore the token.
+ return true
+ }
+ case a.Select:
+ p.reconstructActiveFormattingElements()
+ p.addElement()
+ p.framesetOK = false
+ p.im = inSelectInTableIM
+ return true
+ }
+ case EndTagToken:
+ switch p.tok.DataAtom {
+ case a.Caption:
+ if p.popUntil(tableScope, a.Caption) {
+ p.clearActiveFormattingElements()
+ p.im = inTableIM
+ }
+ return true
+ case a.Table:
+ if p.popUntil(tableScope, a.Caption) {
+ p.clearActiveFormattingElements()
+ p.im = inTableIM
+ return false
+ } else {
+ // Ignore the token.
+ return true
+ }
+ case a.Body, a.Col, a.Colgroup, a.Html, a.Tbody, a.Td, a.Tfoot, a.Th, a.Thead, a.Tr:
+ // Ignore the token.
+ return true
+ }
+ }
+ return inBodyIM(p)
+}
+
+// Section 12.2.5.4.12.
+func inColumnGroupIM(p *parser) bool {
+ switch p.tok.Type {
+ case TextToken:
+ s := strings.TrimLeft(p.tok.Data, whitespace)
+ if len(s) < len(p.tok.Data) {
+ // Add the initial whitespace to the current node.
+ p.addText(p.tok.Data[:len(p.tok.Data)-len(s)])
+ if s == "" {
+ return true
+ }
+ p.tok.Data = s
+ }
+ case CommentToken:
+ p.addChild(&Node{
+ Type: CommentNode,
+ Data: p.tok.Data,
+ })
+ return true
+ case DoctypeToken:
+ // Ignore the token.
+ return true
+ case StartTagToken:
+ switch p.tok.DataAtom {
+ case a.Html:
+ return inBodyIM(p)
+ case a.Col:
+ p.addElement()
+ p.oe.pop()
+ p.acknowledgeSelfClosingTag()
+ return true
+ }
+ case EndTagToken:
+ switch p.tok.DataAtom {
+ case a.Colgroup:
+ if p.oe.top().DataAtom != a.Html {
+ p.oe.pop()
+ p.im = inTableIM
+ }
+ return true
+ case a.Col:
+ // Ignore the token.
+ return true
+ }
+ }
+ if p.oe.top().DataAtom != a.Html {
+ p.oe.pop()
+ p.im = inTableIM
+ return false
+ }
+ return true
+}
+
+// Section 12.2.5.4.13.
+func inTableBodyIM(p *parser) bool {
+ switch p.tok.Type {
+ case StartTagToken:
+ switch p.tok.DataAtom {
+ case a.Tr:
+ p.clearStackToContext(tableBodyScope)
+ p.addElement()
+ p.im = inRowIM
+ return true
+ case a.Td, a.Th:
+ p.parseImpliedToken(StartTagToken, a.Tr, a.Tr.String())
+ return false
+ case a.Caption, a.Col, a.Colgroup, a.Tbody, a.Tfoot, a.Thead:
+ if p.popUntil(tableScope, a.Tbody, a.Thead, a.Tfoot) {
+ p.im = inTableIM
+ return false
+ }
+ // Ignore the token.
+ return true
+ }
+ case EndTagToken:
+ switch p.tok.DataAtom {
+ case a.Tbody, a.Tfoot, a.Thead:
+ if p.elementInScope(tableScope, p.tok.DataAtom) {
+ p.clearStackToContext(tableBodyScope)
+ p.oe.pop()
+ p.im = inTableIM
+ }
+ return true
+ case a.Table:
+ if p.popUntil(tableScope, a.Tbody, a.Thead, a.Tfoot) {
+ p.im = inTableIM
+ return false
+ }
+ // Ignore the token.
+ return true
+ case a.Body, a.Caption, a.Col, a.Colgroup, a.Html, a.Td, a.Th, a.Tr:
+ // Ignore the token.
+ return true
+ }
+ case CommentToken:
+ p.addChild(&Node{
+ Type: CommentNode,
+ Data: p.tok.Data,
+ })
+ return true
+ }
+
+ return inTableIM(p)
+}
+
+// Section 12.2.5.4.14.
+func inRowIM(p *parser) bool {
+ switch p.tok.Type {
+ case StartTagToken:
+ switch p.tok.DataAtom {
+ case a.Td, a.Th:
+ p.clearStackToContext(tableRowScope)
+ p.addElement()
+ p.afe = append(p.afe, &scopeMarker)
+ p.im = inCellIM
+ return true
+ case a.Caption, a.Col, a.Colgroup, a.Tbody, a.Tfoot, a.Thead, a.Tr:
+ if p.popUntil(tableScope, a.Tr) {
+ p.im = inTableBodyIM
+ return false
+ }
+ // Ignore the token.
+ return true
+ }
+ case EndTagToken:
+ switch p.tok.DataAtom {
+ case a.Tr:
+ if p.popUntil(tableScope, a.Tr) {
+ p.im = inTableBodyIM
+ return true
+ }
+ // Ignore the token.
+ return true
+ case a.Table:
+ if p.popUntil(tableScope, a.Tr) {
+ p.im = inTableBodyIM
+ return false
+ }
+ // Ignore the token.
+ return true
+ case a.Tbody, a.Tfoot, a.Thead:
+ if p.elementInScope(tableScope, p.tok.DataAtom) {
+ p.parseImpliedToken(EndTagToken, a.Tr, a.Tr.String())
+ return false
+ }
+ // Ignore the token.
+ return true
+ case a.Body, a.Caption, a.Col, a.Colgroup, a.Html, a.Td, a.Th:
+ // Ignore the token.
+ return true
+ }
+ }
+
+ return inTableIM(p)
+}
+
+// Section 12.2.5.4.15.
+func inCellIM(p *parser) bool {
+ switch p.tok.Type {
+ case StartTagToken:
+ switch p.tok.DataAtom {
+ case a.Caption, a.Col, a.Colgroup, a.Tbody, a.Td, a.Tfoot, a.Th, a.Thead, a.Tr:
+ if p.popUntil(tableScope, a.Td, a.Th) {
+ // Close the cell and reprocess.
+ p.clearActiveFormattingElements()
+ p.im = inRowIM
+ return false
+ }
+ // Ignore the token.
+ return true
+ case a.Select:
+ p.reconstructActiveFormattingElements()
+ p.addElement()
+ p.framesetOK = false
+ p.im = inSelectInTableIM
+ return true
+ }
+ case EndTagToken:
+ switch p.tok.DataAtom {
+ case a.Td, a.Th:
+ if !p.popUntil(tableScope, p.tok.DataAtom) {
+ // Ignore the token.
+ return true
+ }
+ p.clearActiveFormattingElements()
+ p.im = inRowIM
+ return true
+ case a.Body, a.Caption, a.Col, a.Colgroup, a.Html:
+ // Ignore the token.
+ return true
+ case a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr:
+ if !p.elementInScope(tableScope, p.tok.DataAtom) {
+ // Ignore the token.
+ return true
+ }
+ // Close the cell and reprocess.
+ p.popUntil(tableScope, a.Td, a.Th)
+ p.clearActiveFormattingElements()
+ p.im = inRowIM
+ return false
+ }
+ }
+ return inBodyIM(p)
+}
+
+// Section 12.2.5.4.16.
+func inSelectIM(p *parser) bool {
+ switch p.tok.Type {
+ case ErrorToken:
+ // Stop parsing.
+ return true
+ case TextToken:
+ p.addText(strings.Replace(p.tok.Data, "\x00", "", -1))
+ case StartTagToken:
+ switch p.tok.DataAtom {
+ case a.Html:
+ return inBodyIM(p)
+ case a.Option:
+ if p.top().DataAtom == a.Option {
+ p.oe.pop()
+ }
+ p.addElement()
+ case a.Optgroup:
+ if p.top().DataAtom == a.Option {
+ p.oe.pop()
+ }
+ if p.top().DataAtom == a.Optgroup {
+ p.oe.pop()
+ }
+ p.addElement()
+ case a.Select:
+ p.tok.Type = EndTagToken
+ return false
+ case a.Input, a.Keygen, a.Textarea:
+ if p.elementInScope(selectScope, a.Select) {
+ p.parseImpliedToken(EndTagToken, a.Select, a.Select.String())
+ return false
+ }
+ // In order to properly ignore <textarea>, we need to change the tokenizer mode.
+ p.tokenizer.NextIsNotRawText()
+ // Ignore the token.
+ return true
+ case a.Script:
+ return inHeadIM(p)
+ }
+ case EndTagToken:
+ switch p.tok.DataAtom {
+ case a.Option:
+ if p.top().DataAtom == a.Option {
+ p.oe.pop()
+ }
+ case a.Optgroup:
+ i := len(p.oe) - 1
+ if p.oe[i].DataAtom == a.Option {
+ i--
+ }
+ if p.oe[i].DataAtom == a.Optgroup {
+ p.oe = p.oe[:i]
+ }
+ case a.Select:
+ if p.popUntil(selectScope, a.Select) {
+ p.resetInsertionMode()
+ }
+ }
+ case CommentToken:
+ p.addChild(&Node{
+ Type: CommentNode,
+ Data: p.tok.Data,
+ })
+ case DoctypeToken:
+ // Ignore the token.
+ return true
+ }
+
+ return true
+}
+
+// Section 12.2.5.4.17.
+func inSelectInTableIM(p *parser) bool {
+ switch p.tok.Type {
+ case StartTagToken, EndTagToken:
+ switch p.tok.DataAtom {
+ case a.Caption, a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr, a.Td, a.Th:
+ if p.tok.Type == StartTagToken || p.elementInScope(tableScope, p.tok.DataAtom) {
+ p.parseImpliedToken(EndTagToken, a.Select, a.Select.String())
+ return false
+ } else {
+ // Ignore the token.
+ return true
+ }
+ }
+ }
+ return inSelectIM(p)
+}
+
+// Section 12.2.5.4.18.
+func afterBodyIM(p *parser) bool {
+ switch p.tok.Type {
+ case ErrorToken:
+ // Stop parsing.
+ return true
+ case TextToken:
+ s := strings.TrimLeft(p.tok.Data, whitespace)
+ if len(s) == 0 {
+ // It was all whitespace.
+ return inBodyIM(p)
+ }
+ case StartTagToken:
+ if p.tok.DataAtom == a.Html {
+ return inBodyIM(p)
+ }
+ case EndTagToken:
+ if p.tok.DataAtom == a.Html {
+ if !p.fragment {
+ p.im = afterAfterBodyIM
+ }
+ return true
+ }
+ case CommentToken:
+ // The comment is attached to the <html> element.
+ if len(p.oe) < 1 || p.oe[0].DataAtom != a.Html {
+ panic("html: bad parser state: <html> element not found, in the after-body insertion mode")
+ }
+ p.oe[0].AppendChild(&Node{
+ Type: CommentNode,
+ Data: p.tok.Data,
+ })
+ return true
+ }
+ p.im = inBodyIM
+ return false
+}
+
+// Section 12.2.5.4.19.
+func inFramesetIM(p *parser) bool {
+ switch p.tok.Type {
+ case CommentToken:
+ p.addChild(&Node{
+ Type: CommentNode,
+ Data: p.tok.Data,
+ })
+ case TextToken:
+ // Ignore all text but whitespace.
+ s := strings.Map(func(c rune) rune {
+ switch c {
+ case ' ', '\t', '\n', '\f', '\r':
+ return c
+ }
+ return -1
+ }, p.tok.Data)
+ if s != "" {
+ p.addText(s)
+ }
+ case StartTagToken:
+ switch p.tok.DataAtom {
+ case a.Html:
+ return inBodyIM(p)
+ case a.Frameset:
+ p.addElement()
+ case a.Frame:
+ p.addElement()
+ p.oe.pop()
+ p.acknowledgeSelfClosingTag()
+ case a.Noframes:
+ return inHeadIM(p)
+ }
+ case EndTagToken:
+ switch p.tok.DataAtom {
+ case a.Frameset:
+ if p.oe.top().DataAtom != a.Html {
+ p.oe.pop()
+ if p.oe.top().DataAtom != a.Frameset {
+ p.im = afterFramesetIM
+ return true
+ }
+ }
+ }
+ default:
+ // Ignore the token.
+ }
+ return true
+}
+
+// Section 12.2.5.4.20.
+func afterFramesetIM(p *parser) bool {
+ switch p.tok.Type {
+ case CommentToken:
+ p.addChild(&Node{
+ Type: CommentNode,
+ Data: p.tok.Data,
+ })
+ case TextToken:
+ // Ignore all text but whitespace.
+ s := strings.Map(func(c rune) rune {
+ switch c {
+ case ' ', '\t', '\n', '\f', '\r':
+ return c
+ }
+ return -1
+ }, p.tok.Data)
+ if s != "" {
+ p.addText(s)
+ }
+ case StartTagToken:
+ switch p.tok.DataAtom {
+ case a.Html:
+ return inBodyIM(p)
+ case a.Noframes:
+ return inHeadIM(p)
+ }
+ case EndTagToken:
+ switch p.tok.DataAtom {
+ case a.Html:
+ p.im = afterAfterFramesetIM
+ return true
+ }
+ default:
+ // Ignore the token.
+ }
+ return true
+}
+
+// Section 12.2.5.4.21.
+func afterAfterBodyIM(p *parser) bool {
+ switch p.tok.Type {
+ case ErrorToken:
+ // Stop parsing.
+ return true
+ case TextToken:
+ s := strings.TrimLeft(p.tok.Data, whitespace)
+ if len(s) == 0 {
+ // It was all whitespace.
+ return inBodyIM(p)
+ }
+ case StartTagToken:
+ if p.tok.DataAtom == a.Html {
+ return inBodyIM(p)
+ }
+ case CommentToken:
+ p.doc.AppendChild(&Node{
+ Type: CommentNode,
+ Data: p.tok.Data,
+ })
+ return true
+ case DoctypeToken:
+ return inBodyIM(p)
+ }
+ p.im = inBodyIM
+ return false
+}
+
+// Section 12.2.5.4.22.
+func afterAfterFramesetIM(p *parser) bool {
+ switch p.tok.Type {
+ case CommentToken:
+ p.doc.AppendChild(&Node{
+ Type: CommentNode,
+ Data: p.tok.Data,
+ })
+ case TextToken:
+ // Ignore all text but whitespace.
+ s := strings.Map(func(c rune) rune {
+ switch c {
+ case ' ', '\t', '\n', '\f', '\r':
+ return c
+ }
+ return -1
+ }, p.tok.Data)
+ if s != "" {
+ p.tok.Data = s
+ return inBodyIM(p)
+ }
+ case StartTagToken:
+ switch p.tok.DataAtom {
+ case a.Html:
+ return inBodyIM(p)
+ case a.Noframes:
+ return inHeadIM(p)
+ }
+ case DoctypeToken:
+ return inBodyIM(p)
+ default:
+ // Ignore the token.
+ }
+ return true
+}
+
+const whitespaceOrNUL = whitespace + "\x00"
+
+// Section 12.2.5.5.
+func parseForeignContent(p *parser) bool {
+ switch p.tok.Type {
+ case TextToken:
+ if p.framesetOK {
+ p.framesetOK = strings.TrimLeft(p.tok.Data, whitespaceOrNUL) == ""
+ }
+ p.tok.Data = strings.Replace(p.tok.Data, "\x00", "\ufffd", -1)
+ p.addText(p.tok.Data)
+ case CommentToken:
+ p.addChild(&Node{
+ Type: CommentNode,
+ Data: p.tok.Data,
+ })
+ case StartTagToken:
+ b := breakout[p.tok.Data]
+ if p.tok.DataAtom == a.Font {
+ loop:
+ for _, attr := range p.tok.Attr {
+ switch attr.Key {
+ case "color", "face", "size":
+ b = true
+ break loop
+ }
+ }
+ }
+ if b {
+ for i := len(p.oe) - 1; i >= 0; i-- {
+ n := p.oe[i]
+ if n.Namespace == "" || htmlIntegrationPoint(n) || mathMLTextIntegrationPoint(n) {
+ p.oe = p.oe[:i+1]
+ break
+ }
+ }
+ return false
+ }
+ switch p.top().Namespace {
+ case "math":
+ adjustAttributeNames(p.tok.Attr, mathMLAttributeAdjustments)
+ case "svg":
+ // Adjust SVG tag names. The tokenizer lower-cases tag names, but
+ // SVG wants e.g. "foreignObject" with a capital second "O".
+ if x := svgTagNameAdjustments[p.tok.Data]; x != "" {
+ p.tok.DataAtom = a.Lookup([]byte(x))
+ p.tok.Data = x
+ }
+ adjustAttributeNames(p.tok.Attr, svgAttributeAdjustments)
+ default:
+ panic("html: bad parser state: unexpected namespace")
+ }
+ adjustForeignAttributes(p.tok.Attr)
+ namespace := p.top().Namespace
+ p.addElement()
+ p.top().Namespace = namespace
+ if namespace != "" {
+ // Don't let the tokenizer go into raw text mode in foreign content
+ // (e.g. in an SVG <title> tag).
+ p.tokenizer.NextIsNotRawText()
+ }
+ if p.hasSelfClosingToken {
+ p.oe.pop()
+ p.acknowledgeSelfClosingTag()
+ }
+ case EndTagToken:
+ for i := len(p.oe) - 1; i >= 0; i-- {
+ if p.oe[i].Namespace == "" {
+ return p.im(p)
+ }
+ if strings.EqualFold(p.oe[i].Data, p.tok.Data) {
+ p.oe = p.oe[:i]
+ break
+ }
+ }
+ return true
+ default:
+ // Ignore the token.
+ }
+ return true
+}
+
+// Section 12.2.5.
+func (p *parser) inForeignContent() bool {
+ if len(p.oe) == 0 {
+ return false
+ }
+ n := p.oe[len(p.oe)-1]
+ if n.Namespace == "" {
+ return false
+ }
+ if mathMLTextIntegrationPoint(n) {
+ if p.tok.Type == StartTagToken && p.tok.DataAtom != a.Mglyph && p.tok.DataAtom != a.Malignmark {
+ return false
+ }
+ if p.tok.Type == TextToken {
+ return false
+ }
+ }
+ if n.Namespace == "math" && n.DataAtom == a.AnnotationXml && p.tok.Type == StartTagToken && p.tok.DataAtom == a.Svg {
+ return false
+ }
+ if htmlIntegrationPoint(n) && (p.tok.Type == StartTagToken || p.tok.Type == TextToken) {
+ return false
+ }
+ if p.tok.Type == ErrorToken {
+ return false
+ }
+ return true
+}
+
+// parseImpliedToken parses a token as though it had appeared in the parser's
+// input.
+func (p *parser) parseImpliedToken(t TokenType, dataAtom a.Atom, data string) {
+ realToken, selfClosing := p.tok, p.hasSelfClosingToken
+ p.tok = Token{
+ Type: t,
+ DataAtom: dataAtom,
+ Data: data,
+ }
+ p.hasSelfClosingToken = false
+ p.parseCurrentToken()
+ p.tok, p.hasSelfClosingToken = realToken, selfClosing
+}
+
+// parseCurrentToken runs the current token through the parsing routines
+// until it is consumed.
+func (p *parser) parseCurrentToken() {
+ if p.tok.Type == SelfClosingTagToken {
+ p.hasSelfClosingToken = true
+ p.tok.Type = StartTagToken
+ }
+
+ consumed := false
+ for !consumed {
+ if p.inForeignContent() {
+ consumed = parseForeignContent(p)
+ } else {
+ consumed = p.im(p)
+ }
+ }
+
+ if p.hasSelfClosingToken {
+ // This is a parse error, but ignore it.
+ p.hasSelfClosingToken = false
+ }
+}
+
+func (p *parser) parse() error {
+ // Iterate until EOF. Any other error will cause an early return.
+ var err error
+ for err != io.EOF {
+ // CDATA sections are allowed only in foreign content.
+ n := p.oe.top()
+ p.tokenizer.AllowCDATA(n != nil && n.Namespace != "")
+ // Read and parse the next token.
+ p.tokenizer.Next()
+ p.tok = p.tokenizer.Token()
+ if p.tok.Type == ErrorToken {
+ err = p.tokenizer.Err()
+ if err != nil && err != io.EOF {
+ return err
+ }
+ }
+ p.parseCurrentToken()
+ }
+ return nil
+}
+
+// Parse returns the parse tree for the HTML from the given Reader.
+// The input is assumed to be UTF-8 encoded.
+func Parse(r io.Reader) (*Node, error) {
+ p := &parser{
+ tokenizer: NewTokenizer(r),
+ doc: &Node{
+ Type: DocumentNode,
+ },
+ scripting: true,
+ framesetOK: true,
+ im: initialIM,
+ }
+ err := p.parse()
+ if err != nil {
+ return nil, err
+ }
+ return p.doc, nil
+}
+
+// ParseFragment parses a fragment of HTML and returns the nodes that were
+// found. If the fragment is the InnerHTML for an existing element, pass that
+// element in context.
+func ParseFragment(r io.Reader, context *Node) ([]*Node, error) {
+ contextTag := ""
+ if context != nil {
+ if context.Type != ElementNode {
+ return nil, errors.New("html: ParseFragment of non-element Node")
+ }
+ // The next check isn't just context.DataAtom.String() == context.Data because
+ // it is valid to pass an element whose tag isn't a known atom. For example,
+ // DataAtom == 0 and Data = "tagfromthefuture" is perfectly consistent.
+ if context.DataAtom != a.Lookup([]byte(context.Data)) {
+ return nil, fmt.Errorf("html: inconsistent Node: DataAtom=%q, Data=%q", context.DataAtom, context.Data)
+ }
+ contextTag = context.DataAtom.String()
+ }
+ p := &parser{
+ tokenizer: NewTokenizerFragment(r, contextTag),
+ doc: &Node{
+ Type: DocumentNode,
+ },
+ scripting: true,
+ fragment: true,
+ context: context,
+ }
+
+ root := &Node{
+ Type: ElementNode,
+ DataAtom: a.Html,
+ Data: a.Html.String(),
+ }
+ p.doc.AppendChild(root)
+ p.oe = nodeStack{root}
+ p.resetInsertionMode()
+
+ for n := context; n != nil; n = n.Parent {
+ if n.Type == ElementNode && n.DataAtom == a.Form {
+ p.form = n
+ break
+ }
+ }
+
+ err := p.parse()
+ if err != nil {
+ return nil, err
+ }
+
+ parent := p.doc
+ if context != nil {
+ parent = root
+ }
+
+ var result []*Node
+ for c := parent.FirstChild; c != nil; {
+ next := c.NextSibling
+ parent.RemoveChild(c)
+ result = append(result, c)
+ c = next
+ }
+ return result, nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/parse_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/parse_test.go
new file mode 100644
index 000000000..7e47d11be
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/parse_test.go
@@ -0,0 +1,388 @@
+// Copyright 2010 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 html
+
+import (
+ "bufio"
+ "bytes"
+ "errors"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "runtime"
+ "sort"
+ "strings"
+ "testing"
+
+ "golang.org/x/net/html/atom"
+)
+
+// readParseTest reads a single test case from r.
+func readParseTest(r *bufio.Reader) (text, want, context string, err error) {
+ line, err := r.ReadSlice('\n')
+ if err != nil {
+ return "", "", "", err
+ }
+ var b []byte
+
+ // Read the HTML.
+ if string(line) != "#data\n" {
+ return "", "", "", fmt.Errorf(`got %q want "#data\n"`, line)
+ }
+ for {
+ line, err = r.ReadSlice('\n')
+ if err != nil {
+ return "", "", "", err
+ }
+ if line[0] == '#' {
+ break
+ }
+ b = append(b, line...)
+ }
+ text = strings.TrimSuffix(string(b), "\n")
+ b = b[:0]
+
+ // Skip the error list.
+ if string(line) != "#errors\n" {
+ return "", "", "", fmt.Errorf(`got %q want "#errors\n"`, line)
+ }
+ for {
+ line, err = r.ReadSlice('\n')
+ if err != nil {
+ return "", "", "", err
+ }
+ if line[0] == '#' {
+ break
+ }
+ }
+
+ if string(line) == "#document-fragment\n" {
+ line, err = r.ReadSlice('\n')
+ if err != nil {
+ return "", "", "", err
+ }
+ context = strings.TrimSpace(string(line))
+ line, err = r.ReadSlice('\n')
+ if err != nil {
+ return "", "", "", err
+ }
+ }
+
+ // Read the dump of what the parse tree should be.
+ if string(line) != "#document\n" {
+ return "", "", "", fmt.Errorf(`got %q want "#document\n"`, line)
+ }
+ inQuote := false
+ for {
+ line, err = r.ReadSlice('\n')
+ if err != nil && err != io.EOF {
+ return "", "", "", err
+ }
+ trimmed := bytes.Trim(line, "| \n")
+ if len(trimmed) > 0 {
+ if line[0] == '|' && trimmed[0] == '"' {
+ inQuote = true
+ }
+ if trimmed[len(trimmed)-1] == '"' && !(line[0] == '|' && len(trimmed) == 1) {
+ inQuote = false
+ }
+ }
+ if len(line) == 0 || len(line) == 1 && line[0] == '\n' && !inQuote {
+ break
+ }
+ b = append(b, line...)
+ }
+ return text, string(b), context, nil
+}
+
+func dumpIndent(w io.Writer, level int) {
+ io.WriteString(w, "| ")
+ for i := 0; i < level; i++ {
+ io.WriteString(w, " ")
+ }
+}
+
+type sortedAttributes []Attribute
+
+func (a sortedAttributes) Len() int {
+ return len(a)
+}
+
+func (a sortedAttributes) Less(i, j int) bool {
+ if a[i].Namespace != a[j].Namespace {
+ return a[i].Namespace < a[j].Namespace
+ }
+ return a[i].Key < a[j].Key
+}
+
+func (a sortedAttributes) Swap(i, j int) {
+ a[i], a[j] = a[j], a[i]
+}
+
+func dumpLevel(w io.Writer, n *Node, level int) error {
+ dumpIndent(w, level)
+ switch n.Type {
+ case ErrorNode:
+ return errors.New("unexpected ErrorNode")
+ case DocumentNode:
+ return errors.New("unexpected DocumentNode")
+ case ElementNode:
+ if n.Namespace != "" {
+ fmt.Fprintf(w, "<%s %s>", n.Namespace, n.Data)
+ } else {
+ fmt.Fprintf(w, "<%s>", n.Data)
+ }
+ attr := sortedAttributes(n.Attr)
+ sort.Sort(attr)
+ for _, a := range attr {
+ io.WriteString(w, "\n")
+ dumpIndent(w, level+1)
+ if a.Namespace != "" {
+ fmt.Fprintf(w, `%s %s="%s"`, a.Namespace, a.Key, a.Val)
+ } else {
+ fmt.Fprintf(w, `%s="%s"`, a.Key, a.Val)
+ }
+ }
+ case TextNode:
+ fmt.Fprintf(w, `"%s"`, n.Data)
+ case CommentNode:
+ fmt.Fprintf(w, "<!-- %s -->", n.Data)
+ case DoctypeNode:
+ fmt.Fprintf(w, "<!DOCTYPE %s", n.Data)
+ if n.Attr != nil {
+ var p, s string
+ for _, a := range n.Attr {
+ switch a.Key {
+ case "public":
+ p = a.Val
+ case "system":
+ s = a.Val
+ }
+ }
+ if p != "" || s != "" {
+ fmt.Fprintf(w, ` "%s"`, p)
+ fmt.Fprintf(w, ` "%s"`, s)
+ }
+ }
+ io.WriteString(w, ">")
+ case scopeMarkerNode:
+ return errors.New("unexpected scopeMarkerNode")
+ default:
+ return errors.New("unknown node type")
+ }
+ io.WriteString(w, "\n")
+ for c := n.FirstChild; c != nil; c = c.NextSibling {
+ if err := dumpLevel(w, c, level+1); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func dump(n *Node) (string, error) {
+ if n == nil || n.FirstChild == nil {
+ return "", nil
+ }
+ var b bytes.Buffer
+ for c := n.FirstChild; c != nil; c = c.NextSibling {
+ if err := dumpLevel(&b, c, 0); err != nil {
+ return "", err
+ }
+ }
+ return b.String(), nil
+}
+
+const testDataDir = "testdata/webkit/"
+
+func TestParser(t *testing.T) {
+ testFiles, err := filepath.Glob(testDataDir + "*.dat")
+ if err != nil {
+ t.Fatal(err)
+ }
+ for _, tf := range testFiles {
+ f, err := os.Open(tf)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer f.Close()
+ r := bufio.NewReader(f)
+
+ for i := 0; ; i++ {
+ text, want, context, err := readParseTest(r)
+ if err == io.EOF {
+ break
+ }
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ err = testParseCase(text, want, context)
+
+ if err != nil {
+ t.Errorf("%s test #%d %q, %s", tf, i, text, err)
+ }
+ }
+ }
+}
+
+// testParseCase tests one test case from the test files. If the test does not
+// pass, it returns an error that explains the failure.
+// text is the HTML to be parsed, want is a dump of the correct parse tree,
+// and context is the name of the context node, if any.
+func testParseCase(text, want, context string) (err error) {
+ defer func() {
+ if x := recover(); x != nil {
+ switch e := x.(type) {
+ case error:
+ err = e
+ default:
+ err = fmt.Errorf("%v", e)
+ }
+ }
+ }()
+
+ var doc *Node
+ if context == "" {
+ doc, err = Parse(strings.NewReader(text))
+ if err != nil {
+ return err
+ }
+ } else {
+ contextNode := &Node{
+ Type: ElementNode,
+ DataAtom: atom.Lookup([]byte(context)),
+ Data: context,
+ }
+ nodes, err := ParseFragment(strings.NewReader(text), contextNode)
+ if err != nil {
+ return err
+ }
+ doc = &Node{
+ Type: DocumentNode,
+ }
+ for _, n := range nodes {
+ doc.AppendChild(n)
+ }
+ }
+
+ if err := checkTreeConsistency(doc); err != nil {
+ return err
+ }
+
+ got, err := dump(doc)
+ if err != nil {
+ return err
+ }
+ // Compare the parsed tree to the #document section.
+ if got != want {
+ return fmt.Errorf("got vs want:\n----\n%s----\n%s----", got, want)
+ }
+
+ if renderTestBlacklist[text] || context != "" {
+ return nil
+ }
+
+ // Check that rendering and re-parsing results in an identical tree.
+ pr, pw := io.Pipe()
+ go func() {
+ pw.CloseWithError(Render(pw, doc))
+ }()
+ doc1, err := Parse(pr)
+ if err != nil {
+ return err
+ }
+ got1, err := dump(doc1)
+ if err != nil {
+ return err
+ }
+ if got != got1 {
+ return fmt.Errorf("got vs got1:\n----\n%s----\n%s----", got, got1)
+ }
+
+ return nil
+}
+
+// Some test input result in parse trees are not 'well-formed' despite
+// following the HTML5 recovery algorithms. Rendering and re-parsing such a
+// tree will not result in an exact clone of that tree. We blacklist such
+// inputs from the render test.
+var renderTestBlacklist = map[string]bool{
+ // The second <a> will be reparented to the first <table>'s parent. This
+ // results in an <a> whose parent is an <a>, which is not 'well-formed'.
+ `<a><table><td><a><table></table><a></tr><a></table><b>X</b>C<a>Y`: true,
+ // The same thing with a <p>:
+ `<p><table></p>`: true,
+ // More cases of <a> being reparented:
+ `<a href="blah">aba<table><a href="foo">br<tr><td></td></tr>x</table>aoe`: true,
+ `<a><table><a></table><p><a><div><a>`: true,
+ `<a><table><td><a><table></table><a></tr><a></table><a>`: true,
+ // A similar reparenting situation involving <nobr>:
+ `<!DOCTYPE html><body><b><nobr>1<table><nobr></b><i><nobr>2<nobr></i>3`: true,
+ // A <plaintext> element is reparented, putting it before a table.
+ // A <plaintext> element can't have anything after it in HTML.
+ `<table><plaintext><td>`: true,
+ `<!doctype html><table><plaintext></plaintext>`: true,
+ `<!doctype html><table><tbody><plaintext></plaintext>`: true,
+ `<!doctype html><table><tbody><tr><plaintext></plaintext>`: true,
+ // A form inside a table inside a form doesn't work either.
+ `<!doctype html><form><table></form><form></table></form>`: true,
+ // A script that ends at EOF may escape its own closing tag when rendered.
+ `<!doctype html><script><!--<script `: true,
+ `<!doctype html><script><!--<script <`: true,
+ `<!doctype html><script><!--<script <a`: true,
+ `<!doctype html><script><!--<script </`: true,
+ `<!doctype html><script><!--<script </s`: true,
+ `<!doctype html><script><!--<script </script`: true,
+ `<!doctype html><script><!--<script </scripta`: true,
+ `<!doctype html><script><!--<script -`: true,
+ `<!doctype html><script><!--<script -a`: true,
+ `<!doctype html><script><!--<script -<`: true,
+ `<!doctype html><script><!--<script --`: true,
+ `<!doctype html><script><!--<script --a`: true,
+ `<!doctype html><script><!--<script --<`: true,
+ `<script><!--<script `: true,
+ `<script><!--<script <a`: true,
+ `<script><!--<script </script`: true,
+ `<script><!--<script </scripta`: true,
+ `<script><!--<script -`: true,
+ `<script><!--<script -a`: true,
+ `<script><!--<script --`: true,
+ `<script><!--<script --a`: true,
+ `<script><!--<script <`: true,
+ `<script><!--<script </`: true,
+ `<script><!--<script </s`: true,
+ // Reconstructing the active formatting elements results in a <plaintext>
+ // element that contains an <a> element.
+ `<!doctype html><p><a><plaintext>b`: true,
+}
+
+func TestNodeConsistency(t *testing.T) {
+ // inconsistentNode is a Node whose DataAtom and Data do not agree.
+ inconsistentNode := &Node{
+ Type: ElementNode,
+ DataAtom: atom.Frameset,
+ Data: "table",
+ }
+ _, err := ParseFragment(strings.NewReader("<p>hello</p>"), inconsistentNode)
+ if err == nil {
+ t.Errorf("got nil error, want non-nil")
+ }
+}
+
+func BenchmarkParser(b *testing.B) {
+ buf, err := ioutil.ReadFile("testdata/go1.html")
+ if err != nil {
+ b.Fatalf("could not read testdata/go1.html: %v", err)
+ }
+ b.SetBytes(int64(len(buf)))
+ runtime.GC()
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ Parse(bytes.NewBuffer(buf))
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/render.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/render.go
new file mode 100644
index 000000000..d34564f49
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/render.go
@@ -0,0 +1,271 @@
+// Copyright 2011 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 html
+
+import (
+ "bufio"
+ "errors"
+ "fmt"
+ "io"
+ "strings"
+)
+
+type writer interface {
+ io.Writer
+ io.ByteWriter
+ WriteString(string) (int, error)
+}
+
+// Render renders the parse tree n to the given writer.
+//
+// Rendering is done on a 'best effort' basis: calling Parse on the output of
+// Render will always result in something similar to the original tree, but it
+// is not necessarily an exact clone unless the original tree was 'well-formed'.
+// 'Well-formed' is not easily specified; the HTML5 specification is
+// complicated.
+//
+// Calling Parse on arbitrary input typically results in a 'well-formed' parse
+// tree. However, it is possible for Parse to yield a 'badly-formed' parse tree.
+// For example, in a 'well-formed' parse tree, no <a> element is a child of
+// another <a> element: parsing "<a><a>" results in two sibling elements.
+// Similarly, in a 'well-formed' parse tree, no <a> element is a child of a
+// <table> element: parsing "<p><table><a>" results in a <p> with two sibling
+// children; the <a> is reparented to the <table>'s parent. However, calling
+// Parse on "<a><table><a>" does not return an error, but the result has an <a>
+// element with an <a> child, and is therefore not 'well-formed'.
+//
+// Programmatically constructed trees are typically also 'well-formed', but it
+// is possible to construct a tree that looks innocuous but, when rendered and
+// re-parsed, results in a different tree. A simple example is that a solitary
+// text node would become a tree containing <html>, <head> and <body> elements.
+// Another example is that the programmatic equivalent of "a<head>b</head>c"
+// becomes "<html><head><head/><body>abc</body></html>".
+func Render(w io.Writer, n *Node) error {
+ if x, ok := w.(writer); ok {
+ return render(x, n)
+ }
+ buf := bufio.NewWriter(w)
+ if err := render(buf, n); err != nil {
+ return err
+ }
+ return buf.Flush()
+}
+
+// plaintextAbort is returned from render1 when a <plaintext> element
+// has been rendered. No more end tags should be rendered after that.
+var plaintextAbort = errors.New("html: internal error (plaintext abort)")
+
+func render(w writer, n *Node) error {
+ err := render1(w, n)
+ if err == plaintextAbort {
+ err = nil
+ }
+ return err
+}
+
+func render1(w writer, n *Node) error {
+ // Render non-element nodes; these are the easy cases.
+ switch n.Type {
+ case ErrorNode:
+ return errors.New("html: cannot render an ErrorNode node")
+ case TextNode:
+ return escape(w, n.Data)
+ case DocumentNode:
+ for c := n.FirstChild; c != nil; c = c.NextSibling {
+ if err := render1(w, c); err != nil {
+ return err
+ }
+ }
+ return nil
+ case ElementNode:
+ // No-op.
+ case CommentNode:
+ if _, err := w.WriteString("<!--"); err != nil {
+ return err
+ }
+ if _, err := w.WriteString(n.Data); err != nil {
+ return err
+ }
+ if _, err := w.WriteString("-->"); err != nil {
+ return err
+ }
+ return nil
+ case DoctypeNode:
+ if _, err := w.WriteString("<!DOCTYPE "); err != nil {
+ return err
+ }
+ if _, err := w.WriteString(n.Data); err != nil {
+ return err
+ }
+ if n.Attr != nil {
+ var p, s string
+ for _, a := range n.Attr {
+ switch a.Key {
+ case "public":
+ p = a.Val
+ case "system":
+ s = a.Val
+ }
+ }
+ if p != "" {
+ if _, err := w.WriteString(" PUBLIC "); err != nil {
+ return err
+ }
+ if err := writeQuoted(w, p); err != nil {
+ return err
+ }
+ if s != "" {
+ if err := w.WriteByte(' '); err != nil {
+ return err
+ }
+ if err := writeQuoted(w, s); err != nil {
+ return err
+ }
+ }
+ } else if s != "" {
+ if _, err := w.WriteString(" SYSTEM "); err != nil {
+ return err
+ }
+ if err := writeQuoted(w, s); err != nil {
+ return err
+ }
+ }
+ }
+ return w.WriteByte('>')
+ default:
+ return errors.New("html: unknown node type")
+ }
+
+ // Render the <xxx> opening tag.
+ if err := w.WriteByte('<'); err != nil {
+ return err
+ }
+ if _, err := w.WriteString(n.Data); err != nil {
+ return err
+ }
+ for _, a := range n.Attr {
+ if err := w.WriteByte(' '); err != nil {
+ return err
+ }
+ if a.Namespace != "" {
+ if _, err := w.WriteString(a.Namespace); err != nil {
+ return err
+ }
+ if err := w.WriteByte(':'); err != nil {
+ return err
+ }
+ }
+ if _, err := w.WriteString(a.Key); err != nil {
+ return err
+ }
+ if _, err := w.WriteString(`="`); err != nil {
+ return err
+ }
+ if err := escape(w, a.Val); err != nil {
+ return err
+ }
+ if err := w.WriteByte('"'); err != nil {
+ return err
+ }
+ }
+ if voidElements[n.Data] {
+ if n.FirstChild != nil {
+ return fmt.Errorf("html: void element <%s> has child nodes", n.Data)
+ }
+ _, err := w.WriteString("/>")
+ return err
+ }
+ if err := w.WriteByte('>'); err != nil {
+ return err
+ }
+
+ // Add initial newline where there is danger of a newline beging ignored.
+ if c := n.FirstChild; c != nil && c.Type == TextNode && strings.HasPrefix(c.Data, "\n") {
+ switch n.Data {
+ case "pre", "listing", "textarea":
+ if err := w.WriteByte('\n'); err != nil {
+ return err
+ }
+ }
+ }
+
+ // Render any child nodes.
+ switch n.Data {
+ case "iframe", "noembed", "noframes", "noscript", "plaintext", "script", "style", "xmp":
+ for c := n.FirstChild; c != nil; c = c.NextSibling {
+ if c.Type == TextNode {
+ if _, err := w.WriteString(c.Data); err != nil {
+ return err
+ }
+ } else {
+ if err := render1(w, c); err != nil {
+ return err
+ }
+ }
+ }
+ if n.Data == "plaintext" {
+ // Don't render anything else. <plaintext> must be the
+ // last element in the file, with no closing tag.
+ return plaintextAbort
+ }
+ default:
+ for c := n.FirstChild; c != nil; c = c.NextSibling {
+ if err := render1(w, c); err != nil {
+ return err
+ }
+ }
+ }
+
+ // Render the </xxx> closing tag.
+ if _, err := w.WriteString("</"); err != nil {
+ return err
+ }
+ if _, err := w.WriteString(n.Data); err != nil {
+ return err
+ }
+ return w.WriteByte('>')
+}
+
+// writeQuoted writes s to w surrounded by quotes. Normally it will use double
+// quotes, but if s contains a double quote, it will use single quotes.
+// It is used for writing the identifiers in a doctype declaration.
+// In valid HTML, they can't contain both types of quotes.
+func writeQuoted(w writer, s string) error {
+ var q byte = '"'
+ if strings.Contains(s, `"`) {
+ q = '\''
+ }
+ if err := w.WriteByte(q); err != nil {
+ return err
+ }
+ if _, err := w.WriteString(s); err != nil {
+ return err
+ }
+ if err := w.WriteByte(q); err != nil {
+ return err
+ }
+ return nil
+}
+
+// Section 12.1.2, "Elements", gives this list of void elements. Void elements
+// are those that can't have any contents.
+var voidElements = map[string]bool{
+ "area": true,
+ "base": true,
+ "br": true,
+ "col": true,
+ "command": true,
+ "embed": true,
+ "hr": true,
+ "img": true,
+ "input": true,
+ "keygen": true,
+ "link": true,
+ "meta": true,
+ "param": true,
+ "source": true,
+ "track": true,
+ "wbr": true,
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/render_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/render_test.go
new file mode 100644
index 000000000..11da54b31
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/render_test.go
@@ -0,0 +1,156 @@
+// Copyright 2010 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 html
+
+import (
+ "bytes"
+ "testing"
+)
+
+func TestRenderer(t *testing.T) {
+ nodes := [...]*Node{
+ 0: {
+ Type: ElementNode,
+ Data: "html",
+ },
+ 1: {
+ Type: ElementNode,
+ Data: "head",
+ },
+ 2: {
+ Type: ElementNode,
+ Data: "body",
+ },
+ 3: {
+ Type: TextNode,
+ Data: "0<1",
+ },
+ 4: {
+ Type: ElementNode,
+ Data: "p",
+ Attr: []Attribute{
+ {
+ Key: "id",
+ Val: "A",
+ },
+ {
+ Key: "foo",
+ Val: `abc"def`,
+ },
+ },
+ },
+ 5: {
+ Type: TextNode,
+ Data: "2",
+ },
+ 6: {
+ Type: ElementNode,
+ Data: "b",
+ Attr: []Attribute{
+ {
+ Key: "empty",
+ Val: "",
+ },
+ },
+ },
+ 7: {
+ Type: TextNode,
+ Data: "3",
+ },
+ 8: {
+ Type: ElementNode,
+ Data: "i",
+ Attr: []Attribute{
+ {
+ Key: "backslash",
+ Val: `\`,
+ },
+ },
+ },
+ 9: {
+ Type: TextNode,
+ Data: "&4",
+ },
+ 10: {
+ Type: TextNode,
+ Data: "5",
+ },
+ 11: {
+ Type: ElementNode,
+ Data: "blockquote",
+ },
+ 12: {
+ Type: ElementNode,
+ Data: "br",
+ },
+ 13: {
+ Type: TextNode,
+ Data: "6",
+ },
+ }
+
+ // Build a tree out of those nodes, based on a textual representation.
+ // Only the ".\t"s are significant. The trailing HTML-like text is
+ // just commentary. The "0:" prefixes are for easy cross-reference with
+ // the nodes array.
+ treeAsText := [...]string{
+ 0: `<html>`,
+ 1: `. <head>`,
+ 2: `. <body>`,
+ 3: `. . "0&lt;1"`,
+ 4: `. . <p id="A" foo="abc&#34;def">`,
+ 5: `. . . "2"`,
+ 6: `. . . <b empty="">`,
+ 7: `. . . . "3"`,
+ 8: `. . . <i backslash="\">`,
+ 9: `. . . . "&amp;4"`,
+ 10: `. . "5"`,
+ 11: `. . <blockquote>`,
+ 12: `. . <br>`,
+ 13: `. . "6"`,
+ }
+ if len(nodes) != len(treeAsText) {
+ t.Fatal("len(nodes) != len(treeAsText)")
+ }
+ var stack [8]*Node
+ for i, line := range treeAsText {
+ level := 0
+ for line[0] == '.' {
+ // Strip a leading ".\t".
+ line = line[2:]
+ level++
+ }
+ n := nodes[i]
+ if level == 0 {
+ if stack[0] != nil {
+ t.Fatal("multiple root nodes")
+ }
+ stack[0] = n
+ } else {
+ stack[level-1].AppendChild(n)
+ stack[level] = n
+ for i := level + 1; i < len(stack); i++ {
+ stack[i] = nil
+ }
+ }
+ // At each stage of tree construction, we check all nodes for consistency.
+ for j, m := range nodes {
+ if err := checkNodeConsistency(m); err != nil {
+ t.Fatalf("i=%d, j=%d: %v", i, j, err)
+ }
+ }
+ }
+
+ want := `<html><head></head><body>0&lt;1<p id="A" foo="abc&#34;def">` +
+ `2<b empty="">3</b><i backslash="\">&amp;4</i></p>` +
+ `5<blockquote></blockquote><br/>6</body></html>`
+ b := new(bytes.Buffer)
+ if err := Render(b, nodes[0]); err != nil {
+ t.Fatal(err)
+ }
+ if got := b.String(); got != want {
+ t.Errorf("got vs want:\n%s\n%s\n", got, want)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/go1.html b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/go1.html
new file mode 100644
index 000000000..d238257c3
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/go1.html
@@ -0,0 +1,2237 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+
+ <title>Go 1 Release Notes - The Go Programming Language</title>
+
+<link type="text/css" rel="stylesheet" href="/doc/style.css">
+<script type="text/javascript" src="/doc/godocs.js"></script>
+
+<link rel="search" type="application/opensearchdescription+xml" title="godoc" href="/opensearch.xml" />
+
+<script type="text/javascript">
+var _gaq = _gaq || [];
+_gaq.push(["_setAccount", "UA-11222381-2"]);
+_gaq.push(["_trackPageview"]);
+</script>
+</head>
+<body>
+
+<div id="topbar"><div class="container wide">
+
+<form method="GET" action="/search">
+<div id="menu">
+<a href="/doc/">Documents</a>
+<a href="/ref/">References</a>
+<a href="/pkg/">Packages</a>
+<a href="/project/">The Project</a>
+<a href="/help/">Help</a>
+<input type="text" id="search" name="q" class="inactive" value="Search">
+</div>
+<div id="heading"><a href="/">The Go Programming Language</a></div>
+</form>
+
+</div></div>
+
+<div id="page" class="wide">
+
+
+ <div id="plusone"><g:plusone size="small" annotation="none"></g:plusone></div>
+ <h1>Go 1 Release Notes</h1>
+
+
+
+
+<div id="nav"></div>
+
+
+
+
+<h2 id="introduction">Introduction to Go 1</h2>
+
+<p>
+Go version 1, Go 1 for short, defines a language and a set of core libraries
+that provide a stable foundation for creating reliable products, projects, and
+publications.
+</p>
+
+<p>
+The driving motivation for Go 1 is stability for its users. People should be able to
+write Go programs and expect that they will continue to compile and run without
+change, on a time scale of years, including in production environments such as
+Google App Engine. Similarly, people should be able to write books about Go, be
+able to say which version of Go the book is describing, and have that version
+number still be meaningful much later.
+</p>
+
+<p>
+Code that compiles in Go 1 should, with few exceptions, continue to compile and
+run throughout the lifetime of that version, even as we issue updates and bug
+fixes such as Go version 1.1, 1.2, and so on. Other than critical fixes, changes
+made to the language and library for subsequent releases of Go 1 may
+add functionality but will not break existing Go 1 programs.
+<a href="go1compat.html">The Go 1 compatibility document</a>
+explains the compatibility guidelines in more detail.
+</p>
+
+<p>
+Go 1 is a representation of Go as it used today, not a wholesale rethinking of
+the language. We avoided designing new features and instead focused on cleaning
+up problems and inconsistencies and improving portability. There are a number
+changes to the Go language and packages that we had considered for some time and
+prototyped but not released primarily because they are significant and
+backwards-incompatible. Go 1 was an opportunity to get them out, which is
+helpful for the long term, but also means that Go 1 introduces incompatibilities
+for old programs. Fortunately, the <code>go</code> <code>fix</code> tool can
+automate much of the work needed to bring programs up to the Go 1 standard.
+</p>
+
+<p>
+This document outlines the major changes in Go 1 that will affect programmers
+updating existing code; its reference point is the prior release, r60 (tagged as
+r60.3). It also explains how to update code from r60 to run under Go 1.
+</p>
+
+<h2 id="language">Changes to the language</h2>
+
+<h3 id="append">Append</h3>
+
+<p>
+The <code>append</code> predeclared variadic function makes it easy to grow a slice
+by adding elements to the end.
+A common use is to add bytes to the end of a byte slice when generating output.
+However, <code>append</code> did not provide a way to append a string to a <code>[]byte</code>,
+which is another common case.
+</p>
+
+<pre><!--{{code "/doc/progs/go1.go" `/greeting := ..byte/` `/append.*hello/`}}
+--> greeting := []byte{}
+ greeting = append(greeting, []byte(&#34;hello &#34;)...)</pre>
+
+<p>
+By analogy with the similar property of <code>copy</code>, Go 1
+permits a string to be appended (byte-wise) directly to a byte
+slice, reducing the friction between strings and byte slices.
+The conversion is no longer necessary:
+</p>
+
+<pre><!--{{code "/doc/progs/go1.go" `/append.*world/`}}
+--> greeting = append(greeting, &#34;world&#34;...)</pre>
+
+<p>
+<em>Updating</em>:
+This is a new feature, so existing code needs no changes.
+</p>
+
+<h3 id="close">Close</h3>
+
+<p>
+The <code>close</code> predeclared function provides a mechanism
+for a sender to signal that no more values will be sent.
+It is important to the implementation of <code>for</code> <code>range</code>
+loops over channels and is helpful in other situations.
+Partly by design and partly because of race conditions that can occur otherwise,
+it is intended for use only by the goroutine sending on the channel,
+not by the goroutine receiving data.
+However, before Go 1 there was no compile-time checking that <code>close</code>
+was being used correctly.
+</p>
+
+<p>
+To close this gap, at least in part, Go 1 disallows <code>close</code> on receive-only channels.
+Attempting to close such a channel is a compile-time error.
+</p>
+
+<pre>
+ var c chan int
+ var csend chan&lt;- int = c
+ var crecv &lt;-chan int = c
+ close(c) // legal
+ close(csend) // legal
+ close(crecv) // illegal
+</pre>
+
+<p>
+<em>Updating</em>:
+Existing code that attempts to close a receive-only channel was
+erroneous even before Go 1 and should be fixed. The compiler will
+now reject such code.
+</p>
+
+<h3 id="literals">Composite literals</h3>
+
+<p>
+In Go 1, a composite literal of array, slice, or map type can elide the
+type specification for the elements' initializers if they are of pointer type.
+All four of the initializations in this example are legal; the last one was illegal before Go 1.
+</p>
+
+<pre><!--{{code "/doc/progs/go1.go" `/type Date struct/` `/STOP/`}}
+--> type Date struct {
+ month string
+ day int
+ }
+ <span class="comment">// Struct values, fully qualified; always legal.</span>
+ holiday1 := []Date{
+ Date{&#34;Feb&#34;, 14},
+ Date{&#34;Nov&#34;, 11},
+ Date{&#34;Dec&#34;, 25},
+ }
+ <span class="comment">// Struct values, type name elided; always legal.</span>
+ holiday2 := []Date{
+ {&#34;Feb&#34;, 14},
+ {&#34;Nov&#34;, 11},
+ {&#34;Dec&#34;, 25},
+ }
+ <span class="comment">// Pointers, fully qualified, always legal.</span>
+ holiday3 := []*Date{
+ &amp;Date{&#34;Feb&#34;, 14},
+ &amp;Date{&#34;Nov&#34;, 11},
+ &amp;Date{&#34;Dec&#34;, 25},
+ }
+ <span class="comment">// Pointers, type name elided; legal in Go 1.</span>
+ holiday4 := []*Date{
+ {&#34;Feb&#34;, 14},
+ {&#34;Nov&#34;, 11},
+ {&#34;Dec&#34;, 25},
+ }</pre>
+
+<p>
+<em>Updating</em>:
+This change has no effect on existing code, but the command
+<code>gofmt</code> <code>-s</code> applied to existing source
+will, among other things, elide explicit element types wherever permitted.
+</p>
+
+
+<h3 id="init">Goroutines during init</h3>
+
+<p>
+The old language defined that <code>go</code> statements executed during initialization created goroutines but that they did not begin to run until initialization of the entire program was complete.
+This introduced clumsiness in many places and, in effect, limited the utility
+of the <code>init</code> construct:
+if it was possible for another package to use the library during initialization, the library
+was forced to avoid goroutines.
+This design was done for reasons of simplicity and safety but,
+as our confidence in the language grew, it seemed unnecessary.
+Running goroutines during initialization is no more complex or unsafe than running them during normal execution.
+</p>
+
+<p>
+In Go 1, code that uses goroutines can be called from
+<code>init</code> routines and global initialization expressions
+without introducing a deadlock.
+</p>
+
+<pre><!--{{code "/doc/progs/go1.go" `/PackageGlobal/` `/^}/`}}
+-->var PackageGlobal int
+
+func init() {
+ c := make(chan int)
+ go initializationFunction(c)
+ PackageGlobal = &lt;-c
+}</pre>
+
+<p>
+<em>Updating</em>:
+This is a new feature, so existing code needs no changes,
+although it's possible that code that depends on goroutines not starting before <code>main</code> will break.
+There was no such code in the standard repository.
+</p>
+
+<h3 id="rune">The rune type</h3>
+
+<p>
+The language spec allows the <code>int</code> type to be 32 or 64 bits wide, but current implementations set <code>int</code> to 32 bits even on 64-bit platforms.
+It would be preferable to have <code>int</code> be 64 bits on 64-bit platforms.
+(There are important consequences for indexing large slices.)
+However, this change would waste space when processing Unicode characters with
+the old language because the <code>int</code> type was also used to hold Unicode code points: each code point would waste an extra 32 bits of storage if <code>int</code> grew from 32 bits to 64.
+</p>
+
+<p>
+To make changing to 64-bit <code>int</code> feasible,
+Go 1 introduces a new basic type, <code>rune</code>, to represent
+individual Unicode code points.
+It is an alias for <code>int32</code>, analogous to <code>byte</code>
+as an alias for <code>uint8</code>.
+</p>
+
+<p>
+Character literals such as <code>'a'</code>, <code>'語'</code>, and <code>'\u0345'</code>
+now have default type <code>rune</code>,
+analogous to <code>1.0</code> having default type <code>float64</code>.
+A variable initialized to a character constant will therefore
+have type <code>rune</code> unless otherwise specified.
+</p>
+
+<p>
+Libraries have been updated to use <code>rune</code> rather than <code>int</code>
+when appropriate. For instance, the functions <code>unicode.ToLower</code> and
+relatives now take and return a <code>rune</code>.
+</p>
+
+<pre><!--{{code "/doc/progs/go1.go" `/STARTRUNE/` `/ENDRUNE/`}}
+--> delta := &#39;δ&#39; <span class="comment">// delta has type rune.</span>
+ var DELTA rune
+ DELTA = unicode.ToUpper(delta)
+ epsilon := unicode.ToLower(DELTA + 1)
+ if epsilon != &#39;δ&#39;+1 {
+ log.Fatal(&#34;inconsistent casing for Greek&#34;)
+ }</pre>
+
+<p>
+<em>Updating</em>:
+Most source code will be unaffected by this because the type inference from
+<code>:=</code> initializers introduces the new type silently, and it propagates
+from there.
+Some code may get type errors that a trivial conversion will resolve.
+</p>
+
+<h3 id="error">The error type</h3>
+
+<p>
+Go 1 introduces a new built-in type, <code>error</code>, which has the following definition:
+</p>
+
+<pre>
+ type error interface {
+ Error() string
+ }
+</pre>
+
+<p>
+Since the consequences of this type are all in the package library,
+it is discussed <a href="#errors">below</a>.
+</p>
+
+<h3 id="delete">Deleting from maps</h3>
+
+<p>
+In the old language, to delete the entry with key <code>k</code> from map <code>m</code>, one wrote the statement,
+</p>
+
+<pre>
+ m[k] = value, false
+</pre>
+
+<p>
+This syntax was a peculiar special case, the only two-to-one assignment.
+It required passing a value (usually ignored) that is evaluated but discarded,
+plus a boolean that was nearly always the constant <code>false</code>.
+It did the job but was odd and a point of contention.
+</p>
+
+<p>
+In Go 1, that syntax has gone; instead there is a new built-in
+function, <code>delete</code>. The call
+</p>
+
+<pre><!--{{code "/doc/progs/go1.go" `/delete\(m, k\)/`}}
+--> delete(m, k)</pre>
+
+<p>
+will delete the map entry retrieved by the expression <code>m[k]</code>.
+There is no return value. Deleting a non-existent entry is a no-op.
+</p>
+
+<p>
+<em>Updating</em>:
+Running <code>go</code> <code>fix</code> will convert expressions of the form <code>m[k] = value,
+false</code> into <code>delete(m, k)</code> when it is clear that
+the ignored value can be safely discarded from the program and
+<code>false</code> refers to the predefined boolean constant.
+The fix tool
+will flag other uses of the syntax for inspection by the programmer.
+</p>
+
+<h3 id="iteration">Iterating in maps</h3>
+
+<p>
+The old language specification did not define the order of iteration for maps,
+and in practice it differed across hardware platforms.
+This caused tests that iterated over maps to be fragile and non-portable, with the
+unpleasant property that a test might always pass on one machine but break on another.
+</p>
+
+<p>
+In Go 1, the order in which elements are visited when iterating
+over a map using a <code>for</code> <code>range</code> statement
+is defined to be unpredictable, even if the same loop is run multiple
+times with the same map.
+Code should not assume that the elements are visited in any particular order.
+</p>
+
+<p>
+This change means that code that depends on iteration order is very likely to break early and be fixed long before it becomes a problem.
+Just as important, it allows the map implementation to ensure better map balancing even when programs are using range loops to select an element from a map.
+</p>
+
+<pre><!--{{code "/doc/progs/go1.go" `/Sunday/` `/^ }/`}}
+--> m := map[string]int{&#34;Sunday&#34;: 0, &#34;Monday&#34;: 1}
+ for name, value := range m {
+ <span class="comment">// This loop should not assume Sunday will be visited first.</span>
+ f(name, value)
+ }</pre>
+
+<p>
+<em>Updating</em>:
+This is one change where tools cannot help. Most existing code
+will be unaffected, but some programs may break or misbehave; we
+recommend manual checking of all range statements over maps to
+verify they do not depend on iteration order. There were a few such
+examples in the standard repository; they have been fixed.
+Note that it was already incorrect to depend on the iteration order, which
+was unspecified. This change codifies the unpredictability.
+</p>
+
+<h3 id="multiple_assignment">Multiple assignment</h3>
+
+<p>
+The language specification has long guaranteed that in assignments
+the right-hand-side expressions are all evaluated before any left-hand-side expressions are assigned.
+To guarantee predictable behavior,
+Go 1 refines the specification further.
+</p>
+
+<p>
+If the left-hand side of the assignment
+statement contains expressions that require evaluation, such as
+function calls or array indexing operations, these will all be done
+using the usual left-to-right rule before any variables are assigned
+their value. Once everything is evaluated, the actual assignments
+proceed in left-to-right order.
+</p>
+
+<p>
+These examples illustrate the behavior.
+</p>
+
+<pre><!--{{code "/doc/progs/go1.go" `/sa :=/` `/then sc.0. = 2/`}}
+--> sa := []int{1, 2, 3}
+ i := 0
+ i, sa[i] = 1, 2 <span class="comment">// sets i = 1, sa[0] = 2</span>
+
+ sb := []int{1, 2, 3}
+ j := 0
+ sb[j], j = 2, 1 <span class="comment">// sets sb[0] = 2, j = 1</span>
+
+ sc := []int{1, 2, 3}
+ sc[0], sc[0] = 1, 2 <span class="comment">// sets sc[0] = 1, then sc[0] = 2 (so sc[0] = 2 at end)</span></pre>
+
+<p>
+<em>Updating</em>:
+This is one change where tools cannot help, but breakage is unlikely.
+No code in the standard repository was broken by this change, and code
+that depended on the previous unspecified behavior was already incorrect.
+</p>
+
+<h3 id="shadowing">Returns and shadowed variables</h3>
+
+<p>
+A common mistake is to use <code>return</code> (without arguments) after an assignment to a variable that has the same name as a result variable but is not the same variable.
+This situation is called <em>shadowing</em>: the result variable has been shadowed by another variable with the same name declared in an inner scope.
+</p>
+
+<p>
+In functions with named return values,
+the Go 1 compilers disallow return statements without arguments if any of the named return values is shadowed at the point of the return statement.
+(It isn't part of the specification, because this is one area we are still exploring;
+the situation is analogous to the compilers rejecting functions that do not end with an explicit return statement.)
+</p>
+
+<p>
+This function implicitly returns a shadowed return value and will be rejected by the compiler:
+</p>
+
+<pre>
+ func Bug() (i, j, k int) {
+ for i = 0; i &lt; 5; i++ {
+ for j := 0; j &lt; 5; j++ { // Redeclares j.
+ k += i*j
+ if k > 100 {
+ return // Rejected: j is shadowed here.
+ }
+ }
+ }
+ return // OK: j is not shadowed here.
+ }
+</pre>
+
+<p>
+<em>Updating</em>:
+Code that shadows return values in this way will be rejected by the compiler and will need to be fixed by hand.
+The few cases that arose in the standard repository were mostly bugs.
+</p>
+
+<h3 id="unexported">Copying structs with unexported fields</h3>
+
+<p>
+The old language did not allow a package to make a copy of a struct value containing unexported fields belonging to a different package.
+There was, however, a required exception for a method receiver;
+also, the implementations of <code>copy</code> and <code>append</code> have never honored the restriction.
+</p>
+
+<p>
+Go 1 will allow packages to copy struct values containing unexported fields from other packages.
+Besides resolving the inconsistency,
+this change admits a new kind of API: a package can return an opaque value without resorting to a pointer or interface.
+The new implementations of <code>time.Time</code> and
+<code>reflect.Value</code> are examples of types taking advantage of this new property.
+</p>
+
+<p>
+As an example, if package <code>p</code> includes the definitions,
+</p>
+
+<pre>
+ type Struct struct {
+ Public int
+ secret int
+ }
+ func NewStruct(a int) Struct { // Note: not a pointer.
+ return Struct{a, f(a)}
+ }
+ func (s Struct) String() string {
+ return fmt.Sprintf("{%d (secret %d)}", s.Public, s.secret)
+ }
+</pre>
+
+<p>
+a package that imports <code>p</code> can assign and copy values of type
+<code>p.Struct</code> at will.
+Behind the scenes the unexported fields will be assigned and copied just
+as if they were exported,
+but the client code will never be aware of them. The code
+</p>
+
+<pre>
+ import "p"
+
+ myStruct := p.NewStruct(23)
+ copyOfMyStruct := myStruct
+ fmt.Println(myStruct, copyOfMyStruct)
+</pre>
+
+<p>
+will show that the secret field of the struct has been copied to the new value.
+</p>
+
+<p>
+<em>Updating</em>:
+This is a new feature, so existing code needs no changes.
+</p>
+
+<h3 id="equality">Equality</h3>
+
+<p>
+Before Go 1, the language did not define equality on struct and array values.
+This meant,
+among other things, that structs and arrays could not be used as map keys.
+On the other hand, Go did define equality on function and map values.
+Function equality was problematic in the presence of closures
+(when are two closures equal?)
+while map equality compared pointers, not the maps' content, which was usually
+not what the user would want.
+</p>
+
+<p>
+Go 1 addressed these issues.
+First, structs and arrays can be compared for equality and inequality
+(<code>==</code> and <code>!=</code>),
+and therefore be used as map keys,
+provided they are composed from elements for which equality is also defined,
+using element-wise comparison.
+</p>
+
+<pre><!--{{code "/doc/progs/go1.go" `/type Day struct/` `/Printf/`}}
+--> type Day struct {
+ long string
+ short string
+ }
+ Christmas := Day{&#34;Christmas&#34;, &#34;XMas&#34;}
+ Thanksgiving := Day{&#34;Thanksgiving&#34;, &#34;Turkey&#34;}
+ holiday := map[Day]bool{
+ Christmas: true,
+ Thanksgiving: true,
+ }
+ fmt.Printf(&#34;Christmas is a holiday: %t\n&#34;, holiday[Christmas])</pre>
+
+<p>
+Second, Go 1 removes the definition of equality for function values,
+except for comparison with <code>nil</code>.
+Finally, map equality is gone too, also except for comparison with <code>nil</code>.
+</p>
+
+<p>
+Note that equality is still undefined for slices, for which the
+calculation is in general infeasible. Also note that the ordered
+comparison operators (<code>&lt;</code> <code>&lt;=</code>
+<code>&gt;</code> <code>&gt;=</code>) are still undefined for
+structs and arrays.
+
+<p>
+<em>Updating</em>:
+Struct and array equality is a new feature, so existing code needs no changes.
+Existing code that depends on function or map equality will be
+rejected by the compiler and will need to be fixed by hand.
+Few programs will be affected, but the fix may require some
+redesign.
+</p>
+
+<h2 id="packages">The package hierarchy</h2>
+
+<p>
+Go 1 addresses many deficiencies in the old standard library and
+cleans up a number of packages, making them more internally consistent
+and portable.
+</p>
+
+<p>
+This section describes how the packages have been rearranged in Go 1.
+Some have moved, some have been renamed, some have been deleted.
+New packages are described in later sections.
+</p>
+
+<h3 id="hierarchy">The package hierarchy</h3>
+
+<p>
+Go 1 has a rearranged package hierarchy that groups related items
+into subdirectories. For instance, <code>utf8</code> and
+<code>utf16</code> now occupy subdirectories of <code>unicode</code>.
+Also, <a href="#subrepo">some packages</a> have moved into
+subrepositories of
+<a href="http://code.google.com/p/go"><code>code.google.com/p/go</code></a>
+while <a href="#deleted">others</a> have been deleted outright.
+</p>
+
+<table class="codetable" frame="border" summary="Moved packages">
+<colgroup align="left" width="60%"></colgroup>
+<colgroup align="left" width="40%"></colgroup>
+<tr>
+<th align="left">Old path</th>
+<th align="left">New path</th>
+</tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>asn1</td> <td>encoding/asn1</td></tr>
+<tr><td>csv</td> <td>encoding/csv</td></tr>
+<tr><td>gob</td> <td>encoding/gob</td></tr>
+<tr><td>json</td> <td>encoding/json</td></tr>
+<tr><td>xml</td> <td>encoding/xml</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>exp/template/html</td> <td>html/template</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>big</td> <td>math/big</td></tr>
+<tr><td>cmath</td> <td>math/cmplx</td></tr>
+<tr><td>rand</td> <td>math/rand</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>http</td> <td>net/http</td></tr>
+<tr><td>http/cgi</td> <td>net/http/cgi</td></tr>
+<tr><td>http/fcgi</td> <td>net/http/fcgi</td></tr>
+<tr><td>http/httptest</td> <td>net/http/httptest</td></tr>
+<tr><td>http/pprof</td> <td>net/http/pprof</td></tr>
+<tr><td>mail</td> <td>net/mail</td></tr>
+<tr><td>rpc</td> <td>net/rpc</td></tr>
+<tr><td>rpc/jsonrpc</td> <td>net/rpc/jsonrpc</td></tr>
+<tr><td>smtp</td> <td>net/smtp</td></tr>
+<tr><td>url</td> <td>net/url</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>exec</td> <td>os/exec</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>scanner</td> <td>text/scanner</td></tr>
+<tr><td>tabwriter</td> <td>text/tabwriter</td></tr>
+<tr><td>template</td> <td>text/template</td></tr>
+<tr><td>template/parse</td> <td>text/template/parse</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>utf8</td> <td>unicode/utf8</td></tr>
+<tr><td>utf16</td> <td>unicode/utf16</td></tr>
+</table>
+
+<p>
+Note that the package names for the old <code>cmath</code> and
+<code>exp/template/html</code> packages have changed to <code>cmplx</code>
+and <code>template</code>.
+</p>
+
+<p>
+<em>Updating</em>:
+Running <code>go</code> <code>fix</code> will update all imports and package renames for packages that
+remain inside the standard repository. Programs that import packages
+that are no longer in the standard repository will need to be edited
+by hand.
+</p>
+
+<h3 id="exp">The package tree exp</h3>
+
+<p>
+Because they are not standardized, the packages under the <code>exp</code> directory will not be available in the
+standard Go 1 release distributions, although they will be available in source code form
+in <a href="http://code.google.com/p/go/">the repository</a> for
+developers who wish to use them.
+</p>
+
+<p>
+Several packages have moved under <code>exp</code> at the time of Go 1's release:
+</p>
+
+<ul>
+<li><code>ebnf</code></li>
+<li><code>html</code><sup>&#8224;</sup></li>
+<li><code>go/types</code></li>
+</ul>
+
+<p>
+(<sup>&#8224;</sup>The <code>EscapeString</code> and <code>UnescapeString</code> types remain
+in package <code>html</code>.)
+</p>
+
+<p>
+All these packages are available under the same names, with the prefix <code>exp/</code>: <code>exp/ebnf</code> etc.
+</p>
+
+<p>
+Also, the <code>utf8.String</code> type has been moved to its own package, <code>exp/utf8string</code>.
+</p>
+
+<p>
+Finally, the <code>gotype</code> command now resides in <code>exp/gotype</code>, while
+<code>ebnflint</code> is now in <code>exp/ebnflint</code>.
+If they are installed, they now reside in <code>$GOROOT/bin/tool</code>.
+</p>
+
+<p>
+<em>Updating</em>:
+Code that uses packages in <code>exp</code> will need to be updated by hand,
+or else compiled from an installation that has <code>exp</code> available.
+The <code>go</code> <code>fix</code> tool or the compiler will complain about such uses.
+</p>
+
+<h3 id="old">The package tree old</h3>
+
+<p>
+Because they are deprecated, the packages under the <code>old</code> directory will not be available in the
+standard Go 1 release distributions, although they will be available in source code form for
+developers who wish to use them.
+</p>
+
+<p>
+The packages in their new locations are:
+</p>
+
+<ul>
+<li><code>old/netchan</code></li>
+<li><code>old/regexp</code></li>
+<li><code>old/template</code></li>
+</ul>
+
+<p>
+<em>Updating</em>:
+Code that uses packages now in <code>old</code> will need to be updated by hand,
+or else compiled from an installation that has <code>old</code> available.
+The <code>go</code> <code>fix</code> tool will warn about such uses.
+</p>
+
+<h3 id="deleted">Deleted packages</h3>
+
+<p>
+Go 1 deletes several packages outright:
+</p>
+
+<ul>
+<li><code>container/vector</code></li>
+<li><code>exp/datafmt</code></li>
+<li><code>go/typechecker</code></li>
+<li><code>try</code></li>
+</ul>
+
+<p>
+and also the command <code>gotry</code>.
+</p>
+
+<p>
+<em>Updating</em>:
+Code that uses <code>container/vector</code> should be updated to use
+slices directly. See
+<a href="http://code.google.com/p/go-wiki/wiki/SliceTricks">the Go
+Language Community Wiki</a> for some suggestions.
+Code that uses the other packages (there should be almost zero) will need to be rethought.
+</p>
+
+<h3 id="subrepo">Packages moving to subrepositories</h3>
+
+<p>
+Go 1 has moved a number of packages into other repositories, usually sub-repositories of
+<a href="http://code.google.com/p/go/">the main Go repository</a>.
+This table lists the old and new import paths:
+
+<table class="codetable" frame="border" summary="Sub-repositories">
+<colgroup align="left" width="40%"></colgroup>
+<colgroup align="left" width="60%"></colgroup>
+<tr>
+<th align="left">Old</th>
+<th align="left">New</th>
+</tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>crypto/bcrypt</td> <td>code.google.com/p/go.crypto/bcrypt</tr>
+<tr><td>crypto/blowfish</td> <td>code.google.com/p/go.crypto/blowfish</tr>
+<tr><td>crypto/cast5</td> <td>code.google.com/p/go.crypto/cast5</tr>
+<tr><td>crypto/md4</td> <td>code.google.com/p/go.crypto/md4</tr>
+<tr><td>crypto/ocsp</td> <td>code.google.com/p/go.crypto/ocsp</tr>
+<tr><td>crypto/openpgp</td> <td>code.google.com/p/go.crypto/openpgp</tr>
+<tr><td>crypto/openpgp/armor</td> <td>code.google.com/p/go.crypto/openpgp/armor</tr>
+<tr><td>crypto/openpgp/elgamal</td> <td>code.google.com/p/go.crypto/openpgp/elgamal</tr>
+<tr><td>crypto/openpgp/errors</td> <td>code.google.com/p/go.crypto/openpgp/errors</tr>
+<tr><td>crypto/openpgp/packet</td> <td>code.google.com/p/go.crypto/openpgp/packet</tr>
+<tr><td>crypto/openpgp/s2k</td> <td>code.google.com/p/go.crypto/openpgp/s2k</tr>
+<tr><td>crypto/ripemd160</td> <td>code.google.com/p/go.crypto/ripemd160</tr>
+<tr><td>crypto/twofish</td> <td>code.google.com/p/go.crypto/twofish</tr>
+<tr><td>crypto/xtea</td> <td>code.google.com/p/go.crypto/xtea</tr>
+<tr><td>exp/ssh</td> <td>code.google.com/p/go.crypto/ssh</tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>image/bmp</td> <td>code.google.com/p/go.image/bmp</tr>
+<tr><td>image/tiff</td> <td>code.google.com/p/go.image/tiff</tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>net/dict</td> <td>code.google.com/p/go.net/dict</tr>
+<tr><td>net/websocket</td> <td>code.google.com/p/go.net/websocket</tr>
+<tr><td>exp/spdy</td> <td>code.google.com/p/go.net/spdy</tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>encoding/git85</td> <td>code.google.com/p/go.codereview/git85</tr>
+<tr><td>patch</td> <td>code.google.com/p/go.codereview/patch</tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>exp/wingui</td> <td>code.google.com/p/gowingui</tr>
+</table>
+
+<p>
+<em>Updating</em>:
+Running <code>go</code> <code>fix</code> will update imports of these packages to use the new import paths.
+Installations that depend on these packages will need to install them using
+a <code>go get</code> command.
+</p>
+
+<h2 id="major">Major changes to the library</h2>
+
+<p>
+This section describes significant changes to the core libraries, the ones that
+affect the most programs.
+</p>
+
+<h3 id="errors">The error type and errors package</h3>
+
+<p>
+The placement of <code>os.Error</code> in package <code>os</code> is mostly historical: errors first came up when implementing package <code>os</code>, and they seemed system-related at the time.
+Since then it has become clear that errors are more fundamental than the operating system. For example, it would be nice to use <code>Errors</code> in packages that <code>os</code> depends on, like <code>syscall</code>.
+Also, having <code>Error</code> in <code>os</code> introduces many dependencies on <code>os</code> that would otherwise not exist.
+</p>
+
+<p>
+Go 1 solves these problems by introducing a built-in <code>error</code> interface type and a separate <code>errors</code> package (analogous to <code>bytes</code> and <code>strings</code>) that contains utility functions.
+It replaces <code>os.NewError</code> with
+<a href="/pkg/errors/#New"><code>errors.New</code></a>,
+giving errors a more central place in the environment.
+</p>
+
+<p>
+So the widely-used <code>String</code> method does not cause accidental satisfaction
+of the <code>error</code> interface, the <code>error</code> interface uses instead
+the name <code>Error</code> for that method:
+</p>
+
+<pre>
+ type error interface {
+ Error() string
+ }
+</pre>
+
+<p>
+The <code>fmt</code> library automatically invokes <code>Error</code>, as it already
+does for <code>String</code>, for easy printing of error values.
+</p>
+
+<pre><!--{{code "/doc/progs/go1.go" `/START ERROR EXAMPLE/` `/END ERROR EXAMPLE/`}}
+-->type SyntaxError struct {
+ File string
+ Line int
+ Message string
+}
+
+func (se *SyntaxError) Error() string {
+ return fmt.Sprintf(&#34;%s:%d: %s&#34;, se.File, se.Line, se.Message)
+}</pre>
+
+<p>
+All standard packages have been updated to use the new interface; the old <code>os.Error</code> is gone.
+</p>
+
+<p>
+A new package, <a href="/pkg/errors/"><code>errors</code></a>, contains the function
+</p>
+
+<pre>
+func New(text string) error
+</pre>
+
+<p>
+to turn a string into an error. It replaces the old <code>os.NewError</code>.
+</p>
+
+<pre><!--{{code "/doc/progs/go1.go" `/ErrSyntax/`}}
+--> var ErrSyntax = errors.New(&#34;syntax error&#34;)</pre>
+
+<p>
+<em>Updating</em>:
+Running <code>go</code> <code>fix</code> will update almost all code affected by the change.
+Code that defines error types with a <code>String</code> method will need to be updated
+by hand to rename the methods to <code>Error</code>.
+</p>
+
+<h3 id="errno">System call errors</h3>
+
+<p>
+The old <code>syscall</code> package, which predated <code>os.Error</code>
+(and just about everything else),
+returned errors as <code>int</code> values.
+In turn, the <code>os</code> package forwarded many of these errors, such
+as <code>EINVAL</code>, but using a different set of errors on each platform.
+This behavior was unpleasant and unportable.
+</p>
+
+<p>
+In Go 1, the
+<a href="/pkg/syscall/"><code>syscall</code></a>
+package instead returns an <code>error</code> for system call errors.
+On Unix, the implementation is done by a
+<a href="/pkg/syscall/#Errno"><code>syscall.Errno</code></a> type
+that satisfies <code>error</code> and replaces the old <code>os.Errno</code>.
+</p>
+
+<p>
+The changes affecting <code>os.EINVAL</code> and relatives are
+described <a href="#os">elsewhere</a>.
+
+<p>
+<em>Updating</em>:
+Running <code>go</code> <code>fix</code> will update almost all code affected by the change.
+Regardless, most code should use the <code>os</code> package
+rather than <code>syscall</code> and so will be unaffected.
+</p>
+
+<h3 id="time">Time</h3>
+
+<p>
+Time is always a challenge to support well in a programming language.
+The old Go <code>time</code> package had <code>int64</code> units, no
+real type safety,
+and no distinction between absolute times and durations.
+</p>
+
+<p>
+One of the most sweeping changes in the Go 1 library is therefore a
+complete redesign of the
+<a href="/pkg/time/"><code>time</code></a> package.
+Instead of an integer number of nanoseconds as an <code>int64</code>,
+and a separate <code>*time.Time</code> type to deal with human
+units such as hours and years,
+there are now two fundamental types:
+<a href="/pkg/time/#Time"><code>time.Time</code></a>
+(a value, so the <code>*</code> is gone), which represents a moment in time;
+and <a href="/pkg/time/#Duration"><code>time.Duration</code></a>,
+which represents an interval.
+Both have nanosecond resolution.
+A <code>Time</code> can represent any time into the ancient
+past and remote future, while a <code>Duration</code> can
+span plus or minus only about 290 years.
+There are methods on these types, plus a number of helpful
+predefined constant durations such as <code>time.Second</code>.
+</p>
+
+<p>
+Among the new methods are things like
+<a href="/pkg/time/#Time.Add"><code>Time.Add</code></a>,
+which adds a <code>Duration</code> to a <code>Time</code>, and
+<a href="/pkg/time/#Time.Sub"><code>Time.Sub</code></a>,
+which subtracts two <code>Times</code> to yield a <code>Duration</code>.
+</p>
+
+<p>
+The most important semantic change is that the Unix epoch (Jan 1, 1970) is now
+relevant only for those functions and methods that mention Unix:
+<a href="/pkg/time/#Unix"><code>time.Unix</code></a>
+and the <a href="/pkg/time/#Time.Unix"><code>Unix</code></a>
+and <a href="/pkg/time/#Time.UnixNano"><code>UnixNano</code></a> methods
+of the <code>Time</code> type.
+In particular,
+<a href="/pkg/time/#Now"><code>time.Now</code></a>
+returns a <code>time.Time</code> value rather than, in the old
+API, an integer nanosecond count since the Unix epoch.
+</p>
+
+<pre><!--{{code "/doc/progs/go1.go" `/sleepUntil/` `/^}/`}}
+--><span class="comment">// sleepUntil sleeps until the specified time. It returns immediately if it&#39;s too late.</span>
+func sleepUntil(wakeup time.Time) {
+ now := time.Now() <span class="comment">// A Time.</span>
+ if !wakeup.After(now) {
+ return
+ }
+ delta := wakeup.Sub(now) <span class="comment">// A Duration.</span>
+ fmt.Printf(&#34;Sleeping for %.3fs\n&#34;, delta.Seconds())
+ time.Sleep(delta)
+}</pre>
+
+<p>
+The new types, methods, and constants have been propagated through
+all the standard packages that use time, such as <code>os</code> and
+its representation of file time stamps.
+</p>
+
+<p>
+<em>Updating</em>:
+The <code>go</code> <code>fix</code> tool will update many uses of the old <code>time</code> package to use the new
+types and methods, although it does not replace values such as <code>1e9</code>
+representing nanoseconds per second.
+Also, because of type changes in some of the values that arise,
+some of the expressions rewritten by the fix tool may require
+further hand editing; in such cases the rewrite will include
+the correct function or method for the old functionality, but
+may have the wrong type or require further analysis.
+</p>
+
+<h2 id="minor">Minor changes to the library</h2>
+
+<p>
+This section describes smaller changes, such as those to less commonly
+used packages or that affect
+few programs beyond the need to run <code>go</code> <code>fix</code>.
+This category includes packages that are new in Go 1.
+Collectively they improve portability, regularize behavior, and
+make the interfaces more modern and Go-like.
+</p>
+
+<h3 id="archive_zip">The archive/zip package</h3>
+
+<p>
+In Go 1, <a href="/pkg/archive/zip/#Writer"><code>*zip.Writer</code></a> no
+longer has a <code>Write</code> method. Its presence was a mistake.
+</p>
+
+<p>
+<em>Updating</em>:
+What little code is affected will be caught by the compiler and must be updated by hand.
+</p>
+
+<h3 id="bufio">The bufio package</h3>
+
+<p>
+In Go 1, <a href="/pkg/bufio/#NewReaderSize"><code>bufio.NewReaderSize</code></a>
+and
+<a href="/pkg/bufio/#NewWriterSize"><code>bufio.NewWriterSize</code></a>
+functions no longer return an error for invalid sizes.
+If the argument size is too small or invalid, it is adjusted.
+</p>
+
+<p>
+<em>Updating</em>:
+Running <code>go</code> <code>fix</code> will update calls that assign the error to _.
+Calls that aren't fixed will be caught by the compiler and must be updated by hand.
+</p>
+
+<h3 id="compress">The compress/flate, compress/gzip and compress/zlib packages</h3>
+
+<p>
+In Go 1, the <code>NewWriterXxx</code> functions in
+<a href="/pkg/compress/flate"><code>compress/flate</code></a>,
+<a href="/pkg/compress/gzip"><code>compress/gzip</code></a> and
+<a href="/pkg/compress/zlib"><code>compress/zlib</code></a>
+all return <code>(*Writer, error)</code> if they take a compression level,
+and <code>*Writer</code> otherwise. Package <code>gzip</code>'s
+<code>Compressor</code> and <code>Decompressor</code> types have been renamed
+to <code>Writer</code> and <code>Reader</code>. Package <code>flate</code>'s
+<code>WrongValueError</code> type has been removed.
+</p>
+
+<p>
+<em>Updating</em>
+Running <code>go</code> <code>fix</code> will update old names and calls that assign the error to _.
+Calls that aren't fixed will be caught by the compiler and must be updated by hand.
+</p>
+
+<h3 id="crypto_aes_des">The crypto/aes and crypto/des packages</h3>
+
+<p>
+In Go 1, the <code>Reset</code> method has been removed. Go does not guarantee
+that memory is not copied and therefore this method was misleading.
+</p>
+
+<p>
+The cipher-specific types <code>*aes.Cipher</code>, <code>*des.Cipher</code>,
+and <code>*des.TripleDESCipher</code> have been removed in favor of
+<code>cipher.Block</code>.
+</p>
+
+<p>
+<em>Updating</em>:
+Remove the calls to Reset. Replace uses of the specific cipher types with
+cipher.Block.
+</p>
+
+<h3 id="crypto_elliptic">The crypto/elliptic package</h3>
+
+<p>
+In Go 1, <a href="/pkg/crypto/elliptic/#Curve"><code>elliptic.Curve</code></a>
+has been made an interface to permit alternative implementations. The curve
+parameters have been moved to the
+<a href="/pkg/crypto/elliptic/#CurveParams"><code>elliptic.CurveParams</code></a>
+structure.
+</p>
+
+<p>
+<em>Updating</em>:
+Existing users of <code>*elliptic.Curve</code> will need to change to
+simply <code>elliptic.Curve</code>. Calls to <code>Marshal</code>,
+<code>Unmarshal</code> and <code>GenerateKey</code> are now functions
+in <code>crypto/elliptic</code> that take an <code>elliptic.Curve</code>
+as their first argument.
+</p>
+
+<h3 id="crypto_hmac">The crypto/hmac package</h3>
+
+<p>
+In Go 1, the hash-specific functions, such as <code>hmac.NewMD5</code>, have
+been removed from <code>crypto/hmac</code>. Instead, <code>hmac.New</code> takes
+a function that returns a <code>hash.Hash</code>, such as <code>md5.New</code>.
+</p>
+
+<p>
+<em>Updating</em>:
+Running <code>go</code> <code>fix</code> will perform the needed changes.
+</p>
+
+<h3 id="crypto_x509">The crypto/x509 package</h3>
+
+<p>
+In Go 1, the
+<a href="/pkg/crypto/x509/#CreateCertificate"><code>CreateCertificate</code></a>
+and
+<a href="/pkg/crypto/x509/#CreateCRL"><code>CreateCRL</code></a>
+functions in <code>crypto/x509</code> have been altered to take an
+<code>interface{}</code> where they previously took a <code>*rsa.PublicKey</code>
+or <code>*rsa.PrivateKey</code>. This will allow other public key algorithms
+to be implemented in the future.
+</p>
+
+<p>
+<em>Updating</em>:
+No changes will be needed.
+</p>
+
+<h3 id="encoding_binary">The encoding/binary package</h3>
+
+<p>
+In Go 1, the <code>binary.TotalSize</code> function has been replaced by
+<a href="/pkg/encoding/binary/#Size"><code>Size</code></a>,
+which takes an <code>interface{}</code> argument rather than
+a <code>reflect.Value</code>.
+</p>
+
+<p>
+<em>Updating</em>:
+What little code is affected will be caught by the compiler and must be updated by hand.
+</p>
+
+<h3 id="encoding_xml">The encoding/xml package</h3>
+
+<p>
+In Go 1, the <a href="/pkg/encoding/xml/"><code>xml</code></a> package
+has been brought closer in design to the other marshaling packages such
+as <a href="/pkg/encoding/gob/"><code>encoding/gob</code></a>.
+</p>
+
+<p>
+The old <code>Parser</code> type is renamed
+<a href="/pkg/encoding/xml/#Decoder"><code>Decoder</code></a> and has a new
+<a href="/pkg/encoding/xml/#Decoder.Decode"><code>Decode</code></a> method. An
+<a href="/pkg/encoding/xml/#Encoder"><code>Encoder</code></a> type was also introduced.
+</p>
+
+<p>
+The functions <a href="/pkg/encoding/xml/#Marshal"><code>Marshal</code></a>
+and <a href="/pkg/encoding/xml/#Unmarshal"><code>Unmarshal</code></a>
+work with <code>[]byte</code> values now. To work with streams,
+use the new <a href="/pkg/encoding/xml/#Encoder"><code>Encoder</code></a>
+and <a href="/pkg/encoding/xml/#Decoder"><code>Decoder</code></a> types.
+</p>
+
+<p>
+When marshaling or unmarshaling values, the format of supported flags in
+field tags has changed to be closer to the
+<a href="/pkg/encoding/json"><code>json</code></a> package
+(<code>`xml:"name,flag"`</code>). The matching done between field tags, field
+names, and the XML attribute and element names is now case-sensitive.
+The <code>XMLName</code> field tag, if present, must also match the name
+of the XML element being marshaled.
+</p>
+
+<p>
+<em>Updating</em>:
+Running <code>go</code> <code>fix</code> will update most uses of the package except for some calls to
+<code>Unmarshal</code>. Special care must be taken with field tags,
+since the fix tool will not update them and if not fixed by hand they will
+misbehave silently in some cases. For example, the old
+<code>"attr"</code> is now written <code>",attr"</code> while plain
+<code>"attr"</code> remains valid but with a different meaning.
+</p>
+
+<h3 id="expvar">The expvar package</h3>
+
+<p>
+In Go 1, the <code>RemoveAll</code> function has been removed.
+The <code>Iter</code> function and Iter method on <code>*Map</code> have
+been replaced by
+<a href="/pkg/expvar/#Do"><code>Do</code></a>
+and
+<a href="/pkg/expvar/#Map.Do"><code>(*Map).Do</code></a>.
+</p>
+
+<p>
+<em>Updating</em>:
+Most code using <code>expvar</code> will not need changing. The rare code that used
+<code>Iter</code> can be updated to pass a closure to <code>Do</code> to achieve the same effect.
+</p>
+
+<h3 id="flag">The flag package</h3>
+
+<p>
+In Go 1, the interface <a href="/pkg/flag/#Value"><code>flag.Value</code></a> has changed slightly.
+The <code>Set</code> method now returns an <code>error</code> instead of
+a <code>bool</code> to indicate success or failure.
+</p>
+
+<p>
+There is also a new kind of flag, <code>Duration</code>, to support argument
+values specifying time intervals.
+Values for such flags must be given units, just as <code>time.Duration</code>
+formats them: <code>10s</code>, <code>1h30m</code>, etc.
+</p>
+
+<pre><!--{{code "/doc/progs/go1.go" `/timeout/`}}
+-->var timeout = flag.Duration(&#34;timeout&#34;, 30*time.Second, &#34;how long to wait for completion&#34;)</pre>
+
+<p>
+<em>Updating</em>:
+Programs that implement their own flags will need minor manual fixes to update their
+<code>Set</code> methods.
+The <code>Duration</code> flag is new and affects no existing code.
+</p>
+
+
+<h3 id="go">The go/* packages</h3>
+
+<p>
+Several packages under <code>go</code> have slightly revised APIs.
+</p>
+
+<p>
+A concrete <code>Mode</code> type was introduced for configuration mode flags
+in the packages
+<a href="/pkg/go/scanner/"><code>go/scanner</code></a>,
+<a href="/pkg/go/parser/"><code>go/parser</code></a>,
+<a href="/pkg/go/printer/"><code>go/printer</code></a>, and
+<a href="/pkg/go/doc/"><code>go/doc</code></a>.
+</p>
+
+<p>
+The modes <code>AllowIllegalChars</code> and <code>InsertSemis</code> have been removed
+from the <a href="/pkg/go/scanner/"><code>go/scanner</code></a> package. They were mostly
+useful for scanning text other then Go source files. Instead, the
+<a href="/pkg/text/scanner/"><code>text/scanner</code></a> package should be used
+for that purpose.
+</p>
+
+<p>
+The <a href="/pkg/go/scanner/#ErrorHandler"><code>ErrorHandler</code></a> provided
+to the scanner's <a href="/pkg/go/scanner/#Scanner.Init"><code>Init</code></a> method is
+now simply a function rather than an interface. The <code>ErrorVector</code> type has
+been removed in favor of the (existing) <a href="/pkg/go/scanner/#ErrorList"><code>ErrorList</code></a>
+type, and the <code>ErrorVector</code> methods have been migrated. Instead of embedding
+an <code>ErrorVector</code> in a client of the scanner, now a client should maintain
+an <code>ErrorList</code>.
+</p>
+
+<p>
+The set of parse functions provided by the <a href="/pkg/go/parser/"><code>go/parser</code></a>
+package has been reduced to the primary parse function
+<a href="/pkg/go/parser/#ParseFile"><code>ParseFile</code></a>, and a couple of
+convenience functions <a href="/pkg/go/parser/#ParseDir"><code>ParseDir</code></a>
+and <a href="/pkg/go/parser/#ParseExpr"><code>ParseExpr</code></a>.
+</p>
+
+<p>
+The <a href="/pkg/go/printer/"><code>go/printer</code></a> package supports an additional
+configuration mode <a href="/pkg/go/printer/#Mode"><code>SourcePos</code></a>;
+if set, the printer will emit <code>//line</code> comments such that the generated
+output contains the original source code position information. The new type
+<a href="/pkg/go/printer/#CommentedNode"><code>CommentedNode</code></a> can be
+used to provide comments associated with an arbitrary
+<a href="/pkg/go/ast/#Node"><code>ast.Node</code></a> (until now only
+<a href="/pkg/go/ast/#File"><code>ast.File</code></a> carried comment information).
+</p>
+
+<p>
+The type names of the <a href="/pkg/go/doc/"><code>go/doc</code></a> package have been
+streamlined by removing the <code>Doc</code> suffix: <code>PackageDoc</code>
+is now <code>Package</code>, <code>ValueDoc</code> is <code>Value</code>, etc.
+Also, all types now consistently have a <code>Name</code> field (or <code>Names</code>,
+in the case of type <code>Value</code>) and <code>Type.Factories</code> has become
+<code>Type.Funcs</code>.
+Instead of calling <code>doc.NewPackageDoc(pkg, importpath)</code>,
+documentation for a package is created with:
+</p>
+
+<pre>
+ doc.New(pkg, importpath, mode)
+</pre>
+
+<p>
+where the new <code>mode</code> parameter specifies the operation mode:
+if set to <a href="/pkg/go/doc/#AllDecls"><code>AllDecls</code></a>, all declarations
+(not just exported ones) are considered.
+The function <code>NewFileDoc</code> was removed, and the function
+<code>CommentText</code> has become the method
+<a href="/pkg/go/ast/#Text"><code>Text</code></a> of
+<a href="/pkg/go/ast/#CommentGroup"><code>ast.CommentGroup</code></a>.
+</p>
+
+<p>
+In package <a href="/pkg/go/token/"><code>go/token</code></a>, the
+<a href="/pkg/go/token/#FileSet"><code>token.FileSet</code></a> method <code>Files</code>
+(which originally returned a channel of <code>*token.File</code>s) has been replaced
+with the iterator <a href="/pkg/go/token/#FileSet.Iterate"><code>Iterate</code></a> that
+accepts a function argument instead.
+</p>
+
+<p>
+In package <a href="/pkg/go/build/"><code>go/build</code></a>, the API
+has been nearly completely replaced.
+The package still computes Go package information
+but it does not run the build: the <code>Cmd</code> and <code>Script</code>
+types are gone.
+(To build code, use the new
+<a href="/cmd/go/"><code>go</code></a> command instead.)
+The <code>DirInfo</code> type is now named
+<a href="/pkg/go/build/#Package"><code>Package</code></a>.
+<code>FindTree</code> and <code>ScanDir</code> are replaced by
+<a href="/pkg/go/build/#Import"><code>Import</code></a>
+and
+<a href="/pkg/go/build/#ImportDir"><code>ImportDir</code></a>.
+</p>
+
+<p>
+<em>Updating</em>:
+Code that uses packages in <code>go</code> will have to be updated by hand; the
+compiler will reject incorrect uses. Templates used in conjunction with any of the
+<code>go/doc</code> types may need manual fixes; the renamed fields will lead
+to run-time errors.
+</p>
+
+<h3 id="hash">The hash package</h3>
+
+<p>
+In Go 1, the definition of <a href="/pkg/hash/#Hash"><code>hash.Hash</code></a> includes
+a new method, <code>BlockSize</code>. This new method is used primarily in the
+cryptographic libraries.
+</p>
+
+<p>
+The <code>Sum</code> method of the
+<a href="/pkg/hash/#Hash"><code>hash.Hash</code></a> interface now takes a
+<code>[]byte</code> argument, to which the hash value will be appended.
+The previous behavior can be recreated by adding a <code>nil</code> argument to the call.
+</p>
+
+<p>
+<em>Updating</em>:
+Existing implementations of <code>hash.Hash</code> will need to add a
+<code>BlockSize</code> method. Hashes that process the input one byte at
+a time can implement <code>BlockSize</code> to return 1.
+Running <code>go</code> <code>fix</code> will update calls to the <code>Sum</code> methods of the various
+implementations of <code>hash.Hash</code>.
+</p>
+
+<p>
+<em>Updating</em>:
+Since the package's functionality is new, no updating is necessary.
+</p>
+
+<h3 id="http">The http package</h3>
+
+<p>
+In Go 1 the <a href="/pkg/net/http/"><code>http</code></a> package is refactored,
+putting some of the utilities into a
+<a href="/pkg/net/http/httputil/"><code>httputil</code></a> subdirectory.
+These pieces are only rarely needed by HTTP clients.
+The affected items are:
+</p>
+
+<ul>
+<li>ClientConn</li>
+<li>DumpRequest</li>
+<li>DumpRequestOut</li>
+<li>DumpResponse</li>
+<li>NewChunkedReader</li>
+<li>NewChunkedWriter</li>
+<li>NewClientConn</li>
+<li>NewProxyClientConn</li>
+<li>NewServerConn</li>
+<li>NewSingleHostReverseProxy</li>
+<li>ReverseProxy</li>
+<li>ServerConn</li>
+</ul>
+
+<p>
+The <code>Request.RawURL</code> field has been removed; it was a
+historical artifact.
+</p>
+
+<p>
+The <code>Handle</code> and <code>HandleFunc</code>
+functions, and the similarly-named methods of <code>ServeMux</code>,
+now panic if an attempt is made to register the same pattern twice.
+</p>
+
+<p>
+<em>Updating</em>:
+Running <code>go</code> <code>fix</code> will update the few programs that are affected except for
+uses of <code>RawURL</code>, which must be fixed by hand.
+</p>
+
+<h3 id="image">The image package</h3>
+
+<p>
+The <a href="/pkg/image/"><code>image</code></a> package has had a number of
+minor changes, rearrangements and renamings.
+</p>
+
+<p>
+Most of the color handling code has been moved into its own package,
+<a href="/pkg/image/color/"><code>image/color</code></a>.
+For the elements that moved, a symmetry arises; for instance,
+each pixel of an
+<a href="/pkg/image/#RGBA"><code>image.RGBA</code></a>
+is a
+<a href="/pkg/image/color/#RGBA"><code>color.RGBA</code></a>.
+</p>
+
+<p>
+The old <code>image/ycbcr</code> package has been folded, with some
+renamings, into the
+<a href="/pkg/image/"><code>image</code></a>
+and
+<a href="/pkg/image/color/"><code>image/color</code></a>
+packages.
+</p>
+
+<p>
+The old <code>image.ColorImage</code> type is still in the <code>image</code>
+package but has been renamed
+<a href="/pkg/image/#Uniform"><code>image.Uniform</code></a>,
+while <code>image.Tiled</code> has been removed.
+</p>
+
+<p>
+This table lists the renamings.
+</p>
+
+<table class="codetable" frame="border" summary="image renames">
+<colgroup align="left" width="50%"></colgroup>
+<colgroup align="left" width="50%"></colgroup>
+<tr>
+<th align="left">Old</th>
+<th align="left">New</th>
+</tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>image.Color</td> <td>color.Color</td></tr>
+<tr><td>image.ColorModel</td> <td>color.Model</td></tr>
+<tr><td>image.ColorModelFunc</td> <td>color.ModelFunc</td></tr>
+<tr><td>image.PalettedColorModel</td> <td>color.Palette</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>image.RGBAColor</td> <td>color.RGBA</td></tr>
+<tr><td>image.RGBA64Color</td> <td>color.RGBA64</td></tr>
+<tr><td>image.NRGBAColor</td> <td>color.NRGBA</td></tr>
+<tr><td>image.NRGBA64Color</td> <td>color.NRGBA64</td></tr>
+<tr><td>image.AlphaColor</td> <td>color.Alpha</td></tr>
+<tr><td>image.Alpha16Color</td> <td>color.Alpha16</td></tr>
+<tr><td>image.GrayColor</td> <td>color.Gray</td></tr>
+<tr><td>image.Gray16Color</td> <td>color.Gray16</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>image.RGBAColorModel</td> <td>color.RGBAModel</td></tr>
+<tr><td>image.RGBA64ColorModel</td> <td>color.RGBA64Model</td></tr>
+<tr><td>image.NRGBAColorModel</td> <td>color.NRGBAModel</td></tr>
+<tr><td>image.NRGBA64ColorModel</td> <td>color.NRGBA64Model</td></tr>
+<tr><td>image.AlphaColorModel</td> <td>color.AlphaModel</td></tr>
+<tr><td>image.Alpha16ColorModel</td> <td>color.Alpha16Model</td></tr>
+<tr><td>image.GrayColorModel</td> <td>color.GrayModel</td></tr>
+<tr><td>image.Gray16ColorModel</td> <td>color.Gray16Model</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>ycbcr.RGBToYCbCr</td> <td>color.RGBToYCbCr</td></tr>
+<tr><td>ycbcr.YCbCrToRGB</td> <td>color.YCbCrToRGB</td></tr>
+<tr><td>ycbcr.YCbCrColorModel</td> <td>color.YCbCrModel</td></tr>
+<tr><td>ycbcr.YCbCrColor</td> <td>color.YCbCr</td></tr>
+<tr><td>ycbcr.YCbCr</td> <td>image.YCbCr</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>ycbcr.SubsampleRatio444</td> <td>image.YCbCrSubsampleRatio444</td></tr>
+<tr><td>ycbcr.SubsampleRatio422</td> <td>image.YCbCrSubsampleRatio422</td></tr>
+<tr><td>ycbcr.SubsampleRatio420</td> <td>image.YCbCrSubsampleRatio420</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>image.ColorImage</td> <td>image.Uniform</td></tr>
+</table>
+
+<p>
+The image package's <code>New</code> functions
+(<a href="/pkg/image/#NewRGBA"><code>NewRGBA</code></a>,
+<a href="/pkg/image/#NewRGBA64"><code>NewRGBA64</code></a>, etc.)
+take an <a href="/pkg/image/#Rectangle"><code>image.Rectangle</code></a> as an argument
+instead of four integers.
+</p>
+
+<p>
+Finally, there are new predefined <code>color.Color</code> variables
+<a href="/pkg/image/color/#Black"><code>color.Black</code></a>,
+<a href="/pkg/image/color/#White"><code>color.White</code></a>,
+<a href="/pkg/image/color/#Opaque"><code>color.Opaque</code></a>
+and
+<a href="/pkg/image/color/#Transparent"><code>color.Transparent</code></a>.
+</p>
+
+<p>
+<em>Updating</em>:
+Running <code>go</code> <code>fix</code> will update almost all code affected by the change.
+</p>
+
+<h3 id="log_syslog">The log/syslog package</h3>
+
+<p>
+In Go 1, the <a href="/pkg/log/syslog/#NewLogger"><code>syslog.NewLogger</code></a>
+function returns an error as well as a <code>log.Logger</code>.
+</p>
+
+<p>
+<em>Updating</em>:
+What little code is affected will be caught by the compiler and must be updated by hand.
+</p>
+
+<h3 id="mime">The mime package</h3>
+
+<p>
+In Go 1, the <a href="/pkg/mime/#FormatMediaType"><code>FormatMediaType</code></a> function
+of the <code>mime</code> package has been simplified to make it
+consistent with
+<a href="/pkg/mime/#ParseMediaType"><code>ParseMediaType</code></a>.
+It now takes <code>"text/html"</code> rather than <code>"text"</code> and <code>"html"</code>.
+</p>
+
+<p>
+<em>Updating</em>:
+What little code is affected will be caught by the compiler and must be updated by hand.
+</p>
+
+<h3 id="net">The net package</h3>
+
+<p>
+In Go 1, the various <code>SetTimeout</code>,
+<code>SetReadTimeout</code>, and <code>SetWriteTimeout</code> methods
+have been replaced with
+<a href="/pkg/net/#IPConn.SetDeadline"><code>SetDeadline</code></a>,
+<a href="/pkg/net/#IPConn.SetReadDeadline"><code>SetReadDeadline</code></a>, and
+<a href="/pkg/net/#IPConn.SetWriteDeadline"><code>SetWriteDeadline</code></a>,
+respectively. Rather than taking a timeout value in nanoseconds that
+apply to any activity on the connection, the new methods set an
+absolute deadline (as a <code>time.Time</code> value) after which
+reads and writes will time out and no longer block.
+</p>
+
+<p>
+There are also new functions
+<a href="/pkg/net/#DialTimeout"><code>net.DialTimeout</code></a>
+to simplify timing out dialing a network address and
+<a href="/pkg/net/#ListenMulticastUDP"><code>net.ListenMulticastUDP</code></a>
+to allow multicast UDP to listen concurrently across multiple listeners.
+The <code>net.ListenMulticastUDP</code> function replaces the old
+<code>JoinGroup</code> and <code>LeaveGroup</code> methods.
+</p>
+
+<p>
+<em>Updating</em>:
+Code that uses the old methods will fail to compile and must be updated by hand.
+The semantic change makes it difficult for the fix tool to update automatically.
+</p>
+
+<h3 id="os">The os package</h3>
+
+<p>
+The <code>Time</code> function has been removed; callers should use
+the <a href="/pkg/time/#Time"><code>Time</code></a> type from the
+<code>time</code> package.
+</p>
+
+<p>
+The <code>Exec</code> function has been removed; callers should use
+<code>Exec</code> from the <code>syscall</code> package, where available.
+</p>
+
+<p>
+The <code>ShellExpand</code> function has been renamed to <a
+href="/pkg/os/#ExpandEnv"><code>ExpandEnv</code></a>.
+</p>
+
+<p>
+The <a href="/pkg/os/#NewFile"><code>NewFile</code></a> function
+now takes a <code>uintptr</code> fd, instead of an <code>int</code>.
+The <a href="/pkg/os/#File.Fd"><code>Fd</code></a> method on files now
+also returns a <code>uintptr</code>.
+</p>
+
+<p>
+There are no longer error constants such as <code>EINVAL</code>
+in the <code>os</code> package, since the set of values varied with
+the underlying operating system. There are new portable functions like
+<a href="/pkg/os/#IsPermission"><code>IsPermission</code></a>
+to test common error properties, plus a few new error values
+with more Go-like names, such as
+<a href="/pkg/os/#ErrPermission"><code>ErrPermission</code></a>
+and
+<a href="/pkg/os/#ErrNoEnv"><code>ErrNoEnv</code></a>.
+</p>
+
+<p>
+The <code>Getenverror</code> function has been removed. To distinguish
+between a non-existent environment variable and an empty string,
+use <a href="/pkg/os/#Environ"><code>os.Environ</code></a> or
+<a href="/pkg/syscall/#Getenv"><code>syscall.Getenv</code></a>.
+</p>
+
+
+<p>
+The <a href="/pkg/os/#Process.Wait"><code>Process.Wait</code></a> method has
+dropped its option argument and the associated constants are gone
+from the package.
+Also, the function <code>Wait</code> is gone; only the method of
+the <code>Process</code> type persists.
+</p>
+
+<p>
+The <code>Waitmsg</code> type returned by
+<a href="/pkg/os/#Process.Wait"><code>Process.Wait</code></a>
+has been replaced with a more portable
+<a href="/pkg/os/#ProcessState"><code>ProcessState</code></a>
+type with accessor methods to recover information about the
+process.
+Because of changes to <code>Wait</code>, the <code>ProcessState</code>
+value always describes an exited process.
+Portability concerns simplified the interface in other ways, but the values returned by the
+<a href="/pkg/os/#ProcessState.Sys"><code>ProcessState.Sys</code></a> and
+<a href="/pkg/os/#ProcessState.SysUsage"><code>ProcessState.SysUsage</code></a>
+methods can be type-asserted to underlying system-specific data structures such as
+<a href="/pkg/syscall/#WaitStatus"><code>syscall.WaitStatus</code></a> and
+<a href="/pkg/syscall/#Rusage"><code>syscall.Rusage</code></a> on Unix.
+</p>
+
+<p>
+<em>Updating</em>:
+Running <code>go</code> <code>fix</code> will drop a zero argument to <code>Process.Wait</code>.
+All other changes will be caught by the compiler and must be updated by hand.
+</p>
+
+<h4 id="os_fileinfo">The os.FileInfo type</h4>
+
+<p>
+Go 1 redefines the <a href="/pkg/os/#FileInfo"><code>os.FileInfo</code></a> type,
+changing it from a struct to an interface:
+</p>
+
+<pre>
+ type FileInfo interface {
+ Name() string // base name of the file
+ Size() int64 // length in bytes
+ Mode() FileMode // file mode bits
+ ModTime() time.Time // modification time
+ IsDir() bool // abbreviation for Mode().IsDir()
+ Sys() interface{} // underlying data source (can return nil)
+ }
+</pre>
+
+<p>
+The file mode information has been moved into a subtype called
+<a href="/pkg/os/#FileMode"><code>os.FileMode</code></a>,
+a simple integer type with <code>IsDir</code>, <code>Perm</code>, and <code>String</code>
+methods.
+</p>
+
+<p>
+The system-specific details of file modes and properties such as (on Unix)
+i-number have been removed from <code>FileInfo</code> altogether.
+Instead, each operating system's <code>os</code> package provides an
+implementation of the <code>FileInfo</code> interface, which
+has a <code>Sys</code> method that returns the
+system-specific representation of file metadata.
+For instance, to discover the i-number of a file on a Unix system, unpack
+the <code>FileInfo</code> like this:
+</p>
+
+<pre>
+ fi, err := os.Stat("hello.go")
+ if err != nil {
+ log.Fatal(err)
+ }
+ // Check that it's a Unix file.
+ unixStat, ok := fi.Sys().(*syscall.Stat_t)
+ if !ok {
+ log.Fatal("hello.go: not a Unix file")
+ }
+ fmt.Printf("file i-number: %d\n", unixStat.Ino)
+</pre>
+
+<p>
+Assuming (which is unwise) that <code>"hello.go"</code> is a Unix file,
+the i-number expression could be contracted to
+</p>
+
+<pre>
+ fi.Sys().(*syscall.Stat_t).Ino
+</pre>
+
+<p>
+The vast majority of uses of <code>FileInfo</code> need only the methods
+of the standard interface.
+</p>
+
+<p>
+The <code>os</code> package no longer contains wrappers for the POSIX errors
+such as <code>ENOENT</code>.
+For the few programs that need to verify particular error conditions, there are
+now the boolean functions
+<a href="/pkg/os/#IsExist"><code>IsExist</code></a>,
+<a href="/pkg/os/#IsNotExist"><code>IsNotExist</code></a>
+and
+<a href="/pkg/os/#IsPermission"><code>IsPermission</code></a>.
+</p>
+
+<pre><!--{{code "/doc/progs/go1.go" `/os\.Open/` `/}/`}}
+--> f, err := os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600)
+ if os.IsExist(err) {
+ log.Printf(&#34;%s already exists&#34;, name)
+ }</pre>
+
+<p>
+<em>Updating</em>:
+Running <code>go</code> <code>fix</code> will update code that uses the old equivalent of the current <code>os.FileInfo</code>
+and <code>os.FileMode</code> API.
+Code that needs system-specific file details will need to be updated by hand.
+Code that uses the old POSIX error values from the <code>os</code> package
+will fail to compile and will also need to be updated by hand.
+</p>
+
+<h3 id="os_signal">The os/signal package</h3>
+
+<p>
+The <code>os/signal</code> package in Go 1 replaces the
+<code>Incoming</code> function, which returned a channel
+that received all incoming signals,
+with the selective <code>Notify</code> function, which asks
+for delivery of specific signals on an existing channel.
+</p>
+
+<p>
+<em>Updating</em>:
+Code must be updated by hand.
+A literal translation of
+</p>
+<pre>
+c := signal.Incoming()
+</pre>
+<p>
+is
+</p>
+<pre>
+c := make(chan os.Signal)
+signal.Notify(c) // ask for all signals
+</pre>
+<p>
+but most code should list the specific signals it wants to handle instead:
+</p>
+<pre>
+c := make(chan os.Signal)
+signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT)
+</pre>
+
+<h3 id="path_filepath">The path/filepath package</h3>
+
+<p>
+In Go 1, the <a href="/pkg/path/filepath/#Walk"><code>Walk</code></a> function of the
+<code>path/filepath</code> package
+has been changed to take a function value of type
+<a href="/pkg/path/filepath/#WalkFunc"><code>WalkFunc</code></a>
+instead of a <code>Visitor</code> interface value.
+<code>WalkFunc</code> unifies the handling of both files and directories.
+</p>
+
+<pre>
+ type WalkFunc func(path string, info os.FileInfo, err error) error
+</pre>
+
+<p>
+The <code>WalkFunc</code> function will be called even for files or directories that could not be opened;
+in such cases the error argument will describe the failure.
+If a directory's contents are to be skipped,
+the function should return the value <a href="/pkg/path/filepath/#variables"><code>filepath.SkipDir</code></a>
+</p>
+
+<pre><!--{{code "/doc/progs/go1.go" `/STARTWALK/` `/ENDWALK/`}}
+--> markFn := func(path string, info os.FileInfo, err error) error {
+ if path == &#34;pictures&#34; { <span class="comment">// Will skip walking of directory pictures and its contents.</span>
+ return filepath.SkipDir
+ }
+ if err != nil {
+ return err
+ }
+ log.Println(path)
+ return nil
+ }
+ err := filepath.Walk(&#34;.&#34;, markFn)
+ if err != nil {
+ log.Fatal(err)
+ }</pre>
+
+<p>
+<em>Updating</em>:
+The change simplifies most code but has subtle consequences, so affected programs
+will need to be updated by hand.
+The compiler will catch code using the old interface.
+</p>
+
+<h3 id="regexp">The regexp package</h3>
+
+<p>
+The <a href="/pkg/regexp/"><code>regexp</code></a> package has been rewritten.
+It has the same interface but the specification of the regular expressions
+it supports has changed from the old "egrep" form to that of
+<a href="http://code.google.com/p/re2/">RE2</a>.
+</p>
+
+<p>
+<em>Updating</em>:
+Code that uses the package should have its regular expressions checked by hand.
+</p>
+
+<h3 id="runtime">The runtime package</h3>
+
+<p>
+In Go 1, much of the API exported by package
+<code>runtime</code> has been removed in favor of
+functionality provided by other packages.
+Code using the <code>runtime.Type</code> interface
+or its specific concrete type implementations should
+now use package <a href="/pkg/reflect/"><code>reflect</code></a>.
+Code using <code>runtime.Semacquire</code> or <code>runtime.Semrelease</code>
+should use channels or the abstractions in package <a href="/pkg/sync/"><code>sync</code></a>.
+The <code>runtime.Alloc</code>, <code>runtime.Free</code>,
+and <code>runtime.Lookup</code> functions, an unsafe API created for
+debugging the memory allocator, have no replacement.
+</p>
+
+<p>
+Before, <code>runtime.MemStats</code> was a global variable holding
+statistics about memory allocation, and calls to <code>runtime.UpdateMemStats</code>
+ensured that it was up to date.
+In Go 1, <code>runtime.MemStats</code> is a struct type, and code should use
+<a href="/pkg/runtime/#ReadMemStats"><code>runtime.ReadMemStats</code></a>
+to obtain the current statistics.
+</p>
+
+<p>
+The package adds a new function,
+<a href="/pkg/runtime/#NumCPU"><code>runtime.NumCPU</code></a>, that returns the number of CPUs available
+for parallel execution, as reported by the operating system kernel.
+Its value can inform the setting of <code>GOMAXPROCS</code>.
+The <code>runtime.Cgocalls</code> and <code>runtime.Goroutines</code> functions
+have been renamed to <code>runtime.NumCgoCall</code> and <code>runtime.NumGoroutine</code>.
+</p>
+
+<p>
+<em>Updating</em>:
+Running <code>go</code> <code>fix</code> will update code for the function renamings.
+Other code will need to be updated by hand.
+</p>
+
+<h3 id="strconv">The strconv package</h3>
+
+<p>
+In Go 1, the
+<a href="/pkg/strconv/"><code>strconv</code></a>
+package has been significantly reworked to make it more Go-like and less C-like,
+although <code>Atoi</code> lives on (it's similar to
+<code>int(ParseInt(x, 10, 0))</code>, as does
+<code>Itoa(x)</code> (<code>FormatInt(int64(x), 10)</code>).
+There are also new variants of some of the functions that append to byte slices rather than
+return strings, to allow control over allocation.
+</p>
+
+<p>
+This table summarizes the renamings; see the
+<a href="/pkg/strconv/">package documentation</a>
+for full details.
+</p>
+
+<table class="codetable" frame="border" summary="strconv renames">
+<colgroup align="left" width="50%"></colgroup>
+<colgroup align="left" width="50%"></colgroup>
+<tr>
+<th align="left">Old call</th>
+<th align="left">New call</th>
+</tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>Atob(x)</td> <td>ParseBool(x)</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>Atof32(x)</td> <td>ParseFloat(x, 32)§</td></tr>
+<tr><td>Atof64(x)</td> <td>ParseFloat(x, 64)</td></tr>
+<tr><td>AtofN(x, n)</td> <td>ParseFloat(x, n)</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>Atoi(x)</td> <td>Atoi(x)</td></tr>
+<tr><td>Atoi(x)</td> <td>ParseInt(x, 10, 0)§</td></tr>
+<tr><td>Atoi64(x)</td> <td>ParseInt(x, 10, 64)</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>Atoui(x)</td> <td>ParseUint(x, 10, 0)§</td></tr>
+<tr><td>Atoui64(x)</td> <td>ParseUint(x, 10, 64)</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>Btoi64(x, b)</td> <td>ParseInt(x, b, 64)</td></tr>
+<tr><td>Btoui64(x, b)</td> <td>ParseUint(x, b, 64)</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>Btoa(x)</td> <td>FormatBool(x)</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>Ftoa32(x, f, p)</td> <td>FormatFloat(float64(x), f, p, 32)</td></tr>
+<tr><td>Ftoa64(x, f, p)</td> <td>FormatFloat(x, f, p, 64)</td></tr>
+<tr><td>FtoaN(x, f, p, n)</td> <td>FormatFloat(x, f, p, n)</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>Itoa(x)</td> <td>Itoa(x)</td></tr>
+<tr><td>Itoa(x)</td> <td>FormatInt(int64(x), 10)</td></tr>
+<tr><td>Itoa64(x)</td> <td>FormatInt(x, 10)</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>Itob(x, b)</td> <td>FormatInt(int64(x), b)</td></tr>
+<tr><td>Itob64(x, b)</td> <td>FormatInt(x, b)</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>Uitoa(x)</td> <td>FormatUint(uint64(x), 10)</td></tr>
+<tr><td>Uitoa64(x)</td> <td>FormatUint(x, 10)</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>Uitob(x, b)</td> <td>FormatUint(uint64(x), b)</td></tr>
+<tr><td>Uitob64(x, b)</td> <td>FormatUint(x, b)</td></tr>
+</table>
+
+<p>
+<em>Updating</em>:
+Running <code>go</code> <code>fix</code> will update almost all code affected by the change.
+<br>
+§ <code>Atoi</code> persists but <code>Atoui</code> and <code>Atof32</code> do not, so
+they may require
+a cast that must be added by hand; the <code>go</code> <code>fix</code> tool will warn about it.
+</p>
+
+
+<h3 id="templates">The template packages</h3>
+
+<p>
+The <code>template</code> and <code>exp/template/html</code> packages have moved to
+<a href="/pkg/text/template/"><code>text/template</code></a> and
+<a href="/pkg/html/template/"><code>html/template</code></a>.
+More significant, the interface to these packages has been simplified.
+The template language is the same, but the concept of "template set" is gone
+and the functions and methods of the packages have changed accordingly,
+often by elimination.
+</p>
+
+<p>
+Instead of sets, a <code>Template</code> object
+may contain multiple named template definitions,
+in effect constructing
+name spaces for template invocation.
+A template can invoke any other template associated with it, but only those
+templates associated with it.
+The simplest way to associate templates is to parse them together, something
+made easier with the new structure of the packages.
+</p>
+
+<p>
+<em>Updating</em>:
+The imports will be updated by fix tool.
+Single-template uses will be otherwise be largely unaffected.
+Code that uses multiple templates in concert will need to be updated by hand.
+The <a href="/pkg/text/template/#examples">examples</a> in
+the documentation for <code>text/template</code> can provide guidance.
+</p>
+
+<h3 id="testing">The testing package</h3>
+
+<p>
+The testing package has a type, <code>B</code>, passed as an argument to benchmark functions.
+In Go 1, <code>B</code> has new methods, analogous to those of <code>T</code>, enabling
+logging and failure reporting.
+</p>
+
+<pre><!--{{code "/doc/progs/go1.go" `/func.*Benchmark/` `/^}/`}}
+-->func BenchmarkSprintf(b *testing.B) {
+ <span class="comment">// Verify correctness before running benchmark.</span>
+ b.StopTimer()
+ got := fmt.Sprintf(&#34;%x&#34;, 23)
+ const expect = &#34;17&#34;
+ if expect != got {
+ b.Fatalf(&#34;expected %q; got %q&#34;, expect, got)
+ }
+ b.StartTimer()
+ for i := 0; i &lt; b.N; i++ {
+ fmt.Sprintf(&#34;%x&#34;, 23)
+ }
+}</pre>
+
+<p>
+<em>Updating</em>:
+Existing code is unaffected, although benchmarks that use <code>println</code>
+or <code>panic</code> should be updated to use the new methods.
+</p>
+
+<h3 id="testing_script">The testing/script package</h3>
+
+<p>
+The testing/script package has been deleted. It was a dreg.
+</p>
+
+<p>
+<em>Updating</em>:
+No code is likely to be affected.
+</p>
+
+<h3 id="unsafe">The unsafe package</h3>
+
+<p>
+In Go 1, the functions
+<code>unsafe.Typeof</code>, <code>unsafe.Reflect</code>,
+<code>unsafe.Unreflect</code>, <code>unsafe.New</code>, and
+<code>unsafe.NewArray</code> have been removed;
+they duplicated safer functionality provided by
+package <a href="/pkg/reflect/"><code>reflect</code></a>.
+</p>
+
+<p>
+<em>Updating</em>:
+Code using these functions must be rewritten to use
+package <a href="/pkg/reflect/"><code>reflect</code></a>.
+The changes to <a href="http://code.google.com/p/go/source/detail?r=2646dc956207">encoding/gob</a> and the <a href="http://code.google.com/p/goprotobuf/source/detail?r=5340ad310031">protocol buffer library</a>
+may be helpful as examples.
+</p>
+
+<h3 id="url">The url package</h3>
+
+<p>
+In Go 1 several fields from the <a href="/pkg/net/url/#URL"><code>url.URL</code></a> type
+were removed or replaced.
+</p>
+
+<p>
+The <a href="/pkg/net/url/#URL.String"><code>String</code></a> method now
+predictably rebuilds an encoded URL string using all of <code>URL</code>'s
+fields as necessary. The resulting string will also no longer have
+passwords escaped.
+</p>
+
+<p>
+The <code>Raw</code> field has been removed. In most cases the <code>String</code>
+method may be used in its place.
+</p>
+
+<p>
+The old <code>RawUserinfo</code> field is replaced by the <code>User</code>
+field, of type <a href="/pkg/net/url/#Userinfo"><code>*net.Userinfo</code></a>.
+Values of this type may be created using the new <a href="/pkg/net/url/#User"><code>net.User</code></a>
+and <a href="/pkg/net/url/#UserPassword"><code>net.UserPassword</code></a>
+functions. The <code>EscapeUserinfo</code> and <code>UnescapeUserinfo</code>
+functions are also gone.
+</p>
+
+<p>
+The <code>RawAuthority</code> field has been removed. The same information is
+available in the <code>Host</code> and <code>User</code> fields.
+</p>
+
+<p>
+The <code>RawPath</code> field and the <code>EncodedPath</code> method have
+been removed. The path information in rooted URLs (with a slash following the
+schema) is now available only in decoded form in the <code>Path</code> field.
+Occasionally, the encoded data may be required to obtain information that
+was lost in the decoding process. These cases must be handled by accessing
+the data the URL was built from.
+</p>
+
+<p>
+URLs with non-rooted paths, such as <code>"mailto:dev@golang.org?subject=Hi"</code>,
+are also handled differently. The <code>OpaquePath</code> boolean field has been
+removed and a new <code>Opaque</code> string field introduced to hold the encoded
+path for such URLs. In Go 1, the cited URL parses as:
+</p>
+
+<pre>
+ URL{
+ Scheme: "mailto",
+ Opaque: "dev@golang.org",
+ RawQuery: "subject=Hi",
+ }
+</pre>
+
+<p>
+A new <a href="/pkg/net/url/#URL.RequestURI"><code>RequestURI</code></a> method was
+added to <code>URL</code>.
+</p>
+
+<p>
+The <code>ParseWithReference</code> function has been renamed to <code>ParseWithFragment</code>.
+</p>
+
+<p>
+<em>Updating</em>:
+Code that uses the old fields will fail to compile and must be updated by hand.
+The semantic changes make it difficult for the fix tool to update automatically.
+</p>
+
+<h2 id="cmd_go">The go command</h2>
+
+<p>
+Go 1 introduces the <a href="/cmd/go/">go command</a>, a tool for fetching,
+building, and installing Go packages and commands. The <code>go</code> command
+does away with makefiles, instead using Go source code to find dependencies and
+determine build conditions. Most existing Go programs will no longer require
+makefiles to be built.
+</p>
+
+<p>
+See <a href="/doc/code.html">How to Write Go Code</a> for a primer on the
+<code>go</code> command and the <a href="/cmd/go/">go command documentation</a>
+for the full details.
+</p>
+
+<p>
+<em>Updating</em>:
+Projects that depend on the Go project's old makefile-based build
+infrastructure (<code>Make.pkg</code>, <code>Make.cmd</code>, and so on) should
+switch to using the <code>go</code> command for building Go code and, if
+necessary, rewrite their makefiles to perform any auxiliary build tasks.
+</p>
+
+<h2 id="cmd_cgo">The cgo command</h2>
+
+<p>
+In Go 1, the <a href="/cmd/cgo">cgo command</a>
+uses a different <code>_cgo_export.h</code>
+file, which is generated for packages containing <code>//export</code> lines.
+The <code>_cgo_export.h</code> file now begins with the C preamble comment,
+so that exported function definitions can use types defined there.
+This has the effect of compiling the preamble multiple times, so a
+package using <code>//export</code> must not put function definitions
+or variable initializations in the C preamble.
+</p>
+
+<h2 id="releases">Packaged releases</h2>
+
+<p>
+One of the most significant changes associated with Go 1 is the availability
+of prepackaged, downloadable distributions.
+They are available for many combinations of architecture and operating system
+(including Windows) and the list will grow.
+Installation details are described on the
+<a href="/doc/install">Getting Started</a> page, while
+the distributions themselves are listed on the
+<a href="http://code.google.com/p/go/downloads/list">downloads page</a>.
+
+
+</div>
+
+<div id="footer">
+Build version go1.0.1.<br>
+A link <a href="http://code.google.com/policies.html#restrictions">noted</a>,
+and then, coming up on the very next line, we will
+find yet another link, link 3.0 if you will,
+after a few more words <a href="/LINK">link text</a>.<br>
+<a href="/doc/tos.html">Terms of Service</a> |
+<a href="http://www.google.com/intl/en/privacy/privacy-policy.html">Privacy Policy</a>
+</div>
+
+<script type="text/javascript">
+(function() {
+ var ga = document.createElement("script"); ga.type = "text/javascript"; ga.async = true;
+ ga.src = ("https:" == document.location.protocol ? "https://ssl" : "http://www") + ".google-analytics.com/ga.js";
+ var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(ga, s);
+})();
+</script>
+</body>
+<script type="text/javascript">
+ (function() {
+ var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
+ po.src = 'https://apis.google.com/js/plusone.js';
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
+ })();
+</script>
+</html>
+
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/README b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/README
new file mode 100644
index 000000000..9b4c2d8be
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/README
@@ -0,0 +1,28 @@
+The *.dat files in this directory are copied from The WebKit Open Source
+Project, specifically $WEBKITROOT/LayoutTests/html5lib/resources.
+WebKit is licensed under a BSD style license.
+http://webkit.org/coding/bsd-license.html says:
+
+Copyright (C) 2009 Apple Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS "AS IS" AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/adoption01.dat b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/adoption01.dat
new file mode 100644
index 000000000..787e1b01e
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/adoption01.dat
@@ -0,0 +1,194 @@
+#data
+<a><p></a></p>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| <p>
+| <a>
+
+#data
+<a>1<p>2</a>3</p>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| "1"
+| <p>
+| <a>
+| "2"
+| "3"
+
+#data
+<a>1<button>2</a>3</button>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| "1"
+| <button>
+| <a>
+| "2"
+| "3"
+
+#data
+<a>1<b>2</a>3</b>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| "1"
+| <b>
+| "2"
+| <b>
+| "3"
+
+#data
+<a>1<div>2<div>3</a>4</div>5</div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| "1"
+| <div>
+| <a>
+| "2"
+| <div>
+| <a>
+| "3"
+| "4"
+| "5"
+
+#data
+<table><a>1<p>2</a>3</p>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| "1"
+| <p>
+| <a>
+| "2"
+| "3"
+| <table>
+
+#data
+<b><b><a><p></a>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| <b>
+| <a>
+| <p>
+| <a>
+
+#data
+<b><a><b><p></a>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| <a>
+| <b>
+| <b>
+| <p>
+| <a>
+
+#data
+<a><b><b><p></a>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| <b>
+| <b>
+| <b>
+| <b>
+| <p>
+| <a>
+
+#data
+<p>1<s id="A">2<b id="B">3</p>4</s>5</b>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| "1"
+| <s>
+| id="A"
+| "2"
+| <b>
+| id="B"
+| "3"
+| <s>
+| id="A"
+| <b>
+| id="B"
+| "4"
+| <b>
+| id="B"
+| "5"
+
+#data
+<table><a>1<td>2</td>3</table>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| "1"
+| <a>
+| "3"
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| "2"
+
+#data
+<table>A<td>B</td>C</table>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "AC"
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| "B"
+
+#data
+<a><svg><tr><input></a>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| <svg svg>
+| <svg tr>
+| <svg input>
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/adoption02.dat b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/adoption02.dat
new file mode 100644
index 000000000..d18151b44
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/adoption02.dat
@@ -0,0 +1,31 @@
+#data
+<b>1<i>2<p>3</b>4
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| "1"
+| <i>
+| "2"
+| <i>
+| <p>
+| <b>
+| "3"
+| "4"
+
+#data
+<a><div><style></style><address><a>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| <div>
+| <a>
+| <style>
+| <address>
+| <a>
+| <a>
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/comments01.dat b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/comments01.dat
new file mode 100644
index 000000000..44f187683
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/comments01.dat
@@ -0,0 +1,135 @@
+#data
+FOO<!-- BAR -->BAZ
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <!-- BAR -->
+| "BAZ"
+
+#data
+FOO<!-- BAR --!>BAZ
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <!-- BAR -->
+| "BAZ"
+
+#data
+FOO<!-- BAR -- >BAZ
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <!-- BAR -- >BAZ -->
+
+#data
+FOO<!-- BAR -- <QUX> -- MUX -->BAZ
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <!-- BAR -- <QUX> -- MUX -->
+| "BAZ"
+
+#data
+FOO<!-- BAR -- <QUX> -- MUX --!>BAZ
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <!-- BAR -- <QUX> -- MUX -->
+| "BAZ"
+
+#data
+FOO<!-- BAR -- <QUX> -- MUX -- >BAZ
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <!-- BAR -- <QUX> -- MUX -- >BAZ -->
+
+#data
+FOO<!---->BAZ
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <!-- -->
+| "BAZ"
+
+#data
+FOO<!--->BAZ
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <!-- -->
+| "BAZ"
+
+#data
+FOO<!-->BAZ
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <!-- -->
+| "BAZ"
+
+#data
+<?xml version="1.0">Hi
+#errors
+#document
+| <!-- ?xml version="1.0" -->
+| <html>
+| <head>
+| <body>
+| "Hi"
+
+#data
+<?xml version="1.0">
+#errors
+#document
+| <!-- ?xml version="1.0" -->
+| <html>
+| <head>
+| <body>
+
+#data
+<?xml version
+#errors
+#document
+| <!-- ?xml version -->
+| <html>
+| <head>
+| <body>
+
+#data
+FOO<!----->BAZ
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <!-- - -->
+| "BAZ"
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/doctype01.dat b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/doctype01.dat
new file mode 100644
index 000000000..ae457328a
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/doctype01.dat
@@ -0,0 +1,370 @@
+#data
+<!DOCTYPE html>Hello
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!dOctYpE HtMl>Hello
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPEhtml>Hello
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE>Hello
+#errors
+#document
+| <!DOCTYPE >
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE >Hello
+#errors
+#document
+| <!DOCTYPE >
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato>Hello
+#errors
+#document
+| <!DOCTYPE potato>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato >Hello
+#errors
+#document
+| <!DOCTYPE potato>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato taco>Hello
+#errors
+#document
+| <!DOCTYPE potato>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato taco "ddd>Hello
+#errors
+#document
+| <!DOCTYPE potato>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato sYstEM>Hello
+#errors
+#document
+| <!DOCTYPE potato>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato sYstEM >Hello
+#errors
+#document
+| <!DOCTYPE potato>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato sYstEM ggg>Hello
+#errors
+#document
+| <!DOCTYPE potato>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato SYSTEM taco >Hello
+#errors
+#document
+| <!DOCTYPE potato>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato SYSTEM 'taco"'>Hello
+#errors
+#document
+| <!DOCTYPE potato "" "taco"">
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato SYSTEM "taco">Hello
+#errors
+#document
+| <!DOCTYPE potato "" "taco">
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato SYSTEM "tai'co">Hello
+#errors
+#document
+| <!DOCTYPE potato "" "tai'co">
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato SYSTEMtaco "ddd">Hello
+#errors
+#document
+| <!DOCTYPE potato>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato grass SYSTEM taco>Hello
+#errors
+#document
+| <!DOCTYPE potato>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato pUbLIc>Hello
+#errors
+#document
+| <!DOCTYPE potato>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato pUbLIc >Hello
+#errors
+#document
+| <!DOCTYPE potato>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato pUbLIcgoof>Hello
+#errors
+#document
+| <!DOCTYPE potato>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato PUBLIC goof>Hello
+#errors
+#document
+| <!DOCTYPE potato>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato PUBLIC "go'of">Hello
+#errors
+#document
+| <!DOCTYPE potato "go'of" "">
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato PUBLIC 'go'of'>Hello
+#errors
+#document
+| <!DOCTYPE potato "go" "">
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato PUBLIC 'go:hh of' >Hello
+#errors
+#document
+| <!DOCTYPE potato "go:hh of" "">
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato PUBLIC "W3C-//dfdf" SYSTEM ggg>Hello
+#errors
+#document
+| <!DOCTYPE potato "W3C-//dfdf" "">
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">Hello
+#errors
+#document
+| <!DOCTYPE html "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE ...>Hello
+#errors
+#document
+| <!DOCTYPE ...>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+#errors
+#document
+| <!DOCTYPE html "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+| <html>
+| <head>
+| <body>
+
+#data
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
+#errors
+#document
+| <!DOCTYPE html "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
+| <html>
+| <head>
+| <body>
+
+#data
+<!DOCTYPE root-element [SYSTEM OR PUBLIC FPI] "uri" [
+<!-- internal declarations -->
+]>
+#errors
+#document
+| <!DOCTYPE root-element>
+| <html>
+| <head>
+| <body>
+| "]>"
+
+#data
+<!DOCTYPE html PUBLIC
+ "-//WAPFORUM//DTD XHTML Mobile 1.0//EN"
+ "http://www.wapforum.org/DTD/xhtml-mobile10.dtd">
+#errors
+#document
+| <!DOCTYPE html "-//WAPFORUM//DTD XHTML Mobile 1.0//EN" "http://www.wapforum.org/DTD/xhtml-mobile10.dtd">
+| <html>
+| <head>
+| <body>
+
+#data
+<!DOCTYPE HTML SYSTEM "http://www.w3.org/DTD/HTML4-strict.dtd"><body><b>Mine!</b></body>
+#errors
+#document
+| <!DOCTYPE html "" "http://www.w3.org/DTD/HTML4-strict.dtd">
+| <html>
+| <head>
+| <body>
+| <b>
+| "Mine!"
+
+#data
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""http://www.w3.org/TR/html4/strict.dtd">
+#errors
+#document
+| <!DOCTYPE html "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+| <html>
+| <head>
+| <body>
+
+#data
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"'http://www.w3.org/TR/html4/strict.dtd'>
+#errors
+#document
+| <!DOCTYPE html "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+| <html>
+| <head>
+| <body>
+
+#data
+<!DOCTYPE HTML PUBLIC"-//W3C//DTD HTML 4.01//EN"'http://www.w3.org/TR/html4/strict.dtd'>
+#errors
+#document
+| <!DOCTYPE html "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+| <html>
+| <head>
+| <body>
+
+#data
+<!DOCTYPE HTML PUBLIC'-//W3C//DTD HTML 4.01//EN''http://www.w3.org/TR/html4/strict.dtd'>
+#errors
+#document
+| <!DOCTYPE html "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+| <html>
+| <head>
+| <body>
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/entities01.dat b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/entities01.dat
new file mode 100644
index 000000000..c8073b781
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/entities01.dat
@@ -0,0 +1,603 @@
+#data
+FOO&gt;BAR
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO>BAR"
+
+#data
+FOO&gtBAR
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO>BAR"
+
+#data
+FOO&gt BAR
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO> BAR"
+
+#data
+FOO&gt;;;BAR
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO>;;BAR"
+
+#data
+I'm &notit; I tell you
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "I'm ¬it; I tell you"
+
+#data
+I'm &notin; I tell you
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "I'm ∉ I tell you"
+
+#data
+FOO& BAR
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO& BAR"
+
+#data
+FOO&<BAR>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO&"
+| <bar>
+
+#data
+FOO&&&&gt;BAR
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO&&&>BAR"
+
+#data
+FOO&#41;BAR
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO)BAR"
+
+#data
+FOO&#x41;BAR
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOOABAR"
+
+#data
+FOO&#X41;BAR
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOOABAR"
+
+#data
+FOO&#BAR
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO&#BAR"
+
+#data
+FOO&#ZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO&#ZOO"
+
+#data
+FOO&#xBAR
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOOºR"
+
+#data
+FOO&#xZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO&#xZOO"
+
+#data
+FOO&#XZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO&#XZOO"
+
+#data
+FOO&#41BAR
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO)BAR"
+
+#data
+FOO&#x41BAR
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO䆺R"
+
+#data
+FOO&#x41ZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOOAZOO"
+
+#data
+FOO&#x0000;ZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO�ZOO"
+
+#data
+FOO&#x0078;ZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOOxZOO"
+
+#data
+FOO&#x0079;ZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOOyZOO"
+
+#data
+FOO&#x0080;ZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO€ZOO"
+
+#data
+FOO&#x0081;ZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOOZOO"
+
+#data
+FOO&#x0082;ZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO‚ZOO"
+
+#data
+FOO&#x0083;ZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOOƒZOO"
+
+#data
+FOO&#x0084;ZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO„ZOO"
+
+#data
+FOO&#x0085;ZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO…ZOO"
+
+#data
+FOO&#x0086;ZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO†ZOO"
+
+#data
+FOO&#x0087;ZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO‡ZOO"
+
+#data
+FOO&#x0088;ZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOOˆZOO"
+
+#data
+FOO&#x0089;ZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO‰ZOO"
+
+#data
+FOO&#x008A;ZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOOŠZOO"
+
+#data
+FOO&#x008B;ZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO‹ZOO"
+
+#data
+FOO&#x008C;ZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOOŒZOO"
+
+#data
+FOO&#x008D;ZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOOZOO"
+
+#data
+FOO&#x008E;ZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOOŽZOO"
+
+#data
+FOO&#x008F;ZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOOZOO"
+
+#data
+FOO&#x0090;ZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOOZOO"
+
+#data
+FOO&#x0091;ZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO‘ZOO"
+
+#data
+FOO&#x0092;ZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO’ZOO"
+
+#data
+FOO&#x0093;ZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO“ZOO"
+
+#data
+FOO&#x0094;ZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO”ZOO"
+
+#data
+FOO&#x0095;ZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO•ZOO"
+
+#data
+FOO&#x0096;ZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO–ZOO"
+
+#data
+FOO&#x0097;ZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO—ZOO"
+
+#data
+FOO&#x0098;ZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO˜ZOO"
+
+#data
+FOO&#x0099;ZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO™ZOO"
+
+#data
+FOO&#x009A;ZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOOšZOO"
+
+#data
+FOO&#x009B;ZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO›ZOO"
+
+#data
+FOO&#x009C;ZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOOœZOO"
+
+#data
+FOO&#x009D;ZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOOZOO"
+
+#data
+FOO&#x009E;ZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOOžZOO"
+
+#data
+FOO&#x009F;ZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOOŸZOO"
+
+#data
+FOO&#x00A0;ZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO ZOO"
+
+#data
+FOO&#xD7FF;ZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO퟿ZOO"
+
+#data
+FOO&#xD800;ZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO�ZOO"
+
+#data
+FOO&#xD801;ZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO�ZOO"
+
+#data
+FOO&#xDFFE;ZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO�ZOO"
+
+#data
+FOO&#xDFFF;ZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO�ZOO"
+
+#data
+FOO&#xE000;ZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOOZOO"
+
+#data
+FOO&#x10FFFE;ZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO􏿾ZOO"
+
+#data
+FOO&#x1087D4;ZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO􈟔ZOO"
+
+#data
+FOO&#x10FFFF;ZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO􏿿ZOO"
+
+#data
+FOO&#x110000;ZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO�ZOO"
+
+#data
+FOO&#xFFFFFF;ZOO
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO�ZOO"
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/entities02.dat b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/entities02.dat
new file mode 100644
index 000000000..e2fb42a07
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/entities02.dat
@@ -0,0 +1,249 @@
+#data
+<div bar="ZZ&gt;YY"></div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ>YY"
+
+#data
+<div bar="ZZ&"></div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ&"
+
+#data
+<div bar='ZZ&'></div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ&"
+
+#data
+<div bar=ZZ&></div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ&"
+
+#data
+<div bar="ZZ&gt=YY"></div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ&gt=YY"
+
+#data
+<div bar="ZZ&gt0YY"></div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ&gt0YY"
+
+#data
+<div bar="ZZ&gt9YY"></div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ&gt9YY"
+
+#data
+<div bar="ZZ&gtaYY"></div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ&gtaYY"
+
+#data
+<div bar="ZZ&gtZYY"></div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ&gtZYY"
+
+#data
+<div bar="ZZ&gt YY"></div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ> YY"
+
+#data
+<div bar="ZZ&gt"></div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ>"
+
+#data
+<div bar='ZZ&gt'></div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ>"
+
+#data
+<div bar=ZZ&gt></div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ>"
+
+#data
+<div bar="ZZ&pound_id=23"></div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ£_id=23"
+
+#data
+<div bar="ZZ&prod_id=23"></div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ&prod_id=23"
+
+#data
+<div bar="ZZ&pound;_id=23"></div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ£_id=23"
+
+#data
+<div bar="ZZ&prod;_id=23"></div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ∏_id=23"
+
+#data
+<div bar="ZZ&pound=23"></div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ&pound=23"
+
+#data
+<div bar="ZZ&prod=23"></div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ&prod=23"
+
+#data
+<div>ZZ&pound_id=23</div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| "ZZ£_id=23"
+
+#data
+<div>ZZ&prod_id=23</div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| "ZZ&prod_id=23"
+
+#data
+<div>ZZ&pound;_id=23</div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| "ZZ£_id=23"
+
+#data
+<div>ZZ&prod;_id=23</div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| "ZZ∏_id=23"
+
+#data
+<div>ZZ&pound=23</div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| "ZZ£=23"
+
+#data
+<div>ZZ&prod=23</div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| "ZZ&prod=23"
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/html5test-com.dat b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/html5test-com.dat
new file mode 100644
index 000000000..d7cb71db0
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/html5test-com.dat
@@ -0,0 +1,246 @@
+#data
+<div<div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div<div>
+
+#data
+<div foo<bar=''>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| foo<bar=""
+
+#data
+<div foo=`bar`>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| foo="`bar`"
+
+#data
+<div \"foo=''>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| \"foo=""
+
+#data
+<a href='\nbar'></a>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| href="\nbar"
+
+#data
+<!DOCTYPE html>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+
+#data
+&lang;&rang;
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "⟨⟩"
+
+#data
+&apos;
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "'"
+
+#data
+&ImaginaryI;
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "ⅈ"
+
+#data
+&Kopf;
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "𝕂"
+
+#data
+&notinva;
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "∉"
+
+#data
+<?import namespace="foo" implementation="#bar">
+#errors
+#document
+| <!-- ?import namespace="foo" implementation="#bar" -->
+| <html>
+| <head>
+| <body>
+
+#data
+<!--foo--bar-->
+#errors
+#document
+| <!-- foo--bar -->
+| <html>
+| <head>
+| <body>
+
+#data
+<![CDATA[x]]>
+#errors
+#document
+| <!-- [CDATA[x]] -->
+| <html>
+| <head>
+| <body>
+
+#data
+<textarea><!--</textarea>--></textarea>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <textarea>
+| "<!--"
+| "-->"
+
+#data
+<textarea><!--</textarea>-->
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <textarea>
+| "<!--"
+| "-->"
+
+#data
+<style><!--</style>--></style>
+#errors
+#document
+| <html>
+| <head>
+| <style>
+| "<!--"
+| <body>
+| "-->"
+
+#data
+<style><!--</style>-->
+#errors
+#document
+| <html>
+| <head>
+| <style>
+| "<!--"
+| <body>
+| "-->"
+
+#data
+<ul><li>A </li> <li>B</li></ul>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <ul>
+| <li>
+| "A "
+| " "
+| <li>
+| "B"
+
+#data
+<table><form><input type=hidden><input></form><div></div></table>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <input>
+| <div>
+| <table>
+| <form>
+| <input>
+| type="hidden"
+
+#data
+<i>A<b>B<p></i>C</b>D
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <i>
+| "A"
+| <b>
+| "B"
+| <b>
+| <p>
+| <b>
+| <i>
+| "C"
+| "D"
+
+#data
+<div></div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+
+#data
+<svg></svg>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+
+#data
+<math></math>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/inbody01.dat b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/inbody01.dat
new file mode 100644
index 000000000..3f2bd374c
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/inbody01.dat
@@ -0,0 +1,43 @@
+#data
+<button>1</foo>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <button>
+| "1"
+
+#data
+<foo>1<p>2</foo>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <foo>
+| "1"
+| <p>
+| "2"
+
+#data
+<dd>1</foo>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <dd>
+| "1"
+
+#data
+<foo>1<dd>2</foo>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <foo>
+| "1"
+| <dd>
+| "2"
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/isindex.dat b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/isindex.dat
new file mode 100644
index 000000000..88325ffe6
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/isindex.dat
@@ -0,0 +1,40 @@
+#data
+<isindex>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <form>
+| <hr>
+| <label>
+| "This is a searchable index. Enter search keywords: "
+| <input>
+| name="isindex"
+| <hr>
+
+#data
+<isindex name="A" action="B" prompt="C" foo="D">
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <form>
+| action="B"
+| <hr>
+| <label>
+| "C"
+| <input>
+| foo="D"
+| name="isindex"
+| <hr>
+
+#data
+<form><isindex>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <form>
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/pending-spec-changes-plain-text-unsafe.dat b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/pending-spec-changes-plain-text-unsafe.dat
new file mode 100644
index 000000000..a5ebb1eb2
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/pending-spec-changes-plain-text-unsafe.dat
Binary files differ
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/pending-spec-changes.dat b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/pending-spec-changes.dat
new file mode 100644
index 000000000..5a9208465
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/pending-spec-changes.dat
@@ -0,0 +1,52 @@
+#data
+<input type="hidden"><frameset>
+#errors
+21: Start tag seen without seeing a doctype first. Expected “<!DOCTYPE html>”.
+31: “frameset” start tag seen.
+31: End of file seen and there were open elements.
+#document
+| <html>
+| <head>
+| <frameset>
+
+#data
+<!DOCTYPE html><table><caption><svg>foo</table>bar
+#errors
+47: End tag “table” did not match the name of the current open element (“svg”).
+47: “table” closed but “caption” was still open.
+47: End tag “table” seen, but there were open elements.
+36: Unclosed element “svg”.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+| <svg svg>
+| "foo"
+| "bar"
+
+#data
+<table><tr><td><svg><desc><td></desc><circle>
+#errors
+7: Start tag seen without seeing a doctype first. Expected “<!DOCTYPE html>”.
+30: A table cell was implicitly closed, but there were open elements.
+26: Unclosed element “desc”.
+20: Unclosed element “svg”.
+37: Stray end tag “desc”.
+45: End of file seen and there were open elements.
+45: Unclosed element “circle”.
+7: Unclosed element “table”.
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <svg svg>
+| <svg desc>
+| <td>
+| <circle>
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/plain-text-unsafe.dat b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/plain-text-unsafe.dat
new file mode 100644
index 000000000..04cc11fb9
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/plain-text-unsafe.dat
Binary files differ
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/scriptdata01.dat b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/scriptdata01.dat
new file mode 100644
index 000000000..76b67f4ba
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/scriptdata01.dat
@@ -0,0 +1,308 @@
+#data
+FOO<script>'Hello'</script>BAR
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| "'Hello'"
+| "BAR"
+
+#data
+FOO<script></script>BAR
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| "BAR"
+
+#data
+FOO<script></script >BAR
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| "BAR"
+
+#data
+FOO<script></script/>BAR
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| "BAR"
+
+#data
+FOO<script></script/ >BAR
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| "BAR"
+
+#data
+FOO<script type="text/plain"></scriptx>BAR
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| type="text/plain"
+| "</scriptx>BAR"
+
+#data
+FOO<script></script foo=">" dd>BAR
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| "BAR"
+
+#data
+FOO<script>'<'</script>BAR
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| "'<'"
+| "BAR"
+
+#data
+FOO<script>'<!'</script>BAR
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| "'<!'"
+| "BAR"
+
+#data
+FOO<script>'<!-'</script>BAR
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| "'<!-'"
+| "BAR"
+
+#data
+FOO<script>'<!--'</script>BAR
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| "'<!--'"
+| "BAR"
+
+#data
+FOO<script>'<!---'</script>BAR
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| "'<!---'"
+| "BAR"
+
+#data
+FOO<script>'<!-->'</script>BAR
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| "'<!-->'"
+| "BAR"
+
+#data
+FOO<script>'<!-->'</script>BAR
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| "'<!-->'"
+| "BAR"
+
+#data
+FOO<script>'<!-- potato'</script>BAR
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| "'<!-- potato'"
+| "BAR"
+
+#data
+FOO<script>'<!-- <sCrIpt'</script>BAR
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| "'<!-- <sCrIpt'"
+| "BAR"
+
+#data
+FOO<script type="text/plain">'<!-- <sCrIpt>'</script>BAR
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| type="text/plain"
+| "'<!-- <sCrIpt>'</script>BAR"
+
+#data
+FOO<script type="text/plain">'<!-- <sCrIpt> -'</script>BAR
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| type="text/plain"
+| "'<!-- <sCrIpt> -'</script>BAR"
+
+#data
+FOO<script type="text/plain">'<!-- <sCrIpt> --'</script>BAR
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| type="text/plain"
+| "'<!-- <sCrIpt> --'</script>BAR"
+
+#data
+FOO<script>'<!-- <sCrIpt> -->'</script>BAR
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| "'<!-- <sCrIpt> -->'"
+| "BAR"
+
+#data
+FOO<script type="text/plain">'<!-- <sCrIpt> --!>'</script>BAR
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| type="text/plain"
+| "'<!-- <sCrIpt> --!>'</script>BAR"
+
+#data
+FOO<script type="text/plain">'<!-- <sCrIpt> -- >'</script>BAR
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| type="text/plain"
+| "'<!-- <sCrIpt> -- >'</script>BAR"
+
+#data
+FOO<script type="text/plain">'<!-- <sCrIpt '</script>BAR
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| type="text/plain"
+| "'<!-- <sCrIpt '</script>BAR"
+
+#data
+FOO<script type="text/plain">'<!-- <sCrIpt/'</script>BAR
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| type="text/plain"
+| "'<!-- <sCrIpt/'</script>BAR"
+
+#data
+FOO<script type="text/plain">'<!-- <sCrIpt\'</script>BAR
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| type="text/plain"
+| "'<!-- <sCrIpt\'"
+| "BAR"
+
+#data
+FOO<script type="text/plain">'<!-- <sCrIpt/'</script>BAR</script>QUX
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| type="text/plain"
+| "'<!-- <sCrIpt/'</script>BAR"
+| "QUX"
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/scripted/adoption01.dat b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/scripted/adoption01.dat
new file mode 100644
index 000000000..4e08d0e84
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/scripted/adoption01.dat
@@ -0,0 +1,15 @@
+#data
+<p><b id="A"><script>document.getElementById("A").id = "B"</script></p>TEXT</b>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <b>
+| id="B"
+| <script>
+| "document.getElementById("A").id = "B""
+| <b>
+| id="A"
+| "TEXT"
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/scripted/webkit01.dat b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/scripted/webkit01.dat
new file mode 100644
index 000000000..ef4a41ca0
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/scripted/webkit01.dat
@@ -0,0 +1,28 @@
+#data
+1<script>document.write("2")</script>3
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "1"
+| <script>
+| "document.write("2")"
+| "23"
+
+#data
+1<script>document.write("<script>document.write('2')</scr"+ "ipt><script>document.write('3')</scr" + "ipt>")</script>4
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "1"
+| <script>
+| "document.write("<script>document.write('2')</scr"+ "ipt><script>document.write('3')</scr" + "ipt>")"
+| <script>
+| "document.write('2')"
+| "2"
+| <script>
+| "document.write('3')"
+| "34"
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tables01.dat b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tables01.dat
new file mode 100644
index 000000000..c4b47e48a
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tables01.dat
@@ -0,0 +1,212 @@
+#data
+<table><th>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <th>
+
+#data
+<table><td>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+
+#data
+<table><col foo='bar'>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <colgroup>
+| <col>
+| foo="bar"
+
+#data
+<table><colgroup></html>foo
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "foo"
+| <table>
+| <colgroup>
+
+#data
+<table></table><p>foo
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <p>
+| "foo"
+
+#data
+<table></body></caption></col></colgroup></html></tbody></td></tfoot></th></thead></tr><td>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+
+#data
+<table><select><option>3</select></table>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <select>
+| <option>
+| "3"
+| <table>
+
+#data
+<table><select><table></table></select></table>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <select>
+| <table>
+| <table>
+
+#data
+<table><select></table>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <select>
+| <table>
+
+#data
+<table><select><option>A<tr><td>B</td></tr></table>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <select>
+| <option>
+| "A"
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| "B"
+
+#data
+<table><td></body></caption></col></colgroup></html>foo
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| "foo"
+
+#data
+<table><td>A</table>B
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| "A"
+| "B"
+
+#data
+<table><tr><caption>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <caption>
+
+#data
+<table><tr></body></caption></col></colgroup></html></td></th><td>foo
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| "foo"
+
+#data
+<table><td><tr>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <tr>
+
+#data
+<table><td><button><td>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <button>
+| <td>
+
+#data
+<table><tr><td><svg><desc><td>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <svg svg>
+| <svg desc>
+| <td>
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests1.dat b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests1.dat
new file mode 100644
index 000000000..cbf8bdda6
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests1.dat
@@ -0,0 +1,1952 @@
+#data
+Test
+#errors
+Line: 1 Col: 4 Unexpected non-space characters. Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <body>
+| "Test"
+
+#data
+<p>One<p>Two
+#errors
+Line: 1 Col: 3 Unexpected start tag (p). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| "One"
+| <p>
+| "Two"
+
+#data
+Line1<br>Line2<br>Line3<br>Line4
+#errors
+Line: 1 Col: 5 Unexpected non-space characters. Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <body>
+| "Line1"
+| <br>
+| "Line2"
+| <br>
+| "Line3"
+| <br>
+| "Line4"
+
+#data
+<html>
+#errors
+Line: 1 Col: 6 Unexpected start tag (html). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<head>
+#errors
+Line: 1 Col: 6 Unexpected start tag (head). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<body>
+#errors
+Line: 1 Col: 6 Unexpected start tag (body). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<html><head>
+#errors
+Line: 1 Col: 6 Unexpected start tag (html). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<html><head></head>
+#errors
+Line: 1 Col: 6 Unexpected start tag (html). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<html><head></head><body>
+#errors
+Line: 1 Col: 6 Unexpected start tag (html). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<html><head></head><body></body>
+#errors
+Line: 1 Col: 6 Unexpected start tag (html). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<html><head><body></body></html>
+#errors
+Line: 1 Col: 6 Unexpected start tag (html). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<html><head></body></html>
+#errors
+Line: 1 Col: 6 Unexpected start tag (html). Expected DOCTYPE.
+Line: 1 Col: 19 Unexpected end tag (body).
+Line: 1 Col: 26 Unexpected end tag (html).
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<html><head><body></html>
+#errors
+Line: 1 Col: 6 Unexpected start tag (html). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<html><body></html>
+#errors
+Line: 1 Col: 6 Unexpected start tag (html). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<body></html>
+#errors
+Line: 1 Col: 6 Unexpected start tag (body). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<head></html>
+#errors
+Line: 1 Col: 6 Unexpected start tag (head). Expected DOCTYPE.
+Line: 1 Col: 13 Unexpected end tag (html). Ignored.
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+</head>
+#errors
+Line: 1 Col: 7 Unexpected end tag (head). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+</body>
+#errors
+Line: 1 Col: 7 Unexpected end tag (body). Expected DOCTYPE.
+Line: 1 Col: 7 Unexpected end tag (body) after the (implied) root element.
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+</html>
+#errors
+Line: 1 Col: 7 Unexpected end tag (html). Expected DOCTYPE.
+Line: 1 Col: 7 Unexpected end tag (html) after the (implied) root element.
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<b><table><td><i></table>
+#errors
+Line: 1 Col: 3 Unexpected start tag (b). Expected DOCTYPE.
+Line: 1 Col: 14 Unexpected table cell start tag (td) in the table body phase.
+Line: 1 Col: 25 Got table cell end tag (td) while required end tags are missing.
+Line: 1 Col: 25 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <i>
+
+#data
+<b><table><td></b><i></table>X
+#errors
+Line: 1 Col: 3 Unexpected start tag (b). Expected DOCTYPE.
+Line: 1 Col: 14 Unexpected table cell start tag (td) in the table body phase.
+Line: 1 Col: 18 End tag (b) violates step 1, paragraph 1 of the adoption agency algorithm.
+Line: 1 Col: 29 Got table cell end tag (td) while required end tags are missing.
+Line: 1 Col: 30 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <i>
+| "X"
+
+#data
+<h1>Hello<h2>World
+#errors
+4: Start tag seen without seeing a doctype first. Expected “<!DOCTYPE html>”.
+13: Heading cannot be a child of another heading.
+18: End of file seen and there were open elements.
+#document
+| <html>
+| <head>
+| <body>
+| <h1>
+| "Hello"
+| <h2>
+| "World"
+
+#data
+<a><p>X<a>Y</a>Z</p></a>
+#errors
+Line: 1 Col: 3 Unexpected start tag (a). Expected DOCTYPE.
+Line: 1 Col: 10 Unexpected start tag (a) implies end tag (a).
+Line: 1 Col: 10 End tag (a) violates step 1, paragraph 3 of the adoption agency algorithm.
+Line: 1 Col: 24 End tag (a) violates step 1, paragraph 1 of the adoption agency algorithm.
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| <p>
+| <a>
+| "X"
+| <a>
+| "Y"
+| "Z"
+
+#data
+<b><button>foo</b>bar
+#errors
+Line: 1 Col: 3 Unexpected start tag (b). Expected DOCTYPE.
+Line: 1 Col: 15 End tag (b) violates step 1, paragraph 1 of the adoption agency algorithm.
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| <button>
+| <b>
+| "foo"
+| "bar"
+
+#data
+<!DOCTYPE html><span><button>foo</span>bar
+#errors
+39: End tag “span” seen but there were unclosed elements.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <span>
+| <button>
+| "foobar"
+
+#data
+<p><b><div><marquee></p></b></div>X
+#errors
+Line: 1 Col: 3 Unexpected start tag (p). Expected DOCTYPE.
+Line: 1 Col: 11 Unexpected end tag (p). Ignored.
+Line: 1 Col: 24 Unexpected end tag (p). Ignored.
+Line: 1 Col: 28 End tag (b) violates step 1, paragraph 1 of the adoption agency algorithm.
+Line: 1 Col: 34 End tag (div) seen too early. Expected other end tag.
+Line: 1 Col: 35 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <b>
+| <div>
+| <b>
+| <marquee>
+| <p>
+| "X"
+
+#data
+<script><div></script></div><title><p></title><p><p>
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 28 Unexpected end tag (div). Ignored.
+#document
+| <html>
+| <head>
+| <script>
+| "<div>"
+| <title>
+| "<p>"
+| <body>
+| <p>
+| <p>
+
+#data
+<!--><div>--<!-->
+#errors
+Line: 1 Col: 5 Incorrect comment.
+Line: 1 Col: 10 Unexpected start tag (div). Expected DOCTYPE.
+Line: 1 Col: 17 Incorrect comment.
+Line: 1 Col: 17 Expected closing tag. Unexpected end of file.
+#document
+| <!-- -->
+| <html>
+| <head>
+| <body>
+| <div>
+| "--"
+| <!-- -->
+
+#data
+<p><hr></p>
+#errors
+Line: 1 Col: 3 Unexpected start tag (p). Expected DOCTYPE.
+Line: 1 Col: 11 Unexpected end tag (p). Ignored.
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <hr>
+| <p>
+
+#data
+<select><b><option><select><option></b></select>X
+#errors
+Line: 1 Col: 8 Unexpected start tag (select). Expected DOCTYPE.
+Line: 1 Col: 11 Unexpected start tag token (b) in the select phase. Ignored.
+Line: 1 Col: 27 Unexpected select start tag in the select phase treated as select end tag.
+Line: 1 Col: 39 End tag (b) violates step 1, paragraph 1 of the adoption agency algorithm.
+Line: 1 Col: 48 Unexpected end tag (select). Ignored.
+Line: 1 Col: 49 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <select>
+| <option>
+| <option>
+| "X"
+
+#data
+<a><table><td><a><table></table><a></tr><a></table><b>X</b>C<a>Y
+#errors
+Line: 1 Col: 3 Unexpected start tag (a). Expected DOCTYPE.
+Line: 1 Col: 14 Unexpected table cell start tag (td) in the table body phase.
+Line: 1 Col: 35 Unexpected start tag (a) implies end tag (a).
+Line: 1 Col: 40 Got table cell end tag (td) while required end tags are missing.
+Line: 1 Col: 43 Unexpected start tag (a) in table context caused voodoo mode.
+Line: 1 Col: 43 Unexpected start tag (a) implies end tag (a).
+Line: 1 Col: 43 End tag (a) violates step 1, paragraph 1 of the adoption agency algorithm.
+Line: 1 Col: 51 Unexpected implied end tag (a) in the table phase.
+Line: 1 Col: 63 Unexpected start tag (a) implies end tag (a).
+Line: 1 Col: 64 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| <a>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <a>
+| <table>
+| <a>
+| <a>
+| <b>
+| "X"
+| "C"
+| <a>
+| "Y"
+
+#data
+<a X>0<b>1<a Y>2
+#errors
+Line: 1 Col: 5 Unexpected start tag (a). Expected DOCTYPE.
+Line: 1 Col: 15 Unexpected start tag (a) implies end tag (a).
+Line: 1 Col: 15 End tag (a) violates step 1, paragraph 3 of the adoption agency algorithm.
+Line: 1 Col: 16 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| x=""
+| "0"
+| <b>
+| "1"
+| <b>
+| <a>
+| y=""
+| "2"
+
+#data
+<!-----><font><div>hello<table>excite!<b>me!<th><i>please!</tr><!--X-->
+#errors
+Line: 1 Col: 7 Unexpected '-' after '--' found in comment.
+Line: 1 Col: 14 Unexpected start tag (font). Expected DOCTYPE.
+Line: 1 Col: 38 Unexpected non-space characters in table context caused voodoo mode.
+Line: 1 Col: 41 Unexpected start tag (b) in table context caused voodoo mode.
+Line: 1 Col: 48 Unexpected implied end tag (b) in the table phase.
+Line: 1 Col: 48 Unexpected table cell start tag (th) in the table body phase.
+Line: 1 Col: 63 Got table cell end tag (th) while required end tags are missing.
+Line: 1 Col: 71 Unexpected end of file. Expected table content.
+#document
+| <!-- - -->
+| <html>
+| <head>
+| <body>
+| <font>
+| <div>
+| "helloexcite!"
+| <b>
+| "me!"
+| <table>
+| <tbody>
+| <tr>
+| <th>
+| <i>
+| "please!"
+| <!-- X -->
+
+#data
+<!DOCTYPE html><li>hello<li>world<ul>how<li>do</ul>you</body><!--do-->
+#errors
+Line: 1 Col: 61 Unexpected end tag (li). Missing end tag (body).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <li>
+| "hello"
+| <li>
+| "world"
+| <ul>
+| "how"
+| <li>
+| "do"
+| "you"
+| <!-- do -->
+
+#data
+<!DOCTYPE html>A<option>B<optgroup>C<select>D</option>E
+#errors
+Line: 1 Col: 54 Unexpected end tag (option) in the select phase. Ignored.
+Line: 1 Col: 55 Expected closing tag. Unexpected end of file.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "A"
+| <option>
+| "B"
+| <optgroup>
+| "C"
+| <select>
+| "DE"
+
+#data
+<
+#errors
+Line: 1 Col: 1 Expected tag name. Got something else instead
+Line: 1 Col: 1 Unexpected non-space characters. Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <body>
+| "<"
+
+#data
+<#
+#errors
+Line: 1 Col: 1 Expected tag name. Got something else instead
+Line: 1 Col: 1 Unexpected non-space characters. Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <body>
+| "<#"
+
+#data
+</
+#errors
+Line: 1 Col: 2 Expected closing tag. Unexpected end of file.
+Line: 1 Col: 2 Unexpected non-space characters. Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <body>
+| "</"
+
+#data
+</#
+#errors
+Line: 1 Col: 2 Expected closing tag. Unexpected character '#' found.
+Line: 1 Col: 3 Unexpected End of file. Expected DOCTYPE.
+#document
+| <!-- # -->
+| <html>
+| <head>
+| <body>
+
+#data
+<?
+#errors
+Line: 1 Col: 1 Expected tag name. Got '?' instead. (HTML doesn't support processing instructions.)
+Line: 1 Col: 2 Unexpected End of file. Expected DOCTYPE.
+#document
+| <!-- ? -->
+| <html>
+| <head>
+| <body>
+
+#data
+<?#
+#errors
+Line: 1 Col: 1 Expected tag name. Got '?' instead. (HTML doesn't support processing instructions.)
+Line: 1 Col: 3 Unexpected End of file. Expected DOCTYPE.
+#document
+| <!-- ?# -->
+| <html>
+| <head>
+| <body>
+
+#data
+<!
+#errors
+Line: 1 Col: 2 Expected '--' or 'DOCTYPE'. Not found.
+Line: 1 Col: 2 Unexpected End of file. Expected DOCTYPE.
+#document
+| <!-- -->
+| <html>
+| <head>
+| <body>
+
+#data
+<!#
+#errors
+Line: 1 Col: 3 Expected '--' or 'DOCTYPE'. Not found.
+Line: 1 Col: 3 Unexpected End of file. Expected DOCTYPE.
+#document
+| <!-- # -->
+| <html>
+| <head>
+| <body>
+
+#data
+<?COMMENT?>
+#errors
+Line: 1 Col: 1 Expected tag name. Got '?' instead. (HTML doesn't support processing instructions.)
+Line: 1 Col: 11 Unexpected End of file. Expected DOCTYPE.
+#document
+| <!-- ?COMMENT? -->
+| <html>
+| <head>
+| <body>
+
+#data
+<!COMMENT>
+#errors
+Line: 1 Col: 2 Expected '--' or 'DOCTYPE'. Not found.
+Line: 1 Col: 10 Unexpected End of file. Expected DOCTYPE.
+#document
+| <!-- COMMENT -->
+| <html>
+| <head>
+| <body>
+
+#data
+</ COMMENT >
+#errors
+Line: 1 Col: 2 Expected closing tag. Unexpected character ' ' found.
+Line: 1 Col: 12 Unexpected End of file. Expected DOCTYPE.
+#document
+| <!-- COMMENT -->
+| <html>
+| <head>
+| <body>
+
+#data
+<?COM--MENT?>
+#errors
+Line: 1 Col: 1 Expected tag name. Got '?' instead. (HTML doesn't support processing instructions.)
+Line: 1 Col: 13 Unexpected End of file. Expected DOCTYPE.
+#document
+| <!-- ?COM--MENT? -->
+| <html>
+| <head>
+| <body>
+
+#data
+<!COM--MENT>
+#errors
+Line: 1 Col: 2 Expected '--' or 'DOCTYPE'. Not found.
+Line: 1 Col: 12 Unexpected End of file. Expected DOCTYPE.
+#document
+| <!-- COM--MENT -->
+| <html>
+| <head>
+| <body>
+
+#data
+</ COM--MENT >
+#errors
+Line: 1 Col: 2 Expected closing tag. Unexpected character ' ' found.
+Line: 1 Col: 14 Unexpected End of file. Expected DOCTYPE.
+#document
+| <!-- COM--MENT -->
+| <html>
+| <head>
+| <body>
+
+#data
+<!DOCTYPE html><style> EOF
+#errors
+Line: 1 Col: 26 Unexpected end of file. Expected end tag (style).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <style>
+| " EOF"
+| <body>
+
+#data
+<!DOCTYPE html><script> <!-- </script> --> </script> EOF
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| " <!-- "
+| " "
+| <body>
+| "--> EOF"
+
+#data
+<b><p></b>TEST
+#errors
+Line: 1 Col: 3 Unexpected start tag (b). Expected DOCTYPE.
+Line: 1 Col: 10 End tag (b) violates step 1, paragraph 3 of the adoption agency algorithm.
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| <p>
+| <b>
+| "TEST"
+
+#data
+<p id=a><b><p id=b></b>TEST
+#errors
+Line: 1 Col: 8 Unexpected start tag (p). Expected DOCTYPE.
+Line: 1 Col: 19 Unexpected end tag (p). Ignored.
+Line: 1 Col: 23 End tag (b) violates step 1, paragraph 2 of the adoption agency algorithm.
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| id="a"
+| <b>
+| <p>
+| id="b"
+| "TEST"
+
+#data
+<b id=a><p><b id=b></p></b>TEST
+#errors
+Line: 1 Col: 8 Unexpected start tag (b). Expected DOCTYPE.
+Line: 1 Col: 23 Unexpected end tag (p). Ignored.
+Line: 1 Col: 27 End tag (b) violates step 1, paragraph 2 of the adoption agency algorithm.
+Line: 1 Col: 31 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| id="a"
+| <p>
+| <b>
+| id="b"
+| "TEST"
+
+#data
+<!DOCTYPE html><title>U-test</title><body><div><p>Test<u></p></div></body>
+#errors
+Line: 1 Col: 61 Unexpected end tag (p). Ignored.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <title>
+| "U-test"
+| <body>
+| <div>
+| <p>
+| "Test"
+| <u>
+
+#data
+<!DOCTYPE html><font><table></font></table></font>
+#errors
+Line: 1 Col: 35 Unexpected end tag (font) in table context caused voodoo mode.
+Line: 1 Col: 35 End tag (font) violates step 1, paragraph 1 of the adoption agency algorithm.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <font>
+| <table>
+
+#data
+<font><p>hello<b>cruel</font>world
+#errors
+Line: 1 Col: 6 Unexpected start tag (font). Expected DOCTYPE.
+Line: 1 Col: 29 End tag (font) violates step 1, paragraph 3 of the adoption agency algorithm.
+Line: 1 Col: 29 End tag (font) violates step 1, paragraph 3 of the adoption agency algorithm.
+Line: 1 Col: 34 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <font>
+| <p>
+| <font>
+| "hello"
+| <b>
+| "cruel"
+| <b>
+| "world"
+
+#data
+<b>Test</i>Test
+#errors
+Line: 1 Col: 3 Unexpected start tag (b). Expected DOCTYPE.
+Line: 1 Col: 11 End tag (i) violates step 1, paragraph 1 of the adoption agency algorithm.
+Line: 1 Col: 15 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| "TestTest"
+
+#data
+<b>A<cite>B<div>C
+#errors
+Line: 1 Col: 3 Unexpected start tag (b). Expected DOCTYPE.
+Line: 1 Col: 17 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| "A"
+| <cite>
+| "B"
+| <div>
+| "C"
+
+#data
+<b>A<cite>B<div>C</cite>D
+#errors
+Line: 1 Col: 3 Unexpected start tag (b). Expected DOCTYPE.
+Line: 1 Col: 24 Unexpected end tag (cite). Ignored.
+Line: 1 Col: 25 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| "A"
+| <cite>
+| "B"
+| <div>
+| "CD"
+
+#data
+<b>A<cite>B<div>C</b>D
+#errors
+Line: 1 Col: 3 Unexpected start tag (b). Expected DOCTYPE.
+Line: 1 Col: 21 End tag (b) violates step 1, paragraph 3 of the adoption agency algorithm.
+Line: 1 Col: 22 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| "A"
+| <cite>
+| "B"
+| <div>
+| <b>
+| "C"
+| "D"
+
+#data
+
+#errors
+Line: 1 Col: 0 Unexpected End of file. Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<DIV>
+#errors
+Line: 1 Col: 5 Unexpected start tag (div). Expected DOCTYPE.
+Line: 1 Col: 5 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+
+#data
+<DIV> abc
+#errors
+Line: 1 Col: 5 Unexpected start tag (div). Expected DOCTYPE.
+Line: 1 Col: 9 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| " abc"
+
+#data
+<DIV> abc <B>
+#errors
+Line: 1 Col: 5 Unexpected start tag (div). Expected DOCTYPE.
+Line: 1 Col: 13 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| " abc "
+| <b>
+
+#data
+<DIV> abc <B> def
+#errors
+Line: 1 Col: 5 Unexpected start tag (div). Expected DOCTYPE.
+Line: 1 Col: 17 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| " abc "
+| <b>
+| " def"
+
+#data
+<DIV> abc <B> def <I>
+#errors
+Line: 1 Col: 5 Unexpected start tag (div). Expected DOCTYPE.
+Line: 1 Col: 21 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| " abc "
+| <b>
+| " def "
+| <i>
+
+#data
+<DIV> abc <B> def <I> ghi
+#errors
+Line: 1 Col: 5 Unexpected start tag (div). Expected DOCTYPE.
+Line: 1 Col: 25 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| " abc "
+| <b>
+| " def "
+| <i>
+| " ghi"
+
+#data
+<DIV> abc <B> def <I> ghi <P>
+#errors
+Line: 1 Col: 5 Unexpected start tag (div). Expected DOCTYPE.
+Line: 1 Col: 29 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| " abc "
+| <b>
+| " def "
+| <i>
+| " ghi "
+| <p>
+
+#data
+<DIV> abc <B> def <I> ghi <P> jkl
+#errors
+Line: 1 Col: 5 Unexpected start tag (div). Expected DOCTYPE.
+Line: 1 Col: 33 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| " abc "
+| <b>
+| " def "
+| <i>
+| " ghi "
+| <p>
+| " jkl"
+
+#data
+<DIV> abc <B> def <I> ghi <P> jkl </B>
+#errors
+Line: 1 Col: 5 Unexpected start tag (div). Expected DOCTYPE.
+Line: 1 Col: 38 End tag (b) violates step 1, paragraph 3 of the adoption agency algorithm.
+Line: 1 Col: 38 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| " abc "
+| <b>
+| " def "
+| <i>
+| " ghi "
+| <i>
+| <p>
+| <b>
+| " jkl "
+
+#data
+<DIV> abc <B> def <I> ghi <P> jkl </B> mno
+#errors
+Line: 1 Col: 5 Unexpected start tag (div). Expected DOCTYPE.
+Line: 1 Col: 38 End tag (b) violates step 1, paragraph 3 of the adoption agency algorithm.
+Line: 1 Col: 42 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| " abc "
+| <b>
+| " def "
+| <i>
+| " ghi "
+| <i>
+| <p>
+| <b>
+| " jkl "
+| " mno"
+
+#data
+<DIV> abc <B> def <I> ghi <P> jkl </B> mno </I>
+#errors
+Line: 1 Col: 5 Unexpected start tag (div). Expected DOCTYPE.
+Line: 1 Col: 38 End tag (b) violates step 1, paragraph 3 of the adoption agency algorithm.
+Line: 1 Col: 47 End tag (i) violates step 1, paragraph 3 of the adoption agency algorithm.
+Line: 1 Col: 47 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| " abc "
+| <b>
+| " def "
+| <i>
+| " ghi "
+| <i>
+| <p>
+| <i>
+| <b>
+| " jkl "
+| " mno "
+
+#data
+<DIV> abc <B> def <I> ghi <P> jkl </B> mno </I> pqr
+#errors
+Line: 1 Col: 5 Unexpected start tag (div). Expected DOCTYPE.
+Line: 1 Col: 38 End tag (b) violates step 1, paragraph 3 of the adoption agency algorithm.
+Line: 1 Col: 47 End tag (i) violates step 1, paragraph 3 of the adoption agency algorithm.
+Line: 1 Col: 51 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| " abc "
+| <b>
+| " def "
+| <i>
+| " ghi "
+| <i>
+| <p>
+| <i>
+| <b>
+| " jkl "
+| " mno "
+| " pqr"
+
+#data
+<DIV> abc <B> def <I> ghi <P> jkl </B> mno </I> pqr </P>
+#errors
+Line: 1 Col: 5 Unexpected start tag (div). Expected DOCTYPE.
+Line: 1 Col: 38 End tag (b) violates step 1, paragraph 3 of the adoption agency algorithm.
+Line: 1 Col: 47 End tag (i) violates step 1, paragraph 3 of the adoption agency algorithm.
+Line: 1 Col: 56 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| " abc "
+| <b>
+| " def "
+| <i>
+| " ghi "
+| <i>
+| <p>
+| <i>
+| <b>
+| " jkl "
+| " mno "
+| " pqr "
+
+#data
+<DIV> abc <B> def <I> ghi <P> jkl </B> mno </I> pqr </P> stu
+#errors
+Line: 1 Col: 5 Unexpected start tag (div). Expected DOCTYPE.
+Line: 1 Col: 38 End tag (b) violates step 1, paragraph 3 of the adoption agency algorithm.
+Line: 1 Col: 47 End tag (i) violates step 1, paragraph 3 of the adoption agency algorithm.
+Line: 1 Col: 60 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| " abc "
+| <b>
+| " def "
+| <i>
+| " ghi "
+| <i>
+| <p>
+| <i>
+| <b>
+| " jkl "
+| " mno "
+| " pqr "
+| " stu"
+
+#data
+<test attribute---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------->
+#errors
+Line: 1 Col: 1040 Unexpected start tag (test). Expected DOCTYPE.
+Line: 1 Col: 1040 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <test>
+| attribute----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------=""
+
+#data
+<a href="blah">aba<table><a href="foo">br<tr><td></td></tr>x</table>aoe
+#errors
+Line: 1 Col: 15 Unexpected start tag (a). Expected DOCTYPE.
+Line: 1 Col: 39 Unexpected start tag (a) in table context caused voodoo mode.
+Line: 1 Col: 39 Unexpected start tag (a) implies end tag (a).
+Line: 1 Col: 39 End tag (a) violates step 1, paragraph 1 of the adoption agency algorithm.
+Line: 1 Col: 45 Unexpected implied end tag (a) in the table phase.
+Line: 1 Col: 68 Unexpected implied end tag (a) in the table phase.
+Line: 1 Col: 71 Expected closing tag. Unexpected end of file.
+
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| href="blah"
+| "aba"
+| <a>
+| href="foo"
+| "br"
+| <a>
+| href="foo"
+| "x"
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <a>
+| href="foo"
+| "aoe"
+
+#data
+<a href="blah">aba<table><tr><td><a href="foo">br</td></tr>x</table>aoe
+#errors
+Line: 1 Col: 15 Unexpected start tag (a). Expected DOCTYPE.
+Line: 1 Col: 54 Got table cell end tag (td) while required end tags are missing.
+Line: 1 Col: 60 Unexpected non-space characters in table context caused voodoo mode.
+Line: 1 Col: 71 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| href="blah"
+| "abax"
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <a>
+| href="foo"
+| "br"
+| "aoe"
+
+#data
+<table><a href="blah">aba<tr><td><a href="foo">br</td></tr>x</table>aoe
+#errors
+Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE.
+Line: 1 Col: 22 Unexpected start tag (a) in table context caused voodoo mode.
+Line: 1 Col: 29 Unexpected implied end tag (a) in the table phase.
+Line: 1 Col: 54 Got table cell end tag (td) while required end tags are missing.
+Line: 1 Col: 68 Unexpected implied end tag (a) in the table phase.
+Line: 1 Col: 71 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| href="blah"
+| "aba"
+| <a>
+| href="blah"
+| "x"
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <a>
+| href="foo"
+| "br"
+| <a>
+| href="blah"
+| "aoe"
+
+#data
+<a href=a>aa<marquee>aa<a href=b>bb</marquee>aa
+#errors
+Line: 1 Col: 10 Unexpected start tag (a). Expected DOCTYPE.
+Line: 1 Col: 45 End tag (marquee) seen too early. Expected other end tag.
+Line: 1 Col: 47 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| href="a"
+| "aa"
+| <marquee>
+| "aa"
+| <a>
+| href="b"
+| "bb"
+| "aa"
+
+#data
+<wbr><strike><code></strike><code><strike></code>
+#errors
+Line: 1 Col: 5 Unexpected start tag (wbr). Expected DOCTYPE.
+Line: 1 Col: 28 End tag (strike) violates step 1, paragraph 3 of the adoption agency algorithm.
+Line: 1 Col: 49 Unexpected end tag (code). Ignored.
+#document
+| <html>
+| <head>
+| <body>
+| <wbr>
+| <strike>
+| <code>
+| <code>
+| <code>
+| <strike>
+
+#data
+<!DOCTYPE html><spacer>foo
+#errors
+26: End of file seen and there were open elements.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <spacer>
+| "foo"
+
+#data
+<title><meta></title><link><title><meta></title>
+#errors
+Line: 1 Col: 7 Unexpected start tag (title). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <title>
+| "<meta>"
+| <link>
+| <title>
+| "<meta>"
+| <body>
+
+#data
+<style><!--</style><meta><script>--><link></script>
+#errors
+Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE.
+Line: 1 Col: 51 Unexpected end of file. Expected end tag (style).
+#document
+| <html>
+| <head>
+| <style>
+| "<!--"
+| <meta>
+| <script>
+| "--><link>"
+| <body>
+
+#data
+<head><meta></head><link>
+#errors
+Line: 1 Col: 6 Unexpected start tag (head). Expected DOCTYPE.
+Line: 1 Col: 25 Unexpected start tag (link) that can be in head. Moved.
+#document
+| <html>
+| <head>
+| <meta>
+| <link>
+| <body>
+
+#data
+<table><tr><tr><td><td><span><th><span>X</table>
+#errors
+Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE.
+Line: 1 Col: 33 Got table cell end tag (td) while required end tags are missing.
+Line: 1 Col: 48 Got table cell end tag (th) while required end tags are missing.
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <tr>
+| <td>
+| <td>
+| <span>
+| <th>
+| <span>
+| "X"
+
+#data
+<body><body><base><link><meta><title><p></title><body><p></body>
+#errors
+Line: 1 Col: 6 Unexpected start tag (body). Expected DOCTYPE.
+Line: 1 Col: 12 Unexpected start tag (body).
+Line: 1 Col: 54 Unexpected start tag (body).
+Line: 1 Col: 64 Unexpected end tag (p). Missing end tag (body).
+#document
+| <html>
+| <head>
+| <body>
+| <base>
+| <link>
+| <meta>
+| <title>
+| "<p>"
+| <p>
+
+#data
+<textarea><p></textarea>
+#errors
+Line: 1 Col: 10 Unexpected start tag (textarea). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <body>
+| <textarea>
+| "<p>"
+
+#data
+<p><image></p>
+#errors
+Line: 1 Col: 3 Unexpected start tag (p). Expected DOCTYPE.
+Line: 1 Col: 10 Unexpected start tag (image). Treated as img.
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <img>
+
+#data
+<a><table><a></table><p><a><div><a>
+#errors
+Line: 1 Col: 3 Unexpected start tag (a). Expected DOCTYPE.
+Line: 1 Col: 13 Unexpected start tag (a) in table context caused voodoo mode.
+Line: 1 Col: 13 Unexpected start tag (a) implies end tag (a).
+Line: 1 Col: 13 End tag (a) violates step 1, paragraph 1 of the adoption agency algorithm.
+Line: 1 Col: 21 Unexpected end tag (table). Expected end tag (a).
+Line: 1 Col: 27 Unexpected start tag (a) implies end tag (a).
+Line: 1 Col: 27 End tag (a) violates step 1, paragraph 2 of the adoption agency algorithm.
+Line: 1 Col: 32 Unexpected end tag (p). Ignored.
+Line: 1 Col: 35 Unexpected start tag (a) implies end tag (a).
+Line: 1 Col: 35 End tag (a) violates step 1, paragraph 2 of the adoption agency algorithm.
+Line: 1 Col: 35 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| <a>
+| <table>
+| <p>
+| <a>
+| <div>
+| <a>
+
+#data
+<head></p><meta><p>
+#errors
+Line: 1 Col: 6 Unexpected start tag (head). Expected DOCTYPE.
+Line: 1 Col: 10 Unexpected end tag (p). Ignored.
+#document
+| <html>
+| <head>
+| <meta>
+| <body>
+| <p>
+
+#data
+<head></html><meta><p>
+#errors
+Line: 1 Col: 6 Unexpected start tag (head). Expected DOCTYPE.
+Line: 1 Col: 19 Unexpected start tag (meta).
+#document
+| <html>
+| <head>
+| <body>
+| <meta>
+| <p>
+
+#data
+<b><table><td><i></table>
+#errors
+Line: 1 Col: 3 Unexpected start tag (b). Expected DOCTYPE.
+Line: 1 Col: 14 Unexpected table cell start tag (td) in the table body phase.
+Line: 1 Col: 25 Got table cell end tag (td) while required end tags are missing.
+Line: 1 Col: 25 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <i>
+
+#data
+<b><table><td></b><i></table>
+#errors
+Line: 1 Col: 3 Unexpected start tag (b). Expected DOCTYPE.
+Line: 1 Col: 14 Unexpected table cell start tag (td) in the table body phase.
+Line: 1 Col: 18 End tag (b) violates step 1, paragraph 1 of the adoption agency algorithm.
+Line: 1 Col: 29 Got table cell end tag (td) while required end tags are missing.
+Line: 1 Col: 29 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <i>
+
+#data
+<h1><h2>
+#errors
+4: Start tag seen without seeing a doctype first. Expected “<!DOCTYPE html>”.
+8: Heading cannot be a child of another heading.
+8: End of file seen and there were open elements.
+#document
+| <html>
+| <head>
+| <body>
+| <h1>
+| <h2>
+
+#data
+<a><p><a></a></p></a>
+#errors
+Line: 1 Col: 3 Unexpected start tag (a). Expected DOCTYPE.
+Line: 1 Col: 9 Unexpected start tag (a) implies end tag (a).
+Line: 1 Col: 9 End tag (a) violates step 1, paragraph 3 of the adoption agency algorithm.
+Line: 1 Col: 21 End tag (a) violates step 1, paragraph 1 of the adoption agency algorithm.
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| <p>
+| <a>
+| <a>
+
+#data
+<b><button></b></button></b>
+#errors
+Line: 1 Col: 3 Unexpected start tag (b). Expected DOCTYPE.
+Line: 1 Col: 15 End tag (b) violates step 1, paragraph 1 of the adoption agency algorithm.
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| <button>
+| <b>
+
+#data
+<p><b><div><marquee></p></b></div>
+#errors
+Line: 1 Col: 3 Unexpected start tag (p). Expected DOCTYPE.
+Line: 1 Col: 11 Unexpected end tag (p). Ignored.
+Line: 1 Col: 24 Unexpected end tag (p). Ignored.
+Line: 1 Col: 28 End tag (b) violates step 1, paragraph 1 of the adoption agency algorithm.
+Line: 1 Col: 34 End tag (div) seen too early. Expected other end tag.
+Line: 1 Col: 34 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <b>
+| <div>
+| <b>
+| <marquee>
+| <p>
+
+#data
+<script></script></div><title></title><p><p>
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 23 Unexpected end tag (div). Ignored.
+#document
+| <html>
+| <head>
+| <script>
+| <title>
+| <body>
+| <p>
+| <p>
+
+#data
+<p><hr></p>
+#errors
+Line: 1 Col: 3 Unexpected start tag (p). Expected DOCTYPE.
+Line: 1 Col: 11 Unexpected end tag (p). Ignored.
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <hr>
+| <p>
+
+#data
+<select><b><option><select><option></b></select>
+#errors
+Line: 1 Col: 8 Unexpected start tag (select). Expected DOCTYPE.
+Line: 1 Col: 11 Unexpected start tag token (b) in the select phase. Ignored.
+Line: 1 Col: 27 Unexpected select start tag in the select phase treated as select end tag.
+Line: 1 Col: 39 End tag (b) violates step 1, paragraph 1 of the adoption agency algorithm.
+Line: 1 Col: 48 Unexpected end tag (select). Ignored.
+Line: 1 Col: 48 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <select>
+| <option>
+| <option>
+
+#data
+<html><head><title></title><body></body></html>
+#errors
+Line: 1 Col: 6 Unexpected start tag (html). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <title>
+| <body>
+
+#data
+<a><table><td><a><table></table><a></tr><a></table><a>
+#errors
+Line: 1 Col: 3 Unexpected start tag (a). Expected DOCTYPE.
+Line: 1 Col: 14 Unexpected table cell start tag (td) in the table body phase.
+Line: 1 Col: 35 Unexpected start tag (a) implies end tag (a).
+Line: 1 Col: 40 Got table cell end tag (td) while required end tags are missing.
+Line: 1 Col: 43 Unexpected start tag (a) in table context caused voodoo mode.
+Line: 1 Col: 43 Unexpected start tag (a) implies end tag (a).
+Line: 1 Col: 43 End tag (a) violates step 1, paragraph 1 of the adoption agency algorithm.
+Line: 1 Col: 51 Unexpected implied end tag (a) in the table phase.
+Line: 1 Col: 54 Unexpected start tag (a) implies end tag (a).
+Line: 1 Col: 54 End tag (a) violates step 1, paragraph 2 of the adoption agency algorithm.
+Line: 1 Col: 54 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| <a>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <a>
+| <table>
+| <a>
+| <a>
+
+#data
+<ul><li></li><div><li></div><li><li><div><li><address><li><b><em></b><li></ul>
+#errors
+Line: 1 Col: 4 Unexpected start tag (ul). Expected DOCTYPE.
+Line: 1 Col: 45 Missing end tag (div, li).
+Line: 1 Col: 58 Missing end tag (address, li).
+Line: 1 Col: 69 End tag (b) violates step 1, paragraph 3 of the adoption agency algorithm.
+#document
+| <html>
+| <head>
+| <body>
+| <ul>
+| <li>
+| <div>
+| <li>
+| <li>
+| <li>
+| <div>
+| <li>
+| <address>
+| <li>
+| <b>
+| <em>
+| <li>
+
+#data
+<ul><li><ul></li><li>a</li></ul></li></ul>
+#errors
+XXX: fix me
+#document
+| <html>
+| <head>
+| <body>
+| <ul>
+| <li>
+| <ul>
+| <li>
+| "a"
+
+#data
+<frameset><frame><frameset><frame></frameset><noframes></noframes></frameset>
+#errors
+Line: 1 Col: 10 Unexpected start tag (frameset). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <frameset>
+| <frame>
+| <frameset>
+| <frame>
+| <noframes>
+
+#data
+<h1><table><td><h3></table><h3></h1>
+#errors
+4: Start tag seen without seeing a doctype first. Expected “<!DOCTYPE html>”.
+15: “td” start tag in table body.
+27: Unclosed elements.
+31: Heading cannot be a child of another heading.
+36: End tag “h1” seen but there were unclosed elements.
+#document
+| <html>
+| <head>
+| <body>
+| <h1>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <h3>
+| <h3>
+
+#data
+<table><colgroup><col><colgroup><col><col><col><colgroup><col><col><thead><tr><td></table>
+#errors
+Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <colgroup>
+| <col>
+| <colgroup>
+| <col>
+| <col>
+| <col>
+| <colgroup>
+| <col>
+| <col>
+| <thead>
+| <tr>
+| <td>
+
+#data
+<table><col><tbody><col><tr><col><td><col></table><col>
+#errors
+Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE.
+Line: 1 Col: 37 Unexpected table cell start tag (td) in the table body phase.
+Line: 1 Col: 55 Unexpected start tag col. Ignored.
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <colgroup>
+| <col>
+| <tbody>
+| <colgroup>
+| <col>
+| <tbody>
+| <tr>
+| <colgroup>
+| <col>
+| <tbody>
+| <tr>
+| <td>
+| <colgroup>
+| <col>
+
+#data
+<table><colgroup><tbody><colgroup><tr><colgroup><td><colgroup></table><colgroup>
+#errors
+Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE.
+Line: 1 Col: 52 Unexpected table cell start tag (td) in the table body phase.
+Line: 1 Col: 80 Unexpected start tag colgroup. Ignored.
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <colgroup>
+| <tbody>
+| <colgroup>
+| <tbody>
+| <tr>
+| <colgroup>
+| <tbody>
+| <tr>
+| <td>
+| <colgroup>
+
+#data
+</strong></b></em></i></u></strike></s></blink></tt></pre></big></small></font></select></h1></h2></h3></h4></h5></h6></body></br></a></img></title></span></style></script></table></th></td></tr></frame></area></link></param></hr></input></col></base></meta></basefont></bgsound></embed></spacer></p></dd></dt></caption></colgroup></tbody></tfoot></thead></address></blockquote></center></dir></div></dl></fieldset></listing></menu></ol></ul></li></nobr></wbr></form></button></marquee></object></html></frameset></head></iframe></image></isindex></noembed></noframes></noscript></optgroup></option></plaintext></textarea>
+#errors
+Line: 1 Col: 9 Unexpected end tag (strong). Expected DOCTYPE.
+Line: 1 Col: 9 Unexpected end tag (strong) after the (implied) root element.
+Line: 1 Col: 13 Unexpected end tag (b) after the (implied) root element.
+Line: 1 Col: 18 Unexpected end tag (em) after the (implied) root element.
+Line: 1 Col: 22 Unexpected end tag (i) after the (implied) root element.
+Line: 1 Col: 26 Unexpected end tag (u) after the (implied) root element.
+Line: 1 Col: 35 Unexpected end tag (strike) after the (implied) root element.
+Line: 1 Col: 39 Unexpected end tag (s) after the (implied) root element.
+Line: 1 Col: 47 Unexpected end tag (blink) after the (implied) root element.
+Line: 1 Col: 52 Unexpected end tag (tt) after the (implied) root element.
+Line: 1 Col: 58 Unexpected end tag (pre) after the (implied) root element.
+Line: 1 Col: 64 Unexpected end tag (big) after the (implied) root element.
+Line: 1 Col: 72 Unexpected end tag (small) after the (implied) root element.
+Line: 1 Col: 79 Unexpected end tag (font) after the (implied) root element.
+Line: 1 Col: 88 Unexpected end tag (select) after the (implied) root element.
+Line: 1 Col: 93 Unexpected end tag (h1) after the (implied) root element.
+Line: 1 Col: 98 Unexpected end tag (h2) after the (implied) root element.
+Line: 1 Col: 103 Unexpected end tag (h3) after the (implied) root element.
+Line: 1 Col: 108 Unexpected end tag (h4) after the (implied) root element.
+Line: 1 Col: 113 Unexpected end tag (h5) after the (implied) root element.
+Line: 1 Col: 118 Unexpected end tag (h6) after the (implied) root element.
+Line: 1 Col: 125 Unexpected end tag (body) after the (implied) root element.
+Line: 1 Col: 130 Unexpected end tag (br). Treated as br element.
+Line: 1 Col: 134 End tag (a) violates step 1, paragraph 1 of the adoption agency algorithm.
+Line: 1 Col: 140 This element (img) has no end tag.
+Line: 1 Col: 148 Unexpected end tag (title). Ignored.
+Line: 1 Col: 155 Unexpected end tag (span). Ignored.
+Line: 1 Col: 163 Unexpected end tag (style). Ignored.
+Line: 1 Col: 172 Unexpected end tag (script). Ignored.
+Line: 1 Col: 180 Unexpected end tag (table). Ignored.
+Line: 1 Col: 185 Unexpected end tag (th). Ignored.
+Line: 1 Col: 190 Unexpected end tag (td). Ignored.
+Line: 1 Col: 195 Unexpected end tag (tr). Ignored.
+Line: 1 Col: 203 This element (frame) has no end tag.
+Line: 1 Col: 210 This element (area) has no end tag.
+Line: 1 Col: 217 Unexpected end tag (link). Ignored.
+Line: 1 Col: 225 This element (param) has no end tag.
+Line: 1 Col: 230 This element (hr) has no end tag.
+Line: 1 Col: 238 This element (input) has no end tag.
+Line: 1 Col: 244 Unexpected end tag (col). Ignored.
+Line: 1 Col: 251 Unexpected end tag (base). Ignored.
+Line: 1 Col: 258 Unexpected end tag (meta). Ignored.
+Line: 1 Col: 269 This element (basefont) has no end tag.
+Line: 1 Col: 279 This element (bgsound) has no end tag.
+Line: 1 Col: 287 This element (embed) has no end tag.
+Line: 1 Col: 296 This element (spacer) has no end tag.
+Line: 1 Col: 300 Unexpected end tag (p). Ignored.
+Line: 1 Col: 305 End tag (dd) seen too early. Expected other end tag.
+Line: 1 Col: 310 End tag (dt) seen too early. Expected other end tag.
+Line: 1 Col: 320 Unexpected end tag (caption). Ignored.
+Line: 1 Col: 331 Unexpected end tag (colgroup). Ignored.
+Line: 1 Col: 339 Unexpected end tag (tbody). Ignored.
+Line: 1 Col: 347 Unexpected end tag (tfoot). Ignored.
+Line: 1 Col: 355 Unexpected end tag (thead). Ignored.
+Line: 1 Col: 365 End tag (address) seen too early. Expected other end tag.
+Line: 1 Col: 378 End tag (blockquote) seen too early. Expected other end tag.
+Line: 1 Col: 387 End tag (center) seen too early. Expected other end tag.
+Line: 1 Col: 393 Unexpected end tag (dir). Ignored.
+Line: 1 Col: 399 End tag (div) seen too early. Expected other end tag.
+Line: 1 Col: 404 End tag (dl) seen too early. Expected other end tag.
+Line: 1 Col: 415 End tag (fieldset) seen too early. Expected other end tag.
+Line: 1 Col: 425 End tag (listing) seen too early. Expected other end tag.
+Line: 1 Col: 432 End tag (menu) seen too early. Expected other end tag.
+Line: 1 Col: 437 End tag (ol) seen too early. Expected other end tag.
+Line: 1 Col: 442 End tag (ul) seen too early. Expected other end tag.
+Line: 1 Col: 447 End tag (li) seen too early. Expected other end tag.
+Line: 1 Col: 454 End tag (nobr) violates step 1, paragraph 1 of the adoption agency algorithm.
+Line: 1 Col: 460 This element (wbr) has no end tag.
+Line: 1 Col: 476 End tag (button) seen too early. Expected other end tag.
+Line: 1 Col: 486 End tag (marquee) seen too early. Expected other end tag.
+Line: 1 Col: 495 End tag (object) seen too early. Expected other end tag.
+Line: 1 Col: 513 Unexpected end tag (html). Ignored.
+Line: 1 Col: 513 Unexpected end tag (frameset). Ignored.
+Line: 1 Col: 520 Unexpected end tag (head). Ignored.
+Line: 1 Col: 529 Unexpected end tag (iframe). Ignored.
+Line: 1 Col: 537 This element (image) has no end tag.
+Line: 1 Col: 547 This element (isindex) has no end tag.
+Line: 1 Col: 557 Unexpected end tag (noembed). Ignored.
+Line: 1 Col: 568 Unexpected end tag (noframes). Ignored.
+Line: 1 Col: 579 Unexpected end tag (noscript). Ignored.
+Line: 1 Col: 590 Unexpected end tag (optgroup). Ignored.
+Line: 1 Col: 599 Unexpected end tag (option). Ignored.
+Line: 1 Col: 611 Unexpected end tag (plaintext). Ignored.
+Line: 1 Col: 622 Unexpected end tag (textarea). Ignored.
+#document
+| <html>
+| <head>
+| <body>
+| <br>
+| <p>
+
+#data
+<table><tr></strong></b></em></i></u></strike></s></blink></tt></pre></big></small></font></select></h1></h2></h3></h4></h5></h6></body></br></a></img></title></span></style></script></table></th></td></tr></frame></area></link></param></hr></input></col></base></meta></basefont></bgsound></embed></spacer></p></dd></dt></caption></colgroup></tbody></tfoot></thead></address></blockquote></center></dir></div></dl></fieldset></listing></menu></ol></ul></li></nobr></wbr></form></button></marquee></object></html></frameset></head></iframe></image></isindex></noembed></noframes></noscript></optgroup></option></plaintext></textarea>
+#errors
+Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE.
+Line: 1 Col: 20 Unexpected end tag (strong) in table context caused voodoo mode.
+Line: 1 Col: 20 End tag (strong) violates step 1, paragraph 1 of the adoption agency algorithm.
+Line: 1 Col: 24 Unexpected end tag (b) in table context caused voodoo mode.
+Line: 1 Col: 24 End tag (b) violates step 1, paragraph 1 of the adoption agency algorithm.
+Line: 1 Col: 29 Unexpected end tag (em) in table context caused voodoo mode.
+Line: 1 Col: 29 End tag (em) violates step 1, paragraph 1 of the adoption agency algorithm.
+Line: 1 Col: 33 Unexpected end tag (i) in table context caused voodoo mode.
+Line: 1 Col: 33 End tag (i) violates step 1, paragraph 1 of the adoption agency algorithm.
+Line: 1 Col: 37 Unexpected end tag (u) in table context caused voodoo mode.
+Line: 1 Col: 37 End tag (u) violates step 1, paragraph 1 of the adoption agency algorithm.
+Line: 1 Col: 46 Unexpected end tag (strike) in table context caused voodoo mode.
+Line: 1 Col: 46 End tag (strike) violates step 1, paragraph 1 of the adoption agency algorithm.
+Line: 1 Col: 50 Unexpected end tag (s) in table context caused voodoo mode.
+Line: 1 Col: 50 End tag (s) violates step 1, paragraph 1 of the adoption agency algorithm.
+Line: 1 Col: 58 Unexpected end tag (blink) in table context caused voodoo mode.
+Line: 1 Col: 58 Unexpected end tag (blink). Ignored.
+Line: 1 Col: 63 Unexpected end tag (tt) in table context caused voodoo mode.
+Line: 1 Col: 63 End tag (tt) violates step 1, paragraph 1 of the adoption agency algorithm.
+Line: 1 Col: 69 Unexpected end tag (pre) in table context caused voodoo mode.
+Line: 1 Col: 69 End tag (pre) seen too early. Expected other end tag.
+Line: 1 Col: 75 Unexpected end tag (big) in table context caused voodoo mode.
+Line: 1 Col: 75 End tag (big) violates step 1, paragraph 1 of the adoption agency algorithm.
+Line: 1 Col: 83 Unexpected end tag (small) in table context caused voodoo mode.
+Line: 1 Col: 83 End tag (small) violates step 1, paragraph 1 of the adoption agency algorithm.
+Line: 1 Col: 90 Unexpected end tag (font) in table context caused voodoo mode.
+Line: 1 Col: 90 End tag (font) violates step 1, paragraph 1 of the adoption agency algorithm.
+Line: 1 Col: 99 Unexpected end tag (select) in table context caused voodoo mode.
+Line: 1 Col: 99 Unexpected end tag (select). Ignored.
+Line: 1 Col: 104 Unexpected end tag (h1) in table context caused voodoo mode.
+Line: 1 Col: 104 End tag (h1) seen too early. Expected other end tag.
+Line: 1 Col: 109 Unexpected end tag (h2) in table context caused voodoo mode.
+Line: 1 Col: 109 End tag (h2) seen too early. Expected other end tag.
+Line: 1 Col: 114 Unexpected end tag (h3) in table context caused voodoo mode.
+Line: 1 Col: 114 End tag (h3) seen too early. Expected other end tag.
+Line: 1 Col: 119 Unexpected end tag (h4) in table context caused voodoo mode.
+Line: 1 Col: 119 End tag (h4) seen too early. Expected other end tag.
+Line: 1 Col: 124 Unexpected end tag (h5) in table context caused voodoo mode.
+Line: 1 Col: 124 End tag (h5) seen too early. Expected other end tag.
+Line: 1 Col: 129 Unexpected end tag (h6) in table context caused voodoo mode.
+Line: 1 Col: 129 End tag (h6) seen too early. Expected other end tag.
+Line: 1 Col: 136 Unexpected end tag (body) in the table row phase. Ignored.
+Line: 1 Col: 141 Unexpected end tag (br) in table context caused voodoo mode.
+Line: 1 Col: 141 Unexpected end tag (br). Treated as br element.
+Line: 1 Col: 145 Unexpected end tag (a) in table context caused voodoo mode.
+Line: 1 Col: 145 End tag (a) violates step 1, paragraph 1 of the adoption agency algorithm.
+Line: 1 Col: 151 Unexpected end tag (img) in table context caused voodoo mode.
+Line: 1 Col: 151 This element (img) has no end tag.
+Line: 1 Col: 159 Unexpected end tag (title) in table context caused voodoo mode.
+Line: 1 Col: 159 Unexpected end tag (title). Ignored.
+Line: 1 Col: 166 Unexpected end tag (span) in table context caused voodoo mode.
+Line: 1 Col: 166 Unexpected end tag (span). Ignored.
+Line: 1 Col: 174 Unexpected end tag (style) in table context caused voodoo mode.
+Line: 1 Col: 174 Unexpected end tag (style). Ignored.
+Line: 1 Col: 183 Unexpected end tag (script) in table context caused voodoo mode.
+Line: 1 Col: 183 Unexpected end tag (script). Ignored.
+Line: 1 Col: 196 Unexpected end tag (th). Ignored.
+Line: 1 Col: 201 Unexpected end tag (td). Ignored.
+Line: 1 Col: 206 Unexpected end tag (tr). Ignored.
+Line: 1 Col: 214 This element (frame) has no end tag.
+Line: 1 Col: 221 This element (area) has no end tag.
+Line: 1 Col: 228 Unexpected end tag (link). Ignored.
+Line: 1 Col: 236 This element (param) has no end tag.
+Line: 1 Col: 241 This element (hr) has no end tag.
+Line: 1 Col: 249 This element (input) has no end tag.
+Line: 1 Col: 255 Unexpected end tag (col). Ignored.
+Line: 1 Col: 262 Unexpected end tag (base). Ignored.
+Line: 1 Col: 269 Unexpected end tag (meta). Ignored.
+Line: 1 Col: 280 This element (basefont) has no end tag.
+Line: 1 Col: 290 This element (bgsound) has no end tag.
+Line: 1 Col: 298 This element (embed) has no end tag.
+Line: 1 Col: 307 This element (spacer) has no end tag.
+Line: 1 Col: 311 Unexpected end tag (p). Ignored.
+Line: 1 Col: 316 End tag (dd) seen too early. Expected other end tag.
+Line: 1 Col: 321 End tag (dt) seen too early. Expected other end tag.
+Line: 1 Col: 331 Unexpected end tag (caption). Ignored.
+Line: 1 Col: 342 Unexpected end tag (colgroup). Ignored.
+Line: 1 Col: 350 Unexpected end tag (tbody). Ignored.
+Line: 1 Col: 358 Unexpected end tag (tfoot). Ignored.
+Line: 1 Col: 366 Unexpected end tag (thead). Ignored.
+Line: 1 Col: 376 End tag (address) seen too early. Expected other end tag.
+Line: 1 Col: 389 End tag (blockquote) seen too early. Expected other end tag.
+Line: 1 Col: 398 End tag (center) seen too early. Expected other end tag.
+Line: 1 Col: 404 Unexpected end tag (dir). Ignored.
+Line: 1 Col: 410 End tag (div) seen too early. Expected other end tag.
+Line: 1 Col: 415 End tag (dl) seen too early. Expected other end tag.
+Line: 1 Col: 426 End tag (fieldset) seen too early. Expected other end tag.
+Line: 1 Col: 436 End tag (listing) seen too early. Expected other end tag.
+Line: 1 Col: 443 End tag (menu) seen too early. Expected other end tag.
+Line: 1 Col: 448 End tag (ol) seen too early. Expected other end tag.
+Line: 1 Col: 453 End tag (ul) seen too early. Expected other end tag.
+Line: 1 Col: 458 End tag (li) seen too early. Expected other end tag.
+Line: 1 Col: 465 End tag (nobr) violates step 1, paragraph 1 of the adoption agency algorithm.
+Line: 1 Col: 471 This element (wbr) has no end tag.
+Line: 1 Col: 487 End tag (button) seen too early. Expected other end tag.
+Line: 1 Col: 497 End tag (marquee) seen too early. Expected other end tag.
+Line: 1 Col: 506 End tag (object) seen too early. Expected other end tag.
+Line: 1 Col: 524 Unexpected end tag (html). Ignored.
+Line: 1 Col: 524 Unexpected end tag (frameset). Ignored.
+Line: 1 Col: 531 Unexpected end tag (head). Ignored.
+Line: 1 Col: 540 Unexpected end tag (iframe). Ignored.
+Line: 1 Col: 548 This element (image) has no end tag.
+Line: 1 Col: 558 This element (isindex) has no end tag.
+Line: 1 Col: 568 Unexpected end tag (noembed). Ignored.
+Line: 1 Col: 579 Unexpected end tag (noframes). Ignored.
+Line: 1 Col: 590 Unexpected end tag (noscript). Ignored.
+Line: 1 Col: 601 Unexpected end tag (optgroup). Ignored.
+Line: 1 Col: 610 Unexpected end tag (option). Ignored.
+Line: 1 Col: 622 Unexpected end tag (plaintext). Ignored.
+Line: 1 Col: 633 Unexpected end tag (textarea). Ignored.
+#document
+| <html>
+| <head>
+| <body>
+| <br>
+| <table>
+| <tbody>
+| <tr>
+| <p>
+
+#data
+<frameset>
+#errors
+Line: 1 Col: 10 Unexpected start tag (frameset). Expected DOCTYPE.
+Line: 1 Col: 10 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <frameset>
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests10.dat b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests10.dat
new file mode 100644
index 000000000..4f8df86f2
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests10.dat
@@ -0,0 +1,799 @@
+#data
+<!DOCTYPE html><svg></svg>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+
+#data
+<!DOCTYPE html><svg></svg><![CDATA[a]]>
+#errors
+29: Bogus comment
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <!-- [CDATA[a]] -->
+
+#data
+<!DOCTYPE html><body><svg></svg>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+
+#data
+<!DOCTYPE html><body><select><svg></svg></select>
+#errors
+35: Stray “svg” start tag.
+42: Stray end tag “svg”
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+
+#data
+<!DOCTYPE html><body><select><option><svg></svg></option></select>
+#errors
+43: Stray “svg” start tag.
+50: Stray end tag “svg”
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| <option>
+
+#data
+<!DOCTYPE html><body><table><svg></svg></table>
+#errors
+34: Start tag “svg” seen in “table”.
+41: Stray end tag “svg”.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <table>
+
+#data
+<!DOCTYPE html><body><table><svg><g>foo</g></svg></table>
+#errors
+34: Start tag “svg” seen in “table”.
+46: Stray end tag “g”.
+53: Stray end tag “svg”.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg g>
+| "foo"
+| <table>
+
+#data
+<!DOCTYPE html><body><table><svg><g>foo</g><g>bar</g></svg></table>
+#errors
+34: Start tag “svg” seen in “table”.
+46: Stray end tag “g”.
+58: Stray end tag “g”.
+65: Stray end tag “svg”.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg g>
+| "foo"
+| <svg g>
+| "bar"
+| <table>
+
+#data
+<!DOCTYPE html><body><table><tbody><svg><g>foo</g><g>bar</g></svg></tbody></table>
+#errors
+41: Start tag “svg” seen in “table”.
+53: Stray end tag “g”.
+65: Stray end tag “g”.
+72: Stray end tag “svg”.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg g>
+| "foo"
+| <svg g>
+| "bar"
+| <table>
+| <tbody>
+
+#data
+<!DOCTYPE html><body><table><tbody><tr><svg><g>foo</g><g>bar</g></svg></tr></tbody></table>
+#errors
+45: Start tag “svg” seen in “table”.
+57: Stray end tag “g”.
+69: Stray end tag “g”.
+76: Stray end tag “svg”.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg g>
+| "foo"
+| <svg g>
+| "bar"
+| <table>
+| <tbody>
+| <tr>
+
+#data
+<!DOCTYPE html><body><table><tbody><tr><td><svg><g>foo</g><g>bar</g></svg></td></tr></tbody></table>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <svg svg>
+| <svg g>
+| "foo"
+| <svg g>
+| "bar"
+
+#data
+<!DOCTYPE html><body><table><tbody><tr><td><svg><g>foo</g><g>bar</g></svg><p>baz</td></tr></tbody></table>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <svg svg>
+| <svg g>
+| "foo"
+| <svg g>
+| "bar"
+| <p>
+| "baz"
+
+#data
+<!DOCTYPE html><body><table><caption><svg><g>foo</g><g>bar</g></svg><p>baz</caption></table>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+| <svg svg>
+| <svg g>
+| "foo"
+| <svg g>
+| "bar"
+| <p>
+| "baz"
+
+#data
+<!DOCTYPE html><body><table><caption><svg><g>foo</g><g>bar</g><p>baz</table><p>quux
+#errors
+70: HTML start tag “p” in a foreign namespace context.
+81: “table” closed but “caption” was still open.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+| <svg svg>
+| <svg g>
+| "foo"
+| <svg g>
+| "bar"
+| <p>
+| "baz"
+| <p>
+| "quux"
+
+#data
+<!DOCTYPE html><body><table><caption><svg><g>foo</g><g>bar</g>baz</table><p>quux
+#errors
+78: “table” closed but “caption” was still open.
+78: Unclosed elements on stack.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+| <svg svg>
+| <svg g>
+| "foo"
+| <svg g>
+| "bar"
+| "baz"
+| <p>
+| "quux"
+
+#data
+<!DOCTYPE html><body><table><colgroup><svg><g>foo</g><g>bar</g><p>baz</table><p>quux
+#errors
+44: Start tag “svg” seen in “table”.
+56: Stray end tag “g”.
+68: Stray end tag “g”.
+71: HTML start tag “p” in a foreign namespace context.
+71: Start tag “p” seen in “table”.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg g>
+| "foo"
+| <svg g>
+| "bar"
+| <p>
+| "baz"
+| <table>
+| <colgroup>
+| <p>
+| "quux"
+
+#data
+<!DOCTYPE html><body><table><tr><td><select><svg><g>foo</g><g>bar</g><p>baz</table><p>quux
+#errors
+50: Stray “svg” start tag.
+54: Stray “g” start tag.
+62: Stray end tag “g”
+66: Stray “g” start tag.
+74: Stray end tag “g”
+77: Stray “p” start tag.
+88: “table” end tag with “select” open.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <select>
+| "foobarbaz"
+| <p>
+| "quux"
+
+#data
+<!DOCTYPE html><body><table><select><svg><g>foo</g><g>bar</g><p>baz</table><p>quux
+#errors
+36: Start tag “select” seen in “table”.
+42: Stray “svg” start tag.
+46: Stray “g” start tag.
+54: Stray end tag “g”
+58: Stray “g” start tag.
+66: Stray end tag “g”
+69: Stray “p” start tag.
+80: “table” end tag with “select” open.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| "foobarbaz"
+| <table>
+| <p>
+| "quux"
+
+#data
+<!DOCTYPE html><body></body></html><svg><g>foo</g><g>bar</g><p>baz
+#errors
+41: Stray “svg” start tag.
+68: HTML start tag “p” in a foreign namespace context.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg g>
+| "foo"
+| <svg g>
+| "bar"
+| <p>
+| "baz"
+
+#data
+<!DOCTYPE html><body></body><svg><g>foo</g><g>bar</g><p>baz
+#errors
+34: Stray “svg” start tag.
+61: HTML start tag “p” in a foreign namespace context.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg g>
+| "foo"
+| <svg g>
+| "bar"
+| <p>
+| "baz"
+
+#data
+<!DOCTYPE html><frameset><svg><g></g><g></g><p><span>
+#errors
+31: Stray “svg” start tag.
+35: Stray “g” start tag.
+40: Stray end tag “g”
+44: Stray “g” start tag.
+49: Stray end tag “g”
+52: Stray “p” start tag.
+58: Stray “span” start tag.
+58: End of file seen and there were open elements.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+
+#data
+<!DOCTYPE html><frameset></frameset><svg><g></g><g></g><p><span>
+#errors
+42: Stray “svg” start tag.
+46: Stray “g” start tag.
+51: Stray end tag “g”
+55: Stray “g” start tag.
+60: Stray end tag “g”
+63: Stray “p” start tag.
+69: Stray “span” start tag.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+
+#data
+<!DOCTYPE html><body xlink:href=foo><svg xlink:href=foo></svg>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| xlink:href="foo"
+| <svg svg>
+| xlink href="foo"
+
+#data
+<!DOCTYPE html><body xlink:href=foo xml:lang=en><svg><g xml:lang=en xlink:href=foo></g></svg>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| xlink:href="foo"
+| xml:lang="en"
+| <svg svg>
+| <svg g>
+| xlink href="foo"
+| xml lang="en"
+
+#data
+<!DOCTYPE html><body xlink:href=foo xml:lang=en><svg><g xml:lang=en xlink:href=foo /></svg>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| xlink:href="foo"
+| xml:lang="en"
+| <svg svg>
+| <svg g>
+| xlink href="foo"
+| xml lang="en"
+
+#data
+<!DOCTYPE html><body xlink:href=foo xml:lang=en><svg><g xml:lang=en xlink:href=foo />bar</svg>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| xlink:href="foo"
+| xml:lang="en"
+| <svg svg>
+| <svg g>
+| xlink href="foo"
+| xml lang="en"
+| "bar"
+
+#data
+<svg></path>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+
+#data
+<div><svg></div>a
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <svg svg>
+| "a"
+
+#data
+<div><svg><path></div>a
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <svg svg>
+| <svg path>
+| "a"
+
+#data
+<div><svg><path></svg><path>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <svg svg>
+| <svg path>
+| <path>
+
+#data
+<div><svg><path><foreignObject><math></div>a
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <svg svg>
+| <svg path>
+| <svg foreignObject>
+| <math math>
+| "a"
+
+#data
+<div><svg><path><foreignObject><p></div>a
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <svg svg>
+| <svg path>
+| <svg foreignObject>
+| <p>
+| "a"
+
+#data
+<!DOCTYPE html><svg><desc><div><svg><ul>a
+#errors
+40: HTML start tag “ul” in a foreign namespace context.
+41: End of file in a foreign namespace context.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg desc>
+| <div>
+| <svg svg>
+| <ul>
+| "a"
+
+#data
+<!DOCTYPE html><svg><desc><svg><ul>a
+#errors
+35: HTML start tag “ul” in a foreign namespace context.
+36: End of file in a foreign namespace context.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg desc>
+| <svg svg>
+| <ul>
+| "a"
+
+#data
+<!DOCTYPE html><p><svg><desc><p>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <svg svg>
+| <svg desc>
+| <p>
+
+#data
+<!DOCTYPE html><p><svg><title><p>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <svg svg>
+| <svg title>
+| <p>
+
+#data
+<div><svg><path><foreignObject><p></foreignObject><p>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <svg svg>
+| <svg path>
+| <svg foreignObject>
+| <p>
+| <p>
+
+#data
+<math><mi><div><object><div><span></span></div></object></div></mi><mi>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mi>
+| <div>
+| <object>
+| <div>
+| <span>
+| <math mi>
+
+#data
+<math><mi><svg><foreignObject><div><div></div></div></foreignObject></svg></mi><mi>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mi>
+| <svg svg>
+| <svg foreignObject>
+| <div>
+| <div>
+| <math mi>
+
+#data
+<svg><script></script><path>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg script>
+| <svg path>
+
+#data
+<table><svg></svg><tr>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <table>
+| <tbody>
+| <tr>
+
+#data
+<math><mi><mglyph>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mi>
+| <math mglyph>
+
+#data
+<math><mi><malignmark>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mi>
+| <math malignmark>
+
+#data
+<math><mo><mglyph>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mo>
+| <math mglyph>
+
+#data
+<math><mo><malignmark>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mo>
+| <math malignmark>
+
+#data
+<math><mn><mglyph>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mn>
+| <math mglyph>
+
+#data
+<math><mn><malignmark>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mn>
+| <math malignmark>
+
+#data
+<math><ms><mglyph>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math ms>
+| <math mglyph>
+
+#data
+<math><ms><malignmark>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math ms>
+| <math malignmark>
+
+#data
+<math><mtext><mglyph>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mtext>
+| <math mglyph>
+
+#data
+<math><mtext><malignmark>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mtext>
+| <math malignmark>
+
+#data
+<math><annotation-xml><svg></svg></annotation-xml><mi>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math annotation-xml>
+| <svg svg>
+| <math mi>
+
+#data
+<math><annotation-xml><svg><foreignObject><div><math><mi></mi></math><span></span></div></foreignObject><path></path></svg></annotation-xml><mi>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math annotation-xml>
+| <svg svg>
+| <svg foreignObject>
+| <div>
+| <math math>
+| <math mi>
+| <span>
+| <svg path>
+| <math mi>
+
+#data
+<math><annotation-xml><svg><foreignObject><math><mi><svg></svg></mi><mo></mo></math><span></span></foreignObject><path></path></svg></annotation-xml><mi>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math annotation-xml>
+| <svg svg>
+| <svg foreignObject>
+| <math math>
+| <math mi>
+| <svg svg>
+| <math mo>
+| <span>
+| <svg path>
+| <math mi>
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests11.dat b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests11.dat
new file mode 100644
index 000000000..638cde479
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests11.dat
@@ -0,0 +1,482 @@
+#data
+<!DOCTYPE html><body><svg attributeName='' attributeType='' baseFrequency='' baseProfile='' calcMode='' clipPathUnits='' contentScriptType='' contentStyleType='' diffuseConstant='' edgeMode='' externalResourcesRequired='' filterRes='' filterUnits='' glyphRef='' gradientTransform='' gradientUnits='' kernelMatrix='' kernelUnitLength='' keyPoints='' keySplines='' keyTimes='' lengthAdjust='' limitingConeAngle='' markerHeight='' markerUnits='' markerWidth='' maskContentUnits='' maskUnits='' numOctaves='' pathLength='' patternContentUnits='' patternTransform='' patternUnits='' pointsAtX='' pointsAtY='' pointsAtZ='' preserveAlpha='' preserveAspectRatio='' primitiveUnits='' refX='' refY='' repeatCount='' repeatDur='' requiredExtensions='' requiredFeatures='' specularConstant='' specularExponent='' spreadMethod='' startOffset='' stdDeviation='' stitchTiles='' surfaceScale='' systemLanguage='' tableValues='' targetX='' targetY='' textLength='' viewBox='' viewTarget='' xChannelSelector='' yChannelSelector='' zoomAndPan=''></svg>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| attributeName=""
+| attributeType=""
+| baseFrequency=""
+| baseProfile=""
+| calcMode=""
+| clipPathUnits=""
+| contentScriptType=""
+| contentStyleType=""
+| diffuseConstant=""
+| edgeMode=""
+| externalResourcesRequired=""
+| filterRes=""
+| filterUnits=""
+| glyphRef=""
+| gradientTransform=""
+| gradientUnits=""
+| kernelMatrix=""
+| kernelUnitLength=""
+| keyPoints=""
+| keySplines=""
+| keyTimes=""
+| lengthAdjust=""
+| limitingConeAngle=""
+| markerHeight=""
+| markerUnits=""
+| markerWidth=""
+| maskContentUnits=""
+| maskUnits=""
+| numOctaves=""
+| pathLength=""
+| patternContentUnits=""
+| patternTransform=""
+| patternUnits=""
+| pointsAtX=""
+| pointsAtY=""
+| pointsAtZ=""
+| preserveAlpha=""
+| preserveAspectRatio=""
+| primitiveUnits=""
+| refX=""
+| refY=""
+| repeatCount=""
+| repeatDur=""
+| requiredExtensions=""
+| requiredFeatures=""
+| specularConstant=""
+| specularExponent=""
+| spreadMethod=""
+| startOffset=""
+| stdDeviation=""
+| stitchTiles=""
+| surfaceScale=""
+| systemLanguage=""
+| tableValues=""
+| targetX=""
+| targetY=""
+| textLength=""
+| viewBox=""
+| viewTarget=""
+| xChannelSelector=""
+| yChannelSelector=""
+| zoomAndPan=""
+
+#data
+<!DOCTYPE html><BODY><SVG ATTRIBUTENAME='' ATTRIBUTETYPE='' BASEFREQUENCY='' BASEPROFILE='' CALCMODE='' CLIPPATHUNITS='' CONTENTSCRIPTTYPE='' CONTENTSTYLETYPE='' DIFFUSECONSTANT='' EDGEMODE='' EXTERNALRESOURCESREQUIRED='' FILTERRES='' FILTERUNITS='' GLYPHREF='' GRADIENTTRANSFORM='' GRADIENTUNITS='' KERNELMATRIX='' KERNELUNITLENGTH='' KEYPOINTS='' KEYSPLINES='' KEYTIMES='' LENGTHADJUST='' LIMITINGCONEANGLE='' MARKERHEIGHT='' MARKERUNITS='' MARKERWIDTH='' MASKCONTENTUNITS='' MASKUNITS='' NUMOCTAVES='' PATHLENGTH='' PATTERNCONTENTUNITS='' PATTERNTRANSFORM='' PATTERNUNITS='' POINTSATX='' POINTSATY='' POINTSATZ='' PRESERVEALPHA='' PRESERVEASPECTRATIO='' PRIMITIVEUNITS='' REFX='' REFY='' REPEATCOUNT='' REPEATDUR='' REQUIREDEXTENSIONS='' REQUIREDFEATURES='' SPECULARCONSTANT='' SPECULAREXPONENT='' SPREADMETHOD='' STARTOFFSET='' STDDEVIATION='' STITCHTILES='' SURFACESCALE='' SYSTEMLANGUAGE='' TABLEVALUES='' TARGETX='' TARGETY='' TEXTLENGTH='' VIEWBOX='' VIEWTARGET='' XCHANNELSELECTOR='' YCHANNELSELECTOR='' ZOOMANDPAN=''></SVG>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| attributeName=""
+| attributeType=""
+| baseFrequency=""
+| baseProfile=""
+| calcMode=""
+| clipPathUnits=""
+| contentScriptType=""
+| contentStyleType=""
+| diffuseConstant=""
+| edgeMode=""
+| externalResourcesRequired=""
+| filterRes=""
+| filterUnits=""
+| glyphRef=""
+| gradientTransform=""
+| gradientUnits=""
+| kernelMatrix=""
+| kernelUnitLength=""
+| keyPoints=""
+| keySplines=""
+| keyTimes=""
+| lengthAdjust=""
+| limitingConeAngle=""
+| markerHeight=""
+| markerUnits=""
+| markerWidth=""
+| maskContentUnits=""
+| maskUnits=""
+| numOctaves=""
+| pathLength=""
+| patternContentUnits=""
+| patternTransform=""
+| patternUnits=""
+| pointsAtX=""
+| pointsAtY=""
+| pointsAtZ=""
+| preserveAlpha=""
+| preserveAspectRatio=""
+| primitiveUnits=""
+| refX=""
+| refY=""
+| repeatCount=""
+| repeatDur=""
+| requiredExtensions=""
+| requiredFeatures=""
+| specularConstant=""
+| specularExponent=""
+| spreadMethod=""
+| startOffset=""
+| stdDeviation=""
+| stitchTiles=""
+| surfaceScale=""
+| systemLanguage=""
+| tableValues=""
+| targetX=""
+| targetY=""
+| textLength=""
+| viewBox=""
+| viewTarget=""
+| xChannelSelector=""
+| yChannelSelector=""
+| zoomAndPan=""
+
+#data
+<!DOCTYPE html><body><svg attributename='' attributetype='' basefrequency='' baseprofile='' calcmode='' clippathunits='' contentscripttype='' contentstyletype='' diffuseconstant='' edgemode='' externalresourcesrequired='' filterres='' filterunits='' glyphref='' gradienttransform='' gradientunits='' kernelmatrix='' kernelunitlength='' keypoints='' keysplines='' keytimes='' lengthadjust='' limitingconeangle='' markerheight='' markerunits='' markerwidth='' maskcontentunits='' maskunits='' numoctaves='' pathlength='' patterncontentunits='' patterntransform='' patternunits='' pointsatx='' pointsaty='' pointsatz='' preservealpha='' preserveaspectratio='' primitiveunits='' refx='' refy='' repeatcount='' repeatdur='' requiredextensions='' requiredfeatures='' specularconstant='' specularexponent='' spreadmethod='' startoffset='' stddeviation='' stitchtiles='' surfacescale='' systemlanguage='' tablevalues='' targetx='' targety='' textlength='' viewbox='' viewtarget='' xchannelselector='' ychannelselector='' zoomandpan=''></svg>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| attributeName=""
+| attributeType=""
+| baseFrequency=""
+| baseProfile=""
+| calcMode=""
+| clipPathUnits=""
+| contentScriptType=""
+| contentStyleType=""
+| diffuseConstant=""
+| edgeMode=""
+| externalResourcesRequired=""
+| filterRes=""
+| filterUnits=""
+| glyphRef=""
+| gradientTransform=""
+| gradientUnits=""
+| kernelMatrix=""
+| kernelUnitLength=""
+| keyPoints=""
+| keySplines=""
+| keyTimes=""
+| lengthAdjust=""
+| limitingConeAngle=""
+| markerHeight=""
+| markerUnits=""
+| markerWidth=""
+| maskContentUnits=""
+| maskUnits=""
+| numOctaves=""
+| pathLength=""
+| patternContentUnits=""
+| patternTransform=""
+| patternUnits=""
+| pointsAtX=""
+| pointsAtY=""
+| pointsAtZ=""
+| preserveAlpha=""
+| preserveAspectRatio=""
+| primitiveUnits=""
+| refX=""
+| refY=""
+| repeatCount=""
+| repeatDur=""
+| requiredExtensions=""
+| requiredFeatures=""
+| specularConstant=""
+| specularExponent=""
+| spreadMethod=""
+| startOffset=""
+| stdDeviation=""
+| stitchTiles=""
+| surfaceScale=""
+| systemLanguage=""
+| tableValues=""
+| targetX=""
+| targetY=""
+| textLength=""
+| viewBox=""
+| viewTarget=""
+| xChannelSelector=""
+| yChannelSelector=""
+| zoomAndPan=""
+
+#data
+<!DOCTYPE html><body><math attributeName='' attributeType='' baseFrequency='' baseProfile='' calcMode='' clipPathUnits='' contentScriptType='' contentStyleType='' diffuseConstant='' edgeMode='' externalResourcesRequired='' filterRes='' filterUnits='' glyphRef='' gradientTransform='' gradientUnits='' kernelMatrix='' kernelUnitLength='' keyPoints='' keySplines='' keyTimes='' lengthAdjust='' limitingConeAngle='' markerHeight='' markerUnits='' markerWidth='' maskContentUnits='' maskUnits='' numOctaves='' pathLength='' patternContentUnits='' patternTransform='' patternUnits='' pointsAtX='' pointsAtY='' pointsAtZ='' preserveAlpha='' preserveAspectRatio='' primitiveUnits='' refX='' refY='' repeatCount='' repeatDur='' requiredExtensions='' requiredFeatures='' specularConstant='' specularExponent='' spreadMethod='' startOffset='' stdDeviation='' stitchTiles='' surfaceScale='' systemLanguage='' tableValues='' targetX='' targetY='' textLength='' viewBox='' viewTarget='' xChannelSelector='' yChannelSelector='' zoomAndPan=''></math>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+| attributename=""
+| attributetype=""
+| basefrequency=""
+| baseprofile=""
+| calcmode=""
+| clippathunits=""
+| contentscripttype=""
+| contentstyletype=""
+| diffuseconstant=""
+| edgemode=""
+| externalresourcesrequired=""
+| filterres=""
+| filterunits=""
+| glyphref=""
+| gradienttransform=""
+| gradientunits=""
+| kernelmatrix=""
+| kernelunitlength=""
+| keypoints=""
+| keysplines=""
+| keytimes=""
+| lengthadjust=""
+| limitingconeangle=""
+| markerheight=""
+| markerunits=""
+| markerwidth=""
+| maskcontentunits=""
+| maskunits=""
+| numoctaves=""
+| pathlength=""
+| patterncontentunits=""
+| patterntransform=""
+| patternunits=""
+| pointsatx=""
+| pointsaty=""
+| pointsatz=""
+| preservealpha=""
+| preserveaspectratio=""
+| primitiveunits=""
+| refx=""
+| refy=""
+| repeatcount=""
+| repeatdur=""
+| requiredextensions=""
+| requiredfeatures=""
+| specularconstant=""
+| specularexponent=""
+| spreadmethod=""
+| startoffset=""
+| stddeviation=""
+| stitchtiles=""
+| surfacescale=""
+| systemlanguage=""
+| tablevalues=""
+| targetx=""
+| targety=""
+| textlength=""
+| viewbox=""
+| viewtarget=""
+| xchannelselector=""
+| ychannelselector=""
+| zoomandpan=""
+
+#data
+<!DOCTYPE html><body><svg><altGlyph /><altGlyphDef /><altGlyphItem /><animateColor /><animateMotion /><animateTransform /><clipPath /><feBlend /><feColorMatrix /><feComponentTransfer /><feComposite /><feConvolveMatrix /><feDiffuseLighting /><feDisplacementMap /><feDistantLight /><feFlood /><feFuncA /><feFuncB /><feFuncG /><feFuncR /><feGaussianBlur /><feImage /><feMerge /><feMergeNode /><feMorphology /><feOffset /><fePointLight /><feSpecularLighting /><feSpotLight /><feTile /><feTurbulence /><foreignObject /><glyphRef /><linearGradient /><radialGradient /><textPath /></svg>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg altGlyph>
+| <svg altGlyphDef>
+| <svg altGlyphItem>
+| <svg animateColor>
+| <svg animateMotion>
+| <svg animateTransform>
+| <svg clipPath>
+| <svg feBlend>
+| <svg feColorMatrix>
+| <svg feComponentTransfer>
+| <svg feComposite>
+| <svg feConvolveMatrix>
+| <svg feDiffuseLighting>
+| <svg feDisplacementMap>
+| <svg feDistantLight>
+| <svg feFlood>
+| <svg feFuncA>
+| <svg feFuncB>
+| <svg feFuncG>
+| <svg feFuncR>
+| <svg feGaussianBlur>
+| <svg feImage>
+| <svg feMerge>
+| <svg feMergeNode>
+| <svg feMorphology>
+| <svg feOffset>
+| <svg fePointLight>
+| <svg feSpecularLighting>
+| <svg feSpotLight>
+| <svg feTile>
+| <svg feTurbulence>
+| <svg foreignObject>
+| <svg glyphRef>
+| <svg linearGradient>
+| <svg radialGradient>
+| <svg textPath>
+
+#data
+<!DOCTYPE html><body><svg><altglyph /><altglyphdef /><altglyphitem /><animatecolor /><animatemotion /><animatetransform /><clippath /><feblend /><fecolormatrix /><fecomponenttransfer /><fecomposite /><feconvolvematrix /><fediffuselighting /><fedisplacementmap /><fedistantlight /><feflood /><fefunca /><fefuncb /><fefuncg /><fefuncr /><fegaussianblur /><feimage /><femerge /><femergenode /><femorphology /><feoffset /><fepointlight /><fespecularlighting /><fespotlight /><fetile /><feturbulence /><foreignobject /><glyphref /><lineargradient /><radialgradient /><textpath /></svg>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg altGlyph>
+| <svg altGlyphDef>
+| <svg altGlyphItem>
+| <svg animateColor>
+| <svg animateMotion>
+| <svg animateTransform>
+| <svg clipPath>
+| <svg feBlend>
+| <svg feColorMatrix>
+| <svg feComponentTransfer>
+| <svg feComposite>
+| <svg feConvolveMatrix>
+| <svg feDiffuseLighting>
+| <svg feDisplacementMap>
+| <svg feDistantLight>
+| <svg feFlood>
+| <svg feFuncA>
+| <svg feFuncB>
+| <svg feFuncG>
+| <svg feFuncR>
+| <svg feGaussianBlur>
+| <svg feImage>
+| <svg feMerge>
+| <svg feMergeNode>
+| <svg feMorphology>
+| <svg feOffset>
+| <svg fePointLight>
+| <svg feSpecularLighting>
+| <svg feSpotLight>
+| <svg feTile>
+| <svg feTurbulence>
+| <svg foreignObject>
+| <svg glyphRef>
+| <svg linearGradient>
+| <svg radialGradient>
+| <svg textPath>
+
+#data
+<!DOCTYPE html><BODY><SVG><ALTGLYPH /><ALTGLYPHDEF /><ALTGLYPHITEM /><ANIMATECOLOR /><ANIMATEMOTION /><ANIMATETRANSFORM /><CLIPPATH /><FEBLEND /><FECOLORMATRIX /><FECOMPONENTTRANSFER /><FECOMPOSITE /><FECONVOLVEMATRIX /><FEDIFFUSELIGHTING /><FEDISPLACEMENTMAP /><FEDISTANTLIGHT /><FEFLOOD /><FEFUNCA /><FEFUNCB /><FEFUNCG /><FEFUNCR /><FEGAUSSIANBLUR /><FEIMAGE /><FEMERGE /><FEMERGENODE /><FEMORPHOLOGY /><FEOFFSET /><FEPOINTLIGHT /><FESPECULARLIGHTING /><FESPOTLIGHT /><FETILE /><FETURBULENCE /><FOREIGNOBJECT /><GLYPHREF /><LINEARGRADIENT /><RADIALGRADIENT /><TEXTPATH /></SVG>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg altGlyph>
+| <svg altGlyphDef>
+| <svg altGlyphItem>
+| <svg animateColor>
+| <svg animateMotion>
+| <svg animateTransform>
+| <svg clipPath>
+| <svg feBlend>
+| <svg feColorMatrix>
+| <svg feComponentTransfer>
+| <svg feComposite>
+| <svg feConvolveMatrix>
+| <svg feDiffuseLighting>
+| <svg feDisplacementMap>
+| <svg feDistantLight>
+| <svg feFlood>
+| <svg feFuncA>
+| <svg feFuncB>
+| <svg feFuncG>
+| <svg feFuncR>
+| <svg feGaussianBlur>
+| <svg feImage>
+| <svg feMerge>
+| <svg feMergeNode>
+| <svg feMorphology>
+| <svg feOffset>
+| <svg fePointLight>
+| <svg feSpecularLighting>
+| <svg feSpotLight>
+| <svg feTile>
+| <svg feTurbulence>
+| <svg foreignObject>
+| <svg glyphRef>
+| <svg linearGradient>
+| <svg radialGradient>
+| <svg textPath>
+
+#data
+<!DOCTYPE html><body><math><altGlyph /><altGlyphDef /><altGlyphItem /><animateColor /><animateMotion /><animateTransform /><clipPath /><feBlend /><feColorMatrix /><feComponentTransfer /><feComposite /><feConvolveMatrix /><feDiffuseLighting /><feDisplacementMap /><feDistantLight /><feFlood /><feFuncA /><feFuncB /><feFuncG /><feFuncR /><feGaussianBlur /><feImage /><feMerge /><feMergeNode /><feMorphology /><feOffset /><fePointLight /><feSpecularLighting /><feSpotLight /><feTile /><feTurbulence /><foreignObject /><glyphRef /><linearGradient /><radialGradient /><textPath /></math>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math altglyph>
+| <math altglyphdef>
+| <math altglyphitem>
+| <math animatecolor>
+| <math animatemotion>
+| <math animatetransform>
+| <math clippath>
+| <math feblend>
+| <math fecolormatrix>
+| <math fecomponenttransfer>
+| <math fecomposite>
+| <math feconvolvematrix>
+| <math fediffuselighting>
+| <math fedisplacementmap>
+| <math fedistantlight>
+| <math feflood>
+| <math fefunca>
+| <math fefuncb>
+| <math fefuncg>
+| <math fefuncr>
+| <math fegaussianblur>
+| <math feimage>
+| <math femerge>
+| <math femergenode>
+| <math femorphology>
+| <math feoffset>
+| <math fepointlight>
+| <math fespecularlighting>
+| <math fespotlight>
+| <math fetile>
+| <math feturbulence>
+| <math foreignobject>
+| <math glyphref>
+| <math lineargradient>
+| <math radialgradient>
+| <math textpath>
+
+#data
+<!DOCTYPE html><body><svg><solidColor /></svg>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg solidcolor>
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests12.dat b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests12.dat
new file mode 100644
index 000000000..63107d277
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests12.dat
@@ -0,0 +1,62 @@
+#data
+<!DOCTYPE html><body><p>foo<math><mtext><i>baz</i></mtext><annotation-xml><svg><desc><b>eggs</b></desc><g><foreignObject><P>spam<TABLE><tr><td><img></td></table></foreignObject></g><g>quux</g></svg></annotation-xml></math>bar
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| "foo"
+| <math math>
+| <math mtext>
+| <i>
+| "baz"
+| <math annotation-xml>
+| <svg svg>
+| <svg desc>
+| <b>
+| "eggs"
+| <svg g>
+| <svg foreignObject>
+| <p>
+| "spam"
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <img>
+| <svg g>
+| "quux"
+| "bar"
+
+#data
+<!DOCTYPE html><body>foo<math><mtext><i>baz</i></mtext><annotation-xml><svg><desc><b>eggs</b></desc><g><foreignObject><P>spam<TABLE><tr><td><img></td></table></foreignObject></g><g>quux</g></svg></annotation-xml></math>bar
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "foo"
+| <math math>
+| <math mtext>
+| <i>
+| "baz"
+| <math annotation-xml>
+| <svg svg>
+| <svg desc>
+| <b>
+| "eggs"
+| <svg g>
+| <svg foreignObject>
+| <p>
+| "spam"
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <img>
+| <svg g>
+| "quux"
+| "bar"
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests14.dat b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests14.dat
new file mode 100644
index 000000000..b8713f885
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests14.dat
@@ -0,0 +1,74 @@
+#data
+<!DOCTYPE html><html><body><xyz:abc></xyz:abc>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <xyz:abc>
+
+#data
+<!DOCTYPE html><html><body><xyz:abc></xyz:abc><span></span>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <xyz:abc>
+| <span>
+
+#data
+<!DOCTYPE html><html><html abc:def=gh><xyz:abc></xyz:abc>
+#errors
+15: Unexpected start tag html
+#document
+| <!DOCTYPE html>
+| <html>
+| abc:def="gh"
+| <head>
+| <body>
+| <xyz:abc>
+
+#data
+<!DOCTYPE html><html xml:lang=bar><html xml:lang=foo>
+#errors
+15: Unexpected start tag html
+#document
+| <!DOCTYPE html>
+| <html>
+| xml:lang="bar"
+| <head>
+| <body>
+
+#data
+<!DOCTYPE html><html 123=456>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| 123="456"
+| <head>
+| <body>
+
+#data
+<!DOCTYPE html><html 123=456><html 789=012>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| 123="456"
+| 789="012"
+| <head>
+| <body>
+
+#data
+<!DOCTYPE html><html><body 789=012>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| 789="012"
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests15.dat b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests15.dat
new file mode 100644
index 000000000..6ce1c0d16
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests15.dat
@@ -0,0 +1,208 @@
+#data
+<!DOCTYPE html><p><b><i><u></p> <p>X
+#errors
+Line: 1 Col: 31 Unexpected end tag (p). Ignored.
+Line: 1 Col: 36 Expected closing tag. Unexpected end of file.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <b>
+| <i>
+| <u>
+| <b>
+| <i>
+| <u>
+| " "
+| <p>
+| "X"
+
+#data
+<p><b><i><u></p>
+<p>X
+#errors
+Line: 1 Col: 3 Unexpected start tag (p). Expected DOCTYPE.
+Line: 1 Col: 16 Unexpected end tag (p). Ignored.
+Line: 2 Col: 4 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <b>
+| <i>
+| <u>
+| <b>
+| <i>
+| <u>
+| "
+"
+| <p>
+| "X"
+
+#data
+<!doctype html></html> <head>
+#errors
+Line: 1 Col: 22 Unexpected end tag (html) after the (implied) root element.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| " "
+
+#data
+<!doctype html></body><meta>
+#errors
+Line: 1 Col: 22 Unexpected end tag (body) after the (implied) root element.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <meta>
+
+#data
+<html></html><!-- foo -->
+#errors
+Line: 1 Col: 6 Unexpected start tag (html). Expected DOCTYPE.
+Line: 1 Col: 13 Unexpected end tag (html) after the (implied) root element.
+#document
+| <html>
+| <head>
+| <body>
+| <!-- foo -->
+
+#data
+<!doctype html></body><title>X</title>
+#errors
+Line: 1 Col: 22 Unexpected end tag (body) after the (implied) root element.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <title>
+| "X"
+
+#data
+<!doctype html><table> X<meta></table>
+#errors
+Line: 1 Col: 24 Unexpected non-space characters in table context caused voodoo mode.
+Line: 1 Col: 30 Unexpected start tag (meta) in table context caused voodoo mode.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| " X"
+| <meta>
+| <table>
+
+#data
+<!doctype html><table> x</table>
+#errors
+Line: 1 Col: 24 Unexpected non-space characters in table context caused voodoo mode.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| " x"
+| <table>
+
+#data
+<!doctype html><table> x </table>
+#errors
+Line: 1 Col: 25 Unexpected non-space characters in table context caused voodoo mode.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| " x "
+| <table>
+
+#data
+<!doctype html><table><tr> x</table>
+#errors
+Line: 1 Col: 28 Unexpected non-space characters in table context caused voodoo mode.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| " x"
+| <table>
+| <tbody>
+| <tr>
+
+#data
+<!doctype html><table>X<style> <tr>x </style> </table>
+#errors
+Line: 1 Col: 23 Unexpected non-space characters in table context caused voodoo mode.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "X"
+| <table>
+| <style>
+| " <tr>x "
+| " "
+
+#data
+<!doctype html><div><table><a>foo</a> <tr><td>bar</td> </tr></table></div>
+#errors
+Line: 1 Col: 30 Unexpected start tag (a) in table context caused voodoo mode.
+Line: 1 Col: 37 Unexpected end tag (a) in table context caused voodoo mode.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <div>
+| <a>
+| "foo"
+| <table>
+| " "
+| <tbody>
+| <tr>
+| <td>
+| "bar"
+| " "
+
+#data
+<frame></frame></frame><frameset><frame><frameset><frame></frameset><noframes></frameset><noframes>
+#errors
+6: Start tag seen without seeing a doctype first. Expected “<!DOCTYPE html>”.
+13: Stray start tag “frame”.
+21: Stray end tag “frame”.
+29: Stray end tag “frame”.
+39: “frameset” start tag after “body” already open.
+105: End of file seen inside an [R]CDATA element.
+105: End of file seen and there were open elements.
+XXX: These errors are wrong, please fix me!
+#document
+| <html>
+| <head>
+| <frameset>
+| <frame>
+| <frameset>
+| <frame>
+| <noframes>
+| "</frameset><noframes>"
+
+#data
+<!DOCTYPE html><object></html>
+#errors
+1: Expected closing tag. Unexpected end of file
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <object>
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests16.dat b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests16.dat
new file mode 100644
index 000000000..c8ef66f0e
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests16.dat
@@ -0,0 +1,2299 @@
+#data
+<!doctype html><script>
+#errors
+Line: 1 Col: 23 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| <body>
+
+#data
+<!doctype html><script>a
+#errors
+Line: 1 Col: 24 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "a"
+| <body>
+
+#data
+<!doctype html><script><
+#errors
+Line: 1 Col: 24 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<"
+| <body>
+
+#data
+<!doctype html><script></
+#errors
+Line: 1 Col: 25 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "</"
+| <body>
+
+#data
+<!doctype html><script></S
+#errors
+Line: 1 Col: 26 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "</S"
+| <body>
+
+#data
+<!doctype html><script></SC
+#errors
+Line: 1 Col: 27 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "</SC"
+| <body>
+
+#data
+<!doctype html><script></SCR
+#errors
+Line: 1 Col: 28 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "</SCR"
+| <body>
+
+#data
+<!doctype html><script></SCRI
+#errors
+Line: 1 Col: 29 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "</SCRI"
+| <body>
+
+#data
+<!doctype html><script></SCRIP
+#errors
+Line: 1 Col: 30 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "</SCRIP"
+| <body>
+
+#data
+<!doctype html><script></SCRIPT
+#errors
+Line: 1 Col: 31 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "</SCRIPT"
+| <body>
+
+#data
+<!doctype html><script></SCRIPT
+#errors
+Line: 1 Col: 32 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| <body>
+
+#data
+<!doctype html><script></s
+#errors
+Line: 1 Col: 26 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "</s"
+| <body>
+
+#data
+<!doctype html><script></sc
+#errors
+Line: 1 Col: 27 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "</sc"
+| <body>
+
+#data
+<!doctype html><script></scr
+#errors
+Line: 1 Col: 28 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "</scr"
+| <body>
+
+#data
+<!doctype html><script></scri
+#errors
+Line: 1 Col: 29 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "</scri"
+| <body>
+
+#data
+<!doctype html><script></scrip
+#errors
+Line: 1 Col: 30 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "</scrip"
+| <body>
+
+#data
+<!doctype html><script></script
+#errors
+Line: 1 Col: 31 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "</script"
+| <body>
+
+#data
+<!doctype html><script></script
+#errors
+Line: 1 Col: 32 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| <body>
+
+#data
+<!doctype html><script><!
+#errors
+Line: 1 Col: 25 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!"
+| <body>
+
+#data
+<!doctype html><script><!a
+#errors
+Line: 1 Col: 26 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!a"
+| <body>
+
+#data
+<!doctype html><script><!-
+#errors
+Line: 1 Col: 26 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!-"
+| <body>
+
+#data
+<!doctype html><script><!-a
+#errors
+Line: 1 Col: 27 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!-a"
+| <body>
+
+#data
+<!doctype html><script><!--
+#errors
+Line: 1 Col: 27 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--"
+| <body>
+
+#data
+<!doctype html><script><!--a
+#errors
+Line: 1 Col: 28 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--a"
+| <body>
+
+#data
+<!doctype html><script><!--<
+#errors
+Line: 1 Col: 28 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<"
+| <body>
+
+#data
+<!doctype html><script><!--<a
+#errors
+Line: 1 Col: 29 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<a"
+| <body>
+
+#data
+<!doctype html><script><!--</
+#errors
+Line: 1 Col: 27 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--</"
+| <body>
+
+#data
+<!doctype html><script><!--</script
+#errors
+Line: 1 Col: 35 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--</script"
+| <body>
+
+#data
+<!doctype html><script><!--</script
+#errors
+Line: 1 Col: 36 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--"
+| <body>
+
+#data
+<!doctype html><script><!--<s
+#errors
+Line: 1 Col: 29 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<s"
+| <body>
+
+#data
+<!doctype html><script><!--<script
+#errors
+Line: 1 Col: 34 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script"
+| <body>
+
+#data
+<!doctype html><script><!--<script
+#errors
+Line: 1 Col: 35 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script "
+| <body>
+
+#data
+<!doctype html><script><!--<script <
+#errors
+Line: 1 Col: 36 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script <"
+| <body>
+
+#data
+<!doctype html><script><!--<script <a
+#errors
+Line: 1 Col: 37 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script <a"
+| <body>
+
+#data
+<!doctype html><script><!--<script </
+#errors
+Line: 1 Col: 37 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script </"
+| <body>
+
+#data
+<!doctype html><script><!--<script </s
+#errors
+Line: 1 Col: 38 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script </s"
+| <body>
+
+#data
+<!doctype html><script><!--<script </script
+#errors
+Line: 1 Col: 43 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script </script"
+| <body>
+
+#data
+<!doctype html><script><!--<script </scripta
+#errors
+Line: 1 Col: 44 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script </scripta"
+| <body>
+
+#data
+<!doctype html><script><!--<script </script
+#errors
+Line: 1 Col: 44 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script </script "
+| <body>
+
+#data
+<!doctype html><script><!--<script </script>
+#errors
+Line: 1 Col: 44 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script </script>"
+| <body>
+
+#data
+<!doctype html><script><!--<script </script/
+#errors
+Line: 1 Col: 44 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script </script/"
+| <body>
+
+#data
+<!doctype html><script><!--<script </script <
+#errors
+Line: 1 Col: 45 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script </script <"
+| <body>
+
+#data
+<!doctype html><script><!--<script </script <a
+#errors
+Line: 1 Col: 46 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script </script <a"
+| <body>
+
+#data
+<!doctype html><script><!--<script </script </
+#errors
+Line: 1 Col: 46 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script </script </"
+| <body>
+
+#data
+<!doctype html><script><!--<script </script </script
+#errors
+Line: 1 Col: 52 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script </script </script"
+| <body>
+
+#data
+<!doctype html><script><!--<script </script </script
+#errors
+Line: 1 Col: 53 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script </script "
+| <body>
+
+#data
+<!doctype html><script><!--<script </script </script/
+#errors
+Line: 1 Col: 53 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script </script "
+| <body>
+
+#data
+<!doctype html><script><!--<script </script </script>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script </script "
+| <body>
+
+#data
+<!doctype html><script><!--<script -
+#errors
+Line: 1 Col: 36 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script -"
+| <body>
+
+#data
+<!doctype html><script><!--<script -a
+#errors
+Line: 1 Col: 37 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script -a"
+| <body>
+
+#data
+<!doctype html><script><!--<script -<
+#errors
+Line: 1 Col: 37 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script -<"
+| <body>
+
+#data
+<!doctype html><script><!--<script --
+#errors
+Line: 1 Col: 37 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script --"
+| <body>
+
+#data
+<!doctype html><script><!--<script --a
+#errors
+Line: 1 Col: 38 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script --a"
+| <body>
+
+#data
+<!doctype html><script><!--<script --<
+#errors
+Line: 1 Col: 38 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script --<"
+| <body>
+
+#data
+<!doctype html><script><!--<script -->
+#errors
+Line: 1 Col: 38 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script -->"
+| <body>
+
+#data
+<!doctype html><script><!--<script --><
+#errors
+Line: 1 Col: 39 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script --><"
+| <body>
+
+#data
+<!doctype html><script><!--<script --></
+#errors
+Line: 1 Col: 40 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script --></"
+| <body>
+
+#data
+<!doctype html><script><!--<script --></script
+#errors
+Line: 1 Col: 46 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script --></script"
+| <body>
+
+#data
+<!doctype html><script><!--<script --></script
+#errors
+Line: 1 Col: 47 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script -->"
+| <body>
+
+#data
+<!doctype html><script><!--<script --></script/
+#errors
+Line: 1 Col: 47 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script -->"
+| <body>
+
+#data
+<!doctype html><script><!--<script --></script>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script -->"
+| <body>
+
+#data
+<!doctype html><script><!--<script><\/script>--></script>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script><\/script>-->"
+| <body>
+
+#data
+<!doctype html><script><!--<script></scr'+'ipt>--></script>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script></scr'+'ipt>-->"
+| <body>
+
+#data
+<!doctype html><script><!--<script></script><script></script></script>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script></script><script></script>"
+| <body>
+
+#data
+<!doctype html><script><!--<script></script><script></script>--><!--</script>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script></script><script></script>--><!--"
+| <body>
+
+#data
+<!doctype html><script><!--<script></script><script></script>-- ></script>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script></script><script></script>-- >"
+| <body>
+
+#data
+<!doctype html><script><!--<script></script><script></script>- -></script>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script></script><script></script>- ->"
+| <body>
+
+#data
+<!doctype html><script><!--<script></script><script></script>- - ></script>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script></script><script></script>- - >"
+| <body>
+
+#data
+<!doctype html><script><!--<script></script><script></script>-></script>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script></script><script></script>->"
+| <body>
+
+#data
+<!doctype html><script><!--<script>--!></script>X
+#errors
+Line: 1 Col: 49 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script>--!></script>X"
+| <body>
+
+#data
+<!doctype html><script><!--<scr'+'ipt></script>--></script>
+#errors
+Line: 1 Col: 59 Unexpected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<scr'+'ipt>"
+| <body>
+| "-->"
+
+#data
+<!doctype html><script><!--<script></scr'+'ipt></script>X
+#errors
+Line: 1 Col: 57 Unexpected end of file. Expected end tag (script).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script></scr'+'ipt></script>X"
+| <body>
+
+#data
+<!doctype html><style><!--<style></style>--></style>
+#errors
+Line: 1 Col: 52 Unexpected end tag (style).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <style>
+| "<!--<style>"
+| <body>
+| "-->"
+
+#data
+<!doctype html><style><!--</style>X
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <style>
+| "<!--"
+| <body>
+| "X"
+
+#data
+<!doctype html><style><!--...</style>...--></style>
+#errors
+Line: 1 Col: 51 Unexpected end tag (style).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <style>
+| "<!--..."
+| <body>
+| "...-->"
+
+#data
+<!doctype html><style><!--<br><html xmlns:v="urn:schemas-microsoft-com:vml"><!--[if !mso]><style></style>X
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <style>
+| "<!--<br><html xmlns:v="urn:schemas-microsoft-com:vml"><!--[if !mso]><style>"
+| <body>
+| "X"
+
+#data
+<!doctype html><style><!--...<style><!--...--!></style>--></style>
+#errors
+Line: 1 Col: 66 Unexpected end tag (style).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <style>
+| "<!--...<style><!--...--!>"
+| <body>
+| "-->"
+
+#data
+<!doctype html><style><!--...</style><!-- --><style>@import ...</style>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <style>
+| "<!--..."
+| <!-- -->
+| <style>
+| "@import ..."
+| <body>
+
+#data
+<!doctype html><style>...<style><!--...</style><!-- --></style>
+#errors
+Line: 1 Col: 63 Unexpected end tag (style).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <style>
+| "...<style><!--..."
+| <!-- -->
+| <body>
+
+#data
+<!doctype html><style>...<!--[if IE]><style>...</style>X
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <style>
+| "...<!--[if IE]><style>..."
+| <body>
+| "X"
+
+#data
+<!doctype html><title><!--<title></title>--></title>
+#errors
+Line: 1 Col: 52 Unexpected end tag (title).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <title>
+| "<!--<title>"
+| <body>
+| "-->"
+
+#data
+<!doctype html><title>&lt;/title></title>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <title>
+| "</title>"
+| <body>
+
+#data
+<!doctype html><title>foo/title><link></head><body>X
+#errors
+Line: 1 Col: 52 Unexpected end of file. Expected end tag (title).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <title>
+| "foo/title><link></head><body>X"
+| <body>
+
+#data
+<!doctype html><noscript><!--<noscript></noscript>--></noscript>
+#errors
+Line: 1 Col: 64 Unexpected end tag (noscript).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <noscript>
+| "<!--<noscript>"
+| <body>
+| "-->"
+
+#data
+<!doctype html><noscript><!--</noscript>X<noscript>--></noscript>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <noscript>
+| "<!--"
+| <body>
+| "X"
+| <noscript>
+| "-->"
+
+#data
+<!doctype html><noscript><iframe></noscript>X
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <noscript>
+| "<iframe>"
+| <body>
+| "X"
+
+#data
+<!doctype html><noframes><!--<noframes></noframes>--></noframes>
+#errors
+Line: 1 Col: 64 Unexpected end tag (noframes).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <noframes>
+| "<!--<noframes>"
+| <body>
+| "-->"
+
+#data
+<!doctype html><noframes><body><script><!--...</script></body></noframes></html>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <noframes>
+| "<body><script><!--...</script></body>"
+| <body>
+
+#data
+<!doctype html><textarea><!--<textarea></textarea>--></textarea>
+#errors
+Line: 1 Col: 64 Unexpected end tag (textarea).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <textarea>
+| "<!--<textarea>"
+| "-->"
+
+#data
+<!doctype html><textarea>&lt;/textarea></textarea>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <textarea>
+| "</textarea>"
+
+#data
+<!doctype html><textarea>&lt;</textarea>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <textarea>
+| "<"
+
+#data
+<!doctype html><textarea>a&lt;b</textarea>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <textarea>
+| "a<b"
+
+#data
+<!doctype html><iframe><!--<iframe></iframe>--></iframe>
+#errors
+Line: 1 Col: 56 Unexpected end tag (iframe).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <iframe>
+| "<!--<iframe>"
+| "-->"
+
+#data
+<!doctype html><iframe>...<!--X->...<!--/X->...</iframe>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <iframe>
+| "...<!--X->...<!--/X->..."
+
+#data
+<!doctype html><xmp><!--<xmp></xmp>--></xmp>
+#errors
+Line: 1 Col: 44 Unexpected end tag (xmp).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <xmp>
+| "<!--<xmp>"
+| "-->"
+
+#data
+<!doctype html><noembed><!--<noembed></noembed>--></noembed>
+#errors
+Line: 1 Col: 60 Unexpected end tag (noembed).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <noembed>
+| "<!--<noembed>"
+| "-->"
+
+#data
+<script>
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 8 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| <body>
+
+#data
+<script>a
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 9 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "a"
+| <body>
+
+#data
+<script><
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 9 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "<"
+| <body>
+
+#data
+<script></
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 10 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "</"
+| <body>
+
+#data
+<script></S
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 11 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "</S"
+| <body>
+
+#data
+<script></SC
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 12 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "</SC"
+| <body>
+
+#data
+<script></SCR
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 13 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "</SCR"
+| <body>
+
+#data
+<script></SCRI
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 14 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "</SCRI"
+| <body>
+
+#data
+<script></SCRIP
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 15 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "</SCRIP"
+| <body>
+
+#data
+<script></SCRIPT
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 16 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "</SCRIPT"
+| <body>
+
+#data
+<script></SCRIPT
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 17 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| <body>
+
+#data
+<script></s
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 11 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "</s"
+| <body>
+
+#data
+<script></sc
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 12 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "</sc"
+| <body>
+
+#data
+<script></scr
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 13 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "</scr"
+| <body>
+
+#data
+<script></scri
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 14 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "</scri"
+| <body>
+
+#data
+<script></scrip
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 15 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "</scrip"
+| <body>
+
+#data
+<script></script
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 16 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "</script"
+| <body>
+
+#data
+<script></script
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 17 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| <body>
+
+#data
+<script><!
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 10 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "<!"
+| <body>
+
+#data
+<script><!a
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 11 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "<!a"
+| <body>
+
+#data
+<script><!-
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 11 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "<!-"
+| <body>
+
+#data
+<script><!-a
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 12 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "<!-a"
+| <body>
+
+#data
+<script><!--
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 12 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "<!--"
+| <body>
+
+#data
+<script><!--a
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 13 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "<!--a"
+| <body>
+
+#data
+<script><!--<
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 13 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<"
+| <body>
+
+#data
+<script><!--<a
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 14 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<a"
+| <body>
+
+#data
+<script><!--</
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 14 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "<!--</"
+| <body>
+
+#data
+<script><!--</script
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 20 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "<!--</script"
+| <body>
+
+#data
+<script><!--</script
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 21 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "<!--"
+| <body>
+
+#data
+<script><!--<s
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 14 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<s"
+| <body>
+
+#data
+<script><!--<script
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 19 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script"
+| <body>
+
+#data
+<script><!--<script
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 20 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script "
+| <body>
+
+#data
+<script><!--<script <
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 21 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script <"
+| <body>
+
+#data
+<script><!--<script <a
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 22 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script <a"
+| <body>
+
+#data
+<script><!--<script </
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 22 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script </"
+| <body>
+
+#data
+<script><!--<script </s
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 23 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script </s"
+| <body>
+
+#data
+<script><!--<script </script
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 28 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script </script"
+| <body>
+
+#data
+<script><!--<script </scripta
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 29 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script </scripta"
+| <body>
+
+#data
+<script><!--<script </script
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 29 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script </script "
+| <body>
+
+#data
+<script><!--<script </script>
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 29 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script </script>"
+| <body>
+
+#data
+<script><!--<script </script/
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 29 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script </script/"
+| <body>
+
+#data
+<script><!--<script </script <
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 30 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script </script <"
+| <body>
+
+#data
+<script><!--<script </script <a
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 31 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script </script <a"
+| <body>
+
+#data
+<script><!--<script </script </
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 31 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script </script </"
+| <body>
+
+#data
+<script><!--<script </script </script
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 38 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script </script </script"
+| <body>
+
+#data
+<script><!--<script </script </script
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 38 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script </script "
+| <body>
+
+#data
+<script><!--<script </script </script/
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 38 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script </script "
+| <body>
+
+#data
+<script><!--<script </script </script>
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script </script "
+| <body>
+
+#data
+<script><!--<script -
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 21 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script -"
+| <body>
+
+#data
+<script><!--<script -a
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 22 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script -a"
+| <body>
+
+#data
+<script><!--<script --
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 22 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script --"
+| <body>
+
+#data
+<script><!--<script --a
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 23 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script --a"
+| <body>
+
+#data
+<script><!--<script -->
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 23 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script -->"
+| <body>
+
+#data
+<script><!--<script --><
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 24 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script --><"
+| <body>
+
+#data
+<script><!--<script --></
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 25 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script --></"
+| <body>
+
+#data
+<script><!--<script --></script
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 31 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script --></script"
+| <body>
+
+#data
+<script><!--<script --></script
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 32 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script -->"
+| <body>
+
+#data
+<script><!--<script --></script/
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 32 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script -->"
+| <body>
+
+#data
+<script><!--<script --></script>
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script -->"
+| <body>
+
+#data
+<script><!--<script><\/script>--></script>
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script><\/script>-->"
+| <body>
+
+#data
+<script><!--<script></scr'+'ipt>--></script>
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script></scr'+'ipt>-->"
+| <body>
+
+#data
+<script><!--<script></script><script></script></script>
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script></script><script></script>"
+| <body>
+
+#data
+<script><!--<script></script><script></script>--><!--</script>
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script></script><script></script>--><!--"
+| <body>
+
+#data
+<script><!--<script></script><script></script>-- ></script>
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script></script><script></script>-- >"
+| <body>
+
+#data
+<script><!--<script></script><script></script>- -></script>
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script></script><script></script>- ->"
+| <body>
+
+#data
+<script><!--<script></script><script></script>- - ></script>
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script></script><script></script>- - >"
+| <body>
+
+#data
+<script><!--<script></script><script></script>-></script>
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script></script><script></script>->"
+| <body>
+
+#data
+<script><!--<script>--!></script>X
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 34 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script>--!></script>X"
+| <body>
+
+#data
+<script><!--<scr'+'ipt></script>--></script>
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 44 Unexpected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<scr'+'ipt>"
+| <body>
+| "-->"
+
+#data
+<script><!--<script></scr'+'ipt></script>X
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 42 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script></scr'+'ipt></script>X"
+| <body>
+
+#data
+<style><!--<style></style>--></style>
+#errors
+Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE.
+Line: 1 Col: 37 Unexpected end tag (style).
+#document
+| <html>
+| <head>
+| <style>
+| "<!--<style>"
+| <body>
+| "-->"
+
+#data
+<style><!--</style>X
+#errors
+Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <style>
+| "<!--"
+| <body>
+| "X"
+
+#data
+<style><!--...</style>...--></style>
+#errors
+Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE.
+Line: 1 Col: 36 Unexpected end tag (style).
+#document
+| <html>
+| <head>
+| <style>
+| "<!--..."
+| <body>
+| "...-->"
+
+#data
+<style><!--<br><html xmlns:v="urn:schemas-microsoft-com:vml"><!--[if !mso]><style></style>X
+#errors
+Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <style>
+| "<!--<br><html xmlns:v="urn:schemas-microsoft-com:vml"><!--[if !mso]><style>"
+| <body>
+| "X"
+
+#data
+<style><!--...<style><!--...--!></style>--></style>
+#errors
+Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE.
+Line: 1 Col: 51 Unexpected end tag (style).
+#document
+| <html>
+| <head>
+| <style>
+| "<!--...<style><!--...--!>"
+| <body>
+| "-->"
+
+#data
+<style><!--...</style><!-- --><style>@import ...</style>
+#errors
+Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <style>
+| "<!--..."
+| <!-- -->
+| <style>
+| "@import ..."
+| <body>
+
+#data
+<style>...<style><!--...</style><!-- --></style>
+#errors
+Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE.
+Line: 1 Col: 48 Unexpected end tag (style).
+#document
+| <html>
+| <head>
+| <style>
+| "...<style><!--..."
+| <!-- -->
+| <body>
+
+#data
+<style>...<!--[if IE]><style>...</style>X
+#errors
+Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <style>
+| "...<!--[if IE]><style>..."
+| <body>
+| "X"
+
+#data
+<title><!--<title></title>--></title>
+#errors
+Line: 1 Col: 7 Unexpected start tag (title). Expected DOCTYPE.
+Line: 1 Col: 37 Unexpected end tag (title).
+#document
+| <html>
+| <head>
+| <title>
+| "<!--<title>"
+| <body>
+| "-->"
+
+#data
+<title>&lt;/title></title>
+#errors
+Line: 1 Col: 7 Unexpected start tag (title). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <title>
+| "</title>"
+| <body>
+
+#data
+<title>foo/title><link></head><body>X
+#errors
+Line: 1 Col: 7 Unexpected start tag (title). Expected DOCTYPE.
+Line: 1 Col: 37 Unexpected end of file. Expected end tag (title).
+#document
+| <html>
+| <head>
+| <title>
+| "foo/title><link></head><body>X"
+| <body>
+
+#data
+<noscript><!--<noscript></noscript>--></noscript>
+#errors
+Line: 1 Col: 10 Unexpected start tag (noscript). Expected DOCTYPE.
+Line: 1 Col: 49 Unexpected end tag (noscript).
+#document
+| <html>
+| <head>
+| <noscript>
+| "<!--<noscript>"
+| <body>
+| "-->"
+
+#data
+<noscript><!--</noscript>X<noscript>--></noscript>
+#errors
+Line: 1 Col: 10 Unexpected start tag (noscript). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <noscript>
+| "<!--"
+| <body>
+| "X"
+| <noscript>
+| "-->"
+
+#data
+<noscript><iframe></noscript>X
+#errors
+Line: 1 Col: 10 Unexpected start tag (noscript). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <noscript>
+| "<iframe>"
+| <body>
+| "X"
+
+#data
+<noframes><!--<noframes></noframes>--></noframes>
+#errors
+Line: 1 Col: 10 Unexpected start tag (noframes). Expected DOCTYPE.
+Line: 1 Col: 49 Unexpected end tag (noframes).
+#document
+| <html>
+| <head>
+| <noframes>
+| "<!--<noframes>"
+| <body>
+| "-->"
+
+#data
+<noframes><body><script><!--...</script></body></noframes></html>
+#errors
+Line: 1 Col: 10 Unexpected start tag (noframes). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <noframes>
+| "<body><script><!--...</script></body>"
+| <body>
+
+#data
+<textarea><!--<textarea></textarea>--></textarea>
+#errors
+Line: 1 Col: 10 Unexpected start tag (textarea). Expected DOCTYPE.
+Line: 1 Col: 49 Unexpected end tag (textarea).
+#document
+| <html>
+| <head>
+| <body>
+| <textarea>
+| "<!--<textarea>"
+| "-->"
+
+#data
+<textarea>&lt;/textarea></textarea>
+#errors
+Line: 1 Col: 10 Unexpected start tag (textarea). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <body>
+| <textarea>
+| "</textarea>"
+
+#data
+<iframe><!--<iframe></iframe>--></iframe>
+#errors
+Line: 1 Col: 8 Unexpected start tag (iframe). Expected DOCTYPE.
+Line: 1 Col: 41 Unexpected end tag (iframe).
+#document
+| <html>
+| <head>
+| <body>
+| <iframe>
+| "<!--<iframe>"
+| "-->"
+
+#data
+<iframe>...<!--X->...<!--/X->...</iframe>
+#errors
+Line: 1 Col: 8 Unexpected start tag (iframe). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <body>
+| <iframe>
+| "...<!--X->...<!--/X->..."
+
+#data
+<xmp><!--<xmp></xmp>--></xmp>
+#errors
+Line: 1 Col: 5 Unexpected start tag (xmp). Expected DOCTYPE.
+Line: 1 Col: 29 Unexpected end tag (xmp).
+#document
+| <html>
+| <head>
+| <body>
+| <xmp>
+| "<!--<xmp>"
+| "-->"
+
+#data
+<noembed><!--<noembed></noembed>--></noembed>
+#errors
+Line: 1 Col: 9 Unexpected start tag (noembed). Expected DOCTYPE.
+Line: 1 Col: 45 Unexpected end tag (noembed).
+#document
+| <html>
+| <head>
+| <body>
+| <noembed>
+| "<!--<noembed>"
+| "-->"
+
+#data
+<!doctype html><table>
+
+#errors
+Line 2 Col 0 Unexpected end of file. Expected table content.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| "
+"
+
+#data
+<!doctype html><table><td><span><font></span><span>
+#errors
+Line 1 Col 26 Unexpected table cell start tag (td) in the table body phase.
+Line 1 Col 45 Unexpected end tag (span).
+Line 1 Col 51 Expected closing tag. Unexpected end of file.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <span>
+| <font>
+| <font>
+| <span>
+
+#data
+<!doctype html><form><table></form><form></table></form>
+#errors
+35: Stray end tag “form”.
+41: Start tag “form” seen in “table”.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <form>
+| <table>
+| <form>
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests17.dat b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests17.dat
new file mode 100644
index 000000000..7b555f888
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests17.dat
@@ -0,0 +1,153 @@
+#data
+<!doctype html><table><tbody><select><tr>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| <table>
+| <tbody>
+| <tr>
+
+#data
+<!doctype html><table><tr><select><td>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+
+#data
+<!doctype html><table><tr><td><select><td>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <select>
+| <td>
+
+#data
+<!doctype html><table><tr><th><select><td>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <th>
+| <select>
+| <td>
+
+#data
+<!doctype html><table><caption><select><tr>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+| <select>
+| <tbody>
+| <tr>
+
+#data
+<!doctype html><select><tr>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+
+#data
+<!doctype html><select><td>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+
+#data
+<!doctype html><select><th>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+
+#data
+<!doctype html><select><tbody>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+
+#data
+<!doctype html><select><thead>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+
+#data
+<!doctype html><select><tfoot>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+
+#data
+<!doctype html><select><caption>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+
+#data
+<!doctype html><table><tr></table>a
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| "a"
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests18.dat b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests18.dat
new file mode 100644
index 000000000..680e1f068
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests18.dat
@@ -0,0 +1,269 @@
+#data
+<!doctype html><plaintext></plaintext>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <plaintext>
+| "</plaintext>"
+
+#data
+<!doctype html><table><plaintext></plaintext>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <plaintext>
+| "</plaintext>"
+| <table>
+
+#data
+<!doctype html><table><tbody><plaintext></plaintext>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <plaintext>
+| "</plaintext>"
+| <table>
+| <tbody>
+
+#data
+<!doctype html><table><tbody><tr><plaintext></plaintext>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <plaintext>
+| "</plaintext>"
+| <table>
+| <tbody>
+| <tr>
+
+#data
+<!doctype html><table><tbody><tr><plaintext></plaintext>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <plaintext>
+| "</plaintext>"
+| <table>
+| <tbody>
+| <tr>
+
+#data
+<!doctype html><table><td><plaintext></plaintext>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <plaintext>
+| "</plaintext>"
+
+#data
+<!doctype html><table><caption><plaintext></plaintext>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+| <plaintext>
+| "</plaintext>"
+
+#data
+<!doctype html><table><tr><style></script></style>abc
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "abc"
+| <table>
+| <tbody>
+| <tr>
+| <style>
+| "</script>"
+
+#data
+<!doctype html><table><tr><script></style></script>abc
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "abc"
+| <table>
+| <tbody>
+| <tr>
+| <script>
+| "</style>"
+
+#data
+<!doctype html><table><caption><style></script></style>abc
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+| <style>
+| "</script>"
+| "abc"
+
+#data
+<!doctype html><table><td><style></script></style>abc
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <style>
+| "</script>"
+| "abc"
+
+#data
+<!doctype html><select><script></style></script>abc
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| <script>
+| "</style>"
+| "abc"
+
+#data
+<!doctype html><table><select><script></style></script>abc
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| <script>
+| "</style>"
+| "abc"
+| <table>
+
+#data
+<!doctype html><table><tr><select><script></style></script>abc
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| <script>
+| "</style>"
+| "abc"
+| <table>
+| <tbody>
+| <tr>
+
+#data
+<!doctype html><frameset></frameset><noframes>abc
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+| <noframes>
+| "abc"
+
+#data
+<!doctype html><frameset></frameset><noframes>abc</noframes><!--abc-->
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+| <noframes>
+| "abc"
+| <!-- abc -->
+
+#data
+<!doctype html><frameset></frameset></html><noframes>abc
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+| <noframes>
+| "abc"
+
+#data
+<!doctype html><frameset></frameset></html><noframes>abc</noframes><!--abc-->
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+| <noframes>
+| "abc"
+| <!-- abc -->
+
+#data
+<!doctype html><table><tr></tbody><tfoot>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <tfoot>
+
+#data
+<!doctype html><table><td><svg></svg>abc<td>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <svg svg>
+| "abc"
+| <td>
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests19.dat b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests19.dat
new file mode 100644
index 000000000..0d62f5a5b
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests19.dat
@@ -0,0 +1,1237 @@
+#data
+<!doctype html><math><mn DefinitionUrl="foo">
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mn>
+| definitionURL="foo"
+
+#data
+<!doctype html><html></p><!--foo-->
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <!-- foo -->
+| <head>
+| <body>
+
+#data
+<!doctype html><head></head></p><!--foo-->
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <!-- foo -->
+| <body>
+
+#data
+<!doctype html><body><p><pre>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <pre>
+
+#data
+<!doctype html><body><p><listing>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <listing>
+
+#data
+<!doctype html><p><plaintext>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <plaintext>
+
+#data
+<!doctype html><p><h1>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <h1>
+
+#data
+<!doctype html><form><isindex>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <form>
+
+#data
+<!doctype html><isindex action="POST">
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <form>
+| action="POST"
+| <hr>
+| <label>
+| "This is a searchable index. Enter search keywords: "
+| <input>
+| name="isindex"
+| <hr>
+
+#data
+<!doctype html><isindex prompt="this is isindex">
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <form>
+| <hr>
+| <label>
+| "this is isindex"
+| <input>
+| name="isindex"
+| <hr>
+
+#data
+<!doctype html><isindex type="hidden">
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <form>
+| <hr>
+| <label>
+| "This is a searchable index. Enter search keywords: "
+| <input>
+| name="isindex"
+| type="hidden"
+| <hr>
+
+#data
+<!doctype html><isindex name="foo">
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <form>
+| <hr>
+| <label>
+| "This is a searchable index. Enter search keywords: "
+| <input>
+| name="isindex"
+| <hr>
+
+#data
+<!doctype html><ruby><p><rp>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <ruby>
+| <p>
+| <rp>
+
+#data
+<!doctype html><ruby><div><span><rp>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <ruby>
+| <div>
+| <span>
+| <rp>
+
+#data
+<!doctype html><ruby><div><p><rp>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <ruby>
+| <div>
+| <p>
+| <rp>
+
+#data
+<!doctype html><ruby><p><rt>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <ruby>
+| <p>
+| <rt>
+
+#data
+<!doctype html><ruby><div><span><rt>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <ruby>
+| <div>
+| <span>
+| <rt>
+
+#data
+<!doctype html><ruby><div><p><rt>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <ruby>
+| <div>
+| <p>
+| <rt>
+
+#data
+<!doctype html><math/><foo>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+| <foo>
+
+#data
+<!doctype html><svg/><foo>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <foo>
+
+#data
+<!doctype html><div></body><!--foo-->
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <div>
+| <!-- foo -->
+
+#data
+<!doctype html><h1><div><h3><span></h1>foo
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <h1>
+| <div>
+| <h3>
+| <span>
+| "foo"
+
+#data
+<!doctype html><p></h3>foo
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| "foo"
+
+#data
+<!doctype html><h3><li>abc</h2>foo
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <h3>
+| <li>
+| "abc"
+| "foo"
+
+#data
+<!doctype html><table>abc<!--foo-->
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "abc"
+| <table>
+| <!-- foo -->
+
+#data
+<!doctype html><table> <!--foo-->
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| " "
+| <!-- foo -->
+
+#data
+<!doctype html><table> b <!--foo-->
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| " b "
+| <table>
+| <!-- foo -->
+
+#data
+<!doctype html><select><option><option>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| <option>
+| <option>
+
+#data
+<!doctype html><select><option></optgroup>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| <option>
+
+#data
+<!doctype html><select><option></optgroup>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| <option>
+
+#data
+<!doctype html><p><math><mi><p><h1>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <math math>
+| <math mi>
+| <p>
+| <h1>
+
+#data
+<!doctype html><p><math><mo><p><h1>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <math math>
+| <math mo>
+| <p>
+| <h1>
+
+#data
+<!doctype html><p><math><mn><p><h1>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <math math>
+| <math mn>
+| <p>
+| <h1>
+
+#data
+<!doctype html><p><math><ms><p><h1>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <math math>
+| <math ms>
+| <p>
+| <h1>
+
+#data
+<!doctype html><p><math><mtext><p><h1>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <math math>
+| <math mtext>
+| <p>
+| <h1>
+
+#data
+<!doctype html><frameset></noframes>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+
+#data
+<!doctype html><html c=d><body></html><html a=b>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| a="b"
+| c="d"
+| <head>
+| <body>
+
+#data
+<!doctype html><html c=d><frameset></frameset></html><html a=b>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| a="b"
+| c="d"
+| <head>
+| <frameset>
+
+#data
+<!doctype html><html><frameset></frameset></html><!--foo-->
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+| <!-- foo -->
+
+#data
+<!doctype html><html><frameset></frameset></html>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+| " "
+
+#data
+<!doctype html><html><frameset></frameset></html>abc
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+
+#data
+<!doctype html><html><frameset></frameset></html><p>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+
+#data
+<!doctype html><html><frameset></frameset></html></p>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+
+#data
+<html><frameset></frameset></html><!doctype html>
+#errors
+#document
+| <html>
+| <head>
+| <frameset>
+
+#data
+<!doctype html><body><frameset>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+
+#data
+<!doctype html><p><frameset><frame>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+| <frame>
+
+#data
+<!doctype html><p>a<frameset>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| "a"
+
+#data
+<!doctype html><p> <frameset><frame>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+| <frame>
+
+#data
+<!doctype html><pre><frameset>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <pre>
+
+#data
+<!doctype html><listing><frameset>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <listing>
+
+#data
+<!doctype html><li><frameset>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <li>
+
+#data
+<!doctype html><dd><frameset>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <dd>
+
+#data
+<!doctype html><dt><frameset>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <dt>
+
+#data
+<!doctype html><button><frameset>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <button>
+
+#data
+<!doctype html><applet><frameset>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <applet>
+
+#data
+<!doctype html><marquee><frameset>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <marquee>
+
+#data
+<!doctype html><object><frameset>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <object>
+
+#data
+<!doctype html><table><frameset>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+
+#data
+<!doctype html><area><frameset>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <area>
+
+#data
+<!doctype html><basefont><frameset>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <basefont>
+| <frameset>
+
+#data
+<!doctype html><bgsound><frameset>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <bgsound>
+| <frameset>
+
+#data
+<!doctype html><br><frameset>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <br>
+
+#data
+<!doctype html><embed><frameset>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <embed>
+
+#data
+<!doctype html><img><frameset>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <img>
+
+#data
+<!doctype html><input><frameset>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <input>
+
+#data
+<!doctype html><keygen><frameset>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <keygen>
+
+#data
+<!doctype html><wbr><frameset>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <wbr>
+
+#data
+<!doctype html><hr><frameset>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <hr>
+
+#data
+<!doctype html><textarea></textarea><frameset>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <textarea>
+
+#data
+<!doctype html><xmp></xmp><frameset>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <xmp>
+
+#data
+<!doctype html><iframe></iframe><frameset>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <iframe>
+
+#data
+<!doctype html><select></select><frameset>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+
+#data
+<!doctype html><svg></svg><frameset><frame>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+| <frame>
+
+#data
+<!doctype html><math></math><frameset><frame>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+| <frame>
+
+#data
+<!doctype html><svg><foreignObject><div> <frameset><frame>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+| <frame>
+
+#data
+<!doctype html><svg>a</svg><frameset><frame>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "a"
+
+#data
+<!doctype html><svg> </svg><frameset><frame>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+| <frame>
+
+#data
+<html>aaa<frameset></frameset>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "aaa"
+
+#data
+<html> a <frameset></frameset>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "a "
+
+#data
+<!doctype html><div><frameset>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+
+#data
+<!doctype html><div><body><frameset>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <div>
+
+#data
+<!doctype html><p><math></p>a
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <math math>
+| "a"
+
+#data
+<!doctype html><p><math><mn><span></p>a
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <math math>
+| <math mn>
+| <span>
+| <p>
+| "a"
+
+#data
+<!doctype html><math></html>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+
+#data
+<!doctype html><meta charset="ascii">
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <meta>
+| charset="ascii"
+| <body>
+
+#data
+<!doctype html><meta http-equiv="content-type" content="text/html;charset=ascii">
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <meta>
+| content="text/html;charset=ascii"
+| http-equiv="content-type"
+| <body>
+
+#data
+<!doctype html><head><!--aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa--><meta charset="utf8">
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <!-- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -->
+| <meta>
+| charset="utf8"
+| <body>
+
+#data
+<!doctype html><html a=b><head></head><html c=d>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| a="b"
+| c="d"
+| <head>
+| <body>
+
+#data
+<!doctype html><image/>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <img>
+
+#data
+<!doctype html>a<i>b<table>c<b>d</i>e</b>f
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "a"
+| <i>
+| "bc"
+| <b>
+| "de"
+| "f"
+| <table>
+
+#data
+<!doctype html><table><i>a<b>b<div>c<a>d</i>e</b>f
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <i>
+| "a"
+| <b>
+| "b"
+| <b>
+| <div>
+| <b>
+| <i>
+| "c"
+| <a>
+| "d"
+| <a>
+| "e"
+| <a>
+| "f"
+| <table>
+
+#data
+<!doctype html><i>a<b>b<div>c<a>d</i>e</b>f
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <i>
+| "a"
+| <b>
+| "b"
+| <b>
+| <div>
+| <b>
+| <i>
+| "c"
+| <a>
+| "d"
+| <a>
+| "e"
+| <a>
+| "f"
+
+#data
+<!doctype html><table><i>a<b>b<div>c</i>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <i>
+| "a"
+| <b>
+| "b"
+| <b>
+| <div>
+| <i>
+| "c"
+| <table>
+
+#data
+<!doctype html><table><i>a<b>b<div>c<a>d</i>e</b>f
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <i>
+| "a"
+| <b>
+| "b"
+| <b>
+| <div>
+| <b>
+| <i>
+| "c"
+| <a>
+| "d"
+| <a>
+| "e"
+| <a>
+| "f"
+| <table>
+
+#data
+<!doctype html><table><i>a<div>b<tr>c<b>d</i>e
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <i>
+| "a"
+| <div>
+| "b"
+| <i>
+| "c"
+| <b>
+| "d"
+| <b>
+| "e"
+| <table>
+| <tbody>
+| <tr>
+
+#data
+<!doctype html><table><td><table><i>a<div>b<b>c</i>d
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <i>
+| "a"
+| <div>
+| <i>
+| "b"
+| <b>
+| "c"
+| <b>
+| "d"
+| <table>
+
+#data
+<!doctype html><body><bgsound>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <bgsound>
+
+#data
+<!doctype html><body><basefont>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <basefont>
+
+#data
+<!doctype html><a><b></a><basefont>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <a>
+| <b>
+| <basefont>
+
+#data
+<!doctype html><a><b></a><bgsound>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <a>
+| <b>
+| <bgsound>
+
+#data
+<!doctype html><figcaption><article></figcaption>a
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <figcaption>
+| <article>
+| "a"
+
+#data
+<!doctype html><summary><article></summary>a
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <summary>
+| <article>
+| "a"
+
+#data
+<!doctype html><p><a><plaintext>b
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <a>
+| <plaintext>
+| <a>
+| "b"
+
+#data
+<!DOCTYPE html><div>a<a></div>b<p>c</p>d
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <div>
+| "a"
+| <a>
+| <a>
+| "b"
+| <p>
+| "c"
+| "d"
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests2.dat b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests2.dat
new file mode 100644
index 000000000..60d859221
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests2.dat
@@ -0,0 +1,763 @@
+#data
+<!DOCTYPE html>Test
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "Test"
+
+#data
+<textarea>test</div>test
+#errors
+Line: 1 Col: 10 Unexpected start tag (textarea). Expected DOCTYPE.
+Line: 1 Col: 24 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <textarea>
+| "test</div>test"
+
+#data
+<table><td>
+#errors
+Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE.
+Line: 1 Col: 11 Unexpected table cell start tag (td) in the table body phase.
+Line: 1 Col: 11 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+
+#data
+<table><td>test</tbody></table>
+#errors
+Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE.
+Line: 1 Col: 11 Unexpected table cell start tag (td) in the table body phase.
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| "test"
+
+#data
+<frame>test
+#errors
+Line: 1 Col: 7 Unexpected start tag (frame). Expected DOCTYPE.
+Line: 1 Col: 7 Unexpected start tag frame. Ignored.
+#document
+| <html>
+| <head>
+| <body>
+| "test"
+
+#data
+<!DOCTYPE html><frameset>test
+#errors
+Line: 1 Col: 29 Unepxected characters in the frameset phase. Characters ignored.
+Line: 1 Col: 29 Expected closing tag. Unexpected end of file.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+
+#data
+<!DOCTYPE html><frameset><!DOCTYPE html>
+#errors
+Line: 1 Col: 40 Unexpected DOCTYPE. Ignored.
+Line: 1 Col: 40 Expected closing tag. Unexpected end of file.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+
+#data
+<!DOCTYPE html><font><p><b>test</font>
+#errors
+Line: 1 Col: 38 End tag (font) violates step 1, paragraph 3 of the adoption agency algorithm.
+Line: 1 Col: 38 End tag (font) violates step 1, paragraph 3 of the adoption agency algorithm.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <font>
+| <p>
+| <font>
+| <b>
+| "test"
+
+#data
+<!DOCTYPE html><dt><div><dd>
+#errors
+Line: 1 Col: 28 Missing end tag (div, dt).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <dt>
+| <div>
+| <dd>
+
+#data
+<script></x
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+Line: 1 Col: 11 Unexpected end of file. Expected end tag (script).
+#document
+| <html>
+| <head>
+| <script>
+| "</x"
+| <body>
+
+#data
+<table><plaintext><td>
+#errors
+Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE.
+Line: 1 Col: 18 Unexpected start tag (plaintext) in table context caused voodoo mode.
+Line: 1 Col: 22 Unexpected end of file. Expected table content.
+#document
+| <html>
+| <head>
+| <body>
+| <plaintext>
+| "<td>"
+| <table>
+
+#data
+<plaintext></plaintext>
+#errors
+Line: 1 Col: 11 Unexpected start tag (plaintext). Expected DOCTYPE.
+Line: 1 Col: 23 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <plaintext>
+| "</plaintext>"
+
+#data
+<!DOCTYPE html><table><tr>TEST
+#errors
+Line: 1 Col: 30 Unexpected non-space characters in table context caused voodoo mode.
+Line: 1 Col: 30 Unexpected end of file. Expected table content.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "TEST"
+| <table>
+| <tbody>
+| <tr>
+
+#data
+<!DOCTYPE html><body t1=1><body t2=2><body t3=3 t4=4>
+#errors
+Line: 1 Col: 37 Unexpected start tag (body).
+Line: 1 Col: 53 Unexpected start tag (body).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| t1="1"
+| t2="2"
+| t3="3"
+| t4="4"
+
+#data
+</b test
+#errors
+Line: 1 Col: 8 Unexpected end of file in attribute name.
+Line: 1 Col: 8 End tag contains unexpected attributes.
+Line: 1 Col: 8 Unexpected end tag (b). Expected DOCTYPE.
+Line: 1 Col: 8 Unexpected end tag (b) after the (implied) root element.
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<!DOCTYPE html></b test<b &=&amp>X
+#errors
+Line: 1 Col: 32 Named entity didn't end with ';'.
+Line: 1 Col: 33 End tag contains unexpected attributes.
+Line: 1 Col: 33 Unexpected end tag (b) after the (implied) root element.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "X"
+
+#data
+<!doctypehtml><scrIPt type=text/x-foobar;baz>X</SCRipt
+#errors
+Line: 1 Col: 9 No space after literal string 'DOCTYPE'.
+Line: 1 Col: 54 Unexpected end of file in the tag name.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| type="text/x-foobar;baz"
+| "X</SCRipt"
+| <body>
+
+#data
+&
+#errors
+Line: 1 Col: 1 Unexpected non-space characters. Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <body>
+| "&"
+
+#data
+&#
+#errors
+Line: 1 Col: 1 Numeric entity expected. Got end of file instead.
+Line: 1 Col: 1 Unexpected non-space characters. Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <body>
+| "&#"
+
+#data
+&#X
+#errors
+Line: 1 Col: 3 Numeric entity expected but none found.
+Line: 1 Col: 3 Unexpected non-space characters. Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <body>
+| "&#X"
+
+#data
+&#x
+#errors
+Line: 1 Col: 3 Numeric entity expected but none found.
+Line: 1 Col: 3 Unexpected non-space characters. Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <body>
+| "&#x"
+
+#data
+&#45
+#errors
+Line: 1 Col: 4 Numeric entity didn't end with ';'.
+Line: 1 Col: 4 Unexpected non-space characters. Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <body>
+| "-"
+
+#data
+&x-test
+#errors
+Line: 1 Col: 1 Named entity expected. Got none.
+Line: 1 Col: 1 Unexpected non-space characters. Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <body>
+| "&x-test"
+
+#data
+<!doctypehtml><p><li>
+#errors
+Line: 1 Col: 9 No space after literal string 'DOCTYPE'.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <li>
+
+#data
+<!doctypehtml><p><dt>
+#errors
+Line: 1 Col: 9 No space after literal string 'DOCTYPE'.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <dt>
+
+#data
+<!doctypehtml><p><dd>
+#errors
+Line: 1 Col: 9 No space after literal string 'DOCTYPE'.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <dd>
+
+#data
+<!doctypehtml><p><form>
+#errors
+Line: 1 Col: 9 No space after literal string 'DOCTYPE'.
+Line: 1 Col: 23 Expected closing tag. Unexpected end of file.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <form>
+
+#data
+<!DOCTYPE html><p></P>X
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| "X"
+
+#data
+&AMP
+#errors
+Line: 1 Col: 4 Named entity didn't end with ';'.
+Line: 1 Col: 4 Unexpected non-space characters. Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <body>
+| "&"
+
+#data
+&AMp;
+#errors
+Line: 1 Col: 1 Named entity expected. Got none.
+Line: 1 Col: 1 Unexpected non-space characters. Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <body>
+| "&AMp;"
+
+#data
+<!DOCTYPE html><html><head></head><body><thisISasillyTESTelementNameToMakeSureCrazyTagNamesArePARSEDcorrectLY>
+#errors
+Line: 1 Col: 110 Expected closing tag. Unexpected end of file.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <thisisasillytestelementnametomakesurecrazytagnamesareparsedcorrectly>
+
+#data
+<!DOCTYPE html>X</body>X
+#errors
+Line: 1 Col: 24 Unexpected non-space characters in the after body phase.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "XX"
+
+#data
+<!DOCTYPE html><!-- X
+#errors
+Line: 1 Col: 21 Unexpected end of file in comment.
+#document
+| <!DOCTYPE html>
+| <!-- X -->
+| <html>
+| <head>
+| <body>
+
+#data
+<!DOCTYPE html><table><caption>test TEST</caption><td>test
+#errors
+Line: 1 Col: 54 Unexpected table cell start tag (td) in the table body phase.
+Line: 1 Col: 58 Expected closing tag. Unexpected end of file.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+| "test TEST"
+| <tbody>
+| <tr>
+| <td>
+| "test"
+
+#data
+<!DOCTYPE html><select><option><optgroup>
+#errors
+Line: 1 Col: 41 Expected closing tag. Unexpected end of file.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| <option>
+| <optgroup>
+
+#data
+<!DOCTYPE html><select><optgroup><option></optgroup><option><select><option>
+#errors
+Line: 1 Col: 68 Unexpected select start tag in the select phase treated as select end tag.
+Line: 1 Col: 76 Expected closing tag. Unexpected end of file.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| <optgroup>
+| <option>
+| <option>
+| <option>
+
+#data
+<!DOCTYPE html><select><optgroup><option><optgroup>
+#errors
+Line: 1 Col: 51 Expected closing tag. Unexpected end of file.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| <optgroup>
+| <option>
+| <optgroup>
+
+#data
+<!DOCTYPE html><datalist><option>foo</datalist>bar
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <datalist>
+| <option>
+| "foo"
+| "bar"
+
+#data
+<!DOCTYPE html><font><input><input></font>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <font>
+| <input>
+| <input>
+
+#data
+<!DOCTYPE html><!-- XXX - XXX -->
+#errors
+#document
+| <!DOCTYPE html>
+| <!-- XXX - XXX -->
+| <html>
+| <head>
+| <body>
+
+#data
+<!DOCTYPE html><!-- XXX - XXX
+#errors
+Line: 1 Col: 29 Unexpected end of file in comment (-)
+#document
+| <!DOCTYPE html>
+| <!-- XXX - XXX -->
+| <html>
+| <head>
+| <body>
+
+#data
+<!DOCTYPE html><!-- XXX - XXX - XXX -->
+#errors
+#document
+| <!DOCTYPE html>
+| <!-- XXX - XXX - XXX -->
+| <html>
+| <head>
+| <body>
+
+#data
+<isindex test=x name=x>
+#errors
+Line: 1 Col: 23 Unexpected start tag (isindex). Expected DOCTYPE.
+Line: 1 Col: 23 Unexpected start tag isindex. Don't use it!
+#document
+| <html>
+| <head>
+| <body>
+| <form>
+| <hr>
+| <label>
+| "This is a searchable index. Enter search keywords: "
+| <input>
+| name="isindex"
+| test="x"
+| <hr>
+
+#data
+test
+test
+#errors
+Line: 2 Col: 4 Unexpected non-space characters. Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <body>
+| "test
+test"
+
+#data
+<!DOCTYPE html><body><title>test</body></title>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <title>
+| "test</body>"
+
+#data
+<!DOCTYPE html><body><title>X</title><meta name=z><link rel=foo><style>
+x { content:"</style" } </style>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <title>
+| "X"
+| <meta>
+| name="z"
+| <link>
+| rel="foo"
+| <style>
+| "
+x { content:"</style" } "
+
+#data
+<!DOCTYPE html><select><optgroup></optgroup></select>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| <optgroup>
+
+#data
+
+
+#errors
+Line: 2 Col: 1 Unexpected End of file. Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<!DOCTYPE html> <html>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+
+#data
+<!DOCTYPE html><script>
+</script> <title>x</title> </head>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "
+"
+| " "
+| <title>
+| "x"
+| " "
+| <body>
+
+#data
+<!DOCTYPE html><html><body><html id=x>
+#errors
+Line: 1 Col: 38 html needs to be the first start tag.
+#document
+| <!DOCTYPE html>
+| <html>
+| id="x"
+| <head>
+| <body>
+
+#data
+<!DOCTYPE html>X</body><html id="x">
+#errors
+Line: 1 Col: 36 Unexpected start tag token (html) in the after body phase.
+Line: 1 Col: 36 html needs to be the first start tag.
+#document
+| <!DOCTYPE html>
+| <html>
+| id="x"
+| <head>
+| <body>
+| "X"
+
+#data
+<!DOCTYPE html><head><html id=x>
+#errors
+Line: 1 Col: 32 html needs to be the first start tag.
+#document
+| <!DOCTYPE html>
+| <html>
+| id="x"
+| <head>
+| <body>
+
+#data
+<!DOCTYPE html>X</html>X
+#errors
+Line: 1 Col: 24 Unexpected non-space characters in the after body phase.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "XX"
+
+#data
+<!DOCTYPE html>X</html>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "X "
+
+#data
+<!DOCTYPE html>X</html><p>X
+#errors
+Line: 1 Col: 26 Unexpected start tag (p).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "X"
+| <p>
+| "X"
+
+#data
+<!DOCTYPE html>X<p/x/y/z>
+#errors
+Line: 1 Col: 19 Expected a > after the /.
+Line: 1 Col: 21 Solidus (/) incorrectly placed in tag.
+Line: 1 Col: 23 Solidus (/) incorrectly placed in tag.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "X"
+| <p>
+| x=""
+| y=""
+| z=""
+
+#data
+<!DOCTYPE html><!--x--
+#errors
+Line: 1 Col: 22 Unexpected end of file in comment (--).
+#document
+| <!DOCTYPE html>
+| <!-- x -->
+| <html>
+| <head>
+| <body>
+
+#data
+<!DOCTYPE html><table><tr><td></p></table>
+#errors
+Line: 1 Col: 34 Unexpected end tag (p). Ignored.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <p>
+
+#data
+<!DOCTYPE <!DOCTYPE HTML>><!--<!--x-->-->
+#errors
+Line: 1 Col: 20 Expected space or '>'. Got ''
+Line: 1 Col: 25 Erroneous DOCTYPE.
+Line: 1 Col: 35 Unexpected character in comment found.
+#document
+| <!DOCTYPE <!doctype>
+| <html>
+| <head>
+| <body>
+| ">"
+| <!-- <!--x -->
+| "-->"
+
+#data
+<!doctype html><div><form></form><div></div></div>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <div>
+| <form>
+| <div>
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests20.dat b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests20.dat
new file mode 100644
index 000000000..6bd825608
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests20.dat
@@ -0,0 +1,455 @@
+#data
+<!doctype html><p><button><button>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <button>
+
+#data
+<!doctype html><p><button><address>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <address>
+
+#data
+<!doctype html><p><button><blockquote>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <blockquote>
+
+#data
+<!doctype html><p><button><menu>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <menu>
+
+#data
+<!doctype html><p><button><p>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <p>
+
+#data
+<!doctype html><p><button><ul>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <ul>
+
+#data
+<!doctype html><p><button><h1>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <h1>
+
+#data
+<!doctype html><p><button><h6>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <h6>
+
+#data
+<!doctype html><p><button><listing>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <listing>
+
+#data
+<!doctype html><p><button><pre>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <pre>
+
+#data
+<!doctype html><p><button><form>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <form>
+
+#data
+<!doctype html><p><button><li>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <li>
+
+#data
+<!doctype html><p><button><dd>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <dd>
+
+#data
+<!doctype html><p><button><dt>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <dt>
+
+#data
+<!doctype html><p><button><plaintext>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <plaintext>
+
+#data
+<!doctype html><p><button><table>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <table>
+
+#data
+<!doctype html><p><button><hr>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <hr>
+
+#data
+<!doctype html><p><button><xmp>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <xmp>
+
+#data
+<!doctype html><p><button></p>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <p>
+
+#data
+<!doctype html><address><button></address>a
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <address>
+| <button>
+| "a"
+
+#data
+<!doctype html><address><button></address>a
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <address>
+| <button>
+| "a"
+
+#data
+<p><table></p>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <p>
+| <table>
+
+#data
+<!doctype html><svg>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+
+#data
+<!doctype html><p><figcaption>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <figcaption>
+
+#data
+<!doctype html><p><summary>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <summary>
+
+#data
+<!doctype html><form><table><form>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <form>
+| <table>
+
+#data
+<!doctype html><table><form><form>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <form>
+
+#data
+<!doctype html><table><form></table><form>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <form>
+
+#data
+<!doctype html><svg><foreignObject><p>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg foreignObject>
+| <p>
+
+#data
+<!doctype html><svg><title>abc
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg title>
+| "abc"
+
+#data
+<option><span><option>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <option>
+| <span>
+| <option>
+
+#data
+<option><option>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <option>
+| <option>
+
+#data
+<math><annotation-xml><div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math annotation-xml>
+| <div>
+
+#data
+<math><annotation-xml encoding="application/svg+xml"><div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math annotation-xml>
+| encoding="application/svg+xml"
+| <div>
+
+#data
+<math><annotation-xml encoding="application/xhtml+xml"><div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math annotation-xml>
+| encoding="application/xhtml+xml"
+| <div>
+
+#data
+<math><annotation-xml encoding="aPPlication/xhtmL+xMl"><div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math annotation-xml>
+| encoding="aPPlication/xhtmL+xMl"
+| <div>
+
+#data
+<math><annotation-xml encoding="text/html"><div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math annotation-xml>
+| encoding="text/html"
+| <div>
+
+#data
+<math><annotation-xml encoding="Text/htmL"><div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math annotation-xml>
+| encoding="Text/htmL"
+| <div>
+
+#data
+<math><annotation-xml encoding=" text/html "><div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math annotation-xml>
+| encoding=" text/html "
+| <div>
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests21.dat b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests21.dat
new file mode 100644
index 000000000..1260ec03e
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests21.dat
@@ -0,0 +1,221 @@
+#data
+<svg><![CDATA[foo]]>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "foo"
+
+#data
+<math><![CDATA[foo]]>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| "foo"
+
+#data
+<div><![CDATA[foo]]>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <!-- [CDATA[foo]] -->
+
+#data
+<svg><![CDATA[foo
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "foo"
+
+#data
+<svg><![CDATA[foo
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "foo"
+
+#data
+<svg><![CDATA[
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+
+#data
+<svg><![CDATA[]]>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+
+#data
+<svg><![CDATA[]] >]]>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "]] >"
+
+#data
+<svg><![CDATA[]] >]]>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "]] >"
+
+#data
+<svg><![CDATA[]]
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "]]"
+
+#data
+<svg><![CDATA[]
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "]"
+
+#data
+<svg><![CDATA[]>a
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "]>a"
+
+#data
+<svg><foreignObject><div><![CDATA[foo]]>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg foreignObject>
+| <div>
+| <!-- [CDATA[foo]] -->
+
+#data
+<svg><![CDATA[<svg>]]>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "<svg>"
+
+#data
+<svg><![CDATA[</svg>a]]>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "</svg>a"
+
+#data
+<svg><![CDATA[<svg>a
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "<svg>a"
+
+#data
+<svg><![CDATA[</svg>a
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "</svg>a"
+
+#data
+<svg><![CDATA[<svg>]]><path>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "<svg>"
+| <svg path>
+
+#data
+<svg><![CDATA[<svg>]]></path>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "<svg>"
+
+#data
+<svg><![CDATA[<svg>]]><!--path-->
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "<svg>"
+| <!-- path -->
+
+#data
+<svg><![CDATA[<svg>]]>path
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "<svg>path"
+
+#data
+<svg><![CDATA[<!--svg-->]]>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "<!--svg-->"
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests22.dat b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests22.dat
new file mode 100644
index 000000000..aab27b2e9
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests22.dat
@@ -0,0 +1,157 @@
+#data
+<a><b><big><em><strong><div>X</a>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| <b>
+| <big>
+| <em>
+| <strong>
+| <big>
+| <em>
+| <strong>
+| <div>
+| <a>
+| "X"
+
+#data
+<a><b><div id=1><div id=2><div id=3><div id=4><div id=5><div id=6><div id=7><div id=8>A</a>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| <b>
+| <b>
+| <div>
+| id="1"
+| <a>
+| <div>
+| id="2"
+| <a>
+| <div>
+| id="3"
+| <a>
+| <div>
+| id="4"
+| <a>
+| <div>
+| id="5"
+| <a>
+| <div>
+| id="6"
+| <a>
+| <div>
+| id="7"
+| <a>
+| <div>
+| id="8"
+| <a>
+| "A"
+
+#data
+<a><b><div id=1><div id=2><div id=3><div id=4><div id=5><div id=6><div id=7><div id=8><div id=9>A</a>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| <b>
+| <b>
+| <div>
+| id="1"
+| <a>
+| <div>
+| id="2"
+| <a>
+| <div>
+| id="3"
+| <a>
+| <div>
+| id="4"
+| <a>
+| <div>
+| id="5"
+| <a>
+| <div>
+| id="6"
+| <a>
+| <div>
+| id="7"
+| <a>
+| <div>
+| id="8"
+| <a>
+| <div>
+| id="9"
+| "A"
+
+#data
+<a><b><div id=1><div id=2><div id=3><div id=4><div id=5><div id=6><div id=7><div id=8><div id=9><div id=10>A</a>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| <b>
+| <b>
+| <div>
+| id="1"
+| <a>
+| <div>
+| id="2"
+| <a>
+| <div>
+| id="3"
+| <a>
+| <div>
+| id="4"
+| <a>
+| <div>
+| id="5"
+| <a>
+| <div>
+| id="6"
+| <a>
+| <div>
+| id="7"
+| <a>
+| <div>
+| id="8"
+| <a>
+| <div>
+| id="9"
+| <div>
+| id="10"
+| "A"
+
+#data
+<cite><b><cite><i><cite><i><cite><i><div>X</b>TEST
+#errors
+Line: 1 Col: 6 Unexpected start tag (cite). Expected DOCTYPE.
+Line: 1 Col: 46 End tag (b) violates step 1, paragraph 3 of the adoption agency algorithm.
+Line: 1 Col: 50 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <cite>
+| <b>
+| <cite>
+| <i>
+| <cite>
+| <i>
+| <cite>
+| <i>
+| <i>
+| <i>
+| <div>
+| <b>
+| "X"
+| "TEST"
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests23.dat b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests23.dat
new file mode 100644
index 000000000..34d2a73f1
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests23.dat
@@ -0,0 +1,155 @@
+#data
+<p><font size=4><font color=red><font size=4><font size=4><font size=4><font size=4><font size=4><font color=red><p>X
+#errors
+3: Start tag seen without seeing a doctype first. Expected “<!DOCTYPE html>”.
+116: Unclosed elements.
+117: End of file seen and there were open elements.
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <font>
+| size="4"
+| <font>
+| color="red"
+| <font>
+| size="4"
+| <font>
+| size="4"
+| <font>
+| size="4"
+| <font>
+| size="4"
+| <font>
+| size="4"
+| <font>
+| color="red"
+| <p>
+| <font>
+| color="red"
+| <font>
+| size="4"
+| <font>
+| size="4"
+| <font>
+| size="4"
+| <font>
+| color="red"
+| "X"
+
+#data
+<p><font size=4><font size=4><font size=4><font size=4><p>X
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <font>
+| size="4"
+| <font>
+| size="4"
+| <font>
+| size="4"
+| <font>
+| size="4"
+| <p>
+| <font>
+| size="4"
+| <font>
+| size="4"
+| <font>
+| size="4"
+| "X"
+
+#data
+<p><font size=4><font size=4><font size=4><font size="5"><font size=4><p>X
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <font>
+| size="4"
+| <font>
+| size="4"
+| <font>
+| size="4"
+| <font>
+| size="5"
+| <font>
+| size="4"
+| <p>
+| <font>
+| size="4"
+| <font>
+| size="4"
+| <font>
+| size="5"
+| <font>
+| size="4"
+| "X"
+
+#data
+<p><font size=4 id=a><font size=4 id=b><font size=4><font size=4><p>X
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <font>
+| id="a"
+| size="4"
+| <font>
+| id="b"
+| size="4"
+| <font>
+| size="4"
+| <font>
+| size="4"
+| <p>
+| <font>
+| id="a"
+| size="4"
+| <font>
+| id="b"
+| size="4"
+| <font>
+| size="4"
+| <font>
+| size="4"
+| "X"
+
+#data
+<p><b id=a><b id=a><b id=a><b><object><b id=a><b id=a>X</object><p>Y
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <b>
+| id="a"
+| <b>
+| id="a"
+| <b>
+| id="a"
+| <b>
+| <object>
+| <b>
+| id="a"
+| <b>
+| id="a"
+| "X"
+| <p>
+| <b>
+| id="a"
+| <b>
+| id="a"
+| <b>
+| id="a"
+| <b>
+| "Y"
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests24.dat b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests24.dat
new file mode 100644
index 000000000..f6dc7eb48
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests24.dat
@@ -0,0 +1,79 @@
+#data
+<!DOCTYPE html>&NotEqualTilde;
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "≂̸"
+
+#data
+<!DOCTYPE html>&NotEqualTilde;A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "≂̸A"
+
+#data
+<!DOCTYPE html>&ThickSpace;
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "  "
+
+#data
+<!DOCTYPE html>&ThickSpace;A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "  A"
+
+#data
+<!DOCTYPE html>&NotSubset;
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "⊂⃒"
+
+#data
+<!DOCTYPE html>&NotSubset;A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "⊂⃒A"
+
+#data
+<!DOCTYPE html>&Gopf;
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "𝔾"
+
+#data
+<!DOCTYPE html>&Gopf;A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "𝔾A"
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests25.dat b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests25.dat
new file mode 100644
index 000000000..00de7295b
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests25.dat
@@ -0,0 +1,219 @@
+#data
+<!DOCTYPE html><body><foo>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <foo>
+| "A"
+
+#data
+<!DOCTYPE html><body><area>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <area>
+| "A"
+
+#data
+<!DOCTYPE html><body><base>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <base>
+| "A"
+
+#data
+<!DOCTYPE html><body><basefont>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <basefont>
+| "A"
+
+#data
+<!DOCTYPE html><body><bgsound>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <bgsound>
+| "A"
+
+#data
+<!DOCTYPE html><body><br>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <br>
+| "A"
+
+#data
+<!DOCTYPE html><body><col>A
+#errors
+26: Stray start tag “col”.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "A"
+
+#data
+<!DOCTYPE html><body><command>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <command>
+| "A"
+
+#data
+<!DOCTYPE html><body><embed>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <embed>
+| "A"
+
+#data
+<!DOCTYPE html><body><frame>A
+#errors
+26: Stray start tag “frame”.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "A"
+
+#data
+<!DOCTYPE html><body><hr>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <hr>
+| "A"
+
+#data
+<!DOCTYPE html><body><img>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <img>
+| "A"
+
+#data
+<!DOCTYPE html><body><input>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <input>
+| "A"
+
+#data
+<!DOCTYPE html><body><keygen>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <keygen>
+| "A"
+
+#data
+<!DOCTYPE html><body><link>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <link>
+| "A"
+
+#data
+<!DOCTYPE html><body><meta>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <meta>
+| "A"
+
+#data
+<!DOCTYPE html><body><param>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <param>
+| "A"
+
+#data
+<!DOCTYPE html><body><source>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <source>
+| "A"
+
+#data
+<!DOCTYPE html><body><track>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <track>
+| "A"
+
+#data
+<!DOCTYPE html><body><wbr>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <wbr>
+| "A"
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests26.dat b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests26.dat
new file mode 100644
index 000000000..fae11ffdf
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests26.dat
@@ -0,0 +1,313 @@
+#data
+<!DOCTYPE html><body><a href='#1'><nobr>1<nobr></a><br><a href='#2'><nobr>2<nobr></a><br><a href='#3'><nobr>3<nobr></a>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <a>
+| href="#1"
+| <nobr>
+| "1"
+| <nobr>
+| <nobr>
+| <br>
+| <a>
+| href="#2"
+| <a>
+| href="#2"
+| <nobr>
+| "2"
+| <nobr>
+| <nobr>
+| <br>
+| <a>
+| href="#3"
+| <a>
+| href="#3"
+| <nobr>
+| "3"
+| <nobr>
+
+#data
+<!DOCTYPE html><body><b><nobr>1<nobr></b><i><nobr>2<nobr></i>3
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <b>
+| <nobr>
+| "1"
+| <nobr>
+| <nobr>
+| <i>
+| <i>
+| <nobr>
+| "2"
+| <nobr>
+| <nobr>
+| "3"
+
+#data
+<!DOCTYPE html><body><b><nobr>1<table><nobr></b><i><nobr>2<nobr></i>3
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <b>
+| <nobr>
+| "1"
+| <nobr>
+| <i>
+| <i>
+| <nobr>
+| "2"
+| <nobr>
+| <nobr>
+| "3"
+| <table>
+
+#data
+<!DOCTYPE html><body><b><nobr>1<table><tr><td><nobr></b><i><nobr>2<nobr></i>3
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <b>
+| <nobr>
+| "1"
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <nobr>
+| <i>
+| <i>
+| <nobr>
+| "2"
+| <nobr>
+| <nobr>
+| "3"
+
+#data
+<!DOCTYPE html><body><b><nobr>1<div><nobr></b><i><nobr>2<nobr></i>3
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <b>
+| <nobr>
+| "1"
+| <div>
+| <b>
+| <nobr>
+| <nobr>
+| <nobr>
+| <i>
+| <i>
+| <nobr>
+| "2"
+| <nobr>
+| <nobr>
+| "3"
+
+#data
+<!DOCTYPE html><body><b><nobr>1<nobr></b><div><i><nobr>2<nobr></i>3
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <b>
+| <nobr>
+| "1"
+| <nobr>
+| <div>
+| <nobr>
+| <i>
+| <i>
+| <nobr>
+| "2"
+| <nobr>
+| <nobr>
+| "3"
+
+#data
+<!DOCTYPE html><body><b><nobr>1<nobr><ins></b><i><nobr>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <b>
+| <nobr>
+| "1"
+| <nobr>
+| <ins>
+| <nobr>
+| <i>
+| <i>
+| <nobr>
+
+#data
+<!DOCTYPE html><body><b><nobr>1<ins><nobr></b><i>2
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <b>
+| <nobr>
+| "1"
+| <ins>
+| <nobr>
+| <nobr>
+| <i>
+| "2"
+
+#data
+<!DOCTYPE html><body><b>1<nobr></b><i><nobr>2</i>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <b>
+| "1"
+| <nobr>
+| <nobr>
+| <i>
+| <i>
+| <nobr>
+| "2"
+
+#data
+<p><code x</code></p>
+
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <code>
+| code=""
+| x<=""
+| <code>
+| code=""
+| x<=""
+| "
+"
+
+#data
+<!DOCTYPE html><svg><foreignObject><p><i></p>a
+#errors
+45: End tag “p” seen, but there were open elements.
+41: Unclosed element “i”.
+46: End of file seen and there were open elements.
+35: Unclosed element “foreignObject”.
+20: Unclosed element “svg”.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg foreignObject>
+| <p>
+| <i>
+| <i>
+| "a"
+
+#data
+<!DOCTYPE html><table><tr><td><svg><foreignObject><p><i></p>a
+#errors
+56: End tag “p” seen, but there were open elements.
+52: Unclosed element “i”.
+57: End of file seen and there were open elements.
+46: Unclosed element “foreignObject”.
+31: Unclosed element “svg”.
+22: Unclosed element “table”.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <svg svg>
+| <svg foreignObject>
+| <p>
+| <i>
+| <i>
+| "a"
+
+#data
+<!DOCTYPE html><math><mtext><p><i></p>a
+#errors
+38: End tag “p” seen, but there were open elements.
+34: Unclosed element “i”.
+39: End of file in a foreign namespace context.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mtext>
+| <p>
+| <i>
+| <i>
+| "a"
+
+#data
+<!DOCTYPE html><table><tr><td><math><mtext><p><i></p>a
+#errors
+53: End tag “p” seen, but there were open elements.
+49: Unclosed element “i”.
+54: End of file in a foreign namespace context.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <math math>
+| <math mtext>
+| <p>
+| <i>
+| <i>
+| "a"
+
+#data
+<!DOCTYPE html><body><div><!/div>a
+#errors
+29: Bogus comment.
+34: End of file seen and there were open elements.
+26: Unclosed element “div”.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <div>
+| <!-- /div -->
+| "a"
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests3.dat b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests3.dat
new file mode 100644
index 000000000..38dc501be
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests3.dat
@@ -0,0 +1,305 @@
+#data
+<head></head><style></style>
+#errors
+Line: 1 Col: 6 Unexpected start tag (head). Expected DOCTYPE.
+Line: 1 Col: 20 Unexpected start tag (style) that can be in head. Moved.
+#document
+| <html>
+| <head>
+| <style>
+| <body>
+
+#data
+<head></head><script></script>
+#errors
+Line: 1 Col: 6 Unexpected start tag (head). Expected DOCTYPE.
+Line: 1 Col: 21 Unexpected start tag (script) that can be in head. Moved.
+#document
+| <html>
+| <head>
+| <script>
+| <body>
+
+#data
+<head></head><!-- --><style></style><!-- --><script></script>
+#errors
+Line: 1 Col: 6 Unexpected start tag (head). Expected DOCTYPE.
+Line: 1 Col: 28 Unexpected start tag (style) that can be in head. Moved.
+#document
+| <html>
+| <head>
+| <style>
+| <script>
+| <!-- -->
+| <!-- -->
+| <body>
+
+#data
+<head></head><!-- -->x<style></style><!-- --><script></script>
+#errors
+Line: 1 Col: 6 Unexpected start tag (head). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <!-- -->
+| <body>
+| "x"
+| <style>
+| <!-- -->
+| <script>
+
+#data
+<!DOCTYPE html><html><head></head><body><pre>
+</pre></body></html>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <pre>
+
+#data
+<!DOCTYPE html><html><head></head><body><pre>
+foo</pre></body></html>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <pre>
+| "foo"
+
+#data
+<!DOCTYPE html><html><head></head><body><pre>
+
+foo</pre></body></html>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <pre>
+| "
+foo"
+
+#data
+<!DOCTYPE html><html><head></head><body><pre>
+foo
+</pre></body></html>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <pre>
+| "foo
+"
+
+#data
+<!DOCTYPE html><html><head></head><body><pre>x</pre><span>
+</span></body></html>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <pre>
+| "x"
+| <span>
+| "
+"
+
+#data
+<!DOCTYPE html><html><head></head><body><pre>x
+y</pre></body></html>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <pre>
+| "x
+y"
+
+#data
+<!DOCTYPE html><html><head></head><body><pre>x<div>
+y</pre></body></html>
+#errors
+Line: 2 Col: 7 End tag (pre) seen too early. Expected other end tag.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <pre>
+| "x"
+| <div>
+| "
+y"
+
+#data
+<!DOCTYPE html><pre>&#x0a;&#x0a;A</pre>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <pre>
+| "
+A"
+
+#data
+<!DOCTYPE html><HTML><META><HEAD></HEAD></HTML>
+#errors
+Line: 1 Col: 33 Unexpected start tag head in existing head. Ignored.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <meta>
+| <body>
+
+#data
+<!DOCTYPE html><HTML><HEAD><head></HEAD></HTML>
+#errors
+Line: 1 Col: 33 Unexpected start tag head in existing head. Ignored.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+
+#data
+<textarea>foo<span>bar</span><i>baz
+#errors
+Line: 1 Col: 10 Unexpected start tag (textarea). Expected DOCTYPE.
+Line: 1 Col: 35 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <textarea>
+| "foo<span>bar</span><i>baz"
+
+#data
+<title>foo<span>bar</em><i>baz
+#errors
+Line: 1 Col: 7 Unexpected start tag (title). Expected DOCTYPE.
+Line: 1 Col: 30 Unexpected end of file. Expected end tag (title).
+#document
+| <html>
+| <head>
+| <title>
+| "foo<span>bar</em><i>baz"
+| <body>
+
+#data
+<!DOCTYPE html><textarea>
+</textarea>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <textarea>
+
+#data
+<!DOCTYPE html><textarea>
+foo</textarea>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <textarea>
+| "foo"
+
+#data
+<!DOCTYPE html><textarea>
+
+foo</textarea>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <textarea>
+| "
+foo"
+
+#data
+<!DOCTYPE html><html><head></head><body><ul><li><div><p><li></ul></body></html>
+#errors
+Line: 1 Col: 60 Missing end tag (div, li).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <ul>
+| <li>
+| <div>
+| <p>
+| <li>
+
+#data
+<!doctype html><nobr><nobr><nobr>
+#errors
+Line: 1 Col: 27 Unexpected start tag (nobr) implies end tag (nobr).
+Line: 1 Col: 33 Unexpected start tag (nobr) implies end tag (nobr).
+Line: 1 Col: 33 Expected closing tag. Unexpected end of file.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <nobr>
+| <nobr>
+| <nobr>
+
+#data
+<!doctype html><nobr><nobr></nobr><nobr>
+#errors
+Line: 1 Col: 27 Unexpected start tag (nobr) implies end tag (nobr).
+Line: 1 Col: 40 Expected closing tag. Unexpected end of file.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <nobr>
+| <nobr>
+| <nobr>
+
+#data
+<!doctype html><html><body><p><table></table></body></html>
+#errors
+Not known
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <table>
+
+#data
+<p><table></table>
+#errors
+Not known
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <table>
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests4.dat b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests4.dat
new file mode 100644
index 000000000..3c506326d
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests4.dat
@@ -0,0 +1,59 @@
+#data
+direct div content
+#errors
+#document-fragment
+div
+#document
+| "direct div content"
+
+#data
+direct textarea content
+#errors
+#document-fragment
+textarea
+#document
+| "direct textarea content"
+
+#data
+textarea content with <em>pseudo</em> <foo>markup
+#errors
+#document-fragment
+textarea
+#document
+| "textarea content with <em>pseudo</em> <foo>markup"
+
+#data
+this is &#x0043;DATA inside a <style> element
+#errors
+#document-fragment
+style
+#document
+| "this is &#x0043;DATA inside a <style> element"
+
+#data
+</plaintext>
+#errors
+#document-fragment
+plaintext
+#document
+| "</plaintext>"
+
+#data
+setting html's innerHTML
+#errors
+Line: 1 Col: 24 Unexpected EOF in inner html mode.
+#document-fragment
+html
+#document
+| <head>
+| <body>
+| "setting html's innerHTML"
+
+#data
+<title>setting head's innerHTML</title>
+#errors
+#document-fragment
+head
+#document
+| <title>
+| "setting head's innerHTML"
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests5.dat b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests5.dat
new file mode 100644
index 000000000..d7b5128a4
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests5.dat
@@ -0,0 +1,191 @@
+#data
+<style> <!-- </style>x
+#errors
+Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE.
+Line: 1 Col: 22 Unexpected end of file. Expected end tag (style).
+#document
+| <html>
+| <head>
+| <style>
+| " <!-- "
+| <body>
+| "x"
+
+#data
+<style> <!-- </style> --> </style>x
+#errors
+Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <style>
+| " <!-- "
+| " "
+| <body>
+| "--> x"
+
+#data
+<style> <!--> </style>x
+#errors
+Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <style>
+| " <!--> "
+| <body>
+| "x"
+
+#data
+<style> <!---> </style>x
+#errors
+Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <style>
+| " <!---> "
+| <body>
+| "x"
+
+#data
+<iframe> <!---> </iframe>x
+#errors
+Line: 1 Col: 8 Unexpected start tag (iframe). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <body>
+| <iframe>
+| " <!---> "
+| "x"
+
+#data
+<iframe> <!--- </iframe>->x</iframe> --> </iframe>x
+#errors
+Line: 1 Col: 8 Unexpected start tag (iframe). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <body>
+| <iframe>
+| " <!--- "
+| "->x --> x"
+
+#data
+<script> <!-- </script> --> </script>x
+#errors
+Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <script>
+| " <!-- "
+| " "
+| <body>
+| "--> x"
+
+#data
+<title> <!-- </title> --> </title>x
+#errors
+Line: 1 Col: 7 Unexpected start tag (title). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <title>
+| " <!-- "
+| " "
+| <body>
+| "--> x"
+
+#data
+<textarea> <!--- </textarea>->x</textarea> --> </textarea>x
+#errors
+Line: 1 Col: 10 Unexpected start tag (textarea). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <body>
+| <textarea>
+| " <!--- "
+| "->x --> x"
+
+#data
+<style> <!</-- </style>x
+#errors
+Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <style>
+| " <!</-- "
+| <body>
+| "x"
+
+#data
+<p><xmp></xmp>
+#errors
+XXX: Unknown
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <xmp>
+
+#data
+<xmp> <!-- > --> </xmp>
+#errors
+Line: 1 Col: 5 Unexpected start tag (xmp). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <body>
+| <xmp>
+| " <!-- > --> "
+
+#data
+<title>&amp;</title>
+#errors
+Line: 1 Col: 7 Unexpected start tag (title). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <title>
+| "&"
+| <body>
+
+#data
+<title><!--&amp;--></title>
+#errors
+Line: 1 Col: 7 Unexpected start tag (title). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <title>
+| "<!--&-->"
+| <body>
+
+#data
+<title><!--</title>
+#errors
+Line: 1 Col: 7 Unexpected start tag (title). Expected DOCTYPE.
+Line: 1 Col: 19 Unexpected end of file. Expected end tag (title).
+#document
+| <html>
+| <head>
+| <title>
+| "<!--"
+| <body>
+
+#data
+<noscript><!--</noscript>--></noscript>
+#errors
+Line: 1 Col: 10 Unexpected start tag (noscript). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <noscript>
+| "<!--"
+| <body>
+| "-->"
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests6.dat b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests6.dat
new file mode 100644
index 000000000..f28ece4fb
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests6.dat
@@ -0,0 +1,663 @@
+#data
+<!doctype html></head> <head>
+#errors
+Line: 1 Col: 29 Unexpected start tag head. Ignored.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| " "
+| <body>
+
+#data
+<!doctype html><form><div></form><div>
+#errors
+33: End tag "form" seen but there were unclosed elements.
+38: End of file seen and there were open elements.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <form>
+| <div>
+| <div>
+
+#data
+<!doctype html><title>&amp;</title>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <title>
+| "&"
+| <body>
+
+#data
+<!doctype html><title><!--&amp;--></title>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <title>
+| "<!--&-->"
+| <body>
+
+#data
+<!doctype>
+#errors
+Line: 1 Col: 9 No space after literal string 'DOCTYPE'.
+Line: 1 Col: 10 Unexpected > character. Expected DOCTYPE name.
+Line: 1 Col: 10 Erroneous DOCTYPE.
+#document
+| <!DOCTYPE >
+| <html>
+| <head>
+| <body>
+
+#data
+<!---x
+#errors
+Line: 1 Col: 6 Unexpected end of file in comment.
+Line: 1 Col: 6 Unexpected End of file. Expected DOCTYPE.
+#document
+| <!-- -x -->
+| <html>
+| <head>
+| <body>
+
+#data
+<body>
+<div>
+#errors
+Line: 1 Col: 6 Unexpected start tag (body).
+Line: 2 Col: 5 Expected closing tag. Unexpected end of file.
+#document-fragment
+div
+#document
+| "
+"
+| <div>
+
+#data
+<frameset></frameset>
+foo
+#errors
+Line: 1 Col: 10 Unexpected start tag (frameset). Expected DOCTYPE.
+Line: 2 Col: 3 Unexpected non-space characters in the after frameset phase. Ignored.
+#document
+| <html>
+| <head>
+| <frameset>
+| "
+"
+
+#data
+<frameset></frameset>
+<noframes>
+#errors
+Line: 1 Col: 10 Unexpected start tag (frameset). Expected DOCTYPE.
+Line: 2 Col: 10 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <frameset>
+| "
+"
+| <noframes>
+
+#data
+<frameset></frameset>
+<div>
+#errors
+Line: 1 Col: 10 Unexpected start tag (frameset). Expected DOCTYPE.
+Line: 2 Col: 5 Unexpected start tag (div) in the after frameset phase. Ignored.
+#document
+| <html>
+| <head>
+| <frameset>
+| "
+"
+
+#data
+<frameset></frameset>
+</html>
+#errors
+Line: 1 Col: 10 Unexpected start tag (frameset). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <frameset>
+| "
+"
+
+#data
+<frameset></frameset>
+</div>
+#errors
+Line: 1 Col: 10 Unexpected start tag (frameset). Expected DOCTYPE.
+Line: 2 Col: 6 Unexpected end tag (div) in the after frameset phase. Ignored.
+#document
+| <html>
+| <head>
+| <frameset>
+| "
+"
+
+#data
+<form><form>
+#errors
+Line: 1 Col: 6 Unexpected start tag (form). Expected DOCTYPE.
+Line: 1 Col: 12 Unexpected start tag (form).
+Line: 1 Col: 12 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <form>
+
+#data
+<button><button>
+#errors
+Line: 1 Col: 8 Unexpected start tag (button). Expected DOCTYPE.
+Line: 1 Col: 16 Unexpected start tag (button) implies end tag (button).
+Line: 1 Col: 16 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <button>
+| <button>
+
+#data
+<table><tr><td></th>
+#errors
+Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE.
+Line: 1 Col: 20 Unexpected end tag (th). Ignored.
+Line: 1 Col: 20 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+
+#data
+<table><caption><td>
+#errors
+Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE.
+Line: 1 Col: 20 Unexpected end tag (td). Ignored.
+Line: 1 Col: 20 Unexpected table cell start tag (td) in the table body phase.
+Line: 1 Col: 20 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+| <tbody>
+| <tr>
+| <td>
+
+#data
+<table><caption><div>
+#errors
+Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE.
+Line: 1 Col: 21 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+| <div>
+
+#data
+</caption><div>
+#errors
+Line: 1 Col: 10 Unexpected end tag (caption). Ignored.
+Line: 1 Col: 15 Expected closing tag. Unexpected end of file.
+#document-fragment
+caption
+#document
+| <div>
+
+#data
+<table><caption><div></caption>
+#errors
+Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE.
+Line: 1 Col: 31 Unexpected end tag (caption). Missing end tag (div).
+Line: 1 Col: 31 Unexpected end of file. Expected table content.
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+| <div>
+
+#data
+<table><caption></table>
+#errors
+Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE.
+Line: 1 Col: 24 Unexpected end table tag in caption. Generates implied end caption.
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+
+#data
+</table><div>
+#errors
+Line: 1 Col: 8 Unexpected end table tag in caption. Generates implied end caption.
+Line: 1 Col: 8 Unexpected end tag (caption). Ignored.
+Line: 1 Col: 13 Expected closing tag. Unexpected end of file.
+#document-fragment
+caption
+#document
+| <div>
+
+#data
+<table><caption></body></col></colgroup></html></tbody></td></tfoot></th></thead></tr>
+#errors
+Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE.
+Line: 1 Col: 23 Unexpected end tag (body). Ignored.
+Line: 1 Col: 29 Unexpected end tag (col). Ignored.
+Line: 1 Col: 40 Unexpected end tag (colgroup). Ignored.
+Line: 1 Col: 47 Unexpected end tag (html). Ignored.
+Line: 1 Col: 55 Unexpected end tag (tbody). Ignored.
+Line: 1 Col: 60 Unexpected end tag (td). Ignored.
+Line: 1 Col: 68 Unexpected end tag (tfoot). Ignored.
+Line: 1 Col: 73 Unexpected end tag (th). Ignored.
+Line: 1 Col: 81 Unexpected end tag (thead). Ignored.
+Line: 1 Col: 86 Unexpected end tag (tr). Ignored.
+Line: 1 Col: 86 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+
+#data
+<table><caption><div></div>
+#errors
+Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE.
+Line: 1 Col: 27 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+| <div>
+
+#data
+<table><tr><td></body></caption></col></colgroup></html>
+#errors
+Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE.
+Line: 1 Col: 22 Unexpected end tag (body). Ignored.
+Line: 1 Col: 32 Unexpected end tag (caption). Ignored.
+Line: 1 Col: 38 Unexpected end tag (col). Ignored.
+Line: 1 Col: 49 Unexpected end tag (colgroup). Ignored.
+Line: 1 Col: 56 Unexpected end tag (html). Ignored.
+Line: 1 Col: 56 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+
+#data
+</table></tbody></tfoot></thead></tr><div>
+#errors
+Line: 1 Col: 8 Unexpected end tag (table). Ignored.
+Line: 1 Col: 16 Unexpected end tag (tbody). Ignored.
+Line: 1 Col: 24 Unexpected end tag (tfoot). Ignored.
+Line: 1 Col: 32 Unexpected end tag (thead). Ignored.
+Line: 1 Col: 37 Unexpected end tag (tr). Ignored.
+Line: 1 Col: 42 Expected closing tag. Unexpected end of file.
+#document-fragment
+td
+#document
+| <div>
+
+#data
+<table><colgroup>foo
+#errors
+Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE.
+Line: 1 Col: 20 Unexpected non-space characters in table context caused voodoo mode.
+Line: 1 Col: 20 Unexpected end of file. Expected table content.
+#document
+| <html>
+| <head>
+| <body>
+| "foo"
+| <table>
+| <colgroup>
+
+#data
+foo<col>
+#errors
+Line: 1 Col: 3 Unexpected end tag (colgroup). Ignored.
+#document-fragment
+colgroup
+#document
+| <col>
+
+#data
+<table><colgroup></col>
+#errors
+Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE.
+Line: 1 Col: 23 This element (col) has no end tag.
+Line: 1 Col: 23 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <colgroup>
+
+#data
+<frameset><div>
+#errors
+Line: 1 Col: 10 Unexpected start tag (frameset). Expected DOCTYPE.
+Line: 1 Col: 15 Unexpected start tag token (div) in the frameset phase. Ignored.
+Line: 1 Col: 15 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <frameset>
+
+#data
+</frameset><frame>
+#errors
+Line: 1 Col: 11 Unexpected end tag token (frameset) in the frameset phase (innerHTML).
+#document-fragment
+frameset
+#document
+| <frame>
+
+#data
+<frameset></div>
+#errors
+Line: 1 Col: 10 Unexpected start tag (frameset). Expected DOCTYPE.
+Line: 1 Col: 16 Unexpected end tag token (div) in the frameset phase. Ignored.
+Line: 1 Col: 16 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <frameset>
+
+#data
+</body><div>
+#errors
+Line: 1 Col: 7 Unexpected end tag (body). Ignored.
+Line: 1 Col: 12 Expected closing tag. Unexpected end of file.
+#document-fragment
+body
+#document
+| <div>
+
+#data
+<table><tr><div>
+#errors
+Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE.
+Line: 1 Col: 16 Unexpected start tag (div) in table context caused voodoo mode.
+Line: 1 Col: 16 Unexpected end of file. Expected table content.
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <table>
+| <tbody>
+| <tr>
+
+#data
+</tr><td>
+#errors
+Line: 1 Col: 5 Unexpected end tag (tr). Ignored.
+#document-fragment
+tr
+#document
+| <td>
+
+#data
+</tbody></tfoot></thead><td>
+#errors
+Line: 1 Col: 8 Unexpected end tag (tbody). Ignored.
+Line: 1 Col: 16 Unexpected end tag (tfoot). Ignored.
+Line: 1 Col: 24 Unexpected end tag (thead). Ignored.
+#document-fragment
+tr
+#document
+| <td>
+
+#data
+<table><tr><div><td>
+#errors
+Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE.
+Line: 1 Col: 16 Unexpected start tag (div) in table context caused voodoo mode.
+Line: 1 Col: 20 Unexpected implied end tag (div) in the table row phase.
+Line: 1 Col: 20 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+
+#data
+<caption><col><colgroup><tbody><tfoot><thead><tr>
+#errors
+Line: 1 Col: 9 Unexpected start tag (caption).
+Line: 1 Col: 14 Unexpected start tag (col).
+Line: 1 Col: 24 Unexpected start tag (colgroup).
+Line: 1 Col: 31 Unexpected start tag (tbody).
+Line: 1 Col: 38 Unexpected start tag (tfoot).
+Line: 1 Col: 45 Unexpected start tag (thead).
+Line: 1 Col: 49 Unexpected end of file. Expected table content.
+#document-fragment
+tbody
+#document
+| <tr>
+
+#data
+<table><tbody></thead>
+#errors
+Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE.
+Line: 1 Col: 22 Unexpected end tag (thead) in the table body phase. Ignored.
+Line: 1 Col: 22 Unexpected end of file. Expected table content.
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+
+#data
+</table><tr>
+#errors
+Line: 1 Col: 8 Unexpected end tag (table). Ignored.
+Line: 1 Col: 12 Unexpected end of file. Expected table content.
+#document-fragment
+tbody
+#document
+| <tr>
+
+#data
+<table><tbody></body></caption></col></colgroup></html></td></th></tr>
+#errors
+Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE.
+Line: 1 Col: 21 Unexpected end tag (body) in the table body phase. Ignored.
+Line: 1 Col: 31 Unexpected end tag (caption) in the table body phase. Ignored.
+Line: 1 Col: 37 Unexpected end tag (col) in the table body phase. Ignored.
+Line: 1 Col: 48 Unexpected end tag (colgroup) in the table body phase. Ignored.
+Line: 1 Col: 55 Unexpected end tag (html) in the table body phase. Ignored.
+Line: 1 Col: 60 Unexpected end tag (td) in the table body phase. Ignored.
+Line: 1 Col: 65 Unexpected end tag (th) in the table body phase. Ignored.
+Line: 1 Col: 70 Unexpected end tag (tr) in the table body phase. Ignored.
+Line: 1 Col: 70 Unexpected end of file. Expected table content.
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+
+#data
+<table><tbody></div>
+#errors
+Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE.
+Line: 1 Col: 20 Unexpected end tag (div) in table context caused voodoo mode.
+Line: 1 Col: 20 End tag (div) seen too early. Expected other end tag.
+Line: 1 Col: 20 Unexpected end of file. Expected table content.
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+
+#data
+<table><table>
+#errors
+Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE.
+Line: 1 Col: 14 Unexpected start tag (table) implies end tag (table).
+Line: 1 Col: 14 Unexpected end of file. Expected table content.
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <table>
+
+#data
+<table></body></caption></col></colgroup></html></tbody></td></tfoot></th></thead></tr>
+#errors
+Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE.
+Line: 1 Col: 14 Unexpected end tag (body). Ignored.
+Line: 1 Col: 24 Unexpected end tag (caption). Ignored.
+Line: 1 Col: 30 Unexpected end tag (col). Ignored.
+Line: 1 Col: 41 Unexpected end tag (colgroup). Ignored.
+Line: 1 Col: 48 Unexpected end tag (html). Ignored.
+Line: 1 Col: 56 Unexpected end tag (tbody). Ignored.
+Line: 1 Col: 61 Unexpected end tag (td). Ignored.
+Line: 1 Col: 69 Unexpected end tag (tfoot). Ignored.
+Line: 1 Col: 74 Unexpected end tag (th). Ignored.
+Line: 1 Col: 82 Unexpected end tag (thead). Ignored.
+Line: 1 Col: 87 Unexpected end tag (tr). Ignored.
+Line: 1 Col: 87 Unexpected end of file. Expected table content.
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+
+#data
+</table><tr>
+#errors
+Line: 1 Col: 8 Unexpected end tag (table). Ignored.
+Line: 1 Col: 12 Unexpected end of file. Expected table content.
+#document-fragment
+table
+#document
+| <tbody>
+| <tr>
+
+#data
+<body></body></html>
+#errors
+Line: 1 Col: 20 Unexpected html end tag in inner html mode.
+Line: 1 Col: 20 Unexpected EOF in inner html mode.
+#document-fragment
+html
+#document
+| <head>
+| <body>
+
+#data
+<html><frameset></frameset></html>
+#errors
+Line: 1 Col: 6 Unexpected start tag (html). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <frameset>
+| " "
+
+#data
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"><html></html>
+#errors
+Line: 1 Col: 50 Erroneous DOCTYPE.
+Line: 1 Col: 63 Unexpected end tag (html) after the (implied) root element.
+#document
+| <!DOCTYPE html "-//W3C//DTD HTML 4.01//EN" "">
+| <html>
+| <head>
+| <body>
+
+#data
+<param><frameset></frameset>
+#errors
+Line: 1 Col: 7 Unexpected start tag (param). Expected DOCTYPE.
+Line: 1 Col: 17 Unexpected start tag (frameset).
+#document
+| <html>
+| <head>
+| <frameset>
+
+#data
+<source><frameset></frameset>
+#errors
+Line: 1 Col: 7 Unexpected start tag (source). Expected DOCTYPE.
+Line: 1 Col: 17 Unexpected start tag (frameset).
+#document
+| <html>
+| <head>
+| <frameset>
+
+#data
+<track><frameset></frameset>
+#errors
+Line: 1 Col: 7 Unexpected start tag (track). Expected DOCTYPE.
+Line: 1 Col: 17 Unexpected start tag (frameset).
+#document
+| <html>
+| <head>
+| <frameset>
+
+#data
+</html><frameset></frameset>
+#errors
+7: End tag seen without seeing a doctype first. Expected “<!DOCTYPE html>”.
+17: Stray “frameset” start tag.
+17: “frameset” start tag seen.
+#document
+| <html>
+| <head>
+| <frameset>
+
+#data
+</body><frameset></frameset>
+#errors
+7: End tag seen without seeing a doctype first. Expected “<!DOCTYPE html>”.
+17: Stray “frameset” start tag.
+17: “frameset” start tag seen.
+#document
+| <html>
+| <head>
+| <frameset>
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests7.dat b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests7.dat
new file mode 100644
index 000000000..f5193c660
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests7.dat
@@ -0,0 +1,390 @@
+#data
+<!doctype html><body><title>X</title>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <title>
+| "X"
+
+#data
+<!doctype html><table><title>X</title></table>
+#errors
+Line: 1 Col: 29 Unexpected start tag (title) in table context caused voodoo mode.
+Line: 1 Col: 38 Unexpected end tag (title) in table context caused voodoo mode.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <title>
+| "X"
+| <table>
+
+#data
+<!doctype html><head></head><title>X</title>
+#errors
+Line: 1 Col: 35 Unexpected start tag (title) that can be in head. Moved.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <title>
+| "X"
+| <body>
+
+#data
+<!doctype html></head><title>X</title>
+#errors
+Line: 1 Col: 29 Unexpected start tag (title) that can be in head. Moved.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <title>
+| "X"
+| <body>
+
+#data
+<!doctype html><table><meta></table>
+#errors
+Line: 1 Col: 28 Unexpected start tag (meta) in table context caused voodoo mode.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <meta>
+| <table>
+
+#data
+<!doctype html><table>X<tr><td><table> <meta></table></table>
+#errors
+Line: 1 Col: 23 Unexpected non-space characters in table context caused voodoo mode.
+Line: 1 Col: 45 Unexpected start tag (meta) in table context caused voodoo mode.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "X"
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <meta>
+| <table>
+| " "
+
+#data
+<!doctype html><html> <head>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+
+#data
+<!doctype html> <head>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+
+#data
+<!doctype html><table><style> <tr>x </style> </table>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <style>
+| " <tr>x "
+| " "
+
+#data
+<!doctype html><table><TBODY><script> <tr>x </script> </table>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <script>
+| " <tr>x "
+| " "
+
+#data
+<!doctype html><p><applet><p>X</p></applet>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <applet>
+| <p>
+| "X"
+
+#data
+<!doctype html><listing>
+X</listing>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <listing>
+| "X"
+
+#data
+<!doctype html><select><input>X
+#errors
+Line: 1 Col: 30 Unexpected input start tag in the select phase.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| <input>
+| "X"
+
+#data
+<!doctype html><select><select>X
+#errors
+Line: 1 Col: 31 Unexpected select start tag in the select phase treated as select end tag.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| "X"
+
+#data
+<!doctype html><table><input type=hidDEN></table>
+#errors
+Line: 1 Col: 41 Unexpected input with type hidden in table context.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <input>
+| type="hidDEN"
+
+#data
+<!doctype html><table>X<input type=hidDEN></table>
+#errors
+Line: 1 Col: 23 Unexpected non-space characters in table context caused voodoo mode.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "X"
+| <table>
+| <input>
+| type="hidDEN"
+
+#data
+<!doctype html><table> <input type=hidDEN></table>
+#errors
+Line: 1 Col: 43 Unexpected input with type hidden in table context.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| " "
+| <input>
+| type="hidDEN"
+
+#data
+<!doctype html><table> <input type='hidDEN'></table>
+#errors
+Line: 1 Col: 45 Unexpected input with type hidden in table context.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| " "
+| <input>
+| type="hidDEN"
+
+#data
+<!doctype html><table><input type=" hidden"><input type=hidDEN></table>
+#errors
+Line: 1 Col: 44 Unexpected start tag (input) in table context caused voodoo mode.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <input>
+| type=" hidden"
+| <table>
+| <input>
+| type="hidDEN"
+
+#data
+<!doctype html><table><select>X<tr>
+#errors
+Line: 1 Col: 30 Unexpected start tag (select) in table context caused voodoo mode.
+Line: 1 Col: 35 Unexpected table element start tag (trs) in the select in table phase.
+Line: 1 Col: 35 Unexpected end of file. Expected table content.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| "X"
+| <table>
+| <tbody>
+| <tr>
+
+#data
+<!doctype html><select>X</select>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| "X"
+
+#data
+<!DOCTYPE hTmL><html></html>
+#errors
+Line: 1 Col: 28 Unexpected end tag (html) after the (implied) root element.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+
+#data
+<!DOCTYPE HTML><html></html>
+#errors
+Line: 1 Col: 28 Unexpected end tag (html) after the (implied) root element.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+
+#data
+<body>X</body></body>
+#errors
+Line: 1 Col: 21 Unexpected end tag token (body) in the after body phase.
+Line: 1 Col: 21 Unexpected EOF in inner html mode.
+#document-fragment
+html
+#document
+| <head>
+| <body>
+| "X"
+
+#data
+<div><p>a</x> b
+#errors
+Line: 1 Col: 5 Unexpected start tag (div). Expected DOCTYPE.
+Line: 1 Col: 13 Unexpected end tag (x). Ignored.
+Line: 1 Col: 15 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <p>
+| "a b"
+
+#data
+<table><tr><td><code></code> </table>
+#errors
+Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <code>
+| " "
+
+#data
+<table><b><tr><td>aaa</td></tr>bbb</table>ccc
+#errors
+XXX: Fix me
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| <b>
+| "bbb"
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| "aaa"
+| <b>
+| "ccc"
+
+#data
+A<table><tr> B</tr> B</table>
+#errors
+XXX: Fix me
+#document
+| <html>
+| <head>
+| <body>
+| "A B B"
+| <table>
+| <tbody>
+| <tr>
+
+#data
+A<table><tr> B</tr> </em>C</table>
+#errors
+XXX: Fix me
+#document
+| <html>
+| <head>
+| <body>
+| "A BC"
+| <table>
+| <tbody>
+| <tr>
+| " "
+
+#data
+<select><keygen>
+#errors
+Not known
+#document
+| <html>
+| <head>
+| <body>
+| <select>
+| <keygen>
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests8.dat b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests8.dat
new file mode 100644
index 000000000..90e6c919e
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests8.dat
@@ -0,0 +1,148 @@
+#data
+<div>
+<div></div>
+</span>x
+#errors
+Line: 1 Col: 5 Unexpected start tag (div). Expected DOCTYPE.
+Line: 3 Col: 7 Unexpected end tag (span). Ignored.
+Line: 3 Col: 8 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| "
+"
+| <div>
+| "
+x"
+
+#data
+<div>x<div></div>
+</span>x
+#errors
+Line: 1 Col: 5 Unexpected start tag (div). Expected DOCTYPE.
+Line: 2 Col: 7 Unexpected end tag (span). Ignored.
+Line: 2 Col: 8 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| "x"
+| <div>
+| "
+x"
+
+#data
+<div>x<div></div>x</span>x
+#errors
+Line: 1 Col: 5 Unexpected start tag (div). Expected DOCTYPE.
+Line: 1 Col: 25 Unexpected end tag (span). Ignored.
+Line: 1 Col: 26 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| "x"
+| <div>
+| "xx"
+
+#data
+<div>x<div></div>y</span>z
+#errors
+Line: 1 Col: 5 Unexpected start tag (div). Expected DOCTYPE.
+Line: 1 Col: 25 Unexpected end tag (span). Ignored.
+Line: 1 Col: 26 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| "x"
+| <div>
+| "yz"
+
+#data
+<table><div>x<div></div>x</span>x
+#errors
+Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE.
+Line: 1 Col: 12 Unexpected start tag (div) in table context caused voodoo mode.
+Line: 1 Col: 18 Unexpected start tag (div) in table context caused voodoo mode.
+Line: 1 Col: 24 Unexpected end tag (div) in table context caused voodoo mode.
+Line: 1 Col: 32 Unexpected end tag (span) in table context caused voodoo mode.
+Line: 1 Col: 32 Unexpected end tag (span). Ignored.
+Line: 1 Col: 33 Unexpected end of file. Expected table content.
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| "x"
+| <div>
+| "xx"
+| <table>
+
+#data
+x<table>x
+#errors
+Line: 1 Col: 1 Unexpected non-space characters. Expected DOCTYPE.
+Line: 1 Col: 9 Unexpected non-space characters in table context caused voodoo mode.
+Line: 1 Col: 9 Unexpected end of file. Expected table content.
+#document
+| <html>
+| <head>
+| <body>
+| "xx"
+| <table>
+
+#data
+x<table><table>x
+#errors
+Line: 1 Col: 1 Unexpected non-space characters. Expected DOCTYPE.
+Line: 1 Col: 15 Unexpected start tag (table) implies end tag (table).
+Line: 1 Col: 16 Unexpected non-space characters in table context caused voodoo mode.
+Line: 1 Col: 16 Unexpected end of file. Expected table content.
+#document
+| <html>
+| <head>
+| <body>
+| "x"
+| <table>
+| "x"
+| <table>
+
+#data
+<b>a<div></div><div></b>y
+#errors
+Line: 1 Col: 3 Unexpected start tag (b). Expected DOCTYPE.
+Line: 1 Col: 24 End tag (b) violates step 1, paragraph 3 of the adoption agency algorithm.
+Line: 1 Col: 25 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| "a"
+| <div>
+| <div>
+| <b>
+| "y"
+
+#data
+<a><div><p></a>
+#errors
+Line: 1 Col: 3 Unexpected start tag (a). Expected DOCTYPE.
+Line: 1 Col: 15 End tag (a) violates step 1, paragraph 3 of the adoption agency algorithm.
+Line: 1 Col: 15 End tag (a) violates step 1, paragraph 3 of the adoption agency algorithm.
+Line: 1 Col: 15 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| <div>
+| <a>
+| <p>
+| <a>
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests9.dat b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests9.dat
new file mode 100644
index 000000000..554e27aec
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests9.dat
@@ -0,0 +1,457 @@
+#data
+<!DOCTYPE html><math></math>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+
+#data
+<!DOCTYPE html><body><math></math>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+
+#data
+<!DOCTYPE html><math><mi>
+#errors
+25: End of file in a foreign namespace context.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mi>
+
+#data
+<!DOCTYPE html><math><annotation-xml><svg><u>
+#errors
+45: HTML start tag “u” in a foreign namespace context.
+45: End of file seen and there were open elements.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math annotation-xml>
+| <svg svg>
+| <u>
+
+#data
+<!DOCTYPE html><body><select><math></math></select>
+#errors
+Line: 1 Col: 35 Unexpected start tag token (math) in the select phase. Ignored.
+Line: 1 Col: 42 Unexpected end tag (math) in the select phase. Ignored.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+
+#data
+<!DOCTYPE html><body><select><option><math></math></option></select>
+#errors
+Line: 1 Col: 43 Unexpected start tag token (math) in the select phase. Ignored.
+Line: 1 Col: 50 Unexpected end tag (math) in the select phase. Ignored.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| <option>
+
+#data
+<!DOCTYPE html><body><table><math></math></table>
+#errors
+Line: 1 Col: 34 Unexpected start tag (math) in table context caused voodoo mode.
+Line: 1 Col: 41 Unexpected end tag (math) in table context caused voodoo mode.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+| <table>
+
+#data
+<!DOCTYPE html><body><table><math><mi>foo</mi></math></table>
+#errors
+Line: 1 Col: 34 Unexpected start tag (math) in table context caused voodoo mode.
+Line: 1 Col: 46 Unexpected end tag (mi) in table context caused voodoo mode.
+Line: 1 Col: 53 Unexpected end tag (math) in table context caused voodoo mode.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mi>
+| "foo"
+| <table>
+
+#data
+<!DOCTYPE html><body><table><math><mi>foo</mi><mi>bar</mi></math></table>
+#errors
+Line: 1 Col: 34 Unexpected start tag (math) in table context caused voodoo mode.
+Line: 1 Col: 46 Unexpected end tag (mi) in table context caused voodoo mode.
+Line: 1 Col: 58 Unexpected end tag (mi) in table context caused voodoo mode.
+Line: 1 Col: 65 Unexpected end tag (math) in table context caused voodoo mode.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mi>
+| "foo"
+| <math mi>
+| "bar"
+| <table>
+
+#data
+<!DOCTYPE html><body><table><tbody><math><mi>foo</mi><mi>bar</mi></math></tbody></table>
+#errors
+Line: 1 Col: 41 Unexpected start tag (math) in table context caused voodoo mode.
+Line: 1 Col: 53 Unexpected end tag (mi) in table context caused voodoo mode.
+Line: 1 Col: 65 Unexpected end tag (mi) in table context caused voodoo mode.
+Line: 1 Col: 72 Unexpected end tag (math) in table context caused voodoo mode.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mi>
+| "foo"
+| <math mi>
+| "bar"
+| <table>
+| <tbody>
+
+#data
+<!DOCTYPE html><body><table><tbody><tr><math><mi>foo</mi><mi>bar</mi></math></tr></tbody></table>
+#errors
+Line: 1 Col: 45 Unexpected start tag (math) in table context caused voodoo mode.
+Line: 1 Col: 57 Unexpected end tag (mi) in table context caused voodoo mode.
+Line: 1 Col: 69 Unexpected end tag (mi) in table context caused voodoo mode.
+Line: 1 Col: 76 Unexpected end tag (math) in table context caused voodoo mode.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mi>
+| "foo"
+| <math mi>
+| "bar"
+| <table>
+| <tbody>
+| <tr>
+
+#data
+<!DOCTYPE html><body><table><tbody><tr><td><math><mi>foo</mi><mi>bar</mi></math></td></tr></tbody></table>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <math math>
+| <math mi>
+| "foo"
+| <math mi>
+| "bar"
+
+#data
+<!DOCTYPE html><body><table><tbody><tr><td><math><mi>foo</mi><mi>bar</mi></math><p>baz</td></tr></tbody></table>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <math math>
+| <math mi>
+| "foo"
+| <math mi>
+| "bar"
+| <p>
+| "baz"
+
+#data
+<!DOCTYPE html><body><table><caption><math><mi>foo</mi><mi>bar</mi></math><p>baz</caption></table>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+| <math math>
+| <math mi>
+| "foo"
+| <math mi>
+| "bar"
+| <p>
+| "baz"
+
+#data
+<!DOCTYPE html><body><table><caption><math><mi>foo</mi><mi>bar</mi><p>baz</table><p>quux
+#errors
+Line: 1 Col: 70 HTML start tag "p" in a foreign namespace context.
+Line: 1 Col: 81 Unexpected end table tag in caption. Generates implied end caption.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+| <math math>
+| <math mi>
+| "foo"
+| <math mi>
+| "bar"
+| <p>
+| "baz"
+| <p>
+| "quux"
+
+#data
+<!DOCTYPE html><body><table><caption><math><mi>foo</mi><mi>bar</mi>baz</table><p>quux
+#errors
+Line: 1 Col: 78 Unexpected end table tag in caption. Generates implied end caption.
+Line: 1 Col: 78 Unexpected end tag (caption). Missing end tag (math).
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+| <math math>
+| <math mi>
+| "foo"
+| <math mi>
+| "bar"
+| "baz"
+| <p>
+| "quux"
+
+#data
+<!DOCTYPE html><body><table><colgroup><math><mi>foo</mi><mi>bar</mi><p>baz</table><p>quux
+#errors
+Line: 1 Col: 44 Unexpected start tag (math) in table context caused voodoo mode.
+Line: 1 Col: 56 Unexpected end tag (mi) in table context caused voodoo mode.
+Line: 1 Col: 68 Unexpected end tag (mi) in table context caused voodoo mode.
+Line: 1 Col: 71 HTML start tag "p" in a foreign namespace context.
+Line: 1 Col: 71 Unexpected start tag (p) in table context caused voodoo mode.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mi>
+| "foo"
+| <math mi>
+| "bar"
+| <p>
+| "baz"
+| <table>
+| <colgroup>
+| <p>
+| "quux"
+
+#data
+<!DOCTYPE html><body><table><tr><td><select><math><mi>foo</mi><mi>bar</mi><p>baz</table><p>quux
+#errors
+Line: 1 Col: 50 Unexpected start tag token (math) in the select phase. Ignored.
+Line: 1 Col: 54 Unexpected start tag token (mi) in the select phase. Ignored.
+Line: 1 Col: 62 Unexpected end tag (mi) in the select phase. Ignored.
+Line: 1 Col: 66 Unexpected start tag token (mi) in the select phase. Ignored.
+Line: 1 Col: 74 Unexpected end tag (mi) in the select phase. Ignored.
+Line: 1 Col: 77 Unexpected start tag token (p) in the select phase. Ignored.
+Line: 1 Col: 88 Unexpected table element end tag (tables) in the select in table phase.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <select>
+| "foobarbaz"
+| <p>
+| "quux"
+
+#data
+<!DOCTYPE html><body><table><select><math><mi>foo</mi><mi>bar</mi><p>baz</table><p>quux
+#errors
+Line: 1 Col: 36 Unexpected start tag (select) in table context caused voodoo mode.
+Line: 1 Col: 42 Unexpected start tag token (math) in the select phase. Ignored.
+Line: 1 Col: 46 Unexpected start tag token (mi) in the select phase. Ignored.
+Line: 1 Col: 54 Unexpected end tag (mi) in the select phase. Ignored.
+Line: 1 Col: 58 Unexpected start tag token (mi) in the select phase. Ignored.
+Line: 1 Col: 66 Unexpected end tag (mi) in the select phase. Ignored.
+Line: 1 Col: 69 Unexpected start tag token (p) in the select phase. Ignored.
+Line: 1 Col: 80 Unexpected table element end tag (tables) in the select in table phase.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| "foobarbaz"
+| <table>
+| <p>
+| "quux"
+
+#data
+<!DOCTYPE html><body></body></html><math><mi>foo</mi><mi>bar</mi><p>baz
+#errors
+Line: 1 Col: 41 Unexpected start tag (math).
+Line: 1 Col: 68 HTML start tag "p" in a foreign namespace context.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mi>
+| "foo"
+| <math mi>
+| "bar"
+| <p>
+| "baz"
+
+#data
+<!DOCTYPE html><body></body><math><mi>foo</mi><mi>bar</mi><p>baz
+#errors
+Line: 1 Col: 34 Unexpected start tag token (math) in the after body phase.
+Line: 1 Col: 61 HTML start tag "p" in a foreign namespace context.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mi>
+| "foo"
+| <math mi>
+| "bar"
+| <p>
+| "baz"
+
+#data
+<!DOCTYPE html><frameset><math><mi></mi><mi></mi><p><span>
+#errors
+Line: 1 Col: 31 Unexpected start tag token (math) in the frameset phase. Ignored.
+Line: 1 Col: 35 Unexpected start tag token (mi) in the frameset phase. Ignored.
+Line: 1 Col: 40 Unexpected end tag token (mi) in the frameset phase. Ignored.
+Line: 1 Col: 44 Unexpected start tag token (mi) in the frameset phase. Ignored.
+Line: 1 Col: 49 Unexpected end tag token (mi) in the frameset phase. Ignored.
+Line: 1 Col: 52 Unexpected start tag token (p) in the frameset phase. Ignored.
+Line: 1 Col: 58 Unexpected start tag token (span) in the frameset phase. Ignored.
+Line: 1 Col: 58 Expected closing tag. Unexpected end of file.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+
+#data
+<!DOCTYPE html><frameset></frameset><math><mi></mi><mi></mi><p><span>
+#errors
+Line: 1 Col: 42 Unexpected start tag (math) in the after frameset phase. Ignored.
+Line: 1 Col: 46 Unexpected start tag (mi) in the after frameset phase. Ignored.
+Line: 1 Col: 51 Unexpected end tag (mi) in the after frameset phase. Ignored.
+Line: 1 Col: 55 Unexpected start tag (mi) in the after frameset phase. Ignored.
+Line: 1 Col: 60 Unexpected end tag (mi) in the after frameset phase. Ignored.
+Line: 1 Col: 63 Unexpected start tag (p) in the after frameset phase. Ignored.
+Line: 1 Col: 69 Unexpected start tag (span) in the after frameset phase. Ignored.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+
+#data
+<!DOCTYPE html><body xlink:href=foo><math xlink:href=foo></math>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| xlink:href="foo"
+| <math math>
+| xlink href="foo"
+
+#data
+<!DOCTYPE html><body xlink:href=foo xml:lang=en><math><mi xml:lang=en xlink:href=foo></mi></math>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| xlink:href="foo"
+| xml:lang="en"
+| <math math>
+| <math mi>
+| xlink href="foo"
+| xml lang="en"
+
+#data
+<!DOCTYPE html><body xlink:href=foo xml:lang=en><math><mi xml:lang=en xlink:href=foo /></math>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| xlink:href="foo"
+| xml:lang="en"
+| <math math>
+| <math mi>
+| xlink href="foo"
+| xml lang="en"
+
+#data
+<!DOCTYPE html><body xlink:href=foo xml:lang=en><math><mi xml:lang=en xlink:href=foo />bar</math>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| xlink:href="foo"
+| xml:lang="en"
+| <math math>
+| <math mi>
+| xlink href="foo"
+| xml lang="en"
+| "bar"
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests_innerHTML_1.dat b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests_innerHTML_1.dat
new file mode 100644
index 000000000..6c78661e0
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tests_innerHTML_1.dat
@@ -0,0 +1,741 @@
+#data
+<body><span>
+#errors
+#document-fragment
+body
+#document
+| <span>
+
+#data
+<span><body>
+#errors
+#document-fragment
+body
+#document
+| <span>
+
+#data
+<span><body>
+#errors
+#document-fragment
+div
+#document
+| <span>
+
+#data
+<body><span>
+#errors
+#document-fragment
+html
+#document
+| <head>
+| <body>
+| <span>
+
+#data
+<frameset><span>
+#errors
+#document-fragment
+body
+#document
+| <span>
+
+#data
+<span><frameset>
+#errors
+#document-fragment
+body
+#document
+| <span>
+
+#data
+<span><frameset>
+#errors
+#document-fragment
+div
+#document
+| <span>
+
+#data
+<frameset><span>
+#errors
+#document-fragment
+html
+#document
+| <head>
+| <frameset>
+
+#data
+<table><tr>
+#errors
+#document-fragment
+table
+#document
+| <tbody>
+| <tr>
+
+#data
+</table><tr>
+#errors
+#document-fragment
+table
+#document
+| <tbody>
+| <tr>
+
+#data
+<a>
+#errors
+#document-fragment
+table
+#document
+| <a>
+
+#data
+<a>
+#errors
+#document-fragment
+table
+#document
+| <a>
+
+#data
+<a><caption>a
+#errors
+#document-fragment
+table
+#document
+| <a>
+| <caption>
+| "a"
+
+#data
+<a><colgroup><col>
+#errors
+#document-fragment
+table
+#document
+| <a>
+| <colgroup>
+| <col>
+
+#data
+<a><tbody><tr>
+#errors
+#document-fragment
+table
+#document
+| <a>
+| <tbody>
+| <tr>
+
+#data
+<a><tfoot><tr>
+#errors
+#document-fragment
+table
+#document
+| <a>
+| <tfoot>
+| <tr>
+
+#data
+<a><thead><tr>
+#errors
+#document-fragment
+table
+#document
+| <a>
+| <thead>
+| <tr>
+
+#data
+<a><tr>
+#errors
+#document-fragment
+table
+#document
+| <a>
+| <tbody>
+| <tr>
+
+#data
+<a><th>
+#errors
+#document-fragment
+table
+#document
+| <a>
+| <tbody>
+| <tr>
+| <th>
+
+#data
+<a><td>
+#errors
+#document-fragment
+table
+#document
+| <a>
+| <tbody>
+| <tr>
+| <td>
+
+#data
+<table></table><tbody>
+#errors
+#document-fragment
+caption
+#document
+| <table>
+
+#data
+</table><span>
+#errors
+#document-fragment
+caption
+#document
+| <span>
+
+#data
+<span></table>
+#errors
+#document-fragment
+caption
+#document
+| <span>
+
+#data
+</caption><span>
+#errors
+#document-fragment
+caption
+#document
+| <span>
+
+#data
+<span></caption><span>
+#errors
+#document-fragment
+caption
+#document
+| <span>
+| <span>
+
+#data
+<span><caption><span>
+#errors
+#document-fragment
+caption
+#document
+| <span>
+| <span>
+
+#data
+<span><col><span>
+#errors
+#document-fragment
+caption
+#document
+| <span>
+| <span>
+
+#data
+<span><colgroup><span>
+#errors
+#document-fragment
+caption
+#document
+| <span>
+| <span>
+
+#data
+<span><html><span>
+#errors
+#document-fragment
+caption
+#document
+| <span>
+| <span>
+
+#data
+<span><tbody><span>
+#errors
+#document-fragment
+caption
+#document
+| <span>
+| <span>
+
+#data
+<span><td><span>
+#errors
+#document-fragment
+caption
+#document
+| <span>
+| <span>
+
+#data
+<span><tfoot><span>
+#errors
+#document-fragment
+caption
+#document
+| <span>
+| <span>
+
+#data
+<span><thead><span>
+#errors
+#document-fragment
+caption
+#document
+| <span>
+| <span>
+
+#data
+<span><th><span>
+#errors
+#document-fragment
+caption
+#document
+| <span>
+| <span>
+
+#data
+<span><tr><span>
+#errors
+#document-fragment
+caption
+#document
+| <span>
+| <span>
+
+#data
+<span></table><span>
+#errors
+#document-fragment
+caption
+#document
+| <span>
+| <span>
+
+#data
+</colgroup><col>
+#errors
+#document-fragment
+colgroup
+#document
+| <col>
+
+#data
+<a><col>
+#errors
+#document-fragment
+colgroup
+#document
+| <col>
+
+#data
+<caption><a>
+#errors
+#document-fragment
+tbody
+#document
+| <a>
+
+#data
+<col><a>
+#errors
+#document-fragment
+tbody
+#document
+| <a>
+
+#data
+<colgroup><a>
+#errors
+#document-fragment
+tbody
+#document
+| <a>
+
+#data
+<tbody><a>
+#errors
+#document-fragment
+tbody
+#document
+| <a>
+
+#data
+<tfoot><a>
+#errors
+#document-fragment
+tbody
+#document
+| <a>
+
+#data
+<thead><a>
+#errors
+#document-fragment
+tbody
+#document
+| <a>
+
+#data
+</table><a>
+#errors
+#document-fragment
+tbody
+#document
+| <a>
+
+#data
+<a><tr>
+#errors
+#document-fragment
+tbody
+#document
+| <a>
+| <tr>
+
+#data
+<a><td>
+#errors
+#document-fragment
+tbody
+#document
+| <a>
+| <tr>
+| <td>
+
+#data
+<a><td>
+#errors
+#document-fragment
+tbody
+#document
+| <a>
+| <tr>
+| <td>
+
+#data
+<a><td>
+#errors
+#document-fragment
+tbody
+#document
+| <a>
+| <tr>
+| <td>
+
+#data
+<td><table><tbody><a><tr>
+#errors
+#document-fragment
+tbody
+#document
+| <tr>
+| <td>
+| <a>
+| <table>
+| <tbody>
+| <tr>
+
+#data
+</tr><td>
+#errors
+#document-fragment
+tr
+#document
+| <td>
+
+#data
+<td><table><a><tr></tr><tr>
+#errors
+#document-fragment
+tr
+#document
+| <td>
+| <a>
+| <table>
+| <tbody>
+| <tr>
+| <tr>
+
+#data
+<caption><td>
+#errors
+#document-fragment
+tr
+#document
+| <td>
+
+#data
+<col><td>
+#errors
+#document-fragment
+tr
+#document
+| <td>
+
+#data
+<colgroup><td>
+#errors
+#document-fragment
+tr
+#document
+| <td>
+
+#data
+<tbody><td>
+#errors
+#document-fragment
+tr
+#document
+| <td>
+
+#data
+<tfoot><td>
+#errors
+#document-fragment
+tr
+#document
+| <td>
+
+#data
+<thead><td>
+#errors
+#document-fragment
+tr
+#document
+| <td>
+
+#data
+<tr><td>
+#errors
+#document-fragment
+tr
+#document
+| <td>
+
+#data
+</table><td>
+#errors
+#document-fragment
+tr
+#document
+| <td>
+
+#data
+<td><table></table><td>
+#errors
+#document-fragment
+tr
+#document
+| <td>
+| <table>
+| <td>
+
+#data
+<td><table></table><td>
+#errors
+#document-fragment
+tr
+#document
+| <td>
+| <table>
+| <td>
+
+#data
+<caption><a>
+#errors
+#document-fragment
+td
+#document
+| <a>
+
+#data
+<col><a>
+#errors
+#document-fragment
+td
+#document
+| <a>
+
+#data
+<colgroup><a>
+#errors
+#document-fragment
+td
+#document
+| <a>
+
+#data
+<tbody><a>
+#errors
+#document-fragment
+td
+#document
+| <a>
+
+#data
+<tfoot><a>
+#errors
+#document-fragment
+td
+#document
+| <a>
+
+#data
+<th><a>
+#errors
+#document-fragment
+td
+#document
+| <a>
+
+#data
+<thead><a>
+#errors
+#document-fragment
+td
+#document
+| <a>
+
+#data
+<tr><a>
+#errors
+#document-fragment
+td
+#document
+| <a>
+
+#data
+</table><a>
+#errors
+#document-fragment
+td
+#document
+| <a>
+
+#data
+</tbody><a>
+#errors
+#document-fragment
+td
+#document
+| <a>
+
+#data
+</td><a>
+#errors
+#document-fragment
+td
+#document
+| <a>
+
+#data
+</tfoot><a>
+#errors
+#document-fragment
+td
+#document
+| <a>
+
+#data
+</thead><a>
+#errors
+#document-fragment
+td
+#document
+| <a>
+
+#data
+</th><a>
+#errors
+#document-fragment
+td
+#document
+| <a>
+
+#data
+</tr><a>
+#errors
+#document-fragment
+td
+#document
+| <a>
+
+#data
+<table><td><td>
+#errors
+#document-fragment
+td
+#document
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <td>
+
+#data
+</select><option>
+#errors
+#document-fragment
+select
+#document
+| <option>
+
+#data
+<input><option>
+#errors
+#document-fragment
+select
+#document
+| <option>
+
+#data
+<keygen><option>
+#errors
+#document-fragment
+select
+#document
+| <option>
+
+#data
+<textarea><option>
+#errors
+#document-fragment
+select
+#document
+| <option>
+
+#data
+</html><!--abc-->
+#errors
+#document-fragment
+html
+#document
+| <head>
+| <body>
+| <!-- abc -->
+
+#data
+</frameset><frame>
+#errors
+#document-fragment
+frameset
+#document
+| <frame>
+
+#data
+#errors
+#document-fragment
+html
+#document
+| <head>
+| <body>
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tricky01.dat b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tricky01.dat
new file mode 100644
index 000000000..084199244
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/tricky01.dat
@@ -0,0 +1,261 @@
+#data
+<b><p>Bold </b> Not bold</p>
+Also not bold.
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| <p>
+| <b>
+| "Bold "
+| " Not bold"
+| "
+Also not bold."
+
+#data
+<html>
+<font color=red><i>Italic and Red<p>Italic and Red </font> Just italic.</p> Italic only.</i> Plain
+<p>I should not be red. <font color=red>Red. <i>Italic and red.</p>
+<p>Italic and red. </i> Red.</font> I should not be red.</p>
+<b>Bold <i>Bold and italic</b> Only Italic </i> Plain
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <font>
+| color="red"
+| <i>
+| "Italic and Red"
+| <i>
+| <p>
+| <font>
+| color="red"
+| "Italic and Red "
+| " Just italic."
+| " Italic only."
+| " Plain
+"
+| <p>
+| "I should not be red. "
+| <font>
+| color="red"
+| "Red. "
+| <i>
+| "Italic and red."
+| <font>
+| color="red"
+| <i>
+| "
+"
+| <p>
+| <font>
+| color="red"
+| <i>
+| "Italic and red. "
+| " Red."
+| " I should not be red."
+| "
+"
+| <b>
+| "Bold "
+| <i>
+| "Bold and italic"
+| <i>
+| " Only Italic "
+| " Plain"
+
+#data
+<html><body>
+<p><font size="7">First paragraph.</p>
+<p>Second paragraph.</p></font>
+<b><p><i>Bold and Italic</b> Italic</p>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "
+"
+| <p>
+| <font>
+| size="7"
+| "First paragraph."
+| <font>
+| size="7"
+| "
+"
+| <p>
+| "Second paragraph."
+| "
+"
+| <b>
+| <p>
+| <b>
+| <i>
+| "Bold and Italic"
+| <i>
+| " Italic"
+
+#data
+<html>
+<dl>
+<dt><b>Boo
+<dd>Goo?
+</dl>
+</html>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <dl>
+| "
+"
+| <dt>
+| <b>
+| "Boo
+"
+| <dd>
+| <b>
+| "Goo?
+"
+| <b>
+| "
+"
+
+#data
+<html><body>
+<label><a><div>Hello<div>World</div></a></label>
+</body></html>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "
+"
+| <label>
+| <a>
+| <div>
+| <a>
+| "Hello"
+| <div>
+| "World"
+| "
+"
+
+#data
+<table><center> <font>a</center> <img> <tr><td> </td> </tr> </table>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <center>
+| " "
+| <font>
+| "a"
+| <font>
+| <img>
+| " "
+| <table>
+| " "
+| <tbody>
+| <tr>
+| <td>
+| " "
+| " "
+| " "
+
+#data
+<table><tr><p><a><p>You should see this text.
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <a>
+| <p>
+| <a>
+| "You should see this text."
+| <table>
+| <tbody>
+| <tr>
+
+#data
+<TABLE>
+<TR>
+<CENTER><CENTER><TD></TD></TR><TR>
+<FONT>
+<TABLE><tr></tr></TABLE>
+</P>
+<a></font><font></a>
+This page contains an insanely badly-nested tag sequence.
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <center>
+| <center>
+| <font>
+| "
+"
+| <table>
+| "
+"
+| <tbody>
+| <tr>
+| "
+"
+| <td>
+| <tr>
+| "
+"
+| <table>
+| <tbody>
+| <tr>
+| <font>
+| "
+"
+| <p>
+| "
+"
+| <a>
+| <a>
+| <font>
+| <font>
+| "
+This page contains an insanely badly-nested tag sequence."
+
+#data
+<html>
+<body>
+<b><nobr><div>This text is in a div inside a nobr</nobr>More text that should not be in the nobr, i.e., the
+nobr should have closed the div inside it implicitly. </b><pre>A pre tag outside everything else.</pre>
+</body>
+</html>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "
+"
+| <b>
+| <nobr>
+| <div>
+| <b>
+| <nobr>
+| "This text is in a div inside a nobr"
+| "More text that should not be in the nobr, i.e., the
+nobr should have closed the div inside it implicitly. "
+| <pre>
+| "A pre tag outside everything else."
+| "
+
+"
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/webkit01.dat b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/webkit01.dat
new file mode 100644
index 000000000..9d425e99d
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/webkit01.dat
@@ -0,0 +1,610 @@
+#data
+Test
+#errors
+Line: 1 Col: 4 Unexpected non-space characters. Expected DOCTYPE.
+#document
+| <html>
+| <head>
+| <body>
+| "Test"
+
+#data
+<div></div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+
+#data
+<div>Test</div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| "Test"
+
+#data
+<di
+#errors
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<div>Hello</div>
+<script>
+console.log("PASS");
+</script>
+<div>Bye</div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| "Hello"
+| "
+"
+| <script>
+| "
+console.log("PASS");
+"
+| "
+"
+| <div>
+| "Bye"
+
+#data
+<div foo="bar">Hello</div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| foo="bar"
+| "Hello"
+
+#data
+<div>Hello</div>
+<script>
+console.log("FOO<span>BAR</span>BAZ");
+</script>
+<div>Bye</div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| "Hello"
+| "
+"
+| <script>
+| "
+console.log("FOO<span>BAR</span>BAZ");
+"
+| "
+"
+| <div>
+| "Bye"
+
+#data
+<foo bar="baz"></foo><potato quack="duck"></potato>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <foo>
+| bar="baz"
+| <potato>
+| quack="duck"
+
+#data
+<foo bar="baz"><potato quack="duck"></potato></foo>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <foo>
+| bar="baz"
+| <potato>
+| quack="duck"
+
+#data
+<foo></foo bar="baz"><potato></potato quack="duck">
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <foo>
+| <potato>
+
+#data
+</ tttt>
+#errors
+#document
+| <!-- tttt -->
+| <html>
+| <head>
+| <body>
+
+#data
+<div FOO ><img><img></div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| foo=""
+| <img>
+| <img>
+
+#data
+<p>Test</p<p>Test2</p>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| "TestTest2"
+
+#data
+<rdar://problem/6869687>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <rdar:>
+| 6869687=""
+| problem=""
+
+#data
+<A>test< /A>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| "test< /A>"
+
+#data
+&lt;
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "<"
+
+#data
+<body foo='bar'><body foo='baz' yo='mama'>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| foo="bar"
+| yo="mama"
+
+#data
+<body></br foo="bar"></body>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <br>
+
+#data
+<bdy><br foo="bar"></body>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <bdy>
+| <br>
+| foo="bar"
+
+#data
+<body></body></br foo="bar">
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <br>
+
+#data
+<bdy></body><br foo="bar">
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <bdy>
+| <br>
+| foo="bar"
+
+#data
+<html><body></body></html><!-- Hi there -->
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <!-- Hi there -->
+
+#data
+<html><body></body></html>x<!-- Hi there -->
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "x"
+| <!-- Hi there -->
+
+#data
+<html><body></body></html>x<!-- Hi there --></html><!-- Again -->
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "x"
+| <!-- Hi there -->
+| <!-- Again -->
+
+#data
+<html><body></body></html>x<!-- Hi there --></body></html><!-- Again -->
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "x"
+| <!-- Hi there -->
+| <!-- Again -->
+
+#data
+<html><body><ruby><div><rp>xx</rp></div></ruby></body></html>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| <div>
+| <rp>
+| "xx"
+
+#data
+<html><body><ruby><div><rt>xx</rt></div></ruby></body></html>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| <div>
+| <rt>
+| "xx"
+
+#data
+<html><frameset><!--1--><noframes>A</noframes><!--2--></frameset><!--3--><noframes>B</noframes><!--4--></html><!--5--><noframes>C</noframes><!--6-->
+#errors
+#document
+| <html>
+| <head>
+| <frameset>
+| <!-- 1 -->
+| <noframes>
+| "A"
+| <!-- 2 -->
+| <!-- 3 -->
+| <noframes>
+| "B"
+| <!-- 4 -->
+| <noframes>
+| "C"
+| <!-- 5 -->
+| <!-- 6 -->
+
+#data
+<select><option>A<select><option>B<select><option>C<select><option>D<select><option>E<select><option>F<select><option>G<select>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <select>
+| <option>
+| "A"
+| <option>
+| "B"
+| <select>
+| <option>
+| "C"
+| <option>
+| "D"
+| <select>
+| <option>
+| "E"
+| <option>
+| "F"
+| <select>
+| <option>
+| "G"
+
+#data
+<dd><dd><dt><dt><dd><li><li>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <dd>
+| <dd>
+| <dt>
+| <dt>
+| <dd>
+| <li>
+| <li>
+
+#data
+<div><b></div><div><nobr>a<nobr>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <b>
+| <div>
+| <b>
+| <nobr>
+| "a"
+| <nobr>
+
+#data
+<head></head>
+<body></body>
+#errors
+#document
+| <html>
+| <head>
+| "
+"
+| <body>
+
+#data
+<head></head> <style></style>ddd
+#errors
+#document
+| <html>
+| <head>
+| <style>
+| " "
+| <body>
+| "ddd"
+
+#data
+<kbd><table></kbd><col><select><tr>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <kbd>
+| <select>
+| <table>
+| <colgroup>
+| <col>
+| <tbody>
+| <tr>
+
+#data
+<kbd><table></kbd><col><select><tr></table><div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <kbd>
+| <select>
+| <table>
+| <colgroup>
+| <col>
+| <tbody>
+| <tr>
+| <div>
+
+#data
+<a><li><style></style><title></title></a>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| <li>
+| <a>
+| <style>
+| <title>
+
+#data
+<font></p><p><meta><title></title></font>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <font>
+| <p>
+| <p>
+| <font>
+| <meta>
+| <title>
+
+#data
+<a><center><title></title><a>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| <center>
+| <a>
+| <title>
+| <a>
+
+#data
+<svg><title><div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg title>
+| <div>
+
+#data
+<svg><title><rect><div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg title>
+| <rect>
+| <div>
+
+#data
+<svg><title><svg><div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg title>
+| <svg svg>
+| <div>
+
+#data
+<img <="" FAIL>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <img>
+| <=""
+| fail=""
+
+#data
+<ul><li><div id='foo'/>A</li><li>B<div>C</div></li></ul>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <ul>
+| <li>
+| <div>
+| id="foo"
+| "A"
+| <li>
+| "B"
+| <div>
+| "C"
+
+#data
+<svg><em><desc></em>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <em>
+| <desc>
+
+#data
+<table><tr><td><svg><desc><td></desc><circle>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <svg svg>
+| <svg desc>
+| <td>
+| <circle>
+
+#data
+<svg><tfoot></mi><td>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg tfoot>
+| <svg td>
+
+#data
+<math><mrow><mrow><mn>1</mn></mrow><mi>a</mi></mrow></math>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mrow>
+| <math mrow>
+| <math mn>
+| "1"
+| <math mi>
+| "a"
+
+#data
+<!doctype html><input type="hidden"><frameset>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+
+#data
+<!doctype html><input type="button"><frameset>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <input>
+| type="button"
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/webkit02.dat b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/webkit02.dat
new file mode 100644
index 000000000..905783d3c
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/testdata/webkit/webkit02.dat
@@ -0,0 +1,159 @@
+#data
+<foo bar=qux/>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <foo>
+| bar="qux/"
+
+#data
+<p id="status"><noscript><strong>A</strong></noscript><span>B</span></p>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| id="status"
+| <noscript>
+| "<strong>A</strong>"
+| <span>
+| "B"
+
+#data
+<div><sarcasm><div></div></sarcasm></div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <sarcasm>
+| <div>
+
+#data
+<html><body><img src="" border="0" alt="><div>A</div></body></html>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<table><td></tbody>A
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "A"
+| <table>
+| <tbody>
+| <tr>
+| <td>
+
+#data
+<table><td></thead>A
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| "A"
+
+#data
+<table><td></tfoot>A
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| "A"
+
+#data
+<table><thead><td></tbody>A
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <thead>
+| <tr>
+| <td>
+| "A"
+
+#data
+<legend>test</legend>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <legend>
+| "test"
+
+#data
+<table><input>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <input>
+| <table>
+
+#data
+<b><em><dcell><postfield><postfield><postfield><postfield><missing_glyph><missing_glyph><missing_glyph><missing_glyph><hkern><aside></b></em>
+#errors
+#document-fragment
+div
+#document
+| <b>
+| <em>
+| <dcell>
+| <postfield>
+| <postfield>
+| <postfield>
+| <postfield>
+| <missing_glyph>
+| <missing_glyph>
+| <missing_glyph>
+| <missing_glyph>
+| <hkern>
+| <aside>
+| <em>
+| <b>
+
+#data
+<isindex action="x">
+#errors
+#document-fragment
+table
+#document
+| <form>
+| action="x"
+| <hr>
+| <label>
+| "This is a searchable index. Enter search keywords: "
+| <input>
+| name="isindex"
+| <hr>
+
+#data
+<option><XH<optgroup></optgroup>
+#errors
+#document-fragment
+select
+#document
+| <option>
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/token.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/token.go
new file mode 100644
index 000000000..893e272a9
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/token.go
@@ -0,0 +1,1219 @@
+// Copyright 2010 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 html
+
+import (
+ "bytes"
+ "errors"
+ "io"
+ "strconv"
+ "strings"
+
+ "golang.org/x/net/html/atom"
+)
+
+// A TokenType is the type of a Token.
+type TokenType uint32
+
+const (
+ // ErrorToken means that an error occurred during tokenization.
+ ErrorToken TokenType = iota
+ // TextToken means a text node.
+ TextToken
+ // A StartTagToken looks like <a>.
+ StartTagToken
+ // An EndTagToken looks like </a>.
+ EndTagToken
+ // A SelfClosingTagToken tag looks like <br/>.
+ SelfClosingTagToken
+ // A CommentToken looks like <!--x-->.
+ CommentToken
+ // A DoctypeToken looks like <!DOCTYPE x>
+ DoctypeToken
+)
+
+// ErrBufferExceeded means that the buffering limit was exceeded.
+var ErrBufferExceeded = errors.New("max buffer exceeded")
+
+// String returns a string representation of the TokenType.
+func (t TokenType) String() string {
+ switch t {
+ case ErrorToken:
+ return "Error"
+ case TextToken:
+ return "Text"
+ case StartTagToken:
+ return "StartTag"
+ case EndTagToken:
+ return "EndTag"
+ case SelfClosingTagToken:
+ return "SelfClosingTag"
+ case CommentToken:
+ return "Comment"
+ case DoctypeToken:
+ return "Doctype"
+ }
+ return "Invalid(" + strconv.Itoa(int(t)) + ")"
+}
+
+// An Attribute is an attribute namespace-key-value triple. Namespace is
+// non-empty for foreign attributes like xlink, Key is alphabetic (and hence
+// does not contain escapable characters like '&', '<' or '>'), and Val is
+// unescaped (it looks like "a<b" rather than "a&lt;b").
+//
+// Namespace is only used by the parser, not the tokenizer.
+type Attribute struct {
+ Namespace, Key, Val string
+}
+
+// A Token consists of a TokenType and some Data (tag name for start and end
+// tags, content for text, comments and doctypes). A tag Token may also contain
+// a slice of Attributes. Data is unescaped for all Tokens (it looks like "a<b"
+// rather than "a&lt;b"). For tag Tokens, DataAtom is the atom for Data, or
+// zero if Data is not a known tag name.
+type Token struct {
+ Type TokenType
+ DataAtom atom.Atom
+ Data string
+ Attr []Attribute
+}
+
+// tagString returns a string representation of a tag Token's Data and Attr.
+func (t Token) tagString() string {
+ if len(t.Attr) == 0 {
+ return t.Data
+ }
+ buf := bytes.NewBufferString(t.Data)
+ for _, a := range t.Attr {
+ buf.WriteByte(' ')
+ buf.WriteString(a.Key)
+ buf.WriteString(`="`)
+ escape(buf, a.Val)
+ buf.WriteByte('"')
+ }
+ return buf.String()
+}
+
+// String returns a string representation of the Token.
+func (t Token) String() string {
+ switch t.Type {
+ case ErrorToken:
+ return ""
+ case TextToken:
+ return EscapeString(t.Data)
+ case StartTagToken:
+ return "<" + t.tagString() + ">"
+ case EndTagToken:
+ return "</" + t.tagString() + ">"
+ case SelfClosingTagToken:
+ return "<" + t.tagString() + "/>"
+ case CommentToken:
+ return "<!--" + t.Data + "-->"
+ case DoctypeToken:
+ return "<!DOCTYPE " + t.Data + ">"
+ }
+ return "Invalid(" + strconv.Itoa(int(t.Type)) + ")"
+}
+
+// span is a range of bytes in a Tokenizer's buffer. The start is inclusive,
+// the end is exclusive.
+type span struct {
+ start, end int
+}
+
+// A Tokenizer returns a stream of HTML Tokens.
+type Tokenizer struct {
+ // r is the source of the HTML text.
+ r io.Reader
+ // tt is the TokenType of the current token.
+ tt TokenType
+ // err is the first error encountered during tokenization. It is possible
+ // for tt != Error && err != nil to hold: this means that Next returned a
+ // valid token but the subsequent Next call will return an error token.
+ // For example, if the HTML text input was just "plain", then the first
+ // Next call would set z.err to io.EOF but return a TextToken, and all
+ // subsequent Next calls would return an ErrorToken.
+ // err is never reset. Once it becomes non-nil, it stays non-nil.
+ err error
+ // readErr is the error returned by the io.Reader r. It is separate from
+ // err because it is valid for an io.Reader to return (n int, err1 error)
+ // such that n > 0 && err1 != nil, and callers should always process the
+ // n > 0 bytes before considering the error err1.
+ readErr error
+ // buf[raw.start:raw.end] holds the raw bytes of the current token.
+ // buf[raw.end:] is buffered input that will yield future tokens.
+ raw span
+ buf []byte
+ // maxBuf limits the data buffered in buf. A value of 0 means unlimited.
+ maxBuf int
+ // buf[data.start:data.end] holds the raw bytes of the current token's data:
+ // a text token's text, a tag token's tag name, etc.
+ data span
+ // pendingAttr is the attribute key and value currently being tokenized.
+ // When complete, pendingAttr is pushed onto attr. nAttrReturned is
+ // incremented on each call to TagAttr.
+ pendingAttr [2]span
+ attr [][2]span
+ nAttrReturned int
+ // rawTag is the "script" in "</script>" that closes the next token. If
+ // non-empty, the subsequent call to Next will return a raw or RCDATA text
+ // token: one that treats "<p>" as text instead of an element.
+ // rawTag's contents are lower-cased.
+ rawTag string
+ // textIsRaw is whether the current text token's data is not escaped.
+ textIsRaw bool
+ // convertNUL is whether NUL bytes in the current token's data should
+ // be converted into \ufffd replacement characters.
+ convertNUL bool
+ // allowCDATA is whether CDATA sections are allowed in the current context.
+ allowCDATA bool
+}
+
+// AllowCDATA sets whether or not the tokenizer recognizes <![CDATA[foo]]> as
+// the text "foo". The default value is false, which means to recognize it as
+// a bogus comment "<!-- [CDATA[foo]] -->" instead.
+//
+// Strictly speaking, an HTML5 compliant tokenizer should allow CDATA if and
+// only if tokenizing foreign content, such as MathML and SVG. However,
+// tracking foreign-contentness is difficult to do purely in the tokenizer,
+// as opposed to the parser, due to HTML integration points: an <svg> element
+// can contain a <foreignObject> that is foreign-to-SVG but not foreign-to-
+// HTML. For strict compliance with the HTML5 tokenization algorithm, it is the
+// responsibility of the user of a tokenizer to call AllowCDATA as appropriate.
+// In practice, if using the tokenizer without caring whether MathML or SVG
+// CDATA is text or comments, such as tokenizing HTML to find all the anchor
+// text, it is acceptable to ignore this responsibility.
+func (z *Tokenizer) AllowCDATA(allowCDATA bool) {
+ z.allowCDATA = allowCDATA
+}
+
+// NextIsNotRawText instructs the tokenizer that the next token should not be
+// considered as 'raw text'. Some elements, such as script and title elements,
+// normally require the next token after the opening tag to be 'raw text' that
+// has no child elements. For example, tokenizing "<title>a<b>c</b>d</title>"
+// yields a start tag token for "<title>", a text token for "a<b>c</b>d", and
+// an end tag token for "</title>". There are no distinct start tag or end tag
+// tokens for the "<b>" and "</b>".
+//
+// This tokenizer implementation will generally look for raw text at the right
+// times. Strictly speaking, an HTML5 compliant tokenizer should not look for
+// raw text if in foreign content: <title> generally needs raw text, but a
+// <title> inside an <svg> does not. Another example is that a <textarea>
+// generally needs raw text, but a <textarea> is not allowed as an immediate
+// child of a <select>; in normal parsing, a <textarea> implies </select>, but
+// one cannot close the implicit element when parsing a <select>'s InnerHTML.
+// Similarly to AllowCDATA, tracking the correct moment to override raw-text-
+// ness is difficult to do purely in the tokenizer, as opposed to the parser.
+// For strict compliance with the HTML5 tokenization algorithm, it is the
+// responsibility of the user of a tokenizer to call NextIsNotRawText as
+// appropriate. In practice, like AllowCDATA, it is acceptable to ignore this
+// responsibility for basic usage.
+//
+// Note that this 'raw text' concept is different from the one offered by the
+// Tokenizer.Raw method.
+func (z *Tokenizer) NextIsNotRawText() {
+ z.rawTag = ""
+}
+
+// Err returns the error associated with the most recent ErrorToken token.
+// This is typically io.EOF, meaning the end of tokenization.
+func (z *Tokenizer) Err() error {
+ if z.tt != ErrorToken {
+ return nil
+ }
+ return z.err
+}
+
+// readByte returns the next byte from the input stream, doing a buffered read
+// from z.r into z.buf if necessary. z.buf[z.raw.start:z.raw.end] remains a contiguous byte
+// slice that holds all the bytes read so far for the current token.
+// It sets z.err if the underlying reader returns an error.
+// Pre-condition: z.err == nil.
+func (z *Tokenizer) readByte() byte {
+ if z.raw.end >= len(z.buf) {
+ // Our buffer is exhausted and we have to read from z.r. Check if the
+ // previous read resulted in an error.
+ if z.readErr != nil {
+ z.err = z.readErr
+ return 0
+ }
+ // We copy z.buf[z.raw.start:z.raw.end] to the beginning of z.buf. If the length
+ // z.raw.end - z.raw.start is more than half the capacity of z.buf, then we
+ // allocate a new buffer before the copy.
+ c := cap(z.buf)
+ d := z.raw.end - z.raw.start
+ var buf1 []byte
+ if 2*d > c {
+ buf1 = make([]byte, d, 2*c)
+ } else {
+ buf1 = z.buf[:d]
+ }
+ copy(buf1, z.buf[z.raw.start:z.raw.end])
+ if x := z.raw.start; x != 0 {
+ // Adjust the data/attr spans to refer to the same contents after the copy.
+ z.data.start -= x
+ z.data.end -= x
+ z.pendingAttr[0].start -= x
+ z.pendingAttr[0].end -= x
+ z.pendingAttr[1].start -= x
+ z.pendingAttr[1].end -= x
+ for i := range z.attr {
+ z.attr[i][0].start -= x
+ z.attr[i][0].end -= x
+ z.attr[i][1].start -= x
+ z.attr[i][1].end -= x
+ }
+ }
+ z.raw.start, z.raw.end, z.buf = 0, d, buf1[:d]
+ // Now that we have copied the live bytes to the start of the buffer,
+ // we read from z.r into the remainder.
+ var n int
+ n, z.readErr = readAtLeastOneByte(z.r, buf1[d:cap(buf1)])
+ if n == 0 {
+ z.err = z.readErr
+ return 0
+ }
+ z.buf = buf1[:d+n]
+ }
+ x := z.buf[z.raw.end]
+ z.raw.end++
+ if z.maxBuf > 0 && z.raw.end-z.raw.start >= z.maxBuf {
+ z.err = ErrBufferExceeded
+ return 0
+ }
+ return x
+}
+
+// Buffered returns a slice containing data buffered but not yet tokenized.
+func (z *Tokenizer) Buffered() []byte {
+ return z.buf[z.raw.end:]
+}
+
+// readAtLeastOneByte wraps an io.Reader so that reading cannot return (0, nil).
+// It returns io.ErrNoProgress if the underlying r.Read method returns (0, nil)
+// too many times in succession.
+func readAtLeastOneByte(r io.Reader, b []byte) (int, error) {
+ for i := 0; i < 100; i++ {
+ n, err := r.Read(b)
+ if n != 0 || err != nil {
+ return n, err
+ }
+ }
+ return 0, io.ErrNoProgress
+}
+
+// skipWhiteSpace skips past any white space.
+func (z *Tokenizer) skipWhiteSpace() {
+ if z.err != nil {
+ return
+ }
+ for {
+ c := z.readByte()
+ if z.err != nil {
+ return
+ }
+ switch c {
+ case ' ', '\n', '\r', '\t', '\f':
+ // No-op.
+ default:
+ z.raw.end--
+ return
+ }
+ }
+}
+
+// readRawOrRCDATA reads until the next "</foo>", where "foo" is z.rawTag and
+// is typically something like "script" or "textarea".
+func (z *Tokenizer) readRawOrRCDATA() {
+ if z.rawTag == "script" {
+ z.readScript()
+ z.textIsRaw = true
+ z.rawTag = ""
+ return
+ }
+loop:
+ for {
+ c := z.readByte()
+ if z.err != nil {
+ break loop
+ }
+ if c != '<' {
+ continue loop
+ }
+ c = z.readByte()
+ if z.err != nil {
+ break loop
+ }
+ if c != '/' {
+ continue loop
+ }
+ if z.readRawEndTag() || z.err != nil {
+ break loop
+ }
+ }
+ z.data.end = z.raw.end
+ // A textarea's or title's RCDATA can contain escaped entities.
+ z.textIsRaw = z.rawTag != "textarea" && z.rawTag != "title"
+ z.rawTag = ""
+}
+
+// readRawEndTag attempts to read a tag like "</foo>", where "foo" is z.rawTag.
+// If it succeeds, it backs up the input position to reconsume the tag and
+// returns true. Otherwise it returns false. The opening "</" has already been
+// consumed.
+func (z *Tokenizer) readRawEndTag() bool {
+ for i := 0; i < len(z.rawTag); i++ {
+ c := z.readByte()
+ if z.err != nil {
+ return false
+ }
+ if c != z.rawTag[i] && c != z.rawTag[i]-('a'-'A') {
+ z.raw.end--
+ return false
+ }
+ }
+ c := z.readByte()
+ if z.err != nil {
+ return false
+ }
+ switch c {
+ case ' ', '\n', '\r', '\t', '\f', '/', '>':
+ // The 3 is 2 for the leading "</" plus 1 for the trailing character c.
+ z.raw.end -= 3 + len(z.rawTag)
+ return true
+ }
+ z.raw.end--
+ return false
+}
+
+// readScript reads until the next </script> tag, following the byzantine
+// rules for escaping/hiding the closing tag.
+func (z *Tokenizer) readScript() {
+ defer func() {
+ z.data.end = z.raw.end
+ }()
+ var c byte
+
+scriptData:
+ c = z.readByte()
+ if z.err != nil {
+ return
+ }
+ if c == '<' {
+ goto scriptDataLessThanSign
+ }
+ goto scriptData
+
+scriptDataLessThanSign:
+ c = z.readByte()
+ if z.err != nil {
+ return
+ }
+ switch c {
+ case '/':
+ goto scriptDataEndTagOpen
+ case '!':
+ goto scriptDataEscapeStart
+ }
+ z.raw.end--
+ goto scriptData
+
+scriptDataEndTagOpen:
+ if z.readRawEndTag() || z.err != nil {
+ return
+ }
+ goto scriptData
+
+scriptDataEscapeStart:
+ c = z.readByte()
+ if z.err != nil {
+ return
+ }
+ if c == '-' {
+ goto scriptDataEscapeStartDash
+ }
+ z.raw.end--
+ goto scriptData
+
+scriptDataEscapeStartDash:
+ c = z.readByte()
+ if z.err != nil {
+ return
+ }
+ if c == '-' {
+ goto scriptDataEscapedDashDash
+ }
+ z.raw.end--
+ goto scriptData
+
+scriptDataEscaped:
+ c = z.readByte()
+ if z.err != nil {
+ return
+ }
+ switch c {
+ case '-':
+ goto scriptDataEscapedDash
+ case '<':
+ goto scriptDataEscapedLessThanSign
+ }
+ goto scriptDataEscaped
+
+scriptDataEscapedDash:
+ c = z.readByte()
+ if z.err != nil {
+ return
+ }
+ switch c {
+ case '-':
+ goto scriptDataEscapedDashDash
+ case '<':
+ goto scriptDataEscapedLessThanSign
+ }
+ goto scriptDataEscaped
+
+scriptDataEscapedDashDash:
+ c = z.readByte()
+ if z.err != nil {
+ return
+ }
+ switch c {
+ case '-':
+ goto scriptDataEscapedDashDash
+ case '<':
+ goto scriptDataEscapedLessThanSign
+ case '>':
+ goto scriptData
+ }
+ goto scriptDataEscaped
+
+scriptDataEscapedLessThanSign:
+ c = z.readByte()
+ if z.err != nil {
+ return
+ }
+ if c == '/' {
+ goto scriptDataEscapedEndTagOpen
+ }
+ if 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' {
+ goto scriptDataDoubleEscapeStart
+ }
+ z.raw.end--
+ goto scriptData
+
+scriptDataEscapedEndTagOpen:
+ if z.readRawEndTag() || z.err != nil {
+ return
+ }
+ goto scriptDataEscaped
+
+scriptDataDoubleEscapeStart:
+ z.raw.end--
+ for i := 0; i < len("script"); i++ {
+ c = z.readByte()
+ if z.err != nil {
+ return
+ }
+ if c != "script"[i] && c != "SCRIPT"[i] {
+ z.raw.end--
+ goto scriptDataEscaped
+ }
+ }
+ c = z.readByte()
+ if z.err != nil {
+ return
+ }
+ switch c {
+ case ' ', '\n', '\r', '\t', '\f', '/', '>':
+ goto scriptDataDoubleEscaped
+ }
+ z.raw.end--
+ goto scriptDataEscaped
+
+scriptDataDoubleEscaped:
+ c = z.readByte()
+ if z.err != nil {
+ return
+ }
+ switch c {
+ case '-':
+ goto scriptDataDoubleEscapedDash
+ case '<':
+ goto scriptDataDoubleEscapedLessThanSign
+ }
+ goto scriptDataDoubleEscaped
+
+scriptDataDoubleEscapedDash:
+ c = z.readByte()
+ if z.err != nil {
+ return
+ }
+ switch c {
+ case '-':
+ goto scriptDataDoubleEscapedDashDash
+ case '<':
+ goto scriptDataDoubleEscapedLessThanSign
+ }
+ goto scriptDataDoubleEscaped
+
+scriptDataDoubleEscapedDashDash:
+ c = z.readByte()
+ if z.err != nil {
+ return
+ }
+ switch c {
+ case '-':
+ goto scriptDataDoubleEscapedDashDash
+ case '<':
+ goto scriptDataDoubleEscapedLessThanSign
+ case '>':
+ goto scriptData
+ }
+ goto scriptDataDoubleEscaped
+
+scriptDataDoubleEscapedLessThanSign:
+ c = z.readByte()
+ if z.err != nil {
+ return
+ }
+ if c == '/' {
+ goto scriptDataDoubleEscapeEnd
+ }
+ z.raw.end--
+ goto scriptDataDoubleEscaped
+
+scriptDataDoubleEscapeEnd:
+ if z.readRawEndTag() {
+ z.raw.end += len("</script>")
+ goto scriptDataEscaped
+ }
+ if z.err != nil {
+ return
+ }
+ goto scriptDataDoubleEscaped
+}
+
+// readComment reads the next comment token starting with "<!--". The opening
+// "<!--" has already been consumed.
+func (z *Tokenizer) readComment() {
+ z.data.start = z.raw.end
+ defer func() {
+ if z.data.end < z.data.start {
+ // It's a comment with no data, like <!-->.
+ z.data.end = z.data.start
+ }
+ }()
+ for dashCount := 2; ; {
+ c := z.readByte()
+ if z.err != nil {
+ // Ignore up to two dashes at EOF.
+ if dashCount > 2 {
+ dashCount = 2
+ }
+ z.data.end = z.raw.end - dashCount
+ return
+ }
+ switch c {
+ case '-':
+ dashCount++
+ continue
+ case '>':
+ if dashCount >= 2 {
+ z.data.end = z.raw.end - len("-->")
+ return
+ }
+ case '!':
+ if dashCount >= 2 {
+ c = z.readByte()
+ if z.err != nil {
+ z.data.end = z.raw.end
+ return
+ }
+ if c == '>' {
+ z.data.end = z.raw.end - len("--!>")
+ return
+ }
+ }
+ }
+ dashCount = 0
+ }
+}
+
+// readUntilCloseAngle reads until the next ">".
+func (z *Tokenizer) readUntilCloseAngle() {
+ z.data.start = z.raw.end
+ for {
+ c := z.readByte()
+ if z.err != nil {
+ z.data.end = z.raw.end
+ return
+ }
+ if c == '>' {
+ z.data.end = z.raw.end - len(">")
+ return
+ }
+ }
+}
+
+// readMarkupDeclaration reads the next token starting with "<!". It might be
+// a "<!--comment-->", a "<!DOCTYPE foo>", a "<![CDATA[section]]>" or
+// "<!a bogus comment". The opening "<!" has already been consumed.
+func (z *Tokenizer) readMarkupDeclaration() TokenType {
+ z.data.start = z.raw.end
+ var c [2]byte
+ for i := 0; i < 2; i++ {
+ c[i] = z.readByte()
+ if z.err != nil {
+ z.data.end = z.raw.end
+ return CommentToken
+ }
+ }
+ if c[0] == '-' && c[1] == '-' {
+ z.readComment()
+ return CommentToken
+ }
+ z.raw.end -= 2
+ if z.readDoctype() {
+ return DoctypeToken
+ }
+ if z.allowCDATA && z.readCDATA() {
+ z.convertNUL = true
+ return TextToken
+ }
+ // It's a bogus comment.
+ z.readUntilCloseAngle()
+ return CommentToken
+}
+
+// readDoctype attempts to read a doctype declaration and returns true if
+// successful. The opening "<!" has already been consumed.
+func (z *Tokenizer) readDoctype() bool {
+ const s = "DOCTYPE"
+ for i := 0; i < len(s); i++ {
+ c := z.readByte()
+ if z.err != nil {
+ z.data.end = z.raw.end
+ return false
+ }
+ if c != s[i] && c != s[i]+('a'-'A') {
+ // Back up to read the fragment of "DOCTYPE" again.
+ z.raw.end = z.data.start
+ return false
+ }
+ }
+ if z.skipWhiteSpace(); z.err != nil {
+ z.data.start = z.raw.end
+ z.data.end = z.raw.end
+ return true
+ }
+ z.readUntilCloseAngle()
+ return true
+}
+
+// readCDATA attempts to read a CDATA section and returns true if
+// successful. The opening "<!" has already been consumed.
+func (z *Tokenizer) readCDATA() bool {
+ const s = "[CDATA["
+ for i := 0; i < len(s); i++ {
+ c := z.readByte()
+ if z.err != nil {
+ z.data.end = z.raw.end
+ return false
+ }
+ if c != s[i] {
+ // Back up to read the fragment of "[CDATA[" again.
+ z.raw.end = z.data.start
+ return false
+ }
+ }
+ z.data.start = z.raw.end
+ brackets := 0
+ for {
+ c := z.readByte()
+ if z.err != nil {
+ z.data.end = z.raw.end
+ return true
+ }
+ switch c {
+ case ']':
+ brackets++
+ case '>':
+ if brackets >= 2 {
+ z.data.end = z.raw.end - len("]]>")
+ return true
+ }
+ brackets = 0
+ default:
+ brackets = 0
+ }
+ }
+}
+
+// startTagIn returns whether the start tag in z.buf[z.data.start:z.data.end]
+// case-insensitively matches any element of ss.
+func (z *Tokenizer) startTagIn(ss ...string) bool {
+loop:
+ for _, s := range ss {
+ if z.data.end-z.data.start != len(s) {
+ continue loop
+ }
+ for i := 0; i < len(s); i++ {
+ c := z.buf[z.data.start+i]
+ if 'A' <= c && c <= 'Z' {
+ c += 'a' - 'A'
+ }
+ if c != s[i] {
+ continue loop
+ }
+ }
+ return true
+ }
+ return false
+}
+
+// readStartTag reads the next start tag token. The opening "<a" has already
+// been consumed, where 'a' means anything in [A-Za-z].
+func (z *Tokenizer) readStartTag() TokenType {
+ z.readTag(true)
+ if z.err != nil {
+ return ErrorToken
+ }
+ // Several tags flag the tokenizer's next token as raw.
+ c, raw := z.buf[z.data.start], false
+ if 'A' <= c && c <= 'Z' {
+ c += 'a' - 'A'
+ }
+ switch c {
+ case 'i':
+ raw = z.startTagIn("iframe")
+ case 'n':
+ raw = z.startTagIn("noembed", "noframes", "noscript")
+ case 'p':
+ raw = z.startTagIn("plaintext")
+ case 's':
+ raw = z.startTagIn("script", "style")
+ case 't':
+ raw = z.startTagIn("textarea", "title")
+ case 'x':
+ raw = z.startTagIn("xmp")
+ }
+ if raw {
+ z.rawTag = strings.ToLower(string(z.buf[z.data.start:z.data.end]))
+ }
+ // Look for a self-closing token like "<br/>".
+ if z.err == nil && z.buf[z.raw.end-2] == '/' {
+ return SelfClosingTagToken
+ }
+ return StartTagToken
+}
+
+// readTag reads the next tag token and its attributes. If saveAttr, those
+// attributes are saved in z.attr, otherwise z.attr is set to an empty slice.
+// The opening "<a" or "</a" has already been consumed, where 'a' means anything
+// in [A-Za-z].
+func (z *Tokenizer) readTag(saveAttr bool) {
+ z.attr = z.attr[:0]
+ z.nAttrReturned = 0
+ // Read the tag name and attribute key/value pairs.
+ z.readTagName()
+ if z.skipWhiteSpace(); z.err != nil {
+ return
+ }
+ for {
+ c := z.readByte()
+ if z.err != nil || c == '>' {
+ break
+ }
+ z.raw.end--
+ z.readTagAttrKey()
+ z.readTagAttrVal()
+ // Save pendingAttr if saveAttr and that attribute has a non-empty key.
+ if saveAttr && z.pendingAttr[0].start != z.pendingAttr[0].end {
+ z.attr = append(z.attr, z.pendingAttr)
+ }
+ if z.skipWhiteSpace(); z.err != nil {
+ break
+ }
+ }
+}
+
+// readTagName sets z.data to the "div" in "<div k=v>". The reader (z.raw.end)
+// is positioned such that the first byte of the tag name (the "d" in "<div")
+// has already been consumed.
+func (z *Tokenizer) readTagName() {
+ z.data.start = z.raw.end - 1
+ for {
+ c := z.readByte()
+ if z.err != nil {
+ z.data.end = z.raw.end
+ return
+ }
+ switch c {
+ case ' ', '\n', '\r', '\t', '\f':
+ z.data.end = z.raw.end - 1
+ return
+ case '/', '>':
+ z.raw.end--
+ z.data.end = z.raw.end
+ return
+ }
+ }
+}
+
+// readTagAttrKey sets z.pendingAttr[0] to the "k" in "<div k=v>".
+// Precondition: z.err == nil.
+func (z *Tokenizer) readTagAttrKey() {
+ z.pendingAttr[0].start = z.raw.end
+ for {
+ c := z.readByte()
+ if z.err != nil {
+ z.pendingAttr[0].end = z.raw.end
+ return
+ }
+ switch c {
+ case ' ', '\n', '\r', '\t', '\f', '/':
+ z.pendingAttr[0].end = z.raw.end - 1
+ return
+ case '=', '>':
+ z.raw.end--
+ z.pendingAttr[0].end = z.raw.end
+ return
+ }
+ }
+}
+
+// readTagAttrVal sets z.pendingAttr[1] to the "v" in "<div k=v>".
+func (z *Tokenizer) readTagAttrVal() {
+ z.pendingAttr[1].start = z.raw.end
+ z.pendingAttr[1].end = z.raw.end
+ if z.skipWhiteSpace(); z.err != nil {
+ return
+ }
+ c := z.readByte()
+ if z.err != nil {
+ return
+ }
+ if c != '=' {
+ z.raw.end--
+ return
+ }
+ if z.skipWhiteSpace(); z.err != nil {
+ return
+ }
+ quote := z.readByte()
+ if z.err != nil {
+ return
+ }
+ switch quote {
+ case '>':
+ z.raw.end--
+ return
+
+ case '\'', '"':
+ z.pendingAttr[1].start = z.raw.end
+ for {
+ c := z.readByte()
+ if z.err != nil {
+ z.pendingAttr[1].end = z.raw.end
+ return
+ }
+ if c == quote {
+ z.pendingAttr[1].end = z.raw.end - 1
+ return
+ }
+ }
+
+ default:
+ z.pendingAttr[1].start = z.raw.end - 1
+ for {
+ c := z.readByte()
+ if z.err != nil {
+ z.pendingAttr[1].end = z.raw.end
+ return
+ }
+ switch c {
+ case ' ', '\n', '\r', '\t', '\f':
+ z.pendingAttr[1].end = z.raw.end - 1
+ return
+ case '>':
+ z.raw.end--
+ z.pendingAttr[1].end = z.raw.end
+ return
+ }
+ }
+ }
+}
+
+// Next scans the next token and returns its type.
+func (z *Tokenizer) Next() TokenType {
+ z.raw.start = z.raw.end
+ z.data.start = z.raw.end
+ z.data.end = z.raw.end
+ if z.err != nil {
+ z.tt = ErrorToken
+ return z.tt
+ }
+ if z.rawTag != "" {
+ if z.rawTag == "plaintext" {
+ // Read everything up to EOF.
+ for z.err == nil {
+ z.readByte()
+ }
+ z.data.end = z.raw.end
+ z.textIsRaw = true
+ } else {
+ z.readRawOrRCDATA()
+ }
+ if z.data.end > z.data.start {
+ z.tt = TextToken
+ z.convertNUL = true
+ return z.tt
+ }
+ }
+ z.textIsRaw = false
+ z.convertNUL = false
+
+loop:
+ for {
+ c := z.readByte()
+ if z.err != nil {
+ break loop
+ }
+ if c != '<' {
+ continue loop
+ }
+
+ // Check if the '<' we have just read is part of a tag, comment
+ // or doctype. If not, it's part of the accumulated text token.
+ c = z.readByte()
+ if z.err != nil {
+ break loop
+ }
+ var tokenType TokenType
+ switch {
+ case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z':
+ tokenType = StartTagToken
+ case c == '/':
+ tokenType = EndTagToken
+ case c == '!' || c == '?':
+ // We use CommentToken to mean any of "<!--actual comments-->",
+ // "<!DOCTYPE declarations>" and "<?xml processing instructions?>".
+ tokenType = CommentToken
+ default:
+ // Reconsume the current character.
+ z.raw.end--
+ continue
+ }
+
+ // We have a non-text token, but we might have accumulated some text
+ // before that. If so, we return the text first, and return the non-
+ // text token on the subsequent call to Next.
+ if x := z.raw.end - len("<a"); z.raw.start < x {
+ z.raw.end = x
+ z.data.end = x
+ z.tt = TextToken
+ return z.tt
+ }
+ switch tokenType {
+ case StartTagToken:
+ z.tt = z.readStartTag()
+ return z.tt
+ case EndTagToken:
+ c = z.readByte()
+ if z.err != nil {
+ break loop
+ }
+ if c == '>' {
+ // "</>" does not generate a token at all. Generate an empty comment
+ // to allow passthrough clients to pick up the data using Raw.
+ // Reset the tokenizer state and start again.
+ z.tt = CommentToken
+ return z.tt
+ }
+ if 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' {
+ z.readTag(false)
+ if z.err != nil {
+ z.tt = ErrorToken
+ } else {
+ z.tt = EndTagToken
+ }
+ return z.tt
+ }
+ z.raw.end--
+ z.readUntilCloseAngle()
+ z.tt = CommentToken
+ return z.tt
+ case CommentToken:
+ if c == '!' {
+ z.tt = z.readMarkupDeclaration()
+ return z.tt
+ }
+ z.raw.end--
+ z.readUntilCloseAngle()
+ z.tt = CommentToken
+ return z.tt
+ }
+ }
+ if z.raw.start < z.raw.end {
+ z.data.end = z.raw.end
+ z.tt = TextToken
+ return z.tt
+ }
+ z.tt = ErrorToken
+ return z.tt
+}
+
+// Raw returns the unmodified text of the current token. Calling Next, Token,
+// Text, TagName or TagAttr may change the contents of the returned slice.
+func (z *Tokenizer) Raw() []byte {
+ return z.buf[z.raw.start:z.raw.end]
+}
+
+// convertNewlines converts "\r" and "\r\n" in s to "\n".
+// The conversion happens in place, but the resulting slice may be shorter.
+func convertNewlines(s []byte) []byte {
+ for i, c := range s {
+ if c != '\r' {
+ continue
+ }
+
+ src := i + 1
+ if src >= len(s) || s[src] != '\n' {
+ s[i] = '\n'
+ continue
+ }
+
+ dst := i
+ for src < len(s) {
+ if s[src] == '\r' {
+ if src+1 < len(s) && s[src+1] == '\n' {
+ src++
+ }
+ s[dst] = '\n'
+ } else {
+ s[dst] = s[src]
+ }
+ src++
+ dst++
+ }
+ return s[:dst]
+ }
+ return s
+}
+
+var (
+ nul = []byte("\x00")
+ replacement = []byte("\ufffd")
+)
+
+// Text returns the unescaped text of a text, comment or doctype token. The
+// contents of the returned slice may change on the next call to Next.
+func (z *Tokenizer) Text() []byte {
+ switch z.tt {
+ case TextToken, CommentToken, DoctypeToken:
+ s := z.buf[z.data.start:z.data.end]
+ z.data.start = z.raw.end
+ z.data.end = z.raw.end
+ s = convertNewlines(s)
+ if (z.convertNUL || z.tt == CommentToken) && bytes.Contains(s, nul) {
+ s = bytes.Replace(s, nul, replacement, -1)
+ }
+ if !z.textIsRaw {
+ s = unescape(s, false)
+ }
+ return s
+ }
+ return nil
+}
+
+// TagName returns the lower-cased name of a tag token (the `img` out of
+// `<IMG SRC="foo">`) and whether the tag has attributes.
+// The contents of the returned slice may change on the next call to Next.
+func (z *Tokenizer) TagName() (name []byte, hasAttr bool) {
+ if z.data.start < z.data.end {
+ switch z.tt {
+ case StartTagToken, EndTagToken, SelfClosingTagToken:
+ s := z.buf[z.data.start:z.data.end]
+ z.data.start = z.raw.end
+ z.data.end = z.raw.end
+ return lower(s), z.nAttrReturned < len(z.attr)
+ }
+ }
+ return nil, false
+}
+
+// TagAttr returns the lower-cased key and unescaped value of the next unparsed
+// attribute for the current tag token and whether there are more attributes.
+// The contents of the returned slices may change on the next call to Next.
+func (z *Tokenizer) TagAttr() (key, val []byte, moreAttr bool) {
+ if z.nAttrReturned < len(z.attr) {
+ switch z.tt {
+ case StartTagToken, SelfClosingTagToken:
+ x := z.attr[z.nAttrReturned]
+ z.nAttrReturned++
+ key = z.buf[x[0].start:x[0].end]
+ val = z.buf[x[1].start:x[1].end]
+ return lower(key), unescape(convertNewlines(val), true), z.nAttrReturned < len(z.attr)
+ }
+ }
+ return nil, nil, false
+}
+
+// Token returns the next Token. The result's Data and Attr values remain valid
+// after subsequent Next calls.
+func (z *Tokenizer) Token() Token {
+ t := Token{Type: z.tt}
+ switch z.tt {
+ case TextToken, CommentToken, DoctypeToken:
+ t.Data = string(z.Text())
+ case StartTagToken, SelfClosingTagToken, EndTagToken:
+ name, moreAttr := z.TagName()
+ for moreAttr {
+ var key, val []byte
+ key, val, moreAttr = z.TagAttr()
+ t.Attr = append(t.Attr, Attribute{"", atom.String(key), string(val)})
+ }
+ if a := atom.Lookup(name); a != 0 {
+ t.DataAtom, t.Data = a, a.String()
+ } else {
+ t.DataAtom, t.Data = 0, string(name)
+ }
+ }
+ return t
+}
+
+// SetMaxBuf sets a limit on the amount of data buffered during tokenization.
+// A value of 0 means unlimited.
+func (z *Tokenizer) SetMaxBuf(n int) {
+ z.maxBuf = n
+}
+
+// NewTokenizer returns a new HTML Tokenizer for the given Reader.
+// The input is assumed to be UTF-8 encoded.
+func NewTokenizer(r io.Reader) *Tokenizer {
+ return NewTokenizerFragment(r, "")
+}
+
+// NewTokenizerFragment returns a new HTML Tokenizer for the given Reader, for
+// tokenizing an existing element's InnerHTML fragment. contextTag is that
+// element's tag, such as "div" or "iframe".
+//
+// For example, how the InnerHTML "a<b" is tokenized depends on whether it is
+// for a <p> tag or a <script> tag.
+//
+// The input is assumed to be UTF-8 encoded.
+func NewTokenizerFragment(r io.Reader, contextTag string) *Tokenizer {
+ z := &Tokenizer{
+ r: r,
+ buf: make([]byte, 0, 4096),
+ }
+ if contextTag != "" {
+ switch s := strings.ToLower(contextTag); s {
+ case "iframe", "noembed", "noframes", "noscript", "plaintext", "script", "style", "title", "textarea", "xmp":
+ z.rawTag = s
+ }
+ }
+ return z
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/token_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/token_test.go
new file mode 100644
index 000000000..20221c328
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/html/token_test.go
@@ -0,0 +1,748 @@
+// Copyright 2010 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 html
+
+import (
+ "bytes"
+ "io"
+ "io/ioutil"
+ "reflect"
+ "runtime"
+ "strings"
+ "testing"
+)
+
+type tokenTest struct {
+ // A short description of the test case.
+ desc string
+ // The HTML to parse.
+ html string
+ // The string representations of the expected tokens, joined by '$'.
+ golden string
+}
+
+var tokenTests = []tokenTest{
+ {
+ "empty",
+ "",
+ "",
+ },
+ // A single text node. The tokenizer should not break text nodes on whitespace,
+ // nor should it normalize whitespace within a text node.
+ {
+ "text",
+ "foo bar",
+ "foo bar",
+ },
+ // An entity.
+ {
+ "entity",
+ "one &lt; two",
+ "one &lt; two",
+ },
+ // A start, self-closing and end tag. The tokenizer does not care if the start
+ // and end tokens don't match; that is the job of the parser.
+ {
+ "tags",
+ "<a>b<c/>d</e>",
+ "<a>$b$<c/>$d$</e>",
+ },
+ // Angle brackets that aren't a tag.
+ {
+ "not a tag #0",
+ "<",
+ "&lt;",
+ },
+ {
+ "not a tag #1",
+ "</",
+ "&lt;/",
+ },
+ {
+ "not a tag #2",
+ "</>",
+ "<!---->",
+ },
+ {
+ "not a tag #3",
+ "a</>b",
+ "a$<!---->$b",
+ },
+ {
+ "not a tag #4",
+ "</ >",
+ "<!-- -->",
+ },
+ {
+ "not a tag #5",
+ "</.",
+ "<!--.-->",
+ },
+ {
+ "not a tag #6",
+ "</.>",
+ "<!--.-->",
+ },
+ {
+ "not a tag #7",
+ "a < b",
+ "a &lt; b",
+ },
+ {
+ "not a tag #8",
+ "<.>",
+ "&lt;.&gt;",
+ },
+ {
+ "not a tag #9",
+ "a<<<b>>>c",
+ "a&lt;&lt;$<b>$&gt;&gt;c",
+ },
+ {
+ "not a tag #10",
+ "if x<0 and y < 0 then x*y>0",
+ "if x&lt;0 and y &lt; 0 then x*y&gt;0",
+ },
+ {
+ "not a tag #11",
+ "<<p>",
+ "&lt;$<p>",
+ },
+ // EOF in a tag name.
+ {
+ "tag name eof #0",
+ "<a",
+ "",
+ },
+ {
+ "tag name eof #1",
+ "<a ",
+ "",
+ },
+ {
+ "tag name eof #2",
+ "a<b",
+ "a",
+ },
+ {
+ "tag name eof #3",
+ "<a><b",
+ "<a>",
+ },
+ {
+ "tag name eof #4",
+ `<a x`,
+ ``,
+ },
+ // Some malformed tags that are missing a '>'.
+ {
+ "malformed tag #0",
+ `<p</p>`,
+ `<p< p="">`,
+ },
+ {
+ "malformed tag #1",
+ `<p </p>`,
+ `<p <="" p="">`,
+ },
+ {
+ "malformed tag #2",
+ `<p id`,
+ ``,
+ },
+ {
+ "malformed tag #3",
+ `<p id=`,
+ ``,
+ },
+ {
+ "malformed tag #4",
+ `<p id=>`,
+ `<p id="">`,
+ },
+ {
+ "malformed tag #5",
+ `<p id=0`,
+ ``,
+ },
+ {
+ "malformed tag #6",
+ `<p id=0</p>`,
+ `<p id="0&lt;/p">`,
+ },
+ {
+ "malformed tag #7",
+ `<p id="0</p>`,
+ ``,
+ },
+ {
+ "malformed tag #8",
+ `<p id="0"</p>`,
+ `<p id="0" <="" p="">`,
+ },
+ {
+ "malformed tag #9",
+ `<p></p id`,
+ `<p>`,
+ },
+ // Raw text and RCDATA.
+ {
+ "basic raw text",
+ "<script><a></b></script>",
+ "<script>$&lt;a&gt;&lt;/b&gt;$</script>",
+ },
+ {
+ "unfinished script end tag",
+ "<SCRIPT>a</SCR",
+ "<script>$a&lt;/SCR",
+ },
+ {
+ "broken script end tag",
+ "<SCRIPT>a</SCR ipt>",
+ "<script>$a&lt;/SCR ipt&gt;",
+ },
+ {
+ "EOF in script end tag",
+ "<SCRIPT>a</SCRipt",
+ "<script>$a&lt;/SCRipt",
+ },
+ {
+ "scriptx end tag",
+ "<SCRIPT>a</SCRiptx",
+ "<script>$a&lt;/SCRiptx",
+ },
+ {
+ "' ' completes script end tag",
+ "<SCRIPT>a</SCRipt ",
+ "<script>$a",
+ },
+ {
+ "'>' completes script end tag",
+ "<SCRIPT>a</SCRipt>",
+ "<script>$a$</script>",
+ },
+ {
+ "self-closing script end tag",
+ "<SCRIPT>a</SCRipt/>",
+ "<script>$a$</script>",
+ },
+ {
+ "nested script tag",
+ "<SCRIPT>a</SCRipt<script>",
+ "<script>$a&lt;/SCRipt&lt;script&gt;",
+ },
+ {
+ "script end tag after unfinished",
+ "<SCRIPT>a</SCRipt</script>",
+ "<script>$a&lt;/SCRipt$</script>",
+ },
+ {
+ "script/style mismatched tags",
+ "<script>a</style>",
+ "<script>$a&lt;/style&gt;",
+ },
+ {
+ "style element with entity",
+ "<style>&apos;",
+ "<style>$&amp;apos;",
+ },
+ {
+ "textarea with tag",
+ "<textarea><div></textarea>",
+ "<textarea>$&lt;div&gt;$</textarea>",
+ },
+ {
+ "title with tag and entity",
+ "<title><b>K&amp;R C</b></title>",
+ "<title>$&lt;b&gt;K&amp;R C&lt;/b&gt;$</title>",
+ },
+ // DOCTYPE tests.
+ {
+ "Proper DOCTYPE",
+ "<!DOCTYPE html>",
+ "<!DOCTYPE html>",
+ },
+ {
+ "DOCTYPE with no space",
+ "<!doctypehtml>",
+ "<!DOCTYPE html>",
+ },
+ {
+ "DOCTYPE with two spaces",
+ "<!doctype html>",
+ "<!DOCTYPE html>",
+ },
+ {
+ "looks like DOCTYPE but isn't",
+ "<!DOCUMENT html>",
+ "<!--DOCUMENT html-->",
+ },
+ {
+ "DOCTYPE at EOF",
+ "<!DOCtype",
+ "<!DOCTYPE >",
+ },
+ // XML processing instructions.
+ {
+ "XML processing instruction",
+ "<?xml?>",
+ "<!--?xml?-->",
+ },
+ // Comments.
+ {
+ "comment0",
+ "abc<b><!-- skipme --></b>def",
+ "abc$<b>$<!-- skipme -->$</b>$def",
+ },
+ {
+ "comment1",
+ "a<!-->z",
+ "a$<!---->$z",
+ },
+ {
+ "comment2",
+ "a<!--->z",
+ "a$<!---->$z",
+ },
+ {
+ "comment3",
+ "a<!--x>-->z",
+ "a$<!--x>-->$z",
+ },
+ {
+ "comment4",
+ "a<!--x->-->z",
+ "a$<!--x->-->$z",
+ },
+ {
+ "comment5",
+ "a<!>z",
+ "a$<!---->$z",
+ },
+ {
+ "comment6",
+ "a<!->z",
+ "a$<!----->$z",
+ },
+ {
+ "comment7",
+ "a<!---<>z",
+ "a$<!---<>z-->",
+ },
+ {
+ "comment8",
+ "a<!--z",
+ "a$<!--z-->",
+ },
+ {
+ "comment9",
+ "a<!--z-",
+ "a$<!--z-->",
+ },
+ {
+ "comment10",
+ "a<!--z--",
+ "a$<!--z-->",
+ },
+ {
+ "comment11",
+ "a<!--z---",
+ "a$<!--z--->",
+ },
+ {
+ "comment12",
+ "a<!--z----",
+ "a$<!--z---->",
+ },
+ {
+ "comment13",
+ "a<!--x--!>z",
+ "a$<!--x-->$z",
+ },
+ // An attribute with a backslash.
+ {
+ "backslash",
+ `<p id="a\"b">`,
+ `<p id="a\" b"="">`,
+ },
+ // Entities, tag name and attribute key lower-casing, and whitespace
+ // normalization within a tag.
+ {
+ "tricky",
+ "<p \t\n iD=\"a&quot;B\" foo=\"bar\"><EM>te&lt;&amp;;xt</em></p>",
+ `<p id="a&#34;B" foo="bar">$<em>$te&lt;&amp;;xt$</em>$</p>`,
+ },
+ // A nonexistent entity. Tokenizing and converting back to a string should
+ // escape the "&" to become "&amp;".
+ {
+ "noSuchEntity",
+ `<a b="c&noSuchEntity;d">&lt;&alsoDoesntExist;&`,
+ `<a b="c&amp;noSuchEntity;d">$&lt;&amp;alsoDoesntExist;&amp;`,
+ },
+ {
+ "entity without semicolon",
+ `&notit;&notin;<a b="q=z&amp=5&notice=hello&not;=world">`,
+ `¬it;∉$<a b="q=z&amp;amp=5&amp;notice=hello¬=world">`,
+ },
+ {
+ "entity with digits",
+ "&frac12;",
+ "½",
+ },
+ // Attribute tests:
+ // http://dev.w3.org/html5/pf-summary/Overview.html#attributes
+ {
+ "Empty attribute",
+ `<input disabled FOO>`,
+ `<input disabled="" foo="">`,
+ },
+ {
+ "Empty attribute, whitespace",
+ `<input disabled FOO >`,
+ `<input disabled="" foo="">`,
+ },
+ {
+ "Unquoted attribute value",
+ `<input value=yes FOO=BAR>`,
+ `<input value="yes" foo="BAR">`,
+ },
+ {
+ "Unquoted attribute value, spaces",
+ `<input value = yes FOO = BAR>`,
+ `<input value="yes" foo="BAR">`,
+ },
+ {
+ "Unquoted attribute value, trailing space",
+ `<input value=yes FOO=BAR >`,
+ `<input value="yes" foo="BAR">`,
+ },
+ {
+ "Single-quoted attribute value",
+ `<input value='yes' FOO='BAR'>`,
+ `<input value="yes" foo="BAR">`,
+ },
+ {
+ "Single-quoted attribute value, trailing space",
+ `<input value='yes' FOO='BAR' >`,
+ `<input value="yes" foo="BAR">`,
+ },
+ {
+ "Double-quoted attribute value",
+ `<input value="I'm an attribute" FOO="BAR">`,
+ `<input value="I&#39;m an attribute" foo="BAR">`,
+ },
+ {
+ "Attribute name characters",
+ `<meta http-equiv="content-type">`,
+ `<meta http-equiv="content-type">`,
+ },
+ {
+ "Mixed attributes",
+ `a<P V="0 1" w='2' X=3 y>z`,
+ `a$<p v="0 1" w="2" x="3" y="">$z`,
+ },
+ {
+ "Attributes with a solitary single quote",
+ `<p id=can't><p id=won't>`,
+ `<p id="can&#39;t">$<p id="won&#39;t">`,
+ },
+}
+
+func TestTokenizer(t *testing.T) {
+loop:
+ for _, tt := range tokenTests {
+ z := NewTokenizer(strings.NewReader(tt.html))
+ if tt.golden != "" {
+ for i, s := range strings.Split(tt.golden, "$") {
+ if z.Next() == ErrorToken {
+ t.Errorf("%s token %d: want %q got error %v", tt.desc, i, s, z.Err())
+ continue loop
+ }
+ actual := z.Token().String()
+ if s != actual {
+ t.Errorf("%s token %d: want %q got %q", tt.desc, i, s, actual)
+ continue loop
+ }
+ }
+ }
+ z.Next()
+ if z.Err() != io.EOF {
+ t.Errorf("%s: want EOF got %q", tt.desc, z.Err())
+ }
+ }
+}
+
+func TestMaxBuffer(t *testing.T) {
+ // Exceeding the maximum buffer size generates ErrBufferExceeded.
+ z := NewTokenizer(strings.NewReader("<" + strings.Repeat("t", 10)))
+ z.SetMaxBuf(5)
+ tt := z.Next()
+ if got, want := tt, ErrorToken; got != want {
+ t.Fatalf("token type: got: %v want: %v", got, want)
+ }
+ if got, want := z.Err(), ErrBufferExceeded; got != want {
+ t.Errorf("error type: got: %v want: %v", got, want)
+ }
+ if got, want := string(z.Raw()), "<tttt"; got != want {
+ t.Fatalf("buffered before overflow: got: %q want: %q", got, want)
+ }
+}
+
+func TestMaxBufferReconstruction(t *testing.T) {
+ // Exceeding the maximum buffer size at any point while tokenizing permits
+ // reconstructing the original input.
+tests:
+ for _, test := range tokenTests {
+ for maxBuf := 1; ; maxBuf++ {
+ r := strings.NewReader(test.html)
+ z := NewTokenizer(r)
+ z.SetMaxBuf(maxBuf)
+ var tokenized bytes.Buffer
+ for {
+ tt := z.Next()
+ tokenized.Write(z.Raw())
+ if tt == ErrorToken {
+ if err := z.Err(); err != io.EOF && err != ErrBufferExceeded {
+ t.Errorf("%s: unexpected error: %v", test.desc, err)
+ }
+ break
+ }
+ }
+ // Anything tokenized along with untokenized input or data left in the reader.
+ assembled, err := ioutil.ReadAll(io.MultiReader(&tokenized, bytes.NewReader(z.Buffered()), r))
+ if err != nil {
+ t.Errorf("%s: ReadAll: %v", test.desc, err)
+ continue tests
+ }
+ if got, want := string(assembled), test.html; got != want {
+ t.Errorf("%s: reassembled html:\n got: %q\nwant: %q", test.desc, got, want)
+ continue tests
+ }
+ // EOF indicates that we completed tokenization and hence found the max
+ // maxBuf that generates ErrBufferExceeded, so continue to the next test.
+ if z.Err() == io.EOF {
+ break
+ }
+ } // buffer sizes
+ } // tests
+}
+
+func TestPassthrough(t *testing.T) {
+ // Accumulating the raw output for each parse event should reconstruct the
+ // original input.
+ for _, test := range tokenTests {
+ z := NewTokenizer(strings.NewReader(test.html))
+ var parsed bytes.Buffer
+ for {
+ tt := z.Next()
+ parsed.Write(z.Raw())
+ if tt == ErrorToken {
+ break
+ }
+ }
+ if got, want := parsed.String(), test.html; got != want {
+ t.Errorf("%s: parsed output:\n got: %q\nwant: %q", test.desc, got, want)
+ }
+ }
+}
+
+func TestBufAPI(t *testing.T) {
+ s := "0<a>1</a>2<b>3<a>4<a>5</a>6</b>7</a>8<a/>9"
+ z := NewTokenizer(bytes.NewBufferString(s))
+ var result bytes.Buffer
+ depth := 0
+loop:
+ for {
+ tt := z.Next()
+ switch tt {
+ case ErrorToken:
+ if z.Err() != io.EOF {
+ t.Error(z.Err())
+ }
+ break loop
+ case TextToken:
+ if depth > 0 {
+ result.Write(z.Text())
+ }
+ case StartTagToken, EndTagToken:
+ tn, _ := z.TagName()
+ if len(tn) == 1 && tn[0] == 'a' {
+ if tt == StartTagToken {
+ depth++
+ } else {
+ depth--
+ }
+ }
+ }
+ }
+ u := "14567"
+ v := string(result.Bytes())
+ if u != v {
+ t.Errorf("TestBufAPI: want %q got %q", u, v)
+ }
+}
+
+func TestConvertNewlines(t *testing.T) {
+ testCases := map[string]string{
+ "Mac\rDOS\r\nUnix\n": "Mac\nDOS\nUnix\n",
+ "Unix\nMac\rDOS\r\n": "Unix\nMac\nDOS\n",
+ "DOS\r\nDOS\r\nDOS\r\n": "DOS\nDOS\nDOS\n",
+ "": "",
+ "\n": "\n",
+ "\n\r": "\n\n",
+ "\r": "\n",
+ "\r\n": "\n",
+ "\r\n\n": "\n\n",
+ "\r\n\r": "\n\n",
+ "\r\n\r\n": "\n\n",
+ "\r\r": "\n\n",
+ "\r\r\n": "\n\n",
+ "\r\r\n\n": "\n\n\n",
+ "\r\r\r\n": "\n\n\n",
+ "\r \n": "\n \n",
+ "xyz": "xyz",
+ }
+ for in, want := range testCases {
+ if got := string(convertNewlines([]byte(in))); got != want {
+ t.Errorf("input %q: got %q, want %q", in, got, want)
+ }
+ }
+}
+
+func TestReaderEdgeCases(t *testing.T) {
+ const s = "<p>An io.Reader can return (0, nil) or (n, io.EOF).</p>"
+ testCases := []io.Reader{
+ &zeroOneByteReader{s: s},
+ &eofStringsReader{s: s},
+ &stuckReader{},
+ }
+ for i, tc := range testCases {
+ got := []TokenType{}
+ z := NewTokenizer(tc)
+ for {
+ tt := z.Next()
+ if tt == ErrorToken {
+ break
+ }
+ got = append(got, tt)
+ }
+ if err := z.Err(); err != nil && err != io.EOF {
+ if err != io.ErrNoProgress {
+ t.Errorf("i=%d: %v", i, err)
+ }
+ continue
+ }
+ want := []TokenType{
+ StartTagToken,
+ TextToken,
+ EndTagToken,
+ }
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("i=%d: got %v, want %v", i, got, want)
+ continue
+ }
+ }
+}
+
+// zeroOneByteReader is like a strings.Reader that alternates between
+// returning 0 bytes and 1 byte at a time.
+type zeroOneByteReader struct {
+ s string
+ n int
+}
+
+func (r *zeroOneByteReader) Read(p []byte) (int, error) {
+ if len(p) == 0 {
+ return 0, nil
+ }
+ if len(r.s) == 0 {
+ return 0, io.EOF
+ }
+ r.n++
+ if r.n%2 != 0 {
+ return 0, nil
+ }
+ p[0], r.s = r.s[0], r.s[1:]
+ return 1, nil
+}
+
+// eofStringsReader is like a strings.Reader but can return an (n, err) where
+// n > 0 && err != nil.
+type eofStringsReader struct {
+ s string
+}
+
+func (r *eofStringsReader) Read(p []byte) (int, error) {
+ n := copy(p, r.s)
+ r.s = r.s[n:]
+ if r.s != "" {
+ return n, nil
+ }
+ return n, io.EOF
+}
+
+// stuckReader is an io.Reader that always returns no data and no error.
+type stuckReader struct{}
+
+func (*stuckReader) Read(p []byte) (int, error) {
+ return 0, nil
+}
+
+const (
+ rawLevel = iota
+ lowLevel
+ highLevel
+)
+
+func benchmarkTokenizer(b *testing.B, level int) {
+ buf, err := ioutil.ReadFile("testdata/go1.html")
+ if err != nil {
+ b.Fatalf("could not read testdata/go1.html: %v", err)
+ }
+ b.SetBytes(int64(len(buf)))
+ runtime.GC()
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ z := NewTokenizer(bytes.NewBuffer(buf))
+ for {
+ tt := z.Next()
+ if tt == ErrorToken {
+ if err := z.Err(); err != nil && err != io.EOF {
+ b.Fatalf("tokenizer error: %v", err)
+ }
+ break
+ }
+ switch level {
+ case rawLevel:
+ // Calling z.Raw just returns the raw bytes of the token. It does
+ // not unescape &lt; to <, or lower-case tag names and attribute keys.
+ z.Raw()
+ case lowLevel:
+ // Caling z.Text, z.TagName and z.TagAttr returns []byte values
+ // whose contents may change on the next call to z.Next.
+ switch tt {
+ case TextToken, CommentToken, DoctypeToken:
+ z.Text()
+ case StartTagToken, SelfClosingTagToken:
+ _, more := z.TagName()
+ for more {
+ _, _, more = z.TagAttr()
+ }
+ case EndTagToken:
+ z.TagName()
+ }
+ case highLevel:
+ // Calling z.Token converts []byte values to strings whose validity
+ // extend beyond the next call to z.Next.
+ z.Token()
+ }
+ }
+ }
+}
+
+func BenchmarkRawLevelTokenizer(b *testing.B) { benchmarkTokenizer(b, rawLevel) }
+func BenchmarkLowLevelTokenizer(b *testing.B) { benchmarkTokenizer(b, lowLevel) }
+func BenchmarkHighLevelTokenizer(b *testing.B) { benchmarkTokenizer(b, highLevel) }
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http/httpproxy/export_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http/httpproxy/export_test.go
new file mode 100644
index 000000000..36b29d2db
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http/httpproxy/export_test.go
@@ -0,0 +1,7 @@
+// 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 httpproxy
+
+var ExportUseProxy = (*Config).useProxy
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http/httpproxy/go19_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http/httpproxy/go19_test.go
new file mode 100644
index 000000000..2117ca569
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http/httpproxy/go19_test.go
@@ -0,0 +1,13 @@
+// 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.
+
+// +build go1.9
+
+package httpproxy_test
+
+import "testing"
+
+func init() {
+ setHelper = func(t *testing.T) { t.Helper() }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http/httpproxy/proxy.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http/httpproxy/proxy.go
new file mode 100644
index 000000000..cbe1d2a0a
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http/httpproxy/proxy.go
@@ -0,0 +1,239 @@
+// 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 httpproxy provides support for HTTP proxy determination
+// based on environment variables, as provided by net/http's
+// ProxyFromEnvironment function.
+//
+// The API is not subject to the Go 1 compatibility promise and may change at
+// any time.
+package httpproxy
+
+import (
+ "errors"
+ "fmt"
+ "net"
+ "net/url"
+ "os"
+ "strings"
+ "unicode/utf8"
+
+ "golang.org/x/net/idna"
+)
+
+// Config holds configuration for HTTP proxy settings. See
+// FromEnvironment for details.
+type Config struct {
+ // HTTPProxy represents the value of the HTTP_PROXY or
+ // http_proxy environment variable. It will be used as the proxy
+ // URL for HTTP requests and HTTPS requests unless overridden by
+ // HTTPSProxy or NoProxy.
+ HTTPProxy string
+
+ // HTTPSProxy represents the HTTPS_PROXY or https_proxy
+ // environment variable. It will be used as the proxy URL for
+ // HTTPS requests unless overridden by NoProxy.
+ HTTPSProxy string
+
+ // NoProxy represents the NO_PROXY or no_proxy environment
+ // variable. It specifies URLs that should be excluded from
+ // proxying as a comma-separated list of domain names or a
+ // single asterisk (*) to indicate that no proxying should be
+ // done. A domain name matches that name and all subdomains. A
+ // domain name with a leading "." matches subdomains only. For
+ // example "foo.com" matches "foo.com" and "bar.foo.com";
+ // ".y.com" matches "x.y.com" but not "y.com".
+ NoProxy string
+
+ // CGI holds whether the current process is running
+ // as a CGI handler (FromEnvironment infers this from the
+ // 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.
+ CGI bool
+}
+
+// FromEnvironment returns a Config instance populated from the
+// environment variables HTTP_PROXY, HTTPS_PROXY and NO_PROXY (or the
+// lowercase versions thereof). HTTPS_PROXY takes precedence over
+// HTTP_PROXY for https requests.
+//
+// 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"),
+ CGI: os.Getenv("REQUEST_METHOD") != "",
+ }
+}
+
+func getEnvAny(names ...string) string {
+ for _, n := range names {
+ if val := os.Getenv(n); val != "" {
+ return val
+ }
+ }
+ return ""
+}
+
+// ProxyFunc returns a function that determines the proxy URL to use for
+// a given request URL. Changing the contents of cfg will not affect
+// proxy functions created earlier.
+//
+// A nil URL and nil error are returned if no proxy is defined in the
+// 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" (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) {
+ // Prevent Config changes from affecting the function calculation.
+ // TODO Preprocess proxy settings for more efficient evaluation.
+ cfg1 := *cfg
+ return cfg1.proxyForURL
+}
+
+func (cfg *Config) proxyForURL(reqURL *url.URL) (*url.URL, error) {
+ var proxy string
+ if reqURL.Scheme == "https" {
+ proxy = cfg.HTTPSProxy
+ }
+ if proxy == "" {
+ proxy = cfg.HTTPProxy
+ if proxy != "" && cfg.CGI {
+ return nil, errors.New("refusing to use HTTP_PROXY value in CGI environment; see golang.org/s/cgihttpproxy")
+ }
+ }
+ if proxy == "" {
+ return nil, nil
+ }
+ if !cfg.useProxy(canonicalAddr(reqURL)) {
+ return nil, nil
+ }
+ proxyURL, err := url.Parse(proxy)
+ if err != nil ||
+ (proxyURL.Scheme != "http" &&
+ proxyURL.Scheme != "https" &&
+ proxyURL.Scheme != "socks5") {
+ // proxy was bogus. Try prepending "http://" to it and
+ // see if that parses correctly. If not, we fall
+ // through and complain about the original one.
+ if proxyURL, err := url.Parse("http://" + proxy); err == nil {
+ return proxyURL, nil
+ }
+ }
+ if err != nil {
+ return nil, fmt.Errorf("invalid proxy address %q: %v", proxy, err)
+ }
+ return proxyURL, nil
+}
+
+// useProxy reports whether requests to addr should use a proxy,
+// according to the NO_PROXY or no_proxy environment variable.
+// addr is always a canonicalAddr with a host and port.
+func (cfg *Config) useProxy(addr string) bool {
+ if len(addr) == 0 {
+ return true
+ }
+ host, _, err := net.SplitHostPort(addr)
+ if err != nil {
+ return false
+ }
+ if host == "localhost" {
+ return false
+ }
+ if ip := net.ParseIP(host); ip != nil {
+ if ip.IsLoopback() {
+ return false
+ }
+ }
+
+ noProxy := cfg.NoProxy
+ if noProxy == "*" {
+ return false
+ }
+
+ addr = strings.ToLower(strings.TrimSpace(addr))
+ if hasPort(addr) {
+ addr = addr[:strings.LastIndex(addr, ":")]
+ }
+
+ for _, p := range strings.Split(noProxy, ",") {
+ p = strings.ToLower(strings.TrimSpace(p))
+ if len(p) == 0 {
+ continue
+ }
+ if hasPort(p) {
+ p = p[:strings.LastIndex(p, ":")]
+ }
+ if addr == p {
+ return false
+ }
+ if len(p) == 0 {
+ // There is no host part, likely the entry is malformed; ignore.
+ continue
+ }
+ if p[0] == '.' && (strings.HasSuffix(addr, p) || addr == p[1:]) {
+ // no_proxy ".foo.com" matches "bar.foo.com" or "foo.com"
+ return false
+ }
+ if p[0] != '.' && strings.HasSuffix(addr, p) && addr[len(addr)-len(p)-1] == '.' {
+ // no_proxy "foo.com" matches "bar.foo.com"
+ return false
+ }
+ }
+ return true
+}
+
+var portMap = map[string]string{
+ "http": "80",
+ "https": "443",
+ "socks5": "1080",
+}
+
+// canonicalAddr returns url.Host but always with a ":port" suffix
+func canonicalAddr(url *url.URL) string {
+ addr := url.Hostname()
+ if v, err := idnaASCII(addr); err == nil {
+ addr = v
+ }
+ port := url.Port()
+ if port == "" {
+ port = portMap[url.Scheme]
+ }
+ return net.JoinHostPort(addr, port)
+}
+
+// Given a string of the form "host", "host:port", or "[ipv6::address]:port",
+// return true if the string includes a port.
+func hasPort(s string) bool { return strings.LastIndex(s, ":") > strings.LastIndex(s, "]") }
+
+func idnaASCII(v string) (string, error) {
+ // TODO: Consider removing this check after verifying performance is okay.
+ // Right now punycode verification, length checks, context checks, and the
+ // permissible character tests are all omitted. It also prevents the ToASCII
+ // call from salvaging an invalid IDN, when possible. As a result it may be
+ // possible to have two IDNs that appear identical to the user where the
+ // ASCII-only version causes an error downstream whereas the non-ASCII
+ // version does not.
+ // Note that for correct ASCII IDNs ToASCII will only do considerably more
+ // work, but it will not cause an allocation.
+ if isASCII(v) {
+ return v, nil
+ }
+ return idna.Lookup.ToASCII(v)
+}
+
+func isASCII(s string) bool {
+ for i := 0; i < len(s); i++ {
+ if s[i] >= utf8.RuneSelf {
+ return false
+ }
+ }
+ return true
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http/httpproxy/proxy_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http/httpproxy/proxy_test.go
new file mode 100644
index 000000000..e4af199c6
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http/httpproxy/proxy_test.go
@@ -0,0 +1,301 @@
+// 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 httpproxy_test
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "net/url"
+ "os"
+ "strings"
+ "testing"
+
+ "golang.org/x/net/http/httpproxy"
+)
+
+// setHelper calls t.Helper() for Go 1.9+ (see go19_test.go) and does nothing otherwise.
+var setHelper = func(t *testing.T) {}
+
+type proxyForURLTest struct {
+ cfg httpproxy.Config
+ req string // URL to fetch; blank means "http://example.com"
+ want string
+ wanterr error
+}
+
+func (t proxyForURLTest) String() string {
+ var buf bytes.Buffer
+ space := func() {
+ if buf.Len() > 0 {
+ buf.WriteByte(' ')
+ }
+ }
+ if t.cfg.HTTPProxy != "" {
+ fmt.Fprintf(&buf, "http_proxy=%q", t.cfg.HTTPProxy)
+ }
+ if t.cfg.HTTPSProxy != "" {
+ space()
+ fmt.Fprintf(&buf, "https_proxy=%q", t.cfg.HTTPSProxy)
+ }
+ if t.cfg.NoProxy != "" {
+ space()
+ fmt.Fprintf(&buf, "no_proxy=%q", t.cfg.NoProxy)
+ }
+ req := "http://example.com"
+ if t.req != "" {
+ req = t.req
+ }
+ space()
+ fmt.Fprintf(&buf, "req=%q", req)
+ return strings.TrimSpace(buf.String())
+}
+
+var proxyForURLTests = []proxyForURLTest{{
+ cfg: httpproxy.Config{
+ HTTPProxy: "127.0.0.1:8080",
+ },
+ want: "http://127.0.0.1:8080",
+}, {
+ cfg: httpproxy.Config{
+ HTTPProxy: "cache.corp.example.com:1234",
+ },
+ want: "http://cache.corp.example.com:1234",
+}, {
+ cfg: httpproxy.Config{
+ HTTPProxy: "cache.corp.example.com",
+ },
+ want: "http://cache.corp.example.com",
+}, {
+ cfg: httpproxy.Config{
+ HTTPProxy: "https://cache.corp.example.com",
+ },
+ want: "https://cache.corp.example.com",
+}, {
+ cfg: httpproxy.Config{
+ HTTPProxy: "http://127.0.0.1:8080",
+ },
+ want: "http://127.0.0.1:8080",
+}, {
+ cfg: httpproxy.Config{
+ HTTPProxy: "https://127.0.0.1:8080",
+ },
+ want: "https://127.0.0.1:8080",
+}, {
+ cfg: httpproxy.Config{
+ HTTPProxy: "socks5://127.0.0.1",
+ },
+ want: "socks5://127.0.0.1",
+}, {
+ // Don't use secure for http
+ cfg: httpproxy.Config{
+ HTTPProxy: "http.proxy.tld",
+ HTTPSProxy: "secure.proxy.tld",
+ },
+ req: "http://insecure.tld/",
+ want: "http://http.proxy.tld",
+}, {
+ // Use secure for https.
+ cfg: httpproxy.Config{
+ HTTPProxy: "http.proxy.tld",
+ HTTPSProxy: "secure.proxy.tld",
+ },
+ req: "https://secure.tld/",
+ want: "http://secure.proxy.tld",
+}, {
+ cfg: httpproxy.Config{
+ HTTPProxy: "http.proxy.tld",
+ HTTPSProxy: "https://secure.proxy.tld",
+ },
+ req: "https://secure.tld/",
+ want: "https://secure.proxy.tld",
+}, {
+ // Issue 16405: don't use HTTP_PROXY in a CGI environment,
+ // where HTTP_PROXY can be attacker-controlled.
+ cfg: httpproxy.Config{
+ HTTPProxy: "http://10.1.2.3:8080",
+ CGI: true,
+ },
+ want: "<nil>",
+ wanterr: errors.New("refusing to use HTTP_PROXY value in CGI environment; see golang.org/s/cgihttpproxy"),
+}, {
+ // HTTPS proxy is still used even in CGI environment.
+ // (perhaps dubious but it's the historical behaviour).
+ cfg: httpproxy.Config{
+ HTTPSProxy: "https://secure.proxy.tld",
+ CGI: true,
+ },
+ req: "https://secure.tld/",
+ want: "https://secure.proxy.tld",
+}, {
+ want: "<nil>",
+}, {
+ cfg: httpproxy.Config{
+ NoProxy: "example.com",
+ HTTPProxy: "proxy",
+ },
+ req: "http://example.com/",
+ want: "<nil>",
+}, {
+ cfg: httpproxy.Config{
+ NoProxy: ".example.com",
+ HTTPProxy: "proxy",
+ },
+ req: "http://example.com/",
+ want: "<nil>",
+}, {
+ cfg: httpproxy.Config{
+ NoProxy: "ample.com",
+ HTTPProxy: "proxy",
+ },
+ req: "http://example.com/",
+ want: "http://proxy",
+}, {
+ cfg: httpproxy.Config{
+ NoProxy: "example.com",
+ HTTPProxy: "proxy",
+ },
+ req: "http://foo.example.com/",
+ want: "<nil>",
+}, {
+ cfg: httpproxy.Config{
+ NoProxy: ".foo.com",
+ HTTPProxy: "proxy",
+ },
+ req: "http://example.com/",
+ want: "http://proxy",
+}}
+
+func testProxyForURL(t *testing.T, tt proxyForURLTest) {
+ setHelper(t)
+ reqURLStr := tt.req
+ if reqURLStr == "" {
+ reqURLStr = "http://example.com"
+ }
+ reqURL, err := url.Parse(reqURLStr)
+ if err != nil {
+ t.Errorf("invalid URL %q", reqURLStr)
+ return
+ }
+ cfg := tt.cfg
+ proxyForURL := cfg.ProxyFunc()
+ url, err := proxyForURL(reqURL)
+ if g, e := fmt.Sprintf("%v", err), fmt.Sprintf("%v", tt.wanterr); g != e {
+ t.Errorf("%v: got error = %q, want %q", tt, g, e)
+ return
+ }
+ if got := fmt.Sprintf("%s", url); got != tt.want {
+ t.Errorf("%v: got URL = %q, want %q", tt, url, tt.want)
+ }
+
+ // Check that changing the Config doesn't change the results
+ // of the functuon.
+ cfg = httpproxy.Config{}
+ url, err = proxyForURL(reqURL)
+ if g, e := fmt.Sprintf("%v", err), fmt.Sprintf("%v", tt.wanterr); g != e {
+ t.Errorf("(after mutating config) %v: got error = %q, want %q", tt, g, e)
+ return
+ }
+ if got := fmt.Sprintf("%s", url); got != tt.want {
+ t.Errorf("(after mutating config) %v: got URL = %q, want %q", tt, url, tt.want)
+ }
+}
+
+func TestProxyForURL(t *testing.T) {
+ for _, tt := range proxyForURLTests {
+ testProxyForURL(t, tt)
+ }
+}
+
+func TestFromEnvironment(t *testing.T) {
+ os.Setenv("HTTP_PROXY", "httpproxy")
+ os.Setenv("HTTPS_PROXY", "httpsproxy")
+ os.Setenv("NO_PROXY", "noproxy")
+ os.Setenv("REQUEST_METHOD", "")
+ got := httpproxy.FromEnvironment()
+ want := httpproxy.Config{
+ HTTPProxy: "httpproxy",
+ HTTPSProxy: "httpsproxy",
+ NoProxy: "noproxy",
+ }
+ if *got != want {
+ t.Errorf("unexpected proxy config, got %#v want %#v", got, want)
+ }
+}
+
+func TestFromEnvironmentWithRequestMethod(t *testing.T) {
+ os.Setenv("HTTP_PROXY", "httpproxy")
+ os.Setenv("HTTPS_PROXY", "httpsproxy")
+ os.Setenv("NO_PROXY", "noproxy")
+ os.Setenv("REQUEST_METHOD", "PUT")
+ got := httpproxy.FromEnvironment()
+ want := httpproxy.Config{
+ HTTPProxy: "httpproxy",
+ HTTPSProxy: "httpsproxy",
+ NoProxy: "noproxy",
+ CGI: true,
+ }
+ if *got != want {
+ t.Errorf("unexpected proxy config, got %#v want %#v", got, want)
+ }
+}
+
+func TestFromEnvironmentLowerCase(t *testing.T) {
+ os.Setenv("http_proxy", "httpproxy")
+ os.Setenv("https_proxy", "httpsproxy")
+ os.Setenv("no_proxy", "noproxy")
+ os.Setenv("REQUEST_METHOD", "")
+ got := httpproxy.FromEnvironment()
+ want := httpproxy.Config{
+ HTTPProxy: "httpproxy",
+ HTTPSProxy: "httpsproxy",
+ NoProxy: "noproxy",
+ }
+ if *got != want {
+ t.Errorf("unexpected proxy config, got %#v want %#v", got, want)
+ }
+}
+
+var UseProxyTests = []struct {
+ host string
+ match bool
+}{
+ // Never proxy localhost:
+ {"localhost", false},
+ {"127.0.0.1", false},
+ {"127.0.0.2", false},
+ {"[::1]", false},
+ {"[::2]", true}, // not a loopback address
+
+ {"barbaz.net", false}, // match as .barbaz.net
+ {"foobar.com", false}, // have a port but match
+ {"foofoobar.com", true}, // not match as a part of foobar.com
+ {"baz.com", true}, // not match as a part of barbaz.com
+ {"localhost.net", true}, // not match as suffix of address
+ {"local.localhost", true}, // not match as prefix as address
+ {"barbarbaz.net", true}, // not match because NO_PROXY have a '.'
+ {"www.foobar.com", false}, // match because NO_PROXY includes "foobar.com"
+}
+
+func TestUseProxy(t *testing.T) {
+ cfg := &httpproxy.Config{
+ NoProxy: "foobar.com, .barbaz.net",
+ }
+ for _, test := range UseProxyTests {
+ if httpproxy.ExportUseProxy(cfg, test.host+":80") != test.match {
+ t.Errorf("useProxy(%v) = %v, want %v", test.host, !test.match, test.match)
+ }
+ }
+}
+
+func TestInvalidNoProxy(t *testing.T) {
+ cfg := &httpproxy.Config{
+ NoProxy: ":1",
+ }
+ ok := httpproxy.ExportUseProxy(cfg, "example.com:80") // should not panic
+ if !ok {
+ t.Errorf("useProxy unexpected return; got false; want true")
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/.gitignore b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/.gitignore
new file mode 100644
index 000000000..190f12234
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/.gitignore
@@ -0,0 +1,2 @@
+*~
+h2i/h2i
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/Dockerfile b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/Dockerfile
new file mode 100644
index 000000000..53fc52579
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/Dockerfile
@@ -0,0 +1,51 @@
+#
+# This Dockerfile builds a recent curl with HTTP/2 client support, using
+# a recent nghttp2 build.
+#
+# See the Makefile for how to tag it. If Docker and that image is found, the
+# Go tests use this curl binary for integration tests.
+#
+
+FROM ubuntu:trusty
+
+RUN apt-get update && \
+ apt-get upgrade -y && \
+ apt-get install -y git-core build-essential wget
+
+RUN apt-get install -y --no-install-recommends \
+ autotools-dev libtool pkg-config zlib1g-dev \
+ libcunit1-dev libssl-dev libxml2-dev libevent-dev \
+ automake autoconf
+
+# The list of packages nghttp2 recommends for h2load:
+RUN apt-get install -y --no-install-recommends make binutils \
+ autoconf automake autotools-dev \
+ libtool pkg-config zlib1g-dev libcunit1-dev libssl-dev libxml2-dev \
+ libev-dev libevent-dev libjansson-dev libjemalloc-dev \
+ cython python3.4-dev python-setuptools
+
+# Note: setting NGHTTP2_VER before the git clone, so an old git clone isn't cached:
+ENV NGHTTP2_VER 895da9a
+RUN cd /root && git clone https://github.com/tatsuhiro-t/nghttp2.git
+
+WORKDIR /root/nghttp2
+RUN git reset --hard $NGHTTP2_VER
+RUN autoreconf -i
+RUN automake
+RUN autoconf
+RUN ./configure
+RUN make
+RUN make install
+
+WORKDIR /root
+RUN wget http://curl.haxx.se/download/curl-7.45.0.tar.gz
+RUN tar -zxvf curl-7.45.0.tar.gz
+WORKDIR /root/curl-7.45.0
+RUN ./configure --with-ssl --with-nghttp2=/usr/local
+RUN make
+RUN make install
+RUN ldconfig
+
+CMD ["-h"]
+ENTRYPOINT ["/usr/local/bin/curl"]
+
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/Makefile b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/Makefile
new file mode 100644
index 000000000..55fd826f7
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/Makefile
@@ -0,0 +1,3 @@
+curlimage:
+ docker build -t gohttp2/curl .
+
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/README b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/README
new file mode 100644
index 000000000..360d5aa37
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/README
@@ -0,0 +1,20 @@
+This is a work-in-progress HTTP/2 implementation for Go.
+
+It will eventually live in the Go standard library and won't require
+any changes to your code to use. It will just be automatic.
+
+Status:
+
+* The server support is pretty good. A few things are missing
+ but are being worked on.
+* The client work has just started but shares a lot of code
+ is coming along much quicker.
+
+Docs are at https://godoc.org/golang.org/x/net/http2
+
+Demo test server at https://http2.golang.org/
+
+Help & bug reports welcome!
+
+Contributing: https://golang.org/doc/contribute.html
+Bugs: https://golang.org/issue/new?title=x/net/http2:+
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/ciphers.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/ciphers.go
new file mode 100644
index 000000000..698860b77
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/ciphers.go
@@ -0,0 +1,641 @@
+// 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 http2
+
+// A list of the possible cipher suite ids. Taken from
+// http://www.iana.org/assignments/tls-parameters/tls-parameters.txt
+
+const (
+ cipher_TLS_NULL_WITH_NULL_NULL uint16 = 0x0000
+ cipher_TLS_RSA_WITH_NULL_MD5 uint16 = 0x0001
+ cipher_TLS_RSA_WITH_NULL_SHA uint16 = 0x0002
+ cipher_TLS_RSA_EXPORT_WITH_RC4_40_MD5 uint16 = 0x0003
+ cipher_TLS_RSA_WITH_RC4_128_MD5 uint16 = 0x0004
+ cipher_TLS_RSA_WITH_RC4_128_SHA uint16 = 0x0005
+ cipher_TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 uint16 = 0x0006
+ cipher_TLS_RSA_WITH_IDEA_CBC_SHA uint16 = 0x0007
+ cipher_TLS_RSA_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x0008
+ cipher_TLS_RSA_WITH_DES_CBC_SHA uint16 = 0x0009
+ cipher_TLS_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x000A
+ cipher_TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x000B
+ cipher_TLS_DH_DSS_WITH_DES_CBC_SHA uint16 = 0x000C
+ cipher_TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA uint16 = 0x000D
+ cipher_TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x000E
+ cipher_TLS_DH_RSA_WITH_DES_CBC_SHA uint16 = 0x000F
+ cipher_TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x0010
+ cipher_TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x0011
+ cipher_TLS_DHE_DSS_WITH_DES_CBC_SHA uint16 = 0x0012
+ cipher_TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA uint16 = 0x0013
+ cipher_TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x0014
+ cipher_TLS_DHE_RSA_WITH_DES_CBC_SHA uint16 = 0x0015
+ cipher_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x0016
+ cipher_TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 uint16 = 0x0017
+ cipher_TLS_DH_anon_WITH_RC4_128_MD5 uint16 = 0x0018
+ cipher_TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x0019
+ cipher_TLS_DH_anon_WITH_DES_CBC_SHA uint16 = 0x001A
+ cipher_TLS_DH_anon_WITH_3DES_EDE_CBC_SHA uint16 = 0x001B
+ // Reserved uint16 = 0x001C-1D
+ cipher_TLS_KRB5_WITH_DES_CBC_SHA uint16 = 0x001E
+ cipher_TLS_KRB5_WITH_3DES_EDE_CBC_SHA uint16 = 0x001F
+ cipher_TLS_KRB5_WITH_RC4_128_SHA uint16 = 0x0020
+ cipher_TLS_KRB5_WITH_IDEA_CBC_SHA uint16 = 0x0021
+ cipher_TLS_KRB5_WITH_DES_CBC_MD5 uint16 = 0x0022
+ cipher_TLS_KRB5_WITH_3DES_EDE_CBC_MD5 uint16 = 0x0023
+ cipher_TLS_KRB5_WITH_RC4_128_MD5 uint16 = 0x0024
+ cipher_TLS_KRB5_WITH_IDEA_CBC_MD5 uint16 = 0x0025
+ cipher_TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA uint16 = 0x0026
+ cipher_TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA uint16 = 0x0027
+ cipher_TLS_KRB5_EXPORT_WITH_RC4_40_SHA uint16 = 0x0028
+ cipher_TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5 uint16 = 0x0029
+ cipher_TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5 uint16 = 0x002A
+ cipher_TLS_KRB5_EXPORT_WITH_RC4_40_MD5 uint16 = 0x002B
+ cipher_TLS_PSK_WITH_NULL_SHA uint16 = 0x002C
+ cipher_TLS_DHE_PSK_WITH_NULL_SHA uint16 = 0x002D
+ cipher_TLS_RSA_PSK_WITH_NULL_SHA uint16 = 0x002E
+ cipher_TLS_RSA_WITH_AES_128_CBC_SHA uint16 = 0x002F
+ cipher_TLS_DH_DSS_WITH_AES_128_CBC_SHA uint16 = 0x0030
+ cipher_TLS_DH_RSA_WITH_AES_128_CBC_SHA uint16 = 0x0031
+ cipher_TLS_DHE_DSS_WITH_AES_128_CBC_SHA uint16 = 0x0032
+ cipher_TLS_DHE_RSA_WITH_AES_128_CBC_SHA uint16 = 0x0033
+ cipher_TLS_DH_anon_WITH_AES_128_CBC_SHA uint16 = 0x0034
+ cipher_TLS_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0035
+ cipher_TLS_DH_DSS_WITH_AES_256_CBC_SHA uint16 = 0x0036
+ cipher_TLS_DH_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0037
+ cipher_TLS_DHE_DSS_WITH_AES_256_CBC_SHA uint16 = 0x0038
+ cipher_TLS_DHE_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0039
+ cipher_TLS_DH_anon_WITH_AES_256_CBC_SHA uint16 = 0x003A
+ cipher_TLS_RSA_WITH_NULL_SHA256 uint16 = 0x003B
+ cipher_TLS_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0x003C
+ cipher_TLS_RSA_WITH_AES_256_CBC_SHA256 uint16 = 0x003D
+ cipher_TLS_DH_DSS_WITH_AES_128_CBC_SHA256 uint16 = 0x003E
+ cipher_TLS_DH_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0x003F
+ cipher_TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 uint16 = 0x0040
+ cipher_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0041
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0042
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0043
+ cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0044
+ cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0045
+ cipher_TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0046
+ // Reserved uint16 = 0x0047-4F
+ // Reserved uint16 = 0x0050-58
+ // Reserved uint16 = 0x0059-5C
+ // Unassigned uint16 = 0x005D-5F
+ // Reserved uint16 = 0x0060-66
+ cipher_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0x0067
+ cipher_TLS_DH_DSS_WITH_AES_256_CBC_SHA256 uint16 = 0x0068
+ cipher_TLS_DH_RSA_WITH_AES_256_CBC_SHA256 uint16 = 0x0069
+ cipher_TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 uint16 = 0x006A
+ cipher_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 uint16 = 0x006B
+ cipher_TLS_DH_anon_WITH_AES_128_CBC_SHA256 uint16 = 0x006C
+ cipher_TLS_DH_anon_WITH_AES_256_CBC_SHA256 uint16 = 0x006D
+ // Unassigned uint16 = 0x006E-83
+ cipher_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0084
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0085
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0086
+ cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0087
+ cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0088
+ cipher_TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0089
+ cipher_TLS_PSK_WITH_RC4_128_SHA uint16 = 0x008A
+ cipher_TLS_PSK_WITH_3DES_EDE_CBC_SHA uint16 = 0x008B
+ cipher_TLS_PSK_WITH_AES_128_CBC_SHA uint16 = 0x008C
+ cipher_TLS_PSK_WITH_AES_256_CBC_SHA uint16 = 0x008D
+ cipher_TLS_DHE_PSK_WITH_RC4_128_SHA uint16 = 0x008E
+ cipher_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA uint16 = 0x008F
+ cipher_TLS_DHE_PSK_WITH_AES_128_CBC_SHA uint16 = 0x0090
+ cipher_TLS_DHE_PSK_WITH_AES_256_CBC_SHA uint16 = 0x0091
+ cipher_TLS_RSA_PSK_WITH_RC4_128_SHA uint16 = 0x0092
+ cipher_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA uint16 = 0x0093
+ cipher_TLS_RSA_PSK_WITH_AES_128_CBC_SHA uint16 = 0x0094
+ cipher_TLS_RSA_PSK_WITH_AES_256_CBC_SHA uint16 = 0x0095
+ cipher_TLS_RSA_WITH_SEED_CBC_SHA uint16 = 0x0096
+ cipher_TLS_DH_DSS_WITH_SEED_CBC_SHA uint16 = 0x0097
+ cipher_TLS_DH_RSA_WITH_SEED_CBC_SHA uint16 = 0x0098
+ cipher_TLS_DHE_DSS_WITH_SEED_CBC_SHA uint16 = 0x0099
+ cipher_TLS_DHE_RSA_WITH_SEED_CBC_SHA uint16 = 0x009A
+ cipher_TLS_DH_anon_WITH_SEED_CBC_SHA uint16 = 0x009B
+ cipher_TLS_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0x009C
+ cipher_TLS_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0x009D
+ cipher_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0x009E
+ cipher_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0x009F
+ cipher_TLS_DH_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0x00A0
+ cipher_TLS_DH_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0x00A1
+ cipher_TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 uint16 = 0x00A2
+ cipher_TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 uint16 = 0x00A3
+ cipher_TLS_DH_DSS_WITH_AES_128_GCM_SHA256 uint16 = 0x00A4
+ cipher_TLS_DH_DSS_WITH_AES_256_GCM_SHA384 uint16 = 0x00A5
+ cipher_TLS_DH_anon_WITH_AES_128_GCM_SHA256 uint16 = 0x00A6
+ cipher_TLS_DH_anon_WITH_AES_256_GCM_SHA384 uint16 = 0x00A7
+ cipher_TLS_PSK_WITH_AES_128_GCM_SHA256 uint16 = 0x00A8
+ cipher_TLS_PSK_WITH_AES_256_GCM_SHA384 uint16 = 0x00A9
+ cipher_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 uint16 = 0x00AA
+ cipher_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 uint16 = 0x00AB
+ cipher_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 uint16 = 0x00AC
+ cipher_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 uint16 = 0x00AD
+ cipher_TLS_PSK_WITH_AES_128_CBC_SHA256 uint16 = 0x00AE
+ cipher_TLS_PSK_WITH_AES_256_CBC_SHA384 uint16 = 0x00AF
+ cipher_TLS_PSK_WITH_NULL_SHA256 uint16 = 0x00B0
+ cipher_TLS_PSK_WITH_NULL_SHA384 uint16 = 0x00B1
+ cipher_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 uint16 = 0x00B2
+ cipher_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 uint16 = 0x00B3
+ cipher_TLS_DHE_PSK_WITH_NULL_SHA256 uint16 = 0x00B4
+ cipher_TLS_DHE_PSK_WITH_NULL_SHA384 uint16 = 0x00B5
+ cipher_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 uint16 = 0x00B6
+ cipher_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 uint16 = 0x00B7
+ cipher_TLS_RSA_PSK_WITH_NULL_SHA256 uint16 = 0x00B8
+ cipher_TLS_RSA_PSK_WITH_NULL_SHA384 uint16 = 0x00B9
+ cipher_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BA
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BB
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BC
+ cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BD
+ cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BE
+ cipher_TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BF
+ cipher_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C0
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C1
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C2
+ cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C3
+ cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C4
+ cipher_TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C5
+ // Unassigned uint16 = 0x00C6-FE
+ cipher_TLS_EMPTY_RENEGOTIATION_INFO_SCSV uint16 = 0x00FF
+ // Unassigned uint16 = 0x01-55,*
+ cipher_TLS_FALLBACK_SCSV uint16 = 0x5600
+ // Unassigned uint16 = 0x5601 - 0xC000
+ cipher_TLS_ECDH_ECDSA_WITH_NULL_SHA uint16 = 0xC001
+ cipher_TLS_ECDH_ECDSA_WITH_RC4_128_SHA uint16 = 0xC002
+ cipher_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC003
+ cipher_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA uint16 = 0xC004
+ cipher_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA uint16 = 0xC005
+ cipher_TLS_ECDHE_ECDSA_WITH_NULL_SHA uint16 = 0xC006
+ cipher_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA uint16 = 0xC007
+ cipher_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC008
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA uint16 = 0xC009
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA uint16 = 0xC00A
+ cipher_TLS_ECDH_RSA_WITH_NULL_SHA uint16 = 0xC00B
+ cipher_TLS_ECDH_RSA_WITH_RC4_128_SHA uint16 = 0xC00C
+ cipher_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC00D
+ cipher_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA uint16 = 0xC00E
+ cipher_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA uint16 = 0xC00F
+ cipher_TLS_ECDHE_RSA_WITH_NULL_SHA uint16 = 0xC010
+ cipher_TLS_ECDHE_RSA_WITH_RC4_128_SHA uint16 = 0xC011
+ cipher_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC012
+ cipher_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA uint16 = 0xC013
+ cipher_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA uint16 = 0xC014
+ cipher_TLS_ECDH_anon_WITH_NULL_SHA uint16 = 0xC015
+ cipher_TLS_ECDH_anon_WITH_RC4_128_SHA uint16 = 0xC016
+ cipher_TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA uint16 = 0xC017
+ cipher_TLS_ECDH_anon_WITH_AES_128_CBC_SHA uint16 = 0xC018
+ cipher_TLS_ECDH_anon_WITH_AES_256_CBC_SHA uint16 = 0xC019
+ cipher_TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC01A
+ cipher_TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC01B
+ cipher_TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA uint16 = 0xC01C
+ cipher_TLS_SRP_SHA_WITH_AES_128_CBC_SHA uint16 = 0xC01D
+ cipher_TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA uint16 = 0xC01E
+ cipher_TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA uint16 = 0xC01F
+ cipher_TLS_SRP_SHA_WITH_AES_256_CBC_SHA uint16 = 0xC020
+ cipher_TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA uint16 = 0xC021
+ cipher_TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA uint16 = 0xC022
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 uint16 = 0xC023
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 uint16 = 0xC024
+ cipher_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 uint16 = 0xC025
+ cipher_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 uint16 = 0xC026
+ cipher_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0xC027
+ cipher_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 uint16 = 0xC028
+ cipher_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0xC029
+ cipher_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 uint16 = 0xC02A
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 uint16 = 0xC02B
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 uint16 = 0xC02C
+ cipher_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 uint16 = 0xC02D
+ cipher_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 uint16 = 0xC02E
+ cipher_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0xC02F
+ cipher_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0xC030
+ cipher_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0xC031
+ cipher_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0xC032
+ cipher_TLS_ECDHE_PSK_WITH_RC4_128_SHA uint16 = 0xC033
+ cipher_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA uint16 = 0xC034
+ cipher_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA uint16 = 0xC035
+ cipher_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA uint16 = 0xC036
+ cipher_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 uint16 = 0xC037
+ cipher_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 uint16 = 0xC038
+ cipher_TLS_ECDHE_PSK_WITH_NULL_SHA uint16 = 0xC039
+ cipher_TLS_ECDHE_PSK_WITH_NULL_SHA256 uint16 = 0xC03A
+ cipher_TLS_ECDHE_PSK_WITH_NULL_SHA384 uint16 = 0xC03B
+ cipher_TLS_RSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC03C
+ cipher_TLS_RSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC03D
+ cipher_TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC03E
+ cipher_TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC03F
+ cipher_TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC040
+ cipher_TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC041
+ cipher_TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC042
+ cipher_TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC043
+ cipher_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC044
+ cipher_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC045
+ cipher_TLS_DH_anon_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC046
+ cipher_TLS_DH_anon_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC047
+ cipher_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC048
+ cipher_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC049
+ cipher_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC04A
+ cipher_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC04B
+ cipher_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC04C
+ cipher_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC04D
+ cipher_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC04E
+ cipher_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC04F
+ cipher_TLS_RSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC050
+ cipher_TLS_RSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC051
+ cipher_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC052
+ cipher_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC053
+ cipher_TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC054
+ cipher_TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC055
+ cipher_TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC056
+ cipher_TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC057
+ cipher_TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC058
+ cipher_TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC059
+ cipher_TLS_DH_anon_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC05A
+ cipher_TLS_DH_anon_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC05B
+ cipher_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC05C
+ cipher_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC05D
+ cipher_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC05E
+ cipher_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC05F
+ cipher_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC060
+ cipher_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC061
+ cipher_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC062
+ cipher_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC063
+ cipher_TLS_PSK_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC064
+ cipher_TLS_PSK_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC065
+ cipher_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC066
+ cipher_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC067
+ cipher_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC068
+ cipher_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC069
+ cipher_TLS_PSK_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC06A
+ cipher_TLS_PSK_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC06B
+ cipher_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC06C
+ cipher_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC06D
+ cipher_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC06E
+ cipher_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC06F
+ cipher_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC070
+ cipher_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC071
+ cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC072
+ cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC073
+ cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC074
+ cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC075
+ cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC076
+ cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC077
+ cipher_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC078
+ cipher_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC079
+ cipher_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC07A
+ cipher_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC07B
+ cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC07C
+ cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC07D
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC07E
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC07F
+ cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC080
+ cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC081
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC082
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC083
+ cipher_TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC084
+ cipher_TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC085
+ cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC086
+ cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC087
+ cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC088
+ cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC089
+ cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC08A
+ cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC08B
+ cipher_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC08C
+ cipher_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC08D
+ cipher_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC08E
+ cipher_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC08F
+ cipher_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC090
+ cipher_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC091
+ cipher_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC092
+ cipher_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC093
+ cipher_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC094
+ cipher_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC095
+ cipher_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC096
+ cipher_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC097
+ cipher_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC098
+ cipher_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC099
+ cipher_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC09A
+ cipher_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC09B
+ cipher_TLS_RSA_WITH_AES_128_CCM uint16 = 0xC09C
+ cipher_TLS_RSA_WITH_AES_256_CCM uint16 = 0xC09D
+ cipher_TLS_DHE_RSA_WITH_AES_128_CCM uint16 = 0xC09E
+ cipher_TLS_DHE_RSA_WITH_AES_256_CCM uint16 = 0xC09F
+ cipher_TLS_RSA_WITH_AES_128_CCM_8 uint16 = 0xC0A0
+ cipher_TLS_RSA_WITH_AES_256_CCM_8 uint16 = 0xC0A1
+ cipher_TLS_DHE_RSA_WITH_AES_128_CCM_8 uint16 = 0xC0A2
+ cipher_TLS_DHE_RSA_WITH_AES_256_CCM_8 uint16 = 0xC0A3
+ cipher_TLS_PSK_WITH_AES_128_CCM uint16 = 0xC0A4
+ cipher_TLS_PSK_WITH_AES_256_CCM uint16 = 0xC0A5
+ cipher_TLS_DHE_PSK_WITH_AES_128_CCM uint16 = 0xC0A6
+ cipher_TLS_DHE_PSK_WITH_AES_256_CCM uint16 = 0xC0A7
+ cipher_TLS_PSK_WITH_AES_128_CCM_8 uint16 = 0xC0A8
+ cipher_TLS_PSK_WITH_AES_256_CCM_8 uint16 = 0xC0A9
+ cipher_TLS_PSK_DHE_WITH_AES_128_CCM_8 uint16 = 0xC0AA
+ cipher_TLS_PSK_DHE_WITH_AES_256_CCM_8 uint16 = 0xC0AB
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CCM uint16 = 0xC0AC
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CCM uint16 = 0xC0AD
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 uint16 = 0xC0AE
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 uint16 = 0xC0AF
+ // Unassigned uint16 = 0xC0B0-FF
+ // Unassigned uint16 = 0xC1-CB,*
+ // Unassigned uint16 = 0xCC00-A7
+ cipher_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCA8
+ cipher_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCA9
+ cipher_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCAA
+ cipher_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCAB
+ cipher_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCAC
+ cipher_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCAD
+ cipher_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCAE
+)
+
+// isBadCipher reports whether the cipher is blacklisted by the HTTP/2 spec.
+// References:
+// https://tools.ietf.org/html/rfc7540#appendix-A
+// Reject cipher suites from Appendix A.
+// "This list includes those cipher suites that do not
+// offer an ephemeral key exchange and those that are
+// based on the TLS null, stream or block cipher type"
+func isBadCipher(cipher uint16) bool {
+ switch cipher {
+ case cipher_TLS_NULL_WITH_NULL_NULL,
+ cipher_TLS_RSA_WITH_NULL_MD5,
+ cipher_TLS_RSA_WITH_NULL_SHA,
+ cipher_TLS_RSA_EXPORT_WITH_RC4_40_MD5,
+ cipher_TLS_RSA_WITH_RC4_128_MD5,
+ cipher_TLS_RSA_WITH_RC4_128_SHA,
+ cipher_TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5,
+ cipher_TLS_RSA_WITH_IDEA_CBC_SHA,
+ cipher_TLS_RSA_EXPORT_WITH_DES40_CBC_SHA,
+ cipher_TLS_RSA_WITH_DES_CBC_SHA,
+ cipher_TLS_RSA_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA,
+ cipher_TLS_DH_DSS_WITH_DES_CBC_SHA,
+ cipher_TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA,
+ cipher_TLS_DH_RSA_WITH_DES_CBC_SHA,
+ cipher_TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA,
+ cipher_TLS_DHE_DSS_WITH_DES_CBC_SHA,
+ cipher_TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,
+ cipher_TLS_DHE_RSA_WITH_DES_CBC_SHA,
+ cipher_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_DH_anon_EXPORT_WITH_RC4_40_MD5,
+ cipher_TLS_DH_anon_WITH_RC4_128_MD5,
+ cipher_TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA,
+ cipher_TLS_DH_anon_WITH_DES_CBC_SHA,
+ cipher_TLS_DH_anon_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_KRB5_WITH_DES_CBC_SHA,
+ cipher_TLS_KRB5_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_KRB5_WITH_RC4_128_SHA,
+ cipher_TLS_KRB5_WITH_IDEA_CBC_SHA,
+ cipher_TLS_KRB5_WITH_DES_CBC_MD5,
+ cipher_TLS_KRB5_WITH_3DES_EDE_CBC_MD5,
+ cipher_TLS_KRB5_WITH_RC4_128_MD5,
+ cipher_TLS_KRB5_WITH_IDEA_CBC_MD5,
+ cipher_TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA,
+ cipher_TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA,
+ cipher_TLS_KRB5_EXPORT_WITH_RC4_40_SHA,
+ cipher_TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5,
+ cipher_TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5,
+ cipher_TLS_KRB5_EXPORT_WITH_RC4_40_MD5,
+ cipher_TLS_PSK_WITH_NULL_SHA,
+ cipher_TLS_DHE_PSK_WITH_NULL_SHA,
+ cipher_TLS_RSA_PSK_WITH_NULL_SHA,
+ cipher_TLS_RSA_WITH_AES_128_CBC_SHA,
+ cipher_TLS_DH_DSS_WITH_AES_128_CBC_SHA,
+ cipher_TLS_DH_RSA_WITH_AES_128_CBC_SHA,
+ cipher_TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
+ cipher_TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
+ cipher_TLS_DH_anon_WITH_AES_128_CBC_SHA,
+ cipher_TLS_RSA_WITH_AES_256_CBC_SHA,
+ cipher_TLS_DH_DSS_WITH_AES_256_CBC_SHA,
+ cipher_TLS_DH_RSA_WITH_AES_256_CBC_SHA,
+ cipher_TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
+ cipher_TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
+ cipher_TLS_DH_anon_WITH_AES_256_CBC_SHA,
+ cipher_TLS_RSA_WITH_NULL_SHA256,
+ cipher_TLS_RSA_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_RSA_WITH_AES_256_CBC_SHA256,
+ cipher_TLS_DH_DSS_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_DH_RSA_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA,
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA,
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA,
+ cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA,
+ cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,
+ cipher_TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA,
+ cipher_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_DH_DSS_WITH_AES_256_CBC_SHA256,
+ cipher_TLS_DH_RSA_WITH_AES_256_CBC_SHA256,
+ cipher_TLS_DHE_DSS_WITH_AES_256_CBC_SHA256,
+ cipher_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
+ cipher_TLS_DH_anon_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_DH_anon_WITH_AES_256_CBC_SHA256,
+ cipher_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA,
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA,
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA,
+ cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA,
+ cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,
+ cipher_TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA,
+ cipher_TLS_PSK_WITH_RC4_128_SHA,
+ cipher_TLS_PSK_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_PSK_WITH_AES_128_CBC_SHA,
+ cipher_TLS_PSK_WITH_AES_256_CBC_SHA,
+ cipher_TLS_DHE_PSK_WITH_RC4_128_SHA,
+ cipher_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_DHE_PSK_WITH_AES_128_CBC_SHA,
+ cipher_TLS_DHE_PSK_WITH_AES_256_CBC_SHA,
+ cipher_TLS_RSA_PSK_WITH_RC4_128_SHA,
+ cipher_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_RSA_PSK_WITH_AES_128_CBC_SHA,
+ cipher_TLS_RSA_PSK_WITH_AES_256_CBC_SHA,
+ cipher_TLS_RSA_WITH_SEED_CBC_SHA,
+ cipher_TLS_DH_DSS_WITH_SEED_CBC_SHA,
+ cipher_TLS_DH_RSA_WITH_SEED_CBC_SHA,
+ cipher_TLS_DHE_DSS_WITH_SEED_CBC_SHA,
+ cipher_TLS_DHE_RSA_WITH_SEED_CBC_SHA,
+ cipher_TLS_DH_anon_WITH_SEED_CBC_SHA,
+ cipher_TLS_RSA_WITH_AES_128_GCM_SHA256,
+ cipher_TLS_RSA_WITH_AES_256_GCM_SHA384,
+ cipher_TLS_DH_RSA_WITH_AES_128_GCM_SHA256,
+ cipher_TLS_DH_RSA_WITH_AES_256_GCM_SHA384,
+ cipher_TLS_DH_DSS_WITH_AES_128_GCM_SHA256,
+ cipher_TLS_DH_DSS_WITH_AES_256_GCM_SHA384,
+ cipher_TLS_DH_anon_WITH_AES_128_GCM_SHA256,
+ cipher_TLS_DH_anon_WITH_AES_256_GCM_SHA384,
+ cipher_TLS_PSK_WITH_AES_128_GCM_SHA256,
+ cipher_TLS_PSK_WITH_AES_256_GCM_SHA384,
+ cipher_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256,
+ cipher_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384,
+ cipher_TLS_PSK_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_PSK_WITH_AES_256_CBC_SHA384,
+ cipher_TLS_PSK_WITH_NULL_SHA256,
+ cipher_TLS_PSK_WITH_NULL_SHA384,
+ cipher_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384,
+ cipher_TLS_DHE_PSK_WITH_NULL_SHA256,
+ cipher_TLS_DHE_PSK_WITH_NULL_SHA384,
+ cipher_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384,
+ cipher_TLS_RSA_PSK_WITH_NULL_SHA256,
+ cipher_TLS_RSA_PSK_WITH_NULL_SHA384,
+ cipher_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256,
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256,
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256,
+ cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256,
+ cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256,
+ cipher_TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256,
+ cipher_TLS_EMPTY_RENEGOTIATION_INFO_SCSV,
+ cipher_TLS_ECDH_ECDSA_WITH_NULL_SHA,
+ cipher_TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
+ cipher_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
+ cipher_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
+ cipher_TLS_ECDHE_ECDSA_WITH_NULL_SHA,
+ cipher_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
+ cipher_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
+ cipher_TLS_ECDH_RSA_WITH_NULL_SHA,
+ cipher_TLS_ECDH_RSA_WITH_RC4_128_SHA,
+ cipher_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
+ cipher_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
+ cipher_TLS_ECDHE_RSA_WITH_NULL_SHA,
+ cipher_TLS_ECDHE_RSA_WITH_RC4_128_SHA,
+ cipher_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+ cipher_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
+ cipher_TLS_ECDH_anon_WITH_NULL_SHA,
+ cipher_TLS_ECDH_anon_WITH_RC4_128_SHA,
+ cipher_TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_ECDH_anon_WITH_AES_128_CBC_SHA,
+ cipher_TLS_ECDH_anon_WITH_AES_256_CBC_SHA,
+ cipher_TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_SRP_SHA_WITH_AES_128_CBC_SHA,
+ cipher_TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA,
+ cipher_TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA,
+ cipher_TLS_SRP_SHA_WITH_AES_256_CBC_SHA,
+ cipher_TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA,
+ cipher_TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA,
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
+ cipher_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384,
+ cipher_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
+ cipher_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384,
+ cipher_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,
+ cipher_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384,
+ cipher_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,
+ cipher_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384,
+ cipher_TLS_ECDHE_PSK_WITH_RC4_128_SHA,
+ cipher_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA,
+ cipher_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA,
+ cipher_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384,
+ cipher_TLS_ECDHE_PSK_WITH_NULL_SHA,
+ cipher_TLS_ECDHE_PSK_WITH_NULL_SHA256,
+ cipher_TLS_ECDHE_PSK_WITH_NULL_SHA384,
+ cipher_TLS_RSA_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_RSA_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_DH_anon_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_DH_anon_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_RSA_WITH_ARIA_128_GCM_SHA256,
+ cipher_TLS_RSA_WITH_ARIA_256_GCM_SHA384,
+ cipher_TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256,
+ cipher_TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384,
+ cipher_TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256,
+ cipher_TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384,
+ cipher_TLS_DH_anon_WITH_ARIA_128_GCM_SHA256,
+ cipher_TLS_DH_anon_WITH_ARIA_256_GCM_SHA384,
+ cipher_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256,
+ cipher_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384,
+ cipher_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256,
+ cipher_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384,
+ cipher_TLS_PSK_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_PSK_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_PSK_WITH_ARIA_128_GCM_SHA256,
+ cipher_TLS_PSK_WITH_ARIA_256_GCM_SHA384,
+ cipher_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256,
+ cipher_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384,
+ cipher_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
+ cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
+ cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384,
+ cipher_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384,
+ cipher_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256,
+ cipher_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384,
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256,
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384,
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256,
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384,
+ cipher_TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256,
+ cipher_TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384,
+ cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256,
+ cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384,
+ cipher_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256,
+ cipher_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384,
+ cipher_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256,
+ cipher_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384,
+ cipher_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256,
+ cipher_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384,
+ cipher_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384,
+ cipher_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
+ cipher_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384,
+ cipher_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
+ cipher_TLS_RSA_WITH_AES_128_CCM,
+ cipher_TLS_RSA_WITH_AES_256_CCM,
+ cipher_TLS_RSA_WITH_AES_128_CCM_8,
+ cipher_TLS_RSA_WITH_AES_256_CCM_8,
+ cipher_TLS_PSK_WITH_AES_128_CCM,
+ cipher_TLS_PSK_WITH_AES_256_CCM,
+ cipher_TLS_PSK_WITH_AES_128_CCM_8,
+ cipher_TLS_PSK_WITH_AES_256_CCM_8:
+ return true
+ default:
+ return false
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/ciphers_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/ciphers_test.go
new file mode 100644
index 000000000..764bbc8c8
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/ciphers_test.go
@@ -0,0 +1,309 @@
+// 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 http2
+
+import "testing"
+
+func TestIsBadCipherBad(t *testing.T) {
+ for _, c := range badCiphers {
+ if !isBadCipher(c) {
+ t.Errorf("Wrong result for isBadCipher(%d), want true", c)
+ }
+ }
+}
+
+// verify we don't give false positives on ciphers not on blacklist
+func TestIsBadCipherGood(t *testing.T) {
+ goodCiphers := map[uint16]string{
+ cipher_TLS_DHE_RSA_WITH_AES_256_CCM: "cipher_TLS_DHE_RSA_WITH_AES_256_CCM",
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CCM: "cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CCM",
+ cipher_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256: "cipher_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256",
+ }
+ for c, name := range goodCiphers {
+ if isBadCipher(c) {
+ t.Errorf("Wrong result for isBadCipher(%d) %s, want false", c, name)
+ }
+ }
+}
+
+// copied from https://http2.github.io/http2-spec/#BadCipherSuites,
+var badCiphers = []uint16{
+ cipher_TLS_NULL_WITH_NULL_NULL,
+ cipher_TLS_RSA_WITH_NULL_MD5,
+ cipher_TLS_RSA_WITH_NULL_SHA,
+ cipher_TLS_RSA_EXPORT_WITH_RC4_40_MD5,
+ cipher_TLS_RSA_WITH_RC4_128_MD5,
+ cipher_TLS_RSA_WITH_RC4_128_SHA,
+ cipher_TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5,
+ cipher_TLS_RSA_WITH_IDEA_CBC_SHA,
+ cipher_TLS_RSA_EXPORT_WITH_DES40_CBC_SHA,
+ cipher_TLS_RSA_WITH_DES_CBC_SHA,
+ cipher_TLS_RSA_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA,
+ cipher_TLS_DH_DSS_WITH_DES_CBC_SHA,
+ cipher_TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA,
+ cipher_TLS_DH_RSA_WITH_DES_CBC_SHA,
+ cipher_TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA,
+ cipher_TLS_DHE_DSS_WITH_DES_CBC_SHA,
+ cipher_TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,
+ cipher_TLS_DHE_RSA_WITH_DES_CBC_SHA,
+ cipher_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_DH_anon_EXPORT_WITH_RC4_40_MD5,
+ cipher_TLS_DH_anon_WITH_RC4_128_MD5,
+ cipher_TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA,
+ cipher_TLS_DH_anon_WITH_DES_CBC_SHA,
+ cipher_TLS_DH_anon_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_KRB5_WITH_DES_CBC_SHA,
+ cipher_TLS_KRB5_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_KRB5_WITH_RC4_128_SHA,
+ cipher_TLS_KRB5_WITH_IDEA_CBC_SHA,
+ cipher_TLS_KRB5_WITH_DES_CBC_MD5,
+ cipher_TLS_KRB5_WITH_3DES_EDE_CBC_MD5,
+ cipher_TLS_KRB5_WITH_RC4_128_MD5,
+ cipher_TLS_KRB5_WITH_IDEA_CBC_MD5,
+ cipher_TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA,
+ cipher_TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA,
+ cipher_TLS_KRB5_EXPORT_WITH_RC4_40_SHA,
+ cipher_TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5,
+ cipher_TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5,
+ cipher_TLS_KRB5_EXPORT_WITH_RC4_40_MD5,
+ cipher_TLS_PSK_WITH_NULL_SHA,
+ cipher_TLS_DHE_PSK_WITH_NULL_SHA,
+ cipher_TLS_RSA_PSK_WITH_NULL_SHA,
+ cipher_TLS_RSA_WITH_AES_128_CBC_SHA,
+ cipher_TLS_DH_DSS_WITH_AES_128_CBC_SHA,
+ cipher_TLS_DH_RSA_WITH_AES_128_CBC_SHA,
+ cipher_TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
+ cipher_TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
+ cipher_TLS_DH_anon_WITH_AES_128_CBC_SHA,
+ cipher_TLS_RSA_WITH_AES_256_CBC_SHA,
+ cipher_TLS_DH_DSS_WITH_AES_256_CBC_SHA,
+ cipher_TLS_DH_RSA_WITH_AES_256_CBC_SHA,
+ cipher_TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
+ cipher_TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
+ cipher_TLS_DH_anon_WITH_AES_256_CBC_SHA,
+ cipher_TLS_RSA_WITH_NULL_SHA256,
+ cipher_TLS_RSA_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_RSA_WITH_AES_256_CBC_SHA256,
+ cipher_TLS_DH_DSS_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_DH_RSA_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA,
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA,
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA,
+ cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA,
+ cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,
+ cipher_TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA,
+ cipher_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_DH_DSS_WITH_AES_256_CBC_SHA256,
+ cipher_TLS_DH_RSA_WITH_AES_256_CBC_SHA256,
+ cipher_TLS_DHE_DSS_WITH_AES_256_CBC_SHA256,
+ cipher_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
+ cipher_TLS_DH_anon_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_DH_anon_WITH_AES_256_CBC_SHA256,
+ cipher_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA,
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA,
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA,
+ cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA,
+ cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,
+ cipher_TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA,
+ cipher_TLS_PSK_WITH_RC4_128_SHA,
+ cipher_TLS_PSK_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_PSK_WITH_AES_128_CBC_SHA,
+ cipher_TLS_PSK_WITH_AES_256_CBC_SHA,
+ cipher_TLS_DHE_PSK_WITH_RC4_128_SHA,
+ cipher_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_DHE_PSK_WITH_AES_128_CBC_SHA,
+ cipher_TLS_DHE_PSK_WITH_AES_256_CBC_SHA,
+ cipher_TLS_RSA_PSK_WITH_RC4_128_SHA,
+ cipher_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_RSA_PSK_WITH_AES_128_CBC_SHA,
+ cipher_TLS_RSA_PSK_WITH_AES_256_CBC_SHA,
+ cipher_TLS_RSA_WITH_SEED_CBC_SHA,
+ cipher_TLS_DH_DSS_WITH_SEED_CBC_SHA,
+ cipher_TLS_DH_RSA_WITH_SEED_CBC_SHA,
+ cipher_TLS_DHE_DSS_WITH_SEED_CBC_SHA,
+ cipher_TLS_DHE_RSA_WITH_SEED_CBC_SHA,
+ cipher_TLS_DH_anon_WITH_SEED_CBC_SHA,
+ cipher_TLS_RSA_WITH_AES_128_GCM_SHA256,
+ cipher_TLS_RSA_WITH_AES_256_GCM_SHA384,
+ cipher_TLS_DH_RSA_WITH_AES_128_GCM_SHA256,
+ cipher_TLS_DH_RSA_WITH_AES_256_GCM_SHA384,
+ cipher_TLS_DH_DSS_WITH_AES_128_GCM_SHA256,
+ cipher_TLS_DH_DSS_WITH_AES_256_GCM_SHA384,
+ cipher_TLS_DH_anon_WITH_AES_128_GCM_SHA256,
+ cipher_TLS_DH_anon_WITH_AES_256_GCM_SHA384,
+ cipher_TLS_PSK_WITH_AES_128_GCM_SHA256,
+ cipher_TLS_PSK_WITH_AES_256_GCM_SHA384,
+ cipher_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256,
+ cipher_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384,
+ cipher_TLS_PSK_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_PSK_WITH_AES_256_CBC_SHA384,
+ cipher_TLS_PSK_WITH_NULL_SHA256,
+ cipher_TLS_PSK_WITH_NULL_SHA384,
+ cipher_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384,
+ cipher_TLS_DHE_PSK_WITH_NULL_SHA256,
+ cipher_TLS_DHE_PSK_WITH_NULL_SHA384,
+ cipher_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384,
+ cipher_TLS_RSA_PSK_WITH_NULL_SHA256,
+ cipher_TLS_RSA_PSK_WITH_NULL_SHA384,
+ cipher_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256,
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256,
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256,
+ cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256,
+ cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256,
+ cipher_TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256,
+ cipher_TLS_EMPTY_RENEGOTIATION_INFO_SCSV,
+ cipher_TLS_ECDH_ECDSA_WITH_NULL_SHA,
+ cipher_TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
+ cipher_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
+ cipher_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
+ cipher_TLS_ECDHE_ECDSA_WITH_NULL_SHA,
+ cipher_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
+ cipher_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
+ cipher_TLS_ECDH_RSA_WITH_NULL_SHA,
+ cipher_TLS_ECDH_RSA_WITH_RC4_128_SHA,
+ cipher_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
+ cipher_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
+ cipher_TLS_ECDHE_RSA_WITH_NULL_SHA,
+ cipher_TLS_ECDHE_RSA_WITH_RC4_128_SHA,
+ cipher_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+ cipher_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
+ cipher_TLS_ECDH_anon_WITH_NULL_SHA,
+ cipher_TLS_ECDH_anon_WITH_RC4_128_SHA,
+ cipher_TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_ECDH_anon_WITH_AES_128_CBC_SHA,
+ cipher_TLS_ECDH_anon_WITH_AES_256_CBC_SHA,
+ cipher_TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_SRP_SHA_WITH_AES_128_CBC_SHA,
+ cipher_TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA,
+ cipher_TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA,
+ cipher_TLS_SRP_SHA_WITH_AES_256_CBC_SHA,
+ cipher_TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA,
+ cipher_TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA,
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
+ cipher_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384,
+ cipher_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
+ cipher_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384,
+ cipher_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,
+ cipher_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384,
+ cipher_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,
+ cipher_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384,
+ cipher_TLS_ECDHE_PSK_WITH_RC4_128_SHA,
+ cipher_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA,
+ cipher_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA,
+ cipher_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384,
+ cipher_TLS_ECDHE_PSK_WITH_NULL_SHA,
+ cipher_TLS_ECDHE_PSK_WITH_NULL_SHA256,
+ cipher_TLS_ECDHE_PSK_WITH_NULL_SHA384,
+ cipher_TLS_RSA_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_RSA_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_DH_anon_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_DH_anon_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_RSA_WITH_ARIA_128_GCM_SHA256,
+ cipher_TLS_RSA_WITH_ARIA_256_GCM_SHA384,
+ cipher_TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256,
+ cipher_TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384,
+ cipher_TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256,
+ cipher_TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384,
+ cipher_TLS_DH_anon_WITH_ARIA_128_GCM_SHA256,
+ cipher_TLS_DH_anon_WITH_ARIA_256_GCM_SHA384,
+ cipher_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256,
+ cipher_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384,
+ cipher_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256,
+ cipher_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384,
+ cipher_TLS_PSK_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_PSK_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_PSK_WITH_ARIA_128_GCM_SHA256,
+ cipher_TLS_PSK_WITH_ARIA_256_GCM_SHA384,
+ cipher_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256,
+ cipher_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384,
+ cipher_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
+ cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
+ cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384,
+ cipher_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384,
+ cipher_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256,
+ cipher_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384,
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256,
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384,
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256,
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384,
+ cipher_TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256,
+ cipher_TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384,
+ cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256,
+ cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384,
+ cipher_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256,
+ cipher_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384,
+ cipher_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256,
+ cipher_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384,
+ cipher_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256,
+ cipher_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384,
+ cipher_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384,
+ cipher_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
+ cipher_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384,
+ cipher_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
+ cipher_TLS_RSA_WITH_AES_128_CCM,
+ cipher_TLS_RSA_WITH_AES_256_CCM,
+ cipher_TLS_RSA_WITH_AES_128_CCM_8,
+ cipher_TLS_RSA_WITH_AES_256_CCM_8,
+ cipher_TLS_PSK_WITH_AES_128_CCM,
+ cipher_TLS_PSK_WITH_AES_256_CCM,
+ cipher_TLS_PSK_WITH_AES_128_CCM_8,
+ cipher_TLS_PSK_WITH_AES_256_CCM_8,
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/client_conn_pool.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/client_conn_pool.go
new file mode 100644
index 000000000..bdf5652b0
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/client_conn_pool.go
@@ -0,0 +1,256 @@
+// Copyright 2015 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.
+
+// Transport code's client connection pooling.
+
+package http2
+
+import (
+ "crypto/tls"
+ "net/http"
+ "sync"
+)
+
+// ClientConnPool manages a pool of HTTP/2 client connections.
+type ClientConnPool interface {
+ GetClientConn(req *http.Request, addr string) (*ClientConn, error)
+ MarkDead(*ClientConn)
+}
+
+// clientConnPoolIdleCloser is the interface implemented by ClientConnPool
+// implementations which can close their idle connections.
+type clientConnPoolIdleCloser interface {
+ ClientConnPool
+ closeIdleConnections()
+}
+
+var (
+ _ clientConnPoolIdleCloser = (*clientConnPool)(nil)
+ _ clientConnPoolIdleCloser = noDialClientConnPool{}
+)
+
+// TODO: use singleflight for dialing and addConnCalls?
+type clientConnPool struct {
+ t *Transport
+
+ mu sync.Mutex // TODO: maybe switch to RWMutex
+ // TODO: add support for sharing conns based on cert names
+ // (e.g. share conn for googleapis.com and appspot.com)
+ conns map[string][]*ClientConn // key is host:port
+ dialing map[string]*dialCall // currently in-flight dials
+ keys map[*ClientConn][]string
+ addConnCalls map[string]*addConnCall // in-flight addConnIfNeede calls
+}
+
+func (p *clientConnPool) GetClientConn(req *http.Request, addr string) (*ClientConn, error) {
+ return p.getClientConn(req, addr, dialOnMiss)
+}
+
+const (
+ dialOnMiss = true
+ noDialOnMiss = false
+)
+
+func (p *clientConnPool) getClientConn(req *http.Request, addr string, dialOnMiss bool) (*ClientConn, error) {
+ if isConnectionCloseRequest(req) && dialOnMiss {
+ // It gets its own connection.
+ const singleUse = true
+ cc, err := p.t.dialClientConn(addr, singleUse)
+ if err != nil {
+ return nil, err
+ }
+ return cc, nil
+ }
+ p.mu.Lock()
+ for _, cc := range p.conns[addr] {
+ if cc.CanTakeNewRequest() {
+ p.mu.Unlock()
+ return cc, nil
+ }
+ }
+ if !dialOnMiss {
+ p.mu.Unlock()
+ return nil, ErrNoCachedConn
+ }
+ call := p.getStartDialLocked(addr)
+ p.mu.Unlock()
+ <-call.done
+ return call.res, call.err
+}
+
+// dialCall is an in-flight Transport dial call to a host.
+type dialCall struct {
+ p *clientConnPool
+ done chan struct{} // closed when done
+ res *ClientConn // valid after done is closed
+ err error // valid after done is closed
+}
+
+// requires p.mu is held.
+func (p *clientConnPool) getStartDialLocked(addr string) *dialCall {
+ if call, ok := p.dialing[addr]; ok {
+ // A dial is already in-flight. Don't start another.
+ return call
+ }
+ call := &dialCall{p: p, done: make(chan struct{})}
+ if p.dialing == nil {
+ p.dialing = make(map[string]*dialCall)
+ }
+ p.dialing[addr] = call
+ go call.dial(addr)
+ return call
+}
+
+// run in its own goroutine.
+func (c *dialCall) dial(addr string) {
+ const singleUse = false // shared conn
+ c.res, c.err = c.p.t.dialClientConn(addr, singleUse)
+ close(c.done)
+
+ c.p.mu.Lock()
+ delete(c.p.dialing, addr)
+ if c.err == nil {
+ c.p.addConnLocked(addr, c.res)
+ }
+ c.p.mu.Unlock()
+}
+
+// addConnIfNeeded makes a NewClientConn out of c if a connection for key doesn't
+// already exist. It coalesces concurrent calls with the same key.
+// This is used by the http1 Transport code when it creates a new connection. Because
+// the http1 Transport doesn't de-dup TCP dials to outbound hosts (because it doesn't know
+// the protocol), it can get into a situation where it has multiple TLS connections.
+// This code decides which ones live or die.
+// The return value used is whether c was used.
+// c is never closed.
+func (p *clientConnPool) addConnIfNeeded(key string, t *Transport, c *tls.Conn) (used bool, err error) {
+ p.mu.Lock()
+ for _, cc := range p.conns[key] {
+ if cc.CanTakeNewRequest() {
+ p.mu.Unlock()
+ return false, nil
+ }
+ }
+ call, dup := p.addConnCalls[key]
+ if !dup {
+ if p.addConnCalls == nil {
+ p.addConnCalls = make(map[string]*addConnCall)
+ }
+ call = &addConnCall{
+ p: p,
+ done: make(chan struct{}),
+ }
+ p.addConnCalls[key] = call
+ go call.run(t, key, c)
+ }
+ p.mu.Unlock()
+
+ <-call.done
+ if call.err != nil {
+ return false, call.err
+ }
+ return !dup, nil
+}
+
+type addConnCall struct {
+ p *clientConnPool
+ done chan struct{} // closed when done
+ err error
+}
+
+func (c *addConnCall) run(t *Transport, key string, tc *tls.Conn) {
+ cc, err := t.NewClientConn(tc)
+
+ p := c.p
+ p.mu.Lock()
+ if err != nil {
+ c.err = err
+ } else {
+ p.addConnLocked(key, cc)
+ }
+ delete(p.addConnCalls, key)
+ p.mu.Unlock()
+ close(c.done)
+}
+
+func (p *clientConnPool) addConn(key string, cc *ClientConn) {
+ p.mu.Lock()
+ p.addConnLocked(key, cc)
+ p.mu.Unlock()
+}
+
+// p.mu must be held
+func (p *clientConnPool) addConnLocked(key string, cc *ClientConn) {
+ for _, v := range p.conns[key] {
+ if v == cc {
+ return
+ }
+ }
+ if p.conns == nil {
+ p.conns = make(map[string][]*ClientConn)
+ }
+ if p.keys == nil {
+ p.keys = make(map[*ClientConn][]string)
+ }
+ p.conns[key] = append(p.conns[key], cc)
+ p.keys[cc] = append(p.keys[cc], key)
+}
+
+func (p *clientConnPool) MarkDead(cc *ClientConn) {
+ p.mu.Lock()
+ defer p.mu.Unlock()
+ for _, key := range p.keys[cc] {
+ vv, ok := p.conns[key]
+ if !ok {
+ continue
+ }
+ newList := filterOutClientConn(vv, cc)
+ if len(newList) > 0 {
+ p.conns[key] = newList
+ } else {
+ delete(p.conns, key)
+ }
+ }
+ delete(p.keys, cc)
+}
+
+func (p *clientConnPool) closeIdleConnections() {
+ p.mu.Lock()
+ defer p.mu.Unlock()
+ // TODO: don't close a cc if it was just added to the pool
+ // milliseconds ago and has never been used. There's currently
+ // a small race window with the HTTP/1 Transport's integration
+ // where it can add an idle conn just before using it, and
+ // somebody else can concurrently call CloseIdleConns and
+ // break some caller's RoundTrip.
+ for _, vv := range p.conns {
+ for _, cc := range vv {
+ cc.closeIfIdle()
+ }
+ }
+}
+
+func filterOutClientConn(in []*ClientConn, exclude *ClientConn) []*ClientConn {
+ out := in[:0]
+ for _, v := range in {
+ if v != exclude {
+ out = append(out, v)
+ }
+ }
+ // If we filtered it out, zero out the last item to prevent
+ // the GC from seeing it.
+ if len(in) != len(out) {
+ in[len(in)-1] = nil
+ }
+ return out
+}
+
+// noDialClientConnPool is an implementation of http2.ClientConnPool
+// which never dials. We let the HTTP/1.1 client dial and use its TLS
+// connection instead.
+type noDialClientConnPool struct{ *clientConnPool }
+
+func (p noDialClientConnPool) GetClientConn(req *http.Request, addr string) (*ClientConn, error) {
+ return p.getClientConn(req, addr, noDialOnMiss)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/configure_transport.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/configure_transport.go
new file mode 100644
index 000000000..b65fc6d42
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/configure_transport.go
@@ -0,0 +1,80 @@
+// Copyright 2015 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.
+
+// +build go1.6
+
+package http2
+
+import (
+ "crypto/tls"
+ "fmt"
+ "net/http"
+)
+
+func configureTransport(t1 *http.Transport) (*Transport, error) {
+ connPool := new(clientConnPool)
+ t2 := &Transport{
+ ConnPool: noDialClientConnPool{connPool},
+ t1: t1,
+ }
+ connPool.t = t2
+ if err := registerHTTPSProtocol(t1, noDialH2RoundTripper{t2}); err != nil {
+ return nil, err
+ }
+ if t1.TLSClientConfig == nil {
+ t1.TLSClientConfig = new(tls.Config)
+ }
+ if !strSliceContains(t1.TLSClientConfig.NextProtos, "h2") {
+ t1.TLSClientConfig.NextProtos = append([]string{"h2"}, t1.TLSClientConfig.NextProtos...)
+ }
+ if !strSliceContains(t1.TLSClientConfig.NextProtos, "http/1.1") {
+ t1.TLSClientConfig.NextProtos = append(t1.TLSClientConfig.NextProtos, "http/1.1")
+ }
+ upgradeFn := func(authority string, c *tls.Conn) http.RoundTripper {
+ addr := authorityAddr("https", authority)
+ if used, err := connPool.addConnIfNeeded(addr, t2, c); err != nil {
+ go c.Close()
+ return erringRoundTripper{err}
+ } else if !used {
+ // Turns out we don't need this c.
+ // For example, two goroutines made requests to the same host
+ // at the same time, both kicking off TCP dials. (since protocol
+ // was unknown)
+ go c.Close()
+ }
+ return t2
+ }
+ if m := t1.TLSNextProto; len(m) == 0 {
+ t1.TLSNextProto = map[string]func(string, *tls.Conn) http.RoundTripper{
+ "h2": upgradeFn,
+ }
+ } else {
+ m["h2"] = upgradeFn
+ }
+ return t2, nil
+}
+
+// registerHTTPSProtocol calls Transport.RegisterProtocol but
+// converting panics into errors.
+func registerHTTPSProtocol(t *http.Transport, rt http.RoundTripper) (err error) {
+ defer func() {
+ if e := recover(); e != nil {
+ err = fmt.Errorf("%v", e)
+ }
+ }()
+ t.RegisterProtocol("https", rt)
+ return nil
+}
+
+// noDialH2RoundTripper is a RoundTripper which only tries to complete the request
+// if there's already has a cached connection to the host.
+type noDialH2RoundTripper struct{ t *Transport }
+
+func (rt noDialH2RoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
+ res, err := rt.t.RoundTrip(req)
+ if err == ErrNoCachedConn {
+ return nil, http.ErrSkipAltProtocol
+ }
+ return res, err
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/databuffer.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/databuffer.go
new file mode 100644
index 000000000..a3067f8de
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/databuffer.go
@@ -0,0 +1,146 @@
+// Copyright 2014 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 http2
+
+import (
+ "errors"
+ "fmt"
+ "sync"
+)
+
+// Buffer chunks are allocated from a pool to reduce pressure on GC.
+// The maximum wasted space per dataBuffer is 2x the largest size class,
+// which happens when the dataBuffer has multiple chunks and there is
+// one unread byte in both the first and last chunks. We use a few size
+// classes to minimize overheads for servers that typically receive very
+// small request bodies.
+//
+// TODO: Benchmark to determine if the pools are necessary. The GC may have
+// improved enough that we can instead allocate chunks like this:
+// make([]byte, max(16<<10, expectedBytesRemaining))
+var (
+ dataChunkSizeClasses = []int{
+ 1 << 10,
+ 2 << 10,
+ 4 << 10,
+ 8 << 10,
+ 16 << 10,
+ }
+ dataChunkPools = [...]sync.Pool{
+ {New: func() interface{} { return make([]byte, 1<<10) }},
+ {New: func() interface{} { return make([]byte, 2<<10) }},
+ {New: func() interface{} { return make([]byte, 4<<10) }},
+ {New: func() interface{} { return make([]byte, 8<<10) }},
+ {New: func() interface{} { return make([]byte, 16<<10) }},
+ }
+)
+
+func getDataBufferChunk(size int64) []byte {
+ i := 0
+ for ; i < len(dataChunkSizeClasses)-1; i++ {
+ if size <= int64(dataChunkSizeClasses[i]) {
+ break
+ }
+ }
+ return dataChunkPools[i].Get().([]byte)
+}
+
+func putDataBufferChunk(p []byte) {
+ for i, n := range dataChunkSizeClasses {
+ if len(p) == n {
+ dataChunkPools[i].Put(p)
+ return
+ }
+ }
+ panic(fmt.Sprintf("unexpected buffer len=%v", len(p)))
+}
+
+// dataBuffer is an io.ReadWriter backed by a list of data chunks.
+// Each dataBuffer is used to read DATA frames on a single stream.
+// The buffer is divided into chunks so the server can limit the
+// total memory used by a single connection without limiting the
+// request body size on any single stream.
+type dataBuffer struct {
+ chunks [][]byte
+ r int // next byte to read is chunks[0][r]
+ w int // next byte to write is chunks[len(chunks)-1][w]
+ size int // total buffered bytes
+ expected int64 // we expect at least this many bytes in future Write calls (ignored if <= 0)
+}
+
+var errReadEmpty = errors.New("read from empty dataBuffer")
+
+// Read copies bytes from the buffer into p.
+// It is an error to read when no data is available.
+func (b *dataBuffer) Read(p []byte) (int, error) {
+ if b.size == 0 {
+ return 0, errReadEmpty
+ }
+ var ntotal int
+ for len(p) > 0 && b.size > 0 {
+ readFrom := b.bytesFromFirstChunk()
+ n := copy(p, readFrom)
+ p = p[n:]
+ ntotal += n
+ b.r += n
+ b.size -= n
+ // If the first chunk has been consumed, advance to the next chunk.
+ if b.r == len(b.chunks[0]) {
+ putDataBufferChunk(b.chunks[0])
+ end := len(b.chunks) - 1
+ copy(b.chunks[:end], b.chunks[1:])
+ b.chunks[end] = nil
+ b.chunks = b.chunks[:end]
+ b.r = 0
+ }
+ }
+ return ntotal, nil
+}
+
+func (b *dataBuffer) bytesFromFirstChunk() []byte {
+ if len(b.chunks) == 1 {
+ return b.chunks[0][b.r:b.w]
+ }
+ return b.chunks[0][b.r:]
+}
+
+// Len returns the number of bytes of the unread portion of the buffer.
+func (b *dataBuffer) Len() int {
+ return b.size
+}
+
+// Write appends p to the buffer.
+func (b *dataBuffer) Write(p []byte) (int, error) {
+ ntotal := len(p)
+ for len(p) > 0 {
+ // If the last chunk is empty, allocate a new chunk. Try to allocate
+ // enough to fully copy p plus any additional bytes we expect to
+ // receive. However, this may allocate less than len(p).
+ want := int64(len(p))
+ if b.expected > want {
+ want = b.expected
+ }
+ chunk := b.lastChunkOrAlloc(want)
+ n := copy(chunk[b.w:], p)
+ p = p[n:]
+ b.w += n
+ b.size += n
+ b.expected -= int64(n)
+ }
+ return ntotal, nil
+}
+
+func (b *dataBuffer) lastChunkOrAlloc(want int64) []byte {
+ if len(b.chunks) != 0 {
+ last := b.chunks[len(b.chunks)-1]
+ if b.w < len(last) {
+ return last
+ }
+ }
+ chunk := getDataBufferChunk(want)
+ b.chunks = append(b.chunks, chunk)
+ b.w = 0
+ return chunk
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/databuffer_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/databuffer_test.go
new file mode 100644
index 000000000..028e12e52
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/databuffer_test.go
@@ -0,0 +1,157 @@
+// 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.
+
+// +build go1.7
+
+package http2
+
+import (
+ "bytes"
+ "fmt"
+ "reflect"
+ "testing"
+)
+
+func fmtDataChunk(chunk []byte) string {
+ out := ""
+ var last byte
+ var count int
+ for _, c := range chunk {
+ if c != last {
+ if count > 0 {
+ out += fmt.Sprintf(" x %d ", count)
+ count = 0
+ }
+ out += string([]byte{c})
+ last = c
+ }
+ count++
+ }
+ if count > 0 {
+ out += fmt.Sprintf(" x %d", count)
+ }
+ return out
+}
+
+func fmtDataChunks(chunks [][]byte) string {
+ var out string
+ for _, chunk := range chunks {
+ out += fmt.Sprintf("{%q}", fmtDataChunk(chunk))
+ }
+ return out
+}
+
+func testDataBuffer(t *testing.T, wantBytes []byte, setup func(t *testing.T) *dataBuffer) {
+ // Run setup, then read the remaining bytes from the dataBuffer and check
+ // that they match wantBytes. We use different read sizes to check corner
+ // cases in Read.
+ for _, readSize := range []int{1, 2, 1 * 1024, 32 * 1024} {
+ t.Run(fmt.Sprintf("ReadSize=%d", readSize), func(t *testing.T) {
+ b := setup(t)
+ buf := make([]byte, readSize)
+ var gotRead bytes.Buffer
+ for {
+ n, err := b.Read(buf)
+ gotRead.Write(buf[:n])
+ if err == errReadEmpty {
+ break
+ }
+ if err != nil {
+ t.Fatalf("error after %v bytes: %v", gotRead.Len(), err)
+ }
+ }
+ if got, want := gotRead.Bytes(), wantBytes; !bytes.Equal(got, want) {
+ t.Errorf("FinalRead=%q, want %q", fmtDataChunk(got), fmtDataChunk(want))
+ }
+ })
+ }
+}
+
+func TestDataBufferAllocation(t *testing.T) {
+ writes := [][]byte{
+ bytes.Repeat([]byte("a"), 1*1024-1),
+ []byte("a"),
+ bytes.Repeat([]byte("b"), 4*1024-1),
+ []byte("b"),
+ bytes.Repeat([]byte("c"), 8*1024-1),
+ []byte("c"),
+ bytes.Repeat([]byte("d"), 16*1024-1),
+ []byte("d"),
+ bytes.Repeat([]byte("e"), 32*1024),
+ }
+ var wantRead bytes.Buffer
+ for _, p := range writes {
+ wantRead.Write(p)
+ }
+
+ testDataBuffer(t, wantRead.Bytes(), func(t *testing.T) *dataBuffer {
+ b := &dataBuffer{}
+ for _, p := range writes {
+ if n, err := b.Write(p); n != len(p) || err != nil {
+ t.Fatalf("Write(%q x %d)=%v,%v want %v,nil", p[:1], len(p), n, err, len(p))
+ }
+ }
+ want := [][]byte{
+ bytes.Repeat([]byte("a"), 1*1024),
+ bytes.Repeat([]byte("b"), 4*1024),
+ bytes.Repeat([]byte("c"), 8*1024),
+ bytes.Repeat([]byte("d"), 16*1024),
+ bytes.Repeat([]byte("e"), 16*1024),
+ bytes.Repeat([]byte("e"), 16*1024),
+ }
+ if !reflect.DeepEqual(b.chunks, want) {
+ t.Errorf("dataBuffer.chunks\ngot: %s\nwant: %s", fmtDataChunks(b.chunks), fmtDataChunks(want))
+ }
+ return b
+ })
+}
+
+func TestDataBufferAllocationWithExpected(t *testing.T) {
+ writes := [][]byte{
+ bytes.Repeat([]byte("a"), 1*1024), // allocates 16KB
+ bytes.Repeat([]byte("b"), 14*1024),
+ bytes.Repeat([]byte("c"), 15*1024), // allocates 16KB more
+ bytes.Repeat([]byte("d"), 2*1024),
+ bytes.Repeat([]byte("e"), 1*1024), // overflows 32KB expectation, allocates just 1KB
+ }
+ var wantRead bytes.Buffer
+ for _, p := range writes {
+ wantRead.Write(p)
+ }
+
+ testDataBuffer(t, wantRead.Bytes(), func(t *testing.T) *dataBuffer {
+ b := &dataBuffer{expected: 32 * 1024}
+ for _, p := range writes {
+ if n, err := b.Write(p); n != len(p) || err != nil {
+ t.Fatalf("Write(%q x %d)=%v,%v want %v,nil", p[:1], len(p), n, err, len(p))
+ }
+ }
+ want := [][]byte{
+ append(bytes.Repeat([]byte("a"), 1*1024), append(bytes.Repeat([]byte("b"), 14*1024), bytes.Repeat([]byte("c"), 1*1024)...)...),
+ append(bytes.Repeat([]byte("c"), 14*1024), bytes.Repeat([]byte("d"), 2*1024)...),
+ bytes.Repeat([]byte("e"), 1*1024),
+ }
+ if !reflect.DeepEqual(b.chunks, want) {
+ t.Errorf("dataBuffer.chunks\ngot: %s\nwant: %s", fmtDataChunks(b.chunks), fmtDataChunks(want))
+ }
+ return b
+ })
+}
+
+func TestDataBufferWriteAfterPartialRead(t *testing.T) {
+ testDataBuffer(t, []byte("cdxyz"), func(t *testing.T) *dataBuffer {
+ b := &dataBuffer{}
+ if n, err := b.Write([]byte("abcd")); n != 4 || err != nil {
+ t.Fatalf("Write(\"abcd\")=%v,%v want 4,nil", n, err)
+ }
+ p := make([]byte, 2)
+ if n, err := b.Read(p); n != 2 || err != nil || !bytes.Equal(p, []byte("ab")) {
+ t.Fatalf("Read()=%q,%v,%v want \"ab\",2,nil", p, n, err)
+ }
+ if n, err := b.Write([]byte("xyz")); n != 3 || err != nil {
+ t.Fatalf("Write(\"xyz\")=%v,%v want 3,nil", n, err)
+ }
+ return b
+ })
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/errors.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/errors.go
new file mode 100644
index 000000000..71f2c4631
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/errors.go
@@ -0,0 +1,133 @@
+// Copyright 2014 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 http2
+
+import (
+ "errors"
+ "fmt"
+)
+
+// An ErrCode is an unsigned 32-bit error code as defined in the HTTP/2 spec.
+type ErrCode uint32
+
+const (
+ ErrCodeNo ErrCode = 0x0
+ ErrCodeProtocol ErrCode = 0x1
+ ErrCodeInternal ErrCode = 0x2
+ ErrCodeFlowControl ErrCode = 0x3
+ ErrCodeSettingsTimeout ErrCode = 0x4
+ ErrCodeStreamClosed ErrCode = 0x5
+ ErrCodeFrameSize ErrCode = 0x6
+ ErrCodeRefusedStream ErrCode = 0x7
+ ErrCodeCancel ErrCode = 0x8
+ ErrCodeCompression ErrCode = 0x9
+ ErrCodeConnect ErrCode = 0xa
+ ErrCodeEnhanceYourCalm ErrCode = 0xb
+ ErrCodeInadequateSecurity ErrCode = 0xc
+ ErrCodeHTTP11Required ErrCode = 0xd
+)
+
+var errCodeName = map[ErrCode]string{
+ ErrCodeNo: "NO_ERROR",
+ ErrCodeProtocol: "PROTOCOL_ERROR",
+ ErrCodeInternal: "INTERNAL_ERROR",
+ ErrCodeFlowControl: "FLOW_CONTROL_ERROR",
+ ErrCodeSettingsTimeout: "SETTINGS_TIMEOUT",
+ ErrCodeStreamClosed: "STREAM_CLOSED",
+ ErrCodeFrameSize: "FRAME_SIZE_ERROR",
+ ErrCodeRefusedStream: "REFUSED_STREAM",
+ ErrCodeCancel: "CANCEL",
+ ErrCodeCompression: "COMPRESSION_ERROR",
+ ErrCodeConnect: "CONNECT_ERROR",
+ ErrCodeEnhanceYourCalm: "ENHANCE_YOUR_CALM",
+ ErrCodeInadequateSecurity: "INADEQUATE_SECURITY",
+ ErrCodeHTTP11Required: "HTTP_1_1_REQUIRED",
+}
+
+func (e ErrCode) String() string {
+ if s, ok := errCodeName[e]; ok {
+ return s
+ }
+ return fmt.Sprintf("unknown error code 0x%x", uint32(e))
+}
+
+// ConnectionError is an error that results in the termination of the
+// entire connection.
+type ConnectionError ErrCode
+
+func (e ConnectionError) Error() string { return fmt.Sprintf("connection error: %s", ErrCode(e)) }
+
+// StreamError is an error that only affects one stream within an
+// HTTP/2 connection.
+type StreamError struct {
+ StreamID uint32
+ Code ErrCode
+ Cause error // optional additional detail
+}
+
+func streamError(id uint32, code ErrCode) StreamError {
+ return StreamError{StreamID: id, Code: code}
+}
+
+func (e StreamError) Error() string {
+ if e.Cause != nil {
+ return fmt.Sprintf("stream error: stream ID %d; %v; %v", e.StreamID, e.Code, e.Cause)
+ }
+ return fmt.Sprintf("stream error: stream ID %d; %v", e.StreamID, e.Code)
+}
+
+// 6.9.1 The Flow Control Window
+// "If a sender receives a WINDOW_UPDATE that causes a flow control
+// window to exceed this maximum it MUST terminate either the stream
+// or the connection, as appropriate. For streams, [...]; for the
+// connection, a GOAWAY frame with a FLOW_CONTROL_ERROR code."
+type goAwayFlowError struct{}
+
+func (goAwayFlowError) Error() string { return "connection exceeded flow control window size" }
+
+// connError represents an HTTP/2 ConnectionError error code, along
+// with a string (for debugging) explaining why.
+//
+// Errors of this type are only returned by the frame parser functions
+// and converted into ConnectionError(Code), after stashing away
+// the Reason into the Framer's errDetail field, accessible via
+// the (*Framer).ErrorDetail method.
+type connError struct {
+ Code ErrCode // the ConnectionError error code
+ Reason string // additional reason
+}
+
+func (e connError) Error() string {
+ return fmt.Sprintf("http2: connection error: %v: %v", e.Code, e.Reason)
+}
+
+type pseudoHeaderError string
+
+func (e pseudoHeaderError) Error() string {
+ return fmt.Sprintf("invalid pseudo-header %q", string(e))
+}
+
+type duplicatePseudoHeaderError string
+
+func (e duplicatePseudoHeaderError) Error() string {
+ return fmt.Sprintf("duplicate pseudo-header %q", string(e))
+}
+
+type headerFieldNameError string
+
+func (e headerFieldNameError) Error() string {
+ return fmt.Sprintf("invalid header field name %q", string(e))
+}
+
+type headerFieldValueError string
+
+func (e headerFieldValueError) Error() string {
+ return fmt.Sprintf("invalid header field value %q", string(e))
+}
+
+var (
+ errMixPseudoHeaderTypes = errors.New("mix of request and response pseudo headers")
+ errPseudoAfterRegular = errors.New("pseudo header field after regular")
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/errors_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/errors_test.go
new file mode 100644
index 000000000..da5c58c31
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/errors_test.go
@@ -0,0 +1,24 @@
+// Copyright 2014 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 http2
+
+import "testing"
+
+func TestErrCodeString(t *testing.T) {
+ tests := []struct {
+ err ErrCode
+ want string
+ }{
+ {ErrCodeProtocol, "PROTOCOL_ERROR"},
+ {0xd, "HTTP_1_1_REQUIRED"},
+ {0xf, "unknown error code 0xf"},
+ }
+ for i, tt := range tests {
+ got := tt.err.String()
+ if got != tt.want {
+ t.Errorf("%d. Error = %q; want %q", i, got, tt.want)
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/flow.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/flow.go
new file mode 100644
index 000000000..957de2542
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/flow.go
@@ -0,0 +1,50 @@
+// Copyright 2014 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.
+
+// Flow control
+
+package http2
+
+// flow is the flow control window's size.
+type flow struct {
+ // n is the number of DATA bytes we're allowed to send.
+ // A flow is kept both on a conn and a per-stream.
+ n int32
+
+ // conn points to the shared connection-level flow that is
+ // shared by all streams on that conn. It is nil for the flow
+ // that's on the conn directly.
+ conn *flow
+}
+
+func (f *flow) setConnFlow(cf *flow) { f.conn = cf }
+
+func (f *flow) available() int32 {
+ n := f.n
+ if f.conn != nil && f.conn.n < n {
+ n = f.conn.n
+ }
+ return n
+}
+
+func (f *flow) take(n int32) {
+ if n > f.available() {
+ panic("internal error: took too much")
+ }
+ f.n -= n
+ if f.conn != nil {
+ f.conn.n -= n
+ }
+}
+
+// add adds n bytes (positive or negative) to the flow control window.
+// It returns false if the sum would exceed 2^31-1.
+func (f *flow) add(n int32) bool {
+ remain := (1<<31 - 1) - f.n
+ if n > remain {
+ return false
+ }
+ f.n += n
+ return true
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/flow_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/flow_test.go
new file mode 100644
index 000000000..859adf5d1
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/flow_test.go
@@ -0,0 +1,53 @@
+// Copyright 2014 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 http2
+
+import "testing"
+
+func TestFlow(t *testing.T) {
+ var st flow
+ var conn flow
+ st.add(3)
+ conn.add(2)
+
+ if got, want := st.available(), int32(3); got != want {
+ t.Errorf("available = %d; want %d", got, want)
+ }
+ st.setConnFlow(&conn)
+ if got, want := st.available(), int32(2); got != want {
+ t.Errorf("after parent setup, available = %d; want %d", got, want)
+ }
+
+ st.take(2)
+ if got, want := conn.available(), int32(0); got != want {
+ t.Errorf("after taking 2, conn = %d; want %d", got, want)
+ }
+ if got, want := st.available(), int32(0); got != want {
+ t.Errorf("after taking 2, stream = %d; want %d", got, want)
+ }
+}
+
+func TestFlowAdd(t *testing.T) {
+ var f flow
+ if !f.add(1) {
+ t.Fatal("failed to add 1")
+ }
+ if !f.add(-1) {
+ t.Fatal("failed to add -1")
+ }
+ if got, want := f.available(), int32(0); got != want {
+ t.Fatalf("size = %d; want %d", got, want)
+ }
+ if !f.add(1<<31 - 1) {
+ t.Fatal("failed to add 2^31-1")
+ }
+ if got, want := f.available(), int32(1<<31-1); got != want {
+ t.Fatalf("size = %d; want %d", got, want)
+ }
+ if f.add(1) {
+ t.Fatal("adding 1 to max shouldn't be allowed")
+ }
+
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/frame.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/frame.go
new file mode 100644
index 000000000..3b1489072
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/frame.go
@@ -0,0 +1,1579 @@
+// Copyright 2014 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 http2
+
+import (
+ "bytes"
+ "encoding/binary"
+ "errors"
+ "fmt"
+ "io"
+ "log"
+ "strings"
+ "sync"
+
+ "golang.org/x/net/http2/hpack"
+ "golang.org/x/net/lex/httplex"
+)
+
+const frameHeaderLen = 9
+
+var padZeros = make([]byte, 255) // zeros for padding
+
+// A FrameType is a registered frame type as defined in
+// http://http2.github.io/http2-spec/#rfc.section.11.2
+type FrameType uint8
+
+const (
+ FrameData FrameType = 0x0
+ FrameHeaders FrameType = 0x1
+ FramePriority FrameType = 0x2
+ FrameRSTStream FrameType = 0x3
+ FrameSettings FrameType = 0x4
+ FramePushPromise FrameType = 0x5
+ FramePing FrameType = 0x6
+ FrameGoAway FrameType = 0x7
+ FrameWindowUpdate FrameType = 0x8
+ FrameContinuation FrameType = 0x9
+)
+
+var frameName = map[FrameType]string{
+ FrameData: "DATA",
+ FrameHeaders: "HEADERS",
+ FramePriority: "PRIORITY",
+ FrameRSTStream: "RST_STREAM",
+ FrameSettings: "SETTINGS",
+ FramePushPromise: "PUSH_PROMISE",
+ FramePing: "PING",
+ FrameGoAway: "GOAWAY",
+ FrameWindowUpdate: "WINDOW_UPDATE",
+ FrameContinuation: "CONTINUATION",
+}
+
+func (t FrameType) String() string {
+ if s, ok := frameName[t]; ok {
+ return s
+ }
+ return fmt.Sprintf("UNKNOWN_FRAME_TYPE_%d", uint8(t))
+}
+
+// Flags is a bitmask of HTTP/2 flags.
+// The meaning of flags varies depending on the frame type.
+type Flags uint8
+
+// Has reports whether f contains all (0 or more) flags in v.
+func (f Flags) Has(v Flags) bool {
+ return (f & v) == v
+}
+
+// Frame-specific FrameHeader flag bits.
+const (
+ // Data Frame
+ FlagDataEndStream Flags = 0x1
+ FlagDataPadded Flags = 0x8
+
+ // Headers Frame
+ FlagHeadersEndStream Flags = 0x1
+ FlagHeadersEndHeaders Flags = 0x4
+ FlagHeadersPadded Flags = 0x8
+ FlagHeadersPriority Flags = 0x20
+
+ // Settings Frame
+ FlagSettingsAck Flags = 0x1
+
+ // Ping Frame
+ FlagPingAck Flags = 0x1
+
+ // Continuation Frame
+ FlagContinuationEndHeaders Flags = 0x4
+
+ FlagPushPromiseEndHeaders Flags = 0x4
+ FlagPushPromisePadded Flags = 0x8
+)
+
+var flagName = map[FrameType]map[Flags]string{
+ FrameData: {
+ FlagDataEndStream: "END_STREAM",
+ FlagDataPadded: "PADDED",
+ },
+ FrameHeaders: {
+ FlagHeadersEndStream: "END_STREAM",
+ FlagHeadersEndHeaders: "END_HEADERS",
+ FlagHeadersPadded: "PADDED",
+ FlagHeadersPriority: "PRIORITY",
+ },
+ FrameSettings: {
+ FlagSettingsAck: "ACK",
+ },
+ FramePing: {
+ FlagPingAck: "ACK",
+ },
+ FrameContinuation: {
+ FlagContinuationEndHeaders: "END_HEADERS",
+ },
+ FramePushPromise: {
+ FlagPushPromiseEndHeaders: "END_HEADERS",
+ FlagPushPromisePadded: "PADDED",
+ },
+}
+
+// a frameParser parses a frame given its FrameHeader and payload
+// bytes. The length of payload will always equal fh.Length (which
+// might be 0).
+type frameParser func(fc *frameCache, fh FrameHeader, payload []byte) (Frame, error)
+
+var frameParsers = map[FrameType]frameParser{
+ FrameData: parseDataFrame,
+ FrameHeaders: parseHeadersFrame,
+ FramePriority: parsePriorityFrame,
+ FrameRSTStream: parseRSTStreamFrame,
+ FrameSettings: parseSettingsFrame,
+ FramePushPromise: parsePushPromise,
+ FramePing: parsePingFrame,
+ FrameGoAway: parseGoAwayFrame,
+ FrameWindowUpdate: parseWindowUpdateFrame,
+ FrameContinuation: parseContinuationFrame,
+}
+
+func typeFrameParser(t FrameType) frameParser {
+ if f := frameParsers[t]; f != nil {
+ return f
+ }
+ return parseUnknownFrame
+}
+
+// A FrameHeader is the 9 byte header of all HTTP/2 frames.
+//
+// See http://http2.github.io/http2-spec/#FrameHeader
+type FrameHeader struct {
+ valid bool // caller can access []byte fields in the Frame
+
+ // Type is the 1 byte frame type. There are ten standard frame
+ // types, but extension frame types may be written by WriteRawFrame
+ // and will be returned by ReadFrame (as UnknownFrame).
+ Type FrameType
+
+ // Flags are the 1 byte of 8 potential bit flags per frame.
+ // They are specific to the frame type.
+ Flags Flags
+
+ // Length is the length of the frame, not including the 9 byte header.
+ // The maximum size is one byte less than 16MB (uint24), but only
+ // frames up to 16KB are allowed without peer agreement.
+ Length uint32
+
+ // StreamID is which stream this frame is for. Certain frames
+ // are not stream-specific, in which case this field is 0.
+ StreamID uint32
+}
+
+// Header returns h. It exists so FrameHeaders can be embedded in other
+// specific frame types and implement the Frame interface.
+func (h FrameHeader) Header() FrameHeader { return h }
+
+func (h FrameHeader) String() string {
+ var buf bytes.Buffer
+ buf.WriteString("[FrameHeader ")
+ h.writeDebug(&buf)
+ buf.WriteByte(']')
+ return buf.String()
+}
+
+func (h FrameHeader) writeDebug(buf *bytes.Buffer) {
+ buf.WriteString(h.Type.String())
+ if h.Flags != 0 {
+ buf.WriteString(" flags=")
+ set := 0
+ for i := uint8(0); i < 8; i++ {
+ if h.Flags&(1<<i) == 0 {
+ continue
+ }
+ set++
+ if set > 1 {
+ buf.WriteByte('|')
+ }
+ name := flagName[h.Type][Flags(1<<i)]
+ if name != "" {
+ buf.WriteString(name)
+ } else {
+ fmt.Fprintf(buf, "0x%x", 1<<i)
+ }
+ }
+ }
+ if h.StreamID != 0 {
+ fmt.Fprintf(buf, " stream=%d", h.StreamID)
+ }
+ fmt.Fprintf(buf, " len=%d", h.Length)
+}
+
+func (h *FrameHeader) checkValid() {
+ if !h.valid {
+ panic("Frame accessor called on non-owned Frame")
+ }
+}
+
+func (h *FrameHeader) invalidate() { h.valid = false }
+
+// frame header bytes.
+// Used only by ReadFrameHeader.
+var fhBytes = sync.Pool{
+ New: func() interface{} {
+ buf := make([]byte, frameHeaderLen)
+ return &buf
+ },
+}
+
+// ReadFrameHeader reads 9 bytes from r and returns a FrameHeader.
+// Most users should use Framer.ReadFrame instead.
+func ReadFrameHeader(r io.Reader) (FrameHeader, error) {
+ bufp := fhBytes.Get().(*[]byte)
+ defer fhBytes.Put(bufp)
+ return readFrameHeader(*bufp, r)
+}
+
+func readFrameHeader(buf []byte, r io.Reader) (FrameHeader, error) {
+ _, err := io.ReadFull(r, buf[:frameHeaderLen])
+ if err != nil {
+ return FrameHeader{}, err
+ }
+ return FrameHeader{
+ Length: (uint32(buf[0])<<16 | uint32(buf[1])<<8 | uint32(buf[2])),
+ Type: FrameType(buf[3]),
+ Flags: Flags(buf[4]),
+ StreamID: binary.BigEndian.Uint32(buf[5:]) & (1<<31 - 1),
+ valid: true,
+ }, nil
+}
+
+// A Frame is the base interface implemented by all frame types.
+// Callers will generally type-assert the specific frame type:
+// *HeadersFrame, *SettingsFrame, *WindowUpdateFrame, etc.
+//
+// Frames are only valid until the next call to Framer.ReadFrame.
+type Frame interface {
+ Header() FrameHeader
+
+ // invalidate is called by Framer.ReadFrame to make this
+ // frame's buffers as being invalid, since the subsequent
+ // frame will reuse them.
+ invalidate()
+}
+
+// A Framer reads and writes Frames.
+type Framer struct {
+ r io.Reader
+ lastFrame Frame
+ errDetail error
+
+ // lastHeaderStream is non-zero if the last frame was an
+ // unfinished HEADERS/CONTINUATION.
+ lastHeaderStream uint32
+
+ maxReadSize uint32
+ headerBuf [frameHeaderLen]byte
+
+ // TODO: let getReadBuf be configurable, and use a less memory-pinning
+ // allocator in server.go to minimize memory pinned for many idle conns.
+ // Will probably also need to make frame invalidation have a hook too.
+ getReadBuf func(size uint32) []byte
+ readBuf []byte // cache for default getReadBuf
+
+ maxWriteSize uint32 // zero means unlimited; TODO: implement
+
+ w io.Writer
+ wbuf []byte
+
+ // AllowIllegalWrites permits the Framer's Write methods to
+ // write frames that do not conform to the HTTP/2 spec. This
+ // permits using the Framer to test other HTTP/2
+ // implementations' conformance to the spec.
+ // If false, the Write methods will prefer to return an error
+ // rather than comply.
+ AllowIllegalWrites bool
+
+ // AllowIllegalReads permits the Framer's ReadFrame method
+ // to return non-compliant frames or frame orders.
+ // This is for testing and permits using the Framer to test
+ // other HTTP/2 implementations' conformance to the spec.
+ // It is not compatible with ReadMetaHeaders.
+ AllowIllegalReads bool
+
+ // ReadMetaHeaders if non-nil causes ReadFrame to merge
+ // HEADERS and CONTINUATION frames together and return
+ // MetaHeadersFrame instead.
+ ReadMetaHeaders *hpack.Decoder
+
+ // MaxHeaderListSize is the http2 MAX_HEADER_LIST_SIZE.
+ // It's used only if ReadMetaHeaders is set; 0 means a sane default
+ // (currently 16MB)
+ // If the limit is hit, MetaHeadersFrame.Truncated is set true.
+ MaxHeaderListSize uint32
+
+ // TODO: track which type of frame & with which flags was sent
+ // last. Then return an error (unless AllowIllegalWrites) if
+ // we're in the middle of a header block and a
+ // non-Continuation or Continuation on a different stream is
+ // attempted to be written.
+
+ logReads, logWrites bool
+
+ debugFramer *Framer // only use for logging written writes
+ debugFramerBuf *bytes.Buffer
+ debugReadLoggerf func(string, ...interface{})
+ debugWriteLoggerf func(string, ...interface{})
+
+ frameCache *frameCache // nil if frames aren't reused (default)
+}
+
+func (fr *Framer) maxHeaderListSize() uint32 {
+ if fr.MaxHeaderListSize == 0 {
+ return 16 << 20 // sane default, per docs
+ }
+ return fr.MaxHeaderListSize
+}
+
+func (f *Framer) startWrite(ftype FrameType, flags Flags, streamID uint32) {
+ // Write the FrameHeader.
+ f.wbuf = append(f.wbuf[:0],
+ 0, // 3 bytes of length, filled in in endWrite
+ 0,
+ 0,
+ byte(ftype),
+ byte(flags),
+ byte(streamID>>24),
+ byte(streamID>>16),
+ byte(streamID>>8),
+ byte(streamID))
+}
+
+func (f *Framer) endWrite() error {
+ // Now that we know the final size, fill in the FrameHeader in
+ // the space previously reserved for it. Abuse append.
+ length := len(f.wbuf) - frameHeaderLen
+ if length >= (1 << 24) {
+ return ErrFrameTooLarge
+ }
+ _ = append(f.wbuf[:0],
+ byte(length>>16),
+ byte(length>>8),
+ byte(length))
+ if f.logWrites {
+ f.logWrite()
+ }
+
+ n, err := f.w.Write(f.wbuf)
+ if err == nil && n != len(f.wbuf) {
+ err = io.ErrShortWrite
+ }
+ return err
+}
+
+func (f *Framer) logWrite() {
+ if f.debugFramer == nil {
+ f.debugFramerBuf = new(bytes.Buffer)
+ f.debugFramer = NewFramer(nil, f.debugFramerBuf)
+ f.debugFramer.logReads = false // we log it ourselves, saying "wrote" below
+ // Let us read anything, even if we accidentally wrote it
+ // in the wrong order:
+ f.debugFramer.AllowIllegalReads = true
+ }
+ f.debugFramerBuf.Write(f.wbuf)
+ fr, err := f.debugFramer.ReadFrame()
+ if err != nil {
+ f.debugWriteLoggerf("http2: Framer %p: failed to decode just-written frame", f)
+ return
+ }
+ f.debugWriteLoggerf("http2: Framer %p: wrote %v", f, summarizeFrame(fr))
+}
+
+func (f *Framer) writeByte(v byte) { f.wbuf = append(f.wbuf, v) }
+func (f *Framer) writeBytes(v []byte) { f.wbuf = append(f.wbuf, v...) }
+func (f *Framer) writeUint16(v uint16) { f.wbuf = append(f.wbuf, byte(v>>8), byte(v)) }
+func (f *Framer) writeUint32(v uint32) {
+ f.wbuf = append(f.wbuf, byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
+}
+
+const (
+ minMaxFrameSize = 1 << 14
+ maxFrameSize = 1<<24 - 1
+)
+
+// SetReuseFrames allows the Framer to reuse Frames.
+// If called on a Framer, Frames returned by calls to ReadFrame are only
+// valid until the next call to ReadFrame.
+func (fr *Framer) SetReuseFrames() {
+ if fr.frameCache != nil {
+ return
+ }
+ fr.frameCache = &frameCache{}
+}
+
+type frameCache struct {
+ dataFrame DataFrame
+}
+
+func (fc *frameCache) getDataFrame() *DataFrame {
+ if fc == nil {
+ return &DataFrame{}
+ }
+ return &fc.dataFrame
+}
+
+// NewFramer returns a Framer that writes frames to w and reads them from r.
+func NewFramer(w io.Writer, r io.Reader) *Framer {
+ fr := &Framer{
+ w: w,
+ r: r,
+ logReads: logFrameReads,
+ logWrites: logFrameWrites,
+ debugReadLoggerf: log.Printf,
+ debugWriteLoggerf: log.Printf,
+ }
+ fr.getReadBuf = func(size uint32) []byte {
+ if cap(fr.readBuf) >= int(size) {
+ return fr.readBuf[:size]
+ }
+ fr.readBuf = make([]byte, size)
+ return fr.readBuf
+ }
+ fr.SetMaxReadFrameSize(maxFrameSize)
+ return fr
+}
+
+// SetMaxReadFrameSize sets the maximum size of a frame
+// that will be read by a subsequent call to ReadFrame.
+// It is the caller's responsibility to advertise this
+// limit with a SETTINGS frame.
+func (fr *Framer) SetMaxReadFrameSize(v uint32) {
+ if v > maxFrameSize {
+ v = maxFrameSize
+ }
+ fr.maxReadSize = v
+}
+
+// ErrorDetail returns a more detailed error of the last error
+// returned by Framer.ReadFrame. For instance, if ReadFrame
+// returns a StreamError with code PROTOCOL_ERROR, ErrorDetail
+// will say exactly what was invalid. ErrorDetail is not guaranteed
+// to return a non-nil value and like the rest of the http2 package,
+// its return value is not protected by an API compatibility promise.
+// ErrorDetail is reset after the next call to ReadFrame.
+func (fr *Framer) ErrorDetail() error {
+ return fr.errDetail
+}
+
+// ErrFrameTooLarge is returned from Framer.ReadFrame when the peer
+// sends a frame that is larger than declared with SetMaxReadFrameSize.
+var ErrFrameTooLarge = errors.New("http2: frame too large")
+
+// terminalReadFrameError reports whether err is an unrecoverable
+// error from ReadFrame and no other frames should be read.
+func terminalReadFrameError(err error) bool {
+ if _, ok := err.(StreamError); ok {
+ return false
+ }
+ return err != nil
+}
+
+// ReadFrame reads a single frame. The returned Frame is only valid
+// until the next call to ReadFrame.
+//
+// If the frame is larger than previously set with SetMaxReadFrameSize, the
+// returned error is ErrFrameTooLarge. Other errors may be of type
+// ConnectionError, StreamError, or anything else from the underlying
+// reader.
+func (fr *Framer) ReadFrame() (Frame, error) {
+ fr.errDetail = nil
+ if fr.lastFrame != nil {
+ fr.lastFrame.invalidate()
+ }
+ fh, err := readFrameHeader(fr.headerBuf[:], fr.r)
+ if err != nil {
+ return nil, err
+ }
+ if fh.Length > fr.maxReadSize {
+ return nil, ErrFrameTooLarge
+ }
+ payload := fr.getReadBuf(fh.Length)
+ if _, err := io.ReadFull(fr.r, payload); err != nil {
+ return nil, err
+ }
+ f, err := typeFrameParser(fh.Type)(fr.frameCache, fh, payload)
+ if err != nil {
+ if ce, ok := err.(connError); ok {
+ return nil, fr.connError(ce.Code, ce.Reason)
+ }
+ return nil, err
+ }
+ if err := fr.checkFrameOrder(f); err != nil {
+ return nil, err
+ }
+ if fr.logReads {
+ fr.debugReadLoggerf("http2: Framer %p: read %v", fr, summarizeFrame(f))
+ }
+ if fh.Type == FrameHeaders && fr.ReadMetaHeaders != nil {
+ return fr.readMetaFrame(f.(*HeadersFrame))
+ }
+ return f, nil
+}
+
+// connError returns ConnectionError(code) but first
+// stashes away a public reason to the caller can optionally relay it
+// to the peer before hanging up on them. This might help others debug
+// their implementations.
+func (fr *Framer) connError(code ErrCode, reason string) error {
+ fr.errDetail = errors.New(reason)
+ return ConnectionError(code)
+}
+
+// checkFrameOrder reports an error if f is an invalid frame to return
+// next from ReadFrame. Mostly it checks whether HEADERS and
+// CONTINUATION frames are contiguous.
+func (fr *Framer) checkFrameOrder(f Frame) error {
+ last := fr.lastFrame
+ fr.lastFrame = f
+ if fr.AllowIllegalReads {
+ return nil
+ }
+
+ fh := f.Header()
+ if fr.lastHeaderStream != 0 {
+ if fh.Type != FrameContinuation {
+ return fr.connError(ErrCodeProtocol,
+ fmt.Sprintf("got %s for stream %d; expected CONTINUATION following %s for stream %d",
+ fh.Type, fh.StreamID,
+ last.Header().Type, fr.lastHeaderStream))
+ }
+ if fh.StreamID != fr.lastHeaderStream {
+ return fr.connError(ErrCodeProtocol,
+ fmt.Sprintf("got CONTINUATION for stream %d; expected stream %d",
+ fh.StreamID, fr.lastHeaderStream))
+ }
+ } else if fh.Type == FrameContinuation {
+ return fr.connError(ErrCodeProtocol, fmt.Sprintf("unexpected CONTINUATION for stream %d", fh.StreamID))
+ }
+
+ switch fh.Type {
+ case FrameHeaders, FrameContinuation:
+ if fh.Flags.Has(FlagHeadersEndHeaders) {
+ fr.lastHeaderStream = 0
+ } else {
+ fr.lastHeaderStream = fh.StreamID
+ }
+ }
+
+ return nil
+}
+
+// A DataFrame conveys arbitrary, variable-length sequences of octets
+// associated with a stream.
+// See http://http2.github.io/http2-spec/#rfc.section.6.1
+type DataFrame struct {
+ FrameHeader
+ data []byte
+}
+
+func (f *DataFrame) StreamEnded() bool {
+ return f.FrameHeader.Flags.Has(FlagDataEndStream)
+}
+
+// Data returns the frame's data octets, not including any padding
+// size byte or padding suffix bytes.
+// The caller must not retain the returned memory past the next
+// call to ReadFrame.
+func (f *DataFrame) Data() []byte {
+ f.checkValid()
+ return f.data
+}
+
+func parseDataFrame(fc *frameCache, fh FrameHeader, payload []byte) (Frame, error) {
+ if fh.StreamID == 0 {
+ // DATA frames MUST be associated with a stream. If a
+ // DATA frame is received whose stream identifier
+ // field is 0x0, the recipient MUST respond with a
+ // connection error (Section 5.4.1) of type
+ // PROTOCOL_ERROR.
+ return nil, connError{ErrCodeProtocol, "DATA frame with stream ID 0"}
+ }
+ f := fc.getDataFrame()
+ f.FrameHeader = fh
+
+ var padSize byte
+ if fh.Flags.Has(FlagDataPadded) {
+ var err error
+ payload, padSize, err = readByte(payload)
+ if err != nil {
+ return nil, err
+ }
+ }
+ if int(padSize) > len(payload) {
+ // If the length of the padding is greater than the
+ // length of the frame payload, the recipient MUST
+ // treat this as a connection error.
+ // Filed: https://github.com/http2/http2-spec/issues/610
+ return nil, connError{ErrCodeProtocol, "pad size larger than data payload"}
+ }
+ f.data = payload[:len(payload)-int(padSize)]
+ return f, nil
+}
+
+var (
+ errStreamID = errors.New("invalid stream ID")
+ errDepStreamID = errors.New("invalid dependent stream ID")
+ errPadLength = errors.New("pad length too large")
+ errPadBytes = errors.New("padding bytes must all be zeros unless AllowIllegalWrites is enabled")
+)
+
+func validStreamIDOrZero(streamID uint32) bool {
+ return streamID&(1<<31) == 0
+}
+
+func validStreamID(streamID uint32) bool {
+ return streamID != 0 && streamID&(1<<31) == 0
+}
+
+// WriteData writes a DATA frame.
+//
+// It will perform exactly one Write to the underlying Writer.
+// It is the caller's responsibility not to violate the maximum frame size
+// and to not call other Write methods concurrently.
+func (f *Framer) WriteData(streamID uint32, endStream bool, data []byte) error {
+ return f.WriteDataPadded(streamID, endStream, data, nil)
+}
+
+// WriteData writes a DATA frame with optional padding.
+//
+// If pad is nil, the padding bit is not sent.
+// The length of pad must not exceed 255 bytes.
+// The bytes of pad must all be zero, unless f.AllowIllegalWrites is set.
+//
+// It will perform exactly one Write to the underlying Writer.
+// It is the caller's responsibility not to violate the maximum frame size
+// and to not call other Write methods concurrently.
+func (f *Framer) WriteDataPadded(streamID uint32, endStream bool, data, pad []byte) error {
+ if !validStreamID(streamID) && !f.AllowIllegalWrites {
+ return errStreamID
+ }
+ if len(pad) > 0 {
+ if len(pad) > 255 {
+ return errPadLength
+ }
+ if !f.AllowIllegalWrites {
+ for _, b := range pad {
+ if b != 0 {
+ // "Padding octets MUST be set to zero when sending."
+ return errPadBytes
+ }
+ }
+ }
+ }
+ var flags Flags
+ if endStream {
+ flags |= FlagDataEndStream
+ }
+ if pad != nil {
+ flags |= FlagDataPadded
+ }
+ f.startWrite(FrameData, flags, streamID)
+ if pad != nil {
+ f.wbuf = append(f.wbuf, byte(len(pad)))
+ }
+ f.wbuf = append(f.wbuf, data...)
+ f.wbuf = append(f.wbuf, pad...)
+ return f.endWrite()
+}
+
+// A SettingsFrame conveys configuration parameters that affect how
+// endpoints communicate, such as preferences and constraints on peer
+// behavior.
+//
+// See http://http2.github.io/http2-spec/#SETTINGS
+type SettingsFrame struct {
+ FrameHeader
+ p []byte
+}
+
+func parseSettingsFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
+ if fh.Flags.Has(FlagSettingsAck) && fh.Length > 0 {
+ // When this (ACK 0x1) bit is set, the payload of the
+ // SETTINGS frame MUST be empty. Receipt of a
+ // SETTINGS frame with the ACK flag set and a length
+ // field value other than 0 MUST be treated as a
+ // connection error (Section 5.4.1) of type
+ // FRAME_SIZE_ERROR.
+ return nil, ConnectionError(ErrCodeFrameSize)
+ }
+ if fh.StreamID != 0 {
+ // SETTINGS frames always apply to a connection,
+ // never a single stream. The stream identifier for a
+ // SETTINGS frame MUST be zero (0x0). If an endpoint
+ // receives a SETTINGS frame whose stream identifier
+ // field is anything other than 0x0, the endpoint MUST
+ // respond with a connection error (Section 5.4.1) of
+ // type PROTOCOL_ERROR.
+ return nil, ConnectionError(ErrCodeProtocol)
+ }
+ if len(p)%6 != 0 {
+ // Expecting even number of 6 byte settings.
+ return nil, ConnectionError(ErrCodeFrameSize)
+ }
+ f := &SettingsFrame{FrameHeader: fh, p: p}
+ if v, ok := f.Value(SettingInitialWindowSize); ok && v > (1<<31)-1 {
+ // Values above the maximum flow control window size of 2^31 - 1 MUST
+ // be treated as a connection error (Section 5.4.1) of type
+ // FLOW_CONTROL_ERROR.
+ return nil, ConnectionError(ErrCodeFlowControl)
+ }
+ return f, nil
+}
+
+func (f *SettingsFrame) IsAck() bool {
+ return f.FrameHeader.Flags.Has(FlagSettingsAck)
+}
+
+func (f *SettingsFrame) Value(s SettingID) (v uint32, ok bool) {
+ f.checkValid()
+ buf := f.p
+ for len(buf) > 0 {
+ settingID := SettingID(binary.BigEndian.Uint16(buf[:2]))
+ if settingID == s {
+ return binary.BigEndian.Uint32(buf[2:6]), true
+ }
+ buf = buf[6:]
+ }
+ return 0, false
+}
+
+// ForeachSetting runs fn for each setting.
+// It stops and returns the first error.
+func (f *SettingsFrame) ForeachSetting(fn func(Setting) error) error {
+ f.checkValid()
+ buf := f.p
+ for len(buf) > 0 {
+ if err := fn(Setting{
+ SettingID(binary.BigEndian.Uint16(buf[:2])),
+ binary.BigEndian.Uint32(buf[2:6]),
+ }); err != nil {
+ return err
+ }
+ buf = buf[6:]
+ }
+ return nil
+}
+
+// WriteSettings writes a SETTINGS frame with zero or more settings
+// specified and the ACK bit not set.
+//
+// It will perform exactly one Write to the underlying Writer.
+// It is the caller's responsibility to not call other Write methods concurrently.
+func (f *Framer) WriteSettings(settings ...Setting) error {
+ f.startWrite(FrameSettings, 0, 0)
+ for _, s := range settings {
+ f.writeUint16(uint16(s.ID))
+ f.writeUint32(s.Val)
+ }
+ return f.endWrite()
+}
+
+// WriteSettingsAck writes an empty SETTINGS frame with the ACK bit set.
+//
+// It will perform exactly one Write to the underlying Writer.
+// It is the caller's responsibility to not call other Write methods concurrently.
+func (f *Framer) WriteSettingsAck() error {
+ f.startWrite(FrameSettings, FlagSettingsAck, 0)
+ return f.endWrite()
+}
+
+// A PingFrame is a mechanism for measuring a minimal round trip time
+// from the sender, as well as determining whether an idle connection
+// is still functional.
+// See http://http2.github.io/http2-spec/#rfc.section.6.7
+type PingFrame struct {
+ FrameHeader
+ Data [8]byte
+}
+
+func (f *PingFrame) IsAck() bool { return f.Flags.Has(FlagPingAck) }
+
+func parsePingFrame(_ *frameCache, fh FrameHeader, payload []byte) (Frame, error) {
+ if len(payload) != 8 {
+ return nil, ConnectionError(ErrCodeFrameSize)
+ }
+ if fh.StreamID != 0 {
+ return nil, ConnectionError(ErrCodeProtocol)
+ }
+ f := &PingFrame{FrameHeader: fh}
+ copy(f.Data[:], payload)
+ return f, nil
+}
+
+func (f *Framer) WritePing(ack bool, data [8]byte) error {
+ var flags Flags
+ if ack {
+ flags = FlagPingAck
+ }
+ f.startWrite(FramePing, flags, 0)
+ f.writeBytes(data[:])
+ return f.endWrite()
+}
+
+// A GoAwayFrame informs the remote peer to stop creating streams on this connection.
+// See http://http2.github.io/http2-spec/#rfc.section.6.8
+type GoAwayFrame struct {
+ FrameHeader
+ LastStreamID uint32
+ ErrCode ErrCode
+ debugData []byte
+}
+
+// DebugData returns any debug data in the GOAWAY frame. Its contents
+// are not defined.
+// The caller must not retain the returned memory past the next
+// call to ReadFrame.
+func (f *GoAwayFrame) DebugData() []byte {
+ f.checkValid()
+ return f.debugData
+}
+
+func parseGoAwayFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
+ if fh.StreamID != 0 {
+ return nil, ConnectionError(ErrCodeProtocol)
+ }
+ if len(p) < 8 {
+ return nil, ConnectionError(ErrCodeFrameSize)
+ }
+ return &GoAwayFrame{
+ FrameHeader: fh,
+ LastStreamID: binary.BigEndian.Uint32(p[:4]) & (1<<31 - 1),
+ ErrCode: ErrCode(binary.BigEndian.Uint32(p[4:8])),
+ debugData: p[8:],
+ }, nil
+}
+
+func (f *Framer) WriteGoAway(maxStreamID uint32, code ErrCode, debugData []byte) error {
+ f.startWrite(FrameGoAway, 0, 0)
+ f.writeUint32(maxStreamID & (1<<31 - 1))
+ f.writeUint32(uint32(code))
+ f.writeBytes(debugData)
+ return f.endWrite()
+}
+
+// An UnknownFrame is the frame type returned when the frame type is unknown
+// or no specific frame type parser exists.
+type UnknownFrame struct {
+ FrameHeader
+ p []byte
+}
+
+// Payload returns the frame's payload (after the header). It is not
+// valid to call this method after a subsequent call to
+// Framer.ReadFrame, nor is it valid to retain the returned slice.
+// The memory is owned by the Framer and is invalidated when the next
+// frame is read.
+func (f *UnknownFrame) Payload() []byte {
+ f.checkValid()
+ return f.p
+}
+
+func parseUnknownFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
+ return &UnknownFrame{fh, p}, nil
+}
+
+// A WindowUpdateFrame is used to implement flow control.
+// See http://http2.github.io/http2-spec/#rfc.section.6.9
+type WindowUpdateFrame struct {
+ FrameHeader
+ Increment uint32 // never read with high bit set
+}
+
+func parseWindowUpdateFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
+ if len(p) != 4 {
+ return nil, ConnectionError(ErrCodeFrameSize)
+ }
+ inc := binary.BigEndian.Uint32(p[:4]) & 0x7fffffff // mask off high reserved bit
+ if inc == 0 {
+ // A receiver MUST treat the receipt of a
+ // WINDOW_UPDATE frame with an flow control window
+ // increment of 0 as a stream error (Section 5.4.2) of
+ // type PROTOCOL_ERROR; errors on the connection flow
+ // control window MUST be treated as a connection
+ // error (Section 5.4.1).
+ if fh.StreamID == 0 {
+ return nil, ConnectionError(ErrCodeProtocol)
+ }
+ return nil, streamError(fh.StreamID, ErrCodeProtocol)
+ }
+ return &WindowUpdateFrame{
+ FrameHeader: fh,
+ Increment: inc,
+ }, nil
+}
+
+// WriteWindowUpdate writes a WINDOW_UPDATE frame.
+// The increment value must be between 1 and 2,147,483,647, inclusive.
+// If the Stream ID is zero, the window update applies to the
+// connection as a whole.
+func (f *Framer) WriteWindowUpdate(streamID, incr uint32) error {
+ // "The legal range for the increment to the flow control window is 1 to 2^31-1 (2,147,483,647) octets."
+ if (incr < 1 || incr > 2147483647) && !f.AllowIllegalWrites {
+ return errors.New("illegal window increment value")
+ }
+ f.startWrite(FrameWindowUpdate, 0, streamID)
+ f.writeUint32(incr)
+ return f.endWrite()
+}
+
+// A HeadersFrame is used to open a stream and additionally carries a
+// header block fragment.
+type HeadersFrame struct {
+ FrameHeader
+
+ // Priority is set if FlagHeadersPriority is set in the FrameHeader.
+ Priority PriorityParam
+
+ headerFragBuf []byte // not owned
+}
+
+func (f *HeadersFrame) HeaderBlockFragment() []byte {
+ f.checkValid()
+ return f.headerFragBuf
+}
+
+func (f *HeadersFrame) HeadersEnded() bool {
+ return f.FrameHeader.Flags.Has(FlagHeadersEndHeaders)
+}
+
+func (f *HeadersFrame) StreamEnded() bool {
+ return f.FrameHeader.Flags.Has(FlagHeadersEndStream)
+}
+
+func (f *HeadersFrame) HasPriority() bool {
+ return f.FrameHeader.Flags.Has(FlagHeadersPriority)
+}
+
+func parseHeadersFrame(_ *frameCache, fh FrameHeader, p []byte) (_ Frame, err error) {
+ hf := &HeadersFrame{
+ FrameHeader: fh,
+ }
+ if fh.StreamID == 0 {
+ // HEADERS frames MUST be associated with a stream. If a HEADERS frame
+ // is received whose stream identifier field is 0x0, the recipient MUST
+ // respond with a connection error (Section 5.4.1) of type
+ // PROTOCOL_ERROR.
+ return nil, connError{ErrCodeProtocol, "HEADERS frame with stream ID 0"}
+ }
+ var padLength uint8
+ if fh.Flags.Has(FlagHeadersPadded) {
+ if p, padLength, err = readByte(p); err != nil {
+ return
+ }
+ }
+ if fh.Flags.Has(FlagHeadersPriority) {
+ var v uint32
+ p, v, err = readUint32(p)
+ if err != nil {
+ return nil, err
+ }
+ hf.Priority.StreamDep = v & 0x7fffffff
+ hf.Priority.Exclusive = (v != hf.Priority.StreamDep) // high bit was set
+ p, hf.Priority.Weight, err = readByte(p)
+ if err != nil {
+ return nil, err
+ }
+ }
+ if len(p)-int(padLength) <= 0 {
+ return nil, streamError(fh.StreamID, ErrCodeProtocol)
+ }
+ hf.headerFragBuf = p[:len(p)-int(padLength)]
+ return hf, nil
+}
+
+// HeadersFrameParam are the parameters for writing a HEADERS frame.
+type HeadersFrameParam struct {
+ // StreamID is the required Stream ID to initiate.
+ StreamID uint32
+ // BlockFragment is part (or all) of a Header Block.
+ BlockFragment []byte
+
+ // EndStream indicates that the header block is the last that
+ // the endpoint will send for the identified stream. Setting
+ // this flag causes the stream to enter one of "half closed"
+ // states.
+ EndStream bool
+
+ // EndHeaders indicates that this frame contains an entire
+ // header block and is not followed by any
+ // CONTINUATION frames.
+ EndHeaders bool
+
+ // PadLength is the optional number of bytes of zeros to add
+ // to this frame.
+ PadLength uint8
+
+ // Priority, if non-zero, includes stream priority information
+ // in the HEADER frame.
+ Priority PriorityParam
+}
+
+// WriteHeaders writes a single HEADERS frame.
+//
+// This is a low-level header writing method. Encoding headers and
+// splitting them into any necessary CONTINUATION frames is handled
+// elsewhere.
+//
+// It will perform exactly one Write to the underlying Writer.
+// It is the caller's responsibility to not call other Write methods concurrently.
+func (f *Framer) WriteHeaders(p HeadersFrameParam) error {
+ if !validStreamID(p.StreamID) && !f.AllowIllegalWrites {
+ return errStreamID
+ }
+ var flags Flags
+ if p.PadLength != 0 {
+ flags |= FlagHeadersPadded
+ }
+ if p.EndStream {
+ flags |= FlagHeadersEndStream
+ }
+ if p.EndHeaders {
+ flags |= FlagHeadersEndHeaders
+ }
+ if !p.Priority.IsZero() {
+ flags |= FlagHeadersPriority
+ }
+ f.startWrite(FrameHeaders, flags, p.StreamID)
+ if p.PadLength != 0 {
+ f.writeByte(p.PadLength)
+ }
+ if !p.Priority.IsZero() {
+ v := p.Priority.StreamDep
+ if !validStreamIDOrZero(v) && !f.AllowIllegalWrites {
+ return errDepStreamID
+ }
+ if p.Priority.Exclusive {
+ v |= 1 << 31
+ }
+ f.writeUint32(v)
+ f.writeByte(p.Priority.Weight)
+ }
+ f.wbuf = append(f.wbuf, p.BlockFragment...)
+ f.wbuf = append(f.wbuf, padZeros[:p.PadLength]...)
+ return f.endWrite()
+}
+
+// A PriorityFrame specifies the sender-advised priority of a stream.
+// See http://http2.github.io/http2-spec/#rfc.section.6.3
+type PriorityFrame struct {
+ FrameHeader
+ PriorityParam
+}
+
+// PriorityParam are the stream prioritzation parameters.
+type PriorityParam struct {
+ // StreamDep is a 31-bit stream identifier for the
+ // stream that this stream depends on. Zero means no
+ // dependency.
+ StreamDep uint32
+
+ // Exclusive is whether the dependency is exclusive.
+ Exclusive bool
+
+ // Weight is the stream's zero-indexed weight. It should be
+ // set together with StreamDep, or neither should be set. Per
+ // the spec, "Add one to the value to obtain a weight between
+ // 1 and 256."
+ Weight uint8
+}
+
+func (p PriorityParam) IsZero() bool {
+ return p == PriorityParam{}
+}
+
+func parsePriorityFrame(_ *frameCache, fh FrameHeader, payload []byte) (Frame, error) {
+ if fh.StreamID == 0 {
+ return nil, connError{ErrCodeProtocol, "PRIORITY frame with stream ID 0"}
+ }
+ if len(payload) != 5 {
+ return nil, connError{ErrCodeFrameSize, fmt.Sprintf("PRIORITY frame payload size was %d; want 5", len(payload))}
+ }
+ v := binary.BigEndian.Uint32(payload[:4])
+ streamID := v & 0x7fffffff // mask off high bit
+ return &PriorityFrame{
+ FrameHeader: fh,
+ PriorityParam: PriorityParam{
+ Weight: payload[4],
+ StreamDep: streamID,
+ Exclusive: streamID != v, // was high bit set?
+ },
+ }, nil
+}
+
+// WritePriority writes a PRIORITY frame.
+//
+// It will perform exactly one Write to the underlying Writer.
+// It is the caller's responsibility to not call other Write methods concurrently.
+func (f *Framer) WritePriority(streamID uint32, p PriorityParam) error {
+ if !validStreamID(streamID) && !f.AllowIllegalWrites {
+ return errStreamID
+ }
+ if !validStreamIDOrZero(p.StreamDep) {
+ return errDepStreamID
+ }
+ f.startWrite(FramePriority, 0, streamID)
+ v := p.StreamDep
+ if p.Exclusive {
+ v |= 1 << 31
+ }
+ f.writeUint32(v)
+ f.writeByte(p.Weight)
+ return f.endWrite()
+}
+
+// A RSTStreamFrame allows for abnormal termination of a stream.
+// See http://http2.github.io/http2-spec/#rfc.section.6.4
+type RSTStreamFrame struct {
+ FrameHeader
+ ErrCode ErrCode
+}
+
+func parseRSTStreamFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
+ if len(p) != 4 {
+ return nil, ConnectionError(ErrCodeFrameSize)
+ }
+ if fh.StreamID == 0 {
+ return nil, ConnectionError(ErrCodeProtocol)
+ }
+ return &RSTStreamFrame{fh, ErrCode(binary.BigEndian.Uint32(p[:4]))}, nil
+}
+
+// WriteRSTStream writes a RST_STREAM frame.
+//
+// It will perform exactly one Write to the underlying Writer.
+// It is the caller's responsibility to not call other Write methods concurrently.
+func (f *Framer) WriteRSTStream(streamID uint32, code ErrCode) error {
+ if !validStreamID(streamID) && !f.AllowIllegalWrites {
+ return errStreamID
+ }
+ f.startWrite(FrameRSTStream, 0, streamID)
+ f.writeUint32(uint32(code))
+ return f.endWrite()
+}
+
+// A ContinuationFrame is used to continue a sequence of header block fragments.
+// See http://http2.github.io/http2-spec/#rfc.section.6.10
+type ContinuationFrame struct {
+ FrameHeader
+ headerFragBuf []byte
+}
+
+func parseContinuationFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
+ if fh.StreamID == 0 {
+ return nil, connError{ErrCodeProtocol, "CONTINUATION frame with stream ID 0"}
+ }
+ return &ContinuationFrame{fh, p}, nil
+}
+
+func (f *ContinuationFrame) HeaderBlockFragment() []byte {
+ f.checkValid()
+ return f.headerFragBuf
+}
+
+func (f *ContinuationFrame) HeadersEnded() bool {
+ return f.FrameHeader.Flags.Has(FlagContinuationEndHeaders)
+}
+
+// WriteContinuation writes a CONTINUATION frame.
+//
+// It will perform exactly one Write to the underlying Writer.
+// It is the caller's responsibility to not call other Write methods concurrently.
+func (f *Framer) WriteContinuation(streamID uint32, endHeaders bool, headerBlockFragment []byte) error {
+ if !validStreamID(streamID) && !f.AllowIllegalWrites {
+ return errStreamID
+ }
+ var flags Flags
+ if endHeaders {
+ flags |= FlagContinuationEndHeaders
+ }
+ f.startWrite(FrameContinuation, flags, streamID)
+ f.wbuf = append(f.wbuf, headerBlockFragment...)
+ return f.endWrite()
+}
+
+// A PushPromiseFrame is used to initiate a server stream.
+// See http://http2.github.io/http2-spec/#rfc.section.6.6
+type PushPromiseFrame struct {
+ FrameHeader
+ PromiseID uint32
+ headerFragBuf []byte // not owned
+}
+
+func (f *PushPromiseFrame) HeaderBlockFragment() []byte {
+ f.checkValid()
+ return f.headerFragBuf
+}
+
+func (f *PushPromiseFrame) HeadersEnded() bool {
+ return f.FrameHeader.Flags.Has(FlagPushPromiseEndHeaders)
+}
+
+func parsePushPromise(_ *frameCache, fh FrameHeader, p []byte) (_ Frame, err error) {
+ pp := &PushPromiseFrame{
+ FrameHeader: fh,
+ }
+ if pp.StreamID == 0 {
+ // PUSH_PROMISE frames MUST be associated with an existing,
+ // peer-initiated stream. The stream identifier of a
+ // PUSH_PROMISE frame indicates the stream it is associated
+ // with. If the stream identifier field specifies the value
+ // 0x0, a recipient MUST respond with a connection error
+ // (Section 5.4.1) of type PROTOCOL_ERROR.
+ return nil, ConnectionError(ErrCodeProtocol)
+ }
+ // The PUSH_PROMISE frame includes optional padding.
+ // Padding fields and flags are identical to those defined for DATA frames
+ var padLength uint8
+ if fh.Flags.Has(FlagPushPromisePadded) {
+ if p, padLength, err = readByte(p); err != nil {
+ return
+ }
+ }
+
+ p, pp.PromiseID, err = readUint32(p)
+ if err != nil {
+ return
+ }
+ pp.PromiseID = pp.PromiseID & (1<<31 - 1)
+
+ if int(padLength) > len(p) {
+ // like the DATA frame, error out if padding is longer than the body.
+ return nil, ConnectionError(ErrCodeProtocol)
+ }
+ pp.headerFragBuf = p[:len(p)-int(padLength)]
+ return pp, nil
+}
+
+// PushPromiseParam are the parameters for writing a PUSH_PROMISE frame.
+type PushPromiseParam struct {
+ // StreamID is the required Stream ID to initiate.
+ StreamID uint32
+
+ // PromiseID is the required Stream ID which this
+ // Push Promises
+ PromiseID uint32
+
+ // BlockFragment is part (or all) of a Header Block.
+ BlockFragment []byte
+
+ // EndHeaders indicates that this frame contains an entire
+ // header block and is not followed by any
+ // CONTINUATION frames.
+ EndHeaders bool
+
+ // PadLength is the optional number of bytes of zeros to add
+ // to this frame.
+ PadLength uint8
+}
+
+// WritePushPromise writes a single PushPromise Frame.
+//
+// As with Header Frames, This is the low level call for writing
+// individual frames. Continuation frames are handled elsewhere.
+//
+// It will perform exactly one Write to the underlying Writer.
+// It is the caller's responsibility to not call other Write methods concurrently.
+func (f *Framer) WritePushPromise(p PushPromiseParam) error {
+ if !validStreamID(p.StreamID) && !f.AllowIllegalWrites {
+ return errStreamID
+ }
+ var flags Flags
+ if p.PadLength != 0 {
+ flags |= FlagPushPromisePadded
+ }
+ if p.EndHeaders {
+ flags |= FlagPushPromiseEndHeaders
+ }
+ f.startWrite(FramePushPromise, flags, p.StreamID)
+ if p.PadLength != 0 {
+ f.writeByte(p.PadLength)
+ }
+ if !validStreamID(p.PromiseID) && !f.AllowIllegalWrites {
+ return errStreamID
+ }
+ f.writeUint32(p.PromiseID)
+ f.wbuf = append(f.wbuf, p.BlockFragment...)
+ f.wbuf = append(f.wbuf, padZeros[:p.PadLength]...)
+ return f.endWrite()
+}
+
+// WriteRawFrame writes a raw frame. This can be used to write
+// extension frames unknown to this package.
+func (f *Framer) WriteRawFrame(t FrameType, flags Flags, streamID uint32, payload []byte) error {
+ f.startWrite(t, flags, streamID)
+ f.writeBytes(payload)
+ return f.endWrite()
+}
+
+func readByte(p []byte) (remain []byte, b byte, err error) {
+ if len(p) == 0 {
+ return nil, 0, io.ErrUnexpectedEOF
+ }
+ return p[1:], p[0], nil
+}
+
+func readUint32(p []byte) (remain []byte, v uint32, err error) {
+ if len(p) < 4 {
+ return nil, 0, io.ErrUnexpectedEOF
+ }
+ return p[4:], binary.BigEndian.Uint32(p[:4]), nil
+}
+
+type streamEnder interface {
+ StreamEnded() bool
+}
+
+type headersEnder interface {
+ HeadersEnded() bool
+}
+
+type headersOrContinuation interface {
+ headersEnder
+ HeaderBlockFragment() []byte
+}
+
+// A MetaHeadersFrame is the representation of one HEADERS frame and
+// zero or more contiguous CONTINUATION frames and the decoding of
+// their HPACK-encoded contents.
+//
+// This type of frame does not appear on the wire and is only returned
+// by the Framer when Framer.ReadMetaHeaders is set.
+type MetaHeadersFrame struct {
+ *HeadersFrame
+
+ // Fields are the fields contained in the HEADERS and
+ // CONTINUATION frames. The underlying slice is owned by the
+ // Framer and must not be retained after the next call to
+ // ReadFrame.
+ //
+ // Fields are guaranteed to be in the correct http2 order and
+ // not have unknown pseudo header fields or invalid header
+ // field names or values. Required pseudo header fields may be
+ // missing, however. Use the MetaHeadersFrame.Pseudo accessor
+ // method access pseudo headers.
+ Fields []hpack.HeaderField
+
+ // Truncated is whether the max header list size limit was hit
+ // and Fields is incomplete. The hpack decoder state is still
+ // valid, however.
+ Truncated bool
+}
+
+// PseudoValue returns the given pseudo header field's value.
+// The provided pseudo field should not contain the leading colon.
+func (mh *MetaHeadersFrame) PseudoValue(pseudo string) string {
+ for _, hf := range mh.Fields {
+ if !hf.IsPseudo() {
+ return ""
+ }
+ if hf.Name[1:] == pseudo {
+ return hf.Value
+ }
+ }
+ return ""
+}
+
+// RegularFields returns the regular (non-pseudo) header fields of mh.
+// The caller does not own the returned slice.
+func (mh *MetaHeadersFrame) RegularFields() []hpack.HeaderField {
+ for i, hf := range mh.Fields {
+ if !hf.IsPseudo() {
+ return mh.Fields[i:]
+ }
+ }
+ return nil
+}
+
+// PseudoFields returns the pseudo header fields of mh.
+// The caller does not own the returned slice.
+func (mh *MetaHeadersFrame) PseudoFields() []hpack.HeaderField {
+ for i, hf := range mh.Fields {
+ if !hf.IsPseudo() {
+ return mh.Fields[:i]
+ }
+ }
+ return mh.Fields
+}
+
+func (mh *MetaHeadersFrame) checkPseudos() error {
+ var isRequest, isResponse bool
+ pf := mh.PseudoFields()
+ for i, hf := range pf {
+ switch hf.Name {
+ case ":method", ":path", ":scheme", ":authority":
+ isRequest = true
+ case ":status":
+ isResponse = true
+ default:
+ return pseudoHeaderError(hf.Name)
+ }
+ // Check for duplicates.
+ // This would be a bad algorithm, but N is 4.
+ // And this doesn't allocate.
+ for _, hf2 := range pf[:i] {
+ if hf.Name == hf2.Name {
+ return duplicatePseudoHeaderError(hf.Name)
+ }
+ }
+ }
+ if isRequest && isResponse {
+ return errMixPseudoHeaderTypes
+ }
+ return nil
+}
+
+func (fr *Framer) maxHeaderStringLen() int {
+ v := fr.maxHeaderListSize()
+ if uint32(int(v)) == v {
+ return int(v)
+ }
+ // They had a crazy big number for MaxHeaderBytes anyway,
+ // so give them unlimited header lengths:
+ return 0
+}
+
+// readMetaFrame returns 0 or more CONTINUATION frames from fr and
+// merge them into into the provided hf and returns a MetaHeadersFrame
+// with the decoded hpack values.
+func (fr *Framer) readMetaFrame(hf *HeadersFrame) (*MetaHeadersFrame, error) {
+ if fr.AllowIllegalReads {
+ return nil, errors.New("illegal use of AllowIllegalReads with ReadMetaHeaders")
+ }
+ mh := &MetaHeadersFrame{
+ HeadersFrame: hf,
+ }
+ var remainSize = fr.maxHeaderListSize()
+ var sawRegular bool
+
+ var invalid error // pseudo header field errors
+ hdec := fr.ReadMetaHeaders
+ hdec.SetEmitEnabled(true)
+ hdec.SetMaxStringLength(fr.maxHeaderStringLen())
+ hdec.SetEmitFunc(func(hf hpack.HeaderField) {
+ if VerboseLogs && fr.logReads {
+ fr.debugReadLoggerf("http2: decoded hpack field %+v", hf)
+ }
+ if !httplex.ValidHeaderFieldValue(hf.Value) {
+ invalid = headerFieldValueError(hf.Value)
+ }
+ isPseudo := strings.HasPrefix(hf.Name, ":")
+ if isPseudo {
+ if sawRegular {
+ invalid = errPseudoAfterRegular
+ }
+ } else {
+ sawRegular = true
+ if !validWireHeaderFieldName(hf.Name) {
+ invalid = headerFieldNameError(hf.Name)
+ }
+ }
+
+ if invalid != nil {
+ hdec.SetEmitEnabled(false)
+ return
+ }
+
+ size := hf.Size()
+ if size > remainSize {
+ hdec.SetEmitEnabled(false)
+ mh.Truncated = true
+ return
+ }
+ remainSize -= size
+
+ mh.Fields = append(mh.Fields, hf)
+ })
+ // Lose reference to MetaHeadersFrame:
+ defer hdec.SetEmitFunc(func(hf hpack.HeaderField) {})
+
+ var hc headersOrContinuation = hf
+ for {
+ frag := hc.HeaderBlockFragment()
+ if _, err := hdec.Write(frag); err != nil {
+ return nil, ConnectionError(ErrCodeCompression)
+ }
+
+ if hc.HeadersEnded() {
+ break
+ }
+ if f, err := fr.ReadFrame(); err != nil {
+ return nil, err
+ } else {
+ hc = f.(*ContinuationFrame) // guaranteed by checkFrameOrder
+ }
+ }
+
+ mh.HeadersFrame.headerFragBuf = nil
+ mh.HeadersFrame.invalidate()
+
+ if err := hdec.Close(); err != nil {
+ return nil, ConnectionError(ErrCodeCompression)
+ }
+ if invalid != nil {
+ fr.errDetail = invalid
+ if VerboseLogs {
+ log.Printf("http2: invalid header: %v", invalid)
+ }
+ return nil, StreamError{mh.StreamID, ErrCodeProtocol, invalid}
+ }
+ if err := mh.checkPseudos(); err != nil {
+ fr.errDetail = err
+ if VerboseLogs {
+ log.Printf("http2: invalid pseudo headers: %v", err)
+ }
+ return nil, StreamError{mh.StreamID, ErrCodeProtocol, err}
+ }
+ return mh, nil
+}
+
+func summarizeFrame(f Frame) string {
+ var buf bytes.Buffer
+ f.Header().writeDebug(&buf)
+ switch f := f.(type) {
+ case *SettingsFrame:
+ n := 0
+ f.ForeachSetting(func(s Setting) error {
+ n++
+ if n == 1 {
+ buf.WriteString(", settings:")
+ }
+ fmt.Fprintf(&buf, " %v=%v,", s.ID, s.Val)
+ return nil
+ })
+ if n > 0 {
+ buf.Truncate(buf.Len() - 1) // remove trailing comma
+ }
+ case *DataFrame:
+ data := f.Data()
+ const max = 256
+ if len(data) > max {
+ data = data[:max]
+ }
+ fmt.Fprintf(&buf, " data=%q", data)
+ if len(f.Data()) > max {
+ fmt.Fprintf(&buf, " (%d bytes omitted)", len(f.Data())-max)
+ }
+ case *WindowUpdateFrame:
+ if f.StreamID == 0 {
+ buf.WriteString(" (conn)")
+ }
+ fmt.Fprintf(&buf, " incr=%v", f.Increment)
+ case *PingFrame:
+ fmt.Fprintf(&buf, " ping=%q", f.Data[:])
+ case *GoAwayFrame:
+ fmt.Fprintf(&buf, " LastStreamID=%v ErrCode=%v Debug=%q",
+ f.LastStreamID, f.ErrCode, f.debugData)
+ case *RSTStreamFrame:
+ fmt.Fprintf(&buf, " ErrCode=%v", f.ErrCode)
+ }
+ return buf.String()
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/frame_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/frame_test.go
new file mode 100644
index 000000000..37266bc58
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/frame_test.go
@@ -0,0 +1,1191 @@
+// Copyright 2014 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 http2
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "reflect"
+ "strings"
+ "testing"
+ "unsafe"
+
+ "golang.org/x/net/http2/hpack"
+)
+
+func testFramer() (*Framer, *bytes.Buffer) {
+ buf := new(bytes.Buffer)
+ return NewFramer(buf, buf), buf
+}
+
+func TestFrameSizes(t *testing.T) {
+ // Catch people rearranging the FrameHeader fields.
+ if got, want := int(unsafe.Sizeof(FrameHeader{})), 12; got != want {
+ t.Errorf("FrameHeader size = %d; want %d", got, want)
+ }
+}
+
+func TestFrameTypeString(t *testing.T) {
+ tests := []struct {
+ ft FrameType
+ want string
+ }{
+ {FrameData, "DATA"},
+ {FramePing, "PING"},
+ {FrameGoAway, "GOAWAY"},
+ {0xf, "UNKNOWN_FRAME_TYPE_15"},
+ }
+
+ for i, tt := range tests {
+ got := tt.ft.String()
+ if got != tt.want {
+ t.Errorf("%d. String(FrameType %d) = %q; want %q", i, int(tt.ft), got, tt.want)
+ }
+ }
+}
+
+func TestWriteRST(t *testing.T) {
+ fr, buf := testFramer()
+ var streamID uint32 = 1<<24 + 2<<16 + 3<<8 + 4
+ var errCode uint32 = 7<<24 + 6<<16 + 5<<8 + 4
+ fr.WriteRSTStream(streamID, ErrCode(errCode))
+ const wantEnc = "\x00\x00\x04\x03\x00\x01\x02\x03\x04\x07\x06\x05\x04"
+ if buf.String() != wantEnc {
+ t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
+ }
+ f, err := fr.ReadFrame()
+ if err != nil {
+ t.Fatal(err)
+ }
+ want := &RSTStreamFrame{
+ FrameHeader: FrameHeader{
+ valid: true,
+ Type: 0x3,
+ Flags: 0x0,
+ Length: 0x4,
+ StreamID: 0x1020304,
+ },
+ ErrCode: 0x7060504,
+ }
+ if !reflect.DeepEqual(f, want) {
+ t.Errorf("parsed back %#v; want %#v", f, want)
+ }
+}
+
+func TestWriteData(t *testing.T) {
+ fr, buf := testFramer()
+ var streamID uint32 = 1<<24 + 2<<16 + 3<<8 + 4
+ data := []byte("ABC")
+ fr.WriteData(streamID, true, data)
+ const wantEnc = "\x00\x00\x03\x00\x01\x01\x02\x03\x04ABC"
+ if buf.String() != wantEnc {
+ t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
+ }
+ f, err := fr.ReadFrame()
+ if err != nil {
+ t.Fatal(err)
+ }
+ df, ok := f.(*DataFrame)
+ if !ok {
+ t.Fatalf("got %T; want *DataFrame", f)
+ }
+ if !bytes.Equal(df.Data(), data) {
+ t.Errorf("got %q; want %q", df.Data(), data)
+ }
+ if f.Header().Flags&1 == 0 {
+ t.Errorf("didn't see END_STREAM flag")
+ }
+}
+
+func TestWriteDataPadded(t *testing.T) {
+ tests := [...]struct {
+ streamID uint32
+ endStream bool
+ data []byte
+ pad []byte
+ wantHeader FrameHeader
+ }{
+ // Unpadded:
+ 0: {
+ streamID: 1,
+ endStream: true,
+ data: []byte("foo"),
+ pad: nil,
+ wantHeader: FrameHeader{
+ Type: FrameData,
+ Flags: FlagDataEndStream,
+ Length: 3,
+ StreamID: 1,
+ },
+ },
+
+ // Padded bit set, but no padding:
+ 1: {
+ streamID: 1,
+ endStream: true,
+ data: []byte("foo"),
+ pad: []byte{},
+ wantHeader: FrameHeader{
+ Type: FrameData,
+ Flags: FlagDataEndStream | FlagDataPadded,
+ Length: 4,
+ StreamID: 1,
+ },
+ },
+
+ // Padded bit set, with padding:
+ 2: {
+ streamID: 1,
+ endStream: false,
+ data: []byte("foo"),
+ pad: []byte{0, 0, 0},
+ wantHeader: FrameHeader{
+ Type: FrameData,
+ Flags: FlagDataPadded,
+ Length: 7,
+ StreamID: 1,
+ },
+ },
+ }
+ for i, tt := range tests {
+ fr, _ := testFramer()
+ fr.WriteDataPadded(tt.streamID, tt.endStream, tt.data, tt.pad)
+ f, err := fr.ReadFrame()
+ if err != nil {
+ t.Errorf("%d. ReadFrame: %v", i, err)
+ continue
+ }
+ got := f.Header()
+ tt.wantHeader.valid = true
+ if got != tt.wantHeader {
+ t.Errorf("%d. read %+v; want %+v", i, got, tt.wantHeader)
+ continue
+ }
+ df := f.(*DataFrame)
+ if !bytes.Equal(df.Data(), tt.data) {
+ t.Errorf("%d. got %q; want %q", i, df.Data(), tt.data)
+ }
+ }
+}
+
+func TestWriteHeaders(t *testing.T) {
+ tests := []struct {
+ name string
+ p HeadersFrameParam
+ wantEnc string
+ wantFrame *HeadersFrame
+ }{
+ {
+ "basic",
+ HeadersFrameParam{
+ StreamID: 42,
+ BlockFragment: []byte("abc"),
+ Priority: PriorityParam{},
+ },
+ "\x00\x00\x03\x01\x00\x00\x00\x00*abc",
+ &HeadersFrame{
+ FrameHeader: FrameHeader{
+ valid: true,
+ StreamID: 42,
+ Type: FrameHeaders,
+ Length: uint32(len("abc")),
+ },
+ Priority: PriorityParam{},
+ headerFragBuf: []byte("abc"),
+ },
+ },
+ {
+ "basic + end flags",
+ HeadersFrameParam{
+ StreamID: 42,
+ BlockFragment: []byte("abc"),
+ EndStream: true,
+ EndHeaders: true,
+ Priority: PriorityParam{},
+ },
+ "\x00\x00\x03\x01\x05\x00\x00\x00*abc",
+ &HeadersFrame{
+ FrameHeader: FrameHeader{
+ valid: true,
+ StreamID: 42,
+ Type: FrameHeaders,
+ Flags: FlagHeadersEndStream | FlagHeadersEndHeaders,
+ Length: uint32(len("abc")),
+ },
+ Priority: PriorityParam{},
+ headerFragBuf: []byte("abc"),
+ },
+ },
+ {
+ "with padding",
+ HeadersFrameParam{
+ StreamID: 42,
+ BlockFragment: []byte("abc"),
+ EndStream: true,
+ EndHeaders: true,
+ PadLength: 5,
+ Priority: PriorityParam{},
+ },
+ "\x00\x00\t\x01\r\x00\x00\x00*\x05abc\x00\x00\x00\x00\x00",
+ &HeadersFrame{
+ FrameHeader: FrameHeader{
+ valid: true,
+ StreamID: 42,
+ Type: FrameHeaders,
+ Flags: FlagHeadersEndStream | FlagHeadersEndHeaders | FlagHeadersPadded,
+ Length: uint32(1 + len("abc") + 5), // pad length + contents + padding
+ },
+ Priority: PriorityParam{},
+ headerFragBuf: []byte("abc"),
+ },
+ },
+ {
+ "with priority",
+ HeadersFrameParam{
+ StreamID: 42,
+ BlockFragment: []byte("abc"),
+ EndStream: true,
+ EndHeaders: true,
+ PadLength: 2,
+ Priority: PriorityParam{
+ StreamDep: 15,
+ Exclusive: true,
+ Weight: 127,
+ },
+ },
+ "\x00\x00\v\x01-\x00\x00\x00*\x02\x80\x00\x00\x0f\u007fabc\x00\x00",
+ &HeadersFrame{
+ FrameHeader: FrameHeader{
+ valid: true,
+ StreamID: 42,
+ Type: FrameHeaders,
+ Flags: FlagHeadersEndStream | FlagHeadersEndHeaders | FlagHeadersPadded | FlagHeadersPriority,
+ Length: uint32(1 + 5 + len("abc") + 2), // pad length + priority + contents + padding
+ },
+ Priority: PriorityParam{
+ StreamDep: 15,
+ Exclusive: true,
+ Weight: 127,
+ },
+ headerFragBuf: []byte("abc"),
+ },
+ },
+ {
+ "with priority stream dep zero", // golang.org/issue/15444
+ HeadersFrameParam{
+ StreamID: 42,
+ BlockFragment: []byte("abc"),
+ EndStream: true,
+ EndHeaders: true,
+ PadLength: 2,
+ Priority: PriorityParam{
+ StreamDep: 0,
+ Exclusive: true,
+ Weight: 127,
+ },
+ },
+ "\x00\x00\v\x01-\x00\x00\x00*\x02\x80\x00\x00\x00\u007fabc\x00\x00",
+ &HeadersFrame{
+ FrameHeader: FrameHeader{
+ valid: true,
+ StreamID: 42,
+ Type: FrameHeaders,
+ Flags: FlagHeadersEndStream | FlagHeadersEndHeaders | FlagHeadersPadded | FlagHeadersPriority,
+ Length: uint32(1 + 5 + len("abc") + 2), // pad length + priority + contents + padding
+ },
+ Priority: PriorityParam{
+ StreamDep: 0,
+ Exclusive: true,
+ Weight: 127,
+ },
+ headerFragBuf: []byte("abc"),
+ },
+ },
+ }
+ for _, tt := range tests {
+ fr, buf := testFramer()
+ if err := fr.WriteHeaders(tt.p); err != nil {
+ t.Errorf("test %q: %v", tt.name, err)
+ continue
+ }
+ if buf.String() != tt.wantEnc {
+ t.Errorf("test %q: encoded %q; want %q", tt.name, buf.Bytes(), tt.wantEnc)
+ }
+ f, err := fr.ReadFrame()
+ if err != nil {
+ t.Errorf("test %q: failed to read the frame back: %v", tt.name, err)
+ continue
+ }
+ if !reflect.DeepEqual(f, tt.wantFrame) {
+ t.Errorf("test %q: mismatch.\n got: %#v\nwant: %#v\n", tt.name, f, tt.wantFrame)
+ }
+ }
+}
+
+func TestWriteInvalidStreamDep(t *testing.T) {
+ fr, _ := testFramer()
+ err := fr.WriteHeaders(HeadersFrameParam{
+ StreamID: 42,
+ Priority: PriorityParam{
+ StreamDep: 1 << 31,
+ },
+ })
+ if err != errDepStreamID {
+ t.Errorf("header error = %v; want %q", err, errDepStreamID)
+ }
+
+ err = fr.WritePriority(2, PriorityParam{StreamDep: 1 << 31})
+ if err != errDepStreamID {
+ t.Errorf("priority error = %v; want %q", err, errDepStreamID)
+ }
+}
+
+func TestWriteContinuation(t *testing.T) {
+ const streamID = 42
+ tests := []struct {
+ name string
+ end bool
+ frag []byte
+
+ wantFrame *ContinuationFrame
+ }{
+ {
+ "not end",
+ false,
+ []byte("abc"),
+ &ContinuationFrame{
+ FrameHeader: FrameHeader{
+ valid: true,
+ StreamID: streamID,
+ Type: FrameContinuation,
+ Length: uint32(len("abc")),
+ },
+ headerFragBuf: []byte("abc"),
+ },
+ },
+ {
+ "end",
+ true,
+ []byte("def"),
+ &ContinuationFrame{
+ FrameHeader: FrameHeader{
+ valid: true,
+ StreamID: streamID,
+ Type: FrameContinuation,
+ Flags: FlagContinuationEndHeaders,
+ Length: uint32(len("def")),
+ },
+ headerFragBuf: []byte("def"),
+ },
+ },
+ }
+ for _, tt := range tests {
+ fr, _ := testFramer()
+ if err := fr.WriteContinuation(streamID, tt.end, tt.frag); err != nil {
+ t.Errorf("test %q: %v", tt.name, err)
+ continue
+ }
+ fr.AllowIllegalReads = true
+ f, err := fr.ReadFrame()
+ if err != nil {
+ t.Errorf("test %q: failed to read the frame back: %v", tt.name, err)
+ continue
+ }
+ if !reflect.DeepEqual(f, tt.wantFrame) {
+ t.Errorf("test %q: mismatch.\n got: %#v\nwant: %#v\n", tt.name, f, tt.wantFrame)
+ }
+ }
+}
+
+func TestWritePriority(t *testing.T) {
+ const streamID = 42
+ tests := []struct {
+ name string
+ priority PriorityParam
+ wantFrame *PriorityFrame
+ }{
+ {
+ "not exclusive",
+ PriorityParam{
+ StreamDep: 2,
+ Exclusive: false,
+ Weight: 127,
+ },
+ &PriorityFrame{
+ FrameHeader{
+ valid: true,
+ StreamID: streamID,
+ Type: FramePriority,
+ Length: 5,
+ },
+ PriorityParam{
+ StreamDep: 2,
+ Exclusive: false,
+ Weight: 127,
+ },
+ },
+ },
+
+ {
+ "exclusive",
+ PriorityParam{
+ StreamDep: 3,
+ Exclusive: true,
+ Weight: 77,
+ },
+ &PriorityFrame{
+ FrameHeader{
+ valid: true,
+ StreamID: streamID,
+ Type: FramePriority,
+ Length: 5,
+ },
+ PriorityParam{
+ StreamDep: 3,
+ Exclusive: true,
+ Weight: 77,
+ },
+ },
+ },
+ }
+ for _, tt := range tests {
+ fr, _ := testFramer()
+ if err := fr.WritePriority(streamID, tt.priority); err != nil {
+ t.Errorf("test %q: %v", tt.name, err)
+ continue
+ }
+ f, err := fr.ReadFrame()
+ if err != nil {
+ t.Errorf("test %q: failed to read the frame back: %v", tt.name, err)
+ continue
+ }
+ if !reflect.DeepEqual(f, tt.wantFrame) {
+ t.Errorf("test %q: mismatch.\n got: %#v\nwant: %#v\n", tt.name, f, tt.wantFrame)
+ }
+ }
+}
+
+func TestWriteSettings(t *testing.T) {
+ fr, buf := testFramer()
+ settings := []Setting{{1, 2}, {3, 4}}
+ fr.WriteSettings(settings...)
+ const wantEnc = "\x00\x00\f\x04\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x03\x00\x00\x00\x04"
+ if buf.String() != wantEnc {
+ t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
+ }
+ f, err := fr.ReadFrame()
+ if err != nil {
+ t.Fatal(err)
+ }
+ sf, ok := f.(*SettingsFrame)
+ if !ok {
+ t.Fatalf("Got a %T; want a SettingsFrame", f)
+ }
+ var got []Setting
+ sf.ForeachSetting(func(s Setting) error {
+ got = append(got, s)
+ valBack, ok := sf.Value(s.ID)
+ if !ok || valBack != s.Val {
+ t.Errorf("Value(%d) = %v, %v; want %v, true", s.ID, valBack, ok, s.Val)
+ }
+ return nil
+ })
+ if !reflect.DeepEqual(settings, got) {
+ t.Errorf("Read settings %+v != written settings %+v", got, settings)
+ }
+}
+
+func TestWriteSettingsAck(t *testing.T) {
+ fr, buf := testFramer()
+ fr.WriteSettingsAck()
+ const wantEnc = "\x00\x00\x00\x04\x01\x00\x00\x00\x00"
+ if buf.String() != wantEnc {
+ t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
+ }
+}
+
+func TestWriteWindowUpdate(t *testing.T) {
+ fr, buf := testFramer()
+ const streamID = 1<<24 + 2<<16 + 3<<8 + 4
+ const incr = 7<<24 + 6<<16 + 5<<8 + 4
+ if err := fr.WriteWindowUpdate(streamID, incr); err != nil {
+ t.Fatal(err)
+ }
+ const wantEnc = "\x00\x00\x04\x08\x00\x01\x02\x03\x04\x07\x06\x05\x04"
+ if buf.String() != wantEnc {
+ t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
+ }
+ f, err := fr.ReadFrame()
+ if err != nil {
+ t.Fatal(err)
+ }
+ want := &WindowUpdateFrame{
+ FrameHeader: FrameHeader{
+ valid: true,
+ Type: 0x8,
+ Flags: 0x0,
+ Length: 0x4,
+ StreamID: 0x1020304,
+ },
+ Increment: 0x7060504,
+ }
+ if !reflect.DeepEqual(f, want) {
+ t.Errorf("parsed back %#v; want %#v", f, want)
+ }
+}
+
+func TestWritePing(t *testing.T) { testWritePing(t, false) }
+func TestWritePingAck(t *testing.T) { testWritePing(t, true) }
+
+func testWritePing(t *testing.T, ack bool) {
+ fr, buf := testFramer()
+ if err := fr.WritePing(ack, [8]byte{1, 2, 3, 4, 5, 6, 7, 8}); err != nil {
+ t.Fatal(err)
+ }
+ var wantFlags Flags
+ if ack {
+ wantFlags = FlagPingAck
+ }
+ var wantEnc = "\x00\x00\x08\x06" + string(wantFlags) + "\x00\x00\x00\x00" + "\x01\x02\x03\x04\x05\x06\x07\x08"
+ if buf.String() != wantEnc {
+ t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
+ }
+
+ f, err := fr.ReadFrame()
+ if err != nil {
+ t.Fatal(err)
+ }
+ want := &PingFrame{
+ FrameHeader: FrameHeader{
+ valid: true,
+ Type: 0x6,
+ Flags: wantFlags,
+ Length: 0x8,
+ StreamID: 0,
+ },
+ Data: [8]byte{1, 2, 3, 4, 5, 6, 7, 8},
+ }
+ if !reflect.DeepEqual(f, want) {
+ t.Errorf("parsed back %#v; want %#v", f, want)
+ }
+}
+
+func TestReadFrameHeader(t *testing.T) {
+ tests := []struct {
+ in string
+ want FrameHeader
+ }{
+ {in: "\x00\x00\x00" + "\x00" + "\x00" + "\x00\x00\x00\x00", want: FrameHeader{}},
+ {in: "\x01\x02\x03" + "\x04" + "\x05" + "\x06\x07\x08\x09", want: FrameHeader{
+ Length: 66051, Type: 4, Flags: 5, StreamID: 101124105,
+ }},
+ // Ignore high bit:
+ {in: "\xff\xff\xff" + "\xff" + "\xff" + "\xff\xff\xff\xff", want: FrameHeader{
+ Length: 16777215, Type: 255, Flags: 255, StreamID: 2147483647}},
+ {in: "\xff\xff\xff" + "\xff" + "\xff" + "\x7f\xff\xff\xff", want: FrameHeader{
+ Length: 16777215, Type: 255, Flags: 255, StreamID: 2147483647}},
+ }
+ for i, tt := range tests {
+ got, err := readFrameHeader(make([]byte, 9), strings.NewReader(tt.in))
+ if err != nil {
+ t.Errorf("%d. readFrameHeader(%q) = %v", i, tt.in, err)
+ continue
+ }
+ tt.want.valid = true
+ if got != tt.want {
+ t.Errorf("%d. readFrameHeader(%q) = %+v; want %+v", i, tt.in, got, tt.want)
+ }
+ }
+}
+
+func TestReadWriteFrameHeader(t *testing.T) {
+ tests := []struct {
+ len uint32
+ typ FrameType
+ flags Flags
+ streamID uint32
+ }{
+ {len: 0, typ: 255, flags: 1, streamID: 0},
+ {len: 0, typ: 255, flags: 1, streamID: 1},
+ {len: 0, typ: 255, flags: 1, streamID: 255},
+ {len: 0, typ: 255, flags: 1, streamID: 256},
+ {len: 0, typ: 255, flags: 1, streamID: 65535},
+ {len: 0, typ: 255, flags: 1, streamID: 65536},
+
+ {len: 0, typ: 1, flags: 255, streamID: 1},
+ {len: 255, typ: 1, flags: 255, streamID: 1},
+ {len: 256, typ: 1, flags: 255, streamID: 1},
+ {len: 65535, typ: 1, flags: 255, streamID: 1},
+ {len: 65536, typ: 1, flags: 255, streamID: 1},
+ {len: 16777215, typ: 1, flags: 255, streamID: 1},
+ }
+ for _, tt := range tests {
+ fr, buf := testFramer()
+ fr.startWrite(tt.typ, tt.flags, tt.streamID)
+ fr.writeBytes(make([]byte, tt.len))
+ fr.endWrite()
+ fh, err := ReadFrameHeader(buf)
+ if err != nil {
+ t.Errorf("ReadFrameHeader(%+v) = %v", tt, err)
+ continue
+ }
+ if fh.Type != tt.typ || fh.Flags != tt.flags || fh.Length != tt.len || fh.StreamID != tt.streamID {
+ t.Errorf("ReadFrameHeader(%+v) = %+v; mismatch", tt, fh)
+ }
+ }
+
+}
+
+func TestWriteTooLargeFrame(t *testing.T) {
+ fr, _ := testFramer()
+ fr.startWrite(0, 1, 1)
+ fr.writeBytes(make([]byte, 1<<24))
+ err := fr.endWrite()
+ if err != ErrFrameTooLarge {
+ t.Errorf("endWrite = %v; want errFrameTooLarge", err)
+ }
+}
+
+func TestWriteGoAway(t *testing.T) {
+ const debug = "foo"
+ fr, buf := testFramer()
+ if err := fr.WriteGoAway(0x01020304, 0x05060708, []byte(debug)); err != nil {
+ t.Fatal(err)
+ }
+ const wantEnc = "\x00\x00\v\a\x00\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08" + debug
+ if buf.String() != wantEnc {
+ t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
+ }
+ f, err := fr.ReadFrame()
+ if err != nil {
+ t.Fatal(err)
+ }
+ want := &GoAwayFrame{
+ FrameHeader: FrameHeader{
+ valid: true,
+ Type: 0x7,
+ Flags: 0,
+ Length: uint32(4 + 4 + len(debug)),
+ StreamID: 0,
+ },
+ LastStreamID: 0x01020304,
+ ErrCode: 0x05060708,
+ debugData: []byte(debug),
+ }
+ if !reflect.DeepEqual(f, want) {
+ t.Fatalf("parsed back:\n%#v\nwant:\n%#v", f, want)
+ }
+ if got := string(f.(*GoAwayFrame).DebugData()); got != debug {
+ t.Errorf("debug data = %q; want %q", got, debug)
+ }
+}
+
+func TestWritePushPromise(t *testing.T) {
+ pp := PushPromiseParam{
+ StreamID: 42,
+ PromiseID: 42,
+ BlockFragment: []byte("abc"),
+ }
+ fr, buf := testFramer()
+ if err := fr.WritePushPromise(pp); err != nil {
+ t.Fatal(err)
+ }
+ const wantEnc = "\x00\x00\x07\x05\x00\x00\x00\x00*\x00\x00\x00*abc"
+ if buf.String() != wantEnc {
+ t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
+ }
+ f, err := fr.ReadFrame()
+ if err != nil {
+ t.Fatal(err)
+ }
+ _, ok := f.(*PushPromiseFrame)
+ if !ok {
+ t.Fatalf("got %T; want *PushPromiseFrame", f)
+ }
+ want := &PushPromiseFrame{
+ FrameHeader: FrameHeader{
+ valid: true,
+ Type: 0x5,
+ Flags: 0x0,
+ Length: 0x7,
+ StreamID: 42,
+ },
+ PromiseID: 42,
+ headerFragBuf: []byte("abc"),
+ }
+ if !reflect.DeepEqual(f, want) {
+ t.Fatalf("parsed back:\n%#v\nwant:\n%#v", f, want)
+ }
+}
+
+// test checkFrameOrder and that HEADERS and CONTINUATION frames can't be intermingled.
+func TestReadFrameOrder(t *testing.T) {
+ head := func(f *Framer, id uint32, end bool) {
+ f.WriteHeaders(HeadersFrameParam{
+ StreamID: id,
+ BlockFragment: []byte("foo"), // unused, but non-empty
+ EndHeaders: end,
+ })
+ }
+ cont := func(f *Framer, id uint32, end bool) {
+ f.WriteContinuation(id, end, []byte("foo"))
+ }
+
+ tests := [...]struct {
+ name string
+ w func(*Framer)
+ atLeast int
+ wantErr string
+ }{
+ 0: {
+ w: func(f *Framer) {
+ head(f, 1, true)
+ },
+ },
+ 1: {
+ w: func(f *Framer) {
+ head(f, 1, true)
+ head(f, 2, true)
+ },
+ },
+ 2: {
+ wantErr: "got HEADERS for stream 2; expected CONTINUATION following HEADERS for stream 1",
+ w: func(f *Framer) {
+ head(f, 1, false)
+ head(f, 2, true)
+ },
+ },
+ 3: {
+ wantErr: "got DATA for stream 1; expected CONTINUATION following HEADERS for stream 1",
+ w: func(f *Framer) {
+ head(f, 1, false)
+ },
+ },
+ 4: {
+ w: func(f *Framer) {
+ head(f, 1, false)
+ cont(f, 1, true)
+ head(f, 2, true)
+ },
+ },
+ 5: {
+ wantErr: "got CONTINUATION for stream 2; expected stream 1",
+ w: func(f *Framer) {
+ head(f, 1, false)
+ cont(f, 2, true)
+ head(f, 2, true)
+ },
+ },
+ 6: {
+ wantErr: "unexpected CONTINUATION for stream 1",
+ w: func(f *Framer) {
+ cont(f, 1, true)
+ },
+ },
+ 7: {
+ wantErr: "unexpected CONTINUATION for stream 1",
+ w: func(f *Framer) {
+ cont(f, 1, false)
+ },
+ },
+ 8: {
+ wantErr: "HEADERS frame with stream ID 0",
+ w: func(f *Framer) {
+ head(f, 0, true)
+ },
+ },
+ 9: {
+ wantErr: "CONTINUATION frame with stream ID 0",
+ w: func(f *Framer) {
+ cont(f, 0, true)
+ },
+ },
+ 10: {
+ wantErr: "unexpected CONTINUATION for stream 1",
+ atLeast: 5,
+ w: func(f *Framer) {
+ head(f, 1, false)
+ cont(f, 1, false)
+ cont(f, 1, false)
+ cont(f, 1, false)
+ cont(f, 1, true)
+ cont(f, 1, false)
+ },
+ },
+ }
+ for i, tt := range tests {
+ buf := new(bytes.Buffer)
+ f := NewFramer(buf, buf)
+ f.AllowIllegalWrites = true
+ tt.w(f)
+ f.WriteData(1, true, nil) // to test transition away from last step
+
+ var err error
+ n := 0
+ var log bytes.Buffer
+ for {
+ var got Frame
+ got, err = f.ReadFrame()
+ fmt.Fprintf(&log, " read %v, %v\n", got, err)
+ if err != nil {
+ break
+ }
+ n++
+ }
+ if err == io.EOF {
+ err = nil
+ }
+ ok := tt.wantErr == ""
+ if ok && err != nil {
+ t.Errorf("%d. after %d good frames, ReadFrame = %v; want success\n%s", i, n, err, log.Bytes())
+ continue
+ }
+ if !ok && err != ConnectionError(ErrCodeProtocol) {
+ t.Errorf("%d. after %d good frames, ReadFrame = %v; want ConnectionError(ErrCodeProtocol)\n%s", i, n, err, log.Bytes())
+ continue
+ }
+ if !((f.errDetail == nil && tt.wantErr == "") || (fmt.Sprint(f.errDetail) == tt.wantErr)) {
+ t.Errorf("%d. framer eror = %q; want %q\n%s", i, f.errDetail, tt.wantErr, log.Bytes())
+ }
+ if n < tt.atLeast {
+ t.Errorf("%d. framer only read %d frames; want at least %d\n%s", i, n, tt.atLeast, log.Bytes())
+ }
+ }
+}
+
+func TestMetaFrameHeader(t *testing.T) {
+ write := func(f *Framer, frags ...[]byte) {
+ for i, frag := range frags {
+ end := (i == len(frags)-1)
+ if i == 0 {
+ f.WriteHeaders(HeadersFrameParam{
+ StreamID: 1,
+ BlockFragment: frag,
+ EndHeaders: end,
+ })
+ } else {
+ f.WriteContinuation(1, end, frag)
+ }
+ }
+ }
+
+ want := func(flags Flags, length uint32, pairs ...string) *MetaHeadersFrame {
+ mh := &MetaHeadersFrame{
+ HeadersFrame: &HeadersFrame{
+ FrameHeader: FrameHeader{
+ Type: FrameHeaders,
+ Flags: flags,
+ Length: length,
+ StreamID: 1,
+ },
+ },
+ Fields: []hpack.HeaderField(nil),
+ }
+ for len(pairs) > 0 {
+ mh.Fields = append(mh.Fields, hpack.HeaderField{
+ Name: pairs[0],
+ Value: pairs[1],
+ })
+ pairs = pairs[2:]
+ }
+ return mh
+ }
+ truncated := func(mh *MetaHeadersFrame) *MetaHeadersFrame {
+ mh.Truncated = true
+ return mh
+ }
+
+ const noFlags Flags = 0
+
+ oneKBString := strings.Repeat("a", 1<<10)
+
+ tests := [...]struct {
+ name string
+ w func(*Framer)
+ want interface{} // *MetaHeaderFrame or error
+ wantErrReason string
+ maxHeaderListSize uint32
+ }{
+ 0: {
+ name: "single_headers",
+ w: func(f *Framer) {
+ var he hpackEncoder
+ all := he.encodeHeaderRaw(t, ":method", "GET", ":path", "/")
+ write(f, all)
+ },
+ want: want(FlagHeadersEndHeaders, 2, ":method", "GET", ":path", "/"),
+ },
+ 1: {
+ name: "with_continuation",
+ w: func(f *Framer) {
+ var he hpackEncoder
+ all := he.encodeHeaderRaw(t, ":method", "GET", ":path", "/", "foo", "bar")
+ write(f, all[:1], all[1:])
+ },
+ want: want(noFlags, 1, ":method", "GET", ":path", "/", "foo", "bar"),
+ },
+ 2: {
+ name: "with_two_continuation",
+ w: func(f *Framer) {
+ var he hpackEncoder
+ all := he.encodeHeaderRaw(t, ":method", "GET", ":path", "/", "foo", "bar")
+ write(f, all[:2], all[2:4], all[4:])
+ },
+ want: want(noFlags, 2, ":method", "GET", ":path", "/", "foo", "bar"),
+ },
+ 3: {
+ name: "big_string_okay",
+ w: func(f *Framer) {
+ var he hpackEncoder
+ all := he.encodeHeaderRaw(t, ":method", "GET", ":path", "/", "foo", oneKBString)
+ write(f, all[:2], all[2:])
+ },
+ want: want(noFlags, 2, ":method", "GET", ":path", "/", "foo", oneKBString),
+ },
+ 4: {
+ name: "big_string_error",
+ w: func(f *Framer) {
+ var he hpackEncoder
+ all := he.encodeHeaderRaw(t, ":method", "GET", ":path", "/", "foo", oneKBString)
+ write(f, all[:2], all[2:])
+ },
+ maxHeaderListSize: (1 << 10) / 2,
+ want: ConnectionError(ErrCodeCompression),
+ },
+ 5: {
+ name: "max_header_list_truncated",
+ w: func(f *Framer) {
+ var he hpackEncoder
+ var pairs = []string{":method", "GET", ":path", "/"}
+ for i := 0; i < 100; i++ {
+ pairs = append(pairs, "foo", "bar")
+ }
+ all := he.encodeHeaderRaw(t, pairs...)
+ write(f, all[:2], all[2:])
+ },
+ maxHeaderListSize: (1 << 10) / 2,
+ want: truncated(want(noFlags, 2,
+ ":method", "GET",
+ ":path", "/",
+ "foo", "bar",
+ "foo", "bar",
+ "foo", "bar",
+ "foo", "bar",
+ "foo", "bar",
+ "foo", "bar",
+ "foo", "bar",
+ "foo", "bar",
+ "foo", "bar",
+ "foo", "bar",
+ "foo", "bar", // 11
+ )),
+ },
+ 6: {
+ name: "pseudo_order",
+ w: func(f *Framer) {
+ write(f, encodeHeaderRaw(t,
+ ":method", "GET",
+ "foo", "bar",
+ ":path", "/", // bogus
+ ))
+ },
+ want: streamError(1, ErrCodeProtocol),
+ wantErrReason: "pseudo header field after regular",
+ },
+ 7: {
+ name: "pseudo_unknown",
+ w: func(f *Framer) {
+ write(f, encodeHeaderRaw(t,
+ ":unknown", "foo", // bogus
+ "foo", "bar",
+ ))
+ },
+ want: streamError(1, ErrCodeProtocol),
+ wantErrReason: "invalid pseudo-header \":unknown\"",
+ },
+ 8: {
+ name: "pseudo_mix_request_response",
+ w: func(f *Framer) {
+ write(f, encodeHeaderRaw(t,
+ ":method", "GET",
+ ":status", "100",
+ ))
+ },
+ want: streamError(1, ErrCodeProtocol),
+ wantErrReason: "mix of request and response pseudo headers",
+ },
+ 9: {
+ name: "pseudo_dup",
+ w: func(f *Framer) {
+ write(f, encodeHeaderRaw(t,
+ ":method", "GET",
+ ":method", "POST",
+ ))
+ },
+ want: streamError(1, ErrCodeProtocol),
+ wantErrReason: "duplicate pseudo-header \":method\"",
+ },
+ 10: {
+ name: "trailer_okay_no_pseudo",
+ w: func(f *Framer) { write(f, encodeHeaderRaw(t, "foo", "bar")) },
+ want: want(FlagHeadersEndHeaders, 8, "foo", "bar"),
+ },
+ 11: {
+ name: "invalid_field_name",
+ w: func(f *Framer) { write(f, encodeHeaderRaw(t, "CapitalBad", "x")) },
+ want: streamError(1, ErrCodeProtocol),
+ wantErrReason: "invalid header field name \"CapitalBad\"",
+ },
+ 12: {
+ name: "invalid_field_value",
+ w: func(f *Framer) { write(f, encodeHeaderRaw(t, "key", "bad_null\x00")) },
+ want: streamError(1, ErrCodeProtocol),
+ wantErrReason: "invalid header field value \"bad_null\\x00\"",
+ },
+ }
+ for i, tt := range tests {
+ buf := new(bytes.Buffer)
+ f := NewFramer(buf, buf)
+ f.ReadMetaHeaders = hpack.NewDecoder(initialHeaderTableSize, nil)
+ f.MaxHeaderListSize = tt.maxHeaderListSize
+ tt.w(f)
+
+ name := tt.name
+ if name == "" {
+ name = fmt.Sprintf("test index %d", i)
+ }
+
+ var got interface{}
+ var err error
+ got, err = f.ReadFrame()
+ if err != nil {
+ got = err
+
+ // Ignore the StreamError.Cause field, if it matches the wantErrReason.
+ // The test table above predates the Cause field.
+ if se, ok := err.(StreamError); ok && se.Cause != nil && se.Cause.Error() == tt.wantErrReason {
+ se.Cause = nil
+ got = se
+ }
+ }
+ if !reflect.DeepEqual(got, tt.want) {
+ if mhg, ok := got.(*MetaHeadersFrame); ok {
+ if mhw, ok := tt.want.(*MetaHeadersFrame); ok {
+ hg := mhg.HeadersFrame
+ hw := mhw.HeadersFrame
+ if hg != nil && hw != nil && !reflect.DeepEqual(*hg, *hw) {
+ t.Errorf("%s: headers differ:\n got: %+v\nwant: %+v\n", name, *hg, *hw)
+ }
+ }
+ }
+ str := func(v interface{}) string {
+ if _, ok := v.(error); ok {
+ return fmt.Sprintf("error %v", v)
+ } else {
+ return fmt.Sprintf("value %#v", v)
+ }
+ }
+ t.Errorf("%s:\n got: %v\nwant: %s", name, str(got), str(tt.want))
+ }
+ if tt.wantErrReason != "" && tt.wantErrReason != fmt.Sprint(f.errDetail) {
+ t.Errorf("%s: got error reason %q; want %q", name, f.errDetail, tt.wantErrReason)
+ }
+ }
+}
+
+func TestSetReuseFrames(t *testing.T) {
+ fr, buf := testFramer()
+ fr.SetReuseFrames()
+
+ // Check that DataFrames are reused. Note that
+ // SetReuseFrames only currently implements reuse of DataFrames.
+ firstDf := readAndVerifyDataFrame("ABC", 3, fr, buf, t)
+
+ for i := 0; i < 10; i++ {
+ df := readAndVerifyDataFrame("XYZ", 3, fr, buf, t)
+ if df != firstDf {
+ t.Errorf("Expected Framer to return references to the same DataFrame. Have %v and %v", &df, &firstDf)
+ }
+ }
+
+ for i := 0; i < 10; i++ {
+ df := readAndVerifyDataFrame("", 0, fr, buf, t)
+ if df != firstDf {
+ t.Errorf("Expected Framer to return references to the same DataFrame. Have %v and %v", &df, &firstDf)
+ }
+ }
+
+ for i := 0; i < 10; i++ {
+ df := readAndVerifyDataFrame("HHH", 3, fr, buf, t)
+ if df != firstDf {
+ t.Errorf("Expected Framer to return references to the same DataFrame. Have %v and %v", &df, &firstDf)
+ }
+ }
+}
+
+func TestSetReuseFramesMoreThanOnce(t *testing.T) {
+ fr, buf := testFramer()
+ fr.SetReuseFrames()
+
+ firstDf := readAndVerifyDataFrame("ABC", 3, fr, buf, t)
+ fr.SetReuseFrames()
+
+ for i := 0; i < 10; i++ {
+ df := readAndVerifyDataFrame("XYZ", 3, fr, buf, t)
+ // SetReuseFrames should be idempotent
+ fr.SetReuseFrames()
+ if df != firstDf {
+ t.Errorf("Expected Framer to return references to the same DataFrame. Have %v and %v", &df, &firstDf)
+ }
+ }
+}
+
+func TestNoSetReuseFrames(t *testing.T) {
+ fr, buf := testFramer()
+ const numNewDataFrames = 10
+ dfSoFar := make([]interface{}, numNewDataFrames)
+
+ // Check that DataFrames are not reused if SetReuseFrames wasn't called.
+ // SetReuseFrames only currently implements reuse of DataFrames.
+ for i := 0; i < numNewDataFrames; i++ {
+ df := readAndVerifyDataFrame("XYZ", 3, fr, buf, t)
+ for _, item := range dfSoFar {
+ if df == item {
+ t.Errorf("Expected Framer to return new DataFrames since SetNoReuseFrames not set.")
+ }
+ }
+ dfSoFar[i] = df
+ }
+}
+
+func readAndVerifyDataFrame(data string, length byte, fr *Framer, buf *bytes.Buffer, t *testing.T) *DataFrame {
+ var streamID uint32 = 1<<24 + 2<<16 + 3<<8 + 4
+ fr.WriteData(streamID, true, []byte(data))
+ wantEnc := "\x00\x00" + string(length) + "\x00\x01\x01\x02\x03\x04" + data
+ if buf.String() != wantEnc {
+ t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
+ }
+ f, err := fr.ReadFrame()
+ if err != nil {
+ t.Fatal(err)
+ }
+ df, ok := f.(*DataFrame)
+ if !ok {
+ t.Fatalf("got %T; want *DataFrame", f)
+ }
+ if !bytes.Equal(df.Data(), []byte(data)) {
+ t.Errorf("got %q; want %q", df.Data(), []byte(data))
+ }
+ if f.Header().Flags&1 == 0 {
+ t.Errorf("didn't see END_STREAM flag")
+ }
+ return df
+}
+
+func encodeHeaderRaw(t *testing.T, pairs ...string) []byte {
+ var he hpackEncoder
+ return he.encodeHeaderRaw(t, pairs...)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/go16.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/go16.go
new file mode 100644
index 000000000..00b2e9e3c
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/go16.go
@@ -0,0 +1,16 @@
+// 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.
+
+// +build go1.6
+
+package http2
+
+import (
+ "net/http"
+ "time"
+)
+
+func transportExpectContinueTimeout(t1 *http.Transport) time.Duration {
+ return t1.ExpectContinueTimeout
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/go17.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/go17.go
new file mode 100644
index 000000000..47b7fae08
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/go17.go
@@ -0,0 +1,106 @@
+// 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.
+
+// +build go1.7
+
+package http2
+
+import (
+ "context"
+ "net"
+ "net/http"
+ "net/http/httptrace"
+ "time"
+)
+
+type contextContext interface {
+ context.Context
+}
+
+func serverConnBaseContext(c net.Conn, opts *ServeConnOpts) (ctx contextContext, cancel func()) {
+ ctx, cancel = context.WithCancel(context.Background())
+ ctx = context.WithValue(ctx, http.LocalAddrContextKey, c.LocalAddr())
+ if hs := opts.baseConfig(); hs != nil {
+ ctx = context.WithValue(ctx, http.ServerContextKey, hs)
+ }
+ return
+}
+
+func contextWithCancel(ctx contextContext) (_ contextContext, cancel func()) {
+ return context.WithCancel(ctx)
+}
+
+func requestWithContext(req *http.Request, ctx contextContext) *http.Request {
+ return req.WithContext(ctx)
+}
+
+type clientTrace httptrace.ClientTrace
+
+func reqContext(r *http.Request) context.Context { return r.Context() }
+
+func (t *Transport) idleConnTimeout() time.Duration {
+ if t.t1 != nil {
+ return t.t1.IdleConnTimeout
+ }
+ return 0
+}
+
+func setResponseUncompressed(res *http.Response) { res.Uncompressed = true }
+
+func traceGotConn(req *http.Request, cc *ClientConn) {
+ trace := httptrace.ContextClientTrace(req.Context())
+ if trace == nil || trace.GotConn == nil {
+ return
+ }
+ ci := httptrace.GotConnInfo{Conn: cc.tconn}
+ cc.mu.Lock()
+ ci.Reused = cc.nextStreamID > 1
+ ci.WasIdle = len(cc.streams) == 0 && ci.Reused
+ if ci.WasIdle && !cc.lastActive.IsZero() {
+ ci.IdleTime = time.Now().Sub(cc.lastActive)
+ }
+ cc.mu.Unlock()
+
+ trace.GotConn(ci)
+}
+
+func traceWroteHeaders(trace *clientTrace) {
+ if trace != nil && trace.WroteHeaders != nil {
+ trace.WroteHeaders()
+ }
+}
+
+func traceGot100Continue(trace *clientTrace) {
+ if trace != nil && trace.Got100Continue != nil {
+ trace.Got100Continue()
+ }
+}
+
+func traceWait100Continue(trace *clientTrace) {
+ if trace != nil && trace.Wait100Continue != nil {
+ trace.Wait100Continue()
+ }
+}
+
+func traceWroteRequest(trace *clientTrace, err error) {
+ if trace != nil && trace.WroteRequest != nil {
+ trace.WroteRequest(httptrace.WroteRequestInfo{Err: err})
+ }
+}
+
+func traceFirstResponseByte(trace *clientTrace) {
+ if trace != nil && trace.GotFirstResponseByte != nil {
+ trace.GotFirstResponseByte()
+ }
+}
+
+func requestTrace(req *http.Request) *clientTrace {
+ trace := httptrace.ContextClientTrace(req.Context())
+ return (*clientTrace)(trace)
+}
+
+// Ping sends a PING frame to the server and waits for the ack.
+func (cc *ClientConn) Ping(ctx context.Context) error {
+ return cc.ping(ctx)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/go17_not18.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/go17_not18.go
new file mode 100644
index 000000000..b4c52ecec
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/go17_not18.go
@@ -0,0 +1,36 @@
+// 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.
+
+// +build go1.7,!go1.8
+
+package http2
+
+import "crypto/tls"
+
+// temporary copy of Go 1.7's private tls.Config.clone:
+func cloneTLSConfig(c *tls.Config) *tls.Config {
+ return &tls.Config{
+ Rand: c.Rand,
+ Time: c.Time,
+ Certificates: c.Certificates,
+ NameToCertificate: c.NameToCertificate,
+ GetCertificate: c.GetCertificate,
+ RootCAs: c.RootCAs,
+ NextProtos: c.NextProtos,
+ ServerName: c.ServerName,
+ ClientAuth: c.ClientAuth,
+ ClientCAs: c.ClientCAs,
+ InsecureSkipVerify: c.InsecureSkipVerify,
+ CipherSuites: c.CipherSuites,
+ PreferServerCipherSuites: c.PreferServerCipherSuites,
+ SessionTicketsDisabled: c.SessionTicketsDisabled,
+ SessionTicketKey: c.SessionTicketKey,
+ ClientSessionCache: c.ClientSessionCache,
+ MinVersion: c.MinVersion,
+ MaxVersion: c.MaxVersion,
+ CurvePreferences: c.CurvePreferences,
+ DynamicRecordSizingDisabled: c.DynamicRecordSizingDisabled,
+ Renegotiation: c.Renegotiation,
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/go18.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/go18.go
new file mode 100644
index 000000000..4f30d228a
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/go18.go
@@ -0,0 +1,56 @@
+// Copyright 2015 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.
+
+// +build go1.8
+
+package http2
+
+import (
+ "crypto/tls"
+ "io"
+ "net/http"
+)
+
+func cloneTLSConfig(c *tls.Config) *tls.Config {
+ c2 := c.Clone()
+ c2.GetClientCertificate = c.GetClientCertificate // golang.org/issue/19264
+ return c2
+}
+
+var _ http.Pusher = (*responseWriter)(nil)
+
+// Push implements http.Pusher.
+func (w *responseWriter) Push(target string, opts *http.PushOptions) error {
+ internalOpts := pushOptions{}
+ if opts != nil {
+ internalOpts.Method = opts.Method
+ internalOpts.Header = opts.Header
+ }
+ return w.push(target, internalOpts)
+}
+
+func configureServer18(h1 *http.Server, h2 *Server) error {
+ if h2.IdleTimeout == 0 {
+ if h1.IdleTimeout != 0 {
+ h2.IdleTimeout = h1.IdleTimeout
+ } else {
+ h2.IdleTimeout = h1.ReadTimeout
+ }
+ }
+ return nil
+}
+
+func shouldLogPanic(panicValue interface{}) bool {
+ return panicValue != nil && panicValue != http.ErrAbortHandler
+}
+
+func reqGetBody(req *http.Request) func() (io.ReadCloser, error) {
+ return req.GetBody
+}
+
+func reqBodyIsNoBody(body io.ReadCloser) bool {
+ return body == http.NoBody
+}
+
+func go18httpNoBody() io.ReadCloser { return http.NoBody } // for tests only
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/go18_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/go18_test.go
new file mode 100644
index 000000000..30e3b038b
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/go18_test.go
@@ -0,0 +1,79 @@
+// 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.
+
+// +build go1.8
+
+package http2
+
+import (
+ "crypto/tls"
+ "net/http"
+ "testing"
+ "time"
+)
+
+// Tests that http2.Server.IdleTimeout is initialized from
+// http.Server.{Idle,Read}Timeout. http.Server.IdleTimeout was
+// added in Go 1.8.
+func TestConfigureServerIdleTimeout_Go18(t *testing.T) {
+ const timeout = 5 * time.Second
+ const notThisOne = 1 * time.Second
+
+ // With a zero http2.Server, verify that it copies IdleTimeout:
+ {
+ s1 := &http.Server{
+ IdleTimeout: timeout,
+ ReadTimeout: notThisOne,
+ }
+ s2 := &Server{}
+ if err := ConfigureServer(s1, s2); err != nil {
+ t.Fatal(err)
+ }
+ if s2.IdleTimeout != timeout {
+ t.Errorf("s2.IdleTimeout = %v; want %v", s2.IdleTimeout, timeout)
+ }
+ }
+
+ // And that it falls back to ReadTimeout:
+ {
+ s1 := &http.Server{
+ ReadTimeout: timeout,
+ }
+ s2 := &Server{}
+ if err := ConfigureServer(s1, s2); err != nil {
+ t.Fatal(err)
+ }
+ if s2.IdleTimeout != timeout {
+ t.Errorf("s2.IdleTimeout = %v; want %v", s2.IdleTimeout, timeout)
+ }
+ }
+
+ // Verify that s1's IdleTimeout doesn't overwrite an existing setting:
+ {
+ s1 := &http.Server{
+ IdleTimeout: notThisOne,
+ }
+ s2 := &Server{
+ IdleTimeout: timeout,
+ }
+ if err := ConfigureServer(s1, s2); err != nil {
+ t.Fatal(err)
+ }
+ if s2.IdleTimeout != timeout {
+ t.Errorf("s2.IdleTimeout = %v; want %v", s2.IdleTimeout, timeout)
+ }
+ }
+}
+
+func TestCertClone(t *testing.T) {
+ c := &tls.Config{
+ GetClientCertificate: func(*tls.CertificateRequestInfo) (*tls.Certificate, error) {
+ panic("shouldn't be called")
+ },
+ }
+ c2 := cloneTLSConfig(c)
+ if c2.GetClientCertificate == nil {
+ t.Error("GetClientCertificate is nil")
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/go19.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/go19.go
new file mode 100644
index 000000000..38124ba56
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/go19.go
@@ -0,0 +1,16 @@
+// Copyright 2015 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.
+
+// +build go1.9
+
+package http2
+
+import (
+ "net/http"
+)
+
+func configureServer19(s *http.Server, conf *Server) error {
+ s.RegisterOnShutdown(conf.state.startGracefulShutdown)
+ return nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/go19_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/go19_test.go
new file mode 100644
index 000000000..22b000667
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/go19_test.go
@@ -0,0 +1,59 @@
+// 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.
+
+// +build go1.9
+
+package http2
+
+import (
+ "context"
+ "net/http"
+ "reflect"
+ "testing"
+ "time"
+)
+
+func TestServerGracefulShutdown(t *testing.T) {
+ var st *serverTester
+ handlerDone := make(chan struct{})
+ st = newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+ defer close(handlerDone)
+ go st.ts.Config.Shutdown(context.Background())
+
+ ga := st.wantGoAway()
+ if ga.ErrCode != ErrCodeNo {
+ t.Errorf("GOAWAY error = %v; want ErrCodeNo", ga.ErrCode)
+ }
+ if ga.LastStreamID != 1 {
+ t.Errorf("GOAWAY LastStreamID = %v; want 1", ga.LastStreamID)
+ }
+
+ w.Header().Set("x-foo", "bar")
+ })
+ defer st.Close()
+
+ st.greet()
+ st.bodylessReq1()
+
+ select {
+ case <-handlerDone:
+ case <-time.After(5 * time.Second):
+ t.Fatalf("server did not shutdown?")
+ }
+ hf := st.wantHeaders()
+ goth := st.decodeHeader(hf.HeaderBlockFragment())
+ wanth := [][2]string{
+ {":status", "200"},
+ {"x-foo", "bar"},
+ {"content-length", "0"},
+ }
+ if !reflect.DeepEqual(goth, wanth) {
+ t.Errorf("Got headers %v; want %v", goth, wanth)
+ }
+
+ n, err := st.cc.Read([]byte{0})
+ if n != 0 || err == nil {
+ t.Errorf("Read = %v, %v; want 0, non-nil", n, err)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/gotrack.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/gotrack.go
new file mode 100644
index 000000000..9933c9f8c
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/gotrack.go
@@ -0,0 +1,170 @@
+// Copyright 2014 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.
+
+// Defensive debug-only utility to track that functions run on the
+// goroutine that they're supposed to.
+
+package http2
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "os"
+ "runtime"
+ "strconv"
+ "sync"
+)
+
+var DebugGoroutines = os.Getenv("DEBUG_HTTP2_GOROUTINES") == "1"
+
+type goroutineLock uint64
+
+func newGoroutineLock() goroutineLock {
+ if !DebugGoroutines {
+ return 0
+ }
+ return goroutineLock(curGoroutineID())
+}
+
+func (g goroutineLock) check() {
+ if !DebugGoroutines {
+ return
+ }
+ if curGoroutineID() != uint64(g) {
+ panic("running on the wrong goroutine")
+ }
+}
+
+func (g goroutineLock) checkNotOn() {
+ if !DebugGoroutines {
+ return
+ }
+ if curGoroutineID() == uint64(g) {
+ panic("running on the wrong goroutine")
+ }
+}
+
+var goroutineSpace = []byte("goroutine ")
+
+func curGoroutineID() uint64 {
+ bp := littleBuf.Get().(*[]byte)
+ defer littleBuf.Put(bp)
+ b := *bp
+ b = b[:runtime.Stack(b, false)]
+ // Parse the 4707 out of "goroutine 4707 ["
+ b = bytes.TrimPrefix(b, goroutineSpace)
+ i := bytes.IndexByte(b, ' ')
+ if i < 0 {
+ panic(fmt.Sprintf("No space found in %q", b))
+ }
+ b = b[:i]
+ n, err := parseUintBytes(b, 10, 64)
+ if err != nil {
+ panic(fmt.Sprintf("Failed to parse goroutine ID out of %q: %v", b, err))
+ }
+ return n
+}
+
+var littleBuf = sync.Pool{
+ New: func() interface{} {
+ buf := make([]byte, 64)
+ return &buf
+ },
+}
+
+// parseUintBytes is like strconv.ParseUint, but using a []byte.
+func parseUintBytes(s []byte, base int, bitSize int) (n uint64, err error) {
+ var cutoff, maxVal uint64
+
+ if bitSize == 0 {
+ bitSize = int(strconv.IntSize)
+ }
+
+ s0 := s
+ switch {
+ case len(s) < 1:
+ err = strconv.ErrSyntax
+ goto Error
+
+ case 2 <= base && base <= 36:
+ // valid base; nothing to do
+
+ case base == 0:
+ // Look for octal, hex prefix.
+ switch {
+ case s[0] == '0' && len(s) > 1 && (s[1] == 'x' || s[1] == 'X'):
+ base = 16
+ s = s[2:]
+ if len(s) < 1 {
+ err = strconv.ErrSyntax
+ goto Error
+ }
+ case s[0] == '0':
+ base = 8
+ default:
+ base = 10
+ }
+
+ default:
+ err = errors.New("invalid base " + strconv.Itoa(base))
+ goto Error
+ }
+
+ n = 0
+ cutoff = cutoff64(base)
+ maxVal = 1<<uint(bitSize) - 1
+
+ for i := 0; i < len(s); i++ {
+ var v byte
+ d := s[i]
+ switch {
+ case '0' <= d && d <= '9':
+ v = d - '0'
+ case 'a' <= d && d <= 'z':
+ v = d - 'a' + 10
+ case 'A' <= d && d <= 'Z':
+ v = d - 'A' + 10
+ default:
+ n = 0
+ err = strconv.ErrSyntax
+ goto Error
+ }
+ if int(v) >= base {
+ n = 0
+ err = strconv.ErrSyntax
+ goto Error
+ }
+
+ if n >= cutoff {
+ // n*base overflows
+ n = 1<<64 - 1
+ err = strconv.ErrRange
+ goto Error
+ }
+ n *= uint64(base)
+
+ n1 := n + uint64(v)
+ if n1 < n || n1 > maxVal {
+ // n+v overflows
+ n = 1<<64 - 1
+ err = strconv.ErrRange
+ goto Error
+ }
+ n = n1
+ }
+
+ return n, nil
+
+Error:
+ return n, &strconv.NumError{Func: "ParseUint", Num: string(s0), Err: err}
+}
+
+// Return the first number n such that n*base >= 1<<64.
+func cutoff64(base int) uint64 {
+ if base < 2 {
+ return 0
+ }
+ return (1<<64-1)/uint64(base) + 1
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/gotrack_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/gotrack_test.go
new file mode 100644
index 000000000..06db61231
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/gotrack_test.go
@@ -0,0 +1,33 @@
+// Copyright 2014 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 http2
+
+import (
+ "fmt"
+ "strings"
+ "testing"
+)
+
+func TestGoroutineLock(t *testing.T) {
+ oldDebug := DebugGoroutines
+ DebugGoroutines = true
+ defer func() { DebugGoroutines = oldDebug }()
+
+ g := newGoroutineLock()
+ g.check()
+
+ sawPanic := make(chan interface{})
+ go func() {
+ defer func() { sawPanic <- recover() }()
+ g.check() // should panic
+ }()
+ e := <-sawPanic
+ if e == nil {
+ t.Fatal("did not see panic from check in other goroutine")
+ }
+ if !strings.Contains(fmt.Sprint(e), "wrong goroutine") {
+ t.Errorf("expected on see panic about running on the wrong goroutine; got %v", e)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2demo/.gitignore b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2demo/.gitignore
new file mode 100644
index 000000000..0de86ddbc
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2demo/.gitignore
@@ -0,0 +1,5 @@
+h2demo
+h2demo.linux
+client-id.dat
+client-secret.dat
+token.dat
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2demo/Makefile b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2demo/Makefile
new file mode 100644
index 000000000..f5c31ef3e
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2demo/Makefile
@@ -0,0 +1,8 @@
+h2demo.linux: h2demo.go
+ GOOS=linux go build --tags=h2demo -o h2demo.linux .
+
+FORCE:
+
+upload: FORCE
+ go install golang.org/x/build/cmd/upload
+ upload --verbose --osarch=linux-amd64 --tags=h2demo --file=go:golang.org/x/net/http2/h2demo --public http2-demo-server-tls/h2demo
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2demo/README b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2demo/README
new file mode 100644
index 000000000..212a96f38
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2demo/README
@@ -0,0 +1,16 @@
+
+Client:
+ -- Firefox nightly with about:config network.http.spdy.enabled.http2draft set true
+ -- Chrome: go to chrome://flags/#enable-spdy4, save and restart (button at bottom)
+
+Make CA:
+$ openssl genrsa -out rootCA.key 2048
+$ openssl req -x509 -new -nodes -key rootCA.key -days 1024 -out rootCA.pem
+... install that to Firefox
+
+Make cert:
+$ openssl genrsa -out server.key 2048
+$ openssl req -new -key server.key -out server.csr
+$ openssl x509 -req -in server.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out server.crt -days 500
+
+
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2demo/h2demo.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2demo/h2demo.go
new file mode 100644
index 000000000..9853107b9
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2demo/h2demo.go
@@ -0,0 +1,538 @@
+// Copyright 2014 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.
+
+// +build h2demo
+
+package main
+
+import (
+ "bytes"
+ "crypto/tls"
+ "flag"
+ "fmt"
+ "hash/crc32"
+ "image"
+ "image/jpeg"
+ "io"
+ "io/ioutil"
+ "log"
+ "net"
+ "net/http"
+ "os"
+ "path"
+ "regexp"
+ "runtime"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+
+ "go4.org/syncutil/singleflight"
+ "golang.org/x/crypto/acme/autocert"
+ "golang.org/x/net/http2"
+)
+
+var (
+ prod = flag.Bool("prod", false, "Whether to configure itself to be the production http2.golang.org server.")
+
+ httpsAddr = flag.String("https_addr", "localhost:4430", "TLS address to listen on ('host:port' or ':port'). Required.")
+ httpAddr = flag.String("http_addr", "", "Plain HTTP address to listen on ('host:port', or ':port'). Empty means no HTTP.")
+
+ hostHTTP = flag.String("http_host", "", "Optional host or host:port to use for http:// links to this service. By default, this is implied from -http_addr.")
+ hostHTTPS = flag.String("https_host", "", "Optional host or host:port to use for http:// links to this service. By default, this is implied from -https_addr.")
+)
+
+func homeOldHTTP(w http.ResponseWriter, r *http.Request) {
+ io.WriteString(w, `<html>
+<body>
+<h1>Go + HTTP/2</h1>
+<p>Welcome to <a href="https://golang.org/">the Go language</a>'s <a href="https://http2.github.io/">HTTP/2</a> demo & interop server.</p>
+<p>Unfortunately, you're <b>not</b> using HTTP/2 right now. To do so:</p>
+<ul>
+ <li>Use Firefox Nightly or go to <b>about:config</b> and enable "network.http.spdy.enabled.http2draft"</li>
+ <li>Use Google Chrome Canary and/or go to <b>chrome://flags/#enable-spdy4</b> to <i>Enable SPDY/4</i> (Chrome's name for HTTP/2)</li>
+</ul>
+<p>See code & instructions for connecting at <a href="https://github.com/golang/net/tree/master/http2">https://github.com/golang/net/tree/master/http2</a>.</p>
+
+</body></html>`)
+}
+
+func home(w http.ResponseWriter, r *http.Request) {
+ if r.URL.Path != "/" {
+ http.NotFound(w, r)
+ return
+ }
+ io.WriteString(w, `<html>
+<body>
+<h1>Go + HTTP/2</h1>
+
+<p>Welcome to <a href="https://golang.org/">the Go language</a>'s <a
+href="https://http2.github.io/">HTTP/2</a> demo & interop server.</p>
+
+<p>Congratulations, <b>you're using HTTP/2 right now</b>.</p>
+
+<p>This server exists for others in the HTTP/2 community to test their HTTP/2 client implementations and point out flaws in our server.</p>
+
+<p>
+The code is at <a href="https://golang.org/x/net/http2">golang.org/x/net/http2</a> and
+is used transparently by the Go standard library from Go 1.6 and later.
+</p>
+
+<p>Contact info: <i>bradfitz@golang.org</i>, or <a
+href="https://golang.org/s/http2bug">file a bug</a>.</p>
+
+<h2>Handlers for testing</h2>
+<ul>
+ <li>GET <a href="/reqinfo">/reqinfo</a> to dump the request + headers received</li>
+ <li>GET <a href="/clockstream">/clockstream</a> streams the current time every second</li>
+ <li>GET <a href="/gophertiles">/gophertiles</a> to see a page with a bunch of images</li>
+ <li>GET <a href="/serverpush">/serverpush</a> to see a page with server push</li>
+ <li>GET <a href="/file/gopher.png">/file/gopher.png</a> for a small file (does If-Modified-Since, Content-Range, etc)</li>
+ <li>GET <a href="/file/go.src.tar.gz">/file/go.src.tar.gz</a> for a larger file (~10 MB)</li>
+ <li>GET <a href="/redirect">/redirect</a> to redirect back to / (this page)</li>
+ <li>GET <a href="/goroutines">/goroutines</a> to see all active goroutines in this server</li>
+ <li>PUT something to <a href="/crc32">/crc32</a> to get a count of number of bytes and its CRC-32</li>
+ <li>PUT something to <a href="/ECHO">/ECHO</a> and it will be streamed back to you capitalized</li>
+</ul>
+
+</body></html>`)
+}
+
+func reqInfoHandler(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "text/plain")
+ fmt.Fprintf(w, "Method: %s\n", r.Method)
+ fmt.Fprintf(w, "Protocol: %s\n", r.Proto)
+ fmt.Fprintf(w, "Host: %s\n", r.Host)
+ fmt.Fprintf(w, "RemoteAddr: %s\n", r.RemoteAddr)
+ fmt.Fprintf(w, "RequestURI: %q\n", r.RequestURI)
+ fmt.Fprintf(w, "URL: %#v\n", r.URL)
+ fmt.Fprintf(w, "Body.ContentLength: %d (-1 means unknown)\n", r.ContentLength)
+ fmt.Fprintf(w, "Close: %v (relevant for HTTP/1 only)\n", r.Close)
+ fmt.Fprintf(w, "TLS: %#v\n", r.TLS)
+ fmt.Fprintf(w, "\nHeaders:\n")
+ r.Header.Write(w)
+}
+
+func crcHandler(w http.ResponseWriter, r *http.Request) {
+ if r.Method != "PUT" {
+ http.Error(w, "PUT required.", 400)
+ return
+ }
+ crc := crc32.NewIEEE()
+ n, err := io.Copy(crc, r.Body)
+ if err == nil {
+ w.Header().Set("Content-Type", "text/plain")
+ fmt.Fprintf(w, "bytes=%d, CRC32=%x", n, crc.Sum(nil))
+ }
+}
+
+type capitalizeReader struct {
+ r io.Reader
+}
+
+func (cr capitalizeReader) Read(p []byte) (n int, err error) {
+ n, err = cr.r.Read(p)
+ for i, b := range p[:n] {
+ if b >= 'a' && b <= 'z' {
+ p[i] = b - ('a' - 'A')
+ }
+ }
+ return
+}
+
+type flushWriter struct {
+ w io.Writer
+}
+
+func (fw flushWriter) Write(p []byte) (n int, err error) {
+ n, err = fw.w.Write(p)
+ if f, ok := fw.w.(http.Flusher); ok {
+ f.Flush()
+ }
+ return
+}
+
+func echoCapitalHandler(w http.ResponseWriter, r *http.Request) {
+ if r.Method != "PUT" {
+ http.Error(w, "PUT required.", 400)
+ return
+ }
+ io.Copy(flushWriter{w}, capitalizeReader{r.Body})
+}
+
+var (
+ fsGrp singleflight.Group
+ fsMu sync.Mutex // guards fsCache
+ fsCache = map[string]http.Handler{}
+)
+
+// fileServer returns a file-serving handler that proxies URL.
+// It lazily fetches URL on the first access and caches its contents forever.
+func fileServer(url string, latency time.Duration) http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if latency > 0 {
+ time.Sleep(latency)
+ }
+ hi, err := fsGrp.Do(url, func() (interface{}, error) {
+ fsMu.Lock()
+ if h, ok := fsCache[url]; ok {
+ fsMu.Unlock()
+ return h, nil
+ }
+ fsMu.Unlock()
+
+ res, err := http.Get(url)
+ if err != nil {
+ return nil, err
+ }
+ defer res.Body.Close()
+ slurp, err := ioutil.ReadAll(res.Body)
+ if err != nil {
+ return nil, err
+ }
+
+ modTime := time.Now()
+ var h http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ http.ServeContent(w, r, path.Base(url), modTime, bytes.NewReader(slurp))
+ })
+ fsMu.Lock()
+ fsCache[url] = h
+ fsMu.Unlock()
+ return h, nil
+ })
+ if err != nil {
+ http.Error(w, err.Error(), 500)
+ return
+ }
+ hi.(http.Handler).ServeHTTP(w, r)
+ })
+}
+
+func clockStreamHandler(w http.ResponseWriter, r *http.Request) {
+ clientGone := w.(http.CloseNotifier).CloseNotify()
+ w.Header().Set("Content-Type", "text/plain")
+ ticker := time.NewTicker(1 * time.Second)
+ defer ticker.Stop()
+ fmt.Fprintf(w, "# ~1KB of junk to force browsers to start rendering immediately: \n")
+ io.WriteString(w, strings.Repeat("# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n", 13))
+
+ for {
+ fmt.Fprintf(w, "%v\n", time.Now())
+ w.(http.Flusher).Flush()
+ select {
+ case <-ticker.C:
+ case <-clientGone:
+ log.Printf("Client %v disconnected from the clock", r.RemoteAddr)
+ return
+ }
+ }
+}
+
+func registerHandlers() {
+ tiles := newGopherTilesHandler()
+ push := newPushHandler()
+
+ mux2 := http.NewServeMux()
+ http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+ switch {
+ case r.URL.Path == "/gophertiles":
+ tiles.ServeHTTP(w, r) // allow HTTP/2 + HTTP/1.x
+ return
+ case strings.HasPrefix(r.URL.Path, "/serverpush"):
+ push.ServeHTTP(w, r) // allow HTTP/2 + HTTP/1.x
+ return
+ case r.TLS == nil: // do not allow HTTP/1.x for anything else
+ http.Redirect(w, r, "https://"+httpsHost()+"/", http.StatusFound)
+ return
+ }
+ if r.ProtoMajor == 1 {
+ if r.URL.Path == "/reqinfo" {
+ reqInfoHandler(w, r)
+ return
+ }
+ homeOldHTTP(w, r)
+ return
+ }
+ mux2.ServeHTTP(w, r)
+ })
+ mux2.HandleFunc("/", home)
+ mux2.Handle("/file/gopher.png", fileServer("https://golang.org/doc/gopher/frontpage.png", 0))
+ mux2.Handle("/file/go.src.tar.gz", fileServer("https://storage.googleapis.com/golang/go1.4.1.src.tar.gz", 0))
+ mux2.HandleFunc("/reqinfo", reqInfoHandler)
+ mux2.HandleFunc("/crc32", crcHandler)
+ mux2.HandleFunc("/ECHO", echoCapitalHandler)
+ mux2.HandleFunc("/clockstream", clockStreamHandler)
+ mux2.Handle("/gophertiles", tiles)
+ mux2.HandleFunc("/redirect", func(w http.ResponseWriter, r *http.Request) {
+ http.Redirect(w, r, "/", http.StatusFound)
+ })
+ stripHomedir := regexp.MustCompile(`/(Users|home)/\w+`)
+ mux2.HandleFunc("/goroutines", func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "text/plain; charset=utf-8")
+ buf := make([]byte, 2<<20)
+ w.Write(stripHomedir.ReplaceAll(buf[:runtime.Stack(buf, true)], nil))
+ })
+}
+
+var pushResources = map[string]http.Handler{
+ "/serverpush/static/jquery.min.js": fileServer("https://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js", 100*time.Millisecond),
+ "/serverpush/static/godocs.js": fileServer("https://golang.org/lib/godoc/godocs.js", 100*time.Millisecond),
+ "/serverpush/static/playground.js": fileServer("https://golang.org/lib/godoc/playground.js", 100*time.Millisecond),
+ "/serverpush/static/style.css": fileServer("https://golang.org/lib/godoc/style.css", 100*time.Millisecond),
+}
+
+func newPushHandler() http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ for path, handler := range pushResources {
+ if r.URL.Path == path {
+ handler.ServeHTTP(w, r)
+ return
+ }
+ }
+
+ cacheBust := time.Now().UnixNano()
+ if pusher, ok := w.(http.Pusher); ok {
+ for path := range pushResources {
+ url := fmt.Sprintf("%s?%d", path, cacheBust)
+ if err := pusher.Push(url, nil); err != nil {
+ log.Printf("Failed to push %v: %v", path, err)
+ }
+ }
+ }
+ time.Sleep(100 * time.Millisecond) // fake network latency + parsing time
+ if err := pushTmpl.Execute(w, struct {
+ CacheBust int64
+ HTTPSHost string
+ HTTPHost string
+ }{
+ CacheBust: cacheBust,
+ HTTPSHost: httpsHost(),
+ HTTPHost: httpHost(),
+ }); err != nil {
+ log.Printf("Executing server push template: %v", err)
+ }
+ })
+}
+
+func newGopherTilesHandler() http.Handler {
+ const gopherURL = "https://blog.golang.org/go-programming-language-turns-two_gophers.jpg"
+ res, err := http.Get(gopherURL)
+ if err != nil {
+ log.Fatal(err)
+ }
+ if res.StatusCode != 200 {
+ log.Fatalf("Error fetching %s: %v", gopherURL, res.Status)
+ }
+ slurp, err := ioutil.ReadAll(res.Body)
+ res.Body.Close()
+ if err != nil {
+ log.Fatal(err)
+ }
+ im, err := jpeg.Decode(bytes.NewReader(slurp))
+ if err != nil {
+ if len(slurp) > 1024 {
+ slurp = slurp[:1024]
+ }
+ log.Fatalf("Failed to decode gopher image: %v (got %q)", err, slurp)
+ }
+
+ type subImager interface {
+ SubImage(image.Rectangle) image.Image
+ }
+ const tileSize = 32
+ xt := im.Bounds().Max.X / tileSize
+ yt := im.Bounds().Max.Y / tileSize
+ var tile [][][]byte // y -> x -> jpeg bytes
+ for yi := 0; yi < yt; yi++ {
+ var row [][]byte
+ for xi := 0; xi < xt; xi++ {
+ si := im.(subImager).SubImage(image.Rectangle{
+ Min: image.Point{xi * tileSize, yi * tileSize},
+ Max: image.Point{(xi + 1) * tileSize, (yi + 1) * tileSize},
+ })
+ buf := new(bytes.Buffer)
+ if err := jpeg.Encode(buf, si, &jpeg.Options{Quality: 90}); err != nil {
+ log.Fatal(err)
+ }
+ row = append(row, buf.Bytes())
+ }
+ tile = append(tile, row)
+ }
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ ms, _ := strconv.Atoi(r.FormValue("latency"))
+ const nanosPerMilli = 1e6
+ if r.FormValue("x") != "" {
+ x, _ := strconv.Atoi(r.FormValue("x"))
+ y, _ := strconv.Atoi(r.FormValue("y"))
+ if ms <= 1000 {
+ time.Sleep(time.Duration(ms) * nanosPerMilli)
+ }
+ if x >= 0 && x < xt && y >= 0 && y < yt {
+ http.ServeContent(w, r, "", time.Time{}, bytes.NewReader(tile[y][x]))
+ return
+ }
+ }
+ io.WriteString(w, "<html><body onload='showtimes()'>")
+ fmt.Fprintf(w, "A grid of %d tiled images is below. Compare:<p>", xt*yt)
+ for _, ms := range []int{0, 30, 200, 1000} {
+ d := time.Duration(ms) * nanosPerMilli
+ fmt.Fprintf(w, "[<a href='https://%s/gophertiles?latency=%d'>HTTP/2, %v latency</a>] [<a href='http://%s/gophertiles?latency=%d'>HTTP/1, %v latency</a>]<br>\n",
+ httpsHost(), ms, d,
+ httpHost(), ms, d,
+ )
+ }
+ io.WriteString(w, "<p>\n")
+ cacheBust := time.Now().UnixNano()
+ for y := 0; y < yt; y++ {
+ for x := 0; x < xt; x++ {
+ fmt.Fprintf(w, "<img width=%d height=%d src='/gophertiles?x=%d&y=%d&cachebust=%d&latency=%d'>",
+ tileSize, tileSize, x, y, cacheBust, ms)
+ }
+ io.WriteString(w, "<br/>\n")
+ }
+ io.WriteString(w, `<p><div id='loadtimes'></div></p>
+<script>
+function showtimes() {
+ var times = 'Times from connection start:<br>'
+ times += 'DOM loaded: ' + (window.performance.timing.domContentLoadedEventEnd - window.performance.timing.connectStart) + 'ms<br>'
+ times += 'DOM complete (images loaded): ' + (window.performance.timing.domComplete - window.performance.timing.connectStart) + 'ms<br>'
+ document.getElementById('loadtimes').innerHTML = times
+}
+</script>
+<hr><a href='/'>&lt;&lt Back to Go HTTP/2 demo server</a></body></html>`)
+ })
+}
+
+func httpsHost() string {
+ if *hostHTTPS != "" {
+ return *hostHTTPS
+ }
+ if v := *httpsAddr; strings.HasPrefix(v, ":") {
+ return "localhost" + v
+ } else {
+ return v
+ }
+}
+
+func httpHost() string {
+ if *hostHTTP != "" {
+ return *hostHTTP
+ }
+ if v := *httpAddr; strings.HasPrefix(v, ":") {
+ return "localhost" + v
+ } else {
+ return v
+ }
+}
+
+func serveProdTLS() error {
+ const cacheDir = "/var/cache/autocert"
+ if err := os.MkdirAll(cacheDir, 0700); err != nil {
+ return err
+ }
+ m := autocert.Manager{
+ Cache: autocert.DirCache(cacheDir),
+ Prompt: autocert.AcceptTOS,
+ HostPolicy: autocert.HostWhitelist("http2.golang.org"),
+ }
+ srv := &http.Server{
+ TLSConfig: &tls.Config{
+ GetCertificate: m.GetCertificate,
+ },
+ }
+ http2.ConfigureServer(srv, &http2.Server{
+ NewWriteScheduler: func() http2.WriteScheduler {
+ return http2.NewPriorityWriteScheduler(nil)
+ },
+ })
+ ln, err := net.Listen("tcp", ":443")
+ if err != nil {
+ return err
+ }
+ return srv.Serve(tls.NewListener(tcpKeepAliveListener{ln.(*net.TCPListener)}, srv.TLSConfig))
+}
+
+type tcpKeepAliveListener struct {
+ *net.TCPListener
+}
+
+func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) {
+ tc, err := ln.AcceptTCP()
+ if err != nil {
+ return
+ }
+ tc.SetKeepAlive(true)
+ tc.SetKeepAlivePeriod(3 * time.Minute)
+ return tc, nil
+}
+
+func serveProd() error {
+ errc := make(chan error, 2)
+ go func() { errc <- http.ListenAndServe(":80", nil) }()
+ go func() { errc <- serveProdTLS() }()
+ return <-errc
+}
+
+const idleTimeout = 5 * time.Minute
+const activeTimeout = 10 * time.Minute
+
+// TODO: put this into the standard library and actually send
+// PING frames and GOAWAY, etc: golang.org/issue/14204
+func idleTimeoutHook() func(net.Conn, http.ConnState) {
+ var mu sync.Mutex
+ m := map[net.Conn]*time.Timer{}
+ return func(c net.Conn, cs http.ConnState) {
+ mu.Lock()
+ defer mu.Unlock()
+ if t, ok := m[c]; ok {
+ delete(m, c)
+ t.Stop()
+ }
+ var d time.Duration
+ switch cs {
+ case http.StateNew, http.StateIdle:
+ d = idleTimeout
+ case http.StateActive:
+ d = activeTimeout
+ default:
+ return
+ }
+ m[c] = time.AfterFunc(d, func() {
+ log.Printf("closing idle conn %v after %v", c.RemoteAddr(), d)
+ go c.Close()
+ })
+ }
+}
+
+func main() {
+ var srv http.Server
+ flag.BoolVar(&http2.VerboseLogs, "verbose", false, "Verbose HTTP/2 debugging.")
+ flag.Parse()
+ srv.Addr = *httpsAddr
+ srv.ConnState = idleTimeoutHook()
+
+ registerHandlers()
+
+ if *prod {
+ *hostHTTP = "http2.golang.org"
+ *hostHTTPS = "http2.golang.org"
+ log.Fatal(serveProd())
+ }
+
+ url := "https://" + httpsHost() + "/"
+ log.Printf("Listening on " + url)
+ http2.ConfigureServer(&srv, &http2.Server{})
+
+ if *httpAddr != "" {
+ go func() {
+ log.Printf("Listening on http://" + httpHost() + "/ (for unencrypted HTTP/1)")
+ log.Fatal(http.ListenAndServe(*httpAddr, nil))
+ }()
+ }
+
+ go func() {
+ log.Fatal(srv.ListenAndServeTLS("server.crt", "server.key"))
+ }()
+ select {}
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2demo/launch.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2demo/launch.go
new file mode 100644
index 000000000..df0866a30
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2demo/launch.go
@@ -0,0 +1,302 @@
+// Copyright 2014 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.
+
+// +build ignore
+
+package main
+
+import (
+ "bufio"
+ "bytes"
+ "encoding/json"
+ "flag"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "log"
+ "net/http"
+ "os"
+ "strings"
+ "time"
+
+ "golang.org/x/oauth2"
+ "golang.org/x/oauth2/google"
+ compute "google.golang.org/api/compute/v1"
+)
+
+var (
+ proj = flag.String("project", "symbolic-datum-552", "name of Project")
+ zone = flag.String("zone", "us-central1-a", "GCE zone")
+ mach = flag.String("machinetype", "n1-standard-1", "Machine type")
+ instName = flag.String("instance_name", "http2-demo", "Name of VM instance.")
+ sshPub = flag.String("ssh_public_key", "", "ssh public key file to authorize. Can modify later in Google's web UI anyway.")
+ staticIP = flag.String("static_ip", "130.211.116.44", "Static IP to use. If empty, automatic.")
+
+ writeObject = flag.String("write_object", "", "If non-empty, a VM isn't created and the flag value is Google Cloud Storage bucket/object to write. The contents from stdin.")
+ publicObject = flag.Bool("write_object_is_public", false, "Whether the object created by --write_object should be public.")
+)
+
+func readFile(v string) string {
+ slurp, err := ioutil.ReadFile(v)
+ if err != nil {
+ log.Fatalf("Error reading %s: %v", v, err)
+ }
+ return strings.TrimSpace(string(slurp))
+}
+
+var config = &oauth2.Config{
+ // The client-id and secret should be for an "Installed Application" when using
+ // the CLI. Later we'll use a web application with a callback.
+ ClientID: readFile("client-id.dat"),
+ ClientSecret: readFile("client-secret.dat"),
+ Endpoint: google.Endpoint,
+ Scopes: []string{
+ compute.DevstorageFullControlScope,
+ compute.ComputeScope,
+ "https://www.googleapis.com/auth/sqlservice",
+ "https://www.googleapis.com/auth/sqlservice.admin",
+ },
+ RedirectURL: "urn:ietf:wg:oauth:2.0:oob",
+}
+
+const baseConfig = `#cloud-config
+coreos:
+ units:
+ - name: h2demo.service
+ command: start
+ content: |
+ [Unit]
+ Description=HTTP2 Demo
+
+ [Service]
+ ExecStartPre=/bin/bash -c 'mkdir -p /opt/bin && curl -s -o /opt/bin/h2demo http://storage.googleapis.com/http2-demo-server-tls/h2demo && chmod +x /opt/bin/h2demo'
+ ExecStart=/opt/bin/h2demo --prod
+ RestartSec=5s
+ Restart=always
+ Type=simple
+
+ [Install]
+ WantedBy=multi-user.target
+`
+
+func main() {
+ flag.Parse()
+ if *proj == "" {
+ log.Fatalf("Missing --project flag")
+ }
+ prefix := "https://www.googleapis.com/compute/v1/projects/" + *proj
+ machType := prefix + "/zones/" + *zone + "/machineTypes/" + *mach
+
+ const tokenFileName = "token.dat"
+ tokenFile := tokenCacheFile(tokenFileName)
+ tokenSource := oauth2.ReuseTokenSource(nil, tokenFile)
+ token, err := tokenSource.Token()
+ if err != nil {
+ if *writeObject != "" {
+ log.Fatalf("Can't use --write_object without a valid token.dat file already cached.")
+ }
+ log.Printf("Error getting token from %s: %v", tokenFileName, err)
+ log.Printf("Get auth code from %v", config.AuthCodeURL("my-state"))
+ fmt.Print("\nEnter auth code: ")
+ sc := bufio.NewScanner(os.Stdin)
+ sc.Scan()
+ authCode := strings.TrimSpace(sc.Text())
+ token, err = config.Exchange(oauth2.NoContext, authCode)
+ if err != nil {
+ log.Fatalf("Error exchanging auth code for a token: %v", err)
+ }
+ if err := tokenFile.WriteToken(token); err != nil {
+ log.Fatalf("Error writing to %s: %v", tokenFileName, err)
+ }
+ tokenSource = oauth2.ReuseTokenSource(token, nil)
+ }
+
+ oauthClient := oauth2.NewClient(oauth2.NoContext, tokenSource)
+
+ if *writeObject != "" {
+ writeCloudStorageObject(oauthClient)
+ return
+ }
+
+ computeService, _ := compute.New(oauthClient)
+
+ natIP := *staticIP
+ if natIP == "" {
+ // Try to find it by name.
+ aggAddrList, err := computeService.Addresses.AggregatedList(*proj).Do()
+ if err != nil {
+ log.Fatal(err)
+ }
+ // http://godoc.org/code.google.com/p/google-api-go-client/compute/v1#AddressAggregatedList
+ IPLoop:
+ for _, asl := range aggAddrList.Items {
+ for _, addr := range asl.Addresses {
+ if addr.Name == *instName+"-ip" && addr.Status == "RESERVED" {
+ natIP = addr.Address
+ break IPLoop
+ }
+ }
+ }
+ }
+
+ cloudConfig := baseConfig
+ if *sshPub != "" {
+ key := strings.TrimSpace(readFile(*sshPub))
+ cloudConfig += fmt.Sprintf("\nssh_authorized_keys:\n - %s\n", key)
+ }
+ if os.Getenv("USER") == "bradfitz" {
+ cloudConfig += fmt.Sprintf("\nssh_authorized_keys:\n - %s\n", "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAwks9dwWKlRC+73gRbvYtVg0vdCwDSuIlyt4z6xa/YU/jTDynM4R4W10hm2tPjy8iR1k8XhDv4/qdxe6m07NjG/By1tkmGpm1mGwho4Pr5kbAAy/Qg+NLCSdAYnnE00FQEcFOC15GFVMOW2AzDGKisReohwH9eIzHPzdYQNPRWXE= bradfitz@papag.bradfitz.com")
+ }
+ const maxCloudConfig = 32 << 10 // per compute API docs
+ if len(cloudConfig) > maxCloudConfig {
+ log.Fatalf("cloud config length of %d bytes is over %d byte limit", len(cloudConfig), maxCloudConfig)
+ }
+
+ instance := &compute.Instance{
+ Name: *instName,
+ Description: "Go Builder",
+ MachineType: machType,
+ Disks: []*compute.AttachedDisk{instanceDisk(computeService)},
+ Tags: &compute.Tags{
+ Items: []string{"http-server", "https-server"},
+ },
+ Metadata: &compute.Metadata{
+ Items: []*compute.MetadataItems{
+ {
+ Key: "user-data",
+ Value: &cloudConfig,
+ },
+ },
+ },
+ NetworkInterfaces: []*compute.NetworkInterface{
+ {
+ AccessConfigs: []*compute.AccessConfig{
+ {
+ Type: "ONE_TO_ONE_NAT",
+ Name: "External NAT",
+ NatIP: natIP,
+ },
+ },
+ Network: prefix + "/global/networks/default",
+ },
+ },
+ ServiceAccounts: []*compute.ServiceAccount{
+ {
+ Email: "default",
+ Scopes: []string{
+ compute.DevstorageFullControlScope,
+ compute.ComputeScope,
+ },
+ },
+ },
+ }
+
+ log.Printf("Creating instance...")
+ op, err := computeService.Instances.Insert(*proj, *zone, instance).Do()
+ if err != nil {
+ log.Fatalf("Failed to create instance: %v", err)
+ }
+ opName := op.Name
+ log.Printf("Created. Waiting on operation %v", opName)
+OpLoop:
+ for {
+ time.Sleep(2 * time.Second)
+ op, err := computeService.ZoneOperations.Get(*proj, *zone, opName).Do()
+ if err != nil {
+ log.Fatalf("Failed to get op %s: %v", opName, err)
+ }
+ switch op.Status {
+ case "PENDING", "RUNNING":
+ log.Printf("Waiting on operation %v", opName)
+ continue
+ case "DONE":
+ if op.Error != nil {
+ for _, operr := range op.Error.Errors {
+ log.Printf("Error: %+v", operr)
+ }
+ log.Fatalf("Failed to start.")
+ }
+ log.Printf("Success. %+v", op)
+ break OpLoop
+ default:
+ log.Fatalf("Unknown status %q: %+v", op.Status, op)
+ }
+ }
+
+ inst, err := computeService.Instances.Get(*proj, *zone, *instName).Do()
+ if err != nil {
+ log.Fatalf("Error getting instance after creation: %v", err)
+ }
+ ij, _ := json.MarshalIndent(inst, "", " ")
+ log.Printf("Instance: %s", ij)
+}
+
+func instanceDisk(svc *compute.Service) *compute.AttachedDisk {
+ const imageURL = "https://www.googleapis.com/compute/v1/projects/coreos-cloud/global/images/coreos-stable-444-5-0-v20141016"
+ diskName := *instName + "-disk"
+
+ return &compute.AttachedDisk{
+ AutoDelete: true,
+ Boot: true,
+ Type: "PERSISTENT",
+ InitializeParams: &compute.AttachedDiskInitializeParams{
+ DiskName: diskName,
+ SourceImage: imageURL,
+ DiskSizeGb: 50,
+ },
+ }
+}
+
+func writeCloudStorageObject(httpClient *http.Client) {
+ content := os.Stdin
+ const maxSlurp = 1 << 20
+ var buf bytes.Buffer
+ n, err := io.CopyN(&buf, content, maxSlurp)
+ if err != nil && err != io.EOF {
+ log.Fatalf("Error reading from stdin: %v, %v", n, err)
+ }
+ contentType := http.DetectContentType(buf.Bytes())
+
+ req, err := http.NewRequest("PUT", "https://storage.googleapis.com/"+*writeObject, io.MultiReader(&buf, content))
+ if err != nil {
+ log.Fatal(err)
+ }
+ req.Header.Set("x-goog-api-version", "2")
+ if *publicObject {
+ req.Header.Set("x-goog-acl", "public-read")
+ }
+ req.Header.Set("Content-Type", contentType)
+ res, err := httpClient.Do(req)
+ if err != nil {
+ log.Fatal(err)
+ }
+ if res.StatusCode != 200 {
+ res.Write(os.Stderr)
+ log.Fatalf("Failed.")
+ }
+ log.Printf("Success.")
+ os.Exit(0)
+}
+
+type tokenCacheFile string
+
+func (f tokenCacheFile) Token() (*oauth2.Token, error) {
+ slurp, err := ioutil.ReadFile(string(f))
+ if err != nil {
+ return nil, err
+ }
+ t := new(oauth2.Token)
+ if err := json.Unmarshal(slurp, t); err != nil {
+ return nil, err
+ }
+ return t, nil
+}
+
+func (f tokenCacheFile) WriteToken(t *oauth2.Token) error {
+ jt, err := json.Marshal(t)
+ if err != nil {
+ return err
+ }
+ return ioutil.WriteFile(string(f), jt, 0600)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2demo/rootCA.key b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2demo/rootCA.key
new file mode 100644
index 000000000..a15a6abaf
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2demo/rootCA.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAt5fAjp4fTcekWUTfzsp0kyih1OYbsGL0KX1eRbSSR8Od0+9Q
+62Hyny+GFwMTb4A/KU8mssoHvcceSAAbwfbxFK/+s51TobqUnORZrOoTZjkUygby
+XDSK99YBbcR1Pip8vwMTm4XKuLtCigeBBdjjAQdgUO28LENGlsMnmeYkJfODVGnV
+mr5Ltb9ANA8IKyTfsnHJ4iOCS/PlPbUj2q7YnoVLposUBMlgUb/CykX3mOoLb4yJ
+JQyA/iST6ZxiIEj36D4yWZ5lg7YJl+UiiBQHGCnPdGyipqV06ex0heYWcaiW8LWZ
+SUQ93jQ+WVCH8hT7DQO1dmsvUmXlq/JeAlwQ/QIDAQABAoIBAFFHV7JMAqPWnMYA
+nezY6J81v9+XN+7xABNWM2Q8uv4WdksbigGLTXR3/680Z2hXqJ7LMeC5XJACFT/e
+/Gr0vmpgOCygnCPfjGehGKpavtfksXV3edikUlnCXsOP1C//c1bFL+sMYmFCVgTx
+qYdDK8yKzXNGrKYT6q5YG7IglyRNV1rsQa8lM/5taFYiD1Ck/3tQi3YIq8Lcuser
+hrxsMABcQ6mi+EIvG6Xr4mfJug0dGJMHG4RG1UGFQn6RXrQq2+q53fC8ZbVUSi0j
+NQ918aKFzktwv+DouKU0ME4I9toks03gM860bAL7zCbKGmwR3hfgX/TqzVCWpG9E
+LDVfvekCgYEA8fk9N53jbBRmULUGEf4qWypcLGiZnNU0OeXWpbPV9aa3H0VDytA7
+8fCN2dPAVDPqlthMDdVe983NCNwp2Yo8ZimDgowyIAKhdC25s1kejuaiH9OAPj3c
+0f8KbriYX4n8zNHxFwK6Ae3pQ6EqOLJVCUsziUaZX9nyKY5aZlyX6xcCgYEAwjws
+K62PjC64U5wYddNLp+kNdJ4edx+a7qBb3mEgPvSFT2RO3/xafJyG8kQB30Mfstjd
+bRxyUV6N0vtX1zA7VQtRUAvfGCecpMo+VQZzcHXKzoRTnQ7eZg4Lmj5fQ9tOAKAo
+QCVBoSW/DI4PZL26CAMDcAba4Pa22ooLapoRIQsCgYA6pIfkkbxLNkpxpt2YwLtt
+Kr/590O7UaR9n6k8sW/aQBRDXNsILR1KDl2ifAIxpf9lnXgZJiwE7HiTfCAcW7c1
+nzwDCI0hWuHcMTS/NYsFYPnLsstyyjVZI3FY0h4DkYKV9Q9z3zJLQ2hz/nwoD3gy
+b2pHC7giFcTts1VPV4Nt8wKBgHeFn4ihHJweg76vZz3Z78w7VNRWGFklUalVdDK7
+gaQ7w2y/ROn/146mo0OhJaXFIFRlrpvdzVrU3GDf2YXJYDlM5ZRkObwbZADjksev
+WInzcgDy3KDg7WnPasRXbTfMU4t/AkW2p1QKbi3DnSVYuokDkbH2Beo45vxDxhKr
+C69RAoGBAIyo3+OJenoZmoNzNJl2WPW5MeBUzSh8T/bgyjFTdqFHF5WiYRD/lfHj
+x9Glyw2nutuT4hlOqHvKhgTYdDMsF2oQ72fe3v8Q5FU7FuKndNPEAyvKNXZaShVA
+hnlhv5DjXKb0wFWnt5PCCiQLtzG0yyHaITrrEme7FikkIcTxaX/Y
+-----END RSA PRIVATE KEY-----
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2demo/rootCA.pem b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2demo/rootCA.pem
new file mode 100644
index 000000000..3a323e774
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2demo/rootCA.pem
@@ -0,0 +1,26 @@
+-----BEGIN CERTIFICATE-----
+MIIEWjCCA0KgAwIBAgIJALfRlWsI8YQHMA0GCSqGSIb3DQEBBQUAMHsxCzAJBgNV
+BAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEUMBIG
+A1UEChMLQnJhZGZpdHppbmMxEjAQBgNVBAMTCWxvY2FsaG9zdDEdMBsGCSqGSIb3
+DQEJARYOYnJhZEBkYW5nYS5jb20wHhcNMTQwNzE1MjA0NjA1WhcNMTcwNTA0MjA0
+NjA1WjB7MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDVNhbiBG
+cmFuY2lzY28xFDASBgNVBAoTC0JyYWRmaXR6aW5jMRIwEAYDVQQDEwlsb2NhbGhv
+c3QxHTAbBgkqhkiG9w0BCQEWDmJyYWRAZGFuZ2EuY29tMIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEAt5fAjp4fTcekWUTfzsp0kyih1OYbsGL0KX1eRbSS
+R8Od0+9Q62Hyny+GFwMTb4A/KU8mssoHvcceSAAbwfbxFK/+s51TobqUnORZrOoT
+ZjkUygbyXDSK99YBbcR1Pip8vwMTm4XKuLtCigeBBdjjAQdgUO28LENGlsMnmeYk
+JfODVGnVmr5Ltb9ANA8IKyTfsnHJ4iOCS/PlPbUj2q7YnoVLposUBMlgUb/CykX3
+mOoLb4yJJQyA/iST6ZxiIEj36D4yWZ5lg7YJl+UiiBQHGCnPdGyipqV06ex0heYW
+caiW8LWZSUQ93jQ+WVCH8hT7DQO1dmsvUmXlq/JeAlwQ/QIDAQABo4HgMIHdMB0G
+A1UdDgQWBBRcAROthS4P4U7vTfjByC569R7E6DCBrQYDVR0jBIGlMIGigBRcAROt
+hS4P4U7vTfjByC569R7E6KF/pH0wezELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNB
+MRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRQwEgYDVQQKEwtCcmFkZml0emluYzES
+MBAGA1UEAxMJbG9jYWxob3N0MR0wGwYJKoZIhvcNAQkBFg5icmFkQGRhbmdhLmNv
+bYIJALfRlWsI8YQHMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAG6h
+U9f9sNH0/6oBbGGy2EVU0UgITUQIrFWo9rFkrW5k/XkDjQm+3lzjT0iGR4IxE/Ao
+eU6sQhua7wrWeFEn47GL98lnCsJdD7oZNhFmQ95Tb/LnDUjs5Yj9brP0NWzXfYU4
+UK2ZnINJRcJpB8iRCaCxE8DdcUF0XqIEq6pA272snoLmiXLMvNl3kYEdm+je6voD
+58SNVEUsztzQyXmJEhCpwVI0A6QCjzXj+qvpmw3ZZHi8JwXei8ZZBLTSFBki8Z7n
+sH9BBH38/SzUmAN4QHSPy1gjqm00OAE8NaYDkh/bzE4d7mLGGMWp/WE3KPSu82HF
+kPe6XoSbiLm/kxk32T0=
+-----END CERTIFICATE-----
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2demo/rootCA.srl b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2demo/rootCA.srl
new file mode 100644
index 000000000..6db389188
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2demo/rootCA.srl
@@ -0,0 +1 @@
+E2CE26BF3285059C
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2demo/server.crt b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2demo/server.crt
new file mode 100644
index 000000000..c59059bd6
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2demo/server.crt
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDPjCCAiYCCQDizia/MoUFnDANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJV
+UzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xFDASBgNVBAoT
+C0JyYWRmaXR6aW5jMRIwEAYDVQQDEwlsb2NhbGhvc3QxHTAbBgkqhkiG9w0BCQEW
+DmJyYWRAZGFuZ2EuY29tMB4XDTE0MDcxNTIwNTAyN1oXDTE1MTEyNzIwNTAyN1ow
+RzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMQswCQYDVQQHEwJTRjEeMBwGA1UE
+ChMVYnJhZGZpdHogaHR0cDIgc2VydmVyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEAs1Y9CyLFrdL8VQWN1WaifDqaZFnoqjHhCMlc1TfG2zA+InDifx2l
+gZD3o8FeNnAcfM2sPlk3+ZleOYw9P/CklFVDlvqmpCv9ss/BEp/dDaWvy1LmJ4c2
+dbQJfmTxn7CV1H3TsVJvKdwFmdoABb41NoBp6+NNO7OtDyhbIMiCI0pL3Nefb3HL
+A7hIMo3DYbORTtJLTIH9W8YKrEWL0lwHLrYFx/UdutZnv+HjdmO6vCN4na55mjws
+/vjKQUmc7xeY7Xe20xDEG2oDKVkL2eD7FfyrYMS3rO1ExP2KSqlXYG/1S9I/fz88
+F0GK7HX55b5WjZCl2J3ERVdnv/0MQv+sYQIDAQABMA0GCSqGSIb3DQEBBQUAA4IB
+AQC0zL+n/YpRZOdulSu9tS8FxrstXqGWoxfe+vIUgqfMZ5+0MkjJ/vW0FqlLDl2R
+rn4XaR3e7FmWkwdDVbq/UB6lPmoAaFkCgh9/5oapMaclNVNnfF3fjCJfRr+qj/iD
+EmJStTIN0ZuUjAlpiACmfnpEU55PafT5Zx+i1yE4FGjw8bJpFoyD4Hnm54nGjX19
+KeCuvcYFUPnBm3lcL0FalF2AjqV02WTHYNQk7YF/oeO7NKBoEgvGvKG3x+xaOeBI
+dwvdq175ZsGul30h+QjrRlXhH/twcuaT3GSdoysDl9cCYE8f1Mk8PD6gan3uBCJU
+90p6/CbU71bGbfpM2PHot2fm
+-----END CERTIFICATE-----
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2demo/server.key b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2demo/server.key
new file mode 100644
index 000000000..f329c1421
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2demo/server.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAs1Y9CyLFrdL8VQWN1WaifDqaZFnoqjHhCMlc1TfG2zA+InDi
+fx2lgZD3o8FeNnAcfM2sPlk3+ZleOYw9P/CklFVDlvqmpCv9ss/BEp/dDaWvy1Lm
+J4c2dbQJfmTxn7CV1H3TsVJvKdwFmdoABb41NoBp6+NNO7OtDyhbIMiCI0pL3Nef
+b3HLA7hIMo3DYbORTtJLTIH9W8YKrEWL0lwHLrYFx/UdutZnv+HjdmO6vCN4na55
+mjws/vjKQUmc7xeY7Xe20xDEG2oDKVkL2eD7FfyrYMS3rO1ExP2KSqlXYG/1S9I/
+fz88F0GK7HX55b5WjZCl2J3ERVdnv/0MQv+sYQIDAQABAoIBADQ2spUwbY+bcz4p
+3M66ECrNQTBggP40gYl2XyHxGGOu2xhZ94f9ELf1hjRWU2DUKWco1rJcdZClV6q3
+qwmXvcM2Q/SMS8JW0ImkNVl/0/NqPxGatEnj8zY30d/L8hGFb0orzFu/XYA5gCP4
+NbN2WrXgk3ZLeqwcNxHHtSiJWGJ/fPyeDWAu/apy75u9Xf2GlzBZmV6HYD9EfK80
+LTlI60f5FO487CrJnboL7ovPJrIHn+k05xRQqwma4orpz932rTXnTjs9Lg6KtbQN
+a7PrqfAntIISgr11a66Mng3IYH1lYqJsWJJwX/xHT4WLEy0EH4/0+PfYemJekz2+
+Co62drECgYEA6O9zVJZXrLSDsIi54cfxA7nEZWm5CAtkYWeAHa4EJ+IlZ7gIf9sL
+W8oFcEfFGpvwVqWZ+AsQ70dsjXAv3zXaG0tmg9FtqWp7pzRSMPidifZcQwWkKeTO
+gJnFmnVyed8h6GfjTEu4gxo1/S5U0V+mYSha01z5NTnN6ltKx1Or3b0CgYEAxRgm
+S30nZxnyg/V7ys61AZhst1DG2tkZXEMcA7dYhabMoXPJAP/EfhlWwpWYYUs/u0gS
+Wwmf5IivX5TlYScgmkvb/NYz0u4ZmOXkLTnLPtdKKFXhjXJcHjUP67jYmOxNlJLp
+V4vLRnFxTpffAV+OszzRxsXX6fvruwZBANYJeXUCgYBVouLFsFgfWGYp2rpr9XP4
+KK25kvrBqF6JKOIDB1zjxNJ3pUMKrl8oqccCFoCyXa4oTM2kUX0yWxHfleUjrMq4
+yimwQKiOZmV7fVLSSjSw6e/VfBd0h3gb82ygcplZkN0IclkwTY5SNKqwn/3y07V5
+drqdhkrgdJXtmQ6O5YYECQKBgATERcDToQ1USlI4sKrB/wyv1AlG8dg/IebiVJ4e
+ZAyvcQmClFzq0qS+FiQUnB/WQw9TeeYrwGs1hxBHuJh16srwhLyDrbMvQP06qh8R
+48F8UXXSRec22dV9MQphaROhu2qZdv1AC0WD3tqov6L33aqmEOi+xi8JgbT/PLk5
+c/c1AoGBAI1A/02ryksW6/wc7/6SP2M2rTy4m1sD/GnrTc67EHnRcVBdKO6qH2RY
+nqC8YcveC2ZghgPTDsA3VGuzuBXpwY6wTyV99q6jxQJ6/xcrD9/NUG6Uwv/xfCxl
+IJLeBYEqQundSSny3VtaAUK8Ul1nxpTvVRNwtcyWTo8RHAAyNPWd
+-----END RSA PRIVATE KEY-----
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2demo/tmpl.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2demo/tmpl.go
new file mode 100644
index 000000000..504d6a78a
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2demo/tmpl.go
@@ -0,0 +1,1991 @@
+// 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.
+
+// +build h2demo
+
+package main
+
+import "html/template"
+
+var pushTmpl = template.Must(template.New("serverpush").Parse(`
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<meta name="theme-color" content="#375EAB">
+
+ <title>HTTP/2 Server Push Demo</title>
+
+<link type="text/css" rel="stylesheet" href="/serverpush/static/style.css?{{.CacheBust}}">
+<script>
+window.initFuncs = [];
+</script>
+
+<script>
+function showtimes() {
+ var times = 'DOM loaded: ' + (window.performance.timing.domContentLoadedEventEnd - window.performance.timing.navigationStart) + 'ms, '
+ times += 'DOM complete (all loaded): ' + (window.performance.timing.domComplete - window.performance.timing.navigationStart) + 'ms, '
+ times += 'Load event fired: ' + (window.performance.timing.loadEventStart - window.performance.timing.navigationStart) + 'ms'
+ document.getElementById('loadtimes').innerHTML = times
+}
+</script>
+
+</head>
+<body onload="showtimes()">
+
+<div style="background:#fff9a4;padding:10px">
+Note: This page exists for demonstration purposes. For the actual cmd/go docs, go to <a href="golang.org/cmd/go">golang.org/cmd/go</a>.
+</div>
+
+<div style="padding:20px">
+
+
+<a href="https://{{.HTTPSHost}}/serverpush">HTTP/2 with Server Push</a> | <a href="http://{{.HTTPHost}}/serverpush">HTTP only</a>
+<div id="loadtimes"></div>
+
+</div>
+
+<div id='lowframe' style="position: fixed; bottom: 0; left: 0; height: 0; width: 100%; border-top: thin solid grey; background-color: white; overflow: auto;">
+...
+</div><!-- #lowframe -->
+
+<div id="topbar" class="wide"><div class="container">
+<div class="top-heading" id="heading-wide"><a href="/">The Go Programming Language</a></div>
+<div class="top-heading" id="heading-narrow"><a href="/">Go</a></div>
+<a href="#" id="menu-button"><span id="menu-button-arrow">&#9661;</span></a>
+<form method="GET" action="/search">
+<div id="menu">
+<a href="/doc/">Documents</a>
+<a href="/pkg/">Packages</a>
+<a href="/project/">The Project</a>
+<a href="/help/">Help</a>
+<a href="/blog/">Blog</a>
+
+<a id="playgroundButton" href="http://play.golang.org/" title="Show Go Playground">Play</a>
+
+<input type="text" id="search" name="q" class="inactive" value="Search" placeholder="Search">
+</div>
+</form>
+
+</div></div>
+
+
+<div id="playground" class="play">
+ <div class="input"><textarea class="code" spellcheck="false">package main
+
+import "fmt"
+
+func main() {
+ fmt.Println("Hello, 世界")
+}</textarea></div>
+ <div class="output"></div>
+ <div class="buttons">
+ <a class="run" title="Run this code [shift-enter]">Run</a>
+ <a class="fmt" title="Format this code">Format</a>
+
+ <a class="share" title="Share this code">Share</a>
+
+ </div>
+</div>
+
+
+<div id="page" class="wide">
+<div class="container">
+
+
+ <h1>Command go</h1>
+
+
+
+
+<div id="nav"></div>
+
+
+<!--
+ Copyright 2009 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.
+-->
+<!--
+ Note: Static (i.e., not template-generated) href and id
+ attributes start with "pkg-" to make it impossible for
+ them to conflict with generated attributes (some of which
+ correspond to Go identifiers).
+-->
+
+ <script type='text/javascript'>
+ document.ANALYSIS_DATA = null;
+ document.CALLGRAPH = null;
+ </script>
+
+
+
+ <p>
+Go is a tool for managing Go source code.
+</p>
+<p>
+Usage:
+</p>
+<pre>go command [arguments]
+</pre>
+<p>
+The commands are:
+</p>
+<pre>build compile packages and dependencies
+clean remove object files
+doc show documentation for package or symbol
+env print Go environment information
+bug start a bug report
+fix run go tool fix on packages
+fmt run gofmt on package sources
+generate generate Go files by processing source
+get download and install packages and dependencies
+install compile and install packages and dependencies
+list list packages
+run compile and run Go program
+test test packages
+tool run specified go tool
+version print Go version
+vet run go tool vet on packages
+</pre>
+<p>
+Use &#34;go help [command]&#34; for more information about a command.
+</p>
+<p>
+Additional help topics:
+</p>
+<pre>c calling between Go and C
+buildmode description of build modes
+filetype file types
+gopath GOPATH environment variable
+environment environment variables
+importpath import path syntax
+packages description of package lists
+testflag description of testing flags
+testfunc description of testing functions
+</pre>
+<p>
+Use &#34;go help [topic]&#34; for more information about that topic.
+</p>
+<h3 id="hdr-Compile_packages_and_dependencies">Compile packages and dependencies</h3>
+<p>
+Usage:
+</p>
+<pre>go build [-o output] [-i] [build flags] [packages]
+</pre>
+<p>
+Build compiles the packages named by the import paths,
+along with their dependencies, but it does not install the results.
+</p>
+<p>
+If the arguments to build are a list of .go files, build treats
+them as a list of source files specifying a single package.
+</p>
+<p>
+When compiling a single main package, build writes
+the resulting executable to an output file named after
+the first source file (&#39;go build ed.go rx.go&#39; writes &#39;ed&#39; or &#39;ed.exe&#39;)
+or the source code directory (&#39;go build unix/sam&#39; writes &#39;sam&#39; or &#39;sam.exe&#39;).
+The &#39;.exe&#39; suffix is added when writing a Windows executable.
+</p>
+<p>
+When compiling multiple packages or a single non-main package,
+build compiles the packages but discards the resulting object,
+serving only as a check that the packages can be built.
+</p>
+<p>
+When compiling packages, build ignores files that end in &#39;_test.go&#39;.
+</p>
+<p>
+The -o flag, only allowed when compiling a single package,
+forces build to write the resulting executable or object
+to the named output file, instead of the default behavior described
+in the last two paragraphs.
+</p>
+<p>
+The -i flag installs the packages that are dependencies of the target.
+</p>
+<p>
+The build flags are shared by the build, clean, get, install, list, run,
+and test commands:
+</p>
+<pre>-a
+ force rebuilding of packages that are already up-to-date.
+-n
+ print the commands but do not run them.
+-p n
+ the number of programs, such as build commands or
+ test binaries, that can be run in parallel.
+ The default is the number of CPUs available.
+-race
+ enable data race detection.
+ Supported only on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64.
+-msan
+ enable interoperation with memory sanitizer.
+ Supported only on linux/amd64,
+ and only with Clang/LLVM as the host C compiler.
+-v
+ print the names of packages as they are compiled.
+-work
+ print the name of the temporary work directory and
+ do not delete it when exiting.
+-x
+ print the commands.
+
+-asmflags &#39;flag list&#39;
+ arguments to pass on each go tool asm invocation.
+-buildmode mode
+ build mode to use. See &#39;go help buildmode&#39; for more.
+-compiler name
+ name of compiler to use, as in runtime.Compiler (gccgo or gc).
+-gccgoflags &#39;arg list&#39;
+ arguments to pass on each gccgo compiler/linker invocation.
+-gcflags &#39;arg list&#39;
+ arguments to pass on each go tool compile invocation.
+-installsuffix suffix
+ a suffix to use in the name of the package installation directory,
+ in order to keep output separate from default builds.
+ If using the -race flag, the install suffix is automatically set to race
+ or, if set explicitly, has _race appended to it. Likewise for the -msan
+ flag. Using a -buildmode option that requires non-default compile flags
+ has a similar effect.
+-ldflags &#39;flag list&#39;
+ arguments to pass on each go tool link invocation.
+-linkshared
+ link against shared libraries previously created with
+ -buildmode=shared.
+-pkgdir dir
+ install and load all packages from dir instead of the usual locations.
+ For example, when building with a non-standard configuration,
+ use -pkgdir to keep generated packages in a separate location.
+-tags &#39;tag list&#39;
+ a list of build tags to consider satisfied during the build.
+ For more information about build tags, see the description of
+ build constraints in the documentation for the go/build package.
+-toolexec &#39;cmd args&#39;
+ a program to use to invoke toolchain programs like vet and asm.
+ For example, instead of running asm, the go command will run
+ &#39;cmd args /path/to/asm &lt;arguments for asm&gt;&#39;.
+</pre>
+<p>
+The list flags accept a space-separated list of strings. To embed spaces
+in an element in the list, surround it with either single or double quotes.
+</p>
+<p>
+For more about specifying packages, see &#39;go help packages&#39;.
+For more about where packages and binaries are installed,
+run &#39;go help gopath&#39;.
+For more about calling between Go and C/C++, run &#39;go help c&#39;.
+</p>
+<p>
+Note: Build adheres to certain conventions such as those described
+by &#39;go help gopath&#39;. Not all projects can follow these conventions,
+however. Installations that have their own conventions or that use
+a separate software build system may choose to use lower-level
+invocations such as &#39;go tool compile&#39; and &#39;go tool link&#39; to avoid
+some of the overheads and design decisions of the build tool.
+</p>
+<p>
+See also: go install, go get, go clean.
+</p>
+<h3 id="hdr-Remove_object_files">Remove object files</h3>
+<p>
+Usage:
+</p>
+<pre>go clean [-i] [-r] [-n] [-x] [build flags] [packages]
+</pre>
+<p>
+Clean removes object files from package source directories.
+The go command builds most objects in a temporary directory,
+so go clean is mainly concerned with object files left by other
+tools or by manual invocations of go build.
+</p>
+<p>
+Specifically, clean removes the following files from each of the
+source directories corresponding to the import paths:
+</p>
+<pre>_obj/ old object directory, left from Makefiles
+_test/ old test directory, left from Makefiles
+_testmain.go old gotest file, left from Makefiles
+test.out old test log, left from Makefiles
+build.out old test log, left from Makefiles
+*.[568ao] object files, left from Makefiles
+
+DIR(.exe) from go build
+DIR.test(.exe) from go test -c
+MAINFILE(.exe) from go build MAINFILE.go
+*.so from SWIG
+</pre>
+<p>
+In the list, DIR represents the final path element of the
+directory, and MAINFILE is the base name of any Go source
+file in the directory that is not included when building
+the package.
+</p>
+<p>
+The -i flag causes clean to remove the corresponding installed
+archive or binary (what &#39;go install&#39; would create).
+</p>
+<p>
+The -n flag causes clean to print the remove commands it would execute,
+but not run them.
+</p>
+<p>
+The -r flag causes clean to be applied recursively to all the
+dependencies of the packages named by the import paths.
+</p>
+<p>
+The -x flag causes clean to print remove commands as it executes them.
+</p>
+<p>
+For more about build flags, see &#39;go help build&#39;.
+</p>
+<p>
+For more about specifying packages, see &#39;go help packages&#39;.
+</p>
+<h3 id="hdr-Show_documentation_for_package_or_symbol">Show documentation for package or symbol</h3>
+<p>
+Usage:
+</p>
+<pre>go doc [-u] [-c] [package|[package.]symbol[.method]]
+</pre>
+<p>
+Doc prints the documentation comments associated with the item identified by its
+arguments (a package, const, func, type, var, or method) followed by a one-line
+summary of each of the first-level items &#34;under&#34; that item (package-level
+declarations for a package, methods for a type, etc.).
+</p>
+<p>
+Doc accepts zero, one, or two arguments.
+</p>
+<p>
+Given no arguments, that is, when run as
+</p>
+<pre>go doc
+</pre>
+<p>
+it prints the package documentation for the package in the current directory.
+If the package is a command (package main), the exported symbols of the package
+are elided from the presentation unless the -cmd flag is provided.
+</p>
+<p>
+When run with one argument, the argument is treated as a Go-syntax-like
+representation of the item to be documented. What the argument selects depends
+on what is installed in GOROOT and GOPATH, as well as the form of the argument,
+which is schematically one of these:
+</p>
+<pre>go doc &lt;pkg&gt;
+go doc &lt;sym&gt;[.&lt;method&gt;]
+go doc [&lt;pkg&gt;.]&lt;sym&gt;[.&lt;method&gt;]
+go doc [&lt;pkg&gt;.][&lt;sym&gt;.]&lt;method&gt;
+</pre>
+<p>
+The first item in this list matched by the argument is the one whose documentation
+is printed. (See the examples below.) However, if the argument starts with a capital
+letter it is assumed to identify a symbol or method in the current directory.
+</p>
+<p>
+For packages, the order of scanning is determined lexically in breadth-first order.
+That is, the package presented is the one that matches the search and is nearest
+the root and lexically first at its level of the hierarchy. The GOROOT tree is
+always scanned in its entirety before GOPATH.
+</p>
+<p>
+If there is no package specified or matched, the package in the current
+directory is selected, so &#34;go doc Foo&#34; shows the documentation for symbol Foo in
+the current package.
+</p>
+<p>
+The package path must be either a qualified path or a proper suffix of a
+path. The go tool&#39;s usual package mechanism does not apply: package path
+elements like . and ... are not implemented by go doc.
+</p>
+<p>
+When run with two arguments, the first must be a full package path (not just a
+suffix), and the second is a symbol or symbol and method; this is similar to the
+syntax accepted by godoc:
+</p>
+<pre>go doc &lt;pkg&gt; &lt;sym&gt;[.&lt;method&gt;]
+</pre>
+<p>
+In all forms, when matching symbols, lower-case letters in the argument match
+either case but upper-case letters match exactly. This means that there may be
+multiple matches of a lower-case argument in a package if different symbols have
+different cases. If this occurs, documentation for all matches is printed.
+</p>
+<p>
+Examples:
+</p>
+<pre>go doc
+ Show documentation for current package.
+go doc Foo
+ Show documentation for Foo in the current package.
+ (Foo starts with a capital letter so it cannot match
+ a package path.)
+go doc encoding/json
+ Show documentation for the encoding/json package.
+go doc json
+ Shorthand for encoding/json.
+go doc json.Number (or go doc json.number)
+ Show documentation and method summary for json.Number.
+go doc json.Number.Int64 (or go doc json.number.int64)
+ Show documentation for json.Number&#39;s Int64 method.
+go doc cmd/doc
+ Show package docs for the doc command.
+go doc -cmd cmd/doc
+ Show package docs and exported symbols within the doc command.
+go doc template.new
+ Show documentation for html/template&#39;s New function.
+ (html/template is lexically before text/template)
+go doc text/template.new # One argument
+ Show documentation for text/template&#39;s New function.
+go doc text/template new # Two arguments
+ Show documentation for text/template&#39;s New function.
+
+At least in the current tree, these invocations all print the
+documentation for json.Decoder&#39;s Decode method:
+
+go doc json.Decoder.Decode
+go doc json.decoder.decode
+go doc json.decode
+cd go/src/encoding/json; go doc decode
+</pre>
+<p>
+Flags:
+</p>
+<pre>-c
+ Respect case when matching symbols.
+-cmd
+ Treat a command (package main) like a regular package.
+ Otherwise package main&#39;s exported symbols are hidden
+ when showing the package&#39;s top-level documentation.
+-u
+ Show documentation for unexported as well as exported
+ symbols and methods.
+</pre>
+<h3 id="hdr-Print_Go_environment_information">Print Go environment information</h3>
+<p>
+Usage:
+</p>
+<pre>go env [var ...]
+</pre>
+<p>
+Env prints Go environment information.
+</p>
+<p>
+By default env prints information as a shell script
+(on Windows, a batch file). If one or more variable
+names is given as arguments, env prints the value of
+each named variable on its own line.
+</p>
+<h3 id="hdr-Start_a_bug_report">Start a bug report</h3>
+<p>
+Usage:
+</p>
+<pre>go bug
+</pre>
+<p>
+Bug opens the default browser and starts a new bug report.
+The report includes useful system information.
+</p>
+<h3 id="hdr-Run_go_tool_fix_on_packages">Run go tool fix on packages</h3>
+<p>
+Usage:
+</p>
+<pre>go fix [packages]
+</pre>
+<p>
+Fix runs the Go fix command on the packages named by the import paths.
+</p>
+<p>
+For more about fix, see &#39;go doc cmd/fix&#39;.
+For more about specifying packages, see &#39;go help packages&#39;.
+</p>
+<p>
+To run fix with specific options, run &#39;go tool fix&#39;.
+</p>
+<p>
+See also: go fmt, go vet.
+</p>
+<h3 id="hdr-Run_gofmt_on_package_sources">Run gofmt on package sources</h3>
+<p>
+Usage:
+</p>
+<pre>go fmt [-n] [-x] [packages]
+</pre>
+<p>
+Fmt runs the command &#39;gofmt -l -w&#39; on the packages named
+by the import paths. It prints the names of the files that are modified.
+</p>
+<p>
+For more about gofmt, see &#39;go doc cmd/gofmt&#39;.
+For more about specifying packages, see &#39;go help packages&#39;.
+</p>
+<p>
+The -n flag prints commands that would be executed.
+The -x flag prints commands as they are executed.
+</p>
+<p>
+To run gofmt with specific options, run gofmt itself.
+</p>
+<p>
+See also: go fix, go vet.
+</p>
+<h3 id="hdr-Generate_Go_files_by_processing_source">Generate Go files by processing source</h3>
+<p>
+Usage:
+</p>
+<pre>go generate [-run regexp] [-n] [-v] [-x] [build flags] [file.go... | packages]
+</pre>
+<p>
+Generate runs commands described by directives within existing
+files. Those commands can run any process but the intent is to
+create or update Go source files.
+</p>
+<p>
+Go generate is never run automatically by go build, go get, go test,
+and so on. It must be run explicitly.
+</p>
+<p>
+Go generate scans the file for directives, which are lines of
+the form,
+</p>
+<pre>//go:generate command argument...
+</pre>
+<p>
+(note: no leading spaces and no space in &#34;//go&#34;) where command
+is the generator to be run, corresponding to an executable file
+that can be run locally. It must either be in the shell path
+(gofmt), a fully qualified path (/usr/you/bin/mytool), or a
+command alias, described below.
+</p>
+<p>
+Note that go generate does not parse the file, so lines that look
+like directives in comments or multiline strings will be treated
+as directives.
+</p>
+<p>
+The arguments to the directive are space-separated tokens or
+double-quoted strings passed to the generator as individual
+arguments when it is run.
+</p>
+<p>
+Quoted strings use Go syntax and are evaluated before execution; a
+quoted string appears as a single argument to the generator.
+</p>
+<p>
+Go generate sets several variables when it runs the generator:
+</p>
+<pre>$GOARCH
+ The execution architecture (arm, amd64, etc.)
+$GOOS
+ The execution operating system (linux, windows, etc.)
+$GOFILE
+ The base name of the file.
+$GOLINE
+ The line number of the directive in the source file.
+$GOPACKAGE
+ The name of the package of the file containing the directive.
+$DOLLAR
+ A dollar sign.
+</pre>
+<p>
+Other than variable substitution and quoted-string evaluation, no
+special processing such as &#34;globbing&#34; is performed on the command
+line.
+</p>
+<p>
+As a last step before running the command, any invocations of any
+environment variables with alphanumeric names, such as $GOFILE or
+$HOME, are expanded throughout the command line. The syntax for
+variable expansion is $NAME on all operating systems. Due to the
+order of evaluation, variables are expanded even inside quoted
+strings. If the variable NAME is not set, $NAME expands to the
+empty string.
+</p>
+<p>
+A directive of the form,
+</p>
+<pre>//go:generate -command xxx args...
+</pre>
+<p>
+specifies, for the remainder of this source file only, that the
+string xxx represents the command identified by the arguments. This
+can be used to create aliases or to handle multiword generators.
+For example,
+</p>
+<pre>//go:generate -command foo go tool foo
+</pre>
+<p>
+specifies that the command &#34;foo&#34; represents the generator
+&#34;go tool foo&#34;.
+</p>
+<p>
+Generate processes packages in the order given on the command line,
+one at a time. If the command line lists .go files, they are treated
+as a single package. Within a package, generate processes the
+source files in a package in file name order, one at a time. Within
+a source file, generate runs generators in the order they appear
+in the file, one at a time.
+</p>
+<p>
+If any generator returns an error exit status, &#34;go generate&#34; skips
+all further processing for that package.
+</p>
+<p>
+The generator is run in the package&#39;s source directory.
+</p>
+<p>
+Go generate accepts one specific flag:
+</p>
+<pre>-run=&#34;&#34;
+ if non-empty, specifies a regular expression to select
+ directives whose full original source text (excluding
+ any trailing spaces and final newline) matches the
+ expression.
+</pre>
+<p>
+It also accepts the standard build flags including -v, -n, and -x.
+The -v flag prints the names of packages and files as they are
+processed.
+The -n flag prints commands that would be executed.
+The -x flag prints commands as they are executed.
+</p>
+<p>
+For more about build flags, see &#39;go help build&#39;.
+</p>
+<p>
+For more about specifying packages, see &#39;go help packages&#39;.
+</p>
+<h3 id="hdr-Download_and_install_packages_and_dependencies">Download and install packages and dependencies</h3>
+<p>
+Usage:
+</p>
+<pre>go get [-d] [-f] [-fix] [-insecure] [-t] [-u] [build flags] [packages]
+</pre>
+<p>
+Get downloads the packages named by the import paths, along with their
+dependencies. It then installs the named packages, like &#39;go install&#39;.
+</p>
+<p>
+The -d flag instructs get to stop after downloading the packages; that is,
+it instructs get not to install the packages.
+</p>
+<p>
+The -f flag, valid only when -u is set, forces get -u not to verify that
+each package has been checked out from the source control repository
+implied by its import path. This can be useful if the source is a local fork
+of the original.
+</p>
+<p>
+The -fix flag instructs get to run the fix tool on the downloaded packages
+before resolving dependencies or building the code.
+</p>
+<p>
+The -insecure flag permits fetching from repositories and resolving
+custom domains using insecure schemes such as HTTP. Use with caution.
+</p>
+<p>
+The -t flag instructs get to also download the packages required to build
+the tests for the specified packages.
+</p>
+<p>
+The -u flag instructs get to use the network to update the named packages
+and their dependencies. By default, get uses the network to check out
+missing packages but does not use it to look for updates to existing packages.
+</p>
+<p>
+The -v flag enables verbose progress and debug output.
+</p>
+<p>
+Get also accepts build flags to control the installation. See &#39;go help build&#39;.
+</p>
+<p>
+When checking out a new package, get creates the target directory
+GOPATH/src/&lt;import-path&gt;. If the GOPATH contains multiple entries,
+get uses the first one. For more details see: &#39;go help gopath&#39;.
+</p>
+<p>
+When checking out or updating a package, get looks for a branch or tag
+that matches the locally installed version of Go. The most important
+rule is that if the local installation is running version &#34;go1&#34;, get
+searches for a branch or tag named &#34;go1&#34;. If no such version exists it
+retrieves the most recent version of the package.
+</p>
+<p>
+When go get checks out or updates a Git repository,
+it also updates any git submodules referenced by the repository.
+</p>
+<p>
+Get never checks out or updates code stored in vendor directories.
+</p>
+<p>
+For more about specifying packages, see &#39;go help packages&#39;.
+</p>
+<p>
+For more about how &#39;go get&#39; finds source code to
+download, see &#39;go help importpath&#39;.
+</p>
+<p>
+See also: go build, go install, go clean.
+</p>
+<h3 id="hdr-Compile_and_install_packages_and_dependencies">Compile and install packages and dependencies</h3>
+<p>
+Usage:
+</p>
+<pre>go install [build flags] [packages]
+</pre>
+<p>
+Install compiles and installs the packages named by the import paths,
+along with their dependencies.
+</p>
+<p>
+For more about the build flags, see &#39;go help build&#39;.
+For more about specifying packages, see &#39;go help packages&#39;.
+</p>
+<p>
+See also: go build, go get, go clean.
+</p>
+<h3 id="hdr-List_packages">List packages</h3>
+<p>
+Usage:
+</p>
+<pre>go list [-e] [-f format] [-json] [build flags] [packages]
+</pre>
+<p>
+List lists the packages named by the import paths, one per line.
+</p>
+<p>
+The default output shows the package import path:
+</p>
+<pre>bytes
+encoding/json
+github.com/gorilla/mux
+golang.org/x/net/html
+</pre>
+<p>
+The -f flag specifies an alternate format for the list, using the
+syntax of package template. The default output is equivalent to -f
+&#39;&#39;. The struct being passed to the template is:
+</p>
+<pre>type Package struct {
+ Dir string // directory containing package sources
+ ImportPath string // import path of package in dir
+ ImportComment string // path in import comment on package statement
+ Name string // package name
+ Doc string // package documentation string
+ Target string // install path
+ Shlib string // the shared library that contains this package (only set when -linkshared)
+ Goroot bool // is this package in the Go root?
+ Standard bool // is this package part of the standard Go library?
+ Stale bool // would &#39;go install&#39; do anything for this package?
+ StaleReason string // explanation for Stale==true
+ Root string // Go root or Go path dir containing this package
+ ConflictDir string // this directory shadows Dir in $GOPATH
+ BinaryOnly bool // binary-only package: cannot be recompiled from sources
+
+ // Source files
+ GoFiles []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles)
+ CgoFiles []string // .go sources files that import &#34;C&#34;
+ IgnoredGoFiles []string // .go sources ignored due to build constraints
+ CFiles []string // .c source files
+ CXXFiles []string // .cc, .cxx and .cpp source files
+ MFiles []string // .m source files
+ HFiles []string // .h, .hh, .hpp and .hxx source files
+ FFiles []string // .f, .F, .for and .f90 Fortran source files
+ SFiles []string // .s source files
+ SwigFiles []string // .swig files
+ SwigCXXFiles []string // .swigcxx files
+ SysoFiles []string // .syso object files to add to archive
+ TestGoFiles []string // _test.go files in package
+ XTestGoFiles []string // _test.go files outside package
+
+ // Cgo directives
+ CgoCFLAGS []string // cgo: flags for C compiler
+ CgoCPPFLAGS []string // cgo: flags for C preprocessor
+ CgoCXXFLAGS []string // cgo: flags for C++ compiler
+ CgoFFLAGS []string // cgo: flags for Fortran compiler
+ CgoLDFLAGS []string // cgo: flags for linker
+ CgoPkgConfig []string // cgo: pkg-config names
+
+ // Dependency information
+ Imports []string // import paths used by this package
+ Deps []string // all (recursively) imported dependencies
+ TestImports []string // imports from TestGoFiles
+ XTestImports []string // imports from XTestGoFiles
+
+ // Error information
+ Incomplete bool // this package or a dependency has an error
+ Error *PackageError // error loading package
+ DepsErrors []*PackageError // errors loading dependencies
+}
+</pre>
+<p>
+Packages stored in vendor directories report an ImportPath that includes the
+path to the vendor directory (for example, &#34;d/vendor/p&#34; instead of &#34;p&#34;),
+so that the ImportPath uniquely identifies a given copy of a package.
+The Imports, Deps, TestImports, and XTestImports lists also contain these
+expanded imports paths. See golang.org/s/go15vendor for more about vendoring.
+</p>
+<p>
+The error information, if any, is
+</p>
+<pre>type PackageError struct {
+ ImportStack []string // shortest path from package named on command line to this one
+ Pos string // position of error (if present, file:line:col)
+ Err string // the error itself
+}
+</pre>
+<p>
+The template function &#34;join&#34; calls strings.Join.
+</p>
+<p>
+The template function &#34;context&#34; returns the build context, defined as:
+</p>
+<pre>type Context struct {
+ GOARCH string // target architecture
+ GOOS string // target operating system
+ GOROOT string // Go root
+ GOPATH string // Go path
+ CgoEnabled bool // whether cgo can be used
+ UseAllFiles bool // use files regardless of +build lines, file names
+ Compiler string // compiler to assume when computing target paths
+ BuildTags []string // build constraints to match in +build lines
+ ReleaseTags []string // releases the current release is compatible with
+ InstallSuffix string // suffix to use in the name of the install dir
+}
+</pre>
+<p>
+For more information about the meaning of these fields see the documentation
+for the go/build package&#39;s Context type.
+</p>
+<p>
+The -json flag causes the package data to be printed in JSON format
+instead of using the template format.
+</p>
+<p>
+The -e flag changes the handling of erroneous packages, those that
+cannot be found or are malformed. By default, the list command
+prints an error to standard error for each erroneous package and
+omits the packages from consideration during the usual printing.
+With the -e flag, the list command never prints errors to standard
+error and instead processes the erroneous packages with the usual
+printing. Erroneous packages will have a non-empty ImportPath and
+a non-nil Error field; other information may or may not be missing
+(zeroed).
+</p>
+<p>
+For more about build flags, see &#39;go help build&#39;.
+</p>
+<p>
+For more about specifying packages, see &#39;go help packages&#39;.
+</p>
+<h3 id="hdr-Compile_and_run_Go_program">Compile and run Go program</h3>
+<p>
+Usage:
+</p>
+<pre>go run [build flags] [-exec xprog] gofiles... [arguments...]
+</pre>
+<p>
+Run compiles and runs the main package comprising the named Go source files.
+A Go source file is defined to be a file ending in a literal &#34;.go&#34; suffix.
+</p>
+<p>
+By default, &#39;go run&#39; runs the compiled binary directly: &#39;a.out arguments...&#39;.
+If the -exec flag is given, &#39;go run&#39; invokes the binary using xprog:
+</p>
+<pre>&#39;xprog a.out arguments...&#39;.
+</pre>
+<p>
+If the -exec flag is not given, GOOS or GOARCH is different from the system
+default, and a program named go_$GOOS_$GOARCH_exec can be found
+on the current search path, &#39;go run&#39; invokes the binary using that program,
+for example &#39;go_nacl_386_exec a.out arguments...&#39;. This allows execution of
+cross-compiled programs when a simulator or other execution method is
+available.
+</p>
+<p>
+For more about build flags, see &#39;go help build&#39;.
+</p>
+<p>
+See also: go build.
+</p>
+<h3 id="hdr-Test_packages">Test packages</h3>
+<p>
+Usage:
+</p>
+<pre>go test [build/test flags] [packages] [build/test flags &amp; test binary flags]
+</pre>
+<p>
+&#39;Go test&#39; automates testing the packages named by the import paths.
+It prints a summary of the test results in the format:
+</p>
+<pre>ok archive/tar 0.011s
+FAIL archive/zip 0.022s
+ok compress/gzip 0.033s
+...
+</pre>
+<p>
+followed by detailed output for each failed package.
+</p>
+<p>
+&#39;Go test&#39; recompiles each package along with any files with names matching
+the file pattern &#34;*_test.go&#34;.
+Files whose names begin with &#34;_&#34; (including &#34;_test.go&#34;) or &#34;.&#34; are ignored.
+These additional files can contain test functions, benchmark functions, and
+example functions. See &#39;go help testfunc&#39; for more.
+Each listed package causes the execution of a separate test binary.
+</p>
+<p>
+Test files that declare a package with the suffix &#34;_test&#34; will be compiled as a
+separate package, and then linked and run with the main test binary.
+</p>
+<p>
+The go tool will ignore a directory named &#34;testdata&#34;, making it available
+to hold ancillary data needed by the tests.
+</p>
+<p>
+By default, go test needs no arguments. It compiles and tests the package
+with source in the current directory, including tests, and runs the tests.
+</p>
+<p>
+The package is built in a temporary directory so it does not interfere with the
+non-test installation.
+</p>
+<p>
+In addition to the build flags, the flags handled by &#39;go test&#39; itself are:
+</p>
+<pre>-args
+ Pass the remainder of the command line (everything after -args)
+ to the test binary, uninterpreted and unchanged.
+ Because this flag consumes the remainder of the command line,
+ the package list (if present) must appear before this flag.
+
+-c
+ Compile the test binary to pkg.test but do not run it
+ (where pkg is the last element of the package&#39;s import path).
+ The file name can be changed with the -o flag.
+
+-exec xprog
+ Run the test binary using xprog. The behavior is the same as
+ in &#39;go run&#39;. See &#39;go help run&#39; for details.
+
+-i
+ Install packages that are dependencies of the test.
+ Do not run the test.
+
+-o file
+ Compile the test binary to the named file.
+ The test still runs (unless -c or -i is specified).
+</pre>
+<p>
+The test binary also accepts flags that control execution of the test; these
+flags are also accessible by &#39;go test&#39;. See &#39;go help testflag&#39; for details.
+</p>
+<p>
+For more about build flags, see &#39;go help build&#39;.
+For more about specifying packages, see &#39;go help packages&#39;.
+</p>
+<p>
+See also: go build, go vet.
+</p>
+<h3 id="hdr-Run_specified_go_tool">Run specified go tool</h3>
+<p>
+Usage:
+</p>
+<pre>go tool [-n] command [args...]
+</pre>
+<p>
+Tool runs the go tool command identified by the arguments.
+With no arguments it prints the list of known tools.
+</p>
+<p>
+The -n flag causes tool to print the command that would be
+executed but not execute it.
+</p>
+<p>
+For more about each tool command, see &#39;go tool command -h&#39;.
+</p>
+<h3 id="hdr-Print_Go_version">Print Go version</h3>
+<p>
+Usage:
+</p>
+<pre>go version
+</pre>
+<p>
+Version prints the Go version, as reported by runtime.Version.
+</p>
+<h3 id="hdr-Run_go_tool_vet_on_packages">Run go tool vet on packages</h3>
+<p>
+Usage:
+</p>
+<pre>go vet [-n] [-x] [build flags] [packages]
+</pre>
+<p>
+Vet runs the Go vet command on the packages named by the import paths.
+</p>
+<p>
+For more about vet, see &#39;go doc cmd/vet&#39;.
+For more about specifying packages, see &#39;go help packages&#39;.
+</p>
+<p>
+To run the vet tool with specific options, run &#39;go tool vet&#39;.
+</p>
+<p>
+The -n flag prints commands that would be executed.
+The -x flag prints commands as they are executed.
+</p>
+<p>
+For more about build flags, see &#39;go help build&#39;.
+</p>
+<p>
+See also: go fmt, go fix.
+</p>
+<h3 id="hdr-Calling_between_Go_and_C">Calling between Go and C</h3>
+<p>
+There are two different ways to call between Go and C/C++ code.
+</p>
+<p>
+The first is the cgo tool, which is part of the Go distribution. For
+information on how to use it see the cgo documentation (go doc cmd/cgo).
+</p>
+<p>
+The second is the SWIG program, which is a general tool for
+interfacing between languages. For information on SWIG see
+<a href="http://swig.org/">http://swig.org/</a>. When running go build, any file with a .swig
+extension will be passed to SWIG. Any file with a .swigcxx extension
+will be passed to SWIG with the -c++ option.
+</p>
+<p>
+When either cgo or SWIG is used, go build will pass any .c, .m, .s,
+or .S files to the C compiler, and any .cc, .cpp, .cxx files to the C++
+compiler. The CC or CXX environment variables may be set to determine
+the C or C++ compiler, respectively, to use.
+</p>
+<h3 id="hdr-Description_of_build_modes">Description of build modes</h3>
+<p>
+The &#39;go build&#39; and &#39;go install&#39; commands take a -buildmode argument which
+indicates which kind of object file is to be built. Currently supported values
+are:
+</p>
+<pre>-buildmode=archive
+ Build the listed non-main packages into .a files. Packages named
+ main are ignored.
+
+-buildmode=c-archive
+ Build the listed main package, plus all packages it imports,
+ into a C archive file. The only callable symbols will be those
+ functions exported using a cgo //export comment. Requires
+ exactly one main package to be listed.
+
+-buildmode=c-shared
+ Build the listed main packages, plus all packages that they
+ import, into C shared libraries. The only callable symbols will
+ be those functions exported using a cgo //export comment.
+ Non-main packages are ignored.
+
+-buildmode=default
+ Listed main packages are built into executables and listed
+ non-main packages are built into .a files (the default
+ behavior).
+
+-buildmode=shared
+ Combine all the listed non-main packages into a single shared
+ library that will be used when building with the -linkshared
+ option. Packages named main are ignored.
+
+-buildmode=exe
+ Build the listed main packages and everything they import into
+ executables. Packages not named main are ignored.
+
+-buildmode=pie
+ Build the listed main packages and everything they import into
+ position independent executables (PIE). Packages not named
+ main are ignored.
+
+-buildmode=plugin
+ Build the listed main packages, plus all packages that they
+ import, into a Go plugin. Packages not named main are ignored.
+</pre>
+<h3 id="hdr-File_types">File types</h3>
+<p>
+The go command examines the contents of a restricted set of files
+in each directory. It identifies which files to examine based on
+the extension of the file name. These extensions are:
+</p>
+<pre>.go
+ Go source files.
+.c, .h
+ C source files.
+ If the package uses cgo or SWIG, these will be compiled with the
+ OS-native compiler (typically gcc); otherwise they will
+ trigger an error.
+.cc, .cpp, .cxx, .hh, .hpp, .hxx
+ C++ source files. Only useful with cgo or SWIG, and always
+ compiled with the OS-native compiler.
+.m
+ Objective-C source files. Only useful with cgo, and always
+ compiled with the OS-native compiler.
+.s, .S
+ Assembler source files.
+ If the package uses cgo or SWIG, these will be assembled with the
+ OS-native assembler (typically gcc (sic)); otherwise they
+ will be assembled with the Go assembler.
+.swig, .swigcxx
+ SWIG definition files.
+.syso
+ System object files.
+</pre>
+<p>
+Files of each of these types except .syso may contain build
+constraints, but the go command stops scanning for build constraints
+at the first item in the file that is not a blank line or //-style
+line comment. See the go/build package documentation for
+more details.
+</p>
+<p>
+Non-test Go source files can also include a //go:binary-only-package
+comment, indicating that the package sources are included
+for documentation only and must not be used to build the
+package binary. This enables distribution of Go packages in
+their compiled form alone. See the go/build package documentation
+for more details.
+</p>
+<h3 id="hdr-GOPATH_environment_variable">GOPATH environment variable</h3>
+<p>
+The Go path is used to resolve import statements.
+It is implemented by and documented in the go/build package.
+</p>
+<p>
+The GOPATH environment variable lists places to look for Go code.
+On Unix, the value is a colon-separated string.
+On Windows, the value is a semicolon-separated string.
+On Plan 9, the value is a list.
+</p>
+<p>
+If the environment variable is unset, GOPATH defaults
+to a subdirectory named &#34;go&#34; in the user&#39;s home directory
+($HOME/go on Unix, %USERPROFILE%\go on Windows),
+unless that directory holds a Go distribution.
+Run &#34;go env GOPATH&#34; to see the current GOPATH.
+</p>
+<p>
+See <a href="https://golang.org/wiki/SettingGOPATH">https://golang.org/wiki/SettingGOPATH</a> to set a custom GOPATH.
+</p>
+<p>
+Each directory listed in GOPATH must have a prescribed structure:
+</p>
+<p>
+The src directory holds source code. The path below src
+determines the import path or executable name.
+</p>
+<p>
+The pkg directory holds installed package objects.
+As in the Go tree, each target operating system and
+architecture pair has its own subdirectory of pkg
+(pkg/GOOS_GOARCH).
+</p>
+<p>
+If DIR is a directory listed in the GOPATH, a package with
+source in DIR/src/foo/bar can be imported as &#34;foo/bar&#34; and
+has its compiled form installed to &#34;DIR/pkg/GOOS_GOARCH/foo/bar.a&#34;.
+</p>
+<p>
+The bin directory holds compiled commands.
+Each command is named for its source directory, but only
+the final element, not the entire path. That is, the
+command with source in DIR/src/foo/quux is installed into
+DIR/bin/quux, not DIR/bin/foo/quux. The &#34;foo/&#34; prefix is stripped
+so that you can add DIR/bin to your PATH to get at the
+installed commands. If the GOBIN environment variable is
+set, commands are installed to the directory it names instead
+of DIR/bin. GOBIN must be an absolute path.
+</p>
+<p>
+Here&#39;s an example directory layout:
+</p>
+<pre>GOPATH=/home/user/go
+
+/home/user/go/
+ src/
+ foo/
+ bar/ (go code in package bar)
+ x.go
+ quux/ (go code in package main)
+ y.go
+ bin/
+ quux (installed command)
+ pkg/
+ linux_amd64/
+ foo/
+ bar.a (installed package object)
+</pre>
+<p>
+Go searches each directory listed in GOPATH to find source code,
+but new packages are always downloaded into the first directory
+in the list.
+</p>
+<p>
+See <a href="https://golang.org/doc/code.html">https://golang.org/doc/code.html</a> for an example.
+</p>
+<h3 id="hdr-Internal_Directories">Internal Directories</h3>
+<p>
+Code in or below a directory named &#34;internal&#34; is importable only
+by code in the directory tree rooted at the parent of &#34;internal&#34;.
+Here&#39;s an extended version of the directory layout above:
+</p>
+<pre>/home/user/go/
+ src/
+ crash/
+ bang/ (go code in package bang)
+ b.go
+ foo/ (go code in package foo)
+ f.go
+ bar/ (go code in package bar)
+ x.go
+ internal/
+ baz/ (go code in package baz)
+ z.go
+ quux/ (go code in package main)
+ y.go
+</pre>
+<p>
+The code in z.go is imported as &#34;foo/internal/baz&#34;, but that
+import statement can only appear in source files in the subtree
+rooted at foo. The source files foo/f.go, foo/bar/x.go, and
+foo/quux/y.go can all import &#34;foo/internal/baz&#34;, but the source file
+crash/bang/b.go cannot.
+</p>
+<p>
+See <a href="https://golang.org/s/go14internal">https://golang.org/s/go14internal</a> for details.
+</p>
+<h3 id="hdr-Vendor_Directories">Vendor Directories</h3>
+<p>
+Go 1.6 includes support for using local copies of external dependencies
+to satisfy imports of those dependencies, often referred to as vendoring.
+</p>
+<p>
+Code below a directory named &#34;vendor&#34; is importable only
+by code in the directory tree rooted at the parent of &#34;vendor&#34;,
+and only using an import path that omits the prefix up to and
+including the vendor element.
+</p>
+<p>
+Here&#39;s the example from the previous section,
+but with the &#34;internal&#34; directory renamed to &#34;vendor&#34;
+and a new foo/vendor/crash/bang directory added:
+</p>
+<pre>/home/user/go/
+ src/
+ crash/
+ bang/ (go code in package bang)
+ b.go
+ foo/ (go code in package foo)
+ f.go
+ bar/ (go code in package bar)
+ x.go
+ vendor/
+ crash/
+ bang/ (go code in package bang)
+ b.go
+ baz/ (go code in package baz)
+ z.go
+ quux/ (go code in package main)
+ y.go
+</pre>
+<p>
+The same visibility rules apply as for internal, but the code
+in z.go is imported as &#34;baz&#34;, not as &#34;foo/vendor/baz&#34;.
+</p>
+<p>
+Code in vendor directories deeper in the source tree shadows
+code in higher directories. Within the subtree rooted at foo, an import
+of &#34;crash/bang&#34; resolves to &#34;foo/vendor/crash/bang&#34;, not the
+top-level &#34;crash/bang&#34;.
+</p>
+<p>
+Code in vendor directories is not subject to import path
+checking (see &#39;go help importpath&#39;).
+</p>
+<p>
+When &#39;go get&#39; checks out or updates a git repository, it now also
+updates submodules.
+</p>
+<p>
+Vendor directories do not affect the placement of new repositories
+being checked out for the first time by &#39;go get&#39;: those are always
+placed in the main GOPATH, never in a vendor subtree.
+</p>
+<p>
+See <a href="https://golang.org/s/go15vendor">https://golang.org/s/go15vendor</a> for details.
+</p>
+<h3 id="hdr-Environment_variables">Environment variables</h3>
+<p>
+The go command, and the tools it invokes, examine a few different
+environment variables. For many of these, you can see the default
+value of on your system by running &#39;go env NAME&#39;, where NAME is the
+name of the variable.
+</p>
+<p>
+General-purpose environment variables:
+</p>
+<pre>GCCGO
+ The gccgo command to run for &#39;go build -compiler=gccgo&#39;.
+GOARCH
+ The architecture, or processor, for which to compile code.
+ Examples are amd64, 386, arm, ppc64.
+GOBIN
+ The directory where &#39;go install&#39; will install a command.
+GOOS
+ The operating system for which to compile code.
+ Examples are linux, darwin, windows, netbsd.
+GOPATH
+ For more details see: &#39;go help gopath&#39;.
+GORACE
+ Options for the race detector.
+ See <a href="https://golang.org/doc/articles/race_detector.html">https://golang.org/doc/articles/race_detector.html</a>.
+GOROOT
+ The root of the go tree.
+</pre>
+<p>
+Environment variables for use with cgo:
+</p>
+<pre>CC
+ The command to use to compile C code.
+CGO_ENABLED
+ Whether the cgo command is supported. Either 0 or 1.
+CGO_CFLAGS
+ Flags that cgo will pass to the compiler when compiling
+ C code.
+CGO_CPPFLAGS
+ Flags that cgo will pass to the compiler when compiling
+ C or C++ code.
+CGO_CXXFLAGS
+ Flags that cgo will pass to the compiler when compiling
+ C++ code.
+CGO_FFLAGS
+ Flags that cgo will pass to the compiler when compiling
+ Fortran code.
+CGO_LDFLAGS
+ Flags that cgo will pass to the compiler when linking.
+CXX
+ The command to use to compile C++ code.
+PKG_CONFIG
+ Path to pkg-config tool.
+</pre>
+<p>
+Architecture-specific environment variables:
+</p>
+<pre>GOARM
+ For GOARCH=arm, the ARM architecture for which to compile.
+ Valid values are 5, 6, 7.
+GO386
+ For GOARCH=386, the floating point instruction set.
+ Valid values are 387, sse2.
+</pre>
+<p>
+Special-purpose environment variables:
+</p>
+<pre>GOROOT_FINAL
+ The root of the installed Go tree, when it is
+ installed in a location other than where it is built.
+ File names in stack traces are rewritten from GOROOT to
+ GOROOT_FINAL.
+GO_EXTLINK_ENABLED
+ Whether the linker should use external linking mode
+ when using -linkmode=auto with code that uses cgo.
+ Set to 0 to disable external linking mode, 1 to enable it.
+GIT_ALLOW_PROTOCOL
+ Defined by Git. A colon-separated list of schemes that are allowed to be used
+ with git fetch/clone. If set, any scheme not explicitly mentioned will be
+ considered insecure by &#39;go get&#39;.
+</pre>
+<h3 id="hdr-Import_path_syntax">Import path syntax</h3>
+<p>
+An import path (see &#39;go help packages&#39;) denotes a package stored in the local
+file system. In general, an import path denotes either a standard package (such
+as &#34;unicode/utf8&#34;) or a package found in one of the work spaces (For more
+details see: &#39;go help gopath&#39;).
+</p>
+<h3 id="hdr-Relative_import_paths">Relative import paths</h3>
+<p>
+An import path beginning with ./ or ../ is called a relative path.
+The toolchain supports relative import paths as a shortcut in two ways.
+</p>
+<p>
+First, a relative path can be used as a shorthand on the command line.
+If you are working in the directory containing the code imported as
+&#34;unicode&#34; and want to run the tests for &#34;unicode/utf8&#34;, you can type
+&#34;go test ./utf8&#34; instead of needing to specify the full path.
+Similarly, in the reverse situation, &#34;go test ..&#34; will test &#34;unicode&#34; from
+the &#34;unicode/utf8&#34; directory. Relative patterns are also allowed, like
+&#34;go test ./...&#34; to test all subdirectories. See &#39;go help packages&#39; for details
+on the pattern syntax.
+</p>
+<p>
+Second, if you are compiling a Go program not in a work space,
+you can use a relative path in an import statement in that program
+to refer to nearby code also not in a work space.
+This makes it easy to experiment with small multipackage programs
+outside of the usual work spaces, but such programs cannot be
+installed with &#34;go install&#34; (there is no work space in which to install them),
+so they are rebuilt from scratch each time they are built.
+To avoid ambiguity, Go programs cannot use relative import paths
+within a work space.
+</p>
+<h3 id="hdr-Remote_import_paths">Remote import paths</h3>
+<p>
+Certain import paths also
+describe how to obtain the source code for the package using
+a revision control system.
+</p>
+<p>
+A few common code hosting sites have special syntax:
+</p>
+<pre>Bitbucket (Git, Mercurial)
+
+ import &#34;bitbucket.org/user/project&#34;
+ import &#34;bitbucket.org/user/project/sub/directory&#34;
+
+GitHub (Git)
+
+ import &#34;github.com/user/project&#34;
+ import &#34;github.com/user/project/sub/directory&#34;
+
+Launchpad (Bazaar)
+
+ import &#34;launchpad.net/project&#34;
+ import &#34;launchpad.net/project/series&#34;
+ import &#34;launchpad.net/project/series/sub/directory&#34;
+
+ import &#34;launchpad.net/~user/project/branch&#34;
+ import &#34;launchpad.net/~user/project/branch/sub/directory&#34;
+
+IBM DevOps Services (Git)
+
+ import &#34;hub.jazz.net/git/user/project&#34;
+ import &#34;hub.jazz.net/git/user/project/sub/directory&#34;
+</pre>
+<p>
+For code hosted on other servers, import paths may either be qualified
+with the version control type, or the go tool can dynamically fetch
+the import path over https/http and discover where the code resides
+from a &lt;meta&gt; tag in the HTML.
+</p>
+<p>
+To declare the code location, an import path of the form
+</p>
+<pre>repository.vcs/path
+</pre>
+<p>
+specifies the given repository, with or without the .vcs suffix,
+using the named version control system, and then the path inside
+that repository. The supported version control systems are:
+</p>
+<pre>Bazaar .bzr
+Git .git
+Mercurial .hg
+Subversion .svn
+</pre>
+<p>
+For example,
+</p>
+<pre>import &#34;example.org/user/foo.hg&#34;
+</pre>
+<p>
+denotes the root directory of the Mercurial repository at
+example.org/user/foo or foo.hg, and
+</p>
+<pre>import &#34;example.org/repo.git/foo/bar&#34;
+</pre>
+<p>
+denotes the foo/bar directory of the Git repository at
+example.org/repo or repo.git.
+</p>
+<p>
+When a version control system supports multiple protocols,
+each is tried in turn when downloading. For example, a Git
+download tries https://, then git+ssh://.
+</p>
+<p>
+By default, downloads are restricted to known secure protocols
+(e.g. https, ssh). To override this setting for Git downloads, the
+GIT_ALLOW_PROTOCOL environment variable can be set (For more details see:
+&#39;go help environment&#39;).
+</p>
+<p>
+If the import path is not a known code hosting site and also lacks a
+version control qualifier, the go tool attempts to fetch the import
+over https/http and looks for a &lt;meta&gt; tag in the document&#39;s HTML
+&lt;head&gt;.
+</p>
+<p>
+The meta tag has the form:
+</p>
+<pre>&lt;meta name=&#34;go-import&#34; content=&#34;import-prefix vcs repo-root&#34;&gt;
+</pre>
+<p>
+The import-prefix is the import path corresponding to the repository
+root. It must be a prefix or an exact match of the package being
+fetched with &#34;go get&#34;. If it&#39;s not an exact match, another http
+request is made at the prefix to verify the &lt;meta&gt; tags match.
+</p>
+<p>
+The meta tag should appear as early in the file as possible.
+In particular, it should appear before any raw JavaScript or CSS,
+to avoid confusing the go command&#39;s restricted parser.
+</p>
+<p>
+The vcs is one of &#34;git&#34;, &#34;hg&#34;, &#34;svn&#34;, etc,
+</p>
+<p>
+The repo-root is the root of the version control system
+containing a scheme and not containing a .vcs qualifier.
+</p>
+<p>
+For example,
+</p>
+<pre>import &#34;example.org/pkg/foo&#34;
+</pre>
+<p>
+will result in the following requests:
+</p>
+<pre><a href="https://example.org/pkg/foo?go-get=1">https://example.org/pkg/foo?go-get=1</a> (preferred)
+<a href="http://example.org/pkg/foo?go-get=1">http://example.org/pkg/foo?go-get=1</a> (fallback, only with -insecure)
+</pre>
+<p>
+If that page contains the meta tag
+</p>
+<pre>&lt;meta name=&#34;go-import&#34; content=&#34;example.org git <a href="https://code.org/r/p/exproj">https://code.org/r/p/exproj</a>&#34;&gt;
+</pre>
+<p>
+the go tool will verify that <a href="https://example.org/?go-get=1">https://example.org/?go-get=1</a> contains the
+same meta tag and then git clone <a href="https://code.org/r/p/exproj">https://code.org/r/p/exproj</a> into
+GOPATH/src/example.org.
+</p>
+<p>
+New downloaded packages are written to the first directory listed in the GOPATH
+environment variable (For more details see: &#39;go help gopath&#39;).
+</p>
+<p>
+The go command attempts to download the version of the
+package appropriate for the Go release being used.
+Run &#39;go help get&#39; for more.
+</p>
+<h3 id="hdr-Import_path_checking">Import path checking</h3>
+<p>
+When the custom import path feature described above redirects to a
+known code hosting site, each of the resulting packages has two possible
+import paths, using the custom domain or the known hosting site.
+</p>
+<p>
+A package statement is said to have an &#34;import comment&#34; if it is immediately
+followed (before the next newline) by a comment of one of these two forms:
+</p>
+<pre>package math // import &#34;path&#34;
+package math /* import &#34;path&#34; */
+</pre>
+<p>
+The go command will refuse to install a package with an import comment
+unless it is being referred to by that import path. In this way, import comments
+let package authors make sure the custom import path is used and not a
+direct path to the underlying code hosting site.
+</p>
+<p>
+Import path checking is disabled for code found within vendor trees.
+This makes it possible to copy code into alternate locations in vendor trees
+without needing to update import comments.
+</p>
+<p>
+See <a href="https://golang.org/s/go14customimport">https://golang.org/s/go14customimport</a> for details.
+</p>
+<h3 id="hdr-Description_of_package_lists">Description of package lists</h3>
+<p>
+Many commands apply to a set of packages:
+</p>
+<pre>go action [packages]
+</pre>
+<p>
+Usually, [packages] is a list of import paths.
+</p>
+<p>
+An import path that is a rooted path or that begins with
+a . or .. element is interpreted as a file system path and
+denotes the package in that directory.
+</p>
+<p>
+Otherwise, the import path P denotes the package found in
+the directory DIR/src/P for some DIR listed in the GOPATH
+environment variable (For more details see: &#39;go help gopath&#39;).
+</p>
+<p>
+If no import paths are given, the action applies to the
+package in the current directory.
+</p>
+<p>
+There are four reserved names for paths that should not be used
+for packages to be built with the go tool:
+</p>
+<p>
+- &#34;main&#34; denotes the top-level package in a stand-alone executable.
+</p>
+<p>
+- &#34;all&#34; expands to all package directories found in all the GOPATH
+trees. For example, &#39;go list all&#39; lists all the packages on the local
+system.
+</p>
+<p>
+- &#34;std&#34; is like all but expands to just the packages in the standard
+Go library.
+</p>
+<p>
+- &#34;cmd&#34; expands to the Go repository&#39;s commands and their
+internal libraries.
+</p>
+<p>
+Import paths beginning with &#34;cmd/&#34; only match source code in
+the Go repository.
+</p>
+<p>
+An import path is a pattern if it includes one or more &#34;...&#34; wildcards,
+each of which can match any string, including the empty string and
+strings containing slashes. Such a pattern expands to all package
+directories found in the GOPATH trees with names matching the
+patterns. As a special case, x/... matches x as well as x&#39;s subdirectories.
+For example, net/... expands to net and packages in its subdirectories.
+</p>
+<p>
+An import path can also name a package to be downloaded from
+a remote repository. Run &#39;go help importpath&#39; for details.
+</p>
+<p>
+Every package in a program must have a unique import path.
+By convention, this is arranged by starting each path with a
+unique prefix that belongs to you. For example, paths used
+internally at Google all begin with &#39;google&#39;, and paths
+denoting remote repositories begin with the path to the code,
+such as &#39;github.com/user/repo&#39;.
+</p>
+<p>
+Packages in a program need not have unique package names,
+but there are two reserved package names with special meaning.
+The name main indicates a command, not a library.
+Commands are built into binaries and cannot be imported.
+The name documentation indicates documentation for
+a non-Go program in the directory. Files in package documentation
+are ignored by the go command.
+</p>
+<p>
+As a special case, if the package list is a list of .go files from a
+single directory, the command is applied to a single synthesized
+package made up of exactly those files, ignoring any build constraints
+in those files and ignoring any other files in the directory.
+</p>
+<p>
+Directory and file names that begin with &#34;.&#34; or &#34;_&#34; are ignored
+by the go tool, as are directories named &#34;testdata&#34;.
+</p>
+<h3 id="hdr-Description_of_testing_flags">Description of testing flags</h3>
+<p>
+The &#39;go test&#39; command takes both flags that apply to &#39;go test&#39; itself
+and flags that apply to the resulting test binary.
+</p>
+<p>
+Several of the flags control profiling and write an execution profile
+suitable for &#34;go tool pprof&#34;; run &#34;go tool pprof -h&#34; for more
+information. The --alloc_space, --alloc_objects, and --show_bytes
+options of pprof control how the information is presented.
+</p>
+<p>
+The following flags are recognized by the &#39;go test&#39; command and
+control the execution of any test:
+</p>
+<pre>-bench regexp
+ Run (sub)benchmarks matching a regular expression.
+ The given regular expression is split into smaller ones by
+ top-level &#39;/&#39;, where each must match the corresponding part of a
+ benchmark&#39;s identifier.
+ By default, no benchmarks run. To run all benchmarks,
+ use &#39;-bench .&#39; or &#39;-bench=.&#39;.
+
+-benchtime t
+ Run enough iterations of each benchmark to take t, specified
+ as a time.Duration (for example, -benchtime 1h30s).
+ The default is 1 second (1s).
+
+-count n
+ Run each test and benchmark n times (default 1).
+ If -cpu is set, run n times for each GOMAXPROCS value.
+ Examples are always run once.
+
+-cover
+ Enable coverage analysis.
+
+-covermode set,count,atomic
+ Set the mode for coverage analysis for the package[s]
+ being tested. The default is &#34;set&#34; unless -race is enabled,
+ in which case it is &#34;atomic&#34;.
+ The values:
+ set: bool: does this statement run?
+ count: int: how many times does this statement run?
+ atomic: int: count, but correct in multithreaded tests;
+ significantly more expensive.
+ Sets -cover.
+
+-coverpkg pkg1,pkg2,pkg3
+ Apply coverage analysis in each test to the given list of packages.
+ The default is for each test to analyze only the package being tested.
+ Packages are specified as import paths.
+ Sets -cover.
+
+-cpu 1,2,4
+ Specify a list of GOMAXPROCS values for which the tests or
+ benchmarks should be executed. The default is the current value
+ of GOMAXPROCS.
+
+-parallel n
+ Allow parallel execution of test functions that call t.Parallel.
+ The value of this flag is the maximum number of tests to run
+ simultaneously; by default, it is set to the value of GOMAXPROCS.
+ Note that -parallel only applies within a single test binary.
+ The &#39;go test&#39; command may run tests for different packages
+ in parallel as well, according to the setting of the -p flag
+ (see &#39;go help build&#39;).
+
+-run regexp
+ Run only those tests and examples matching the regular expression.
+ For tests the regular expression is split into smaller ones by
+ top-level &#39;/&#39;, where each must match the corresponding part of a
+ test&#39;s identifier.
+
+-short
+ Tell long-running tests to shorten their run time.
+ It is off by default but set during all.bash so that installing
+ the Go tree can run a sanity check but not spend time running
+ exhaustive tests.
+
+-timeout t
+ If a test runs longer than t, panic.
+ The default is 10 minutes (10m).
+
+-v
+ Verbose output: log all tests as they are run. Also print all
+ text from Log and Logf calls even if the test succeeds.
+</pre>
+<p>
+The following flags are also recognized by &#39;go test&#39; and can be used to
+profile the tests during execution:
+</p>
+<pre>-benchmem
+ Print memory allocation statistics for benchmarks.
+
+-blockprofile block.out
+ Write a goroutine blocking profile to the specified file
+ when all tests are complete.
+ Writes test binary as -c would.
+
+-blockprofilerate n
+ Control the detail provided in goroutine blocking profiles by
+ calling runtime.SetBlockProfileRate with n.
+ See &#39;go doc runtime.SetBlockProfileRate&#39;.
+ The profiler aims to sample, on average, one blocking event every
+ n nanoseconds the program spends blocked. By default,
+ if -test.blockprofile is set without this flag, all blocking events
+ are recorded, equivalent to -test.blockprofilerate=1.
+
+-coverprofile cover.out
+ Write a coverage profile to the file after all tests have passed.
+ Sets -cover.
+
+-cpuprofile cpu.out
+ Write a CPU profile to the specified file before exiting.
+ Writes test binary as -c would.
+
+-memprofile mem.out
+ Write a memory profile to the file after all tests have passed.
+ Writes test binary as -c would.
+
+-memprofilerate n
+ Enable more precise (and expensive) memory profiles by setting
+ runtime.MemProfileRate. See &#39;go doc runtime.MemProfileRate&#39;.
+ To profile all memory allocations, use -test.memprofilerate=1
+ and pass --alloc_space flag to the pprof tool.
+
+-mutexprofile mutex.out
+ Write a mutex contention profile to the specified file
+ when all tests are complete.
+ Writes test binary as -c would.
+
+-mutexprofilefraction n
+ Sample 1 in n stack traces of goroutines holding a
+ contended mutex.
+
+-outputdir directory
+ Place output files from profiling in the specified directory,
+ by default the directory in which &#34;go test&#34; is running.
+
+-trace trace.out
+ Write an execution trace to the specified file before exiting.
+</pre>
+<p>
+Each of these flags is also recognized with an optional &#39;test.&#39; prefix,
+as in -test.v. When invoking the generated test binary (the result of
+&#39;go test -c&#39;) directly, however, the prefix is mandatory.
+</p>
+<p>
+The &#39;go test&#39; command rewrites or removes recognized flags,
+as appropriate, both before and after the optional package list,
+before invoking the test binary.
+</p>
+<p>
+For instance, the command
+</p>
+<pre>go test -v -myflag testdata -cpuprofile=prof.out -x
+</pre>
+<p>
+will compile the test binary and then run it as
+</p>
+<pre>pkg.test -test.v -myflag testdata -test.cpuprofile=prof.out
+</pre>
+<p>
+(The -x flag is removed because it applies only to the go command&#39;s
+execution, not to the test itself.)
+</p>
+<p>
+The test flags that generate profiles (other than for coverage) also
+leave the test binary in pkg.test for use when analyzing the profiles.
+</p>
+<p>
+When &#39;go test&#39; runs a test binary, it does so from within the
+corresponding package&#39;s source code directory. Depending on the test,
+it may be necessary to do the same when invoking a generated test
+binary directly.
+</p>
+<p>
+The command-line package list, if present, must appear before any
+flag not known to the go test command. Continuing the example above,
+the package list would have to appear before -myflag, but could appear
+on either side of -v.
+</p>
+<p>
+To keep an argument for a test binary from being interpreted as a
+known flag or a package name, use -args (see &#39;go help test&#39;) which
+passes the remainder of the command line through to the test binary
+uninterpreted and unaltered.
+</p>
+<p>
+For instance, the command
+</p>
+<pre>go test -v -args -x -v
+</pre>
+<p>
+will compile the test binary and then run it as
+</p>
+<pre>pkg.test -test.v -x -v
+</pre>
+<p>
+Similarly,
+</p>
+<pre>go test -args math
+</pre>
+<p>
+will compile the test binary and then run it as
+</p>
+<pre>pkg.test math
+</pre>
+<p>
+In the first example, the -x and the second -v are passed through to the
+test binary unchanged and with no effect on the go command itself.
+In the second example, the argument math is passed through to the test
+binary, instead of being interpreted as the package list.
+</p>
+<h3 id="hdr-Description_of_testing_functions">Description of testing functions</h3>
+<p>
+The &#39;go test&#39; command expects to find test, benchmark, and example functions
+in the &#34;*_test.go&#34; files corresponding to the package under test.
+</p>
+<p>
+A test function is one named TestXXX (where XXX is any alphanumeric string
+not starting with a lower case letter) and should have the signature,
+</p>
+<pre>func TestXXX(t *testing.T) { ... }
+</pre>
+<p>
+A benchmark function is one named BenchmarkXXX and should have the signature,
+</p>
+<pre>func BenchmarkXXX(b *testing.B) { ... }
+</pre>
+<p>
+An example function is similar to a test function but, instead of using
+*testing.T to report success or failure, prints output to os.Stdout.
+If the last comment in the function starts with &#34;Output:&#34; then the output
+is compared exactly against the comment (see examples below). If the last
+comment begins with &#34;Unordered output:&#34; then the output is compared to the
+comment, however the order of the lines is ignored. An example with no such
+comment is compiled but not executed. An example with no text after
+&#34;Output:&#34; is compiled, executed, and expected to produce no output.
+</p>
+<p>
+Godoc displays the body of ExampleXXX to demonstrate the use
+of the function, constant, or variable XXX. An example of a method M with
+receiver type T or *T is named ExampleT_M. There may be multiple examples
+for a given function, constant, or variable, distinguished by a trailing _xxx,
+where xxx is a suffix not beginning with an upper case letter.
+</p>
+<p>
+Here is an example of an example:
+</p>
+<pre>func ExamplePrintln() {
+ Println(&#34;The output of\nthis example.&#34;)
+ // Output: The output of
+ // this example.
+}
+</pre>
+<p>
+Here is another example where the ordering of the output is ignored:
+</p>
+<pre>func ExamplePerm() {
+ for _, value := range Perm(4) {
+ fmt.Println(value)
+ }
+
+ // Unordered output: 4
+ // 2
+ // 1
+ // 3
+ // 0
+}
+</pre>
+<p>
+The entire test file is presented as the example when it contains a single
+example function, at least one other function, type, variable, or constant
+declaration, and no test or benchmark functions.
+</p>
+<p>
+See the documentation of the testing package for more information.
+</p>
+
+<div id="footer">
+Build version go1.8.<br>
+Except as <a href="https://developers.google.com/site-policies#restrictions">noted</a>,
+the content of this page is licensed under the
+Creative Commons Attribution 3.0 License,
+and code is licensed under a <a href="/LICENSE">BSD license</a>.<br>
+<a href="/doc/tos.html">Terms of Service</a> |
+<a href="http://www.google.com/intl/en/policies/privacy/">Privacy Policy</a>
+</div>
+
+</div><!-- .container -->
+</div><!-- #page -->
+
+<!-- TODO(adonovan): load these from <head> using "defer" attribute? -->
+<script type="text/javascript" src="/serverpush/static/jquery.min.js?{{.CacheBust}}"></script>
+<script type="text/javascript" src="/serverpush/static/playground.js?{{.CacheBust}}"></script>
+<script>var goVersion = "go1.8";</script>
+<script type="text/javascript" src="/serverpush/static/godocs.js?{{.CacheBust}}"></script>
+</body>
+</html>
+`))
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2i/README.md b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2i/README.md
new file mode 100644
index 000000000..fb5c5efb0
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2i/README.md
@@ -0,0 +1,97 @@
+# h2i
+
+**h2i** is an interactive HTTP/2 ("h2") console debugger. Miss the good ol'
+days of telnetting to your HTTP/1.n servers? We're bringing you
+back.
+
+Features:
+- send raw HTTP/2 frames
+ - PING
+ - SETTINGS
+ - HEADERS
+ - etc
+- type in HTTP/1.n and have it auto-HPACK/frame-ify it for HTTP/2
+- pretty print all received HTTP/2 frames from the peer (including HPACK decoding)
+- tab completion of commands, options
+
+Not yet features, but soon:
+- unnecessary CONTINUATION frames on short boundaries, to test peer implementations
+- request bodies (DATA frames)
+- send invalid frames for testing server implementations (supported by underlying Framer)
+
+Later:
+- act like a server
+
+## Installation
+
+```
+$ go get golang.org/x/net/http2/h2i
+$ h2i <host>
+```
+
+## Demo
+
+```
+$ h2i
+Usage: h2i <hostname>
+
+ -insecure
+ Whether to skip TLS cert validation
+ -nextproto string
+ Comma-separated list of NPN/ALPN protocol names to negotiate. (default "h2,h2-14")
+
+$ h2i google.com
+Connecting to google.com:443 ...
+Connected to 74.125.224.41:443
+Negotiated protocol "h2-14"
+[FrameHeader SETTINGS len=18]
+ [MAX_CONCURRENT_STREAMS = 100]
+ [INITIAL_WINDOW_SIZE = 1048576]
+ [MAX_FRAME_SIZE = 16384]
+[FrameHeader WINDOW_UPDATE len=4]
+ Window-Increment = 983041
+
+h2i> PING h2iSayHI
+[FrameHeader PING flags=ACK len=8]
+ Data = "h2iSayHI"
+h2i> headers
+(as HTTP/1.1)> GET / HTTP/1.1
+(as HTTP/1.1)> Host: ip.appspot.com
+(as HTTP/1.1)> User-Agent: h2i/brad-n-blake
+(as HTTP/1.1)>
+Opening Stream-ID 1:
+ :authority = ip.appspot.com
+ :method = GET
+ :path = /
+ :scheme = https
+ user-agent = h2i/brad-n-blake
+[FrameHeader HEADERS flags=END_HEADERS stream=1 len=77]
+ :status = "200"
+ alternate-protocol = "443:quic,p=1"
+ content-length = "15"
+ content-type = "text/html"
+ date = "Fri, 01 May 2015 23:06:56 GMT"
+ server = "Google Frontend"
+[FrameHeader DATA flags=END_STREAM stream=1 len=15]
+ "173.164.155.78\n"
+[FrameHeader PING len=8]
+ Data = "\x00\x00\x00\x00\x00\x00\x00\x00"
+h2i> ping
+[FrameHeader PING flags=ACK len=8]
+ Data = "h2i_ping"
+h2i> ping
+[FrameHeader PING flags=ACK len=8]
+ Data = "h2i_ping"
+h2i> ping
+[FrameHeader GOAWAY len=22]
+ Last-Stream-ID = 1; Error-Code = PROTOCOL_ERROR (1)
+
+ReadFrame: EOF
+```
+
+## Status
+
+Quick few hour hack. So much yet to do. Feel free to file issues for
+bugs or wishlist items, but [@bmizerany](https://github.com/bmizerany/)
+and I aren't yet accepting pull requests until things settle down.
+
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2i/h2i.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2i/h2i.go
new file mode 100644
index 000000000..62e57527c
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/h2i/h2i.go
@@ -0,0 +1,522 @@
+// Copyright 2015 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.
+
+// +build !plan9,!solaris
+
+/*
+The h2i command is an interactive HTTP/2 console.
+
+Usage:
+ $ h2i [flags] <hostname>
+
+Interactive commands in the console: (all parts case-insensitive)
+
+ ping [data]
+ settings ack
+ settings FOO=n BAR=z
+ headers (open a new stream by typing HTTP/1.1)
+*/
+package main
+
+import (
+ "bufio"
+ "bytes"
+ "crypto/tls"
+ "errors"
+ "flag"
+ "fmt"
+ "io"
+ "log"
+ "net"
+ "net/http"
+ "os"
+ "regexp"
+ "strconv"
+ "strings"
+
+ "golang.org/x/crypto/ssh/terminal"
+ "golang.org/x/net/http2"
+ "golang.org/x/net/http2/hpack"
+)
+
+// Flags
+var (
+ flagNextProto = flag.String("nextproto", "h2,h2-14", "Comma-separated list of NPN/ALPN protocol names to negotiate.")
+ flagInsecure = flag.Bool("insecure", false, "Whether to skip TLS cert validation")
+ flagSettings = flag.String("settings", "empty", "comma-separated list of KEY=value settings for the initial SETTINGS frame. The magic value 'empty' sends an empty initial settings frame, and the magic value 'omit' causes no initial settings frame to be sent.")
+ flagDial = flag.String("dial", "", "optional ip:port to dial, to connect to a host:port but use a different SNI name (including a SNI name without DNS)")
+)
+
+type command struct {
+ run func(*h2i, []string) error // required
+
+ // complete optionally specifies tokens (case-insensitive) which are
+ // valid for this subcommand.
+ complete func() []string
+}
+
+var commands = map[string]command{
+ "ping": {run: (*h2i).cmdPing},
+ "settings": {
+ run: (*h2i).cmdSettings,
+ complete: func() []string {
+ return []string{
+ "ACK",
+ http2.SettingHeaderTableSize.String(),
+ http2.SettingEnablePush.String(),
+ http2.SettingMaxConcurrentStreams.String(),
+ http2.SettingInitialWindowSize.String(),
+ http2.SettingMaxFrameSize.String(),
+ http2.SettingMaxHeaderListSize.String(),
+ }
+ },
+ },
+ "quit": {run: (*h2i).cmdQuit},
+ "headers": {run: (*h2i).cmdHeaders},
+}
+
+func usage() {
+ fmt.Fprintf(os.Stderr, "Usage: h2i <hostname>\n\n")
+ flag.PrintDefaults()
+}
+
+// withPort adds ":443" if another port isn't already present.
+func withPort(host string) string {
+ if _, _, err := net.SplitHostPort(host); err != nil {
+ return net.JoinHostPort(host, "443")
+ }
+ return host
+}
+
+// withoutPort strips the port from addr if present.
+func withoutPort(addr string) string {
+ if h, _, err := net.SplitHostPort(addr); err == nil {
+ return h
+ }
+ return addr
+}
+
+// h2i is the app's state.
+type h2i struct {
+ host string
+ tc *tls.Conn
+ framer *http2.Framer
+ term *terminal.Terminal
+
+ // owned by the command loop:
+ streamID uint32
+ hbuf bytes.Buffer
+ henc *hpack.Encoder
+
+ // owned by the readFrames loop:
+ peerSetting map[http2.SettingID]uint32
+ hdec *hpack.Decoder
+}
+
+func main() {
+ flag.Usage = usage
+ flag.Parse()
+ if flag.NArg() != 1 {
+ usage()
+ os.Exit(2)
+ }
+ log.SetFlags(0)
+
+ host := flag.Arg(0)
+ app := &h2i{
+ host: host,
+ peerSetting: make(map[http2.SettingID]uint32),
+ }
+ app.henc = hpack.NewEncoder(&app.hbuf)
+
+ if err := app.Main(); err != nil {
+ if app.term != nil {
+ app.logf("%v\n", err)
+ } else {
+ fmt.Fprintf(os.Stderr, "%v\n", err)
+ }
+ os.Exit(1)
+ }
+ fmt.Fprintf(os.Stdout, "\n")
+}
+
+func (app *h2i) Main() error {
+ cfg := &tls.Config{
+ ServerName: withoutPort(app.host),
+ NextProtos: strings.Split(*flagNextProto, ","),
+ InsecureSkipVerify: *flagInsecure,
+ }
+
+ hostAndPort := *flagDial
+ if hostAndPort == "" {
+ hostAndPort = withPort(app.host)
+ }
+ log.Printf("Connecting to %s ...", hostAndPort)
+ tc, err := tls.Dial("tcp", hostAndPort, cfg)
+ if err != nil {
+ return fmt.Errorf("Error dialing %s: %v", hostAndPort, err)
+ }
+ log.Printf("Connected to %v", tc.RemoteAddr())
+ defer tc.Close()
+
+ if err := tc.Handshake(); err != nil {
+ return fmt.Errorf("TLS handshake: %v", err)
+ }
+ if !*flagInsecure {
+ if err := tc.VerifyHostname(app.host); err != nil {
+ return fmt.Errorf("VerifyHostname: %v", err)
+ }
+ }
+ state := tc.ConnectionState()
+ log.Printf("Negotiated protocol %q", state.NegotiatedProtocol)
+ if !state.NegotiatedProtocolIsMutual || state.NegotiatedProtocol == "" {
+ return fmt.Errorf("Could not negotiate protocol mutually")
+ }
+
+ if _, err := io.WriteString(tc, http2.ClientPreface); err != nil {
+ return err
+ }
+
+ app.framer = http2.NewFramer(tc, tc)
+
+ oldState, err := terminal.MakeRaw(int(os.Stdin.Fd()))
+ if err != nil {
+ return err
+ }
+ defer terminal.Restore(0, oldState)
+
+ var screen = struct {
+ io.Reader
+ io.Writer
+ }{os.Stdin, os.Stdout}
+
+ app.term = terminal.NewTerminal(screen, "h2i> ")
+ lastWord := regexp.MustCompile(`.+\W(\w+)$`)
+ app.term.AutoCompleteCallback = func(line string, pos int, key rune) (newLine string, newPos int, ok bool) {
+ if key != '\t' {
+ return
+ }
+ if pos != len(line) {
+ // TODO: we're being lazy for now, only supporting tab completion at the end.
+ return
+ }
+ // Auto-complete for the command itself.
+ if !strings.Contains(line, " ") {
+ var name string
+ name, _, ok = lookupCommand(line)
+ if !ok {
+ return
+ }
+ return name, len(name), true
+ }
+ _, c, ok := lookupCommand(line[:strings.IndexByte(line, ' ')])
+ if !ok || c.complete == nil {
+ return
+ }
+ if strings.HasSuffix(line, " ") {
+ app.logf("%s", strings.Join(c.complete(), " "))
+ return line, pos, true
+ }
+ m := lastWord.FindStringSubmatch(line)
+ if m == nil {
+ return line, len(line), true
+ }
+ soFar := m[1]
+ var match []string
+ for _, cand := range c.complete() {
+ if len(soFar) > len(cand) || !strings.EqualFold(cand[:len(soFar)], soFar) {
+ continue
+ }
+ match = append(match, cand)
+ }
+ if len(match) == 0 {
+ return
+ }
+ if len(match) > 1 {
+ // TODO: auto-complete any common prefix
+ app.logf("%s", strings.Join(match, " "))
+ return line, pos, true
+ }
+ newLine = line[:len(line)-len(soFar)] + match[0]
+ return newLine, len(newLine), true
+
+ }
+
+ errc := make(chan error, 2)
+ go func() { errc <- app.readFrames() }()
+ go func() { errc <- app.readConsole() }()
+ return <-errc
+}
+
+func (app *h2i) logf(format string, args ...interface{}) {
+ fmt.Fprintf(app.term, format+"\r\n", args...)
+}
+
+func (app *h2i) readConsole() error {
+ if s := *flagSettings; s != "omit" {
+ var args []string
+ if s != "empty" {
+ args = strings.Split(s, ",")
+ }
+ _, c, ok := lookupCommand("settings")
+ if !ok {
+ panic("settings command not found")
+ }
+ c.run(app, args)
+ }
+
+ for {
+ line, err := app.term.ReadLine()
+ if err == io.EOF {
+ return nil
+ }
+ if err != nil {
+ return fmt.Errorf("terminal.ReadLine: %v", err)
+ }
+ f := strings.Fields(line)
+ if len(f) == 0 {
+ continue
+ }
+ cmd, args := f[0], f[1:]
+ if _, c, ok := lookupCommand(cmd); ok {
+ err = c.run(app, args)
+ } else {
+ app.logf("Unknown command %q", line)
+ }
+ if err == errExitApp {
+ return nil
+ }
+ if err != nil {
+ return err
+ }
+ }
+}
+
+func lookupCommand(prefix string) (name string, c command, ok bool) {
+ prefix = strings.ToLower(prefix)
+ if c, ok = commands[prefix]; ok {
+ return prefix, c, ok
+ }
+
+ for full, candidate := range commands {
+ if strings.HasPrefix(full, prefix) {
+ if c.run != nil {
+ return "", command{}, false // ambiguous
+ }
+ c = candidate
+ name = full
+ }
+ }
+ return name, c, c.run != nil
+}
+
+var errExitApp = errors.New("internal sentinel error value to quit the console reading loop")
+
+func (a *h2i) cmdQuit(args []string) error {
+ if len(args) > 0 {
+ a.logf("the QUIT command takes no argument")
+ return nil
+ }
+ return errExitApp
+}
+
+func (a *h2i) cmdSettings(args []string) error {
+ if len(args) == 1 && strings.EqualFold(args[0], "ACK") {
+ return a.framer.WriteSettingsAck()
+ }
+ var settings []http2.Setting
+ for _, arg := range args {
+ if strings.EqualFold(arg, "ACK") {
+ a.logf("Error: ACK must be only argument with the SETTINGS command")
+ return nil
+ }
+ eq := strings.Index(arg, "=")
+ if eq == -1 {
+ a.logf("Error: invalid argument %q (expected SETTING_NAME=nnnn)", arg)
+ return nil
+ }
+ sid, ok := settingByName(arg[:eq])
+ if !ok {
+ a.logf("Error: unknown setting name %q", arg[:eq])
+ return nil
+ }
+ val, err := strconv.ParseUint(arg[eq+1:], 10, 32)
+ if err != nil {
+ a.logf("Error: invalid argument %q (expected SETTING_NAME=nnnn)", arg)
+ return nil
+ }
+ settings = append(settings, http2.Setting{
+ ID: sid,
+ Val: uint32(val),
+ })
+ }
+ a.logf("Sending: %v", settings)
+ return a.framer.WriteSettings(settings...)
+}
+
+func settingByName(name string) (http2.SettingID, bool) {
+ for _, sid := range [...]http2.SettingID{
+ http2.SettingHeaderTableSize,
+ http2.SettingEnablePush,
+ http2.SettingMaxConcurrentStreams,
+ http2.SettingInitialWindowSize,
+ http2.SettingMaxFrameSize,
+ http2.SettingMaxHeaderListSize,
+ } {
+ if strings.EqualFold(sid.String(), name) {
+ return sid, true
+ }
+ }
+ return 0, false
+}
+
+func (app *h2i) cmdPing(args []string) error {
+ if len(args) > 1 {
+ app.logf("invalid PING usage: only accepts 0 or 1 args")
+ return nil // nil means don't end the program
+ }
+ var data [8]byte
+ if len(args) == 1 {
+ copy(data[:], args[0])
+ } else {
+ copy(data[:], "h2i_ping")
+ }
+ return app.framer.WritePing(false, data)
+}
+
+func (app *h2i) cmdHeaders(args []string) error {
+ if len(args) > 0 {
+ app.logf("Error: HEADERS doesn't yet take arguments.")
+ // TODO: flags for restricting window size, to force CONTINUATION
+ // frames.
+ return nil
+ }
+ var h1req bytes.Buffer
+ app.term.SetPrompt("(as HTTP/1.1)> ")
+ defer app.term.SetPrompt("h2i> ")
+ for {
+ line, err := app.term.ReadLine()
+ if err != nil {
+ return err
+ }
+ h1req.WriteString(line)
+ h1req.WriteString("\r\n")
+ if line == "" {
+ break
+ }
+ }
+ req, err := http.ReadRequest(bufio.NewReader(&h1req))
+ if err != nil {
+ app.logf("Invalid HTTP/1.1 request: %v", err)
+ return nil
+ }
+ if app.streamID == 0 {
+ app.streamID = 1
+ } else {
+ app.streamID += 2
+ }
+ app.logf("Opening Stream-ID %d:", app.streamID)
+ hbf := app.encodeHeaders(req)
+ if len(hbf) > 16<<10 {
+ app.logf("TODO: h2i doesn't yet write CONTINUATION frames. Copy it from transport.go")
+ return nil
+ }
+ return app.framer.WriteHeaders(http2.HeadersFrameParam{
+ StreamID: app.streamID,
+ BlockFragment: hbf,
+ EndStream: req.Method == "GET" || req.Method == "HEAD", // good enough for now
+ EndHeaders: true, // for now
+ })
+}
+
+func (app *h2i) readFrames() error {
+ for {
+ f, err := app.framer.ReadFrame()
+ if err != nil {
+ return fmt.Errorf("ReadFrame: %v", err)
+ }
+ app.logf("%v", f)
+ switch f := f.(type) {
+ case *http2.PingFrame:
+ app.logf(" Data = %q", f.Data)
+ case *http2.SettingsFrame:
+ f.ForeachSetting(func(s http2.Setting) error {
+ app.logf(" %v", s)
+ app.peerSetting[s.ID] = s.Val
+ return nil
+ })
+ case *http2.WindowUpdateFrame:
+ app.logf(" Window-Increment = %v", f.Increment)
+ case *http2.GoAwayFrame:
+ app.logf(" Last-Stream-ID = %d; Error-Code = %v (%d)", f.LastStreamID, f.ErrCode, f.ErrCode)
+ case *http2.DataFrame:
+ app.logf(" %q", f.Data())
+ case *http2.HeadersFrame:
+ if f.HasPriority() {
+ app.logf(" PRIORITY = %v", f.Priority)
+ }
+ if app.hdec == nil {
+ // TODO: if the user uses h2i to send a SETTINGS frame advertising
+ // something larger, we'll need to respect SETTINGS_HEADER_TABLE_SIZE
+ // and stuff here instead of using the 4k default. But for now:
+ tableSize := uint32(4 << 10)
+ app.hdec = hpack.NewDecoder(tableSize, app.onNewHeaderField)
+ }
+ app.hdec.Write(f.HeaderBlockFragment())
+ case *http2.PushPromiseFrame:
+ if app.hdec == nil {
+ // TODO: if the user uses h2i to send a SETTINGS frame advertising
+ // something larger, we'll need to respect SETTINGS_HEADER_TABLE_SIZE
+ // and stuff here instead of using the 4k default. But for now:
+ tableSize := uint32(4 << 10)
+ app.hdec = hpack.NewDecoder(tableSize, app.onNewHeaderField)
+ }
+ app.hdec.Write(f.HeaderBlockFragment())
+ }
+ }
+}
+
+// called from readLoop
+func (app *h2i) onNewHeaderField(f hpack.HeaderField) {
+ if f.Sensitive {
+ app.logf(" %s = %q (SENSITIVE)", f.Name, f.Value)
+ }
+ app.logf(" %s = %q", f.Name, f.Value)
+}
+
+func (app *h2i) encodeHeaders(req *http.Request) []byte {
+ app.hbuf.Reset()
+
+ // TODO(bradfitz): figure out :authority-vs-Host stuff between http2 and Go
+ host := req.Host
+ if host == "" {
+ host = req.URL.Host
+ }
+
+ path := req.RequestURI
+ if path == "" {
+ path = "/"
+ }
+
+ app.writeHeader(":authority", host) // probably not right for all sites
+ app.writeHeader(":method", req.Method)
+ app.writeHeader(":path", path)
+ app.writeHeader(":scheme", "https")
+
+ for k, vv := range req.Header {
+ lowKey := strings.ToLower(k)
+ if lowKey == "host" {
+ continue
+ }
+ for _, v := range vv {
+ app.writeHeader(lowKey, v)
+ }
+ }
+ return app.hbuf.Bytes()
+}
+
+func (app *h2i) writeHeader(name, value string) {
+ app.henc.WriteField(hpack.HeaderField{Name: name, Value: value})
+ app.logf(" %s = %s", name, value)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/headermap.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/headermap.go
new file mode 100644
index 000000000..c2805f6ac
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/headermap.go
@@ -0,0 +1,78 @@
+// Copyright 2014 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 http2
+
+import (
+ "net/http"
+ "strings"
+)
+
+var (
+ commonLowerHeader = map[string]string{} // Go-Canonical-Case -> lower-case
+ commonCanonHeader = map[string]string{} // lower-case -> Go-Canonical-Case
+)
+
+func init() {
+ for _, v := range []string{
+ "accept",
+ "accept-charset",
+ "accept-encoding",
+ "accept-language",
+ "accept-ranges",
+ "age",
+ "access-control-allow-origin",
+ "allow",
+ "authorization",
+ "cache-control",
+ "content-disposition",
+ "content-encoding",
+ "content-language",
+ "content-length",
+ "content-location",
+ "content-range",
+ "content-type",
+ "cookie",
+ "date",
+ "etag",
+ "expect",
+ "expires",
+ "from",
+ "host",
+ "if-match",
+ "if-modified-since",
+ "if-none-match",
+ "if-unmodified-since",
+ "last-modified",
+ "link",
+ "location",
+ "max-forwards",
+ "proxy-authenticate",
+ "proxy-authorization",
+ "range",
+ "referer",
+ "refresh",
+ "retry-after",
+ "server",
+ "set-cookie",
+ "strict-transport-security",
+ "trailer",
+ "transfer-encoding",
+ "user-agent",
+ "vary",
+ "via",
+ "www-authenticate",
+ } {
+ chk := http.CanonicalHeaderKey(v)
+ commonLowerHeader[chk] = v
+ commonCanonHeader[v] = chk
+ }
+}
+
+func lowerHeader(v string) string {
+ if s, ok := commonLowerHeader[v]; ok {
+ return s
+ }
+ return strings.ToLower(v)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/hpack/encode.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/hpack/encode.go
new file mode 100644
index 000000000..54726c2a3
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/hpack/encode.go
@@ -0,0 +1,240 @@
+// Copyright 2014 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 hpack
+
+import (
+ "io"
+)
+
+const (
+ uint32Max = ^uint32(0)
+ initialHeaderTableSize = 4096
+)
+
+type Encoder struct {
+ dynTab dynamicTable
+ // minSize is the minimum table size set by
+ // SetMaxDynamicTableSize after the previous Header Table Size
+ // Update.
+ minSize uint32
+ // maxSizeLimit is the maximum table size this encoder
+ // supports. This will protect the encoder from too large
+ // size.
+ maxSizeLimit uint32
+ // tableSizeUpdate indicates whether "Header Table Size
+ // Update" is required.
+ tableSizeUpdate bool
+ w io.Writer
+ buf []byte
+}
+
+// NewEncoder returns a new Encoder which performs HPACK encoding. An
+// encoded data is written to w.
+func NewEncoder(w io.Writer) *Encoder {
+ e := &Encoder{
+ minSize: uint32Max,
+ maxSizeLimit: initialHeaderTableSize,
+ tableSizeUpdate: false,
+ w: w,
+ }
+ e.dynTab.table.init()
+ e.dynTab.setMaxSize(initialHeaderTableSize)
+ return e
+}
+
+// WriteField encodes f into a single Write to e's underlying Writer.
+// This function may also produce bytes for "Header Table Size Update"
+// if necessary. If produced, it is done before encoding f.
+func (e *Encoder) WriteField(f HeaderField) error {
+ e.buf = e.buf[:0]
+
+ if e.tableSizeUpdate {
+ e.tableSizeUpdate = false
+ if e.minSize < e.dynTab.maxSize {
+ e.buf = appendTableSize(e.buf, e.minSize)
+ }
+ e.minSize = uint32Max
+ e.buf = appendTableSize(e.buf, e.dynTab.maxSize)
+ }
+
+ idx, nameValueMatch := e.searchTable(f)
+ if nameValueMatch {
+ e.buf = appendIndexed(e.buf, idx)
+ } else {
+ indexing := e.shouldIndex(f)
+ if indexing {
+ e.dynTab.add(f)
+ }
+
+ if idx == 0 {
+ e.buf = appendNewName(e.buf, f, indexing)
+ } else {
+ e.buf = appendIndexedName(e.buf, f, idx, indexing)
+ }
+ }
+ n, err := e.w.Write(e.buf)
+ if err == nil && n != len(e.buf) {
+ err = io.ErrShortWrite
+ }
+ return err
+}
+
+// searchTable searches f in both stable and dynamic header tables.
+// The static header table is searched first. Only when there is no
+// exact match for both name and value, the dynamic header table is
+// then searched. If there is no match, i is 0. If both name and value
+// match, i is the matched index and nameValueMatch becomes true. If
+// only name matches, i points to that index and nameValueMatch
+// becomes false.
+func (e *Encoder) searchTable(f HeaderField) (i uint64, nameValueMatch bool) {
+ i, nameValueMatch = staticTable.search(f)
+ if nameValueMatch {
+ return i, true
+ }
+
+ j, nameValueMatch := e.dynTab.table.search(f)
+ if nameValueMatch || (i == 0 && j != 0) {
+ return j + uint64(staticTable.len()), nameValueMatch
+ }
+
+ return i, false
+}
+
+// SetMaxDynamicTableSize changes the dynamic header table size to v.
+// The actual size is bounded by the value passed to
+// SetMaxDynamicTableSizeLimit.
+func (e *Encoder) SetMaxDynamicTableSize(v uint32) {
+ if v > e.maxSizeLimit {
+ v = e.maxSizeLimit
+ }
+ if v < e.minSize {
+ e.minSize = v
+ }
+ e.tableSizeUpdate = true
+ e.dynTab.setMaxSize(v)
+}
+
+// SetMaxDynamicTableSizeLimit changes the maximum value that can be
+// specified in SetMaxDynamicTableSize to v. By default, it is set to
+// 4096, which is the same size of the default dynamic header table
+// size described in HPACK specification. If the current maximum
+// dynamic header table size is strictly greater than v, "Header Table
+// Size Update" will be done in the next WriteField call and the
+// maximum dynamic header table size is truncated to v.
+func (e *Encoder) SetMaxDynamicTableSizeLimit(v uint32) {
+ e.maxSizeLimit = v
+ if e.dynTab.maxSize > v {
+ e.tableSizeUpdate = true
+ e.dynTab.setMaxSize(v)
+ }
+}
+
+// shouldIndex reports whether f should be indexed.
+func (e *Encoder) shouldIndex(f HeaderField) bool {
+ return !f.Sensitive && f.Size() <= e.dynTab.maxSize
+}
+
+// appendIndexed appends index i, as encoded in "Indexed Header Field"
+// representation, to dst and returns the extended buffer.
+func appendIndexed(dst []byte, i uint64) []byte {
+ first := len(dst)
+ dst = appendVarInt(dst, 7, i)
+ dst[first] |= 0x80
+ return dst
+}
+
+// appendNewName appends f, as encoded in one of "Literal Header field
+// - New Name" representation variants, to dst and returns the
+// extended buffer.
+//
+// If f.Sensitive is true, "Never Indexed" representation is used. If
+// f.Sensitive is false and indexing is true, "Inremental Indexing"
+// representation is used.
+func appendNewName(dst []byte, f HeaderField, indexing bool) []byte {
+ dst = append(dst, encodeTypeByte(indexing, f.Sensitive))
+ dst = appendHpackString(dst, f.Name)
+ return appendHpackString(dst, f.Value)
+}
+
+// appendIndexedName appends f and index i referring indexed name
+// entry, as encoded in one of "Literal Header field - Indexed Name"
+// representation variants, to dst and returns the extended buffer.
+//
+// If f.Sensitive is true, "Never Indexed" representation is used. If
+// f.Sensitive is false and indexing is true, "Incremental Indexing"
+// representation is used.
+func appendIndexedName(dst []byte, f HeaderField, i uint64, indexing bool) []byte {
+ first := len(dst)
+ var n byte
+ if indexing {
+ n = 6
+ } else {
+ n = 4
+ }
+ dst = appendVarInt(dst, n, i)
+ dst[first] |= encodeTypeByte(indexing, f.Sensitive)
+ return appendHpackString(dst, f.Value)
+}
+
+// appendTableSize appends v, as encoded in "Header Table Size Update"
+// representation, to dst and returns the extended buffer.
+func appendTableSize(dst []byte, v uint32) []byte {
+ first := len(dst)
+ dst = appendVarInt(dst, 5, uint64(v))
+ dst[first] |= 0x20
+ return dst
+}
+
+// appendVarInt appends i, as encoded in variable integer form using n
+// bit prefix, to dst and returns the extended buffer.
+//
+// See
+// http://http2.github.io/http2-spec/compression.html#integer.representation
+func appendVarInt(dst []byte, n byte, i uint64) []byte {
+ k := uint64((1 << n) - 1)
+ if i < k {
+ return append(dst, byte(i))
+ }
+ dst = append(dst, byte(k))
+ i -= k
+ for ; i >= 128; i >>= 7 {
+ dst = append(dst, byte(0x80|(i&0x7f)))
+ }
+ return append(dst, byte(i))
+}
+
+// appendHpackString appends s, as encoded in "String Literal"
+// representation, to dst and returns the the extended buffer.
+//
+// s will be encoded in Huffman codes only when it produces strictly
+// shorter byte string.
+func appendHpackString(dst []byte, s string) []byte {
+ huffmanLength := HuffmanEncodeLength(s)
+ if huffmanLength < uint64(len(s)) {
+ first := len(dst)
+ dst = appendVarInt(dst, 7, huffmanLength)
+ dst = AppendHuffmanString(dst, s)
+ dst[first] |= 0x80
+ } else {
+ dst = appendVarInt(dst, 7, uint64(len(s)))
+ dst = append(dst, s...)
+ }
+ return dst
+}
+
+// encodeTypeByte returns type byte. If sensitive is true, type byte
+// for "Never Indexed" representation is returned. If sensitive is
+// false and indexing is true, type byte for "Incremental Indexing"
+// representation is returned. Otherwise, type byte for "Without
+// Indexing" is returned.
+func encodeTypeByte(indexing, sensitive bool) byte {
+ if sensitive {
+ return 0x10
+ }
+ if indexing {
+ return 0x40
+ }
+ return 0
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/hpack/encode_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/hpack/encode_test.go
new file mode 100644
index 000000000..05f12db9c
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/hpack/encode_test.go
@@ -0,0 +1,386 @@
+// Copyright 2014 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 hpack
+
+import (
+ "bytes"
+ "encoding/hex"
+ "fmt"
+ "math/rand"
+ "reflect"
+ "strings"
+ "testing"
+)
+
+func TestEncoderTableSizeUpdate(t *testing.T) {
+ tests := []struct {
+ size1, size2 uint32
+ wantHex string
+ }{
+ // Should emit 2 table size updates (2048 and 4096)
+ {2048, 4096, "3fe10f 3fe11f 82"},
+
+ // Should emit 1 table size update (2048)
+ {16384, 2048, "3fe10f 82"},
+ }
+ for _, tt := range tests {
+ var buf bytes.Buffer
+ e := NewEncoder(&buf)
+ e.SetMaxDynamicTableSize(tt.size1)
+ e.SetMaxDynamicTableSize(tt.size2)
+ if err := e.WriteField(pair(":method", "GET")); err != nil {
+ t.Fatal(err)
+ }
+ want := removeSpace(tt.wantHex)
+ if got := hex.EncodeToString(buf.Bytes()); got != want {
+ t.Errorf("e.SetDynamicTableSize %v, %v = %q; want %q", tt.size1, tt.size2, got, want)
+ }
+ }
+}
+
+func TestEncoderWriteField(t *testing.T) {
+ var buf bytes.Buffer
+ e := NewEncoder(&buf)
+ var got []HeaderField
+ d := NewDecoder(4<<10, func(f HeaderField) {
+ got = append(got, f)
+ })
+
+ tests := []struct {
+ hdrs []HeaderField
+ }{
+ {[]HeaderField{
+ pair(":method", "GET"),
+ pair(":scheme", "http"),
+ pair(":path", "/"),
+ pair(":authority", "www.example.com"),
+ }},
+ {[]HeaderField{
+ pair(":method", "GET"),
+ pair(":scheme", "http"),
+ pair(":path", "/"),
+ pair(":authority", "www.example.com"),
+ pair("cache-control", "no-cache"),
+ }},
+ {[]HeaderField{
+ pair(":method", "GET"),
+ pair(":scheme", "https"),
+ pair(":path", "/index.html"),
+ pair(":authority", "www.example.com"),
+ pair("custom-key", "custom-value"),
+ }},
+ }
+ for i, tt := range tests {
+ buf.Reset()
+ got = got[:0]
+ for _, hf := range tt.hdrs {
+ if err := e.WriteField(hf); err != nil {
+ t.Fatal(err)
+ }
+ }
+ _, err := d.Write(buf.Bytes())
+ if err != nil {
+ t.Errorf("%d. Decoder Write = %v", i, err)
+ }
+ if !reflect.DeepEqual(got, tt.hdrs) {
+ t.Errorf("%d. Decoded %+v; want %+v", i, got, tt.hdrs)
+ }
+ }
+}
+
+func TestEncoderSearchTable(t *testing.T) {
+ e := NewEncoder(nil)
+
+ e.dynTab.add(pair("foo", "bar"))
+ e.dynTab.add(pair("blake", "miz"))
+ e.dynTab.add(pair(":method", "GET"))
+
+ tests := []struct {
+ hf HeaderField
+ wantI uint64
+ wantMatch bool
+ }{
+ // Name and Value match
+ {pair("foo", "bar"), uint64(staticTable.len()) + 3, true},
+ {pair("blake", "miz"), uint64(staticTable.len()) + 2, true},
+ {pair(":method", "GET"), 2, true},
+
+ // Only name match because Sensitive == true. This is allowed to match
+ // any ":method" entry. The current implementation uses the last entry
+ // added in newStaticTable.
+ {HeaderField{":method", "GET", true}, 3, false},
+
+ // Only Name matches
+ {pair("foo", "..."), uint64(staticTable.len()) + 3, false},
+ {pair("blake", "..."), uint64(staticTable.len()) + 2, false},
+ // As before, this is allowed to match any ":method" entry.
+ {pair(":method", "..."), 3, false},
+
+ // None match
+ {pair("foo-", "bar"), 0, false},
+ }
+ for _, tt := range tests {
+ if gotI, gotMatch := e.searchTable(tt.hf); gotI != tt.wantI || gotMatch != tt.wantMatch {
+ t.Errorf("d.search(%+v) = %v, %v; want %v, %v", tt.hf, gotI, gotMatch, tt.wantI, tt.wantMatch)
+ }
+ }
+}
+
+func TestAppendVarInt(t *testing.T) {
+ tests := []struct {
+ n byte
+ i uint64
+ want []byte
+ }{
+ // Fits in a byte:
+ {1, 0, []byte{0}},
+ {2, 2, []byte{2}},
+ {3, 6, []byte{6}},
+ {4, 14, []byte{14}},
+ {5, 30, []byte{30}},
+ {6, 62, []byte{62}},
+ {7, 126, []byte{126}},
+ {8, 254, []byte{254}},
+
+ // Multiple bytes:
+ {5, 1337, []byte{31, 154, 10}},
+ }
+ for _, tt := range tests {
+ got := appendVarInt(nil, tt.n, tt.i)
+ if !bytes.Equal(got, tt.want) {
+ t.Errorf("appendVarInt(nil, %v, %v) = %v; want %v", tt.n, tt.i, got, tt.want)
+ }
+ }
+}
+
+func TestAppendHpackString(t *testing.T) {
+ tests := []struct {
+ s, wantHex string
+ }{
+ // Huffman encoded
+ {"www.example.com", "8c f1e3 c2e5 f23a 6ba0 ab90 f4ff"},
+
+ // Not Huffman encoded
+ {"a", "01 61"},
+
+ // zero length
+ {"", "00"},
+ }
+ for _, tt := range tests {
+ want := removeSpace(tt.wantHex)
+ buf := appendHpackString(nil, tt.s)
+ if got := hex.EncodeToString(buf); want != got {
+ t.Errorf("appendHpackString(nil, %q) = %q; want %q", tt.s, got, want)
+ }
+ }
+}
+
+func TestAppendIndexed(t *testing.T) {
+ tests := []struct {
+ i uint64
+ wantHex string
+ }{
+ // 1 byte
+ {1, "81"},
+ {126, "fe"},
+
+ // 2 bytes
+ {127, "ff00"},
+ {128, "ff01"},
+ }
+ for _, tt := range tests {
+ want := removeSpace(tt.wantHex)
+ buf := appendIndexed(nil, tt.i)
+ if got := hex.EncodeToString(buf); want != got {
+ t.Errorf("appendIndex(nil, %v) = %q; want %q", tt.i, got, want)
+ }
+ }
+}
+
+func TestAppendNewName(t *testing.T) {
+ tests := []struct {
+ f HeaderField
+ indexing bool
+ wantHex string
+ }{
+ // Incremental indexing
+ {HeaderField{"custom-key", "custom-value", false}, true, "40 88 25a8 49e9 5ba9 7d7f 89 25a8 49e9 5bb8 e8b4 bf"},
+
+ // Without indexing
+ {HeaderField{"custom-key", "custom-value", false}, false, "00 88 25a8 49e9 5ba9 7d7f 89 25a8 49e9 5bb8 e8b4 bf"},
+
+ // Never indexed
+ {HeaderField{"custom-key", "custom-value", true}, true, "10 88 25a8 49e9 5ba9 7d7f 89 25a8 49e9 5bb8 e8b4 bf"},
+ {HeaderField{"custom-key", "custom-value", true}, false, "10 88 25a8 49e9 5ba9 7d7f 89 25a8 49e9 5bb8 e8b4 bf"},
+ }
+ for _, tt := range tests {
+ want := removeSpace(tt.wantHex)
+ buf := appendNewName(nil, tt.f, tt.indexing)
+ if got := hex.EncodeToString(buf); want != got {
+ t.Errorf("appendNewName(nil, %+v, %v) = %q; want %q", tt.f, tt.indexing, got, want)
+ }
+ }
+}
+
+func TestAppendIndexedName(t *testing.T) {
+ tests := []struct {
+ f HeaderField
+ i uint64
+ indexing bool
+ wantHex string
+ }{
+ // Incremental indexing
+ {HeaderField{":status", "302", false}, 8, true, "48 82 6402"},
+
+ // Without indexing
+ {HeaderField{":status", "302", false}, 8, false, "08 82 6402"},
+
+ // Never indexed
+ {HeaderField{":status", "302", true}, 8, true, "18 82 6402"},
+ {HeaderField{":status", "302", true}, 8, false, "18 82 6402"},
+ }
+ for _, tt := range tests {
+ want := removeSpace(tt.wantHex)
+ buf := appendIndexedName(nil, tt.f, tt.i, tt.indexing)
+ if got := hex.EncodeToString(buf); want != got {
+ t.Errorf("appendIndexedName(nil, %+v, %v) = %q; want %q", tt.f, tt.indexing, got, want)
+ }
+ }
+}
+
+func TestAppendTableSize(t *testing.T) {
+ tests := []struct {
+ i uint32
+ wantHex string
+ }{
+ // Fits into 1 byte
+ {30, "3e"},
+
+ // Extra byte
+ {31, "3f00"},
+ {32, "3f01"},
+ }
+ for _, tt := range tests {
+ want := removeSpace(tt.wantHex)
+ buf := appendTableSize(nil, tt.i)
+ if got := hex.EncodeToString(buf); want != got {
+ t.Errorf("appendTableSize(nil, %v) = %q; want %q", tt.i, got, want)
+ }
+ }
+}
+
+func TestEncoderSetMaxDynamicTableSize(t *testing.T) {
+ var buf bytes.Buffer
+ e := NewEncoder(&buf)
+ tests := []struct {
+ v uint32
+ wantUpdate bool
+ wantMinSize uint32
+ wantMaxSize uint32
+ }{
+ // Set new table size to 2048
+ {2048, true, 2048, 2048},
+
+ // Set new table size to 16384, but still limited to
+ // 4096
+ {16384, true, 2048, 4096},
+ }
+ for _, tt := range tests {
+ e.SetMaxDynamicTableSize(tt.v)
+ if got := e.tableSizeUpdate; tt.wantUpdate != got {
+ t.Errorf("e.tableSizeUpdate = %v; want %v", got, tt.wantUpdate)
+ }
+ if got := e.minSize; tt.wantMinSize != got {
+ t.Errorf("e.minSize = %v; want %v", got, tt.wantMinSize)
+ }
+ if got := e.dynTab.maxSize; tt.wantMaxSize != got {
+ t.Errorf("e.maxSize = %v; want %v", got, tt.wantMaxSize)
+ }
+ }
+}
+
+func TestEncoderSetMaxDynamicTableSizeLimit(t *testing.T) {
+ e := NewEncoder(nil)
+ // 4095 < initialHeaderTableSize means maxSize is truncated to
+ // 4095.
+ e.SetMaxDynamicTableSizeLimit(4095)
+ if got, want := e.dynTab.maxSize, uint32(4095); got != want {
+ t.Errorf("e.dynTab.maxSize = %v; want %v", got, want)
+ }
+ if got, want := e.maxSizeLimit, uint32(4095); got != want {
+ t.Errorf("e.maxSizeLimit = %v; want %v", got, want)
+ }
+ if got, want := e.tableSizeUpdate, true; got != want {
+ t.Errorf("e.tableSizeUpdate = %v; want %v", got, want)
+ }
+ // maxSize will be truncated to maxSizeLimit
+ e.SetMaxDynamicTableSize(16384)
+ if got, want := e.dynTab.maxSize, uint32(4095); got != want {
+ t.Errorf("e.dynTab.maxSize = %v; want %v", got, want)
+ }
+ // 8192 > current maxSizeLimit, so maxSize does not change.
+ e.SetMaxDynamicTableSizeLimit(8192)
+ if got, want := e.dynTab.maxSize, uint32(4095); got != want {
+ t.Errorf("e.dynTab.maxSize = %v; want %v", got, want)
+ }
+ if got, want := e.maxSizeLimit, uint32(8192); got != want {
+ t.Errorf("e.maxSizeLimit = %v; want %v", got, want)
+ }
+}
+
+func removeSpace(s string) string {
+ return strings.Replace(s, " ", "", -1)
+}
+
+func BenchmarkEncoderSearchTable(b *testing.B) {
+ e := NewEncoder(nil)
+
+ // A sample of possible header fields.
+ // This is not based on any actual data from HTTP/2 traces.
+ var possible []HeaderField
+ for _, f := range staticTable.ents {
+ if f.Value == "" {
+ possible = append(possible, f)
+ continue
+ }
+ // Generate 5 random values, except for cookie and set-cookie,
+ // which we know can have many values in practice.
+ num := 5
+ if f.Name == "cookie" || f.Name == "set-cookie" {
+ num = 25
+ }
+ for i := 0; i < num; i++ {
+ f.Value = fmt.Sprintf("%s-%d", f.Name, i)
+ possible = append(possible, f)
+ }
+ }
+ for k := 0; k < 10; k++ {
+ f := HeaderField{
+ Name: fmt.Sprintf("x-header-%d", k),
+ Sensitive: rand.Int()%2 == 0,
+ }
+ for i := 0; i < 5; i++ {
+ f.Value = fmt.Sprintf("%s-%d", f.Name, i)
+ possible = append(possible, f)
+ }
+ }
+
+ // Add a random sample to the dynamic table. This very loosely simulates
+ // a history of 100 requests with 20 header fields per request.
+ for r := 0; r < 100*20; r++ {
+ f := possible[rand.Int31n(int32(len(possible)))]
+ // Skip if this is in the staticTable verbatim.
+ if _, has := staticTable.search(f); !has {
+ e.dynTab.add(f)
+ }
+ }
+
+ b.ResetTimer()
+ for n := 0; n < b.N; n++ {
+ for _, f := range possible {
+ e.searchTable(f)
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/hpack/hpack.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/hpack/hpack.go
new file mode 100644
index 000000000..176644acd
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/hpack/hpack.go
@@ -0,0 +1,490 @@
+// Copyright 2014 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 hpack implements HPACK, a compression format for
+// efficiently representing HTTP header fields in the context of HTTP/2.
+//
+// See http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-09
+package hpack
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+)
+
+// A DecodingError is something the spec defines as a decoding error.
+type DecodingError struct {
+ Err error
+}
+
+func (de DecodingError) Error() string {
+ return fmt.Sprintf("decoding error: %v", de.Err)
+}
+
+// An InvalidIndexError is returned when an encoder references a table
+// entry before the static table or after the end of the dynamic table.
+type InvalidIndexError int
+
+func (e InvalidIndexError) Error() string {
+ return fmt.Sprintf("invalid indexed representation index %d", int(e))
+}
+
+// A HeaderField is a name-value pair. Both the name and value are
+// treated as opaque sequences of octets.
+type HeaderField struct {
+ Name, Value string
+
+ // Sensitive means that this header field should never be
+ // indexed.
+ Sensitive bool
+}
+
+// IsPseudo reports whether the header field is an http2 pseudo header.
+// That is, it reports whether it starts with a colon.
+// It is not otherwise guaranteed to be a valid pseudo header field,
+// though.
+func (hf HeaderField) IsPseudo() bool {
+ return len(hf.Name) != 0 && hf.Name[0] == ':'
+}
+
+func (hf HeaderField) String() string {
+ var suffix string
+ if hf.Sensitive {
+ suffix = " (sensitive)"
+ }
+ return fmt.Sprintf("header field %q = %q%s", hf.Name, hf.Value, suffix)
+}
+
+// Size returns the size of an entry per RFC 7541 section 4.1.
+func (hf HeaderField) Size() uint32 {
+ // http://http2.github.io/http2-spec/compression.html#rfc.section.4.1
+ // "The size of the dynamic table is the sum of the size of
+ // its entries. The size of an entry is the sum of its name's
+ // length in octets (as defined in Section 5.2), its value's
+ // length in octets (see Section 5.2), plus 32. The size of
+ // an entry is calculated using the length of the name and
+ // value without any Huffman encoding applied."
+
+ // This can overflow if somebody makes a large HeaderField
+ // Name and/or Value by hand, but we don't care, because that
+ // won't happen on the wire because the encoding doesn't allow
+ // it.
+ return uint32(len(hf.Name) + len(hf.Value) + 32)
+}
+
+// A Decoder is the decoding context for incremental processing of
+// header blocks.
+type Decoder struct {
+ dynTab dynamicTable
+ emit func(f HeaderField)
+
+ emitEnabled bool // whether calls to emit are enabled
+ maxStrLen int // 0 means unlimited
+
+ // buf is the unparsed buffer. It's only written to
+ // saveBuf if it was truncated in the middle of a header
+ // block. Because it's usually not owned, we can only
+ // process it under Write.
+ buf []byte // not owned; only valid during Write
+
+ // saveBuf is previous data passed to Write which we weren't able
+ // to fully parse before. Unlike buf, we own this data.
+ saveBuf bytes.Buffer
+}
+
+// NewDecoder returns a new decoder with the provided maximum dynamic
+// table size. The emitFunc will be called for each valid field
+// parsed, in the same goroutine as calls to Write, before Write returns.
+func NewDecoder(maxDynamicTableSize uint32, emitFunc func(f HeaderField)) *Decoder {
+ d := &Decoder{
+ emit: emitFunc,
+ emitEnabled: true,
+ }
+ d.dynTab.table.init()
+ d.dynTab.allowedMaxSize = maxDynamicTableSize
+ d.dynTab.setMaxSize(maxDynamicTableSize)
+ return d
+}
+
+// ErrStringLength is returned by Decoder.Write when the max string length
+// (as configured by Decoder.SetMaxStringLength) would be violated.
+var ErrStringLength = errors.New("hpack: string too long")
+
+// SetMaxStringLength sets the maximum size of a HeaderField name or
+// value string. If a string exceeds this length (even after any
+// decompression), Write will return ErrStringLength.
+// A value of 0 means unlimited and is the default from NewDecoder.
+func (d *Decoder) SetMaxStringLength(n int) {
+ d.maxStrLen = n
+}
+
+// SetEmitFunc changes the callback used when new header fields
+// are decoded.
+// It must be non-nil. It does not affect EmitEnabled.
+func (d *Decoder) SetEmitFunc(emitFunc func(f HeaderField)) {
+ d.emit = emitFunc
+}
+
+// SetEmitEnabled controls whether the emitFunc provided to NewDecoder
+// should be called. The default is true.
+//
+// This facility exists to let servers enforce MAX_HEADER_LIST_SIZE
+// while still decoding and keeping in-sync with decoder state, but
+// without doing unnecessary decompression or generating unnecessary
+// garbage for header fields past the limit.
+func (d *Decoder) SetEmitEnabled(v bool) { d.emitEnabled = v }
+
+// EmitEnabled reports whether calls to the emitFunc provided to NewDecoder
+// are currently enabled. The default is true.
+func (d *Decoder) EmitEnabled() bool { return d.emitEnabled }
+
+// TODO: add method *Decoder.Reset(maxSize, emitFunc) to let callers re-use Decoders and their
+// underlying buffers for garbage reasons.
+
+func (d *Decoder) SetMaxDynamicTableSize(v uint32) {
+ d.dynTab.setMaxSize(v)
+}
+
+// SetAllowedMaxDynamicTableSize sets the upper bound that the encoded
+// stream (via dynamic table size updates) may set the maximum size
+// to.
+func (d *Decoder) SetAllowedMaxDynamicTableSize(v uint32) {
+ d.dynTab.allowedMaxSize = v
+}
+
+type dynamicTable struct {
+ // http://http2.github.io/http2-spec/compression.html#rfc.section.2.3.2
+ table headerFieldTable
+ size uint32 // in bytes
+ maxSize uint32 // current maxSize
+ allowedMaxSize uint32 // maxSize may go up to this, inclusive
+}
+
+func (dt *dynamicTable) setMaxSize(v uint32) {
+ dt.maxSize = v
+ dt.evict()
+}
+
+func (dt *dynamicTable) add(f HeaderField) {
+ dt.table.addEntry(f)
+ dt.size += f.Size()
+ dt.evict()
+}
+
+// If we're too big, evict old stuff.
+func (dt *dynamicTable) evict() {
+ var n int
+ for dt.size > dt.maxSize && n < dt.table.len() {
+ dt.size -= dt.table.ents[n].Size()
+ n++
+ }
+ dt.table.evictOldest(n)
+}
+
+func (d *Decoder) maxTableIndex() int {
+ // This should never overflow. RFC 7540 Section 6.5.2 limits the size of
+ // the dynamic table to 2^32 bytes, where each entry will occupy more than
+ // one byte. Further, the staticTable has a fixed, small length.
+ return d.dynTab.table.len() + staticTable.len()
+}
+
+func (d *Decoder) at(i uint64) (hf HeaderField, ok bool) {
+ // See Section 2.3.3.
+ if i == 0 {
+ return
+ }
+ if i <= uint64(staticTable.len()) {
+ return staticTable.ents[i-1], true
+ }
+ if i > uint64(d.maxTableIndex()) {
+ return
+ }
+ // In the dynamic table, newer entries have lower indices.
+ // However, dt.ents[0] is the oldest entry. Hence, dt.ents is
+ // the reversed dynamic table.
+ dt := d.dynTab.table
+ return dt.ents[dt.len()-(int(i)-staticTable.len())], true
+}
+
+// Decode decodes an entire block.
+//
+// TODO: remove this method and make it incremental later? This is
+// easier for debugging now.
+func (d *Decoder) DecodeFull(p []byte) ([]HeaderField, error) {
+ var hf []HeaderField
+ saveFunc := d.emit
+ defer func() { d.emit = saveFunc }()
+ d.emit = func(f HeaderField) { hf = append(hf, f) }
+ if _, err := d.Write(p); err != nil {
+ return nil, err
+ }
+ if err := d.Close(); err != nil {
+ return nil, err
+ }
+ return hf, nil
+}
+
+func (d *Decoder) Close() error {
+ if d.saveBuf.Len() > 0 {
+ d.saveBuf.Reset()
+ return DecodingError{errors.New("truncated headers")}
+ }
+ return nil
+}
+
+func (d *Decoder) Write(p []byte) (n int, err error) {
+ if len(p) == 0 {
+ // Prevent state machine CPU attacks (making us redo
+ // work up to the point of finding out we don't have
+ // enough data)
+ return
+ }
+ // Only copy the data if we have to. Optimistically assume
+ // that p will contain a complete header block.
+ if d.saveBuf.Len() == 0 {
+ d.buf = p
+ } else {
+ d.saveBuf.Write(p)
+ d.buf = d.saveBuf.Bytes()
+ d.saveBuf.Reset()
+ }
+
+ for len(d.buf) > 0 {
+ err = d.parseHeaderFieldRepr()
+ if err == errNeedMore {
+ // Extra paranoia, making sure saveBuf won't
+ // get too large. All the varint and string
+ // reading code earlier should already catch
+ // overlong things and return ErrStringLength,
+ // but keep this as a last resort.
+ const varIntOverhead = 8 // conservative
+ if d.maxStrLen != 0 && int64(len(d.buf)) > 2*(int64(d.maxStrLen)+varIntOverhead) {
+ return 0, ErrStringLength
+ }
+ d.saveBuf.Write(d.buf)
+ return len(p), nil
+ }
+ if err != nil {
+ break
+ }
+ }
+ return len(p), err
+}
+
+// errNeedMore is an internal sentinel error value that means the
+// buffer is truncated and we need to read more data before we can
+// continue parsing.
+var errNeedMore = errors.New("need more data")
+
+type indexType int
+
+const (
+ indexedTrue indexType = iota
+ indexedFalse
+ indexedNever
+)
+
+func (v indexType) indexed() bool { return v == indexedTrue }
+func (v indexType) sensitive() bool { return v == indexedNever }
+
+// returns errNeedMore if there isn't enough data available.
+// any other error is fatal.
+// consumes d.buf iff it returns nil.
+// precondition: must be called with len(d.buf) > 0
+func (d *Decoder) parseHeaderFieldRepr() error {
+ b := d.buf[0]
+ switch {
+ case b&128 != 0:
+ // Indexed representation.
+ // High bit set?
+ // http://http2.github.io/http2-spec/compression.html#rfc.section.6.1
+ return d.parseFieldIndexed()
+ case b&192 == 64:
+ // 6.2.1 Literal Header Field with Incremental Indexing
+ // 0b10xxxxxx: top two bits are 10
+ // http://http2.github.io/http2-spec/compression.html#rfc.section.6.2.1
+ return d.parseFieldLiteral(6, indexedTrue)
+ case b&240 == 0:
+ // 6.2.2 Literal Header Field without Indexing
+ // 0b0000xxxx: top four bits are 0000
+ // http://http2.github.io/http2-spec/compression.html#rfc.section.6.2.2
+ return d.parseFieldLiteral(4, indexedFalse)
+ case b&240 == 16:
+ // 6.2.3 Literal Header Field never Indexed
+ // 0b0001xxxx: top four bits are 0001
+ // http://http2.github.io/http2-spec/compression.html#rfc.section.6.2.3
+ return d.parseFieldLiteral(4, indexedNever)
+ case b&224 == 32:
+ // 6.3 Dynamic Table Size Update
+ // Top three bits are '001'.
+ // http://http2.github.io/http2-spec/compression.html#rfc.section.6.3
+ return d.parseDynamicTableSizeUpdate()
+ }
+
+ return DecodingError{errors.New("invalid encoding")}
+}
+
+// (same invariants and behavior as parseHeaderFieldRepr)
+func (d *Decoder) parseFieldIndexed() error {
+ buf := d.buf
+ idx, buf, err := readVarInt(7, buf)
+ if err != nil {
+ return err
+ }
+ hf, ok := d.at(idx)
+ if !ok {
+ return DecodingError{InvalidIndexError(idx)}
+ }
+ d.buf = buf
+ return d.callEmit(HeaderField{Name: hf.Name, Value: hf.Value})
+}
+
+// (same invariants and behavior as parseHeaderFieldRepr)
+func (d *Decoder) parseFieldLiteral(n uint8, it indexType) error {
+ buf := d.buf
+ nameIdx, buf, err := readVarInt(n, buf)
+ if err != nil {
+ return err
+ }
+
+ var hf HeaderField
+ wantStr := d.emitEnabled || it.indexed()
+ if nameIdx > 0 {
+ ihf, ok := d.at(nameIdx)
+ if !ok {
+ return DecodingError{InvalidIndexError(nameIdx)}
+ }
+ hf.Name = ihf.Name
+ } else {
+ hf.Name, buf, err = d.readString(buf, wantStr)
+ if err != nil {
+ return err
+ }
+ }
+ hf.Value, buf, err = d.readString(buf, wantStr)
+ if err != nil {
+ return err
+ }
+ d.buf = buf
+ if it.indexed() {
+ d.dynTab.add(hf)
+ }
+ hf.Sensitive = it.sensitive()
+ return d.callEmit(hf)
+}
+
+func (d *Decoder) callEmit(hf HeaderField) error {
+ if d.maxStrLen != 0 {
+ if len(hf.Name) > d.maxStrLen || len(hf.Value) > d.maxStrLen {
+ return ErrStringLength
+ }
+ }
+ if d.emitEnabled {
+ d.emit(hf)
+ }
+ return nil
+}
+
+// (same invariants and behavior as parseHeaderFieldRepr)
+func (d *Decoder) parseDynamicTableSizeUpdate() error {
+ buf := d.buf
+ size, buf, err := readVarInt(5, buf)
+ if err != nil {
+ return err
+ }
+ if size > uint64(d.dynTab.allowedMaxSize) {
+ return DecodingError{errors.New("dynamic table size update too large")}
+ }
+ d.dynTab.setMaxSize(uint32(size))
+ d.buf = buf
+ return nil
+}
+
+var errVarintOverflow = DecodingError{errors.New("varint integer overflow")}
+
+// readVarInt reads an unsigned variable length integer off the
+// beginning of p. n is the parameter as described in
+// http://http2.github.io/http2-spec/compression.html#rfc.section.5.1.
+//
+// n must always be between 1 and 8.
+//
+// The returned remain buffer is either a smaller suffix of p, or err != nil.
+// The error is errNeedMore if p doesn't contain a complete integer.
+func readVarInt(n byte, p []byte) (i uint64, remain []byte, err error) {
+ if n < 1 || n > 8 {
+ panic("bad n")
+ }
+ if len(p) == 0 {
+ return 0, p, errNeedMore
+ }
+ i = uint64(p[0])
+ if n < 8 {
+ i &= (1 << uint64(n)) - 1
+ }
+ if i < (1<<uint64(n))-1 {
+ return i, p[1:], nil
+ }
+
+ origP := p
+ p = p[1:]
+ var m uint64
+ for len(p) > 0 {
+ b := p[0]
+ p = p[1:]
+ i += uint64(b&127) << m
+ if b&128 == 0 {
+ return i, p, nil
+ }
+ m += 7
+ if m >= 63 { // TODO: proper overflow check. making this up.
+ return 0, origP, errVarintOverflow
+ }
+ }
+ return 0, origP, errNeedMore
+}
+
+// readString decodes an hpack string from p.
+//
+// wantStr is whether s will be used. If false, decompression and
+// []byte->string garbage are skipped if s will be ignored
+// anyway. This does mean that huffman decoding errors for non-indexed
+// strings past the MAX_HEADER_LIST_SIZE are ignored, but the server
+// is returning an error anyway, and because they're not indexed, the error
+// won't affect the decoding state.
+func (d *Decoder) readString(p []byte, wantStr bool) (s string, remain []byte, err error) {
+ if len(p) == 0 {
+ return "", p, errNeedMore
+ }
+ isHuff := p[0]&128 != 0
+ strLen, p, err := readVarInt(7, p)
+ if err != nil {
+ return "", p, err
+ }
+ if d.maxStrLen != 0 && strLen > uint64(d.maxStrLen) {
+ return "", nil, ErrStringLength
+ }
+ if uint64(len(p)) < strLen {
+ return "", p, errNeedMore
+ }
+ if !isHuff {
+ if wantStr {
+ s = string(p[:strLen])
+ }
+ return s, p[strLen:], nil
+ }
+
+ if wantStr {
+ buf := bufPool.Get().(*bytes.Buffer)
+ buf.Reset() // don't trust others
+ defer bufPool.Put(buf)
+ if err := huffmanDecode(buf, d.maxStrLen, p[:strLen]); err != nil {
+ buf.Reset()
+ return "", nil, err
+ }
+ s = buf.String()
+ buf.Reset() // be nice to GC
+ }
+ return s, p[strLen:], nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/hpack/hpack_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/hpack/hpack_test.go
new file mode 100644
index 000000000..bc7f47678
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/hpack/hpack_test.go
@@ -0,0 +1,722 @@
+// Copyright 2014 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 hpack
+
+import (
+ "bytes"
+ "encoding/hex"
+ "fmt"
+ "math/rand"
+ "reflect"
+ "strings"
+ "testing"
+ "time"
+)
+
+func (d *Decoder) mustAt(idx int) HeaderField {
+ if hf, ok := d.at(uint64(idx)); !ok {
+ panic(fmt.Sprintf("bogus index %d", idx))
+ } else {
+ return hf
+ }
+}
+
+func TestDynamicTableAt(t *testing.T) {
+ d := NewDecoder(4096, nil)
+ at := d.mustAt
+ if got, want := at(2), (pair(":method", "GET")); got != want {
+ t.Errorf("at(2) = %v; want %v", got, want)
+ }
+ d.dynTab.add(pair("foo", "bar"))
+ d.dynTab.add(pair("blake", "miz"))
+ if got, want := at(staticTable.len()+1), (pair("blake", "miz")); got != want {
+ t.Errorf("at(dyn 1) = %v; want %v", got, want)
+ }
+ if got, want := at(staticTable.len()+2), (pair("foo", "bar")); got != want {
+ t.Errorf("at(dyn 2) = %v; want %v", got, want)
+ }
+ if got, want := at(3), (pair(":method", "POST")); got != want {
+ t.Errorf("at(3) = %v; want %v", got, want)
+ }
+}
+
+func TestDynamicTableSizeEvict(t *testing.T) {
+ d := NewDecoder(4096, nil)
+ if want := uint32(0); d.dynTab.size != want {
+ t.Fatalf("size = %d; want %d", d.dynTab.size, want)
+ }
+ add := d.dynTab.add
+ add(pair("blake", "eats pizza"))
+ if want := uint32(15 + 32); d.dynTab.size != want {
+ t.Fatalf("after pizza, size = %d; want %d", d.dynTab.size, want)
+ }
+ add(pair("foo", "bar"))
+ if want := uint32(15 + 32 + 6 + 32); d.dynTab.size != want {
+ t.Fatalf("after foo bar, size = %d; want %d", d.dynTab.size, want)
+ }
+ d.dynTab.setMaxSize(15 + 32 + 1 /* slop */)
+ if want := uint32(6 + 32); d.dynTab.size != want {
+ t.Fatalf("after setMaxSize, size = %d; want %d", d.dynTab.size, want)
+ }
+ if got, want := d.mustAt(staticTable.len()+1), (pair("foo", "bar")); got != want {
+ t.Errorf("at(dyn 1) = %v; want %v", got, want)
+ }
+ add(pair("long", strings.Repeat("x", 500)))
+ if want := uint32(0); d.dynTab.size != want {
+ t.Fatalf("after big one, size = %d; want %d", d.dynTab.size, want)
+ }
+}
+
+func TestDecoderDecode(t *testing.T) {
+ tests := []struct {
+ name string
+ in []byte
+ want []HeaderField
+ wantDynTab []HeaderField // newest entry first
+ }{
+ // C.2.1 Literal Header Field with Indexing
+ // http://http2.github.io/http2-spec/compression.html#rfc.section.C.2.1
+ {"C.2.1", dehex("400a 6375 7374 6f6d 2d6b 6579 0d63 7573 746f 6d2d 6865 6164 6572"),
+ []HeaderField{pair("custom-key", "custom-header")},
+ []HeaderField{pair("custom-key", "custom-header")},
+ },
+
+ // C.2.2 Literal Header Field without Indexing
+ // http://http2.github.io/http2-spec/compression.html#rfc.section.C.2.2
+ {"C.2.2", dehex("040c 2f73 616d 706c 652f 7061 7468"),
+ []HeaderField{pair(":path", "/sample/path")},
+ []HeaderField{}},
+
+ // C.2.3 Literal Header Field never Indexed
+ // http://http2.github.io/http2-spec/compression.html#rfc.section.C.2.3
+ {"C.2.3", dehex("1008 7061 7373 776f 7264 0673 6563 7265 74"),
+ []HeaderField{{"password", "secret", true}},
+ []HeaderField{}},
+
+ // C.2.4 Indexed Header Field
+ // http://http2.github.io/http2-spec/compression.html#rfc.section.C.2.4
+ {"C.2.4", []byte("\x82"),
+ []HeaderField{pair(":method", "GET")},
+ []HeaderField{}},
+ }
+ for _, tt := range tests {
+ d := NewDecoder(4096, nil)
+ hf, err := d.DecodeFull(tt.in)
+ if err != nil {
+ t.Errorf("%s: %v", tt.name, err)
+ continue
+ }
+ if !reflect.DeepEqual(hf, tt.want) {
+ t.Errorf("%s: Got %v; want %v", tt.name, hf, tt.want)
+ }
+ gotDynTab := d.dynTab.reverseCopy()
+ if !reflect.DeepEqual(gotDynTab, tt.wantDynTab) {
+ t.Errorf("%s: dynamic table after = %v; want %v", tt.name, gotDynTab, tt.wantDynTab)
+ }
+ }
+}
+
+func (dt *dynamicTable) reverseCopy() (hf []HeaderField) {
+ hf = make([]HeaderField, len(dt.table.ents))
+ for i := range hf {
+ hf[i] = dt.table.ents[len(dt.table.ents)-1-i]
+ }
+ return
+}
+
+type encAndWant struct {
+ enc []byte
+ want []HeaderField
+ wantDynTab []HeaderField
+ wantDynSize uint32
+}
+
+// C.3 Request Examples without Huffman Coding
+// http://http2.github.io/http2-spec/compression.html#rfc.section.C.3
+func TestDecodeC3_NoHuffman(t *testing.T) {
+ testDecodeSeries(t, 4096, []encAndWant{
+ {dehex("8286 8441 0f77 7777 2e65 7861 6d70 6c65 2e63 6f6d"),
+ []HeaderField{
+ pair(":method", "GET"),
+ pair(":scheme", "http"),
+ pair(":path", "/"),
+ pair(":authority", "www.example.com"),
+ },
+ []HeaderField{
+ pair(":authority", "www.example.com"),
+ },
+ 57,
+ },
+ {dehex("8286 84be 5808 6e6f 2d63 6163 6865"),
+ []HeaderField{
+ pair(":method", "GET"),
+ pair(":scheme", "http"),
+ pair(":path", "/"),
+ pair(":authority", "www.example.com"),
+ pair("cache-control", "no-cache"),
+ },
+ []HeaderField{
+ pair("cache-control", "no-cache"),
+ pair(":authority", "www.example.com"),
+ },
+ 110,
+ },
+ {dehex("8287 85bf 400a 6375 7374 6f6d 2d6b 6579 0c63 7573 746f 6d2d 7661 6c75 65"),
+ []HeaderField{
+ pair(":method", "GET"),
+ pair(":scheme", "https"),
+ pair(":path", "/index.html"),
+ pair(":authority", "www.example.com"),
+ pair("custom-key", "custom-value"),
+ },
+ []HeaderField{
+ pair("custom-key", "custom-value"),
+ pair("cache-control", "no-cache"),
+ pair(":authority", "www.example.com"),
+ },
+ 164,
+ },
+ })
+}
+
+// C.4 Request Examples with Huffman Coding
+// http://http2.github.io/http2-spec/compression.html#rfc.section.C.4
+func TestDecodeC4_Huffman(t *testing.T) {
+ testDecodeSeries(t, 4096, []encAndWant{
+ {dehex("8286 8441 8cf1 e3c2 e5f2 3a6b a0ab 90f4 ff"),
+ []HeaderField{
+ pair(":method", "GET"),
+ pair(":scheme", "http"),
+ pair(":path", "/"),
+ pair(":authority", "www.example.com"),
+ },
+ []HeaderField{
+ pair(":authority", "www.example.com"),
+ },
+ 57,
+ },
+ {dehex("8286 84be 5886 a8eb 1064 9cbf"),
+ []HeaderField{
+ pair(":method", "GET"),
+ pair(":scheme", "http"),
+ pair(":path", "/"),
+ pair(":authority", "www.example.com"),
+ pair("cache-control", "no-cache"),
+ },
+ []HeaderField{
+ pair("cache-control", "no-cache"),
+ pair(":authority", "www.example.com"),
+ },
+ 110,
+ },
+ {dehex("8287 85bf 4088 25a8 49e9 5ba9 7d7f 8925 a849 e95b b8e8 b4bf"),
+ []HeaderField{
+ pair(":method", "GET"),
+ pair(":scheme", "https"),
+ pair(":path", "/index.html"),
+ pair(":authority", "www.example.com"),
+ pair("custom-key", "custom-value"),
+ },
+ []HeaderField{
+ pair("custom-key", "custom-value"),
+ pair("cache-control", "no-cache"),
+ pair(":authority", "www.example.com"),
+ },
+ 164,
+ },
+ })
+}
+
+// http://http2.github.io/http2-spec/compression.html#rfc.section.C.5
+// "This section shows several consecutive header lists, corresponding
+// to HTTP responses, on the same connection. The HTTP/2 setting
+// parameter SETTINGS_HEADER_TABLE_SIZE is set to the value of 256
+// octets, causing some evictions to occur."
+func TestDecodeC5_ResponsesNoHuff(t *testing.T) {
+ testDecodeSeries(t, 256, []encAndWant{
+ {dehex(`
+4803 3330 3258 0770 7269 7661 7465 611d
+4d6f 6e2c 2032 3120 4f63 7420 3230 3133
+2032 303a 3133 3a32 3120 474d 546e 1768
+7474 7073 3a2f 2f77 7777 2e65 7861 6d70
+6c65 2e63 6f6d
+`),
+ []HeaderField{
+ pair(":status", "302"),
+ pair("cache-control", "private"),
+ pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
+ pair("location", "https://www.example.com"),
+ },
+ []HeaderField{
+ pair("location", "https://www.example.com"),
+ pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
+ pair("cache-control", "private"),
+ pair(":status", "302"),
+ },
+ 222,
+ },
+ {dehex("4803 3330 37c1 c0bf"),
+ []HeaderField{
+ pair(":status", "307"),
+ pair("cache-control", "private"),
+ pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
+ pair("location", "https://www.example.com"),
+ },
+ []HeaderField{
+ pair(":status", "307"),
+ pair("location", "https://www.example.com"),
+ pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
+ pair("cache-control", "private"),
+ },
+ 222,
+ },
+ {dehex(`
+88c1 611d 4d6f 6e2c 2032 3120 4f63 7420
+3230 3133 2032 303a 3133 3a32 3220 474d
+54c0 5a04 677a 6970 7738 666f 6f3d 4153
+444a 4b48 514b 425a 584f 5157 454f 5049
+5541 5851 5745 4f49 553b 206d 6178 2d61
+6765 3d33 3630 303b 2076 6572 7369 6f6e
+3d31
+`),
+ []HeaderField{
+ pair(":status", "200"),
+ pair("cache-control", "private"),
+ pair("date", "Mon, 21 Oct 2013 20:13:22 GMT"),
+ pair("location", "https://www.example.com"),
+ pair("content-encoding", "gzip"),
+ pair("set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"),
+ },
+ []HeaderField{
+ pair("set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"),
+ pair("content-encoding", "gzip"),
+ pair("date", "Mon, 21 Oct 2013 20:13:22 GMT"),
+ },
+ 215,
+ },
+ })
+}
+
+// http://http2.github.io/http2-spec/compression.html#rfc.section.C.6
+// "This section shows the same examples as the previous section, but
+// using Huffman encoding for the literal values. The HTTP/2 setting
+// parameter SETTINGS_HEADER_TABLE_SIZE is set to the value of 256
+// octets, causing some evictions to occur. The eviction mechanism
+// uses the length of the decoded literal values, so the same
+// evictions occurs as in the previous section."
+func TestDecodeC6_ResponsesHuffman(t *testing.T) {
+ testDecodeSeries(t, 256, []encAndWant{
+ {dehex(`
+4882 6402 5885 aec3 771a 4b61 96d0 7abe
+9410 54d4 44a8 2005 9504 0b81 66e0 82a6
+2d1b ff6e 919d 29ad 1718 63c7 8f0b 97c8
+e9ae 82ae 43d3
+`),
+ []HeaderField{
+ pair(":status", "302"),
+ pair("cache-control", "private"),
+ pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
+ pair("location", "https://www.example.com"),
+ },
+ []HeaderField{
+ pair("location", "https://www.example.com"),
+ pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
+ pair("cache-control", "private"),
+ pair(":status", "302"),
+ },
+ 222,
+ },
+ {dehex("4883 640e ffc1 c0bf"),
+ []HeaderField{
+ pair(":status", "307"),
+ pair("cache-control", "private"),
+ pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
+ pair("location", "https://www.example.com"),
+ },
+ []HeaderField{
+ pair(":status", "307"),
+ pair("location", "https://www.example.com"),
+ pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
+ pair("cache-control", "private"),
+ },
+ 222,
+ },
+ {dehex(`
+88c1 6196 d07a be94 1054 d444 a820 0595
+040b 8166 e084 a62d 1bff c05a 839b d9ab
+77ad 94e7 821d d7f2 e6c7 b335 dfdf cd5b
+3960 d5af 2708 7f36 72c1 ab27 0fb5 291f
+9587 3160 65c0 03ed 4ee5 b106 3d50 07
+`),
+ []HeaderField{
+ pair(":status", "200"),
+ pair("cache-control", "private"),
+ pair("date", "Mon, 21 Oct 2013 20:13:22 GMT"),
+ pair("location", "https://www.example.com"),
+ pair("content-encoding", "gzip"),
+ pair("set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"),
+ },
+ []HeaderField{
+ pair("set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"),
+ pair("content-encoding", "gzip"),
+ pair("date", "Mon, 21 Oct 2013 20:13:22 GMT"),
+ },
+ 215,
+ },
+ })
+}
+
+func testDecodeSeries(t *testing.T, size uint32, steps []encAndWant) {
+ d := NewDecoder(size, nil)
+ for i, step := range steps {
+ hf, err := d.DecodeFull(step.enc)
+ if err != nil {
+ t.Fatalf("Error at step index %d: %v", i, err)
+ }
+ if !reflect.DeepEqual(hf, step.want) {
+ t.Fatalf("At step index %d: Got headers %v; want %v", i, hf, step.want)
+ }
+ gotDynTab := d.dynTab.reverseCopy()
+ if !reflect.DeepEqual(gotDynTab, step.wantDynTab) {
+ t.Errorf("After step index %d, dynamic table = %v; want %v", i, gotDynTab, step.wantDynTab)
+ }
+ if d.dynTab.size != step.wantDynSize {
+ t.Errorf("After step index %d, dynamic table size = %v; want %v", i, d.dynTab.size, step.wantDynSize)
+ }
+ }
+}
+
+func TestHuffmanDecodeExcessPadding(t *testing.T) {
+ tests := [][]byte{
+ {0xff}, // Padding Exceeds 7 bits
+ {0x1f, 0xff}, // {"a", 1 byte excess padding}
+ {0x1f, 0xff, 0xff}, // {"a", 2 byte excess padding}
+ {0x1f, 0xff, 0xff, 0xff}, // {"a", 3 byte excess padding}
+ {0xff, 0x9f, 0xff, 0xff, 0xff}, // {"a", 29 bit excess padding}
+ {'R', 0xbc, '0', 0xff, 0xff, 0xff, 0xff}, // Padding ends on partial symbol.
+ }
+ for i, in := range tests {
+ var buf bytes.Buffer
+ if _, err := HuffmanDecode(&buf, in); err != ErrInvalidHuffman {
+ t.Errorf("test-%d: decode(%q) = %v; want ErrInvalidHuffman", i, in, err)
+ }
+ }
+}
+
+func TestHuffmanDecodeEOS(t *testing.T) {
+ in := []byte{0xff, 0xff, 0xff, 0xff, 0xfc} // {EOS, "?"}
+ var buf bytes.Buffer
+ if _, err := HuffmanDecode(&buf, in); err != ErrInvalidHuffman {
+ t.Errorf("error = %v; want ErrInvalidHuffman", err)
+ }
+}
+
+func TestHuffmanDecodeMaxLengthOnTrailingByte(t *testing.T) {
+ in := []byte{0x00, 0x01} // {"0", "0", "0"}
+ var buf bytes.Buffer
+ if err := huffmanDecode(&buf, 2, in); err != ErrStringLength {
+ t.Errorf("error = %v; want ErrStringLength", err)
+ }
+}
+
+func TestHuffmanDecodeCorruptPadding(t *testing.T) {
+ in := []byte{0x00}
+ var buf bytes.Buffer
+ if _, err := HuffmanDecode(&buf, in); err != ErrInvalidHuffman {
+ t.Errorf("error = %v; want ErrInvalidHuffman", err)
+ }
+}
+
+func TestHuffmanDecode(t *testing.T) {
+ tests := []struct {
+ inHex, want string
+ }{
+ {"f1e3 c2e5 f23a 6ba0 ab90 f4ff", "www.example.com"},
+ {"a8eb 1064 9cbf", "no-cache"},
+ {"25a8 49e9 5ba9 7d7f", "custom-key"},
+ {"25a8 49e9 5bb8 e8b4 bf", "custom-value"},
+ {"6402", "302"},
+ {"aec3 771a 4b", "private"},
+ {"d07a be94 1054 d444 a820 0595 040b 8166 e082 a62d 1bff", "Mon, 21 Oct 2013 20:13:21 GMT"},
+ {"9d29 ad17 1863 c78f 0b97 c8e9 ae82 ae43 d3", "https://www.example.com"},
+ {"9bd9 ab", "gzip"},
+ {"94e7 821d d7f2 e6c7 b335 dfdf cd5b 3960 d5af 2708 7f36 72c1 ab27 0fb5 291f 9587 3160 65c0 03ed 4ee5 b106 3d50 07",
+ "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"},
+ }
+ for i, tt := range tests {
+ var buf bytes.Buffer
+ in, err := hex.DecodeString(strings.Replace(tt.inHex, " ", "", -1))
+ if err != nil {
+ t.Errorf("%d. hex input error: %v", i, err)
+ continue
+ }
+ if _, err := HuffmanDecode(&buf, in); err != nil {
+ t.Errorf("%d. decode error: %v", i, err)
+ continue
+ }
+ if got := buf.String(); tt.want != got {
+ t.Errorf("%d. decode = %q; want %q", i, got, tt.want)
+ }
+ }
+}
+
+func TestAppendHuffmanString(t *testing.T) {
+ tests := []struct {
+ in, want string
+ }{
+ {"www.example.com", "f1e3 c2e5 f23a 6ba0 ab90 f4ff"},
+ {"no-cache", "a8eb 1064 9cbf"},
+ {"custom-key", "25a8 49e9 5ba9 7d7f"},
+ {"custom-value", "25a8 49e9 5bb8 e8b4 bf"},
+ {"302", "6402"},
+ {"private", "aec3 771a 4b"},
+ {"Mon, 21 Oct 2013 20:13:21 GMT", "d07a be94 1054 d444 a820 0595 040b 8166 e082 a62d 1bff"},
+ {"https://www.example.com", "9d29 ad17 1863 c78f 0b97 c8e9 ae82 ae43 d3"},
+ {"gzip", "9bd9 ab"},
+ {"foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1",
+ "94e7 821d d7f2 e6c7 b335 dfdf cd5b 3960 d5af 2708 7f36 72c1 ab27 0fb5 291f 9587 3160 65c0 03ed 4ee5 b106 3d50 07"},
+ }
+ for i, tt := range tests {
+ buf := []byte{}
+ want := strings.Replace(tt.want, " ", "", -1)
+ buf = AppendHuffmanString(buf, tt.in)
+ if got := hex.EncodeToString(buf); want != got {
+ t.Errorf("%d. encode = %q; want %q", i, got, want)
+ }
+ }
+}
+
+func TestHuffmanMaxStrLen(t *testing.T) {
+ const msg = "Some string"
+ huff := AppendHuffmanString(nil, msg)
+
+ testGood := func(max int) {
+ var out bytes.Buffer
+ if err := huffmanDecode(&out, max, huff); err != nil {
+ t.Errorf("For maxLen=%d, unexpected error: %v", max, err)
+ }
+ if out.String() != msg {
+ t.Errorf("For maxLen=%d, out = %q; want %q", max, out.String(), msg)
+ }
+ }
+ testGood(0)
+ testGood(len(msg))
+ testGood(len(msg) + 1)
+
+ var out bytes.Buffer
+ if err := huffmanDecode(&out, len(msg)-1, huff); err != ErrStringLength {
+ t.Errorf("err = %v; want ErrStringLength", err)
+ }
+}
+
+func TestHuffmanRoundtripStress(t *testing.T) {
+ const Len = 50 // of uncompressed string
+ input := make([]byte, Len)
+ var output bytes.Buffer
+ var huff []byte
+
+ n := 5000
+ if testing.Short() {
+ n = 100
+ }
+ seed := time.Now().UnixNano()
+ t.Logf("Seed = %v", seed)
+ src := rand.New(rand.NewSource(seed))
+ var encSize int64
+ for i := 0; i < n; i++ {
+ for l := range input {
+ input[l] = byte(src.Intn(256))
+ }
+ huff = AppendHuffmanString(huff[:0], string(input))
+ encSize += int64(len(huff))
+ output.Reset()
+ if err := huffmanDecode(&output, 0, huff); err != nil {
+ t.Errorf("Failed to decode %q -> %q -> error %v", input, huff, err)
+ continue
+ }
+ if !bytes.Equal(output.Bytes(), input) {
+ t.Errorf("Roundtrip failure on %q -> %q -> %q", input, huff, output.Bytes())
+ }
+ }
+ t.Logf("Compressed size of original: %0.02f%% (%v -> %v)", 100*(float64(encSize)/(Len*float64(n))), Len*n, encSize)
+}
+
+func TestHuffmanDecodeFuzz(t *testing.T) {
+ const Len = 50 // of compressed
+ var buf, zbuf bytes.Buffer
+
+ n := 5000
+ if testing.Short() {
+ n = 100
+ }
+ seed := time.Now().UnixNano()
+ t.Logf("Seed = %v", seed)
+ src := rand.New(rand.NewSource(seed))
+ numFail := 0
+ for i := 0; i < n; i++ {
+ zbuf.Reset()
+ if i == 0 {
+ // Start with at least one invalid one.
+ zbuf.WriteString("00\x91\xff\xff\xff\xff\xc8")
+ } else {
+ for l := 0; l < Len; l++ {
+ zbuf.WriteByte(byte(src.Intn(256)))
+ }
+ }
+
+ buf.Reset()
+ if err := huffmanDecode(&buf, 0, zbuf.Bytes()); err != nil {
+ if err == ErrInvalidHuffman {
+ numFail++
+ continue
+ }
+ t.Errorf("Failed to decode %q: %v", zbuf.Bytes(), err)
+ continue
+ }
+ }
+ t.Logf("%0.02f%% are invalid (%d / %d)", 100*float64(numFail)/float64(n), numFail, n)
+ if numFail < 1 {
+ t.Error("expected at least one invalid huffman encoding (test starts with one)")
+ }
+}
+
+func TestReadVarInt(t *testing.T) {
+ type res struct {
+ i uint64
+ consumed int
+ err error
+ }
+ tests := []struct {
+ n byte
+ p []byte
+ want res
+ }{
+ // Fits in a byte:
+ {1, []byte{0}, res{0, 1, nil}},
+ {2, []byte{2}, res{2, 1, nil}},
+ {3, []byte{6}, res{6, 1, nil}},
+ {4, []byte{14}, res{14, 1, nil}},
+ {5, []byte{30}, res{30, 1, nil}},
+ {6, []byte{62}, res{62, 1, nil}},
+ {7, []byte{126}, res{126, 1, nil}},
+ {8, []byte{254}, res{254, 1, nil}},
+
+ // Doesn't fit in a byte:
+ {1, []byte{1}, res{0, 0, errNeedMore}},
+ {2, []byte{3}, res{0, 0, errNeedMore}},
+ {3, []byte{7}, res{0, 0, errNeedMore}},
+ {4, []byte{15}, res{0, 0, errNeedMore}},
+ {5, []byte{31}, res{0, 0, errNeedMore}},
+ {6, []byte{63}, res{0, 0, errNeedMore}},
+ {7, []byte{127}, res{0, 0, errNeedMore}},
+ {8, []byte{255}, res{0, 0, errNeedMore}},
+
+ // Ignoring top bits:
+ {5, []byte{255, 154, 10}, res{1337, 3, nil}}, // high dummy three bits: 111
+ {5, []byte{159, 154, 10}, res{1337, 3, nil}}, // high dummy three bits: 100
+ {5, []byte{191, 154, 10}, res{1337, 3, nil}}, // high dummy three bits: 101
+
+ // Extra byte:
+ {5, []byte{191, 154, 10, 2}, res{1337, 3, nil}}, // extra byte
+
+ // Short a byte:
+ {5, []byte{191, 154}, res{0, 0, errNeedMore}},
+
+ // integer overflow:
+ {1, []byte{255, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128}, res{0, 0, errVarintOverflow}},
+ }
+ for _, tt := range tests {
+ i, remain, err := readVarInt(tt.n, tt.p)
+ consumed := len(tt.p) - len(remain)
+ got := res{i, consumed, err}
+ if got != tt.want {
+ t.Errorf("readVarInt(%d, %v ~ %x) = %+v; want %+v", tt.n, tt.p, tt.p, got, tt.want)
+ }
+ }
+}
+
+// Fuzz crash, originally reported at https://github.com/bradfitz/http2/issues/56
+func TestHuffmanFuzzCrash(t *testing.T) {
+ got, err := HuffmanDecodeToString([]byte("00\x91\xff\xff\xff\xff\xc8"))
+ if got != "" {
+ t.Errorf("Got %q; want empty string", got)
+ }
+ if err != ErrInvalidHuffman {
+ t.Errorf("Err = %v; want ErrInvalidHuffman", err)
+ }
+}
+
+func pair(name, value string) HeaderField {
+ return HeaderField{Name: name, Value: value}
+}
+
+func dehex(s string) []byte {
+ s = strings.Replace(s, " ", "", -1)
+ s = strings.Replace(s, "\n", "", -1)
+ b, err := hex.DecodeString(s)
+ if err != nil {
+ panic(err)
+ }
+ return b
+}
+
+func TestEmitEnabled(t *testing.T) {
+ var buf bytes.Buffer
+ enc := NewEncoder(&buf)
+ enc.WriteField(HeaderField{Name: "foo", Value: "bar"})
+ enc.WriteField(HeaderField{Name: "foo", Value: "bar"})
+
+ numCallback := 0
+ var dec *Decoder
+ dec = NewDecoder(8<<20, func(HeaderField) {
+ numCallback++
+ dec.SetEmitEnabled(false)
+ })
+ if !dec.EmitEnabled() {
+ t.Errorf("initial emit enabled = false; want true")
+ }
+ if _, err := dec.Write(buf.Bytes()); err != nil {
+ t.Error(err)
+ }
+ if numCallback != 1 {
+ t.Errorf("num callbacks = %d; want 1", numCallback)
+ }
+ if dec.EmitEnabled() {
+ t.Errorf("emit enabled = true; want false")
+ }
+}
+
+func TestSaveBufLimit(t *testing.T) {
+ const maxStr = 1 << 10
+ var got []HeaderField
+ dec := NewDecoder(initialHeaderTableSize, func(hf HeaderField) {
+ got = append(got, hf)
+ })
+ dec.SetMaxStringLength(maxStr)
+ var frag []byte
+ frag = append(frag[:0], encodeTypeByte(false, false))
+ frag = appendVarInt(frag, 7, 3)
+ frag = append(frag, "foo"...)
+ frag = appendVarInt(frag, 7, 3)
+ frag = append(frag, "bar"...)
+
+ if _, err := dec.Write(frag); err != nil {
+ t.Fatal(err)
+ }
+
+ want := []HeaderField{{Name: "foo", Value: "bar"}}
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("After small writes, got %v; want %v", got, want)
+ }
+
+ frag = append(frag[:0], encodeTypeByte(false, false))
+ frag = appendVarInt(frag, 7, maxStr*3)
+ frag = append(frag, make([]byte, maxStr*3)...)
+
+ _, err := dec.Write(frag)
+ if err != ErrStringLength {
+ t.Fatalf("Write error = %v; want ErrStringLength", err)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/hpack/huffman.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/hpack/huffman.go
new file mode 100644
index 000000000..8850e3946
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/hpack/huffman.go
@@ -0,0 +1,212 @@
+// Copyright 2014 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 hpack
+
+import (
+ "bytes"
+ "errors"
+ "io"
+ "sync"
+)
+
+var bufPool = sync.Pool{
+ New: func() interface{} { return new(bytes.Buffer) },
+}
+
+// HuffmanDecode decodes the string in v and writes the expanded
+// result to w, returning the number of bytes written to w and the
+// Write call's return value. At most one Write call is made.
+func HuffmanDecode(w io.Writer, v []byte) (int, error) {
+ buf := bufPool.Get().(*bytes.Buffer)
+ buf.Reset()
+ defer bufPool.Put(buf)
+ if err := huffmanDecode(buf, 0, v); err != nil {
+ return 0, err
+ }
+ return w.Write(buf.Bytes())
+}
+
+// HuffmanDecodeToString decodes the string in v.
+func HuffmanDecodeToString(v []byte) (string, error) {
+ buf := bufPool.Get().(*bytes.Buffer)
+ buf.Reset()
+ defer bufPool.Put(buf)
+ if err := huffmanDecode(buf, 0, v); err != nil {
+ return "", err
+ }
+ return buf.String(), nil
+}
+
+// ErrInvalidHuffman is returned for errors found decoding
+// Huffman-encoded strings.
+var ErrInvalidHuffman = errors.New("hpack: invalid Huffman-encoded data")
+
+// huffmanDecode decodes v to buf.
+// If maxLen is greater than 0, attempts to write more to buf than
+// maxLen bytes will return ErrStringLength.
+func huffmanDecode(buf *bytes.Buffer, maxLen int, v []byte) error {
+ n := rootHuffmanNode
+ // cur is the bit buffer that has not been fed into n.
+ // cbits is the number of low order bits in cur that are valid.
+ // sbits is the number of bits of the symbol prefix being decoded.
+ cur, cbits, sbits := uint(0), uint8(0), uint8(0)
+ for _, b := range v {
+ cur = cur<<8 | uint(b)
+ cbits += 8
+ sbits += 8
+ for cbits >= 8 {
+ idx := byte(cur >> (cbits - 8))
+ n = n.children[idx]
+ if n == nil {
+ return ErrInvalidHuffman
+ }
+ if n.children == nil {
+ if maxLen != 0 && buf.Len() == maxLen {
+ return ErrStringLength
+ }
+ buf.WriteByte(n.sym)
+ cbits -= n.codeLen
+ n = rootHuffmanNode
+ sbits = cbits
+ } else {
+ cbits -= 8
+ }
+ }
+ }
+ for cbits > 0 {
+ n = n.children[byte(cur<<(8-cbits))]
+ if n == nil {
+ return ErrInvalidHuffman
+ }
+ if n.children != nil || n.codeLen > cbits {
+ break
+ }
+ if maxLen != 0 && buf.Len() == maxLen {
+ return ErrStringLength
+ }
+ buf.WriteByte(n.sym)
+ cbits -= n.codeLen
+ n = rootHuffmanNode
+ sbits = cbits
+ }
+ if sbits > 7 {
+ // Either there was an incomplete symbol, or overlong padding.
+ // Both are decoding errors per RFC 7541 section 5.2.
+ return ErrInvalidHuffman
+ }
+ if mask := uint(1<<cbits - 1); cur&mask != mask {
+ // Trailing bits must be a prefix of EOS per RFC 7541 section 5.2.
+ return ErrInvalidHuffman
+ }
+
+ return nil
+}
+
+type node struct {
+ // children is non-nil for internal nodes
+ children []*node
+
+ // The following are only valid if children is nil:
+ codeLen uint8 // number of bits that led to the output of sym
+ sym byte // output symbol
+}
+
+func newInternalNode() *node {
+ return &node{children: make([]*node, 256)}
+}
+
+var rootHuffmanNode = newInternalNode()
+
+func init() {
+ if len(huffmanCodes) != 256 {
+ panic("unexpected size")
+ }
+ for i, code := range huffmanCodes {
+ addDecoderNode(byte(i), code, huffmanCodeLen[i])
+ }
+}
+
+func addDecoderNode(sym byte, code uint32, codeLen uint8) {
+ cur := rootHuffmanNode
+ for codeLen > 8 {
+ codeLen -= 8
+ i := uint8(code >> codeLen)
+ if cur.children[i] == nil {
+ cur.children[i] = newInternalNode()
+ }
+ cur = cur.children[i]
+ }
+ shift := 8 - codeLen
+ start, end := int(uint8(code<<shift)), int(1<<shift)
+ for i := start; i < start+end; i++ {
+ cur.children[i] = &node{sym: sym, codeLen: codeLen}
+ }
+}
+
+// AppendHuffmanString appends s, as encoded in Huffman codes, to dst
+// and returns the extended buffer.
+func AppendHuffmanString(dst []byte, s string) []byte {
+ rembits := uint8(8)
+
+ for i := 0; i < len(s); i++ {
+ if rembits == 8 {
+ dst = append(dst, 0)
+ }
+ dst, rembits = appendByteToHuffmanCode(dst, rembits, s[i])
+ }
+
+ if rembits < 8 {
+ // special EOS symbol
+ code := uint32(0x3fffffff)
+ nbits := uint8(30)
+
+ t := uint8(code >> (nbits - rembits))
+ dst[len(dst)-1] |= t
+ }
+
+ return dst
+}
+
+// HuffmanEncodeLength returns the number of bytes required to encode
+// s in Huffman codes. The result is round up to byte boundary.
+func HuffmanEncodeLength(s string) uint64 {
+ n := uint64(0)
+ for i := 0; i < len(s); i++ {
+ n += uint64(huffmanCodeLen[s[i]])
+ }
+ return (n + 7) / 8
+}
+
+// appendByteToHuffmanCode appends Huffman code for c to dst and
+// returns the extended buffer and the remaining bits in the last
+// element. The appending is not byte aligned and the remaining bits
+// in the last element of dst is given in rembits.
+func appendByteToHuffmanCode(dst []byte, rembits uint8, c byte) ([]byte, uint8) {
+ code := huffmanCodes[c]
+ nbits := huffmanCodeLen[c]
+
+ for {
+ if rembits > nbits {
+ t := uint8(code << (rembits - nbits))
+ dst[len(dst)-1] |= t
+ rembits -= nbits
+ break
+ }
+
+ t := uint8(code >> (nbits - rembits))
+ dst[len(dst)-1] |= t
+
+ nbits -= rembits
+ rembits = 8
+
+ if nbits == 0 {
+ break
+ }
+
+ dst = append(dst, 0)
+ }
+
+ return dst, rembits
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/hpack/tables.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/hpack/tables.go
new file mode 100644
index 000000000..a66cfbea6
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/hpack/tables.go
@@ -0,0 +1,479 @@
+// Copyright 2014 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 hpack
+
+import (
+ "fmt"
+)
+
+// headerFieldTable implements a list of HeaderFields.
+// This is used to implement the static and dynamic tables.
+type headerFieldTable struct {
+ // For static tables, entries are never evicted.
+ //
+ // For dynamic tables, entries are evicted from ents[0] and added to the end.
+ // Each entry has a unique id that starts at one and increments for each
+ // entry that is added. This unique id is stable across evictions, meaning
+ // it can be used as a pointer to a specific entry. As in hpack, unique ids
+ // are 1-based. The unique id for ents[k] is k + evictCount + 1.
+ //
+ // Zero is not a valid unique id.
+ //
+ // evictCount should not overflow in any remotely practical situation. In
+ // practice, we will have one dynamic table per HTTP/2 connection. If we
+ // assume a very powerful server that handles 1M QPS per connection and each
+ // request adds (then evicts) 100 entries from the table, it would still take
+ // 2M years for evictCount to overflow.
+ ents []HeaderField
+ evictCount uint64
+
+ // byName maps a HeaderField name to the unique id of the newest entry with
+ // the same name. See above for a definition of "unique id".
+ byName map[string]uint64
+
+ // byNameValue maps a HeaderField name/value pair to the unique id of the newest
+ // entry with the same name and value. See above for a definition of "unique id".
+ byNameValue map[pairNameValue]uint64
+}
+
+type pairNameValue struct {
+ name, value string
+}
+
+func (t *headerFieldTable) init() {
+ t.byName = make(map[string]uint64)
+ t.byNameValue = make(map[pairNameValue]uint64)
+}
+
+// len reports the number of entries in the table.
+func (t *headerFieldTable) len() int {
+ return len(t.ents)
+}
+
+// addEntry adds a new entry.
+func (t *headerFieldTable) addEntry(f HeaderField) {
+ id := uint64(t.len()) + t.evictCount + 1
+ t.byName[f.Name] = id
+ t.byNameValue[pairNameValue{f.Name, f.Value}] = id
+ t.ents = append(t.ents, f)
+}
+
+// evictOldest evicts the n oldest entries in the table.
+func (t *headerFieldTable) evictOldest(n int) {
+ if n > t.len() {
+ panic(fmt.Sprintf("evictOldest(%v) on table with %v entries", n, t.len()))
+ }
+ for k := 0; k < n; k++ {
+ f := t.ents[k]
+ id := t.evictCount + uint64(k) + 1
+ if t.byName[f.Name] == id {
+ delete(t.byName, f.Name)
+ }
+ if p := (pairNameValue{f.Name, f.Value}); t.byNameValue[p] == id {
+ delete(t.byNameValue, p)
+ }
+ }
+ copy(t.ents, t.ents[n:])
+ for k := t.len() - n; k < t.len(); k++ {
+ t.ents[k] = HeaderField{} // so strings can be garbage collected
+ }
+ t.ents = t.ents[:t.len()-n]
+ if t.evictCount+uint64(n) < t.evictCount {
+ panic("evictCount overflow")
+ }
+ t.evictCount += uint64(n)
+}
+
+// search finds f in the table. If there is no match, i is 0.
+// If both name and value match, i is the matched index and nameValueMatch
+// becomes true. If only name matches, i points to that index and
+// nameValueMatch becomes false.
+//
+// The returned index is a 1-based HPACK index. For dynamic tables, HPACK says
+// that index 1 should be the newest entry, but t.ents[0] is the oldest entry,
+// meaning t.ents is reversed for dynamic tables. Hence, when t is a dynamic
+// table, the return value i actually refers to the entry t.ents[t.len()-i].
+//
+// All tables are assumed to be a dynamic tables except for the global
+// staticTable pointer.
+//
+// See Section 2.3.3.
+func (t *headerFieldTable) search(f HeaderField) (i uint64, nameValueMatch bool) {
+ if !f.Sensitive {
+ if id := t.byNameValue[pairNameValue{f.Name, f.Value}]; id != 0 {
+ return t.idToIndex(id), true
+ }
+ }
+ if id := t.byName[f.Name]; id != 0 {
+ return t.idToIndex(id), false
+ }
+ return 0, false
+}
+
+// idToIndex converts a unique id to an HPACK index.
+// See Section 2.3.3.
+func (t *headerFieldTable) idToIndex(id uint64) uint64 {
+ if id <= t.evictCount {
+ panic(fmt.Sprintf("id (%v) <= evictCount (%v)", id, t.evictCount))
+ }
+ k := id - t.evictCount - 1 // convert id to an index t.ents[k]
+ if t != staticTable {
+ return uint64(t.len()) - k // dynamic table
+ }
+ return k + 1
+}
+
+// http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-07#appendix-B
+var staticTable = newStaticTable()
+var staticTableEntries = [...]HeaderField{
+ {Name: ":authority"},
+ {Name: ":method", Value: "GET"},
+ {Name: ":method", Value: "POST"},
+ {Name: ":path", Value: "/"},
+ {Name: ":path", Value: "/index.html"},
+ {Name: ":scheme", Value: "http"},
+ {Name: ":scheme", Value: "https"},
+ {Name: ":status", Value: "200"},
+ {Name: ":status", Value: "204"},
+ {Name: ":status", Value: "206"},
+ {Name: ":status", Value: "304"},
+ {Name: ":status", Value: "400"},
+ {Name: ":status", Value: "404"},
+ {Name: ":status", Value: "500"},
+ {Name: "accept-charset"},
+ {Name: "accept-encoding", Value: "gzip, deflate"},
+ {Name: "accept-language"},
+ {Name: "accept-ranges"},
+ {Name: "accept"},
+ {Name: "access-control-allow-origin"},
+ {Name: "age"},
+ {Name: "allow"},
+ {Name: "authorization"},
+ {Name: "cache-control"},
+ {Name: "content-disposition"},
+ {Name: "content-encoding"},
+ {Name: "content-language"},
+ {Name: "content-length"},
+ {Name: "content-location"},
+ {Name: "content-range"},
+ {Name: "content-type"},
+ {Name: "cookie"},
+ {Name: "date"},
+ {Name: "etag"},
+ {Name: "expect"},
+ {Name: "expires"},
+ {Name: "from"},
+ {Name: "host"},
+ {Name: "if-match"},
+ {Name: "if-modified-since"},
+ {Name: "if-none-match"},
+ {Name: "if-range"},
+ {Name: "if-unmodified-since"},
+ {Name: "last-modified"},
+ {Name: "link"},
+ {Name: "location"},
+ {Name: "max-forwards"},
+ {Name: "proxy-authenticate"},
+ {Name: "proxy-authorization"},
+ {Name: "range"},
+ {Name: "referer"},
+ {Name: "refresh"},
+ {Name: "retry-after"},
+ {Name: "server"},
+ {Name: "set-cookie"},
+ {Name: "strict-transport-security"},
+ {Name: "transfer-encoding"},
+ {Name: "user-agent"},
+ {Name: "vary"},
+ {Name: "via"},
+ {Name: "www-authenticate"},
+}
+
+func newStaticTable() *headerFieldTable {
+ t := &headerFieldTable{}
+ t.init()
+ for _, e := range staticTableEntries[:] {
+ t.addEntry(e)
+ }
+ return t
+}
+
+var huffmanCodes = [256]uint32{
+ 0x1ff8,
+ 0x7fffd8,
+ 0xfffffe2,
+ 0xfffffe3,
+ 0xfffffe4,
+ 0xfffffe5,
+ 0xfffffe6,
+ 0xfffffe7,
+ 0xfffffe8,
+ 0xffffea,
+ 0x3ffffffc,
+ 0xfffffe9,
+ 0xfffffea,
+ 0x3ffffffd,
+ 0xfffffeb,
+ 0xfffffec,
+ 0xfffffed,
+ 0xfffffee,
+ 0xfffffef,
+ 0xffffff0,
+ 0xffffff1,
+ 0xffffff2,
+ 0x3ffffffe,
+ 0xffffff3,
+ 0xffffff4,
+ 0xffffff5,
+ 0xffffff6,
+ 0xffffff7,
+ 0xffffff8,
+ 0xffffff9,
+ 0xffffffa,
+ 0xffffffb,
+ 0x14,
+ 0x3f8,
+ 0x3f9,
+ 0xffa,
+ 0x1ff9,
+ 0x15,
+ 0xf8,
+ 0x7fa,
+ 0x3fa,
+ 0x3fb,
+ 0xf9,
+ 0x7fb,
+ 0xfa,
+ 0x16,
+ 0x17,
+ 0x18,
+ 0x0,
+ 0x1,
+ 0x2,
+ 0x19,
+ 0x1a,
+ 0x1b,
+ 0x1c,
+ 0x1d,
+ 0x1e,
+ 0x1f,
+ 0x5c,
+ 0xfb,
+ 0x7ffc,
+ 0x20,
+ 0xffb,
+ 0x3fc,
+ 0x1ffa,
+ 0x21,
+ 0x5d,
+ 0x5e,
+ 0x5f,
+ 0x60,
+ 0x61,
+ 0x62,
+ 0x63,
+ 0x64,
+ 0x65,
+ 0x66,
+ 0x67,
+ 0x68,
+ 0x69,
+ 0x6a,
+ 0x6b,
+ 0x6c,
+ 0x6d,
+ 0x6e,
+ 0x6f,
+ 0x70,
+ 0x71,
+ 0x72,
+ 0xfc,
+ 0x73,
+ 0xfd,
+ 0x1ffb,
+ 0x7fff0,
+ 0x1ffc,
+ 0x3ffc,
+ 0x22,
+ 0x7ffd,
+ 0x3,
+ 0x23,
+ 0x4,
+ 0x24,
+ 0x5,
+ 0x25,
+ 0x26,
+ 0x27,
+ 0x6,
+ 0x74,
+ 0x75,
+ 0x28,
+ 0x29,
+ 0x2a,
+ 0x7,
+ 0x2b,
+ 0x76,
+ 0x2c,
+ 0x8,
+ 0x9,
+ 0x2d,
+ 0x77,
+ 0x78,
+ 0x79,
+ 0x7a,
+ 0x7b,
+ 0x7ffe,
+ 0x7fc,
+ 0x3ffd,
+ 0x1ffd,
+ 0xffffffc,
+ 0xfffe6,
+ 0x3fffd2,
+ 0xfffe7,
+ 0xfffe8,
+ 0x3fffd3,
+ 0x3fffd4,
+ 0x3fffd5,
+ 0x7fffd9,
+ 0x3fffd6,
+ 0x7fffda,
+ 0x7fffdb,
+ 0x7fffdc,
+ 0x7fffdd,
+ 0x7fffde,
+ 0xffffeb,
+ 0x7fffdf,
+ 0xffffec,
+ 0xffffed,
+ 0x3fffd7,
+ 0x7fffe0,
+ 0xffffee,
+ 0x7fffe1,
+ 0x7fffe2,
+ 0x7fffe3,
+ 0x7fffe4,
+ 0x1fffdc,
+ 0x3fffd8,
+ 0x7fffe5,
+ 0x3fffd9,
+ 0x7fffe6,
+ 0x7fffe7,
+ 0xffffef,
+ 0x3fffda,
+ 0x1fffdd,
+ 0xfffe9,
+ 0x3fffdb,
+ 0x3fffdc,
+ 0x7fffe8,
+ 0x7fffe9,
+ 0x1fffde,
+ 0x7fffea,
+ 0x3fffdd,
+ 0x3fffde,
+ 0xfffff0,
+ 0x1fffdf,
+ 0x3fffdf,
+ 0x7fffeb,
+ 0x7fffec,
+ 0x1fffe0,
+ 0x1fffe1,
+ 0x3fffe0,
+ 0x1fffe2,
+ 0x7fffed,
+ 0x3fffe1,
+ 0x7fffee,
+ 0x7fffef,
+ 0xfffea,
+ 0x3fffe2,
+ 0x3fffe3,
+ 0x3fffe4,
+ 0x7ffff0,
+ 0x3fffe5,
+ 0x3fffe6,
+ 0x7ffff1,
+ 0x3ffffe0,
+ 0x3ffffe1,
+ 0xfffeb,
+ 0x7fff1,
+ 0x3fffe7,
+ 0x7ffff2,
+ 0x3fffe8,
+ 0x1ffffec,
+ 0x3ffffe2,
+ 0x3ffffe3,
+ 0x3ffffe4,
+ 0x7ffffde,
+ 0x7ffffdf,
+ 0x3ffffe5,
+ 0xfffff1,
+ 0x1ffffed,
+ 0x7fff2,
+ 0x1fffe3,
+ 0x3ffffe6,
+ 0x7ffffe0,
+ 0x7ffffe1,
+ 0x3ffffe7,
+ 0x7ffffe2,
+ 0xfffff2,
+ 0x1fffe4,
+ 0x1fffe5,
+ 0x3ffffe8,
+ 0x3ffffe9,
+ 0xffffffd,
+ 0x7ffffe3,
+ 0x7ffffe4,
+ 0x7ffffe5,
+ 0xfffec,
+ 0xfffff3,
+ 0xfffed,
+ 0x1fffe6,
+ 0x3fffe9,
+ 0x1fffe7,
+ 0x1fffe8,
+ 0x7ffff3,
+ 0x3fffea,
+ 0x3fffeb,
+ 0x1ffffee,
+ 0x1ffffef,
+ 0xfffff4,
+ 0xfffff5,
+ 0x3ffffea,
+ 0x7ffff4,
+ 0x3ffffeb,
+ 0x7ffffe6,
+ 0x3ffffec,
+ 0x3ffffed,
+ 0x7ffffe7,
+ 0x7ffffe8,
+ 0x7ffffe9,
+ 0x7ffffea,
+ 0x7ffffeb,
+ 0xffffffe,
+ 0x7ffffec,
+ 0x7ffffed,
+ 0x7ffffee,
+ 0x7ffffef,
+ 0x7fffff0,
+ 0x3ffffee,
+}
+
+var huffmanCodeLen = [256]uint8{
+ 13, 23, 28, 28, 28, 28, 28, 28, 28, 24, 30, 28, 28, 30, 28, 28,
+ 28, 28, 28, 28, 28, 28, 30, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 6, 10, 10, 12, 13, 6, 8, 11, 10, 10, 8, 11, 8, 6, 6, 6,
+ 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 8, 15, 6, 12, 10,
+ 13, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 8, 7, 8, 13, 19, 13, 14, 6,
+ 15, 5, 6, 5, 6, 5, 6, 6, 6, 5, 7, 7, 6, 6, 6, 5,
+ 6, 7, 6, 5, 5, 6, 7, 7, 7, 7, 7, 15, 11, 14, 13, 28,
+ 20, 22, 20, 20, 22, 22, 22, 23, 22, 23, 23, 23, 23, 23, 24, 23,
+ 24, 24, 22, 23, 24, 23, 23, 23, 23, 21, 22, 23, 22, 23, 23, 24,
+ 22, 21, 20, 22, 22, 23, 23, 21, 23, 22, 22, 24, 21, 22, 23, 23,
+ 21, 21, 22, 21, 23, 22, 23, 23, 20, 22, 22, 22, 23, 22, 22, 23,
+ 26, 26, 20, 19, 22, 23, 22, 25, 26, 26, 26, 27, 27, 26, 24, 25,
+ 19, 21, 26, 27, 27, 26, 27, 24, 21, 21, 26, 26, 28, 27, 27, 27,
+ 20, 24, 20, 21, 22, 21, 21, 23, 22, 22, 25, 25, 24, 24, 26, 23,
+ 26, 27, 26, 26, 27, 27, 27, 27, 27, 28, 27, 27, 27, 27, 27, 26,
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/hpack/tables_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/hpack/tables_test.go
new file mode 100644
index 000000000..d963f3635
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/hpack/tables_test.go
@@ -0,0 +1,214 @@
+// 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 hpack
+
+import (
+ "bufio"
+ "regexp"
+ "strconv"
+ "strings"
+ "testing"
+)
+
+func TestHeaderFieldTable(t *testing.T) {
+ table := &headerFieldTable{}
+ table.init()
+ table.addEntry(pair("key1", "value1-1"))
+ table.addEntry(pair("key2", "value2-1"))
+ table.addEntry(pair("key1", "value1-2"))
+ table.addEntry(pair("key3", "value3-1"))
+ table.addEntry(pair("key4", "value4-1"))
+ table.addEntry(pair("key2", "value2-2"))
+
+ // Tests will be run twice: once before evicting anything, and
+ // again after evicting the three oldest entries.
+ tests := []struct {
+ f HeaderField
+ beforeWantStaticI uint64
+ beforeWantMatch bool
+ afterWantStaticI uint64
+ afterWantMatch bool
+ }{
+ {HeaderField{"key1", "value1-1", false}, 1, true, 0, false},
+ {HeaderField{"key1", "value1-2", false}, 3, true, 0, false},
+ {HeaderField{"key1", "value1-3", false}, 3, false, 0, false},
+ {HeaderField{"key2", "value2-1", false}, 2, true, 3, false},
+ {HeaderField{"key2", "value2-2", false}, 6, true, 3, true},
+ {HeaderField{"key2", "value2-3", false}, 6, false, 3, false},
+ {HeaderField{"key4", "value4-1", false}, 5, true, 2, true},
+ // Name match only, because sensitive.
+ {HeaderField{"key4", "value4-1", true}, 5, false, 2, false},
+ // Key not found.
+ {HeaderField{"key5", "value5-x", false}, 0, false, 0, false},
+ }
+
+ staticToDynamic := func(i uint64) uint64 {
+ if i == 0 {
+ return 0
+ }
+ return uint64(table.len()) - i + 1 // dynamic is the reversed table
+ }
+
+ searchStatic := func(f HeaderField) (uint64, bool) {
+ old := staticTable
+ staticTable = table
+ defer func() { staticTable = old }()
+ return staticTable.search(f)
+ }
+
+ searchDynamic := func(f HeaderField) (uint64, bool) {
+ return table.search(f)
+ }
+
+ for _, test := range tests {
+ gotI, gotMatch := searchStatic(test.f)
+ if wantI, wantMatch := test.beforeWantStaticI, test.beforeWantMatch; gotI != wantI || gotMatch != wantMatch {
+ t.Errorf("before evictions: searchStatic(%+v)=%v,%v want %v,%v", test.f, gotI, gotMatch, wantI, wantMatch)
+ }
+ gotI, gotMatch = searchDynamic(test.f)
+ wantDynamicI := staticToDynamic(test.beforeWantStaticI)
+ if wantI, wantMatch := wantDynamicI, test.beforeWantMatch; gotI != wantI || gotMatch != wantMatch {
+ t.Errorf("before evictions: searchDynamic(%+v)=%v,%v want %v,%v", test.f, gotI, gotMatch, wantI, wantMatch)
+ }
+ }
+
+ table.evictOldest(3)
+
+ for _, test := range tests {
+ gotI, gotMatch := searchStatic(test.f)
+ if wantI, wantMatch := test.afterWantStaticI, test.afterWantMatch; gotI != wantI || gotMatch != wantMatch {
+ t.Errorf("after evictions: searchStatic(%+v)=%v,%v want %v,%v", test.f, gotI, gotMatch, wantI, wantMatch)
+ }
+ gotI, gotMatch = searchDynamic(test.f)
+ wantDynamicI := staticToDynamic(test.afterWantStaticI)
+ if wantI, wantMatch := wantDynamicI, test.afterWantMatch; gotI != wantI || gotMatch != wantMatch {
+ t.Errorf("after evictions: searchDynamic(%+v)=%v,%v want %v,%v", test.f, gotI, gotMatch, wantI, wantMatch)
+ }
+ }
+}
+
+func TestHeaderFieldTable_LookupMapEviction(t *testing.T) {
+ table := &headerFieldTable{}
+ table.init()
+ table.addEntry(pair("key1", "value1-1"))
+ table.addEntry(pair("key2", "value2-1"))
+ table.addEntry(pair("key1", "value1-2"))
+ table.addEntry(pair("key3", "value3-1"))
+ table.addEntry(pair("key4", "value4-1"))
+ table.addEntry(pair("key2", "value2-2"))
+
+ // evict all pairs
+ table.evictOldest(table.len())
+
+ if l := table.len(); l > 0 {
+ t.Errorf("table.len() = %d, want 0", l)
+ }
+
+ if l := len(table.byName); l > 0 {
+ t.Errorf("len(table.byName) = %d, want 0", l)
+ }
+
+ if l := len(table.byNameValue); l > 0 {
+ t.Errorf("len(table.byNameValue) = %d, want 0", l)
+ }
+}
+
+func TestStaticTable(t *testing.T) {
+ fromSpec := `
+ +-------+-----------------------------+---------------+
+ | 1 | :authority | |
+ | 2 | :method | GET |
+ | 3 | :method | POST |
+ | 4 | :path | / |
+ | 5 | :path | /index.html |
+ | 6 | :scheme | http |
+ | 7 | :scheme | https |
+ | 8 | :status | 200 |
+ | 9 | :status | 204 |
+ | 10 | :status | 206 |
+ | 11 | :status | 304 |
+ | 12 | :status | 400 |
+ | 13 | :status | 404 |
+ | 14 | :status | 500 |
+ | 15 | accept-charset | |
+ | 16 | accept-encoding | gzip, deflate |
+ | 17 | accept-language | |
+ | 18 | accept-ranges | |
+ | 19 | accept | |
+ | 20 | access-control-allow-origin | |
+ | 21 | age | |
+ | 22 | allow | |
+ | 23 | authorization | |
+ | 24 | cache-control | |
+ | 25 | content-disposition | |
+ | 26 | content-encoding | |
+ | 27 | content-language | |
+ | 28 | content-length | |
+ | 29 | content-location | |
+ | 30 | content-range | |
+ | 31 | content-type | |
+ | 32 | cookie | |
+ | 33 | date | |
+ | 34 | etag | |
+ | 35 | expect | |
+ | 36 | expires | |
+ | 37 | from | |
+ | 38 | host | |
+ | 39 | if-match | |
+ | 40 | if-modified-since | |
+ | 41 | if-none-match | |
+ | 42 | if-range | |
+ | 43 | if-unmodified-since | |
+ | 44 | last-modified | |
+ | 45 | link | |
+ | 46 | location | |
+ | 47 | max-forwards | |
+ | 48 | proxy-authenticate | |
+ | 49 | proxy-authorization | |
+ | 50 | range | |
+ | 51 | referer | |
+ | 52 | refresh | |
+ | 53 | retry-after | |
+ | 54 | server | |
+ | 55 | set-cookie | |
+ | 56 | strict-transport-security | |
+ | 57 | transfer-encoding | |
+ | 58 | user-agent | |
+ | 59 | vary | |
+ | 60 | via | |
+ | 61 | www-authenticate | |
+ +-------+-----------------------------+---------------+
+`
+ bs := bufio.NewScanner(strings.NewReader(fromSpec))
+ re := regexp.MustCompile(`\| (\d+)\s+\| (\S+)\s*\| (\S(.*\S)?)?\s+\|`)
+ for bs.Scan() {
+ l := bs.Text()
+ if !strings.Contains(l, "|") {
+ continue
+ }
+ m := re.FindStringSubmatch(l)
+ if m == nil {
+ continue
+ }
+ i, err := strconv.Atoi(m[1])
+ if err != nil {
+ t.Errorf("Bogus integer on line %q", l)
+ continue
+ }
+ if i < 1 || i > staticTable.len() {
+ t.Errorf("Bogus index %d on line %q", i, l)
+ continue
+ }
+ if got, want := staticTable.ents[i-1].Name, m[2]; got != want {
+ t.Errorf("header index %d name = %q; want %q", i, got, want)
+ }
+ if got, want := staticTable.ents[i-1].Value, m[3]; got != want {
+ t.Errorf("header index %d value = %q; want %q", i, got, want)
+ }
+ }
+ if err := bs.Err(); err != nil {
+ t.Error(err)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/http2.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/http2.go
new file mode 100644
index 000000000..d565f40e0
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/http2.go
@@ -0,0 +1,391 @@
+// Copyright 2014 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 http2 implements the HTTP/2 protocol.
+//
+// This package is low-level and intended to be used directly by very
+// few people. Most users will use it indirectly through the automatic
+// use by the net/http package (from Go 1.6 and later).
+// For use in earlier Go versions see ConfigureServer. (Transport support
+// requires Go 1.6 or later)
+//
+// See https://http2.github.io/ for more information on HTTP/2.
+//
+// See https://http2.golang.org/ for a test server running this code.
+//
+package http2 // import "golang.org/x/net/http2"
+
+import (
+ "bufio"
+ "crypto/tls"
+ "errors"
+ "fmt"
+ "io"
+ "net/http"
+ "os"
+ "sort"
+ "strconv"
+ "strings"
+ "sync"
+
+ "golang.org/x/net/lex/httplex"
+)
+
+var (
+ VerboseLogs bool
+ logFrameWrites bool
+ logFrameReads bool
+ inTests bool
+)
+
+func init() {
+ e := os.Getenv("GODEBUG")
+ if strings.Contains(e, "http2debug=1") {
+ VerboseLogs = true
+ }
+ if strings.Contains(e, "http2debug=2") {
+ VerboseLogs = true
+ logFrameWrites = true
+ logFrameReads = true
+ }
+}
+
+const (
+ // ClientPreface is the string that must be sent by new
+ // connections from clients.
+ ClientPreface = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
+
+ // SETTINGS_MAX_FRAME_SIZE default
+ // http://http2.github.io/http2-spec/#rfc.section.6.5.2
+ initialMaxFrameSize = 16384
+
+ // NextProtoTLS is the NPN/ALPN protocol negotiated during
+ // HTTP/2's TLS setup.
+ NextProtoTLS = "h2"
+
+ // http://http2.github.io/http2-spec/#SettingValues
+ initialHeaderTableSize = 4096
+
+ initialWindowSize = 65535 // 6.9.2 Initial Flow Control Window Size
+
+ defaultMaxReadFrameSize = 1 << 20
+)
+
+var (
+ clientPreface = []byte(ClientPreface)
+)
+
+type streamState int
+
+// HTTP/2 stream states.
+//
+// See http://tools.ietf.org/html/rfc7540#section-5.1.
+//
+// For simplicity, the server code merges "reserved (local)" into
+// "half-closed (remote)". This is one less state transition to track.
+// The only downside is that we send PUSH_PROMISEs slightly less
+// liberally than allowable. More discussion here:
+// https://lists.w3.org/Archives/Public/ietf-http-wg/2016JulSep/0599.html
+//
+// "reserved (remote)" is omitted since the client code does not
+// support server push.
+const (
+ stateIdle streamState = iota
+ stateOpen
+ stateHalfClosedLocal
+ stateHalfClosedRemote
+ stateClosed
+)
+
+var stateName = [...]string{
+ stateIdle: "Idle",
+ stateOpen: "Open",
+ stateHalfClosedLocal: "HalfClosedLocal",
+ stateHalfClosedRemote: "HalfClosedRemote",
+ stateClosed: "Closed",
+}
+
+func (st streamState) String() string {
+ return stateName[st]
+}
+
+// Setting is a setting parameter: which setting it is, and its value.
+type Setting struct {
+ // ID is which setting is being set.
+ // See http://http2.github.io/http2-spec/#SettingValues
+ ID SettingID
+
+ // Val is the value.
+ Val uint32
+}
+
+func (s Setting) String() string {
+ return fmt.Sprintf("[%v = %d]", s.ID, s.Val)
+}
+
+// Valid reports whether the setting is valid.
+func (s Setting) Valid() error {
+ // Limits and error codes from 6.5.2 Defined SETTINGS Parameters
+ switch s.ID {
+ case SettingEnablePush:
+ if s.Val != 1 && s.Val != 0 {
+ return ConnectionError(ErrCodeProtocol)
+ }
+ case SettingInitialWindowSize:
+ if s.Val > 1<<31-1 {
+ return ConnectionError(ErrCodeFlowControl)
+ }
+ case SettingMaxFrameSize:
+ if s.Val < 16384 || s.Val > 1<<24-1 {
+ return ConnectionError(ErrCodeProtocol)
+ }
+ }
+ return nil
+}
+
+// A SettingID is an HTTP/2 setting as defined in
+// http://http2.github.io/http2-spec/#iana-settings
+type SettingID uint16
+
+const (
+ SettingHeaderTableSize SettingID = 0x1
+ SettingEnablePush SettingID = 0x2
+ SettingMaxConcurrentStreams SettingID = 0x3
+ SettingInitialWindowSize SettingID = 0x4
+ SettingMaxFrameSize SettingID = 0x5
+ SettingMaxHeaderListSize SettingID = 0x6
+)
+
+var settingName = map[SettingID]string{
+ SettingHeaderTableSize: "HEADER_TABLE_SIZE",
+ SettingEnablePush: "ENABLE_PUSH",
+ SettingMaxConcurrentStreams: "MAX_CONCURRENT_STREAMS",
+ SettingInitialWindowSize: "INITIAL_WINDOW_SIZE",
+ SettingMaxFrameSize: "MAX_FRAME_SIZE",
+ SettingMaxHeaderListSize: "MAX_HEADER_LIST_SIZE",
+}
+
+func (s SettingID) String() string {
+ if v, ok := settingName[s]; ok {
+ return v
+ }
+ 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 httplex.ValidHeaderName for the base rules.
+//
+// Further, http2 says:
+// "Just as in HTTP/1.x, header field names are strings of ASCII
+// characters that are compared in a case-insensitive
+// fashion. However, header field names MUST be converted to
+// lowercase prior to their encoding in HTTP/2. "
+func validWireHeaderFieldName(v string) bool {
+ if len(v) == 0 {
+ return false
+ }
+ for _, r := range v {
+ if !httplex.IsTokenRune(r) {
+ return false
+ }
+ if 'A' <= r && r <= 'Z' {
+ return false
+ }
+ }
+ return true
+}
+
+var httpCodeStringCommon = map[int]string{} // n -> strconv.Itoa(n)
+
+func init() {
+ for i := 100; i <= 999; i++ {
+ if v := http.StatusText(i); v != "" {
+ httpCodeStringCommon[i] = strconv.Itoa(i)
+ }
+ }
+}
+
+func httpCodeString(code int) string {
+ if s, ok := httpCodeStringCommon[code]; ok {
+ return s
+ }
+ return strconv.Itoa(code)
+}
+
+// from pkg io
+type stringWriter interface {
+ WriteString(s string) (n int, err error)
+}
+
+// A gate lets two goroutines coordinate their activities.
+type gate chan struct{}
+
+func (g gate) Done() { g <- struct{}{} }
+func (g gate) Wait() { <-g }
+
+// A closeWaiter is like a sync.WaitGroup but only goes 1 to 0 (open to closed).
+type closeWaiter chan struct{}
+
+// Init makes a closeWaiter usable.
+// It exists because so a closeWaiter value can be placed inside a
+// larger struct and have the Mutex and Cond's memory in the same
+// allocation.
+func (cw *closeWaiter) Init() {
+ *cw = make(chan struct{})
+}
+
+// Close marks the closeWaiter as closed and unblocks any waiters.
+func (cw closeWaiter) Close() {
+ close(cw)
+}
+
+// Wait waits for the closeWaiter to become closed.
+func (cw closeWaiter) Wait() {
+ <-cw
+}
+
+// bufferedWriter is a buffered writer that writes to w.
+// Its buffered writer is lazily allocated as needed, to minimize
+// idle memory usage with many connections.
+type bufferedWriter struct {
+ w io.Writer // immutable
+ bw *bufio.Writer // non-nil when data is buffered
+}
+
+func newBufferedWriter(w io.Writer) *bufferedWriter {
+ return &bufferedWriter{w: w}
+}
+
+// bufWriterPoolBufferSize is the size of bufio.Writer's
+// buffers created using bufWriterPool.
+//
+// TODO: pick a less arbitrary value? this is a bit under
+// (3 x typical 1500 byte MTU) at least. Other than that,
+// not much thought went into it.
+const bufWriterPoolBufferSize = 4 << 10
+
+var bufWriterPool = sync.Pool{
+ New: func() interface{} {
+ return bufio.NewWriterSize(nil, bufWriterPoolBufferSize)
+ },
+}
+
+func (w *bufferedWriter) Available() int {
+ if w.bw == nil {
+ return bufWriterPoolBufferSize
+ }
+ return w.bw.Available()
+}
+
+func (w *bufferedWriter) Write(p []byte) (n int, err error) {
+ if w.bw == nil {
+ bw := bufWriterPool.Get().(*bufio.Writer)
+ bw.Reset(w.w)
+ w.bw = bw
+ }
+ return w.bw.Write(p)
+}
+
+func (w *bufferedWriter) Flush() error {
+ bw := w.bw
+ if bw == nil {
+ return nil
+ }
+ err := bw.Flush()
+ bw.Reset(nil)
+ bufWriterPool.Put(bw)
+ w.bw = nil
+ return err
+}
+
+func mustUint31(v int32) uint32 {
+ if v < 0 || v > 2147483647 {
+ panic("out of range")
+ }
+ return uint32(v)
+}
+
+// bodyAllowedForStatus reports whether a given response status code
+// permits a body. See RFC 2616, section 4.4.
+func bodyAllowedForStatus(status int) bool {
+ switch {
+ case status >= 100 && status <= 199:
+ return false
+ case status == 204:
+ return false
+ case status == 304:
+ return false
+ }
+ return true
+}
+
+type httpError struct {
+ msg string
+ timeout bool
+}
+
+func (e *httpError) Error() string { return e.msg }
+func (e *httpError) Timeout() bool { return e.timeout }
+func (e *httpError) Temporary() bool { return true }
+
+var errTimeout error = &httpError{msg: "http2: timeout awaiting response headers", timeout: true}
+
+type connectionStater interface {
+ ConnectionState() tls.ConnectionState
+}
+
+var sorterPool = sync.Pool{New: func() interface{} { return new(sorter) }}
+
+type sorter struct {
+ v []string // owned by sorter
+}
+
+func (s *sorter) Len() int { return len(s.v) }
+func (s *sorter) Swap(i, j int) { s.v[i], s.v[j] = s.v[j], s.v[i] }
+func (s *sorter) Less(i, j int) bool { return s.v[i] < s.v[j] }
+
+// Keys returns the sorted keys of h.
+//
+// The returned slice is only valid until s used again or returned to
+// its pool.
+func (s *sorter) Keys(h http.Header) []string {
+ keys := s.v[:0]
+ for k := range h {
+ keys = append(keys, k)
+ }
+ s.v = keys
+ sort.Sort(s)
+ return keys
+}
+
+func (s *sorter) SortStrings(ss []string) {
+ // Our sorter works on s.v, which sorter owns, so
+ // stash it away while we sort the user's buffer.
+ save := s.v
+ s.v = ss
+ sort.Sort(s)
+ s.v = save
+}
+
+// validPseudoPath reports whether v is a valid :path pseudo-header
+// value. It must be either:
+//
+// *) a non-empty string starting with '/'
+// *) the string '*', for OPTIONS requests.
+//
+// For now this is only used a quick check for deciding when to clean
+// up Opaque URLs before sending requests from the Transport.
+// See golang.org/issue/16847
+//
+// We used to enforce that the path also didn't start with "//", but
+// Google's GFE accepts such paths and Chrome sends them, so ignore
+// that part of the spec. See golang.org/issue/19103.
+func validPseudoPath(v string) bool {
+ return (len(v) > 0 && v[0] == '/') || v == "*"
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/http2_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/http2_test.go
new file mode 100644
index 000000000..524877647
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/http2_test.go
@@ -0,0 +1,199 @@
+// Copyright 2014 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 http2
+
+import (
+ "bytes"
+ "errors"
+ "flag"
+ "fmt"
+ "net/http"
+ "os/exec"
+ "strconv"
+ "strings"
+ "testing"
+
+ "golang.org/x/net/http2/hpack"
+)
+
+var knownFailing = flag.Bool("known_failing", false, "Run known-failing tests.")
+
+func condSkipFailingTest(t *testing.T) {
+ if !*knownFailing {
+ t.Skip("Skipping known-failing test without --known_failing")
+ }
+}
+
+func init() {
+ inTests = true
+ DebugGoroutines = true
+ flag.BoolVar(&VerboseLogs, "verboseh2", VerboseLogs, "Verbose HTTP/2 debug logging")
+}
+
+func TestSettingString(t *testing.T) {
+ tests := []struct {
+ s Setting
+ want string
+ }{
+ {Setting{SettingMaxFrameSize, 123}, "[MAX_FRAME_SIZE = 123]"},
+ {Setting{1<<16 - 1, 123}, "[UNKNOWN_SETTING_65535 = 123]"},
+ }
+ for i, tt := range tests {
+ got := fmt.Sprint(tt.s)
+ if got != tt.want {
+ t.Errorf("%d. for %#v, string = %q; want %q", i, tt.s, got, tt.want)
+ }
+ }
+}
+
+type twriter struct {
+ t testing.TB
+ st *serverTester // optional
+}
+
+func (w twriter) Write(p []byte) (n int, err error) {
+ if w.st != nil {
+ ps := string(p)
+ for _, phrase := range w.st.logFilter {
+ if strings.Contains(ps, phrase) {
+ return len(p), nil // no logging
+ }
+ }
+ }
+ w.t.Logf("%s", p)
+ return len(p), nil
+}
+
+// like encodeHeader, but don't add implicit pseudo headers.
+func encodeHeaderNoImplicit(t *testing.T, headers ...string) []byte {
+ var buf bytes.Buffer
+ enc := hpack.NewEncoder(&buf)
+ for len(headers) > 0 {
+ k, v := headers[0], headers[1]
+ headers = headers[2:]
+ if err := enc.WriteField(hpack.HeaderField{Name: k, Value: v}); err != nil {
+ t.Fatalf("HPACK encoding error for %q/%q: %v", k, v, err)
+ }
+ }
+ return buf.Bytes()
+}
+
+// Verify that curl has http2.
+func requireCurl(t *testing.T) {
+ out, err := dockerLogs(curl(t, "--version"))
+ if err != nil {
+ t.Skipf("failed to determine curl features; skipping test")
+ }
+ if !strings.Contains(string(out), "HTTP2") {
+ t.Skip("curl doesn't support HTTP2; skipping test")
+ }
+}
+
+func curl(t *testing.T, args ...string) (container string) {
+ out, err := exec.Command("docker", append([]string{"run", "-d", "--net=host", "gohttp2/curl"}, args...)...).Output()
+ if err != nil {
+ t.Skipf("Failed to run curl in docker: %v, %s", err, out)
+ }
+ return strings.TrimSpace(string(out))
+}
+
+// Verify that h2load exists.
+func requireH2load(t *testing.T) {
+ out, err := dockerLogs(h2load(t, "--version"))
+ if err != nil {
+ t.Skipf("failed to probe h2load; skipping test: %s", out)
+ }
+ if !strings.Contains(string(out), "h2load nghttp2/") {
+ t.Skipf("h2load not present; skipping test. (Output=%q)", out)
+ }
+}
+
+func h2load(t *testing.T, args ...string) (container string) {
+ out, err := exec.Command("docker", append([]string{"run", "-d", "--net=host", "--entrypoint=/usr/local/bin/h2load", "gohttp2/curl"}, args...)...).Output()
+ if err != nil {
+ t.Skipf("Failed to run h2load in docker: %v, %s", err, out)
+ }
+ return strings.TrimSpace(string(out))
+}
+
+type puppetCommand struct {
+ fn func(w http.ResponseWriter, r *http.Request)
+ done chan<- bool
+}
+
+type handlerPuppet struct {
+ ch chan puppetCommand
+}
+
+func newHandlerPuppet() *handlerPuppet {
+ return &handlerPuppet{
+ ch: make(chan puppetCommand),
+ }
+}
+
+func (p *handlerPuppet) act(w http.ResponseWriter, r *http.Request) {
+ for cmd := range p.ch {
+ cmd.fn(w, r)
+ cmd.done <- true
+ }
+}
+
+func (p *handlerPuppet) done() { close(p.ch) }
+func (p *handlerPuppet) do(fn func(http.ResponseWriter, *http.Request)) {
+ done := make(chan bool)
+ p.ch <- puppetCommand{fn, done}
+ <-done
+}
+func dockerLogs(container string) ([]byte, error) {
+ out, err := exec.Command("docker", "wait", container).CombinedOutput()
+ if err != nil {
+ return out, err
+ }
+ exitStatus, err := strconv.Atoi(strings.TrimSpace(string(out)))
+ if err != nil {
+ return out, errors.New("unexpected exit status from docker wait")
+ }
+ out, err = exec.Command("docker", "logs", container).CombinedOutput()
+ exec.Command("docker", "rm", container).Run()
+ if err == nil && exitStatus != 0 {
+ err = fmt.Errorf("exit status %d: %s", exitStatus, out)
+ }
+ return out, err
+}
+
+func kill(container string) {
+ exec.Command("docker", "kill", container).Run()
+ exec.Command("docker", "rm", container).Run()
+}
+
+func cleanDate(res *http.Response) {
+ if d := res.Header["Date"]; len(d) == 1 {
+ d[0] = "XXX"
+ }
+}
+
+func TestSorterPoolAllocs(t *testing.T) {
+ ss := []string{"a", "b", "c"}
+ h := http.Header{
+ "a": nil,
+ "b": nil,
+ "c": nil,
+ }
+ sorter := new(sorter)
+
+ if allocs := testing.AllocsPerRun(100, func() {
+ sorter.SortStrings(ss)
+ }); allocs >= 1 {
+ t.Logf("SortStrings allocs = %v; want <1", allocs)
+ }
+
+ if allocs := testing.AllocsPerRun(5, func() {
+ if len(sorter.Keys(h)) != 3 {
+ t.Fatal("wrong result")
+ }
+ }); allocs > 0 {
+ t.Logf("Keys allocs = %v; want <1", allocs)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/not_go16.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/not_go16.go
new file mode 100644
index 000000000..508cebcc4
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/not_go16.go
@@ -0,0 +1,21 @@
+// Copyright 2015 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.
+
+// +build !go1.6
+
+package http2
+
+import (
+ "net/http"
+ "time"
+)
+
+func configureTransport(t1 *http.Transport) (*Transport, error) {
+ return nil, errTransportVersion
+}
+
+func transportExpectContinueTimeout(t1 *http.Transport) time.Duration {
+ return 0
+
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/not_go17.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/not_go17.go
new file mode 100644
index 000000000..140434a79
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/not_go17.go
@@ -0,0 +1,87 @@
+// 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.
+
+// +build !go1.7
+
+package http2
+
+import (
+ "crypto/tls"
+ "net"
+ "net/http"
+ "time"
+)
+
+type contextContext interface {
+ Done() <-chan struct{}
+ Err() error
+}
+
+type fakeContext struct{}
+
+func (fakeContext) Done() <-chan struct{} { return nil }
+func (fakeContext) Err() error { panic("should not be called") }
+
+func reqContext(r *http.Request) fakeContext {
+ return fakeContext{}
+}
+
+func setResponseUncompressed(res *http.Response) {
+ // Nothing.
+}
+
+type clientTrace struct{}
+
+func requestTrace(*http.Request) *clientTrace { return nil }
+func traceGotConn(*http.Request, *ClientConn) {}
+func traceFirstResponseByte(*clientTrace) {}
+func traceWroteHeaders(*clientTrace) {}
+func traceWroteRequest(*clientTrace, error) {}
+func traceGot100Continue(trace *clientTrace) {}
+func traceWait100Continue(trace *clientTrace) {}
+
+func nop() {}
+
+func serverConnBaseContext(c net.Conn, opts *ServeConnOpts) (ctx contextContext, cancel func()) {
+ return nil, nop
+}
+
+func contextWithCancel(ctx contextContext) (_ contextContext, cancel func()) {
+ return ctx, nop
+}
+
+func requestWithContext(req *http.Request, ctx contextContext) *http.Request {
+ return req
+}
+
+// temporary copy of Go 1.6's private tls.Config.clone:
+func cloneTLSConfig(c *tls.Config) *tls.Config {
+ return &tls.Config{
+ Rand: c.Rand,
+ Time: c.Time,
+ Certificates: c.Certificates,
+ NameToCertificate: c.NameToCertificate,
+ GetCertificate: c.GetCertificate,
+ RootCAs: c.RootCAs,
+ NextProtos: c.NextProtos,
+ ServerName: c.ServerName,
+ ClientAuth: c.ClientAuth,
+ ClientCAs: c.ClientCAs,
+ InsecureSkipVerify: c.InsecureSkipVerify,
+ CipherSuites: c.CipherSuites,
+ PreferServerCipherSuites: c.PreferServerCipherSuites,
+ SessionTicketsDisabled: c.SessionTicketsDisabled,
+ SessionTicketKey: c.SessionTicketKey,
+ ClientSessionCache: c.ClientSessionCache,
+ MinVersion: c.MinVersion,
+ MaxVersion: c.MaxVersion,
+ CurvePreferences: c.CurvePreferences,
+ }
+}
+
+func (cc *ClientConn) Ping(ctx contextContext) error {
+ return cc.ping(ctx)
+}
+
+func (t *Transport) idleConnTimeout() time.Duration { return 0 }
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/not_go18.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/not_go18.go
new file mode 100644
index 000000000..6f8d3f86f
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/not_go18.go
@@ -0,0 +1,29 @@
+// 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.
+
+// +build !go1.8
+
+package http2
+
+import (
+ "io"
+ "net/http"
+)
+
+func configureServer18(h1 *http.Server, h2 *Server) error {
+ // No IdleTimeout to sync prior to Go 1.8.
+ return nil
+}
+
+func shouldLogPanic(panicValue interface{}) bool {
+ return panicValue != nil
+}
+
+func reqGetBody(req *http.Request) func() (io.ReadCloser, error) {
+ return nil
+}
+
+func reqBodyIsNoBody(io.ReadCloser) bool { return false }
+
+func go18httpNoBody() io.ReadCloser { return nil } // for tests only
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/not_go19.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/not_go19.go
new file mode 100644
index 000000000..5ae07726b
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/not_go19.go
@@ -0,0 +1,16 @@
+// 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.
+
+// +build !go1.9
+
+package http2
+
+import (
+ "net/http"
+)
+
+func configureServer19(s *http.Server, conf *Server) error {
+ // not supported prior to go1.9
+ return nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/pipe.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/pipe.go
new file mode 100644
index 000000000..a6140099c
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/pipe.go
@@ -0,0 +1,163 @@
+// Copyright 2014 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 http2
+
+import (
+ "errors"
+ "io"
+ "sync"
+)
+
+// pipe is a goroutine-safe io.Reader/io.Writer pair. It's like
+// io.Pipe except there are no PipeReader/PipeWriter halves, and the
+// underlying buffer is an interface. (io.Pipe is always unbuffered)
+type pipe struct {
+ mu sync.Mutex
+ c sync.Cond // c.L lazily initialized to &p.mu
+ b pipeBuffer // nil when done reading
+ err error // read error once empty. non-nil means closed.
+ breakErr error // immediate read error (caller doesn't see rest of b)
+ donec chan struct{} // closed on error
+ readFn func() // optional code to run in Read before error
+}
+
+type pipeBuffer interface {
+ Len() int
+ io.Writer
+ io.Reader
+}
+
+func (p *pipe) Len() int {
+ p.mu.Lock()
+ defer p.mu.Unlock()
+ if p.b == nil {
+ return 0
+ }
+ return p.b.Len()
+}
+
+// Read waits until data is available and copies bytes
+// from the buffer into p.
+func (p *pipe) Read(d []byte) (n int, err error) {
+ p.mu.Lock()
+ defer p.mu.Unlock()
+ if p.c.L == nil {
+ p.c.L = &p.mu
+ }
+ for {
+ if p.breakErr != nil {
+ return 0, p.breakErr
+ }
+ if p.b != nil && p.b.Len() > 0 {
+ return p.b.Read(d)
+ }
+ if p.err != nil {
+ if p.readFn != nil {
+ p.readFn() // e.g. copy trailers
+ p.readFn = nil // not sticky like p.err
+ }
+ p.b = nil
+ return 0, p.err
+ }
+ p.c.Wait()
+ }
+}
+
+var errClosedPipeWrite = errors.New("write on closed buffer")
+
+// Write copies bytes from p into the buffer and wakes a reader.
+// It is an error to write more data than the buffer can hold.
+func (p *pipe) Write(d []byte) (n int, err error) {
+ p.mu.Lock()
+ defer p.mu.Unlock()
+ if p.c.L == nil {
+ p.c.L = &p.mu
+ }
+ defer p.c.Signal()
+ if p.err != nil {
+ return 0, errClosedPipeWrite
+ }
+ if p.breakErr != nil {
+ return len(d), nil // discard when there is no reader
+ }
+ return p.b.Write(d)
+}
+
+// CloseWithError causes the next Read (waking up a current blocked
+// Read if needed) to return the provided err after all data has been
+// read.
+//
+// The error must be non-nil.
+func (p *pipe) CloseWithError(err error) { p.closeWithError(&p.err, err, nil) }
+
+// BreakWithError causes the next Read (waking up a current blocked
+// Read if needed) to return the provided err immediately, without
+// waiting for unread data.
+func (p *pipe) BreakWithError(err error) { p.closeWithError(&p.breakErr, err, nil) }
+
+// closeWithErrorAndCode is like CloseWithError but also sets some code to run
+// in the caller's goroutine before returning the error.
+func (p *pipe) closeWithErrorAndCode(err error, fn func()) { p.closeWithError(&p.err, err, fn) }
+
+func (p *pipe) closeWithError(dst *error, err error, fn func()) {
+ if err == nil {
+ panic("err must be non-nil")
+ }
+ p.mu.Lock()
+ defer p.mu.Unlock()
+ if p.c.L == nil {
+ p.c.L = &p.mu
+ }
+ defer p.c.Signal()
+ if *dst != nil {
+ // Already been done.
+ return
+ }
+ p.readFn = fn
+ if dst == &p.breakErr {
+ p.b = nil
+ }
+ *dst = err
+ p.closeDoneLocked()
+}
+
+// requires p.mu be held.
+func (p *pipe) closeDoneLocked() {
+ if p.donec == nil {
+ return
+ }
+ // Close if unclosed. This isn't racy since we always
+ // hold p.mu while closing.
+ select {
+ case <-p.donec:
+ default:
+ close(p.donec)
+ }
+}
+
+// Err returns the error (if any) first set by BreakWithError or CloseWithError.
+func (p *pipe) Err() error {
+ p.mu.Lock()
+ defer p.mu.Unlock()
+ if p.breakErr != nil {
+ return p.breakErr
+ }
+ return p.err
+}
+
+// Done returns a channel which is closed if and when this pipe is closed
+// with CloseWithError.
+func (p *pipe) Done() <-chan struct{} {
+ p.mu.Lock()
+ defer p.mu.Unlock()
+ if p.donec == nil {
+ p.donec = make(chan struct{})
+ if p.err != nil || p.breakErr != nil {
+ // Already hit an error.
+ p.closeDoneLocked()
+ }
+ }
+ return p.donec
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/pipe_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/pipe_test.go
new file mode 100644
index 000000000..1bf351ff6
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/pipe_test.go
@@ -0,0 +1,130 @@
+// Copyright 2014 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 http2
+
+import (
+ "bytes"
+ "errors"
+ "io"
+ "io/ioutil"
+ "testing"
+)
+
+func TestPipeClose(t *testing.T) {
+ var p pipe
+ p.b = new(bytes.Buffer)
+ a := errors.New("a")
+ b := errors.New("b")
+ p.CloseWithError(a)
+ p.CloseWithError(b)
+ _, err := p.Read(make([]byte, 1))
+ if err != a {
+ t.Errorf("err = %v want %v", err, a)
+ }
+}
+
+func TestPipeDoneChan(t *testing.T) {
+ var p pipe
+ done := p.Done()
+ select {
+ case <-done:
+ t.Fatal("done too soon")
+ default:
+ }
+ p.CloseWithError(io.EOF)
+ select {
+ case <-done:
+ default:
+ t.Fatal("should be done")
+ }
+}
+
+func TestPipeDoneChan_ErrFirst(t *testing.T) {
+ var p pipe
+ p.CloseWithError(io.EOF)
+ done := p.Done()
+ select {
+ case <-done:
+ default:
+ t.Fatal("should be done")
+ }
+}
+
+func TestPipeDoneChan_Break(t *testing.T) {
+ var p pipe
+ done := p.Done()
+ select {
+ case <-done:
+ t.Fatal("done too soon")
+ default:
+ }
+ p.BreakWithError(io.EOF)
+ select {
+ case <-done:
+ default:
+ t.Fatal("should be done")
+ }
+}
+
+func TestPipeDoneChan_Break_ErrFirst(t *testing.T) {
+ var p pipe
+ p.BreakWithError(io.EOF)
+ done := p.Done()
+ select {
+ case <-done:
+ default:
+ t.Fatal("should be done")
+ }
+}
+
+func TestPipeCloseWithError(t *testing.T) {
+ p := &pipe{b: new(bytes.Buffer)}
+ const body = "foo"
+ io.WriteString(p, body)
+ a := errors.New("test error")
+ p.CloseWithError(a)
+ all, err := ioutil.ReadAll(p)
+ if string(all) != body {
+ t.Errorf("read bytes = %q; want %q", all, body)
+ }
+ if err != a {
+ t.Logf("read error = %v, %v", err, a)
+ }
+ // Read and Write should fail.
+ if n, err := p.Write([]byte("abc")); err != errClosedPipeWrite || n != 0 {
+ t.Errorf("Write(abc) after close\ngot %v, %v\nwant 0, %v", n, err, errClosedPipeWrite)
+ }
+ if n, err := p.Read(make([]byte, 1)); err == nil || n != 0 {
+ t.Errorf("Read() after close\ngot %v, nil\nwant 0, %v", n, errClosedPipeWrite)
+ }
+}
+
+func TestPipeBreakWithError(t *testing.T) {
+ p := &pipe{b: new(bytes.Buffer)}
+ io.WriteString(p, "foo")
+ a := errors.New("test err")
+ p.BreakWithError(a)
+ all, err := ioutil.ReadAll(p)
+ if string(all) != "" {
+ t.Errorf("read bytes = %q; want empty string", all)
+ }
+ if err != a {
+ t.Logf("read error = %v, %v", err, a)
+ }
+ if p.b != nil {
+ t.Errorf("buffer should be nil after BreakWithError")
+ }
+ // Write should succeed silently.
+ if n, err := p.Write([]byte("abc")); err != nil || n != 3 {
+ t.Errorf("Write(abc) after break\ngot %v, %v\nwant 0, nil", n, err)
+ }
+ if p.b != nil {
+ t.Errorf("buffer should be nil after Write")
+ }
+ // Read should fail.
+ if n, err := p.Read(make([]byte, 1)); err == nil || n != 0 {
+ t.Errorf("Read() after close\ngot %v, nil\nwant 0, not nil", n)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/server.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/server.go
new file mode 100644
index 000000000..7a502263a
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/server.go
@@ -0,0 +1,2888 @@
+// Copyright 2014 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.
+
+// TODO: turn off the serve goroutine when idle, so
+// an idle conn only has the readFrames goroutine active. (which could
+// also be optimized probably to pin less memory in crypto/tls). This
+// would involve tracking when the serve goroutine is active (atomic
+// int32 read/CAS probably?) and starting it up when frames arrive,
+// and shutting it down when all handlers exit. the occasional PING
+// packets could use time.AfterFunc to call sc.wakeStartServeLoop()
+// (which is a no-op if already running) and then queue the PING write
+// as normal. The serve loop would then exit in most cases (if no
+// Handlers running) and not be woken up again until the PING packet
+// returns.
+
+// TODO (maybe): add a mechanism for Handlers to going into
+// half-closed-local mode (rw.(io.Closer) test?) but not exit their
+// handler, and continue to be able to read from the
+// Request.Body. This would be a somewhat semantic change from HTTP/1
+// (or at least what we expose in net/http), so I'd probably want to
+// add it there too. For now, this package says that returning from
+// the Handler ServeHTTP function means you're both done reading and
+// done writing, without a way to stop just one or the other.
+
+package http2
+
+import (
+ "bufio"
+ "bytes"
+ "crypto/tls"
+ "errors"
+ "fmt"
+ "io"
+ "log"
+ "math"
+ "net"
+ "net/http"
+ "net/textproto"
+ "net/url"
+ "os"
+ "reflect"
+ "runtime"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+
+ "golang.org/x/net/http2/hpack"
+)
+
+const (
+ prefaceTimeout = 10 * time.Second
+ firstSettingsTimeout = 2 * time.Second // should be in-flight with preface anyway
+ handlerChunkWriteSize = 4 << 10
+ defaultMaxStreams = 250 // TODO: make this 100 as the GFE seems to?
+)
+
+var (
+ errClientDisconnected = errors.New("client disconnected")
+ errClosedBody = errors.New("body closed by handler")
+ errHandlerComplete = errors.New("http2: request body closed due to handler exiting")
+ errStreamClosed = errors.New("http2: stream closed")
+)
+
+var responseWriterStatePool = sync.Pool{
+ New: func() interface{} {
+ rws := &responseWriterState{}
+ rws.bw = bufio.NewWriterSize(chunkWriter{rws}, handlerChunkWriteSize)
+ return rws
+ },
+}
+
+// Test hooks.
+var (
+ testHookOnConn func()
+ testHookGetServerConn func(*serverConn)
+ testHookOnPanicMu *sync.Mutex // nil except in tests
+ testHookOnPanic func(sc *serverConn, panicVal interface{}) (rePanic bool)
+)
+
+// Server is an HTTP/2 server.
+type Server struct {
+ // MaxHandlers limits the number of http.Handler ServeHTTP goroutines
+ // which may run at a time over all connections.
+ // Negative or zero no limit.
+ // TODO: implement
+ MaxHandlers int
+
+ // MaxConcurrentStreams optionally specifies the number of
+ // concurrent streams that each client may have open at a
+ // time. This is unrelated to the number of http.Handler goroutines
+ // which may be active globally, which is MaxHandlers.
+ // If zero, MaxConcurrentStreams defaults to at least 100, per
+ // the HTTP/2 spec's recommendations.
+ MaxConcurrentStreams uint32
+
+ // MaxReadFrameSize optionally specifies the largest frame
+ // this server is willing to read. A valid value is between
+ // 16k and 16M, inclusive. If zero or otherwise invalid, a
+ // default value is used.
+ MaxReadFrameSize uint32
+
+ // PermitProhibitedCipherSuites, if true, permits the use of
+ // cipher suites prohibited by the HTTP/2 spec.
+ PermitProhibitedCipherSuites bool
+
+ // IdleTimeout specifies how long until idle clients should be
+ // closed with a GOAWAY frame. PING frames are not considered
+ // activity for the purposes of IdleTimeout.
+ IdleTimeout time.Duration
+
+ // MaxUploadBufferPerConnection is the size of the initial flow
+ // control window for each connections. The HTTP/2 spec does not
+ // allow this to be smaller than 65535 or larger than 2^32-1.
+ // If the value is outside this range, a default value will be
+ // used instead.
+ MaxUploadBufferPerConnection int32
+
+ // MaxUploadBufferPerStream is the size of the initial flow control
+ // window for each stream. The HTTP/2 spec does not allow this to
+ // be larger than 2^32-1. If the value is zero or larger than the
+ // maximum, a default value will be used instead.
+ MaxUploadBufferPerStream int32
+
+ // NewWriteScheduler constructs a write scheduler for a connection.
+ // If nil, a default scheduler is chosen.
+ NewWriteScheduler func() WriteScheduler
+
+ // Internal state. This is a pointer (rather than embedded directly)
+ // so that we don't embed a Mutex in this struct, which will make the
+ // struct non-copyable, which might break some callers.
+ state *serverInternalState
+}
+
+func (s *Server) initialConnRecvWindowSize() int32 {
+ if s.MaxUploadBufferPerConnection > initialWindowSize {
+ return s.MaxUploadBufferPerConnection
+ }
+ return 1 << 20
+}
+
+func (s *Server) initialStreamRecvWindowSize() int32 {
+ if s.MaxUploadBufferPerStream > 0 {
+ return s.MaxUploadBufferPerStream
+ }
+ return 1 << 20
+}
+
+func (s *Server) maxReadFrameSize() uint32 {
+ if v := s.MaxReadFrameSize; v >= minMaxFrameSize && v <= maxFrameSize {
+ return v
+ }
+ return defaultMaxReadFrameSize
+}
+
+func (s *Server) maxConcurrentStreams() uint32 {
+ if v := s.MaxConcurrentStreams; v > 0 {
+ return v
+ }
+ return defaultMaxStreams
+}
+
+type serverInternalState struct {
+ mu sync.Mutex
+ activeConns map[*serverConn]struct{}
+}
+
+func (s *serverInternalState) registerConn(sc *serverConn) {
+ if s == nil {
+ return // if the Server was used without calling ConfigureServer
+ }
+ s.mu.Lock()
+ s.activeConns[sc] = struct{}{}
+ s.mu.Unlock()
+}
+
+func (s *serverInternalState) unregisterConn(sc *serverConn) {
+ if s == nil {
+ return // if the Server was used without calling ConfigureServer
+ }
+ s.mu.Lock()
+ delete(s.activeConns, sc)
+ s.mu.Unlock()
+}
+
+func (s *serverInternalState) startGracefulShutdown() {
+ if s == nil {
+ return // if the Server was used without calling ConfigureServer
+ }
+ s.mu.Lock()
+ for sc := range s.activeConns {
+ sc.startGracefulShutdown()
+ }
+ s.mu.Unlock()
+}
+
+// ConfigureServer adds HTTP/2 support to a net/http Server.
+//
+// The configuration conf may be nil.
+//
+// ConfigureServer must be called before s begins serving.
+func ConfigureServer(s *http.Server, conf *Server) error {
+ if s == nil {
+ panic("nil *http.Server")
+ }
+ if conf == nil {
+ conf = new(Server)
+ }
+ conf.state = &serverInternalState{activeConns: make(map[*serverConn]struct{})}
+ if err := configureServer18(s, conf); err != nil {
+ return err
+ }
+ if err := configureServer19(s, conf); err != nil {
+ return err
+ }
+
+ if s.TLSConfig == nil {
+ s.TLSConfig = new(tls.Config)
+ } else if s.TLSConfig.CipherSuites != nil {
+ // If they already provided a CipherSuite list, return
+ // an error if it has a bad order or is missing
+ // ECDHE_RSA_WITH_AES_128_GCM_SHA256 or ECDHE_ECDSA_WITH_AES_128_GCM_SHA256.
+ haveRequired := false
+ sawBad := false
+ for i, cs := range s.TLSConfig.CipherSuites {
+ switch cs {
+ case tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+ // Alternative MTI cipher to not discourage ECDSA-only servers.
+ // See http://golang.org/cl/30721 for further information.
+ tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
+ haveRequired = true
+ }
+ if isBadCipher(cs) {
+ sawBad = true
+ } else if sawBad {
+ return fmt.Errorf("http2: TLSConfig.CipherSuites index %d contains an HTTP/2-approved cipher suite (%#04x), but it comes after unapproved cipher suites. With this configuration, clients that don't support previous, approved cipher suites may be given an unapproved one and reject the connection.", i, cs)
+ }
+ }
+ if !haveRequired {
+ return fmt.Errorf("http2: TLSConfig.CipherSuites is missing an HTTP/2-required AES_128_GCM_SHA256 cipher.")
+ }
+ }
+
+ // Note: not setting MinVersion to tls.VersionTLS12,
+ // as we don't want to interfere with HTTP/1.1 traffic
+ // on the user's server. We enforce TLS 1.2 later once
+ // we accept a connection. Ideally this should be done
+ // during next-proto selection, but using TLS <1.2 with
+ // HTTP/2 is still the client's bug.
+
+ s.TLSConfig.PreferServerCipherSuites = true
+
+ haveNPN := false
+ for _, p := range s.TLSConfig.NextProtos {
+ if p == NextProtoTLS {
+ haveNPN = true
+ break
+ }
+ }
+ if !haveNPN {
+ s.TLSConfig.NextProtos = append(s.TLSConfig.NextProtos, NextProtoTLS)
+ }
+
+ if s.TLSNextProto == nil {
+ s.TLSNextProto = map[string]func(*http.Server, *tls.Conn, http.Handler){}
+ }
+ protoHandler := func(hs *http.Server, c *tls.Conn, h http.Handler) {
+ if testHookOnConn != nil {
+ testHookOnConn()
+ }
+ conf.ServeConn(c, &ServeConnOpts{
+ Handler: h,
+ BaseConfig: hs,
+ })
+ }
+ s.TLSNextProto[NextProtoTLS] = protoHandler
+ return nil
+}
+
+// ServeConnOpts are options for the Server.ServeConn method.
+type ServeConnOpts struct {
+ // BaseConfig optionally sets the base configuration
+ // for values. If nil, defaults are used.
+ BaseConfig *http.Server
+
+ // Handler specifies which handler to use for processing
+ // requests. If nil, BaseConfig.Handler is used. If BaseConfig
+ // or BaseConfig.Handler is nil, http.DefaultServeMux is used.
+ Handler http.Handler
+}
+
+func (o *ServeConnOpts) baseConfig() *http.Server {
+ if o != nil && o.BaseConfig != nil {
+ return o.BaseConfig
+ }
+ return new(http.Server)
+}
+
+func (o *ServeConnOpts) handler() http.Handler {
+ if o != nil {
+ if o.Handler != nil {
+ return o.Handler
+ }
+ if o.BaseConfig != nil && o.BaseConfig.Handler != nil {
+ return o.BaseConfig.Handler
+ }
+ }
+ return http.DefaultServeMux
+}
+
+// ServeConn serves HTTP/2 requests on the provided connection and
+// blocks until the connection is no longer readable.
+//
+// ServeConn starts speaking HTTP/2 assuming that c has not had any
+// reads or writes. It writes its initial settings frame and expects
+// to be able to read the preface and settings frame from the
+// client. If c has a ConnectionState method like a *tls.Conn, the
+// ConnectionState is used to verify the TLS ciphersuite and to set
+// the Request.TLS field in Handlers.
+//
+// ServeConn does not support h2c by itself. Any h2c support must be
+// implemented in terms of providing a suitably-behaving net.Conn.
+//
+// The opts parameter is optional. If nil, default values are used.
+func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
+ baseCtx, cancel := serverConnBaseContext(c, opts)
+ defer cancel()
+
+ sc := &serverConn{
+ srv: s,
+ hs: opts.baseConfig(),
+ conn: c,
+ baseCtx: baseCtx,
+ remoteAddrStr: c.RemoteAddr().String(),
+ bw: newBufferedWriter(c),
+ handler: opts.handler(),
+ streams: make(map[uint32]*stream),
+ readFrameCh: make(chan readFrameResult),
+ wantWriteFrameCh: make(chan FrameWriteRequest, 8),
+ serveMsgCh: make(chan interface{}, 8),
+ wroteFrameCh: make(chan frameWriteResult, 1), // buffered; one send in writeFrameAsync
+ bodyReadCh: make(chan bodyReadMsg), // buffering doesn't matter either way
+ doneServing: make(chan struct{}),
+ clientMaxStreams: math.MaxUint32, // Section 6.5.2: "Initially, there is no limit to this value"
+ advMaxStreams: s.maxConcurrentStreams(),
+ initialStreamSendWindowSize: initialWindowSize,
+ maxFrameSize: initialMaxFrameSize,
+ headerTableSize: initialHeaderTableSize,
+ serveG: newGoroutineLock(),
+ pushEnabled: true,
+ }
+
+ s.state.registerConn(sc)
+ defer s.state.unregisterConn(sc)
+
+ // The net/http package sets the write deadline from the
+ // http.Server.WriteTimeout during the TLS handshake, but then
+ // passes the connection off to us with the deadline already set.
+ // Write deadlines are set per stream in serverConn.newStream.
+ // Disarm the net.Conn write deadline here.
+ if sc.hs.WriteTimeout != 0 {
+ sc.conn.SetWriteDeadline(time.Time{})
+ }
+
+ if s.NewWriteScheduler != nil {
+ sc.writeSched = s.NewWriteScheduler()
+ } else {
+ sc.writeSched = NewRandomWriteScheduler()
+ }
+
+ // These start at the RFC-specified defaults. If there is a higher
+ // configured value for inflow, that will be updated when we send a
+ // WINDOW_UPDATE shortly after sending SETTINGS.
+ sc.flow.add(initialWindowSize)
+ sc.inflow.add(initialWindowSize)
+ sc.hpackEncoder = hpack.NewEncoder(&sc.headerWriteBuf)
+
+ fr := NewFramer(sc.bw, c)
+ fr.ReadMetaHeaders = hpack.NewDecoder(initialHeaderTableSize, nil)
+ fr.MaxHeaderListSize = sc.maxHeaderListSize()
+ fr.SetMaxReadFrameSize(s.maxReadFrameSize())
+ sc.framer = fr
+
+ if tc, ok := c.(connectionStater); ok {
+ sc.tlsState = new(tls.ConnectionState)
+ *sc.tlsState = tc.ConnectionState()
+ // 9.2 Use of TLS Features
+ // An implementation of HTTP/2 over TLS MUST use TLS
+ // 1.2 or higher with the restrictions on feature set
+ // and cipher suite described in this section. Due to
+ // implementation limitations, it might not be
+ // possible to fail TLS negotiation. An endpoint MUST
+ // immediately terminate an HTTP/2 connection that
+ // does not meet the TLS requirements described in
+ // this section with a connection error (Section
+ // 5.4.1) of type INADEQUATE_SECURITY.
+ if sc.tlsState.Version < tls.VersionTLS12 {
+ sc.rejectConn(ErrCodeInadequateSecurity, "TLS version too low")
+ return
+ }
+
+ if sc.tlsState.ServerName == "" {
+ // Client must use SNI, but we don't enforce that anymore,
+ // since it was causing problems when connecting to bare IP
+ // addresses during development.
+ //
+ // TODO: optionally enforce? Or enforce at the time we receive
+ // a new request, and verify the the ServerName matches the :authority?
+ // But that precludes proxy situations, perhaps.
+ //
+ // So for now, do nothing here again.
+ }
+
+ if !s.PermitProhibitedCipherSuites && isBadCipher(sc.tlsState.CipherSuite) {
+ // "Endpoints MAY choose to generate a connection error
+ // (Section 5.4.1) of type INADEQUATE_SECURITY if one of
+ // the prohibited cipher suites are negotiated."
+ //
+ // We choose that. In my opinion, the spec is weak
+ // here. It also says both parties must support at least
+ // TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 so there's no
+ // excuses here. If we really must, we could allow an
+ // "AllowInsecureWeakCiphers" option on the server later.
+ // Let's see how it plays out first.
+ sc.rejectConn(ErrCodeInadequateSecurity, fmt.Sprintf("Prohibited TLS 1.2 Cipher Suite: %x", sc.tlsState.CipherSuite))
+ return
+ }
+ }
+
+ if hook := testHookGetServerConn; hook != nil {
+ hook(sc)
+ }
+ sc.serve()
+}
+
+func (sc *serverConn) rejectConn(err ErrCode, debug string) {
+ sc.vlogf("http2: server rejecting conn: %v, %s", err, debug)
+ // ignoring errors. hanging up anyway.
+ sc.framer.WriteGoAway(0, err, []byte(debug))
+ sc.bw.Flush()
+ sc.conn.Close()
+}
+
+type serverConn struct {
+ // Immutable:
+ srv *Server
+ hs *http.Server
+ conn net.Conn
+ bw *bufferedWriter // writing to conn
+ handler http.Handler
+ baseCtx contextContext
+ framer *Framer
+ doneServing chan struct{} // closed when serverConn.serve ends
+ readFrameCh chan readFrameResult // written by serverConn.readFrames
+ wantWriteFrameCh chan FrameWriteRequest // from handlers -> serve
+ wroteFrameCh chan frameWriteResult // from writeFrameAsync -> serve, tickles more frame writes
+ bodyReadCh chan bodyReadMsg // from handlers -> serve
+ serveMsgCh chan interface{} // misc messages & code to send to / run on the serve loop
+ flow flow // conn-wide (not stream-specific) outbound flow control
+ inflow flow // conn-wide inbound flow control
+ tlsState *tls.ConnectionState // shared by all handlers, like net/http
+ remoteAddrStr string
+ writeSched WriteScheduler
+
+ // Everything following is owned by the serve loop; use serveG.check():
+ serveG goroutineLock // used to verify funcs are on serve()
+ pushEnabled bool
+ sawFirstSettings bool // got the initial SETTINGS frame after the preface
+ needToSendSettingsAck bool
+ unackedSettings int // how many SETTINGS have we sent without ACKs?
+ clientMaxStreams uint32 // SETTINGS_MAX_CONCURRENT_STREAMS from client (our PUSH_PROMISE limit)
+ advMaxStreams uint32 // our SETTINGS_MAX_CONCURRENT_STREAMS advertised the client
+ curClientStreams uint32 // number of open streams initiated by the client
+ curPushedStreams uint32 // number of open streams initiated by server push
+ maxClientStreamID uint32 // max ever seen from client (odd), or 0 if there have been no client requests
+ maxPushPromiseID uint32 // ID of the last push promise (even), or 0 if there have been no pushes
+ streams map[uint32]*stream
+ initialStreamSendWindowSize int32
+ maxFrameSize int32
+ headerTableSize uint32
+ peerMaxHeaderListSize uint32 // zero means unknown (default)
+ canonHeader map[string]string // http2-lower-case -> Go-Canonical-Case
+ writingFrame bool // started writing a frame (on serve goroutine or separate)
+ writingFrameAsync bool // started a frame on its own goroutine but haven't heard back on wroteFrameCh
+ needsFrameFlush bool // last frame write wasn't a flush
+ inGoAway bool // we've started to or sent GOAWAY
+ inFrameScheduleLoop bool // whether we're in the scheduleFrameWrite loop
+ needToSendGoAway bool // we need to schedule a GOAWAY frame write
+ goAwayCode ErrCode
+ shutdownTimer *time.Timer // nil until used
+ idleTimer *time.Timer // nil if unused
+
+ // Owned by the writeFrameAsync goroutine:
+ headerWriteBuf bytes.Buffer
+ hpackEncoder *hpack.Encoder
+
+ // Used by startGracefulShutdown.
+ shutdownOnce sync.Once
+}
+
+func (sc *serverConn) maxHeaderListSize() uint32 {
+ n := sc.hs.MaxHeaderBytes
+ if n <= 0 {
+ n = http.DefaultMaxHeaderBytes
+ }
+ // http2's count is in a slightly different unit and includes 32 bytes per pair.
+ // So, take the net/http.Server value and pad it up a bit, assuming 10 headers.
+ const perFieldOverhead = 32 // per http2 spec
+ const typicalHeaders = 10 // conservative
+ return uint32(n + typicalHeaders*perFieldOverhead)
+}
+
+func (sc *serverConn) curOpenStreams() uint32 {
+ sc.serveG.check()
+ return sc.curClientStreams + sc.curPushedStreams
+}
+
+// stream represents a stream. This is the minimal metadata needed by
+// the serve goroutine. Most of the actual stream state is owned by
+// the http.Handler's goroutine in the responseWriter. Because the
+// responseWriter's responseWriterState is recycled at the end of a
+// handler, this struct intentionally has no pointer to the
+// *responseWriter{,State} itself, as the Handler ending nils out the
+// responseWriter's state field.
+type stream struct {
+ // immutable:
+ sc *serverConn
+ id uint32
+ body *pipe // non-nil if expecting DATA frames
+ cw closeWaiter // closed wait stream transitions to closed state
+ ctx contextContext
+ 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
+ state streamState
+ resetQueued bool // RST_STREAM queued for write; set by sc.resetStream
+ gotTrailerHeader bool // HEADER frame for trailers was seen
+ wroteHeaders bool // whether we wrote headers (not status 100)
+ writeDeadline *time.Timer // nil if unused
+
+ trailer http.Header // accumulated trailers
+ reqTrailer http.Header // handler's Request.Trailer
+}
+
+func (sc *serverConn) Framer() *Framer { return sc.framer }
+func (sc *serverConn) CloseConn() error { return sc.conn.Close() }
+func (sc *serverConn) Flush() error { return sc.bw.Flush() }
+func (sc *serverConn) HeaderEncoder() (*hpack.Encoder, *bytes.Buffer) {
+ return sc.hpackEncoder, &sc.headerWriteBuf
+}
+
+func (sc *serverConn) state(streamID uint32) (streamState, *stream) {
+ sc.serveG.check()
+ // http://tools.ietf.org/html/rfc7540#section-5.1
+ if st, ok := sc.streams[streamID]; ok {
+ return st.state, st
+ }
+ // "The first use of a new stream identifier implicitly closes all
+ // streams in the "idle" state that might have been initiated by
+ // that peer with a lower-valued stream identifier. For example, if
+ // a client sends a HEADERS frame on stream 7 without ever sending a
+ // frame on stream 5, then stream 5 transitions to the "closed"
+ // state when the first frame for stream 7 is sent or received."
+ if streamID%2 == 1 {
+ if streamID <= sc.maxClientStreamID {
+ return stateClosed, nil
+ }
+ } else {
+ if streamID <= sc.maxPushPromiseID {
+ return stateClosed, nil
+ }
+ }
+ return stateIdle, nil
+}
+
+// setConnState calls the net/http ConnState hook for this connection, if configured.
+// Note that the net/http package does StateNew and StateClosed for us.
+// There is currently no plan for StateHijacked or hijacking HTTP/2 connections.
+func (sc *serverConn) setConnState(state http.ConnState) {
+ if sc.hs.ConnState != nil {
+ sc.hs.ConnState(sc.conn, state)
+ }
+}
+
+func (sc *serverConn) vlogf(format string, args ...interface{}) {
+ if VerboseLogs {
+ sc.logf(format, args...)
+ }
+}
+
+func (sc *serverConn) logf(format string, args ...interface{}) {
+ if lg := sc.hs.ErrorLog; lg != nil {
+ lg.Printf(format, args...)
+ } else {
+ log.Printf(format, args...)
+ }
+}
+
+// errno returns v's underlying uintptr, else 0.
+//
+// TODO: remove this helper function once http2 can use build
+// tags. See comment in isClosedConnError.
+func errno(v error) uintptr {
+ if rv := reflect.ValueOf(v); rv.Kind() == reflect.Uintptr {
+ return uintptr(rv.Uint())
+ }
+ return 0
+}
+
+// isClosedConnError reports whether err is an error from use of a closed
+// network connection.
+func isClosedConnError(err error) bool {
+ if err == nil {
+ return false
+ }
+
+ // TODO: remove this string search and be more like the Windows
+ // case below. That might involve modifying the standard library
+ // to return better error types.
+ str := err.Error()
+ if strings.Contains(str, "use of closed network connection") {
+ return true
+ }
+
+ // TODO(bradfitz): x/tools/cmd/bundle doesn't really support
+ // build tags, so I can't make an http2_windows.go file with
+ // Windows-specific stuff. Fix that and move this, once we
+ // have a way to bundle this into std's net/http somehow.
+ if runtime.GOOS == "windows" {
+ if oe, ok := err.(*net.OpError); ok && oe.Op == "read" {
+ if se, ok := oe.Err.(*os.SyscallError); ok && se.Syscall == "wsarecv" {
+ const WSAECONNABORTED = 10053
+ const WSAECONNRESET = 10054
+ if n := errno(se.Err); n == WSAECONNRESET || n == WSAECONNABORTED {
+ return true
+ }
+ }
+ }
+ }
+ return false
+}
+
+func (sc *serverConn) condlogf(err error, format string, args ...interface{}) {
+ if err == nil {
+ return
+ }
+ if err == io.EOF || err == io.ErrUnexpectedEOF || isClosedConnError(err) || err == errPrefaceTimeout {
+ // Boring, expected errors.
+ sc.vlogf(format, args...)
+ } else {
+ sc.logf(format, args...)
+ }
+}
+
+func (sc *serverConn) canonicalHeader(v string) string {
+ sc.serveG.check()
+ cv, ok := commonCanonHeader[v]
+ if ok {
+ return cv
+ }
+ cv, ok = sc.canonHeader[v]
+ if ok {
+ return cv
+ }
+ if sc.canonHeader == nil {
+ sc.canonHeader = make(map[string]string)
+ }
+ cv = http.CanonicalHeaderKey(v)
+ sc.canonHeader[v] = cv
+ return cv
+}
+
+type readFrameResult struct {
+ f Frame // valid until readMore is called
+ err error
+
+ // readMore should be called once the consumer no longer needs or
+ // retains f. After readMore, f is invalid and more frames can be
+ // read.
+ readMore func()
+}
+
+// readFrames is the loop that reads incoming frames.
+// It takes care to only read one frame at a time, blocking until the
+// consumer is done with the frame.
+// It's run on its own goroutine.
+func (sc *serverConn) readFrames() {
+ gate := make(gate)
+ gateDone := gate.Done
+ for {
+ f, err := sc.framer.ReadFrame()
+ select {
+ case sc.readFrameCh <- readFrameResult{f, err, gateDone}:
+ case <-sc.doneServing:
+ return
+ }
+ select {
+ case <-gate:
+ case <-sc.doneServing:
+ return
+ }
+ if terminalReadFrameError(err) {
+ return
+ }
+ }
+}
+
+// frameWriteResult is the message passed from writeFrameAsync to the serve goroutine.
+type frameWriteResult struct {
+ wr FrameWriteRequest // what was written (or attempted)
+ err error // result of the writeFrame call
+}
+
+// writeFrameAsync runs in its own goroutine and writes a single frame
+// and then reports when it's done.
+// At most one goroutine can be running writeFrameAsync at a time per
+// serverConn.
+func (sc *serverConn) writeFrameAsync(wr FrameWriteRequest) {
+ err := wr.write.writeFrame(sc)
+ sc.wroteFrameCh <- frameWriteResult{wr, err}
+}
+
+func (sc *serverConn) closeAllStreamsOnConnClose() {
+ sc.serveG.check()
+ for _, st := range sc.streams {
+ sc.closeStream(st, errClientDisconnected)
+ }
+}
+
+func (sc *serverConn) stopShutdownTimer() {
+ sc.serveG.check()
+ if t := sc.shutdownTimer; t != nil {
+ t.Stop()
+ }
+}
+
+func (sc *serverConn) notePanic() {
+ // Note: this is for serverConn.serve panicking, not http.Handler code.
+ if testHookOnPanicMu != nil {
+ testHookOnPanicMu.Lock()
+ defer testHookOnPanicMu.Unlock()
+ }
+ if testHookOnPanic != nil {
+ if e := recover(); e != nil {
+ if testHookOnPanic(sc, e) {
+ panic(e)
+ }
+ }
+ }
+}
+
+func (sc *serverConn) serve() {
+ sc.serveG.check()
+ defer sc.notePanic()
+ defer sc.conn.Close()
+ defer sc.closeAllStreamsOnConnClose()
+ defer sc.stopShutdownTimer()
+ defer close(sc.doneServing) // unblocks handlers trying to send
+
+ if VerboseLogs {
+ sc.vlogf("http2: server connection from %v on %p", sc.conn.RemoteAddr(), sc.hs)
+ }
+
+ sc.writeFrame(FrameWriteRequest{
+ write: writeSettings{
+ {SettingMaxFrameSize, sc.srv.maxReadFrameSize()},
+ {SettingMaxConcurrentStreams, sc.advMaxStreams},
+ {SettingMaxHeaderListSize, sc.maxHeaderListSize()},
+ {SettingInitialWindowSize, uint32(sc.srv.initialStreamRecvWindowSize())},
+ },
+ })
+ sc.unackedSettings++
+
+ // Each connection starts with intialWindowSize inflow tokens.
+ // If a higher value is configured, we add more tokens.
+ if diff := sc.srv.initialConnRecvWindowSize() - initialWindowSize; diff > 0 {
+ sc.sendWindowUpdate(nil, int(diff))
+ }
+
+ if err := sc.readPreface(); err != nil {
+ sc.condlogf(err, "http2: server: error reading preface from client %v: %v", sc.conn.RemoteAddr(), err)
+ return
+ }
+ // Now that we've got the preface, get us out of the
+ // "StateNew" state. We can't go directly to idle, though.
+ // Active means we read some data and anticipate a request. We'll
+ // do another Active when we get a HEADERS frame.
+ sc.setConnState(http.StateActive)
+ sc.setConnState(http.StateIdle)
+
+ if sc.srv.IdleTimeout != 0 {
+ sc.idleTimer = time.AfterFunc(sc.srv.IdleTimeout, sc.onIdleTimer)
+ defer sc.idleTimer.Stop()
+ }
+
+ go sc.readFrames() // closed by defer sc.conn.Close above
+
+ settingsTimer := time.AfterFunc(firstSettingsTimeout, sc.onSettingsTimer)
+ defer settingsTimer.Stop()
+
+ loopNum := 0
+ for {
+ loopNum++
+ select {
+ case wr := <-sc.wantWriteFrameCh:
+ if se, ok := wr.write.(StreamError); ok {
+ sc.resetStream(se)
+ break
+ }
+ sc.writeFrame(wr)
+ case res := <-sc.wroteFrameCh:
+ sc.wroteFrame(res)
+ case res := <-sc.readFrameCh:
+ if !sc.processFrameFromReader(res) {
+ return
+ }
+ res.readMore()
+ if settingsTimer != nil {
+ settingsTimer.Stop()
+ settingsTimer = nil
+ }
+ case m := <-sc.bodyReadCh:
+ sc.noteBodyRead(m.st, m.n)
+ case msg := <-sc.serveMsgCh:
+ switch v := msg.(type) {
+ case func(int):
+ v(loopNum) // for testing
+ case *serverMessage:
+ switch v {
+ case settingsTimerMsg:
+ sc.logf("timeout waiting for SETTINGS frames from %v", sc.conn.RemoteAddr())
+ return
+ case idleTimerMsg:
+ sc.vlogf("connection is idle")
+ sc.goAway(ErrCodeNo)
+ case shutdownTimerMsg:
+ sc.vlogf("GOAWAY close timer fired; closing conn from %v", sc.conn.RemoteAddr())
+ return
+ case gracefulShutdownMsg:
+ sc.startGracefulShutdownInternal()
+ default:
+ panic("unknown timer")
+ }
+ case *startPushRequest:
+ sc.startPush(v)
+ default:
+ panic(fmt.Sprintf("unexpected type %T", v))
+ }
+ }
+
+ // Start the shutdown timer after sending a GOAWAY. When sending GOAWAY
+ // with no error code (graceful shutdown), don't start the timer until
+ // all open streams have been completed.
+ sentGoAway := sc.inGoAway && !sc.needToSendGoAway && !sc.writingFrame
+ gracefulShutdownComplete := sc.goAwayCode == ErrCodeNo && sc.curOpenStreams() == 0
+ if sentGoAway && sc.shutdownTimer == nil && (sc.goAwayCode != ErrCodeNo || gracefulShutdownComplete) {
+ sc.shutDownIn(goAwayTimeout)
+ }
+ }
+}
+
+func (sc *serverConn) awaitGracefulShutdown(sharedCh <-chan struct{}, privateCh chan struct{}) {
+ select {
+ case <-sc.doneServing:
+ case <-sharedCh:
+ close(privateCh)
+ }
+}
+
+type serverMessage int
+
+// Message values sent to serveMsgCh.
+var (
+ settingsTimerMsg = new(serverMessage)
+ idleTimerMsg = new(serverMessage)
+ shutdownTimerMsg = new(serverMessage)
+ gracefulShutdownMsg = new(serverMessage)
+)
+
+func (sc *serverConn) onSettingsTimer() { sc.sendServeMsg(settingsTimerMsg) }
+func (sc *serverConn) onIdleTimer() { sc.sendServeMsg(idleTimerMsg) }
+func (sc *serverConn) onShutdownTimer() { sc.sendServeMsg(shutdownTimerMsg) }
+
+func (sc *serverConn) sendServeMsg(msg interface{}) {
+ sc.serveG.checkNotOn() // NOT
+ select {
+ case sc.serveMsgCh <- msg:
+ case <-sc.doneServing:
+ }
+}
+
+var errPrefaceTimeout = errors.New("timeout waiting for client preface")
+
+// readPreface reads the ClientPreface greeting from the peer or
+// returns errPrefaceTimeout on timeout, or an error if the greeting
+// is invalid.
+func (sc *serverConn) readPreface() error {
+ errc := make(chan error, 1)
+ go func() {
+ // Read the client preface
+ buf := make([]byte, len(ClientPreface))
+ if _, err := io.ReadFull(sc.conn, buf); err != nil {
+ errc <- err
+ } else if !bytes.Equal(buf, clientPreface) {
+ errc <- fmt.Errorf("bogus greeting %q", buf)
+ } else {
+ errc <- nil
+ }
+ }()
+ timer := time.NewTimer(prefaceTimeout) // TODO: configurable on *Server?
+ defer timer.Stop()
+ select {
+ case <-timer.C:
+ return errPrefaceTimeout
+ case err := <-errc:
+ if err == nil {
+ if VerboseLogs {
+ sc.vlogf("http2: server: client %v said hello", sc.conn.RemoteAddr())
+ }
+ }
+ return err
+ }
+}
+
+var errChanPool = sync.Pool{
+ New: func() interface{} { return make(chan error, 1) },
+}
+
+var writeDataPool = sync.Pool{
+ New: func() interface{} { return new(writeData) },
+}
+
+// writeDataFromHandler writes DATA response frames from a handler on
+// the given stream.
+func (sc *serverConn) writeDataFromHandler(stream *stream, data []byte, endStream bool) error {
+ ch := errChanPool.Get().(chan error)
+ writeArg := writeDataPool.Get().(*writeData)
+ *writeArg = writeData{stream.id, data, endStream}
+ err := sc.writeFrameFromHandler(FrameWriteRequest{
+ write: writeArg,
+ stream: stream,
+ done: ch,
+ })
+ if err != nil {
+ return err
+ }
+ var frameWriteDone bool // the frame write is done (successfully or not)
+ select {
+ case err = <-ch:
+ frameWriteDone = true
+ case <-sc.doneServing:
+ return errClientDisconnected
+ case <-stream.cw:
+ // If both ch and stream.cw were ready (as might
+ // happen on the final Write after an http.Handler
+ // ends), prefer the write result. Otherwise this
+ // might just be us successfully closing the stream.
+ // The writeFrameAsync and serve goroutines guarantee
+ // that the ch send will happen before the stream.cw
+ // close.
+ select {
+ case err = <-ch:
+ frameWriteDone = true
+ default:
+ return errStreamClosed
+ }
+ }
+ errChanPool.Put(ch)
+ if frameWriteDone {
+ writeDataPool.Put(writeArg)
+ }
+ return err
+}
+
+// writeFrameFromHandler sends wr to sc.wantWriteFrameCh, but aborts
+// if the connection has gone away.
+//
+// This must not be run from the serve goroutine itself, else it might
+// deadlock writing to sc.wantWriteFrameCh (which is only mildly
+// buffered and is read by serve itself). If you're on the serve
+// goroutine, call writeFrame instead.
+func (sc *serverConn) writeFrameFromHandler(wr FrameWriteRequest) error {
+ sc.serveG.checkNotOn() // NOT
+ select {
+ case sc.wantWriteFrameCh <- wr:
+ return nil
+ case <-sc.doneServing:
+ // Serve loop is gone.
+ // Client has closed their connection to the server.
+ return errClientDisconnected
+ }
+}
+
+// writeFrame schedules a frame to write and sends it if there's nothing
+// already being written.
+//
+// There is no pushback here (the serve goroutine never blocks). It's
+// the http.Handlers that block, waiting for their previous frames to
+// make it onto the wire
+//
+// If you're not on the serve goroutine, use writeFrameFromHandler instead.
+func (sc *serverConn) writeFrame(wr FrameWriteRequest) {
+ sc.serveG.check()
+
+ // If true, wr will not be written and wr.done will not be signaled.
+ var ignoreWrite bool
+
+ // We are not allowed to write frames on closed streams. RFC 7540 Section
+ // 5.1.1 says: "An endpoint MUST NOT send frames other than PRIORITY on
+ // a closed stream." Our server never sends PRIORITY, so that exception
+ // does not apply.
+ //
+ // The serverConn might close an open stream while the stream's handler
+ // is still running. For example, the server might close a stream when it
+ // receives bad data from the client. If this happens, the handler might
+ // attempt to write a frame after the stream has been closed (since the
+ // handler hasn't yet been notified of the close). In this case, we simply
+ // ignore the frame. The handler will notice that the stream is closed when
+ // it waits for the frame to be written.
+ //
+ // As an exception to this rule, we allow sending RST_STREAM after close.
+ // This allows us to immediately reject new streams without tracking any
+ // state for those streams (except for the queued RST_STREAM frame). This
+ // may result in duplicate RST_STREAMs in some cases, but the client should
+ // ignore those.
+ if wr.StreamID() != 0 {
+ _, isReset := wr.write.(StreamError)
+ if state, _ := sc.state(wr.StreamID()); state == stateClosed && !isReset {
+ ignoreWrite = true
+ }
+ }
+
+ // Don't send a 100-continue response if we've already sent headers.
+ // See golang.org/issue/14030.
+ switch wr.write.(type) {
+ case *writeResHeaders:
+ wr.stream.wroteHeaders = true
+ case write100ContinueHeadersFrame:
+ if wr.stream.wroteHeaders {
+ // We do not need to notify wr.done because this frame is
+ // never written with wr.done != nil.
+ if wr.done != nil {
+ panic("wr.done != nil for write100ContinueHeadersFrame")
+ }
+ ignoreWrite = true
+ }
+ }
+
+ if !ignoreWrite {
+ sc.writeSched.Push(wr)
+ }
+ sc.scheduleFrameWrite()
+}
+
+// startFrameWrite starts a goroutine to write wr (in a separate
+// goroutine since that might block on the network), and updates the
+// serve goroutine's state about the world, updated from info in wr.
+func (sc *serverConn) startFrameWrite(wr FrameWriteRequest) {
+ sc.serveG.check()
+ if sc.writingFrame {
+ panic("internal error: can only be writing one frame at a time")
+ }
+
+ st := wr.stream
+ if st != nil {
+ switch st.state {
+ case stateHalfClosedLocal:
+ switch wr.write.(type) {
+ case StreamError, handlerPanicRST, writeWindowUpdate:
+ // RFC 7540 Section 5.1 allows sending RST_STREAM, PRIORITY, and WINDOW_UPDATE
+ // in this state. (We never send PRIORITY from the server, so that is not checked.)
+ default:
+ panic(fmt.Sprintf("internal error: attempt to send frame on a half-closed-local stream: %v", wr))
+ }
+ case stateClosed:
+ panic(fmt.Sprintf("internal error: attempt to send frame on a closed stream: %v", wr))
+ }
+ }
+ if wpp, ok := wr.write.(*writePushPromise); ok {
+ var err error
+ wpp.promisedID, err = wpp.allocatePromisedID()
+ if err != nil {
+ sc.writingFrameAsync = false
+ wr.replyToWriter(err)
+ return
+ }
+ }
+
+ sc.writingFrame = true
+ sc.needsFrameFlush = true
+ if wr.write.staysWithinBuffer(sc.bw.Available()) {
+ sc.writingFrameAsync = false
+ err := wr.write.writeFrame(sc)
+ sc.wroteFrame(frameWriteResult{wr, err})
+ } else {
+ sc.writingFrameAsync = true
+ go sc.writeFrameAsync(wr)
+ }
+}
+
+// errHandlerPanicked is the error given to any callers blocked in a read from
+// Request.Body when the main goroutine panics. Since most handlers read in the
+// the main ServeHTTP goroutine, this will show up rarely.
+var errHandlerPanicked = errors.New("http2: handler panicked")
+
+// wroteFrame is called on the serve goroutine with the result of
+// whatever happened on writeFrameAsync.
+func (sc *serverConn) wroteFrame(res frameWriteResult) {
+ sc.serveG.check()
+ if !sc.writingFrame {
+ panic("internal error: expected to be already writing a frame")
+ }
+ sc.writingFrame = false
+ sc.writingFrameAsync = false
+
+ wr := res.wr
+
+ if writeEndsStream(wr.write) {
+ st := wr.stream
+ if st == nil {
+ panic("internal error: expecting non-nil stream")
+ }
+ switch st.state {
+ case stateOpen:
+ // Here we would go to stateHalfClosedLocal in
+ // theory, but since our handler is done and
+ // the net/http package provides no mechanism
+ // for closing a ResponseWriter while still
+ // reading data (see possible TODO at top of
+ // this file), we go into closed state here
+ // anyway, after telling the peer we're
+ // hanging up on them. We'll transition to
+ // stateClosed after the RST_STREAM frame is
+ // written.
+ st.state = stateHalfClosedLocal
+ // Section 8.1: a server MAY request that the client abort
+ // transmission of a request without error by sending a
+ // RST_STREAM with an error code of NO_ERROR after sending
+ // a complete response.
+ sc.resetStream(streamError(st.id, ErrCodeNo))
+ case stateHalfClosedRemote:
+ sc.closeStream(st, errHandlerComplete)
+ }
+ } else {
+ switch v := wr.write.(type) {
+ case StreamError:
+ // st may be unknown if the RST_STREAM was generated to reject bad input.
+ if st, ok := sc.streams[v.StreamID]; ok {
+ sc.closeStream(st, v)
+ }
+ case handlerPanicRST:
+ sc.closeStream(wr.stream, errHandlerPanicked)
+ }
+ }
+
+ // Reply (if requested) to unblock the ServeHTTP goroutine.
+ wr.replyToWriter(res.err)
+
+ sc.scheduleFrameWrite()
+}
+
+// scheduleFrameWrite tickles the frame writing scheduler.
+//
+// If a frame is already being written, nothing happens. This will be called again
+// when the frame is done being written.
+//
+// If a frame isn't being written we need to send one, the best frame
+// to send is selected, preferring first things that aren't
+// stream-specific (e.g. ACKing settings), and then finding the
+// highest priority stream.
+//
+// If a frame isn't being written and there's nothing else to send, we
+// flush the write buffer.
+func (sc *serverConn) scheduleFrameWrite() {
+ sc.serveG.check()
+ if sc.writingFrame || sc.inFrameScheduleLoop {
+ return
+ }
+ sc.inFrameScheduleLoop = true
+ for !sc.writingFrameAsync {
+ if sc.needToSendGoAway {
+ sc.needToSendGoAway = false
+ sc.startFrameWrite(FrameWriteRequest{
+ write: &writeGoAway{
+ maxStreamID: sc.maxClientStreamID,
+ code: sc.goAwayCode,
+ },
+ })
+ continue
+ }
+ if sc.needToSendSettingsAck {
+ sc.needToSendSettingsAck = false
+ sc.startFrameWrite(FrameWriteRequest{write: writeSettingsAck{}})
+ continue
+ }
+ if !sc.inGoAway || sc.goAwayCode == ErrCodeNo {
+ if wr, ok := sc.writeSched.Pop(); ok {
+ sc.startFrameWrite(wr)
+ continue
+ }
+ }
+ if sc.needsFrameFlush {
+ sc.startFrameWrite(FrameWriteRequest{write: flushFrameWriter{}})
+ sc.needsFrameFlush = false // after startFrameWrite, since it sets this true
+ continue
+ }
+ break
+ }
+ sc.inFrameScheduleLoop = false
+}
+
+// startGracefulShutdown gracefully shuts down a connection. This
+// sends GOAWAY with ErrCodeNo to tell the client we're gracefully
+// shutting down. The connection isn't closed until all current
+// streams are done.
+//
+// startGracefulShutdown returns immediately; it does not wait until
+// the connection has shut down.
+func (sc *serverConn) startGracefulShutdown() {
+ sc.serveG.checkNotOn() // NOT
+ sc.shutdownOnce.Do(func() { sc.sendServeMsg(gracefulShutdownMsg) })
+}
+
+// After sending GOAWAY, the connection will close after goAwayTimeout.
+// If we close the connection immediately after sending GOAWAY, there may
+// be unsent data in our kernel receive buffer, which will cause the kernel
+// to send a TCP RST on close() instead of a FIN. This RST will abort the
+// connection immediately, whether or not the client had received the GOAWAY.
+//
+// Ideally we should delay for at least 1 RTT + epsilon so the client has
+// a chance to read the GOAWAY and stop sending messages. Measuring RTT
+// is hard, so we approximate with 1 second. See golang.org/issue/18701.
+//
+// This is a var so it can be shorter in tests, where all requests uses the
+// loopback interface making the expected RTT very small.
+//
+// TODO: configurable?
+var goAwayTimeout = 1 * time.Second
+
+func (sc *serverConn) startGracefulShutdownInternal() {
+ sc.goAway(ErrCodeNo)
+}
+
+func (sc *serverConn) goAway(code ErrCode) {
+ sc.serveG.check()
+ if sc.inGoAway {
+ return
+ }
+ sc.inGoAway = true
+ sc.needToSendGoAway = true
+ sc.goAwayCode = code
+ sc.scheduleFrameWrite()
+}
+
+func (sc *serverConn) shutDownIn(d time.Duration) {
+ sc.serveG.check()
+ sc.shutdownTimer = time.AfterFunc(d, sc.onShutdownTimer)
+}
+
+func (sc *serverConn) resetStream(se StreamError) {
+ sc.serveG.check()
+ sc.writeFrame(FrameWriteRequest{write: se})
+ if st, ok := sc.streams[se.StreamID]; ok {
+ st.resetQueued = true
+ }
+}
+
+// processFrameFromReader processes the serve loop's read from readFrameCh from the
+// frame-reading goroutine.
+// processFrameFromReader returns whether the connection should be kept open.
+func (sc *serverConn) processFrameFromReader(res readFrameResult) bool {
+ sc.serveG.check()
+ err := res.err
+ if err != nil {
+ if err == ErrFrameTooLarge {
+ sc.goAway(ErrCodeFrameSize)
+ return true // goAway will close the loop
+ }
+ clientGone := err == io.EOF || err == io.ErrUnexpectedEOF || isClosedConnError(err)
+ if clientGone {
+ // TODO: could we also get into this state if
+ // the peer does a half close
+ // (e.g. CloseWrite) because they're done
+ // sending frames but they're still wanting
+ // our open replies? Investigate.
+ // TODO: add CloseWrite to crypto/tls.Conn first
+ // so we have a way to test this? I suppose
+ // just for testing we could have a non-TLS mode.
+ return false
+ }
+ } else {
+ f := res.f
+ if VerboseLogs {
+ sc.vlogf("http2: server read frame %v", summarizeFrame(f))
+ }
+ err = sc.processFrame(f)
+ if err == nil {
+ return true
+ }
+ }
+
+ switch ev := err.(type) {
+ case StreamError:
+ sc.resetStream(ev)
+ return true
+ case goAwayFlowError:
+ sc.goAway(ErrCodeFlowControl)
+ return true
+ case ConnectionError:
+ sc.logf("http2: server connection error from %v: %v", sc.conn.RemoteAddr(), ev)
+ sc.goAway(ErrCode(ev))
+ return true // goAway will handle shutdown
+ default:
+ if res.err != nil {
+ sc.vlogf("http2: server closing client connection; error reading frame from client %s: %v", sc.conn.RemoteAddr(), err)
+ } else {
+ sc.logf("http2: server closing client connection: %v", err)
+ }
+ return false
+ }
+}
+
+func (sc *serverConn) processFrame(f Frame) error {
+ sc.serveG.check()
+
+ // First frame received must be SETTINGS.
+ if !sc.sawFirstSettings {
+ if _, ok := f.(*SettingsFrame); !ok {
+ return ConnectionError(ErrCodeProtocol)
+ }
+ sc.sawFirstSettings = true
+ }
+
+ switch f := f.(type) {
+ case *SettingsFrame:
+ return sc.processSettings(f)
+ case *MetaHeadersFrame:
+ return sc.processHeaders(f)
+ case *WindowUpdateFrame:
+ return sc.processWindowUpdate(f)
+ case *PingFrame:
+ return sc.processPing(f)
+ case *DataFrame:
+ return sc.processData(f)
+ case *RSTStreamFrame:
+ return sc.processResetStream(f)
+ case *PriorityFrame:
+ return sc.processPriority(f)
+ case *GoAwayFrame:
+ return sc.processGoAway(f)
+ case *PushPromiseFrame:
+ // A client cannot push. Thus, servers MUST treat the receipt of a PUSH_PROMISE
+ // frame as a connection error (Section 5.4.1) of type PROTOCOL_ERROR.
+ return ConnectionError(ErrCodeProtocol)
+ default:
+ sc.vlogf("http2: server ignoring frame: %v", f.Header())
+ return nil
+ }
+}
+
+func (sc *serverConn) processPing(f *PingFrame) error {
+ sc.serveG.check()
+ if f.IsAck() {
+ // 6.7 PING: " An endpoint MUST NOT respond to PING frames
+ // containing this flag."
+ return nil
+ }
+ if f.StreamID != 0 {
+ // "PING frames are not associated with any individual
+ // stream. If a PING frame is received with a stream
+ // identifier field value other than 0x0, the recipient MUST
+ // respond with a connection error (Section 5.4.1) of type
+ // PROTOCOL_ERROR."
+ return ConnectionError(ErrCodeProtocol)
+ }
+ if sc.inGoAway && sc.goAwayCode != ErrCodeNo {
+ return nil
+ }
+ sc.writeFrame(FrameWriteRequest{write: writePingAck{f}})
+ return nil
+}
+
+func (sc *serverConn) processWindowUpdate(f *WindowUpdateFrame) error {
+ sc.serveG.check()
+ switch {
+ case f.StreamID != 0: // stream-level flow control
+ state, st := sc.state(f.StreamID)
+ if state == stateIdle {
+ // Section 5.1: "Receiving any frame other than HEADERS
+ // or PRIORITY on a stream in this state MUST be
+ // treated as a connection error (Section 5.4.1) of
+ // type PROTOCOL_ERROR."
+ return ConnectionError(ErrCodeProtocol)
+ }
+ if st == nil {
+ // "WINDOW_UPDATE can be sent by a peer that has sent a
+ // frame bearing the END_STREAM flag. This means that a
+ // receiver could receive a WINDOW_UPDATE frame on a "half
+ // closed (remote)" or "closed" stream. A receiver MUST
+ // NOT treat this as an error, see Section 5.1."
+ return nil
+ }
+ if !st.flow.add(int32(f.Increment)) {
+ return streamError(f.StreamID, ErrCodeFlowControl)
+ }
+ default: // connection-level flow control
+ if !sc.flow.add(int32(f.Increment)) {
+ return goAwayFlowError{}
+ }
+ }
+ sc.scheduleFrameWrite()
+ return nil
+}
+
+func (sc *serverConn) processResetStream(f *RSTStreamFrame) error {
+ sc.serveG.check()
+
+ state, st := sc.state(f.StreamID)
+ if state == stateIdle {
+ // 6.4 "RST_STREAM frames MUST NOT be sent for a
+ // stream in the "idle" state. If a RST_STREAM frame
+ // identifying an idle stream is received, the
+ // recipient MUST treat this as a connection error
+ // (Section 5.4.1) of type PROTOCOL_ERROR.
+ return ConnectionError(ErrCodeProtocol)
+ }
+ if st != nil {
+ st.cancelCtx()
+ sc.closeStream(st, streamError(f.StreamID, f.ErrCode))
+ }
+ return nil
+}
+
+func (sc *serverConn) closeStream(st *stream, err error) {
+ sc.serveG.check()
+ if st.state == stateIdle || st.state == stateClosed {
+ panic(fmt.Sprintf("invariant; can't close stream in state %v", st.state))
+ }
+ st.state = stateClosed
+ if st.writeDeadline != nil {
+ st.writeDeadline.Stop()
+ }
+ if st.isPushed() {
+ sc.curPushedStreams--
+ } else {
+ sc.curClientStreams--
+ }
+ delete(sc.streams, st.id)
+ if len(sc.streams) == 0 {
+ sc.setConnState(http.StateIdle)
+ if sc.srv.IdleTimeout != 0 {
+ sc.idleTimer.Reset(sc.srv.IdleTimeout)
+ }
+ if h1ServerKeepAlivesDisabled(sc.hs) {
+ sc.startGracefulShutdownInternal()
+ }
+ }
+ if p := st.body; p != nil {
+ // Return any buffered unread bytes worth of conn-level flow control.
+ // See golang.org/issue/16481
+ sc.sendWindowUpdate(nil, p.Len())
+
+ p.CloseWithError(err)
+ }
+ st.cw.Close() // signals Handler's CloseNotifier, unblocks writes, etc
+ sc.writeSched.CloseStream(st.id)
+}
+
+func (sc *serverConn) processSettings(f *SettingsFrame) error {
+ sc.serveG.check()
+ if f.IsAck() {
+ sc.unackedSettings--
+ if sc.unackedSettings < 0 {
+ // Why is the peer ACKing settings we never sent?
+ // The spec doesn't mention this case, but
+ // hang up on them anyway.
+ return ConnectionError(ErrCodeProtocol)
+ }
+ return nil
+ }
+ if err := f.ForeachSetting(sc.processSetting); err != nil {
+ return err
+ }
+ sc.needToSendSettingsAck = true
+ sc.scheduleFrameWrite()
+ return nil
+}
+
+func (sc *serverConn) processSetting(s Setting) error {
+ sc.serveG.check()
+ if err := s.Valid(); err != nil {
+ return err
+ }
+ if VerboseLogs {
+ sc.vlogf("http2: server processing setting %v", s)
+ }
+ switch s.ID {
+ case SettingHeaderTableSize:
+ sc.headerTableSize = s.Val
+ sc.hpackEncoder.SetMaxDynamicTableSize(s.Val)
+ case SettingEnablePush:
+ sc.pushEnabled = s.Val != 0
+ case SettingMaxConcurrentStreams:
+ sc.clientMaxStreams = s.Val
+ case SettingInitialWindowSize:
+ return sc.processSettingInitialWindowSize(s.Val)
+ case SettingMaxFrameSize:
+ sc.maxFrameSize = int32(s.Val) // the maximum valid s.Val is < 2^31
+ case SettingMaxHeaderListSize:
+ sc.peerMaxHeaderListSize = s.Val
+ default:
+ // Unknown setting: "An endpoint that receives a SETTINGS
+ // frame with any unknown or unsupported identifier MUST
+ // ignore that setting."
+ if VerboseLogs {
+ sc.vlogf("http2: server ignoring unknown setting %v", s)
+ }
+ }
+ return nil
+}
+
+func (sc *serverConn) processSettingInitialWindowSize(val uint32) error {
+ sc.serveG.check()
+ // Note: val already validated to be within range by
+ // processSetting's Valid call.
+
+ // "A SETTINGS frame can alter the initial flow control window
+ // size for all current streams. When the value of
+ // SETTINGS_INITIAL_WINDOW_SIZE changes, a receiver MUST
+ // adjust the size of all stream flow control windows that it
+ // maintains by the difference between the new value and the
+ // old value."
+ old := sc.initialStreamSendWindowSize
+ sc.initialStreamSendWindowSize = int32(val)
+ growth := int32(val) - old // may be negative
+ for _, st := range sc.streams {
+ if !st.flow.add(growth) {
+ // 6.9.2 Initial Flow Control Window Size
+ // "An endpoint MUST treat a change to
+ // SETTINGS_INITIAL_WINDOW_SIZE that causes any flow
+ // control window to exceed the maximum size as a
+ // connection error (Section 5.4.1) of type
+ // FLOW_CONTROL_ERROR."
+ return ConnectionError(ErrCodeFlowControl)
+ }
+ }
+ return nil
+}
+
+func (sc *serverConn) processData(f *DataFrame) error {
+ sc.serveG.check()
+ if sc.inGoAway && sc.goAwayCode != ErrCodeNo {
+ return nil
+ }
+ data := f.Data()
+
+ // "If a DATA frame is received whose stream is not in "open"
+ // or "half closed (local)" state, the recipient MUST respond
+ // with a stream error (Section 5.4.2) of type STREAM_CLOSED."
+ id := f.Header().StreamID
+ state, st := sc.state(id)
+ if id == 0 || state == stateIdle {
+ // Section 5.1: "Receiving any frame other than HEADERS
+ // or PRIORITY on a stream in this state MUST be
+ // treated as a connection error (Section 5.4.1) of
+ // type PROTOCOL_ERROR."
+ return ConnectionError(ErrCodeProtocol)
+ }
+ if st == nil || state != stateOpen || st.gotTrailerHeader || st.resetQueued {
+ // This includes sending a RST_STREAM if the stream is
+ // in stateHalfClosedLocal (which currently means that
+ // the http.Handler returned, so it's done reading &
+ // done writing). Try to stop the client from sending
+ // more DATA.
+
+ // But still enforce their connection-level flow control,
+ // and return any flow control bytes since we're not going
+ // to consume them.
+ if sc.inflow.available() < int32(f.Length) {
+ return streamError(id, ErrCodeFlowControl)
+ }
+ // Deduct the flow control from inflow, since we're
+ // going to immediately add it back in
+ // sendWindowUpdate, which also schedules sending the
+ // frames.
+ sc.inflow.take(int32(f.Length))
+ sc.sendWindowUpdate(nil, int(f.Length)) // conn-level
+
+ if st != nil && st.resetQueued {
+ // Already have a stream error in flight. Don't send another.
+ return nil
+ }
+ return streamError(id, ErrCodeStreamClosed)
+ }
+ if st.body == nil {
+ panic("internal error: should have a body in this state")
+ }
+
+ // Sender sending more than they'd declared?
+ if st.declBodyBytes != -1 && st.bodyBytes+int64(len(data)) > st.declBodyBytes {
+ st.body.CloseWithError(fmt.Errorf("sender tried to send more than declared Content-Length of %d bytes", st.declBodyBytes))
+ return streamError(id, ErrCodeStreamClosed)
+ }
+ if f.Length > 0 {
+ // Check whether the client has flow control quota.
+ if st.inflow.available() < int32(f.Length) {
+ return streamError(id, ErrCodeFlowControl)
+ }
+ st.inflow.take(int32(f.Length))
+
+ if len(data) > 0 {
+ wrote, err := st.body.Write(data)
+ if err != nil {
+ return streamError(id, ErrCodeStreamClosed)
+ }
+ if wrote != len(data) {
+ panic("internal error: bad Writer")
+ }
+ st.bodyBytes += int64(len(data))
+ }
+
+ // Return any padded flow control now, since we won't
+ // refund it later on body reads.
+ if pad := int32(f.Length) - int32(len(data)); pad > 0 {
+ sc.sendWindowUpdate32(nil, pad)
+ sc.sendWindowUpdate32(st, pad)
+ }
+ }
+ if f.StreamEnded() {
+ st.endStream()
+ }
+ return nil
+}
+
+func (sc *serverConn) processGoAway(f *GoAwayFrame) error {
+ sc.serveG.check()
+ if f.ErrCode != ErrCodeNo {
+ sc.logf("http2: received GOAWAY %+v, starting graceful shutdown", f)
+ } else {
+ sc.vlogf("http2: received GOAWAY %+v, starting graceful shutdown", f)
+ }
+ sc.startGracefulShutdownInternal()
+ // http://tools.ietf.org/html/rfc7540#section-6.8
+ // We should not create any new streams, which means we should disable push.
+ sc.pushEnabled = false
+ return nil
+}
+
+// isPushed reports whether the stream is server-initiated.
+func (st *stream) isPushed() bool {
+ return st.id%2 == 0
+}
+
+// endStream closes a Request.Body's pipe. It is called when a DATA
+// frame says a request body is over (or after trailers).
+func (st *stream) endStream() {
+ sc := st.sc
+ sc.serveG.check()
+
+ if st.declBodyBytes != -1 && st.declBodyBytes != st.bodyBytes {
+ st.body.CloseWithError(fmt.Errorf("request declared a Content-Length of %d but only wrote %d bytes",
+ st.declBodyBytes, st.bodyBytes))
+ } else {
+ st.body.closeWithErrorAndCode(io.EOF, st.copyTrailersToHandlerRequest)
+ st.body.CloseWithError(io.EOF)
+ }
+ st.state = stateHalfClosedRemote
+}
+
+// copyTrailersToHandlerRequest is run in the Handler's goroutine in
+// its Request.Body.Read just before it gets io.EOF.
+func (st *stream) copyTrailersToHandlerRequest() {
+ for k, vv := range st.trailer {
+ if _, ok := st.reqTrailer[k]; ok {
+ // Only copy it over it was pre-declared.
+ st.reqTrailer[k] = vv
+ }
+ }
+}
+
+// onWriteTimeout is run on its own goroutine (from time.AfterFunc)
+// when the stream's WriteTimeout has fired.
+func (st *stream) onWriteTimeout() {
+ st.sc.writeFrameFromHandler(FrameWriteRequest{write: streamError(st.id, ErrCodeInternal)})
+}
+
+func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
+ sc.serveG.check()
+ id := f.StreamID
+ if sc.inGoAway {
+ // Ignore.
+ return nil
+ }
+ // http://tools.ietf.org/html/rfc7540#section-5.1.1
+ // Streams initiated by a client MUST use odd-numbered stream
+ // identifiers. [...] An endpoint that receives an unexpected
+ // stream identifier MUST respond with a connection error
+ // (Section 5.4.1) of type PROTOCOL_ERROR.
+ if id%2 != 1 {
+ return ConnectionError(ErrCodeProtocol)
+ }
+ // A HEADERS frame can be used to create a new stream or
+ // send a trailer for an open one. If we already have a stream
+ // open, let it process its own HEADERS frame (trailers at this
+ // point, if it's valid).
+ if st := sc.streams[f.StreamID]; st != nil {
+ if st.resetQueued {
+ // We're sending RST_STREAM to close the stream, so don't bother
+ // processing this frame.
+ return nil
+ }
+ return st.processTrailerHeaders(f)
+ }
+
+ // [...] The identifier of a newly established stream MUST be
+ // numerically greater than all streams that the initiating
+ // endpoint has opened or reserved. [...] An endpoint that
+ // receives an unexpected stream identifier MUST respond with
+ // a connection error (Section 5.4.1) of type PROTOCOL_ERROR.
+ if id <= sc.maxClientStreamID {
+ return ConnectionError(ErrCodeProtocol)
+ }
+ sc.maxClientStreamID = id
+
+ if sc.idleTimer != nil {
+ sc.idleTimer.Stop()
+ }
+
+ // http://tools.ietf.org/html/rfc7540#section-5.1.2
+ // [...] Endpoints MUST NOT exceed the limit set by their peer. An
+ // endpoint that receives a HEADERS frame that causes their
+ // advertised concurrent stream limit to be exceeded MUST treat
+ // this as a stream error (Section 5.4.2) of type PROTOCOL_ERROR
+ // or REFUSED_STREAM.
+ if sc.curClientStreams+1 > sc.advMaxStreams {
+ if sc.unackedSettings == 0 {
+ // They should know better.
+ return streamError(id, ErrCodeProtocol)
+ }
+ // Assume it's a network race, where they just haven't
+ // received our last SETTINGS update. But actually
+ // this can't happen yet, because we don't yet provide
+ // a way for users to adjust server parameters at
+ // runtime.
+ return streamError(id, ErrCodeRefusedStream)
+ }
+
+ initialState := stateOpen
+ if f.StreamEnded() {
+ initialState = stateHalfClosedRemote
+ }
+ st := sc.newStream(id, 0, initialState)
+
+ if f.HasPriority() {
+ if err := checkPriority(f.StreamID, f.Priority); err != nil {
+ return err
+ }
+ sc.writeSched.AdjustStream(st.id, f.Priority)
+ }
+
+ rw, req, err := sc.newWriterAndRequest(st, f)
+ if err != nil {
+ return err
+ }
+ st.reqTrailer = req.Trailer
+ if st.reqTrailer != nil {
+ st.trailer = make(http.Header)
+ }
+ st.body = req.Body.(*requestBody).pipe // may be nil
+ st.declBodyBytes = req.ContentLength
+
+ handler := sc.handler.ServeHTTP
+ if f.Truncated {
+ // Their header list was too long. Send a 431 error.
+ handler = handleHeaderListTooLong
+ } else if err := checkValidHTTP2RequestHeaders(req.Header); err != nil {
+ handler = new400Handler(err)
+ }
+
+ // The net/http package sets the read deadline from the
+ // http.Server.ReadTimeout during the TLS handshake, but then
+ // passes the connection off to us with the deadline already
+ // set. Disarm it here after the request headers are read,
+ // similar to how the http1 server works. Here it's
+ // technically more like the http1 Server's ReadHeaderTimeout
+ // (in Go 1.8), though. That's a more sane option anyway.
+ if sc.hs.ReadTimeout != 0 {
+ sc.conn.SetReadDeadline(time.Time{})
+ }
+
+ go sc.runHandler(rw, req, handler)
+ return nil
+}
+
+func (st *stream) processTrailerHeaders(f *MetaHeadersFrame) error {
+ sc := st.sc
+ sc.serveG.check()
+ if st.gotTrailerHeader {
+ return ConnectionError(ErrCodeProtocol)
+ }
+ st.gotTrailerHeader = true
+ if !f.StreamEnded() {
+ return streamError(st.id, ErrCodeProtocol)
+ }
+
+ if len(f.PseudoFields()) > 0 {
+ return streamError(st.id, ErrCodeProtocol)
+ }
+ if st.trailer != nil {
+ for _, hf := range f.RegularFields() {
+ key := sc.canonicalHeader(hf.Name)
+ if !ValidTrailerHeader(key) {
+ // TODO: send more details to the peer somehow. But http2 has
+ // no way to send debug data at a stream level. Discuss with
+ // HTTP folk.
+ return streamError(st.id, ErrCodeProtocol)
+ }
+ st.trailer[key] = append(st.trailer[key], hf.Value)
+ }
+ }
+ st.endStream()
+ return nil
+}
+
+func checkPriority(streamID uint32, p PriorityParam) error {
+ if streamID == p.StreamDep {
+ // Section 5.3.1: "A stream cannot depend on itself. An endpoint MUST treat
+ // this as a stream error (Section 5.4.2) of type PROTOCOL_ERROR."
+ // Section 5.3.3 says that a stream can depend on one of its dependencies,
+ // so it's only self-dependencies that are forbidden.
+ return streamError(streamID, ErrCodeProtocol)
+ }
+ return nil
+}
+
+func (sc *serverConn) processPriority(f *PriorityFrame) error {
+ if sc.inGoAway {
+ return nil
+ }
+ if err := checkPriority(f.StreamID, f.PriorityParam); err != nil {
+ return err
+ }
+ sc.writeSched.AdjustStream(f.StreamID, f.PriorityParam)
+ return nil
+}
+
+func (sc *serverConn) newStream(id, pusherID uint32, state streamState) *stream {
+ sc.serveG.check()
+ if id == 0 {
+ panic("internal error: cannot create stream with id 0")
+ }
+
+ ctx, cancelCtx := contextWithCancel(sc.baseCtx)
+ st := &stream{
+ sc: sc,
+ id: id,
+ state: state,
+ ctx: ctx,
+ cancelCtx: cancelCtx,
+ }
+ st.cw.Init()
+ st.flow.conn = &sc.flow // link to conn-level counter
+ st.flow.add(sc.initialStreamSendWindowSize)
+ st.inflow.conn = &sc.inflow // link to conn-level counter
+ st.inflow.add(sc.srv.initialStreamRecvWindowSize())
+ if sc.hs.WriteTimeout != 0 {
+ st.writeDeadline = time.AfterFunc(sc.hs.WriteTimeout, st.onWriteTimeout)
+ }
+
+ sc.streams[id] = st
+ sc.writeSched.OpenStream(st.id, OpenStreamOptions{PusherID: pusherID})
+ if st.isPushed() {
+ sc.curPushedStreams++
+ } else {
+ sc.curClientStreams++
+ }
+ if sc.curOpenStreams() == 1 {
+ sc.setConnState(http.StateActive)
+ }
+
+ return st
+}
+
+func (sc *serverConn) newWriterAndRequest(st *stream, f *MetaHeadersFrame) (*responseWriter, *http.Request, error) {
+ sc.serveG.check()
+
+ rp := requestParam{
+ method: f.PseudoValue("method"),
+ scheme: f.PseudoValue("scheme"),
+ authority: f.PseudoValue("authority"),
+ path: f.PseudoValue("path"),
+ }
+
+ isConnect := rp.method == "CONNECT"
+ if isConnect {
+ if rp.path != "" || rp.scheme != "" || rp.authority == "" {
+ return nil, nil, streamError(f.StreamID, ErrCodeProtocol)
+ }
+ } else if rp.method == "" || rp.path == "" || (rp.scheme != "https" && rp.scheme != "http") {
+ // See 8.1.2.6 Malformed Requests and Responses:
+ //
+ // Malformed requests or responses that are detected
+ // MUST be treated as a stream error (Section 5.4.2)
+ // of type PROTOCOL_ERROR."
+ //
+ // 8.1.2.3 Request Pseudo-Header Fields
+ // "All HTTP/2 requests MUST include exactly one valid
+ // value for the :method, :scheme, and :path
+ // pseudo-header fields"
+ return nil, nil, streamError(f.StreamID, ErrCodeProtocol)
+ }
+
+ bodyOpen := !f.StreamEnded()
+ if rp.method == "HEAD" && bodyOpen {
+ // HEAD requests can't have bodies
+ return nil, nil, streamError(f.StreamID, ErrCodeProtocol)
+ }
+
+ rp.header = make(http.Header)
+ for _, hf := range f.RegularFields() {
+ rp.header.Add(sc.canonicalHeader(hf.Name), hf.Value)
+ }
+ if rp.authority == "" {
+ rp.authority = rp.header.Get("Host")
+ }
+
+ rw, req, err := sc.newWriterAndRequestNoBody(st, rp)
+ if err != nil {
+ return nil, nil, err
+ }
+ if bodyOpen {
+ if vv, ok := rp.header["Content-Length"]; ok {
+ req.ContentLength, _ = strconv.ParseInt(vv[0], 10, 64)
+ } else {
+ req.ContentLength = -1
+ }
+ req.Body.(*requestBody).pipe = &pipe{
+ b: &dataBuffer{expected: req.ContentLength},
+ }
+ }
+ return rw, req, nil
+}
+
+type requestParam struct {
+ method string
+ scheme, authority, path string
+ header http.Header
+}
+
+func (sc *serverConn) newWriterAndRequestNoBody(st *stream, rp requestParam) (*responseWriter, *http.Request, error) {
+ sc.serveG.check()
+
+ var tlsState *tls.ConnectionState // nil if not scheme https
+ if rp.scheme == "https" {
+ tlsState = sc.tlsState
+ }
+
+ needsContinue := rp.header.Get("Expect") == "100-continue"
+ if needsContinue {
+ rp.header.Del("Expect")
+ }
+ // Merge Cookie headers into one "; "-delimited value.
+ if cookies := rp.header["Cookie"]; len(cookies) > 1 {
+ rp.header.Set("Cookie", strings.Join(cookies, "; "))
+ }
+
+ // Setup Trailers
+ var trailer http.Header
+ for _, v := range rp.header["Trailer"] {
+ for _, key := range strings.Split(v, ",") {
+ key = http.CanonicalHeaderKey(strings.TrimSpace(key))
+ switch key {
+ case "Transfer-Encoding", "Trailer", "Content-Length":
+ // Bogus. (copy of http1 rules)
+ // Ignore.
+ default:
+ if trailer == nil {
+ trailer = make(http.Header)
+ }
+ trailer[key] = nil
+ }
+ }
+ }
+ delete(rp.header, "Trailer")
+
+ var url_ *url.URL
+ var requestURI string
+ if rp.method == "CONNECT" {
+ url_ = &url.URL{Host: rp.authority}
+ requestURI = rp.authority // mimic HTTP/1 server behavior
+ } else {
+ var err error
+ url_, err = url.ParseRequestURI(rp.path)
+ if err != nil {
+ return nil, nil, streamError(st.id, ErrCodeProtocol)
+ }
+ requestURI = rp.path
+ }
+
+ body := &requestBody{
+ conn: sc,
+ stream: st,
+ needsContinue: needsContinue,
+ }
+ req := &http.Request{
+ Method: rp.method,
+ URL: url_,
+ RemoteAddr: sc.remoteAddrStr,
+ Header: rp.header,
+ RequestURI: requestURI,
+ Proto: "HTTP/2.0",
+ ProtoMajor: 2,
+ ProtoMinor: 0,
+ TLS: tlsState,
+ Host: rp.authority,
+ Body: body,
+ Trailer: trailer,
+ }
+ req = requestWithContext(req, st.ctx)
+
+ rws := responseWriterStatePool.Get().(*responseWriterState)
+ bwSave := rws.bw
+ *rws = responseWriterState{} // zero all the fields
+ rws.conn = sc
+ rws.bw = bwSave
+ rws.bw.Reset(chunkWriter{rws})
+ rws.stream = st
+ rws.req = req
+ rws.body = body
+
+ rw := &responseWriter{rws: rws}
+ return rw, req, nil
+}
+
+// Run on its own goroutine.
+func (sc *serverConn) runHandler(rw *responseWriter, req *http.Request, handler func(http.ResponseWriter, *http.Request)) {
+ didPanic := true
+ defer func() {
+ rw.rws.stream.cancelCtx()
+ if didPanic {
+ e := recover()
+ sc.writeFrameFromHandler(FrameWriteRequest{
+ write: handlerPanicRST{rw.rws.stream.id},
+ stream: rw.rws.stream,
+ })
+ // Same as net/http:
+ if shouldLogPanic(e) {
+ const size = 64 << 10
+ buf := make([]byte, size)
+ buf = buf[:runtime.Stack(buf, false)]
+ sc.logf("http2: panic serving %v: %v\n%s", sc.conn.RemoteAddr(), e, buf)
+ }
+ return
+ }
+ rw.handlerDone()
+ }()
+ handler(rw, req)
+ didPanic = false
+}
+
+func handleHeaderListTooLong(w http.ResponseWriter, r *http.Request) {
+ // 10.5.1 Limits on Header Block Size:
+ // .. "A server that receives a larger header block than it is
+ // willing to handle can send an HTTP 431 (Request Header Fields Too
+ // Large) status code"
+ const statusRequestHeaderFieldsTooLarge = 431 // only in Go 1.6+
+ w.WriteHeader(statusRequestHeaderFieldsTooLarge)
+ io.WriteString(w, "<h1>HTTP Error 431</h1><p>Request Header Field(s) Too Large</p>")
+}
+
+// called from handler goroutines.
+// h may be nil.
+func (sc *serverConn) writeHeaders(st *stream, headerData *writeResHeaders) error {
+ sc.serveG.checkNotOn() // NOT on
+ var errc chan error
+ if headerData.h != nil {
+ // If there's a header map (which we don't own), so we have to block on
+ // waiting for this frame to be written, so an http.Flush mid-handler
+ // writes out the correct value of keys, before a handler later potentially
+ // mutates it.
+ errc = errChanPool.Get().(chan error)
+ }
+ if err := sc.writeFrameFromHandler(FrameWriteRequest{
+ write: headerData,
+ stream: st,
+ done: errc,
+ }); err != nil {
+ return err
+ }
+ if errc != nil {
+ select {
+ case err := <-errc:
+ errChanPool.Put(errc)
+ return err
+ case <-sc.doneServing:
+ return errClientDisconnected
+ case <-st.cw:
+ return errStreamClosed
+ }
+ }
+ return nil
+}
+
+// called from handler goroutines.
+func (sc *serverConn) write100ContinueHeaders(st *stream) {
+ sc.writeFrameFromHandler(FrameWriteRequest{
+ write: write100ContinueHeadersFrame{st.id},
+ stream: st,
+ })
+}
+
+// A bodyReadMsg tells the server loop that the http.Handler read n
+// bytes of the DATA from the client on the given stream.
+type bodyReadMsg struct {
+ st *stream
+ n int
+}
+
+// called from handler goroutines.
+// Notes that the handler for the given stream ID read n bytes of its body
+// and schedules flow control tokens to be sent.
+func (sc *serverConn) noteBodyReadFromHandler(st *stream, n int, err error) {
+ sc.serveG.checkNotOn() // NOT on
+ if n > 0 {
+ select {
+ case sc.bodyReadCh <- bodyReadMsg{st, n}:
+ case <-sc.doneServing:
+ }
+ }
+}
+
+func (sc *serverConn) noteBodyRead(st *stream, n int) {
+ sc.serveG.check()
+ sc.sendWindowUpdate(nil, n) // conn-level
+ if st.state != stateHalfClosedRemote && st.state != stateClosed {
+ // Don't send this WINDOW_UPDATE if the stream is closed
+ // remotely.
+ sc.sendWindowUpdate(st, n)
+ }
+}
+
+// st may be nil for conn-level
+func (sc *serverConn) sendWindowUpdate(st *stream, n int) {
+ sc.serveG.check()
+ // "The legal range for the increment to the flow control
+ // window is 1 to 2^31-1 (2,147,483,647) octets."
+ // A Go Read call on 64-bit machines could in theory read
+ // a larger Read than this. Very unlikely, but we handle it here
+ // rather than elsewhere for now.
+ const maxUint31 = 1<<31 - 1
+ for n >= maxUint31 {
+ sc.sendWindowUpdate32(st, maxUint31)
+ n -= maxUint31
+ }
+ sc.sendWindowUpdate32(st, int32(n))
+}
+
+// st may be nil for conn-level
+func (sc *serverConn) sendWindowUpdate32(st *stream, n int32) {
+ sc.serveG.check()
+ if n == 0 {
+ return
+ }
+ if n < 0 {
+ panic("negative update")
+ }
+ var streamID uint32
+ if st != nil {
+ streamID = st.id
+ }
+ sc.writeFrame(FrameWriteRequest{
+ write: writeWindowUpdate{streamID: streamID, n: uint32(n)},
+ stream: st,
+ })
+ var ok bool
+ if st == nil {
+ ok = sc.inflow.add(n)
+ } else {
+ ok = st.inflow.add(n)
+ }
+ if !ok {
+ panic("internal error; sent too many window updates without decrements?")
+ }
+}
+
+// requestBody is the Handler's Request.Body type.
+// Read and Close may be called concurrently.
+type requestBody struct {
+ stream *stream
+ conn *serverConn
+ closed bool // for use by Close only
+ sawEOF bool // for use by Read only
+ pipe *pipe // non-nil if we have a HTTP entity message body
+ needsContinue bool // need to send a 100-continue
+}
+
+func (b *requestBody) Close() error {
+ if b.pipe != nil && !b.closed {
+ b.pipe.BreakWithError(errClosedBody)
+ }
+ b.closed = true
+ return nil
+}
+
+func (b *requestBody) Read(p []byte) (n int, err error) {
+ if b.needsContinue {
+ b.needsContinue = false
+ b.conn.write100ContinueHeaders(b.stream)
+ }
+ if b.pipe == nil || b.sawEOF {
+ return 0, io.EOF
+ }
+ n, err = b.pipe.Read(p)
+ if err == io.EOF {
+ b.sawEOF = true
+ }
+ if b.conn == nil && inTests {
+ return
+ }
+ b.conn.noteBodyReadFromHandler(b.stream, n, err)
+ return
+}
+
+// responseWriter is the http.ResponseWriter implementation. It's
+// intentionally small (1 pointer wide) to minimize garbage. The
+// responseWriterState pointer inside is zeroed at the end of a
+// request (in handlerDone) and calls on the responseWriter thereafter
+// simply crash (caller's mistake), but the much larger responseWriterState
+// and buffers are reused between multiple requests.
+type responseWriter struct {
+ rws *responseWriterState
+}
+
+// Optional http.ResponseWriter interfaces implemented.
+var (
+ _ http.CloseNotifier = (*responseWriter)(nil)
+ _ http.Flusher = (*responseWriter)(nil)
+ _ stringWriter = (*responseWriter)(nil)
+)
+
+type responseWriterState struct {
+ // immutable within a request:
+ stream *stream
+ req *http.Request
+ body *requestBody // to close at end of request, if DATA frames didn't
+ conn *serverConn
+
+ // TODO: adjust buffer writing sizes based on server config, frame size updates from peer, etc
+ bw *bufio.Writer // writing to a chunkWriter{this *responseWriterState}
+
+ // mutated by http.Handler goroutine:
+ handlerHeader http.Header // nil until called
+ snapHeader http.Header // snapshot of handlerHeader at WriteHeader time
+ trailers []string // set in writeChunk
+ status int // status code passed to WriteHeader
+ wroteHeader bool // WriteHeader called (explicitly or implicitly). Not necessarily sent to user yet.
+ sentHeader bool // have we sent the header frame?
+ handlerDone bool // handler has finished
+ dirty bool // a Write failed; don't reuse this responseWriterState
+
+ sentContentLen int64 // non-zero if handler set a Content-Length header
+ wroteBytes int64
+
+ closeNotifierMu sync.Mutex // guards closeNotifierCh
+ closeNotifierCh chan bool // nil until first used
+}
+
+type chunkWriter struct{ rws *responseWriterState }
+
+func (cw chunkWriter) Write(p []byte) (n int, err error) { return cw.rws.writeChunk(p) }
+
+func (rws *responseWriterState) hasTrailers() bool { return len(rws.trailers) != 0 }
+
+// declareTrailer is called for each Trailer header when the
+// response header is written. It notes that a header will need to be
+// written in the trailers at the end of the response.
+func (rws *responseWriterState) declareTrailer(k string) {
+ k = http.CanonicalHeaderKey(k)
+ if !ValidTrailerHeader(k) {
+ // Forbidden by RFC 2616 14.40.
+ rws.conn.logf("ignoring invalid trailer %q", k)
+ return
+ }
+ if !strSliceContains(rws.trailers, k) {
+ rws.trailers = append(rws.trailers, k)
+ }
+}
+
+// writeChunk writes chunks from the bufio.Writer. But because
+// bufio.Writer may bypass its chunking, sometimes p may be
+// arbitrarily large.
+//
+// writeChunk is also responsible (on the first chunk) for sending the
+// HEADER response.
+func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
+ if !rws.wroteHeader {
+ rws.writeHeader(200)
+ }
+
+ isHeadResp := rws.req.Method == "HEAD"
+ if !rws.sentHeader {
+ rws.sentHeader = true
+ var ctype, clen string
+ if clen = rws.snapHeader.Get("Content-Length"); clen != "" {
+ rws.snapHeader.Del("Content-Length")
+ clen64, err := strconv.ParseInt(clen, 10, 64)
+ if err == nil && clen64 >= 0 {
+ rws.sentContentLen = clen64
+ } else {
+ clen = ""
+ }
+ }
+ if clen == "" && rws.handlerDone && bodyAllowedForStatus(rws.status) && (len(p) > 0 || !isHeadResp) {
+ clen = strconv.Itoa(len(p))
+ }
+ _, hasContentType := rws.snapHeader["Content-Type"]
+ if !hasContentType && bodyAllowedForStatus(rws.status) && len(p) > 0 {
+ ctype = http.DetectContentType(p)
+ }
+ var date string
+ if _, ok := rws.snapHeader["Date"]; !ok {
+ // TODO(bradfitz): be faster here, like net/http? measure.
+ date = time.Now().UTC().Format(http.TimeFormat)
+ }
+
+ for _, v := range rws.snapHeader["Trailer"] {
+ foreachHeaderElement(v, rws.declareTrailer)
+ }
+
+ endStream := (rws.handlerDone && !rws.hasTrailers() && len(p) == 0) || isHeadResp
+ err = rws.conn.writeHeaders(rws.stream, &writeResHeaders{
+ streamID: rws.stream.id,
+ httpResCode: rws.status,
+ h: rws.snapHeader,
+ endStream: endStream,
+ contentType: ctype,
+ contentLength: clen,
+ date: date,
+ })
+ if err != nil {
+ rws.dirty = true
+ return 0, err
+ }
+ if endStream {
+ return 0, nil
+ }
+ }
+ if isHeadResp {
+ return len(p), nil
+ }
+ if len(p) == 0 && !rws.handlerDone {
+ return 0, nil
+ }
+
+ if rws.handlerDone {
+ rws.promoteUndeclaredTrailers()
+ }
+
+ endStream := rws.handlerDone && !rws.hasTrailers()
+ if len(p) > 0 || endStream {
+ // only send a 0 byte DATA frame if we're ending the stream.
+ if err := rws.conn.writeDataFromHandler(rws.stream, p, endStream); err != nil {
+ rws.dirty = true
+ return 0, err
+ }
+ }
+
+ if rws.handlerDone && rws.hasTrailers() {
+ err = rws.conn.writeHeaders(rws.stream, &writeResHeaders{
+ streamID: rws.stream.id,
+ h: rws.handlerHeader,
+ trailers: rws.trailers,
+ endStream: true,
+ })
+ if err != nil {
+ rws.dirty = true
+ }
+ return len(p), err
+ }
+ return len(p), nil
+}
+
+// TrailerPrefix is a magic prefix for ResponseWriter.Header map keys
+// that, if present, signals that the map entry is actually for
+// the response trailers, and not the response headers. The prefix
+// is stripped after the ServeHTTP call finishes and the values are
+// sent in the trailers.
+//
+// This mechanism is intended only for trailers that are not known
+// prior to the headers being written. If the set of trailers is fixed
+// or known before the header is written, the normal Go trailers mechanism
+// is preferred:
+// https://golang.org/pkg/net/http/#ResponseWriter
+// https://golang.org/pkg/net/http/#example_ResponseWriter_trailers
+const TrailerPrefix = "Trailer:"
+
+// promoteUndeclaredTrailers permits http.Handlers to set trailers
+// after the header has already been flushed. Because the Go
+// ResponseWriter interface has no way to set Trailers (only the
+// Header), and because we didn't want to expand the ResponseWriter
+// interface, and because nobody used trailers, and because RFC 2616
+// says you SHOULD (but not must) predeclare any trailers in the
+// header, the official ResponseWriter rules said trailers in Go must
+// be predeclared, and then we reuse the same ResponseWriter.Header()
+// map to mean both Headers and Trailers. When it's time to write the
+// Trailers, we pick out the fields of Headers that were declared as
+// trailers. That worked for a while, until we found the first major
+// user of Trailers in the wild: gRPC (using them only over http2),
+// and gRPC libraries permit setting trailers mid-stream without
+// predeclarnig them. So: change of plans. We still permit the old
+// way, but we also permit this hack: if a Header() key begins with
+// "Trailer:", the suffix of that key is a Trailer. Because ':' is an
+// invalid token byte anyway, there is no ambiguity. (And it's already
+// filtered out) It's mildly hacky, but not terrible.
+//
+// This method runs after the Handler is done and promotes any Header
+// fields to be trailers.
+func (rws *responseWriterState) promoteUndeclaredTrailers() {
+ for k, vv := range rws.handlerHeader {
+ if !strings.HasPrefix(k, TrailerPrefix) {
+ continue
+ }
+ trailerKey := strings.TrimPrefix(k, TrailerPrefix)
+ rws.declareTrailer(trailerKey)
+ rws.handlerHeader[http.CanonicalHeaderKey(trailerKey)] = vv
+ }
+
+ if len(rws.trailers) > 1 {
+ sorter := sorterPool.Get().(*sorter)
+ sorter.SortStrings(rws.trailers)
+ sorterPool.Put(sorter)
+ }
+}
+
+func (w *responseWriter) Flush() {
+ rws := w.rws
+ if rws == nil {
+ panic("Header called after Handler finished")
+ }
+ if rws.bw.Buffered() > 0 {
+ if err := rws.bw.Flush(); err != nil {
+ // Ignore the error. The frame writer already knows.
+ return
+ }
+ } else {
+ // The bufio.Writer won't call chunkWriter.Write
+ // (writeChunk with zero bytes, so we have to do it
+ // ourselves to force the HTTP response header and/or
+ // final DATA frame (with END_STREAM) to be sent.
+ rws.writeChunk(nil)
+ }
+}
+
+func (w *responseWriter) CloseNotify() <-chan bool {
+ rws := w.rws
+ if rws == nil {
+ panic("CloseNotify called after Handler finished")
+ }
+ rws.closeNotifierMu.Lock()
+ ch := rws.closeNotifierCh
+ if ch == nil {
+ ch = make(chan bool, 1)
+ rws.closeNotifierCh = ch
+ cw := rws.stream.cw
+ go func() {
+ cw.Wait() // wait for close
+ ch <- true
+ }()
+ }
+ rws.closeNotifierMu.Unlock()
+ return ch
+}
+
+func (w *responseWriter) Header() http.Header {
+ rws := w.rws
+ if rws == nil {
+ panic("Header called after Handler finished")
+ }
+ if rws.handlerHeader == nil {
+ rws.handlerHeader = make(http.Header)
+ }
+ return rws.handlerHeader
+}
+
+// checkWriteHeaderCode is a copy of net/http's checkWriteHeaderCode.
+func checkWriteHeaderCode(code int) {
+ // Issue 22880: require valid WriteHeader status codes.
+ // For now we only enforce that it's three digits.
+ // In the future we might block things over 599 (600 and above aren't defined
+ // at http://httpwg.org/specs/rfc7231.html#status.codes)
+ // and we might block under 200 (once we have more mature 1xx support).
+ // But for now any three digits.
+ //
+ // We used to send "HTTP/1.1 000 0" on the wire in responses but there's
+ // no equivalent bogus thing we can realistically send in HTTP/2,
+ // so we'll consistently panic instead and help people find their bugs
+ // early. (We can't return an error from WriteHeader even if we wanted to.)
+ if code < 100 || code > 999 {
+ panic(fmt.Sprintf("invalid WriteHeader code %v", code))
+ }
+}
+
+func (w *responseWriter) WriteHeader(code int) {
+ checkWriteHeaderCode(code)
+ rws := w.rws
+ if rws == nil {
+ panic("WriteHeader called after Handler finished")
+ }
+ rws.writeHeader(code)
+}
+
+func (rws *responseWriterState) writeHeader(code int) {
+ if !rws.wroteHeader {
+ rws.wroteHeader = true
+ rws.status = code
+ if len(rws.handlerHeader) > 0 {
+ rws.snapHeader = cloneHeader(rws.handlerHeader)
+ }
+ }
+}
+
+func cloneHeader(h http.Header) http.Header {
+ h2 := make(http.Header, len(h))
+ for k, vv := range h {
+ vv2 := make([]string, len(vv))
+ copy(vv2, vv)
+ h2[k] = vv2
+ }
+ return h2
+}
+
+// The Life Of A Write is like this:
+//
+// * Handler calls w.Write or w.WriteString ->
+// * -> rws.bw (*bufio.Writer) ->
+// * (Handler might call Flush)
+// * -> chunkWriter{rws}
+// * -> responseWriterState.writeChunk(p []byte)
+// * -> responseWriterState.writeChunk (most of the magic; see comment there)
+func (w *responseWriter) Write(p []byte) (n int, err error) {
+ return w.write(len(p), p, "")
+}
+
+func (w *responseWriter) WriteString(s string) (n int, err error) {
+ return w.write(len(s), nil, s)
+}
+
+// either dataB or dataS is non-zero.
+func (w *responseWriter) write(lenData int, dataB []byte, dataS string) (n int, err error) {
+ rws := w.rws
+ if rws == nil {
+ panic("Write called after Handler finished")
+ }
+ if !rws.wroteHeader {
+ w.WriteHeader(200)
+ }
+ if !bodyAllowedForStatus(rws.status) {
+ return 0, http.ErrBodyNotAllowed
+ }
+ rws.wroteBytes += int64(len(dataB)) + int64(len(dataS)) // only one can be set
+ if rws.sentContentLen != 0 && rws.wroteBytes > rws.sentContentLen {
+ // TODO: send a RST_STREAM
+ return 0, errors.New("http2: handler wrote more than declared Content-Length")
+ }
+
+ if dataB != nil {
+ return rws.bw.Write(dataB)
+ } else {
+ return rws.bw.WriteString(dataS)
+ }
+}
+
+func (w *responseWriter) handlerDone() {
+ rws := w.rws
+ dirty := rws.dirty
+ rws.handlerDone = true
+ w.Flush()
+ w.rws = nil
+ if !dirty {
+ // Only recycle the pool if all prior Write calls to
+ // the serverConn goroutine completed successfully. If
+ // they returned earlier due to resets from the peer
+ // there might still be write goroutines outstanding
+ // from the serverConn referencing the rws memory. See
+ // issue 20704.
+ responseWriterStatePool.Put(rws)
+ }
+}
+
+// Push errors.
+var (
+ ErrRecursivePush = errors.New("http2: recursive push not allowed")
+ ErrPushLimitReached = errors.New("http2: push would exceed peer's SETTINGS_MAX_CONCURRENT_STREAMS")
+)
+
+// pushOptions is the internal version of http.PushOptions, which we
+// cannot include here because it's only defined in Go 1.8 and later.
+type pushOptions struct {
+ Method string
+ Header http.Header
+}
+
+func (w *responseWriter) push(target string, opts pushOptions) error {
+ st := w.rws.stream
+ sc := st.sc
+ sc.serveG.checkNotOn()
+
+ // No recursive pushes: "PUSH_PROMISE frames MUST only be sent on a peer-initiated stream."
+ // http://tools.ietf.org/html/rfc7540#section-6.6
+ if st.isPushed() {
+ return ErrRecursivePush
+ }
+
+ // Default options.
+ if opts.Method == "" {
+ opts.Method = "GET"
+ }
+ if opts.Header == nil {
+ opts.Header = http.Header{}
+ }
+ wantScheme := "http"
+ if w.rws.req.TLS != nil {
+ wantScheme = "https"
+ }
+
+ // Validate the request.
+ u, err := url.Parse(target)
+ if err != nil {
+ return err
+ }
+ if u.Scheme == "" {
+ if !strings.HasPrefix(target, "/") {
+ return fmt.Errorf("target must be an absolute URL or an absolute path: %q", target)
+ }
+ u.Scheme = wantScheme
+ u.Host = w.rws.req.Host
+ } else {
+ if u.Scheme != wantScheme {
+ return fmt.Errorf("cannot push URL with scheme %q from request with scheme %q", u.Scheme, wantScheme)
+ }
+ if u.Host == "" {
+ return errors.New("URL must have a host")
+ }
+ }
+ for k := range opts.Header {
+ if strings.HasPrefix(k, ":") {
+ return fmt.Errorf("promised request headers cannot include pseudo header %q", k)
+ }
+ // These headers are meaningful only if the request has a body,
+ // but PUSH_PROMISE requests cannot have a body.
+ // http://tools.ietf.org/html/rfc7540#section-8.2
+ // Also disallow Host, since the promised URL must be absolute.
+ switch strings.ToLower(k) {
+ case "content-length", "content-encoding", "trailer", "te", "expect", "host":
+ return fmt.Errorf("promised request headers cannot include %q", k)
+ }
+ }
+ if err := checkValidHTTP2RequestHeaders(opts.Header); err != nil {
+ return err
+ }
+
+ // The RFC effectively limits promised requests to GET and HEAD:
+ // "Promised requests MUST be cacheable [GET, HEAD, or POST], and MUST be safe [GET or HEAD]"
+ // http://tools.ietf.org/html/rfc7540#section-8.2
+ if opts.Method != "GET" && opts.Method != "HEAD" {
+ return fmt.Errorf("method %q must be GET or HEAD", opts.Method)
+ }
+
+ msg := &startPushRequest{
+ parent: st,
+ method: opts.Method,
+ url: u,
+ header: cloneHeader(opts.Header),
+ done: errChanPool.Get().(chan error),
+ }
+
+ select {
+ case <-sc.doneServing:
+ return errClientDisconnected
+ case <-st.cw:
+ return errStreamClosed
+ case sc.serveMsgCh <- msg:
+ }
+
+ select {
+ case <-sc.doneServing:
+ return errClientDisconnected
+ case <-st.cw:
+ return errStreamClosed
+ case err := <-msg.done:
+ errChanPool.Put(msg.done)
+ return err
+ }
+}
+
+type startPushRequest struct {
+ parent *stream
+ method string
+ url *url.URL
+ header http.Header
+ done chan error
+}
+
+func (sc *serverConn) startPush(msg *startPushRequest) {
+ sc.serveG.check()
+
+ // http://tools.ietf.org/html/rfc7540#section-6.6.
+ // PUSH_PROMISE frames MUST only be sent on a peer-initiated stream that
+ // is in either the "open" or "half-closed (remote)" state.
+ if msg.parent.state != stateOpen && msg.parent.state != stateHalfClosedRemote {
+ // responseWriter.Push checks that the stream is peer-initiaed.
+ msg.done <- errStreamClosed
+ return
+ }
+
+ // http://tools.ietf.org/html/rfc7540#section-6.6.
+ if !sc.pushEnabled {
+ msg.done <- http.ErrNotSupported
+ return
+ }
+
+ // PUSH_PROMISE frames must be sent in increasing order by stream ID, so
+ // we allocate an ID for the promised stream lazily, when the PUSH_PROMISE
+ // is written. Once the ID is allocated, we start the request handler.
+ allocatePromisedID := func() (uint32, error) {
+ sc.serveG.check()
+
+ // Check this again, just in case. Technically, we might have received
+ // an updated SETTINGS by the time we got around to writing this frame.
+ if !sc.pushEnabled {
+ return 0, http.ErrNotSupported
+ }
+ // http://tools.ietf.org/html/rfc7540#section-6.5.2.
+ if sc.curPushedStreams+1 > sc.clientMaxStreams {
+ return 0, ErrPushLimitReached
+ }
+
+ // http://tools.ietf.org/html/rfc7540#section-5.1.1.
+ // Streams initiated by the server MUST use even-numbered identifiers.
+ // A server that is unable to establish a new stream identifier can send a GOAWAY
+ // frame so that the client is forced to open a new connection for new streams.
+ if sc.maxPushPromiseID+2 >= 1<<31 {
+ sc.startGracefulShutdownInternal()
+ return 0, ErrPushLimitReached
+ }
+ sc.maxPushPromiseID += 2
+ promisedID := sc.maxPushPromiseID
+
+ // http://tools.ietf.org/html/rfc7540#section-8.2.
+ // Strictly speaking, the new stream should start in "reserved (local)", then
+ // transition to "half closed (remote)" after sending the initial HEADERS, but
+ // we start in "half closed (remote)" for simplicity.
+ // See further comments at the definition of stateHalfClosedRemote.
+ promised := sc.newStream(promisedID, msg.parent.id, stateHalfClosedRemote)
+ rw, req, err := sc.newWriterAndRequestNoBody(promised, requestParam{
+ method: msg.method,
+ scheme: msg.url.Scheme,
+ authority: msg.url.Host,
+ path: msg.url.RequestURI(),
+ header: cloneHeader(msg.header), // clone since handler runs concurrently with writing the PUSH_PROMISE
+ })
+ if err != nil {
+ // Should not happen, since we've already validated msg.url.
+ panic(fmt.Sprintf("newWriterAndRequestNoBody(%+v): %v", msg.url, err))
+ }
+
+ go sc.runHandler(rw, req, sc.handler.ServeHTTP)
+ return promisedID, nil
+ }
+
+ sc.writeFrame(FrameWriteRequest{
+ write: &writePushPromise{
+ streamID: msg.parent.id,
+ method: msg.method,
+ url: msg.url,
+ h: msg.header,
+ allocatePromisedID: allocatePromisedID,
+ },
+ stream: msg.parent,
+ done: msg.done,
+ })
+}
+
+// foreachHeaderElement splits v according to the "#rule" construction
+// in RFC 2616 section 2.1 and calls fn for each non-empty element.
+func foreachHeaderElement(v string, fn func(string)) {
+ v = textproto.TrimString(v)
+ if v == "" {
+ return
+ }
+ if !strings.Contains(v, ",") {
+ fn(v)
+ return
+ }
+ for _, f := range strings.Split(v, ",") {
+ if f = textproto.TrimString(f); f != "" {
+ fn(f)
+ }
+ }
+}
+
+// From http://httpwg.org/specs/rfc7540.html#rfc.section.8.1.2.2
+var connHeaders = []string{
+ "Connection",
+ "Keep-Alive",
+ "Proxy-Connection",
+ "Transfer-Encoding",
+ "Upgrade",
+}
+
+// checkValidHTTP2RequestHeaders checks whether h is a valid HTTP/2 request,
+// per RFC 7540 Section 8.1.2.2.
+// The returned error is reported to users.
+func checkValidHTTP2RequestHeaders(h http.Header) error {
+ for _, k := range connHeaders {
+ if _, ok := h[k]; ok {
+ return fmt.Errorf("request header %q is not valid in HTTP/2", k)
+ }
+ }
+ te := h["Te"]
+ if len(te) > 0 && (len(te) > 1 || (te[0] != "trailers" && te[0] != "")) {
+ return errors.New(`request header "TE" may only be "trailers" in HTTP/2`)
+ }
+ return nil
+}
+
+func new400Handler(err error) http.HandlerFunc {
+ return func(w http.ResponseWriter, r *http.Request) {
+ http.Error(w, err.Error(), http.StatusBadRequest)
+ }
+}
+
+// ValidTrailerHeader reports whether name is a valid header field name to appear
+// in trailers.
+// See: http://tools.ietf.org/html/rfc7230#section-4.1.2
+func ValidTrailerHeader(name string) bool {
+ name = http.CanonicalHeaderKey(name)
+ if strings.HasPrefix(name, "If-") || badTrailer[name] {
+ return false
+ }
+ return true
+}
+
+var badTrailer = map[string]bool{
+ "Authorization": true,
+ "Cache-Control": true,
+ "Connection": true,
+ "Content-Encoding": true,
+ "Content-Length": true,
+ "Content-Range": true,
+ "Content-Type": true,
+ "Expect": true,
+ "Host": true,
+ "Keep-Alive": true,
+ "Max-Forwards": true,
+ "Pragma": true,
+ "Proxy-Authenticate": true,
+ "Proxy-Authorization": true,
+ "Proxy-Connection": true,
+ "Range": true,
+ "Realm": true,
+ "Te": true,
+ "Trailer": true,
+ "Transfer-Encoding": true,
+ "Www-Authenticate": true,
+}
+
+// h1ServerKeepAlivesDisabled reports whether hs has its keep-alives
+// disabled. See comments on h1ServerShutdownChan above for why
+// the code is written this way.
+func h1ServerKeepAlivesDisabled(hs *http.Server) bool {
+ var x interface{} = hs
+ type I interface {
+ doKeepAlives() bool
+ }
+ if hs, ok := x.(I); ok {
+ return !hs.doKeepAlives()
+ }
+ return false
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/server_push_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/server_push_test.go
new file mode 100644
index 000000000..918fd30dc
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/server_push_test.go
@@ -0,0 +1,521 @@
+// 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.
+
+// +build go1.8
+
+package http2
+
+import (
+ "errors"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "net/http"
+ "reflect"
+ "strconv"
+ "sync"
+ "testing"
+ "time"
+)
+
+func TestServer_Push_Success(t *testing.T) {
+ const (
+ mainBody = "<html>index page</html>"
+ pushedBody = "<html>pushed page</html>"
+ userAgent = "testagent"
+ cookie = "testcookie"
+ )
+
+ var stURL string
+ checkPromisedReq := func(r *http.Request, wantMethod string, wantH http.Header) error {
+ if got, want := r.Method, wantMethod; got != want {
+ return fmt.Errorf("promised Req.Method=%q, want %q", got, want)
+ }
+ if got, want := r.Header, wantH; !reflect.DeepEqual(got, want) {
+ return fmt.Errorf("promised Req.Header=%q, want %q", got, want)
+ }
+ if got, want := "https://"+r.Host, stURL; got != want {
+ return fmt.Errorf("promised Req.Host=%q, want %q", got, want)
+ }
+ if r.Body == nil {
+ return fmt.Errorf("nil Body")
+ }
+ if buf, err := ioutil.ReadAll(r.Body); err != nil || len(buf) != 0 {
+ return fmt.Errorf("ReadAll(Body)=%q,%v, want '',nil", buf, err)
+ }
+ return nil
+ }
+
+ errc := make(chan error, 3)
+ st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+ switch r.URL.RequestURI() {
+ case "/":
+ // Push "/pushed?get" as a GET request, using an absolute URL.
+ opt := &http.PushOptions{
+ Header: http.Header{
+ "User-Agent": {userAgent},
+ },
+ }
+ if err := w.(http.Pusher).Push(stURL+"/pushed?get", opt); err != nil {
+ errc <- fmt.Errorf("error pushing /pushed?get: %v", err)
+ return
+ }
+ // Push "/pushed?head" as a HEAD request, using a path.
+ opt = &http.PushOptions{
+ Method: "HEAD",
+ Header: http.Header{
+ "User-Agent": {userAgent},
+ "Cookie": {cookie},
+ },
+ }
+ if err := w.(http.Pusher).Push("/pushed?head", opt); err != nil {
+ errc <- fmt.Errorf("error pushing /pushed?head: %v", err)
+ return
+ }
+ w.Header().Set("Content-Type", "text/html")
+ w.Header().Set("Content-Length", strconv.Itoa(len(mainBody)))
+ w.WriteHeader(200)
+ io.WriteString(w, mainBody)
+ errc <- nil
+
+ case "/pushed?get":
+ wantH := http.Header{}
+ wantH.Set("User-Agent", userAgent)
+ if err := checkPromisedReq(r, "GET", wantH); err != nil {
+ errc <- fmt.Errorf("/pushed?get: %v", err)
+ return
+ }
+ w.Header().Set("Content-Type", "text/html")
+ w.Header().Set("Content-Length", strconv.Itoa(len(pushedBody)))
+ w.WriteHeader(200)
+ io.WriteString(w, pushedBody)
+ errc <- nil
+
+ case "/pushed?head":
+ wantH := http.Header{}
+ wantH.Set("User-Agent", userAgent)
+ wantH.Set("Cookie", cookie)
+ if err := checkPromisedReq(r, "HEAD", wantH); err != nil {
+ errc <- fmt.Errorf("/pushed?head: %v", err)
+ return
+ }
+ w.WriteHeader(204)
+ errc <- nil
+
+ default:
+ errc <- fmt.Errorf("unknown RequestURL %q", r.URL.RequestURI())
+ }
+ })
+ stURL = st.ts.URL
+
+ // Send one request, which should push two responses.
+ st.greet()
+ getSlash(st)
+ for k := 0; k < 3; k++ {
+ select {
+ case <-time.After(2 * time.Second):
+ t.Errorf("timeout waiting for handler %d to finish", k)
+ case err := <-errc:
+ if err != nil {
+ t.Fatal(err)
+ }
+ }
+ }
+
+ checkPushPromise := func(f Frame, promiseID uint32, wantH [][2]string) error {
+ pp, ok := f.(*PushPromiseFrame)
+ if !ok {
+ return fmt.Errorf("got a %T; want *PushPromiseFrame", f)
+ }
+ if !pp.HeadersEnded() {
+ return fmt.Errorf("want END_HEADERS flag in PushPromiseFrame")
+ }
+ if got, want := pp.PromiseID, promiseID; got != want {
+ return fmt.Errorf("got PromiseID %v; want %v", got, want)
+ }
+ gotH := st.decodeHeader(pp.HeaderBlockFragment())
+ if !reflect.DeepEqual(gotH, wantH) {
+ return fmt.Errorf("got promised headers %v; want %v", gotH, wantH)
+ }
+ return nil
+ }
+ checkHeaders := func(f Frame, wantH [][2]string) error {
+ hf, ok := f.(*HeadersFrame)
+ if !ok {
+ return fmt.Errorf("got a %T; want *HeadersFrame", f)
+ }
+ gotH := st.decodeHeader(hf.HeaderBlockFragment())
+ if !reflect.DeepEqual(gotH, wantH) {
+ return fmt.Errorf("got response headers %v; want %v", gotH, wantH)
+ }
+ return nil
+ }
+ checkData := func(f Frame, wantData string) error {
+ df, ok := f.(*DataFrame)
+ if !ok {
+ return fmt.Errorf("got a %T; want *DataFrame", f)
+ }
+ if gotData := string(df.Data()); gotData != wantData {
+ return fmt.Errorf("got response data %q; want %q", gotData, wantData)
+ }
+ return nil
+ }
+
+ // Stream 1 has 2 PUSH_PROMISE + HEADERS + DATA
+ // Stream 2 has HEADERS + DATA
+ // Stream 4 has HEADERS
+ expected := map[uint32][]func(Frame) error{
+ 1: {
+ func(f Frame) error {
+ return checkPushPromise(f, 2, [][2]string{
+ {":method", "GET"},
+ {":scheme", "https"},
+ {":authority", st.ts.Listener.Addr().String()},
+ {":path", "/pushed?get"},
+ {"user-agent", userAgent},
+ })
+ },
+ func(f Frame) error {
+ return checkPushPromise(f, 4, [][2]string{
+ {":method", "HEAD"},
+ {":scheme", "https"},
+ {":authority", st.ts.Listener.Addr().String()},
+ {":path", "/pushed?head"},
+ {"cookie", cookie},
+ {"user-agent", userAgent},
+ })
+ },
+ func(f Frame) error {
+ return checkHeaders(f, [][2]string{
+ {":status", "200"},
+ {"content-type", "text/html"},
+ {"content-length", strconv.Itoa(len(mainBody))},
+ })
+ },
+ func(f Frame) error {
+ return checkData(f, mainBody)
+ },
+ },
+ 2: {
+ func(f Frame) error {
+ return checkHeaders(f, [][2]string{
+ {":status", "200"},
+ {"content-type", "text/html"},
+ {"content-length", strconv.Itoa(len(pushedBody))},
+ })
+ },
+ func(f Frame) error {
+ return checkData(f, pushedBody)
+ },
+ },
+ 4: {
+ func(f Frame) error {
+ return checkHeaders(f, [][2]string{
+ {":status", "204"},
+ })
+ },
+ },
+ }
+
+ consumed := map[uint32]int{}
+ for k := 0; len(expected) > 0; k++ {
+ f, err := st.readFrame()
+ if err != nil {
+ for id, left := range expected {
+ t.Errorf("stream %d: missing %d frames", id, len(left))
+ }
+ t.Fatalf("readFrame %d: %v", k, err)
+ }
+ id := f.Header().StreamID
+ label := fmt.Sprintf("stream %d, frame %d", id, consumed[id])
+ if len(expected[id]) == 0 {
+ t.Fatalf("%s: unexpected frame %#+v", label, f)
+ }
+ check := expected[id][0]
+ expected[id] = expected[id][1:]
+ if len(expected[id]) == 0 {
+ delete(expected, id)
+ }
+ if err := check(f); err != nil {
+ t.Fatalf("%s: %v", label, err)
+ }
+ consumed[id]++
+ }
+}
+
+func TestServer_Push_SuccessNoRace(t *testing.T) {
+ // Regression test for issue #18326. Ensure the request handler can mutate
+ // pushed request headers without racing with the PUSH_PROMISE write.
+ errc := make(chan error, 2)
+ st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+ switch r.URL.RequestURI() {
+ case "/":
+ opt := &http.PushOptions{
+ Header: http.Header{"User-Agent": {"testagent"}},
+ }
+ if err := w.(http.Pusher).Push("/pushed", opt); err != nil {
+ errc <- fmt.Errorf("error pushing: %v", err)
+ return
+ }
+ w.WriteHeader(200)
+ errc <- nil
+
+ case "/pushed":
+ // Update request header, ensure there is no race.
+ r.Header.Set("User-Agent", "newagent")
+ r.Header.Set("Cookie", "cookie")
+ w.WriteHeader(200)
+ errc <- nil
+
+ default:
+ errc <- fmt.Errorf("unknown RequestURL %q", r.URL.RequestURI())
+ }
+ })
+
+ // Send one request, which should push one response.
+ st.greet()
+ getSlash(st)
+ for k := 0; k < 2; k++ {
+ select {
+ case <-time.After(2 * time.Second):
+ t.Errorf("timeout waiting for handler %d to finish", k)
+ case err := <-errc:
+ if err != nil {
+ t.Fatal(err)
+ }
+ }
+ }
+}
+
+func TestServer_Push_RejectRecursivePush(t *testing.T) {
+ // Expect two requests, but might get three if there's a bug and the second push succeeds.
+ errc := make(chan error, 3)
+ handler := func(w http.ResponseWriter, r *http.Request) error {
+ baseURL := "https://" + r.Host
+ switch r.URL.Path {
+ case "/":
+ if err := w.(http.Pusher).Push(baseURL+"/push1", nil); err != nil {
+ return fmt.Errorf("first Push()=%v, want nil", err)
+ }
+ return nil
+
+ case "/push1":
+ if got, want := w.(http.Pusher).Push(baseURL+"/push2", nil), ErrRecursivePush; got != want {
+ return fmt.Errorf("Push()=%v, want %v", got, want)
+ }
+ return nil
+
+ default:
+ return fmt.Errorf("unexpected path: %q", r.URL.Path)
+ }
+ }
+ st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+ errc <- handler(w, r)
+ })
+ defer st.Close()
+ st.greet()
+ getSlash(st)
+ if err := <-errc; err != nil {
+ t.Errorf("First request failed: %v", err)
+ }
+ if err := <-errc; err != nil {
+ t.Errorf("Second request failed: %v", err)
+ }
+}
+
+func testServer_Push_RejectSingleRequest(t *testing.T, doPush func(http.Pusher, *http.Request) error, settings ...Setting) {
+ // Expect one request, but might get two if there's a bug and the push succeeds.
+ errc := make(chan error, 2)
+ st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+ errc <- doPush(w.(http.Pusher), r)
+ })
+ defer st.Close()
+ st.greet()
+ if err := st.fr.WriteSettings(settings...); err != nil {
+ st.t.Fatalf("WriteSettings: %v", err)
+ }
+ st.wantSettingsAck()
+ getSlash(st)
+ if err := <-errc; err != nil {
+ t.Error(err)
+ }
+ // Should not get a PUSH_PROMISE frame.
+ hf := st.wantHeaders()
+ if !hf.StreamEnded() {
+ t.Error("stream should end after headers")
+ }
+}
+
+func TestServer_Push_RejectIfDisabled(t *testing.T) {
+ testServer_Push_RejectSingleRequest(t,
+ func(p http.Pusher, r *http.Request) error {
+ if got, want := p.Push("https://"+r.Host+"/pushed", nil), http.ErrNotSupported; got != want {
+ return fmt.Errorf("Push()=%v, want %v", got, want)
+ }
+ return nil
+ },
+ Setting{SettingEnablePush, 0})
+}
+
+func TestServer_Push_RejectWhenNoConcurrentStreams(t *testing.T) {
+ testServer_Push_RejectSingleRequest(t,
+ func(p http.Pusher, r *http.Request) error {
+ if got, want := p.Push("https://"+r.Host+"/pushed", nil), ErrPushLimitReached; got != want {
+ return fmt.Errorf("Push()=%v, want %v", got, want)
+ }
+ return nil
+ },
+ Setting{SettingMaxConcurrentStreams, 0})
+}
+
+func TestServer_Push_RejectWrongScheme(t *testing.T) {
+ testServer_Push_RejectSingleRequest(t,
+ func(p http.Pusher, r *http.Request) error {
+ if err := p.Push("http://"+r.Host+"/pushed", nil); err == nil {
+ return errors.New("Push() should have failed (push target URL is http)")
+ }
+ return nil
+ })
+}
+
+func TestServer_Push_RejectMissingHost(t *testing.T) {
+ testServer_Push_RejectSingleRequest(t,
+ func(p http.Pusher, r *http.Request) error {
+ if err := p.Push("https:pushed", nil); err == nil {
+ return errors.New("Push() should have failed (push target URL missing host)")
+ }
+ return nil
+ })
+}
+
+func TestServer_Push_RejectRelativePath(t *testing.T) {
+ testServer_Push_RejectSingleRequest(t,
+ func(p http.Pusher, r *http.Request) error {
+ if err := p.Push("../test", nil); err == nil {
+ return errors.New("Push() should have failed (push target is a relative path)")
+ }
+ return nil
+ })
+}
+
+func TestServer_Push_RejectForbiddenMethod(t *testing.T) {
+ testServer_Push_RejectSingleRequest(t,
+ func(p http.Pusher, r *http.Request) error {
+ if err := p.Push("https://"+r.Host+"/pushed", &http.PushOptions{Method: "POST"}); err == nil {
+ return errors.New("Push() should have failed (cannot promise a POST)")
+ }
+ return nil
+ })
+}
+
+func TestServer_Push_RejectForbiddenHeader(t *testing.T) {
+ testServer_Push_RejectSingleRequest(t,
+ func(p http.Pusher, r *http.Request) error {
+ header := http.Header{
+ "Content-Length": {"10"},
+ "Content-Encoding": {"gzip"},
+ "Trailer": {"Foo"},
+ "Te": {"trailers"},
+ "Host": {"test.com"},
+ ":authority": {"test.com"},
+ }
+ if err := p.Push("https://"+r.Host+"/pushed", &http.PushOptions{Header: header}); err == nil {
+ return errors.New("Push() should have failed (forbidden headers)")
+ }
+ return nil
+ })
+}
+
+func TestServer_Push_StateTransitions(t *testing.T) {
+ const body = "foo"
+
+ gotPromise := make(chan bool)
+ finishedPush := make(chan bool)
+
+ st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+ switch r.URL.RequestURI() {
+ case "/":
+ if err := w.(http.Pusher).Push("/pushed", nil); err != nil {
+ t.Errorf("Push error: %v", err)
+ }
+ // Don't finish this request until the push finishes so we don't
+ // nondeterministically interleave output frames with the push.
+ <-finishedPush
+ case "/pushed":
+ <-gotPromise
+ }
+ w.Header().Set("Content-Type", "text/html")
+ w.Header().Set("Content-Length", strconv.Itoa(len(body)))
+ w.WriteHeader(200)
+ io.WriteString(w, body)
+ })
+ defer st.Close()
+
+ st.greet()
+ if st.stream(2) != nil {
+ t.Fatal("stream 2 should be empty")
+ }
+ if got, want := st.streamState(2), stateIdle; got != want {
+ t.Fatalf("streamState(2)=%v, want %v", got, want)
+ }
+ getSlash(st)
+ // After the PUSH_PROMISE is sent, the stream should be stateHalfClosedRemote.
+ st.wantPushPromise()
+ if got, want := st.streamState(2), stateHalfClosedRemote; got != want {
+ t.Fatalf("streamState(2)=%v, want %v", got, want)
+ }
+ // We stall the HTTP handler for "/pushed" until the above check. If we don't
+ // stall the handler, then the handler might write HEADERS and DATA and finish
+ // the stream before we check st.streamState(2) -- should that happen, we'll
+ // see stateClosed and fail the above check.
+ close(gotPromise)
+ st.wantHeaders()
+ if df := st.wantData(); !df.StreamEnded() {
+ t.Fatal("expected END_STREAM flag on DATA")
+ }
+ if got, want := st.streamState(2), stateClosed; got != want {
+ t.Fatalf("streamState(2)=%v, want %v", got, want)
+ }
+ close(finishedPush)
+}
+
+func TestServer_Push_RejectAfterGoAway(t *testing.T) {
+ var readyOnce sync.Once
+ ready := make(chan struct{})
+ errc := make(chan error, 2)
+ st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+ select {
+ case <-ready:
+ case <-time.After(5 * time.Second):
+ errc <- fmt.Errorf("timeout waiting for GOAWAY to be processed")
+ }
+ if got, want := w.(http.Pusher).Push("https://"+r.Host+"/pushed", nil), http.ErrNotSupported; got != want {
+ errc <- fmt.Errorf("Push()=%v, want %v", got, want)
+ }
+ errc <- nil
+ })
+ defer st.Close()
+ st.greet()
+ getSlash(st)
+
+ // Send GOAWAY and wait for it to be processed.
+ st.fr.WriteGoAway(1, ErrCodeNo, nil)
+ go func() {
+ for {
+ select {
+ case <-ready:
+ return
+ default:
+ }
+ st.sc.serveMsgCh <- func(loopNum int) {
+ if !st.sc.pushEnabled {
+ readyOnce.Do(func() { close(ready) })
+ }
+ }
+ }
+ }()
+ if err := <-errc; err != nil {
+ t.Error(err)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/server_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/server_test.go
new file mode 100644
index 000000000..bd1ba20d0
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/server_test.go
@@ -0,0 +1,3725 @@
+// Copyright 2014 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 http2
+
+import (
+ "bytes"
+ "crypto/tls"
+ "errors"
+ "flag"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "log"
+ "net"
+ "net/http"
+ "net/http/httptest"
+ "os"
+ "os/exec"
+ "reflect"
+ "runtime"
+ "strconv"
+ "strings"
+ "sync"
+ "sync/atomic"
+ "testing"
+ "time"
+
+ "golang.org/x/net/http2/hpack"
+)
+
+var stderrVerbose = flag.Bool("stderr_verbose", false, "Mirror verbosity to stderr, unbuffered")
+
+func stderrv() io.Writer {
+ if *stderrVerbose {
+ return os.Stderr
+ }
+
+ return ioutil.Discard
+}
+
+type serverTester struct {
+ cc net.Conn // client conn
+ t testing.TB
+ ts *httptest.Server
+ fr *Framer
+ serverLogBuf bytes.Buffer // logger for httptest.Server
+ logFilter []string // substrings to filter out
+ scMu sync.Mutex // guards sc
+ sc *serverConn
+ hpackDec *hpack.Decoder
+ decodedHeaders [][2]string
+
+ // If http2debug!=2, then we capture Frame debug logs that will be written
+ // to t.Log after a test fails. The read and write logs use separate locks
+ // and buffers so we don't accidentally introduce synchronization between
+ // the read and write goroutines, which may hide data races.
+ frameReadLogMu sync.Mutex
+ frameReadLogBuf bytes.Buffer
+ frameWriteLogMu sync.Mutex
+ frameWriteLogBuf bytes.Buffer
+
+ // writing headers:
+ headerBuf bytes.Buffer
+ hpackEnc *hpack.Encoder
+}
+
+func init() {
+ testHookOnPanicMu = new(sync.Mutex)
+ goAwayTimeout = 25 * time.Millisecond
+}
+
+func resetHooks() {
+ testHookOnPanicMu.Lock()
+ testHookOnPanic = nil
+ testHookOnPanicMu.Unlock()
+}
+
+type serverTesterOpt string
+
+var optOnlyServer = serverTesterOpt("only_server")
+var optQuiet = serverTesterOpt("quiet_logging")
+var optFramerReuseFrames = serverTesterOpt("frame_reuse_frames")
+
+func newServerTester(t testing.TB, handler http.HandlerFunc, opts ...interface{}) *serverTester {
+ resetHooks()
+
+ ts := httptest.NewUnstartedServer(handler)
+
+ tlsConfig := &tls.Config{
+ InsecureSkipVerify: true,
+ NextProtos: []string{NextProtoTLS},
+ }
+
+ var onlyServer, quiet, framerReuseFrames bool
+ h2server := new(Server)
+ for _, opt := range opts {
+ switch v := opt.(type) {
+ case func(*tls.Config):
+ v(tlsConfig)
+ case func(*httptest.Server):
+ v(ts)
+ case func(*Server):
+ v(h2server)
+ case serverTesterOpt:
+ switch v {
+ case optOnlyServer:
+ onlyServer = true
+ case optQuiet:
+ quiet = true
+ case optFramerReuseFrames:
+ framerReuseFrames = true
+ }
+ case func(net.Conn, http.ConnState):
+ ts.Config.ConnState = v
+ default:
+ t.Fatalf("unknown newServerTester option type %T", v)
+ }
+ }
+
+ ConfigureServer(ts.Config, h2server)
+
+ st := &serverTester{
+ t: t,
+ ts: ts,
+ }
+ st.hpackEnc = hpack.NewEncoder(&st.headerBuf)
+ st.hpackDec = hpack.NewDecoder(initialHeaderTableSize, st.onHeaderField)
+
+ ts.TLS = ts.Config.TLSConfig // the httptest.Server has its own copy of this TLS config
+ if quiet {
+ ts.Config.ErrorLog = log.New(ioutil.Discard, "", 0)
+ } else {
+ ts.Config.ErrorLog = log.New(io.MultiWriter(stderrv(), twriter{t: t, st: st}, &st.serverLogBuf), "", log.LstdFlags)
+ }
+ ts.StartTLS()
+
+ if VerboseLogs {
+ t.Logf("Running test server at: %s", ts.URL)
+ }
+ testHookGetServerConn = func(v *serverConn) {
+ st.scMu.Lock()
+ defer st.scMu.Unlock()
+ st.sc = v
+ }
+ log.SetOutput(io.MultiWriter(stderrv(), twriter{t: t, st: st}))
+ if !onlyServer {
+ cc, err := tls.Dial("tcp", ts.Listener.Addr().String(), tlsConfig)
+ if err != nil {
+ t.Fatal(err)
+ }
+ st.cc = cc
+ st.fr = NewFramer(cc, cc)
+ if framerReuseFrames {
+ st.fr.SetReuseFrames()
+ }
+ if !logFrameReads && !logFrameWrites {
+ st.fr.debugReadLoggerf = func(m string, v ...interface{}) {
+ m = time.Now().Format("2006-01-02 15:04:05.999999999 ") + strings.TrimPrefix(m, "http2: ") + "\n"
+ st.frameReadLogMu.Lock()
+ fmt.Fprintf(&st.frameReadLogBuf, m, v...)
+ st.frameReadLogMu.Unlock()
+ }
+ st.fr.debugWriteLoggerf = func(m string, v ...interface{}) {
+ m = time.Now().Format("2006-01-02 15:04:05.999999999 ") + strings.TrimPrefix(m, "http2: ") + "\n"
+ st.frameWriteLogMu.Lock()
+ fmt.Fprintf(&st.frameWriteLogBuf, m, v...)
+ st.frameWriteLogMu.Unlock()
+ }
+ st.fr.logReads = true
+ st.fr.logWrites = true
+ }
+ }
+ return st
+}
+
+func (st *serverTester) closeConn() {
+ st.scMu.Lock()
+ defer st.scMu.Unlock()
+ st.sc.conn.Close()
+}
+
+func (st *serverTester) addLogFilter(phrase string) {
+ st.logFilter = append(st.logFilter, phrase)
+}
+
+func (st *serverTester) stream(id uint32) *stream {
+ ch := make(chan *stream, 1)
+ st.sc.serveMsgCh <- func(int) {
+ ch <- st.sc.streams[id]
+ }
+ return <-ch
+}
+
+func (st *serverTester) streamState(id uint32) streamState {
+ ch := make(chan streamState, 1)
+ st.sc.serveMsgCh <- func(int) {
+ state, _ := st.sc.state(id)
+ ch <- state
+ }
+ return <-ch
+}
+
+// loopNum reports how many times this conn's select loop has gone around.
+func (st *serverTester) loopNum() int {
+ lastc := make(chan int, 1)
+ st.sc.serveMsgCh <- func(loopNum int) {
+ lastc <- loopNum
+ }
+ return <-lastc
+}
+
+// awaitIdle heuristically awaits for the server conn's select loop to be idle.
+// The heuristic is that the server connection's serve loop must schedule
+// 50 times in a row without any channel sends or receives occurring.
+func (st *serverTester) awaitIdle() {
+ remain := 50
+ last := st.loopNum()
+ for remain > 0 {
+ n := st.loopNum()
+ if n == last+1 {
+ remain--
+ } else {
+ remain = 50
+ }
+ last = n
+ }
+}
+
+func (st *serverTester) Close() {
+ if st.t.Failed() {
+ st.frameReadLogMu.Lock()
+ if st.frameReadLogBuf.Len() > 0 {
+ st.t.Logf("Framer read log:\n%s", st.frameReadLogBuf.String())
+ }
+ st.frameReadLogMu.Unlock()
+
+ st.frameWriteLogMu.Lock()
+ if st.frameWriteLogBuf.Len() > 0 {
+ st.t.Logf("Framer write log:\n%s", st.frameWriteLogBuf.String())
+ }
+ st.frameWriteLogMu.Unlock()
+
+ // If we failed already (and are likely in a Fatal,
+ // unwindowing), force close the connection, so the
+ // httptest.Server doesn't wait forever for the conn
+ // to close.
+ if st.cc != nil {
+ st.cc.Close()
+ }
+ }
+ st.ts.Close()
+ if st.cc != nil {
+ st.cc.Close()
+ }
+ log.SetOutput(os.Stderr)
+}
+
+// greet initiates the client's HTTP/2 connection into a state where
+// frames may be sent.
+func (st *serverTester) greet() {
+ st.greetAndCheckSettings(func(Setting) error { return nil })
+}
+
+func (st *serverTester) greetAndCheckSettings(checkSetting func(s Setting) error) {
+ st.writePreface()
+ st.writeInitialSettings()
+ st.wantSettings().ForeachSetting(checkSetting)
+ st.writeSettingsAck()
+
+ // The initial WINDOW_UPDATE and SETTINGS ACK can come in any order.
+ var gotSettingsAck bool
+ var gotWindowUpdate bool
+
+ for i := 0; i < 2; i++ {
+ f, err := st.readFrame()
+ if err != nil {
+ st.t.Fatal(err)
+ }
+ switch f := f.(type) {
+ case *SettingsFrame:
+ if !f.Header().Flags.Has(FlagSettingsAck) {
+ st.t.Fatal("Settings Frame didn't have ACK set")
+ }
+ gotSettingsAck = true
+
+ case *WindowUpdateFrame:
+ if f.FrameHeader.StreamID != 0 {
+ st.t.Fatalf("WindowUpdate StreamID = %d; want 0", f.FrameHeader.StreamID)
+ }
+ incr := uint32((&Server{}).initialConnRecvWindowSize() - initialWindowSize)
+ if f.Increment != incr {
+ st.t.Fatalf("WindowUpdate increment = %d; want %d", f.Increment, incr)
+ }
+ gotWindowUpdate = true
+
+ default:
+ st.t.Fatalf("Wanting a settings ACK or window update, received a %T", f)
+ }
+ }
+
+ if !gotSettingsAck {
+ st.t.Fatalf("Didn't get a settings ACK")
+ }
+ if !gotWindowUpdate {
+ st.t.Fatalf("Didn't get a window update")
+ }
+}
+
+func (st *serverTester) writePreface() {
+ n, err := st.cc.Write(clientPreface)
+ if err != nil {
+ st.t.Fatalf("Error writing client preface: %v", err)
+ }
+ if n != len(clientPreface) {
+ st.t.Fatalf("Writing client preface, wrote %d bytes; want %d", n, len(clientPreface))
+ }
+}
+
+func (st *serverTester) writeInitialSettings() {
+ if err := st.fr.WriteSettings(); err != nil {
+ st.t.Fatalf("Error writing initial SETTINGS frame from client to server: %v", err)
+ }
+}
+
+func (st *serverTester) writeSettingsAck() {
+ if err := st.fr.WriteSettingsAck(); err != nil {
+ st.t.Fatalf("Error writing ACK of server's SETTINGS: %v", err)
+ }
+}
+
+func (st *serverTester) writeHeaders(p HeadersFrameParam) {
+ if err := st.fr.WriteHeaders(p); err != nil {
+ st.t.Fatalf("Error writing HEADERS: %v", err)
+ }
+}
+
+func (st *serverTester) writePriority(id uint32, p PriorityParam) {
+ if err := st.fr.WritePriority(id, p); err != nil {
+ st.t.Fatalf("Error writing PRIORITY: %v", err)
+ }
+}
+
+func (st *serverTester) encodeHeaderField(k, v string) {
+ err := st.hpackEnc.WriteField(hpack.HeaderField{Name: k, Value: v})
+ if err != nil {
+ st.t.Fatalf("HPACK encoding error for %q/%q: %v", k, v, err)
+ }
+}
+
+// encodeHeaderRaw is the magic-free version of encodeHeader.
+// It takes 0 or more (k, v) pairs and encodes them.
+func (st *serverTester) encodeHeaderRaw(headers ...string) []byte {
+ if len(headers)%2 == 1 {
+ panic("odd number of kv args")
+ }
+ st.headerBuf.Reset()
+ for len(headers) > 0 {
+ k, v := headers[0], headers[1]
+ st.encodeHeaderField(k, v)
+ headers = headers[2:]
+ }
+ return st.headerBuf.Bytes()
+}
+
+// encodeHeader encodes headers and returns their HPACK bytes. headers
+// must contain an even number of key/value pairs. There may be
+// multiple pairs for keys (e.g. "cookie"). The :method, :path, and
+// :scheme headers default to GET, / and https. The :authority header
+// defaults to st.ts.Listener.Addr().
+func (st *serverTester) encodeHeader(headers ...string) []byte {
+ if len(headers)%2 == 1 {
+ panic("odd number of kv args")
+ }
+
+ st.headerBuf.Reset()
+ defaultAuthority := st.ts.Listener.Addr().String()
+
+ if len(headers) == 0 {
+ // Fast path, mostly for benchmarks, so test code doesn't pollute
+ // profiles when we're looking to improve server allocations.
+ st.encodeHeaderField(":method", "GET")
+ st.encodeHeaderField(":scheme", "https")
+ st.encodeHeaderField(":authority", defaultAuthority)
+ st.encodeHeaderField(":path", "/")
+ return st.headerBuf.Bytes()
+ }
+
+ if len(headers) == 2 && headers[0] == ":method" {
+ // Another fast path for benchmarks.
+ st.encodeHeaderField(":method", headers[1])
+ st.encodeHeaderField(":scheme", "https")
+ st.encodeHeaderField(":authority", defaultAuthority)
+ st.encodeHeaderField(":path", "/")
+ return st.headerBuf.Bytes()
+ }
+
+ pseudoCount := map[string]int{}
+ keys := []string{":method", ":scheme", ":authority", ":path"}
+ vals := map[string][]string{
+ ":method": {"GET"},
+ ":scheme": {"https"},
+ ":authority": {defaultAuthority},
+ ":path": {"/"},
+ }
+ for len(headers) > 0 {
+ k, v := headers[0], headers[1]
+ headers = headers[2:]
+ if _, ok := vals[k]; !ok {
+ keys = append(keys, k)
+ }
+ if strings.HasPrefix(k, ":") {
+ pseudoCount[k]++
+ if pseudoCount[k] == 1 {
+ vals[k] = []string{v}
+ } else {
+ // Allows testing of invalid headers w/ dup pseudo fields.
+ vals[k] = append(vals[k], v)
+ }
+ } else {
+ vals[k] = append(vals[k], v)
+ }
+ }
+ for _, k := range keys {
+ for _, v := range vals[k] {
+ st.encodeHeaderField(k, v)
+ }
+ }
+ return st.headerBuf.Bytes()
+}
+
+// bodylessReq1 writes a HEADERS frames with StreamID 1 and EndStream and EndHeaders set.
+func (st *serverTester) bodylessReq1(headers ...string) {
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: 1, // clients send odd numbers
+ BlockFragment: st.encodeHeader(headers...),
+ EndStream: true,
+ EndHeaders: true,
+ })
+}
+
+func (st *serverTester) writeData(streamID uint32, endStream bool, data []byte) {
+ if err := st.fr.WriteData(streamID, endStream, data); err != nil {
+ st.t.Fatalf("Error writing DATA: %v", err)
+ }
+}
+
+func (st *serverTester) writeDataPadded(streamID uint32, endStream bool, data, pad []byte) {
+ if err := st.fr.WriteDataPadded(streamID, endStream, data, pad); err != nil {
+ st.t.Fatalf("Error writing DATA: %v", err)
+ }
+}
+
+func readFrameTimeout(fr *Framer, wait time.Duration) (Frame, error) {
+ ch := make(chan interface{}, 1)
+ go func() {
+ fr, err := fr.ReadFrame()
+ if err != nil {
+ ch <- err
+ } else {
+ ch <- fr
+ }
+ }()
+ t := time.NewTimer(wait)
+ select {
+ case v := <-ch:
+ t.Stop()
+ if fr, ok := v.(Frame); ok {
+ return fr, nil
+ }
+ return nil, v.(error)
+ case <-t.C:
+ return nil, errors.New("timeout waiting for frame")
+ }
+}
+
+func (st *serverTester) readFrame() (Frame, error) {
+ return readFrameTimeout(st.fr, 2*time.Second)
+}
+
+func (st *serverTester) wantHeaders() *HeadersFrame {
+ f, err := st.readFrame()
+ if err != nil {
+ st.t.Fatalf("Error while expecting a HEADERS frame: %v", err)
+ }
+ hf, ok := f.(*HeadersFrame)
+ if !ok {
+ st.t.Fatalf("got a %T; want *HeadersFrame", f)
+ }
+ return hf
+}
+
+func (st *serverTester) wantContinuation() *ContinuationFrame {
+ f, err := st.readFrame()
+ if err != nil {
+ st.t.Fatalf("Error while expecting a CONTINUATION frame: %v", err)
+ }
+ cf, ok := f.(*ContinuationFrame)
+ if !ok {
+ st.t.Fatalf("got a %T; want *ContinuationFrame", f)
+ }
+ return cf
+}
+
+func (st *serverTester) wantData() *DataFrame {
+ f, err := st.readFrame()
+ if err != nil {
+ st.t.Fatalf("Error while expecting a DATA frame: %v", err)
+ }
+ df, ok := f.(*DataFrame)
+ if !ok {
+ st.t.Fatalf("got a %T; want *DataFrame", f)
+ }
+ return df
+}
+
+func (st *serverTester) wantSettings() *SettingsFrame {
+ f, err := st.readFrame()
+ if err != nil {
+ st.t.Fatalf("Error while expecting a SETTINGS frame: %v", err)
+ }
+ sf, ok := f.(*SettingsFrame)
+ if !ok {
+ st.t.Fatalf("got a %T; want *SettingsFrame", f)
+ }
+ return sf
+}
+
+func (st *serverTester) wantPing() *PingFrame {
+ f, err := st.readFrame()
+ if err != nil {
+ st.t.Fatalf("Error while expecting a PING frame: %v", err)
+ }
+ pf, ok := f.(*PingFrame)
+ if !ok {
+ st.t.Fatalf("got a %T; want *PingFrame", f)
+ }
+ return pf
+}
+
+func (st *serverTester) wantGoAway() *GoAwayFrame {
+ f, err := st.readFrame()
+ if err != nil {
+ st.t.Fatalf("Error while expecting a GOAWAY frame: %v", err)
+ }
+ gf, ok := f.(*GoAwayFrame)
+ if !ok {
+ st.t.Fatalf("got a %T; want *GoAwayFrame", f)
+ }
+ return gf
+}
+
+func (st *serverTester) wantRSTStream(streamID uint32, errCode ErrCode) {
+ f, err := st.readFrame()
+ if err != nil {
+ st.t.Fatalf("Error while expecting an RSTStream frame: %v", err)
+ }
+ rs, ok := f.(*RSTStreamFrame)
+ if !ok {
+ st.t.Fatalf("got a %T; want *RSTStreamFrame", f)
+ }
+ if rs.FrameHeader.StreamID != streamID {
+ st.t.Fatalf("RSTStream StreamID = %d; want %d", rs.FrameHeader.StreamID, streamID)
+ }
+ if rs.ErrCode != errCode {
+ st.t.Fatalf("RSTStream ErrCode = %d (%s); want %d (%s)", rs.ErrCode, rs.ErrCode, errCode, errCode)
+ }
+}
+
+func (st *serverTester) wantWindowUpdate(streamID, incr uint32) {
+ f, err := st.readFrame()
+ if err != nil {
+ st.t.Fatalf("Error while expecting a WINDOW_UPDATE frame: %v", err)
+ }
+ wu, ok := f.(*WindowUpdateFrame)
+ if !ok {
+ st.t.Fatalf("got a %T; want *WindowUpdateFrame", f)
+ }
+ if wu.FrameHeader.StreamID != streamID {
+ st.t.Fatalf("WindowUpdate StreamID = %d; want %d", wu.FrameHeader.StreamID, streamID)
+ }
+ if wu.Increment != incr {
+ st.t.Fatalf("WindowUpdate increment = %d; want %d", wu.Increment, incr)
+ }
+}
+
+func (st *serverTester) wantSettingsAck() {
+ f, err := st.readFrame()
+ if err != nil {
+ st.t.Fatal(err)
+ }
+ sf, ok := f.(*SettingsFrame)
+ if !ok {
+ st.t.Fatalf("Wanting a settings ACK, received a %T", f)
+ }
+ if !sf.Header().Flags.Has(FlagSettingsAck) {
+ st.t.Fatal("Settings Frame didn't have ACK set")
+ }
+}
+
+func (st *serverTester) wantPushPromise() *PushPromiseFrame {
+ f, err := st.readFrame()
+ if err != nil {
+ st.t.Fatal(err)
+ }
+ ppf, ok := f.(*PushPromiseFrame)
+ if !ok {
+ st.t.Fatalf("Wanted PushPromise, received %T", ppf)
+ }
+ return ppf
+}
+
+func TestServer(t *testing.T) {
+ gotReq := make(chan bool, 1)
+ st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Foo", "Bar")
+ gotReq <- true
+ })
+ defer st.Close()
+
+ covers("3.5", `
+ The server connection preface consists of a potentially empty
+ SETTINGS frame ([SETTINGS]) that MUST be the first frame the
+ server sends in the HTTP/2 connection.
+ `)
+
+ st.greet()
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: 1, // clients send odd numbers
+ BlockFragment: st.encodeHeader(),
+ EndStream: true, // no DATA frames
+ EndHeaders: true,
+ })
+
+ select {
+ case <-gotReq:
+ case <-time.After(2 * time.Second):
+ t.Error("timeout waiting for request")
+ }
+}
+
+func TestServer_Request_Get(t *testing.T) {
+ testServerRequest(t, func(st *serverTester) {
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: 1, // clients send odd numbers
+ BlockFragment: st.encodeHeader("foo-bar", "some-value"),
+ EndStream: true, // no DATA frames
+ EndHeaders: true,
+ })
+ }, func(r *http.Request) {
+ if r.Method != "GET" {
+ t.Errorf("Method = %q; want GET", r.Method)
+ }
+ if r.URL.Path != "/" {
+ t.Errorf("URL.Path = %q; want /", r.URL.Path)
+ }
+ if r.ContentLength != 0 {
+ t.Errorf("ContentLength = %v; want 0", r.ContentLength)
+ }
+ if r.Close {
+ t.Error("Close = true; want false")
+ }
+ if !strings.Contains(r.RemoteAddr, ":") {
+ t.Errorf("RemoteAddr = %q; want something with a colon", r.RemoteAddr)
+ }
+ if r.Proto != "HTTP/2.0" || r.ProtoMajor != 2 || r.ProtoMinor != 0 {
+ t.Errorf("Proto = %q Major=%v,Minor=%v; want HTTP/2.0", r.Proto, r.ProtoMajor, r.ProtoMinor)
+ }
+ wantHeader := http.Header{
+ "Foo-Bar": []string{"some-value"},
+ }
+ if !reflect.DeepEqual(r.Header, wantHeader) {
+ t.Errorf("Header = %#v; want %#v", r.Header, wantHeader)
+ }
+ if n, err := r.Body.Read([]byte(" ")); err != io.EOF || n != 0 {
+ t.Errorf("Read = %d, %v; want 0, EOF", n, err)
+ }
+ })
+}
+
+func TestServer_Request_Get_PathSlashes(t *testing.T) {
+ testServerRequest(t, func(st *serverTester) {
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: 1, // clients send odd numbers
+ BlockFragment: st.encodeHeader(":path", "/%2f/"),
+ EndStream: true, // no DATA frames
+ EndHeaders: true,
+ })
+ }, func(r *http.Request) {
+ if r.RequestURI != "/%2f/" {
+ t.Errorf("RequestURI = %q; want /%%2f/", r.RequestURI)
+ }
+ if r.URL.Path != "///" {
+ t.Errorf("URL.Path = %q; want ///", r.URL.Path)
+ }
+ })
+}
+
+// TODO: add a test with EndStream=true on the HEADERS but setting a
+// Content-Length anyway. Should we just omit it and force it to
+// zero?
+
+func TestServer_Request_Post_NoContentLength_EndStream(t *testing.T) {
+ testServerRequest(t, func(st *serverTester) {
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: 1, // clients send odd numbers
+ BlockFragment: st.encodeHeader(":method", "POST"),
+ EndStream: true,
+ EndHeaders: true,
+ })
+ }, func(r *http.Request) {
+ if r.Method != "POST" {
+ t.Errorf("Method = %q; want POST", r.Method)
+ }
+ if r.ContentLength != 0 {
+ t.Errorf("ContentLength = %v; want 0", r.ContentLength)
+ }
+ if n, err := r.Body.Read([]byte(" ")); err != io.EOF || n != 0 {
+ t.Errorf("Read = %d, %v; want 0, EOF", n, err)
+ }
+ })
+}
+
+func TestServer_Request_Post_Body_ImmediateEOF(t *testing.T) {
+ testBodyContents(t, -1, "", func(st *serverTester) {
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: 1, // clients send odd numbers
+ BlockFragment: st.encodeHeader(":method", "POST"),
+ EndStream: false, // to say DATA frames are coming
+ EndHeaders: true,
+ })
+ st.writeData(1, true, nil) // just kidding. empty body.
+ })
+}
+
+func TestServer_Request_Post_Body_OneData(t *testing.T) {
+ const content = "Some content"
+ testBodyContents(t, -1, content, func(st *serverTester) {
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: 1, // clients send odd numbers
+ BlockFragment: st.encodeHeader(":method", "POST"),
+ EndStream: false, // to say DATA frames are coming
+ EndHeaders: true,
+ })
+ st.writeData(1, true, []byte(content))
+ })
+}
+
+func TestServer_Request_Post_Body_TwoData(t *testing.T) {
+ const content = "Some content"
+ testBodyContents(t, -1, content, func(st *serverTester) {
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: 1, // clients send odd numbers
+ BlockFragment: st.encodeHeader(":method", "POST"),
+ EndStream: false, // to say DATA frames are coming
+ EndHeaders: true,
+ })
+ st.writeData(1, false, []byte(content[:5]))
+ st.writeData(1, true, []byte(content[5:]))
+ })
+}
+
+func TestServer_Request_Post_Body_ContentLength_Correct(t *testing.T) {
+ const content = "Some content"
+ testBodyContents(t, int64(len(content)), content, func(st *serverTester) {
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: 1, // clients send odd numbers
+ BlockFragment: st.encodeHeader(
+ ":method", "POST",
+ "content-length", strconv.Itoa(len(content)),
+ ),
+ EndStream: false, // to say DATA frames are coming
+ EndHeaders: true,
+ })
+ st.writeData(1, true, []byte(content))
+ })
+}
+
+func TestServer_Request_Post_Body_ContentLength_TooLarge(t *testing.T) {
+ testBodyContentsFail(t, 3, "request declared a Content-Length of 3 but only wrote 2 bytes",
+ func(st *serverTester) {
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: 1, // clients send odd numbers
+ BlockFragment: st.encodeHeader(
+ ":method", "POST",
+ "content-length", "3",
+ ),
+ EndStream: false, // to say DATA frames are coming
+ EndHeaders: true,
+ })
+ st.writeData(1, true, []byte("12"))
+ })
+}
+
+func TestServer_Request_Post_Body_ContentLength_TooSmall(t *testing.T) {
+ testBodyContentsFail(t, 4, "sender tried to send more than declared Content-Length of 4 bytes",
+ func(st *serverTester) {
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: 1, // clients send odd numbers
+ BlockFragment: st.encodeHeader(
+ ":method", "POST",
+ "content-length", "4",
+ ),
+ EndStream: false, // to say DATA frames are coming
+ EndHeaders: true,
+ })
+ st.writeData(1, true, []byte("12345"))
+ })
+}
+
+func testBodyContents(t *testing.T, wantContentLength int64, wantBody string, write func(st *serverTester)) {
+ testServerRequest(t, write, func(r *http.Request) {
+ if r.Method != "POST" {
+ t.Errorf("Method = %q; want POST", r.Method)
+ }
+ if r.ContentLength != wantContentLength {
+ t.Errorf("ContentLength = %v; want %d", r.ContentLength, wantContentLength)
+ }
+ all, err := ioutil.ReadAll(r.Body)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if string(all) != wantBody {
+ t.Errorf("Read = %q; want %q", all, wantBody)
+ }
+ if err := r.Body.Close(); err != nil {
+ t.Fatalf("Close: %v", err)
+ }
+ })
+}
+
+func testBodyContentsFail(t *testing.T, wantContentLength int64, wantReadError string, write func(st *serverTester)) {
+ testServerRequest(t, write, func(r *http.Request) {
+ if r.Method != "POST" {
+ t.Errorf("Method = %q; want POST", r.Method)
+ }
+ if r.ContentLength != wantContentLength {
+ t.Errorf("ContentLength = %v; want %d", r.ContentLength, wantContentLength)
+ }
+ all, err := ioutil.ReadAll(r.Body)
+ if err == nil {
+ t.Fatalf("expected an error (%q) reading from the body. Successfully read %q instead.",
+ wantReadError, all)
+ }
+ if !strings.Contains(err.Error(), wantReadError) {
+ t.Fatalf("Body.Read = %v; want substring %q", err, wantReadError)
+ }
+ if err := r.Body.Close(); err != nil {
+ t.Fatalf("Close: %v", err)
+ }
+ })
+}
+
+// Using a Host header, instead of :authority
+func TestServer_Request_Get_Host(t *testing.T) {
+ const host = "example.com"
+ testServerRequest(t, func(st *serverTester) {
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: 1, // clients send odd numbers
+ BlockFragment: st.encodeHeader(":authority", "", "host", host),
+ EndStream: true,
+ EndHeaders: true,
+ })
+ }, func(r *http.Request) {
+ if r.Host != host {
+ t.Errorf("Host = %q; want %q", r.Host, host)
+ }
+ })
+}
+
+// Using an :authority pseudo-header, instead of Host
+func TestServer_Request_Get_Authority(t *testing.T) {
+ const host = "example.com"
+ testServerRequest(t, func(st *serverTester) {
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: 1, // clients send odd numbers
+ BlockFragment: st.encodeHeader(":authority", host),
+ EndStream: true,
+ EndHeaders: true,
+ })
+ }, func(r *http.Request) {
+ if r.Host != host {
+ t.Errorf("Host = %q; want %q", r.Host, host)
+ }
+ })
+}
+
+func TestServer_Request_WithContinuation(t *testing.T) {
+ wantHeader := http.Header{
+ "Foo-One": []string{"value-one"},
+ "Foo-Two": []string{"value-two"},
+ "Foo-Three": []string{"value-three"},
+ }
+ testServerRequest(t, func(st *serverTester) {
+ fullHeaders := st.encodeHeader(
+ "foo-one", "value-one",
+ "foo-two", "value-two",
+ "foo-three", "value-three",
+ )
+ remain := fullHeaders
+ chunks := 0
+ for len(remain) > 0 {
+ const maxChunkSize = 5
+ chunk := remain
+ if len(chunk) > maxChunkSize {
+ chunk = chunk[:maxChunkSize]
+ }
+ remain = remain[len(chunk):]
+
+ if chunks == 0 {
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: 1, // clients send odd numbers
+ BlockFragment: chunk,
+ EndStream: true, // no DATA frames
+ EndHeaders: false, // we'll have continuation frames
+ })
+ } else {
+ err := st.fr.WriteContinuation(1, len(remain) == 0, chunk)
+ if err != nil {
+ t.Fatal(err)
+ }
+ }
+ chunks++
+ }
+ if chunks < 2 {
+ t.Fatal("too few chunks")
+ }
+ }, func(r *http.Request) {
+ if !reflect.DeepEqual(r.Header, wantHeader) {
+ t.Errorf("Header = %#v; want %#v", r.Header, wantHeader)
+ }
+ })
+}
+
+// Concatenated cookie headers. ("8.1.2.5 Compressing the Cookie Header Field")
+func TestServer_Request_CookieConcat(t *testing.T) {
+ const host = "example.com"
+ testServerRequest(t, func(st *serverTester) {
+ st.bodylessReq1(
+ ":authority", host,
+ "cookie", "a=b",
+ "cookie", "c=d",
+ "cookie", "e=f",
+ )
+ }, func(r *http.Request) {
+ const want = "a=b; c=d; e=f"
+ if got := r.Header.Get("Cookie"); got != want {
+ t.Errorf("Cookie = %q; want %q", got, want)
+ }
+ })
+}
+
+func TestServer_Request_Reject_CapitalHeader(t *testing.T) {
+ testRejectRequest(t, func(st *serverTester) { st.bodylessReq1("UPPER", "v") })
+}
+
+func TestServer_Request_Reject_HeaderFieldNameColon(t *testing.T) {
+ testRejectRequest(t, func(st *serverTester) { st.bodylessReq1("has:colon", "v") })
+}
+
+func TestServer_Request_Reject_HeaderFieldNameNULL(t *testing.T) {
+ testRejectRequest(t, func(st *serverTester) { st.bodylessReq1("has\x00null", "v") })
+}
+
+func TestServer_Request_Reject_HeaderFieldNameEmpty(t *testing.T) {
+ testRejectRequest(t, func(st *serverTester) { st.bodylessReq1("", "v") })
+}
+
+func TestServer_Request_Reject_HeaderFieldValueNewline(t *testing.T) {
+ testRejectRequest(t, func(st *serverTester) { st.bodylessReq1("foo", "has\nnewline") })
+}
+
+func TestServer_Request_Reject_HeaderFieldValueCR(t *testing.T) {
+ testRejectRequest(t, func(st *serverTester) { st.bodylessReq1("foo", "has\rcarriage") })
+}
+
+func TestServer_Request_Reject_HeaderFieldValueDEL(t *testing.T) {
+ testRejectRequest(t, func(st *serverTester) { st.bodylessReq1("foo", "has\x7fdel") })
+}
+
+func TestServer_Request_Reject_Pseudo_Missing_method(t *testing.T) {
+ testRejectRequest(t, func(st *serverTester) { st.bodylessReq1(":method", "") })
+}
+
+func TestServer_Request_Reject_Pseudo_ExactlyOne(t *testing.T) {
+ // 8.1.2.3 Request Pseudo-Header Fields
+ // "All HTTP/2 requests MUST include exactly one valid value" ...
+ testRejectRequest(t, func(st *serverTester) {
+ st.addLogFilter("duplicate pseudo-header")
+ st.bodylessReq1(":method", "GET", ":method", "POST")
+ })
+}
+
+func TestServer_Request_Reject_Pseudo_AfterRegular(t *testing.T) {
+ // 8.1.2.3 Request Pseudo-Header Fields
+ // "All pseudo-header fields MUST appear in the header block
+ // before regular header fields. Any request or response that
+ // contains a pseudo-header field that appears in a header
+ // block after a regular header field MUST be treated as
+ // malformed (Section 8.1.2.6)."
+ testRejectRequest(t, func(st *serverTester) {
+ st.addLogFilter("pseudo-header after regular header")
+ var buf bytes.Buffer
+ enc := hpack.NewEncoder(&buf)
+ enc.WriteField(hpack.HeaderField{Name: ":method", Value: "GET"})
+ enc.WriteField(hpack.HeaderField{Name: "regular", Value: "foobar"})
+ enc.WriteField(hpack.HeaderField{Name: ":path", Value: "/"})
+ enc.WriteField(hpack.HeaderField{Name: ":scheme", Value: "https"})
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: 1, // clients send odd numbers
+ BlockFragment: buf.Bytes(),
+ EndStream: true,
+ EndHeaders: true,
+ })
+ })
+}
+
+func TestServer_Request_Reject_Pseudo_Missing_path(t *testing.T) {
+ testRejectRequest(t, func(st *serverTester) { st.bodylessReq1(":path", "") })
+}
+
+func TestServer_Request_Reject_Pseudo_Missing_scheme(t *testing.T) {
+ testRejectRequest(t, func(st *serverTester) { st.bodylessReq1(":scheme", "") })
+}
+
+func TestServer_Request_Reject_Pseudo_scheme_invalid(t *testing.T) {
+ testRejectRequest(t, func(st *serverTester) { st.bodylessReq1(":scheme", "bogus") })
+}
+
+func TestServer_Request_Reject_Pseudo_Unknown(t *testing.T) {
+ testRejectRequest(t, func(st *serverTester) {
+ st.addLogFilter(`invalid pseudo-header ":unknown_thing"`)
+ st.bodylessReq1(":unknown_thing", "")
+ })
+}
+
+func testRejectRequest(t *testing.T, send func(*serverTester)) {
+ st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+ t.Error("server request made it to handler; should've been rejected")
+ })
+ defer st.Close()
+
+ st.greet()
+ send(st)
+ st.wantRSTStream(1, ErrCodeProtocol)
+}
+
+func testRejectRequestWithProtocolError(t *testing.T, send func(*serverTester)) {
+ st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+ t.Error("server request made it to handler; should've been rejected")
+ }, optQuiet)
+ defer st.Close()
+
+ st.greet()
+ send(st)
+ gf := st.wantGoAway()
+ if gf.ErrCode != ErrCodeProtocol {
+ t.Errorf("err code = %v; want %v", gf.ErrCode, ErrCodeProtocol)
+ }
+}
+
+// Section 5.1, on idle connections: "Receiving any frame other than
+// HEADERS or PRIORITY on a stream in this state MUST be treated as a
+// connection error (Section 5.4.1) of type PROTOCOL_ERROR."
+func TestRejectFrameOnIdle_WindowUpdate(t *testing.T) {
+ testRejectRequestWithProtocolError(t, func(st *serverTester) {
+ st.fr.WriteWindowUpdate(123, 456)
+ })
+}
+func TestRejectFrameOnIdle_Data(t *testing.T) {
+ testRejectRequestWithProtocolError(t, func(st *serverTester) {
+ st.fr.WriteData(123, true, nil)
+ })
+}
+func TestRejectFrameOnIdle_RSTStream(t *testing.T) {
+ testRejectRequestWithProtocolError(t, func(st *serverTester) {
+ st.fr.WriteRSTStream(123, ErrCodeCancel)
+ })
+}
+
+func TestServer_Request_Connect(t *testing.T) {
+ testServerRequest(t, func(st *serverTester) {
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: 1,
+ BlockFragment: st.encodeHeaderRaw(
+ ":method", "CONNECT",
+ ":authority", "example.com:123",
+ ),
+ EndStream: true,
+ EndHeaders: true,
+ })
+ }, func(r *http.Request) {
+ if g, w := r.Method, "CONNECT"; g != w {
+ t.Errorf("Method = %q; want %q", g, w)
+ }
+ if g, w := r.RequestURI, "example.com:123"; g != w {
+ t.Errorf("RequestURI = %q; want %q", g, w)
+ }
+ if g, w := r.URL.Host, "example.com:123"; g != w {
+ t.Errorf("URL.Host = %q; want %q", g, w)
+ }
+ })
+}
+
+func TestServer_Request_Connect_InvalidPath(t *testing.T) {
+ testServerRejectsStream(t, ErrCodeProtocol, func(st *serverTester) {
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: 1,
+ BlockFragment: st.encodeHeaderRaw(
+ ":method", "CONNECT",
+ ":authority", "example.com:123",
+ ":path", "/bogus",
+ ),
+ EndStream: true,
+ EndHeaders: true,
+ })
+ })
+}
+
+func TestServer_Request_Connect_InvalidScheme(t *testing.T) {
+ testServerRejectsStream(t, ErrCodeProtocol, func(st *serverTester) {
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: 1,
+ BlockFragment: st.encodeHeaderRaw(
+ ":method", "CONNECT",
+ ":authority", "example.com:123",
+ ":scheme", "https",
+ ),
+ EndStream: true,
+ EndHeaders: true,
+ })
+ })
+}
+
+func TestServer_Ping(t *testing.T) {
+ st := newServerTester(t, nil)
+ defer st.Close()
+ st.greet()
+
+ // Server should ignore this one, since it has ACK set.
+ ackPingData := [8]byte{1, 2, 4, 8, 16, 32, 64, 128}
+ if err := st.fr.WritePing(true, ackPingData); err != nil {
+ t.Fatal(err)
+ }
+
+ // But the server should reply to this one, since ACK is false.
+ pingData := [8]byte{1, 2, 3, 4, 5, 6, 7, 8}
+ if err := st.fr.WritePing(false, pingData); err != nil {
+ t.Fatal(err)
+ }
+
+ pf := st.wantPing()
+ if !pf.Flags.Has(FlagPingAck) {
+ t.Error("response ping doesn't have ACK set")
+ }
+ if pf.Data != pingData {
+ t.Errorf("response ping has data %q; want %q", pf.Data, pingData)
+ }
+}
+
+func TestServer_RejectsLargeFrames(t *testing.T) {
+ if runtime.GOOS == "windows" {
+ t.Skip("see golang.org/issue/13434")
+ }
+
+ st := newServerTester(t, nil)
+ defer st.Close()
+ st.greet()
+
+ // Write too large of a frame (too large by one byte)
+ // We ignore the return value because it's expected that the server
+ // will only read the first 9 bytes (the headre) and then disconnect.
+ st.fr.WriteRawFrame(0xff, 0, 0, make([]byte, defaultMaxReadFrameSize+1))
+
+ gf := st.wantGoAway()
+ if gf.ErrCode != ErrCodeFrameSize {
+ t.Errorf("GOAWAY err = %v; want %v", gf.ErrCode, ErrCodeFrameSize)
+ }
+ if st.serverLogBuf.Len() != 0 {
+ // Previously we spun here for a bit until the GOAWAY disconnect
+ // timer fired, logging while we fired.
+ t.Errorf("unexpected server output: %.500s\n", st.serverLogBuf.Bytes())
+ }
+}
+
+func TestServer_Handler_Sends_WindowUpdate(t *testing.T) {
+ puppet := newHandlerPuppet()
+ st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+ puppet.act(w, r)
+ })
+ defer st.Close()
+ defer puppet.done()
+
+ st.greet()
+
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: 1, // clients send odd numbers
+ BlockFragment: st.encodeHeader(":method", "POST"),
+ EndStream: false, // data coming
+ EndHeaders: true,
+ })
+ st.writeData(1, false, []byte("abcdef"))
+ puppet.do(readBodyHandler(t, "abc"))
+ st.wantWindowUpdate(0, 3)
+ st.wantWindowUpdate(1, 3)
+
+ puppet.do(readBodyHandler(t, "def"))
+ st.wantWindowUpdate(0, 3)
+ st.wantWindowUpdate(1, 3)
+
+ st.writeData(1, true, []byte("ghijkl")) // END_STREAM here
+ puppet.do(readBodyHandler(t, "ghi"))
+ puppet.do(readBodyHandler(t, "jkl"))
+ st.wantWindowUpdate(0, 3)
+ st.wantWindowUpdate(0, 3) // no more stream-level, since END_STREAM
+}
+
+// the version of the TestServer_Handler_Sends_WindowUpdate with padding.
+// See golang.org/issue/16556
+func TestServer_Handler_Sends_WindowUpdate_Padding(t *testing.T) {
+ puppet := newHandlerPuppet()
+ st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+ puppet.act(w, r)
+ })
+ defer st.Close()
+ defer puppet.done()
+
+ st.greet()
+
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: 1,
+ BlockFragment: st.encodeHeader(":method", "POST"),
+ EndStream: false,
+ EndHeaders: true,
+ })
+ st.writeDataPadded(1, false, []byte("abcdef"), []byte{0, 0, 0, 0})
+
+ // Expect to immediately get our 5 bytes of padding back for
+ // both the connection and stream (4 bytes of padding + 1 byte of length)
+ st.wantWindowUpdate(0, 5)
+ st.wantWindowUpdate(1, 5)
+
+ puppet.do(readBodyHandler(t, "abc"))
+ st.wantWindowUpdate(0, 3)
+ st.wantWindowUpdate(1, 3)
+
+ puppet.do(readBodyHandler(t, "def"))
+ st.wantWindowUpdate(0, 3)
+ st.wantWindowUpdate(1, 3)
+}
+
+func TestServer_Send_GoAway_After_Bogus_WindowUpdate(t *testing.T) {
+ st := newServerTester(t, nil)
+ defer st.Close()
+ st.greet()
+ if err := st.fr.WriteWindowUpdate(0, 1<<31-1); err != nil {
+ t.Fatal(err)
+ }
+ gf := st.wantGoAway()
+ if gf.ErrCode != ErrCodeFlowControl {
+ t.Errorf("GOAWAY err = %v; want %v", gf.ErrCode, ErrCodeFlowControl)
+ }
+ if gf.LastStreamID != 0 {
+ t.Errorf("GOAWAY last stream ID = %v; want %v", gf.LastStreamID, 0)
+ }
+}
+
+func TestServer_Send_RstStream_After_Bogus_WindowUpdate(t *testing.T) {
+ inHandler := make(chan bool)
+ blockHandler := make(chan bool)
+ st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+ inHandler <- true
+ <-blockHandler
+ })
+ defer st.Close()
+ defer close(blockHandler)
+ st.greet()
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: 1,
+ BlockFragment: st.encodeHeader(":method", "POST"),
+ EndStream: false, // keep it open
+ EndHeaders: true,
+ })
+ <-inHandler
+ // Send a bogus window update:
+ if err := st.fr.WriteWindowUpdate(1, 1<<31-1); err != nil {
+ t.Fatal(err)
+ }
+ st.wantRSTStream(1, ErrCodeFlowControl)
+}
+
+// testServerPostUnblock sends a hanging POST with unsent data to handler,
+// then runs fn once in the handler, and verifies that the error returned from
+// handler is acceptable. It fails if takes over 5 seconds for handler to exit.
+func testServerPostUnblock(t *testing.T,
+ handler func(http.ResponseWriter, *http.Request) error,
+ fn func(*serverTester),
+ checkErr func(error),
+ otherHeaders ...string) {
+ inHandler := make(chan bool)
+ errc := make(chan error, 1)
+ st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+ inHandler <- true
+ errc <- handler(w, r)
+ })
+ defer st.Close()
+ st.greet()
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: 1,
+ BlockFragment: st.encodeHeader(append([]string{":method", "POST"}, otherHeaders...)...),
+ EndStream: false, // keep it open
+ EndHeaders: true,
+ })
+ <-inHandler
+ fn(st)
+ select {
+ case err := <-errc:
+ if checkErr != nil {
+ checkErr(err)
+ }
+ case <-time.After(5 * time.Second):
+ t.Fatal("timeout waiting for Handler to return")
+ }
+}
+
+func TestServer_RSTStream_Unblocks_Read(t *testing.T) {
+ testServerPostUnblock(t,
+ func(w http.ResponseWriter, r *http.Request) (err error) {
+ _, err = r.Body.Read(make([]byte, 1))
+ return
+ },
+ func(st *serverTester) {
+ if err := st.fr.WriteRSTStream(1, ErrCodeCancel); err != nil {
+ t.Fatal(err)
+ }
+ },
+ func(err error) {
+ want := StreamError{StreamID: 0x1, Code: 0x8}
+ if !reflect.DeepEqual(err, want) {
+ t.Errorf("Read error = %v; want %v", err, want)
+ }
+ },
+ )
+}
+
+func TestServer_RSTStream_Unblocks_Header_Write(t *testing.T) {
+ // Run this test a bunch, because it doesn't always
+ // deadlock. But with a bunch, it did.
+ n := 50
+ if testing.Short() {
+ n = 5
+ }
+ for i := 0; i < n; i++ {
+ testServer_RSTStream_Unblocks_Header_Write(t)
+ }
+}
+
+func testServer_RSTStream_Unblocks_Header_Write(t *testing.T) {
+ inHandler := make(chan bool, 1)
+ unblockHandler := make(chan bool, 1)
+ headerWritten := make(chan bool, 1)
+ wroteRST := make(chan bool, 1)
+
+ st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+ inHandler <- true
+ <-wroteRST
+ w.Header().Set("foo", "bar")
+ w.WriteHeader(200)
+ w.(http.Flusher).Flush()
+ headerWritten <- true
+ <-unblockHandler
+ })
+ defer st.Close()
+
+ st.greet()
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: 1,
+ BlockFragment: st.encodeHeader(":method", "POST"),
+ EndStream: false, // keep it open
+ EndHeaders: true,
+ })
+ <-inHandler
+ if err := st.fr.WriteRSTStream(1, ErrCodeCancel); err != nil {
+ t.Fatal(err)
+ }
+ wroteRST <- true
+ st.awaitIdle()
+ select {
+ case <-headerWritten:
+ case <-time.After(2 * time.Second):
+ t.Error("timeout waiting for header write")
+ }
+ unblockHandler <- true
+}
+
+func TestServer_DeadConn_Unblocks_Read(t *testing.T) {
+ testServerPostUnblock(t,
+ func(w http.ResponseWriter, r *http.Request) (err error) {
+ _, err = r.Body.Read(make([]byte, 1))
+ return
+ },
+ func(st *serverTester) { st.cc.Close() },
+ func(err error) {
+ if err == nil {
+ t.Error("unexpected nil error from Request.Body.Read")
+ }
+ },
+ )
+}
+
+var blockUntilClosed = func(w http.ResponseWriter, r *http.Request) error {
+ <-w.(http.CloseNotifier).CloseNotify()
+ return nil
+}
+
+func TestServer_CloseNotify_After_RSTStream(t *testing.T) {
+ testServerPostUnblock(t, blockUntilClosed, func(st *serverTester) {
+ if err := st.fr.WriteRSTStream(1, ErrCodeCancel); err != nil {
+ t.Fatal(err)
+ }
+ }, nil)
+}
+
+func TestServer_CloseNotify_After_ConnClose(t *testing.T) {
+ testServerPostUnblock(t, blockUntilClosed, func(st *serverTester) { st.cc.Close() }, nil)
+}
+
+// that CloseNotify unblocks after a stream error due to the client's
+// problem that's unrelated to them explicitly canceling it (which is
+// TestServer_CloseNotify_After_RSTStream above)
+func TestServer_CloseNotify_After_StreamError(t *testing.T) {
+ testServerPostUnblock(t, blockUntilClosed, func(st *serverTester) {
+ // data longer than declared Content-Length => stream error
+ st.writeData(1, true, []byte("1234"))
+ }, nil, "content-length", "3")
+}
+
+func TestServer_StateTransitions(t *testing.T) {
+ var st *serverTester
+ inHandler := make(chan bool)
+ writeData := make(chan bool)
+ leaveHandler := make(chan bool)
+ st = newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+ inHandler <- true
+ if st.stream(1) == nil {
+ t.Errorf("nil stream 1 in handler")
+ }
+ if got, want := st.streamState(1), stateOpen; got != want {
+ t.Errorf("in handler, state is %v; want %v", got, want)
+ }
+ writeData <- true
+ if n, err := r.Body.Read(make([]byte, 1)); n != 0 || err != io.EOF {
+ t.Errorf("body read = %d, %v; want 0, EOF", n, err)
+ }
+ if got, want := st.streamState(1), stateHalfClosedRemote; got != want {
+ t.Errorf("in handler, state is %v; want %v", got, want)
+ }
+
+ <-leaveHandler
+ })
+ st.greet()
+ if st.stream(1) != nil {
+ t.Fatal("stream 1 should be empty")
+ }
+ if got := st.streamState(1); got != stateIdle {
+ t.Fatalf("stream 1 should be idle; got %v", got)
+ }
+
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: 1,
+ BlockFragment: st.encodeHeader(":method", "POST"),
+ EndStream: false, // keep it open
+ EndHeaders: true,
+ })
+ <-inHandler
+ <-writeData
+ st.writeData(1, true, nil)
+
+ leaveHandler <- true
+ hf := st.wantHeaders()
+ if !hf.StreamEnded() {
+ t.Fatal("expected END_STREAM flag")
+ }
+
+ if got, want := st.streamState(1), stateClosed; got != want {
+ t.Errorf("at end, state is %v; want %v", got, want)
+ }
+ if st.stream(1) != nil {
+ t.Fatal("at end, stream 1 should be gone")
+ }
+}
+
+// test HEADERS w/o EndHeaders + another HEADERS (should get rejected)
+func TestServer_Rejects_HeadersNoEnd_Then_Headers(t *testing.T) {
+ testServerRejectsConn(t, func(st *serverTester) {
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: 1,
+ BlockFragment: st.encodeHeader(),
+ EndStream: true,
+ EndHeaders: false,
+ })
+ st.writeHeaders(HeadersFrameParam{ // Not a continuation.
+ StreamID: 3, // different stream.
+ BlockFragment: st.encodeHeader(),
+ EndStream: true,
+ EndHeaders: true,
+ })
+ })
+}
+
+// test HEADERS w/o EndHeaders + PING (should get rejected)
+func TestServer_Rejects_HeadersNoEnd_Then_Ping(t *testing.T) {
+ testServerRejectsConn(t, func(st *serverTester) {
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: 1,
+ BlockFragment: st.encodeHeader(),
+ EndStream: true,
+ EndHeaders: false,
+ })
+ if err := st.fr.WritePing(false, [8]byte{}); err != nil {
+ t.Fatal(err)
+ }
+ })
+}
+
+// test HEADERS w/ EndHeaders + a continuation HEADERS (should get rejected)
+func TestServer_Rejects_HeadersEnd_Then_Continuation(t *testing.T) {
+ testServerRejectsConn(t, func(st *serverTester) {
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: 1,
+ BlockFragment: st.encodeHeader(),
+ EndStream: true,
+ EndHeaders: true,
+ })
+ st.wantHeaders()
+ if err := st.fr.WriteContinuation(1, true, encodeHeaderNoImplicit(t, "foo", "bar")); err != nil {
+ t.Fatal(err)
+ }
+ })
+}
+
+// test HEADERS w/o EndHeaders + a continuation HEADERS on wrong stream ID
+func TestServer_Rejects_HeadersNoEnd_Then_ContinuationWrongStream(t *testing.T) {
+ testServerRejectsConn(t, func(st *serverTester) {
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: 1,
+ BlockFragment: st.encodeHeader(),
+ EndStream: true,
+ EndHeaders: false,
+ })
+ if err := st.fr.WriteContinuation(3, true, encodeHeaderNoImplicit(t, "foo", "bar")); err != nil {
+ t.Fatal(err)
+ }
+ })
+}
+
+// No HEADERS on stream 0.
+func TestServer_Rejects_Headers0(t *testing.T) {
+ testServerRejectsConn(t, func(st *serverTester) {
+ st.fr.AllowIllegalWrites = true
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: 0,
+ BlockFragment: st.encodeHeader(),
+ EndStream: true,
+ EndHeaders: true,
+ })
+ })
+}
+
+// No CONTINUATION on stream 0.
+func TestServer_Rejects_Continuation0(t *testing.T) {
+ testServerRejectsConn(t, func(st *serverTester) {
+ st.fr.AllowIllegalWrites = true
+ if err := st.fr.WriteContinuation(0, true, st.encodeHeader()); err != nil {
+ t.Fatal(err)
+ }
+ })
+}
+
+// No PRIORITY on stream 0.
+func TestServer_Rejects_Priority0(t *testing.T) {
+ testServerRejectsConn(t, func(st *serverTester) {
+ st.fr.AllowIllegalWrites = true
+ st.writePriority(0, PriorityParam{StreamDep: 1})
+ })
+}
+
+// No HEADERS frame with a self-dependence.
+func TestServer_Rejects_HeadersSelfDependence(t *testing.T) {
+ testServerRejectsStream(t, ErrCodeProtocol, func(st *serverTester) {
+ st.fr.AllowIllegalWrites = true
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: 1,
+ BlockFragment: st.encodeHeader(),
+ EndStream: true,
+ EndHeaders: true,
+ Priority: PriorityParam{StreamDep: 1},
+ })
+ })
+}
+
+// No PRIORTY frame with a self-dependence.
+func TestServer_Rejects_PrioritySelfDependence(t *testing.T) {
+ testServerRejectsStream(t, ErrCodeProtocol, func(st *serverTester) {
+ st.fr.AllowIllegalWrites = true
+ st.writePriority(1, PriorityParam{StreamDep: 1})
+ })
+}
+
+func TestServer_Rejects_PushPromise(t *testing.T) {
+ testServerRejectsConn(t, func(st *serverTester) {
+ pp := PushPromiseParam{
+ StreamID: 1,
+ PromiseID: 3,
+ }
+ if err := st.fr.WritePushPromise(pp); err != nil {
+ t.Fatal(err)
+ }
+ })
+}
+
+// testServerRejectsConn tests that the server hangs up with a GOAWAY
+// frame and a server close after the client does something
+// deserving a CONNECTION_ERROR.
+func testServerRejectsConn(t *testing.T, writeReq func(*serverTester)) {
+ st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {})
+ st.addLogFilter("connection error: PROTOCOL_ERROR")
+ defer st.Close()
+ st.greet()
+ writeReq(st)
+
+ st.wantGoAway()
+ errc := make(chan error, 1)
+ go func() {
+ fr, err := st.fr.ReadFrame()
+ if err == nil {
+ err = fmt.Errorf("got frame of type %T", fr)
+ }
+ errc <- err
+ }()
+ select {
+ case err := <-errc:
+ if err != io.EOF {
+ t.Errorf("ReadFrame = %v; want io.EOF", err)
+ }
+ case <-time.After(2 * time.Second):
+ t.Error("timeout waiting for disconnect")
+ }
+}
+
+// testServerRejectsStream tests that the server sends a RST_STREAM with the provided
+// error code after a client sends a bogus request.
+func testServerRejectsStream(t *testing.T, code ErrCode, writeReq func(*serverTester)) {
+ st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {})
+ defer st.Close()
+ st.greet()
+ writeReq(st)
+ st.wantRSTStream(1, code)
+}
+
+// testServerRequest sets up an idle HTTP/2 connection and lets you
+// write a single request with writeReq, and then verify that the
+// *http.Request is built correctly in checkReq.
+func testServerRequest(t *testing.T, writeReq func(*serverTester), checkReq func(*http.Request)) {
+ gotReq := make(chan bool, 1)
+ st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+ if r.Body == nil {
+ t.Fatal("nil Body")
+ }
+ checkReq(r)
+ gotReq <- true
+ })
+ defer st.Close()
+
+ st.greet()
+ writeReq(st)
+
+ select {
+ case <-gotReq:
+ case <-time.After(2 * time.Second):
+ t.Error("timeout waiting for request")
+ }
+}
+
+func getSlash(st *serverTester) { st.bodylessReq1() }
+
+func TestServer_Response_NoData(t *testing.T) {
+ testServerResponse(t, func(w http.ResponseWriter, r *http.Request) error {
+ // Nothing.
+ return nil
+ }, func(st *serverTester) {
+ getSlash(st)
+ hf := st.wantHeaders()
+ if !hf.StreamEnded() {
+ t.Fatal("want END_STREAM flag")
+ }
+ if !hf.HeadersEnded() {
+ t.Fatal("want END_HEADERS flag")
+ }
+ })
+}
+
+func TestServer_Response_NoData_Header_FooBar(t *testing.T) {
+ testServerResponse(t, func(w http.ResponseWriter, r *http.Request) error {
+ w.Header().Set("Foo-Bar", "some-value")
+ return nil
+ }, func(st *serverTester) {
+ getSlash(st)
+ hf := st.wantHeaders()
+ if !hf.StreamEnded() {
+ t.Fatal("want END_STREAM flag")
+ }
+ if !hf.HeadersEnded() {
+ t.Fatal("want END_HEADERS flag")
+ }
+ goth := st.decodeHeader(hf.HeaderBlockFragment())
+ wanth := [][2]string{
+ {":status", "200"},
+ {"foo-bar", "some-value"},
+ {"content-length", "0"},
+ }
+ if !reflect.DeepEqual(goth, wanth) {
+ t.Errorf("Got headers %v; want %v", goth, wanth)
+ }
+ })
+}
+
+func TestServer_Response_Data_Sniff_DoesntOverride(t *testing.T) {
+ const msg = "<html>this is HTML."
+ testServerResponse(t, func(w http.ResponseWriter, r *http.Request) error {
+ w.Header().Set("Content-Type", "foo/bar")
+ io.WriteString(w, msg)
+ return nil
+ }, func(st *serverTester) {
+ getSlash(st)
+ hf := st.wantHeaders()
+ if hf.StreamEnded() {
+ t.Fatal("don't want END_STREAM, expecting data")
+ }
+ if !hf.HeadersEnded() {
+ t.Fatal("want END_HEADERS flag")
+ }
+ goth := st.decodeHeader(hf.HeaderBlockFragment())
+ wanth := [][2]string{
+ {":status", "200"},
+ {"content-type", "foo/bar"},
+ {"content-length", strconv.Itoa(len(msg))},
+ }
+ if !reflect.DeepEqual(goth, wanth) {
+ t.Errorf("Got headers %v; want %v", goth, wanth)
+ }
+ df := st.wantData()
+ if !df.StreamEnded() {
+ t.Error("expected DATA to have END_STREAM flag")
+ }
+ if got := string(df.Data()); got != msg {
+ t.Errorf("got DATA %q; want %q", got, msg)
+ }
+ })
+}
+
+func TestServer_Response_TransferEncoding_chunked(t *testing.T) {
+ const msg = "hi"
+ testServerResponse(t, func(w http.ResponseWriter, r *http.Request) error {
+ w.Header().Set("Transfer-Encoding", "chunked") // should be stripped
+ io.WriteString(w, msg)
+ return nil
+ }, func(st *serverTester) {
+ getSlash(st)
+ hf := st.wantHeaders()
+ goth := st.decodeHeader(hf.HeaderBlockFragment())
+ wanth := [][2]string{
+ {":status", "200"},
+ {"content-type", "text/plain; charset=utf-8"},
+ {"content-length", strconv.Itoa(len(msg))},
+ }
+ if !reflect.DeepEqual(goth, wanth) {
+ t.Errorf("Got headers %v; want %v", goth, wanth)
+ }
+ })
+}
+
+// Header accessed only after the initial write.
+func TestServer_Response_Data_IgnoreHeaderAfterWrite_After(t *testing.T) {
+ const msg = "<html>this is HTML."
+ testServerResponse(t, func(w http.ResponseWriter, r *http.Request) error {
+ io.WriteString(w, msg)
+ w.Header().Set("foo", "should be ignored")
+ return nil
+ }, func(st *serverTester) {
+ getSlash(st)
+ hf := st.wantHeaders()
+ if hf.StreamEnded() {
+ t.Fatal("unexpected END_STREAM")
+ }
+ if !hf.HeadersEnded() {
+ t.Fatal("want END_HEADERS flag")
+ }
+ goth := st.decodeHeader(hf.HeaderBlockFragment())
+ wanth := [][2]string{
+ {":status", "200"},
+ {"content-type", "text/html; charset=utf-8"},
+ {"content-length", strconv.Itoa(len(msg))},
+ }
+ if !reflect.DeepEqual(goth, wanth) {
+ t.Errorf("Got headers %v; want %v", goth, wanth)
+ }
+ })
+}
+
+// Header accessed before the initial write and later mutated.
+func TestServer_Response_Data_IgnoreHeaderAfterWrite_Overwrite(t *testing.T) {
+ const msg = "<html>this is HTML."
+ testServerResponse(t, func(w http.ResponseWriter, r *http.Request) error {
+ w.Header().Set("foo", "proper value")
+ io.WriteString(w, msg)
+ w.Header().Set("foo", "should be ignored")
+ return nil
+ }, func(st *serverTester) {
+ getSlash(st)
+ hf := st.wantHeaders()
+ if hf.StreamEnded() {
+ t.Fatal("unexpected END_STREAM")
+ }
+ if !hf.HeadersEnded() {
+ t.Fatal("want END_HEADERS flag")
+ }
+ goth := st.decodeHeader(hf.HeaderBlockFragment())
+ wanth := [][2]string{
+ {":status", "200"},
+ {"foo", "proper value"},
+ {"content-type", "text/html; charset=utf-8"},
+ {"content-length", strconv.Itoa(len(msg))},
+ }
+ if !reflect.DeepEqual(goth, wanth) {
+ t.Errorf("Got headers %v; want %v", goth, wanth)
+ }
+ })
+}
+
+func TestServer_Response_Data_SniffLenType(t *testing.T) {
+ const msg = "<html>this is HTML."
+ testServerResponse(t, func(w http.ResponseWriter, r *http.Request) error {
+ io.WriteString(w, msg)
+ return nil
+ }, func(st *serverTester) {
+ getSlash(st)
+ hf := st.wantHeaders()
+ if hf.StreamEnded() {
+ t.Fatal("don't want END_STREAM, expecting data")
+ }
+ if !hf.HeadersEnded() {
+ t.Fatal("want END_HEADERS flag")
+ }
+ goth := st.decodeHeader(hf.HeaderBlockFragment())
+ wanth := [][2]string{
+ {":status", "200"},
+ {"content-type", "text/html; charset=utf-8"},
+ {"content-length", strconv.Itoa(len(msg))},
+ }
+ if !reflect.DeepEqual(goth, wanth) {
+ t.Errorf("Got headers %v; want %v", goth, wanth)
+ }
+ df := st.wantData()
+ if !df.StreamEnded() {
+ t.Error("expected DATA to have END_STREAM flag")
+ }
+ if got := string(df.Data()); got != msg {
+ t.Errorf("got DATA %q; want %q", got, msg)
+ }
+ })
+}
+
+func TestServer_Response_Header_Flush_MidWrite(t *testing.T) {
+ const msg = "<html>this is HTML"
+ const msg2 = ", and this is the next chunk"
+ testServerResponse(t, func(w http.ResponseWriter, r *http.Request) error {
+ io.WriteString(w, msg)
+ w.(http.Flusher).Flush()
+ io.WriteString(w, msg2)
+ return nil
+ }, func(st *serverTester) {
+ getSlash(st)
+ hf := st.wantHeaders()
+ if hf.StreamEnded() {
+ t.Fatal("unexpected END_STREAM flag")
+ }
+ if !hf.HeadersEnded() {
+ t.Fatal("want END_HEADERS flag")
+ }
+ goth := st.decodeHeader(hf.HeaderBlockFragment())
+ wanth := [][2]string{
+ {":status", "200"},
+ {"content-type", "text/html; charset=utf-8"}, // sniffed
+ // and no content-length
+ }
+ if !reflect.DeepEqual(goth, wanth) {
+ t.Errorf("Got headers %v; want %v", goth, wanth)
+ }
+ {
+ df := st.wantData()
+ if df.StreamEnded() {
+ t.Error("unexpected END_STREAM flag")
+ }
+ if got := string(df.Data()); got != msg {
+ t.Errorf("got DATA %q; want %q", got, msg)
+ }
+ }
+ {
+ df := st.wantData()
+ if !df.StreamEnded() {
+ t.Error("wanted END_STREAM flag on last data chunk")
+ }
+ if got := string(df.Data()); got != msg2 {
+ t.Errorf("got DATA %q; want %q", got, msg2)
+ }
+ }
+ })
+}
+
+func TestServer_Response_LargeWrite(t *testing.T) {
+ const size = 1 << 20
+ const maxFrameSize = 16 << 10
+ testServerResponse(t, func(w http.ResponseWriter, r *http.Request) error {
+ n, err := w.Write(bytes.Repeat([]byte("a"), size))
+ if err != nil {
+ return fmt.Errorf("Write error: %v", err)
+ }
+ if n != size {
+ return fmt.Errorf("wrong size %d from Write", n)
+ }
+ return nil
+ }, func(st *serverTester) {
+ if err := st.fr.WriteSettings(
+ Setting{SettingInitialWindowSize, 0},
+ Setting{SettingMaxFrameSize, maxFrameSize},
+ ); err != nil {
+ t.Fatal(err)
+ }
+ st.wantSettingsAck()
+
+ getSlash(st) // make the single request
+
+ // Give the handler quota to write:
+ if err := st.fr.WriteWindowUpdate(1, size); err != nil {
+ t.Fatal(err)
+ }
+ // Give the handler quota to write to connection-level
+ // window as well
+ if err := st.fr.WriteWindowUpdate(0, size); err != nil {
+ t.Fatal(err)
+ }
+ hf := st.wantHeaders()
+ if hf.StreamEnded() {
+ t.Fatal("unexpected END_STREAM flag")
+ }
+ if !hf.HeadersEnded() {
+ t.Fatal("want END_HEADERS flag")
+ }
+ goth := st.decodeHeader(hf.HeaderBlockFragment())
+ wanth := [][2]string{
+ {":status", "200"},
+ {"content-type", "text/plain; charset=utf-8"}, // sniffed
+ // and no content-length
+ }
+ if !reflect.DeepEqual(goth, wanth) {
+ t.Errorf("Got headers %v; want %v", goth, wanth)
+ }
+ var bytes, frames int
+ for {
+ df := st.wantData()
+ bytes += len(df.Data())
+ frames++
+ for _, b := range df.Data() {
+ if b != 'a' {
+ t.Fatal("non-'a' byte seen in DATA")
+ }
+ }
+ if df.StreamEnded() {
+ break
+ }
+ }
+ if bytes != size {
+ t.Errorf("Got %d bytes; want %d", bytes, size)
+ }
+ if want := int(size / maxFrameSize); frames < want || frames > want*2 {
+ t.Errorf("Got %d frames; want %d", frames, size)
+ }
+ })
+}
+
+// Test that the handler can't write more than the client allows
+func TestServer_Response_LargeWrite_FlowControlled(t *testing.T) {
+ // Make these reads. Before each read, the client adds exactly enough
+ // flow-control to satisfy the read. Numbers chosen arbitrarily.
+ reads := []int{123, 1, 13, 127}
+ size := 0
+ for _, n := range reads {
+ size += n
+ }
+
+ testServerResponse(t, func(w http.ResponseWriter, r *http.Request) error {
+ w.(http.Flusher).Flush()
+ n, err := w.Write(bytes.Repeat([]byte("a"), size))
+ if err != nil {
+ return fmt.Errorf("Write error: %v", err)
+ }
+ if n != size {
+ return fmt.Errorf("wrong size %d from Write", n)
+ }
+ return nil
+ }, func(st *serverTester) {
+ // Set the window size to something explicit for this test.
+ // It's also how much initial data we expect.
+ if err := st.fr.WriteSettings(Setting{SettingInitialWindowSize, uint32(reads[0])}); err != nil {
+ t.Fatal(err)
+ }
+ st.wantSettingsAck()
+
+ getSlash(st) // make the single request
+
+ hf := st.wantHeaders()
+ if hf.StreamEnded() {
+ t.Fatal("unexpected END_STREAM flag")
+ }
+ if !hf.HeadersEnded() {
+ t.Fatal("want END_HEADERS flag")
+ }
+
+ df := st.wantData()
+ if got := len(df.Data()); got != reads[0] {
+ t.Fatalf("Initial window size = %d but got DATA with %d bytes", reads[0], got)
+ }
+
+ for _, quota := range reads[1:] {
+ if err := st.fr.WriteWindowUpdate(1, uint32(quota)); err != nil {
+ t.Fatal(err)
+ }
+ df := st.wantData()
+ if int(quota) != len(df.Data()) {
+ t.Fatalf("read %d bytes after giving %d quota", len(df.Data()), quota)
+ }
+ }
+ })
+}
+
+// Test that the handler blocked in a Write is unblocked if the server sends a RST_STREAM.
+func TestServer_Response_RST_Unblocks_LargeWrite(t *testing.T) {
+ const size = 1 << 20
+ const maxFrameSize = 16 << 10
+ testServerResponse(t, func(w http.ResponseWriter, r *http.Request) error {
+ w.(http.Flusher).Flush()
+ errc := make(chan error, 1)
+ go func() {
+ _, err := w.Write(bytes.Repeat([]byte("a"), size))
+ errc <- err
+ }()
+ select {
+ case err := <-errc:
+ if err == nil {
+ return errors.New("unexpected nil error from Write in handler")
+ }
+ return nil
+ case <-time.After(2 * time.Second):
+ return errors.New("timeout waiting for Write in handler")
+ }
+ }, func(st *serverTester) {
+ if err := st.fr.WriteSettings(
+ Setting{SettingInitialWindowSize, 0},
+ Setting{SettingMaxFrameSize, maxFrameSize},
+ ); err != nil {
+ t.Fatal(err)
+ }
+ st.wantSettingsAck()
+
+ getSlash(st) // make the single request
+
+ hf := st.wantHeaders()
+ if hf.StreamEnded() {
+ t.Fatal("unexpected END_STREAM flag")
+ }
+ if !hf.HeadersEnded() {
+ t.Fatal("want END_HEADERS flag")
+ }
+
+ if err := st.fr.WriteRSTStream(1, ErrCodeCancel); err != nil {
+ t.Fatal(err)
+ }
+ })
+}
+
+func TestServer_Response_Empty_Data_Not_FlowControlled(t *testing.T) {
+ testServerResponse(t, func(w http.ResponseWriter, r *http.Request) error {
+ w.(http.Flusher).Flush()
+ // Nothing; send empty DATA
+ return nil
+ }, func(st *serverTester) {
+ // Handler gets no data quota:
+ if err := st.fr.WriteSettings(Setting{SettingInitialWindowSize, 0}); err != nil {
+ t.Fatal(err)
+ }
+ st.wantSettingsAck()
+
+ getSlash(st) // make the single request
+
+ hf := st.wantHeaders()
+ if hf.StreamEnded() {
+ t.Fatal("unexpected END_STREAM flag")
+ }
+ if !hf.HeadersEnded() {
+ t.Fatal("want END_HEADERS flag")
+ }
+
+ df := st.wantData()
+ if got := len(df.Data()); got != 0 {
+ t.Fatalf("unexpected %d DATA bytes; want 0", got)
+ }
+ if !df.StreamEnded() {
+ t.Fatal("DATA didn't have END_STREAM")
+ }
+ })
+}
+
+func TestServer_Response_Automatic100Continue(t *testing.T) {
+ const msg = "foo"
+ const reply = "bar"
+ testServerResponse(t, func(w http.ResponseWriter, r *http.Request) error {
+ if v := r.Header.Get("Expect"); v != "" {
+ t.Errorf("Expect header = %q; want empty", v)
+ }
+ buf := make([]byte, len(msg))
+ // This read should trigger the 100-continue being sent.
+ if n, err := io.ReadFull(r.Body, buf); err != nil || n != len(msg) || string(buf) != msg {
+ return fmt.Errorf("ReadFull = %q, %v; want %q, nil", buf[:n], err, msg)
+ }
+ _, err := io.WriteString(w, reply)
+ return err
+ }, func(st *serverTester) {
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: 1, // clients send odd numbers
+ BlockFragment: st.encodeHeader(":method", "POST", "expect", "100-continue"),
+ EndStream: false,
+ EndHeaders: true,
+ })
+ hf := st.wantHeaders()
+ if hf.StreamEnded() {
+ t.Fatal("unexpected END_STREAM flag")
+ }
+ if !hf.HeadersEnded() {
+ t.Fatal("want END_HEADERS flag")
+ }
+ goth := st.decodeHeader(hf.HeaderBlockFragment())
+ wanth := [][2]string{
+ {":status", "100"},
+ }
+ if !reflect.DeepEqual(goth, wanth) {
+ t.Fatalf("Got headers %v; want %v", goth, wanth)
+ }
+
+ // Okay, they sent status 100, so we can send our
+ // gigantic and/or sensitive "foo" payload now.
+ st.writeData(1, true, []byte(msg))
+
+ st.wantWindowUpdate(0, uint32(len(msg)))
+
+ hf = st.wantHeaders()
+ if hf.StreamEnded() {
+ t.Fatal("expected data to follow")
+ }
+ if !hf.HeadersEnded() {
+ t.Fatal("want END_HEADERS flag")
+ }
+ goth = st.decodeHeader(hf.HeaderBlockFragment())
+ wanth = [][2]string{
+ {":status", "200"},
+ {"content-type", "text/plain; charset=utf-8"},
+ {"content-length", strconv.Itoa(len(reply))},
+ }
+ if !reflect.DeepEqual(goth, wanth) {
+ t.Errorf("Got headers %v; want %v", goth, wanth)
+ }
+
+ df := st.wantData()
+ if string(df.Data()) != reply {
+ t.Errorf("Client read %q; want %q", df.Data(), reply)
+ }
+ if !df.StreamEnded() {
+ t.Errorf("expect data stream end")
+ }
+ })
+}
+
+func TestServer_HandlerWriteErrorOnDisconnect(t *testing.T) {
+ errc := make(chan error, 1)
+ testServerResponse(t, func(w http.ResponseWriter, r *http.Request) error {
+ p := []byte("some data.\n")
+ for {
+ _, err := w.Write(p)
+ if err != nil {
+ errc <- err
+ return nil
+ }
+ }
+ }, func(st *serverTester) {
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: 1,
+ BlockFragment: st.encodeHeader(),
+ EndStream: false,
+ EndHeaders: true,
+ })
+ hf := st.wantHeaders()
+ if hf.StreamEnded() {
+ t.Fatal("unexpected END_STREAM flag")
+ }
+ if !hf.HeadersEnded() {
+ t.Fatal("want END_HEADERS flag")
+ }
+ // Close the connection and wait for the handler to (hopefully) notice.
+ st.cc.Close()
+ select {
+ case <-errc:
+ case <-time.After(5 * time.Second):
+ t.Error("timeout")
+ }
+ })
+}
+
+func TestServer_Rejects_Too_Many_Streams(t *testing.T) {
+ const testPath = "/some/path"
+
+ inHandler := make(chan uint32)
+ leaveHandler := make(chan bool)
+ st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+ id := w.(*responseWriter).rws.stream.id
+ inHandler <- id
+ if id == 1+(defaultMaxStreams+1)*2 && r.URL.Path != testPath {
+ t.Errorf("decoded final path as %q; want %q", r.URL.Path, testPath)
+ }
+ <-leaveHandler
+ })
+ defer st.Close()
+ st.greet()
+ nextStreamID := uint32(1)
+ streamID := func() uint32 {
+ defer func() { nextStreamID += 2 }()
+ return nextStreamID
+ }
+ sendReq := func(id uint32, headers ...string) {
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: id,
+ BlockFragment: st.encodeHeader(headers...),
+ EndStream: true,
+ EndHeaders: true,
+ })
+ }
+ for i := 0; i < defaultMaxStreams; i++ {
+ sendReq(streamID())
+ <-inHandler
+ }
+ defer func() {
+ for i := 0; i < defaultMaxStreams; i++ {
+ leaveHandler <- true
+ }
+ }()
+
+ // And this one should cross the limit:
+ // (It's also sent as a CONTINUATION, to verify we still track the decoder context,
+ // even if we're rejecting it)
+ rejectID := streamID()
+ headerBlock := st.encodeHeader(":path", testPath)
+ frag1, frag2 := headerBlock[:3], headerBlock[3:]
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: rejectID,
+ BlockFragment: frag1,
+ EndStream: true,
+ EndHeaders: false, // CONTINUATION coming
+ })
+ if err := st.fr.WriteContinuation(rejectID, true, frag2); err != nil {
+ t.Fatal(err)
+ }
+ st.wantRSTStream(rejectID, ErrCodeProtocol)
+
+ // But let a handler finish:
+ leaveHandler <- true
+ st.wantHeaders()
+
+ // And now another stream should be able to start:
+ goodID := streamID()
+ sendReq(goodID, ":path", testPath)
+ select {
+ case got := <-inHandler:
+ if got != goodID {
+ t.Errorf("Got stream %d; want %d", got, goodID)
+ }
+ case <-time.After(3 * time.Second):
+ t.Error("timeout waiting for handler")
+ }
+}
+
+// So many response headers that the server needs to use CONTINUATION frames:
+func TestServer_Response_ManyHeaders_With_Continuation(t *testing.T) {
+ testServerResponse(t, func(w http.ResponseWriter, r *http.Request) error {
+ h := w.Header()
+ for i := 0; i < 5000; i++ {
+ h.Set(fmt.Sprintf("x-header-%d", i), fmt.Sprintf("x-value-%d", i))
+ }
+ return nil
+ }, func(st *serverTester) {
+ getSlash(st)
+ hf := st.wantHeaders()
+ if hf.HeadersEnded() {
+ t.Fatal("got unwanted END_HEADERS flag")
+ }
+ n := 0
+ for {
+ n++
+ cf := st.wantContinuation()
+ if cf.HeadersEnded() {
+ break
+ }
+ }
+ if n < 5 {
+ t.Errorf("Only got %d CONTINUATION frames; expected 5+ (currently 6)", n)
+ }
+ })
+}
+
+// This previously crashed (reported by Mathieu Lonjaret as observed
+// while using Camlistore) because we got a DATA frame from the client
+// after the handler exited and our logic at the time was wrong,
+// keeping a stream in the map in stateClosed, which tickled an
+// invariant check later when we tried to remove that stream (via
+// defer sc.closeAllStreamsOnConnClose) when the serverConn serve loop
+// ended.
+func TestServer_NoCrash_HandlerClose_Then_ClientClose(t *testing.T) {
+ testServerResponse(t, func(w http.ResponseWriter, r *http.Request) error {
+ // nothing
+ return nil
+ }, func(st *serverTester) {
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: 1,
+ BlockFragment: st.encodeHeader(),
+ EndStream: false, // DATA is coming
+ EndHeaders: true,
+ })
+ hf := st.wantHeaders()
+ if !hf.HeadersEnded() || !hf.StreamEnded() {
+ t.Fatalf("want END_HEADERS+END_STREAM, got %v", hf)
+ }
+
+ // Sent when the a Handler closes while a client has
+ // indicated it's still sending DATA:
+ st.wantRSTStream(1, ErrCodeNo)
+
+ // Now the handler has ended, so it's ended its
+ // stream, but the client hasn't closed its side
+ // (stateClosedLocal). So send more data and verify
+ // it doesn't crash with an internal invariant panic, like
+ // it did before.
+ st.writeData(1, true, []byte("foo"))
+
+ // Get our flow control bytes back, since the handler didn't get them.
+ st.wantWindowUpdate(0, uint32(len("foo")))
+
+ // Sent after a peer sends data anyway (admittedly the
+ // previous RST_STREAM might've still been in-flight),
+ // but they'll get the more friendly 'cancel' code
+ // first.
+ st.wantRSTStream(1, ErrCodeStreamClosed)
+
+ // Set up a bunch of machinery to record the panic we saw
+ // previously.
+ var (
+ panMu sync.Mutex
+ panicVal interface{}
+ )
+
+ testHookOnPanicMu.Lock()
+ testHookOnPanic = func(sc *serverConn, pv interface{}) bool {
+ panMu.Lock()
+ panicVal = pv
+ panMu.Unlock()
+ return true
+ }
+ testHookOnPanicMu.Unlock()
+
+ // Now force the serve loop to end, via closing the connection.
+ st.cc.Close()
+ select {
+ case <-st.sc.doneServing:
+ // Loop has exited.
+ panMu.Lock()
+ got := panicVal
+ panMu.Unlock()
+ if got != nil {
+ t.Errorf("Got panic: %v", got)
+ }
+ case <-time.After(5 * time.Second):
+ t.Error("timeout")
+ }
+ })
+}
+
+func TestServer_Rejects_TLS10(t *testing.T) { testRejectTLS(t, tls.VersionTLS10) }
+func TestServer_Rejects_TLS11(t *testing.T) { testRejectTLS(t, tls.VersionTLS11) }
+
+func testRejectTLS(t *testing.T, max uint16) {
+ st := newServerTester(t, nil, func(c *tls.Config) {
+ c.MaxVersion = max
+ })
+ defer st.Close()
+ gf := st.wantGoAway()
+ if got, want := gf.ErrCode, ErrCodeInadequateSecurity; got != want {
+ t.Errorf("Got error code %v; want %v", got, want)
+ }
+}
+
+func TestServer_Rejects_TLSBadCipher(t *testing.T) {
+ st := newServerTester(t, nil, func(c *tls.Config) {
+ // Only list bad ones:
+ c.CipherSuites = []uint16{
+ tls.TLS_RSA_WITH_RC4_128_SHA,
+ tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
+ tls.TLS_RSA_WITH_AES_128_CBC_SHA,
+ tls.TLS_RSA_WITH_AES_256_CBC_SHA,
+ tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
+ tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+ tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
+ tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
+ tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
+ tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+ tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
+ cipher_TLS_RSA_WITH_AES_128_CBC_SHA256,
+ }
+ })
+ defer st.Close()
+ gf := st.wantGoAway()
+ if got, want := gf.ErrCode, ErrCodeInadequateSecurity; got != want {
+ t.Errorf("Got error code %v; want %v", got, want)
+ }
+}
+
+func TestServer_Advertises_Common_Cipher(t *testing.T) {
+ const requiredSuite = tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
+ st := newServerTester(t, nil, func(c *tls.Config) {
+ // Have the client only support the one required by the spec.
+ c.CipherSuites = []uint16{requiredSuite}
+ }, func(ts *httptest.Server) {
+ var srv *http.Server = ts.Config
+ // Have the server configured with no specific cipher suites.
+ // This tests that Go's defaults include the required one.
+ srv.TLSConfig = nil
+ })
+ defer st.Close()
+ st.greet()
+}
+
+func (st *serverTester) onHeaderField(f hpack.HeaderField) {
+ if f.Name == "date" {
+ return
+ }
+ st.decodedHeaders = append(st.decodedHeaders, [2]string{f.Name, f.Value})
+}
+
+func (st *serverTester) decodeHeader(headerBlock []byte) (pairs [][2]string) {
+ st.decodedHeaders = nil
+ if _, err := st.hpackDec.Write(headerBlock); err != nil {
+ st.t.Fatalf("hpack decoding error: %v", err)
+ }
+ if err := st.hpackDec.Close(); err != nil {
+ st.t.Fatalf("hpack decoding error: %v", err)
+ }
+ return st.decodedHeaders
+}
+
+// testServerResponse sets up an idle HTTP/2 connection. The client function should
+// write a single request that must be handled by the handler. This waits up to 5s
+// for client to return, then up to an additional 2s for the handler to return.
+func testServerResponse(t testing.TB,
+ handler func(http.ResponseWriter, *http.Request) error,
+ client func(*serverTester),
+) {
+ errc := make(chan error, 1)
+ st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+ if r.Body == nil {
+ t.Fatal("nil Body")
+ }
+ errc <- handler(w, r)
+ })
+ defer st.Close()
+
+ donec := make(chan bool)
+ go func() {
+ defer close(donec)
+ st.greet()
+ client(st)
+ }()
+
+ select {
+ case <-donec:
+ case <-time.After(5 * time.Second):
+ t.Fatal("timeout in client")
+ }
+
+ select {
+ case err := <-errc:
+ if err != nil {
+ t.Fatalf("Error in handler: %v", err)
+ }
+ case <-time.After(2 * time.Second):
+ t.Fatal("timeout in handler")
+ }
+}
+
+// readBodyHandler returns an http Handler func that reads len(want)
+// bytes from r.Body and fails t if the contents read were not
+// the value of want.
+func readBodyHandler(t *testing.T, want string) func(w http.ResponseWriter, r *http.Request) {
+ return func(w http.ResponseWriter, r *http.Request) {
+ buf := make([]byte, len(want))
+ _, err := io.ReadFull(r.Body, buf)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ if string(buf) != want {
+ t.Errorf("read %q; want %q", buf, want)
+ }
+ }
+}
+
+// TestServerWithCurl currently fails, hence the LenientCipherSuites test. See:
+// https://github.com/tatsuhiro-t/nghttp2/issues/140 &
+// http://sourceforge.net/p/curl/bugs/1472/
+func TestServerWithCurl(t *testing.T) { testServerWithCurl(t, false) }
+func TestServerWithCurl_LenientCipherSuites(t *testing.T) { testServerWithCurl(t, true) }
+
+func testServerWithCurl(t *testing.T, permitProhibitedCipherSuites bool) {
+ if runtime.GOOS != "linux" {
+ t.Skip("skipping Docker test when not on Linux; requires --net which won't work with boot2docker anyway")
+ }
+ if testing.Short() {
+ t.Skip("skipping curl test in short mode")
+ }
+ requireCurl(t)
+ var gotConn int32
+ testHookOnConn = func() { atomic.StoreInt32(&gotConn, 1) }
+
+ const msg = "Hello from curl!\n"
+ ts := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Foo", "Bar")
+ w.Header().Set("Client-Proto", r.Proto)
+ io.WriteString(w, msg)
+ }))
+ ConfigureServer(ts.Config, &Server{
+ PermitProhibitedCipherSuites: permitProhibitedCipherSuites,
+ })
+ ts.TLS = ts.Config.TLSConfig // the httptest.Server has its own copy of this TLS config
+ ts.StartTLS()
+ defer ts.Close()
+
+ t.Logf("Running test server for curl to hit at: %s", ts.URL)
+ container := curl(t, "--silent", "--http2", "--insecure", "-v", ts.URL)
+ defer kill(container)
+ resc := make(chan interface{}, 1)
+ go func() {
+ res, err := dockerLogs(container)
+ if err != nil {
+ resc <- err
+ } else {
+ resc <- res
+ }
+ }()
+ select {
+ case res := <-resc:
+ if err, ok := res.(error); ok {
+ t.Fatal(err)
+ }
+ body := string(res.([]byte))
+ // Search for both "key: value" and "key:value", since curl changed their format
+ // Our Dockerfile contains the latest version (no space), but just in case people
+ // didn't rebuild, check both.
+ if !strings.Contains(body, "foo: Bar") && !strings.Contains(body, "foo:Bar") {
+ t.Errorf("didn't see foo: Bar header")
+ t.Logf("Got: %s", body)
+ }
+ if !strings.Contains(body, "client-proto: HTTP/2") && !strings.Contains(body, "client-proto:HTTP/2") {
+ t.Errorf("didn't see client-proto: HTTP/2 header")
+ t.Logf("Got: %s", res)
+ }
+ if !strings.Contains(string(res.([]byte)), msg) {
+ t.Errorf("didn't see %q content", msg)
+ t.Logf("Got: %s", res)
+ }
+ case <-time.After(3 * time.Second):
+ t.Errorf("timeout waiting for curl")
+ }
+
+ if atomic.LoadInt32(&gotConn) == 0 {
+ t.Error("never saw an http2 connection")
+ }
+}
+
+var doh2load = flag.Bool("h2load", false, "Run h2load test")
+
+func TestServerWithH2Load(t *testing.T) {
+ if !*doh2load {
+ t.Skip("Skipping without --h2load flag.")
+ }
+ if runtime.GOOS != "linux" {
+ t.Skip("skipping Docker test when not on Linux; requires --net which won't work with boot2docker anyway")
+ }
+ requireH2load(t)
+
+ msg := strings.Repeat("Hello, h2load!\n", 5000)
+ ts := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ io.WriteString(w, msg)
+ w.(http.Flusher).Flush()
+ io.WriteString(w, msg)
+ }))
+ ts.StartTLS()
+ defer ts.Close()
+
+ cmd := exec.Command("docker", "run", "--net=host", "--entrypoint=/usr/local/bin/h2load", "gohttp2/curl",
+ "-n100000", "-c100", "-m100", ts.URL)
+ cmd.Stdout = os.Stdout
+ cmd.Stderr = os.Stderr
+ if err := cmd.Run(); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Issue 12843
+func TestServerDoS_MaxHeaderListSize(t *testing.T) {
+ st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {})
+ defer st.Close()
+
+ // shake hands
+ frameSize := defaultMaxReadFrameSize
+ var advHeaderListSize *uint32
+ st.greetAndCheckSettings(func(s Setting) error {
+ switch s.ID {
+ case SettingMaxFrameSize:
+ if s.Val < minMaxFrameSize {
+ frameSize = minMaxFrameSize
+ } else if s.Val > maxFrameSize {
+ frameSize = maxFrameSize
+ } else {
+ frameSize = int(s.Val)
+ }
+ case SettingMaxHeaderListSize:
+ advHeaderListSize = &s.Val
+ }
+ return nil
+ })
+
+ if advHeaderListSize == nil {
+ t.Errorf("server didn't advertise a max header list size")
+ } else if *advHeaderListSize == 0 {
+ t.Errorf("server advertised a max header list size of 0")
+ }
+
+ st.encodeHeaderField(":method", "GET")
+ st.encodeHeaderField(":path", "/")
+ st.encodeHeaderField(":scheme", "https")
+ cookie := strings.Repeat("*", 4058)
+ st.encodeHeaderField("cookie", cookie)
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: 1,
+ BlockFragment: st.headerBuf.Bytes(),
+ EndStream: true,
+ EndHeaders: false,
+ })
+
+ // Capture the short encoding of a duplicate ~4K cookie, now
+ // that we've already sent it once.
+ st.headerBuf.Reset()
+ st.encodeHeaderField("cookie", cookie)
+
+ // Now send 1MB of it.
+ const size = 1 << 20
+ b := bytes.Repeat(st.headerBuf.Bytes(), size/st.headerBuf.Len())
+ for len(b) > 0 {
+ chunk := b
+ if len(chunk) > frameSize {
+ chunk = chunk[:frameSize]
+ }
+ b = b[len(chunk):]
+ st.fr.WriteContinuation(1, len(b) == 0, chunk)
+ }
+
+ h := st.wantHeaders()
+ if !h.HeadersEnded() {
+ t.Fatalf("Got HEADERS without END_HEADERS set: %v", h)
+ }
+ headers := st.decodeHeader(h.HeaderBlockFragment())
+ want := [][2]string{
+ {":status", "431"},
+ {"content-type", "text/html; charset=utf-8"},
+ {"content-length", "63"},
+ }
+ if !reflect.DeepEqual(headers, want) {
+ t.Errorf("Headers mismatch.\n got: %q\nwant: %q\n", headers, want)
+ }
+}
+
+func TestCompressionErrorOnWrite(t *testing.T) {
+ const maxStrLen = 8 << 10
+ var serverConfig *http.Server
+ st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+ // No response body.
+ }, func(ts *httptest.Server) {
+ serverConfig = ts.Config
+ serverConfig.MaxHeaderBytes = maxStrLen
+ })
+ st.addLogFilter("connection error: COMPRESSION_ERROR")
+ defer st.Close()
+ st.greet()
+
+ maxAllowed := st.sc.framer.maxHeaderStringLen()
+
+ // Crank this up, now that we have a conn connected with the
+ // hpack.Decoder's max string length set has been initialized
+ // from the earlier low ~8K value. We want this higher so don't
+ // hit the max header list size. We only want to test hitting
+ // the max string size.
+ serverConfig.MaxHeaderBytes = 1 << 20
+
+ // First a request with a header that's exactly the max allowed size
+ // for the hpack compression. It's still too long for the header list
+ // size, so we'll get the 431 error, but that keeps the compression
+ // context still valid.
+ hbf := st.encodeHeader("foo", strings.Repeat("a", maxAllowed))
+
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: 1,
+ BlockFragment: hbf,
+ EndStream: true,
+ EndHeaders: true,
+ })
+ h := st.wantHeaders()
+ if !h.HeadersEnded() {
+ t.Fatalf("Got HEADERS without END_HEADERS set: %v", h)
+ }
+ headers := st.decodeHeader(h.HeaderBlockFragment())
+ want := [][2]string{
+ {":status", "431"},
+ {"content-type", "text/html; charset=utf-8"},
+ {"content-length", "63"},
+ }
+ if !reflect.DeepEqual(headers, want) {
+ t.Errorf("Headers mismatch.\n got: %q\nwant: %q\n", headers, want)
+ }
+ df := st.wantData()
+ if !strings.Contains(string(df.Data()), "HTTP Error 431") {
+ t.Errorf("Unexpected data body: %q", df.Data())
+ }
+ if !df.StreamEnded() {
+ t.Fatalf("expect data stream end")
+ }
+
+ // And now send one that's just one byte too big.
+ hbf = st.encodeHeader("bar", strings.Repeat("b", maxAllowed+1))
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: 3,
+ BlockFragment: hbf,
+ EndStream: true,
+ EndHeaders: true,
+ })
+ ga := st.wantGoAway()
+ if ga.ErrCode != ErrCodeCompression {
+ t.Errorf("GOAWAY err = %v; want ErrCodeCompression", ga.ErrCode)
+ }
+}
+
+func TestCompressionErrorOnClose(t *testing.T) {
+ st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+ // No response body.
+ })
+ st.addLogFilter("connection error: COMPRESSION_ERROR")
+ defer st.Close()
+ st.greet()
+
+ hbf := st.encodeHeader("foo", "bar")
+ hbf = hbf[:len(hbf)-1] // truncate one byte from the end, so hpack.Decoder.Close fails.
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: 1,
+ BlockFragment: hbf,
+ EndStream: true,
+ EndHeaders: true,
+ })
+ ga := st.wantGoAway()
+ if ga.ErrCode != ErrCodeCompression {
+ t.Errorf("GOAWAY err = %v; want ErrCodeCompression", ga.ErrCode)
+ }
+}
+
+// test that a server handler can read trailers from a client
+func TestServerReadsTrailers(t *testing.T) {
+ const testBody = "some test body"
+ writeReq := func(st *serverTester) {
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: 1, // clients send odd numbers
+ BlockFragment: st.encodeHeader("trailer", "Foo, Bar", "trailer", "Baz"),
+ EndStream: false,
+ EndHeaders: true,
+ })
+ st.writeData(1, false, []byte(testBody))
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: 1, // clients send odd numbers
+ BlockFragment: st.encodeHeaderRaw(
+ "foo", "foov",
+ "bar", "barv",
+ "baz", "bazv",
+ "surprise", "wasn't declared; shouldn't show up",
+ ),
+ EndStream: true,
+ EndHeaders: true,
+ })
+ }
+ checkReq := func(r *http.Request) {
+ wantTrailer := http.Header{
+ "Foo": nil,
+ "Bar": nil,
+ "Baz": nil,
+ }
+ if !reflect.DeepEqual(r.Trailer, wantTrailer) {
+ t.Errorf("initial Trailer = %v; want %v", r.Trailer, wantTrailer)
+ }
+ slurp, err := ioutil.ReadAll(r.Body)
+ if string(slurp) != testBody {
+ t.Errorf("read body %q; want %q", slurp, testBody)
+ }
+ if err != nil {
+ t.Fatalf("Body slurp: %v", err)
+ }
+ wantTrailerAfter := http.Header{
+ "Foo": {"foov"},
+ "Bar": {"barv"},
+ "Baz": {"bazv"},
+ }
+ if !reflect.DeepEqual(r.Trailer, wantTrailerAfter) {
+ t.Errorf("final Trailer = %v; want %v", r.Trailer, wantTrailerAfter)
+ }
+ }
+ testServerRequest(t, writeReq, checkReq)
+}
+
+// test that a server handler can send trailers
+func TestServerWritesTrailers_WithFlush(t *testing.T) { testServerWritesTrailers(t, true) }
+func TestServerWritesTrailers_WithoutFlush(t *testing.T) { testServerWritesTrailers(t, false) }
+
+func testServerWritesTrailers(t *testing.T, withFlush bool) {
+ // See https://httpwg.github.io/specs/rfc7540.html#rfc.section.8.1.3
+ testServerResponse(t, func(w http.ResponseWriter, r *http.Request) error {
+ w.Header().Set("Trailer", "Server-Trailer-A, Server-Trailer-B")
+ w.Header().Add("Trailer", "Server-Trailer-C")
+ w.Header().Add("Trailer", "Transfer-Encoding, Content-Length, Trailer") // filtered
+
+ // Regular headers:
+ w.Header().Set("Foo", "Bar")
+ w.Header().Set("Content-Length", "5") // len("Hello")
+
+ io.WriteString(w, "Hello")
+ if withFlush {
+ w.(http.Flusher).Flush()
+ }
+ w.Header().Set("Server-Trailer-A", "valuea")
+ w.Header().Set("Server-Trailer-C", "valuec") // skipping B
+ // After a flush, random keys like Server-Surprise shouldn't show up:
+ w.Header().Set("Server-Surpise", "surprise! this isn't predeclared!")
+ // But we do permit promoting keys to trailers after a
+ // flush if they start with the magic
+ // otherwise-invalid "Trailer:" prefix:
+ w.Header().Set("Trailer:Post-Header-Trailer", "hi1")
+ w.Header().Set("Trailer:post-header-trailer2", "hi2")
+ w.Header().Set("Trailer:Range", "invalid")
+ w.Header().Set("Trailer:Foo\x01Bogus", "invalid")
+ w.Header().Set("Transfer-Encoding", "should not be included; Forbidden by RFC 2616 14.40")
+ w.Header().Set("Content-Length", "should not be included; Forbidden by RFC 2616 14.40")
+ w.Header().Set("Trailer", "should not be included; Forbidden by RFC 2616 14.40")
+ return nil
+ }, func(st *serverTester) {
+ getSlash(st)
+ hf := st.wantHeaders()
+ if hf.StreamEnded() {
+ t.Fatal("response HEADERS had END_STREAM")
+ }
+ if !hf.HeadersEnded() {
+ t.Fatal("response HEADERS didn't have END_HEADERS")
+ }
+ goth := st.decodeHeader(hf.HeaderBlockFragment())
+ wanth := [][2]string{
+ {":status", "200"},
+ {"foo", "Bar"},
+ {"trailer", "Server-Trailer-A, Server-Trailer-B"},
+ {"trailer", "Server-Trailer-C"},
+ {"trailer", "Transfer-Encoding, Content-Length, Trailer"},
+ {"content-type", "text/plain; charset=utf-8"},
+ {"content-length", "5"},
+ }
+ if !reflect.DeepEqual(goth, wanth) {
+ t.Errorf("Header mismatch.\n got: %v\nwant: %v", goth, wanth)
+ }
+ df := st.wantData()
+ if string(df.Data()) != "Hello" {
+ t.Fatalf("Client read %q; want Hello", df.Data())
+ }
+ if df.StreamEnded() {
+ t.Fatalf("data frame had STREAM_ENDED")
+ }
+ tf := st.wantHeaders() // for the trailers
+ if !tf.StreamEnded() {
+ t.Fatalf("trailers HEADERS lacked END_STREAM")
+ }
+ if !tf.HeadersEnded() {
+ t.Fatalf("trailers HEADERS lacked END_HEADERS")
+ }
+ wanth = [][2]string{
+ {"post-header-trailer", "hi1"},
+ {"post-header-trailer2", "hi2"},
+ {"server-trailer-a", "valuea"},
+ {"server-trailer-c", "valuec"},
+ }
+ goth = st.decodeHeader(tf.HeaderBlockFragment())
+ if !reflect.DeepEqual(goth, wanth) {
+ t.Errorf("Header mismatch.\n got: %v\nwant: %v", goth, wanth)
+ }
+ })
+}
+
+// validate transmitted header field names & values
+// golang.org/issue/14048
+func TestServerDoesntWriteInvalidHeaders(t *testing.T) {
+ testServerResponse(t, func(w http.ResponseWriter, r *http.Request) error {
+ w.Header().Add("OK1", "x")
+ w.Header().Add("Bad:Colon", "x") // colon (non-token byte) in key
+ w.Header().Add("Bad1\x00", "x") // null in key
+ w.Header().Add("Bad2", "x\x00y") // null in value
+ return nil
+ }, func(st *serverTester) {
+ getSlash(st)
+ hf := st.wantHeaders()
+ if !hf.StreamEnded() {
+ t.Error("response HEADERS lacked END_STREAM")
+ }
+ if !hf.HeadersEnded() {
+ t.Fatal("response HEADERS didn't have END_HEADERS")
+ }
+ goth := st.decodeHeader(hf.HeaderBlockFragment())
+ wanth := [][2]string{
+ {":status", "200"},
+ {"ok1", "x"},
+ {"content-length", "0"},
+ }
+ if !reflect.DeepEqual(goth, wanth) {
+ t.Errorf("Header mismatch.\n got: %v\nwant: %v", goth, wanth)
+ }
+ })
+}
+
+func BenchmarkServerGets(b *testing.B) {
+ defer disableGoroutineTracking()()
+ b.ReportAllocs()
+
+ const msg = "Hello, world"
+ st := newServerTester(b, func(w http.ResponseWriter, r *http.Request) {
+ io.WriteString(w, msg)
+ })
+ defer st.Close()
+ st.greet()
+
+ // Give the server quota to reply. (plus it has the the 64KB)
+ if err := st.fr.WriteWindowUpdate(0, uint32(b.N*len(msg))); err != nil {
+ b.Fatal(err)
+ }
+
+ for i := 0; i < b.N; i++ {
+ id := 1 + uint32(i)*2
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: id,
+ BlockFragment: st.encodeHeader(),
+ EndStream: true,
+ EndHeaders: true,
+ })
+ st.wantHeaders()
+ df := st.wantData()
+ if !df.StreamEnded() {
+ b.Fatalf("DATA didn't have END_STREAM; got %v", df)
+ }
+ }
+}
+
+func BenchmarkServerPosts(b *testing.B) {
+ defer disableGoroutineTracking()()
+ b.ReportAllocs()
+
+ const msg = "Hello, world"
+ st := newServerTester(b, func(w http.ResponseWriter, r *http.Request) {
+ // Consume the (empty) body from th peer before replying, otherwise
+ // the server will sometimes (depending on scheduling) send the peer a
+ // a RST_STREAM with the CANCEL error code.
+ if n, err := io.Copy(ioutil.Discard, r.Body); n != 0 || err != nil {
+ b.Errorf("Copy error; got %v, %v; want 0, nil", n, err)
+ }
+ io.WriteString(w, msg)
+ })
+ defer st.Close()
+ st.greet()
+
+ // Give the server quota to reply. (plus it has the the 64KB)
+ if err := st.fr.WriteWindowUpdate(0, uint32(b.N*len(msg))); err != nil {
+ b.Fatal(err)
+ }
+
+ for i := 0; i < b.N; i++ {
+ id := 1 + uint32(i)*2
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: id,
+ BlockFragment: st.encodeHeader(":method", "POST"),
+ EndStream: false,
+ EndHeaders: true,
+ })
+ st.writeData(id, true, nil)
+ st.wantHeaders()
+ df := st.wantData()
+ if !df.StreamEnded() {
+ b.Fatalf("DATA didn't have END_STREAM; got %v", df)
+ }
+ }
+}
+
+// Send a stream of messages from server to client in separate data frames.
+// Brings up performance issues seen in long streams.
+// Created to show problem in go issue #18502
+func BenchmarkServerToClientStreamDefaultOptions(b *testing.B) {
+ benchmarkServerToClientStream(b)
+}
+
+// Justification for Change-Id: Iad93420ef6c3918f54249d867098f1dadfa324d8
+// Expect to see memory/alloc reduction by opting in to Frame reuse with the Framer.
+func BenchmarkServerToClientStreamReuseFrames(b *testing.B) {
+ benchmarkServerToClientStream(b, optFramerReuseFrames)
+}
+
+func benchmarkServerToClientStream(b *testing.B, newServerOpts ...interface{}) {
+ defer disableGoroutineTracking()()
+ b.ReportAllocs()
+ const msgLen = 1
+ // default window size
+ const windowSize = 1<<16 - 1
+
+ // next message to send from the server and for the client to expect
+ nextMsg := func(i int) []byte {
+ msg := make([]byte, msgLen)
+ msg[0] = byte(i)
+ if len(msg) != msgLen {
+ panic("invalid test setup msg length")
+ }
+ return msg
+ }
+
+ st := newServerTester(b, func(w http.ResponseWriter, r *http.Request) {
+ // Consume the (empty) body from th peer before replying, otherwise
+ // the server will sometimes (depending on scheduling) send the peer a
+ // a RST_STREAM with the CANCEL error code.
+ if n, err := io.Copy(ioutil.Discard, r.Body); n != 0 || err != nil {
+ b.Errorf("Copy error; got %v, %v; want 0, nil", n, err)
+ }
+ for i := 0; i < b.N; i += 1 {
+ w.Write(nextMsg(i))
+ w.(http.Flusher).Flush()
+ }
+ }, newServerOpts...)
+ defer st.Close()
+ st.greet()
+
+ const id = uint32(1)
+
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: id,
+ BlockFragment: st.encodeHeader(":method", "POST"),
+ EndStream: false,
+ EndHeaders: true,
+ })
+
+ st.writeData(id, true, nil)
+ st.wantHeaders()
+
+ var pendingWindowUpdate = uint32(0)
+
+ for i := 0; i < b.N; i += 1 {
+ expected := nextMsg(i)
+ df := st.wantData()
+ if bytes.Compare(expected, df.data) != 0 {
+ b.Fatalf("Bad message received; want %v; got %v", expected, df.data)
+ }
+ // try to send infrequent but large window updates so they don't overwhelm the test
+ pendingWindowUpdate += uint32(len(df.data))
+ if pendingWindowUpdate >= windowSize/2 {
+ if err := st.fr.WriteWindowUpdate(0, pendingWindowUpdate); err != nil {
+ b.Fatal(err)
+ }
+ if err := st.fr.WriteWindowUpdate(id, pendingWindowUpdate); err != nil {
+ b.Fatal(err)
+ }
+ pendingWindowUpdate = 0
+ }
+ }
+ df := st.wantData()
+ if !df.StreamEnded() {
+ b.Fatalf("DATA didn't have END_STREAM; got %v", df)
+ }
+}
+
+// go-fuzz bug, originally reported at https://github.com/bradfitz/http2/issues/53
+// Verify we don't hang.
+func TestIssue53(t *testing.T) {
+ const data = "PRI * HTTP/2.0\r\n\r\nSM" +
+ "\r\n\r\n\x00\x00\x00\x01\ainfinfin\ad"
+ s := &http.Server{
+ ErrorLog: log.New(io.MultiWriter(stderrv(), twriter{t: t}), "", log.LstdFlags),
+ Handler: http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
+ w.Write([]byte("hello"))
+ }),
+ }
+ s2 := &Server{
+ MaxReadFrameSize: 1 << 16,
+ PermitProhibitedCipherSuites: true,
+ }
+ c := &issue53Conn{[]byte(data), false, false}
+ s2.ServeConn(c, &ServeConnOpts{BaseConfig: s})
+ if !c.closed {
+ t.Fatal("connection is not closed")
+ }
+}
+
+type issue53Conn struct {
+ data []byte
+ closed bool
+ written bool
+}
+
+func (c *issue53Conn) Read(b []byte) (n int, err error) {
+ if len(c.data) == 0 {
+ return 0, io.EOF
+ }
+ n = copy(b, c.data)
+ c.data = c.data[n:]
+ return
+}
+
+func (c *issue53Conn) Write(b []byte) (n int, err error) {
+ c.written = true
+ return len(b), nil
+}
+
+func (c *issue53Conn) Close() error {
+ c.closed = true
+ return nil
+}
+
+func (c *issue53Conn) LocalAddr() net.Addr {
+ return &net.TCPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 49706}
+}
+func (c *issue53Conn) RemoteAddr() net.Addr {
+ return &net.TCPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 49706}
+}
+func (c *issue53Conn) SetDeadline(t time.Time) error { return nil }
+func (c *issue53Conn) SetReadDeadline(t time.Time) error { return nil }
+func (c *issue53Conn) SetWriteDeadline(t time.Time) error { return nil }
+
+// golang.org/issue/12895
+func TestConfigureServer(t *testing.T) {
+ tests := []struct {
+ name string
+ tlsConfig *tls.Config
+ wantErr string
+ }{
+ {
+ name: "empty server",
+ },
+ {
+ name: "just the required cipher suite",
+ tlsConfig: &tls.Config{
+ CipherSuites: []uint16{tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+ },
+ },
+ {
+ name: "just the alternative required cipher suite",
+ tlsConfig: &tls.Config{
+ CipherSuites: []uint16{tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
+ },
+ },
+ {
+ name: "missing required cipher suite",
+ tlsConfig: &tls.Config{
+ CipherSuites: []uint16{tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384},
+ },
+ wantErr: "is missing an HTTP/2-required AES_128_GCM_SHA256 cipher.",
+ },
+ {
+ name: "required after bad",
+ tlsConfig: &tls.Config{
+ CipherSuites: []uint16{tls.TLS_RSA_WITH_RC4_128_SHA, tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+ },
+ wantErr: "contains an HTTP/2-approved cipher suite (0xc02f), but it comes after",
+ },
+ {
+ name: "bad after required",
+ tlsConfig: &tls.Config{
+ CipherSuites: []uint16{tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, tls.TLS_RSA_WITH_RC4_128_SHA},
+ },
+ },
+ }
+ for _, tt := range tests {
+ srv := &http.Server{TLSConfig: tt.tlsConfig}
+ err := ConfigureServer(srv, nil)
+ if (err != nil) != (tt.wantErr != "") {
+ if tt.wantErr != "" {
+ t.Errorf("%s: success, but want error", tt.name)
+ } else {
+ t.Errorf("%s: unexpected error: %v", tt.name, err)
+ }
+ }
+ if err != nil && tt.wantErr != "" && !strings.Contains(err.Error(), tt.wantErr) {
+ t.Errorf("%s: err = %v; want substring %q", tt.name, err, tt.wantErr)
+ }
+ if err == nil && !srv.TLSConfig.PreferServerCipherSuites {
+ t.Errorf("%s: PreferServerCipherSuite is false; want true", tt.name)
+ }
+ }
+}
+
+func TestServerRejectHeadWithBody(t *testing.T) {
+ st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+ // No response body.
+ })
+ defer st.Close()
+ st.greet()
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: 1, // clients send odd numbers
+ BlockFragment: st.encodeHeader(":method", "HEAD"),
+ EndStream: false, // what we're testing, a bogus HEAD request with body
+ EndHeaders: true,
+ })
+ st.wantRSTStream(1, ErrCodeProtocol)
+}
+
+func TestServerNoAutoContentLengthOnHead(t *testing.T) {
+ st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+ // No response body. (or smaller than one frame)
+ })
+ defer st.Close()
+ st.greet()
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: 1, // clients send odd numbers
+ BlockFragment: st.encodeHeader(":method", "HEAD"),
+ EndStream: true,
+ EndHeaders: true,
+ })
+ h := st.wantHeaders()
+ headers := st.decodeHeader(h.HeaderBlockFragment())
+ want := [][2]string{
+ {":status", "200"},
+ }
+ if !reflect.DeepEqual(headers, want) {
+ t.Errorf("Headers mismatch.\n got: %q\nwant: %q\n", headers, want)
+ }
+}
+
+// golang.org/issue/13495
+func TestServerNoDuplicateContentType(t *testing.T) {
+ st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+ w.Header()["Content-Type"] = []string{""}
+ fmt.Fprintf(w, "<html><head></head><body>hi</body></html>")
+ })
+ defer st.Close()
+ st.greet()
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: 1,
+ BlockFragment: st.encodeHeader(),
+ EndStream: true,
+ EndHeaders: true,
+ })
+ h := st.wantHeaders()
+ headers := st.decodeHeader(h.HeaderBlockFragment())
+ want := [][2]string{
+ {":status", "200"},
+ {"content-type", ""},
+ {"content-length", "41"},
+ }
+ if !reflect.DeepEqual(headers, want) {
+ t.Errorf("Headers mismatch.\n got: %q\nwant: %q\n", headers, want)
+ }
+}
+
+func disableGoroutineTracking() (restore func()) {
+ old := DebugGoroutines
+ DebugGoroutines = false
+ return func() { DebugGoroutines = old }
+}
+
+func BenchmarkServer_GetRequest(b *testing.B) {
+ defer disableGoroutineTracking()()
+ b.ReportAllocs()
+ const msg = "Hello, world."
+ st := newServerTester(b, func(w http.ResponseWriter, r *http.Request) {
+ n, err := io.Copy(ioutil.Discard, r.Body)
+ if err != nil || n > 0 {
+ b.Errorf("Read %d bytes, error %v; want 0 bytes.", n, err)
+ }
+ io.WriteString(w, msg)
+ })
+ defer st.Close()
+
+ st.greet()
+ // Give the server quota to reply. (plus it has the the 64KB)
+ if err := st.fr.WriteWindowUpdate(0, uint32(b.N*len(msg))); err != nil {
+ b.Fatal(err)
+ }
+ hbf := st.encodeHeader(":method", "GET")
+ for i := 0; i < b.N; i++ {
+ streamID := uint32(1 + 2*i)
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: streamID,
+ BlockFragment: hbf,
+ EndStream: true,
+ EndHeaders: true,
+ })
+ st.wantHeaders()
+ st.wantData()
+ }
+}
+
+func BenchmarkServer_PostRequest(b *testing.B) {
+ defer disableGoroutineTracking()()
+ b.ReportAllocs()
+ const msg = "Hello, world."
+ st := newServerTester(b, func(w http.ResponseWriter, r *http.Request) {
+ n, err := io.Copy(ioutil.Discard, r.Body)
+ if err != nil || n > 0 {
+ b.Errorf("Read %d bytes, error %v; want 0 bytes.", n, err)
+ }
+ io.WriteString(w, msg)
+ })
+ defer st.Close()
+ st.greet()
+ // Give the server quota to reply. (plus it has the the 64KB)
+ if err := st.fr.WriteWindowUpdate(0, uint32(b.N*len(msg))); err != nil {
+ b.Fatal(err)
+ }
+ hbf := st.encodeHeader(":method", "POST")
+ for i := 0; i < b.N; i++ {
+ streamID := uint32(1 + 2*i)
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: streamID,
+ BlockFragment: hbf,
+ EndStream: false,
+ EndHeaders: true,
+ })
+ st.writeData(streamID, true, nil)
+ st.wantHeaders()
+ st.wantData()
+ }
+}
+
+type connStateConn struct {
+ net.Conn
+ cs tls.ConnectionState
+}
+
+func (c connStateConn) ConnectionState() tls.ConnectionState { return c.cs }
+
+// golang.org/issue/12737 -- handle any net.Conn, not just
+// *tls.Conn.
+func TestServerHandleCustomConn(t *testing.T) {
+ var s Server
+ c1, c2 := net.Pipe()
+ clientDone := make(chan struct{})
+ handlerDone := make(chan struct{})
+ var req *http.Request
+ go func() {
+ defer close(clientDone)
+ defer c2.Close()
+ fr := NewFramer(c2, c2)
+ io.WriteString(c2, ClientPreface)
+ fr.WriteSettings()
+ fr.WriteSettingsAck()
+ f, err := fr.ReadFrame()
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ if sf, ok := f.(*SettingsFrame); !ok || sf.IsAck() {
+ t.Errorf("Got %v; want non-ACK SettingsFrame", summarizeFrame(f))
+ return
+ }
+ f, err = fr.ReadFrame()
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ if sf, ok := f.(*SettingsFrame); !ok || !sf.IsAck() {
+ t.Errorf("Got %v; want ACK SettingsFrame", summarizeFrame(f))
+ return
+ }
+ var henc hpackEncoder
+ fr.WriteHeaders(HeadersFrameParam{
+ StreamID: 1,
+ BlockFragment: henc.encodeHeaderRaw(t, ":method", "GET", ":path", "/", ":scheme", "https", ":authority", "foo.com"),
+ EndStream: true,
+ EndHeaders: true,
+ })
+ go io.Copy(ioutil.Discard, c2)
+ <-handlerDone
+ }()
+ const testString = "my custom ConnectionState"
+ fakeConnState := tls.ConnectionState{
+ ServerName: testString,
+ Version: tls.VersionTLS12,
+ CipherSuite: cipher_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+ }
+ go s.ServeConn(connStateConn{c1, fakeConnState}, &ServeConnOpts{
+ BaseConfig: &http.Server{
+ Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ defer close(handlerDone)
+ req = r
+ }),
+ }})
+ select {
+ case <-clientDone:
+ case <-time.After(5 * time.Second):
+ t.Fatal("timeout waiting for handler")
+ }
+ if req.TLS == nil {
+ t.Fatalf("Request.TLS is nil. Got: %#v", req)
+ }
+ if req.TLS.ServerName != testString {
+ t.Fatalf("Request.TLS = %+v; want ServerName of %q", req.TLS, testString)
+ }
+}
+
+// golang.org/issue/14214
+func TestServer_Rejects_ConnHeaders(t *testing.T) {
+ st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+ t.Error("should not get to Handler")
+ })
+ defer st.Close()
+ st.greet()
+ st.bodylessReq1("connection", "foo")
+ hf := st.wantHeaders()
+ goth := st.decodeHeader(hf.HeaderBlockFragment())
+ wanth := [][2]string{
+ {":status", "400"},
+ {"content-type", "text/plain; charset=utf-8"},
+ {"x-content-type-options", "nosniff"},
+ {"content-length", "51"},
+ }
+ if !reflect.DeepEqual(goth, wanth) {
+ t.Errorf("Got headers %v; want %v", goth, wanth)
+ }
+}
+
+type hpackEncoder struct {
+ enc *hpack.Encoder
+ buf bytes.Buffer
+}
+
+func (he *hpackEncoder) encodeHeaderRaw(t *testing.T, headers ...string) []byte {
+ if len(headers)%2 == 1 {
+ panic("odd number of kv args")
+ }
+ he.buf.Reset()
+ if he.enc == nil {
+ he.enc = hpack.NewEncoder(&he.buf)
+ }
+ for len(headers) > 0 {
+ k, v := headers[0], headers[1]
+ err := he.enc.WriteField(hpack.HeaderField{Name: k, Value: v})
+ if err != nil {
+ t.Fatalf("HPACK encoding error for %q/%q: %v", k, v, err)
+ }
+ headers = headers[2:]
+ }
+ return he.buf.Bytes()
+}
+
+func TestCheckValidHTTP2Request(t *testing.T) {
+ tests := []struct {
+ h http.Header
+ want error
+ }{
+ {
+ h: http.Header{"Te": {"trailers"}},
+ want: nil,
+ },
+ {
+ h: http.Header{"Te": {"trailers", "bogus"}},
+ want: errors.New(`request header "TE" may only be "trailers" in HTTP/2`),
+ },
+ {
+ h: http.Header{"Foo": {""}},
+ want: nil,
+ },
+ {
+ h: http.Header{"Connection": {""}},
+ want: errors.New(`request header "Connection" is not valid in HTTP/2`),
+ },
+ {
+ h: http.Header{"Proxy-Connection": {""}},
+ want: errors.New(`request header "Proxy-Connection" is not valid in HTTP/2`),
+ },
+ {
+ h: http.Header{"Keep-Alive": {""}},
+ want: errors.New(`request header "Keep-Alive" is not valid in HTTP/2`),
+ },
+ {
+ h: http.Header{"Upgrade": {""}},
+ want: errors.New(`request header "Upgrade" is not valid in HTTP/2`),
+ },
+ }
+ for i, tt := range tests {
+ got := checkValidHTTP2RequestHeaders(tt.h)
+ if !reflect.DeepEqual(got, tt.want) {
+ t.Errorf("%d. checkValidHTTP2Request = %v; want %v", i, got, tt.want)
+ }
+ }
+}
+
+// golang.org/issue/14030
+func TestExpect100ContinueAfterHandlerWrites(t *testing.T) {
+ const msg = "Hello"
+ const msg2 = "World"
+
+ doRead := make(chan bool, 1)
+ defer close(doRead) // fallback cleanup
+
+ st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+ io.WriteString(w, msg)
+ w.(http.Flusher).Flush()
+
+ // Do a read, which might force a 100-continue status to be sent.
+ <-doRead
+ r.Body.Read(make([]byte, 10))
+
+ io.WriteString(w, msg2)
+
+ }, optOnlyServer)
+ defer st.Close()
+
+ tr := &Transport{TLSClientConfig: tlsConfigInsecure}
+ defer tr.CloseIdleConnections()
+
+ req, _ := http.NewRequest("POST", st.ts.URL, io.LimitReader(neverEnding('A'), 2<<20))
+ req.Header.Set("Expect", "100-continue")
+
+ res, err := tr.RoundTrip(req)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer res.Body.Close()
+
+ buf := make([]byte, len(msg))
+ if _, err := io.ReadFull(res.Body, buf); err != nil {
+ t.Fatal(err)
+ }
+ if string(buf) != msg {
+ t.Fatalf("msg = %q; want %q", buf, msg)
+ }
+
+ doRead <- true
+
+ if _, err := io.ReadFull(res.Body, buf); err != nil {
+ t.Fatal(err)
+ }
+ if string(buf) != msg2 {
+ t.Fatalf("second msg = %q; want %q", buf, msg2)
+ }
+}
+
+type funcReader func([]byte) (n int, err error)
+
+func (f funcReader) Read(p []byte) (n int, err error) { return f(p) }
+
+// golang.org/issue/16481 -- return flow control when streams close with unread data.
+// (The Server version of the bug. See also TestUnreadFlowControlReturned_Transport)
+func TestUnreadFlowControlReturned_Server(t *testing.T) {
+ unblock := make(chan bool, 1)
+ defer close(unblock)
+
+ st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+ // Don't read the 16KB request body. Wait until the client's
+ // done sending it and then return. This should cause the Server
+ // to then return those 16KB of flow control to the client.
+ <-unblock
+ }, optOnlyServer)
+ defer st.Close()
+
+ tr := &Transport{TLSClientConfig: tlsConfigInsecure}
+ defer tr.CloseIdleConnections()
+
+ // This previously hung on the 4th iteration.
+ for i := 0; i < 6; i++ {
+ body := io.MultiReader(
+ io.LimitReader(neverEnding('A'), 16<<10),
+ funcReader(func([]byte) (n int, err error) {
+ unblock <- true
+ return 0, io.EOF
+ }),
+ )
+ req, _ := http.NewRequest("POST", st.ts.URL, body)
+ res, err := tr.RoundTrip(req)
+ if err != nil {
+ t.Fatal(err)
+ }
+ res.Body.Close()
+ }
+
+}
+
+func TestServerIdleTimeout(t *testing.T) {
+ if testing.Short() {
+ t.Skip("skipping in short mode")
+ }
+
+ st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+ }, func(h2s *Server) {
+ h2s.IdleTimeout = 500 * time.Millisecond
+ })
+ defer st.Close()
+
+ st.greet()
+ ga := st.wantGoAway()
+ if ga.ErrCode != ErrCodeNo {
+ t.Errorf("GOAWAY error = %v; want ErrCodeNo", ga.ErrCode)
+ }
+}
+
+func TestServerIdleTimeout_AfterRequest(t *testing.T) {
+ if testing.Short() {
+ t.Skip("skipping in short mode")
+ }
+ const timeout = 250 * time.Millisecond
+
+ st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+ time.Sleep(timeout * 2)
+ }, func(h2s *Server) {
+ h2s.IdleTimeout = timeout
+ })
+ defer st.Close()
+
+ st.greet()
+
+ // Send a request which takes twice the timeout. Verifies the
+ // idle timeout doesn't fire while we're in a request:
+ st.bodylessReq1()
+ st.wantHeaders()
+
+ // But the idle timeout should be rearmed after the request
+ // is done:
+ ga := st.wantGoAway()
+ if ga.ErrCode != ErrCodeNo {
+ t.Errorf("GOAWAY error = %v; want ErrCodeNo", ga.ErrCode)
+ }
+}
+
+// grpc-go closes the Request.Body currently with a Read.
+// Verify that it doesn't race.
+// See https://github.com/grpc/grpc-go/pull/938
+func TestRequestBodyReadCloseRace(t *testing.T) {
+ for i := 0; i < 100; i++ {
+ body := &requestBody{
+ pipe: &pipe{
+ b: new(bytes.Buffer),
+ },
+ }
+ body.pipe.CloseWithError(io.EOF)
+
+ done := make(chan bool, 1)
+ buf := make([]byte, 10)
+ go func() {
+ time.Sleep(1 * time.Millisecond)
+ body.Close()
+ done <- true
+ }()
+ body.Read(buf)
+ <-done
+ }
+}
+
+func TestIssue20704Race(t *testing.T) {
+ if testing.Short() && os.Getenv("GO_BUILDER_NAME") == "" {
+ t.Skip("skipping in short mode")
+ }
+ const (
+ itemSize = 1 << 10
+ itemCount = 100
+ )
+
+ st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+ for i := 0; i < itemCount; i++ {
+ _, err := w.Write(make([]byte, itemSize))
+ if err != nil {
+ return
+ }
+ }
+ }, optOnlyServer)
+ defer st.Close()
+
+ tr := &Transport{TLSClientConfig: tlsConfigInsecure}
+ defer tr.CloseIdleConnections()
+ cl := &http.Client{Transport: tr}
+
+ for i := 0; i < 1000; i++ {
+ resp, err := cl.Get(st.ts.URL)
+ if err != nil {
+ t.Fatal(err)
+ }
+ // Force a RST stream to the server by closing without
+ // reading the body:
+ resp.Body.Close()
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/testdata/draft-ietf-httpbis-http2.xml b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/testdata/draft-ietf-httpbis-http2.xml
new file mode 100644
index 000000000..31a84bed4
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/testdata/draft-ietf-httpbis-http2.xml
@@ -0,0 +1,5021 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="lib/rfc2629.xslt"?>
+<?rfc toc="yes" ?>
+<?rfc symrefs="yes" ?>
+<?rfc sortrefs="yes" ?>
+<?rfc compact="yes"?>
+<?rfc subcompact="no" ?>
+<?rfc linkmailto="no" ?>
+<?rfc editing="no" ?>
+<?rfc comments="yes" ?>
+<?rfc inline="yes"?>
+<?rfc rfcedstyle="yes"?>
+<?rfc-ext allow-markup-in-artwork="yes" ?>
+<?rfc-ext include-index="no" ?>
+
+<rfc ipr="trust200902"
+ category="std"
+ docName="draft-ietf-httpbis-http2-latest"
+ x:maturity-level="proposed"
+ xmlns:x="http://purl.org/net/xml2rfc/ext">
+ <x:feedback template="mailto:ietf-http-wg@w3.org?subject={docname},%20%22{section}%22&amp;body=&lt;{ref}&gt;:"/>
+ <front>
+ <title abbrev="HTTP/2">Hypertext Transfer Protocol version 2</title>
+
+ <author initials="M." surname="Belshe" fullname="Mike Belshe">
+ <organization>Twist</organization>
+ <address>
+ <email>mbelshe@chromium.org</email>
+ </address>
+ </author>
+
+ <author initials="R." surname="Peon" fullname="Roberto Peon">
+ <organization>Google, Inc</organization>
+ <address>
+ <email>fenix@google.com</email>
+ </address>
+ </author>
+
+ <author initials="M." surname="Thomson" fullname="Martin Thomson" role="editor">
+ <organization>Mozilla</organization>
+ <address>
+ <postal>
+ <street>331 E Evelyn Street</street>
+ <city>Mountain View</city>
+ <region>CA</region>
+ <code>94041</code>
+ <country>US</country>
+ </postal>
+ <email>martin.thomson@gmail.com</email>
+ </address>
+ </author>
+
+ <date year="2014" />
+ <area>Applications</area>
+ <workgroup>HTTPbis</workgroup>
+ <keyword>HTTP</keyword>
+ <keyword>SPDY</keyword>
+ <keyword>Web</keyword>
+
+ <abstract>
+ <t>
+ This specification describes an optimized expression of the semantics of the Hypertext
+ Transfer Protocol (HTTP). HTTP/2 enables a more efficient use of network resources and a
+ reduced perception of latency by introducing header field compression and allowing multiple
+ concurrent messages on the same connection. It also introduces unsolicited push of
+ representations from servers to clients.
+ </t>
+ <t>
+ This specification is an alternative to, but does not obsolete, the HTTP/1.1 message syntax.
+ HTTP's existing semantics remain unchanged.
+ </t>
+ </abstract>
+
+ <note title="Editorial Note (To be removed by RFC Editor)">
+ <t>
+ Discussion of this draft takes place on the HTTPBIS working group mailing list
+ (ietf-http-wg@w3.org), which is archived at <eref
+ target="https://lists.w3.org/Archives/Public/ietf-http-wg/"/>.
+ </t>
+ <t>
+ Working Group information can be found at <eref
+ target="https://tools.ietf.org/wg/httpbis/"/>; that specific to HTTP/2 are at <eref
+ target="https://http2.github.io/"/>.
+ </t>
+ <t>
+ The changes in this draft are summarized in <xref
+ target="change.log"/>.
+ </t>
+ </note>
+
+ </front>
+
+ <middle>
+ <section anchor="intro" title="Introduction">
+
+ <t>
+ The Hypertext Transfer Protocol (HTTP) is a wildly successful protocol. However, the
+ HTTP/1.1 message format (<xref target="RFC7230" x:fmt="," x:rel="#http.message"/>) has
+ several characteristics that have a negative overall effect on application performance
+ today.
+ </t>
+ <t>
+ In particular, HTTP/1.0 allowed only one request to be outstanding at a time on a given
+ TCP connection. HTTP/1.1 added request pipelining, but this only partially addressed
+ request concurrency and still suffers from head-of-line blocking. Therefore, HTTP/1.1
+ clients that need to make many requests typically use multiple connections to a server in
+ order to achieve concurrency and thereby reduce latency.
+ </t>
+ <t>
+ Furthermore, HTTP header fields are often repetitive and verbose, causing unnecessary
+ network traffic, as well as causing the initial <xref target="TCP">TCP</xref> congestion
+ window to quickly fill. This can result in excessive latency when multiple requests are
+ made on a new TCP connection.
+ </t>
+ <t>
+ HTTP/2 addresses these issues by defining an optimized mapping of HTTP's semantics to an
+ underlying connection. Specifically, it allows interleaving of request and response
+ messages on the same connection and uses an efficient coding for HTTP header fields. It
+ also allows prioritization of requests, letting more important requests complete more
+ quickly, further improving performance.
+ </t>
+ <t>
+ The resulting protocol is more friendly to the network, because fewer TCP connections can
+ be used in comparison to HTTP/1.x. This means less competition with other flows, and
+ longer-lived connections, which in turn leads to better utilization of available network
+ capacity.
+ </t>
+ <t>
+ Finally, HTTP/2 also enables more efficient processing of messages through use of binary
+ message framing.
+ </t>
+ </section>
+
+ <section anchor="Overview" title="HTTP/2 Protocol Overview">
+ <t>
+ HTTP/2 provides an optimized transport for HTTP semantics. HTTP/2 supports all of the core
+ features of HTTP/1.1, but aims to be more efficient in several ways.
+ </t>
+ <t>
+ The basic protocol unit in HTTP/2 is a <xref target="FrameHeader">frame</xref>. Each frame
+ type serves a different purpose. For example, <x:ref>HEADERS</x:ref> and
+ <x:ref>DATA</x:ref> frames form the basis of <xref target="HttpSequence">HTTP requests and
+ responses</xref>; other frame types like <x:ref>SETTINGS</x:ref>,
+ <x:ref>WINDOW_UPDATE</x:ref>, and <x:ref>PUSH_PROMISE</x:ref> are used in support of other
+ HTTP/2 features.
+ </t>
+ <t>
+ Multiplexing of requests is achieved by having each HTTP request-response exchange
+ associated with its own <xref target="StreamsLayer">stream</xref>. Streams are largely
+ independent of each other, so a blocked or stalled request or response does not prevent
+ progress on other streams.
+ </t>
+ <t>
+ Flow control and prioritization ensure that it is possible to efficiently use multiplexed
+ streams. <xref target="FlowControl">Flow control</xref> helps to ensure that only data that
+ can be used by a receiver is transmitted. <xref
+ target="StreamPriority">Prioritization</xref> ensures that limited resources can be directed
+ to the most important streams first.
+ </t>
+ <t>
+ HTTP/2 adds a new interaction mode, whereby a server can <xref target="PushResources">push
+ responses to a client</xref>. Server push allows a server to speculatively send a client
+ data that the server anticipates the client will need, trading off some network usage
+ against a potential latency gain. The server does this by synthesizing a request, which it
+ sends as a <x:ref>PUSH_PROMISE</x:ref> frame. The server is then able to send a response to
+ the synthetic request on a separate stream.
+ </t>
+ <t>
+ Frames that contain HTTP header fields are <xref target="HeaderBlock">compressed</xref>.
+ HTTP requests can be highly redundant, so compression can reduce the size of requests and
+ responses significantly.
+ </t>
+
+ <section title="Document Organization">
+ <t>
+ The HTTP/2 specification is split into four parts:
+ <list style="symbols">
+ <t>
+ <xref target="starting">Starting HTTP/2</xref> covers how an HTTP/2 connection is
+ initiated.
+ </t>
+ <t>
+ The <xref target="FramingLayer">framing</xref> and <xref
+ target="StreamsLayer">streams</xref> layers describe the way HTTP/2 frames are
+ structured and formed into multiplexed streams.
+ </t>
+ <t>
+ <xref target="FrameTypes">Frame</xref> and <xref target="ErrorCodes">error</xref>
+ definitions include details of the frame and error types used in HTTP/2.
+ </t>
+ <t>
+ <xref target="HTTPLayer">HTTP mappings</xref> and <xref target="HttpExtra">additional
+ requirements</xref> describe how HTTP semantics are expressed using frames and
+ streams.
+ </t>
+ </list>
+ </t>
+ <t>
+ While some of the frame and stream layer concepts are isolated from HTTP, this
+ specification does not define a completely generic framing layer. The framing and streams
+ layers are tailored to the needs of the HTTP protocol and server push.
+ </t>
+ </section>
+
+ <section title="Conventions and Terminology">
+ <t>
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD
+ NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as
+ described in <xref target="RFC2119">RFC 2119</xref>.
+ </t>
+ <t>
+ All numeric values are in network byte order. Values are unsigned unless otherwise
+ indicated. Literal values are provided in decimal or hexadecimal as appropriate.
+ Hexadecimal literals are prefixed with <spanx style="verb">0x</spanx> to distinguish them
+ from decimal literals.
+ </t>
+ <t>
+ The following terms are used:
+ <list style="hanging">
+ <t hangText="client:">
+ The endpoint initiating the HTTP/2 connection.
+ </t>
+ <t hangText="connection:">
+ A transport-layer connection between two endpoints.
+ </t>
+ <t hangText="connection error:">
+ An error that affects the entire HTTP/2 connection.
+ </t>
+ <t hangText="endpoint:">
+ Either the client or server of the connection.
+ </t>
+ <t hangText="frame:">
+ The smallest unit of communication within an HTTP/2 connection, consisting of a header
+ and a variable-length sequence of octets structured according to the frame type.
+ </t>
+ <t hangText="peer:">
+ An endpoint. When discussing a particular endpoint, "peer" refers to the endpoint
+ that is remote to the primary subject of discussion.
+ </t>
+ <t hangText="receiver:">
+ An endpoint that is receiving frames.
+ </t>
+ <t hangText="sender:">
+ An endpoint that is transmitting frames.
+ </t>
+ <t hangText="server:">
+ The endpoint which did not initiate the HTTP/2 connection.
+ </t>
+ <t hangText="stream:">
+ A bi-directional flow of frames across a virtual channel within the HTTP/2 connection.
+ </t>
+ <t hangText="stream error:">
+ An error on the individual HTTP/2 stream.
+ </t>
+ </list>
+ </t>
+ <t>
+ Finally, the terms "gateway", "intermediary", "proxy", and "tunnel" are defined
+ in <xref target="RFC7230" x:fmt="of" x:rel="#intermediaries"/>.
+ </t>
+ </section>
+ </section>
+
+ <section anchor="starting" title="Starting HTTP/2">
+ <t>
+ An HTTP/2 connection is an application layer protocol running on top of a TCP connection
+ (<xref target="TCP"/>). The client is the TCP connection initiator.
+ </t>
+ <t>
+ HTTP/2 uses the same "http" and "https" URI schemes used by HTTP/1.1. HTTP/2 shares the same
+ default port numbers: 80 for "http" URIs and 443 for "https" URIs. As a result,
+ implementations processing requests for target resource URIs like <spanx
+ style="verb">http://example.org/foo</spanx> or <spanx
+ style="verb">https://example.com/bar</spanx> are required to first discover whether the
+ upstream server (the immediate peer to which the client wishes to establish a connection)
+ supports HTTP/2.
+ </t>
+
+ <t>
+ The means by which support for HTTP/2 is determined is different for "http" and "https"
+ URIs. Discovery for "http" URIs is described in <xref target="discover-http"/>. Discovery
+ for "https" URIs is described in <xref target="discover-https"/>.
+ </t>
+
+ <section anchor="versioning" title="HTTP/2 Version Identification">
+ <t>
+ The protocol defined in this document has two identifiers.
+ <list style="symbols">
+ <x:lt>
+ <t>
+ The string "h2" identifies the protocol where HTTP/2 uses <xref
+ target="TLS12">TLS</xref>. This identifier is used in the <xref
+ target="TLS-ALPN">TLS application layer protocol negotiation extension (ALPN)</xref>
+ field and any place that HTTP/2 over TLS is identified.
+ </t>
+ <t>
+ The "h2" string is serialized into an ALPN protocol identifier as the two octet
+ sequence: 0x68, 0x32.
+ </t>
+ </x:lt>
+ <x:lt>
+ <t>
+ The string "h2c" identifies the protocol where HTTP/2 is run over cleartext TCP.
+ This identifier is used in the HTTP/1.1 Upgrade header field and any place that
+ HTTP/2 over TCP is identified.
+ </t>
+ </x:lt>
+ </list>
+ </t>
+ <t>
+ Negotiating "h2" or "h2c" implies the use of the transport, security, framing and message
+ semantics described in this document.
+ </t>
+ <t>
+ <cref>RFC Editor's Note: please remove the remainder of this section prior to the
+ publication of a final version of this document.</cref>
+ </t>
+ <t>
+ Only implementations of the final, published RFC can identify themselves as "h2" or "h2c".
+ Until such an RFC exists, implementations MUST NOT identify themselves using these
+ strings.
+ </t>
+ <t>
+ Examples and text throughout the rest of this document use "h2" as a matter of
+ editorial convenience only. Implementations of draft versions MUST NOT identify using
+ this string.
+ </t>
+ <t>
+ Implementations of draft versions of the protocol MUST add the string "-" and the
+ corresponding draft number to the identifier. For example, draft-ietf-httpbis-http2-11
+ over TLS is identified using the string "h2-11".
+ </t>
+ <t>
+ Non-compatible experiments that are based on these draft versions MUST append the string
+ "-" and an experiment name to the identifier. For example, an experimental implementation
+ of packet mood-based encoding based on draft-ietf-httpbis-http2-09 might identify itself
+ as "h2-09-emo". Note that any label MUST conform to the "token" syntax defined in
+ <xref target="RFC7230" x:fmt="of" x:rel="#field.components"/>. Experimenters are
+ encouraged to coordinate their experiments on the ietf-http-wg@w3.org mailing list.
+ </t>
+ </section>
+
+ <section anchor="discover-http" title="Starting HTTP/2 for &quot;http&quot; URIs">
+ <t>
+ A client that makes a request for an "http" URI without prior knowledge about support for
+ HTTP/2 uses the HTTP Upgrade mechanism (<xref target="RFC7230" x:fmt="of"
+ x:rel="#header.upgrade"/>). The client makes an HTTP/1.1 request that includes an Upgrade
+ header field identifying HTTP/2 with the "h2c" token. The HTTP/1.1 request MUST include
+ exactly one <xref target="Http2SettingsHeader">HTTP2-Settings</xref> header field.
+ </t>
+ <figure>
+ <preamble>For example:</preamble>
+ <artwork type="message/http; msgtype=&#34;request&#34;" x:indent-with=" "><![CDATA[
+GET / HTTP/1.1
+Host: server.example.com
+Connection: Upgrade, HTTP2-Settings
+Upgrade: h2c
+HTTP2-Settings: <base64url encoding of HTTP/2 SETTINGS payload>
+
+]]></artwork>
+ </figure>
+ <t>
+ Requests that contain an entity body MUST be sent in their entirety before the client can
+ send HTTP/2 frames. This means that a large request entity can block the use of the
+ connection until it is completely sent.
+ </t>
+ <t>
+ If concurrency of an initial request with subsequent requests is important, an OPTIONS
+ request can be used to perform the upgrade to HTTP/2, at the cost of an additional
+ round-trip.
+ </t>
+ <t>
+ A server that does not support HTTP/2 can respond to the request as though the Upgrade
+ header field were absent:
+ </t>
+ <figure>
+ <artwork type="message/http; msgtype=&#34;response&#34;" x:indent-with=" ">
+HTTP/1.1 200 OK
+Content-Length: 243
+Content-Type: text/html
+
+...
+</artwork>
+ </figure>
+ <t>
+ A server MUST ignore a "h2" token in an Upgrade header field. Presence of a token with
+ "h2" implies HTTP/2 over TLS, which is instead negotiated as described in <xref
+ target="discover-https"/>.
+ </t>
+ <t>
+ A server that supports HTTP/2 can accept the upgrade with a 101 (Switching Protocols)
+ response. After the empty line that terminates the 101 response, the server can begin
+ sending HTTP/2 frames. These frames MUST include a response to the request that initiated
+ the Upgrade.
+ </t>
+
+ <figure>
+ <preamble>
+ For example:
+ </preamble>
+ <artwork type="message/http; msgtype=&#34;response&#34;" x:indent-with=" ">
+HTTP/1.1 101 Switching Protocols
+Connection: Upgrade
+Upgrade: h2c
+
+[ HTTP/2 connection ...
+</artwork>
+ </figure>
+ <t>
+ The first HTTP/2 frame sent by the server is a <x:ref>SETTINGS</x:ref> frame (<xref
+ target="SETTINGS"/>) as the server connection preface (<xref
+ target="ConnectionHeader"/>). Upon receiving the 101 response, the client sends a <xref
+ target="ConnectionHeader">connection preface</xref>, which includes a
+ <x:ref>SETTINGS</x:ref> frame.
+ </t>
+ <t>
+ The HTTP/1.1 request that is sent prior to upgrade is assigned stream identifier 1 and is
+ assigned <xref target="pri-default">default priority values</xref>. Stream 1 is
+ implicitly half closed from the client toward the server, since the request is completed
+ as an HTTP/1.1 request. After commencing the HTTP/2 connection, stream 1 is used for the
+ response.
+ </t>
+
+ <section anchor="Http2SettingsHeader" title="HTTP2-Settings Header Field">
+ <t>
+ A request that upgrades from HTTP/1.1 to HTTP/2 MUST include exactly one <spanx
+ style="verb">HTTP2-Settings</spanx> header field. The <spanx
+ style="verb">HTTP2-Settings</spanx> header field is a connection-specific header field
+ that includes parameters that govern the HTTP/2 connection, provided in anticipation of
+ the server accepting the request to upgrade.
+ </t>
+ <figure>
+ <artwork type="abnf" x:indent-with=" "><![CDATA[
+HTTP2-Settings = token68
+]]></artwork>
+ </figure>
+ <t>
+ A server MUST NOT upgrade the connection to HTTP/2 if this header field is not present,
+ or if more than one is present. A server MUST NOT send this header field.
+ </t>
+
+ <t>
+ The content of the <spanx style="verb">HTTP2-Settings</spanx> header field is the
+ payload of a <x:ref>SETTINGS</x:ref> frame (<xref target="SETTINGS"/>), encoded as a
+ base64url string (that is, the URL- and filename-safe Base64 encoding described in <xref
+ target="RFC4648" x:fmt="of" x:sec="5"/>, with any trailing '=' characters omitted). The
+ <xref target="RFC5234">ABNF</xref> production for <spanx style="verb">token68</spanx> is
+ defined in <xref target="RFC7235" x:fmt="of" x:rel="#challenge.and.response"/>.
+ </t>
+ <t>
+ Since the upgrade is only intended to apply to the immediate connection, a client
+ sending <spanx style="verb">HTTP2-Settings</spanx> MUST also send <spanx
+ style="verb">HTTP2-Settings</spanx> as a connection option in the <spanx
+ style="verb">Connection</spanx> header field to prevent it from being forwarded
+ downstream.
+ </t>
+ <t>
+ A server decodes and interprets these values as it would any other
+ <x:ref>SETTINGS</x:ref> frame. <xref target="SettingsSync">Acknowledgement of the
+ SETTINGS parameters</xref> is not necessary, since a 101 response serves as implicit
+ acknowledgment. Providing these values in the Upgrade request gives a client an
+ opportunity to provide parameters prior to receiving any frames from the server.
+ </t>
+ </section>
+ </section>
+
+ <section anchor="discover-https" title="Starting HTTP/2 for &quot;https&quot; URIs">
+ <t>
+ A client that makes a request to an "https" URI uses <xref target="TLS12">TLS</xref>
+ with the <xref target="TLS-ALPN">application layer protocol negotiation extension</xref>.
+ </t>
+ <t>
+ HTTP/2 over TLS uses the "h2" application token. The "h2c" token MUST NOT be sent by a
+ client or selected by a server.
+ </t>
+ <t>
+ Once TLS negotiation is complete, both the client and the server send a <xref
+ target="ConnectionHeader">connection preface</xref>.
+ </t>
+ </section>
+
+ <section anchor="known-http" title="Starting HTTP/2 with Prior Knowledge">
+ <t>
+ A client can learn that a particular server supports HTTP/2 by other means. For example,
+ <xref target="ALT-SVC"/> describes a mechanism for advertising this capability.
+ </t>
+ <t>
+ A client MAY immediately send HTTP/2 frames to a server that is known to support HTTP/2,
+ after the <xref target="ConnectionHeader">connection preface</xref>; a server can
+ identify such a connection by the presence of the connection preface. This only affects
+ the establishment of HTTP/2 connections over cleartext TCP; implementations that support
+ HTTP/2 over TLS MUST use <xref target="TLS-ALPN">protocol negotiation in TLS</xref>.
+ </t>
+ <t>
+ Without additional information, prior support for HTTP/2 is not a strong signal that a
+ given server will support HTTP/2 for future connections. For example, it is possible for
+ server configurations to change, for configurations to differ between instances in
+ clustered servers, or for network conditions to change.
+ </t>
+ </section>
+
+ <section anchor="ConnectionHeader" title="HTTP/2 Connection Preface">
+ <t>
+ Upon establishment of a TCP connection and determination that HTTP/2 will be used by both
+ peers, each endpoint MUST send a connection preface as a final confirmation and to
+ establish the initial SETTINGS parameters for the HTTP/2 connection. The client and
+ server each send a different connection preface.
+ </t>
+ <t>
+ The client connection preface starts with a sequence of 24 octets, which in hex notation
+ are:
+ </t>
+ <figure>
+ <artwork type="inline" x:indent-with=" "><![CDATA[
+0x505249202a20485454502f322e300d0a0d0a534d0d0a0d0a
+]]></artwork>
+ </figure>
+ <t>
+ (the string <spanx style="verb">PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n</spanx>). This sequence
+ is followed by a <x:ref>SETTINGS</x:ref> frame (<xref target="SETTINGS"/>). The
+ <x:ref>SETTINGS</x:ref> frame MAY be empty. The client sends the client connection
+ preface immediately upon receipt of a 101 Switching Protocols response (indicating a
+ successful upgrade), or as the first application data octets of a TLS connection. If
+ starting an HTTP/2 connection with prior knowledge of server support for the protocol, the
+ client connection preface is sent upon connection establishment.
+ </t>
+ <t>
+ <list>
+ <t>
+ The client connection preface is selected so that a large proportion of HTTP/1.1 or
+ HTTP/1.0 servers and intermediaries do not attempt to process further frames. Note
+ that this does not address the concerns raised in <xref target="TALKING"/>.
+ </t>
+ </list>
+ </t>
+ <t>
+ The server connection preface consists of a potentially empty <x:ref>SETTINGS</x:ref>
+ frame (<xref target="SETTINGS"/>) that MUST be the first frame the server sends in the
+ HTTP/2 connection.
+ </t>
+ <t>
+ The <x:ref>SETTINGS</x:ref> frames received from a peer as part of the connection preface
+ MUST be acknowledged (see <xref target="SettingsSync"/>) after sending the connection
+ preface.
+ </t>
+ <t>
+ To avoid unnecessary latency, clients are permitted to send additional frames to the
+ server immediately after sending the client connection preface, without waiting to receive
+ the server connection preface. It is important to note, however, that the server
+ connection preface <x:ref>SETTINGS</x:ref> frame might include parameters that necessarily
+ alter how a client is expected to communicate with the server. Upon receiving the
+ <x:ref>SETTINGS</x:ref> frame, the client is expected to honor any parameters established.
+ In some configurations, it is possible for the server to transmit <x:ref>SETTINGS</x:ref>
+ before the client sends additional frames, providing an opportunity to avoid this issue.
+ </t>
+ <t>
+ Clients and servers MUST treat an invalid connection preface as a <xref
+ target="ConnectionErrorHandler">connection error</xref> of type
+ <x:ref>PROTOCOL_ERROR</x:ref>. A <x:ref>GOAWAY</x:ref> frame (<xref target="GOAWAY"/>)
+ MAY be omitted in this case, since an invalid preface indicates that the peer is not using
+ HTTP/2.
+ </t>
+ </section>
+ </section>
+
+ <section anchor="FramingLayer" title="HTTP Frames">
+ <t>
+ Once the HTTP/2 connection is established, endpoints can begin exchanging frames.
+ </t>
+
+ <section anchor="FrameHeader" title="Frame Format">
+ <t>
+ All frames begin with a fixed 9-octet header followed by a variable-length payload.
+ </t>
+ <figure title="Frame Layout">
+ <artwork type="inline"><![CDATA[
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Length (24) |
+ +---------------+---------------+---------------+
+ | Type (8) | Flags (8) |
+ +-+-+-----------+---------------+-------------------------------+
+ |R| Stream Identifier (31) |
+ +=+=============================================================+
+ | Frame Payload (0...) ...
+ +---------------------------------------------------------------+
+]]></artwork>
+ </figure>
+ <t>
+ The fields of the frame header are defined as:
+ <list style="hanging">
+ <x:lt hangText="Length:">
+ <t>
+ The length of the frame payload expressed as an unsigned 24-bit integer. Values
+ greater than 2<x:sup>14</x:sup> (16,384) MUST NOT be sent unless the receiver has
+ set a larger value for <x:ref>SETTINGS_MAX_FRAME_SIZE</x:ref>.
+ </t>
+ <t>
+ The 9 octets of the frame header are not included in this value.
+ </t>
+ </x:lt>
+ <x:lt hangText="Type:">
+ <t>
+ The 8-bit type of the frame. The frame type determines the format and semantics of
+ the frame. Implementations MUST ignore and discard any frame that has a type that
+ is unknown.
+ </t>
+ </x:lt>
+ <x:lt hangText="Flags:">
+ <t>
+ An 8-bit field reserved for frame-type specific boolean flags.
+ </t>
+ <t>
+ Flags are assigned semantics specific to the indicated frame type. Flags that have
+ no defined semantics for a particular frame type MUST be ignored, and MUST be left
+ unset (0) when sending.
+ </t>
+ </x:lt>
+ <x:lt hangText="R:">
+ <t>
+ A reserved 1-bit field. The semantics of this bit are undefined and the bit MUST
+ remain unset (0) when sending and MUST be ignored when receiving.
+ </t>
+ </x:lt>
+ <x:lt hangText="Stream Identifier:">
+ <t>
+ A 31-bit stream identifier (see <xref target="StreamIdentifiers"/>). The value 0 is
+ reserved for frames that are associated with the connection as a whole as opposed to
+ an individual stream.
+ </t>
+ </x:lt>
+ </list>
+ </t>
+ <t>
+ The structure and content of the frame payload is dependent entirely on the frame type.
+ </t>
+ </section>
+
+ <section anchor="FrameSize" title="Frame Size">
+ <t>
+ The size of a frame payload is limited by the maximum size that a receiver advertises in
+ the <x:ref>SETTINGS_MAX_FRAME_SIZE</x:ref> setting. This setting can have any value
+ between 2<x:sup>14</x:sup> (16,384) and 2<x:sup>24</x:sup>-1 (16,777,215) octets,
+ inclusive.
+ </t>
+ <t>
+ All implementations MUST be capable of receiving and minimally processing frames up to
+ 2<x:sup>14</x:sup> octets in length, plus the 9 octet <xref target="FrameHeader">frame
+ header</xref>. The size of the frame header is not included when describing frame sizes.
+ <list style="hanging">
+ <t hangText="Note:">
+ Certain frame types, such as <xref target="PING">PING</xref>, impose additional limits
+ on the amount of payload data allowed.
+ </t>
+ </list>
+ </t>
+ <t>
+ If a frame size exceeds any defined limit, or is too small to contain mandatory frame
+ data, the endpoint MUST send a <x:ref>FRAME_SIZE_ERROR</x:ref> error. A frame size error
+ in a frame that could alter the state of the entire connection MUST be treated as a <xref
+ target="ConnectionErrorHandler">connection error</xref>; this includes any frame carrying
+ a <xref target="HeaderBlock">header block</xref> (that is, <x:ref>HEADERS</x:ref>,
+ <x:ref>PUSH_PROMISE</x:ref>, and <x:ref>CONTINUATION</x:ref>), <x:ref>SETTINGS</x:ref>,
+ and any <x:ref>WINDOW_UPDATE</x:ref> frame with a stream identifier of 0.
+ </t>
+ <t>
+ Endpoints are not obligated to use all available space in a frame. Responsiveness can be
+ improved by using frames that are smaller than the permitted maximum size. Sending large
+ frames can result in delays in sending time-sensitive frames (such
+ <x:ref>RST_STREAM</x:ref>, <x:ref>WINDOW_UPDATE</x:ref>, or <x:ref>PRIORITY</x:ref>)
+ which if blocked by the transmission of a large frame, could affect performance.
+ </t>
+ </section>
+
+ <section anchor="HeaderBlock" title="Header Compression and Decompression">
+ <t>
+ Just as in HTTP/1, a header field in HTTP/2 is a name with one or more associated values.
+ They are used within HTTP request and response messages as well as server push operations
+ (see <xref target="PushResources" />).
+ </t>
+ <t>
+ Header lists are collections of zero or more header fields. When transmitted over a
+ connection, a header list is serialized into a header block using <xref
+ target="COMPRESSION">HTTP Header Compression</xref>. The serialized header block is then
+ divided into one or more octet sequences, called header block fragments, and transmitted
+ within the payload of <xref target="HEADERS">HEADERS</xref>, <xref
+ target="PUSH_PROMISE">PUSH_PROMISE</xref> or <xref
+ target="CONTINUATION">CONTINUATION</xref> frames.
+ </t>
+ <t>
+ The <xref target="COOKIE">Cookie header field</xref> is treated specially by the HTTP
+ mapping (see <xref target="CompressCookie"/>).
+ </t>
+ <t>
+ A receiving endpoint reassembles the header block by concatenating its fragments, then
+ decompresses the block to reconstruct the header list.
+ </t>
+ <t>
+ A complete header block consists of either:
+ <list style="symbols">
+ <t>
+ a single <x:ref>HEADERS</x:ref> or <x:ref>PUSH_PROMISE</x:ref> frame,
+ with the END_HEADERS flag set, or
+ </t>
+ <t>
+ a <x:ref>HEADERS</x:ref> or <x:ref>PUSH_PROMISE</x:ref> frame with the END_HEADERS
+ flag cleared and one or more <x:ref>CONTINUATION</x:ref> frames,
+ where the last <x:ref>CONTINUATION</x:ref> frame has the END_HEADERS flag set.
+ </t>
+ </list>
+ </t>
+ <t>
+ Header compression is stateful. One compression context and one decompression context is
+ used for the entire connection. Each header block is processed as a discrete unit.
+ Header blocks MUST be transmitted as a contiguous sequence of frames, with no interleaved
+ frames of any other type or from any other stream. The last frame in a sequence of
+ <x:ref>HEADERS</x:ref> or <x:ref>CONTINUATION</x:ref> frames MUST have the END_HEADERS
+ flag set. The last frame in a sequence of <x:ref>PUSH_PROMISE</x:ref> or
+ <x:ref>CONTINUATION</x:ref> frames MUST have the END_HEADERS flag set. This allows a
+ header block to be logically equivalent to a single frame.
+ </t>
+ <t>
+ Header block fragments can only be sent as the payload of <x:ref>HEADERS</x:ref>,
+ <x:ref>PUSH_PROMISE</x:ref> or <x:ref>CONTINUATION</x:ref> frames, because these frames
+ carry data that can modify the compression context maintained by a receiver. An endpoint
+ receiving <x:ref>HEADERS</x:ref>, <x:ref>PUSH_PROMISE</x:ref> or
+ <x:ref>CONTINUATION</x:ref> frames MUST reassemble header blocks and perform decompression
+ even if the frames are to be discarded. A receiver MUST terminate the connection with a
+ <xref target="ConnectionErrorHandler">connection error</xref> of type
+ <x:ref>COMPRESSION_ERROR</x:ref> if it does not decompress a header block.
+ </t>
+ </section>
+ </section>
+
+ <section anchor="StreamsLayer" title="Streams and Multiplexing">
+ <t>
+ A "stream" is an independent, bi-directional sequence of frames exchanged between the client
+ and server within an HTTP/2 connection. Streams have several important characteristics:
+ <list style="symbols">
+ <t>
+ A single HTTP/2 connection can contain multiple concurrently open streams, with either
+ endpoint interleaving frames from multiple streams.
+ </t>
+ <t>
+ Streams can be established and used unilaterally or shared by either the client or
+ server.
+ </t>
+ <t>
+ Streams can be closed by either endpoint.
+ </t>
+ <t>
+ The order in which frames are sent on a stream is significant. Recipients process frames
+ in the order they are received. In particular, the order of <x:ref>HEADERS</x:ref>,
+ and <x:ref>DATA</x:ref> frames is semantically significant.
+ </t>
+ <t>
+ Streams are identified by an integer. Stream identifiers are assigned to streams by the
+ endpoint initiating the stream.
+ </t>
+ </list>
+ </t>
+
+ <section anchor="StreamStates" title="Stream States">
+ <t>
+ The lifecycle of a stream is shown in <xref target="StreamStatesFigure"/>.
+ </t>
+
+ <figure anchor="StreamStatesFigure" title="Stream States">
+ <artwork type="drawing">
+ <![CDATA[
+ +--------+
+ PP | | PP
+ ,--------| idle |--------.
+ / | | \
+ v +--------+ v
+ +----------+ | +----------+
+ | | | H | |
+ ,---| reserved | | | reserved |---.
+ | | (local) | v | (remote) | |
+ | +----------+ +--------+ +----------+ |
+ | | ES | | ES | |
+ | | H ,-------| open |-------. | H |
+ | | / | | \ | |
+ | v v +--------+ v v |
+ | +----------+ | +----------+ |
+ | | half | | | half | |
+ | | closed | | R | closed | |
+ | | (remote) | | | (local) | |
+ | +----------+ | +----------+ |
+ | | v | |
+ | | ES / R +--------+ ES / R | |
+ | `----------->| |<-----------' |
+ | R | closed | R |
+ `-------------------->| |<--------------------'
+ +--------+
+
+ H: HEADERS frame (with implied CONTINUATIONs)
+ PP: PUSH_PROMISE frame (with implied CONTINUATIONs)
+ ES: END_STREAM flag
+ R: RST_STREAM frame
+]]>
+ </artwork>
+ </figure>
+
+ <t>
+ Note that this diagram shows stream state transitions and the frames and flags that affect
+ those transitions only. In this regard, <x:ref>CONTINUATION</x:ref> frames do not result
+ in state transitions; they are effectively part of the <x:ref>HEADERS</x:ref> or
+ <x:ref>PUSH_PROMISE</x:ref> that they follow. For this purpose, the END_STREAM flag is
+ processed as a separate event to the frame that bears it; a <x:ref>HEADERS</x:ref> frame
+ with the END_STREAM flag set can cause two state transitions.
+ </t>
+ <t>
+ Both endpoints have a subjective view of the state of a stream that could be different
+ when frames are in transit. Endpoints do not coordinate the creation of streams; they are
+ created unilaterally by either endpoint. The negative consequences of a mismatch in
+ states are limited to the "closed" state after sending <x:ref>RST_STREAM</x:ref>, where
+ frames might be received for some time after closing.
+ </t>
+ <t>
+ Streams have the following states:
+ <list style="hanging">
+
+ <x:lt hangText="idle:">
+ <t>
+ <vspace blankLines="0"/>
+ All streams start in the "idle" state. In this state, no frames have been
+ exchanged.
+ </t>
+ <t>
+ The following transitions are valid from this state:
+ <list style="symbols">
+ <t>
+ Sending or receiving a <x:ref>HEADERS</x:ref> frame causes the stream to become
+ "open". The stream identifier is selected as described in <xref
+ target="StreamIdentifiers"/>. The same <x:ref>HEADERS</x:ref> frame can also
+ cause a stream to immediately become "half closed".
+ </t>
+ <t>
+ Sending a <x:ref>PUSH_PROMISE</x:ref> frame marks the associated stream for
+ later use. The stream state for the reserved stream transitions to "reserved
+ (local)".
+ </t>
+ <t>
+ Receiving a <x:ref>PUSH_PROMISE</x:ref> frame marks the associated stream as
+ reserved by the remote peer. The state of the stream becomes "reserved
+ (remote)".
+ </t>
+ </list>
+ </t>
+ <t>
+ Receiving any frames other than <x:ref>HEADERS</x:ref> or
+ <x:ref>PUSH_PROMISE</x:ref> on a stream in this state MUST be treated as a <xref
+ target="ConnectionErrorHandler">connection error</xref> of type
+ <x:ref>PROTOCOL_ERROR</x:ref>.
+ </t>
+ </x:lt>
+
+ <x:lt hangText="reserved (local):">
+ <t>
+ <vspace blankLines="0"/>
+ A stream in the "reserved (local)" state is one that has been promised by sending a
+ <x:ref>PUSH_PROMISE</x:ref> frame. A <x:ref>PUSH_PROMISE</x:ref> frame reserves an
+ idle stream by associating the stream with an open stream that was initiated by the
+ remote peer (see <xref target="PushResources"/>).
+ </t>
+ <t>
+ In this state, only the following transitions are possible:
+ <list style="symbols">
+ <t>
+ The endpoint can send a <x:ref>HEADERS</x:ref> frame. This causes the stream to
+ open in a "half closed (remote)" state.
+ </t>
+ <t>
+ Either endpoint can send a <x:ref>RST_STREAM</x:ref> frame to cause the stream
+ to become "closed". This releases the stream reservation.
+ </t>
+ </list>
+ </t>
+ <t>
+ An endpoint MUST NOT send any type of frame other than <x:ref>HEADERS</x:ref> or
+ <x:ref>RST_STREAM</x:ref> in this state.
+ </t>
+ <t>
+ A <x:ref>PRIORITY</x:ref> frame MAY be received in this state. Receiving any type
+ of frame other than <x:ref>RST_STREAM</x:ref> or <x:ref>PRIORITY</x:ref> on a stream
+ in this state MUST be treated as a <xref target="ConnectionErrorHandler">connection
+ error</xref> of type <x:ref>PROTOCOL_ERROR</x:ref>.
+ </t>
+ </x:lt>
+
+ <x:lt hangText="reserved (remote):">
+ <t>
+ <vspace blankLines="0"/>
+ A stream in the "reserved (remote)" state has been reserved by a remote peer.
+ </t>
+ <t>
+ In this state, only the following transitions are possible:
+ <list style="symbols">
+ <t>
+ Receiving a <x:ref>HEADERS</x:ref> frame causes the stream to transition to
+ "half closed (local)".
+ </t>
+ <t>
+ Either endpoint can send a <x:ref>RST_STREAM</x:ref> frame to cause the stream
+ to become "closed". This releases the stream reservation.
+ </t>
+ </list>
+ </t>
+ <t>
+ An endpoint MAY send a <x:ref>PRIORITY</x:ref> frame in this state to reprioritize
+ the reserved stream. An endpoint MUST NOT send any type of frame other than
+ <x:ref>RST_STREAM</x:ref>, <x:ref>WINDOW_UPDATE</x:ref>, or <x:ref>PRIORITY</x:ref>
+ in this state.
+ </t>
+ <t>
+ Receiving any type of frame other than <x:ref>HEADERS</x:ref> or
+ <x:ref>RST_STREAM</x:ref> on a stream in this state MUST be treated as a <xref
+ target="ConnectionErrorHandler">connection error</xref> of type
+ <x:ref>PROTOCOL_ERROR</x:ref>.
+ </t>
+ </x:lt>
+
+ <x:lt hangText="open:">
+ <t>
+ <vspace blankLines="0"/>
+ A stream in the "open" state may be used by both peers to send frames of any type.
+ In this state, sending peers observe advertised <xref target="FlowControl">stream
+ level flow control limits</xref>.
+ </t>
+ <t>
+ From this state either endpoint can send a frame with an END_STREAM flag set, which
+ causes the stream to transition into one of the "half closed" states: an endpoint
+ sending an END_STREAM flag causes the stream state to become "half closed (local)";
+ an endpoint receiving an END_STREAM flag causes the stream state to become "half
+ closed (remote)".
+ </t>
+ <t>
+ Either endpoint can send a <x:ref>RST_STREAM</x:ref> frame from this state, causing
+ it to transition immediately to "closed".
+ </t>
+ </x:lt>
+
+ <x:lt hangText="half closed (local):">
+ <t>
+ <vspace blankLines="0"/>
+ A stream that is in the "half closed (local)" state cannot be used for sending
+ frames. Only <x:ref>WINDOW_UPDATE</x:ref>, <x:ref>PRIORITY</x:ref> and
+ <x:ref>RST_STREAM</x:ref> frames can be sent in this state.
+ </t>
+ <t>
+ A stream transitions from this state to "closed" when a frame that contains an
+ END_STREAM flag is received, or when either peer sends a <x:ref>RST_STREAM</x:ref>
+ frame.
+ </t>
+ <t>
+ A receiver can ignore <x:ref>WINDOW_UPDATE</x:ref> frames in this state, which might
+ arrive for a short period after a frame bearing the END_STREAM flag is sent.
+ </t>
+ <t>
+ <x:ref>PRIORITY</x:ref> frames received in this state are used to reprioritize
+ streams that depend on the current stream.
+ </t>
+ </x:lt>
+
+ <x:lt hangText="half closed (remote):">
+ <t>
+ <vspace blankLines="0"/>
+ A stream that is "half closed (remote)" is no longer being used by the peer to send
+ frames. In this state, an endpoint is no longer obligated to maintain a receiver
+ flow control window if it performs flow control.
+ </t>
+ <t>
+ If an endpoint receives additional frames for a stream that is in this state, other
+ than <x:ref>WINDOW_UPDATE</x:ref>, <x:ref>PRIORITY</x:ref> or
+ <x:ref>RST_STREAM</x:ref>, it MUST respond with a <xref
+ target="StreamErrorHandler">stream error</xref> of type
+ <x:ref>STREAM_CLOSED</x:ref>.
+ </t>
+ <t>
+ A stream that is "half closed (remote)" can be used by the endpoint to send frames
+ of any type. In this state, the endpoint continues to observe advertised <xref
+ target="FlowControl">stream level flow control limits</xref>.
+ </t>
+ <t>
+ A stream can transition from this state to "closed" by sending a frame that contains
+ an END_STREAM flag, or when either peer sends a <x:ref>RST_STREAM</x:ref> frame.
+ </t>
+ </x:lt>
+
+ <x:lt hangText="closed:">
+ <t>
+ <vspace blankLines="0"/>
+ The "closed" state is the terminal state.
+ </t>
+ <t>
+ An endpoint MUST NOT send frames other than <x:ref>PRIORITY</x:ref> on a closed
+ stream. An endpoint that receives any frame other than <x:ref>PRIORITY</x:ref>
+ after receiving a <x:ref>RST_STREAM</x:ref> MUST treat that as a <xref
+ target="StreamErrorHandler">stream error</xref> of type
+ <x:ref>STREAM_CLOSED</x:ref>. Similarly, an endpoint that receives any frames after
+ receiving a frame with the END_STREAM flag set MUST treat that as a <xref
+ target="ConnectionErrorHandler">connection error</xref> of type
+ <x:ref>STREAM_CLOSED</x:ref>, unless the frame is permitted as described below.
+ </t>
+ <t>
+ <x:ref>WINDOW_UPDATE</x:ref> or <x:ref>RST_STREAM</x:ref> frames can be received in
+ this state for a short period after a <x:ref>DATA</x:ref> or <x:ref>HEADERS</x:ref>
+ frame containing an END_STREAM flag is sent. Until the remote peer receives and
+ processes <x:ref>RST_STREAM</x:ref> or the frame bearing the END_STREAM flag, it
+ might send frames of these types. Endpoints MUST ignore
+ <x:ref>WINDOW_UPDATE</x:ref> or <x:ref>RST_STREAM</x:ref> frames received in this
+ state, though endpoints MAY choose to treat frames that arrive a significant time
+ after sending END_STREAM as a <xref target="ConnectionErrorHandler">connection
+ error</xref> of type <x:ref>PROTOCOL_ERROR</x:ref>.
+ </t>
+ <t>
+ <x:ref>PRIORITY</x:ref> frames can be sent on closed streams to prioritize streams
+ that are dependent on the closed stream. Endpoints SHOULD process
+ <x:ref>PRIORITY</x:ref> frame, though they can be ignored if the stream has been
+ removed from the dependency tree (see <xref target="priority-gc"/>).
+ </t>
+ <t>
+ If this state is reached as a result of sending a <x:ref>RST_STREAM</x:ref> frame,
+ the peer that receives the <x:ref>RST_STREAM</x:ref> might have already sent - or
+ enqueued for sending - frames on the stream that cannot be withdrawn. An endpoint
+ MUST ignore frames that it receives on closed streams after it has sent a
+ <x:ref>RST_STREAM</x:ref> frame. An endpoint MAY choose to limit the period over
+ which it ignores frames and treat frames that arrive after this time as being in
+ error.
+ </t>
+ <t>
+ Flow controlled frames (i.e., <x:ref>DATA</x:ref>) received after sending
+ <x:ref>RST_STREAM</x:ref> are counted toward the connection flow control window.
+ Even though these frames might be ignored, because they are sent before the sender
+ receives the <x:ref>RST_STREAM</x:ref>, the sender will consider the frames to count
+ against the flow control window.
+ </t>
+ <t>
+ An endpoint might receive a <x:ref>PUSH_PROMISE</x:ref> frame after it sends
+ <x:ref>RST_STREAM</x:ref>. <x:ref>PUSH_PROMISE</x:ref> causes a stream to become
+ "reserved" even if the associated stream has been reset. Therefore, a
+ <x:ref>RST_STREAM</x:ref> is needed to close an unwanted promised stream.
+ </t>
+ </x:lt>
+ </list>
+ </t>
+ <t>
+ In the absence of more specific guidance elsewhere in this document, implementations
+ SHOULD treat the receipt of a frame that is not expressly permitted in the description of
+ a state as a <xref target="ConnectionErrorHandler">connection error</xref> of type
+ <x:ref>PROTOCOL_ERROR</x:ref>. Frame of unknown types are ignored.
+ </t>
+ <t>
+ An example of the state transitions for an HTTP request/response exchange can be found in
+ <xref target="HttpSequence"/>. An example of the state transitions for server push can be
+ found in <xref target="PushRequests"/> and <xref target="PushResponses"/>.
+ </t>
+
+ <section anchor="StreamIdentifiers" title="Stream Identifiers">
+ <t>
+ Streams are identified with an unsigned 31-bit integer. Streams initiated by a client
+ MUST use odd-numbered stream identifiers; those initiated by the server MUST use
+ even-numbered stream identifiers. A stream identifier of zero (0x0) is used for
+ connection control messages; the stream identifier zero cannot be used to establish a
+ new stream.
+ </t>
+ <t>
+ HTTP/1.1 requests that are upgraded to HTTP/2 (see <xref target="discover-http"/>) are
+ responded to with a stream identifier of one (0x1). After the upgrade
+ completes, stream 0x1 is "half closed (local)" to the client. Therefore, stream 0x1
+ cannot be selected as a new stream identifier by a client that upgrades from HTTP/1.1.
+ </t>
+ <t>
+ The identifier of a newly established stream MUST be numerically greater than all
+ streams that the initiating endpoint has opened or reserved. This governs streams that
+ are opened using a <x:ref>HEADERS</x:ref> frame and streams that are reserved using
+ <x:ref>PUSH_PROMISE</x:ref>. An endpoint that receives an unexpected stream identifier
+ MUST respond with a <xref target="ConnectionErrorHandler">connection error</xref> of
+ type <x:ref>PROTOCOL_ERROR</x:ref>.
+ </t>
+ <t>
+ The first use of a new stream identifier implicitly closes all streams in the "idle"
+ state that might have been initiated by that peer with a lower-valued stream identifier.
+ For example, if a client sends a <x:ref>HEADERS</x:ref> frame on stream 7 without ever
+ sending a frame on stream 5, then stream 5 transitions to the "closed" state when the
+ first frame for stream 7 is sent or received.
+ </t>
+ <t>
+ Stream identifiers cannot be reused. Long-lived connections can result in an endpoint
+ exhausting the available range of stream identifiers. A client that is unable to
+ establish a new stream identifier can establish a new connection for new streams. A
+ server that is unable to establish a new stream identifier can send a
+ <x:ref>GOAWAY</x:ref> frame so that the client is forced to open a new connection for
+ new streams.
+ </t>
+ </section>
+
+ <section title="Stream Concurrency">
+ <t>
+ A peer can limit the number of concurrently active streams using the
+ <x:ref>SETTINGS_MAX_CONCURRENT_STREAMS</x:ref> parameter (see <xref
+ target="SettingValues"/>) within a <x:ref>SETTINGS</x:ref> frame. The maximum concurrent
+ streams setting is specific to each endpoint and applies only to the peer that receives
+ the setting. That is, clients specify the maximum number of concurrent streams the
+ server can initiate, and servers specify the maximum number of concurrent streams the
+ client can initiate.
+ </t>
+ <t>
+ Streams that are in the "open" state, or either of the "half closed" states count toward
+ the maximum number of streams that an endpoint is permitted to open. Streams in any of
+ these three states count toward the limit advertised in the
+ <x:ref>SETTINGS_MAX_CONCURRENT_STREAMS</x:ref> setting. Streams in either of the
+ "reserved" states do not count toward the stream limit.
+ </t>
+ <t>
+ Endpoints MUST NOT exceed the limit set by their peer. An endpoint that receives a
+ <x:ref>HEADERS</x:ref> frame that causes their advertised concurrent stream limit to be
+ exceeded MUST treat this as a <xref target="StreamErrorHandler">stream error</xref>. An
+ endpoint that wishes to reduce the value of
+ <x:ref>SETTINGS_MAX_CONCURRENT_STREAMS</x:ref> to a value that is below the current
+ number of open streams can either close streams that exceed the new value or allow
+ streams to complete.
+ </t>
+ </section>
+ </section>
+
+ <section anchor="FlowControl" title="Flow Control">
+ <t>
+ Using streams for multiplexing introduces contention over use of the TCP connection,
+ resulting in blocked streams. A flow control scheme ensures that streams on the same
+ connection do not destructively interfere with each other. Flow control is used for both
+ individual streams and for the connection as a whole.
+ </t>
+ <t>
+ HTTP/2 provides for flow control through use of the <xref
+ target="WINDOW_UPDATE">WINDOW_UPDATE frame</xref>.
+ </t>
+
+ <section anchor="fc-principles" title="Flow Control Principles">
+ <t>
+ HTTP/2 stream flow control aims to allow a variety of flow control algorithms to be
+ used without requiring protocol changes. Flow control in HTTP/2 has the following
+ characteristics:
+ <list style="numbers">
+ <t>
+ Flow control is specific to a connection; i.e., it is "hop-by-hop", not
+ "end-to-end".
+ </t>
+ <t>
+ Flow control is based on window update frames. Receivers advertise how many octets
+ they are prepared to receive on a stream and for the entire connection. This is a
+ credit-based scheme.
+ </t>
+ <t>
+ Flow control is directional with overall control provided by the receiver. A
+ receiver MAY choose to set any window size that it desires for each stream and for
+ the entire connection. A sender MUST respect flow control limits imposed by a
+ receiver. Clients, servers and intermediaries all independently advertise their
+ flow control window as a receiver and abide by the flow control limits set by
+ their peer when sending.
+ </t>
+ <t>
+ The initial value for the flow control window is 65,535 octets for both new streams
+ and the overall connection.
+ </t>
+ <t>
+ The frame type determines whether flow control applies to a frame. Of the frames
+ specified in this document, only <x:ref>DATA</x:ref> frames are subject to flow
+ control; all other frame types do not consume space in the advertised flow control
+ window. This ensures that important control frames are not blocked by flow control.
+ </t>
+ <t>
+ Flow control cannot be disabled.
+ </t>
+ <t>
+ HTTP/2 defines only the format and semantics of the <x:ref>WINDOW_UPDATE</x:ref>
+ frame (<xref target="WINDOW_UPDATE"/>). This document does not stipulate how a
+ receiver decides when to send this frame or the value that it sends, nor does it
+ specify how a sender chooses to send packets. Implementations are able to select
+ any algorithm that suits their needs.
+ </t>
+ </list>
+ </t>
+ <t>
+ Implementations are also responsible for managing how requests and responses are sent
+ based on priority; choosing how to avoid head of line blocking for requests; and
+ managing the creation of new streams. Algorithm choices for these could interact with
+ any flow control algorithm.
+ </t>
+ </section>
+
+ <section anchor="DisableFlowControl" title="Appropriate Use of Flow Control">
+ <t>
+ Flow control is defined to protect endpoints that are operating under resource
+ constraints. For example, a proxy needs to share memory between many connections, and
+ also might have a slow upstream connection and a fast downstream one. Flow control
+ addresses cases where the receiver is unable process data on one stream, yet wants to
+ continue to process other streams in the same connection.
+ </t>
+ <t>
+ Deployments that do not require this capability can advertise a flow control window of
+ the maximum size, incrementing the available space when new data is received. This
+ effectively disables flow control for that receiver. Conversely, a sender is always
+ subject to the flow control window advertised by the receiver.
+ </t>
+ <t>
+ Deployments with constrained resources (for example, memory) can employ flow control to
+ limit the amount of memory a peer can consume. Note, however, that this can lead to
+ suboptimal use of available network resources if flow control is enabled without
+ knowledge of the bandwidth-delay product (see <xref target="RFC1323"/>).
+ </t>
+ <t>
+ Even with full awareness of the current bandwidth-delay product, implementation of flow
+ control can be difficult. When using flow control, the receiver MUST read from the TCP
+ receive buffer in a timely fashion. Failure to do so could lead to a deadlock when
+ critical frames, such as <x:ref>WINDOW_UPDATE</x:ref>, are not read and acted upon.
+ </t>
+ </section>
+ </section>
+
+ <section anchor="StreamPriority" title="Stream priority">
+ <t>
+ A client can assign a priority for a new stream by including prioritization information in
+ the <xref target="HEADERS">HEADERS frame</xref> that opens the stream. For an existing
+ stream, the <xref target="PRIORITY">PRIORITY frame</xref> can be used to change the
+ priority.
+ </t>
+ <t>
+ The purpose of prioritization is to allow an endpoint to express how it would prefer its
+ peer allocate resources when managing concurrent streams. Most importantly, priority can
+ be used to select streams for transmitting frames when there is limited capacity for
+ sending.
+ </t>
+ <t>
+ Streams can be prioritized by marking them as dependent on the completion of other streams
+ (<xref target="pri-depend"/>). Each dependency is assigned a relative weight, a number
+ that is used to determine the relative proportion of available resources that are assigned
+ to streams dependent on the same stream.
+ </t>
+ <!--
+ Note that stream dependencies have not yet been validated in practice. The theory
+ might be fairly sound, but there are no implementations currently sending these. If it
+ turns out that they are not useful, or actively harmful, implementations will be requested
+ to avoid creating stream dependencies.
+ -->
+ <t>
+ Explicitly setting the priority for a stream is input to a prioritization process. It
+ does not guarantee any particular processing or transmission order for the stream relative
+ to any other stream. An endpoint cannot force a peer to process concurrent streams in a
+ particular order using priority. Expressing priority is therefore only ever a suggestion.
+ </t>
+ <t>
+ Providing prioritization information is optional, so default values are used if no
+ explicit indicator is provided (<xref target="pri-default"/>).
+ </t>
+
+ <section title="Stream Dependencies" anchor="pri-depend">
+ <t>
+ Each stream can be given an explicit dependency on another stream. Including a
+ dependency expresses a preference to allocate resources to the identified stream rather
+ than to the dependent stream.
+ </t>
+ <t>
+ A stream that is not dependent on any other stream is given a stream dependency of 0x0.
+ In other words, the non-existent stream 0 forms the root of the tree.
+ </t>
+ <t>
+ A stream that depends on another stream is a dependent stream. The stream upon which a
+ stream is dependent is a parent stream. A dependency on a stream that is not currently
+ in the tree - such as a stream in the "idle" state - results in that stream being given
+ a <xref target="pri-default">default priority</xref>.
+ </t>
+ <t>
+ When assigning a dependency on another stream, the stream is added as a new dependency
+ of the parent stream. Dependent streams that share the same parent are not ordered with
+ respect to each other. For example, if streams B and C are dependent on stream A, and
+ if stream D is created with a dependency on stream A, this results in a dependency order
+ of A followed by B, C, and D in any order.
+ </t>
+ <figure title="Example of Default Dependency Creation">
+ <artwork type="inline"><![CDATA[
+ A A
+ / \ ==> /|\
+ B C B D C
+]]></artwork>
+ </figure>
+ <t>
+ An exclusive flag allows for the insertion of a new level of dependencies. The
+ exclusive flag causes the stream to become the sole dependency of its parent stream,
+ causing other dependencies to become dependent on the exclusive stream. In the
+ previous example, if stream D is created with an exclusive dependency on stream A, this
+ results in D becoming the dependency parent of B and C.
+ </t>
+ <figure title="Example of Exclusive Dependency Creation">
+ <artwork type="inline"><![CDATA[
+ A
+ A |
+ / \ ==> D
+ B C / \
+ B C
+]]></artwork>
+ </figure>
+ <t>
+ Inside the dependency tree, a dependent stream SHOULD only be allocated resources if all
+ of the streams that it depends on (the chain of parent streams up to 0x0) are either
+ closed, or it is not possible to make progress on them.
+ </t>
+ <t>
+ A stream cannot depend on itself. An endpoint MUST treat this as a <xref
+ target="StreamErrorHandler">stream error</xref> of type <x:ref>PROTOCOL_ERROR</x:ref>.
+ </t>
+ </section>
+
+ <section title="Dependency Weighting">
+ <t>
+ All dependent streams are allocated an integer weight between 1 and 256 (inclusive).
+ </t>
+ <t>
+ Streams with the same parent SHOULD be allocated resources proportionally based on their
+ weight. Thus, if stream B depends on stream A with weight 4, and C depends on stream A
+ with weight 12, and if no progress can be made on A, stream B ideally receives one third
+ of the resources allocated to stream C.
+ </t>
+ </section>
+
+ <section anchor="reprioritize" title="Reprioritization">
+ <t>
+ Stream priorities are changed using the <x:ref>PRIORITY</x:ref> frame. Setting a
+ dependency causes a stream to become dependent on the identified parent stream.
+ </t>
+ <t>
+ Dependent streams move with their parent stream if the parent is reprioritized. Setting
+ a dependency with the exclusive flag for a reprioritized stream moves all the
+ dependencies of the new parent stream to become dependent on the reprioritized stream.
+ </t>
+ <t>
+ If a stream is made dependent on one of its own dependencies, the formerly dependent
+ stream is first moved to be dependent on the reprioritized stream's previous parent.
+ The moved dependency retains its weight.
+ </t>
+ <figure title="Example of Dependency Reordering">
+ <preamble>
+ For example, consider an original dependency tree where B and C depend on A, D and E
+ depend on C, and F depends on D. If A is made dependent on D, then D takes the place
+ of A. All other dependency relationships stay the same, except for F, which becomes
+ dependent on A if the reprioritization is exclusive.
+ </preamble>
+ <artwork type="inline"><![CDATA[
+ ? ? ? ?
+ | / \ | |
+ A D A D D
+ / \ / / \ / \ |
+ B C ==> F B C ==> F A OR A
+ / \ | / \ /|\
+ D E E B C B C F
+ | | |
+ F E E
+ (intermediate) (non-exclusive) (exclusive)
+]]></artwork>
+ </figure>
+ </section>
+
+ <section anchor="priority-gc" title="Prioritization State Management">
+ <t>
+ When a stream is removed from the dependency tree, its dependencies can be moved to
+ become dependent on the parent of the closed stream. The weights of new dependencies
+ are recalculated by distributing the weight of the dependency of the closed stream
+ proportionally based on the weights of its dependencies.
+ </t>
+ <t>
+ Streams that are removed from the dependency tree cause some prioritization information
+ to be lost. Resources are shared between streams with the same parent stream, which
+ means that if a stream in that set closes or becomes blocked, any spare capacity
+ allocated to a stream is distributed to the immediate neighbors of the stream. However,
+ if the common dependency is removed from the tree, those streams share resources with
+ streams at the next highest level.
+ </t>
+ <t>
+ For example, assume streams A and B share a parent, and streams C and D both depend on
+ stream A. Prior to the removal of stream A, if streams A and D are unable to proceed,
+ then stream C receives all the resources dedicated to stream A. If stream A is removed
+ from the tree, the weight of stream A is divided between streams C and D. If stream D
+ is still unable to proceed, this results in stream C receiving a reduced proportion of
+ resources. For equal starting weights, C receives one third, rather than one half, of
+ available resources.
+ </t>
+ <t>
+ It is possible for a stream to become closed while prioritization information that
+ creates a dependency on that stream is in transit. If a stream identified in a
+ dependency has no associated priority information, then the dependent stream is instead
+ assigned a <xref target="pri-default">default priority</xref>. This potentially creates
+ suboptimal prioritization, since the stream could be given a priority that is different
+ to what is intended.
+ </t>
+ <t>
+ To avoid these problems, an endpoint SHOULD retain stream prioritization state for a
+ period after streams become closed. The longer state is retained, the lower the chance
+ that streams are assigned incorrect or default priority values.
+ </t>
+ <t>
+ This could create a large state burden for an endpoint, so this state MAY be limited.
+ An endpoint MAY apply a fixed upper limit on the number of closed streams for which
+ prioritization state is tracked to limit state exposure. The amount of additional state
+ an endpoint maintains could be dependent on load; under high load, prioritization state
+ can be discarded to limit resource commitments. In extreme cases, an endpoint could
+ even discard prioritization state for active or reserved streams. If a fixed limit is
+ applied, endpoints SHOULD maintain state for at least as many streams as allowed by
+ their setting for <x:ref>SETTINGS_MAX_CONCURRENT_STREAMS</x:ref>.
+ </t>
+ <t>
+ An endpoint receiving a <x:ref>PRIORITY</x:ref> frame that changes the priority of a
+ closed stream SHOULD alter the dependencies of the streams that depend on it, if it has
+ retained enough state to do so.
+ </t>
+ </section>
+
+ <section title="Default Priorities" anchor="pri-default">
+ <t>
+ Providing priority information is optional. Streams are assigned a non-exclusive
+ dependency on stream 0x0 by default. <xref target="PushResources">Pushed streams</xref>
+ initially depend on their associated stream. In both cases, streams are assigned a
+ default weight of 16.
+ </t>
+ </section>
+ </section>
+
+ <section title="Error Handling">
+ <t>
+ HTTP/2 framing permits two classes of error:
+ <list style="symbols">
+ <t>
+ An error condition that renders the entire connection unusable is a connection error.
+ </t>
+ <t>
+ An error in an individual stream is a stream error.
+ </t>
+ </list>
+ </t>
+ <t>
+ A list of error codes is included in <xref target="ErrorCodes"/>.
+ </t>
+
+ <section anchor="ConnectionErrorHandler" title="Connection Error Handling">
+ <t>
+ A connection error is any error which prevents further processing of the framing layer,
+ or which corrupts any connection state.
+ </t>
+ <t>
+ An endpoint that encounters a connection error SHOULD first send a <x:ref>GOAWAY</x:ref>
+ frame (<xref target="GOAWAY"/>) with the stream identifier of the last stream that it
+ successfully received from its peer. The <x:ref>GOAWAY</x:ref> frame includes an error
+ code that indicates why the connection is terminating. After sending the
+ <x:ref>GOAWAY</x:ref> frame, the endpoint MUST close the TCP connection.
+ </t>
+ <t>
+ It is possible that the <x:ref>GOAWAY</x:ref> will not be reliably received by the
+ receiving endpoint (see <xref target="RFC7230" x:fmt=","
+ x:rel="#persistent.tear-down"/>). In the event of a connection error,
+ <x:ref>GOAWAY</x:ref> only provides a best effort attempt to communicate with the peer
+ about why the connection is being terminated.
+ </t>
+ <t>
+ An endpoint can end a connection at any time. In particular, an endpoint MAY choose to
+ treat a stream error as a connection error. Endpoints SHOULD send a
+ <x:ref>GOAWAY</x:ref> frame when ending a connection, providing that circumstances
+ permit it.
+ </t>
+ </section>
+
+ <section anchor="StreamErrorHandler" title="Stream Error Handling">
+ <t>
+ A stream error is an error related to a specific stream that does not affect processing
+ of other streams.
+ </t>
+ <t>
+ An endpoint that detects a stream error sends a <x:ref>RST_STREAM</x:ref> frame (<xref
+ target="RST_STREAM"/>) that contains the stream identifier of the stream where the error
+ occurred. The <x:ref>RST_STREAM</x:ref> frame includes an error code that indicates the
+ type of error.
+ </t>
+ <t>
+ A <x:ref>RST_STREAM</x:ref> is the last frame that an endpoint can send on a stream.
+ The peer that sends the <x:ref>RST_STREAM</x:ref> frame MUST be prepared to receive any
+ frames that were sent or enqueued for sending by the remote peer. These frames can be
+ ignored, except where they modify connection state (such as the state maintained for
+ <xref target="HeaderBlock">header compression</xref>, or flow control).
+ </t>
+ <t>
+ Normally, an endpoint SHOULD NOT send more than one <x:ref>RST_STREAM</x:ref> frame for
+ any stream. However, an endpoint MAY send additional <x:ref>RST_STREAM</x:ref> frames if
+ it receives frames on a closed stream after more than a round-trip time. This behavior
+ is permitted to deal with misbehaving implementations.
+ </t>
+ <t>
+ An endpoint MUST NOT send a <x:ref>RST_STREAM</x:ref> in response to an
+ <x:ref>RST_STREAM</x:ref> frame, to avoid looping.
+ </t>
+ </section>
+
+ <section title="Connection Termination">
+ <t>
+ If the TCP connection is closed or reset while streams remain in open or half closed
+ states, then the endpoint MUST assume that those streams were abnormally interrupted and
+ could be incomplete.
+ </t>
+ </section>
+ </section>
+
+ <section anchor="extensibility" title="Extending HTTP/2">
+ <t>
+ HTTP/2 permits extension of the protocol. Protocol extensions can be used to provide
+ additional services or alter any aspect of the protocol, within the limitations described
+ in this section. Extensions are effective only within the scope of a single HTTP/2
+ connection.
+ </t>
+ <t>
+ Extensions are permitted to use new <xref target="FrameHeader">frame types</xref>, new
+ <xref target="SettingValues">settings</xref>, or new <xref target="ErrorCodes">error
+ codes</xref>. Registries are established for managing these extension points: <xref
+ target="iana-frames">frame types</xref>, <xref target="iana-settings">settings</xref> and
+ <xref target="iana-errors">error codes</xref>.
+ </t>
+ <t>
+ Implementations MUST ignore unknown or unsupported values in all extensible protocol
+ elements. Implementations MUST discard frames that have unknown or unsupported types.
+ This means that any of these extension points can be safely used by extensions without
+ prior arrangement or negotiation. However, extension frames that appear in the middle of
+ a <xref target="HeaderBlock">header block</xref> are not permitted; these MUST be treated
+ as a <xref target="ConnectionErrorHandler">connection error</xref> of type
+ <x:ref>PROTOCOL_ERROR</x:ref>.
+ </t>
+ <t>
+ However, extensions that could change the semantics of existing protocol components MUST
+ be negotiated before being used. For example, an extension that changes the layout of the
+ <x:ref>HEADERS</x:ref> frame cannot be used until the peer has given a positive signal
+ that this is acceptable. In this case, it could also be necessary to coordinate when the
+ revised layout comes into effect. Note that treating any frame other than
+ <x:ref>DATA</x:ref> frames as flow controlled is such a change in semantics, and can only
+ be done through negotiation.
+ </t>
+ <t>
+ This document doesn't mandate a specific method for negotiating the use of an extension,
+ but notes that a <xref target="SettingValues">setting</xref> could be used for that
+ purpose. If both peers set a value that indicates willingness to use the extension, then
+ the extension can be used. If a setting is used for extension negotiation, the initial
+ value MUST be defined so that the extension is initially disabled.
+ </t>
+ </section>
+ </section>
+
+ <section anchor="FrameTypes" title="Frame Definitions">
+ <t>
+ This specification defines a number of frame types, each identified by a unique 8-bit type
+ code. Each frame type serves a distinct purpose either in the establishment and management
+ of the connection as a whole, or of individual streams.
+ </t>
+ <t>
+ The transmission of specific frame types can alter the state of a connection. If endpoints
+ fail to maintain a synchronized view of the connection state, successful communication
+ within the connection will no longer be possible. Therefore, it is important that endpoints
+ have a shared comprehension of how the state is affected by the use any given frame.
+ </t>
+
+ <section anchor="DATA" title="DATA">
+ <t>
+ DATA frames (type=0x0) convey arbitrary, variable-length sequences of octets associated
+ with a stream. One or more DATA frames are used, for instance, to carry HTTP request or
+ response payloads.
+ </t>
+ <t>
+ DATA frames MAY also contain arbitrary padding. Padding can be added to DATA frames to
+ obscure the size of messages.
+ </t>
+ <figure title="DATA Frame Payload">
+ <artwork type="inline"><![CDATA[
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ |Pad Length? (8)|
+ +---------------+-----------------------------------------------+
+ | Data (*) ...
+ +---------------------------------------------------------------+
+ | Padding (*) ...
+ +---------------------------------------------------------------+
+]]></artwork>
+ </figure>
+ <t>
+ The DATA frame contains the following fields:
+ <list style="hanging">
+ <t hangText="Pad Length:">
+ An 8-bit field containing the length of the frame padding in units of octets. This
+ field is optional and is only present if the PADDED flag is set.
+ </t>
+ <t hangText="Data:">
+ Application data. The amount of data is the remainder of the frame payload after
+ subtracting the length of the other fields that are present.
+ </t>
+ <t hangText="Padding:">
+ Padding octets that contain no application semantic value. Padding octets MUST be set
+ to zero when sending and ignored when receiving.
+ </t>
+ </list>
+ </t>
+
+ <t>
+ The DATA frame defines the following flags:
+ <list style="hanging">
+ <t hangText="END_STREAM (0x1):">
+ Bit 1 being set indicates that this frame is the last that the endpoint will send for
+ the identified stream. Setting this flag causes the stream to enter one of <xref
+ target="StreamStates">the "half closed" states or the "closed" state</xref>.
+ </t>
+ <t hangText="PADDED (0x8):">
+ Bit 4 being set indicates that the Pad Length field and any padding that it describes
+ is present.
+ </t>
+ </list>
+ </t>
+ <t>
+ DATA frames MUST be associated with a stream. If a DATA frame is received whose stream
+ identifier field is 0x0, the recipient MUST respond with a <xref
+ target="ConnectionErrorHandler">connection error</xref> of type
+ <x:ref>PROTOCOL_ERROR</x:ref>.
+ </t>
+ <t>
+ DATA frames are subject to flow control and can only be sent when a stream is in the
+ "open" or "half closed (remote)" states. The entire DATA frame payload is included in flow
+ control, including Pad Length and Padding fields if present. If a DATA frame is received
+ whose stream is not in "open" or "half closed (local)" state, the recipient MUST respond
+ with a <xref target="StreamErrorHandler">stream error</xref> of type
+ <x:ref>STREAM_CLOSED</x:ref>.
+ </t>
+ <t>
+ The total number of padding octets is determined by the value of the Pad Length field. If
+ the length of the padding is greater than the length of the frame payload, the recipient
+ MUST treat this as a <xref target="ConnectionErrorHandler">connection error</xref> of
+ type <x:ref>PROTOCOL_ERROR</x:ref>.
+ <list style="hanging">
+ <t hangText="Note:">
+ A frame can be increased in size by one octet by including a Pad Length field with a
+ value of zero.
+ </t>
+ </list>
+ </t>
+ <t>
+ Padding is a security feature; see <xref target="padding"/>.
+ </t>
+ </section>
+
+ <section anchor="HEADERS" title="HEADERS">
+ <t>
+ The HEADERS frame (type=0x1) is used to <xref target="StreamStates">open a stream</xref>,
+ and additionally carries a header block fragment. HEADERS frames can be sent on a stream
+ in the "open" or "half closed (remote)" states.
+ </t>
+ <figure title="HEADERS Frame Payload">
+ <artwork type="inline"><![CDATA[
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ |Pad Length? (8)|
+ +-+-------------+-----------------------------------------------+
+ |E| Stream Dependency? (31) |
+ +-+-------------+-----------------------------------------------+
+ | Weight? (8) |
+ +-+-------------+-----------------------------------------------+
+ | Header Block Fragment (*) ...
+ +---------------------------------------------------------------+
+ | Padding (*) ...
+ +---------------------------------------------------------------+
+]]></artwork>
+ </figure>
+ <t>
+ The HEADERS frame payload has the following fields:
+ <list style="hanging">
+ <t hangText="Pad Length:">
+ An 8-bit field containing the length of the frame padding in units of octets. This
+ field is only present if the PADDED flag is set.
+ </t>
+ <t hangText="E:">
+ A single bit flag indicates that the stream dependency is exclusive, see <xref
+ target="StreamPriority"/>. This field is only present if the PRIORITY flag is set.
+ </t>
+ <t hangText="Stream Dependency:">
+ A 31-bit stream identifier for the stream that this stream depends on, see <xref
+ target="StreamPriority"/>. This field is only present if the PRIORITY flag is set.
+ </t>
+ <t hangText="Weight:">
+ An 8-bit weight for the stream, see <xref target="StreamPriority"/>. Add one to the
+ value to obtain a weight between 1 and 256. This field is only present if the
+ PRIORITY flag is set.
+ </t>
+ <t hangText="Header Block Fragment:">
+ A <xref target="HeaderBlock">header block fragment</xref>.
+ </t>
+ <t hangText="Padding:">
+ Padding octets that contain no application semantic value. Padding octets MUST be set
+ to zero when sending and ignored when receiving.
+ </t>
+ </list>
+ </t>
+
+ <t>
+ The HEADERS frame defines the following flags:
+ <list style="hanging">
+ <x:lt hangText="END_STREAM (0x1):">
+ <t>
+ Bit 1 being set indicates that the <xref target="HeaderBlock">header block</xref> is
+ the last that the endpoint will send for the identified stream. Setting this flag
+ causes the stream to enter one of <xref target="StreamStates">"half closed"
+ states</xref>.
+ </t>
+ <t>
+ A HEADERS frame carries the END_STREAM flag that signals the end of a stream.
+ However, a HEADERS frame with the END_STREAM flag set can be followed by
+ <x:ref>CONTINUATION</x:ref> frames on the same stream. Logically, the
+ <x:ref>CONTINUATION</x:ref> frames are part of the HEADERS frame.
+ </t>
+ </x:lt>
+ <x:lt hangText="END_HEADERS (0x4):">
+ <t>
+ Bit 3 being set indicates that this frame contains an entire <xref
+ target="HeaderBlock">header block</xref> and is not followed by any
+ <x:ref>CONTINUATION</x:ref> frames.
+ </t>
+ <t>
+ A HEADERS frame without the END_HEADERS flag set MUST be followed by a
+ <x:ref>CONTINUATION</x:ref> frame for the same stream. A receiver MUST treat the
+ receipt of any other type of frame or a frame on a different stream as a <xref
+ target="ConnectionErrorHandler">connection error</xref> of type
+ <x:ref>PROTOCOL_ERROR</x:ref>.
+ </t>
+ </x:lt>
+ <x:lt hangText="PADDED (0x8):">
+ <t>
+ Bit 4 being set indicates that the Pad Length field and any padding that it
+ describes is present.
+ </t>
+ </x:lt>
+ <x:lt hangText="PRIORITY (0x20):">
+ <t>
+ Bit 6 being set indicates that the Exclusive Flag (E), Stream Dependency, and Weight
+ fields are present; see <xref target="StreamPriority"/>.
+ </t>
+ </x:lt>
+ </list>
+ </t>
+
+ <t>
+ The payload of a HEADERS frame contains a <xref target="HeaderBlock">header block
+ fragment</xref>. A header block that does not fit within a HEADERS frame is continued in
+ a <xref target="CONTINUATION">CONTINUATION frame</xref>.
+ </t>
+
+ <t>
+ HEADERS frames MUST be associated with a stream. If a HEADERS frame is received whose
+ stream identifier field is 0x0, the recipient MUST respond with a <xref
+ target="ConnectionErrorHandler">connection error</xref> of type
+ <x:ref>PROTOCOL_ERROR</x:ref>.
+ </t>
+
+ <t>
+ The HEADERS frame changes the connection state as described in <xref
+ target="HeaderBlock"/>.
+ </t>
+
+ <t>
+ The HEADERS frame includes optional padding. Padding fields and flags are identical to
+ those defined for <xref target="DATA">DATA frames</xref>.
+ </t>
+ <t>
+ Prioritization information in a HEADERS frame is logically equivalent to a separate
+ <x:ref>PRIORITY</x:ref> frame, but inclusion in HEADERS avoids the potential for churn in
+ stream prioritization when new streams are created. Priorization fields in HEADERS frames
+ subsequent to the first on a stream <xref target="reprioritize">reprioritize the
+ stream</xref>.
+ </t>
+ </section>
+
+ <section anchor="PRIORITY" title="PRIORITY">
+ <t>
+ The PRIORITY frame (type=0x2) specifies the <xref target="StreamPriority">sender-advised
+ priority of a stream</xref>. It can be sent at any time for an existing stream, including
+ closed streams. This enables reprioritization of existing streams.
+ </t>
+ <figure title="PRIORITY Frame Payload">
+ <artwork type="inline"><![CDATA[
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ |E| Stream Dependency (31) |
+ +-+-------------+-----------------------------------------------+
+ | Weight (8) |
+ +-+-------------+
+]]></artwork>
+ </figure>
+ <t>
+ The payload of a PRIORITY frame contains the following fields:
+ <list style="hanging">
+ <t hangText="E:">
+ A single bit flag indicates that the stream dependency is exclusive, see <xref
+ target="StreamPriority"/>.
+ </t>
+ <t hangText="Stream Dependency:">
+ A 31-bit stream identifier for the stream that this stream depends on, see <xref
+ target="StreamPriority"/>.
+ </t>
+ <t hangText="Weight:">
+ An 8-bit weight for the identified stream dependency, see <xref
+ target="StreamPriority"/>. Add one to the value to obtain a weight between 1 and 256.
+ </t>
+ </list>
+ </t>
+
+ <t>
+ The PRIORITY frame does not define any flags.
+ </t>
+
+ <t>
+ The PRIORITY frame is associated with an existing stream. If a PRIORITY frame is received
+ with a stream identifier of 0x0, the recipient MUST respond with a <xref
+ target="ConnectionErrorHandler">connection error</xref> of type
+ <x:ref>PROTOCOL_ERROR</x:ref>.
+ </t>
+ <t>
+ The PRIORITY frame can be sent on a stream in any of the "reserved (remote)", "open",
+ "half closed (local)", "half closed (remote)", or "closed" states, though it cannot be
+ sent between consecutive frames that comprise a single <xref target="HeaderBlock">header
+ block</xref>. Note that this frame could arrive after processing or frame sending has
+ completed, which would cause it to have no effect on the current stream. For a stream
+ that is in the "half closed (remote)" or "closed" - state, this frame can only affect
+ processing of the current stream and not frame transmission.
+ </t>
+ <t>
+ The PRIORITY frame is the only frame that can be sent for a stream in the "closed" state.
+ This allows for the reprioritization of a group of dependent streams by altering the
+ priority of a parent stream, which might be closed. However, a PRIORITY frame sent on a
+ closed stream risks being ignored due to the peer having discarded priority state
+ information for that stream.
+ </t>
+ </section>
+
+ <section anchor="RST_STREAM" title="RST_STREAM">
+ <t>
+ The RST_STREAM frame (type=0x3) allows for abnormal termination of a stream. When sent by
+ the initiator of a stream, it indicates that they wish to cancel the stream or that an
+ error condition has occurred. When sent by the receiver of a stream, it indicates that
+ either the receiver is rejecting the stream, requesting that the stream be cancelled, or
+ that an error condition has occurred.
+ </t>
+ <figure title="RST_STREAM Frame Payload">
+ <artwork type="inline"><![CDATA[
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Error Code (32) |
+ +---------------------------------------------------------------+
+]]></artwork>
+ </figure>
+
+ <t>
+ The RST_STREAM frame contains a single unsigned, 32-bit integer identifying the <xref
+ target="ErrorCodes">error code</xref>. The error code indicates why the stream is being
+ terminated.
+ </t>
+
+ <t>
+ The RST_STREAM frame does not define any flags.
+ </t>
+
+ <t>
+ The RST_STREAM frame fully terminates the referenced stream and causes it to enter the
+ closed state. After receiving a RST_STREAM on a stream, the receiver MUST NOT send
+ additional frames for that stream, with the exception of <x:ref>PRIORITY</x:ref>. However,
+ after sending the RST_STREAM, the sending endpoint MUST be prepared to receive and process
+ additional frames sent on the stream that might have been sent by the peer prior to the
+ arrival of the RST_STREAM.
+ </t>
+
+ <t>
+ RST_STREAM frames MUST be associated with a stream. If a RST_STREAM frame is received
+ with a stream identifier of 0x0, the recipient MUST treat this as a <xref
+ target="ConnectionErrorHandler">connection error</xref> of type
+ <x:ref>PROTOCOL_ERROR</x:ref>.
+ </t>
+
+ <t>
+ RST_STREAM frames MUST NOT be sent for a stream in the "idle" state. If a RST_STREAM
+ frame identifying an idle stream is received, the recipient MUST treat this as a <xref
+ target="ConnectionErrorHandler">connection error</xref> of type
+ <x:ref>PROTOCOL_ERROR</x:ref>.
+ </t>
+
+ </section>
+
+ <section anchor="SETTINGS" title="SETTINGS">
+ <t>
+ The SETTINGS frame (type=0x4) conveys configuration parameters that affect how endpoints
+ communicate, such as preferences and constraints on peer behavior. The SETTINGS frame is
+ also used to acknowledge the receipt of those parameters. Individually, a SETTINGS
+ parameter can also be referred to as a "setting".
+ </t>
+ <t>
+ SETTINGS parameters are not negotiated; they describe characteristics of the sending peer,
+ which are used by the receiving peer. Different values for the same parameter can be
+ advertised by each peer. For example, a client might set a high initial flow control
+ window, whereas a server might set a lower value to conserve resources.
+ </t>
+
+ <t>
+ A SETTINGS frame MUST be sent by both endpoints at the start of a connection, and MAY be
+ sent at any other time by either endpoint over the lifetime of the connection.
+ Implementations MUST support all of the parameters defined by this specification.
+ </t>
+
+ <t>
+ Each parameter in a SETTINGS frame replaces any existing value for that parameter.
+ Parameters are processed in the order in which they appear, and a receiver of a SETTINGS
+ frame does not need to maintain any state other than the current value of its
+ parameters. Therefore, the value of a SETTINGS parameter is the last value that is seen by
+ a receiver.
+ </t>
+ <t>
+ SETTINGS parameters are acknowledged by the receiving peer. To enable this, the SETTINGS
+ frame defines the following flag:
+ <list style="hanging">
+ <t hangText="ACK (0x1):">
+ Bit 1 being set indicates that this frame acknowledges receipt and application of the
+ peer's SETTINGS frame. When this bit is set, the payload of the SETTINGS frame MUST
+ be empty. Receipt of a SETTINGS frame with the ACK flag set and a length field value
+ other than 0 MUST be treated as a <xref target="ConnectionErrorHandler">connection
+ error</xref> of type <x:ref>FRAME_SIZE_ERROR</x:ref>. For more info, see <xref
+ target="SettingsSync">Settings Synchronization</xref>.
+ </t>
+ </list>
+ </t>
+ <t>
+ SETTINGS frames always apply to a connection, never a single stream. The stream
+ identifier for a SETTINGS frame MUST be zero (0x0). If an endpoint receives a SETTINGS
+ frame whose stream identifier field is anything other than 0x0, the endpoint MUST respond
+ with a <xref target="ConnectionErrorHandler">connection error</xref> of type
+ <x:ref>PROTOCOL_ERROR</x:ref>.
+ </t>
+ <t>
+ The SETTINGS frame affects connection state. A badly formed or incomplete SETTINGS frame
+ MUST be treated as a <xref target="ConnectionErrorHandler">connection error</xref> of type
+ <x:ref>PROTOCOL_ERROR</x:ref>.
+ </t>
+
+ <section title="SETTINGS Format" anchor="SettingFormat">
+ <t>
+ The payload of a SETTINGS frame consists of zero or more parameters, each consisting of
+ an unsigned 16-bit setting identifier and an unsigned 32-bit value.
+ </t>
+
+ <figure title="Setting Format">
+ <artwork type="inline"><![CDATA[
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Identifier (16) |
+ +-------------------------------+-------------------------------+
+ | Value (32) |
+ +---------------------------------------------------------------+
+]]></artwork>
+ </figure>
+ </section>
+
+ <section anchor="SettingValues" title="Defined SETTINGS Parameters">
+ <t>
+ The following parameters are defined:
+ <list style="hanging">
+ <x:lt hangText="SETTINGS_HEADER_TABLE_SIZE (0x1):"
+ anchor="SETTINGS_HEADER_TABLE_SIZE">
+ <t>
+ Allows the sender to inform the remote endpoint of the maximum size of the header
+ compression table used to decode header blocks, in octets. The encoder can select
+ any size equal to or less than this value by using signaling specific to the
+ header compression format inside a header block. The initial value is 4,096
+ octets.
+ </t>
+ </x:lt>
+ <x:lt hangText="SETTINGS_ENABLE_PUSH (0x2):"
+ anchor="SETTINGS_ENABLE_PUSH">
+ <t>
+ This setting can be use to disable <xref target="PushResources">server
+ push</xref>. An endpoint MUST NOT send a <x:ref>PUSH_PROMISE</x:ref> frame if it
+ receives this parameter set to a value of 0. An endpoint that has both set this
+ parameter to 0 and had it acknowledged MUST treat the receipt of a
+ <x:ref>PUSH_PROMISE</x:ref> frame as a <xref
+ target="ConnectionErrorHandler">connection error</xref> of type
+ <x:ref>PROTOCOL_ERROR</x:ref>.
+ </t>
+ <t>
+ The initial value is 1, which indicates that server push is permitted. Any value
+ other than 0 or 1 MUST be treated as a <xref
+ target="ConnectionErrorHandler">connection error</xref> of type
+ <x:ref>PROTOCOL_ERROR</x:ref>.
+ </t>
+ </x:lt>
+ <x:lt hangText="SETTINGS_MAX_CONCURRENT_STREAMS (0x3):"
+ anchor="SETTINGS_MAX_CONCURRENT_STREAMS">
+ <t>
+ Indicates the maximum number of concurrent streams that the sender will allow.
+ This limit is directional: it applies to the number of streams that the sender
+ permits the receiver to create. Initially there is no limit to this value. It is
+ recommended that this value be no smaller than 100, so as to not unnecessarily
+ limit parallelism.
+ </t>
+ <t>
+ A value of 0 for SETTINGS_MAX_CONCURRENT_STREAMS SHOULD NOT be treated as special
+ by endpoints. A zero value does prevent the creation of new streams, however this
+ can also happen for any limit that is exhausted with active streams. Servers
+ SHOULD only set a zero value for short durations; if a server does not wish to
+ accept requests, closing the connection could be preferable.
+ </t>
+ </x:lt>
+ <x:lt hangText="SETTINGS_INITIAL_WINDOW_SIZE (0x4):"
+ anchor="SETTINGS_INITIAL_WINDOW_SIZE">
+ <t>
+ Indicates the sender's initial window size (in octets) for stream level flow
+ control. The initial value is 2<x:sup>16</x:sup>-1 (65,535) octets.
+ </t>
+ <t>
+ This setting affects the window size of all streams, including existing streams,
+ see <xref target="InitialWindowSize"/>.
+ </t>
+ <t>
+ Values above the maximum flow control window size of 2<x:sup>31</x:sup>-1 MUST
+ be treated as a <xref target="ConnectionErrorHandler">connection error</xref> of
+ type <x:ref>FLOW_CONTROL_ERROR</x:ref>.
+ </t>
+ </x:lt>
+ <x:lt hangText="SETTINGS_MAX_FRAME_SIZE (0x5):"
+ anchor="SETTINGS_MAX_FRAME_SIZE">
+ <t>
+ Indicates the size of the largest frame payload that the sender is willing to
+ receive, in octets.
+ </t>
+ <t>
+ The initial value is 2<x:sup>14</x:sup> (16,384) octets. The value advertised by
+ an endpoint MUST be between this initial value and the maximum allowed frame size
+ (2<x:sup>24</x:sup>-1 or 16,777,215 octets), inclusive. Values outside this range
+ MUST be treated as a <xref target="ConnectionErrorHandler">connection error</xref>
+ of type <x:ref>PROTOCOL_ERROR</x:ref>.
+ </t>
+ </x:lt>
+ <x:lt hangText="SETTINGS_MAX_HEADER_LIST_SIZE (0x6):"
+ anchor="SETTINGS_MAX_HEADER_LIST_SIZE">
+ <t>
+ This advisory setting informs a peer of the maximum size of header list that the
+ sender is prepared to accept, in octets. The value is based on the uncompressed
+ size of header fields, including the length of the name and value in octets plus
+ an overhead of 32 octets for each header field.
+ </t>
+ <t>
+ For any given request, a lower limit than what is advertised MAY be enforced. The
+ initial value of this setting is unlimited.
+ </t>
+ </x:lt>
+ </list>
+ </t>
+ <t>
+ An endpoint that receives a SETTINGS frame with any unknown or unsupported identifier
+ MUST ignore that setting.
+ </t>
+ </section>
+
+ <section anchor="SettingsSync" title="Settings Synchronization">
+ <t>
+ Most values in SETTINGS benefit from or require an understanding of when the peer has
+ received and applied the changed parameter values. In order to provide
+ such synchronization timepoints, the recipient of a SETTINGS frame in which the ACK flag
+ is not set MUST apply the updated parameters as soon as possible upon receipt.
+ </t>
+ <t>
+ The values in the SETTINGS frame MUST be processed in the order they appear, with no
+ other frame processing between values. Unsupported parameters MUST be ignored. Once
+ all values have been processed, the recipient MUST immediately emit a SETTINGS frame
+ with the ACK flag set. Upon receiving a SETTINGS frame with the ACK flag set, the sender
+ of the altered parameters can rely on the setting having been applied.
+ </t>
+ <t>
+ If the sender of a SETTINGS frame does not receive an acknowledgement within a
+ reasonable amount of time, it MAY issue a <xref
+ target="ConnectionErrorHandler">connection error</xref> of type
+ <x:ref>SETTINGS_TIMEOUT</x:ref>.
+ </t>
+ </section>
+ </section>
+
+ <section anchor="PUSH_PROMISE" title="PUSH_PROMISE">
+ <t>
+ The PUSH_PROMISE frame (type=0x5) is used to notify the peer endpoint in advance of
+ streams the sender intends to initiate. The PUSH_PROMISE frame includes the unsigned
+ 31-bit identifier of the stream the endpoint plans to create along with a set of headers
+ that provide additional context for the stream. <xref target="PushResources"/> contains a
+ thorough description of the use of PUSH_PROMISE frames.
+ </t>
+
+ <figure title="PUSH_PROMISE Payload Format">
+ <artwork type="inline"><![CDATA[
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ |Pad Length? (8)|
+ +-+-------------+-----------------------------------------------+
+ |R| Promised Stream ID (31) |
+ +-+-----------------------------+-------------------------------+
+ | Header Block Fragment (*) ...
+ +---------------------------------------------------------------+
+ | Padding (*) ...
+ +---------------------------------------------------------------+
+]]></artwork>
+ </figure>
+ <t>
+ The PUSH_PROMISE frame payload has the following fields:
+ <list style="hanging">
+ <t hangText="Pad Length:">
+ An 8-bit field containing the length of the frame padding in units of octets. This
+ field is only present if the PADDED flag is set.
+ </t>
+ <t hangText="R:">
+ A single reserved bit.
+ </t>
+ <t hangText="Promised Stream ID:">
+ An unsigned 31-bit integer that identifies the stream that is reserved by the
+ PUSH_PROMISE. The promised stream identifier MUST be a valid choice for the next
+ stream sent by the sender (see <xref target="StreamIdentifiers">new stream
+ identifier</xref>).
+ </t>
+ <t hangText="Header Block Fragment:">
+ A <xref target="HeaderBlock">header block fragment</xref> containing request header
+ fields.
+ </t>
+ <t hangText="Padding:">
+ Padding octets.
+ </t>
+ </list>
+ </t>
+
+ <t>
+ The PUSH_PROMISE frame defines the following flags:
+ <list style="hanging">
+ <x:lt hangText="END_HEADERS (0x4):">
+ <t>
+ Bit 3 being set indicates that this frame contains an entire <xref
+ target="HeaderBlock">header block</xref> and is not followed by any
+ <x:ref>CONTINUATION</x:ref> frames.
+ </t>
+ <t>
+ A PUSH_PROMISE frame without the END_HEADERS flag set MUST be followed by a
+ CONTINUATION frame for the same stream. A receiver MUST treat the receipt of any
+ other type of frame or a frame on a different stream as a <xref
+ target="ConnectionErrorHandler">connection error</xref> of type
+ <x:ref>PROTOCOL_ERROR</x:ref>.
+ </t>
+ </x:lt>
+ <x:lt hangText="PADDED (0x8):">
+ <t>
+ Bit 4 being set indicates that the Pad Length field and any padding that it
+ describes is present.
+ </t>
+ </x:lt>
+ </list>
+ </t>
+
+ <t>
+ PUSH_PROMISE frames MUST be associated with an existing, peer-initiated stream. The stream
+ identifier of a PUSH_PROMISE frame indicates the stream it is associated with. If the
+ stream identifier field specifies the value 0x0, a recipient MUST respond with a <xref
+ target="ConnectionErrorHandler">connection error</xref> of type
+ <x:ref>PROTOCOL_ERROR</x:ref>.
+ </t>
+
+ <t>
+ Promised streams are not required to be used in the order they are promised. The
+ PUSH_PROMISE only reserves stream identifiers for later use.
+ </t>
+
+ <t>
+ PUSH_PROMISE MUST NOT be sent if the <x:ref>SETTINGS_ENABLE_PUSH</x:ref> setting of the
+ peer endpoint is set to 0. An endpoint that has set this setting and has received
+ acknowledgement MUST treat the receipt of a PUSH_PROMISE frame as a <xref
+ target="ConnectionErrorHandler">connection error</xref> of type
+ <x:ref>PROTOCOL_ERROR</x:ref>.
+ </t>
+ <t>
+ Recipients of PUSH_PROMISE frames can choose to reject promised streams by returning a
+ <x:ref>RST_STREAM</x:ref> referencing the promised stream identifier back to the sender of
+ the PUSH_PROMISE.
+ </t>
+
+ <t>
+ A PUSH_PROMISE frame modifies the connection state in two ways. The inclusion of a <xref
+ target="HeaderBlock">header block</xref> potentially modifies the state maintained for
+ header compression. PUSH_PROMISE also reserves a stream for later use, causing the
+ promised stream to enter the "reserved" state. A sender MUST NOT send a PUSH_PROMISE on a
+ stream unless that stream is either "open" or "half closed (remote)"; the sender MUST
+ ensure that the promised stream is a valid choice for a <xref
+ target="StreamIdentifiers">new stream identifier</xref> (that is, the promised stream MUST
+ be in the "idle" state).
+ </t>
+ <t>
+ Since PUSH_PROMISE reserves a stream, ignoring a PUSH_PROMISE frame causes the stream
+ state to become indeterminate. A receiver MUST treat the receipt of a PUSH_PROMISE on a
+ stream that is neither "open" nor "half closed (local)" as a <xref
+ target="ConnectionErrorHandler">connection error</xref> of type
+ <x:ref>PROTOCOL_ERROR</x:ref>. However, an endpoint that has sent
+ <x:ref>RST_STREAM</x:ref> on the associated stream MUST handle PUSH_PROMISE frames that
+ might have been created before the <x:ref>RST_STREAM</x:ref> frame is received and
+ processed.
+ </t>
+ <t>
+ A receiver MUST treat the receipt of a PUSH_PROMISE that promises an <xref
+ target="StreamIdentifiers">illegal stream identifier</xref> (that is, an identifier for a
+ stream that is not currently in the "idle" state) as a <xref
+ target="ConnectionErrorHandler">connection error</xref> of type
+ <x:ref>PROTOCOL_ERROR</x:ref>.
+ </t>
+
+ <t>
+ The PUSH_PROMISE frame includes optional padding. Padding fields and flags are identical
+ to those defined for <xref target="DATA">DATA frames</xref>.
+ </t>
+ </section>
+
+ <section anchor="PING" title="PING">
+ <t>
+ The PING frame (type=0x6) is a mechanism for measuring a minimal round trip time from the
+ sender, as well as determining whether an idle connection is still functional. PING
+ frames can be sent from any endpoint.
+ </t>
+ <figure title="PING Payload Format">
+ <artwork type="inline"><![CDATA[
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ | Opaque Data (64) |
+ | |
+ +---------------------------------------------------------------+
+]]></artwork>
+ </figure>
+
+ <t>
+ In addition to the frame header, PING frames MUST contain 8 octets of data in the payload.
+ A sender can include any value it chooses and use those bytes in any fashion.
+ </t>
+ <t>
+ Receivers of a PING frame that does not include an ACK flag MUST send a PING frame with
+ the ACK flag set in response, with an identical payload. PING responses SHOULD be given
+ higher priority than any other frame.
+ </t>
+
+ <t>
+ The PING frame defines the following flags:
+ <list style="hanging">
+ <t hangText="ACK (0x1):">
+ Bit 1 being set indicates that this PING frame is a PING response. An endpoint MUST
+ set this flag in PING responses. An endpoint MUST NOT respond to PING frames
+ containing this flag.
+ </t>
+ </list>
+ </t>
+ <t>
+ PING frames are not associated with any individual stream. If a PING frame is received
+ with a stream identifier field value other than 0x0, the recipient MUST respond with a
+ <xref target="ConnectionErrorHandler">connection error</xref> of type
+ <x:ref>PROTOCOL_ERROR</x:ref>.
+ </t>
+ <t>
+ Receipt of a PING frame with a length field value other than 8 MUST be treated as a <xref
+ target="ConnectionErrorHandler">connection error</xref> of type
+ <x:ref>FRAME_SIZE_ERROR</x:ref>.
+ </t>
+
+ </section>
+
+ <section anchor="GOAWAY" title="GOAWAY">
+ <t>
+ The GOAWAY frame (type=0x7) informs the remote peer to stop creating streams on this
+ connection. GOAWAY can be sent by either the client or the server. Once sent, the sender
+ will ignore frames sent on any new streams with identifiers higher than the included last
+ stream identifier. Receivers of a GOAWAY frame MUST NOT open additional streams on the
+ connection, although a new connection can be established for new streams.
+ </t>
+ <t>
+ The purpose of this frame is to allow an endpoint to gracefully stop accepting new
+ streams, while still finishing processing of previously established streams. This enables
+ administrative actions, like server maintainance.
+ </t>
+ <t>
+ There is an inherent race condition between an endpoint starting new streams and the
+ remote sending a GOAWAY frame. To deal with this case, the GOAWAY contains the stream
+ identifier of the last peer-initiated stream which was or might be processed on the
+ sending endpoint in this connection. For instance, if the server sends a GOAWAY frame,
+ the identified stream is the highest numbered stream initiated by the client.
+ </t>
+ <t>
+ If the receiver of the GOAWAY has sent data on streams with a higher stream identifier
+ than what is indicated in the GOAWAY frame, those streams are not or will not be
+ processed. The receiver of the GOAWAY frame can treat the streams as though they had
+ never been created at all, thereby allowing those streams to be retried later on a new
+ connection.
+ </t>
+ <t>
+ Endpoints SHOULD always send a GOAWAY frame before closing a connection so that the remote
+ can know whether a stream has been partially processed or not. For example, if an HTTP
+ client sends a POST at the same time that a server closes a connection, the client cannot
+ know if the server started to process that POST request if the server does not send a
+ GOAWAY frame to indicate what streams it might have acted on.
+ </t>
+ <t>
+ An endpoint might choose to close a connection without sending GOAWAY for misbehaving
+ peers.
+ </t>
+
+ <figure title="GOAWAY Payload Format">
+ <artwork type="inline"><![CDATA[
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ |R| Last-Stream-ID (31) |
+ +-+-------------------------------------------------------------+
+ | Error Code (32) |
+ +---------------------------------------------------------------+
+ | Additional Debug Data (*) |
+ +---------------------------------------------------------------+
+]]></artwork>
+ </figure>
+ <t>
+ The GOAWAY frame does not define any flags.
+ </t>
+ <t>
+ The GOAWAY frame applies to the connection, not a specific stream. An endpoint MUST treat
+ a <x:ref>GOAWAY</x:ref> frame with a stream identifier other than 0x0 as a <xref
+ target="ConnectionErrorHandler">connection error</xref> of type
+ <x:ref>PROTOCOL_ERROR</x:ref>.
+ </t>
+ <t>
+ The last stream identifier in the GOAWAY frame contains the highest numbered stream
+ identifier for which the sender of the GOAWAY frame might have taken some action on, or
+ might yet take action on. All streams up to and including the identified stream might
+ have been processed in some way. The last stream identifier can be set to 0 if no streams
+ were processed.
+ <list style="hanging">
+ <t hangText="Note:">
+ In this context, "processed" means that some data from the stream was passed to some
+ higher layer of software that might have taken some action as a result.
+ </t>
+ </list>
+ If a connection terminates without a GOAWAY frame, the last stream identifier is
+ effectively the highest possible stream identifier.
+ </t>
+ <t>
+ On streams with lower or equal numbered identifiers that were not closed completely prior
+ to the connection being closed, re-attempting requests, transactions, or any protocol
+ activity is not possible, with the exception of idempotent actions like HTTP GET, PUT, or
+ DELETE. Any protocol activity that uses higher numbered streams can be safely retried
+ using a new connection.
+ </t>
+ <t>
+ Activity on streams numbered lower or equal to the last stream identifier might still
+ complete successfully. The sender of a GOAWAY frame might gracefully shut down a
+ connection by sending a GOAWAY frame, maintaining the connection in an open state until
+ all in-progress streams complete.
+ </t>
+ <t>
+ An endpoint MAY send multiple GOAWAY frames if circumstances change. For instance, an
+ endpoint that sends GOAWAY with <x:ref>NO_ERROR</x:ref> during graceful shutdown could
+ subsequently encounter an condition that requires immediate termination of the connection.
+ The last stream identifier from the last GOAWAY frame received indicates which streams
+ could have been acted upon. Endpoints MUST NOT increase the value they send in the last
+ stream identifier, since the peers might already have retried unprocessed requests on
+ another connection.
+ </t>
+ <t>
+ A client that is unable to retry requests loses all requests that are in flight when the
+ server closes the connection. This is especially true for intermediaries that might
+ not be serving clients using HTTP/2. A server that is attempting to gracefully shut down
+ a connection SHOULD send an initial GOAWAY frame with the last stream identifier set to
+ 2<x:sup>31</x:sup>-1 and a <x:ref>NO_ERROR</x:ref> code. This signals to the client that
+ a shutdown is imminent and that no further requests can be initiated. After waiting at
+ least one round trip time, the server can send another GOAWAY frame with an updated last
+ stream identifier. This ensures that a connection can be cleanly shut down without losing
+ requests.
+ </t>
+
+ <t>
+ After sending a GOAWAY frame, the sender can discard frames for streams with identifiers
+ higher than the identified last stream. However, any frames that alter connection state
+ cannot be completely ignored. For instance, <x:ref>HEADERS</x:ref>,
+ <x:ref>PUSH_PROMISE</x:ref> and <x:ref>CONTINUATION</x:ref> frames MUST be minimally
+ processed to ensure the state maintained for header compression is consistent (see <xref
+ target="HeaderBlock"/>); similarly DATA frames MUST be counted toward the connection flow
+ control window. Failure to process these frames can cause flow control or header
+ compression state to become unsynchronized.
+ </t>
+
+ <t>
+ The GOAWAY frame also contains a 32-bit <xref target="ErrorCodes">error code</xref> that
+ contains the reason for closing the connection.
+ </t>
+ <t>
+ Endpoints MAY append opaque data to the payload of any GOAWAY frame. Additional debug
+ data is intended for diagnostic purposes only and carries no semantic value. Debug
+ information could contain security- or privacy-sensitive data. Logged or otherwise
+ persistently stored debug data MUST have adequate safeguards to prevent unauthorized
+ access.
+ </t>
+ </section>
+
+ <section anchor="WINDOW_UPDATE" title="WINDOW_UPDATE">
+ <t>
+ The WINDOW_UPDATE frame (type=0x8) is used to implement flow control; see <xref
+ target="FlowControl"/> for an overview.
+ </t>
+ <t>
+ Flow control operates at two levels: on each individual stream and on the entire
+ connection.
+ </t>
+ <t>
+ Both types of flow control are hop-by-hop; that is, only between the two endpoints.
+ Intermediaries do not forward WINDOW_UPDATE frames between dependent connections.
+ However, throttling of data transfer by any receiver can indirectly cause the propagation
+ of flow control information toward the original sender.
+ </t>
+ <t>
+ Flow control only applies to frames that are identified as being subject to flow control.
+ Of the frame types defined in this document, this includes only <x:ref>DATA</x:ref> frames.
+ Frames that are exempt from flow control MUST be accepted and processed, unless the
+ receiver is unable to assign resources to handling the frame. A receiver MAY respond with
+ a <xref target="StreamErrorHandler">stream error</xref> or <xref
+ target="ConnectionErrorHandler">connection error</xref> of type
+ <x:ref>FLOW_CONTROL_ERROR</x:ref> if it is unable to accept a frame.
+ </t>
+ <figure title="WINDOW_UPDATE Payload Format">
+ <artwork type="inline"><![CDATA[
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ |R| Window Size Increment (31) |
+ +-+-------------------------------------------------------------+
+]]></artwork>
+ </figure>
+ <t>
+ The payload of a WINDOW_UPDATE frame is one reserved bit, plus an unsigned 31-bit integer
+ indicating the number of octets that the sender can transmit in addition to the existing
+ flow control window. The legal range for the increment to the flow control window is 1 to
+ 2<x:sup>31</x:sup>-1 (0x7fffffff) octets.
+ </t>
+ <t>
+ The WINDOW_UPDATE frame does not define any flags.
+ </t>
+ <t>
+ The WINDOW_UPDATE frame can be specific to a stream or to the entire connection. In the
+ former case, the frame's stream identifier indicates the affected stream; in the latter,
+ the value "0" indicates that the entire connection is the subject of the frame.
+ </t>
+ <t>
+ A receiver MUST treat the receipt of a WINDOW_UPDATE frame with an flow control window
+ increment of 0 as a <xref target="StreamErrorHandler">stream error</xref> of type
+ <x:ref>PROTOCOL_ERROR</x:ref>; errors on the connection flow control window MUST be
+ treated as a <xref target="ConnectionErrorHandler">connection error</xref>.
+ </t>
+ <t>
+ WINDOW_UPDATE can be sent by a peer that has sent a frame bearing the END_STREAM flag.
+ This means that a receiver could receive a WINDOW_UPDATE frame on a "half closed (remote)"
+ or "closed" stream. A receiver MUST NOT treat this as an error, see <xref
+ target="StreamStates"/>.
+ </t>
+ <t>
+ A receiver that receives a flow controlled frame MUST always account for its contribution
+ against the connection flow control window, unless the receiver treats this as a <xref
+ target="ConnectionErrorHandler">connection error</xref>. This is necessary even if the
+ frame is in error. Since the sender counts the frame toward the flow control window, if
+ the receiver does not, the flow control window at sender and receiver can become
+ different.
+ </t>
+
+ <section title="The Flow Control Window">
+ <t>
+ Flow control in HTTP/2 is implemented using a window kept by each sender on every
+ stream. The flow control window is a simple integer value that indicates how many octets
+ of data the sender is permitted to transmit; as such, its size is a measure of the
+ buffering capacity of the receiver.
+ </t>
+ <t>
+ Two flow control windows are applicable: the stream flow control window and the
+ connection flow control window. The sender MUST NOT send a flow controlled frame with a
+ length that exceeds the space available in either of the flow control windows advertised
+ by the receiver. Frames with zero length with the END_STREAM flag set (that is, an
+ empty <x:ref>DATA</x:ref> frame) MAY be sent if there is no available space in either
+ flow control window.
+ </t>
+ <t>
+ For flow control calculations, the 9 octet frame header is not counted.
+ </t>
+ <t>
+ After sending a flow controlled frame, the sender reduces the space available in both
+ windows by the length of the transmitted frame.
+ </t>
+ <t>
+ The receiver of a frame sends a WINDOW_UPDATE frame as it consumes data and frees up
+ space in flow control windows. Separate WINDOW_UPDATE frames are sent for the stream
+ and connection level flow control windows.
+ </t>
+ <t>
+ A sender that receives a WINDOW_UPDATE frame updates the corresponding window by the
+ amount specified in the frame.
+ </t>
+ <t>
+ A sender MUST NOT allow a flow control window to exceed 2<x:sup>31</x:sup>-1 octets.
+ If a sender receives a WINDOW_UPDATE that causes a flow control window to exceed this
+ maximum it MUST terminate either the stream or the connection, as appropriate. For
+ streams, the sender sends a <x:ref>RST_STREAM</x:ref> with the error code of
+ <x:ref>FLOW_CONTROL_ERROR</x:ref> code; for the connection, a <x:ref>GOAWAY</x:ref>
+ frame with a <x:ref>FLOW_CONTROL_ERROR</x:ref> code.
+ </t>
+ <t>
+ Flow controlled frames from the sender and WINDOW_UPDATE frames from the receiver are
+ completely asynchronous with respect to each other. This property allows a receiver to
+ aggressively update the window size kept by the sender to prevent streams from stalling.
+ </t>
+ </section>
+
+ <section anchor="InitialWindowSize" title="Initial Flow Control Window Size">
+ <t>
+ When an HTTP/2 connection is first established, new streams are created with an initial
+ flow control window size of 65,535 octets. The connection flow control window is 65,535
+ octets. Both endpoints can adjust the initial window size for new streams by including
+ a value for <x:ref>SETTINGS_INITIAL_WINDOW_SIZE</x:ref> in the <x:ref>SETTINGS</x:ref>
+ frame that forms part of the connection preface. The connection flow control window can
+ only be changed using WINDOW_UPDATE frames.
+ </t>
+ <t>
+ Prior to receiving a <x:ref>SETTINGS</x:ref> frame that sets a value for
+ <x:ref>SETTINGS_INITIAL_WINDOW_SIZE</x:ref>, an endpoint can only use the default
+ initial window size when sending flow controlled frames. Similarly, the connection flow
+ control window is set to the default initial window size until a WINDOW_UPDATE frame is
+ received.
+ </t>
+ <t>
+ A <x:ref>SETTINGS</x:ref> frame can alter the initial flow control window size for all
+ current streams. When the value of <x:ref>SETTINGS_INITIAL_WINDOW_SIZE</x:ref> changes,
+ a receiver MUST adjust the size of all stream flow control windows that it maintains by
+ the difference between the new value and the old value.
+ </t>
+ <t>
+ A change to <x:ref>SETTINGS_INITIAL_WINDOW_SIZE</x:ref> can cause the available space in
+ a flow control window to become negative. A sender MUST track the negative flow control
+ window, and MUST NOT send new flow controlled frames until it receives WINDOW_UPDATE
+ frames that cause the flow control window to become positive.
+ </t>
+ <t>
+ For example, if the client sends 60KB immediately on connection establishment, and the
+ server sets the initial window size to be 16KB, the client will recalculate the
+ available flow control window to be -44KB on receipt of the <x:ref>SETTINGS</x:ref>
+ frame. The client retains a negative flow control window until WINDOW_UPDATE frames
+ restore the window to being positive, after which the client can resume sending.
+ </t>
+ <t>
+ A <x:ref>SETTINGS</x:ref> frame cannot alter the connection flow control window.
+ </t>
+ <t>
+ An endpoint MUST treat a change to <x:ref>SETTINGS_INITIAL_WINDOW_SIZE</x:ref> that
+ causes any flow control window to exceed the maximum size as a <xref
+ target="ConnectionErrorHandler">connection error</xref> of type
+ <x:ref>FLOW_CONTROL_ERROR</x:ref>.
+ </t>
+ </section>
+
+ <section title="Reducing the Stream Window Size">
+ <t>
+ A receiver that wishes to use a smaller flow control window than the current size can
+ send a new <x:ref>SETTINGS</x:ref> frame. However, the receiver MUST be prepared to
+ receive data that exceeds this window size, since the sender might send data that
+ exceeds the lower limit prior to processing the <x:ref>SETTINGS</x:ref> frame.
+ </t>
+ <t>
+ After sending a SETTINGS frame that reduces the initial flow control window size, a
+ receiver has two options for handling streams that exceed flow control limits:
+ <list style="numbers">
+ <t>
+ The receiver can immediately send <x:ref>RST_STREAM</x:ref> with
+ <x:ref>FLOW_CONTROL_ERROR</x:ref> error code for the affected streams.
+ </t>
+ <t>
+ The receiver can accept the streams and tolerate the resulting head of line
+ blocking, sending WINDOW_UPDATE frames as it consumes data.
+ </t>
+ </list>
+ </t>
+ </section>
+ </section>
+
+ <section anchor="CONTINUATION" title="CONTINUATION">
+ <t>
+ The CONTINUATION frame (type=0x9) is used to continue a sequence of <xref
+ target="HeaderBlock">header block fragments</xref>. Any number of CONTINUATION frames can
+ be sent on an existing stream, as long as the preceding frame is on the same stream and is
+ a <x:ref>HEADERS</x:ref>, <x:ref>PUSH_PROMISE</x:ref> or CONTINUATION frame without the
+ END_HEADERS flag set.
+ </t>
+
+ <figure title="CONTINUATION Frame Payload">
+ <artwork type="inline"><![CDATA[
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Header Block Fragment (*) ...
+ +---------------------------------------------------------------+
+]]></artwork>
+ </figure>
+ <t>
+ The CONTINUATION frame payload contains a <xref target="HeaderBlock">header block
+ fragment</xref>.
+ </t>
+
+ <t>
+ The CONTINUATION frame defines the following flag:
+ <list style="hanging">
+ <x:lt hangText="END_HEADERS (0x4):">
+ <t>
+ Bit 3 being set indicates that this frame ends a <xref target="HeaderBlock">header
+ block</xref>.
+ </t>
+ <t>
+ If the END_HEADERS bit is not set, this frame MUST be followed by another
+ CONTINUATION frame. A receiver MUST treat the receipt of any other type of frame or
+ a frame on a different stream as a <xref target="ConnectionErrorHandler">connection
+ error</xref> of type <x:ref>PROTOCOL_ERROR</x:ref>.
+ </t>
+ </x:lt>
+ </list>
+ </t>
+
+ <t>
+ The CONTINUATION frame changes the connection state as defined in <xref
+ target="HeaderBlock" />.
+ </t>
+
+ <t>
+ CONTINUATION frames MUST be associated with a stream. If a CONTINUATION frame is received
+ whose stream identifier field is 0x0, the recipient MUST respond with a <xref
+ target="ConnectionErrorHandler">connection error</xref> of type PROTOCOL_ERROR.
+ </t>
+
+ <t>
+ A CONTINUATION frame MUST be preceded by a <x:ref>HEADERS</x:ref>,
+ <x:ref>PUSH_PROMISE</x:ref> or CONTINUATION frame without the END_HEADERS flag set. A
+ recipient that observes violation of this rule MUST respond with a <xref
+ target="ConnectionErrorHandler"> connection error</xref> of type
+ <x:ref>PROTOCOL_ERROR</x:ref>.
+ </t>
+ </section>
+ </section>
+
+ <section anchor="ErrorCodes" title="Error Codes">
+ <t>
+ Error codes are 32-bit fields that are used in <x:ref>RST_STREAM</x:ref> and
+ <x:ref>GOAWAY</x:ref> frames to convey the reasons for the stream or connection error.
+ </t>
+
+ <t>
+ Error codes share a common code space. Some error codes apply only to either streams or the
+ entire connection and have no defined semantics in the other context.
+ </t>
+
+ <t>
+ The following error codes are defined:
+ <list style="hanging">
+ <t hangText="NO_ERROR (0x0):" anchor="NO_ERROR">
+ The associated condition is not as a result of an error. For example, a
+ <x:ref>GOAWAY</x:ref> might include this code to indicate graceful shutdown of a
+ connection.
+ </t>
+ <t hangText="PROTOCOL_ERROR (0x1):" anchor="PROTOCOL_ERROR">
+ The endpoint detected an unspecific protocol error. This error is for use when a more
+ specific error code is not available.
+ </t>
+ <t hangText="INTERNAL_ERROR (0x2):" anchor="INTERNAL_ERROR">
+ The endpoint encountered an unexpected internal error.
+ </t>
+ <t hangText="FLOW_CONTROL_ERROR (0x3):" anchor="FLOW_CONTROL_ERROR">
+ The endpoint detected that its peer violated the flow control protocol.
+ </t>
+ <t hangText="SETTINGS_TIMEOUT (0x4):" anchor="SETTINGS_TIMEOUT">
+ The endpoint sent a <x:ref>SETTINGS</x:ref> frame, but did not receive a response in a
+ timely manner. See <xref target="SettingsSync">Settings Synchronization</xref>.
+ </t>
+ <t hangText="STREAM_CLOSED (0x5):" anchor="STREAM_CLOSED">
+ The endpoint received a frame after a stream was half closed.
+ </t>
+ <t hangText="FRAME_SIZE_ERROR (0x6):" anchor="FRAME_SIZE_ERROR">
+ The endpoint received a frame with an invalid size.
+ </t>
+ <t hangText="REFUSED_STREAM (0x7):" anchor="REFUSED_STREAM">
+ The endpoint refuses the stream prior to performing any application processing, see
+ <xref target="Reliability"/> for details.
+ </t>
+ <t hangText="CANCEL (0x8):" anchor="CANCEL">
+ Used by the endpoint to indicate that the stream is no longer needed.
+ </t>
+ <t hangText="COMPRESSION_ERROR (0x9):" anchor="COMPRESSION_ERROR">
+ The endpoint is unable to maintain the header compression context for the connection.
+ </t>
+ <t hangText="CONNECT_ERROR (0xa):" anchor="CONNECT_ERROR">
+ The connection established in response to a <xref target="CONNECT">CONNECT
+ request</xref> was reset or abnormally closed.
+ </t>
+ <t hangText="ENHANCE_YOUR_CALM (0xb):" anchor="ENHANCE_YOUR_CALM">
+ The endpoint detected that its peer is exhibiting a behavior that might be generating
+ excessive load.
+ </t>
+ <t hangText="INADEQUATE_SECURITY (0xc):" anchor="INADEQUATE_SECURITY">
+ The underlying transport has properties that do not meet minimum security
+ requirements (see <xref target="TLSUsage"/>).
+ </t>
+ </list>
+ </t>
+ <t>
+ Unknown or unsupported error codes MUST NOT trigger any special behavior. These MAY be
+ treated by an implementation as being equivalent to <x:ref>INTERNAL_ERROR</x:ref>.
+ </t>
+ </section>
+
+ <section anchor="HTTPLayer" title="HTTP Message Exchanges">
+ <t>
+ HTTP/2 is intended to be as compatible as possible with current uses of HTTP. This means
+ that, from the application perspective, the features of the protocol are largely
+ unchanged. To achieve this, all request and response semantics are preserved, although the
+ syntax of conveying those semantics has changed.
+ </t>
+ <t>
+ Thus, the specification and requirements of HTTP/1.1 Semantics and Content <xref
+ target="RFC7231"/>, Conditional Requests <xref target="RFC7232"/>, Range Requests <xref
+ target="RFC7233"/>, Caching <xref target="RFC7234"/> and Authentication <xref
+ target="RFC7235"/> are applicable to HTTP/2. Selected portions of HTTP/1.1 Message Syntax
+ and Routing <xref target="RFC7230"/>, such as the HTTP and HTTPS URI schemes, are also
+ applicable in HTTP/2, but the expression of those semantics for this protocol are defined
+ in the sections below.
+ </t>
+
+ <section anchor="HttpSequence" title="HTTP Request/Response Exchange">
+ <t>
+ A client sends an HTTP request on a new stream, using a previously unused <xref
+ target="StreamIdentifiers">stream identifier</xref>. A server sends an HTTP response on
+ the same stream as the request.
+ </t>
+ <t>
+ An HTTP message (request or response) consists of:
+ <list style="numbers">
+ <t>
+ for a response only, zero or more <x:ref>HEADERS</x:ref> frames (each followed by zero
+ or more <x:ref>CONTINUATION</x:ref> frames) containing the message headers of
+ informational (1xx) HTTP responses (see <xref target="RFC7230" x:fmt=","
+ x:rel="#header.fields"/> and <xref target="RFC7231" x:fmt="," x:rel="#status.1xx"/>),
+ and
+ </t>
+ <t>
+ one <x:ref>HEADERS</x:ref> frame (followed by zero or more <x:ref>CONTINUATION</x:ref>
+ frames) containing the message headers (see <xref target="RFC7230" x:fmt=","
+ x:rel="#header.fields"/>), and
+ </t>
+ <t>
+ zero or more <x:ref>DATA</x:ref> frames containing the message payload (see <xref
+ target="RFC7230" x:fmt="," x:rel="#message.body"/>), and
+ </t>
+ <t>
+ optionally, one <x:ref>HEADERS</x:ref> frame, followed by zero or more
+ <x:ref>CONTINUATION</x:ref> frames containing the trailer-part, if present (see <xref
+ target="RFC7230" x:fmt="," x:rel="#chunked.trailer.part"/>).
+ </t>
+ </list>
+ The last frame in the sequence bears an END_STREAM flag, noting that a
+ <x:ref>HEADERS</x:ref> frame bearing the END_STREAM flag can be followed by
+ <x:ref>CONTINUATION</x:ref> frames that carry any remaining portions of the header block.
+ </t>
+ <t>
+ Other frames (from any stream) MUST NOT occur between either <x:ref>HEADERS</x:ref> frame
+ and any <x:ref>CONTINUATION</x:ref> frames that might follow.
+ </t>
+
+ <t>
+ Trailing header fields are carried in a header block that also terminates the stream.
+ That is, a sequence starting with a <x:ref>HEADERS</x:ref> frame, followed by zero or more
+ <x:ref>CONTINUATION</x:ref> frames, where the <x:ref>HEADERS</x:ref> frame bears an
+ END_STREAM flag. Header blocks after the first that do not terminate the stream are not
+ part of an HTTP request or response.
+ </t>
+ <t>
+ A <x:ref>HEADERS</x:ref> frame (and associated <x:ref>CONTINUATION</x:ref> frames) can
+ only appear at the start or end of a stream. An endpoint that receives a
+ <x:ref>HEADERS</x:ref> frame without the END_STREAM flag set after receiving a final
+ (non-informational) status code MUST treat the corresponding request or response as <xref
+ target="malformed">malformed</xref>.
+ </t>
+
+ <t>
+ An HTTP request/response exchange fully consumes a single stream. A request starts with
+ the <x:ref>HEADERS</x:ref> frame that puts the stream into an "open" state. The request
+ ends with a frame bearing END_STREAM, which causes the stream to become "half closed
+ (local)" for the client and "half closed (remote)" for the server. A response starts with
+ a <x:ref>HEADERS</x:ref> frame and ends with a frame bearing END_STREAM, which places the
+ stream in the "closed" state.
+ <!-- Yes, the response might be completed before the request does, but that's not a detail
+ we need to expand upon. It's complicated enough explaining this as it is. -->
+ </t>
+
+ <section anchor="informational-responses" title="Upgrading From HTTP/2">
+ <t>
+ HTTP/2 removes support for the 101 (Switching Protocols) informational status code
+ (<xref target="RFC7231" x:fmt="," x:rel="#status.101"/>).
+ </t>
+ <t>
+ The semantics of 101 (Switching Protocols) aren't applicable to a multiplexed protocol.
+ Alternative protocols are able to use the same mechanisms that HTTP/2 uses to negotiate
+ their use (see <xref target="starting"/>).
+ </t>
+ </section>
+
+ <section anchor="HttpHeaders" title="HTTP Header Fields">
+ <t>
+ HTTP header fields carry information as a series of key-value pairs. For a listing of
+ registered HTTP headers, see the Message Header Field Registry maintained at <eref
+ target="https://www.iana.org/assignments/message-headers"/>.
+ </t>
+
+ <section anchor="PseudoHeaderFields" title="Pseudo-Header Fields">
+ <t>
+ While HTTP/1.x used the message start-line (see <xref target="RFC7230" x:fmt=","
+ x:rel="#start.line"/>) to convey the target URI and method of the request, and the
+ status code for the response, HTTP/2 uses special pseudo-header fields beginning with
+ ':' character (ASCII 0x3a) for this purpose.
+ </t>
+ <t>
+ Pseudo-header fields are not HTTP header fields. Endpoints MUST NOT generate
+ pseudo-header fields other than those defined in this document.
+ </t>
+ <t>
+ Pseudo-header fields are only valid in the context in which they are defined.
+ Pseudo-header fields defined for requests MUST NOT appear in responses; pseudo-header
+ fields defined for responses MUST NOT appear in requests. Pseudo-header fields MUST
+ NOT appear in trailers. Endpoints MUST treat a request or response that contains
+ undefined or invalid pseudo-header fields as <xref
+ target="malformed">malformed</xref>.
+ </t>
+ <t>
+ Just as in HTTP/1.x, header field names are strings of ASCII characters that are
+ compared in a case-insensitive fashion. However, header field names MUST be converted
+ to lowercase prior to their encoding in HTTP/2. A request or response containing
+ uppercase header field names MUST be treated as <xref
+ target="malformed">malformed</xref>.
+ </t>
+ <t>
+ All pseudo-header fields MUST appear in the header block before regular header fields.
+ Any request or response that contains a pseudo-header field that appears in a header
+ block after a regular header field MUST be treated as <xref
+ target="malformed">malformed</xref>.
+ </t>
+ </section>
+
+ <section title="Connection-Specific Header Fields">
+ <t>
+ HTTP/2 does not use the <spanx style="verb">Connection</spanx> header field to
+ indicate connection-specific header fields; in this protocol, connection-specific
+ metadata is conveyed by other means. An endpoint MUST NOT generate a HTTP/2 message
+ containing connection-specific header fields; any message containing
+ connection-specific header fields MUST be treated as <xref
+ target="malformed">malformed</xref>.
+ </t>
+ <t>
+ This means that an intermediary transforming an HTTP/1.x message to HTTP/2 will need
+ to remove any header fields nominated by the Connection header field, along with the
+ Connection header field itself. Such intermediaries SHOULD also remove other
+ connection-specific header fields, such as Keep-Alive, Proxy-Connection,
+ Transfer-Encoding and Upgrade, even if they are not nominated by Connection.
+ </t>
+ <t>
+ One exception to this is the TE header field, which MAY be present in an HTTP/2
+ request, but when it is MUST NOT contain any value other than "trailers".
+ </t>
+ <t>
+ <list style="hanging">
+ <t hangText="Note:">
+ HTTP/2 purposefully does not support upgrade to another protocol. The handshake
+ methods described in <xref target="starting"/> are believed sufficient to
+ negotiate the use of alternative protocols.
+ </t>
+ </list>
+ </t>
+ </section>
+
+ <section anchor="HttpRequest" title="Request Pseudo-Header Fields">
+ <t>
+ The following pseudo-header fields are defined for HTTP/2 requests:
+ <list style="symbols">
+ <x:lt>
+ <t>
+ The <spanx style="verb">:method</spanx> pseudo-header field includes the HTTP
+ method (<xref target="RFC7231" x:fmt="," x:rel="#methods"/>).
+ </t>
+ </x:lt>
+ <x:lt>
+ <t>
+ The <spanx style="verb">:scheme</spanx> pseudo-header field includes the scheme
+ portion of the target URI (<xref target="RFC3986" x:fmt="," x:sec="3.1"/>).
+ </t>
+ <t>
+ <spanx style="verb">:scheme</spanx> is not restricted to <spanx
+ style="verb">http</spanx> and <spanx style="verb">https</spanx> schemed URIs. A
+ proxy or gateway can translate requests for non-HTTP schemes, enabling the use
+ of HTTP to interact with non-HTTP services.
+ </t>
+ </x:lt>
+ <x:lt>
+ <t>
+ The <spanx style="verb">:authority</spanx> pseudo-header field includes the
+ authority portion of the target URI (<xref target="RFC3986" x:fmt=","
+ x:sec="3.2"/>). The authority MUST NOT include the deprecated <spanx
+ style="verb">userinfo</spanx> subcomponent for <spanx style="verb">http</spanx>
+ or <spanx style="verb">https</spanx> schemed URIs.
+ </t>
+ <t>
+ To ensure that the HTTP/1.1 request line can be reproduced accurately, this
+ pseudo-header field MUST be omitted when translating from an HTTP/1.1 request
+ that has a request target in origin or asterisk form (see <xref
+ target="RFC7230" x:fmt="," x:rel="#request-target"/>). Clients that generate
+ HTTP/2 requests directly SHOULD use the <spanx>:authority</spanx> pseudo-header
+ field instead of the <spanx style="verb">Host</spanx> header field. An
+ intermediary that converts an HTTP/2 request to HTTP/1.1 MUST create a <spanx
+ style="verb">Host</spanx> header field if one is not present in a request by
+ copying the value of the <spanx style="verb">:authority</spanx> pseudo-header
+ field.
+ </t>
+ </x:lt>
+ <x:lt>
+ <t>
+ The <spanx style="verb">:path</spanx> pseudo-header field includes the path and
+ query parts of the target URI (the <spanx style="verb">path-absolute</spanx>
+ production from <xref target="RFC3986"/> and optionally a '?' character
+ followed by the <spanx style="verb">query</spanx> production, see <xref
+ target="RFC3986" x:fmt="," x:sec="3.3"/> and <xref target="RFC3986" x:fmt=","
+ x:sec="3.4"/>). A request in asterisk form includes the value '*' for the
+ <spanx style="verb">:path</spanx> pseudo-header field.
+ </t>
+ <t>
+ This pseudo-header field MUST NOT be empty for <spanx style="verb">http</spanx>
+ or <spanx style="verb">https</spanx> URIs; <spanx style="verb">http</spanx> or
+ <spanx style="verb">https</spanx> URIs that do not contain a path component
+ MUST include a value of '/'. The exception to this rule is an OPTIONS request
+ for an <spanx style="verb">http</spanx> or <spanx style="verb">https</spanx>
+ URI that does not include a path component; these MUST include a <spanx
+ style="verb">:path</spanx> pseudo-header field with a value of '*' (see <xref
+ target="RFC7230" x:fmt="," x:rel="#asterisk-form"/>).
+ </t>
+ </x:lt>
+ </list>
+ </t>
+ <t>
+ All HTTP/2 requests MUST include exactly one valid value for the <spanx
+ style="verb">:method</spanx>, <spanx style="verb">:scheme</spanx>, and <spanx
+ style="verb">:path</spanx> pseudo-header fields, unless it is a <xref
+ target="CONNECT">CONNECT request</xref>. An HTTP request that omits mandatory
+ pseudo-header fields is <xref target="malformed">malformed</xref>.
+ </t>
+ <t>
+ HTTP/2 does not define a way to carry the version identifier that is included in the
+ HTTP/1.1 request line.
+ </t>
+ </section>
+
+ <section anchor="HttpResponse" title="Response Pseudo-Header Fields">
+ <t>
+ For HTTP/2 responses, a single <spanx style="verb">:status</spanx> pseudo-header
+ field is defined that carries the HTTP status code field (see <xref target="RFC7231"
+ x:fmt="," x:rel="#status.codes"/>). This pseudo-header field MUST be included in all
+ responses, otherwise the response is <xref target="malformed">malformed</xref>.
+ </t>
+ <t>
+ HTTP/2 does not define a way to carry the version or reason phrase that is included in
+ an HTTP/1.1 status line.
+ </t>
+ </section>
+
+ <section anchor="CompressCookie" title="Compressing the Cookie Header Field">
+ <t>
+ The <xref target="COOKIE">Cookie header field</xref> can carry a significant amount of
+ redundant data.
+ </t>
+ <t>
+ The Cookie header field uses a semi-colon (";") to delimit cookie-pairs (or "crumbs").
+ This header field doesn't follow the list construction rules in HTTP (see <xref
+ target="RFC7230" x:fmt="," x:rel="#field.order"/>), which prevents cookie-pairs from
+ being separated into different name-value pairs. This can significantly reduce
+ compression efficiency as individual cookie-pairs are updated.
+ </t>
+ <t>
+ To allow for better compression efficiency, the Cookie header field MAY be split into
+ separate header fields, each with one or more cookie-pairs. If there are multiple
+ Cookie header fields after decompression, these MUST be concatenated into a single
+ octet string using the two octet delimiter of 0x3B, 0x20 (the ASCII string "; ")
+ before being passed into a non-HTTP/2 context, such as an HTTP/1.1 connection, or a
+ generic HTTP server application.
+ </t>
+ <figure>
+ <preamble>
+ Therefore, the following two lists of Cookie header fields are semantically
+ equivalent.
+ </preamble>
+ <artwork type="inline"><![CDATA[
+ cookie: a=b; c=d; e=f
+
+ cookie: a=b
+ cookie: c=d
+ cookie: e=f
+]]></artwork>
+ </figure>
+ </section>
+
+ <section anchor="malformed" title="Malformed Requests and Responses">
+ <t>
+ A malformed request or response is one that is an otherwise valid sequence of HTTP/2
+ frames, but is otherwise invalid due to the presence of extraneous frames, prohibited
+ header fields, the absence of mandatory header fields, or the inclusion of uppercase
+ header field names.
+ </t>
+ <t>
+ A request or response that includes an entity body can include a <spanx
+ style="verb">content-length</spanx> header field. A request or response is also
+ malformed if the value of a <spanx style="verb">content-length</spanx> header field
+ does not equal the sum of the <x:ref>DATA</x:ref> frame payload lengths that form the
+ body. A response that is defined to have no payload, as described in <xref
+ target="RFC7230" x:fmt="," x:rel="#header.content-length"/>, can have a non-zero
+ <spanx style="verb">content-length</spanx> header field, even though no content is
+ included in <x:ref>DATA</x:ref> frames.
+ </t>
+ <t>
+ Intermediaries that process HTTP requests or responses (i.e., any intermediary not
+ acting as a tunnel) MUST NOT forward a malformed request or response. Malformed
+ requests or responses that are detected MUST be treated as a <xref
+ target="StreamErrorHandler">stream error</xref> of type <x:ref>PROTOCOL_ERROR</x:ref>.
+ </t>
+ <t>
+ For malformed requests, a server MAY send an HTTP response prior to closing or
+ resetting the stream. Clients MUST NOT accept a malformed response. Note that these
+ requirements are intended to protect against several types of common attacks against
+ HTTP; they are deliberately strict, because being permissive can expose
+ implementations to these vulnerabilities.
+ </t>
+ </section>
+ </section>
+
+ <section title="Examples">
+ <t>
+ This section shows HTTP/1.1 requests and responses, with illustrations of equivalent
+ HTTP/2 requests and responses.
+ </t>
+ <t>
+ An HTTP GET request includes request header fields and no body and is therefore
+ transmitted as a single <x:ref>HEADERS</x:ref> frame, followed by zero or more
+ <x:ref>CONTINUATION</x:ref> frames containing the serialized block of request header
+ fields. The <x:ref>HEADERS</x:ref> frame in the following has both the END_HEADERS and
+ END_STREAM flags set; no <x:ref>CONTINUATION</x:ref> frames are sent:
+ </t>
+
+ <figure>
+ <artwork type="inline"><![CDATA[
+ GET /resource HTTP/1.1 HEADERS
+ Host: example.org ==> + END_STREAM
+ Accept: image/jpeg + END_HEADERS
+ :method = GET
+ :scheme = https
+ :path = /resource
+ host = example.org
+ accept = image/jpeg
+]]></artwork>
+ </figure>
+
+ <t>
+ Similarly, a response that includes only response header fields is transmitted as a
+ <x:ref>HEADERS</x:ref> frame (again, followed by zero or more
+ <x:ref>CONTINUATION</x:ref> frames) containing the serialized block of response header
+ fields.
+ </t>
+
+ <figure>
+ <artwork type="inline"><![CDATA[
+ HTTP/1.1 304 Not Modified HEADERS
+ ETag: "xyzzy" ==> + END_STREAM
+ Expires: Thu, 23 Jan ... + END_HEADERS
+ :status = 304
+ etag = "xyzzy"
+ expires = Thu, 23 Jan ...
+]]></artwork>
+ </figure>
+
+ <t>
+ An HTTP POST request that includes request header fields and payload data is transmitted
+ as one <x:ref>HEADERS</x:ref> frame, followed by zero or more
+ <x:ref>CONTINUATION</x:ref> frames containing the request header fields, followed by one
+ or more <x:ref>DATA</x:ref> frames, with the last <x:ref>CONTINUATION</x:ref> (or
+ <x:ref>HEADERS</x:ref>) frame having the END_HEADERS flag set and the final
+ <x:ref>DATA</x:ref> frame having the END_STREAM flag set:
+ </t>
+
+ <figure>
+ <artwork type="inline"><![CDATA[
+ POST /resource HTTP/1.1 HEADERS
+ Host: example.org ==> - END_STREAM
+ Content-Type: image/jpeg - END_HEADERS
+ Content-Length: 123 :method = POST
+ :path = /resource
+ {binary data} :scheme = https
+
+ CONTINUATION
+ + END_HEADERS
+ content-type = image/jpeg
+ host = example.org
+ content-length = 123
+
+ DATA
+ + END_STREAM
+ {binary data}
+]]></artwork>
+ <postamble>
+ Note that data contributing to any given header field could be spread between header
+ block fragments. The allocation of header fields to frames in this example is
+ illustrative only.
+ </postamble>
+ </figure>
+
+ <t>
+ A response that includes header fields and payload data is transmitted as a
+ <x:ref>HEADERS</x:ref> frame, followed by zero or more <x:ref>CONTINUATION</x:ref>
+ frames, followed by one or more <x:ref>DATA</x:ref> frames, with the last
+ <x:ref>DATA</x:ref> frame in the sequence having the END_STREAM flag set:
+ </t>
+
+ <figure>
+ <artwork type="inline"><![CDATA[
+ HTTP/1.1 200 OK HEADERS
+ Content-Type: image/jpeg ==> - END_STREAM
+ Content-Length: 123 + END_HEADERS
+ :status = 200
+ {binary data} content-type = image/jpeg
+ content-length = 123
+
+ DATA
+ + END_STREAM
+ {binary data}
+]]></artwork>
+ </figure>
+
+ <t>
+ Trailing header fields are sent as a header block after both the request or response
+ header block and all the <x:ref>DATA</x:ref> frames have been sent. The
+ <x:ref>HEADERS</x:ref> frame starting the trailers header block has the END_STREAM flag
+ set.
+ </t>
+
+ <figure>
+ <artwork type="inline"><![CDATA[
+ HTTP/1.1 200 OK HEADERS
+ Content-Type: image/jpeg ==> - END_STREAM
+ Transfer-Encoding: chunked + END_HEADERS
+ Trailer: Foo :status = 200
+ content-length = 123
+ 123 content-type = image/jpeg
+ {binary data} trailer = Foo
+ 0
+ Foo: bar DATA
+ - END_STREAM
+ {binary data}
+
+ HEADERS
+ + END_STREAM
+ + END_HEADERS
+ foo = bar
+]]></artwork>
+ </figure>
+
+
+ <figure>
+ <preamble>
+ An informational response using a 1xx status code other than 101 is transmitted as a
+ <x:ref>HEADERS</x:ref> frame, followed by zero or more <x:ref>CONTINUATION</x:ref>
+ frames:
+ </preamble>
+ <artwork type="inline"><![CDATA[
+ HTTP/1.1 103 BAR HEADERS
+ Extension-Field: bar ==> - END_STREAM
+ + END_HEADERS
+ :status = 103
+ extension-field = bar
+]]></artwork>
+ </figure>
+ </section>
+
+ <section anchor="Reliability" title="Request Reliability Mechanisms in HTTP/2">
+ <t>
+ In HTTP/1.1, an HTTP client is unable to retry a non-idempotent request when an error
+ occurs, because there is no means to determine the nature of the error. It is possible
+ that some server processing occurred prior to the error, which could result in
+ undesirable effects if the request were reattempted.
+ </t>
+ <t>
+ HTTP/2 provides two mechanisms for providing a guarantee to a client that a request has
+ not been processed:
+ <list style="symbols">
+ <t>
+ The <x:ref>GOAWAY</x:ref> frame indicates the highest stream number that might have
+ been processed. Requests on streams with higher numbers are therefore guaranteed to
+ be safe to retry.
+ </t>
+ <t>
+ The <x:ref>REFUSED_STREAM</x:ref> error code can be included in a
+ <x:ref>RST_STREAM</x:ref> frame to indicate that the stream is being closed prior to
+ any processing having occurred. Any request that was sent on the reset stream can
+ be safely retried.
+ </t>
+ </list>
+ </t>
+ <t>
+ Requests that have not been processed have not failed; clients MAY automatically retry
+ them, even those with non-idempotent methods.
+ </t>
+ <t>
+ A server MUST NOT indicate that a stream has not been processed unless it can guarantee
+ that fact. If frames that are on a stream are passed to the application layer for any
+ stream, then <x:ref>REFUSED_STREAM</x:ref> MUST NOT be used for that stream, and a
+ <x:ref>GOAWAY</x:ref> frame MUST include a stream identifier that is greater than or
+ equal to the given stream identifier.
+ </t>
+ <t>
+ In addition to these mechanisms, the <x:ref>PING</x:ref> frame provides a way for a
+ client to easily test a connection. Connections that remain idle can become broken as
+ some middleboxes (for instance, network address translators, or load balancers) silently
+ discard connection bindings. The <x:ref>PING</x:ref> frame allows a client to safely
+ test whether a connection is still active without sending a request.
+ </t>
+ </section>
+ </section>
+
+ <section anchor="PushResources" title="Server Push">
+ <t>
+ HTTP/2 allows a server to pre-emptively send (or "push") responses (along with
+ corresponding "promised" requests) to a client in association with a previous
+ client-initiated request. This can be useful when the server knows the client will need
+ to have those responses available in order to fully process the response to the original
+ request.
+ </t>
+
+ <t>
+ Pushing additional message exchanges in this fashion is optional, and is negotiated
+ between individual endpoints. The <x:ref>SETTINGS_ENABLE_PUSH</x:ref> setting can be set
+ to 0 to indicate that server push is disabled.
+ </t>
+ <t>
+ Promised requests MUST be cacheable (see <xref target="RFC7231" x:fmt=","
+ x:rel="#cacheable.methods"/>), MUST be safe (see <xref target="RFC7231" x:fmt=","
+ x:rel="#safe.methods"/>) and MUST NOT include a request body. Clients that receive a
+ promised request that is not cacheable, unsafe or that includes a request body MUST
+ reset the stream with a <xref target="StreamErrorHandler">stream error</xref> of type
+ <x:ref>PROTOCOL_ERROR</x:ref>.
+ </t>
+ <t>
+ Pushed responses that are cacheable (see <xref target="RFC7234" x:fmt=","
+ x:rel="#response.cacheability"/>) can be stored by the client, if it implements a HTTP
+ cache. Pushed responses are considered successfully validated on the origin server (e.g.,
+ if the "no-cache" cache response directive <xref target="RFC7234" x:fmt=","
+ x:rel="#cache-response-directive"/> is present) while the stream identified by the
+ promised stream ID is still open.
+ </t>
+ <t>
+ Pushed responses that are not cacheable MUST NOT be stored by any HTTP cache. They MAY
+ be made available to the application separately.
+ </t>
+ <t>
+ An intermediary can receive pushes from the server and choose not to forward them on to
+ the client. In other words, how to make use of the pushed information is up to that
+ intermediary. Equally, the intermediary might choose to make additional pushes to the
+ client, without any action taken by the server.
+ </t>
+ <t>
+ A client cannot push. Thus, servers MUST treat the receipt of a
+ <x:ref>PUSH_PROMISE</x:ref> frame as a <xref target="ConnectionErrorHandler">connection
+ error</xref> of type <x:ref>PROTOCOL_ERROR</x:ref>. Clients MUST reject any attempt to
+ change the <x:ref>SETTINGS_ENABLE_PUSH</x:ref> setting to a value other than 0 by treating
+ the message as a <xref target="ConnectionErrorHandler">connection error</xref> of type
+ <x:ref>PROTOCOL_ERROR</x:ref>.
+ </t>
+
+ <section anchor="PushRequests" title="Push Requests">
+ <t>
+ Server push is semantically equivalent to a server responding to a request; however, in
+ this case that request is also sent by the server, as a <x:ref>PUSH_PROMISE</x:ref>
+ frame.
+ </t>
+ <t>
+ The <x:ref>PUSH_PROMISE</x:ref> frame includes a header block that contains a complete
+ set of request header fields that the server attributes to the request. It is not
+ possible to push a response to a request that includes a request body.
+ </t>
+
+ <t>
+ Pushed responses are always associated with an explicit request from the client. The
+ <x:ref>PUSH_PROMISE</x:ref> frames sent by the server are sent on that explicit
+ request's stream. The <x:ref>PUSH_PROMISE</x:ref> frame also includes a promised stream
+ identifier, chosen from the stream identifiers available to the server (see <xref
+ target="StreamIdentifiers"/>).
+ </t>
+
+ <t>
+ The header fields in <x:ref>PUSH_PROMISE</x:ref> and any subsequent
+ <x:ref>CONTINUATION</x:ref> frames MUST be a valid and complete set of <xref
+ target="HttpRequest">request header fields</xref>. The server MUST include a method in
+ the <spanx style="verb">:method</spanx> header field that is safe and cacheable. If a
+ client receives a <x:ref>PUSH_PROMISE</x:ref> that does not include a complete and valid
+ set of header fields, or the <spanx style="verb">:method</spanx> header field identifies
+ a method that is not safe, it MUST respond with a <xref
+ target="StreamErrorHandler">stream error</xref> of type <x:ref>PROTOCOL_ERROR</x:ref>.
+ </t>
+
+ <t>
+ The server SHOULD send <x:ref>PUSH_PROMISE</x:ref> (<xref target="PUSH_PROMISE"/>)
+ frames prior to sending any frames that reference the promised responses. This avoids a
+ race where clients issue requests prior to receiving any <x:ref>PUSH_PROMISE</x:ref>
+ frames.
+ </t>
+ <t>
+ For example, if the server receives a request for a document containing embedded links
+ to multiple image files, and the server chooses to push those additional images to the
+ client, sending push promises before the <x:ref>DATA</x:ref> frames that contain the
+ image links ensures that the client is able to see the promises before discovering
+ embedded links. Similarly, if the server pushes responses referenced by the header block
+ (for instance, in Link header fields), sending the push promises before sending the
+ header block ensures that clients do not request them.
+ </t>
+
+ <t>
+ <x:ref>PUSH_PROMISE</x:ref> frames MUST NOT be sent by the client.
+ </t>
+ <t>
+ <x:ref>PUSH_PROMISE</x:ref> frames can be sent by the server in response to any
+ client-initiated stream, but the stream MUST be in either the "open" or "half closed
+ (remote)" state with respect to the server. <x:ref>PUSH_PROMISE</x:ref> frames are
+ interspersed with the frames that comprise a response, though they cannot be
+ interspersed with <x:ref>HEADERS</x:ref> and <x:ref>CONTINUATION</x:ref> frames that
+ comprise a single header block.
+ </t>
+ <t>
+ Sending a <x:ref>PUSH_PROMISE</x:ref> frame creates a new stream and puts the stream
+ into the “reserved (local)” state for the server and the “reserved (remote)” state for
+ the client.
+ </t>
+ </section>
+
+ <section anchor="PushResponses" title="Push Responses">
+ <t>
+ After sending the <x:ref>PUSH_PROMISE</x:ref> frame, the server can begin delivering the
+ pushed response as a <xref target="HttpResponse">response</xref> on a server-initiated
+ stream that uses the promised stream identifier. The server uses this stream to
+ transmit an HTTP response, using the same sequence of frames as defined in <xref
+ target="HttpSequence"/>. This stream becomes <xref target="StreamStates">"half closed"
+ to the client</xref> after the initial <x:ref>HEADERS</x:ref> frame is sent.
+ </t>
+
+ <t>
+ Once a client receives a <x:ref>PUSH_PROMISE</x:ref> frame and chooses to accept the
+ pushed response, the client SHOULD NOT issue any requests for the promised response
+ until after the promised stream has closed.
+ </t>
+
+ <t>
+ If the client determines, for any reason, that it does not wish to receive the pushed
+ response from the server, or if the server takes too long to begin sending the promised
+ response, the client can send an <x:ref>RST_STREAM</x:ref> frame, using either the
+ <x:ref>CANCEL</x:ref> or <x:ref>REFUSED_STREAM</x:ref> codes, and referencing the pushed
+ stream's identifier.
+ </t>
+ <t>
+ A client can use the <x:ref>SETTINGS_MAX_CONCURRENT_STREAMS</x:ref> setting to limit the
+ number of responses that can be concurrently pushed by a server. Advertising a
+ <x:ref>SETTINGS_MAX_CONCURRENT_STREAMS</x:ref> value of zero disables server push by
+ preventing the server from creating the necessary streams. This does not prohibit a
+ server from sending <x:ref>PUSH_PROMISE</x:ref> frames; clients need to reset any
+ promised streams that are not wanted.
+ </t>
+
+ <t>
+ Clients receiving a pushed response MUST validate that either the server is
+ authoritative (see <xref target="authority"/>), or the proxy that provided the pushed
+ response is configured for the corresponding request. For example, a server that offers
+ a certificate for only the <spanx style="verb">example.com</spanx> DNS-ID or Common Name
+ is not permitted to push a response for <spanx
+ style="verb">https://www.example.org/doc</spanx>.
+ </t>
+ <t>
+ The response for a <x:ref>PUSH_PROMISE</x:ref> stream begins with a
+ <x:ref>HEADERS</x:ref> frame, which immediately puts the stream into the “half closed
+ (remote)” state for the server and “half closed (local)” state for the client, and ends
+ with a frame bearing END_STREAM, which places the stream in the "closed" state.
+ <list style="hanging">
+ <t hangText="Note:">
+ The client never sends a frame with the END_STREAM flag for a server push.
+ </t>
+ </list>
+ </t>
+ </section>
+
+ </section>
+
+ <section anchor="CONNECT" title="The CONNECT Method">
+ <t>
+ In HTTP/1.x, the pseudo-method CONNECT (<xref target="RFC7231" x:fmt=","
+ x:rel="#CONNECT"/>) is used to convert an HTTP connection into a tunnel to a remote host.
+ CONNECT is primarily used with HTTP proxies to establish a TLS session with an origin
+ server for the purposes of interacting with <spanx style="verb">https</spanx> resources.
+ </t>
+ <t>
+ In HTTP/2, the CONNECT method is used to establish a tunnel over a single HTTP/2 stream to
+ a remote host, for similar purposes. The HTTP header field mapping works as defined in
+ <xref target="HttpRequest">Request Header Fields</xref>, with a few
+ differences. Specifically:
+ <list style="symbols">
+ <t>
+ The <spanx style="verb">:method</spanx> header field is set to <spanx
+ style="verb">CONNECT</spanx>.
+ </t>
+ <t>
+ The <spanx style="verb">:scheme</spanx> and <spanx style="verb">:path</spanx> header
+ fields MUST be omitted.
+ </t>
+ <t>
+ The <spanx style="verb">:authority</spanx> header field contains the host and port to
+ connect to (equivalent to the authority-form of the request-target of CONNECT
+ requests, see <xref target="RFC7230" x:fmt="," x:rel="#request-target"/>).
+ </t>
+ </list>
+ </t>
+ <t>
+ A proxy that supports CONNECT establishes a <xref target="TCP">TCP connection</xref> to
+ the server identified in the <spanx style="verb">:authority</spanx> header field. Once
+ this connection is successfully established, the proxy sends a <x:ref>HEADERS</x:ref>
+ frame containing a 2xx series status code to the client, as defined in <xref
+ target="RFC7231" x:fmt="," x:rel="#CONNECT"/>.
+ </t>
+ <t>
+ After the initial <x:ref>HEADERS</x:ref> frame sent by each peer, all subsequent
+ <x:ref>DATA</x:ref> frames correspond to data sent on the TCP connection. The payload of
+ any <x:ref>DATA</x:ref> frames sent by the client is transmitted by the proxy to the TCP
+ server; data received from the TCP server is assembled into <x:ref>DATA</x:ref> frames by
+ the proxy. Frame types other than <x:ref>DATA</x:ref> or stream management frames
+ (<x:ref>RST_STREAM</x:ref>, <x:ref>WINDOW_UPDATE</x:ref>, and <x:ref>PRIORITY</x:ref>)
+ MUST NOT be sent on a connected stream, and MUST be treated as a <xref
+ target="StreamErrorHandler">stream error</xref> if received.
+ </t>
+ <t>
+ The TCP connection can be closed by either peer. The END_STREAM flag on a
+ <x:ref>DATA</x:ref> frame is treated as being equivalent to the TCP FIN bit. A client is
+ expected to send a <x:ref>DATA</x:ref> frame with the END_STREAM flag set after receiving
+ a frame bearing the END_STREAM flag. A proxy that receives a <x:ref>DATA</x:ref> frame
+ with the END_STREAM flag set sends the attached data with the FIN bit set on the last TCP
+ segment. A proxy that receives a TCP segment with the FIN bit set sends a
+ <x:ref>DATA</x:ref> frame with the END_STREAM flag set. Note that the final TCP segment
+ or <x:ref>DATA</x:ref> frame could be empty.
+ </t>
+ <t>
+ A TCP connection error is signaled with <x:ref>RST_STREAM</x:ref>. A proxy treats any
+ error in the TCP connection, which includes receiving a TCP segment with the RST bit set,
+ as a <xref target="StreamErrorHandler">stream error</xref> of type
+ <x:ref>CONNECT_ERROR</x:ref>. Correspondingly, a proxy MUST send a TCP segment with the
+ RST bit set if it detects an error with the stream or the HTTP/2 connection.
+ </t>
+ </section>
+ </section>
+
+ <section anchor="HttpExtra" title="Additional HTTP Requirements/Considerations">
+ <t>
+ This section outlines attributes of the HTTP protocol that improve interoperability, reduce
+ exposure to known security vulnerabilities, or reduce the potential for implementation
+ variation.
+ </t>
+
+ <section title="Connection Management">
+ <t>
+ HTTP/2 connections are persistent. For best performance, it is expected clients will not
+ close connections until it is determined that no further communication with a server is
+ necessary (for example, when a user navigates away from a particular web page), or until
+ the server closes the connection.
+ </t>
+ <t>
+ Clients SHOULD NOT open more than one HTTP/2 connection to a given host and port pair,
+ where host is derived from a URI, a selected <xref target="ALT-SVC">alternative
+ service</xref>, or a configured proxy.
+ </t>
+ <t>
+ A client can create additional connections as replacements, either to replace connections
+ that are near to exhausting the available <xref target="StreamIdentifiers">stream
+ identifier space</xref>, to refresh the keying material for a TLS connection, or to
+ replace connections that have encountered <xref
+ target="ConnectionErrorHandler">errors</xref>.
+ </t>
+ <t>
+ A client MAY open multiple connections to the same IP address and TCP port using different
+ <xref target="TLS-EXT">Server Name Indication</xref> values or to provide different TLS
+ client certificates, but SHOULD avoid creating multiple connections with the same
+ configuration.
+ </t>
+ <t>
+ Servers are encouraged to maintain open connections for as long as possible, but are
+ permitted to terminate idle connections if necessary. When either endpoint chooses to
+ close the transport-layer TCP connection, the terminating endpoint SHOULD first send a
+ <x:ref>GOAWAY</x:ref> (<xref target="GOAWAY"/>) frame so that both endpoints can reliably
+ determine whether previously sent frames have been processed and gracefully complete or
+ terminate any necessary remaining tasks.
+ </t>
+
+ <section anchor="reuse" title="Connection Reuse">
+ <t>
+ Connections that are made to an origin servers, either directly or through a tunnel
+ created using the <xref target="CONNECT">CONNECT method</xref> MAY be reused for
+ requests with multiple different URI authority components. A connection can be reused
+ as long as the origin server is <xref target="authority">authoritative</xref>. For
+ <spanx style="verb">http</spanx> resources, this depends on the host having resolved to
+ the same IP address.
+ </t>
+ <t>
+ For <spanx style="verb">https</spanx> resources, connection reuse additionally depends
+ on having a certificate that is valid for the host in the URI. An origin server might
+ offer a certificate with multiple <spanx style="verb">subjectAltName</spanx> attributes,
+ or names with wildcards, one of which is valid for the authority in the URI. For
+ example, a certificate with a <spanx style="verb">subjectAltName</spanx> of <spanx
+ style="verb">*.example.com</spanx> might permit the use of the same connection for
+ requests to URIs starting with <spanx style="verb">https://a.example.com/</spanx> and
+ <spanx style="verb">https://b.example.com/</spanx>.
+ </t>
+ <t>
+ In some deployments, reusing a connection for multiple origins can result in requests
+ being directed to the wrong origin server. For example, TLS termination might be
+ performed by a middlebox that uses the TLS <xref target="TLS-EXT">Server Name Indication
+ (SNI)</xref> extension to select an origin server. This means that it is possible
+ for clients to send confidential information to servers that might not be the intended
+ target for the request, even though the server is otherwise authoritative.
+ </t>
+ <t>
+ A server that does not wish clients to reuse connections can indicate that it is not
+ authoritative for a request by sending a 421 (Misdirected Request) status code in response
+ to the request (see <xref target="MisdirectedRequest"/>).
+ </t>
+ <t>
+ A client that is configured to use a proxy over HTTP/2 directs requests to that proxy
+ through a single connection. That is, all requests sent via a proxy reuse the
+ connection to the proxy.
+ </t>
+ </section>
+
+ <section anchor="MisdirectedRequest" title="The 421 (Misdirected Request) Status Code">
+ <t>
+ The 421 (Misdirected Request) status code indicates that the request was directed at a
+ server that is not able to produce a response. This can be sent by a server that is not
+ configured to produce responses for the combination of scheme and authority that are
+ included in the request URI.
+ </t>
+ <t>
+ Clients receiving a 421 (Misdirected Request) response from a server MAY retry the
+ request - whether the request method is idempotent or not - over a different connection.
+ This is possible if a connection is reused (<xref target="reuse"/>) or if an alternative
+ service is selected (<xref target="ALT-SVC"/>).
+ </t>
+ <t>
+ This status code MUST NOT be generated by proxies.
+ </t>
+ <t>
+ A 421 response is cacheable by default; i.e., unless otherwise indicated by the method
+ definition or explicit cache controls (see <xref target="RFC7234"
+ x:rel="#heuristic.freshness" x:fmt="of"/>).
+ </t>
+ </section>
+ </section>
+
+ <section title="Use of TLS Features" anchor="TLSUsage">
+ <t>
+ Implementations of HTTP/2 MUST support <xref target="TLS12">TLS 1.2</xref> for HTTP/2 over
+ TLS. The general TLS usage guidance in <xref target="TLSBCP"/> SHOULD be followed, with
+ some additional restrictions that are specific to HTTP/2.
+ </t>
+
+ <t>
+ An implementation of HTTP/2 over TLS MUST use TLS 1.2 or higher with the restrictions on
+ feature set and cipher suite described in this section. Due to implementation
+ limitations, it might not be possible to fail TLS negotiation. An endpoint MUST
+ immediately terminate an HTTP/2 connection that does not meet these minimum requirements
+ with a <xref target="ConnectionErrorHandler">connection error</xref> of type
+ <x:ref>INADEQUATE_SECURITY</x:ref>.
+ </t>
+
+ <section anchor="TLSFeatures" title="TLS Features">
+ <t>
+ The TLS implementation MUST support the <xref target="TLS-EXT">Server Name Indication
+ (SNI)</xref> extension to TLS. HTTP/2 clients MUST indicate the target domain name when
+ negotiating TLS.
+ </t>
+ <t>
+ The TLS implementation MUST disable compression. TLS compression can lead to the
+ exposure of information that would not otherwise be revealed <xref target="RFC3749"/>.
+ Generic compression is unnecessary since HTTP/2 provides compression features that are
+ more aware of context and therefore likely to be more appropriate for use for
+ performance, security or other reasons.
+ </t>
+ <t>
+ The TLS implementation MUST disable renegotiation. An endpoint MUST treat a TLS
+ renegotiation as a <xref target="ConnectionErrorHandler">connection error</xref> of type
+ <x:ref>PROTOCOL_ERROR</x:ref>. Note that disabling renegotiation can result in
+ long-lived connections becoming unusable due to limits on the number of messages the
+ underlying cipher suite can encipher.
+ </t>
+ <t>
+ A client MAY use renegotiation to provide confidentiality protection for client
+ credentials offered in the handshake, but any renegotiation MUST occur prior to sending
+ the connection preface. A server SHOULD request a client certificate if it sees a
+ renegotiation request immediately after establishing a connection.
+ </t>
+ <t>
+ This effectively prevents the use of renegotiation in response to a request for a
+ specific protected resource. A future specification might provide a way to support this
+ use case. <!-- <cref> We are tracking this in a non-blocking fashion in issue #496 and
+ with a new draft. -->
+ </t>
+ </section>
+
+ <section title="TLS Cipher Suites">
+ <t>
+ The set of TLS cipher suites that are permitted in HTTP/2 is restricted. HTTP/2 MUST
+ only be used with cipher suites that have ephemeral key exchange, such as the <xref
+ target="TLS12">ephemeral Diffie-Hellman (DHE)</xref> or the <xref
+ target="RFC4492">elliptic curve variant (ECDHE)</xref>. Ephemeral key exchange MUST
+ have a minimum size of 2048 bits for DHE or security level of 128 bits for ECDHE.
+ Clients MUST accept DHE sizes of up to 4096 bits. HTTP MUST NOT be used with cipher
+ suites that use stream or block ciphers. Authenticated Encryption with Additional Data
+ (AEAD) modes, such as the <xref target="RFC5288">Galois Counter Model (GCM) mode for
+ AES</xref> are acceptable.
+ </t>
+ <t>
+ The effect of these restrictions is that TLS 1.2 implementations could have
+ non-intersecting sets of available cipher suites, since these prevent the use of the
+ cipher suite that TLS 1.2 makes mandatory. To avoid this problem, implementations of
+ HTTP/2 that use TLS 1.2 MUST support TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 <xref
+ target="TLS-ECDHE"/> with P256 <xref target="FIPS186"/>.
+ </t>
+ <t>
+ Clients MAY advertise support of cipher suites that are prohibited by the above
+ restrictions in order to allow for connection to servers that do not support HTTP/2.
+ This enables a fallback to protocols without these constraints without the additional
+ latency imposed by using a separate connection for fallback.
+ </t>
+ </section>
+ </section>
+ </section>
+
+ <section anchor="security" title="Security Considerations">
+ <section title="Server Authority" anchor="authority">
+ <t>
+ HTTP/2 relies on the HTTP/1.1 definition of authority for determining whether a server is
+ authoritative in providing a given response, see <xref target="RFC7230" x:fmt=","
+ x:rel="#establishing.authority"/>. This relies on local name resolution for the "http"
+ URI scheme, and the authenticated server identity for the "https" scheme (see <xref
+ target="RFC2818" x:fmt="," x:sec="3"/>).
+ </t>
+ </section>
+
+ <section title="Cross-Protocol Attacks">
+ <t>
+ In a cross-protocol attack, an attacker causes a client to initiate a transaction in one
+ protocol toward a server that understands a different protocol. An attacker might be able
+ to cause the transaction to appear as valid transaction in the second protocol. In
+ combination with the capabilities of the web context, this can be used to interact with
+ poorly protected servers in private networks.
+ </t>
+ <t>
+ Completing a TLS handshake with an ALPN identifier for HTTP/2 can be considered sufficient
+ protection against cross protocol attacks. ALPN provides a positive indication that a
+ server is willing to proceed with HTTP/2, which prevents attacks on other TLS-based
+ protocols.
+ </t>
+ <t>
+ The encryption in TLS makes it difficult for attackers to control the data which could be
+ used in a cross-protocol attack on a cleartext protocol.
+ </t>
+ <t>
+ The cleartext version of HTTP/2 has minimal protection against cross-protocol attacks.
+ The <xref target="ConnectionHeader">connection preface</xref> contains a string that is
+ designed to confuse HTTP/1.1 servers, but no special protection is offered for other
+ protocols. A server that is willing to ignore parts of an HTTP/1.1 request containing an
+ Upgrade header field in addition to the client connection preface could be exposed to a
+ cross-protocol attack.
+ </t>
+ </section>
+
+ <section title="Intermediary Encapsulation Attacks">
+ <t>
+ HTTP/2 header field names and values are encoded as sequences of octets with a length
+ prefix. This enables HTTP/2 to carry any string of octets as the name or value of a
+ header field. An intermediary that translates HTTP/2 requests or responses into HTTP/1.1
+ directly could permit the creation of corrupted HTTP/1.1 messages. An attacker might
+ exploit this behavior to cause the intermediary to create HTTP/1.1 messages with illegal
+ header fields, extra header fields, or even new messages that are entirely falsified.
+ </t>
+ <t>
+ Header field names or values that contain characters not permitted by HTTP/1.1, including
+ carriage return (ASCII 0xd) or line feed (ASCII 0xa) MUST NOT be translated verbatim by an
+ intermediary, as stipulated in <xref target="RFC7230" x:rel="#field.parsing" x:fmt=","/>.
+ </t>
+ <t>
+ Translation from HTTP/1.x to HTTP/2 does not produce the same opportunity to an attacker.
+ Intermediaries that perform translation to HTTP/2 MUST remove any instances of the <spanx
+ style="verb">obs-fold</spanx> production from header field values.
+ </t>
+ </section>
+
+ <section title="Cacheability of Pushed Responses">
+ <t>
+ Pushed responses do not have an explicit request from the client; the request
+ is provided by the server in the <x:ref>PUSH_PROMISE</x:ref> frame.
+ </t>
+ <t>
+ Caching responses that are pushed is possible based on the guidance provided by the origin
+ server in the Cache-Control header field. However, this can cause issues if a single
+ server hosts more than one tenant. For example, a server might offer multiple users each
+ a small portion of its URI space.
+ </t>
+ <t>
+ Where multiple tenants share space on the same server, that server MUST ensure that
+ tenants are not able to push representations of resources that they do not have authority
+ over. Failure to enforce this would allow a tenant to provide a representation that would
+ be served out of cache, overriding the actual representation that the authoritative tenant
+ provides.
+ </t>
+ <t>
+ Pushed responses for which an origin server is not authoritative (see
+ <xref target="authority"/>) are never cached or used.
+ </t>
+ </section>
+
+ <section anchor="dos" title="Denial of Service Considerations">
+ <t>
+ An HTTP/2 connection can demand a greater commitment of resources to operate than a
+ HTTP/1.1 connection. The use of header compression and flow control depend on a
+ commitment of resources for storing a greater amount of state. Settings for these
+ features ensure that memory commitments for these features are strictly bounded.
+ </t>
+ <t>
+ The number of <x:ref>PUSH_PROMISE</x:ref> frames is not constrained in the same fashion.
+ A client that accepts server push SHOULD limit the number of streams it allows to be in
+ the "reserved (remote)" state. Excessive number of server push streams can be treated as
+ a <xref target="StreamErrorHandler">stream error</xref> of type
+ <x:ref>ENHANCE_YOUR_CALM</x:ref>.
+ </t>
+ <t>
+ Processing capacity cannot be guarded as effectively as state capacity.
+ </t>
+ <t>
+ The <x:ref>SETTINGS</x:ref> frame can be abused to cause a peer to expend additional
+ processing time. This might be done by pointlessly changing SETTINGS parameters, setting
+ multiple undefined parameters, or changing the same setting multiple times in the same
+ frame. <x:ref>WINDOW_UPDATE</x:ref> or <x:ref>PRIORITY</x:ref> frames can be abused to
+ cause an unnecessary waste of resources.
+ </t>
+ <t>
+ Large numbers of small or empty frames can be abused to cause a peer to expend time
+ processing frame headers. Note however that some uses are entirely legitimate, such as
+ the sending of an empty <x:ref>DATA</x:ref> frame to end a stream.
+ </t>
+ <t>
+ Header compression also offers some opportunities to waste processing resources; see <xref
+ target="COMPRESSION" x:fmt="of" x:rel="#Security"/> for more details on potential abuses.
+ </t>
+ <t>
+ Limits in <x:ref>SETTINGS</x:ref> parameters cannot be reduced instantaneously, which
+ leaves an endpoint exposed to behavior from a peer that could exceed the new limits. In
+ particular, immediately after establishing a connection, limits set by a server are not
+ known to clients and could be exceeded without being an obvious protocol violation.
+ </t>
+ <t>
+ All these features - i.e., <x:ref>SETTINGS</x:ref> changes, small frames, header
+ compression - have legitimate uses. These features become a burden only when they are
+ used unnecessarily or to excess.
+ </t>
+ <t>
+ An endpoint that doesn't monitor this behavior exposes itself to a risk of denial of
+ service attack. Implementations SHOULD track the use of these features and set limits on
+ their use. An endpoint MAY treat activity that is suspicious as a <xref
+ target="ConnectionErrorHandler">connection error</xref> of type
+ <x:ref>ENHANCE_YOUR_CALM</x:ref>.
+ </t>
+
+ <section anchor="MaxHeaderBlock" title="Limits on Header Block Size">
+ <t>
+ A large <xref target="HeaderBlock">header block</xref> can cause an implementation to
+ commit a large amount of state. Header fields that are critical for routing can appear
+ toward the end of a header block, which prevents streaming of header fields to their
+ ultimate destination. For this an other reasons, such as ensuring cache correctness,
+ means that an endpoint might need to buffer the entire header block. Since there is no
+ hard limit to the size of a header block, some endpoints could be forced commit a large
+ amount of available memory for header fields.
+ </t>
+ <t>
+ An endpoint can use the <x:ref>SETTINGS_MAX_HEADER_LIST_SIZE</x:ref> to advise peers of
+ limits that might apply on the size of header blocks. This setting is only advisory, so
+ endpoints MAY choose to send header blocks that exceed this limit and risk having the
+ request or response being treated as malformed. This setting specific to a connection,
+ so any request or response could encounter a hop with a lower, unknown limit. An
+ intermediary can attempt to avoid this problem by passing on values presented by
+ different peers, but they are not obligated to do so.
+ </t>
+ <t>
+ A server that receives a larger header block than it is willing to handle can send an
+ HTTP 431 (Request Header Fields Too Large) status code <xref target="RFC6585"/>. A
+ client can discard responses that it cannot process. The header block MUST be processed
+ to ensure a consistent connection state, unless the connection is closed.
+ </t>
+ </section>
+ </section>
+
+ <section title="Use of Compression">
+ <t>
+ HTTP/2 enables greater use of compression for both header fields (<xref
+ target="HeaderBlock"/>) and entity bodies. Compression can allow an attacker to recover
+ secret data when it is compressed in the same context as data under attacker control.
+ </t>
+ <t>
+ There are demonstrable attacks on compression that exploit the characteristics of the web
+ (e.g., <xref target="BREACH"/>). The attacker induces multiple requests containing
+ varying plaintext, observing the length of the resulting ciphertext in each, which
+ reveals a shorter length when a guess about the secret is correct.
+ </t>
+ <t>
+ Implementations communicating on a secure channel MUST NOT compress content that includes
+ both confidential and attacker-controlled data unless separate compression dictionaries
+ are used for each source of data. Compression MUST NOT be used if the source of data
+ cannot be reliably determined. Generic stream compression, such as that provided by TLS
+ MUST NOT be used with HTTP/2 (<xref target="TLSFeatures"/>).
+ </t>
+ <t>
+ Further considerations regarding the compression of header fields are described in <xref
+ target="COMPRESSION"/>.
+ </t>
+ </section>
+
+ <section title="Use of Padding" anchor="padding">
+ <t>
+ Padding within HTTP/2 is not intended as a replacement for general purpose padding, such
+ as might be provided by <xref target="TLS12">TLS</xref>. Redundant padding could even be
+ counterproductive. Correct application can depend on having specific knowledge of the
+ data that is being padded.
+ </t>
+ <t>
+ To mitigate attacks that rely on compression, disabling or limiting compression might be
+ preferable to padding as a countermeasure.
+ </t>
+ <t>
+ Padding can be used to obscure the exact size of frame content, and is provided to
+ mitigate specific attacks within HTTP. For example, attacks where compressed content
+ includes both attacker-controlled plaintext and secret data (see for example, <xref
+ target="BREACH"/>).
+ </t>
+ <t>
+ Use of padding can result in less protection than might seem immediately obvious. At
+ best, padding only makes it more difficult for an attacker to infer length information by
+ increasing the number of frames an attacker has to observe. Incorrectly implemented
+ padding schemes can be easily defeated. In particular, randomized padding with a
+ predictable distribution provides very little protection; similarly, padding payloads to a
+ fixed size exposes information as payload sizes cross the fixed size boundary, which could
+ be possible if an attacker can control plaintext.
+ </t>
+ <t>
+ Intermediaries SHOULD retain padding for <x:ref>DATA</x:ref> frames, but MAY drop padding
+ for <x:ref>HEADERS</x:ref> and <x:ref>PUSH_PROMISE</x:ref> frames. A valid reason for an
+ intermediary to change the amount of padding of frames is to improve the protections that
+ padding provides.
+ </t>
+ </section>
+
+ <section title="Privacy Considerations">
+ <t>
+ Several characteristics of HTTP/2 provide an observer an opportunity to correlate actions
+ of a single client or server over time. This includes the value of settings, the manner
+ in which flow control windows are managed, the way priorities are allocated to streams,
+ timing of reactions to stimulus, and handling of any optional features.
+ </t>
+ <t>
+ As far as this creates observable differences in behavior, they could be used as a basis
+ for fingerprinting a specific client, as defined in <xref target="HTML5" x:fmt="of"
+ x:sec="1.8" x:rel="introduction.html#fingerprint"/>.
+ </t>
+ </section>
+ </section>
+
+ <section anchor="iana" title="IANA Considerations">
+ <t>
+ A string for identifying HTTP/2 is entered into the "Application Layer Protocol Negotiation
+ (ALPN) Protocol IDs" registry established in <xref target="TLS-ALPN"/>.
+ </t>
+ <t>
+ This document establishes a registry for frame types, settings, and error codes. These new
+ registries are entered into a new "Hypertext Transfer Protocol (HTTP) 2 Parameters" section.
+ </t>
+ <t>
+ This document registers the <spanx style="verb">HTTP2-Settings</spanx> header field for
+ use in HTTP; and the 421 (Misdirected Request) status code.
+ </t>
+ <t>
+ This document registers the <spanx style="verb">PRI</spanx> method for use in HTTP, to avoid
+ collisions with the <xref target="ConnectionHeader">connection preface</xref>.
+ </t>
+
+ <section anchor="iana-alpn" title="Registration of HTTP/2 Identification Strings">
+ <t>
+ This document creates two registrations for the identification of HTTP/2 in the
+ "Application Layer Protocol Negotiation (ALPN) Protocol IDs" registry established in <xref
+ target="TLS-ALPN"/>.
+ </t>
+ <t>
+ The "h2" string identifies HTTP/2 when used over TLS:
+ <list style="hanging">
+ <t hangText="Protocol:">HTTP/2 over TLS</t>
+ <t hangText="Identification Sequence:">0x68 0x32 ("h2")</t>
+ <t hangText="Specification:">This document</t>
+ </list>
+ </t>
+ <t>
+ The "h2c" string identifies HTTP/2 when used over cleartext TCP:
+ <list style="hanging">
+ <t hangText="Protocol:">HTTP/2 over TCP</t>
+ <t hangText="Identification Sequence:">0x68 0x32 0x63 ("h2c")</t>
+ <t hangText="Specification:">This document</t>
+ </list>
+ </t>
+ </section>
+
+ <section anchor="iana-frames" title="Frame Type Registry">
+ <t>
+ This document establishes a registry for HTTP/2 frame type codes. The "HTTP/2 Frame
+ Type" registry manages an 8-bit space. The "HTTP/2 Frame Type" registry operates under
+ either of the <xref target="RFC5226">"IETF Review" or "IESG Approval" policies</xref> for
+ values between 0x00 and 0xef, with values between 0xf0 and 0xff being reserved for
+ experimental use.
+ </t>
+ <t>
+ New entries in this registry require the following information:
+ <list style="hanging">
+ <t hangText="Frame Type:">
+ A name or label for the frame type.
+ </t>
+ <t hangText="Code:">
+ The 8-bit code assigned to the frame type.
+ </t>
+ <t hangText="Specification:">
+ A reference to a specification that includes a description of the frame layout,
+ it's semantics and flags that the frame type uses, including any parts of the frame
+ that are conditionally present based on the value of flags.
+ </t>
+ </list>
+ </t>
+ <t>
+ The entries in the following table are registered by this document.
+ </t>
+ <texttable align="left" suppress-title="true">
+ <ttcol>Frame Type</ttcol>
+ <ttcol>Code</ttcol>
+ <ttcol>Section</ttcol>
+ <c>DATA</c><c>0x0</c><c><xref target="DATA"/></c>
+ <c>HEADERS</c><c>0x1</c><c><xref target="HEADERS"/></c>
+ <c>PRIORITY</c><c>0x2</c><c><xref target="PRIORITY"/></c>
+ <c>RST_STREAM</c><c>0x3</c><c><xref target="RST_STREAM"/></c>
+ <c>SETTINGS</c><c>0x4</c><c><xref target="SETTINGS"/></c>
+ <c>PUSH_PROMISE</c><c>0x5</c><c><xref target="PUSH_PROMISE"/></c>
+ <c>PING</c><c>0x6</c><c><xref target="PING"/></c>
+ <c>GOAWAY</c><c>0x7</c><c><xref target="GOAWAY"/></c>
+ <c>WINDOW_UPDATE</c><c>0x8</c><c><xref target="WINDOW_UPDATE"/></c>
+ <c>CONTINUATION</c><c>0x9</c><c><xref target="CONTINUATION"/></c>
+ </texttable>
+ </section>
+
+ <section anchor="iana-settings" title="Settings Registry">
+ <t>
+ This document establishes a registry for HTTP/2 settings. The "HTTP/2 Settings" registry
+ manages a 16-bit space. The "HTTP/2 Settings" registry operates under the <xref
+ target="RFC5226">"Expert Review" policy</xref> for values in the range from 0x0000 to
+ 0xefff, with values between and 0xf000 and 0xffff being reserved for experimental use.
+ </t>
+ <t>
+ New registrations are advised to provide the following information:
+ <list style="hanging">
+ <t hangText="Name:">
+ A symbolic name for the setting. Specifying a setting name is optional.
+ </t>
+ <t hangText="Code:">
+ The 16-bit code assigned to the setting.
+ </t>
+ <t hangText="Initial Value:">
+ An initial value for the setting.
+ </t>
+ <t hangText="Specification:">
+ An optional reference to a specification that describes the use of the setting.
+ </t>
+ </list>
+ </t>
+ <t>
+ An initial set of setting registrations can be found in <xref target="SettingValues"/>.
+ </t>
+ <texttable align="left" suppress-title="true">
+ <ttcol>Name</ttcol>
+ <ttcol>Code</ttcol>
+ <ttcol>Initial Value</ttcol>
+ <ttcol>Specification</ttcol>
+ <c>HEADER_TABLE_SIZE</c>
+ <c>0x1</c><c>4096</c><c><xref target="SettingValues"/></c>
+ <c>ENABLE_PUSH</c>
+ <c>0x2</c><c>1</c><c><xref target="SettingValues"/></c>
+ <c>MAX_CONCURRENT_STREAMS</c>
+ <c>0x3</c><c>(infinite)</c><c><xref target="SettingValues"/></c>
+ <c>INITIAL_WINDOW_SIZE</c>
+ <c>0x4</c><c>65535</c><c><xref target="SettingValues"/></c>
+ <c>MAX_FRAME_SIZE</c>
+ <c>0x5</c><c>16384</c><c><xref target="SettingValues"/></c>
+ <c>MAX_HEADER_LIST_SIZE</c>
+ <c>0x6</c><c>(infinite)</c><c><xref target="SettingValues"/></c>
+ </texttable>
+
+ </section>
+
+ <section anchor="iana-errors" title="Error Code Registry">
+ <t>
+ This document establishes a registry for HTTP/2 error codes. The "HTTP/2 Error Code"
+ registry manages a 32-bit space. The "HTTP/2 Error Code" registry operates under the
+ <xref target="RFC5226">"Expert Review" policy</xref>.
+ </t>
+ <t>
+ Registrations for error codes are required to include a description of the error code. An
+ expert reviewer is advised to examine new registrations for possible duplication with
+ existing error codes. Use of existing registrations is to be encouraged, but not
+ mandated.
+ </t>
+ <t>
+ New registrations are advised to provide the following information:
+ <list style="hanging">
+ <t hangText="Name:">
+ A name for the error code. Specifying an error code name is optional.
+ </t>
+ <t hangText="Code:">
+ The 32-bit error code value.
+ </t>
+ <t hangText="Description:">
+ A brief description of the error code semantics, longer if no detailed specification
+ is provided.
+ </t>
+ <t hangText="Specification:">
+ An optional reference for a specification that defines the error code.
+ </t>
+ </list>
+ </t>
+ <t>
+ The entries in the following table are registered by this document.
+ </t>
+ <texttable align="left" suppress-title="true">
+ <ttcol>Name</ttcol>
+ <ttcol>Code</ttcol>
+ <ttcol>Description</ttcol>
+ <ttcol>Specification</ttcol>
+ <c>NO_ERROR</c><c>0x0</c>
+ <c>Graceful shutdown</c>
+ <c><xref target="ErrorCodes"/></c>
+ <c>PROTOCOL_ERROR</c><c>0x1</c>
+ <c>Protocol error detected</c>
+ <c><xref target="ErrorCodes"/></c>
+ <c>INTERNAL_ERROR</c><c>0x2</c>
+ <c>Implementation fault</c>
+ <c><xref target="ErrorCodes"/></c>
+ <c>FLOW_CONTROL_ERROR</c><c>0x3</c>
+ <c>Flow control limits exceeded</c>
+ <c><xref target="ErrorCodes"/></c>
+ <c>SETTINGS_TIMEOUT</c><c>0x4</c>
+ <c>Settings not acknowledged</c>
+ <c><xref target="ErrorCodes"/></c>
+ <c>STREAM_CLOSED</c><c>0x5</c>
+ <c>Frame received for closed stream</c>
+ <c><xref target="ErrorCodes"/></c>
+ <c>FRAME_SIZE_ERROR</c><c>0x6</c>
+ <c>Frame size incorrect</c>
+ <c><xref target="ErrorCodes"/></c>
+ <c>REFUSED_STREAM</c><c>0x7</c>
+ <c>Stream not processed</c>
+ <c><xref target="ErrorCodes"/></c>
+ <c>CANCEL</c><c>0x8</c>
+ <c>Stream cancelled</c>
+ <c><xref target="ErrorCodes"/></c>
+ <c>COMPRESSION_ERROR</c><c>0x9</c>
+ <c>Compression state not updated</c>
+ <c><xref target="ErrorCodes"/></c>
+ <c>CONNECT_ERROR</c><c>0xa</c>
+ <c>TCP connection error for CONNECT method</c>
+ <c><xref target="ErrorCodes"/></c>
+ <c>ENHANCE_YOUR_CALM</c><c>0xb</c>
+ <c>Processing capacity exceeded</c>
+ <c><xref target="ErrorCodes"/></c>
+ <c>INADEQUATE_SECURITY</c><c>0xc</c>
+ <c>Negotiated TLS parameters not acceptable</c>
+ <c><xref target="ErrorCodes"/></c>
+ </texttable>
+
+ </section>
+
+ <section title="HTTP2-Settings Header Field Registration">
+ <t>
+ This section registers the <spanx style="verb">HTTP2-Settings</spanx> header field in the
+ <xref target="BCP90">Permanent Message Header Field Registry</xref>.
+ <list style="hanging">
+ <t hangText="Header field name:">
+ HTTP2-Settings
+ </t>
+ <t hangText="Applicable protocol:">
+ http
+ </t>
+ <t hangText="Status:">
+ standard
+ </t>
+ <t hangText="Author/Change controller:">
+ IETF
+ </t>
+ <t hangText="Specification document(s):">
+ <xref target="Http2SettingsHeader"/> of this document
+ </t>
+ <t hangText="Related information:">
+ This header field is only used by an HTTP/2 client for Upgrade-based negotiation.
+ </t>
+ </list>
+ </t>
+ </section>
+
+ <section title="PRI Method Registration">
+ <t>
+ This section registers the <spanx style="verb">PRI</spanx> method in the HTTP Method
+ Registry (<xref target="RFC7231" x:fmt="," x:rel="#method.registry"/>).
+ <list style="hanging">
+ <t hangText="Method Name:">
+ PRI
+ </t>
+ <t hangText="Safe">
+ No
+ </t>
+ <t hangText="Idempotent">
+ No
+ </t>
+ <t hangText="Specification document(s)">
+ <xref target="ConnectionHeader"/> of this document
+ </t>
+ <t hangText="Related information:">
+ This method is never used by an actual client. This method will appear to be used
+ when an HTTP/1.1 server or intermediary attempts to parse an HTTP/2 connection
+ preface.
+ </t>
+ </list>
+ </t>
+ </section>
+
+ <section title="The 421 (Misdirected Request) HTTP Status Code"
+ anchor="iana-MisdirectedRequest">
+ <t>
+ This document registers the 421 (Misdirected Request) HTTP Status code in the Hypertext
+ Transfer Protocol (HTTP) Status Code Registry (<xref target="RFC7231" x:fmt=","
+ x:rel="#status.code.registry"/>).
+ </t>
+ <t>
+ <list style="hanging">
+ <t hangText="Status Code:">
+ 421
+ </t>
+ <t hangText="Short Description:">
+ Misdirected Request
+ </t>
+ <t hangText="Specification:">
+ <xref target="MisdirectedRequest"/> of this document
+ </t>
+ </list>
+ </t>
+ </section>
+
+ </section>
+
+ <section title="Acknowledgements">
+ <t>
+ This document includes substantial input from the following individuals:
+ <list style="symbols">
+ <t>
+ Adam Langley, Wan-Teh Chang, Jim Morrison, Mark Nottingham, Alyssa Wilk, Costin
+ Manolache, William Chan, Vitaliy Lvin, Joe Chan, Adam Barth, Ryan Hamilton, Gavin
+ Peters, Kent Alstad, Kevin Lindsay, Paul Amer, Fan Yang, Jonathan Leighton (SPDY
+ contributors).
+ </t>
+ <t>
+ Gabriel Montenegro and Willy Tarreau (Upgrade mechanism).
+ </t>
+ <t>
+ William Chan, Salvatore Loreto, Osama Mazahir, Gabriel Montenegro, Jitu Padhye, Roberto
+ Peon, Rob Trace (Flow control).
+ </t>
+ <t>
+ Mike Bishop (Extensibility).
+ </t>
+ <t>
+ Mark Nottingham, Julian Reschke, James Snell, Jeff Pinner, Mike Bishop, Herve Ruellan
+ (Substantial editorial contributions).
+ </t>
+ <t>
+ Kari Hurtta, Tatsuhiro Tsujikawa, Greg Wilkins, Poul-Henning Kamp.
+ </t>
+ <t>
+ Alexey Melnikov was an editor of this document during 2013.
+ </t>
+ <t>
+ A substantial proportion of Martin's contribution was supported by Microsoft during his
+ employment there.
+ </t>
+ </list>
+ </t>
+ </section>
+ </middle>
+
+ <back>
+ <references title="Normative References">
+ <reference anchor="COMPRESSION">
+ <front>
+ <title>HPACK - Header Compression for HTTP/2</title>
+ <author initials="H." surname="Ruellan" fullname="Herve Ruellan"/>
+ <author initials="R." surname="Peon" fullname="Roberto Peon"/>
+ <date month="July" year="2014" />
+ </front>
+ <seriesInfo name="Internet-Draft" value="draft-ietf-httpbis-header-compression-09" />
+ <x:source href="refs/draft-ietf-httpbis-header-compression-09.xml"/>
+ </reference>
+
+ <reference anchor="TCP">
+ <front>
+ <title abbrev="Transmission Control Protocol">
+ Transmission Control Protocol
+ </title>
+ <author initials="J." surname="Postel" fullname="Jon Postel">
+ <organization>University of Southern California (USC)/Information Sciences
+ Institute</organization>
+ </author>
+ <date year="1981" month="September" />
+ </front>
+ <seriesInfo name="STD" value="7" />
+ <seriesInfo name="RFC" value="793" />
+ </reference>
+
+ <reference anchor="RFC2119">
+ <front>
+ <title>
+ Key words for use in RFCs to Indicate Requirement Levels
+ </title>
+ <author initials="S." surname="Bradner" fullname="Scott Bradner">
+ <organization>Harvard University</organization>
+ <address><email>sob@harvard.edu</email></address>
+ </author>
+ <date month="March" year="1997"/>
+ </front>
+ <seriesInfo name="BCP" value="14"/>
+ <seriesInfo name="RFC" value="2119"/>
+ </reference>
+
+ <reference anchor="RFC2818">
+ <front>
+ <title>
+ HTTP Over TLS
+ </title>
+ <author initials="E." surname="Rescorla" fullname="Eric Rescorla"/>
+ <date month="May" year="2000"/>
+ </front>
+ <seriesInfo name="RFC" value="2818"/>
+ </reference>
+
+ <reference anchor="RFC3986">
+ <front>
+ <title abbrev="URI Generic Syntax">Uniform Resource Identifier (URI): Generic
+ Syntax</title>
+ <author initials="T." surname="Berners-Lee" fullname="Tim Berners-Lee"></author>
+ <author initials="R." surname="Fielding" fullname="Roy T. Fielding"></author>
+ <author initials="L." surname="Masinter" fullname="Larry Masinter"></author>
+ <date year="2005" month="January" />
+ </front>
+ <seriesInfo name="STD" value="66" />
+ <seriesInfo name="RFC" value="3986" />
+ </reference>
+
+ <reference anchor="RFC4648">
+ <front>
+ <title>The Base16, Base32, and Base64 Data Encodings</title>
+ <author fullname="S. Josefsson" initials="S." surname="Josefsson"/>
+ <date year="2006" month="October"/>
+ </front>
+ <seriesInfo value="4648" name="RFC"/>
+ </reference>
+
+ <reference anchor="RFC5226">
+ <front>
+ <title>Guidelines for Writing an IANA Considerations Section in RFCs</title>
+ <author initials="T." surname="Narten" fullname="T. Narten"/>
+ <author initials="H." surname="Alvestrand" fullname="H. Alvestrand"/>
+ <date year="2008" month="May" />
+ </front>
+ <seriesInfo name="BCP" value="26" />
+ <seriesInfo name="RFC" value="5226" />
+ </reference>
+
+ <reference anchor="RFC5234">
+ <front>
+ <title>Augmented BNF for Syntax Specifications: ABNF</title>
+ <author initials="D." surname="Crocker" fullname="D. Crocker"/>
+ <author initials="P." surname="Overell" fullname="P. Overell"/>
+ <date year="2008" month="January" />
+ </front>
+ <seriesInfo name="STD" value="68" />
+ <seriesInfo name="RFC" value="5234" />
+ </reference>
+
+ <reference anchor="TLS12">
+ <front>
+ <title>The Transport Layer Security (TLS) Protocol Version 1.2</title>
+ <author initials="T." surname="Dierks" fullname="Tim Dierks"/>
+ <author initials="E." surname="Rescorla" fullname="Eric Rescorla"/>
+ <date year="2008" month="August" />
+ </front>
+ <seriesInfo name="RFC" value="5246" />
+ </reference>
+
+ <reference anchor="TLS-EXT">
+ <front>
+ <title>
+ Transport Layer Security (TLS) Extensions: Extension Definitions
+ </title>
+ <author initials="D." surname="Eastlake" fullname="D. Eastlake"/>
+ <date year="2011" month="January"/>
+ </front>
+ <seriesInfo name="RFC" value="6066"/>
+ </reference>
+
+ <reference anchor="TLS-ALPN">
+ <front>
+ <title>Transport Layer Security (TLS) Application-Layer Protocol Negotiation Extension</title>
+ <author initials="S." surname="Friedl" fullname="Stephan Friedl"></author>
+ <author initials="A." surname="Popov" fullname="Andrei Popov"></author>
+ <author initials="A." surname="Langley" fullname="Adam Langley"></author>
+ <author initials="E." surname="Stephan" fullname="Emile Stephan"></author>
+ <date month="July" year="2014" />
+ </front>
+ <seriesInfo name="RFC" value="7301" />
+ </reference>
+
+ <reference anchor="TLS-ECDHE">
+ <front>
+ <title>
+ TLS Elliptic Curve Cipher Suites with SHA-256/384 and AES Galois
+ Counter Mode (GCM)
+ </title>
+ <author initials="E." surname="Rescorla" fullname="E. Rescorla"/>
+ <date year="2008" month="August" />
+ </front>
+ <seriesInfo name="RFC" value="5289" />
+ </reference>
+
+ <reference anchor="FIPS186">
+ <front>
+ <title>
+ Digital Signature Standard (DSS)
+ </title>
+ <author><organization>NIST</organization></author>
+ <date year="2013" month="July" />
+ </front>
+ <seriesInfo name="FIPS" value="PUB 186-4" />
+ </reference>
+
+ <reference anchor="RFC7230">
+ <front>
+ <title>
+ Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing</title>
+ <author fullname="Roy T. Fielding" initials="R." role="editor" surname="Fielding">
+ <organization abbrev="Adobe">Adobe Systems Incorporated</organization>
+ <address><email>fielding@gbiv.com</email></address>
+ </author>
+ <author fullname="Julian F. Reschke" initials="J. F." role="editor" surname="Reschke">
+ <organization abbrev="greenbytes">greenbytes GmbH</organization>
+ <address><email>julian.reschke@greenbytes.de</email></address>
+ </author>
+ <date month="June" year="2014" />
+ </front>
+ <seriesInfo name="RFC" value="7230" />
+ <x:source href="refs/rfc7230.xml"
+ basename="https://svn.tools.ietf.org/svn/wg/httpbis/specs/rfc7230"/>
+ </reference>
+ <reference anchor="RFC7231">
+ <front>
+ <title>
+ Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content</title>
+ <author fullname="Roy T. Fielding" initials="R." role="editor" surname="Fielding">
+ <organization abbrev="Adobe">Adobe Systems Incorporated</organization>
+ <address><email>fielding@gbiv.com</email></address>
+ </author>
+ <author fullname="Julian F. Reschke" initials="J. F." role="editor" surname="Reschke">
+ <organization abbrev="greenbytes">greenbytes GmbH</organization>
+ <address><email>julian.reschke@greenbytes.de</email></address>
+ </author>
+ <date month="June" year="2014" />
+ </front>
+ <seriesInfo name="RFC" value="7231" />
+ <x:source href="refs/rfc7231.xml"
+ basename="https://svn.tools.ietf.org/svn/wg/httpbis/specs/rfc7231"/>
+ </reference>
+ <reference anchor="RFC7232">
+ <front>
+ <title>Hypertext Transfer Protocol (HTTP/1.1): Conditional Requests</title>
+ <author fullname="Roy T. Fielding" initials="R." role="editor" surname="Fielding">
+ <organization abbrev="Adobe">Adobe Systems Incorporated</organization>
+ <address><email>fielding@gbiv.com</email></address>
+ </author>
+ <author fullname="Julian F. Reschke" initials="J. F." role="editor" surname="Reschke">
+ <organization abbrev="greenbytes">greenbytes GmbH</organization>
+ <address><email>julian.reschke@greenbytes.de</email></address>
+ </author>
+ <date month="June" year="2014" />
+ </front>
+ <seriesInfo name="RFC" value="7232" />
+ </reference>
+ <reference anchor="RFC7233">
+ <front>
+ <title>Hypertext Transfer Protocol (HTTP/1.1): Range Requests</title>
+ <author initials="R." surname="Fielding" fullname="Roy T. Fielding" role="editor">
+ <organization abbrev="Adobe">Adobe Systems Incorporated</organization>
+ <address><email>fielding@gbiv.com</email></address>
+ </author>
+ <author initials="Y." surname="Lafon" fullname="Yves Lafon" role="editor">
+ <organization abbrev="W3C">World Wide Web Consortium</organization>
+ <address><email>ylafon@w3.org</email></address>
+ </author>
+ <author initials="J. F." surname="Reschke" fullname="Julian F. Reschke" role="editor">
+ <organization abbrev="greenbytes">greenbytes GmbH</organization>
+ <address><email>julian.reschke@greenbytes.de</email></address>
+ </author>
+ <date month="June" year="2014" />
+ </front>
+ <seriesInfo name="RFC" value="7233" />
+ </reference>
+ <reference anchor="RFC7234">
+ <front>
+ <title>Hypertext Transfer Protocol (HTTP/1.1): Caching</title>
+ <author initials="R." surname="Fielding" fullname="Roy T. Fielding" role="editor">
+ <organization abbrev="Adobe">Adobe Systems Incorporated</organization>
+ <address><email>fielding@gbiv.com</email></address>
+ </author>
+ <author fullname="Mark Nottingham" initials="M." role="editor" surname="Nottingham">
+ <organization>Akamai</organization>
+ <address><email>mnot@mnot.net</email></address>
+ </author>
+ <author initials="J. F." surname="Reschke" fullname="Julian F. Reschke" role="editor">
+ <organization abbrev="greenbytes">greenbytes GmbH</organization>
+ <address><email>julian.reschke@greenbytes.de</email></address>
+ </author>
+ <date month="June" year="2014" />
+ </front>
+ <seriesInfo name="RFC" value="7234"/>
+ <x:source href="refs/rfc7234.xml"
+ basename="https://svn.tools.ietf.org/svn/wg/httpbis/specs/rfc7234"/>
+ </reference>
+ <reference anchor="RFC7235">
+ <front>
+ <title>Hypertext Transfer Protocol (HTTP/1.1): Authentication</title>
+ <author initials="R." surname="Fielding" fullname="Roy T. Fielding" role="editor">
+ <organization abbrev="Adobe">Adobe Systems Incorporated</organization>
+ <address><email>fielding@gbiv.com</email></address>
+ </author>
+ <author initials="J. F." surname="Reschke" fullname="Julian F. Reschke" role="editor">
+ <organization abbrev="greenbytes">greenbytes GmbH</organization>
+ <address><email>julian.reschke@greenbytes.de</email></address>
+ </author>
+ <date month="June" year="2014" />
+ </front>
+ <seriesInfo name="RFC" value="7235"/>
+ <x:source href="refs/rfc7235.xml"
+ basename="https://svn.tools.ietf.org/svn/wg/httpbis/specs/rfc7235"/>
+ </reference>
+
+ <reference anchor="COOKIE">
+ <front>
+ <title>HTTP State Management Mechanism</title>
+ <author initials="A." surname="Barth" fullname="A. Barth"/>
+ <date year="2011" month="April" />
+ </front>
+ <seriesInfo name="RFC" value="6265" />
+ </reference>
+ </references>
+
+ <references title="Informative References">
+ <reference anchor="RFC1323">
+ <front>
+ <title>
+ TCP Extensions for High Performance
+ </title>
+ <author initials="V." surname="Jacobson" fullname="Van Jacobson"></author>
+ <author initials="B." surname="Braden" fullname="Bob Braden"></author>
+ <author initials="D." surname="Borman" fullname="Dave Borman"></author>
+ <date year="1992" month="May" />
+ </front>
+ <seriesInfo name="RFC" value="1323" />
+ </reference>
+
+ <reference anchor="RFC3749">
+ <front>
+ <title>Transport Layer Security Protocol Compression Methods</title>
+ <author initials="S." surname="Hollenbeck" fullname="S. Hollenbeck"/>
+ <date year="2004" month="May" />
+ </front>
+ <seriesInfo name="RFC" value="3749" />
+ </reference>
+
+ <reference anchor="RFC6585">
+ <front>
+ <title>Additional HTTP Status Codes</title>
+ <author initials="M." surname="Nottingham" fullname="Mark Nottingham"/>
+ <author initials="R." surname="Fielding" fullname="Roy Fielding"/>
+ <date year="2012" month="April" />
+ </front>
+ <seriesInfo name="RFC" value="6585" />
+ </reference>
+
+ <reference anchor="RFC4492">
+ <front>
+ <title>
+ Elliptic Curve Cryptography (ECC) Cipher Suites for Transport Layer Security (TLS)
+ </title>
+ <author initials="S." surname="Blake-Wilson" fullname="S. Blake-Wilson"/>
+ <author initials="N." surname="Bolyard" fullname="N. Bolyard"/>
+ <author initials="V." surname="Gupta" fullname="V. Gupta"/>
+ <author initials="C." surname="Hawk" fullname="C. Hawk"/>
+ <author initials="B." surname="Moeller" fullname="B. Moeller"/>
+ <date year="2006" month="May" />
+ </front>
+ <seriesInfo name="RFC" value="4492" />
+ </reference>
+
+ <reference anchor="RFC5288">
+ <front>
+ <title>
+ AES Galois Counter Mode (GCM) Cipher Suites for TLS
+ </title>
+ <author initials="J." surname="Salowey" fullname="J. Salowey"/>
+ <author initials="A." surname="Choudhury" fullname="A. Choudhury"/>
+ <author initials="D." surname="McGrew" fullname="D. McGrew"/>
+ <date year="2008" month="August" />
+ </front>
+ <seriesInfo name="RFC" value="5288" />
+ </reference>
+
+ <reference anchor='HTML5'
+ target='http://www.w3.org/TR/2014/CR-html5-20140731/'>
+ <front>
+ <title>HTML5</title>
+ <author fullname='Robin Berjon' surname='Berjon' initials='R.'/>
+ <author fullname='Steve Faulkner' surname='Faulkner' initials='S.'/>
+ <author fullname='Travis Leithead' surname='Leithead' initials='T.'/>
+ <author fullname='Erika Doyle Navara' surname='Doyle Navara' initials='E.'/>
+ <author fullname='Edward O&apos;Connor' surname='O&apos;Connor' initials='E.'/>
+ <author fullname='Silvia Pfeiffer' surname='Pfeiffer' initials='S.'/>
+ <date year='2014' month='July' day='31'/>
+ </front>
+ <seriesInfo name='W3C Candidate Recommendation' value='CR-html5-20140731'/>
+ <annotation>
+ Latest version available at
+ <eref target='http://www.w3.org/TR/html5/'/>.
+ </annotation>
+ </reference>
+
+ <reference anchor="TALKING" target="http://w2spconf.com/2011/papers/websocket.pdf">
+ <front>
+ <title>
+ Talking to Yourself for Fun and Profit
+ </title>
+ <author initials="L-S." surname="Huang"/>
+ <author initials="E." surname="Chen"/>
+ <author initials="A." surname="Barth"/>
+ <author initials="E." surname="Rescorla"/>
+ <author initials="C." surname="Jackson"/>
+ <date year="2011" />
+ </front>
+ </reference>
+
+ <reference anchor="BREACH"
+ target="http://breachattack.com/resources/BREACH%20-%20SSL,%20gone%20in%2030%20seconds.pdf">
+ <front>
+ <title>
+ BREACH: Reviving the CRIME Attack
+ </title>
+ <author initials="Y." surname="Gluck"/>
+ <author initials="N." surname="Harris"/>
+ <author initials="A." surname="Prado"/>
+ <date year="2013" month="July" day="12"/>
+ </front>
+ </reference>
+
+ <reference anchor="BCP90">
+ <front>
+ <title>Registration Procedures for Message Header Fields</title>
+ <author initials="G." surname="Klyne" fullname="G. Klyne">
+ <organization>Nine by Nine</organization>
+ <address><email>GK-IETF@ninebynine.org</email></address>
+ </author>
+ <author initials="M." surname="Nottingham" fullname="M. Nottingham">
+ <organization>BEA Systems</organization>
+ <address><email>mnot@pobox.com</email></address>
+ </author>
+ <author initials="J." surname="Mogul" fullname="J. Mogul">
+ <organization>HP Labs</organization>
+ <address><email>JeffMogul@acm.org</email></address>
+ </author>
+ <date year="2004" month="September" />
+ </front>
+ <seriesInfo name="BCP" value="90" />
+ <seriesInfo name="RFC" value="3864" />
+ </reference>
+
+ <reference anchor="TLSBCP">
+ <front>
+ <title>Recommendations for Secure Use of TLS and DTLS</title>
+ <author initials="Y" surname="Sheffer" fullname="Yaron Sheffer">
+ <organization />
+ </author>
+ <author initials="R" surname="Holz" fullname="Ralph Holz">
+ <organization />
+ </author>
+ <author initials="P" surname="Saint-Andre" fullname="Peter Saint-Andre">
+ <organization />
+ </author>
+ <date month="June" day="23" year="2014" />
+ </front>
+ <seriesInfo name="Internet-Draft" value="draft-ietf-uta-tls-bcp-01" />
+ </reference>
+
+ <reference anchor="ALT-SVC">
+ <front>
+ <title>
+ HTTP Alternative Services
+ </title>
+ <author initials="M." surname="Nottingham" fullname="Mark Nottingham">
+ <organization>Akamai</organization>
+ </author>
+ <author initials="P." surname="McManus" fullname="Patrick McManus">
+ <organization>Mozilla</organization>
+ </author>
+ <author initials="J." surname="Reschke" fullname="Julian Reschke">
+ <organization>greenbytes</organization>
+ </author>
+ <date year="2014" month="April"/>
+ </front>
+ <seriesInfo name="Internet-Draft" value="draft-ietf-httpbis-alt-svc-02"/>
+ <x:source href="refs/draft-ietf-httpbis-alt-svc-02.xml"/>
+ </reference>
+ </references>
+
+ <section title="Change Log" anchor="change.log">
+ <t>
+ This section is to be removed by RFC Editor before publication.
+ </t>
+
+ <section title="Since draft-ietf-httpbis-http2-14" anchor="changes.since.draft-ietf-httpbis-http2-14">
+ <t>
+ Renamed Not Authoritative status code to Misdirected Request.
+ </t>
+ </section>
+
+ <section title="Since draft-ietf-httpbis-http2-13" anchor="changes.since.draft-ietf-httpbis-http2-13">
+ <t>
+ Pseudo-header fields are now required to appear strictly before regular ones.
+ </t>
+ <t>
+ Restored 1xx series status codes, except 101.
+ </t>
+ <t>
+ Changed frame length field 24-bits. Expanded frame header to 9 octets. Added a setting
+ to limit the damage.
+ </t>
+ <t>
+ Added a setting to advise peers of header set size limits.
+ </t>
+ <t>
+ Removed segments.
+ </t>
+ <t>
+ Made non-semantic-bearing <x:ref>HEADERS</x:ref> frames illegal in the HTTP mapping.
+ </t>
+ </section>
+
+ <section title="Since draft-ietf-httpbis-http2-12" anchor="changes.since.draft-ietf-httpbis-http2-12">
+ <t>
+ Restored extensibility options.
+ </t>
+ <t>
+ Restricting TLS cipher suites to AEAD only.
+ </t>
+ <t>
+ Removing Content-Encoding requirements.
+ </t>
+ <t>
+ Permitting the use of <x:ref>PRIORITY</x:ref> after stream close.
+ </t>
+ <t>
+ Removed ALTSVC frame.
+ </t>
+ <t>
+ Removed BLOCKED frame.
+ </t>
+ <t>
+ Reducing the maximum padding size to 256 octets; removing padding from
+ <x:ref>CONTINUATION</x:ref> frames.
+ </t>
+ <t>
+ Removed per-frame GZIP compression.
+ </t>
+ </section>
+
+ <section title="Since draft-ietf-httpbis-http2-11" anchor="changes.since.draft-ietf-httpbis-http2-11">
+ <t>
+ Added BLOCKED frame (at risk).
+ </t>
+ <t>
+ Simplified priority scheme.
+ </t>
+ <t>
+ Added <x:ref>DATA</x:ref> per-frame GZIP compression.
+ </t>
+ </section>
+
+ <section title="Since draft-ietf-httpbis-http2-10" anchor="changes.since.draft-ietf-httpbis-http2-10">
+ <t>
+ Changed "connection header" to "connection preface" to avoid confusion.
+ </t>
+ <t>
+ Added dependency-based stream prioritization.
+ </t>
+ <t>
+ Added "h2c" identifier to distinguish between cleartext and secured HTTP/2.
+ </t>
+ <t>
+ Adding missing padding to <x:ref>PUSH_PROMISE</x:ref>.
+ </t>
+ <t>
+ Integrate ALTSVC frame and supporting text.
+ </t>
+ <t>
+ Dropping requirement on "deflate" Content-Encoding.
+ </t>
+ <t>
+ Improving security considerations around use of compression.
+ </t>
+ </section>
+
+ <section title="Since draft-ietf-httpbis-http2-09" anchor="changes.since.draft-ietf-httpbis-http2-09">
+ <t>
+ Adding padding for data frames.
+ </t>
+ <t>
+ Renumbering frame types, error codes, and settings.
+ </t>
+ <t>
+ Adding INADEQUATE_SECURITY error code.
+ </t>
+ <t>
+ Updating TLS usage requirements to 1.2; forbidding TLS compression.
+ </t>
+ <t>
+ Removing extensibility for frames and settings.
+ </t>
+ <t>
+ Changing setting identifier size.
+ </t>
+ <t>
+ Removing the ability to disable flow control.
+ </t>
+ <t>
+ Changing the protocol identification token to "h2".
+ </t>
+ <t>
+ Changing the use of :authority to make it optional and to allow userinfo in non-HTTP
+ cases.
+ </t>
+ <t>
+ Allowing split on 0x0 for Cookie.
+ </t>
+ <t>
+ Reserved PRI method in HTTP/1.1 to avoid possible future collisions.
+ </t>
+ </section>
+
+ <section title="Since draft-ietf-httpbis-http2-08" anchor="changes.since.draft-ietf-httpbis-http2-08">
+ <t>
+ Added cookie crumbling for more efficient header compression.
+ </t>
+ <t>
+ Added header field ordering with the value-concatenation mechanism.
+ </t>
+ </section>
+
+ <section title="Since draft-ietf-httpbis-http2-07" anchor="changes.since.draft-ietf-httpbis-http2-07">
+ <t>
+ Marked draft for implementation.
+ </t>
+ </section>
+
+ <section title="Since draft-ietf-httpbis-http2-06" anchor="changes.since.draft-ietf-httpbis-http2-06">
+ <t>
+ Adding definition for CONNECT method.
+ </t>
+ <t>
+ Constraining the use of push to safe, cacheable methods with no request body.
+ </t>
+ <t>
+ Changing from :host to :authority to remove any potential confusion.
+ </t>
+ <t>
+ Adding setting for header compression table size.
+ </t>
+ <t>
+ Adding settings acknowledgement.
+ </t>
+ <t>
+ Removing unnecessary and potentially problematic flags from CONTINUATION.
+ </t>
+ <t>
+ Added denial of service considerations.
+ </t>
+ </section>
+ <section title="Since draft-ietf-httpbis-http2-05" anchor="changes.since.draft-ietf-httpbis-http2-05">
+ <t>
+ Marking the draft ready for implementation.
+ </t>
+ <t>
+ Renumbering END_PUSH_PROMISE flag.
+ </t>
+ <t>
+ Editorial clarifications and changes.
+ </t>
+ </section>
+
+ <section title="Since draft-ietf-httpbis-http2-04" anchor="changes.since.draft-ietf-httpbis-http2-04">
+ <t>
+ Added CONTINUATION frame for HEADERS and PUSH_PROMISE.
+ </t>
+ <t>
+ PUSH_PROMISE is no longer implicitly prohibited if SETTINGS_MAX_CONCURRENT_STREAMS is
+ zero.
+ </t>
+ <t>
+ Push expanded to allow all safe methods without a request body.
+ </t>
+ <t>
+ Clarified the use of HTTP header fields in requests and responses. Prohibited HTTP/1.1
+ hop-by-hop header fields.
+ </t>
+ <t>
+ Requiring that intermediaries not forward requests with missing or illegal routing
+ :-headers.
+ </t>
+ <t>
+ Clarified requirements around handling different frames after stream close, stream reset
+ and <x:ref>GOAWAY</x:ref>.
+ </t>
+ <t>
+ Added more specific prohibitions for sending of different frame types in various stream
+ states.
+ </t>
+ <t>
+ Making the last received setting value the effective value.
+ </t>
+ <t>
+ Clarified requirements on TLS version, extension and ciphers.
+ </t>
+ </section>
+
+ <section title="Since draft-ietf-httpbis-http2-03" anchor="changes.since.draft-ietf-httpbis-http2-03">
+ <t>
+ Committed major restructuring atrocities.
+ </t>
+ <t>
+ Added reference to first header compression draft.
+ </t>
+ <t>
+ Added more formal description of frame lifecycle.
+ </t>
+ <t>
+ Moved END_STREAM (renamed from FINAL) back to <x:ref>HEADERS</x:ref>/<x:ref>DATA</x:ref>.
+ </t>
+ <t>
+ Removed HEADERS+PRIORITY, added optional priority to <x:ref>HEADERS</x:ref> frame.
+ </t>
+ <t>
+ Added <x:ref>PRIORITY</x:ref> frame.
+ </t>
+ </section>
+
+ <section title="Since draft-ietf-httpbis-http2-02" anchor="changes.since.draft-ietf-httpbis-http2-02">
+ <t>
+ Added continuations to frames carrying header blocks.
+ </t>
+ <t>
+ Replaced use of "session" with "connection" to avoid confusion with other HTTP stateful
+ concepts, like cookies.
+ </t>
+ <t>
+ Removed "message".
+ </t>
+ <t>
+ Switched to TLS ALPN from NPN.
+ </t>
+ <t>
+ Editorial changes.
+ </t>
+ </section>
+
+ <section title="Since draft-ietf-httpbis-http2-01" anchor="changes.since.draft-ietf-httpbis-http2-01">
+ <t>
+ Added IANA considerations section for frame types, error codes and settings.
+ </t>
+ <t>
+ Removed data frame compression.
+ </t>
+ <t>
+ Added <x:ref>PUSH_PROMISE</x:ref>.
+ </t>
+ <t>
+ Added globally applicable flags to framing.
+ </t>
+ <t>
+ Removed zlib-based header compression mechanism.
+ </t>
+ <t>
+ Updated references.
+ </t>
+ <t>
+ Clarified stream identifier reuse.
+ </t>
+ <t>
+ Removed CREDENTIALS frame and associated mechanisms.
+ </t>
+ <t>
+ Added advice against naive implementation of flow control.
+ </t>
+ <t>
+ Added session header section.
+ </t>
+ <t>
+ Restructured frame header. Removed distinction between data and control frames.
+ </t>
+ <t>
+ Altered flow control properties to include session-level limits.
+ </t>
+ <t>
+ Added note on cacheability of pushed resources and multiple tenant servers.
+ </t>
+ <t>
+ Changed protocol label form based on discussions.
+ </t>
+ </section>
+
+ <section title="Since draft-ietf-httpbis-http2-00" anchor="changes.since.draft-ietf-httpbis-http2-00">
+ <t>
+ Changed title throughout.
+ </t>
+ <t>
+ Removed section on Incompatibilities with SPDY draft#2.
+ </t>
+ <t>
+ Changed <x:ref>INTERNAL_ERROR</x:ref> on <x:ref>GOAWAY</x:ref> to have a value of 2 <eref
+ target="https://groups.google.com/forum/?fromgroups#!topic/spdy-dev/cfUef2gL3iU"/>.
+ </t>
+ <t>
+ Replaced abstract and introduction.
+ </t>
+ <t>
+ Added section on starting HTTP/2.0, including upgrade mechanism.
+ </t>
+ <t>
+ Removed unused references.
+ </t>
+ <t>
+ Added <xref target="fc-principles">flow control principles</xref> based on <eref
+ target="https://tools.ietf.org/html/draft-montenegro-httpbis-http2-fc-principles-01"/>.
+ </t>
+ </section>
+
+ <section title="Since draft-mbelshe-httpbis-spdy-00" anchor="changes.since.draft-mbelshe-httpbis-spdy-00">
+ <t>
+ Adopted as base for draft-ietf-httpbis-http2.
+ </t>
+ <t>
+ Updated authors/editors list.
+ </t>
+ <t>
+ Added status note.
+ </t>
+ </section>
+ </section>
+
+ </back>
+</rfc>
+<!--
+ vim:et:tw=100:sw=2:
+ -->
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/transport.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/transport.go
new file mode 100644
index 000000000..c65f1a397
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/transport.go
@@ -0,0 +1,2284 @@
+// Copyright 2015 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.
+
+// Transport code.
+
+package http2
+
+import (
+ "bufio"
+ "bytes"
+ "compress/gzip"
+ "crypto/rand"
+ "crypto/tls"
+ "errors"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "log"
+ "math"
+ mathrand "math/rand"
+ "net"
+ "net/http"
+ "sort"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+
+ "golang.org/x/net/http2/hpack"
+ "golang.org/x/net/idna"
+ "golang.org/x/net/lex/httplex"
+)
+
+const (
+ // transportDefaultConnFlow is how many connection-level flow control
+ // tokens we give the server at start-up, past the default 64k.
+ transportDefaultConnFlow = 1 << 30
+
+ // transportDefaultStreamFlow is how many stream-level flow
+ // control tokens we announce to the peer, and how many bytes
+ // we buffer per stream.
+ transportDefaultStreamFlow = 4 << 20
+
+ // transportDefaultStreamMinRefresh is the minimum number of bytes we'll send
+ // a stream-level WINDOW_UPDATE for at a time.
+ transportDefaultStreamMinRefresh = 4 << 10
+
+ defaultUserAgent = "Go-http-client/2.0"
+)
+
+// Transport is an HTTP/2 Transport.
+//
+// A Transport internally caches connections to servers. It is safe
+// for concurrent use by multiple goroutines.
+type Transport struct {
+ // DialTLS specifies an optional dial function for creating
+ // TLS connections for requests.
+ //
+ // If DialTLS is nil, tls.Dial is used.
+ //
+ // If the returned net.Conn has a ConnectionState method like tls.Conn,
+ // it will be used to set http.Response.TLS.
+ DialTLS func(network, addr string, cfg *tls.Config) (net.Conn, error)
+
+ // TLSClientConfig specifies the TLS configuration to use with
+ // tls.Client. If nil, the default configuration is used.
+ TLSClientConfig *tls.Config
+
+ // ConnPool optionally specifies an alternate connection pool to use.
+ // If nil, the default is used.
+ ConnPool ClientConnPool
+
+ // DisableCompression, if true, prevents the Transport from
+ // requesting compression with an "Accept-Encoding: gzip"
+ // request header when the Request contains no existing
+ // Accept-Encoding value. If the Transport requests gzip on
+ // its own and gets a gzipped response, it's transparently
+ // decoded in the Response.Body. However, if the user
+ // explicitly requested gzip it is not automatically
+ // uncompressed.
+ DisableCompression bool
+
+ // AllowHTTP, if true, permits HTTP/2 requests using the insecure,
+ // plain-text "http" scheme. Note that this does not enable h2c support.
+ AllowHTTP bool
+
+ // MaxHeaderListSize is the http2 SETTINGS_MAX_HEADER_LIST_SIZE to
+ // send in the initial settings frame. It is how many bytes
+ // of response headers are allowed. Unlike the http2 spec, zero here
+ // means to use a default limit (currently 10MB). If you actually
+ // want to advertise an ulimited value to the peer, Transport
+ // interprets the highest possible value here (0xffffffff or 1<<32-1)
+ // to mean no limit.
+ MaxHeaderListSize uint32
+
+ // t1, if non-nil, is the standard library Transport using
+ // this transport. Its settings are used (but not its
+ // RoundTrip method, etc).
+ t1 *http.Transport
+
+ connPoolOnce sync.Once
+ connPoolOrDef ClientConnPool // non-nil version of ConnPool
+}
+
+func (t *Transport) maxHeaderListSize() uint32 {
+ if t.MaxHeaderListSize == 0 {
+ return 10 << 20
+ }
+ if t.MaxHeaderListSize == 0xffffffff {
+ return 0
+ }
+ return t.MaxHeaderListSize
+}
+
+func (t *Transport) disableCompression() bool {
+ return t.DisableCompression || (t.t1 != nil && t.t1.DisableCompression)
+}
+
+var errTransportVersion = errors.New("http2: ConfigureTransport is only supported starting at Go 1.6")
+
+// ConfigureTransport configures a net/http HTTP/1 Transport to use HTTP/2.
+// It requires Go 1.6 or later and returns an error if the net/http package is too old
+// or if t1 has already been HTTP/2-enabled.
+func ConfigureTransport(t1 *http.Transport) error {
+ _, err := configureTransport(t1) // in configure_transport.go (go1.6) or not_go16.go
+ return err
+}
+
+func (t *Transport) connPool() ClientConnPool {
+ t.connPoolOnce.Do(t.initConnPool)
+ return t.connPoolOrDef
+}
+
+func (t *Transport) initConnPool() {
+ if t.ConnPool != nil {
+ t.connPoolOrDef = t.ConnPool
+ } else {
+ t.connPoolOrDef = &clientConnPool{t: t}
+ }
+}
+
+// ClientConn is the state of a single HTTP/2 client connection to an
+// HTTP/2 server.
+type ClientConn struct {
+ t *Transport
+ tconn net.Conn // usually *tls.Conn, except specialized impls
+ tlsState *tls.ConnectionState // nil only for specialized impls
+ singleUse bool // whether being used for a single http.Request
+
+ // readLoop goroutine fields:
+ readerDone chan struct{} // closed on error
+ readerErr error // set before readerDone is closed
+
+ idleTimeout time.Duration // or 0 for never
+ idleTimer *time.Timer
+
+ mu sync.Mutex // guards following
+ cond *sync.Cond // hold mu; broadcast on flow/closed changes
+ flow flow // our conn-level flow control quota (cs.flow is per stream)
+ inflow flow // peer's conn-level flow control
+ closed bool
+ wantSettingsAck bool // we sent a SETTINGS frame and haven't heard back
+ goAway *GoAwayFrame // if non-nil, the GoAwayFrame we received
+ goAwayDebug string // goAway frame's debug data, retained as a string
+ streams map[uint32]*clientStream // client-initiated
+ nextStreamID uint32
+ pendingRequests int // requests blocked and waiting to be sent because len(streams) == maxConcurrentStreams
+ pings map[[8]byte]chan struct{} // in flight ping data to notification channel
+ bw *bufio.Writer
+ br *bufio.Reader
+ fr *Framer
+ lastActive time.Time
+ // Settings from peer: (also guarded by mu)
+ maxFrameSize uint32
+ maxConcurrentStreams uint32
+ peerMaxHeaderListSize uint64
+ initialWindowSize uint32
+
+ hbuf bytes.Buffer // HPACK encoder writes into this
+ henc *hpack.Encoder
+ freeBuf [][]byte
+
+ wmu sync.Mutex // held while writing; acquire AFTER mu if holding both
+ werr error // first write error that has occurred
+}
+
+// clientStream is the state for a single HTTP/2 stream. One of these
+// is created for each Transport.RoundTrip call.
+type clientStream struct {
+ cc *ClientConn
+ req *http.Request
+ trace *clientTrace // or nil
+ ID uint32
+ resc chan resAndError
+ bufPipe pipe // buffered pipe with the flow-controlled response payload
+ startedWrite bool // started request body write; guarded by cc.mu
+ requestedGzip bool
+ on100 func() // optional code to run if get a 100 continue response
+
+ flow flow // guarded by cc.mu
+ inflow flow // guarded by cc.mu
+ bytesRemain int64 // -1 means unknown; owned by transportResponseBody.Read
+ readErr error // sticky read error; owned by transportResponseBody.Read
+ stopReqBody error // if non-nil, stop writing req body; guarded by cc.mu
+ didReset bool // whether we sent a RST_STREAM to the server; guarded by cc.mu
+
+ peerReset chan struct{} // closed on peer reset
+ resetErr error // populated before peerReset is closed
+
+ done chan struct{} // closed when stream remove from cc.streams map; close calls guarded by cc.mu
+
+ // owned by clientConnReadLoop:
+ firstByte bool // got the first response byte
+ pastHeaders bool // got first MetaHeadersFrame (actual headers)
+ pastTrailers bool // got optional second MetaHeadersFrame (trailers)
+
+ trailer http.Header // accumulated trailers
+ resTrailer *http.Header // client's Response.Trailer
+}
+
+// awaitRequestCancel waits for the user to cancel a request or for the done
+// channel to be signaled. A non-nil error is returned only if the request was
+// canceled.
+func awaitRequestCancel(req *http.Request, done <-chan struct{}) error {
+ ctx := reqContext(req)
+ if req.Cancel == nil && ctx.Done() == nil {
+ return nil
+ }
+ select {
+ case <-req.Cancel:
+ return errRequestCanceled
+ case <-ctx.Done():
+ return ctx.Err()
+ case <-done:
+ return nil
+ }
+}
+
+// awaitRequestCancel waits for the user to cancel a request, its context to
+// expire, or for the request to be done (any way it might be removed from the
+// cc.streams map: peer reset, successful completion, TCP connection breakage,
+// etc). If the request is canceled, then cs will be canceled and closed.
+func (cs *clientStream) awaitRequestCancel(req *http.Request) {
+ if err := awaitRequestCancel(req, cs.done); err != nil {
+ cs.cancelStream()
+ cs.bufPipe.CloseWithError(err)
+ }
+}
+
+func (cs *clientStream) cancelStream() {
+ cc := cs.cc
+ cc.mu.Lock()
+ didReset := cs.didReset
+ cs.didReset = true
+ cc.mu.Unlock()
+
+ if !didReset {
+ cc.writeStreamReset(cs.ID, ErrCodeCancel, nil)
+ cc.forgetStreamID(cs.ID)
+ }
+}
+
+// checkResetOrDone reports any error sent in a RST_STREAM frame by the
+// server, or errStreamClosed if the stream is complete.
+func (cs *clientStream) checkResetOrDone() error {
+ select {
+ case <-cs.peerReset:
+ return cs.resetErr
+ case <-cs.done:
+ return errStreamClosed
+ default:
+ return nil
+ }
+}
+
+func (cs *clientStream) getStartedWrite() bool {
+ cc := cs.cc
+ cc.mu.Lock()
+ defer cc.mu.Unlock()
+ return cs.startedWrite
+}
+
+func (cs *clientStream) abortRequestBodyWrite(err error) {
+ if err == nil {
+ panic("nil error")
+ }
+ cc := cs.cc
+ cc.mu.Lock()
+ cs.stopReqBody = err
+ cc.cond.Broadcast()
+ cc.mu.Unlock()
+}
+
+type stickyErrWriter struct {
+ w io.Writer
+ err *error
+}
+
+func (sew stickyErrWriter) Write(p []byte) (n int, err error) {
+ if *sew.err != nil {
+ return 0, *sew.err
+ }
+ n, err = sew.w.Write(p)
+ *sew.err = err
+ return
+}
+
+var ErrNoCachedConn = errors.New("http2: no cached connection was available")
+
+// RoundTripOpt are options for the Transport.RoundTripOpt method.
+type RoundTripOpt struct {
+ // OnlyCachedConn controls whether RoundTripOpt may
+ // create a new TCP connection. If set true and
+ // no cached connection is available, RoundTripOpt
+ // will return ErrNoCachedConn.
+ OnlyCachedConn bool
+}
+
+func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) {
+ return t.RoundTripOpt(req, RoundTripOpt{})
+}
+
+// authorityAddr returns a given authority (a host/IP, or host:port / ip:port)
+// and returns a host:port. The port 443 is added if needed.
+func authorityAddr(scheme string, authority string) (addr string) {
+ host, port, err := net.SplitHostPort(authority)
+ if err != nil { // authority didn't have a port
+ port = "443"
+ if scheme == "http" {
+ port = "80"
+ }
+ host = authority
+ }
+ if a, err := idna.ToASCII(host); err == nil {
+ host = a
+ }
+ // IPv6 address literal, without a port:
+ if strings.HasPrefix(host, "[") && strings.HasSuffix(host, "]") {
+ return host + ":" + port
+ }
+ return net.JoinHostPort(host, port)
+}
+
+// RoundTripOpt is like RoundTrip, but takes options.
+func (t *Transport) RoundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Response, error) {
+ if !(req.URL.Scheme == "https" || (req.URL.Scheme == "http" && t.AllowHTTP)) {
+ return nil, errors.New("http2: unsupported scheme")
+ }
+
+ addr := authorityAddr(req.URL.Scheme, req.URL.Host)
+ for retry := 0; ; retry++ {
+ cc, err := t.connPool().GetClientConn(req, addr)
+ if err != nil {
+ t.vlogf("http2: Transport failed to get client conn for %s: %v", addr, err)
+ return nil, err
+ }
+ traceGotConn(req, cc)
+ res, gotErrAfterReqBodyWrite, err := cc.roundTrip(req)
+ if err != nil && retry <= 6 {
+ if req, err = shouldRetryRequest(req, err, gotErrAfterReqBodyWrite); err == nil {
+ // After the first retry, do exponential backoff with 10% jitter.
+ if retry == 0 {
+ continue
+ }
+ backoff := float64(uint(1) << (uint(retry) - 1))
+ backoff += backoff * (0.1 * mathrand.Float64())
+ select {
+ case <-time.After(time.Second * time.Duration(backoff)):
+ continue
+ case <-reqContext(req).Done():
+ return nil, reqContext(req).Err()
+ }
+ }
+ }
+ if err != nil {
+ t.vlogf("RoundTrip failure: %v", err)
+ return nil, err
+ }
+ return res, nil
+ }
+}
+
+// CloseIdleConnections closes any connections which were previously
+// connected from previous requests but are now sitting idle.
+// It does not interrupt any connections currently in use.
+func (t *Transport) CloseIdleConnections() {
+ if cp, ok := t.connPool().(clientConnPoolIdleCloser); ok {
+ cp.closeIdleConnections()
+ }
+}
+
+var (
+ errClientConnClosed = errors.New("http2: client conn is closed")
+ errClientConnUnusable = errors.New("http2: client conn not usable")
+ errClientConnGotGoAway = errors.New("http2: Transport received Server's graceful shutdown GOAWAY")
+)
+
+// shouldRetryRequest is called by RoundTrip when a request fails to get
+// response headers. It is always called with a non-nil error.
+// It returns either a request to retry (either the same request, or a
+// modified clone), or an error if the request can't be replayed.
+func shouldRetryRequest(req *http.Request, err error, afterBodyWrite bool) (*http.Request, error) {
+ if !canRetryError(err) {
+ return nil, err
+ }
+ if !afterBodyWrite {
+ return req, nil
+ }
+ // If the Body is nil (or http.NoBody), it's safe to reuse
+ // this request and its Body.
+ if req.Body == nil || reqBodyIsNoBody(req.Body) {
+ return req, nil
+ }
+ // Otherwise we depend on the Request having its GetBody
+ // func defined.
+ getBody := reqGetBody(req) // Go 1.8: getBody = req.GetBody
+ if getBody == nil {
+ return nil, fmt.Errorf("http2: Transport: cannot retry err [%v] after Request.Body was written; define Request.GetBody to avoid this error", err)
+ }
+ body, err := getBody()
+ if err != nil {
+ return nil, err
+ }
+ newReq := *req
+ newReq.Body = body
+ return &newReq, nil
+}
+
+func canRetryError(err error) bool {
+ if err == errClientConnUnusable || err == errClientConnGotGoAway {
+ return true
+ }
+ if se, ok := err.(StreamError); ok {
+ return se.Code == ErrCodeRefusedStream
+ }
+ return false
+}
+
+func (t *Transport) dialClientConn(addr string, singleUse bool) (*ClientConn, error) {
+ host, _, err := net.SplitHostPort(addr)
+ if err != nil {
+ return nil, err
+ }
+ tconn, err := t.dialTLS()("tcp", addr, t.newTLSConfig(host))
+ if err != nil {
+ return nil, err
+ }
+ return t.newClientConn(tconn, singleUse)
+}
+
+func (t *Transport) newTLSConfig(host string) *tls.Config {
+ cfg := new(tls.Config)
+ if t.TLSClientConfig != nil {
+ *cfg = *cloneTLSConfig(t.TLSClientConfig)
+ }
+ if !strSliceContains(cfg.NextProtos, NextProtoTLS) {
+ cfg.NextProtos = append([]string{NextProtoTLS}, cfg.NextProtos...)
+ }
+ if cfg.ServerName == "" {
+ cfg.ServerName = host
+ }
+ return cfg
+}
+
+func (t *Transport) dialTLS() func(string, string, *tls.Config) (net.Conn, error) {
+ if t.DialTLS != nil {
+ return t.DialTLS
+ }
+ return t.dialTLSDefault
+}
+
+func (t *Transport) dialTLSDefault(network, addr string, cfg *tls.Config) (net.Conn, error) {
+ cn, err := tls.Dial(network, addr, cfg)
+ if err != nil {
+ return nil, err
+ }
+ if err := cn.Handshake(); err != nil {
+ return nil, err
+ }
+ if !cfg.InsecureSkipVerify {
+ if err := cn.VerifyHostname(cfg.ServerName); err != nil {
+ return nil, err
+ }
+ }
+ state := cn.ConnectionState()
+ if p := state.NegotiatedProtocol; p != NextProtoTLS {
+ return nil, fmt.Errorf("http2: unexpected ALPN protocol %q; want %q", p, NextProtoTLS)
+ }
+ if !state.NegotiatedProtocolIsMutual {
+ return nil, errors.New("http2: could not negotiate protocol mutually")
+ }
+ return cn, nil
+}
+
+// disableKeepAlives reports whether connections should be closed as
+// soon as possible after handling the first request.
+func (t *Transport) disableKeepAlives() bool {
+ return t.t1 != nil && t.t1.DisableKeepAlives
+}
+
+func (t *Transport) expectContinueTimeout() time.Duration {
+ if t.t1 == nil {
+ return 0
+ }
+ return transportExpectContinueTimeout(t.t1)
+}
+
+func (t *Transport) NewClientConn(c net.Conn) (*ClientConn, error) {
+ return t.newClientConn(c, false)
+}
+
+func (t *Transport) newClientConn(c net.Conn, singleUse bool) (*ClientConn, error) {
+ cc := &ClientConn{
+ t: t,
+ tconn: c,
+ readerDone: make(chan struct{}),
+ nextStreamID: 1,
+ maxFrameSize: 16 << 10, // spec default
+ initialWindowSize: 65535, // spec default
+ maxConcurrentStreams: 1000, // "infinite", per spec. 1000 seems good enough.
+ peerMaxHeaderListSize: 0xffffffffffffffff, // "infinite", per spec. Use 2^64-1 instead.
+ streams: make(map[uint32]*clientStream),
+ singleUse: singleUse,
+ wantSettingsAck: true,
+ pings: make(map[[8]byte]chan struct{}),
+ }
+ if d := t.idleConnTimeout(); d != 0 {
+ cc.idleTimeout = d
+ cc.idleTimer = time.AfterFunc(d, cc.onIdleTimeout)
+ }
+ if VerboseLogs {
+ t.vlogf("http2: Transport creating client conn %p to %v", cc, c.RemoteAddr())
+ }
+
+ cc.cond = sync.NewCond(&cc.mu)
+ cc.flow.add(int32(initialWindowSize))
+
+ // TODO: adjust this writer size to account for frame size +
+ // MTU + crypto/tls record padding.
+ cc.bw = bufio.NewWriter(stickyErrWriter{c, &cc.werr})
+ cc.br = bufio.NewReader(c)
+ cc.fr = NewFramer(cc.bw, cc.br)
+ cc.fr.ReadMetaHeaders = hpack.NewDecoder(initialHeaderTableSize, nil)
+ cc.fr.MaxHeaderListSize = t.maxHeaderListSize()
+
+ // TODO: SetMaxDynamicTableSize, SetMaxDynamicTableSizeLimit on
+ // henc in response to SETTINGS frames?
+ cc.henc = hpack.NewEncoder(&cc.hbuf)
+
+ if cs, ok := c.(connectionStater); ok {
+ state := cs.ConnectionState()
+ cc.tlsState = &state
+ }
+
+ initialSettings := []Setting{
+ {ID: SettingEnablePush, Val: 0},
+ {ID: SettingInitialWindowSize, Val: transportDefaultStreamFlow},
+ }
+ if max := t.maxHeaderListSize(); max != 0 {
+ initialSettings = append(initialSettings, Setting{ID: SettingMaxHeaderListSize, Val: max})
+ }
+
+ cc.bw.Write(clientPreface)
+ cc.fr.WriteSettings(initialSettings...)
+ cc.fr.WriteWindowUpdate(0, transportDefaultConnFlow)
+ cc.inflow.add(transportDefaultConnFlow + initialWindowSize)
+ cc.bw.Flush()
+ if cc.werr != nil {
+ return nil, cc.werr
+ }
+
+ go cc.readLoop()
+ return cc, nil
+}
+
+func (cc *ClientConn) setGoAway(f *GoAwayFrame) {
+ cc.mu.Lock()
+ defer cc.mu.Unlock()
+
+ old := cc.goAway
+ cc.goAway = f
+
+ // Merge the previous and current GoAway error frames.
+ if cc.goAwayDebug == "" {
+ cc.goAwayDebug = string(f.DebugData())
+ }
+ if old != nil && old.ErrCode != ErrCodeNo {
+ cc.goAway.ErrCode = old.ErrCode
+ }
+ last := f.LastStreamID
+ for streamID, cs := range cc.streams {
+ if streamID > last {
+ select {
+ case cs.resc <- resAndError{err: errClientConnGotGoAway}:
+ default:
+ }
+ }
+ }
+}
+
+// CanTakeNewRequest reports whether the connection can take a new request,
+// meaning it has not been closed or received or sent a GOAWAY.
+func (cc *ClientConn) CanTakeNewRequest() bool {
+ cc.mu.Lock()
+ defer cc.mu.Unlock()
+ return cc.canTakeNewRequestLocked()
+}
+
+func (cc *ClientConn) canTakeNewRequestLocked() bool {
+ if cc.singleUse && cc.nextStreamID > 1 {
+ return false
+ }
+ return cc.goAway == nil && !cc.closed &&
+ int64(cc.nextStreamID)+int64(cc.pendingRequests) < math.MaxInt32
+}
+
+// onIdleTimeout is called from a time.AfterFunc goroutine. It will
+// only be called when we're idle, but because we're coming from a new
+// goroutine, there could be a new request coming in at the same time,
+// so this simply calls the synchronized closeIfIdle to shut down this
+// connection. The timer could just call closeIfIdle, but this is more
+// clear.
+func (cc *ClientConn) onIdleTimeout() {
+ cc.closeIfIdle()
+}
+
+func (cc *ClientConn) closeIfIdle() {
+ cc.mu.Lock()
+ if len(cc.streams) > 0 {
+ cc.mu.Unlock()
+ return
+ }
+ cc.closed = true
+ nextID := cc.nextStreamID
+ // TODO: do clients send GOAWAY too? maybe? Just Close:
+ cc.mu.Unlock()
+
+ if VerboseLogs {
+ cc.vlogf("http2: Transport closing idle conn %p (forSingleUse=%v, maxStream=%v)", cc, cc.singleUse, nextID-2)
+ }
+ cc.tconn.Close()
+}
+
+const maxAllocFrameSize = 512 << 10
+
+// frameBuffer returns a scratch buffer suitable for writing DATA frames.
+// They're capped at the min of the peer's max frame size or 512KB
+// (kinda arbitrarily), but definitely capped so we don't allocate 4GB
+// bufers.
+func (cc *ClientConn) frameScratchBuffer() []byte {
+ cc.mu.Lock()
+ size := cc.maxFrameSize
+ if size > maxAllocFrameSize {
+ size = maxAllocFrameSize
+ }
+ for i, buf := range cc.freeBuf {
+ if len(buf) >= int(size) {
+ cc.freeBuf[i] = nil
+ cc.mu.Unlock()
+ return buf[:size]
+ }
+ }
+ cc.mu.Unlock()
+ return make([]byte, size)
+}
+
+func (cc *ClientConn) putFrameScratchBuffer(buf []byte) {
+ cc.mu.Lock()
+ defer cc.mu.Unlock()
+ const maxBufs = 4 // arbitrary; 4 concurrent requests per conn? investigate.
+ if len(cc.freeBuf) < maxBufs {
+ cc.freeBuf = append(cc.freeBuf, buf)
+ return
+ }
+ for i, old := range cc.freeBuf {
+ if old == nil {
+ cc.freeBuf[i] = buf
+ return
+ }
+ }
+ // forget about it.
+}
+
+// errRequestCanceled is a copy of net/http's errRequestCanceled because it's not
+// exported. At least they'll be DeepEqual for h1-vs-h2 comparisons tests.
+var errRequestCanceled = errors.New("net/http: request canceled")
+
+func commaSeparatedTrailers(req *http.Request) (string, error) {
+ keys := make([]string, 0, len(req.Trailer))
+ for k := range req.Trailer {
+ k = http.CanonicalHeaderKey(k)
+ switch k {
+ case "Transfer-Encoding", "Trailer", "Content-Length":
+ return "", &badStringError{"invalid Trailer key", k}
+ }
+ keys = append(keys, k)
+ }
+ if len(keys) > 0 {
+ sort.Strings(keys)
+ return strings.Join(keys, ","), nil
+ }
+ return "", nil
+}
+
+func (cc *ClientConn) responseHeaderTimeout() time.Duration {
+ if cc.t.t1 != nil {
+ return cc.t.t1.ResponseHeaderTimeout
+ }
+ // No way to do this (yet?) with just an http2.Transport. Probably
+ // no need. Request.Cancel this is the new way. We only need to support
+ // this for compatibility with the old http.Transport fields when
+ // we're doing transparent http2.
+ return 0
+}
+
+// checkConnHeaders checks whether req has any invalid connection-level headers.
+// per RFC 7540 section 8.1.2.2: Connection-Specific Header Fields.
+// Certain headers are special-cased as okay but not transmitted later.
+func checkConnHeaders(req *http.Request) error {
+ if v := req.Header.Get("Upgrade"); v != "" {
+ return fmt.Errorf("http2: invalid Upgrade request header: %q", req.Header["Upgrade"])
+ }
+ if vv := req.Header["Transfer-Encoding"]; len(vv) > 0 && (len(vv) > 1 || vv[0] != "" && vv[0] != "chunked") {
+ return fmt.Errorf("http2: invalid Transfer-Encoding request header: %q", vv)
+ }
+ if vv := req.Header["Connection"]; len(vv) > 0 && (len(vv) > 1 || vv[0] != "" && vv[0] != "close" && vv[0] != "keep-alive") {
+ return fmt.Errorf("http2: invalid Connection request header: %q", vv)
+ }
+ return nil
+}
+
+// actualContentLength returns a sanitized version of
+// req.ContentLength, where 0 actually means zero (not unknown) and -1
+// means unknown.
+func actualContentLength(req *http.Request) int64 {
+ if req.Body == nil || reqBodyIsNoBody(req.Body) {
+ return 0
+ }
+ if req.ContentLength != 0 {
+ return req.ContentLength
+ }
+ return -1
+}
+
+func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
+ resp, _, err := cc.roundTrip(req)
+ return resp, err
+}
+
+func (cc *ClientConn) roundTrip(req *http.Request) (res *http.Response, gotErrAfterReqBodyWrite bool, err error) {
+ if err := checkConnHeaders(req); err != nil {
+ return nil, false, err
+ }
+ if cc.idleTimer != nil {
+ cc.idleTimer.Stop()
+ }
+
+ trailers, err := commaSeparatedTrailers(req)
+ if err != nil {
+ return nil, false, err
+ }
+ hasTrailers := trailers != ""
+
+ cc.mu.Lock()
+ if err := cc.awaitOpenSlotForRequest(req); err != nil {
+ cc.mu.Unlock()
+ return nil, false, err
+ }
+
+ body := req.Body
+ contentLen := actualContentLength(req)
+ hasBody := contentLen != 0
+
+ // TODO(bradfitz): this is a copy of the logic in net/http. Unify somewhere?
+ var requestedGzip bool
+ if !cc.t.disableCompression() &&
+ req.Header.Get("Accept-Encoding") == "" &&
+ req.Header.Get("Range") == "" &&
+ req.Method != "HEAD" {
+ // Request gzip only, not deflate. Deflate is ambiguous and
+ // not as universally supported anyway.
+ // See: http://www.gzip.org/zlib/zlib_faq.html#faq38
+ //
+ // Note that we don't request this for HEAD requests,
+ // due to a bug in nginx:
+ // http://trac.nginx.org/nginx/ticket/358
+ // https://golang.org/issue/5522
+ //
+ // We don't request gzip if the request is for a range, since
+ // auto-decoding a portion of a gzipped document will just fail
+ // anyway. See https://golang.org/issue/8923
+ requestedGzip = true
+ }
+
+ // we send: HEADERS{1}, CONTINUATION{0,} + DATA{0,} (DATA is
+ // sent by writeRequestBody below, along with any Trailers,
+ // again in form HEADERS{1}, CONTINUATION{0,})
+ hdrs, err := cc.encodeHeaders(req, requestedGzip, trailers, contentLen)
+ if err != nil {
+ cc.mu.Unlock()
+ return nil, false, err
+ }
+
+ cs := cc.newStream()
+ cs.req = req
+ cs.trace = requestTrace(req)
+ cs.requestedGzip = requestedGzip
+ bodyWriter := cc.t.getBodyWriterState(cs, body)
+ cs.on100 = bodyWriter.on100
+
+ cc.wmu.Lock()
+ endStream := !hasBody && !hasTrailers
+ werr := cc.writeHeaders(cs.ID, endStream, int(cc.maxFrameSize), hdrs)
+ cc.wmu.Unlock()
+ traceWroteHeaders(cs.trace)
+ cc.mu.Unlock()
+
+ if werr != nil {
+ if hasBody {
+ req.Body.Close() // per RoundTripper contract
+ bodyWriter.cancel()
+ }
+ cc.forgetStreamID(cs.ID)
+ // Don't bother sending a RST_STREAM (our write already failed;
+ // no need to keep writing)
+ traceWroteRequest(cs.trace, werr)
+ return nil, false, werr
+ }
+
+ var respHeaderTimer <-chan time.Time
+ if hasBody {
+ bodyWriter.scheduleBodyWrite()
+ } else {
+ traceWroteRequest(cs.trace, nil)
+ if d := cc.responseHeaderTimeout(); d != 0 {
+ timer := time.NewTimer(d)
+ defer timer.Stop()
+ respHeaderTimer = timer.C
+ }
+ }
+
+ readLoopResCh := cs.resc
+ bodyWritten := false
+ ctx := reqContext(req)
+
+ handleReadLoopResponse := func(re resAndError) (*http.Response, bool, error) {
+ res := re.res
+ if re.err != nil || res.StatusCode > 299 {
+ // On error or status code 3xx, 4xx, 5xx, etc abort any
+ // ongoing write, assuming that the server doesn't care
+ // about our request body. If the server replied with 1xx or
+ // 2xx, however, then assume the server DOES potentially
+ // want our body (e.g. full-duplex streaming:
+ // golang.org/issue/13444). If it turns out the server
+ // doesn't, they'll RST_STREAM us soon enough. This is a
+ // heuristic to avoid adding knobs to Transport. Hopefully
+ // we can keep it.
+ bodyWriter.cancel()
+ cs.abortRequestBodyWrite(errStopReqBodyWrite)
+ }
+ if re.err != nil {
+ cc.forgetStreamID(cs.ID)
+ return nil, cs.getStartedWrite(), re.err
+ }
+ res.Request = req
+ res.TLS = cc.tlsState
+ return res, false, nil
+ }
+
+ for {
+ select {
+ case re := <-readLoopResCh:
+ return handleReadLoopResponse(re)
+ case <-respHeaderTimer:
+ if !hasBody || bodyWritten {
+ cc.writeStreamReset(cs.ID, ErrCodeCancel, nil)
+ } else {
+ bodyWriter.cancel()
+ cs.abortRequestBodyWrite(errStopReqBodyWriteAndCancel)
+ }
+ cc.forgetStreamID(cs.ID)
+ return nil, cs.getStartedWrite(), errTimeout
+ case <-ctx.Done():
+ if !hasBody || bodyWritten {
+ cc.writeStreamReset(cs.ID, ErrCodeCancel, nil)
+ } else {
+ bodyWriter.cancel()
+ cs.abortRequestBodyWrite(errStopReqBodyWriteAndCancel)
+ }
+ cc.forgetStreamID(cs.ID)
+ return nil, cs.getStartedWrite(), ctx.Err()
+ case <-req.Cancel:
+ if !hasBody || bodyWritten {
+ cc.writeStreamReset(cs.ID, ErrCodeCancel, nil)
+ } else {
+ bodyWriter.cancel()
+ cs.abortRequestBodyWrite(errStopReqBodyWriteAndCancel)
+ }
+ cc.forgetStreamID(cs.ID)
+ return nil, cs.getStartedWrite(), errRequestCanceled
+ case <-cs.peerReset:
+ // processResetStream already removed the
+ // stream from the streams map; no need for
+ // forgetStreamID.
+ return nil, cs.getStartedWrite(), cs.resetErr
+ case err := <-bodyWriter.resc:
+ // Prefer the read loop's response, if available. Issue 16102.
+ select {
+ case re := <-readLoopResCh:
+ return handleReadLoopResponse(re)
+ default:
+ }
+ if err != nil {
+ return nil, cs.getStartedWrite(), err
+ }
+ bodyWritten = true
+ if d := cc.responseHeaderTimeout(); d != 0 {
+ timer := time.NewTimer(d)
+ defer timer.Stop()
+ respHeaderTimer = timer.C
+ }
+ }
+ }
+}
+
+// awaitOpenSlotForRequest waits until len(streams) < maxConcurrentStreams.
+// Must hold cc.mu.
+func (cc *ClientConn) awaitOpenSlotForRequest(req *http.Request) error {
+ var waitingForConn chan struct{}
+ var waitingForConnErr error // guarded by cc.mu
+ for {
+ cc.lastActive = time.Now()
+ if cc.closed || !cc.canTakeNewRequestLocked() {
+ return errClientConnUnusable
+ }
+ if int64(len(cc.streams))+1 <= int64(cc.maxConcurrentStreams) {
+ if waitingForConn != nil {
+ close(waitingForConn)
+ }
+ return nil
+ }
+ // Unfortunately, we cannot wait on a condition variable and channel at
+ // the same time, so instead, we spin up a goroutine to check if the
+ // request is canceled while we wait for a slot to open in the connection.
+ if waitingForConn == nil {
+ waitingForConn = make(chan struct{})
+ go func() {
+ if err := awaitRequestCancel(req, waitingForConn); err != nil {
+ cc.mu.Lock()
+ waitingForConnErr = err
+ cc.cond.Broadcast()
+ cc.mu.Unlock()
+ }
+ }()
+ }
+ cc.pendingRequests++
+ cc.cond.Wait()
+ cc.pendingRequests--
+ if waitingForConnErr != nil {
+ return waitingForConnErr
+ }
+ }
+}
+
+// requires cc.wmu be held
+func (cc *ClientConn) writeHeaders(streamID uint32, endStream bool, maxFrameSize int, hdrs []byte) error {
+ first := true // first frame written (HEADERS is first, then CONTINUATION)
+ for len(hdrs) > 0 && cc.werr == nil {
+ chunk := hdrs
+ if len(chunk) > maxFrameSize {
+ chunk = chunk[:maxFrameSize]
+ }
+ hdrs = hdrs[len(chunk):]
+ endHeaders := len(hdrs) == 0
+ if first {
+ cc.fr.WriteHeaders(HeadersFrameParam{
+ StreamID: streamID,
+ BlockFragment: chunk,
+ EndStream: endStream,
+ EndHeaders: endHeaders,
+ })
+ first = false
+ } else {
+ cc.fr.WriteContinuation(streamID, endHeaders, chunk)
+ }
+ }
+ // TODO(bradfitz): this Flush could potentially block (as
+ // could the WriteHeaders call(s) above), which means they
+ // wouldn't respond to Request.Cancel being readable. That's
+ // rare, but this should probably be in a goroutine.
+ cc.bw.Flush()
+ return cc.werr
+}
+
+// internal error values; they don't escape to callers
+var (
+ // abort request body write; don't send cancel
+ errStopReqBodyWrite = errors.New("http2: aborting request body write")
+
+ // abort request body write, but send stream reset of cancel.
+ errStopReqBodyWriteAndCancel = errors.New("http2: canceling request")
+)
+
+func (cs *clientStream) writeRequestBody(body io.Reader, bodyCloser io.Closer) (err error) {
+ cc := cs.cc
+ sentEnd := false // whether we sent the final DATA frame w/ END_STREAM
+ buf := cc.frameScratchBuffer()
+ defer cc.putFrameScratchBuffer(buf)
+
+ defer func() {
+ traceWroteRequest(cs.trace, err)
+ // TODO: write h12Compare test showing whether
+ // Request.Body is closed by the Transport,
+ // and in multiple cases: server replies <=299 and >299
+ // while still writing request body
+ cerr := bodyCloser.Close()
+ if err == nil {
+ err = cerr
+ }
+ }()
+
+ req := cs.req
+ hasTrailers := req.Trailer != nil
+
+ var sawEOF bool
+ for !sawEOF {
+ n, err := body.Read(buf)
+ if err == io.EOF {
+ sawEOF = true
+ err = nil
+ } else if err != nil {
+ return err
+ }
+
+ remain := buf[:n]
+ for len(remain) > 0 && err == nil {
+ var allowed int32
+ allowed, err = cs.awaitFlowControl(len(remain))
+ switch {
+ case err == errStopReqBodyWrite:
+ return err
+ case err == errStopReqBodyWriteAndCancel:
+ cc.writeStreamReset(cs.ID, ErrCodeCancel, nil)
+ return err
+ case err != nil:
+ return err
+ }
+ cc.wmu.Lock()
+ data := remain[:allowed]
+ remain = remain[allowed:]
+ sentEnd = sawEOF && len(remain) == 0 && !hasTrailers
+ err = cc.fr.WriteData(cs.ID, sentEnd, data)
+ if err == nil {
+ // TODO(bradfitz): this flush is for latency, not bandwidth.
+ // Most requests won't need this. Make this opt-in or
+ // opt-out? Use some heuristic on the body type? Nagel-like
+ // timers? Based on 'n'? Only last chunk of this for loop,
+ // unless flow control tokens are low? For now, always.
+ // If we change this, see comment below.
+ err = cc.bw.Flush()
+ }
+ cc.wmu.Unlock()
+ }
+ if err != nil {
+ return err
+ }
+ }
+
+ if sentEnd {
+ // Already sent END_STREAM (which implies we have no
+ // trailers) and flushed, because currently all
+ // WriteData frames above get a flush. So we're done.
+ return nil
+ }
+
+ var trls []byte
+ if hasTrailers {
+ cc.mu.Lock()
+ trls, err = cc.encodeTrailers(req)
+ cc.mu.Unlock()
+ if err != nil {
+ cc.writeStreamReset(cs.ID, ErrCodeInternal, err)
+ cc.forgetStreamID(cs.ID)
+ return err
+ }
+ }
+
+ cc.mu.Lock()
+ maxFrameSize := int(cc.maxFrameSize)
+ cc.mu.Unlock()
+
+ cc.wmu.Lock()
+ defer cc.wmu.Unlock()
+
+ // Two ways to send END_STREAM: either with trailers, or
+ // with an empty DATA frame.
+ if len(trls) > 0 {
+ err = cc.writeHeaders(cs.ID, true, maxFrameSize, trls)
+ } else {
+ err = cc.fr.WriteData(cs.ID, true, nil)
+ }
+ if ferr := cc.bw.Flush(); ferr != nil && err == nil {
+ err = ferr
+ }
+ return err
+}
+
+// awaitFlowControl waits for [1, min(maxBytes, cc.cs.maxFrameSize)] flow
+// control tokens from the server.
+// It returns either the non-zero number of tokens taken or an error
+// if the stream is dead.
+func (cs *clientStream) awaitFlowControl(maxBytes int) (taken int32, err error) {
+ cc := cs.cc
+ cc.mu.Lock()
+ defer cc.mu.Unlock()
+ for {
+ if cc.closed {
+ return 0, errClientConnClosed
+ }
+ if cs.stopReqBody != nil {
+ return 0, cs.stopReqBody
+ }
+ if err := cs.checkResetOrDone(); err != nil {
+ return 0, err
+ }
+ if a := cs.flow.available(); a > 0 {
+ take := a
+ if int(take) > maxBytes {
+
+ take = int32(maxBytes) // can't truncate int; take is int32
+ }
+ if take > int32(cc.maxFrameSize) {
+ take = int32(cc.maxFrameSize)
+ }
+ cs.flow.take(take)
+ return take, nil
+ }
+ cc.cond.Wait()
+ }
+}
+
+type badStringError struct {
+ what string
+ str string
+}
+
+func (e *badStringError) Error() string { return fmt.Sprintf("%s %q", e.what, e.str) }
+
+// requires cc.mu be held.
+func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trailers string, contentLength int64) ([]byte, error) {
+ cc.hbuf.Reset()
+
+ host := req.Host
+ if host == "" {
+ host = req.URL.Host
+ }
+ host, err := httplex.PunycodeHostPort(host)
+ if err != nil {
+ return nil, err
+ }
+
+ var path string
+ if req.Method != "CONNECT" {
+ path = req.URL.RequestURI()
+ if !validPseudoPath(path) {
+ orig := path
+ path = strings.TrimPrefix(path, req.URL.Scheme+"://"+host)
+ if !validPseudoPath(path) {
+ if req.URL.Opaque != "" {
+ return nil, fmt.Errorf("invalid request :path %q from URL.Opaque = %q", orig, req.URL.Opaque)
+ } else {
+ return nil, fmt.Errorf("invalid request :path %q", orig)
+ }
+ }
+ }
+ }
+
+ // Check for any invalid headers and return an error before we
+ // potentially pollute our hpack state. (We want to be able to
+ // continue to reuse the hpack encoder for future requests)
+ for k, vv := range req.Header {
+ if !httplex.ValidHeaderFieldName(k) {
+ return nil, fmt.Errorf("invalid HTTP header name %q", k)
+ }
+ for _, v := range vv {
+ if !httplex.ValidHeaderFieldValue(v) {
+ return nil, fmt.Errorf("invalid HTTP header value %q for header %q", v, k)
+ }
+ }
+ }
+
+ enumerateHeaders := func(f func(name, value string)) {
+ // 8.1.2.3 Request Pseudo-Header Fields
+ // The :path pseudo-header field includes the path and query parts of the
+ // target URI (the path-absolute production and optionally a '?' character
+ // followed by the query production (see Sections 3.3 and 3.4 of
+ // [RFC3986]).
+ f(":authority", host)
+ f(":method", req.Method)
+ if req.Method != "CONNECT" {
+ f(":path", path)
+ f(":scheme", req.URL.Scheme)
+ }
+ if trailers != "" {
+ f("trailer", trailers)
+ }
+
+ var didUA bool
+ for k, vv := range req.Header {
+ if strings.EqualFold(k, "host") || strings.EqualFold(k, "content-length") {
+ // Host is :authority, already sent.
+ // Content-Length is automatic, set below.
+ continue
+ } else if strings.EqualFold(k, "connection") || strings.EqualFold(k, "proxy-connection") ||
+ strings.EqualFold(k, "transfer-encoding") || strings.EqualFold(k, "upgrade") ||
+ strings.EqualFold(k, "keep-alive") {
+ // Per 8.1.2.2 Connection-Specific Header
+ // Fields, don't send connection-specific
+ // fields. We have already checked if any
+ // are error-worthy so just ignore the rest.
+ continue
+ } else if strings.EqualFold(k, "user-agent") {
+ // Match Go's http1 behavior: at most one
+ // User-Agent. If set to nil or empty string,
+ // then omit it. Otherwise if not mentioned,
+ // include the default (below).
+ didUA = true
+ if len(vv) < 1 {
+ continue
+ }
+ vv = vv[:1]
+ if vv[0] == "" {
+ continue
+ }
+
+ }
+
+ for _, v := range vv {
+ f(k, v)
+ }
+ }
+ if shouldSendReqContentLength(req.Method, contentLength) {
+ f("content-length", strconv.FormatInt(contentLength, 10))
+ }
+ if addGzipHeader {
+ f("accept-encoding", "gzip")
+ }
+ if !didUA {
+ f("user-agent", defaultUserAgent)
+ }
+ }
+
+ // Do a first pass over the headers counting bytes to ensure
+ // we don't exceed cc.peerMaxHeaderListSize. This is done as a
+ // separate pass before encoding the headers to prevent
+ // modifying the hpack state.
+ hlSize := uint64(0)
+ enumerateHeaders(func(name, value string) {
+ hf := hpack.HeaderField{Name: name, Value: value}
+ hlSize += uint64(hf.Size())
+ })
+
+ if hlSize > cc.peerMaxHeaderListSize {
+ return nil, errRequestHeaderListSize
+ }
+
+ // Header list size is ok. Write the headers.
+ enumerateHeaders(func(name, value string) {
+ cc.writeHeader(strings.ToLower(name), value)
+ })
+
+ return cc.hbuf.Bytes(), nil
+}
+
+// shouldSendReqContentLength reports whether the http2.Transport should send
+// a "content-length" request header. This logic is basically a copy of the net/http
+// transferWriter.shouldSendContentLength.
+// The contentLength is the corrected contentLength (so 0 means actually 0, not unknown).
+// -1 means unknown.
+func shouldSendReqContentLength(method string, contentLength int64) bool {
+ if contentLength > 0 {
+ return true
+ }
+ if contentLength < 0 {
+ return false
+ }
+ // For zero bodies, whether we send a content-length depends on the method.
+ // It also kinda doesn't matter for http2 either way, with END_STREAM.
+ switch method {
+ case "POST", "PUT", "PATCH":
+ return true
+ default:
+ return false
+ }
+}
+
+// requires cc.mu be held.
+func (cc *ClientConn) encodeTrailers(req *http.Request) ([]byte, error) {
+ cc.hbuf.Reset()
+
+ hlSize := uint64(0)
+ for k, vv := range req.Trailer {
+ for _, v := range vv {
+ hf := hpack.HeaderField{Name: k, Value: v}
+ hlSize += uint64(hf.Size())
+ }
+ }
+ if hlSize > cc.peerMaxHeaderListSize {
+ return nil, errRequestHeaderListSize
+ }
+
+ for k, vv := range req.Trailer {
+ // Transfer-Encoding, etc.. have already been filtered at the
+ // start of RoundTrip
+ lowKey := strings.ToLower(k)
+ for _, v := range vv {
+ cc.writeHeader(lowKey, v)
+ }
+ }
+ return cc.hbuf.Bytes(), nil
+}
+
+func (cc *ClientConn) writeHeader(name, value string) {
+ if VerboseLogs {
+ log.Printf("http2: Transport encoding header %q = %q", name, value)
+ }
+ cc.henc.WriteField(hpack.HeaderField{Name: name, Value: value})
+}
+
+type resAndError struct {
+ res *http.Response
+ err error
+}
+
+// requires cc.mu be held.
+func (cc *ClientConn) newStream() *clientStream {
+ cs := &clientStream{
+ cc: cc,
+ ID: cc.nextStreamID,
+ resc: make(chan resAndError, 1),
+ peerReset: make(chan struct{}),
+ done: make(chan struct{}),
+ }
+ cs.flow.add(int32(cc.initialWindowSize))
+ cs.flow.setConnFlow(&cc.flow)
+ cs.inflow.add(transportDefaultStreamFlow)
+ cs.inflow.setConnFlow(&cc.inflow)
+ cc.nextStreamID += 2
+ cc.streams[cs.ID] = cs
+ return cs
+}
+
+func (cc *ClientConn) forgetStreamID(id uint32) {
+ cc.streamByID(id, true)
+}
+
+func (cc *ClientConn) streamByID(id uint32, andRemove bool) *clientStream {
+ cc.mu.Lock()
+ defer cc.mu.Unlock()
+ cs := cc.streams[id]
+ if andRemove && cs != nil && !cc.closed {
+ cc.lastActive = time.Now()
+ delete(cc.streams, id)
+ if len(cc.streams) == 0 && cc.idleTimer != nil {
+ cc.idleTimer.Reset(cc.idleTimeout)
+ }
+ close(cs.done)
+ // Wake up checkResetOrDone via clientStream.awaitFlowControl and
+ // wake up RoundTrip if there is a pending request.
+ cc.cond.Broadcast()
+ }
+ return cs
+}
+
+// clientConnReadLoop is the state owned by the clientConn's frame-reading readLoop.
+type clientConnReadLoop struct {
+ cc *ClientConn
+ closeWhenIdle bool
+}
+
+// readLoop runs in its own goroutine and reads and dispatches frames.
+func (cc *ClientConn) readLoop() {
+ rl := &clientConnReadLoop{cc: cc}
+ defer rl.cleanup()
+ cc.readerErr = rl.run()
+ if ce, ok := cc.readerErr.(ConnectionError); ok {
+ cc.wmu.Lock()
+ cc.fr.WriteGoAway(0, ErrCode(ce), nil)
+ cc.wmu.Unlock()
+ }
+}
+
+// GoAwayError is returned by the Transport when the server closes the
+// TCP connection after sending a GOAWAY frame.
+type GoAwayError struct {
+ LastStreamID uint32
+ ErrCode ErrCode
+ DebugData string
+}
+
+func (e GoAwayError) Error() string {
+ return fmt.Sprintf("http2: server sent GOAWAY and closed the connection; LastStreamID=%v, ErrCode=%v, debug=%q",
+ e.LastStreamID, e.ErrCode, e.DebugData)
+}
+
+func isEOFOrNetReadError(err error) bool {
+ if err == io.EOF {
+ return true
+ }
+ ne, ok := err.(*net.OpError)
+ return ok && ne.Op == "read"
+}
+
+func (rl *clientConnReadLoop) cleanup() {
+ cc := rl.cc
+ defer cc.tconn.Close()
+ defer cc.t.connPool().MarkDead(cc)
+ defer close(cc.readerDone)
+
+ if cc.idleTimer != nil {
+ cc.idleTimer.Stop()
+ }
+
+ // Close any response bodies if the server closes prematurely.
+ // TODO: also do this if we've written the headers but not
+ // gotten a response yet.
+ err := cc.readerErr
+ cc.mu.Lock()
+ if cc.goAway != nil && isEOFOrNetReadError(err) {
+ err = GoAwayError{
+ LastStreamID: cc.goAway.LastStreamID,
+ ErrCode: cc.goAway.ErrCode,
+ DebugData: cc.goAwayDebug,
+ }
+ } else if err == io.EOF {
+ err = io.ErrUnexpectedEOF
+ }
+ for _, cs := range cc.streams {
+ cs.bufPipe.CloseWithError(err) // no-op if already closed
+ select {
+ case cs.resc <- resAndError{err: err}:
+ default:
+ }
+ close(cs.done)
+ }
+ cc.closed = true
+ cc.cond.Broadcast()
+ cc.mu.Unlock()
+}
+
+func (rl *clientConnReadLoop) run() error {
+ cc := rl.cc
+ rl.closeWhenIdle = cc.t.disableKeepAlives() || cc.singleUse
+ gotReply := false // ever saw a HEADERS reply
+ gotSettings := false
+ for {
+ f, err := cc.fr.ReadFrame()
+ if err != nil {
+ cc.vlogf("http2: Transport readFrame error on conn %p: (%T) %v", cc, err, err)
+ }
+ if se, ok := err.(StreamError); ok {
+ if cs := cc.streamByID(se.StreamID, false); cs != nil {
+ cs.cc.writeStreamReset(cs.ID, se.Code, err)
+ cs.cc.forgetStreamID(cs.ID)
+ if se.Cause == nil {
+ se.Cause = cc.fr.errDetail
+ }
+ rl.endStreamError(cs, se)
+ }
+ continue
+ } else if err != nil {
+ return err
+ }
+ if VerboseLogs {
+ cc.vlogf("http2: Transport received %s", summarizeFrame(f))
+ }
+ if !gotSettings {
+ if _, ok := f.(*SettingsFrame); !ok {
+ cc.logf("protocol error: received %T before a SETTINGS frame", f)
+ return ConnectionError(ErrCodeProtocol)
+ }
+ gotSettings = true
+ }
+ maybeIdle := false // whether frame might transition us to idle
+
+ switch f := f.(type) {
+ case *MetaHeadersFrame:
+ err = rl.processHeaders(f)
+ maybeIdle = true
+ gotReply = true
+ case *DataFrame:
+ err = rl.processData(f)
+ maybeIdle = true
+ case *GoAwayFrame:
+ err = rl.processGoAway(f)
+ maybeIdle = true
+ case *RSTStreamFrame:
+ err = rl.processResetStream(f)
+ maybeIdle = true
+ case *SettingsFrame:
+ err = rl.processSettings(f)
+ case *PushPromiseFrame:
+ err = rl.processPushPromise(f)
+ case *WindowUpdateFrame:
+ err = rl.processWindowUpdate(f)
+ case *PingFrame:
+ err = rl.processPing(f)
+ default:
+ cc.logf("Transport: unhandled response frame type %T", f)
+ }
+ if err != nil {
+ if VerboseLogs {
+ cc.vlogf("http2: Transport conn %p received error from processing frame %v: %v", cc, summarizeFrame(f), err)
+ }
+ return err
+ }
+ if rl.closeWhenIdle && gotReply && maybeIdle {
+ cc.closeIfIdle()
+ }
+ }
+}
+
+func (rl *clientConnReadLoop) processHeaders(f *MetaHeadersFrame) error {
+ cc := rl.cc
+ cs := cc.streamByID(f.StreamID, false)
+ if cs == nil {
+ // We'd get here if we canceled a request while the
+ // server had its response still in flight. So if this
+ // was just something we canceled, ignore it.
+ return nil
+ }
+ if f.StreamEnded() {
+ // Issue 20521: If the stream has ended, streamByID() causes
+ // clientStream.done to be closed, which causes the request's bodyWriter
+ // to be closed with an errStreamClosed, which may be received by
+ // clientConn.RoundTrip before the result of processing these headers.
+ // Deferring stream closure allows the header processing to occur first.
+ // clientConn.RoundTrip may still receive the bodyWriter error first, but
+ // the fix for issue 16102 prioritises any response.
+ //
+ // Issue 22413: If there is no request body, we should close the
+ // stream before writing to cs.resc so that the stream is closed
+ // immediately once RoundTrip returns.
+ if cs.req.Body != nil {
+ defer cc.forgetStreamID(f.StreamID)
+ } else {
+ cc.forgetStreamID(f.StreamID)
+ }
+ }
+ if !cs.firstByte {
+ if cs.trace != nil {
+ // TODO(bradfitz): move first response byte earlier,
+ // when we first read the 9 byte header, not waiting
+ // until all the HEADERS+CONTINUATION frames have been
+ // merged. This works for now.
+ traceFirstResponseByte(cs.trace)
+ }
+ cs.firstByte = true
+ }
+ if !cs.pastHeaders {
+ cs.pastHeaders = true
+ } else {
+ return rl.processTrailers(cs, f)
+ }
+
+ res, err := rl.handleResponse(cs, f)
+ if err != nil {
+ if _, ok := err.(ConnectionError); ok {
+ return err
+ }
+ // Any other error type is a stream error.
+ cs.cc.writeStreamReset(f.StreamID, ErrCodeProtocol, err)
+ cc.forgetStreamID(cs.ID)
+ cs.resc <- resAndError{err: err}
+ return nil // return nil from process* funcs to keep conn alive
+ }
+ if res == nil {
+ // (nil, nil) special case. See handleResponse docs.
+ return nil
+ }
+ cs.resTrailer = &res.Trailer
+ cs.resc <- resAndError{res: res}
+ return nil
+}
+
+// may return error types nil, or ConnectionError. Any other error value
+// is a StreamError of type ErrCodeProtocol. The returned error in that case
+// is the detail.
+//
+// As a special case, handleResponse may return (nil, nil) to skip the
+// frame (currently only used for 100 expect continue). This special
+// case is going away after Issue 13851 is fixed.
+func (rl *clientConnReadLoop) handleResponse(cs *clientStream, f *MetaHeadersFrame) (*http.Response, error) {
+ if f.Truncated {
+ return nil, errResponseHeaderListSize
+ }
+
+ status := f.PseudoValue("status")
+ if status == "" {
+ return nil, errors.New("malformed response from server: missing status pseudo header")
+ }
+ statusCode, err := strconv.Atoi(status)
+ if err != nil {
+ return nil, errors.New("malformed response from server: malformed non-numeric status pseudo header")
+ }
+
+ if statusCode == 100 {
+ traceGot100Continue(cs.trace)
+ if cs.on100 != nil {
+ cs.on100() // forces any write delay timer to fire
+ }
+ cs.pastHeaders = false // do it all again
+ return nil, nil
+ }
+
+ header := make(http.Header)
+ res := &http.Response{
+ Proto: "HTTP/2.0",
+ ProtoMajor: 2,
+ Header: header,
+ StatusCode: statusCode,
+ Status: status + " " + http.StatusText(statusCode),
+ }
+ for _, hf := range f.RegularFields() {
+ key := http.CanonicalHeaderKey(hf.Name)
+ if key == "Trailer" {
+ t := res.Trailer
+ if t == nil {
+ t = make(http.Header)
+ res.Trailer = t
+ }
+ foreachHeaderElement(hf.Value, func(v string) {
+ t[http.CanonicalHeaderKey(v)] = nil
+ })
+ } else {
+ header[key] = append(header[key], hf.Value)
+ }
+ }
+
+ streamEnded := f.StreamEnded()
+ isHead := cs.req.Method == "HEAD"
+ if !streamEnded || isHead {
+ res.ContentLength = -1
+ if clens := res.Header["Content-Length"]; len(clens) == 1 {
+ if clen64, err := strconv.ParseInt(clens[0], 10, 64); err == nil {
+ res.ContentLength = clen64
+ } else {
+ // TODO: care? unlike http/1, it won't mess up our framing, so it's
+ // more safe smuggling-wise to ignore.
+ }
+ } else if len(clens) > 1 {
+ // TODO: care? unlike http/1, it won't mess up our framing, so it's
+ // more safe smuggling-wise to ignore.
+ }
+ }
+
+ if streamEnded || isHead {
+ res.Body = noBody
+ return res, nil
+ }
+
+ cs.bufPipe = pipe{b: &dataBuffer{expected: res.ContentLength}}
+ cs.bytesRemain = res.ContentLength
+ res.Body = transportResponseBody{cs}
+ go cs.awaitRequestCancel(cs.req)
+
+ if cs.requestedGzip && res.Header.Get("Content-Encoding") == "gzip" {
+ res.Header.Del("Content-Encoding")
+ res.Header.Del("Content-Length")
+ res.ContentLength = -1
+ res.Body = &gzipReader{body: res.Body}
+ setResponseUncompressed(res)
+ }
+ return res, nil
+}
+
+func (rl *clientConnReadLoop) processTrailers(cs *clientStream, f *MetaHeadersFrame) error {
+ if cs.pastTrailers {
+ // Too many HEADERS frames for this stream.
+ return ConnectionError(ErrCodeProtocol)
+ }
+ cs.pastTrailers = true
+ if !f.StreamEnded() {
+ // We expect that any headers for trailers also
+ // has END_STREAM.
+ return ConnectionError(ErrCodeProtocol)
+ }
+ if len(f.PseudoFields()) > 0 {
+ // No pseudo header fields are defined for trailers.
+ // TODO: ConnectionError might be overly harsh? Check.
+ return ConnectionError(ErrCodeProtocol)
+ }
+
+ trailer := make(http.Header)
+ for _, hf := range f.RegularFields() {
+ key := http.CanonicalHeaderKey(hf.Name)
+ trailer[key] = append(trailer[key], hf.Value)
+ }
+ cs.trailer = trailer
+
+ rl.endStream(cs)
+ return nil
+}
+
+// transportResponseBody is the concrete type of Transport.RoundTrip's
+// Response.Body. It is an io.ReadCloser. On Read, it reads from cs.body.
+// On Close it sends RST_STREAM if EOF wasn't already seen.
+type transportResponseBody struct {
+ cs *clientStream
+}
+
+func (b transportResponseBody) Read(p []byte) (n int, err error) {
+ cs := b.cs
+ cc := cs.cc
+
+ if cs.readErr != nil {
+ return 0, cs.readErr
+ }
+ n, err = b.cs.bufPipe.Read(p)
+ if cs.bytesRemain != -1 {
+ if int64(n) > cs.bytesRemain {
+ n = int(cs.bytesRemain)
+ if err == nil {
+ err = errors.New("net/http: server replied with more than declared Content-Length; truncated")
+ cc.writeStreamReset(cs.ID, ErrCodeProtocol, err)
+ }
+ cs.readErr = err
+ return int(cs.bytesRemain), err
+ }
+ cs.bytesRemain -= int64(n)
+ if err == io.EOF && cs.bytesRemain > 0 {
+ err = io.ErrUnexpectedEOF
+ cs.readErr = err
+ return n, err
+ }
+ }
+ if n == 0 {
+ // No flow control tokens to send back.
+ return
+ }
+
+ cc.mu.Lock()
+ defer cc.mu.Unlock()
+
+ var connAdd, streamAdd int32
+ // Check the conn-level first, before the stream-level.
+ if v := cc.inflow.available(); v < transportDefaultConnFlow/2 {
+ connAdd = transportDefaultConnFlow - v
+ cc.inflow.add(connAdd)
+ }
+ if err == nil { // No need to refresh if the stream is over or failed.
+ // Consider any buffered body data (read from the conn but not
+ // consumed by the client) when computing flow control for this
+ // stream.
+ v := int(cs.inflow.available()) + cs.bufPipe.Len()
+ if v < transportDefaultStreamFlow-transportDefaultStreamMinRefresh {
+ streamAdd = int32(transportDefaultStreamFlow - v)
+ cs.inflow.add(streamAdd)
+ }
+ }
+ if connAdd != 0 || streamAdd != 0 {
+ cc.wmu.Lock()
+ defer cc.wmu.Unlock()
+ if connAdd != 0 {
+ cc.fr.WriteWindowUpdate(0, mustUint31(connAdd))
+ }
+ if streamAdd != 0 {
+ cc.fr.WriteWindowUpdate(cs.ID, mustUint31(streamAdd))
+ }
+ cc.bw.Flush()
+ }
+ return
+}
+
+var errClosedResponseBody = errors.New("http2: response body closed")
+
+func (b transportResponseBody) Close() error {
+ cs := b.cs
+ cc := cs.cc
+
+ serverSentStreamEnd := cs.bufPipe.Err() == io.EOF
+ unread := cs.bufPipe.Len()
+
+ if unread > 0 || !serverSentStreamEnd {
+ cc.mu.Lock()
+ cc.wmu.Lock()
+ if !serverSentStreamEnd {
+ cc.fr.WriteRSTStream(cs.ID, ErrCodeCancel)
+ cs.didReset = true
+ }
+ // Return connection-level flow control.
+ if unread > 0 {
+ cc.inflow.add(int32(unread))
+ cc.fr.WriteWindowUpdate(0, uint32(unread))
+ }
+ cc.bw.Flush()
+ cc.wmu.Unlock()
+ cc.mu.Unlock()
+ }
+
+ cs.bufPipe.BreakWithError(errClosedResponseBody)
+ cc.forgetStreamID(cs.ID)
+ return nil
+}
+
+func (rl *clientConnReadLoop) processData(f *DataFrame) error {
+ cc := rl.cc
+ cs := cc.streamByID(f.StreamID, f.StreamEnded())
+ data := f.Data()
+ if cs == nil {
+ cc.mu.Lock()
+ neverSent := cc.nextStreamID
+ cc.mu.Unlock()
+ if f.StreamID >= neverSent {
+ // We never asked for this.
+ cc.logf("http2: Transport received unsolicited DATA frame; closing connection")
+ return ConnectionError(ErrCodeProtocol)
+ }
+ // We probably did ask for this, but canceled. Just ignore it.
+ // TODO: be stricter here? only silently ignore things which
+ // we canceled, but not things which were closed normally
+ // by the peer? Tough without accumulating too much state.
+
+ // But at least return their flow control:
+ if f.Length > 0 {
+ cc.mu.Lock()
+ cc.inflow.add(int32(f.Length))
+ cc.mu.Unlock()
+
+ cc.wmu.Lock()
+ cc.fr.WriteWindowUpdate(0, uint32(f.Length))
+ cc.bw.Flush()
+ cc.wmu.Unlock()
+ }
+ return nil
+ }
+ if !cs.firstByte {
+ cc.logf("protocol error: received DATA before a HEADERS frame")
+ rl.endStreamError(cs, StreamError{
+ StreamID: f.StreamID,
+ Code: ErrCodeProtocol,
+ })
+ return nil
+ }
+ if f.Length > 0 {
+ if cs.req.Method == "HEAD" && len(data) > 0 {
+ cc.logf("protocol error: received DATA on a HEAD request")
+ rl.endStreamError(cs, StreamError{
+ StreamID: f.StreamID,
+ Code: ErrCodeProtocol,
+ })
+ return nil
+ }
+ // Check connection-level flow control.
+ cc.mu.Lock()
+ if cs.inflow.available() >= int32(f.Length) {
+ cs.inflow.take(int32(f.Length))
+ } else {
+ cc.mu.Unlock()
+ return ConnectionError(ErrCodeFlowControl)
+ }
+ // Return any padded flow control now, since we won't
+ // refund it later on body reads.
+ var refund int
+ if pad := int(f.Length) - len(data); pad > 0 {
+ refund += pad
+ }
+ // Return len(data) now if the stream is already closed,
+ // since data will never be read.
+ didReset := cs.didReset
+ if didReset {
+ refund += len(data)
+ }
+ if refund > 0 {
+ cc.inflow.add(int32(refund))
+ cc.wmu.Lock()
+ cc.fr.WriteWindowUpdate(0, uint32(refund))
+ if !didReset {
+ cs.inflow.add(int32(refund))
+ cc.fr.WriteWindowUpdate(cs.ID, uint32(refund))
+ }
+ cc.bw.Flush()
+ cc.wmu.Unlock()
+ }
+ cc.mu.Unlock()
+
+ if len(data) > 0 && !didReset {
+ if _, err := cs.bufPipe.Write(data); err != nil {
+ rl.endStreamError(cs, err)
+ return err
+ }
+ }
+ }
+
+ if f.StreamEnded() {
+ rl.endStream(cs)
+ }
+ 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.
+ rl.endStreamError(cs, nil)
+}
+
+func (rl *clientConnReadLoop) endStreamError(cs *clientStream, err error) {
+ var code func()
+ if err == nil {
+ err = io.EOF
+ code = cs.copyTrailers
+ }
+ if isConnectionCloseRequest(cs.req) {
+ rl.closeWhenIdle = true
+ }
+ cs.bufPipe.closeWithErrorAndCode(err, code)
+
+ select {
+ case cs.resc <- resAndError{err: err}:
+ default:
+ }
+}
+
+func (cs *clientStream) copyTrailers() {
+ for k, vv := range cs.trailer {
+ t := cs.resTrailer
+ if *t == nil {
+ *t = make(http.Header)
+ }
+ (*t)[k] = vv
+ }
+}
+
+func (rl *clientConnReadLoop) processGoAway(f *GoAwayFrame) error {
+ cc := rl.cc
+ cc.t.connPool().MarkDead(cc)
+ if f.ErrCode != 0 {
+ // TODO: deal with GOAWAY more. particularly the error code
+ cc.vlogf("transport got GOAWAY with error code = %v", f.ErrCode)
+ }
+ cc.setGoAway(f)
+ return nil
+}
+
+func (rl *clientConnReadLoop) processSettings(f *SettingsFrame) error {
+ cc := rl.cc
+ cc.mu.Lock()
+ defer cc.mu.Unlock()
+
+ if f.IsAck() {
+ if cc.wantSettingsAck {
+ cc.wantSettingsAck = false
+ return nil
+ }
+ return ConnectionError(ErrCodeProtocol)
+ }
+
+ err := f.ForeachSetting(func(s Setting) error {
+ switch s.ID {
+ case SettingMaxFrameSize:
+ cc.maxFrameSize = s.Val
+ case SettingMaxConcurrentStreams:
+ cc.maxConcurrentStreams = s.Val
+ case SettingMaxHeaderListSize:
+ cc.peerMaxHeaderListSize = uint64(s.Val)
+ case SettingInitialWindowSize:
+ // Values above the maximum flow-control
+ // window size of 2^31-1 MUST be treated as a
+ // connection error (Section 5.4.1) of type
+ // FLOW_CONTROL_ERROR.
+ if s.Val > math.MaxInt32 {
+ return ConnectionError(ErrCodeFlowControl)
+ }
+
+ // Adjust flow control of currently-open
+ // frames by the difference of the old initial
+ // window size and this one.
+ delta := int32(s.Val) - int32(cc.initialWindowSize)
+ for _, cs := range cc.streams {
+ cs.flow.add(delta)
+ }
+ cc.cond.Broadcast()
+
+ cc.initialWindowSize = s.Val
+ default:
+ // TODO(bradfitz): handle more settings? SETTINGS_HEADER_TABLE_SIZE probably.
+ cc.vlogf("Unhandled Setting: %v", s)
+ }
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+
+ cc.wmu.Lock()
+ defer cc.wmu.Unlock()
+
+ cc.fr.WriteSettingsAck()
+ cc.bw.Flush()
+ return cc.werr
+}
+
+func (rl *clientConnReadLoop) processWindowUpdate(f *WindowUpdateFrame) error {
+ cc := rl.cc
+ cs := cc.streamByID(f.StreamID, false)
+ if f.StreamID != 0 && cs == nil {
+ return nil
+ }
+
+ cc.mu.Lock()
+ defer cc.mu.Unlock()
+
+ fl := &cc.flow
+ if cs != nil {
+ fl = &cs.flow
+ }
+ if !fl.add(int32(f.Increment)) {
+ return ConnectionError(ErrCodeFlowControl)
+ }
+ cc.cond.Broadcast()
+ return nil
+}
+
+func (rl *clientConnReadLoop) processResetStream(f *RSTStreamFrame) error {
+ cs := rl.cc.streamByID(f.StreamID, true)
+ if cs == nil {
+ // TODO: return error if server tries to RST_STEAM an idle stream
+ return nil
+ }
+ select {
+ case <-cs.peerReset:
+ // Already reset.
+ // This is the only goroutine
+ // which closes this, so there
+ // isn't a race.
+ default:
+ err := streamError(cs.ID, f.ErrCode)
+ cs.resetErr = err
+ close(cs.peerReset)
+ cs.bufPipe.CloseWithError(err)
+ cs.cc.cond.Broadcast() // wake up checkResetOrDone via clientStream.awaitFlowControl
+ }
+ return nil
+}
+
+// Ping sends a PING frame to the server and waits for the ack.
+// Public implementation is in go17.go and not_go17.go
+func (cc *ClientConn) ping(ctx contextContext) error {
+ c := make(chan struct{})
+ // Generate a random payload
+ var p [8]byte
+ for {
+ if _, err := rand.Read(p[:]); err != nil {
+ return err
+ }
+ cc.mu.Lock()
+ // check for dup before insert
+ if _, found := cc.pings[p]; !found {
+ cc.pings[p] = c
+ cc.mu.Unlock()
+ break
+ }
+ cc.mu.Unlock()
+ }
+ cc.wmu.Lock()
+ if err := cc.fr.WritePing(false, p); err != nil {
+ cc.wmu.Unlock()
+ return err
+ }
+ if err := cc.bw.Flush(); err != nil {
+ cc.wmu.Unlock()
+ return err
+ }
+ cc.wmu.Unlock()
+ select {
+ case <-c:
+ return nil
+ case <-ctx.Done():
+ return ctx.Err()
+ case <-cc.readerDone:
+ // connection closed
+ return cc.readerErr
+ }
+}
+
+func (rl *clientConnReadLoop) processPing(f *PingFrame) error {
+ if f.IsAck() {
+ cc := rl.cc
+ cc.mu.Lock()
+ defer cc.mu.Unlock()
+ // If ack, notify listener if any
+ if c, ok := cc.pings[f.Data]; ok {
+ close(c)
+ delete(cc.pings, f.Data)
+ }
+ return nil
+ }
+ cc := rl.cc
+ cc.wmu.Lock()
+ defer cc.wmu.Unlock()
+ if err := cc.fr.WritePing(true, f.Data); err != nil {
+ return err
+ }
+ return cc.bw.Flush()
+}
+
+func (rl *clientConnReadLoop) processPushPromise(f *PushPromiseFrame) error {
+ // We told the peer we don't want them.
+ // Spec says:
+ // "PUSH_PROMISE MUST NOT be sent if the SETTINGS_ENABLE_PUSH
+ // setting of the peer endpoint is set to 0. An endpoint that
+ // has set this setting and has received acknowledgement MUST
+ // treat the receipt of a PUSH_PROMISE frame as a connection
+ // error (Section 5.4.1) of type PROTOCOL_ERROR."
+ return ConnectionError(ErrCodeProtocol)
+}
+
+func (cc *ClientConn) writeStreamReset(streamID uint32, code ErrCode, err error) {
+ // TODO: map err to more interesting error codes, once the
+ // HTTP community comes up with some. But currently for
+ // RST_STREAM there's no equivalent to GOAWAY frame's debug
+ // data, and the error codes are all pretty vague ("cancel").
+ cc.wmu.Lock()
+ cc.fr.WriteRSTStream(streamID, code)
+ cc.bw.Flush()
+ cc.wmu.Unlock()
+}
+
+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{}) {
+ cc.t.logf(format, args...)
+}
+
+func (cc *ClientConn) vlogf(format string, args ...interface{}) {
+ cc.t.vlogf(format, args...)
+}
+
+func (t *Transport) vlogf(format string, args ...interface{}) {
+ if VerboseLogs {
+ t.logf(format, args...)
+ }
+}
+
+func (t *Transport) logf(format string, args ...interface{}) {
+ log.Printf(format, args...)
+}
+
+var noBody io.ReadCloser = ioutil.NopCloser(bytes.NewReader(nil))
+
+func strSliceContains(ss []string, s string) bool {
+ for _, v := range ss {
+ if v == s {
+ return true
+ }
+ }
+ return false
+}
+
+type erringRoundTripper struct{ err error }
+
+func (rt erringRoundTripper) RoundTrip(*http.Request) (*http.Response, error) { return nil, rt.err }
+
+// gzipReader wraps a response body so it can lazily
+// call gzip.NewReader on the first call to Read
+type gzipReader struct {
+ body io.ReadCloser // underlying Response.Body
+ zr *gzip.Reader // lazily-initialized gzip reader
+ zerr error // sticky error
+}
+
+func (gz *gzipReader) Read(p []byte) (n int, err error) {
+ if gz.zerr != nil {
+ return 0, gz.zerr
+ }
+ if gz.zr == nil {
+ gz.zr, err = gzip.NewReader(gz.body)
+ if err != nil {
+ gz.zerr = err
+ return 0, err
+ }
+ }
+ return gz.zr.Read(p)
+}
+
+func (gz *gzipReader) Close() error {
+ return gz.body.Close()
+}
+
+type errorReader struct{ err error }
+
+func (r errorReader) Read(p []byte) (int, error) { return 0, r.err }
+
+// bodyWriterState encapsulates various state around the Transport's writing
+// of the request body, particularly regarding doing delayed writes of the body
+// when the request contains "Expect: 100-continue".
+type bodyWriterState struct {
+ cs *clientStream
+ timer *time.Timer // if non-nil, we're doing a delayed write
+ fnonce *sync.Once // to call fn with
+ fn func() // the code to run in the goroutine, writing the body
+ resc chan error // result of fn's execution
+ delay time.Duration // how long we should delay a delayed write for
+}
+
+func (t *Transport) getBodyWriterState(cs *clientStream, body io.Reader) (s bodyWriterState) {
+ s.cs = cs
+ if body == nil {
+ return
+ }
+ resc := make(chan error, 1)
+ s.resc = resc
+ s.fn = func() {
+ cs.cc.mu.Lock()
+ cs.startedWrite = true
+ cs.cc.mu.Unlock()
+ resc <- cs.writeRequestBody(body, cs.req.Body)
+ }
+ s.delay = t.expectContinueTimeout()
+ if s.delay == 0 ||
+ !httplex.HeaderValuesContainsToken(
+ cs.req.Header["Expect"],
+ "100-continue") {
+ return
+ }
+ s.fnonce = new(sync.Once)
+
+ // Arm the timer with a very large duration, which we'll
+ // intentionally lower later. It has to be large now because
+ // we need a handle to it before writing the headers, but the
+ // s.delay value is defined to not start until after the
+ // request headers were written.
+ const hugeDuration = 365 * 24 * time.Hour
+ s.timer = time.AfterFunc(hugeDuration, func() {
+ s.fnonce.Do(s.fn)
+ })
+ return
+}
+
+func (s bodyWriterState) cancel() {
+ if s.timer != nil {
+ s.timer.Stop()
+ }
+}
+
+func (s bodyWriterState) on100() {
+ if s.timer == nil {
+ // If we didn't do a delayed write, ignore the server's
+ // bogus 100 continue response.
+ return
+ }
+ s.timer.Stop()
+ go func() { s.fnonce.Do(s.fn) }()
+}
+
+// scheduleBodyWrite starts writing the body, either immediately (in
+// the common case) or after the delay timeout. It should not be
+// called until after the headers have been written.
+func (s bodyWriterState) scheduleBodyWrite() {
+ if s.timer == nil {
+ // We're not doing a delayed write (see
+ // getBodyWriterState), so just start the writing
+ // goroutine immediately.
+ go s.fn()
+ return
+ }
+ traceWait100Continue(s.cs.trace)
+ if s.timer.Stop() {
+ s.timer.Reset(s.delay)
+ }
+}
+
+// isConnectionCloseRequest reports whether req should use its own
+// connection for a single request and then close the connection.
+func isConnectionCloseRequest(req *http.Request) bool {
+ return req.Close || httplex.HeaderValuesContainsToken(req.Header["Connection"], "close")
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/transport_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/transport_test.go
new file mode 100644
index 000000000..adee48cd3
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/transport_test.go
@@ -0,0 +1,3847 @@
+// Copyright 2015 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 http2
+
+import (
+ "bufio"
+ "bytes"
+ "crypto/tls"
+ "errors"
+ "flag"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "log"
+ "math/rand"
+ "net"
+ "net/http"
+ "net/http/httptest"
+ "net/url"
+ "os"
+ "reflect"
+ "runtime"
+ "sort"
+ "strconv"
+ "strings"
+ "sync"
+ "sync/atomic"
+ "testing"
+ "time"
+
+ "golang.org/x/net/http2/hpack"
+)
+
+var (
+ extNet = flag.Bool("extnet", false, "do external network tests")
+ transportHost = flag.String("transporthost", "http2.golang.org", "hostname to use for TestTransport")
+ insecure = flag.Bool("insecure", false, "insecure TLS dials") // TODO: dead code. remove?
+)
+
+var tlsConfigInsecure = &tls.Config{InsecureSkipVerify: true}
+
+type testContext struct{}
+
+func (testContext) Done() <-chan struct{} { return make(chan struct{}) }
+func (testContext) Err() error { panic("should not be called") }
+func (testContext) Deadline() (deadline time.Time, ok bool) { return time.Time{}, false }
+func (testContext) Value(key interface{}) interface{} { return nil }
+
+func TestTransportExternal(t *testing.T) {
+ if !*extNet {
+ t.Skip("skipping external network test")
+ }
+ req, _ := http.NewRequest("GET", "https://"+*transportHost+"/", nil)
+ rt := &Transport{TLSClientConfig: tlsConfigInsecure}
+ res, err := rt.RoundTrip(req)
+ if err != nil {
+ t.Fatalf("%v", err)
+ }
+ res.Write(os.Stdout)
+}
+
+type fakeTLSConn struct {
+ net.Conn
+}
+
+func (c *fakeTLSConn) ConnectionState() tls.ConnectionState {
+ return tls.ConnectionState{
+ Version: tls.VersionTLS12,
+ CipherSuite: cipher_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+ }
+}
+
+func startH2cServer(t *testing.T) net.Listener {
+ h2Server := &Server{}
+ l := newLocalListener(t)
+ go func() {
+ conn, err := l.Accept()
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ h2Server.ServeConn(&fakeTLSConn{conn}, &ServeConnOpts{Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ fmt.Fprintf(w, "Hello, %v, http: %v", r.URL.Path, r.TLS == nil)
+ })})
+ }()
+ return l
+}
+
+func TestTransportH2c(t *testing.T) {
+ l := startH2cServer(t)
+ defer l.Close()
+ req, err := http.NewRequest("GET", "http://"+l.Addr().String()+"/foobar", nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ tr := &Transport{
+ AllowHTTP: true,
+ DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) {
+ return net.Dial(network, addr)
+ },
+ }
+ res, err := tr.RoundTrip(req)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if res.ProtoMajor != 2 {
+ t.Fatal("proto not h2c")
+ }
+ body, err := ioutil.ReadAll(res.Body)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if got, want := string(body), "Hello, /foobar, http: true"; got != want {
+ t.Fatalf("response got %v, want %v", got, want)
+ }
+}
+
+func TestTransport(t *testing.T) {
+ const body = "sup"
+ st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+ io.WriteString(w, body)
+ }, optOnlyServer)
+ defer st.Close()
+
+ tr := &Transport{TLSClientConfig: tlsConfigInsecure}
+ defer tr.CloseIdleConnections()
+
+ req, err := http.NewRequest("GET", st.ts.URL, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ res, err := tr.RoundTrip(req)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer res.Body.Close()
+
+ t.Logf("Got res: %+v", res)
+ if g, w := res.StatusCode, 200; g != w {
+ t.Errorf("StatusCode = %v; want %v", g, w)
+ }
+ if g, w := res.Status, "200 OK"; g != w {
+ t.Errorf("Status = %q; want %q", g, w)
+ }
+ wantHeader := http.Header{
+ "Content-Length": []string{"3"},
+ "Content-Type": []string{"text/plain; charset=utf-8"},
+ "Date": []string{"XXX"}, // see cleanDate
+ }
+ cleanDate(res)
+ if !reflect.DeepEqual(res.Header, wantHeader) {
+ t.Errorf("res Header = %v; want %v", res.Header, wantHeader)
+ }
+ if res.Request != req {
+ t.Errorf("Response.Request = %p; want %p", res.Request, req)
+ }
+ if res.TLS == nil {
+ t.Error("Response.TLS = nil; want non-nil")
+ }
+ slurp, err := ioutil.ReadAll(res.Body)
+ if err != nil {
+ t.Errorf("Body read: %v", err)
+ } else if string(slurp) != body {
+ t.Errorf("Body = %q; want %q", slurp, body)
+ }
+}
+
+func onSameConn(t *testing.T, modReq func(*http.Request)) bool {
+ st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+ io.WriteString(w, r.RemoteAddr)
+ }, optOnlyServer, func(c net.Conn, st http.ConnState) {
+ t.Logf("conn %v is now state %v", c.RemoteAddr(), st)
+ })
+ defer st.Close()
+ tr := &Transport{TLSClientConfig: tlsConfigInsecure}
+ defer tr.CloseIdleConnections()
+ get := func() string {
+ req, err := http.NewRequest("GET", st.ts.URL, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ modReq(req)
+ res, err := tr.RoundTrip(req)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer res.Body.Close()
+ slurp, err := ioutil.ReadAll(res.Body)
+ if err != nil {
+ t.Fatalf("Body read: %v", err)
+ }
+ addr := strings.TrimSpace(string(slurp))
+ if addr == "" {
+ t.Fatalf("didn't get an addr in response")
+ }
+ return addr
+ }
+ first := get()
+ second := get()
+ return first == second
+}
+
+func TestTransportReusesConns(t *testing.T) {
+ if !onSameConn(t, func(*http.Request) {}) {
+ t.Errorf("first and second responses were on different connections")
+ }
+}
+
+func TestTransportReusesConn_RequestClose(t *testing.T) {
+ if onSameConn(t, func(r *http.Request) { r.Close = true }) {
+ t.Errorf("first and second responses were not on different connections")
+ }
+}
+
+func TestTransportReusesConn_ConnClose(t *testing.T) {
+ if onSameConn(t, func(r *http.Request) { r.Header.Set("Connection", "close") }) {
+ t.Errorf("first and second responses were not on different connections")
+ }
+}
+
+// Tests that the Transport only keeps one pending dial open per destination address.
+// https://golang.org/issue/13397
+func TestTransportGroupsPendingDials(t *testing.T) {
+ st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+ io.WriteString(w, r.RemoteAddr)
+ }, optOnlyServer)
+ defer st.Close()
+ tr := &Transport{
+ TLSClientConfig: tlsConfigInsecure,
+ }
+ defer tr.CloseIdleConnections()
+ var (
+ mu sync.Mutex
+ dials = map[string]int{}
+ )
+ var wg sync.WaitGroup
+ for i := 0; i < 10; i++ {
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ req, err := http.NewRequest("GET", st.ts.URL, nil)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ res, err := tr.RoundTrip(req)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ defer res.Body.Close()
+ slurp, err := ioutil.ReadAll(res.Body)
+ if err != nil {
+ t.Errorf("Body read: %v", err)
+ }
+ addr := strings.TrimSpace(string(slurp))
+ if addr == "" {
+ t.Errorf("didn't get an addr in response")
+ }
+ mu.Lock()
+ dials[addr]++
+ mu.Unlock()
+ }()
+ }
+ wg.Wait()
+ if len(dials) != 1 {
+ t.Errorf("saw %d dials; want 1: %v", len(dials), dials)
+ }
+ tr.CloseIdleConnections()
+ if err := retry(50, 10*time.Millisecond, func() error {
+ cp, ok := tr.connPool().(*clientConnPool)
+ if !ok {
+ return fmt.Errorf("Conn pool is %T; want *clientConnPool", tr.connPool())
+ }
+ cp.mu.Lock()
+ defer cp.mu.Unlock()
+ if len(cp.dialing) != 0 {
+ return fmt.Errorf("dialing map = %v; want empty", cp.dialing)
+ }
+ if len(cp.conns) != 0 {
+ return fmt.Errorf("conns = %v; want empty", cp.conns)
+ }
+ if len(cp.keys) != 0 {
+ return fmt.Errorf("keys = %v; want empty", cp.keys)
+ }
+ return nil
+ }); err != nil {
+ t.Errorf("State of pool after CloseIdleConnections: %v", err)
+ }
+}
+
+func retry(tries int, delay time.Duration, fn func() error) error {
+ var err error
+ for i := 0; i < tries; i++ {
+ err = fn()
+ if err == nil {
+ return nil
+ }
+ time.Sleep(delay)
+ }
+ return err
+}
+
+func TestTransportAbortClosesPipes(t *testing.T) {
+ shutdown := make(chan struct{})
+ st := newServerTester(t,
+ func(w http.ResponseWriter, r *http.Request) {
+ w.(http.Flusher).Flush()
+ <-shutdown
+ },
+ optOnlyServer,
+ )
+ defer st.Close()
+ defer close(shutdown) // we must shutdown before st.Close() to avoid hanging
+
+ done := make(chan struct{})
+ requestMade := make(chan struct{})
+ go func() {
+ defer close(done)
+ tr := &Transport{TLSClientConfig: tlsConfigInsecure}
+ req, err := http.NewRequest("GET", st.ts.URL, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ res, err := tr.RoundTrip(req)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer res.Body.Close()
+ close(requestMade)
+ _, err = ioutil.ReadAll(res.Body)
+ if err == nil {
+ t.Error("expected error from res.Body.Read")
+ }
+ }()
+
+ <-requestMade
+ // Now force the serve loop to end, via closing the connection.
+ st.closeConn()
+ // deadlock? that's a bug.
+ select {
+ case <-done:
+ case <-time.After(3 * time.Second):
+ t.Fatal("timeout")
+ }
+}
+
+// TODO: merge this with TestTransportBody to make TestTransportRequest? This
+// could be a table-driven test with extra goodies.
+func TestTransportPath(t *testing.T) {
+ gotc := make(chan *url.URL, 1)
+ st := newServerTester(t,
+ func(w http.ResponseWriter, r *http.Request) {
+ gotc <- r.URL
+ },
+ optOnlyServer,
+ )
+ defer st.Close()
+
+ tr := &Transport{TLSClientConfig: tlsConfigInsecure}
+ defer tr.CloseIdleConnections()
+ const (
+ path = "/testpath"
+ query = "q=1"
+ )
+ surl := st.ts.URL + path + "?" + query
+ req, err := http.NewRequest("POST", surl, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ c := &http.Client{Transport: tr}
+ res, err := c.Do(req)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer res.Body.Close()
+ got := <-gotc
+ if got.Path != path {
+ t.Errorf("Read Path = %q; want %q", got.Path, path)
+ }
+ if got.RawQuery != query {
+ t.Errorf("Read RawQuery = %q; want %q", got.RawQuery, query)
+ }
+}
+
+func randString(n int) string {
+ rnd := rand.New(rand.NewSource(int64(n)))
+ b := make([]byte, n)
+ for i := range b {
+ b[i] = byte(rnd.Intn(256))
+ }
+ return string(b)
+}
+
+type panicReader struct{}
+
+func (panicReader) Read([]byte) (int, error) { panic("unexpected Read") }
+func (panicReader) Close() error { panic("unexpected Close") }
+
+func TestActualContentLength(t *testing.T) {
+ tests := []struct {
+ req *http.Request
+ want int64
+ }{
+ // Verify we don't read from Body:
+ 0: {
+ req: &http.Request{Body: panicReader{}},
+ want: -1,
+ },
+ // nil Body means 0, regardless of ContentLength:
+ 1: {
+ req: &http.Request{Body: nil, ContentLength: 5},
+ want: 0,
+ },
+ // ContentLength is used if set.
+ 2: {
+ req: &http.Request{Body: panicReader{}, ContentLength: 5},
+ want: 5,
+ },
+ // http.NoBody means 0, not -1.
+ 3: {
+ req: &http.Request{Body: go18httpNoBody()},
+ want: 0,
+ },
+ }
+ for i, tt := range tests {
+ got := actualContentLength(tt.req)
+ if got != tt.want {
+ t.Errorf("test[%d]: got %d; want %d", i, got, tt.want)
+ }
+ }
+}
+
+func TestTransportBody(t *testing.T) {
+ bodyTests := []struct {
+ body string
+ noContentLen bool
+ }{
+ {body: "some message"},
+ {body: "some message", noContentLen: true},
+ {body: strings.Repeat("a", 1<<20), noContentLen: true},
+ {body: strings.Repeat("a", 1<<20)},
+ {body: randString(16<<10 - 1)},
+ {body: randString(16 << 10)},
+ {body: randString(16<<10 + 1)},
+ {body: randString(512<<10 - 1)},
+ {body: randString(512 << 10)},
+ {body: randString(512<<10 + 1)},
+ {body: randString(1<<20 - 1)},
+ {body: randString(1 << 20)},
+ {body: randString(1<<20 + 2)},
+ }
+
+ type reqInfo struct {
+ req *http.Request
+ slurp []byte
+ err error
+ }
+ gotc := make(chan reqInfo, 1)
+ st := newServerTester(t,
+ func(w http.ResponseWriter, r *http.Request) {
+ slurp, err := ioutil.ReadAll(r.Body)
+ if err != nil {
+ gotc <- reqInfo{err: err}
+ } else {
+ gotc <- reqInfo{req: r, slurp: slurp}
+ }
+ },
+ optOnlyServer,
+ )
+ defer st.Close()
+
+ for i, tt := range bodyTests {
+ tr := &Transport{TLSClientConfig: tlsConfigInsecure}
+ defer tr.CloseIdleConnections()
+
+ var body io.Reader = strings.NewReader(tt.body)
+ if tt.noContentLen {
+ body = struct{ io.Reader }{body} // just a Reader, hiding concrete type and other methods
+ }
+ req, err := http.NewRequest("POST", st.ts.URL, body)
+ if err != nil {
+ t.Fatalf("#%d: %v", i, err)
+ }
+ c := &http.Client{Transport: tr}
+ res, err := c.Do(req)
+ if err != nil {
+ t.Fatalf("#%d: %v", i, err)
+ }
+ defer res.Body.Close()
+ ri := <-gotc
+ if ri.err != nil {
+ t.Errorf("#%d: read error: %v", i, ri.err)
+ continue
+ }
+ if got := string(ri.slurp); got != tt.body {
+ t.Errorf("#%d: Read body mismatch.\n got: %q (len %d)\nwant: %q (len %d)", i, shortString(got), len(got), shortString(tt.body), len(tt.body))
+ }
+ wantLen := int64(len(tt.body))
+ if tt.noContentLen && tt.body != "" {
+ wantLen = -1
+ }
+ if ri.req.ContentLength != wantLen {
+ t.Errorf("#%d. handler got ContentLength = %v; want %v", i, ri.req.ContentLength, wantLen)
+ }
+ }
+}
+
+func shortString(v string) string {
+ const maxLen = 100
+ if len(v) <= maxLen {
+ return v
+ }
+ return fmt.Sprintf("%v[...%d bytes omitted...]%v", v[:maxLen/2], len(v)-maxLen, v[len(v)-maxLen/2:])
+}
+
+func TestTransportDialTLS(t *testing.T) {
+ var mu sync.Mutex // guards following
+ var gotReq, didDial bool
+
+ ts := newServerTester(t,
+ func(w http.ResponseWriter, r *http.Request) {
+ mu.Lock()
+ gotReq = true
+ mu.Unlock()
+ },
+ optOnlyServer,
+ )
+ defer ts.Close()
+ tr := &Transport{
+ DialTLS: func(netw, addr string, cfg *tls.Config) (net.Conn, error) {
+ mu.Lock()
+ didDial = true
+ mu.Unlock()
+ cfg.InsecureSkipVerify = true
+ c, err := tls.Dial(netw, addr, cfg)
+ if err != nil {
+ return nil, err
+ }
+ return c, c.Handshake()
+ },
+ }
+ defer tr.CloseIdleConnections()
+ client := &http.Client{Transport: tr}
+ res, err := client.Get(ts.ts.URL)
+ if err != nil {
+ t.Fatal(err)
+ }
+ res.Body.Close()
+ mu.Lock()
+ if !gotReq {
+ t.Error("didn't get request")
+ }
+ if !didDial {
+ t.Error("didn't use dial hook")
+ }
+}
+
+func TestConfigureTransport(t *testing.T) {
+ t1 := &http.Transport{}
+ err := ConfigureTransport(t1)
+ if err == errTransportVersion {
+ t.Skip(err)
+ }
+ if err != nil {
+ t.Fatal(err)
+ }
+ if got := fmt.Sprintf("%#v", t1); !strings.Contains(got, `"h2"`) {
+ // Laziness, to avoid buildtags.
+ t.Errorf("stringification of HTTP/1 transport didn't contain \"h2\": %v", got)
+ }
+ wantNextProtos := []string{"h2", "http/1.1"}
+ if t1.TLSClientConfig == nil {
+ t.Errorf("nil t1.TLSClientConfig")
+ } else if !reflect.DeepEqual(t1.TLSClientConfig.NextProtos, wantNextProtos) {
+ t.Errorf("TLSClientConfig.NextProtos = %q; want %q", t1.TLSClientConfig.NextProtos, wantNextProtos)
+ }
+ if err := ConfigureTransport(t1); err == nil {
+ t.Error("unexpected success on second call to ConfigureTransport")
+ }
+
+ // And does it work?
+ st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+ io.WriteString(w, r.Proto)
+ }, optOnlyServer)
+ defer st.Close()
+
+ t1.TLSClientConfig.InsecureSkipVerify = true
+ c := &http.Client{Transport: t1}
+ res, err := c.Get(st.ts.URL)
+ if err != nil {
+ t.Fatal(err)
+ }
+ slurp, err := ioutil.ReadAll(res.Body)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if got, want := string(slurp), "HTTP/2.0"; got != want {
+ t.Errorf("body = %q; want %q", got, want)
+ }
+}
+
+type capitalizeReader struct {
+ r io.Reader
+}
+
+func (cr capitalizeReader) Read(p []byte) (n int, err error) {
+ n, err = cr.r.Read(p)
+ for i, b := range p[:n] {
+ if b >= 'a' && b <= 'z' {
+ p[i] = b - ('a' - 'A')
+ }
+ }
+ return
+}
+
+type flushWriter struct {
+ w io.Writer
+}
+
+func (fw flushWriter) Write(p []byte) (n int, err error) {
+ n, err = fw.w.Write(p)
+ if f, ok := fw.w.(http.Flusher); ok {
+ f.Flush()
+ }
+ return
+}
+
+type clientTester struct {
+ t *testing.T
+ tr *Transport
+ sc, cc net.Conn // server and client conn
+ fr *Framer // server's framer
+ client func() error
+ server func() error
+}
+
+func newClientTester(t *testing.T) *clientTester {
+ var dialOnce struct {
+ sync.Mutex
+ dialed bool
+ }
+ ct := &clientTester{
+ t: t,
+ }
+ ct.tr = &Transport{
+ TLSClientConfig: tlsConfigInsecure,
+ DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) {
+ dialOnce.Lock()
+ defer dialOnce.Unlock()
+ if dialOnce.dialed {
+ return nil, errors.New("only one dial allowed in test mode")
+ }
+ dialOnce.dialed = true
+ return ct.cc, nil
+ },
+ }
+
+ ln := newLocalListener(t)
+ cc, err := net.Dial("tcp", ln.Addr().String())
+ if err != nil {
+ t.Fatal(err)
+
+ }
+ sc, err := ln.Accept()
+ if err != nil {
+ t.Fatal(err)
+ }
+ ln.Close()
+ ct.cc = cc
+ ct.sc = sc
+ ct.fr = NewFramer(sc, sc)
+ return ct
+}
+
+func newLocalListener(t *testing.T) net.Listener {
+ ln, err := net.Listen("tcp4", "127.0.0.1:0")
+ if err == nil {
+ return ln
+ }
+ ln, err = net.Listen("tcp6", "[::1]:0")
+ if err != nil {
+ t.Fatal(err)
+ }
+ return ln
+}
+
+func (ct *clientTester) greet(settings ...Setting) {
+ buf := make([]byte, len(ClientPreface))
+ _, err := io.ReadFull(ct.sc, buf)
+ if err != nil {
+ ct.t.Fatalf("reading client preface: %v", err)
+ }
+ f, err := ct.fr.ReadFrame()
+ if err != nil {
+ ct.t.Fatalf("Reading client settings frame: %v", err)
+ }
+ if sf, ok := f.(*SettingsFrame); !ok {
+ ct.t.Fatalf("Wanted client settings frame; got %v", f)
+ _ = sf // stash it away?
+ }
+ if err := ct.fr.WriteSettings(settings...); err != nil {
+ ct.t.Fatal(err)
+ }
+ if err := ct.fr.WriteSettingsAck(); err != nil {
+ ct.t.Fatal(err)
+ }
+}
+
+func (ct *clientTester) readNonSettingsFrame() (Frame, error) {
+ for {
+ f, err := ct.fr.ReadFrame()
+ if err != nil {
+ return nil, err
+ }
+ if _, ok := f.(*SettingsFrame); ok {
+ continue
+ }
+ return f, nil
+ }
+}
+
+func (ct *clientTester) cleanup() {
+ ct.tr.CloseIdleConnections()
+}
+
+func (ct *clientTester) run() {
+ errc := make(chan error, 2)
+ ct.start("client", errc, ct.client)
+ ct.start("server", errc, ct.server)
+ defer ct.cleanup()
+ for i := 0; i < 2; i++ {
+ if err := <-errc; err != nil {
+ ct.t.Error(err)
+ return
+ }
+ }
+}
+
+func (ct *clientTester) start(which string, errc chan<- error, fn func() error) {
+ go func() {
+ finished := false
+ var err error
+ defer func() {
+ if !finished {
+ err = fmt.Errorf("%s goroutine didn't finish.", which)
+ } else if err != nil {
+ err = fmt.Errorf("%s: %v", which, err)
+ }
+ errc <- err
+ }()
+ err = fn()
+ finished = true
+ }()
+}
+
+func (ct *clientTester) readFrame() (Frame, error) {
+ return readFrameTimeout(ct.fr, 2*time.Second)
+}
+
+func (ct *clientTester) firstHeaders() (*HeadersFrame, error) {
+ for {
+ f, err := ct.readFrame()
+ if err != nil {
+ return nil, fmt.Errorf("ReadFrame while waiting for Headers: %v", err)
+ }
+ switch f.(type) {
+ case *WindowUpdateFrame, *SettingsFrame:
+ continue
+ }
+ hf, ok := f.(*HeadersFrame)
+ if !ok {
+ return nil, fmt.Errorf("Got %T; want HeadersFrame", f)
+ }
+ return hf, nil
+ }
+}
+
+type countingReader struct {
+ n *int64
+}
+
+func (r countingReader) Read(p []byte) (n int, err error) {
+ for i := range p {
+ p[i] = byte(i)
+ }
+ atomic.AddInt64(r.n, int64(len(p)))
+ return len(p), err
+}
+
+func TestTransportReqBodyAfterResponse_200(t *testing.T) { testTransportReqBodyAfterResponse(t, 200) }
+func TestTransportReqBodyAfterResponse_403(t *testing.T) { testTransportReqBodyAfterResponse(t, 403) }
+
+func testTransportReqBodyAfterResponse(t *testing.T, status int) {
+ const bodySize = 10 << 20
+ clientDone := make(chan struct{})
+ ct := newClientTester(t)
+ ct.client = func() error {
+ defer ct.cc.(*net.TCPConn).CloseWrite()
+ defer close(clientDone)
+
+ var n int64 // atomic
+ req, err := http.NewRequest("PUT", "https://dummy.tld/", io.LimitReader(countingReader{&n}, bodySize))
+ if err != nil {
+ return err
+ }
+ res, err := ct.tr.RoundTrip(req)
+ if err != nil {
+ return fmt.Errorf("RoundTrip: %v", err)
+ }
+ defer res.Body.Close()
+ if res.StatusCode != status {
+ return fmt.Errorf("status code = %v; want %v", res.StatusCode, status)
+ }
+ slurp, err := ioutil.ReadAll(res.Body)
+ if err != nil {
+ return fmt.Errorf("Slurp: %v", err)
+ }
+ if len(slurp) > 0 {
+ return fmt.Errorf("unexpected body: %q", slurp)
+ }
+ if status == 200 {
+ if got := atomic.LoadInt64(&n); got != bodySize {
+ return fmt.Errorf("For 200 response, Transport wrote %d bytes; want %d", got, bodySize)
+ }
+ } else {
+ if got := atomic.LoadInt64(&n); got == 0 || got >= bodySize {
+ return fmt.Errorf("For %d response, Transport wrote %d bytes; want (0,%d) exclusive", status, got, bodySize)
+ }
+ }
+ return nil
+ }
+ ct.server = func() error {
+ ct.greet()
+ var buf bytes.Buffer
+ enc := hpack.NewEncoder(&buf)
+ var dataRecv int64
+ var closed bool
+ for {
+ f, err := ct.fr.ReadFrame()
+ if err != nil {
+ select {
+ case <-clientDone:
+ // If the client's done, it
+ // will have reported any
+ // errors on its side.
+ return nil
+ default:
+ return err
+ }
+ }
+ //println(fmt.Sprintf("server got frame: %v", f))
+ switch f := f.(type) {
+ case *WindowUpdateFrame, *SettingsFrame:
+ case *HeadersFrame:
+ if !f.HeadersEnded() {
+ return fmt.Errorf("headers should have END_HEADERS be ended: %v", f)
+ }
+ if f.StreamEnded() {
+ return fmt.Errorf("headers contains END_STREAM unexpectedly: %v", f)
+ }
+ case *DataFrame:
+ dataLen := len(f.Data())
+ if dataLen > 0 {
+ if dataRecv == 0 {
+ enc.WriteField(hpack.HeaderField{Name: ":status", Value: strconv.Itoa(status)})
+ ct.fr.WriteHeaders(HeadersFrameParam{
+ StreamID: f.StreamID,
+ EndHeaders: true,
+ EndStream: false,
+ BlockFragment: buf.Bytes(),
+ })
+ }
+ if err := ct.fr.WriteWindowUpdate(0, uint32(dataLen)); err != nil {
+ return err
+ }
+ if err := ct.fr.WriteWindowUpdate(f.StreamID, uint32(dataLen)); err != nil {
+ return err
+ }
+ }
+ dataRecv += int64(dataLen)
+
+ if !closed && ((status != 200 && dataRecv > 0) ||
+ (status == 200 && dataRecv == bodySize)) {
+ closed = true
+ if err := ct.fr.WriteData(f.StreamID, true, nil); err != nil {
+ return err
+ }
+ }
+ default:
+ return fmt.Errorf("Unexpected client frame %v", f)
+ }
+ }
+ }
+ ct.run()
+}
+
+// See golang.org/issue/13444
+func TestTransportFullDuplex(t *testing.T) {
+ st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+ w.WriteHeader(200) // redundant but for clarity
+ w.(http.Flusher).Flush()
+ io.Copy(flushWriter{w}, capitalizeReader{r.Body})
+ fmt.Fprintf(w, "bye.\n")
+ }, optOnlyServer)
+ defer st.Close()
+
+ tr := &Transport{TLSClientConfig: tlsConfigInsecure}
+ defer tr.CloseIdleConnections()
+ c := &http.Client{Transport: tr}
+
+ pr, pw := io.Pipe()
+ req, err := http.NewRequest("PUT", st.ts.URL, ioutil.NopCloser(pr))
+ if err != nil {
+ t.Fatal(err)
+ }
+ req.ContentLength = -1
+ res, err := c.Do(req)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer res.Body.Close()
+ if res.StatusCode != 200 {
+ t.Fatalf("StatusCode = %v; want %v", res.StatusCode, 200)
+ }
+ bs := bufio.NewScanner(res.Body)
+ want := func(v string) {
+ if !bs.Scan() {
+ t.Fatalf("wanted to read %q but Scan() = false, err = %v", v, bs.Err())
+ }
+ }
+ write := func(v string) {
+ _, err := io.WriteString(pw, v)
+ if err != nil {
+ t.Fatalf("pipe write: %v", err)
+ }
+ }
+ write("foo\n")
+ want("FOO")
+ write("bar\n")
+ want("BAR")
+ pw.Close()
+ want("bye.")
+ if err := bs.Err(); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestTransportConnectRequest(t *testing.T) {
+ gotc := make(chan *http.Request, 1)
+ st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+ gotc <- r
+ }, optOnlyServer)
+ defer st.Close()
+
+ u, err := url.Parse(st.ts.URL)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ tr := &Transport{TLSClientConfig: tlsConfigInsecure}
+ defer tr.CloseIdleConnections()
+ c := &http.Client{Transport: tr}
+
+ tests := []struct {
+ req *http.Request
+ want string
+ }{
+ {
+ req: &http.Request{
+ Method: "CONNECT",
+ Header: http.Header{},
+ URL: u,
+ },
+ want: u.Host,
+ },
+ {
+ req: &http.Request{
+ Method: "CONNECT",
+ Header: http.Header{},
+ URL: u,
+ Host: "example.com:123",
+ },
+ want: "example.com:123",
+ },
+ }
+
+ for i, tt := range tests {
+ res, err := c.Do(tt.req)
+ if err != nil {
+ t.Errorf("%d. RoundTrip = %v", i, err)
+ continue
+ }
+ res.Body.Close()
+ req := <-gotc
+ if req.Method != "CONNECT" {
+ t.Errorf("method = %q; want CONNECT", req.Method)
+ }
+ if req.Host != tt.want {
+ t.Errorf("Host = %q; want %q", req.Host, tt.want)
+ }
+ if req.URL.Host != tt.want {
+ t.Errorf("URL.Host = %q; want %q", req.URL.Host, tt.want)
+ }
+ }
+}
+
+type headerType int
+
+const (
+ noHeader headerType = iota // omitted
+ oneHeader
+ splitHeader // broken into continuation on purpose
+)
+
+const (
+ f0 = noHeader
+ f1 = oneHeader
+ f2 = splitHeader
+ d0 = false
+ d1 = true
+)
+
+// Test all 36 combinations of response frame orders:
+// (3 ways of 100-continue) * (2 ways of headers) * (2 ways of data) * (3 ways of trailers):func TestTransportResponsePattern_00f0(t *testing.T) { testTransportResponsePattern(h0, h1, false, h0) }
+// Generated by http://play.golang.org/p/SScqYKJYXd
+func TestTransportResPattern_c0h1d0t0(t *testing.T) { testTransportResPattern(t, f0, f1, d0, f0) }
+func TestTransportResPattern_c0h1d0t1(t *testing.T) { testTransportResPattern(t, f0, f1, d0, f1) }
+func TestTransportResPattern_c0h1d0t2(t *testing.T) { testTransportResPattern(t, f0, f1, d0, f2) }
+func TestTransportResPattern_c0h1d1t0(t *testing.T) { testTransportResPattern(t, f0, f1, d1, f0) }
+func TestTransportResPattern_c0h1d1t1(t *testing.T) { testTransportResPattern(t, f0, f1, d1, f1) }
+func TestTransportResPattern_c0h1d1t2(t *testing.T) { testTransportResPattern(t, f0, f1, d1, f2) }
+func TestTransportResPattern_c0h2d0t0(t *testing.T) { testTransportResPattern(t, f0, f2, d0, f0) }
+func TestTransportResPattern_c0h2d0t1(t *testing.T) { testTransportResPattern(t, f0, f2, d0, f1) }
+func TestTransportResPattern_c0h2d0t2(t *testing.T) { testTransportResPattern(t, f0, f2, d0, f2) }
+func TestTransportResPattern_c0h2d1t0(t *testing.T) { testTransportResPattern(t, f0, f2, d1, f0) }
+func TestTransportResPattern_c0h2d1t1(t *testing.T) { testTransportResPattern(t, f0, f2, d1, f1) }
+func TestTransportResPattern_c0h2d1t2(t *testing.T) { testTransportResPattern(t, f0, f2, d1, f2) }
+func TestTransportResPattern_c1h1d0t0(t *testing.T) { testTransportResPattern(t, f1, f1, d0, f0) }
+func TestTransportResPattern_c1h1d0t1(t *testing.T) { testTransportResPattern(t, f1, f1, d0, f1) }
+func TestTransportResPattern_c1h1d0t2(t *testing.T) { testTransportResPattern(t, f1, f1, d0, f2) }
+func TestTransportResPattern_c1h1d1t0(t *testing.T) { testTransportResPattern(t, f1, f1, d1, f0) }
+func TestTransportResPattern_c1h1d1t1(t *testing.T) { testTransportResPattern(t, f1, f1, d1, f1) }
+func TestTransportResPattern_c1h1d1t2(t *testing.T) { testTransportResPattern(t, f1, f1, d1, f2) }
+func TestTransportResPattern_c1h2d0t0(t *testing.T) { testTransportResPattern(t, f1, f2, d0, f0) }
+func TestTransportResPattern_c1h2d0t1(t *testing.T) { testTransportResPattern(t, f1, f2, d0, f1) }
+func TestTransportResPattern_c1h2d0t2(t *testing.T) { testTransportResPattern(t, f1, f2, d0, f2) }
+func TestTransportResPattern_c1h2d1t0(t *testing.T) { testTransportResPattern(t, f1, f2, d1, f0) }
+func TestTransportResPattern_c1h2d1t1(t *testing.T) { testTransportResPattern(t, f1, f2, d1, f1) }
+func TestTransportResPattern_c1h2d1t2(t *testing.T) { testTransportResPattern(t, f1, f2, d1, f2) }
+func TestTransportResPattern_c2h1d0t0(t *testing.T) { testTransportResPattern(t, f2, f1, d0, f0) }
+func TestTransportResPattern_c2h1d0t1(t *testing.T) { testTransportResPattern(t, f2, f1, d0, f1) }
+func TestTransportResPattern_c2h1d0t2(t *testing.T) { testTransportResPattern(t, f2, f1, d0, f2) }
+func TestTransportResPattern_c2h1d1t0(t *testing.T) { testTransportResPattern(t, f2, f1, d1, f0) }
+func TestTransportResPattern_c2h1d1t1(t *testing.T) { testTransportResPattern(t, f2, f1, d1, f1) }
+func TestTransportResPattern_c2h1d1t2(t *testing.T) { testTransportResPattern(t, f2, f1, d1, f2) }
+func TestTransportResPattern_c2h2d0t0(t *testing.T) { testTransportResPattern(t, f2, f2, d0, f0) }
+func TestTransportResPattern_c2h2d0t1(t *testing.T) { testTransportResPattern(t, f2, f2, d0, f1) }
+func TestTransportResPattern_c2h2d0t2(t *testing.T) { testTransportResPattern(t, f2, f2, d0, f2) }
+func TestTransportResPattern_c2h2d1t0(t *testing.T) { testTransportResPattern(t, f2, f2, d1, f0) }
+func TestTransportResPattern_c2h2d1t1(t *testing.T) { testTransportResPattern(t, f2, f2, d1, f1) }
+func TestTransportResPattern_c2h2d1t2(t *testing.T) { testTransportResPattern(t, f2, f2, d1, f2) }
+
+func testTransportResPattern(t *testing.T, expect100Continue, resHeader headerType, withData bool, trailers headerType) {
+ const reqBody = "some request body"
+ const resBody = "some response body"
+
+ if resHeader == noHeader {
+ // TODO: test 100-continue followed by immediate
+ // server stream reset, without headers in the middle?
+ panic("invalid combination")
+ }
+
+ ct := newClientTester(t)
+ ct.client = func() error {
+ req, _ := http.NewRequest("POST", "https://dummy.tld/", strings.NewReader(reqBody))
+ if expect100Continue != noHeader {
+ req.Header.Set("Expect", "100-continue")
+ }
+ res, err := ct.tr.RoundTrip(req)
+ if err != nil {
+ return fmt.Errorf("RoundTrip: %v", err)
+ }
+ defer res.Body.Close()
+ if res.StatusCode != 200 {
+ return fmt.Errorf("status code = %v; want 200", res.StatusCode)
+ }
+ slurp, err := ioutil.ReadAll(res.Body)
+ if err != nil {
+ return fmt.Errorf("Slurp: %v", err)
+ }
+ wantBody := resBody
+ if !withData {
+ wantBody = ""
+ }
+ if string(slurp) != wantBody {
+ return fmt.Errorf("body = %q; want %q", slurp, wantBody)
+ }
+ if trailers == noHeader {
+ if len(res.Trailer) > 0 {
+ t.Errorf("Trailer = %v; want none", res.Trailer)
+ }
+ } else {
+ want := http.Header{"Some-Trailer": {"some-value"}}
+ if !reflect.DeepEqual(res.Trailer, want) {
+ t.Errorf("Trailer = %v; want %v", res.Trailer, want)
+ }
+ }
+ return nil
+ }
+ ct.server = func() error {
+ ct.greet()
+ var buf bytes.Buffer
+ enc := hpack.NewEncoder(&buf)
+
+ for {
+ f, err := ct.fr.ReadFrame()
+ if err != nil {
+ return err
+ }
+ endStream := false
+ send := func(mode headerType) {
+ hbf := buf.Bytes()
+ switch mode {
+ case oneHeader:
+ ct.fr.WriteHeaders(HeadersFrameParam{
+ StreamID: f.Header().StreamID,
+ EndHeaders: true,
+ EndStream: endStream,
+ BlockFragment: hbf,
+ })
+ case splitHeader:
+ if len(hbf) < 2 {
+ panic("too small")
+ }
+ ct.fr.WriteHeaders(HeadersFrameParam{
+ StreamID: f.Header().StreamID,
+ EndHeaders: false,
+ EndStream: endStream,
+ BlockFragment: hbf[:1],
+ })
+ ct.fr.WriteContinuation(f.Header().StreamID, true, hbf[1:])
+ default:
+ panic("bogus mode")
+ }
+ }
+ switch f := f.(type) {
+ case *WindowUpdateFrame, *SettingsFrame:
+ case *DataFrame:
+ if !f.StreamEnded() {
+ // No need to send flow control tokens. The test request body is tiny.
+ continue
+ }
+ // Response headers (1+ frames; 1 or 2 in this test, but never 0)
+ {
+ buf.Reset()
+ enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"})
+ enc.WriteField(hpack.HeaderField{Name: "x-foo", Value: "blah"})
+ enc.WriteField(hpack.HeaderField{Name: "x-bar", Value: "more"})
+ if trailers != noHeader {
+ enc.WriteField(hpack.HeaderField{Name: "trailer", Value: "some-trailer"})
+ }
+ endStream = withData == false && trailers == noHeader
+ send(resHeader)
+ }
+ if withData {
+ endStream = trailers == noHeader
+ ct.fr.WriteData(f.StreamID, endStream, []byte(resBody))
+ }
+ if trailers != noHeader {
+ endStream = true
+ buf.Reset()
+ enc.WriteField(hpack.HeaderField{Name: "some-trailer", Value: "some-value"})
+ send(trailers)
+ }
+ if endStream {
+ return nil
+ }
+ case *HeadersFrame:
+ if expect100Continue != noHeader {
+ buf.Reset()
+ enc.WriteField(hpack.HeaderField{Name: ":status", Value: "100"})
+ send(expect100Continue)
+ }
+ }
+ }
+ }
+ ct.run()
+}
+
+func TestTransportReceiveUndeclaredTrailer(t *testing.T) {
+ ct := newClientTester(t)
+ ct.client = func() error {
+ req, _ := http.NewRequest("GET", "https://dummy.tld/", nil)
+ res, err := ct.tr.RoundTrip(req)
+ if err != nil {
+ return fmt.Errorf("RoundTrip: %v", err)
+ }
+ defer res.Body.Close()
+ if res.StatusCode != 200 {
+ return fmt.Errorf("status code = %v; want 200", res.StatusCode)
+ }
+ slurp, err := ioutil.ReadAll(res.Body)
+ if err != nil {
+ return fmt.Errorf("res.Body ReadAll error = %q, %v; want %v", slurp, err, nil)
+ }
+ if len(slurp) > 0 {
+ return fmt.Errorf("body = %q; want nothing", slurp)
+ }
+ if _, ok := res.Trailer["Some-Trailer"]; !ok {
+ return fmt.Errorf("expected Some-Trailer")
+ }
+ return nil
+ }
+ ct.server = func() error {
+ ct.greet()
+
+ var n int
+ var hf *HeadersFrame
+ for hf == nil && n < 10 {
+ f, err := ct.fr.ReadFrame()
+ if err != nil {
+ return err
+ }
+ hf, _ = f.(*HeadersFrame)
+ n++
+ }
+
+ var buf bytes.Buffer
+ enc := hpack.NewEncoder(&buf)
+
+ // send headers without Trailer header
+ enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"})
+ ct.fr.WriteHeaders(HeadersFrameParam{
+ StreamID: hf.StreamID,
+ EndHeaders: true,
+ EndStream: false,
+ BlockFragment: buf.Bytes(),
+ })
+
+ // send trailers
+ buf.Reset()
+ enc.WriteField(hpack.HeaderField{Name: "some-trailer", Value: "I'm an undeclared Trailer!"})
+ ct.fr.WriteHeaders(HeadersFrameParam{
+ StreamID: hf.StreamID,
+ EndHeaders: true,
+ EndStream: true,
+ BlockFragment: buf.Bytes(),
+ })
+ return nil
+ }
+ ct.run()
+}
+
+func TestTransportInvalidTrailer_Pseudo1(t *testing.T) {
+ testTransportInvalidTrailer_Pseudo(t, oneHeader)
+}
+func TestTransportInvalidTrailer_Pseudo2(t *testing.T) {
+ testTransportInvalidTrailer_Pseudo(t, splitHeader)
+}
+func testTransportInvalidTrailer_Pseudo(t *testing.T, trailers headerType) {
+ testInvalidTrailer(t, trailers, pseudoHeaderError(":colon"), func(enc *hpack.Encoder) {
+ enc.WriteField(hpack.HeaderField{Name: ":colon", Value: "foo"})
+ enc.WriteField(hpack.HeaderField{Name: "foo", Value: "bar"})
+ })
+}
+
+func TestTransportInvalidTrailer_Capital1(t *testing.T) {
+ testTransportInvalidTrailer_Capital(t, oneHeader)
+}
+func TestTransportInvalidTrailer_Capital2(t *testing.T) {
+ testTransportInvalidTrailer_Capital(t, splitHeader)
+}
+func testTransportInvalidTrailer_Capital(t *testing.T, trailers headerType) {
+ testInvalidTrailer(t, trailers, headerFieldNameError("Capital"), func(enc *hpack.Encoder) {
+ enc.WriteField(hpack.HeaderField{Name: "foo", Value: "bar"})
+ enc.WriteField(hpack.HeaderField{Name: "Capital", Value: "bad"})
+ })
+}
+func TestTransportInvalidTrailer_EmptyFieldName(t *testing.T) {
+ testInvalidTrailer(t, oneHeader, headerFieldNameError(""), func(enc *hpack.Encoder) {
+ enc.WriteField(hpack.HeaderField{Name: "", Value: "bad"})
+ })
+}
+func TestTransportInvalidTrailer_BinaryFieldValue(t *testing.T) {
+ testInvalidTrailer(t, oneHeader, headerFieldValueError("has\nnewline"), func(enc *hpack.Encoder) {
+ enc.WriteField(hpack.HeaderField{Name: "x", Value: "has\nnewline"})
+ })
+}
+
+func testInvalidTrailer(t *testing.T, trailers headerType, wantErr error, writeTrailer func(*hpack.Encoder)) {
+ ct := newClientTester(t)
+ ct.client = func() error {
+ req, _ := http.NewRequest("GET", "https://dummy.tld/", nil)
+ res, err := ct.tr.RoundTrip(req)
+ if err != nil {
+ return fmt.Errorf("RoundTrip: %v", err)
+ }
+ defer res.Body.Close()
+ if res.StatusCode != 200 {
+ return fmt.Errorf("status code = %v; want 200", res.StatusCode)
+ }
+ slurp, err := ioutil.ReadAll(res.Body)
+ se, ok := err.(StreamError)
+ if !ok || se.Cause != wantErr {
+ return fmt.Errorf("res.Body ReadAll error = %q, %#v; want StreamError with cause %T, %#v", slurp, err, wantErr, wantErr)
+ }
+ if len(slurp) > 0 {
+ return fmt.Errorf("body = %q; want nothing", slurp)
+ }
+ return nil
+ }
+ ct.server = func() error {
+ ct.greet()
+ var buf bytes.Buffer
+ enc := hpack.NewEncoder(&buf)
+
+ for {
+ f, err := ct.fr.ReadFrame()
+ if err != nil {
+ return err
+ }
+ switch f := f.(type) {
+ case *HeadersFrame:
+ var endStream bool
+ send := func(mode headerType) {
+ hbf := buf.Bytes()
+ switch mode {
+ case oneHeader:
+ ct.fr.WriteHeaders(HeadersFrameParam{
+ StreamID: f.StreamID,
+ EndHeaders: true,
+ EndStream: endStream,
+ BlockFragment: hbf,
+ })
+ case splitHeader:
+ if len(hbf) < 2 {
+ panic("too small")
+ }
+ ct.fr.WriteHeaders(HeadersFrameParam{
+ StreamID: f.StreamID,
+ EndHeaders: false,
+ EndStream: endStream,
+ BlockFragment: hbf[:1],
+ })
+ ct.fr.WriteContinuation(f.StreamID, true, hbf[1:])
+ default:
+ panic("bogus mode")
+ }
+ }
+ // Response headers (1+ frames; 1 or 2 in this test, but never 0)
+ {
+ buf.Reset()
+ enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"})
+ enc.WriteField(hpack.HeaderField{Name: "trailer", Value: "declared"})
+ endStream = false
+ send(oneHeader)
+ }
+ // Trailers:
+ {
+ endStream = true
+ buf.Reset()
+ writeTrailer(enc)
+ send(trailers)
+ }
+ return nil
+ }
+ }
+ }
+ ct.run()
+}
+
+// headerListSize returns the HTTP2 header list size of h.
+// http://httpwg.org/specs/rfc7540.html#SETTINGS_MAX_HEADER_LIST_SIZE
+// http://httpwg.org/specs/rfc7540.html#MaxHeaderBlock
+func headerListSize(h http.Header) (size uint32) {
+ for k, vv := range h {
+ for _, v := range vv {
+ hf := hpack.HeaderField{Name: k, Value: v}
+ size += hf.Size()
+ }
+ }
+ return size
+}
+
+// padHeaders adds data to an http.Header until headerListSize(h) ==
+// limit. Due to the way header list sizes are calculated, padHeaders
+// cannot add fewer than len("Pad-Headers") + 32 bytes to h, and will
+// call t.Fatal if asked to do so. PadHeaders first reserves enough
+// space for an empty "Pad-Headers" key, then adds as many copies of
+// filler as possible. Any remaining bytes necessary to push the
+// header list size up to limit are added to h["Pad-Headers"].
+func padHeaders(t *testing.T, h http.Header, limit uint64, filler string) {
+ if limit > 0xffffffff {
+ t.Fatalf("padHeaders: refusing to pad to more than 2^32-1 bytes. limit = %v", limit)
+ }
+ hf := hpack.HeaderField{Name: "Pad-Headers", Value: ""}
+ minPadding := uint64(hf.Size())
+ size := uint64(headerListSize(h))
+
+ minlimit := size + minPadding
+ if limit < minlimit {
+ t.Fatalf("padHeaders: limit %v < %v", limit, minlimit)
+ }
+
+ // Use a fixed-width format for name so that fieldSize
+ // remains constant.
+ nameFmt := "Pad-Headers-%06d"
+ hf = hpack.HeaderField{Name: fmt.Sprintf(nameFmt, 1), Value: filler}
+ fieldSize := uint64(hf.Size())
+
+ // Add as many complete filler values as possible, leaving
+ // room for at least one empty "Pad-Headers" key.
+ limit = limit - minPadding
+ for i := 0; size+fieldSize < limit; i++ {
+ name := fmt.Sprintf(nameFmt, i)
+ h.Add(name, filler)
+ size += fieldSize
+ }
+
+ // Add enough bytes to reach limit.
+ remain := limit - size
+ lastValue := strings.Repeat("*", int(remain))
+ h.Add("Pad-Headers", lastValue)
+}
+
+func TestPadHeaders(t *testing.T) {
+ check := func(h http.Header, limit uint32, fillerLen int) {
+ if h == nil {
+ h = make(http.Header)
+ }
+ filler := strings.Repeat("f", fillerLen)
+ padHeaders(t, h, uint64(limit), filler)
+ gotSize := headerListSize(h)
+ if gotSize != limit {
+ t.Errorf("Got size = %v; want %v", gotSize, limit)
+ }
+ }
+ // Try all possible combinations for small fillerLen and limit.
+ hf := hpack.HeaderField{Name: "Pad-Headers", Value: ""}
+ minLimit := hf.Size()
+ for limit := minLimit; limit <= 128; limit++ {
+ for fillerLen := 0; uint32(fillerLen) <= limit; fillerLen++ {
+ check(nil, limit, fillerLen)
+ }
+ }
+
+ // Try a few tests with larger limits, plus cumulative
+ // tests. Since these tests are cumulative, tests[i+1].limit
+ // must be >= tests[i].limit + minLimit. See the comment on
+ // padHeaders for more info on why the limit arg has this
+ // restriction.
+ tests := []struct {
+ fillerLen int
+ limit uint32
+ }{
+ {
+ fillerLen: 64,
+ limit: 1024,
+ },
+ {
+ fillerLen: 1024,
+ limit: 1286,
+ },
+ {
+ fillerLen: 256,
+ limit: 2048,
+ },
+ {
+ fillerLen: 1024,
+ limit: 10 * 1024,
+ },
+ {
+ fillerLen: 1023,
+ limit: 11 * 1024,
+ },
+ }
+ h := make(http.Header)
+ for _, tc := range tests {
+ check(nil, tc.limit, tc.fillerLen)
+ check(h, tc.limit, tc.fillerLen)
+ }
+}
+
+func TestTransportChecksRequestHeaderListSize(t *testing.T) {
+ st := newServerTester(t,
+ func(w http.ResponseWriter, r *http.Request) {
+ // Consume body & force client to send
+ // trailers before writing response.
+ // ioutil.ReadAll returns non-nil err for
+ // requests that attempt to send greater than
+ // maxHeaderListSize bytes of trailers, since
+ // those requests generate a stream reset.
+ ioutil.ReadAll(r.Body)
+ r.Body.Close()
+ },
+ func(ts *httptest.Server) {
+ ts.Config.MaxHeaderBytes = 16 << 10
+ },
+ optOnlyServer,
+ optQuiet,
+ )
+ defer st.Close()
+
+ tr := &Transport{TLSClientConfig: tlsConfigInsecure}
+ defer tr.CloseIdleConnections()
+
+ checkRoundTrip := func(req *http.Request, wantErr error, desc string) {
+ res, err := tr.RoundTrip(req)
+ if err != wantErr {
+ if res != nil {
+ res.Body.Close()
+ }
+ t.Errorf("%v: RoundTrip err = %v; want %v", desc, err, wantErr)
+ return
+ }
+ if err == nil {
+ if res == nil {
+ t.Errorf("%v: response nil; want non-nil.", desc)
+ return
+ }
+ defer res.Body.Close()
+ if res.StatusCode != http.StatusOK {
+ t.Errorf("%v: response status = %v; want %v", desc, res.StatusCode, http.StatusOK)
+ }
+ return
+ }
+ if res != nil {
+ t.Errorf("%v: RoundTrip err = %v but response non-nil", desc, err)
+ }
+ }
+ headerListSizeForRequest := func(req *http.Request) (size uint64) {
+ contentLen := actualContentLength(req)
+ trailers, err := commaSeparatedTrailers(req)
+ if err != nil {
+ t.Fatalf("headerListSizeForRequest: %v", err)
+ }
+ cc := &ClientConn{peerMaxHeaderListSize: 0xffffffffffffffff}
+ cc.henc = hpack.NewEncoder(&cc.hbuf)
+ cc.mu.Lock()
+ hdrs, err := cc.encodeHeaders(req, true, trailers, contentLen)
+ cc.mu.Unlock()
+ if err != nil {
+ t.Fatalf("headerListSizeForRequest: %v", err)
+ }
+ hpackDec := hpack.NewDecoder(initialHeaderTableSize, func(hf hpack.HeaderField) {
+ size += uint64(hf.Size())
+ })
+ if len(hdrs) > 0 {
+ if _, err := hpackDec.Write(hdrs); err != nil {
+ t.Fatalf("headerListSizeForRequest: %v", err)
+ }
+ }
+ return size
+ }
+ // Create a new Request for each test, rather than reusing the
+ // same Request, to avoid a race when modifying req.Headers.
+ // See https://github.com/golang/go/issues/21316
+ newRequest := func() *http.Request {
+ // Body must be non-nil to enable writing trailers.
+ body := strings.NewReader("hello")
+ req, err := http.NewRequest("POST", st.ts.URL, body)
+ if err != nil {
+ t.Fatalf("newRequest: NewRequest: %v", err)
+ }
+ return req
+ }
+
+ // Make an arbitrary request to ensure we get the server's
+ // settings frame and initialize peerMaxHeaderListSize.
+ req := newRequest()
+ checkRoundTrip(req, nil, "Initial request")
+
+ // Get the ClientConn associated with the request and validate
+ // peerMaxHeaderListSize.
+ addr := authorityAddr(req.URL.Scheme, req.URL.Host)
+ cc, err := tr.connPool().GetClientConn(req, addr)
+ if err != nil {
+ t.Fatalf("GetClientConn: %v", err)
+ }
+ cc.mu.Lock()
+ peerSize := cc.peerMaxHeaderListSize
+ cc.mu.Unlock()
+ st.scMu.Lock()
+ wantSize := uint64(st.sc.maxHeaderListSize())
+ st.scMu.Unlock()
+ if peerSize != wantSize {
+ t.Errorf("peerMaxHeaderListSize = %v; want %v", peerSize, wantSize)
+ }
+
+ // Sanity check peerSize. (*serverConn) maxHeaderListSize adds
+ // 320 bytes of padding.
+ wantHeaderBytes := uint64(st.ts.Config.MaxHeaderBytes) + 320
+ if peerSize != wantHeaderBytes {
+ t.Errorf("peerMaxHeaderListSize = %v; want %v.", peerSize, wantHeaderBytes)
+ }
+
+ // Pad headers & trailers, but stay under peerSize.
+ req = newRequest()
+ req.Header = make(http.Header)
+ req.Trailer = make(http.Header)
+ filler := strings.Repeat("*", 1024)
+ padHeaders(t, req.Trailer, peerSize, filler)
+ // cc.encodeHeaders adds some default headers to the request,
+ // so we need to leave room for those.
+ defaultBytes := headerListSizeForRequest(req)
+ padHeaders(t, req.Header, peerSize-defaultBytes, filler)
+ checkRoundTrip(req, nil, "Headers & Trailers under limit")
+
+ // Add enough header bytes to push us over peerSize.
+ req = newRequest()
+ req.Header = make(http.Header)
+ padHeaders(t, req.Header, peerSize, filler)
+ checkRoundTrip(req, errRequestHeaderListSize, "Headers over limit")
+
+ // Push trailers over the limit.
+ req = newRequest()
+ req.Trailer = make(http.Header)
+ padHeaders(t, req.Trailer, peerSize+1, filler)
+ checkRoundTrip(req, errRequestHeaderListSize, "Trailers over limit")
+
+ // Send headers with a single large value.
+ req = newRequest()
+ filler = strings.Repeat("*", int(peerSize))
+ req.Header = make(http.Header)
+ req.Header.Set("Big", filler)
+ checkRoundTrip(req, errRequestHeaderListSize, "Single large header")
+
+ // Send trailers with a single large value.
+ req = newRequest()
+ req.Trailer = make(http.Header)
+ req.Trailer.Set("Big", filler)
+ checkRoundTrip(req, errRequestHeaderListSize, "Single large trailer")
+}
+
+func TestTransportChecksResponseHeaderListSize(t *testing.T) {
+ ct := newClientTester(t)
+ ct.client = func() error {
+ req, _ := http.NewRequest("GET", "https://dummy.tld/", nil)
+ res, err := ct.tr.RoundTrip(req)
+ if err != errResponseHeaderListSize {
+ if res != nil {
+ res.Body.Close()
+ }
+ size := int64(0)
+ for k, vv := range res.Header {
+ for _, v := range vv {
+ size += int64(len(k)) + int64(len(v)) + 32
+ }
+ }
+ return fmt.Errorf("RoundTrip Error = %v (and %d bytes of response headers); want errResponseHeaderListSize", err, size)
+ }
+ return nil
+ }
+ ct.server = func() error {
+ ct.greet()
+ var buf bytes.Buffer
+ enc := hpack.NewEncoder(&buf)
+
+ for {
+ f, err := ct.fr.ReadFrame()
+ if err != nil {
+ return err
+ }
+ switch f := f.(type) {
+ case *HeadersFrame:
+ enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"})
+ large := strings.Repeat("a", 1<<10)
+ for i := 0; i < 5042; i++ {
+ enc.WriteField(hpack.HeaderField{Name: large, Value: large})
+ }
+ if size, want := buf.Len(), 6329; size != want {
+ // Note: this number might change if
+ // our hpack implementation
+ // changes. That's fine. This is
+ // just a sanity check that our
+ // response can fit in a single
+ // header block fragment frame.
+ return fmt.Errorf("encoding over 10MB of duplicate keypairs took %d bytes; expected %d", size, want)
+ }
+ ct.fr.WriteHeaders(HeadersFrameParam{
+ StreamID: f.StreamID,
+ EndHeaders: true,
+ EndStream: true,
+ BlockFragment: buf.Bytes(),
+ })
+ return nil
+ }
+ }
+ }
+ ct.run()
+}
+
+// Test that the the Transport returns a typed error from Response.Body.Read calls
+// when the server sends an error. (here we use a panic, since that should generate
+// a stream error, but others like cancel should be similar)
+func TestTransportBodyReadErrorType(t *testing.T) {
+ doPanic := make(chan bool, 1)
+ st := newServerTester(t,
+ func(w http.ResponseWriter, r *http.Request) {
+ w.(http.Flusher).Flush() // force headers out
+ <-doPanic
+ panic("boom")
+ },
+ optOnlyServer,
+ optQuiet,
+ )
+ defer st.Close()
+
+ tr := &Transport{TLSClientConfig: tlsConfigInsecure}
+ defer tr.CloseIdleConnections()
+ c := &http.Client{Transport: tr}
+
+ res, err := c.Get(st.ts.URL)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer res.Body.Close()
+ doPanic <- true
+ buf := make([]byte, 100)
+ n, err := res.Body.Read(buf)
+ want := StreamError{StreamID: 0x1, Code: 0x2}
+ if !reflect.DeepEqual(want, err) {
+ t.Errorf("Read = %v, %#v; want error %#v", n, err, want)
+ }
+}
+
+// golang.org/issue/13924
+// This used to fail after many iterations, especially with -race:
+// go test -v -run=TestTransportDoubleCloseOnWriteError -count=500 -race
+func TestTransportDoubleCloseOnWriteError(t *testing.T) {
+ var (
+ mu sync.Mutex
+ conn net.Conn // to close if set
+ )
+
+ st := newServerTester(t,
+ func(w http.ResponseWriter, r *http.Request) {
+ mu.Lock()
+ defer mu.Unlock()
+ if conn != nil {
+ conn.Close()
+ }
+ },
+ optOnlyServer,
+ )
+ defer st.Close()
+
+ tr := &Transport{
+ TLSClientConfig: tlsConfigInsecure,
+ DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) {
+ tc, err := tls.Dial(network, addr, cfg)
+ if err != nil {
+ return nil, err
+ }
+ mu.Lock()
+ defer mu.Unlock()
+ conn = tc
+ return tc, nil
+ },
+ }
+ defer tr.CloseIdleConnections()
+ c := &http.Client{Transport: tr}
+ c.Get(st.ts.URL)
+}
+
+// Test that the http1 Transport.DisableKeepAlives option is respected
+// and connections are closed as soon as idle.
+// See golang.org/issue/14008
+func TestTransportDisableKeepAlives(t *testing.T) {
+ st := newServerTester(t,
+ func(w http.ResponseWriter, r *http.Request) {
+ io.WriteString(w, "hi")
+ },
+ optOnlyServer,
+ )
+ defer st.Close()
+
+ connClosed := make(chan struct{}) // closed on tls.Conn.Close
+ tr := &Transport{
+ t1: &http.Transport{
+ DisableKeepAlives: true,
+ },
+ TLSClientConfig: tlsConfigInsecure,
+ DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) {
+ tc, err := tls.Dial(network, addr, cfg)
+ if err != nil {
+ return nil, err
+ }
+ return &noteCloseConn{Conn: tc, closefn: func() { close(connClosed) }}, nil
+ },
+ }
+ c := &http.Client{Transport: tr}
+ res, err := c.Get(st.ts.URL)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if _, err := ioutil.ReadAll(res.Body); err != nil {
+ t.Fatal(err)
+ }
+ defer res.Body.Close()
+
+ select {
+ case <-connClosed:
+ case <-time.After(1 * time.Second):
+ t.Errorf("timeout")
+ }
+
+}
+
+// Test concurrent requests with Transport.DisableKeepAlives. We can share connections,
+// but when things are totally idle, it still needs to close.
+func TestTransportDisableKeepAlives_Concurrency(t *testing.T) {
+ const D = 25 * time.Millisecond
+ st := newServerTester(t,
+ func(w http.ResponseWriter, r *http.Request) {
+ time.Sleep(D)
+ io.WriteString(w, "hi")
+ },
+ optOnlyServer,
+ )
+ defer st.Close()
+
+ var dials int32
+ var conns sync.WaitGroup
+ tr := &Transport{
+ t1: &http.Transport{
+ DisableKeepAlives: true,
+ },
+ TLSClientConfig: tlsConfigInsecure,
+ DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) {
+ tc, err := tls.Dial(network, addr, cfg)
+ if err != nil {
+ return nil, err
+ }
+ atomic.AddInt32(&dials, 1)
+ conns.Add(1)
+ return &noteCloseConn{Conn: tc, closefn: func() { conns.Done() }}, nil
+ },
+ }
+ c := &http.Client{Transport: tr}
+ var reqs sync.WaitGroup
+ const N = 20
+ for i := 0; i < N; i++ {
+ reqs.Add(1)
+ if i == N-1 {
+ // For the final request, try to make all the
+ // others close. This isn't verified in the
+ // count, other than the Log statement, since
+ // it's so timing dependent. This test is
+ // really to make sure we don't interrupt a
+ // valid request.
+ time.Sleep(D * 2)
+ }
+ go func() {
+ defer reqs.Done()
+ res, err := c.Get(st.ts.URL)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ if _, err := ioutil.ReadAll(res.Body); err != nil {
+ t.Error(err)
+ return
+ }
+ res.Body.Close()
+ }()
+ }
+ reqs.Wait()
+ conns.Wait()
+ t.Logf("did %d dials, %d requests", atomic.LoadInt32(&dials), N)
+}
+
+type noteCloseConn struct {
+ net.Conn
+ onceClose sync.Once
+ closefn func()
+}
+
+func (c *noteCloseConn) Close() error {
+ c.onceClose.Do(c.closefn)
+ return c.Conn.Close()
+}
+
+func isTimeout(err error) bool {
+ switch err := err.(type) {
+ case nil:
+ return false
+ case *url.Error:
+ return isTimeout(err.Err)
+ case net.Error:
+ return err.Timeout()
+ }
+ return false
+}
+
+// Test that the http1 Transport.ResponseHeaderTimeout option and cancel is sent.
+func TestTransportResponseHeaderTimeout_NoBody(t *testing.T) {
+ testTransportResponseHeaderTimeout(t, false)
+}
+func TestTransportResponseHeaderTimeout_Body(t *testing.T) {
+ testTransportResponseHeaderTimeout(t, true)
+}
+
+func testTransportResponseHeaderTimeout(t *testing.T, body bool) {
+ ct := newClientTester(t)
+ ct.tr.t1 = &http.Transport{
+ ResponseHeaderTimeout: 5 * time.Millisecond,
+ }
+ ct.client = func() error {
+ c := &http.Client{Transport: ct.tr}
+ var err error
+ var n int64
+ const bodySize = 4 << 20
+ if body {
+ _, err = c.Post("https://dummy.tld/", "text/foo", io.LimitReader(countingReader{&n}, bodySize))
+ } else {
+ _, err = c.Get("https://dummy.tld/")
+ }
+ if !isTimeout(err) {
+ t.Errorf("client expected timeout error; got %#v", err)
+ }
+ if body && n != bodySize {
+ t.Errorf("only read %d bytes of body; want %d", n, bodySize)
+ }
+ return nil
+ }
+ ct.server = func() error {
+ ct.greet()
+ for {
+ f, err := ct.fr.ReadFrame()
+ if err != nil {
+ t.Logf("ReadFrame: %v", err)
+ return nil
+ }
+ switch f := f.(type) {
+ case *DataFrame:
+ dataLen := len(f.Data())
+ if dataLen > 0 {
+ if err := ct.fr.WriteWindowUpdate(0, uint32(dataLen)); err != nil {
+ return err
+ }
+ if err := ct.fr.WriteWindowUpdate(f.StreamID, uint32(dataLen)); err != nil {
+ return err
+ }
+ }
+ case *RSTStreamFrame:
+ if f.StreamID == 1 && f.ErrCode == ErrCodeCancel {
+ return nil
+ }
+ }
+ }
+ }
+ ct.run()
+}
+
+func TestTransportDisableCompression(t *testing.T) {
+ const body = "sup"
+ st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+ want := http.Header{
+ "User-Agent": []string{"Go-http-client/2.0"},
+ }
+ if !reflect.DeepEqual(r.Header, want) {
+ t.Errorf("request headers = %v; want %v", r.Header, want)
+ }
+ }, optOnlyServer)
+ defer st.Close()
+
+ tr := &Transport{
+ TLSClientConfig: tlsConfigInsecure,
+ t1: &http.Transport{
+ DisableCompression: true,
+ },
+ }
+ defer tr.CloseIdleConnections()
+
+ req, err := http.NewRequest("GET", st.ts.URL, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ res, err := tr.RoundTrip(req)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer res.Body.Close()
+}
+
+// RFC 7540 section 8.1.2.2
+func TestTransportRejectsConnHeaders(t *testing.T) {
+ st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+ var got []string
+ for k := range r.Header {
+ got = append(got, k)
+ }
+ sort.Strings(got)
+ w.Header().Set("Got-Header", strings.Join(got, ","))
+ }, optOnlyServer)
+ defer st.Close()
+
+ tr := &Transport{TLSClientConfig: tlsConfigInsecure}
+ defer tr.CloseIdleConnections()
+
+ tests := []struct {
+ key string
+ value []string
+ want string
+ }{
+ {
+ key: "Upgrade",
+ value: []string{"anything"},
+ want: "ERROR: http2: invalid Upgrade request header: [\"anything\"]",
+ },
+ {
+ key: "Connection",
+ value: []string{"foo"},
+ want: "ERROR: http2: invalid Connection request header: [\"foo\"]",
+ },
+ {
+ key: "Connection",
+ value: []string{"close"},
+ want: "Accept-Encoding,User-Agent",
+ },
+ {
+ key: "Connection",
+ value: []string{"close", "something-else"},
+ want: "ERROR: http2: invalid Connection request header: [\"close\" \"something-else\"]",
+ },
+ {
+ key: "Connection",
+ value: []string{"keep-alive"},
+ want: "Accept-Encoding,User-Agent",
+ },
+ {
+ key: "Proxy-Connection", // just deleted and ignored
+ value: []string{"keep-alive"},
+ want: "Accept-Encoding,User-Agent",
+ },
+ {
+ key: "Transfer-Encoding",
+ value: []string{""},
+ want: "Accept-Encoding,User-Agent",
+ },
+ {
+ key: "Transfer-Encoding",
+ value: []string{"foo"},
+ want: "ERROR: http2: invalid Transfer-Encoding request header: [\"foo\"]",
+ },
+ {
+ key: "Transfer-Encoding",
+ value: []string{"chunked"},
+ want: "Accept-Encoding,User-Agent",
+ },
+ {
+ key: "Transfer-Encoding",
+ value: []string{"chunked", "other"},
+ want: "ERROR: http2: invalid Transfer-Encoding request header: [\"chunked\" \"other\"]",
+ },
+ {
+ key: "Content-Length",
+ value: []string{"123"},
+ want: "Accept-Encoding,User-Agent",
+ },
+ {
+ key: "Keep-Alive",
+ value: []string{"doop"},
+ want: "Accept-Encoding,User-Agent",
+ },
+ }
+
+ for _, tt := range tests {
+ req, _ := http.NewRequest("GET", st.ts.URL, nil)
+ req.Header[tt.key] = tt.value
+ res, err := tr.RoundTrip(req)
+ var got string
+ if err != nil {
+ got = fmt.Sprintf("ERROR: %v", err)
+ } else {
+ got = res.Header.Get("Got-Header")
+ res.Body.Close()
+ }
+ if got != tt.want {
+ t.Errorf("For key %q, value %q, got = %q; want %q", tt.key, tt.value, got, tt.want)
+ }
+ }
+}
+
+// golang.org/issue/14048
+func TestTransportFailsOnInvalidHeaders(t *testing.T) {
+ st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+ var got []string
+ for k := range r.Header {
+ got = append(got, k)
+ }
+ sort.Strings(got)
+ w.Header().Set("Got-Header", strings.Join(got, ","))
+ }, optOnlyServer)
+ defer st.Close()
+
+ tests := [...]struct {
+ h http.Header
+ wantErr string
+ }{
+ 0: {
+ h: http.Header{"with space": {"foo"}},
+ wantErr: `invalid HTTP header name "with space"`,
+ },
+ 1: {
+ h: http.Header{"name": {"Брэд"}},
+ wantErr: "", // okay
+ },
+ 2: {
+ h: http.Header{"имя": {"Brad"}},
+ wantErr: `invalid HTTP header name "имя"`,
+ },
+ 3: {
+ h: http.Header{"foo": {"foo\x01bar"}},
+ wantErr: `invalid HTTP header value "foo\x01bar" for header "foo"`,
+ },
+ }
+
+ tr := &Transport{TLSClientConfig: tlsConfigInsecure}
+ defer tr.CloseIdleConnections()
+
+ for i, tt := range tests {
+ req, _ := http.NewRequest("GET", st.ts.URL, nil)
+ req.Header = tt.h
+ res, err := tr.RoundTrip(req)
+ var bad bool
+ if tt.wantErr == "" {
+ if err != nil {
+ bad = true
+ t.Errorf("case %d: error = %v; want no error", i, err)
+ }
+ } else {
+ if !strings.Contains(fmt.Sprint(err), tt.wantErr) {
+ bad = true
+ t.Errorf("case %d: error = %v; want error %q", i, err, tt.wantErr)
+ }
+ }
+ if err == nil {
+ if bad {
+ t.Logf("case %d: server got headers %q", i, res.Header.Get("Got-Header"))
+ }
+ res.Body.Close()
+ }
+ }
+}
+
+// Tests that gzipReader doesn't crash on a second Read call following
+// the first Read call's gzip.NewReader returning an error.
+func TestGzipReader_DoubleReadCrash(t *testing.T) {
+ gz := &gzipReader{
+ body: ioutil.NopCloser(strings.NewReader("0123456789")),
+ }
+ var buf [1]byte
+ n, err1 := gz.Read(buf[:])
+ if n != 0 || !strings.Contains(fmt.Sprint(err1), "invalid header") {
+ t.Fatalf("Read = %v, %v; want 0, invalid header", n, err1)
+ }
+ n, err2 := gz.Read(buf[:])
+ if n != 0 || err2 != err1 {
+ t.Fatalf("second Read = %v, %v; want 0, %v", n, err2, err1)
+ }
+}
+
+func TestTransportNewTLSConfig(t *testing.T) {
+ tests := [...]struct {
+ conf *tls.Config
+ host string
+ want *tls.Config
+ }{
+ // Normal case.
+ 0: {
+ conf: nil,
+ host: "foo.com",
+ want: &tls.Config{
+ ServerName: "foo.com",
+ NextProtos: []string{NextProtoTLS},
+ },
+ },
+
+ // User-provided name (bar.com) takes precedence:
+ 1: {
+ conf: &tls.Config{
+ ServerName: "bar.com",
+ },
+ host: "foo.com",
+ want: &tls.Config{
+ ServerName: "bar.com",
+ NextProtos: []string{NextProtoTLS},
+ },
+ },
+
+ // NextProto is prepended:
+ 2: {
+ conf: &tls.Config{
+ NextProtos: []string{"foo", "bar"},
+ },
+ host: "example.com",
+ want: &tls.Config{
+ ServerName: "example.com",
+ NextProtos: []string{NextProtoTLS, "foo", "bar"},
+ },
+ },
+
+ // NextProto is not duplicated:
+ 3: {
+ conf: &tls.Config{
+ NextProtos: []string{"foo", "bar", NextProtoTLS},
+ },
+ host: "example.com",
+ want: &tls.Config{
+ ServerName: "example.com",
+ NextProtos: []string{"foo", "bar", NextProtoTLS},
+ },
+ },
+ }
+ for i, tt := range tests {
+ // Ignore the session ticket keys part, which ends up populating
+ // unexported fields in the Config:
+ if tt.conf != nil {
+ tt.conf.SessionTicketsDisabled = true
+ }
+
+ tr := &Transport{TLSClientConfig: tt.conf}
+ got := tr.newTLSConfig(tt.host)
+
+ got.SessionTicketsDisabled = false
+
+ if !reflect.DeepEqual(got, tt.want) {
+ t.Errorf("%d. got %#v; want %#v", i, got, tt.want)
+ }
+ }
+}
+
+// The Google GFE responds to HEAD requests with a HEADERS frame
+// without END_STREAM, followed by a 0-length DATA frame with
+// END_STREAM. Make sure we don't get confused by that. (We did.)
+func TestTransportReadHeadResponse(t *testing.T) {
+ ct := newClientTester(t)
+ clientDone := make(chan struct{})
+ ct.client = func() error {
+ defer close(clientDone)
+ req, _ := http.NewRequest("HEAD", "https://dummy.tld/", nil)
+ res, err := ct.tr.RoundTrip(req)
+ if err != nil {
+ return err
+ }
+ if res.ContentLength != 123 {
+ return fmt.Errorf("Content-Length = %d; want 123", res.ContentLength)
+ }
+ slurp, err := ioutil.ReadAll(res.Body)
+ if err != nil {
+ return fmt.Errorf("ReadAll: %v", err)
+ }
+ if len(slurp) > 0 {
+ return fmt.Errorf("Unexpected non-empty ReadAll body: %q", slurp)
+ }
+ return nil
+ }
+ ct.server = func() error {
+ ct.greet()
+ for {
+ f, err := ct.fr.ReadFrame()
+ if err != nil {
+ t.Logf("ReadFrame: %v", err)
+ return nil
+ }
+ hf, ok := f.(*HeadersFrame)
+ if !ok {
+ continue
+ }
+ var buf bytes.Buffer
+ enc := hpack.NewEncoder(&buf)
+ enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"})
+ enc.WriteField(hpack.HeaderField{Name: "content-length", Value: "123"})
+ ct.fr.WriteHeaders(HeadersFrameParam{
+ StreamID: hf.StreamID,
+ EndHeaders: true,
+ EndStream: false, // as the GFE does
+ BlockFragment: buf.Bytes(),
+ })
+ ct.fr.WriteData(hf.StreamID, true, nil)
+
+ <-clientDone
+ return nil
+ }
+ }
+ ct.run()
+}
+
+func TestTransportReadHeadResponseWithBody(t *testing.T) {
+ // This test use not valid response format.
+ // Discarding logger output to not spam tests output.
+ log.SetOutput(ioutil.Discard)
+ defer log.SetOutput(os.Stderr)
+
+ response := "redirecting to /elsewhere"
+ ct := newClientTester(t)
+ clientDone := make(chan struct{})
+ ct.client = func() error {
+ defer close(clientDone)
+ req, _ := http.NewRequest("HEAD", "https://dummy.tld/", nil)
+ res, err := ct.tr.RoundTrip(req)
+ if err != nil {
+ return err
+ }
+ if res.ContentLength != int64(len(response)) {
+ return fmt.Errorf("Content-Length = %d; want %d", res.ContentLength, len(response))
+ }
+ slurp, err := ioutil.ReadAll(res.Body)
+ if err != nil {
+ return fmt.Errorf("ReadAll: %v", err)
+ }
+ if len(slurp) > 0 {
+ return fmt.Errorf("Unexpected non-empty ReadAll body: %q", slurp)
+ }
+ return nil
+ }
+ ct.server = func() error {
+ ct.greet()
+ for {
+ f, err := ct.fr.ReadFrame()
+ if err != nil {
+ t.Logf("ReadFrame: %v", err)
+ return nil
+ }
+ hf, ok := f.(*HeadersFrame)
+ if !ok {
+ continue
+ }
+ var buf bytes.Buffer
+ enc := hpack.NewEncoder(&buf)
+ enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"})
+ enc.WriteField(hpack.HeaderField{Name: "content-length", Value: strconv.Itoa(len(response))})
+ ct.fr.WriteHeaders(HeadersFrameParam{
+ StreamID: hf.StreamID,
+ EndHeaders: true,
+ EndStream: false,
+ BlockFragment: buf.Bytes(),
+ })
+ ct.fr.WriteData(hf.StreamID, true, []byte(response))
+
+ <-clientDone
+ return nil
+ }
+ }
+ ct.run()
+}
+
+type neverEnding byte
+
+func (b neverEnding) Read(p []byte) (int, error) {
+ for i := range p {
+ p[i] = byte(b)
+ }
+ return len(p), nil
+}
+
+// golang.org/issue/15425: test that a handler closing the request
+// body doesn't terminate the stream to the peer. (It just stops
+// readability from the handler's side, and eventually the client
+// runs out of flow control tokens)
+func TestTransportHandlerBodyClose(t *testing.T) {
+ const bodySize = 10 << 20
+ st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+ r.Body.Close()
+ io.Copy(w, io.LimitReader(neverEnding('A'), bodySize))
+ }, optOnlyServer)
+ defer st.Close()
+
+ tr := &Transport{TLSClientConfig: tlsConfigInsecure}
+ defer tr.CloseIdleConnections()
+
+ g0 := runtime.NumGoroutine()
+
+ const numReq = 10
+ for i := 0; i < numReq; i++ {
+ req, err := http.NewRequest("POST", st.ts.URL, struct{ io.Reader }{io.LimitReader(neverEnding('A'), bodySize)})
+ if err != nil {
+ t.Fatal(err)
+ }
+ res, err := tr.RoundTrip(req)
+ if err != nil {
+ t.Fatal(err)
+ }
+ n, err := io.Copy(ioutil.Discard, res.Body)
+ res.Body.Close()
+ if n != bodySize || err != nil {
+ t.Fatalf("req#%d: Copy = %d, %v; want %d, nil", i, n, err, bodySize)
+ }
+ }
+ tr.CloseIdleConnections()
+
+ gd := runtime.NumGoroutine() - g0
+ if gd > numReq/2 {
+ t.Errorf("appeared to leak goroutines")
+ }
+
+}
+
+// https://golang.org/issue/15930
+func TestTransportFlowControl(t *testing.T) {
+ const bufLen = 64 << 10
+ var total int64 = 100 << 20 // 100MB
+ if testing.Short() {
+ total = 10 << 20
+ }
+
+ var wrote int64 // updated atomically
+ st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+ b := make([]byte, bufLen)
+ for wrote < total {
+ n, err := w.Write(b)
+ atomic.AddInt64(&wrote, int64(n))
+ if err != nil {
+ t.Errorf("ResponseWriter.Write error: %v", err)
+ break
+ }
+ w.(http.Flusher).Flush()
+ }
+ }, optOnlyServer)
+
+ tr := &Transport{TLSClientConfig: tlsConfigInsecure}
+ defer tr.CloseIdleConnections()
+ req, err := http.NewRequest("GET", st.ts.URL, nil)
+ if err != nil {
+ t.Fatal("NewRequest error:", err)
+ }
+ resp, err := tr.RoundTrip(req)
+ if err != nil {
+ t.Fatal("RoundTrip error:", err)
+ }
+ defer resp.Body.Close()
+
+ var read int64
+ b := make([]byte, bufLen)
+ for {
+ n, err := resp.Body.Read(b)
+ if err == io.EOF {
+ break
+ }
+ if err != nil {
+ t.Fatal("Read error:", err)
+ }
+ read += int64(n)
+
+ const max = transportDefaultStreamFlow
+ if w := atomic.LoadInt64(&wrote); -max > read-w || read-w > max {
+ t.Fatalf("Too much data inflight: server wrote %v bytes but client only received %v", w, read)
+ }
+
+ // Let the server get ahead of the client.
+ time.Sleep(1 * time.Millisecond)
+ }
+}
+
+// golang.org/issue/14627 -- if the server sends a GOAWAY frame, make
+// the Transport remember it and return it back to users (via
+// RoundTrip or request body reads) if needed (e.g. if the server
+// proceeds to close the TCP connection before the client gets its
+// response)
+func TestTransportUsesGoAwayDebugError_RoundTrip(t *testing.T) {
+ testTransportUsesGoAwayDebugError(t, false)
+}
+
+func TestTransportUsesGoAwayDebugError_Body(t *testing.T) {
+ testTransportUsesGoAwayDebugError(t, true)
+}
+
+func testTransportUsesGoAwayDebugError(t *testing.T, failMidBody bool) {
+ ct := newClientTester(t)
+ clientDone := make(chan struct{})
+
+ const goAwayErrCode = ErrCodeHTTP11Required // arbitrary
+ const goAwayDebugData = "some debug data"
+
+ ct.client = func() error {
+ defer close(clientDone)
+ req, _ := http.NewRequest("GET", "https://dummy.tld/", nil)
+ res, err := ct.tr.RoundTrip(req)
+ if failMidBody {
+ if err != nil {
+ return fmt.Errorf("unexpected client RoundTrip error: %v", err)
+ }
+ _, err = io.Copy(ioutil.Discard, res.Body)
+ res.Body.Close()
+ }
+ want := GoAwayError{
+ LastStreamID: 5,
+ ErrCode: goAwayErrCode,
+ DebugData: goAwayDebugData,
+ }
+ if !reflect.DeepEqual(err, want) {
+ t.Errorf("RoundTrip error = %T: %#v, want %T (%#v)", err, err, want, want)
+ }
+ return nil
+ }
+ ct.server = func() error {
+ ct.greet()
+ for {
+ f, err := ct.fr.ReadFrame()
+ if err != nil {
+ t.Logf("ReadFrame: %v", err)
+ return nil
+ }
+ hf, ok := f.(*HeadersFrame)
+ if !ok {
+ continue
+ }
+ if failMidBody {
+ var buf bytes.Buffer
+ enc := hpack.NewEncoder(&buf)
+ enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"})
+ enc.WriteField(hpack.HeaderField{Name: "content-length", Value: "123"})
+ ct.fr.WriteHeaders(HeadersFrameParam{
+ StreamID: hf.StreamID,
+ EndHeaders: true,
+ EndStream: false,
+ BlockFragment: buf.Bytes(),
+ })
+ }
+ // Write two GOAWAY frames, to test that the Transport takes
+ // the interesting parts of both.
+ ct.fr.WriteGoAway(5, ErrCodeNo, []byte(goAwayDebugData))
+ ct.fr.WriteGoAway(5, goAwayErrCode, nil)
+ ct.sc.(*net.TCPConn).CloseWrite()
+ <-clientDone
+ return nil
+ }
+ }
+ ct.run()
+}
+
+func testTransportReturnsUnusedFlowControl(t *testing.T, oneDataFrame bool) {
+ ct := newClientTester(t)
+
+ clientClosed := make(chan struct{})
+ serverWroteFirstByte := make(chan struct{})
+
+ ct.client = func() error {
+ req, _ := http.NewRequest("GET", "https://dummy.tld/", nil)
+ res, err := ct.tr.RoundTrip(req)
+ if err != nil {
+ return err
+ }
+ <-serverWroteFirstByte
+
+ if n, err := res.Body.Read(make([]byte, 1)); err != nil || n != 1 {
+ return fmt.Errorf("body read = %v, %v; want 1, nil", n, err)
+ }
+ res.Body.Close() // leaving 4999 bytes unread
+ close(clientClosed)
+
+ return nil
+ }
+ ct.server = func() error {
+ ct.greet()
+
+ var hf *HeadersFrame
+ for {
+ f, err := ct.fr.ReadFrame()
+ if err != nil {
+ return fmt.Errorf("ReadFrame while waiting for Headers: %v", err)
+ }
+ switch f.(type) {
+ case *WindowUpdateFrame, *SettingsFrame:
+ continue
+ }
+ var ok bool
+ hf, ok = f.(*HeadersFrame)
+ if !ok {
+ return fmt.Errorf("Got %T; want HeadersFrame", f)
+ }
+ break
+ }
+
+ var buf bytes.Buffer
+ enc := hpack.NewEncoder(&buf)
+ enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"})
+ enc.WriteField(hpack.HeaderField{Name: "content-length", Value: "5000"})
+ ct.fr.WriteHeaders(HeadersFrameParam{
+ StreamID: hf.StreamID,
+ EndHeaders: true,
+ EndStream: false,
+ BlockFragment: buf.Bytes(),
+ })
+
+ // Two cases:
+ // - Send one DATA frame with 5000 bytes.
+ // - Send two DATA frames with 1 and 4999 bytes each.
+ //
+ // In both cases, the client should consume one byte of data,
+ // refund that byte, then refund the following 4999 bytes.
+ //
+ // In the second case, the server waits for the client connection to
+ // close before seconding the second DATA frame. This tests the case
+ // where the client receives a DATA frame after it has reset the stream.
+ if oneDataFrame {
+ ct.fr.WriteData(hf.StreamID, false /* don't end stream */, make([]byte, 5000))
+ close(serverWroteFirstByte)
+ <-clientClosed
+ } else {
+ ct.fr.WriteData(hf.StreamID, false /* don't end stream */, make([]byte, 1))
+ close(serverWroteFirstByte)
+ <-clientClosed
+ ct.fr.WriteData(hf.StreamID, false /* don't end stream */, make([]byte, 4999))
+ }
+
+ waitingFor := "RSTStreamFrame"
+ for {
+ f, err := ct.fr.ReadFrame()
+ if err != nil {
+ return fmt.Errorf("ReadFrame while waiting for %s: %v", waitingFor, err)
+ }
+ if _, ok := f.(*SettingsFrame); ok {
+ continue
+ }
+ switch waitingFor {
+ case "RSTStreamFrame":
+ if rf, ok := f.(*RSTStreamFrame); !ok || rf.ErrCode != ErrCodeCancel {
+ return fmt.Errorf("Expected a RSTStreamFrame with code cancel; got %v", summarizeFrame(f))
+ }
+ waitingFor = "WindowUpdateFrame"
+ case "WindowUpdateFrame":
+ if wuf, ok := f.(*WindowUpdateFrame); !ok || wuf.Increment != 4999 {
+ return fmt.Errorf("Expected WindowUpdateFrame for 4999 bytes; got %v", summarizeFrame(f))
+ }
+ return nil
+ }
+ }
+ }
+ ct.run()
+}
+
+// See golang.org/issue/16481
+func TestTransportReturnsUnusedFlowControlSingleWrite(t *testing.T) {
+ testTransportReturnsUnusedFlowControl(t, true)
+}
+
+// See golang.org/issue/20469
+func TestTransportReturnsUnusedFlowControlMultipleWrites(t *testing.T) {
+ testTransportReturnsUnusedFlowControl(t, false)
+}
+
+// Issue 16612: adjust flow control on open streams when transport
+// receives SETTINGS with INITIAL_WINDOW_SIZE from server.
+func TestTransportAdjustsFlowControl(t *testing.T) {
+ ct := newClientTester(t)
+ clientDone := make(chan struct{})
+
+ const bodySize = 1 << 20
+
+ ct.client = func() error {
+ defer ct.cc.(*net.TCPConn).CloseWrite()
+ defer close(clientDone)
+
+ req, _ := http.NewRequest("POST", "https://dummy.tld/", struct{ io.Reader }{io.LimitReader(neverEnding('A'), bodySize)})
+ res, err := ct.tr.RoundTrip(req)
+ if err != nil {
+ return err
+ }
+ res.Body.Close()
+ return nil
+ }
+ ct.server = func() error {
+ _, err := io.ReadFull(ct.sc, make([]byte, len(ClientPreface)))
+ if err != nil {
+ return fmt.Errorf("reading client preface: %v", err)
+ }
+
+ var gotBytes int64
+ var sentSettings bool
+ for {
+ f, err := ct.fr.ReadFrame()
+ if err != nil {
+ select {
+ case <-clientDone:
+ return nil
+ default:
+ return fmt.Errorf("ReadFrame while waiting for Headers: %v", err)
+ }
+ }
+ switch f := f.(type) {
+ case *DataFrame:
+ gotBytes += int64(len(f.Data()))
+ // After we've got half the client's
+ // initial flow control window's worth
+ // of request body data, give it just
+ // enough flow control to finish.
+ if gotBytes >= initialWindowSize/2 && !sentSettings {
+ sentSettings = true
+
+ ct.fr.WriteSettings(Setting{ID: SettingInitialWindowSize, Val: bodySize})
+ ct.fr.WriteWindowUpdate(0, bodySize)
+ ct.fr.WriteSettingsAck()
+ }
+
+ if f.StreamEnded() {
+ var buf bytes.Buffer
+ enc := hpack.NewEncoder(&buf)
+ enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"})
+ ct.fr.WriteHeaders(HeadersFrameParam{
+ StreamID: f.StreamID,
+ EndHeaders: true,
+ EndStream: true,
+ BlockFragment: buf.Bytes(),
+ })
+ }
+ }
+ }
+ }
+ ct.run()
+}
+
+// See golang.org/issue/16556
+func TestTransportReturnsDataPaddingFlowControl(t *testing.T) {
+ ct := newClientTester(t)
+
+ unblockClient := make(chan bool, 1)
+
+ ct.client = func() error {
+ req, _ := http.NewRequest("GET", "https://dummy.tld/", nil)
+ res, err := ct.tr.RoundTrip(req)
+ if err != nil {
+ return err
+ }
+ defer res.Body.Close()
+ <-unblockClient
+ return nil
+ }
+ ct.server = func() error {
+ ct.greet()
+
+ var hf *HeadersFrame
+ for {
+ f, err := ct.fr.ReadFrame()
+ if err != nil {
+ return fmt.Errorf("ReadFrame while waiting for Headers: %v", err)
+ }
+ switch f.(type) {
+ case *WindowUpdateFrame, *SettingsFrame:
+ continue
+ }
+ var ok bool
+ hf, ok = f.(*HeadersFrame)
+ if !ok {
+ return fmt.Errorf("Got %T; want HeadersFrame", f)
+ }
+ break
+ }
+
+ var buf bytes.Buffer
+ enc := hpack.NewEncoder(&buf)
+ enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"})
+ enc.WriteField(hpack.HeaderField{Name: "content-length", Value: "5000"})
+ ct.fr.WriteHeaders(HeadersFrameParam{
+ StreamID: hf.StreamID,
+ EndHeaders: true,
+ EndStream: false,
+ BlockFragment: buf.Bytes(),
+ })
+ pad := make([]byte, 5)
+ ct.fr.WriteDataPadded(hf.StreamID, false, make([]byte, 5000), pad) // without ending stream
+
+ f, err := ct.readNonSettingsFrame()
+ if err != nil {
+ return fmt.Errorf("ReadFrame while waiting for first WindowUpdateFrame: %v", err)
+ }
+ wantBack := uint32(len(pad)) + 1 // one byte for the length of the padding
+ if wuf, ok := f.(*WindowUpdateFrame); !ok || wuf.Increment != wantBack || wuf.StreamID != 0 {
+ return fmt.Errorf("Expected conn WindowUpdateFrame for %d bytes; got %v", wantBack, summarizeFrame(f))
+ }
+
+ f, err = ct.readNonSettingsFrame()
+ if err != nil {
+ return fmt.Errorf("ReadFrame while waiting for second WindowUpdateFrame: %v", err)
+ }
+ if wuf, ok := f.(*WindowUpdateFrame); !ok || wuf.Increment != wantBack || wuf.StreamID == 0 {
+ return fmt.Errorf("Expected stream WindowUpdateFrame for %d bytes; got %v", wantBack, summarizeFrame(f))
+ }
+ unblockClient <- true
+ return nil
+ }
+ ct.run()
+}
+
+// golang.org/issue/16572 -- RoundTrip shouldn't hang when it gets a
+// StreamError as a result of the response HEADERS
+func TestTransportReturnsErrorOnBadResponseHeaders(t *testing.T) {
+ ct := newClientTester(t)
+
+ ct.client = func() error {
+ req, _ := http.NewRequest("GET", "https://dummy.tld/", nil)
+ res, err := ct.tr.RoundTrip(req)
+ if err == nil {
+ res.Body.Close()
+ return errors.New("unexpected successful GET")
+ }
+ want := StreamError{1, ErrCodeProtocol, headerFieldNameError(" content-type")}
+ if !reflect.DeepEqual(want, err) {
+ t.Errorf("RoundTrip error = %#v; want %#v", err, want)
+ }
+ return nil
+ }
+ ct.server = func() error {
+ ct.greet()
+
+ hf, err := ct.firstHeaders()
+ if err != nil {
+ return err
+ }
+
+ var buf bytes.Buffer
+ enc := hpack.NewEncoder(&buf)
+ enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"})
+ enc.WriteField(hpack.HeaderField{Name: " content-type", Value: "bogus"}) // bogus spaces
+ ct.fr.WriteHeaders(HeadersFrameParam{
+ StreamID: hf.StreamID,
+ EndHeaders: true,
+ EndStream: false,
+ BlockFragment: buf.Bytes(),
+ })
+
+ for {
+ fr, err := ct.readFrame()
+ if err != nil {
+ return fmt.Errorf("error waiting for RST_STREAM from client: %v", err)
+ }
+ if _, ok := fr.(*SettingsFrame); ok {
+ continue
+ }
+ if rst, ok := fr.(*RSTStreamFrame); !ok || rst.StreamID != 1 || rst.ErrCode != ErrCodeProtocol {
+ t.Errorf("Frame = %v; want RST_STREAM for stream 1 with ErrCodeProtocol", summarizeFrame(fr))
+ }
+ break
+ }
+
+ return nil
+ }
+ ct.run()
+}
+
+// byteAndEOFReader returns is in an io.Reader which reads one byte
+// (the underlying byte) and io.EOF at once in its Read call.
+type byteAndEOFReader byte
+
+func (b byteAndEOFReader) Read(p []byte) (n int, err error) {
+ if len(p) == 0 {
+ panic("unexpected useless call")
+ }
+ p[0] = byte(b)
+ return 1, io.EOF
+}
+
+// Issue 16788: the Transport had a regression where it started
+// sending a spurious DATA frame with a duplicate END_STREAM bit after
+// the request body writer goroutine had already read an EOF from the
+// Request.Body and included the END_STREAM on a data-carrying DATA
+// frame.
+//
+// Notably, to trigger this, the requests need to use a Request.Body
+// which returns (non-0, io.EOF) and also needs to set the ContentLength
+// explicitly.
+func TestTransportBodyDoubleEndStream(t *testing.T) {
+ st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+ // Nothing.
+ }, optOnlyServer)
+ defer st.Close()
+
+ tr := &Transport{TLSClientConfig: tlsConfigInsecure}
+ defer tr.CloseIdleConnections()
+
+ for i := 0; i < 2; i++ {
+ req, _ := http.NewRequest("POST", st.ts.URL, byteAndEOFReader('a'))
+ req.ContentLength = 1
+ res, err := tr.RoundTrip(req)
+ if err != nil {
+ t.Fatalf("failure on req %d: %v", i+1, err)
+ }
+ defer res.Body.Close()
+ }
+}
+
+// golang.org/issue/16847, golang.org/issue/19103
+func TestTransportRequestPathPseudo(t *testing.T) {
+ type result struct {
+ path string
+ err string
+ }
+ tests := []struct {
+ req *http.Request
+ want result
+ }{
+ 0: {
+ req: &http.Request{
+ Method: "GET",
+ URL: &url.URL{
+ Host: "foo.com",
+ Path: "/foo",
+ },
+ },
+ want: result{path: "/foo"},
+ },
+ // In Go 1.7, we accepted paths of "//foo".
+ // In Go 1.8, we rejected it (issue 16847).
+ // In Go 1.9, we accepted it again (issue 19103).
+ 1: {
+ req: &http.Request{
+ Method: "GET",
+ URL: &url.URL{
+ Host: "foo.com",
+ Path: "//foo",
+ },
+ },
+ want: result{path: "//foo"},
+ },
+
+ // Opaque with //$Matching_Hostname/path
+ 2: {
+ req: &http.Request{
+ Method: "GET",
+ URL: &url.URL{
+ Scheme: "https",
+ Opaque: "//foo.com/path",
+ Host: "foo.com",
+ Path: "/ignored",
+ },
+ },
+ want: result{path: "/path"},
+ },
+
+ // Opaque with some other Request.Host instead:
+ 3: {
+ req: &http.Request{
+ Method: "GET",
+ Host: "bar.com",
+ URL: &url.URL{
+ Scheme: "https",
+ Opaque: "//bar.com/path",
+ Host: "foo.com",
+ Path: "/ignored",
+ },
+ },
+ want: result{path: "/path"},
+ },
+
+ // Opaque without the leading "//":
+ 4: {
+ req: &http.Request{
+ Method: "GET",
+ URL: &url.URL{
+ Opaque: "/path",
+ Host: "foo.com",
+ Path: "/ignored",
+ },
+ },
+ want: result{path: "/path"},
+ },
+
+ // Opaque we can't handle:
+ 5: {
+ req: &http.Request{
+ Method: "GET",
+ URL: &url.URL{
+ Scheme: "https",
+ Opaque: "//unknown_host/path",
+ Host: "foo.com",
+ Path: "/ignored",
+ },
+ },
+ want: result{err: `invalid request :path "https://unknown_host/path" from URL.Opaque = "//unknown_host/path"`},
+ },
+
+ // A CONNECT request:
+ 6: {
+ req: &http.Request{
+ Method: "CONNECT",
+ URL: &url.URL{
+ Host: "foo.com",
+ },
+ },
+ want: result{},
+ },
+ }
+ for i, tt := range tests {
+ cc := &ClientConn{peerMaxHeaderListSize: 0xffffffffffffffff}
+ cc.henc = hpack.NewEncoder(&cc.hbuf)
+ cc.mu.Lock()
+ hdrs, err := cc.encodeHeaders(tt.req, false, "", -1)
+ cc.mu.Unlock()
+ var got result
+ hpackDec := hpack.NewDecoder(initialHeaderTableSize, func(f hpack.HeaderField) {
+ if f.Name == ":path" {
+ got.path = f.Value
+ }
+ })
+ if err != nil {
+ got.err = err.Error()
+ } else if len(hdrs) > 0 {
+ if _, err := hpackDec.Write(hdrs); err != nil {
+ t.Errorf("%d. bogus hpack: %v", i, err)
+ continue
+ }
+ }
+ if got != tt.want {
+ t.Errorf("%d. got %+v; want %+v", i, got, tt.want)
+ }
+
+ }
+
+}
+
+// golang.org/issue/17071 -- don't sniff the first byte of the request body
+// before we've determined that the ClientConn is usable.
+func TestRoundTripDoesntConsumeRequestBodyEarly(t *testing.T) {
+ const body = "foo"
+ req, _ := http.NewRequest("POST", "http://foo.com/", ioutil.NopCloser(strings.NewReader(body)))
+ cc := &ClientConn{
+ closed: true,
+ }
+ _, err := cc.RoundTrip(req)
+ if err != errClientConnUnusable {
+ t.Fatalf("RoundTrip = %v; want errClientConnUnusable", err)
+ }
+ slurp, err := ioutil.ReadAll(req.Body)
+ if err != nil {
+ t.Errorf("ReadAll = %v", err)
+ }
+ if string(slurp) != body {
+ t.Errorf("Body = %q; want %q", slurp, body)
+ }
+}
+
+func TestClientConnPing(t *testing.T) {
+ st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {}, optOnlyServer)
+ defer st.Close()
+ tr := &Transport{TLSClientConfig: tlsConfigInsecure}
+ defer tr.CloseIdleConnections()
+ cc, err := tr.dialClientConn(st.ts.Listener.Addr().String(), false)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err = cc.Ping(testContext{}); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Issue 16974: if the server sent a DATA frame after the user
+// canceled the Transport's Request, the Transport previously wrote to a
+// closed pipe, got an error, and ended up closing the whole TCP
+// connection.
+func TestTransportCancelDataResponseRace(t *testing.T) {
+ cancel := make(chan struct{})
+ clientGotError := make(chan bool, 1)
+
+ const msg = "Hello."
+ st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+ if strings.Contains(r.URL.Path, "/hello") {
+ time.Sleep(50 * time.Millisecond)
+ io.WriteString(w, msg)
+ return
+ }
+ for i := 0; i < 50; i++ {
+ io.WriteString(w, "Some data.")
+ w.(http.Flusher).Flush()
+ if i == 2 {
+ close(cancel)
+ <-clientGotError
+ }
+ time.Sleep(10 * time.Millisecond)
+ }
+ }, optOnlyServer)
+ defer st.Close()
+
+ tr := &Transport{TLSClientConfig: tlsConfigInsecure}
+ defer tr.CloseIdleConnections()
+
+ c := &http.Client{Transport: tr}
+ req, _ := http.NewRequest("GET", st.ts.URL, nil)
+ req.Cancel = cancel
+ res, err := c.Do(req)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if _, err = io.Copy(ioutil.Discard, res.Body); err == nil {
+ t.Fatal("unexpected success")
+ }
+ clientGotError <- true
+
+ res, err = c.Get(st.ts.URL + "/hello")
+ if err != nil {
+ t.Fatal(err)
+ }
+ slurp, err := ioutil.ReadAll(res.Body)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if string(slurp) != msg {
+ t.Errorf("Got = %q; want %q", slurp, msg)
+ }
+}
+
+// Issue 21316: It should be safe to reuse an http.Request after the
+// request has completed.
+func TestTransportNoRaceOnRequestObjectAfterRequestComplete(t *testing.T) {
+ st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+ w.WriteHeader(200)
+ io.WriteString(w, "body")
+ }, optOnlyServer)
+ defer st.Close()
+
+ tr := &Transport{TLSClientConfig: tlsConfigInsecure}
+ defer tr.CloseIdleConnections()
+
+ req, _ := http.NewRequest("GET", st.ts.URL, nil)
+ resp, err := tr.RoundTrip(req)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if _, err = io.Copy(ioutil.Discard, resp.Body); err != nil {
+ t.Fatalf("error reading response body: %v", err)
+ }
+ if err := resp.Body.Close(); err != nil {
+ t.Fatalf("error closing response body: %v", err)
+ }
+
+ // This access of req.Header should not race with code in the transport.
+ req.Header = http.Header{}
+}
+
+func TestTransportRetryAfterGOAWAY(t *testing.T) {
+ var dialer struct {
+ sync.Mutex
+ count int
+ }
+ ct1 := make(chan *clientTester)
+ ct2 := make(chan *clientTester)
+
+ ln := newLocalListener(t)
+ defer ln.Close()
+
+ tr := &Transport{
+ TLSClientConfig: tlsConfigInsecure,
+ }
+ tr.DialTLS = func(network, addr string, cfg *tls.Config) (net.Conn, error) {
+ dialer.Lock()
+ defer dialer.Unlock()
+ dialer.count++
+ if dialer.count == 3 {
+ return nil, errors.New("unexpected number of dials")
+ }
+ cc, err := net.Dial("tcp", ln.Addr().String())
+ if err != nil {
+ return nil, fmt.Errorf("dial error: %v", err)
+ }
+ sc, err := ln.Accept()
+ if err != nil {
+ return nil, fmt.Errorf("accept error: %v", err)
+ }
+ ct := &clientTester{
+ t: t,
+ tr: tr,
+ cc: cc,
+ sc: sc,
+ fr: NewFramer(sc, sc),
+ }
+ switch dialer.count {
+ case 1:
+ ct1 <- ct
+ case 2:
+ ct2 <- ct
+ }
+ return cc, nil
+ }
+
+ errs := make(chan error, 3)
+ done := make(chan struct{})
+ defer close(done)
+
+ // Client.
+ go func() {
+ req, _ := http.NewRequest("GET", "https://dummy.tld/", nil)
+ res, err := tr.RoundTrip(req)
+ if res != nil {
+ res.Body.Close()
+ if got := res.Header.Get("Foo"); got != "bar" {
+ err = fmt.Errorf("foo header = %q; want bar", got)
+ }
+ }
+ if err != nil {
+ err = fmt.Errorf("RoundTrip: %v", err)
+ }
+ errs <- err
+ }()
+
+ connToClose := make(chan io.Closer, 2)
+
+ // Server for the first request.
+ go func() {
+ var ct *clientTester
+ select {
+ case ct = <-ct1:
+ case <-done:
+ return
+ }
+
+ connToClose <- ct.cc
+ ct.greet()
+ hf, err := ct.firstHeaders()
+ if err != nil {
+ errs <- fmt.Errorf("server1 failed reading HEADERS: %v", err)
+ return
+ }
+ t.Logf("server1 got %v", hf)
+ if err := ct.fr.WriteGoAway(0 /*max id*/, ErrCodeNo, nil); err != nil {
+ errs <- fmt.Errorf("server1 failed writing GOAWAY: %v", err)
+ return
+ }
+ errs <- nil
+ }()
+
+ // Server for the second request.
+ go func() {
+ var ct *clientTester
+ select {
+ case ct = <-ct2:
+ case <-done:
+ return
+ }
+
+ connToClose <- ct.cc
+ ct.greet()
+ hf, err := ct.firstHeaders()
+ if err != nil {
+ errs <- fmt.Errorf("server2 failed reading HEADERS: %v", err)
+ return
+ }
+ t.Logf("server2 got %v", hf)
+
+ var buf bytes.Buffer
+ enc := hpack.NewEncoder(&buf)
+ enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"})
+ enc.WriteField(hpack.HeaderField{Name: "foo", Value: "bar"})
+ err = ct.fr.WriteHeaders(HeadersFrameParam{
+ StreamID: hf.StreamID,
+ EndHeaders: true,
+ EndStream: false,
+ BlockFragment: buf.Bytes(),
+ })
+ if err != nil {
+ errs <- fmt.Errorf("server2 failed writing response HEADERS: %v", err)
+ } else {
+ errs <- nil
+ }
+ }()
+
+ for k := 0; k < 3; k++ {
+ select {
+ case err := <-errs:
+ if err != nil {
+ t.Error(err)
+ }
+ case <-time.After(1 * time.Second):
+ t.Errorf("timed out")
+ }
+ }
+
+ for {
+ select {
+ case c := <-connToClose:
+ c.Close()
+ default:
+ return
+ }
+ }
+}
+
+func TestTransportRetryAfterRefusedStream(t *testing.T) {
+ clientDone := make(chan struct{})
+ ct := newClientTester(t)
+ ct.client = func() error {
+ defer ct.cc.(*net.TCPConn).CloseWrite()
+ defer close(clientDone)
+ req, _ := http.NewRequest("GET", "https://dummy.tld/", nil)
+ resp, err := ct.tr.RoundTrip(req)
+ if err != nil {
+ return fmt.Errorf("RoundTrip: %v", err)
+ }
+ resp.Body.Close()
+ if resp.StatusCode != 204 {
+ return fmt.Errorf("Status = %v; want 204", resp.StatusCode)
+ }
+ return nil
+ }
+ ct.server = func() error {
+ ct.greet()
+ var buf bytes.Buffer
+ enc := hpack.NewEncoder(&buf)
+ nreq := 0
+
+ for {
+ f, err := ct.fr.ReadFrame()
+ if err != nil {
+ select {
+ case <-clientDone:
+ // If the client's done, it
+ // will have reported any
+ // errors on its side.
+ return nil
+ default:
+ return err
+ }
+ }
+ switch f := f.(type) {
+ case *WindowUpdateFrame, *SettingsFrame:
+ case *HeadersFrame:
+ if !f.HeadersEnded() {
+ return fmt.Errorf("headers should have END_HEADERS be ended: %v", f)
+ }
+ nreq++
+ if nreq == 1 {
+ ct.fr.WriteRSTStream(f.StreamID, ErrCodeRefusedStream)
+ } else {
+ enc.WriteField(hpack.HeaderField{Name: ":status", Value: "204"})
+ ct.fr.WriteHeaders(HeadersFrameParam{
+ StreamID: f.StreamID,
+ EndHeaders: true,
+ EndStream: true,
+ BlockFragment: buf.Bytes(),
+ })
+ }
+ default:
+ return fmt.Errorf("Unexpected client frame %v", f)
+ }
+ }
+ }
+ ct.run()
+}
+
+func TestTransportRetryHasLimit(t *testing.T) {
+ // Skip in short mode because the total expected delay is 1s+2s+4s+8s+16s=29s.
+ if testing.Short() {
+ t.Skip("skipping long test in short mode")
+ }
+ clientDone := make(chan struct{})
+ ct := newClientTester(t)
+ ct.client = func() error {
+ defer ct.cc.(*net.TCPConn).CloseWrite()
+ defer close(clientDone)
+ req, _ := http.NewRequest("GET", "https://dummy.tld/", nil)
+ resp, err := ct.tr.RoundTrip(req)
+ if err == nil {
+ return fmt.Errorf("RoundTrip expected error, got response: %+v", resp)
+ }
+ t.Logf("expected error, got: %v", err)
+ return nil
+ }
+ ct.server = func() error {
+ ct.greet()
+ for {
+ f, err := ct.fr.ReadFrame()
+ if err != nil {
+ select {
+ case <-clientDone:
+ // If the client's done, it
+ // will have reported any
+ // errors on its side.
+ return nil
+ default:
+ return err
+ }
+ }
+ switch f := f.(type) {
+ case *WindowUpdateFrame, *SettingsFrame:
+ case *HeadersFrame:
+ if !f.HeadersEnded() {
+ return fmt.Errorf("headers should have END_HEADERS be ended: %v", f)
+ }
+ ct.fr.WriteRSTStream(f.StreamID, ErrCodeRefusedStream)
+ default:
+ return fmt.Errorf("Unexpected client frame %v", f)
+ }
+ }
+ }
+ ct.run()
+}
+
+func TestTransportResponseDataBeforeHeaders(t *testing.T) {
+ // This test use not valid response format.
+ // Discarding logger output to not spam tests output.
+ log.SetOutput(ioutil.Discard)
+ defer log.SetOutput(os.Stderr)
+
+ ct := newClientTester(t)
+ ct.client = func() error {
+ defer ct.cc.(*net.TCPConn).CloseWrite()
+ req := httptest.NewRequest("GET", "https://dummy.tld/", nil)
+ // First request is normal to ensure the check is per stream and not per connection.
+ _, err := ct.tr.RoundTrip(req)
+ if err != nil {
+ return fmt.Errorf("RoundTrip expected no error, got: %v", err)
+ }
+ // Second request returns a DATA frame with no HEADERS.
+ resp, err := ct.tr.RoundTrip(req)
+ if err == nil {
+ return fmt.Errorf("RoundTrip expected error, got response: %+v", resp)
+ }
+ if err, ok := err.(StreamError); !ok || err.Code != ErrCodeProtocol {
+ return fmt.Errorf("expected stream PROTOCOL_ERROR, got: %v", err)
+ }
+ return nil
+ }
+ ct.server = func() error {
+ ct.greet()
+ for {
+ f, err := ct.fr.ReadFrame()
+ if err == io.EOF {
+ return nil
+ } else if err != nil {
+ return err
+ }
+ switch f := f.(type) {
+ case *WindowUpdateFrame, *SettingsFrame:
+ case *HeadersFrame:
+ switch f.StreamID {
+ case 1:
+ // Send a valid response to first request.
+ var buf bytes.Buffer
+ enc := hpack.NewEncoder(&buf)
+ enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"})
+ ct.fr.WriteHeaders(HeadersFrameParam{
+ StreamID: f.StreamID,
+ EndHeaders: true,
+ EndStream: true,
+ BlockFragment: buf.Bytes(),
+ })
+ case 3:
+ ct.fr.WriteData(f.StreamID, true, []byte("payload"))
+ }
+ default:
+ return fmt.Errorf("Unexpected client frame %v", f)
+ }
+ }
+ }
+ ct.run()
+}
+func TestTransportRequestsStallAtServerLimit(t *testing.T) {
+ const maxConcurrent = 2
+
+ greet := make(chan struct{}) // server sends initial SETTINGS frame
+ gotRequest := make(chan struct{}) // server received a request
+ clientDone := make(chan struct{})
+
+ // Collect errors from goroutines.
+ var wg sync.WaitGroup
+ errs := make(chan error, 100)
+ defer func() {
+ wg.Wait()
+ close(errs)
+ for err := range errs {
+ t.Error(err)
+ }
+ }()
+
+ // We will send maxConcurrent+2 requests. This checker goroutine waits for the
+ // following stages:
+ // 1. The first maxConcurrent requests are received by the server.
+ // 2. The client will cancel the next request
+ // 3. The server is unblocked so it can service the first maxConcurrent requests
+ // 4. The client will send the final request
+ wg.Add(1)
+ unblockClient := make(chan struct{})
+ clientRequestCancelled := make(chan struct{})
+ unblockServer := make(chan struct{})
+ go func() {
+ defer wg.Done()
+ // Stage 1.
+ for k := 0; k < maxConcurrent; k++ {
+ <-gotRequest
+ }
+ // Stage 2.
+ close(unblockClient)
+ <-clientRequestCancelled
+ // Stage 3: give some time for the final RoundTrip call to be scheduled and
+ // verify that the final request is not sent.
+ time.Sleep(50 * time.Millisecond)
+ select {
+ case <-gotRequest:
+ errs <- errors.New("last request did not stall")
+ close(unblockServer)
+ return
+ default:
+ }
+ close(unblockServer)
+ // Stage 4.
+ <-gotRequest
+ }()
+
+ ct := newClientTester(t)
+ ct.client = func() error {
+ var wg sync.WaitGroup
+ defer func() {
+ wg.Wait()
+ close(clientDone)
+ ct.cc.(*net.TCPConn).CloseWrite()
+ }()
+ for k := 0; k < maxConcurrent+2; k++ {
+ wg.Add(1)
+ go func(k int) {
+ defer wg.Done()
+ // Don't send the second request until after receiving SETTINGS from the server
+ // to avoid a race where we use the default SettingMaxConcurrentStreams, which
+ // is much larger than maxConcurrent. We have to send the first request before
+ // waiting because the first request triggers the dial and greet.
+ if k > 0 {
+ <-greet
+ }
+ // Block until maxConcurrent requests are sent before sending any more.
+ if k >= maxConcurrent {
+ <-unblockClient
+ }
+ req, _ := http.NewRequest("GET", fmt.Sprintf("https://dummy.tld/%d", k), nil)
+ if k == maxConcurrent {
+ // This request will be canceled.
+ cancel := make(chan struct{})
+ req.Cancel = cancel
+ close(cancel)
+ _, err := ct.tr.RoundTrip(req)
+ close(clientRequestCancelled)
+ if err == nil {
+ errs <- fmt.Errorf("RoundTrip(%d) should have failed due to cancel", k)
+ return
+ }
+ } else {
+ resp, err := ct.tr.RoundTrip(req)
+ if err != nil {
+ errs <- fmt.Errorf("RoundTrip(%d): %v", k, err)
+ return
+ }
+ ioutil.ReadAll(resp.Body)
+ resp.Body.Close()
+ if resp.StatusCode != 204 {
+ errs <- fmt.Errorf("Status = %v; want 204", resp.StatusCode)
+ return
+ }
+ }
+ }(k)
+ }
+ return nil
+ }
+
+ ct.server = func() error {
+ var wg sync.WaitGroup
+ defer wg.Wait()
+
+ ct.greet(Setting{SettingMaxConcurrentStreams, maxConcurrent})
+
+ // Server write loop.
+ var buf bytes.Buffer
+ enc := hpack.NewEncoder(&buf)
+ writeResp := make(chan uint32, maxConcurrent+1)
+
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ <-unblockServer
+ for id := range writeResp {
+ buf.Reset()
+ enc.WriteField(hpack.HeaderField{Name: ":status", Value: "204"})
+ ct.fr.WriteHeaders(HeadersFrameParam{
+ StreamID: id,
+ EndHeaders: true,
+ EndStream: true,
+ BlockFragment: buf.Bytes(),
+ })
+ }
+ }()
+
+ // Server read loop.
+ var nreq int
+ for {
+ f, err := ct.fr.ReadFrame()
+ if err != nil {
+ select {
+ case <-clientDone:
+ // If the client's done, it will have reported any errors on its side.
+ return nil
+ default:
+ return err
+ }
+ }
+ switch f := f.(type) {
+ case *WindowUpdateFrame:
+ case *SettingsFrame:
+ // Wait for the client SETTINGS ack until ending the greet.
+ close(greet)
+ case *HeadersFrame:
+ if !f.HeadersEnded() {
+ return fmt.Errorf("headers should have END_HEADERS be ended: %v", f)
+ }
+ gotRequest <- struct{}{}
+ nreq++
+ writeResp <- f.StreamID
+ if nreq == maxConcurrent+1 {
+ close(writeResp)
+ }
+ default:
+ return fmt.Errorf("Unexpected client frame %v", f)
+ }
+ }
+ }
+
+ ct.run()
+}
+
+func TestAuthorityAddr(t *testing.T) {
+ tests := []struct {
+ scheme, authority string
+ want string
+ }{
+ {"http", "foo.com", "foo.com:80"},
+ {"https", "foo.com", "foo.com:443"},
+ {"https", "foo.com:1234", "foo.com:1234"},
+ {"https", "1.2.3.4:1234", "1.2.3.4:1234"},
+ {"https", "1.2.3.4", "1.2.3.4:443"},
+ {"https", "[::1]:1234", "[::1]:1234"},
+ {"https", "[::1]", "[::1]:443"},
+ }
+ for _, tt := range tests {
+ got := authorityAddr(tt.scheme, tt.authority)
+ if got != tt.want {
+ t.Errorf("authorityAddr(%q, %q) = %q; want %q", tt.scheme, tt.authority, got, tt.want)
+ }
+ }
+}
+
+// Issue 20448: stop allocating for DATA frames' payload after
+// Response.Body.Close is called.
+func TestTransportAllocationsAfterResponseBodyClose(t *testing.T) {
+ megabyteZero := make([]byte, 1<<20)
+
+ writeErr := make(chan error, 1)
+
+ st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+ w.(http.Flusher).Flush()
+ var sum int64
+ for i := 0; i < 100; i++ {
+ n, err := w.Write(megabyteZero)
+ sum += int64(n)
+ if err != nil {
+ writeErr <- err
+ return
+ }
+ }
+ t.Logf("wrote all %d bytes", sum)
+ writeErr <- nil
+ }, optOnlyServer)
+ defer st.Close()
+
+ tr := &Transport{TLSClientConfig: tlsConfigInsecure}
+ defer tr.CloseIdleConnections()
+ c := &http.Client{Transport: tr}
+ res, err := c.Get(st.ts.URL)
+ if err != nil {
+ t.Fatal(err)
+ }
+ var buf [1]byte
+ if _, err := res.Body.Read(buf[:]); err != nil {
+ t.Error(err)
+ }
+ if err := res.Body.Close(); err != nil {
+ t.Error(err)
+ }
+
+ trb, ok := res.Body.(transportResponseBody)
+ if !ok {
+ t.Fatalf("res.Body = %T; want transportResponseBody", res.Body)
+ }
+ if trb.cs.bufPipe.b != nil {
+ t.Errorf("response body pipe is still open")
+ }
+
+ gotErr := <-writeErr
+ if gotErr == nil {
+ t.Errorf("Handler unexpectedly managed to write its entire response without getting an error")
+ } else if gotErr != errStreamClosed {
+ t.Errorf("Handler Write err = %v; want errStreamClosed", gotErr)
+ }
+}
+
+// Issue 18891: make sure Request.Body == NoBody means no DATA frame
+// is ever sent, even if empty.
+func TestTransportNoBodyMeansNoDATA(t *testing.T) {
+ ct := newClientTester(t)
+
+ unblockClient := make(chan bool)
+
+ ct.client = func() error {
+ req, _ := http.NewRequest("GET", "https://dummy.tld/", go18httpNoBody())
+ ct.tr.RoundTrip(req)
+ <-unblockClient
+ return nil
+ }
+ ct.server = func() error {
+ defer close(unblockClient)
+ defer ct.cc.(*net.TCPConn).Close()
+ ct.greet()
+
+ for {
+ f, err := ct.fr.ReadFrame()
+ if err != nil {
+ return fmt.Errorf("ReadFrame while waiting for Headers: %v", err)
+ }
+ switch f := f.(type) {
+ default:
+ return fmt.Errorf("Got %T; want HeadersFrame", f)
+ case *WindowUpdateFrame, *SettingsFrame:
+ continue
+ case *HeadersFrame:
+ if !f.StreamEnded() {
+ return fmt.Errorf("got headers frame without END_STREAM")
+ }
+ return nil
+ }
+ }
+ }
+ ct.run()
+}
+
+func benchSimpleRoundTrip(b *testing.B, nHeaders int) {
+ defer disableGoroutineTracking()()
+ b.ReportAllocs()
+ st := newServerTester(b,
+ func(w http.ResponseWriter, r *http.Request) {
+ },
+ optOnlyServer,
+ optQuiet,
+ )
+ defer st.Close()
+
+ tr := &Transport{TLSClientConfig: tlsConfigInsecure}
+ defer tr.CloseIdleConnections()
+
+ req, err := http.NewRequest("GET", st.ts.URL, nil)
+ if err != nil {
+ b.Fatal(err)
+ }
+
+ for i := 0; i < nHeaders; i++ {
+ name := fmt.Sprint("A-", i)
+ req.Header.Set(name, "*")
+ }
+
+ b.ResetTimer()
+
+ for i := 0; i < b.N; i++ {
+ res, err := tr.RoundTrip(req)
+ if err != nil {
+ if res != nil {
+ res.Body.Close()
+ }
+ b.Fatalf("RoundTrip err = %v; want nil", err)
+ }
+ res.Body.Close()
+ if res.StatusCode != http.StatusOK {
+ b.Fatalf("Response code = %v; want %v", res.StatusCode, http.StatusOK)
+ }
+ }
+}
+
+type infiniteReader struct{}
+
+func (r infiniteReader) Read(b []byte) (int, error) {
+ return len(b), nil
+}
+
+// Issue 20521: it is not an error to receive a response and end stream
+// from the server without the body being consumed.
+func TestTransportResponseAndResetWithoutConsumingBodyRace(t *testing.T) {
+ st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+ w.WriteHeader(http.StatusOK)
+ }, optOnlyServer)
+ defer st.Close()
+
+ tr := &Transport{TLSClientConfig: tlsConfigInsecure}
+ defer tr.CloseIdleConnections()
+
+ // The request body needs to be big enough to trigger flow control.
+ req, _ := http.NewRequest("PUT", st.ts.URL, infiniteReader{})
+ res, err := tr.RoundTrip(req)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if res.StatusCode != http.StatusOK {
+ t.Fatalf("Response code = %v; want %v", res.StatusCode, http.StatusOK)
+ }
+}
+
+// Verify transport doesn't crash when receiving bogus response lacking a :status header.
+// Issue 22880.
+func TestTransportHandlesInvalidStatuslessResponse(t *testing.T) {
+ ct := newClientTester(t)
+ ct.client = func() error {
+ req, _ := http.NewRequest("GET", "https://dummy.tld/", nil)
+ _, err := ct.tr.RoundTrip(req)
+ const substr = "malformed response from server: missing status pseudo header"
+ if !strings.Contains(fmt.Sprint(err), substr) {
+ return fmt.Errorf("RoundTrip error = %v; want substring %q", err, substr)
+ }
+ return nil
+ }
+ ct.server = func() error {
+ ct.greet()
+ var buf bytes.Buffer
+ enc := hpack.NewEncoder(&buf)
+
+ for {
+ f, err := ct.fr.ReadFrame()
+ if err != nil {
+ return err
+ }
+ switch f := f.(type) {
+ case *HeadersFrame:
+ enc.WriteField(hpack.HeaderField{Name: "content-type", Value: "text/html"}) // no :status header
+ ct.fr.WriteHeaders(HeadersFrameParam{
+ StreamID: f.StreamID,
+ EndHeaders: true,
+ EndStream: false, // we'll send some DATA to try to crash the transport
+ BlockFragment: buf.Bytes(),
+ })
+ ct.fr.WriteData(f.StreamID, true, []byte("payload"))
+ return nil
+ }
+ }
+ }
+ ct.run()
+}
+
+func BenchmarkClientRequestHeaders(b *testing.B) {
+ b.Run(" 0 Headers", func(b *testing.B) { benchSimpleRoundTrip(b, 0) })
+ b.Run(" 10 Headers", func(b *testing.B) { benchSimpleRoundTrip(b, 10) })
+ b.Run(" 100 Headers", func(b *testing.B) { benchSimpleRoundTrip(b, 100) })
+ b.Run("1000 Headers", func(b *testing.B) { benchSimpleRoundTrip(b, 1000) })
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/write.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/write.go
new file mode 100644
index 000000000..54ab4a88e
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/write.go
@@ -0,0 +1,365 @@
+// Copyright 2014 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 http2
+
+import (
+ "bytes"
+ "fmt"
+ "log"
+ "net/http"
+ "net/url"
+
+ "golang.org/x/net/http2/hpack"
+ "golang.org/x/net/lex/httplex"
+)
+
+// writeFramer is implemented by any type that is used to write frames.
+type writeFramer interface {
+ writeFrame(writeContext) error
+
+ // staysWithinBuffer reports whether this writer promises that
+ // it will only write less than or equal to size bytes, and it
+ // won't Flush the write context.
+ staysWithinBuffer(size int) bool
+}
+
+// writeContext is the interface needed by the various frame writer
+// types below. All the writeFrame methods below are scheduled via the
+// frame writing scheduler (see writeScheduler in writesched.go).
+//
+// This interface is implemented by *serverConn.
+//
+// TODO: decide whether to a) use this in the client code (which didn't
+// end up using this yet, because it has a simpler design, not
+// currently implementing priorities), or b) delete this and
+// make the server code a bit more concrete.
+type writeContext interface {
+ Framer() *Framer
+ Flush() error
+ CloseConn() error
+ // HeaderEncoder returns an HPACK encoder that writes to the
+ // returned buffer.
+ HeaderEncoder() (*hpack.Encoder, *bytes.Buffer)
+}
+
+// writeEndsStream reports whether w writes a frame that will transition
+// the stream to a half-closed local state. This returns false for RST_STREAM,
+// which closes the entire stream (not just the local half).
+func writeEndsStream(w writeFramer) bool {
+ switch v := w.(type) {
+ case *writeData:
+ return v.endStream
+ case *writeResHeaders:
+ return v.endStream
+ case nil:
+ // This can only happen if the caller reuses w after it's
+ // been intentionally nil'ed out to prevent use. Keep this
+ // here to catch future refactoring breaking it.
+ panic("writeEndsStream called on nil writeFramer")
+ }
+ return false
+}
+
+type flushFrameWriter struct{}
+
+func (flushFrameWriter) writeFrame(ctx writeContext) error {
+ return ctx.Flush()
+}
+
+func (flushFrameWriter) staysWithinBuffer(max int) bool { return false }
+
+type writeSettings []Setting
+
+func (s writeSettings) staysWithinBuffer(max int) bool {
+ const settingSize = 6 // uint16 + uint32
+ return frameHeaderLen+settingSize*len(s) <= max
+
+}
+
+func (s writeSettings) writeFrame(ctx writeContext) error {
+ return ctx.Framer().WriteSettings([]Setting(s)...)
+}
+
+type writeGoAway struct {
+ maxStreamID uint32
+ code ErrCode
+}
+
+func (p *writeGoAway) writeFrame(ctx writeContext) error {
+ err := ctx.Framer().WriteGoAway(p.maxStreamID, p.code, nil)
+ ctx.Flush() // ignore error: we're hanging up on them anyway
+ return err
+}
+
+func (*writeGoAway) staysWithinBuffer(max int) bool { return false } // flushes
+
+type writeData struct {
+ streamID uint32
+ p []byte
+ endStream bool
+}
+
+func (w *writeData) String() string {
+ return fmt.Sprintf("writeData(stream=%d, p=%d, endStream=%v)", w.streamID, len(w.p), w.endStream)
+}
+
+func (w *writeData) writeFrame(ctx writeContext) error {
+ return ctx.Framer().WriteData(w.streamID, w.endStream, w.p)
+}
+
+func (w *writeData) staysWithinBuffer(max int) bool {
+ return frameHeaderLen+len(w.p) <= max
+}
+
+// handlerPanicRST is the message sent from handler goroutines when
+// the handler panics.
+type handlerPanicRST struct {
+ StreamID uint32
+}
+
+func (hp handlerPanicRST) writeFrame(ctx writeContext) error {
+ return ctx.Framer().WriteRSTStream(hp.StreamID, ErrCodeInternal)
+}
+
+func (hp handlerPanicRST) staysWithinBuffer(max int) bool { return frameHeaderLen+4 <= max }
+
+func (se StreamError) writeFrame(ctx writeContext) error {
+ return ctx.Framer().WriteRSTStream(se.StreamID, se.Code)
+}
+
+func (se StreamError) staysWithinBuffer(max int) bool { return frameHeaderLen+4 <= max }
+
+type writePingAck struct{ pf *PingFrame }
+
+func (w writePingAck) writeFrame(ctx writeContext) error {
+ return ctx.Framer().WritePing(true, w.pf.Data)
+}
+
+func (w writePingAck) staysWithinBuffer(max int) bool { return frameHeaderLen+len(w.pf.Data) <= max }
+
+type writeSettingsAck struct{}
+
+func (writeSettingsAck) writeFrame(ctx writeContext) error {
+ return ctx.Framer().WriteSettingsAck()
+}
+
+func (writeSettingsAck) staysWithinBuffer(max int) bool { return frameHeaderLen <= max }
+
+// splitHeaderBlock splits headerBlock into fragments so that each fragment fits
+// in a single frame, then calls fn for each fragment. firstFrag/lastFrag are true
+// for the first/last fragment, respectively.
+func splitHeaderBlock(ctx writeContext, headerBlock []byte, fn func(ctx writeContext, frag []byte, firstFrag, lastFrag bool) error) error {
+ // For now we're lazy and just pick the minimum MAX_FRAME_SIZE
+ // that all peers must support (16KB). Later we could care
+ // more and send larger frames if the peer advertised it, but
+ // there's little point. Most headers are small anyway (so we
+ // generally won't have CONTINUATION frames), and extra frames
+ // only waste 9 bytes anyway.
+ const maxFrameSize = 16384
+
+ first := true
+ for len(headerBlock) > 0 {
+ frag := headerBlock
+ if len(frag) > maxFrameSize {
+ frag = frag[:maxFrameSize]
+ }
+ headerBlock = headerBlock[len(frag):]
+ if err := fn(ctx, frag, first, len(headerBlock) == 0); err != nil {
+ return err
+ }
+ first = false
+ }
+ return nil
+}
+
+// writeResHeaders is a request to write a HEADERS and 0+ CONTINUATION frames
+// for HTTP response headers or trailers from a server handler.
+type writeResHeaders struct {
+ streamID uint32
+ httpResCode int // 0 means no ":status" line
+ h http.Header // may be nil
+ trailers []string // if non-nil, which keys of h to write. nil means all.
+ endStream bool
+
+ date string
+ contentType string
+ contentLength string
+}
+
+func encKV(enc *hpack.Encoder, k, v string) {
+ if VerboseLogs {
+ log.Printf("http2: server encoding header %q = %q", k, v)
+ }
+ enc.WriteField(hpack.HeaderField{Name: k, Value: v})
+}
+
+func (w *writeResHeaders) staysWithinBuffer(max int) bool {
+ // TODO: this is a common one. It'd be nice to return true
+ // here and get into the fast path if we could be clever and
+ // calculate the size fast enough, or at least a conservative
+ // uppper bound that usually fires. (Maybe if w.h and
+ // w.trailers are nil, so we don't need to enumerate it.)
+ // Otherwise I'm afraid that just calculating the length to
+ // answer this question would be slower than the ~2µs benefit.
+ return false
+}
+
+func (w *writeResHeaders) writeFrame(ctx writeContext) error {
+ enc, buf := ctx.HeaderEncoder()
+ buf.Reset()
+
+ if w.httpResCode != 0 {
+ encKV(enc, ":status", httpCodeString(w.httpResCode))
+ }
+
+ encodeHeaders(enc, w.h, w.trailers)
+
+ if w.contentType != "" {
+ encKV(enc, "content-type", w.contentType)
+ }
+ if w.contentLength != "" {
+ encKV(enc, "content-length", w.contentLength)
+ }
+ if w.date != "" {
+ encKV(enc, "date", w.date)
+ }
+
+ headerBlock := buf.Bytes()
+ if len(headerBlock) == 0 && w.trailers == nil {
+ panic("unexpected empty hpack")
+ }
+
+ return splitHeaderBlock(ctx, headerBlock, w.writeHeaderBlock)
+}
+
+func (w *writeResHeaders) writeHeaderBlock(ctx writeContext, frag []byte, firstFrag, lastFrag bool) error {
+ if firstFrag {
+ return ctx.Framer().WriteHeaders(HeadersFrameParam{
+ StreamID: w.streamID,
+ BlockFragment: frag,
+ EndStream: w.endStream,
+ EndHeaders: lastFrag,
+ })
+ } else {
+ return ctx.Framer().WriteContinuation(w.streamID, lastFrag, frag)
+ }
+}
+
+// writePushPromise is a request to write a PUSH_PROMISE and 0+ CONTINUATION frames.
+type writePushPromise struct {
+ streamID uint32 // pusher stream
+ method string // for :method
+ url *url.URL // for :scheme, :authority, :path
+ h http.Header
+
+ // Creates an ID for a pushed stream. This runs on serveG just before
+ // the frame is written. The returned ID is copied to promisedID.
+ allocatePromisedID func() (uint32, error)
+ promisedID uint32
+}
+
+func (w *writePushPromise) staysWithinBuffer(max int) bool {
+ // TODO: see writeResHeaders.staysWithinBuffer
+ return false
+}
+
+func (w *writePushPromise) writeFrame(ctx writeContext) error {
+ enc, buf := ctx.HeaderEncoder()
+ buf.Reset()
+
+ encKV(enc, ":method", w.method)
+ encKV(enc, ":scheme", w.url.Scheme)
+ encKV(enc, ":authority", w.url.Host)
+ encKV(enc, ":path", w.url.RequestURI())
+ encodeHeaders(enc, w.h, nil)
+
+ headerBlock := buf.Bytes()
+ if len(headerBlock) == 0 {
+ panic("unexpected empty hpack")
+ }
+
+ return splitHeaderBlock(ctx, headerBlock, w.writeHeaderBlock)
+}
+
+func (w *writePushPromise) writeHeaderBlock(ctx writeContext, frag []byte, firstFrag, lastFrag bool) error {
+ if firstFrag {
+ return ctx.Framer().WritePushPromise(PushPromiseParam{
+ StreamID: w.streamID,
+ PromiseID: w.promisedID,
+ BlockFragment: frag,
+ EndHeaders: lastFrag,
+ })
+ } else {
+ return ctx.Framer().WriteContinuation(w.streamID, lastFrag, frag)
+ }
+}
+
+type write100ContinueHeadersFrame struct {
+ streamID uint32
+}
+
+func (w write100ContinueHeadersFrame) writeFrame(ctx writeContext) error {
+ enc, buf := ctx.HeaderEncoder()
+ buf.Reset()
+ encKV(enc, ":status", "100")
+ return ctx.Framer().WriteHeaders(HeadersFrameParam{
+ StreamID: w.streamID,
+ BlockFragment: buf.Bytes(),
+ EndStream: false,
+ EndHeaders: true,
+ })
+}
+
+func (w write100ContinueHeadersFrame) staysWithinBuffer(max int) bool {
+ // Sloppy but conservative:
+ return 9+2*(len(":status")+len("100")) <= max
+}
+
+type writeWindowUpdate struct {
+ streamID uint32 // or 0 for conn-level
+ n uint32
+}
+
+func (wu writeWindowUpdate) staysWithinBuffer(max int) bool { return frameHeaderLen+4 <= max }
+
+func (wu writeWindowUpdate) writeFrame(ctx writeContext) error {
+ return ctx.Framer().WriteWindowUpdate(wu.streamID, wu.n)
+}
+
+// encodeHeaders encodes an http.Header. If keys is not nil, then (k, h[k])
+// is encoded only only if k is in keys.
+func encodeHeaders(enc *hpack.Encoder, h http.Header, keys []string) {
+ if keys == nil {
+ sorter := sorterPool.Get().(*sorter)
+ // Using defer here, since the returned keys from the
+ // sorter.Keys method is only valid until the sorter
+ // is returned:
+ defer sorterPool.Put(sorter)
+ keys = sorter.Keys(h)
+ }
+ for _, k := range keys {
+ vv := h[k]
+ k = lowerHeader(k)
+ if !validWireHeaderFieldName(k) {
+ // Skip it as backup paranoia. Per
+ // golang.org/issue/14048, these should
+ // already be rejected at a higher level.
+ continue
+ }
+ isTE := k == "transfer-encoding"
+ for _, v := range vv {
+ if !httplex.ValidHeaderFieldValue(v) {
+ // TODO: return an error? golang.org/issue/14048
+ // For now just omit it.
+ continue
+ }
+ // TODO: more of "8.1.2.2 Connection-Specific Header Fields"
+ if isTE && v != "trailers" {
+ continue
+ }
+ encKV(enc, k, v)
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/writesched.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/writesched.go
new file mode 100644
index 000000000..4fe307307
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/writesched.go
@@ -0,0 +1,242 @@
+// Copyright 2014 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 http2
+
+import "fmt"
+
+// WriteScheduler is the interface implemented by HTTP/2 write schedulers.
+// Methods are never called concurrently.
+type WriteScheduler interface {
+ // OpenStream opens a new stream in the write scheduler.
+ // It is illegal to call this with streamID=0 or with a streamID that is
+ // already open -- the call may panic.
+ OpenStream(streamID uint32, options OpenStreamOptions)
+
+ // CloseStream closes a stream in the write scheduler. Any frames queued on
+ // this stream should be discarded. It is illegal to call this on a stream
+ // that is not open -- the call may panic.
+ CloseStream(streamID uint32)
+
+ // AdjustStream adjusts the priority of the given stream. This may be called
+ // on a stream that has not yet been opened or has been closed. Note that
+ // RFC 7540 allows PRIORITY frames to be sent on streams in any state. See:
+ // https://tools.ietf.org/html/rfc7540#section-5.1
+ AdjustStream(streamID uint32, priority PriorityParam)
+
+ // Push queues a frame in the scheduler. In most cases, this will not be
+ // called with wr.StreamID()!=0 unless that stream is currently open. The one
+ // exception is RST_STREAM frames, which may be sent on idle or closed streams.
+ Push(wr FrameWriteRequest)
+
+ // Pop dequeues the next frame to write. Returns false if no frames can
+ // be written. Frames with a given wr.StreamID() are Pop'd in the same
+ // order they are Push'd.
+ Pop() (wr FrameWriteRequest, ok bool)
+}
+
+// OpenStreamOptions specifies extra options for WriteScheduler.OpenStream.
+type OpenStreamOptions struct {
+ // PusherID is zero if the stream was initiated by the client. Otherwise,
+ // PusherID names the stream that pushed the newly opened stream.
+ PusherID uint32
+}
+
+// FrameWriteRequest is a request to write a frame.
+type FrameWriteRequest struct {
+ // write is the interface value that does the writing, once the
+ // WriteScheduler has selected this frame to write. The write
+ // functions are all defined in write.go.
+ write writeFramer
+
+ // stream is the stream on which this frame will be written.
+ // nil for non-stream frames like PING and SETTINGS.
+ stream *stream
+
+ // done, if non-nil, must be a buffered channel with space for
+ // 1 message and is sent the return value from write (or an
+ // earlier error) when the frame has been written.
+ done chan error
+}
+
+// StreamID returns the id of the stream this frame will be written to.
+// 0 is used for non-stream frames such as PING and SETTINGS.
+func (wr FrameWriteRequest) StreamID() uint32 {
+ if wr.stream == nil {
+ if se, ok := wr.write.(StreamError); ok {
+ // (*serverConn).resetStream doesn't set
+ // stream because it doesn't necessarily have
+ // one. So special case this type of write
+ // message.
+ return se.StreamID
+ }
+ return 0
+ }
+ return wr.stream.id
+}
+
+// DataSize returns the number of flow control bytes that must be consumed
+// to write this entire frame. This is 0 for non-DATA frames.
+func (wr FrameWriteRequest) DataSize() int {
+ if wd, ok := wr.write.(*writeData); ok {
+ return len(wd.p)
+ }
+ return 0
+}
+
+// Consume consumes min(n, available) bytes from this frame, where available
+// is the number of flow control bytes available on the stream. Consume returns
+// 0, 1, or 2 frames, where the integer return value gives the number of frames
+// returned.
+//
+// If flow control prevents consuming any bytes, this returns (_, _, 0). If
+// the entire frame was consumed, this returns (wr, _, 1). Otherwise, this
+// returns (consumed, rest, 2), where 'consumed' contains the consumed bytes and
+// 'rest' contains the remaining bytes. The consumed bytes are deducted from the
+// underlying stream's flow control budget.
+func (wr FrameWriteRequest) Consume(n int32) (FrameWriteRequest, FrameWriteRequest, int) {
+ var empty FrameWriteRequest
+
+ // Non-DATA frames are always consumed whole.
+ wd, ok := wr.write.(*writeData)
+ if !ok || len(wd.p) == 0 {
+ return wr, empty, 1
+ }
+
+ // Might need to split after applying limits.
+ allowed := wr.stream.flow.available()
+ if n < allowed {
+ allowed = n
+ }
+ if wr.stream.sc.maxFrameSize < allowed {
+ allowed = wr.stream.sc.maxFrameSize
+ }
+ if allowed <= 0 {
+ return empty, empty, 0
+ }
+ if len(wd.p) > int(allowed) {
+ wr.stream.flow.take(allowed)
+ consumed := FrameWriteRequest{
+ stream: wr.stream,
+ write: &writeData{
+ streamID: wd.streamID,
+ p: wd.p[:allowed],
+ // Even if the original had endStream set, there
+ // are bytes remaining because len(wd.p) > allowed,
+ // so we know endStream is false.
+ endStream: false,
+ },
+ // Our caller is blocking on the final DATA frame, not
+ // this intermediate frame, so no need to wait.
+ done: nil,
+ }
+ rest := FrameWriteRequest{
+ stream: wr.stream,
+ write: &writeData{
+ streamID: wd.streamID,
+ p: wd.p[allowed:],
+ endStream: wd.endStream,
+ },
+ done: wr.done,
+ }
+ return consumed, rest, 2
+ }
+
+ // The frame is consumed whole.
+ // NB: This cast cannot overflow because allowed is <= math.MaxInt32.
+ wr.stream.flow.take(int32(len(wd.p)))
+ return wr, empty, 1
+}
+
+// String is for debugging only.
+func (wr FrameWriteRequest) String() string {
+ var des string
+ if s, ok := wr.write.(fmt.Stringer); ok {
+ des = s.String()
+ } else {
+ des = fmt.Sprintf("%T", wr.write)
+ }
+ return fmt.Sprintf("[FrameWriteRequest stream=%d, ch=%v, writer=%v]", wr.StreamID(), wr.done != nil, des)
+}
+
+// replyToWriter sends err to wr.done and panics if the send must block
+// This does nothing if wr.done is nil.
+func (wr *FrameWriteRequest) replyToWriter(err error) {
+ if wr.done == nil {
+ return
+ }
+ select {
+ case wr.done <- err:
+ default:
+ panic(fmt.Sprintf("unbuffered done channel passed in for type %T", wr.write))
+ }
+ wr.write = nil // prevent use (assume it's tainted after wr.done send)
+}
+
+// writeQueue is used by implementations of WriteScheduler.
+type writeQueue struct {
+ s []FrameWriteRequest
+}
+
+func (q *writeQueue) empty() bool { return len(q.s) == 0 }
+
+func (q *writeQueue) push(wr FrameWriteRequest) {
+ q.s = append(q.s, wr)
+}
+
+func (q *writeQueue) shift() FrameWriteRequest {
+ if len(q.s) == 0 {
+ panic("invalid use of queue")
+ }
+ wr := q.s[0]
+ // TODO: less copy-happy queue.
+ copy(q.s, q.s[1:])
+ q.s[len(q.s)-1] = FrameWriteRequest{}
+ q.s = q.s[:len(q.s)-1]
+ return wr
+}
+
+// consume consumes up to n bytes from q.s[0]. If the frame is
+// entirely consumed, it is removed from the queue. If the frame
+// is partially consumed, the frame is kept with the consumed
+// bytes removed. Returns true iff any bytes were consumed.
+func (q *writeQueue) consume(n int32) (FrameWriteRequest, bool) {
+ if len(q.s) == 0 {
+ return FrameWriteRequest{}, false
+ }
+ consumed, rest, numresult := q.s[0].Consume(n)
+ switch numresult {
+ case 0:
+ return FrameWriteRequest{}, false
+ case 1:
+ q.shift()
+ case 2:
+ q.s[0] = rest
+ }
+ return consumed, true
+}
+
+type writeQueuePool []*writeQueue
+
+// put inserts an unused writeQueue into the pool.
+func (p *writeQueuePool) put(q *writeQueue) {
+ for i := range q.s {
+ q.s[i] = FrameWriteRequest{}
+ }
+ q.s = q.s[:0]
+ *p = append(*p, q)
+}
+
+// get returns an empty writeQueue.
+func (p *writeQueuePool) get() *writeQueue {
+ ln := len(*p)
+ if ln == 0 {
+ return new(writeQueue)
+ }
+ x := ln - 1
+ q := (*p)[x]
+ (*p)[x] = nil
+ *p = (*p)[:x]
+ return q
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/writesched_priority.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/writesched_priority.go
new file mode 100644
index 000000000..848fed6ec
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/writesched_priority.go
@@ -0,0 +1,452 @@
+// 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.
+
+package http2
+
+import (
+ "fmt"
+ "math"
+ "sort"
+)
+
+// RFC 7540, Section 5.3.5: the default weight is 16.
+const priorityDefaultWeight = 15 // 16 = 15 + 1
+
+// PriorityWriteSchedulerConfig configures a priorityWriteScheduler.
+type PriorityWriteSchedulerConfig struct {
+ // MaxClosedNodesInTree controls the maximum number of closed streams to
+ // retain in the priority tree. Setting this to zero saves a small amount
+ // of memory at the cost of performance.
+ //
+ // See RFC 7540, Section 5.3.4:
+ // "It is possible for a stream to become closed while prioritization
+ // information ... is in transit. ... This potentially creates suboptimal
+ // prioritization, since the stream could be given a priority that is
+ // different from what is intended. To avoid these problems, an endpoint
+ // SHOULD retain stream prioritization state for a period after streams
+ // become closed. The longer state is retained, the lower the chance that
+ // streams are assigned incorrect or default priority values."
+ MaxClosedNodesInTree int
+
+ // MaxIdleNodesInTree controls the maximum number of idle streams to
+ // retain in the priority tree. Setting this to zero saves a small amount
+ // of memory at the cost of performance.
+ //
+ // See RFC 7540, Section 5.3.4:
+ // Similarly, streams that are in the "idle" state can be assigned
+ // priority or become a parent of other streams. This allows for the
+ // creation of a grouping node in the dependency tree, which enables
+ // more flexible expressions of priority. Idle streams begin with a
+ // default priority (Section 5.3.5).
+ MaxIdleNodesInTree int
+
+ // ThrottleOutOfOrderWrites enables write throttling to help ensure that
+ // data is delivered in priority order. This works around a race where
+ // stream B depends on stream A and both streams are about to call Write
+ // to queue DATA frames. If B wins the race, a naive scheduler would eagerly
+ // write as much data from B as possible, but this is suboptimal because A
+ // is a higher-priority stream. With throttling enabled, we write a small
+ // amount of data from B to minimize the amount of bandwidth that B can
+ // steal from A.
+ ThrottleOutOfOrderWrites bool
+}
+
+// NewPriorityWriteScheduler constructs a WriteScheduler that schedules
+// frames by following HTTP/2 priorities as described in RFC 7540 Section 5.3.
+// If cfg is nil, default options are used.
+func NewPriorityWriteScheduler(cfg *PriorityWriteSchedulerConfig) WriteScheduler {
+ if cfg == nil {
+ // For justification of these defaults, see:
+ // https://docs.google.com/document/d/1oLhNg1skaWD4_DtaoCxdSRN5erEXrH-KnLrMwEpOtFY
+ cfg = &PriorityWriteSchedulerConfig{
+ MaxClosedNodesInTree: 10,
+ MaxIdleNodesInTree: 10,
+ ThrottleOutOfOrderWrites: false,
+ }
+ }
+
+ ws := &priorityWriteScheduler{
+ nodes: make(map[uint32]*priorityNode),
+ maxClosedNodesInTree: cfg.MaxClosedNodesInTree,
+ maxIdleNodesInTree: cfg.MaxIdleNodesInTree,
+ enableWriteThrottle: cfg.ThrottleOutOfOrderWrites,
+ }
+ ws.nodes[0] = &ws.root
+ if cfg.ThrottleOutOfOrderWrites {
+ ws.writeThrottleLimit = 1024
+ } else {
+ ws.writeThrottleLimit = math.MaxInt32
+ }
+ return ws
+}
+
+type priorityNodeState int
+
+const (
+ priorityNodeOpen priorityNodeState = iota
+ priorityNodeClosed
+ priorityNodeIdle
+)
+
+// priorityNode is a node in an HTTP/2 priority tree.
+// Each node is associated with a single stream ID.
+// See RFC 7540, Section 5.3.
+type priorityNode struct {
+ q writeQueue // queue of pending frames to write
+ id uint32 // id of the stream, or 0 for the root of the tree
+ weight uint8 // the actual weight is weight+1, so the value is in [1,256]
+ state priorityNodeState // open | closed | idle
+ bytes int64 // number of bytes written by this node, or 0 if closed
+ subtreeBytes int64 // sum(node.bytes) of all nodes in this subtree
+
+ // These links form the priority tree.
+ parent *priorityNode
+ kids *priorityNode // start of the kids list
+ prev, next *priorityNode // doubly-linked list of siblings
+}
+
+func (n *priorityNode) setParent(parent *priorityNode) {
+ if n == parent {
+ panic("setParent to self")
+ }
+ if n.parent == parent {
+ return
+ }
+ // Unlink from current parent.
+ if parent := n.parent; parent != nil {
+ if n.prev == nil {
+ parent.kids = n.next
+ } else {
+ n.prev.next = n.next
+ }
+ if n.next != nil {
+ n.next.prev = n.prev
+ }
+ }
+ // Link to new parent.
+ // If parent=nil, remove n from the tree.
+ // Always insert at the head of parent.kids (this is assumed by walkReadyInOrder).
+ n.parent = parent
+ if parent == nil {
+ n.next = nil
+ n.prev = nil
+ } else {
+ n.next = parent.kids
+ n.prev = nil
+ if n.next != nil {
+ n.next.prev = n
+ }
+ parent.kids = n
+ }
+}
+
+func (n *priorityNode) addBytes(b int64) {
+ n.bytes += b
+ for ; n != nil; n = n.parent {
+ n.subtreeBytes += b
+ }
+}
+
+// walkReadyInOrder iterates over the tree in priority order, calling f for each node
+// with a non-empty write queue. When f returns true, this funcion returns true and the
+// walk halts. tmp is used as scratch space for sorting.
+//
+// f(n, openParent) takes two arguments: the node to visit, n, and a bool that is true
+// if any ancestor p of n is still open (ignoring the root node).
+func (n *priorityNode) walkReadyInOrder(openParent bool, tmp *[]*priorityNode, f func(*priorityNode, bool) bool) bool {
+ if !n.q.empty() && f(n, openParent) {
+ return true
+ }
+ if n.kids == nil {
+ return false
+ }
+
+ // Don't consider the root "open" when updating openParent since
+ // we can't send data frames on the root stream (only control frames).
+ if n.id != 0 {
+ openParent = openParent || (n.state == priorityNodeOpen)
+ }
+
+ // Common case: only one kid or all kids have the same weight.
+ // Some clients don't use weights; other clients (like web browsers)
+ // use mostly-linear priority trees.
+ w := n.kids.weight
+ needSort := false
+ for k := n.kids.next; k != nil; k = k.next {
+ if k.weight != w {
+ needSort = true
+ break
+ }
+ }
+ if !needSort {
+ for k := n.kids; k != nil; k = k.next {
+ if k.walkReadyInOrder(openParent, tmp, f) {
+ return true
+ }
+ }
+ return false
+ }
+
+ // Uncommon case: sort the child nodes. We remove the kids from the parent,
+ // then re-insert after sorting so we can reuse tmp for future sort calls.
+ *tmp = (*tmp)[:0]
+ for n.kids != nil {
+ *tmp = append(*tmp, n.kids)
+ n.kids.setParent(nil)
+ }
+ sort.Sort(sortPriorityNodeSiblings(*tmp))
+ for i := len(*tmp) - 1; i >= 0; i-- {
+ (*tmp)[i].setParent(n) // setParent inserts at the head of n.kids
+ }
+ for k := n.kids; k != nil; k = k.next {
+ if k.walkReadyInOrder(openParent, tmp, f) {
+ return true
+ }
+ }
+ return false
+}
+
+type sortPriorityNodeSiblings []*priorityNode
+
+func (z sortPriorityNodeSiblings) Len() int { return len(z) }
+func (z sortPriorityNodeSiblings) Swap(i, k int) { z[i], z[k] = z[k], z[i] }
+func (z sortPriorityNodeSiblings) Less(i, k int) bool {
+ // Prefer the subtree that has sent fewer bytes relative to its weight.
+ // See sections 5.3.2 and 5.3.4.
+ wi, bi := float64(z[i].weight+1), float64(z[i].subtreeBytes)
+ wk, bk := float64(z[k].weight+1), float64(z[k].subtreeBytes)
+ if bi == 0 && bk == 0 {
+ return wi >= wk
+ }
+ if bk == 0 {
+ return false
+ }
+ return bi/bk <= wi/wk
+}
+
+type priorityWriteScheduler struct {
+ // root is the root of the priority tree, where root.id = 0.
+ // The root queues control frames that are not associated with any stream.
+ root priorityNode
+
+ // nodes maps stream ids to priority tree nodes.
+ nodes map[uint32]*priorityNode
+
+ // maxID is the maximum stream id in nodes.
+ maxID uint32
+
+ // lists of nodes that have been closed or are idle, but are kept in
+ // the tree for improved prioritization. When the lengths exceed either
+ // maxClosedNodesInTree or maxIdleNodesInTree, old nodes are discarded.
+ closedNodes, idleNodes []*priorityNode
+
+ // From the config.
+ maxClosedNodesInTree int
+ maxIdleNodesInTree int
+ writeThrottleLimit int32
+ enableWriteThrottle bool
+
+ // tmp is scratch space for priorityNode.walkReadyInOrder to reduce allocations.
+ tmp []*priorityNode
+
+ // pool of empty queues for reuse.
+ queuePool writeQueuePool
+}
+
+func (ws *priorityWriteScheduler) OpenStream(streamID uint32, options OpenStreamOptions) {
+ // The stream may be currently idle but cannot be opened or closed.
+ if curr := ws.nodes[streamID]; curr != nil {
+ if curr.state != priorityNodeIdle {
+ panic(fmt.Sprintf("stream %d already opened", streamID))
+ }
+ curr.state = priorityNodeOpen
+ return
+ }
+
+ // RFC 7540, Section 5.3.5:
+ // "All streams are initially assigned a non-exclusive dependency on stream 0x0.
+ // Pushed streams initially depend on their associated stream. In both cases,
+ // streams are assigned a default weight of 16."
+ parent := ws.nodes[options.PusherID]
+ if parent == nil {
+ parent = &ws.root
+ }
+ n := &priorityNode{
+ q: *ws.queuePool.get(),
+ id: streamID,
+ weight: priorityDefaultWeight,
+ state: priorityNodeOpen,
+ }
+ n.setParent(parent)
+ ws.nodes[streamID] = n
+ if streamID > ws.maxID {
+ ws.maxID = streamID
+ }
+}
+
+func (ws *priorityWriteScheduler) CloseStream(streamID uint32) {
+ if streamID == 0 {
+ panic("violation of WriteScheduler interface: cannot close stream 0")
+ }
+ if ws.nodes[streamID] == nil {
+ panic(fmt.Sprintf("violation of WriteScheduler interface: unknown stream %d", streamID))
+ }
+ if ws.nodes[streamID].state != priorityNodeOpen {
+ panic(fmt.Sprintf("violation of WriteScheduler interface: stream %d already closed", streamID))
+ }
+
+ n := ws.nodes[streamID]
+ n.state = priorityNodeClosed
+ n.addBytes(-n.bytes)
+
+ q := n.q
+ ws.queuePool.put(&q)
+ n.q.s = nil
+ if ws.maxClosedNodesInTree > 0 {
+ ws.addClosedOrIdleNode(&ws.closedNodes, ws.maxClosedNodesInTree, n)
+ } else {
+ ws.removeNode(n)
+ }
+}
+
+func (ws *priorityWriteScheduler) AdjustStream(streamID uint32, priority PriorityParam) {
+ if streamID == 0 {
+ panic("adjustPriority on root")
+ }
+
+ // If streamID does not exist, there are two cases:
+ // - A closed stream that has been removed (this will have ID <= maxID)
+ // - An idle stream that is being used for "grouping" (this will have ID > maxID)
+ n := ws.nodes[streamID]
+ if n == nil {
+ if streamID <= ws.maxID || ws.maxIdleNodesInTree == 0 {
+ return
+ }
+ ws.maxID = streamID
+ n = &priorityNode{
+ q: *ws.queuePool.get(),
+ id: streamID,
+ weight: priorityDefaultWeight,
+ state: priorityNodeIdle,
+ }
+ n.setParent(&ws.root)
+ ws.nodes[streamID] = n
+ ws.addClosedOrIdleNode(&ws.idleNodes, ws.maxIdleNodesInTree, n)
+ }
+
+ // Section 5.3.1: A dependency on a stream that is not currently in the tree
+ // results in that stream being given a default priority (Section 5.3.5).
+ parent := ws.nodes[priority.StreamDep]
+ if parent == nil {
+ n.setParent(&ws.root)
+ n.weight = priorityDefaultWeight
+ return
+ }
+
+ // Ignore if the client tries to make a node its own parent.
+ if n == parent {
+ return
+ }
+
+ // Section 5.3.3:
+ // "If a stream is made dependent on one of its own dependencies, the
+ // formerly dependent stream is first moved to be dependent on the
+ // reprioritized stream's previous parent. The moved dependency retains
+ // its weight."
+ //
+ // That is: if parent depends on n, move parent to depend on n.parent.
+ for x := parent.parent; x != nil; x = x.parent {
+ if x == n {
+ parent.setParent(n.parent)
+ break
+ }
+ }
+
+ // Section 5.3.3: The exclusive flag causes the stream to become the sole
+ // dependency of its parent stream, causing other dependencies to become
+ // dependent on the exclusive stream.
+ if priority.Exclusive {
+ k := parent.kids
+ for k != nil {
+ next := k.next
+ if k != n {
+ k.setParent(n)
+ }
+ k = next
+ }
+ }
+
+ n.setParent(parent)
+ n.weight = priority.Weight
+}
+
+func (ws *priorityWriteScheduler) Push(wr FrameWriteRequest) {
+ var n *priorityNode
+ if id := wr.StreamID(); id == 0 {
+ n = &ws.root
+ } else {
+ n = ws.nodes[id]
+ if n == nil {
+ // id is an idle or closed stream. wr should not be a HEADERS or
+ // DATA frame. However, wr can be a RST_STREAM. In this case, we
+ // push wr onto the root, rather than creating a new priorityNode,
+ // since RST_STREAM is tiny and the stream's priority is unknown
+ // anyway. See issue #17919.
+ if wr.DataSize() > 0 {
+ panic("add DATA on non-open stream")
+ }
+ n = &ws.root
+ }
+ }
+ n.q.push(wr)
+}
+
+func (ws *priorityWriteScheduler) Pop() (wr FrameWriteRequest, ok bool) {
+ ws.root.walkReadyInOrder(false, &ws.tmp, func(n *priorityNode, openParent bool) bool {
+ limit := int32(math.MaxInt32)
+ if openParent {
+ limit = ws.writeThrottleLimit
+ }
+ wr, ok = n.q.consume(limit)
+ if !ok {
+ return false
+ }
+ n.addBytes(int64(wr.DataSize()))
+ // If B depends on A and B continuously has data available but A
+ // does not, gradually increase the throttling limit to allow B to
+ // steal more and more bandwidth from A.
+ if openParent {
+ ws.writeThrottleLimit += 1024
+ if ws.writeThrottleLimit < 0 {
+ ws.writeThrottleLimit = math.MaxInt32
+ }
+ } else if ws.enableWriteThrottle {
+ ws.writeThrottleLimit = 1024
+ }
+ return true
+ })
+ return wr, ok
+}
+
+func (ws *priorityWriteScheduler) addClosedOrIdleNode(list *[]*priorityNode, maxSize int, n *priorityNode) {
+ if maxSize == 0 {
+ return
+ }
+ if len(*list) == maxSize {
+ // Remove the oldest node, then shift left.
+ ws.removeNode((*list)[0])
+ x := (*list)[1:]
+ copy(*list, x)
+ *list = (*list)[:len(x)]
+ }
+ *list = append(*list, n)
+}
+
+func (ws *priorityWriteScheduler) removeNode(n *priorityNode) {
+ for k := n.kids; k != nil; k = k.next {
+ k.setParent(n.parent)
+ }
+ n.setParent(nil)
+ delete(ws.nodes, n.id)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/writesched_priority_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/writesched_priority_test.go
new file mode 100644
index 000000000..f2b535a2c
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/writesched_priority_test.go
@@ -0,0 +1,541 @@
+// 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.
+
+package http2
+
+import (
+ "bytes"
+ "fmt"
+ "sort"
+ "testing"
+)
+
+func defaultPriorityWriteScheduler() *priorityWriteScheduler {
+ return NewPriorityWriteScheduler(nil).(*priorityWriteScheduler)
+}
+
+func checkPriorityWellFormed(ws *priorityWriteScheduler) error {
+ for id, n := range ws.nodes {
+ if id != n.id {
+ return fmt.Errorf("bad ws.nodes: ws.nodes[%d] = %d", id, n.id)
+ }
+ if n.parent == nil {
+ if n.next != nil || n.prev != nil {
+ return fmt.Errorf("bad node %d: nil parent but prev/next not nil", id)
+ }
+ continue
+ }
+ found := false
+ for k := n.parent.kids; k != nil; k = k.next {
+ if k.id == id {
+ found = true
+ break
+ }
+ }
+ if !found {
+ return fmt.Errorf("bad node %d: not found in parent %d kids list", id, n.parent.id)
+ }
+ }
+ return nil
+}
+
+func fmtTree(ws *priorityWriteScheduler, fmtNode func(*priorityNode) string) string {
+ var ids []int
+ for _, n := range ws.nodes {
+ ids = append(ids, int(n.id))
+ }
+ sort.Ints(ids)
+
+ var buf bytes.Buffer
+ for _, id := range ids {
+ if buf.Len() != 0 {
+ buf.WriteString(" ")
+ }
+ if id == 0 {
+ buf.WriteString(fmtNode(&ws.root))
+ } else {
+ buf.WriteString(fmtNode(ws.nodes[uint32(id)]))
+ }
+ }
+ return buf.String()
+}
+
+func fmtNodeParentSkipRoot(n *priorityNode) string {
+ switch {
+ case n.id == 0:
+ return ""
+ case n.parent == nil:
+ return fmt.Sprintf("%d{parent:nil}", n.id)
+ default:
+ return fmt.Sprintf("%d{parent:%d}", n.id, n.parent.id)
+ }
+}
+
+func fmtNodeWeightParentSkipRoot(n *priorityNode) string {
+ switch {
+ case n.id == 0:
+ return ""
+ case n.parent == nil:
+ return fmt.Sprintf("%d{weight:%d,parent:nil}", n.id, n.weight)
+ default:
+ return fmt.Sprintf("%d{weight:%d,parent:%d}", n.id, n.weight, n.parent.id)
+ }
+}
+
+func TestPriorityTwoStreams(t *testing.T) {
+ ws := defaultPriorityWriteScheduler()
+ ws.OpenStream(1, OpenStreamOptions{})
+ ws.OpenStream(2, OpenStreamOptions{})
+
+ want := "1{weight:15,parent:0} 2{weight:15,parent:0}"
+ if got := fmtTree(ws, fmtNodeWeightParentSkipRoot); got != want {
+ t.Errorf("After open\ngot %q\nwant %q", got, want)
+ }
+
+ // Move 1's parent to 2.
+ ws.AdjustStream(1, PriorityParam{
+ StreamDep: 2,
+ Weight: 32,
+ Exclusive: false,
+ })
+ want = "1{weight:32,parent:2} 2{weight:15,parent:0}"
+ if got := fmtTree(ws, fmtNodeWeightParentSkipRoot); got != want {
+ t.Errorf("After adjust\ngot %q\nwant %q", got, want)
+ }
+
+ if err := checkPriorityWellFormed(ws); err != nil {
+ t.Error(err)
+ }
+}
+
+func TestPriorityAdjustExclusiveZero(t *testing.T) {
+ // 1, 2, and 3 are all children of the 0 stream.
+ // Exclusive reprioritization to any of the streams should bring
+ // the rest of the streams under the reprioritized stream.
+ ws := defaultPriorityWriteScheduler()
+ ws.OpenStream(1, OpenStreamOptions{})
+ ws.OpenStream(2, OpenStreamOptions{})
+ ws.OpenStream(3, OpenStreamOptions{})
+
+ want := "1{weight:15,parent:0} 2{weight:15,parent:0} 3{weight:15,parent:0}"
+ if got := fmtTree(ws, fmtNodeWeightParentSkipRoot); got != want {
+ t.Errorf("After open\ngot %q\nwant %q", got, want)
+ }
+
+ ws.AdjustStream(2, PriorityParam{
+ StreamDep: 0,
+ Weight: 20,
+ Exclusive: true,
+ })
+ want = "1{weight:15,parent:2} 2{weight:20,parent:0} 3{weight:15,parent:2}"
+ if got := fmtTree(ws, fmtNodeWeightParentSkipRoot); got != want {
+ t.Errorf("After adjust\ngot %q\nwant %q", got, want)
+ }
+
+ if err := checkPriorityWellFormed(ws); err != nil {
+ t.Error(err)
+ }
+}
+
+func TestPriorityAdjustOwnParent(t *testing.T) {
+ // Assigning a node as its own parent should have no effect.
+ ws := defaultPriorityWriteScheduler()
+ ws.OpenStream(1, OpenStreamOptions{})
+ ws.OpenStream(2, OpenStreamOptions{})
+ ws.AdjustStream(2, PriorityParam{
+ StreamDep: 2,
+ Weight: 20,
+ Exclusive: true,
+ })
+ want := "1{weight:15,parent:0} 2{weight:15,parent:0}"
+ if got := fmtTree(ws, fmtNodeWeightParentSkipRoot); got != want {
+ t.Errorf("After adjust\ngot %q\nwant %q", got, want)
+ }
+ if err := checkPriorityWellFormed(ws); err != nil {
+ t.Error(err)
+ }
+}
+
+func TestPriorityClosedStreams(t *testing.T) {
+ ws := NewPriorityWriteScheduler(&PriorityWriteSchedulerConfig{MaxClosedNodesInTree: 2}).(*priorityWriteScheduler)
+ ws.OpenStream(1, OpenStreamOptions{})
+ ws.OpenStream(2, OpenStreamOptions{PusherID: 1})
+ ws.OpenStream(3, OpenStreamOptions{PusherID: 2})
+ ws.OpenStream(4, OpenStreamOptions{PusherID: 3})
+
+ // Close the first three streams. We lose 1, but keep 2 and 3.
+ ws.CloseStream(1)
+ ws.CloseStream(2)
+ ws.CloseStream(3)
+
+ want := "2{weight:15,parent:0} 3{weight:15,parent:2} 4{weight:15,parent:3}"
+ if got := fmtTree(ws, fmtNodeWeightParentSkipRoot); got != want {
+ t.Errorf("After close\ngot %q\nwant %q", got, want)
+ }
+ if err := checkPriorityWellFormed(ws); err != nil {
+ t.Error(err)
+ }
+
+ // Adding a stream as an exclusive child of 1 gives it default
+ // priorities, since 1 is gone.
+ ws.OpenStream(5, OpenStreamOptions{})
+ ws.AdjustStream(5, PriorityParam{StreamDep: 1, Weight: 15, Exclusive: true})
+
+ // Adding a stream as an exclusive child of 2 should work, since 2 is not gone.
+ ws.OpenStream(6, OpenStreamOptions{})
+ ws.AdjustStream(6, PriorityParam{StreamDep: 2, Weight: 15, Exclusive: true})
+
+ want = "2{weight:15,parent:0} 3{weight:15,parent:6} 4{weight:15,parent:3} 5{weight:15,parent:0} 6{weight:15,parent:2}"
+ if got := fmtTree(ws, fmtNodeWeightParentSkipRoot); got != want {
+ t.Errorf("After add streams\ngot %q\nwant %q", got, want)
+ }
+ if err := checkPriorityWellFormed(ws); err != nil {
+ t.Error(err)
+ }
+}
+
+func TestPriorityClosedStreamsDisabled(t *testing.T) {
+ ws := NewPriorityWriteScheduler(&PriorityWriteSchedulerConfig{}).(*priorityWriteScheduler)
+ ws.OpenStream(1, OpenStreamOptions{})
+ ws.OpenStream(2, OpenStreamOptions{PusherID: 1})
+ ws.OpenStream(3, OpenStreamOptions{PusherID: 2})
+
+ // Close the first two streams. We keep only 3.
+ ws.CloseStream(1)
+ ws.CloseStream(2)
+
+ want := "3{weight:15,parent:0}"
+ if got := fmtTree(ws, fmtNodeWeightParentSkipRoot); got != want {
+ t.Errorf("After close\ngot %q\nwant %q", got, want)
+ }
+ if err := checkPriorityWellFormed(ws); err != nil {
+ t.Error(err)
+ }
+}
+
+func TestPriorityIdleStreams(t *testing.T) {
+ ws := NewPriorityWriteScheduler(&PriorityWriteSchedulerConfig{MaxIdleNodesInTree: 2}).(*priorityWriteScheduler)
+ ws.AdjustStream(1, PriorityParam{StreamDep: 0, Weight: 15}) // idle
+ ws.AdjustStream(2, PriorityParam{StreamDep: 0, Weight: 15}) // idle
+ ws.AdjustStream(3, PriorityParam{StreamDep: 2, Weight: 20}) // idle
+ ws.OpenStream(4, OpenStreamOptions{})
+ ws.OpenStream(5, OpenStreamOptions{})
+ ws.OpenStream(6, OpenStreamOptions{})
+ ws.AdjustStream(4, PriorityParam{StreamDep: 1, Weight: 15})
+ ws.AdjustStream(5, PriorityParam{StreamDep: 2, Weight: 15})
+ ws.AdjustStream(6, PriorityParam{StreamDep: 3, Weight: 15})
+
+ want := "2{weight:15,parent:0} 3{weight:20,parent:2} 4{weight:15,parent:0} 5{weight:15,parent:2} 6{weight:15,parent:3}"
+ if got := fmtTree(ws, fmtNodeWeightParentSkipRoot); got != want {
+ t.Errorf("After open\ngot %q\nwant %q", got, want)
+ }
+ if err := checkPriorityWellFormed(ws); err != nil {
+ t.Error(err)
+ }
+}
+
+func TestPriorityIdleStreamsDisabled(t *testing.T) {
+ ws := NewPriorityWriteScheduler(&PriorityWriteSchedulerConfig{}).(*priorityWriteScheduler)
+ ws.AdjustStream(1, PriorityParam{StreamDep: 0, Weight: 15}) // idle
+ ws.AdjustStream(2, PriorityParam{StreamDep: 0, Weight: 15}) // idle
+ ws.AdjustStream(3, PriorityParam{StreamDep: 2, Weight: 20}) // idle
+ ws.OpenStream(4, OpenStreamOptions{})
+
+ want := "4{weight:15,parent:0}"
+ if got := fmtTree(ws, fmtNodeWeightParentSkipRoot); got != want {
+ t.Errorf("After open\ngot %q\nwant %q", got, want)
+ }
+ if err := checkPriorityWellFormed(ws); err != nil {
+ t.Error(err)
+ }
+}
+
+func TestPrioritySection531NonExclusive(t *testing.T) {
+ // Example from RFC 7540 Section 5.3.1.
+ // A,B,C,D = 1,2,3,4
+ ws := defaultPriorityWriteScheduler()
+ ws.OpenStream(1, OpenStreamOptions{})
+ ws.OpenStream(2, OpenStreamOptions{PusherID: 1})
+ ws.OpenStream(3, OpenStreamOptions{PusherID: 1})
+ ws.OpenStream(4, OpenStreamOptions{})
+ ws.AdjustStream(4, PriorityParam{
+ StreamDep: 1,
+ Weight: 15,
+ Exclusive: false,
+ })
+ want := "1{parent:0} 2{parent:1} 3{parent:1} 4{parent:1}"
+ if got := fmtTree(ws, fmtNodeParentSkipRoot); got != want {
+ t.Errorf("After adjust\ngot %q\nwant %q", got, want)
+ }
+ if err := checkPriorityWellFormed(ws); err != nil {
+ t.Error(err)
+ }
+}
+
+func TestPrioritySection531Exclusive(t *testing.T) {
+ // Example from RFC 7540 Section 5.3.1.
+ // A,B,C,D = 1,2,3,4
+ ws := defaultPriorityWriteScheduler()
+ ws.OpenStream(1, OpenStreamOptions{})
+ ws.OpenStream(2, OpenStreamOptions{PusherID: 1})
+ ws.OpenStream(3, OpenStreamOptions{PusherID: 1})
+ ws.OpenStream(4, OpenStreamOptions{})
+ ws.AdjustStream(4, PriorityParam{
+ StreamDep: 1,
+ Weight: 15,
+ Exclusive: true,
+ })
+ want := "1{parent:0} 2{parent:4} 3{parent:4} 4{parent:1}"
+ if got := fmtTree(ws, fmtNodeParentSkipRoot); got != want {
+ t.Errorf("After adjust\ngot %q\nwant %q", got, want)
+ }
+ if err := checkPriorityWellFormed(ws); err != nil {
+ t.Error(err)
+ }
+}
+
+func makeSection533Tree() *priorityWriteScheduler {
+ // Initial tree from RFC 7540 Section 5.3.3.
+ // A,B,C,D,E,F = 1,2,3,4,5,6
+ ws := defaultPriorityWriteScheduler()
+ ws.OpenStream(1, OpenStreamOptions{})
+ ws.OpenStream(2, OpenStreamOptions{PusherID: 1})
+ ws.OpenStream(3, OpenStreamOptions{PusherID: 1})
+ ws.OpenStream(4, OpenStreamOptions{PusherID: 3})
+ ws.OpenStream(5, OpenStreamOptions{PusherID: 3})
+ ws.OpenStream(6, OpenStreamOptions{PusherID: 4})
+ return ws
+}
+
+func TestPrioritySection533NonExclusive(t *testing.T) {
+ // Example from RFC 7540 Section 5.3.3.
+ // A,B,C,D,E,F = 1,2,3,4,5,6
+ ws := defaultPriorityWriteScheduler()
+ ws.OpenStream(1, OpenStreamOptions{})
+ ws.OpenStream(2, OpenStreamOptions{PusherID: 1})
+ ws.OpenStream(3, OpenStreamOptions{PusherID: 1})
+ ws.OpenStream(4, OpenStreamOptions{PusherID: 3})
+ ws.OpenStream(5, OpenStreamOptions{PusherID: 3})
+ ws.OpenStream(6, OpenStreamOptions{PusherID: 4})
+ ws.AdjustStream(1, PriorityParam{
+ StreamDep: 4,
+ Weight: 15,
+ Exclusive: false,
+ })
+ want := "1{parent:4} 2{parent:1} 3{parent:1} 4{parent:0} 5{parent:3} 6{parent:4}"
+ if got := fmtTree(ws, fmtNodeParentSkipRoot); got != want {
+ t.Errorf("After adjust\ngot %q\nwant %q", got, want)
+ }
+ if err := checkPriorityWellFormed(ws); err != nil {
+ t.Error(err)
+ }
+}
+
+func TestPrioritySection533Exclusive(t *testing.T) {
+ // Example from RFC 7540 Section 5.3.3.
+ // A,B,C,D,E,F = 1,2,3,4,5,6
+ ws := defaultPriorityWriteScheduler()
+ ws.OpenStream(1, OpenStreamOptions{})
+ ws.OpenStream(2, OpenStreamOptions{PusherID: 1})
+ ws.OpenStream(3, OpenStreamOptions{PusherID: 1})
+ ws.OpenStream(4, OpenStreamOptions{PusherID: 3})
+ ws.OpenStream(5, OpenStreamOptions{PusherID: 3})
+ ws.OpenStream(6, OpenStreamOptions{PusherID: 4})
+ ws.AdjustStream(1, PriorityParam{
+ StreamDep: 4,
+ Weight: 15,
+ Exclusive: true,
+ })
+ want := "1{parent:4} 2{parent:1} 3{parent:1} 4{parent:0} 5{parent:3} 6{parent:1}"
+ if got := fmtTree(ws, fmtNodeParentSkipRoot); got != want {
+ t.Errorf("After adjust\ngot %q\nwant %q", got, want)
+ }
+ if err := checkPriorityWellFormed(ws); err != nil {
+ t.Error(err)
+ }
+}
+
+func checkPopAll(ws WriteScheduler, order []uint32) error {
+ for k, id := range order {
+ wr, ok := ws.Pop()
+ if !ok {
+ return fmt.Errorf("Pop[%d]: got ok=false, want %d (order=%v)", k, id, order)
+ }
+ if got := wr.StreamID(); got != id {
+ return fmt.Errorf("Pop[%d]: got %v, want %d (order=%v)", k, got, id, order)
+ }
+ }
+ wr, ok := ws.Pop()
+ if ok {
+ return fmt.Errorf("Pop[%d]: got %v, want ok=false (order=%v)", len(order), wr.StreamID(), order)
+ }
+ return nil
+}
+
+func TestPriorityPopFrom533Tree(t *testing.T) {
+ ws := makeSection533Tree()
+
+ ws.Push(makeWriteHeadersRequest(3 /*C*/))
+ ws.Push(makeWriteNonStreamRequest())
+ ws.Push(makeWriteHeadersRequest(5 /*E*/))
+ ws.Push(makeWriteHeadersRequest(1 /*A*/))
+ t.Log("tree:", fmtTree(ws, fmtNodeParentSkipRoot))
+
+ if err := checkPopAll(ws, []uint32{0 /*NonStream*/, 1, 3, 5}); err != nil {
+ t.Error(err)
+ }
+}
+
+func TestPriorityPopFromLinearTree(t *testing.T) {
+ ws := defaultPriorityWriteScheduler()
+ ws.OpenStream(1, OpenStreamOptions{})
+ ws.OpenStream(2, OpenStreamOptions{PusherID: 1})
+ ws.OpenStream(3, OpenStreamOptions{PusherID: 2})
+ ws.OpenStream(4, OpenStreamOptions{PusherID: 3})
+
+ ws.Push(makeWriteHeadersRequest(3))
+ ws.Push(makeWriteHeadersRequest(4))
+ ws.Push(makeWriteHeadersRequest(1))
+ ws.Push(makeWriteHeadersRequest(2))
+ ws.Push(makeWriteNonStreamRequest())
+ ws.Push(makeWriteNonStreamRequest())
+ t.Log("tree:", fmtTree(ws, fmtNodeParentSkipRoot))
+
+ if err := checkPopAll(ws, []uint32{0, 0 /*NonStreams*/, 1, 2, 3, 4}); err != nil {
+ t.Error(err)
+ }
+}
+
+func TestPriorityFlowControl(t *testing.T) {
+ ws := NewPriorityWriteScheduler(&PriorityWriteSchedulerConfig{ThrottleOutOfOrderWrites: false})
+ ws.OpenStream(1, OpenStreamOptions{})
+ ws.OpenStream(2, OpenStreamOptions{PusherID: 1})
+
+ sc := &serverConn{maxFrameSize: 16}
+ st1 := &stream{id: 1, sc: sc}
+ st2 := &stream{id: 2, sc: sc}
+
+ ws.Push(FrameWriteRequest{&writeData{1, make([]byte, 16), false}, st1, nil})
+ ws.Push(FrameWriteRequest{&writeData{2, make([]byte, 16), false}, st2, nil})
+ ws.AdjustStream(2, PriorityParam{StreamDep: 1})
+
+ // No flow-control bytes available.
+ if wr, ok := ws.Pop(); ok {
+ t.Fatalf("Pop(limited by flow control)=%v,true, want false", wr)
+ }
+
+ // Add enough flow-control bytes to write st2 in two Pop calls.
+ // Should write data from st2 even though it's lower priority than st1.
+ for i := 1; i <= 2; i++ {
+ st2.flow.add(8)
+ wr, ok := ws.Pop()
+ if !ok {
+ t.Fatalf("Pop(%d)=false, want true", i)
+ }
+ if got, want := wr.DataSize(), 8; got != want {
+ t.Fatalf("Pop(%d)=%d bytes, want %d bytes", i, got, want)
+ }
+ }
+}
+
+func TestPriorityThrottleOutOfOrderWrites(t *testing.T) {
+ ws := NewPriorityWriteScheduler(&PriorityWriteSchedulerConfig{ThrottleOutOfOrderWrites: true})
+ ws.OpenStream(1, OpenStreamOptions{})
+ ws.OpenStream(2, OpenStreamOptions{PusherID: 1})
+
+ sc := &serverConn{maxFrameSize: 4096}
+ st1 := &stream{id: 1, sc: sc}
+ st2 := &stream{id: 2, sc: sc}
+ st1.flow.add(4096)
+ st2.flow.add(4096)
+ ws.Push(FrameWriteRequest{&writeData{2, make([]byte, 4096), false}, st2, nil})
+ ws.AdjustStream(2, PriorityParam{StreamDep: 1})
+
+ // We have enough flow-control bytes to write st2 in a single Pop call.
+ // However, due to out-of-order write throttling, the first call should
+ // only write 1KB.
+ wr, ok := ws.Pop()
+ if !ok {
+ t.Fatalf("Pop(st2.first)=false, want true")
+ }
+ if got, want := wr.StreamID(), uint32(2); got != want {
+ t.Fatalf("Pop(st2.first)=stream %d, want stream %d", got, want)
+ }
+ if got, want := wr.DataSize(), 1024; got != want {
+ t.Fatalf("Pop(st2.first)=%d bytes, want %d bytes", got, want)
+ }
+
+ // Now add data on st1. This should take precedence.
+ ws.Push(FrameWriteRequest{&writeData{1, make([]byte, 4096), false}, st1, nil})
+ wr, ok = ws.Pop()
+ if !ok {
+ t.Fatalf("Pop(st1)=false, want true")
+ }
+ if got, want := wr.StreamID(), uint32(1); got != want {
+ t.Fatalf("Pop(st1)=stream %d, want stream %d", got, want)
+ }
+ if got, want := wr.DataSize(), 4096; got != want {
+ t.Fatalf("Pop(st1)=%d bytes, want %d bytes", got, want)
+ }
+
+ // Should go back to writing 1KB from st2.
+ wr, ok = ws.Pop()
+ if !ok {
+ t.Fatalf("Pop(st2.last)=false, want true")
+ }
+ if got, want := wr.StreamID(), uint32(2); got != want {
+ t.Fatalf("Pop(st2.last)=stream %d, want stream %d", got, want)
+ }
+ if got, want := wr.DataSize(), 1024; got != want {
+ t.Fatalf("Pop(st2.last)=%d bytes, want %d bytes", got, want)
+ }
+}
+
+func TestPriorityWeights(t *testing.T) {
+ ws := defaultPriorityWriteScheduler()
+ ws.OpenStream(1, OpenStreamOptions{})
+ ws.OpenStream(2, OpenStreamOptions{})
+
+ sc := &serverConn{maxFrameSize: 8}
+ st1 := &stream{id: 1, sc: sc}
+ st2 := &stream{id: 2, sc: sc}
+ st1.flow.add(40)
+ st2.flow.add(40)
+
+ ws.Push(FrameWriteRequest{&writeData{1, make([]byte, 40), false}, st1, nil})
+ ws.Push(FrameWriteRequest{&writeData{2, make([]byte, 40), false}, st2, nil})
+ ws.AdjustStream(1, PriorityParam{StreamDep: 0, Weight: 34})
+ ws.AdjustStream(2, PriorityParam{StreamDep: 0, Weight: 9})
+
+ // st1 gets 3.5x the bandwidth of st2 (3.5 = (34+1)/(9+1)).
+ // The maximum frame size is 8 bytes. The write sequence should be:
+ // st1, total bytes so far is (st1=8, st=0)
+ // st2, total bytes so far is (st1=8, st=8)
+ // st1, total bytes so far is (st1=16, st=8)
+ // st1, total bytes so far is (st1=24, st=8) // 3x bandwidth
+ // st1, total bytes so far is (st1=32, st=8) // 4x bandwidth
+ // st2, total bytes so far is (st1=32, st=16) // 2x bandwidth
+ // st1, total bytes so far is (st1=40, st=16)
+ // st2, total bytes so far is (st1=40, st=24)
+ // st2, total bytes so far is (st1=40, st=32)
+ // st2, total bytes so far is (st1=40, st=40)
+ if err := checkPopAll(ws, []uint32{1, 2, 1, 1, 1, 2, 1, 2, 2, 2}); err != nil {
+ t.Error(err)
+ }
+}
+
+func TestPriorityRstStreamOnNonOpenStreams(t *testing.T) {
+ ws := NewPriorityWriteScheduler(&PriorityWriteSchedulerConfig{
+ MaxClosedNodesInTree: 0,
+ MaxIdleNodesInTree: 0,
+ })
+ ws.OpenStream(1, OpenStreamOptions{})
+ ws.CloseStream(1)
+ ws.Push(FrameWriteRequest{write: streamError(1, ErrCodeProtocol)})
+ ws.Push(FrameWriteRequest{write: streamError(2, ErrCodeProtocol)})
+
+ if err := checkPopAll(ws, []uint32{1, 2}); err != nil {
+ t.Error(err)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/writesched_random.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/writesched_random.go
new file mode 100644
index 000000000..36d7919f1
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/writesched_random.go
@@ -0,0 +1,72 @@
+// Copyright 2014 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 http2
+
+import "math"
+
+// NewRandomWriteScheduler constructs a WriteScheduler that ignores HTTP/2
+// priorities. Control frames like SETTINGS and PING are written before DATA
+// frames, but if no control frames are queued and multiple streams have queued
+// HEADERS or DATA frames, Pop selects a ready stream arbitrarily.
+func NewRandomWriteScheduler() WriteScheduler {
+ return &randomWriteScheduler{sq: make(map[uint32]*writeQueue)}
+}
+
+type randomWriteScheduler struct {
+ // zero are frames not associated with a specific stream.
+ zero writeQueue
+
+ // sq contains the stream-specific queues, keyed by stream ID.
+ // When a stream is idle or closed, it's deleted from the map.
+ sq map[uint32]*writeQueue
+
+ // pool of empty queues for reuse.
+ queuePool writeQueuePool
+}
+
+func (ws *randomWriteScheduler) OpenStream(streamID uint32, options OpenStreamOptions) {
+ // no-op: idle streams are not tracked
+}
+
+func (ws *randomWriteScheduler) CloseStream(streamID uint32) {
+ q, ok := ws.sq[streamID]
+ if !ok {
+ return
+ }
+ delete(ws.sq, streamID)
+ ws.queuePool.put(q)
+}
+
+func (ws *randomWriteScheduler) AdjustStream(streamID uint32, priority PriorityParam) {
+ // no-op: priorities are ignored
+}
+
+func (ws *randomWriteScheduler) Push(wr FrameWriteRequest) {
+ id := wr.StreamID()
+ if id == 0 {
+ ws.zero.push(wr)
+ return
+ }
+ q, ok := ws.sq[id]
+ if !ok {
+ q = ws.queuePool.get()
+ ws.sq[id] = q
+ }
+ q.push(wr)
+}
+
+func (ws *randomWriteScheduler) Pop() (FrameWriteRequest, bool) {
+ // Control frames first.
+ if !ws.zero.empty() {
+ return ws.zero.shift(), true
+ }
+ // Iterate over all non-idle streams until finding one that can be consumed.
+ for _, q := range ws.sq {
+ if wr, ok := q.consume(math.MaxInt32); ok {
+ return wr, true
+ }
+ }
+ return FrameWriteRequest{}, false
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/writesched_random_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/writesched_random_test.go
new file mode 100644
index 000000000..3bf4aa36a
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/writesched_random_test.go
@@ -0,0 +1,44 @@
+// 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.
+
+package http2
+
+import "testing"
+
+func TestRandomScheduler(t *testing.T) {
+ ws := NewRandomWriteScheduler()
+ ws.Push(makeWriteHeadersRequest(3))
+ ws.Push(makeWriteHeadersRequest(4))
+ ws.Push(makeWriteHeadersRequest(1))
+ ws.Push(makeWriteHeadersRequest(2))
+ ws.Push(makeWriteNonStreamRequest())
+ ws.Push(makeWriteNonStreamRequest())
+
+ // Pop all frames. Should get the non-stream requests first,
+ // followed by the stream requests in any order.
+ var order []FrameWriteRequest
+ for {
+ wr, ok := ws.Pop()
+ if !ok {
+ break
+ }
+ order = append(order, wr)
+ }
+ t.Logf("got frames: %v", order)
+ if len(order) != 6 {
+ t.Fatalf("got %d frames, expected 6", len(order))
+ }
+ if order[0].StreamID() != 0 || order[1].StreamID() != 0 {
+ t.Fatal("expected non-stream frames first", order[0], order[1])
+ }
+ got := make(map[uint32]bool)
+ for _, wr := range order[2:] {
+ got[wr.StreamID()] = true
+ }
+ for id := uint32(1); id <= 4; id++ {
+ if !got[id] {
+ t.Errorf("frame not found for stream %d", id)
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/writesched_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/writesched_test.go
new file mode 100644
index 000000000..0807056bc
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/writesched_test.go
@@ -0,0 +1,125 @@
+// 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.
+
+package http2
+
+import (
+ "fmt"
+ "math"
+ "reflect"
+ "testing"
+)
+
+func makeWriteNonStreamRequest() FrameWriteRequest {
+ return FrameWriteRequest{writeSettingsAck{}, nil, nil}
+}
+
+func makeWriteHeadersRequest(streamID uint32) FrameWriteRequest {
+ st := &stream{id: streamID}
+ return FrameWriteRequest{&writeResHeaders{streamID: streamID, httpResCode: 200}, st, nil}
+}
+
+func checkConsume(wr FrameWriteRequest, nbytes int32, want []FrameWriteRequest) error {
+ consumed, rest, n := wr.Consume(nbytes)
+ var wantConsumed, wantRest FrameWriteRequest
+ switch len(want) {
+ case 0:
+ case 1:
+ wantConsumed = want[0]
+ case 2:
+ wantConsumed = want[0]
+ wantRest = want[1]
+ }
+ if !reflect.DeepEqual(consumed, wantConsumed) || !reflect.DeepEqual(rest, wantRest) || n != len(want) {
+ return fmt.Errorf("got %v, %v, %v\nwant %v, %v, %v", consumed, rest, n, wantConsumed, wantRest, len(want))
+ }
+ return nil
+}
+
+func TestFrameWriteRequestNonData(t *testing.T) {
+ wr := makeWriteNonStreamRequest()
+ if got, want := wr.DataSize(), 0; got != want {
+ t.Errorf("DataSize: got %v, want %v", got, want)
+ }
+
+ // Non-DATA frames are always consumed whole.
+ if err := checkConsume(wr, 0, []FrameWriteRequest{wr}); err != nil {
+ t.Errorf("Consume:\n%v", err)
+ }
+}
+
+func TestFrameWriteRequestData(t *testing.T) {
+ st := &stream{
+ id: 1,
+ sc: &serverConn{maxFrameSize: 16},
+ }
+ const size = 32
+ wr := FrameWriteRequest{&writeData{st.id, make([]byte, size), true}, st, make(chan error)}
+ if got, want := wr.DataSize(), size; got != want {
+ t.Errorf("DataSize: got %v, want %v", got, want)
+ }
+
+ // No flow-control bytes available: cannot consume anything.
+ if err := checkConsume(wr, math.MaxInt32, []FrameWriteRequest{}); err != nil {
+ t.Errorf("Consume(limited by flow control):\n%v", err)
+ }
+
+ // Add enough flow-control bytes to consume the entire frame,
+ // but we're now restricted by st.sc.maxFrameSize.
+ st.flow.add(size)
+ want := []FrameWriteRequest{
+ {
+ write: &writeData{st.id, make([]byte, st.sc.maxFrameSize), false},
+ stream: st,
+ done: nil,
+ },
+ {
+ write: &writeData{st.id, make([]byte, size-st.sc.maxFrameSize), true},
+ stream: st,
+ done: wr.done,
+ },
+ }
+ if err := checkConsume(wr, math.MaxInt32, want); err != nil {
+ t.Errorf("Consume(limited by maxFrameSize):\n%v", err)
+ }
+ rest := want[1]
+
+ // Consume 8 bytes from the remaining frame.
+ want = []FrameWriteRequest{
+ {
+ write: &writeData{st.id, make([]byte, 8), false},
+ stream: st,
+ done: nil,
+ },
+ {
+ write: &writeData{st.id, make([]byte, size-st.sc.maxFrameSize-8), true},
+ stream: st,
+ done: wr.done,
+ },
+ }
+ if err := checkConsume(rest, 8, want); err != nil {
+ t.Errorf("Consume(8):\n%v", err)
+ }
+ rest = want[1]
+
+ // Consume all remaining bytes.
+ want = []FrameWriteRequest{
+ {
+ write: &writeData{st.id, make([]byte, size-st.sc.maxFrameSize-8), true},
+ stream: st,
+ done: wr.done,
+ },
+ }
+ if err := checkConsume(rest, math.MaxInt32, want); err != nil {
+ t.Errorf("Consume(remainder):\n%v", err)
+ }
+}
+
+func TestFrameWriteRequest_StreamID(t *testing.T) {
+ const streamID = 123
+ wr := FrameWriteRequest{write: streamError(streamID, ErrCodeNo)}
+ if got := wr.StreamID(); got != streamID {
+ t.Errorf("FrameWriteRequest(StreamError) = %v; want %v", got, streamID)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/z_spec_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/z_spec_test.go
new file mode 100644
index 000000000..610b2cdbc
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/http2/z_spec_test.go
@@ -0,0 +1,356 @@
+// Copyright 2014 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 http2
+
+import (
+ "bytes"
+ "encoding/xml"
+ "flag"
+ "fmt"
+ "io"
+ "os"
+ "reflect"
+ "regexp"
+ "sort"
+ "strconv"
+ "strings"
+ "sync"
+ "testing"
+)
+
+var coverSpec = flag.Bool("coverspec", false, "Run spec coverage tests")
+
+// The global map of sentence coverage for the http2 spec.
+var defaultSpecCoverage specCoverage
+
+var loadSpecOnce sync.Once
+
+func loadSpec() {
+ if f, err := os.Open("testdata/draft-ietf-httpbis-http2.xml"); err != nil {
+ panic(err)
+ } else {
+ defaultSpecCoverage = readSpecCov(f)
+ f.Close()
+ }
+}
+
+// covers marks all sentences for section sec in defaultSpecCoverage. Sentences not
+// "covered" will be included in report outputted by TestSpecCoverage.
+func covers(sec, sentences string) {
+ loadSpecOnce.Do(loadSpec)
+ defaultSpecCoverage.cover(sec, sentences)
+}
+
+type specPart struct {
+ section string
+ sentence string
+}
+
+func (ss specPart) Less(oo specPart) bool {
+ atoi := func(s string) int {
+ n, err := strconv.Atoi(s)
+ if err != nil {
+ panic(err)
+ }
+ return n
+ }
+ a := strings.Split(ss.section, ".")
+ b := strings.Split(oo.section, ".")
+ for len(a) > 0 {
+ if len(b) == 0 {
+ return false
+ }
+ x, y := atoi(a[0]), atoi(b[0])
+ if x == y {
+ a, b = a[1:], b[1:]
+ continue
+ }
+ return x < y
+ }
+ if len(b) > 0 {
+ return true
+ }
+ return false
+}
+
+type bySpecSection []specPart
+
+func (a bySpecSection) Len() int { return len(a) }
+func (a bySpecSection) Less(i, j int) bool { return a[i].Less(a[j]) }
+func (a bySpecSection) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+
+type specCoverage struct {
+ coverage map[specPart]bool
+ d *xml.Decoder
+}
+
+func joinSection(sec []int) string {
+ s := fmt.Sprintf("%d", sec[0])
+ for _, n := range sec[1:] {
+ s = fmt.Sprintf("%s.%d", s, n)
+ }
+ return s
+}
+
+func (sc specCoverage) readSection(sec []int) {
+ var (
+ buf = new(bytes.Buffer)
+ sub = 0
+ )
+ for {
+ tk, err := sc.d.Token()
+ if err != nil {
+ if err == io.EOF {
+ return
+ }
+ panic(err)
+ }
+ switch v := tk.(type) {
+ case xml.StartElement:
+ if skipElement(v) {
+ if err := sc.d.Skip(); err != nil {
+ panic(err)
+ }
+ if v.Name.Local == "section" {
+ sub++
+ }
+ break
+ }
+ switch v.Name.Local {
+ case "section":
+ sub++
+ sc.readSection(append(sec, sub))
+ case "xref":
+ buf.Write(sc.readXRef(v))
+ }
+ case xml.CharData:
+ if len(sec) == 0 {
+ break
+ }
+ buf.Write(v)
+ case xml.EndElement:
+ if v.Name.Local == "section" {
+ sc.addSentences(joinSection(sec), buf.String())
+ return
+ }
+ }
+ }
+}
+
+func (sc specCoverage) readXRef(se xml.StartElement) []byte {
+ var b []byte
+ for {
+ tk, err := sc.d.Token()
+ if err != nil {
+ panic(err)
+ }
+ switch v := tk.(type) {
+ case xml.CharData:
+ if b != nil {
+ panic("unexpected CharData")
+ }
+ b = []byte(string(v))
+ case xml.EndElement:
+ if v.Name.Local != "xref" {
+ panic("expected </xref>")
+ }
+ if b != nil {
+ return b
+ }
+ sig := attrSig(se)
+ switch sig {
+ case "target":
+ return []byte(fmt.Sprintf("[%s]", attrValue(se, "target")))
+ case "fmt-of,rel,target", "fmt-,,rel,target":
+ return []byte(fmt.Sprintf("[%s, %s]", attrValue(se, "target"), attrValue(se, "rel")))
+ case "fmt-of,sec,target", "fmt-,,sec,target":
+ return []byte(fmt.Sprintf("[section %s of %s]", attrValue(se, "sec"), attrValue(se, "target")))
+ case "fmt-of,rel,sec,target":
+ return []byte(fmt.Sprintf("[section %s of %s, %s]", attrValue(se, "sec"), attrValue(se, "target"), attrValue(se, "rel")))
+ default:
+ panic(fmt.Sprintf("unknown attribute signature %q in %#v", sig, fmt.Sprintf("%#v", se)))
+ }
+ default:
+ panic(fmt.Sprintf("unexpected tag %q", v))
+ }
+ }
+}
+
+var skipAnchor = map[string]bool{
+ "intro": true,
+ "Overview": true,
+}
+
+var skipTitle = map[string]bool{
+ "Acknowledgements": true,
+ "Change Log": true,
+ "Document Organization": true,
+ "Conventions and Terminology": true,
+}
+
+func skipElement(s xml.StartElement) bool {
+ switch s.Name.Local {
+ case "artwork":
+ return true
+ case "section":
+ for _, attr := range s.Attr {
+ switch attr.Name.Local {
+ case "anchor":
+ if skipAnchor[attr.Value] || strings.HasPrefix(attr.Value, "changes.since.") {
+ return true
+ }
+ case "title":
+ if skipTitle[attr.Value] {
+ return true
+ }
+ }
+ }
+ }
+ return false
+}
+
+func readSpecCov(r io.Reader) specCoverage {
+ sc := specCoverage{
+ coverage: map[specPart]bool{},
+ d: xml.NewDecoder(r)}
+ sc.readSection(nil)
+ return sc
+}
+
+func (sc specCoverage) addSentences(sec string, sentence string) {
+ for _, s := range parseSentences(sentence) {
+ sc.coverage[specPart{sec, s}] = false
+ }
+}
+
+func (sc specCoverage) cover(sec string, sentence string) {
+ for _, s := range parseSentences(sentence) {
+ p := specPart{sec, s}
+ if _, ok := sc.coverage[p]; !ok {
+ panic(fmt.Sprintf("Not found in spec: %q, %q", sec, s))
+ }
+ sc.coverage[specPart{sec, s}] = true
+ }
+
+}
+
+var whitespaceRx = regexp.MustCompile(`\s+`)
+
+func parseSentences(sens string) []string {
+ sens = strings.TrimSpace(sens)
+ if sens == "" {
+ return nil
+ }
+ ss := strings.Split(whitespaceRx.ReplaceAllString(sens, " "), ". ")
+ for i, s := range ss {
+ s = strings.TrimSpace(s)
+ if !strings.HasSuffix(s, ".") {
+ s += "."
+ }
+ ss[i] = s
+ }
+ return ss
+}
+
+func TestSpecParseSentences(t *testing.T) {
+ tests := []struct {
+ ss string
+ want []string
+ }{
+ {"Sentence 1. Sentence 2.",
+ []string{
+ "Sentence 1.",
+ "Sentence 2.",
+ }},
+ {"Sentence 1. \nSentence 2.\tSentence 3.",
+ []string{
+ "Sentence 1.",
+ "Sentence 2.",
+ "Sentence 3.",
+ }},
+ }
+
+ for i, tt := range tests {
+ got := parseSentences(tt.ss)
+ if !reflect.DeepEqual(got, tt.want) {
+ t.Errorf("%d: got = %q, want %q", i, got, tt.want)
+ }
+ }
+}
+
+func TestSpecCoverage(t *testing.T) {
+ if !*coverSpec {
+ t.Skip()
+ }
+
+ loadSpecOnce.Do(loadSpec)
+
+ var (
+ list []specPart
+ cv = defaultSpecCoverage.coverage
+ total = len(cv)
+ complete = 0
+ )
+
+ for sp, touched := range defaultSpecCoverage.coverage {
+ if touched {
+ complete++
+ } else {
+ list = append(list, sp)
+ }
+ }
+ sort.Stable(bySpecSection(list))
+
+ if testing.Short() && len(list) > 5 {
+ list = list[:5]
+ }
+
+ for _, p := range list {
+ t.Errorf("\tSECTION %s: %s", p.section, p.sentence)
+ }
+
+ t.Logf("%d/%d (%d%%) sentences covered", complete, total, (complete/total)*100)
+}
+
+func attrSig(se xml.StartElement) string {
+ var names []string
+ for _, attr := range se.Attr {
+ if attr.Name.Local == "fmt" {
+ names = append(names, "fmt-"+attr.Value)
+ } else {
+ names = append(names, attr.Name.Local)
+ }
+ }
+ sort.Strings(names)
+ return strings.Join(names, ",")
+}
+
+func attrValue(se xml.StartElement, attr string) string {
+ for _, a := range se.Attr {
+ if a.Name.Local == attr {
+ return a.Value
+ }
+ }
+ panic("unknown attribute " + attr)
+}
+
+func TestSpecPartLess(t *testing.T) {
+ tests := []struct {
+ sec1, sec2 string
+ want bool
+ }{
+ {"6.2.1", "6.2", false},
+ {"6.2", "6.2.1", true},
+ {"6.10", "6.10.1", true},
+ {"6.10", "6.1.1", false}, // 10, not 1
+ {"6.1", "6.1", false}, // equal, so not less
+ }
+ for _, tt := range tests {
+ got := (specPart{tt.sec1, "foo"}).Less(specPart{tt.sec2, "foo"})
+ if got != tt.want {
+ t.Errorf("Less(%q, %q) = %v; want %v", tt.sec1, tt.sec2, got, tt.want)
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/dstunreach.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/dstunreach.go
new file mode 100644
index 000000000..75db991df
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/dstunreach.go
@@ -0,0 +1,41 @@
+// Copyright 2014 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 icmp
+
+// A DstUnreach represents an ICMP destination unreachable message
+// body.
+type DstUnreach struct {
+ Data []byte // data, known as original datagram field
+ Extensions []Extension // extensions
+}
+
+// Len implements the Len method of MessageBody interface.
+func (p *DstUnreach) Len(proto int) int {
+ if p == nil {
+ return 0
+ }
+ l, _ := multipartMessageBodyDataLen(proto, p.Data, p.Extensions)
+ return 4 + l
+}
+
+// Marshal implements the Marshal method of MessageBody interface.
+func (p *DstUnreach) Marshal(proto int) ([]byte, error) {
+ return marshalMultipartMessageBody(proto, p.Data, p.Extensions)
+}
+
+// parseDstUnreach parses b as an ICMP destination unreachable message
+// body.
+func parseDstUnreach(proto int, b []byte) (MessageBody, error) {
+ if len(b) < 4 {
+ return nil, errMessageTooShort
+ }
+ p := &DstUnreach{}
+ var err error
+ p.Data, p.Extensions, err = parseMultipartMessageBody(proto, b)
+ if err != nil {
+ return nil, err
+ }
+ return p, nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/echo.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/echo.go
new file mode 100644
index 000000000..e6f15efd7
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/echo.go
@@ -0,0 +1,45 @@
+// Copyright 2012 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 icmp
+
+import "encoding/binary"
+
+// An Echo represents an ICMP echo request or reply message body.
+type Echo struct {
+ ID int // identifier
+ Seq int // sequence number
+ Data []byte // data
+}
+
+// Len implements the Len method of MessageBody interface.
+func (p *Echo) Len(proto int) int {
+ if p == nil {
+ return 0
+ }
+ return 4 + len(p.Data)
+}
+
+// Marshal implements the Marshal method of MessageBody interface.
+func (p *Echo) Marshal(proto int) ([]byte, error) {
+ b := make([]byte, 4+len(p.Data))
+ binary.BigEndian.PutUint16(b[:2], uint16(p.ID))
+ binary.BigEndian.PutUint16(b[2:4], uint16(p.Seq))
+ copy(b[4:], p.Data)
+ return b, nil
+}
+
+// parseEcho parses b as an ICMP echo request or reply message body.
+func parseEcho(proto int, b []byte) (MessageBody, error) {
+ bodyLen := len(b)
+ if bodyLen < 4 {
+ return nil, errMessageTooShort
+ }
+ p := &Echo{ID: int(binary.BigEndian.Uint16(b[:2])), Seq: int(binary.BigEndian.Uint16(b[2:4]))}
+ if bodyLen > 4 {
+ p.Data = make([]byte, bodyLen-4)
+ copy(p.Data, b[4:])
+ }
+ return p, nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/endpoint.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/endpoint.go
new file mode 100644
index 000000000..a68bfb010
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/endpoint.go
@@ -0,0 +1,113 @@
+// Copyright 2014 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 icmp
+
+import (
+ "net"
+ "runtime"
+ "syscall"
+ "time"
+
+ "golang.org/x/net/ipv4"
+ "golang.org/x/net/ipv6"
+)
+
+var _ net.PacketConn = &PacketConn{}
+
+// A PacketConn represents a packet network endpoint that uses either
+// ICMPv4 or ICMPv6.
+type PacketConn struct {
+ c net.PacketConn
+ p4 *ipv4.PacketConn
+ p6 *ipv6.PacketConn
+}
+
+func (c *PacketConn) ok() bool { return c != nil && c.c != nil }
+
+// IPv4PacketConn returns the ipv4.PacketConn of c.
+// It returns nil when c is not created as the endpoint for ICMPv4.
+func (c *PacketConn) IPv4PacketConn() *ipv4.PacketConn {
+ if !c.ok() {
+ return nil
+ }
+ return c.p4
+}
+
+// IPv6PacketConn returns the ipv6.PacketConn of c.
+// It returns nil when c is not created as the endpoint for ICMPv6.
+func (c *PacketConn) IPv6PacketConn() *ipv6.PacketConn {
+ if !c.ok() {
+ return nil
+ }
+ return c.p6
+}
+
+// ReadFrom reads an ICMP message from the connection.
+func (c *PacketConn) ReadFrom(b []byte) (int, net.Addr, error) {
+ if !c.ok() {
+ return 0, nil, syscall.EINVAL
+ }
+ // Please be informed that ipv4.NewPacketConn enables
+ // IP_STRIPHDR option by default on Darwin.
+ // See golang.org/issue/9395 for further information.
+ if runtime.GOOS == "darwin" && c.p4 != nil {
+ n, _, peer, err := c.p4.ReadFrom(b)
+ return n, peer, err
+ }
+ return c.c.ReadFrom(b)
+}
+
+// WriteTo writes the ICMP message b to dst.
+// Dst must be net.UDPAddr when c is a non-privileged
+// datagram-oriented ICMP endpoint. Otherwise it must be net.IPAddr.
+func (c *PacketConn) WriteTo(b []byte, dst net.Addr) (int, error) {
+ if !c.ok() {
+ return 0, syscall.EINVAL
+ }
+ return c.c.WriteTo(b, dst)
+}
+
+// Close closes the endpoint.
+func (c *PacketConn) Close() error {
+ if !c.ok() {
+ return syscall.EINVAL
+ }
+ return c.c.Close()
+}
+
+// LocalAddr returns the local network address.
+func (c *PacketConn) LocalAddr() net.Addr {
+ if !c.ok() {
+ return nil
+ }
+ return c.c.LocalAddr()
+}
+
+// SetDeadline sets the read and write deadlines associated with the
+// endpoint.
+func (c *PacketConn) SetDeadline(t time.Time) error {
+ if !c.ok() {
+ return syscall.EINVAL
+ }
+ return c.c.SetDeadline(t)
+}
+
+// SetReadDeadline sets the read deadline associated with the
+// endpoint.
+func (c *PacketConn) SetReadDeadline(t time.Time) error {
+ if !c.ok() {
+ return syscall.EINVAL
+ }
+ return c.c.SetReadDeadline(t)
+}
+
+// SetWriteDeadline sets the write deadline associated with the
+// endpoint.
+func (c *PacketConn) SetWriteDeadline(t time.Time) error {
+ if !c.ok() {
+ return syscall.EINVAL
+ }
+ return c.c.SetWriteDeadline(t)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/example_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/example_test.go
new file mode 100644
index 000000000..1df4ceccd
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/example_test.go
@@ -0,0 +1,63 @@
+// Copyright 2014 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 icmp_test
+
+import (
+ "log"
+ "net"
+ "os"
+ "runtime"
+
+ "golang.org/x/net/icmp"
+ "golang.org/x/net/ipv6"
+)
+
+func ExamplePacketConn_nonPrivilegedPing() {
+ switch runtime.GOOS {
+ case "darwin":
+ case "linux":
+ log.Println("you may need to adjust the net.ipv4.ping_group_range kernel state")
+ default:
+ log.Println("not supported on", runtime.GOOS)
+ return
+ }
+
+ c, err := icmp.ListenPacket("udp6", "fe80::1%en0")
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer c.Close()
+
+ wm := icmp.Message{
+ Type: ipv6.ICMPTypeEchoRequest, Code: 0,
+ Body: &icmp.Echo{
+ ID: os.Getpid() & 0xffff, Seq: 1,
+ Data: []byte("HELLO-R-U-THERE"),
+ },
+ }
+ wb, err := wm.Marshal(nil)
+ if err != nil {
+ log.Fatal(err)
+ }
+ if _, err := c.WriteTo(wb, &net.UDPAddr{IP: net.ParseIP("ff02::1"), Zone: "en0"}); err != nil {
+ log.Fatal(err)
+ }
+
+ rb := make([]byte, 1500)
+ n, peer, err := c.ReadFrom(rb)
+ if err != nil {
+ log.Fatal(err)
+ }
+ rm, err := icmp.ParseMessage(58, rb[:n])
+ if err != nil {
+ log.Fatal(err)
+ }
+ switch rm.Type {
+ case ipv6.ICMPTypeEchoReply:
+ log.Printf("got reflection from %v", peer)
+ default:
+ log.Printf("got %+v; want echo reply", rm)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/extension.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/extension.go
new file mode 100644
index 000000000..402a7514b
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/extension.go
@@ -0,0 +1,89 @@
+// Copyright 2015 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 icmp
+
+import "encoding/binary"
+
+// An Extension represents an ICMP extension.
+type Extension interface {
+ // Len returns the length of ICMP extension.
+ // Proto must be either the ICMPv4 or ICMPv6 protocol number.
+ Len(proto int) int
+
+ // Marshal returns the binary encoding of ICMP extension.
+ // Proto must be either the ICMPv4 or ICMPv6 protocol number.
+ Marshal(proto int) ([]byte, error)
+}
+
+const extensionVersion = 2
+
+func validExtensionHeader(b []byte) bool {
+ v := int(b[0]&0xf0) >> 4
+ s := binary.BigEndian.Uint16(b[2:4])
+ if s != 0 {
+ s = checksum(b)
+ }
+ if v != extensionVersion || s != 0 {
+ return false
+ }
+ return true
+}
+
+// parseExtensions parses b as a list of ICMP extensions.
+// The length attribute l must be the length attribute field in
+// received icmp messages.
+//
+// It will return a list of ICMP extensions and an adjusted length
+// attribute that represents the length of the padded original
+// datagram field. Otherwise, it returns an error.
+func parseExtensions(b []byte, l int) ([]Extension, int, error) {
+ // Still a lot of non-RFC 4884 compliant implementations are
+ // out there. Set the length attribute l to 128 when it looks
+ // inappropriate for backwards compatibility.
+ //
+ // A minimal extension at least requires 8 octets; 4 octets
+ // for an extension header, and 4 octets for a single object
+ // header.
+ //
+ // See RFC 4884 for further information.
+ if 128 > l || l+8 > len(b) {
+ l = 128
+ }
+ if l+8 > len(b) {
+ return nil, -1, errNoExtension
+ }
+ if !validExtensionHeader(b[l:]) {
+ if l == 128 {
+ return nil, -1, errNoExtension
+ }
+ l = 128
+ if !validExtensionHeader(b[l:]) {
+ return nil, -1, errNoExtension
+ }
+ }
+ var exts []Extension
+ for b = b[l+4:]; len(b) >= 4; {
+ ol := int(binary.BigEndian.Uint16(b[:2]))
+ if 4 > ol || ol > len(b) {
+ break
+ }
+ switch b[2] {
+ case classMPLSLabelStack:
+ ext, err := parseMPLSLabelStack(b[:ol])
+ if err != nil {
+ return nil, -1, err
+ }
+ exts = append(exts, ext)
+ case classInterfaceInfo:
+ ext, err := parseInterfaceInfo(b[:ol])
+ if err != nil {
+ return nil, -1, err
+ }
+ exts = append(exts, ext)
+ }
+ b = b[ol:]
+ }
+ return exts, l, nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/extension_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/extension_test.go
new file mode 100644
index 000000000..0b3f7b9e1
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/extension_test.go
@@ -0,0 +1,259 @@
+// Copyright 2015 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 icmp
+
+import (
+ "net"
+ "reflect"
+ "testing"
+
+ "golang.org/x/net/internal/iana"
+)
+
+var marshalAndParseExtensionTests = []struct {
+ proto int
+ hdr []byte
+ obj []byte
+ exts []Extension
+}{
+ // MPLS label stack with no label
+ {
+ proto: iana.ProtocolICMP,
+ hdr: []byte{
+ 0x20, 0x00, 0x00, 0x00,
+ },
+ obj: []byte{
+ 0x00, 0x04, 0x01, 0x01,
+ },
+ exts: []Extension{
+ &MPLSLabelStack{
+ Class: classMPLSLabelStack,
+ Type: typeIncomingMPLSLabelStack,
+ },
+ },
+ },
+ // MPLS label stack with a single label
+ {
+ proto: iana.ProtocolIPv6ICMP,
+ hdr: []byte{
+ 0x20, 0x00, 0x00, 0x00,
+ },
+ obj: []byte{
+ 0x00, 0x08, 0x01, 0x01,
+ 0x03, 0xe8, 0xe9, 0xff,
+ },
+ exts: []Extension{
+ &MPLSLabelStack{
+ Class: classMPLSLabelStack,
+ Type: typeIncomingMPLSLabelStack,
+ Labels: []MPLSLabel{
+ {
+ Label: 16014,
+ TC: 0x4,
+ S: true,
+ TTL: 255,
+ },
+ },
+ },
+ },
+ },
+ // MPLS label stack with multiple labels
+ {
+ proto: iana.ProtocolICMP,
+ hdr: []byte{
+ 0x20, 0x00, 0x00, 0x00,
+ },
+ obj: []byte{
+ 0x00, 0x0c, 0x01, 0x01,
+ 0x03, 0xe8, 0xde, 0xfe,
+ 0x03, 0xe8, 0xe1, 0xff,
+ },
+ exts: []Extension{
+ &MPLSLabelStack{
+ Class: classMPLSLabelStack,
+ Type: typeIncomingMPLSLabelStack,
+ Labels: []MPLSLabel{
+ {
+ Label: 16013,
+ TC: 0x7,
+ S: false,
+ TTL: 254,
+ },
+ {
+ Label: 16014,
+ TC: 0,
+ S: true,
+ TTL: 255,
+ },
+ },
+ },
+ },
+ },
+ // Interface information with no attribute
+ {
+ proto: iana.ProtocolICMP,
+ hdr: []byte{
+ 0x20, 0x00, 0x00, 0x00,
+ },
+ obj: []byte{
+ 0x00, 0x04, 0x02, 0x00,
+ },
+ exts: []Extension{
+ &InterfaceInfo{
+ Class: classInterfaceInfo,
+ },
+ },
+ },
+ // Interface information with ifIndex and name
+ {
+ proto: iana.ProtocolICMP,
+ hdr: []byte{
+ 0x20, 0x00, 0x00, 0x00,
+ },
+ obj: []byte{
+ 0x00, 0x10, 0x02, 0x0a,
+ 0x00, 0x00, 0x00, 0x10,
+ 0x08, byte('e'), byte('n'), byte('1'),
+ byte('0'), byte('1'), 0x00, 0x00,
+ },
+ exts: []Extension{
+ &InterfaceInfo{
+ Class: classInterfaceInfo,
+ Type: 0x0a,
+ Interface: &net.Interface{
+ Index: 16,
+ Name: "en101",
+ },
+ },
+ },
+ },
+ // Interface information with ifIndex, IPAddr, name and MTU
+ {
+ proto: iana.ProtocolIPv6ICMP,
+ hdr: []byte{
+ 0x20, 0x00, 0x00, 0x00,
+ },
+ obj: []byte{
+ 0x00, 0x28, 0x02, 0x0f,
+ 0x00, 0x00, 0x00, 0x0f,
+ 0x00, 0x02, 0x00, 0x00,
+ 0xfe, 0x80, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01,
+ 0x08, byte('e'), byte('n'), byte('1'),
+ byte('0'), byte('1'), 0x00, 0x00,
+ 0x00, 0x00, 0x20, 0x00,
+ },
+ exts: []Extension{
+ &InterfaceInfo{
+ Class: classInterfaceInfo,
+ Type: 0x0f,
+ Interface: &net.Interface{
+ Index: 15,
+ Name: "en101",
+ MTU: 8192,
+ },
+ Addr: &net.IPAddr{
+ IP: net.ParseIP("fe80::1"),
+ Zone: "en101",
+ },
+ },
+ },
+ },
+}
+
+func TestMarshalAndParseExtension(t *testing.T) {
+ for i, tt := range marshalAndParseExtensionTests {
+ for j, ext := range tt.exts {
+ var err error
+ var b []byte
+ switch ext := ext.(type) {
+ case *MPLSLabelStack:
+ b, err = ext.Marshal(tt.proto)
+ if err != nil {
+ t.Errorf("#%v/%v: %v", i, j, err)
+ continue
+ }
+ case *InterfaceInfo:
+ b, err = ext.Marshal(tt.proto)
+ if err != nil {
+ t.Errorf("#%v/%v: %v", i, j, err)
+ continue
+ }
+ }
+ if !reflect.DeepEqual(b, tt.obj) {
+ t.Errorf("#%v/%v: got %#v; want %#v", i, j, b, tt.obj)
+ continue
+ }
+ }
+
+ for j, wire := range []struct {
+ data []byte // original datagram
+ inlattr int // length of padded original datagram, a hint
+ outlattr int // length of padded original datagram, a want
+ err error
+ }{
+ {nil, 0, -1, errNoExtension},
+ {make([]byte, 127), 128, -1, errNoExtension},
+
+ {make([]byte, 128), 127, -1, errNoExtension},
+ {make([]byte, 128), 128, -1, errNoExtension},
+ {make([]byte, 128), 129, -1, errNoExtension},
+
+ {append(make([]byte, 128), append(tt.hdr, tt.obj...)...), 127, 128, nil},
+ {append(make([]byte, 128), append(tt.hdr, tt.obj...)...), 128, 128, nil},
+ {append(make([]byte, 128), append(tt.hdr, tt.obj...)...), 129, 128, nil},
+
+ {append(make([]byte, 512), append(tt.hdr, tt.obj...)...), 511, -1, errNoExtension},
+ {append(make([]byte, 512), append(tt.hdr, tt.obj...)...), 512, 512, nil},
+ {append(make([]byte, 512), append(tt.hdr, tt.obj...)...), 513, -1, errNoExtension},
+ } {
+ exts, l, err := parseExtensions(wire.data, wire.inlattr)
+ if err != wire.err {
+ t.Errorf("#%v/%v: got %v; want %v", i, j, err, wire.err)
+ continue
+ }
+ if wire.err != nil {
+ continue
+ }
+ if l != wire.outlattr {
+ t.Errorf("#%v/%v: got %v; want %v", i, j, l, wire.outlattr)
+ }
+ if !reflect.DeepEqual(exts, tt.exts) {
+ for j, ext := range exts {
+ switch ext := ext.(type) {
+ case *MPLSLabelStack:
+ want := tt.exts[j].(*MPLSLabelStack)
+ t.Errorf("#%v/%v: got %#v; want %#v", i, j, ext, want)
+ case *InterfaceInfo:
+ want := tt.exts[j].(*InterfaceInfo)
+ t.Errorf("#%v/%v: got %#v; want %#v", i, j, ext, want)
+ }
+ }
+ continue
+ }
+ }
+ }
+}
+
+var parseInterfaceNameTests = []struct {
+ b []byte
+ error
+}{
+ {[]byte{0, 'e', 'n', '0'}, errInvalidExtension},
+ {[]byte{4, 'e', 'n', '0'}, nil},
+ {[]byte{7, 'e', 'n', '0', 0xff, 0xff, 0xff, 0xff}, errInvalidExtension},
+ {[]byte{8, 'e', 'n', '0', 0xff, 0xff, 0xff}, errMessageTooShort},
+}
+
+func TestParseInterfaceName(t *testing.T) {
+ ifi := InterfaceInfo{Interface: &net.Interface{}}
+ for i, tt := range parseInterfaceNameTests {
+ if _, err := ifi.parseName(tt.b); err != tt.error {
+ t.Errorf("#%d: got %v; want %v", i, err, tt.error)
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/helper_posix.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/helper_posix.go
new file mode 100644
index 000000000..398fd388f
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/helper_posix.go
@@ -0,0 +1,75 @@
+// Copyright 2014 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.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
+
+package icmp
+
+import (
+ "net"
+ "strconv"
+ "syscall"
+)
+
+func sockaddr(family int, address string) (syscall.Sockaddr, error) {
+ switch family {
+ case syscall.AF_INET:
+ a, err := net.ResolveIPAddr("ip4", address)
+ if err != nil {
+ return nil, err
+ }
+ if len(a.IP) == 0 {
+ a.IP = net.IPv4zero
+ }
+ if a.IP = a.IP.To4(); a.IP == nil {
+ return nil, net.InvalidAddrError("non-ipv4 address")
+ }
+ sa := &syscall.SockaddrInet4{}
+ copy(sa.Addr[:], a.IP)
+ return sa, nil
+ case syscall.AF_INET6:
+ a, err := net.ResolveIPAddr("ip6", address)
+ if err != nil {
+ return nil, err
+ }
+ if len(a.IP) == 0 {
+ a.IP = net.IPv6unspecified
+ }
+ if a.IP.Equal(net.IPv4zero) {
+ a.IP = net.IPv6unspecified
+ }
+ if a.IP = a.IP.To16(); a.IP == nil || a.IP.To4() != nil {
+ return nil, net.InvalidAddrError("non-ipv6 address")
+ }
+ sa := &syscall.SockaddrInet6{ZoneId: zoneToUint32(a.Zone)}
+ copy(sa.Addr[:], a.IP)
+ return sa, nil
+ default:
+ return nil, net.InvalidAddrError("unexpected family")
+ }
+}
+
+func zoneToUint32(zone string) uint32 {
+ if zone == "" {
+ return 0
+ }
+ if ifi, err := net.InterfaceByName(zone); err == nil {
+ return uint32(ifi.Index)
+ }
+ n, err := strconv.Atoi(zone)
+ if err != nil {
+ return 0
+ }
+ return uint32(n)
+}
+
+func last(s string, b byte) int {
+ i := len(s)
+ for i--; i >= 0; i-- {
+ if s[i] == b {
+ break
+ }
+ }
+ return i
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/interface.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/interface.go
new file mode 100644
index 000000000..78b5b98bf
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/interface.go
@@ -0,0 +1,236 @@
+// Copyright 2015 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 icmp
+
+import (
+ "encoding/binary"
+ "net"
+ "strings"
+
+ "golang.org/x/net/internal/iana"
+)
+
+const (
+ classInterfaceInfo = 2
+
+ afiIPv4 = 1
+ afiIPv6 = 2
+)
+
+const (
+ attrMTU = 1 << iota
+ attrName
+ attrIPAddr
+ attrIfIndex
+)
+
+// An InterfaceInfo represents interface and next-hop identification.
+type InterfaceInfo struct {
+ Class int // extension object class number
+ Type int // extension object sub-type
+ Interface *net.Interface
+ Addr *net.IPAddr
+}
+
+func (ifi *InterfaceInfo) nameLen() int {
+ if len(ifi.Interface.Name) > 63 {
+ return 64
+ }
+ l := 1 + len(ifi.Interface.Name)
+ return (l + 3) &^ 3
+}
+
+func (ifi *InterfaceInfo) attrsAndLen(proto int) (attrs, l int) {
+ l = 4
+ if ifi.Interface != nil && ifi.Interface.Index > 0 {
+ attrs |= attrIfIndex
+ l += 4
+ if len(ifi.Interface.Name) > 0 {
+ attrs |= attrName
+ l += ifi.nameLen()
+ }
+ if ifi.Interface.MTU > 0 {
+ attrs |= attrMTU
+ l += 4
+ }
+ }
+ if ifi.Addr != nil {
+ switch proto {
+ case iana.ProtocolICMP:
+ if ifi.Addr.IP.To4() != nil {
+ attrs |= attrIPAddr
+ l += 4 + net.IPv4len
+ }
+ case iana.ProtocolIPv6ICMP:
+ if ifi.Addr.IP.To16() != nil && ifi.Addr.IP.To4() == nil {
+ attrs |= attrIPAddr
+ l += 4 + net.IPv6len
+ }
+ }
+ }
+ return
+}
+
+// Len implements the Len method of Extension interface.
+func (ifi *InterfaceInfo) Len(proto int) int {
+ _, l := ifi.attrsAndLen(proto)
+ return l
+}
+
+// Marshal implements the Marshal method of Extension interface.
+func (ifi *InterfaceInfo) Marshal(proto int) ([]byte, error) {
+ attrs, l := ifi.attrsAndLen(proto)
+ b := make([]byte, l)
+ if err := ifi.marshal(proto, b, attrs, l); err != nil {
+ return nil, err
+ }
+ return b, nil
+}
+
+func (ifi *InterfaceInfo) marshal(proto int, b []byte, attrs, l int) error {
+ binary.BigEndian.PutUint16(b[:2], uint16(l))
+ b[2], b[3] = classInterfaceInfo, byte(ifi.Type)
+ for b = b[4:]; len(b) > 0 && attrs != 0; {
+ switch {
+ case attrs&attrIfIndex != 0:
+ b = ifi.marshalIfIndex(proto, b)
+ attrs &^= attrIfIndex
+ case attrs&attrIPAddr != 0:
+ b = ifi.marshalIPAddr(proto, b)
+ attrs &^= attrIPAddr
+ case attrs&attrName != 0:
+ b = ifi.marshalName(proto, b)
+ attrs &^= attrName
+ case attrs&attrMTU != 0:
+ b = ifi.marshalMTU(proto, b)
+ attrs &^= attrMTU
+ }
+ }
+ return nil
+}
+
+func (ifi *InterfaceInfo) marshalIfIndex(proto int, b []byte) []byte {
+ binary.BigEndian.PutUint32(b[:4], uint32(ifi.Interface.Index))
+ return b[4:]
+}
+
+func (ifi *InterfaceInfo) parseIfIndex(b []byte) ([]byte, error) {
+ if len(b) < 4 {
+ return nil, errMessageTooShort
+ }
+ ifi.Interface.Index = int(binary.BigEndian.Uint32(b[:4]))
+ return b[4:], nil
+}
+
+func (ifi *InterfaceInfo) marshalIPAddr(proto int, b []byte) []byte {
+ switch proto {
+ case iana.ProtocolICMP:
+ binary.BigEndian.PutUint16(b[:2], uint16(afiIPv4))
+ copy(b[4:4+net.IPv4len], ifi.Addr.IP.To4())
+ b = b[4+net.IPv4len:]
+ case iana.ProtocolIPv6ICMP:
+ binary.BigEndian.PutUint16(b[:2], uint16(afiIPv6))
+ copy(b[4:4+net.IPv6len], ifi.Addr.IP.To16())
+ b = b[4+net.IPv6len:]
+ }
+ return b
+}
+
+func (ifi *InterfaceInfo) parseIPAddr(b []byte) ([]byte, error) {
+ if len(b) < 4 {
+ return nil, errMessageTooShort
+ }
+ afi := int(binary.BigEndian.Uint16(b[:2]))
+ b = b[4:]
+ switch afi {
+ case afiIPv4:
+ if len(b) < net.IPv4len {
+ return nil, errMessageTooShort
+ }
+ ifi.Addr.IP = make(net.IP, net.IPv4len)
+ copy(ifi.Addr.IP, b[:net.IPv4len])
+ b = b[net.IPv4len:]
+ case afiIPv6:
+ if len(b) < net.IPv6len {
+ return nil, errMessageTooShort
+ }
+ ifi.Addr.IP = make(net.IP, net.IPv6len)
+ copy(ifi.Addr.IP, b[:net.IPv6len])
+ b = b[net.IPv6len:]
+ }
+ return b, nil
+}
+
+func (ifi *InterfaceInfo) marshalName(proto int, b []byte) []byte {
+ l := byte(ifi.nameLen())
+ b[0] = l
+ copy(b[1:], []byte(ifi.Interface.Name))
+ return b[l:]
+}
+
+func (ifi *InterfaceInfo) parseName(b []byte) ([]byte, error) {
+ if 4 > len(b) || len(b) < int(b[0]) {
+ return nil, errMessageTooShort
+ }
+ l := int(b[0])
+ if l%4 != 0 || 4 > l || l > 64 {
+ return nil, errInvalidExtension
+ }
+ var name [63]byte
+ copy(name[:], b[1:l])
+ ifi.Interface.Name = strings.Trim(string(name[:]), "\000")
+ return b[l:], nil
+}
+
+func (ifi *InterfaceInfo) marshalMTU(proto int, b []byte) []byte {
+ binary.BigEndian.PutUint32(b[:4], uint32(ifi.Interface.MTU))
+ return b[4:]
+}
+
+func (ifi *InterfaceInfo) parseMTU(b []byte) ([]byte, error) {
+ if len(b) < 4 {
+ return nil, errMessageTooShort
+ }
+ ifi.Interface.MTU = int(binary.BigEndian.Uint32(b[:4]))
+ return b[4:], nil
+}
+
+func parseInterfaceInfo(b []byte) (Extension, error) {
+ ifi := &InterfaceInfo{
+ Class: int(b[2]),
+ Type: int(b[3]),
+ }
+ if ifi.Type&(attrIfIndex|attrName|attrMTU) != 0 {
+ ifi.Interface = &net.Interface{}
+ }
+ if ifi.Type&attrIPAddr != 0 {
+ ifi.Addr = &net.IPAddr{}
+ }
+ attrs := ifi.Type & (attrIfIndex | attrIPAddr | attrName | attrMTU)
+ for b = b[4:]; len(b) > 0 && attrs != 0; {
+ var err error
+ switch {
+ case attrs&attrIfIndex != 0:
+ b, err = ifi.parseIfIndex(b)
+ attrs &^= attrIfIndex
+ case attrs&attrIPAddr != 0:
+ b, err = ifi.parseIPAddr(b)
+ attrs &^= attrIPAddr
+ case attrs&attrName != 0:
+ b, err = ifi.parseName(b)
+ attrs &^= attrName
+ case attrs&attrMTU != 0:
+ b, err = ifi.parseMTU(b)
+ attrs &^= attrMTU
+ }
+ if err != nil {
+ return nil, err
+ }
+ }
+ if ifi.Interface != nil && ifi.Interface.Name != "" && ifi.Addr != nil && ifi.Addr.IP.To16() != nil && ifi.Addr.IP.To4() == nil {
+ ifi.Addr.Zone = ifi.Interface.Name
+ }
+ return ifi, nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/ipv4.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/ipv4.go
new file mode 100644
index 000000000..ffc66ed4d
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/ipv4.go
@@ -0,0 +1,61 @@
+// Copyright 2014 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 icmp
+
+import (
+ "encoding/binary"
+ "net"
+ "runtime"
+
+ "golang.org/x/net/internal/socket"
+ "golang.org/x/net/ipv4"
+)
+
+// freebsdVersion is set in sys_freebsd.go.
+// See http://www.freebsd.org/doc/en/books/porters-handbook/freebsd-versions.html.
+var freebsdVersion uint32
+
+// ParseIPv4Header parses b as an IPv4 header of ICMP error message
+// invoking packet, which is contained in ICMP error message.
+func ParseIPv4Header(b []byte) (*ipv4.Header, error) {
+ if len(b) < ipv4.HeaderLen {
+ return nil, errHeaderTooShort
+ }
+ hdrlen := int(b[0]&0x0f) << 2
+ if hdrlen > len(b) {
+ return nil, errBufferTooShort
+ }
+ h := &ipv4.Header{
+ Version: int(b[0] >> 4),
+ Len: hdrlen,
+ TOS: int(b[1]),
+ ID: int(binary.BigEndian.Uint16(b[4:6])),
+ FragOff: int(binary.BigEndian.Uint16(b[6:8])),
+ TTL: int(b[8]),
+ Protocol: int(b[9]),
+ Checksum: int(binary.BigEndian.Uint16(b[10:12])),
+ Src: net.IPv4(b[12], b[13], b[14], b[15]),
+ Dst: net.IPv4(b[16], b[17], b[18], b[19]),
+ }
+ switch runtime.GOOS {
+ case "darwin":
+ h.TotalLen = int(socket.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]))
+ }
+ default:
+ h.TotalLen = int(binary.BigEndian.Uint16(b[2:4]))
+ }
+ h.Flags = ipv4.HeaderFlags(h.FragOff&0xe000) >> 13
+ h.FragOff = h.FragOff & 0x1fff
+ if hdrlen-ipv4.HeaderLen > 0 {
+ h.Options = make([]byte, hdrlen-ipv4.HeaderLen)
+ copy(h.Options, b[ipv4.HeaderLen:])
+ }
+ return h, nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/ipv4_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/ipv4_test.go
new file mode 100644
index 000000000..058953f43
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/ipv4_test.go
@@ -0,0 +1,83 @@
+// Copyright 2014 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 icmp
+
+import (
+ "encoding/binary"
+ "net"
+ "reflect"
+ "runtime"
+ "testing"
+
+ "golang.org/x/net/internal/socket"
+ "golang.org/x/net/ipv4"
+)
+
+type ipv4HeaderTest struct {
+ wireHeaderFromKernel [ipv4.HeaderLen]byte
+ wireHeaderFromTradBSDKernel [ipv4.HeaderLen]byte
+ Header *ipv4.Header
+}
+
+var ipv4HeaderLittleEndianTest = ipv4HeaderTest{
+ // TODO(mikio): Add platform dependent wire header formats when
+ // we support new platforms.
+ wireHeaderFromKernel: [ipv4.HeaderLen]byte{
+ 0x45, 0x01, 0xbe, 0xef,
+ 0xca, 0xfe, 0x45, 0xdc,
+ 0xff, 0x01, 0xde, 0xad,
+ 172, 16, 254, 254,
+ 192, 168, 0, 1,
+ },
+ wireHeaderFromTradBSDKernel: [ipv4.HeaderLen]byte{
+ 0x45, 0x01, 0xef, 0xbe,
+ 0xca, 0xfe, 0x45, 0xdc,
+ 0xff, 0x01, 0xde, 0xad,
+ 172, 16, 254, 254,
+ 192, 168, 0, 1,
+ },
+ Header: &ipv4.Header{
+ Version: ipv4.Version,
+ Len: ipv4.HeaderLen,
+ TOS: 1,
+ TotalLen: 0xbeef,
+ ID: 0xcafe,
+ Flags: ipv4.DontFragment,
+ FragOff: 1500,
+ TTL: 255,
+ Protocol: 1,
+ Checksum: 0xdead,
+ Src: net.IPv4(172, 16, 254, 254),
+ Dst: net.IPv4(192, 168, 0, 1),
+ },
+}
+
+func TestParseIPv4Header(t *testing.T) {
+ tt := &ipv4HeaderLittleEndianTest
+ if socket.NativeEndian != binary.LittleEndian {
+ t.Skip("no test for non-little endian machine yet")
+ }
+
+ var wh []byte
+ switch runtime.GOOS {
+ case "darwin":
+ wh = tt.wireHeaderFromTradBSDKernel[:]
+ case "freebsd":
+ if freebsdVersion >= 1000000 {
+ wh = tt.wireHeaderFromKernel[:]
+ } else {
+ wh = tt.wireHeaderFromTradBSDKernel[:]
+ }
+ default:
+ wh = tt.wireHeaderFromKernel[:]
+ }
+ h, err := ParseIPv4Header(wh)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !reflect.DeepEqual(h, tt.Header) {
+ t.Fatalf("got %#v; want %#v", h, tt.Header)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/ipv6.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/ipv6.go
new file mode 100644
index 000000000..2e8cfeb13
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/ipv6.go
@@ -0,0 +1,23 @@
+// Copyright 2013 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 icmp
+
+import (
+ "net"
+
+ "golang.org/x/net/internal/iana"
+)
+
+const ipv6PseudoHeaderLen = 2*net.IPv6len + 8
+
+// IPv6PseudoHeader returns an IPv6 pseudo header for checksum
+// calculation.
+func IPv6PseudoHeader(src, dst net.IP) []byte {
+ b := make([]byte, ipv6PseudoHeaderLen)
+ copy(b, src.To16())
+ copy(b[net.IPv6len:], dst.To16())
+ b[len(b)-1] = byte(iana.ProtocolIPv6ICMP)
+ return b
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/listen_posix.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/listen_posix.go
new file mode 100644
index 000000000..7fac4f965
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/listen_posix.go
@@ -0,0 +1,100 @@
+// Copyright 2014 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.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
+
+package icmp
+
+import (
+ "net"
+ "os"
+ "runtime"
+ "syscall"
+
+ "golang.org/x/net/internal/iana"
+ "golang.org/x/net/ipv4"
+ "golang.org/x/net/ipv6"
+)
+
+const sysIP_STRIPHDR = 0x17 // for now only darwin supports this option
+
+// ListenPacket listens for incoming ICMP packets addressed to
+// address. See net.Dial for the syntax of address.
+//
+// For non-privileged datagram-oriented ICMP endpoints, network must
+// be "udp4" or "udp6". The endpoint allows to read, write a few
+// limited ICMP messages such as echo request and echo reply.
+// Currently only Darwin and Linux support this.
+//
+// Examples:
+// ListenPacket("udp4", "192.168.0.1")
+// ListenPacket("udp4", "0.0.0.0")
+// ListenPacket("udp6", "fe80::1%en0")
+// ListenPacket("udp6", "::")
+//
+// For privileged raw ICMP endpoints, network must be "ip4" or "ip6"
+// followed by a colon and an ICMP protocol number or name.
+//
+// Examples:
+// ListenPacket("ip4:icmp", "192.168.0.1")
+// ListenPacket("ip4:1", "0.0.0.0")
+// ListenPacket("ip6:ipv6-icmp", "fe80::1%en0")
+// ListenPacket("ip6:58", "::")
+func ListenPacket(network, address string) (*PacketConn, error) {
+ var family, proto int
+ switch network {
+ case "udp4":
+ family, proto = syscall.AF_INET, iana.ProtocolICMP
+ case "udp6":
+ family, proto = syscall.AF_INET6, iana.ProtocolIPv6ICMP
+ default:
+ i := last(network, ':')
+ switch network[:i] {
+ case "ip4":
+ proto = iana.ProtocolICMP
+ case "ip6":
+ proto = iana.ProtocolIPv6ICMP
+ }
+ }
+ var cerr error
+ var c net.PacketConn
+ switch family {
+ case syscall.AF_INET, syscall.AF_INET6:
+ s, err := syscall.Socket(family, syscall.SOCK_DGRAM, proto)
+ if err != nil {
+ return nil, os.NewSyscallError("socket", err)
+ }
+ if runtime.GOOS == "darwin" && family == syscall.AF_INET {
+ if err := syscall.SetsockoptInt(s, iana.ProtocolIP, sysIP_STRIPHDR, 1); err != nil {
+ syscall.Close(s)
+ return nil, os.NewSyscallError("setsockopt", err)
+ }
+ }
+ sa, err := sockaddr(family, address)
+ if err != nil {
+ syscall.Close(s)
+ return nil, err
+ }
+ if err := syscall.Bind(s, sa); err != nil {
+ syscall.Close(s)
+ return nil, os.NewSyscallError("bind", err)
+ }
+ f := os.NewFile(uintptr(s), "datagram-oriented icmp")
+ c, cerr = net.FilePacketConn(f)
+ f.Close()
+ default:
+ c, cerr = net.ListenPacket(network, address)
+ }
+ if cerr != nil {
+ return nil, cerr
+ }
+ switch proto {
+ case iana.ProtocolICMP:
+ return &PacketConn{c: c, p4: ipv4.NewPacketConn(c)}, nil
+ case iana.ProtocolIPv6ICMP:
+ return &PacketConn{c: c, p6: ipv6.NewPacketConn(c)}, nil
+ default:
+ return &PacketConn{c: c}, nil
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/listen_stub.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/listen_stub.go
new file mode 100644
index 000000000..668728d17
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/listen_stub.go
@@ -0,0 +1,33 @@
+// Copyright 2014 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.
+
+// +build nacl plan9
+
+package icmp
+
+// ListenPacket listens for incoming ICMP packets addressed to
+// address. See net.Dial for the syntax of address.
+//
+// For non-privileged datagram-oriented ICMP endpoints, network must
+// be "udp4" or "udp6". The endpoint allows to read, write a few
+// limited ICMP messages such as echo request and echo reply.
+// Currently only Darwin and Linux support this.
+//
+// Examples:
+// ListenPacket("udp4", "192.168.0.1")
+// ListenPacket("udp4", "0.0.0.0")
+// ListenPacket("udp6", "fe80::1%en0")
+// ListenPacket("udp6", "::")
+//
+// For privileged raw ICMP endpoints, network must be "ip4" or "ip6"
+// followed by a colon and an ICMP protocol number or name.
+//
+// Examples:
+// ListenPacket("ip4:icmp", "192.168.0.1")
+// ListenPacket("ip4:1", "0.0.0.0")
+// ListenPacket("ip6:ipv6-icmp", "fe80::1%en0")
+// ListenPacket("ip6:58", "::")
+func ListenPacket(network, address string) (*PacketConn, error) {
+ return nil, errOpNoSupport
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/message.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/message.go
new file mode 100644
index 000000000..81140b0df
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/message.go
@@ -0,0 +1,152 @@
+// Copyright 2012 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 icmp provides basic functions for the manipulation of
+// messages used in the Internet Control Message Protocols,
+// ICMPv4 and ICMPv6.
+//
+// ICMPv4 and ICMPv6 are defined in RFC 792 and RFC 4443.
+// Multi-part message support for ICMP is defined in RFC 4884.
+// ICMP extensions for MPLS are defined in RFC 4950.
+// ICMP extensions for interface and next-hop identification are
+// defined in RFC 5837.
+package icmp // import "golang.org/x/net/icmp"
+
+import (
+ "encoding/binary"
+ "errors"
+ "net"
+ "syscall"
+
+ "golang.org/x/net/internal/iana"
+ "golang.org/x/net/ipv4"
+ "golang.org/x/net/ipv6"
+)
+
+// BUG(mikio): This package is not implemented on NaCl and Plan 9.
+
+var (
+ errMessageTooShort = errors.New("message too short")
+ errHeaderTooShort = errors.New("header too short")
+ errBufferTooShort = errors.New("buffer too short")
+ errOpNoSupport = errors.New("operation not supported")
+ errNoExtension = errors.New("no extension")
+ errInvalidExtension = errors.New("invalid extension")
+)
+
+func checksum(b []byte) uint16 {
+ csumcv := len(b) - 1 // checksum coverage
+ s := uint32(0)
+ for i := 0; i < csumcv; i += 2 {
+ s += uint32(b[i+1])<<8 | uint32(b[i])
+ }
+ if csumcv&1 == 0 {
+ s += uint32(b[csumcv])
+ }
+ s = s>>16 + s&0xffff
+ s = s + s>>16
+ return ^uint16(s)
+}
+
+// A Type represents an ICMP message type.
+type Type interface {
+ Protocol() int
+}
+
+// A Message represents an ICMP message.
+type Message struct {
+ Type Type // type, either ipv4.ICMPType or ipv6.ICMPType
+ Code int // code
+ Checksum int // checksum
+ Body MessageBody // body
+}
+
+// Marshal returns the binary encoding of the ICMP message m.
+//
+// For an ICMPv4 message, the returned message always contains the
+// calculated checksum field.
+//
+// For an ICMPv6 message, the returned message contains the calculated
+// checksum field when psh is not nil, otherwise the kernel will
+// compute the checksum field during the message transmission.
+// When psh is not nil, it must be the pseudo header for IPv6.
+func (m *Message) Marshal(psh []byte) ([]byte, error) {
+ var mtype int
+ switch typ := m.Type.(type) {
+ case ipv4.ICMPType:
+ mtype = int(typ)
+ case ipv6.ICMPType:
+ mtype = int(typ)
+ default:
+ return nil, syscall.EINVAL
+ }
+ b := []byte{byte(mtype), byte(m.Code), 0, 0}
+ if m.Type.Protocol() == iana.ProtocolIPv6ICMP && psh != nil {
+ b = append(psh, b...)
+ }
+ if m.Body != nil && m.Body.Len(m.Type.Protocol()) != 0 {
+ mb, err := m.Body.Marshal(m.Type.Protocol())
+ if err != nil {
+ return nil, err
+ }
+ b = append(b, mb...)
+ }
+ if m.Type.Protocol() == iana.ProtocolIPv6ICMP {
+ if psh == nil { // cannot calculate checksum here
+ return b, nil
+ }
+ off, l := 2*net.IPv6len, len(b)-len(psh)
+ binary.BigEndian.PutUint32(b[off:off+4], uint32(l))
+ }
+ s := checksum(b)
+ // Place checksum back in header; using ^= avoids the
+ // assumption the checksum bytes are zero.
+ b[len(psh)+2] ^= byte(s)
+ b[len(psh)+3] ^= byte(s >> 8)
+ return b[len(psh):], nil
+}
+
+var parseFns = map[Type]func(int, []byte) (MessageBody, error){
+ ipv4.ICMPTypeDestinationUnreachable: parseDstUnreach,
+ ipv4.ICMPTypeTimeExceeded: parseTimeExceeded,
+ ipv4.ICMPTypeParameterProblem: parseParamProb,
+
+ ipv4.ICMPTypeEcho: parseEcho,
+ ipv4.ICMPTypeEchoReply: parseEcho,
+
+ ipv6.ICMPTypeDestinationUnreachable: parseDstUnreach,
+ ipv6.ICMPTypePacketTooBig: parsePacketTooBig,
+ ipv6.ICMPTypeTimeExceeded: parseTimeExceeded,
+ ipv6.ICMPTypeParameterProblem: parseParamProb,
+
+ ipv6.ICMPTypeEchoRequest: parseEcho,
+ ipv6.ICMPTypeEchoReply: parseEcho,
+}
+
+// ParseMessage parses b as an ICMP message.
+// Proto must be either the ICMPv4 or ICMPv6 protocol number.
+func ParseMessage(proto int, b []byte) (*Message, error) {
+ if len(b) < 4 {
+ return nil, errMessageTooShort
+ }
+ var err error
+ m := &Message{Code: int(b[1]), Checksum: int(binary.BigEndian.Uint16(b[2:4]))}
+ switch proto {
+ case iana.ProtocolICMP:
+ m.Type = ipv4.ICMPType(b[0])
+ case iana.ProtocolIPv6ICMP:
+ m.Type = ipv6.ICMPType(b[0])
+ default:
+ return nil, syscall.EINVAL
+ }
+ if fn, ok := parseFns[m.Type]; !ok {
+ m.Body, err = parseDefaultMessageBody(proto, b[4:])
+ } else {
+ m.Body, err = fn(proto, b[4:])
+ }
+ if err != nil {
+ return nil, err
+ }
+ return m, nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/message_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/message_test.go
new file mode 100644
index 000000000..5d2605f8d
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/message_test.go
@@ -0,0 +1,134 @@
+// Copyright 2014 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 icmp_test
+
+import (
+ "net"
+ "reflect"
+ "testing"
+
+ "golang.org/x/net/icmp"
+ "golang.org/x/net/internal/iana"
+ "golang.org/x/net/ipv4"
+ "golang.org/x/net/ipv6"
+)
+
+var marshalAndParseMessageForIPv4Tests = []icmp.Message{
+ {
+ Type: ipv4.ICMPTypeDestinationUnreachable, Code: 15,
+ Body: &icmp.DstUnreach{
+ Data: []byte("ERROR-INVOKING-PACKET"),
+ },
+ },
+ {
+ Type: ipv4.ICMPTypeTimeExceeded, Code: 1,
+ Body: &icmp.TimeExceeded{
+ Data: []byte("ERROR-INVOKING-PACKET"),
+ },
+ },
+ {
+ Type: ipv4.ICMPTypeParameterProblem, Code: 2,
+ Body: &icmp.ParamProb{
+ Pointer: 8,
+ Data: []byte("ERROR-INVOKING-PACKET"),
+ },
+ },
+ {
+ Type: ipv4.ICMPTypeEcho, Code: 0,
+ Body: &icmp.Echo{
+ ID: 1, Seq: 2,
+ Data: []byte("HELLO-R-U-THERE"),
+ },
+ },
+ {
+ Type: ipv4.ICMPTypePhoturis,
+ Body: &icmp.DefaultMessageBody{
+ Data: []byte{0x80, 0x40, 0x20, 0x10},
+ },
+ },
+}
+
+func TestMarshalAndParseMessageForIPv4(t *testing.T) {
+ for i, tt := range marshalAndParseMessageForIPv4Tests {
+ b, err := tt.Marshal(nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ m, err := icmp.ParseMessage(iana.ProtocolICMP, b)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if m.Type != tt.Type || m.Code != tt.Code {
+ t.Errorf("#%v: got %v; want %v", i, m, &tt)
+ }
+ if !reflect.DeepEqual(m.Body, tt.Body) {
+ t.Errorf("#%v: got %v; want %v", i, m.Body, tt.Body)
+ }
+ }
+}
+
+var marshalAndParseMessageForIPv6Tests = []icmp.Message{
+ {
+ Type: ipv6.ICMPTypeDestinationUnreachable, Code: 6,
+ Body: &icmp.DstUnreach{
+ Data: []byte("ERROR-INVOKING-PACKET"),
+ },
+ },
+ {
+ Type: ipv6.ICMPTypePacketTooBig, Code: 0,
+ Body: &icmp.PacketTooBig{
+ MTU: 1<<16 - 1,
+ Data: []byte("ERROR-INVOKING-PACKET"),
+ },
+ },
+ {
+ Type: ipv6.ICMPTypeTimeExceeded, Code: 1,
+ Body: &icmp.TimeExceeded{
+ Data: []byte("ERROR-INVOKING-PACKET"),
+ },
+ },
+ {
+ Type: ipv6.ICMPTypeParameterProblem, Code: 2,
+ Body: &icmp.ParamProb{
+ Pointer: 8,
+ Data: []byte("ERROR-INVOKING-PACKET"),
+ },
+ },
+ {
+ Type: ipv6.ICMPTypeEchoRequest, Code: 0,
+ Body: &icmp.Echo{
+ ID: 1, Seq: 2,
+ Data: []byte("HELLO-R-U-THERE"),
+ },
+ },
+ {
+ Type: ipv6.ICMPTypeDuplicateAddressConfirmation,
+ Body: &icmp.DefaultMessageBody{
+ Data: []byte{0x80, 0x40, 0x20, 0x10},
+ },
+ },
+}
+
+func TestMarshalAndParseMessageForIPv6(t *testing.T) {
+ pshicmp := icmp.IPv6PseudoHeader(net.ParseIP("fe80::1"), net.ParseIP("ff02::1"))
+ for i, tt := range marshalAndParseMessageForIPv6Tests {
+ for _, psh := range [][]byte{pshicmp, nil} {
+ b, err := tt.Marshal(psh)
+ if err != nil {
+ t.Fatal(err)
+ }
+ m, err := icmp.ParseMessage(iana.ProtocolIPv6ICMP, b)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if m.Type != tt.Type || m.Code != tt.Code {
+ t.Errorf("#%v: got %v; want %v", i, m, &tt)
+ }
+ if !reflect.DeepEqual(m.Body, tt.Body) {
+ t.Errorf("#%v: got %v; want %v", i, m.Body, tt.Body)
+ }
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/messagebody.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/messagebody.go
new file mode 100644
index 000000000..2463730ae
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/messagebody.go
@@ -0,0 +1,41 @@
+// Copyright 2012 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 icmp
+
+// A MessageBody represents an ICMP message body.
+type MessageBody interface {
+ // Len returns the length of ICMP message body.
+ // Proto must be either the ICMPv4 or ICMPv6 protocol number.
+ Len(proto int) int
+
+ // Marshal returns the binary encoding of ICMP message body.
+ // Proto must be either the ICMPv4 or ICMPv6 protocol number.
+ Marshal(proto int) ([]byte, error)
+}
+
+// A DefaultMessageBody represents the default message body.
+type DefaultMessageBody struct {
+ Data []byte // data
+}
+
+// Len implements the Len method of MessageBody interface.
+func (p *DefaultMessageBody) Len(proto int) int {
+ if p == nil {
+ return 0
+ }
+ return len(p.Data)
+}
+
+// Marshal implements the Marshal method of MessageBody interface.
+func (p *DefaultMessageBody) Marshal(proto int) ([]byte, error) {
+ return p.Data, nil
+}
+
+// parseDefaultMessageBody parses b as an ICMP message body.
+func parseDefaultMessageBody(proto int, b []byte) (MessageBody, error) {
+ p := &DefaultMessageBody{Data: make([]byte, len(b))}
+ copy(p.Data, b)
+ return p, nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/mpls.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/mpls.go
new file mode 100644
index 000000000..c31491748
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/mpls.go
@@ -0,0 +1,77 @@
+// Copyright 2015 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 icmp
+
+import "encoding/binary"
+
+// A MPLSLabel represents a MPLS label stack entry.
+type MPLSLabel struct {
+ Label int // label value
+ TC int // traffic class; formerly experimental use
+ S bool // bottom of stack
+ TTL int // time to live
+}
+
+const (
+ classMPLSLabelStack = 1
+ typeIncomingMPLSLabelStack = 1
+)
+
+// A MPLSLabelStack represents a MPLS label stack.
+type MPLSLabelStack struct {
+ Class int // extension object class number
+ Type int // extension object sub-type
+ Labels []MPLSLabel
+}
+
+// Len implements the Len method of Extension interface.
+func (ls *MPLSLabelStack) Len(proto int) int {
+ return 4 + (4 * len(ls.Labels))
+}
+
+// Marshal implements the Marshal method of Extension interface.
+func (ls *MPLSLabelStack) Marshal(proto int) ([]byte, error) {
+ b := make([]byte, ls.Len(proto))
+ if err := ls.marshal(proto, b); err != nil {
+ return nil, err
+ }
+ return b, nil
+}
+
+func (ls *MPLSLabelStack) marshal(proto int, b []byte) error {
+ l := ls.Len(proto)
+ binary.BigEndian.PutUint16(b[:2], uint16(l))
+ b[2], b[3] = classMPLSLabelStack, typeIncomingMPLSLabelStack
+ off := 4
+ for _, ll := range ls.Labels {
+ b[off], b[off+1], b[off+2] = byte(ll.Label>>12), byte(ll.Label>>4&0xff), byte(ll.Label<<4&0xf0)
+ b[off+2] |= byte(ll.TC << 1 & 0x0e)
+ if ll.S {
+ b[off+2] |= 0x1
+ }
+ b[off+3] = byte(ll.TTL)
+ off += 4
+ }
+ return nil
+}
+
+func parseMPLSLabelStack(b []byte) (Extension, error) {
+ ls := &MPLSLabelStack{
+ Class: int(b[2]),
+ Type: int(b[3]),
+ }
+ for b = b[4:]; len(b) >= 4; b = b[4:] {
+ ll := MPLSLabel{
+ Label: int(b[0])<<12 | int(b[1])<<4 | int(b[2])>>4,
+ TC: int(b[2]&0x0e) >> 1,
+ TTL: int(b[3]),
+ }
+ if b[2]&0x1 != 0 {
+ ll.S = true
+ }
+ ls.Labels = append(ls.Labels, ll)
+ }
+ return ls, nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/multipart.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/multipart.go
new file mode 100644
index 000000000..f27135660
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/multipart.go
@@ -0,0 +1,109 @@
+// Copyright 2015 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 icmp
+
+import "golang.org/x/net/internal/iana"
+
+// multipartMessageBodyDataLen takes b as an original datagram and
+// exts as extensions, and returns a required length for message body
+// and a required length for a padded original datagram in wire
+// format.
+func multipartMessageBodyDataLen(proto int, b []byte, exts []Extension) (bodyLen, dataLen int) {
+ for _, ext := range exts {
+ bodyLen += ext.Len(proto)
+ }
+ if bodyLen > 0 {
+ dataLen = multipartMessageOrigDatagramLen(proto, b)
+ bodyLen += 4 // length of extension header
+ } else {
+ dataLen = len(b)
+ }
+ bodyLen += dataLen
+ return bodyLen, dataLen
+}
+
+// multipartMessageOrigDatagramLen takes b as an original datagram,
+// and returns a required length for a padded orignal datagram in wire
+// format.
+func multipartMessageOrigDatagramLen(proto int, b []byte) int {
+ roundup := func(b []byte, align int) int {
+ // According to RFC 4884, the padded original datagram
+ // field must contain at least 128 octets.
+ if len(b) < 128 {
+ return 128
+ }
+ r := len(b)
+ return (r + align - 1) & ^(align - 1)
+ }
+ switch proto {
+ case iana.ProtocolICMP:
+ return roundup(b, 4)
+ case iana.ProtocolIPv6ICMP:
+ return roundup(b, 8)
+ default:
+ return len(b)
+ }
+}
+
+// marshalMultipartMessageBody takes data as an original datagram and
+// exts as extesnsions, and returns a binary encoding of message body.
+// It can be used for non-multipart message bodies when exts is nil.
+func marshalMultipartMessageBody(proto int, data []byte, exts []Extension) ([]byte, error) {
+ bodyLen, dataLen := multipartMessageBodyDataLen(proto, data, exts)
+ b := make([]byte, 4+bodyLen)
+ copy(b[4:], data)
+ off := dataLen + 4
+ if len(exts) > 0 {
+ b[dataLen+4] = byte(extensionVersion << 4)
+ off += 4 // length of object header
+ for _, ext := range exts {
+ switch ext := ext.(type) {
+ case *MPLSLabelStack:
+ if err := ext.marshal(proto, b[off:]); err != nil {
+ return nil, err
+ }
+ off += ext.Len(proto)
+ case *InterfaceInfo:
+ attrs, l := ext.attrsAndLen(proto)
+ if err := ext.marshal(proto, b[off:], attrs, l); err != nil {
+ return nil, err
+ }
+ off += ext.Len(proto)
+ }
+ }
+ s := checksum(b[dataLen+4:])
+ b[dataLen+4+2] ^= byte(s)
+ b[dataLen+4+3] ^= byte(s >> 8)
+ switch proto {
+ case iana.ProtocolICMP:
+ b[1] = byte(dataLen / 4)
+ case iana.ProtocolIPv6ICMP:
+ b[0] = byte(dataLen / 8)
+ }
+ }
+ return b, nil
+}
+
+// parseMultipartMessageBody parses b as either a non-multipart
+// message body or a multipart message body.
+func parseMultipartMessageBody(proto int, b []byte) ([]byte, []Extension, error) {
+ var l int
+ switch proto {
+ case iana.ProtocolICMP:
+ l = 4 * int(b[1])
+ case iana.ProtocolIPv6ICMP:
+ l = 8 * int(b[0])
+ }
+ if len(b) == 4 {
+ return nil, nil, nil
+ }
+ exts, l, err := parseExtensions(b[4:], l)
+ if err != nil {
+ l = len(b) - 4
+ }
+ data := make([]byte, l)
+ copy(data, b[4:])
+ return data, exts, nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/multipart_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/multipart_test.go
new file mode 100644
index 000000000..966ccb8da
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/multipart_test.go
@@ -0,0 +1,442 @@
+// Copyright 2015 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 icmp_test
+
+import (
+ "fmt"
+ "net"
+ "reflect"
+ "testing"
+
+ "golang.org/x/net/icmp"
+ "golang.org/x/net/internal/iana"
+ "golang.org/x/net/ipv4"
+ "golang.org/x/net/ipv6"
+)
+
+var marshalAndParseMultipartMessageForIPv4Tests = []icmp.Message{
+ {
+ Type: ipv4.ICMPTypeDestinationUnreachable, Code: 15,
+ Body: &icmp.DstUnreach{
+ Data: []byte("ERROR-INVOKING-PACKET"),
+ Extensions: []icmp.Extension{
+ &icmp.MPLSLabelStack{
+ Class: 1,
+ Type: 1,
+ Labels: []icmp.MPLSLabel{
+ {
+ Label: 16014,
+ TC: 0x4,
+ S: true,
+ TTL: 255,
+ },
+ },
+ },
+ &icmp.InterfaceInfo{
+ Class: 2,
+ Type: 0x0f,
+ Interface: &net.Interface{
+ Index: 15,
+ Name: "en101",
+ MTU: 8192,
+ },
+ Addr: &net.IPAddr{
+ IP: net.IPv4(192, 168, 0, 1).To4(),
+ },
+ },
+ },
+ },
+ },
+ {
+ Type: ipv4.ICMPTypeTimeExceeded, Code: 1,
+ Body: &icmp.TimeExceeded{
+ Data: []byte("ERROR-INVOKING-PACKET"),
+ Extensions: []icmp.Extension{
+ &icmp.InterfaceInfo{
+ Class: 2,
+ Type: 0x0f,
+ Interface: &net.Interface{
+ Index: 15,
+ Name: "en101",
+ MTU: 8192,
+ },
+ Addr: &net.IPAddr{
+ IP: net.IPv4(192, 168, 0, 1).To4(),
+ },
+ },
+ &icmp.MPLSLabelStack{
+ Class: 1,
+ Type: 1,
+ Labels: []icmp.MPLSLabel{
+ {
+ Label: 16014,
+ TC: 0x4,
+ S: true,
+ TTL: 255,
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ Type: ipv4.ICMPTypeParameterProblem, Code: 2,
+ Body: &icmp.ParamProb{
+ Pointer: 8,
+ Data: []byte("ERROR-INVOKING-PACKET"),
+ Extensions: []icmp.Extension{
+ &icmp.MPLSLabelStack{
+ Class: 1,
+ Type: 1,
+ Labels: []icmp.MPLSLabel{
+ {
+ Label: 16014,
+ TC: 0x4,
+ S: true,
+ TTL: 255,
+ },
+ },
+ },
+ &icmp.InterfaceInfo{
+ Class: 2,
+ Type: 0x0f,
+ Interface: &net.Interface{
+ Index: 15,
+ Name: "en101",
+ MTU: 8192,
+ },
+ Addr: &net.IPAddr{
+ IP: net.IPv4(192, 168, 0, 1).To4(),
+ },
+ },
+ &icmp.InterfaceInfo{
+ Class: 2,
+ Type: 0x2f,
+ Interface: &net.Interface{
+ Index: 16,
+ Name: "en102",
+ MTU: 8192,
+ },
+ Addr: &net.IPAddr{
+ IP: net.IPv4(192, 168, 0, 2).To4(),
+ },
+ },
+ },
+ },
+ },
+}
+
+func TestMarshalAndParseMultipartMessageForIPv4(t *testing.T) {
+ for i, tt := range marshalAndParseMultipartMessageForIPv4Tests {
+ b, err := tt.Marshal(nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if b[5] != 32 {
+ t.Errorf("#%v: got %v; want 32", i, b[5])
+ }
+ m, err := icmp.ParseMessage(iana.ProtocolICMP, b)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if m.Type != tt.Type || m.Code != tt.Code {
+ t.Errorf("#%v: got %v; want %v", i, m, &tt)
+ }
+ switch m.Type {
+ case ipv4.ICMPTypeDestinationUnreachable:
+ got, want := m.Body.(*icmp.DstUnreach), tt.Body.(*icmp.DstUnreach)
+ if !reflect.DeepEqual(got.Extensions, want.Extensions) {
+ t.Error(dumpExtensions(i, got.Extensions, want.Extensions))
+ }
+ if len(got.Data) != 128 {
+ t.Errorf("#%v: got %v; want 128", i, len(got.Data))
+ }
+ case ipv4.ICMPTypeTimeExceeded:
+ got, want := m.Body.(*icmp.TimeExceeded), tt.Body.(*icmp.TimeExceeded)
+ if !reflect.DeepEqual(got.Extensions, want.Extensions) {
+ t.Error(dumpExtensions(i, got.Extensions, want.Extensions))
+ }
+ if len(got.Data) != 128 {
+ t.Errorf("#%v: got %v; want 128", i, len(got.Data))
+ }
+ case ipv4.ICMPTypeParameterProblem:
+ got, want := m.Body.(*icmp.ParamProb), tt.Body.(*icmp.ParamProb)
+ if !reflect.DeepEqual(got.Extensions, want.Extensions) {
+ t.Error(dumpExtensions(i, got.Extensions, want.Extensions))
+ }
+ if len(got.Data) != 128 {
+ t.Errorf("#%v: got %v; want 128", i, len(got.Data))
+ }
+ }
+ }
+}
+
+var marshalAndParseMultipartMessageForIPv6Tests = []icmp.Message{
+ {
+ Type: ipv6.ICMPTypeDestinationUnreachable, Code: 6,
+ Body: &icmp.DstUnreach{
+ Data: []byte("ERROR-INVOKING-PACKET"),
+ Extensions: []icmp.Extension{
+ &icmp.MPLSLabelStack{
+ Class: 1,
+ Type: 1,
+ Labels: []icmp.MPLSLabel{
+ {
+ Label: 16014,
+ TC: 0x4,
+ S: true,
+ TTL: 255,
+ },
+ },
+ },
+ &icmp.InterfaceInfo{
+ Class: 2,
+ Type: 0x0f,
+ Interface: &net.Interface{
+ Index: 15,
+ Name: "en101",
+ MTU: 8192,
+ },
+ Addr: &net.IPAddr{
+ IP: net.ParseIP("fe80::1"),
+ Zone: "en101",
+ },
+ },
+ },
+ },
+ },
+ {
+ Type: ipv6.ICMPTypeTimeExceeded, Code: 1,
+ Body: &icmp.TimeExceeded{
+ Data: []byte("ERROR-INVOKING-PACKET"),
+ Extensions: []icmp.Extension{
+ &icmp.InterfaceInfo{
+ Class: 2,
+ Type: 0x0f,
+ Interface: &net.Interface{
+ Index: 15,
+ Name: "en101",
+ MTU: 8192,
+ },
+ Addr: &net.IPAddr{
+ IP: net.ParseIP("fe80::1"),
+ Zone: "en101",
+ },
+ },
+ &icmp.MPLSLabelStack{
+ Class: 1,
+ Type: 1,
+ Labels: []icmp.MPLSLabel{
+ {
+ Label: 16014,
+ TC: 0x4,
+ S: true,
+ TTL: 255,
+ },
+ },
+ },
+ &icmp.InterfaceInfo{
+ Class: 2,
+ Type: 0x2f,
+ Interface: &net.Interface{
+ Index: 16,
+ Name: "en102",
+ MTU: 8192,
+ },
+ Addr: &net.IPAddr{
+ IP: net.ParseIP("fe80::1"),
+ Zone: "en102",
+ },
+ },
+ },
+ },
+ },
+}
+
+func TestMarshalAndParseMultipartMessageForIPv6(t *testing.T) {
+ pshicmp := icmp.IPv6PseudoHeader(net.ParseIP("fe80::1"), net.ParseIP("ff02::1"))
+ for i, tt := range marshalAndParseMultipartMessageForIPv6Tests {
+ for _, psh := range [][]byte{pshicmp, nil} {
+ b, err := tt.Marshal(psh)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if b[4] != 16 {
+ t.Errorf("#%v: got %v; want 16", i, b[4])
+ }
+ m, err := icmp.ParseMessage(iana.ProtocolIPv6ICMP, b)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if m.Type != tt.Type || m.Code != tt.Code {
+ t.Errorf("#%v: got %v; want %v", i, m, &tt)
+ }
+ switch m.Type {
+ case ipv6.ICMPTypeDestinationUnreachable:
+ got, want := m.Body.(*icmp.DstUnreach), tt.Body.(*icmp.DstUnreach)
+ if !reflect.DeepEqual(got.Extensions, want.Extensions) {
+ t.Error(dumpExtensions(i, got.Extensions, want.Extensions))
+ }
+ if len(got.Data) != 128 {
+ t.Errorf("#%v: got %v; want 128", i, len(got.Data))
+ }
+ case ipv6.ICMPTypeTimeExceeded:
+ got, want := m.Body.(*icmp.TimeExceeded), tt.Body.(*icmp.TimeExceeded)
+ if !reflect.DeepEqual(got.Extensions, want.Extensions) {
+ t.Error(dumpExtensions(i, got.Extensions, want.Extensions))
+ }
+ if len(got.Data) != 128 {
+ t.Errorf("#%v: got %v; want 128", i, len(got.Data))
+ }
+ }
+ }
+ }
+}
+
+func dumpExtensions(i int, gotExts, wantExts []icmp.Extension) string {
+ var s string
+ for j, got := range gotExts {
+ switch got := got.(type) {
+ case *icmp.MPLSLabelStack:
+ want := wantExts[j].(*icmp.MPLSLabelStack)
+ if !reflect.DeepEqual(got, want) {
+ s += fmt.Sprintf("#%v/%v: got %#v; want %#v\n", i, j, got, want)
+ }
+ case *icmp.InterfaceInfo:
+ want := wantExts[j].(*icmp.InterfaceInfo)
+ if !reflect.DeepEqual(got, want) {
+ s += fmt.Sprintf("#%v/%v: got %#v, %#v, %#v; want %#v, %#v, %#v\n", i, j, got, got.Interface, got.Addr, want, want.Interface, want.Addr)
+ }
+ }
+ }
+ return s[:len(s)-1]
+}
+
+var multipartMessageBodyLenTests = []struct {
+ proto int
+ in icmp.MessageBody
+ out int
+}{
+ {
+ iana.ProtocolICMP,
+ &icmp.DstUnreach{
+ Data: make([]byte, ipv4.HeaderLen),
+ },
+ 4 + ipv4.HeaderLen, // unused and original datagram
+ },
+ {
+ iana.ProtocolICMP,
+ &icmp.TimeExceeded{
+ Data: make([]byte, ipv4.HeaderLen),
+ },
+ 4 + ipv4.HeaderLen, // unused and original datagram
+ },
+ {
+ iana.ProtocolICMP,
+ &icmp.ParamProb{
+ Data: make([]byte, ipv4.HeaderLen),
+ },
+ 4 + ipv4.HeaderLen, // [pointer, unused] and original datagram
+ },
+
+ {
+ iana.ProtocolICMP,
+ &icmp.ParamProb{
+ Data: make([]byte, ipv4.HeaderLen),
+ Extensions: []icmp.Extension{
+ &icmp.MPLSLabelStack{},
+ },
+ },
+ 4 + 4 + 4 + 0 + 128, // [pointer, length, unused], extension header, object header, object payload, original datagram
+ },
+ {
+ iana.ProtocolICMP,
+ &icmp.ParamProb{
+ Data: make([]byte, 128),
+ Extensions: []icmp.Extension{
+ &icmp.MPLSLabelStack{},
+ },
+ },
+ 4 + 4 + 4 + 0 + 128, // [pointer, length, unused], extension header, object header, object payload and original datagram
+ },
+ {
+ iana.ProtocolICMP,
+ &icmp.ParamProb{
+ Data: make([]byte, 129),
+ Extensions: []icmp.Extension{
+ &icmp.MPLSLabelStack{},
+ },
+ },
+ 4 + 4 + 4 + 0 + 132, // [pointer, length, unused], extension header, object header, object payload and original datagram
+ },
+
+ {
+ iana.ProtocolIPv6ICMP,
+ &icmp.DstUnreach{
+ Data: make([]byte, ipv6.HeaderLen),
+ },
+ 4 + ipv6.HeaderLen, // unused and original datagram
+ },
+ {
+ iana.ProtocolIPv6ICMP,
+ &icmp.PacketTooBig{
+ Data: make([]byte, ipv6.HeaderLen),
+ },
+ 4 + ipv6.HeaderLen, // mtu and original datagram
+ },
+ {
+ iana.ProtocolIPv6ICMP,
+ &icmp.TimeExceeded{
+ Data: make([]byte, ipv6.HeaderLen),
+ },
+ 4 + ipv6.HeaderLen, // unused and original datagram
+ },
+ {
+ iana.ProtocolIPv6ICMP,
+ &icmp.ParamProb{
+ Data: make([]byte, ipv6.HeaderLen),
+ },
+ 4 + ipv6.HeaderLen, // pointer and original datagram
+ },
+
+ {
+ iana.ProtocolIPv6ICMP,
+ &icmp.DstUnreach{
+ Data: make([]byte, 127),
+ Extensions: []icmp.Extension{
+ &icmp.MPLSLabelStack{},
+ },
+ },
+ 4 + 4 + 4 + 0 + 128, // [length, unused], extension header, object header, object payload and original datagram
+ },
+ {
+ iana.ProtocolIPv6ICMP,
+ &icmp.DstUnreach{
+ Data: make([]byte, 128),
+ Extensions: []icmp.Extension{
+ &icmp.MPLSLabelStack{},
+ },
+ },
+ 4 + 4 + 4 + 0 + 128, // [length, unused], extension header, object header, object payload and original datagram
+ },
+ {
+ iana.ProtocolIPv6ICMP,
+ &icmp.DstUnreach{
+ Data: make([]byte, 129),
+ Extensions: []icmp.Extension{
+ &icmp.MPLSLabelStack{},
+ },
+ },
+ 4 + 4 + 4 + 0 + 136, // [length, unused], extension header, object header, object payload and original datagram
+ },
+}
+
+func TestMultipartMessageBodyLen(t *testing.T) {
+ for i, tt := range multipartMessageBodyLenTests {
+ if out := tt.in.Len(tt.proto); out != tt.out {
+ t.Errorf("#%d: got %d; want %d", i, out, tt.out)
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/packettoobig.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/packettoobig.go
new file mode 100644
index 000000000..a1c9df7bf
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/packettoobig.go
@@ -0,0 +1,43 @@
+// Copyright 2014 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 icmp
+
+import "encoding/binary"
+
+// A PacketTooBig represents an ICMP packet too big message body.
+type PacketTooBig struct {
+ MTU int // maximum transmission unit of the nexthop link
+ Data []byte // data, known as original datagram field
+}
+
+// Len implements the Len method of MessageBody interface.
+func (p *PacketTooBig) Len(proto int) int {
+ if p == nil {
+ return 0
+ }
+ return 4 + len(p.Data)
+}
+
+// Marshal implements the Marshal method of MessageBody interface.
+func (p *PacketTooBig) Marshal(proto int) ([]byte, error) {
+ b := make([]byte, 4+len(p.Data))
+ binary.BigEndian.PutUint32(b[:4], uint32(p.MTU))
+ copy(b[4:], p.Data)
+ return b, nil
+}
+
+// parsePacketTooBig parses b as an ICMP packet too big message body.
+func parsePacketTooBig(proto int, b []byte) (MessageBody, error) {
+ bodyLen := len(b)
+ if bodyLen < 4 {
+ return nil, errMessageTooShort
+ }
+ p := &PacketTooBig{MTU: int(binary.BigEndian.Uint32(b[:4]))}
+ if bodyLen > 4 {
+ p.Data = make([]byte, bodyLen-4)
+ copy(p.Data, b[4:])
+ }
+ return p, nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/paramprob.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/paramprob.go
new file mode 100644
index 000000000..0a2548daa
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/paramprob.go
@@ -0,0 +1,63 @@
+// Copyright 2014 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 icmp
+
+import (
+ "encoding/binary"
+ "golang.org/x/net/internal/iana"
+)
+
+// A ParamProb represents an ICMP parameter problem message body.
+type ParamProb struct {
+ Pointer uintptr // offset within the data where the error was detected
+ Data []byte // data, known as original datagram field
+ Extensions []Extension // extensions
+}
+
+// Len implements the Len method of MessageBody interface.
+func (p *ParamProb) Len(proto int) int {
+ if p == nil {
+ return 0
+ }
+ l, _ := multipartMessageBodyDataLen(proto, p.Data, p.Extensions)
+ return 4 + l
+}
+
+// Marshal implements the Marshal method of MessageBody interface.
+func (p *ParamProb) Marshal(proto int) ([]byte, error) {
+ if proto == iana.ProtocolIPv6ICMP {
+ b := make([]byte, p.Len(proto))
+ binary.BigEndian.PutUint32(b[:4], uint32(p.Pointer))
+ copy(b[4:], p.Data)
+ return b, nil
+ }
+ b, err := marshalMultipartMessageBody(proto, p.Data, p.Extensions)
+ if err != nil {
+ return nil, err
+ }
+ b[0] = byte(p.Pointer)
+ return b, nil
+}
+
+// parseParamProb parses b as an ICMP parameter problem message body.
+func parseParamProb(proto int, b []byte) (MessageBody, error) {
+ if len(b) < 4 {
+ return nil, errMessageTooShort
+ }
+ p := &ParamProb{}
+ if proto == iana.ProtocolIPv6ICMP {
+ p.Pointer = uintptr(binary.BigEndian.Uint32(b[:4]))
+ p.Data = make([]byte, len(b)-4)
+ copy(p.Data, b[4:])
+ return p, nil
+ }
+ p.Pointer = uintptr(b[0])
+ var err error
+ p.Data, p.Extensions, err = parseMultipartMessageBody(proto, b)
+ if err != nil {
+ return nil, err
+ }
+ return p, nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/ping_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/ping_test.go
new file mode 100644
index 000000000..3171dad11
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/ping_test.go
@@ -0,0 +1,200 @@
+// Copyright 2014 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 icmp_test
+
+import (
+ "errors"
+ "fmt"
+ "net"
+ "os"
+ "runtime"
+ "sync"
+ "testing"
+ "time"
+
+ "golang.org/x/net/icmp"
+ "golang.org/x/net/internal/iana"
+ "golang.org/x/net/internal/nettest"
+ "golang.org/x/net/ipv4"
+ "golang.org/x/net/ipv6"
+)
+
+func googleAddr(c *icmp.PacketConn, protocol int) (net.Addr, error) {
+ const host = "www.google.com"
+ ips, err := net.LookupIP(host)
+ if err != nil {
+ return nil, err
+ }
+ netaddr := func(ip net.IP) (net.Addr, error) {
+ switch c.LocalAddr().(type) {
+ case *net.UDPAddr:
+ return &net.UDPAddr{IP: ip}, nil
+ case *net.IPAddr:
+ return &net.IPAddr{IP: ip}, nil
+ default:
+ return nil, errors.New("neither UDPAddr nor IPAddr")
+ }
+ }
+ for _, ip := range ips {
+ switch protocol {
+ case iana.ProtocolICMP:
+ if ip.To4() != nil {
+ return netaddr(ip)
+ }
+ case iana.ProtocolIPv6ICMP:
+ if ip.To16() != nil && ip.To4() == nil {
+ return netaddr(ip)
+ }
+ }
+ }
+ return nil, errors.New("no A or AAAA record")
+}
+
+type pingTest struct {
+ network, address string
+ protocol int
+ mtype icmp.Type
+}
+
+var nonPrivilegedPingTests = []pingTest{
+ {"udp4", "0.0.0.0", iana.ProtocolICMP, ipv4.ICMPTypeEcho},
+
+ {"udp6", "::", iana.ProtocolIPv6ICMP, ipv6.ICMPTypeEchoRequest},
+}
+
+func TestNonPrivilegedPing(t *testing.T) {
+ if testing.Short() {
+ t.Skip("avoid external network")
+ }
+ switch runtime.GOOS {
+ case "darwin":
+ case "linux":
+ t.Log("you may need to adjust the net.ipv4.ping_group_range kernel state")
+ default:
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+
+ for i, tt := range nonPrivilegedPingTests {
+ if err := doPing(tt, i); err != nil {
+ t.Error(err)
+ }
+ }
+}
+
+var privilegedPingTests = []pingTest{
+ {"ip4:icmp", "0.0.0.0", iana.ProtocolICMP, ipv4.ICMPTypeEcho},
+
+ {"ip6:ipv6-icmp", "::", iana.ProtocolIPv6ICMP, ipv6.ICMPTypeEchoRequest},
+}
+
+func TestPrivilegedPing(t *testing.T) {
+ if testing.Short() {
+ t.Skip("avoid external network")
+ }
+ if m, ok := nettest.SupportsRawIPSocket(); !ok {
+ t.Skip(m)
+ }
+
+ for i, tt := range privilegedPingTests {
+ if err := doPing(tt, i); err != nil {
+ t.Error(err)
+ }
+ }
+}
+
+func doPing(tt pingTest, seq int) error {
+ c, err := icmp.ListenPacket(tt.network, tt.address)
+ if err != nil {
+ return err
+ }
+ defer c.Close()
+
+ dst, err := googleAddr(c, tt.protocol)
+ if err != nil {
+ return err
+ }
+
+ if tt.network != "udp6" && tt.protocol == iana.ProtocolIPv6ICMP {
+ var f ipv6.ICMPFilter
+ f.SetAll(true)
+ f.Accept(ipv6.ICMPTypeDestinationUnreachable)
+ f.Accept(ipv6.ICMPTypePacketTooBig)
+ f.Accept(ipv6.ICMPTypeTimeExceeded)
+ f.Accept(ipv6.ICMPTypeParameterProblem)
+ f.Accept(ipv6.ICMPTypeEchoReply)
+ if err := c.IPv6PacketConn().SetICMPFilter(&f); err != nil {
+ return err
+ }
+ }
+
+ wm := icmp.Message{
+ Type: tt.mtype, Code: 0,
+ Body: &icmp.Echo{
+ ID: os.Getpid() & 0xffff, Seq: 1 << uint(seq),
+ Data: []byte("HELLO-R-U-THERE"),
+ },
+ }
+ wb, err := wm.Marshal(nil)
+ if err != nil {
+ return err
+ }
+ if n, err := c.WriteTo(wb, dst); err != nil {
+ return err
+ } else if n != len(wb) {
+ return fmt.Errorf("got %v; want %v", n, len(wb))
+ }
+
+ rb := make([]byte, 1500)
+ if err := c.SetReadDeadline(time.Now().Add(3 * time.Second)); err != nil {
+ return err
+ }
+ n, peer, err := c.ReadFrom(rb)
+ if err != nil {
+ return err
+ }
+ rm, err := icmp.ParseMessage(tt.protocol, rb[:n])
+ if err != nil {
+ return err
+ }
+ switch rm.Type {
+ case ipv4.ICMPTypeEchoReply, ipv6.ICMPTypeEchoReply:
+ return nil
+ default:
+ return fmt.Errorf("got %+v from %v; want echo reply", rm, peer)
+ }
+}
+
+func TestConcurrentNonPrivilegedListenPacket(t *testing.T) {
+ if testing.Short() {
+ t.Skip("avoid external network")
+ }
+ switch runtime.GOOS {
+ case "darwin":
+ case "linux":
+ t.Log("you may need to adjust the net.ipv4.ping_group_range kernel state")
+ default:
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+
+ network, address := "udp4", "127.0.0.1"
+ if !nettest.SupportsIPv4() {
+ network, address = "udp6", "::1"
+ }
+ const N = 1000
+ var wg sync.WaitGroup
+ wg.Add(N)
+ for i := 0; i < N; i++ {
+ go func() {
+ defer wg.Done()
+ c, err := icmp.ListenPacket(network, address)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ c.Close()
+ }()
+ }
+ wg.Wait()
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/sys_freebsd.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/sys_freebsd.go
new file mode 100644
index 000000000..c75f3ddaa
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/sys_freebsd.go
@@ -0,0 +1,11 @@
+// Copyright 2014 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 icmp
+
+import "syscall"
+
+func init() {
+ freebsdVersion, _ = syscall.SysctlUint32("kern.osreldate")
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/timeexceeded.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/timeexceeded.go
new file mode 100644
index 000000000..344e15848
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/icmp/timeexceeded.go
@@ -0,0 +1,39 @@
+// Copyright 2014 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 icmp
+
+// A TimeExceeded represents an ICMP time exceeded message body.
+type TimeExceeded struct {
+ Data []byte // data, known as original datagram field
+ Extensions []Extension // extensions
+}
+
+// Len implements the Len method of MessageBody interface.
+func (p *TimeExceeded) Len(proto int) int {
+ if p == nil {
+ return 0
+ }
+ l, _ := multipartMessageBodyDataLen(proto, p.Data, p.Extensions)
+ return 4 + l
+}
+
+// Marshal implements the Marshal method of MessageBody interface.
+func (p *TimeExceeded) Marshal(proto int) ([]byte, error) {
+ return marshalMultipartMessageBody(proto, p.Data, p.Extensions)
+}
+
+// parseTimeExceeded parses b as an ICMP time exceeded message body.
+func parseTimeExceeded(proto int, b []byte) (MessageBody, error) {
+ if len(b) < 4 {
+ return nil, errMessageTooShort
+ }
+ p := &TimeExceeded{}
+ var err error
+ p.Data, p.Extensions, err = parseMultipartMessageBody(proto, b)
+ if err != nil {
+ return nil, err
+ }
+ return p, nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/idna/example_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/idna/example_test.go
new file mode 100644
index 000000000..948f6eb20
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/idna/example_test.go
@@ -0,0 +1,70 @@
+// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
+
+// 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 idna_test
+
+import (
+ "fmt"
+
+ "golang.org/x/net/idna"
+)
+
+func ExampleProfile() {
+ // Raw Punycode has no restrictions and does no mappings.
+ fmt.Println(idna.ToASCII(""))
+ fmt.Println(idna.ToASCII("*.faß.com"))
+ fmt.Println(idna.Punycode.ToASCII("*.faß.com"))
+
+ // Rewrite IDN for lookup. This (currently) uses transitional mappings to
+ // find a balance between IDNA2003 and IDNA2008 compatibility.
+ fmt.Println(idna.Lookup.ToASCII(""))
+ fmt.Println(idna.Lookup.ToASCII("www.faß.com"))
+
+ // Convert an IDN to ASCII for registration purposes. This changes the
+ // encoding, but reports an error if the input was illformed.
+ fmt.Println(idna.Registration.ToASCII(""))
+ fmt.Println(idna.Registration.ToASCII("www.faß.com"))
+
+ // Output:
+ // <nil>
+ // *.xn--fa-hia.com <nil>
+ // *.xn--fa-hia.com <nil>
+ // <nil>
+ // www.fass.com <nil>
+ // idna: invalid label ""
+ // www.xn--fa-hia.com <nil>
+}
+
+func ExampleNew() {
+ var p *idna.Profile
+
+ // Raw Punycode has no restrictions and does no mappings.
+ p = idna.New()
+ fmt.Println(p.ToASCII("*.faß.com"))
+
+ // Do mappings. Note that star is not allowed in a DNS lookup.
+ p = idna.New(
+ idna.MapForLookup(),
+ idna.Transitional(true)) // Map ß -> ss
+ fmt.Println(p.ToASCII("*.faß.com"))
+
+ // Lookup for registration. Also does not allow '*'.
+ p = idna.New(idna.ValidateForRegistration())
+ fmt.Println(p.ToUnicode("*.faß.com"))
+
+ // Set up a profile maps for lookup, but allows wild cards.
+ p = idna.New(
+ idna.MapForLookup(),
+ idna.Transitional(true), // Map ß -> ss
+ idna.StrictDomainName(false)) // Set more permissive ASCII rules.
+ fmt.Println(p.ToASCII("*.faß.com"))
+
+ // Output:
+ // *.xn--fa-hia.com <nil>
+ // *.fass.com idna: disallowed rune U+002A
+ // *.faß.com idna: disallowed rune U+002A
+ // *.fass.com <nil>
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/idna/idna.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/idna/idna.go
new file mode 100644
index 000000000..346fe4423
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/idna/idna.go
@@ -0,0 +1,732 @@
+// 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.
+
+// 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 http://www.unicode.org/reports/tr46.
+// See http://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/bidi"
+ "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 most 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 = true }
+}
+
+// VerifyDNSLength sets whether a Profile should fail if any of the IDN parts
+// are longer than allowed by the RFC.
+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.
+//
+// This is the behavior suggested by the UTS #46 and is adopted by some
+// browsers.
+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.
+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.validateLabels = enable
+ o.fromPuny = validateFromPunycode
+ }
+}
+
+// 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.
+//
+// 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 option in UTS #46.
+func StrictDomainName(use bool) Option {
+ return func(o *options) {
+ o.trie = trie
+ o.useSTD3Rules = use
+ o.fromPuny = validateFromPunycode
+ }
+}
+
+// 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.
+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)
+ }
+}
+
+type options struct {
+ transitional bool
+ useSTD3Rules bool
+ validateLabels 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) (mapped string, isBidi bool, err 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 an 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.validateLabels {
+ s += ":ValidateLabels"
+ }
+ 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,
+ useSTD3Rules: true,
+ validateLabels: true,
+ trie: trie,
+ fromPuny: validateFromPunycode,
+ mapping: validateAndMap,
+ bidirule: bidirule.ValidString,
+ }}
+ display = &Profile{options{
+ useSTD3Rules: true,
+ validateLabels: true,
+ trie: trie,
+ fromPuny: validateFromPunycode,
+ mapping: validateAndMap,
+ bidirule: bidirule.ValidString,
+ }}
+ registration = &Profile{options{
+ useSTD3Rules: true,
+ validateLabels: true,
+ verifyDNSLength: 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 http://www.unicode.org/reports/tr46.
+func (p *Profile) process(s string, toASCII bool) (string, error) {
+ var err error
+ var isBidi bool
+ if p.mapping != nil {
+ s, isBidi, err = p.mapping(p, s)
+ }
+ // Remove leading empty labels.
+ if p.removeLeadingDots {
+ for ; len(s) > 0 && s[0] == '.'; s = s[1:] {
+ }
+ }
+ // 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.
+ 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
+ }
+ isBidi = isBidi || bidirule.DirectionString(u) != bidi.LeftToRight
+ labels.set(u)
+ if err == nil && p.validateLabels {
+ 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 isBidi && p.bidirule != nil && err == nil {
+ for labels.reset(); !labels.done(); labels.next() {
+ if !p.bidirule(labels.label()) {
+ err = &labelError{s, "B"}
+ break
+ }
+ }
+ }
+ 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) (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
+ // faster in the common case.
+ mapped = norm.NFC.String(s)
+ isBidi = bidirule.DirectionString(mapped) == bidi.RightToLeft
+ return mapped, isBidi, nil
+}
+
+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"}
+ }
+ for i := 0; i < len(s); {
+ v, sz := trie.lookupString(s[i:])
+ if sz == 0 {
+ return s, bidi, runeError(utf8.RuneError)
+ }
+ bidi = bidi || info(v).isBidi(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, bidi, runeError(r)
+ }
+ i += sz
+ }
+ return s, bidi, nil
+}
+
+func (c info) isBidi(s string) bool {
+ if !c.isMapped() {
+ return c&attributesMask == rtl
+ }
+ // TODO: also store bidi info for mapped data. This is possible, but a bit
+ // cumbersome and not for the common case.
+ p, _ := bidi.LookupString(s)
+ switch p.Class() {
+ case bidi.R, bidi.AL, bidi.AN:
+ return true
+ }
+ return false
+}
+
+func validateAndMap(p *Profile, s string) (vm string, bidi bool, err error) {
+ var (
+ b []byte
+ k int
+ )
+ // combinedInfoBits contains the or-ed bits of all runes. We use this
+ // to derive the mayNeedNorm bit later. This may trigger normalization
+ // overeagerly, but it will not do so in the common case. The end result
+ // is another 10% saving on BenchmarkProfile for the common case.
+ var combinedInfoBits info
+ for i := 0; i < len(s); {
+ v, sz := trie.lookupString(s[i:])
+ if sz == 0 {
+ b = append(b, s[k:i]...)
+ b = append(b, "\ufffd"...)
+ k = len(s)
+ if err == nil {
+ err = runeError(utf8.RuneError)
+ }
+ break
+ }
+ combinedInfoBits |= info(v)
+ bidi = bidi || info(v).isBidi(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.
+ if combinedInfoBits&mayNeedNorm != 0 {
+ 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, bidi, 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"}
+ }
+ // 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)
+ }
+ 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) (err error) {
+ if s == "" {
+ if p.verifyDNSLength {
+ return &labelError{s, "A4"}
+ }
+ return nil
+ }
+ if !p.validateLabels {
+ return nil
+ }
+ trie := p.trie // p.validateLabels is only set if trie is set.
+ if len(s) > 4 && s[2] == '-' && s[3] == '-' {
+ return &labelError{s, "V2"}
+ }
+ if s[0] == '-' || s[len(s)-1] == '-' {
+ return &labelError{s, "V3"}
+ }
+ // 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
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/idna/idna_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/idna/idna_test.go
new file mode 100644
index 000000000..0b067cac9
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/idna/idna_test.go
@@ -0,0 +1,108 @@
+// Copyright 2012 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 idna
+
+import (
+ "testing"
+)
+
+var idnaTestCases = [...]struct {
+ ascii, unicode string
+}{
+ // Labels.
+ {"books", "books"},
+ {"xn--bcher-kva", "bücher"},
+
+ // Domains.
+ {"foo--xn--bar.org", "foo--xn--bar.org"},
+ {"golang.org", "golang.org"},
+ {"example.xn--p1ai", "example.рф"},
+ {"xn--czrw28b.tw", "商業.tw"},
+ {"www.xn--mller-kva.de", "www.müller.de"},
+}
+
+func TestIDNA(t *testing.T) {
+ for _, tc := range idnaTestCases {
+ if a, err := ToASCII(tc.unicode); err != nil {
+ t.Errorf("ToASCII(%q): %v", tc.unicode, err)
+ } else if a != tc.ascii {
+ t.Errorf("ToASCII(%q): got %q, want %q", tc.unicode, a, tc.ascii)
+ }
+
+ if u, err := ToUnicode(tc.ascii); err != nil {
+ t.Errorf("ToUnicode(%q): %v", tc.ascii, err)
+ } else if u != tc.unicode {
+ t.Errorf("ToUnicode(%q): got %q, want %q", tc.ascii, u, tc.unicode)
+ }
+ }
+}
+
+func TestIDNASeparators(t *testing.T) {
+ type subCase struct {
+ unicode string
+ wantASCII string
+ wantErr bool
+ }
+
+ testCases := []struct {
+ name string
+ profile *Profile
+ subCases []subCase
+ }{
+ {
+ name: "Punycode", profile: Punycode,
+ subCases: []subCase{
+ {"example\u3002jp", "xn--examplejp-ck3h", false},
+ {"東京\uFF0Ejp", "xn--jp-l92cn98g071o", false},
+ {"大阪\uFF61jp", "xn--jp-ku9cz72u463f", false},
+ },
+ },
+ {
+ name: "Lookup", profile: Lookup,
+ subCases: []subCase{
+ {"example\u3002jp", "example.jp", false},
+ {"東京\uFF0Ejp", "xn--1lqs71d.jp", false},
+ {"大阪\uFF61jp", "xn--pssu33l.jp", false},
+ },
+ },
+ {
+ name: "Display", profile: Display,
+ subCases: []subCase{
+ {"example\u3002jp", "example.jp", false},
+ {"東京\uFF0Ejp", "xn--1lqs71d.jp", false},
+ {"大阪\uFF61jp", "xn--pssu33l.jp", false},
+ },
+ },
+ {
+ name: "Registration", profile: Registration,
+ subCases: []subCase{
+ {"example\u3002jp", "", true},
+ {"東京\uFF0Ejp", "", true},
+ {"大阪\uFF61jp", "", true},
+ },
+ },
+ }
+ for _, tc := range testCases {
+ t.Run(tc.name, func(t *testing.T) {
+ for _, c := range tc.subCases {
+ gotA, err := tc.profile.ToASCII(c.unicode)
+ if c.wantErr {
+ if err == nil {
+ t.Errorf("ToASCII(%q): got no error, but an error expected", c.unicode)
+ }
+ } else {
+ if err != nil {
+ t.Errorf("ToASCII(%q): got err=%v, but no error expected", c.unicode, err)
+ } else if gotA != c.wantASCII {
+ t.Errorf("ToASCII(%q): got %q, want %q", c.unicode, gotA, c.wantASCII)
+ }
+ }
+ }
+ })
+ }
+}
+
+// TODO(nigeltao): test errors, once we've specified when ToASCII and ToUnicode
+// return errors.
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/idna/punycode.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/idna/punycode.go
new file mode 100644
index 000000000..02c7d59af
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/idna/punycode.go
@@ -0,0 +1,203 @@
+// 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.
+
+package idna
+
+// This file implements the Punycode algorithm from RFC 3492.
+
+import (
+ "math"
+ "strings"
+ "unicode/utf8"
+)
+
+// These parameter values are specified in section 5.
+//
+// All computation is done with int32s, so that overflow behavior is identical
+// regardless of whether int is 32-bit or 64-bit.
+const (
+ base int32 = 36
+ damp int32 = 700
+ initialBias int32 = 72
+ initialN int32 = 128
+ skew int32 = 38
+ tmax int32 = 26
+ tmin int32 = 1
+)
+
+func punyError(s string) error { return &labelError{s, "A3"} }
+
+// decode decodes a string as specified in section 6.2.
+func decode(encoded string) (string, error) {
+ if encoded == "" {
+ return "", nil
+ }
+ pos := 1 + strings.LastIndex(encoded, "-")
+ if pos == 1 {
+ return "", punyError(encoded)
+ }
+ if pos == len(encoded) {
+ return encoded[:len(encoded)-1], nil
+ }
+ output := make([]rune, 0, len(encoded))
+ if pos != 0 {
+ for _, r := range encoded[:pos-1] {
+ output = append(output, r)
+ }
+ }
+ i, n, bias := int32(0), initialN, initialBias
+ for pos < len(encoded) {
+ oldI, w := i, int32(1)
+ for k := base; ; k += base {
+ if pos == len(encoded) {
+ return "", punyError(encoded)
+ }
+ digit, ok := decodeDigit(encoded[pos])
+ if !ok {
+ return "", punyError(encoded)
+ }
+ pos++
+ i += digit * w
+ if i < 0 {
+ return "", punyError(encoded)
+ }
+ t := k - bias
+ if t < tmin {
+ t = tmin
+ } else if t > tmax {
+ t = tmax
+ }
+ if digit < t {
+ break
+ }
+ w *= base - t
+ if w >= math.MaxInt32/base {
+ return "", punyError(encoded)
+ }
+ }
+ x := int32(len(output) + 1)
+ bias = adapt(i-oldI, x, oldI == 0)
+ n += i / x
+ i %= x
+ if n > utf8.MaxRune || len(output) >= 1024 {
+ return "", punyError(encoded)
+ }
+ output = append(output, 0)
+ copy(output[i+1:], output[i:])
+ output[i] = n
+ i++
+ }
+ return string(output), nil
+}
+
+// encode encodes a string as specified in section 6.3 and prepends prefix to
+// the result.
+//
+// The "while h < length(input)" line in the specification becomes "for
+// remaining != 0" in the Go code, because len(s) in Go is in bytes, not runes.
+func encode(prefix, s string) (string, error) {
+ output := make([]byte, len(prefix), len(prefix)+1+2*len(s))
+ copy(output, prefix)
+ delta, n, bias := int32(0), initialN, initialBias
+ b, remaining := int32(0), int32(0)
+ for _, r := range s {
+ if r < 0x80 {
+ b++
+ output = append(output, byte(r))
+ } else {
+ remaining++
+ }
+ }
+ h := b
+ if b > 0 {
+ output = append(output, '-')
+ }
+ for remaining != 0 {
+ m := int32(0x7fffffff)
+ for _, r := range s {
+ if m > r && r >= n {
+ m = r
+ }
+ }
+ delta += (m - n) * (h + 1)
+ if delta < 0 {
+ return "", punyError(s)
+ }
+ n = m
+ for _, r := range s {
+ if r < n {
+ delta++
+ if delta < 0 {
+ return "", punyError(s)
+ }
+ continue
+ }
+ if r > n {
+ continue
+ }
+ q := delta
+ for k := base; ; k += base {
+ t := k - bias
+ if t < tmin {
+ t = tmin
+ } else if t > tmax {
+ t = tmax
+ }
+ if q < t {
+ break
+ }
+ output = append(output, encodeDigit(t+(q-t)%(base-t)))
+ q = (q - t) / (base - t)
+ }
+ output = append(output, encodeDigit(q))
+ bias = adapt(delta, h+1, h == b)
+ delta = 0
+ h++
+ remaining--
+ }
+ delta++
+ n++
+ }
+ return string(output), nil
+}
+
+func decodeDigit(x byte) (digit int32, ok bool) {
+ switch {
+ case '0' <= x && x <= '9':
+ return int32(x - ('0' - 26)), true
+ case 'A' <= x && x <= 'Z':
+ return int32(x - 'A'), true
+ case 'a' <= x && x <= 'z':
+ return int32(x - 'a'), true
+ }
+ return 0, false
+}
+
+func encodeDigit(digit int32) byte {
+ switch {
+ case 0 <= digit && digit < 26:
+ return byte(digit + 'a')
+ case 26 <= digit && digit < 36:
+ return byte(digit + ('0' - 26))
+ }
+ panic("idna: internal error in punycode encoding")
+}
+
+// adapt is the bias adaptation function specified in section 6.1.
+func adapt(delta, numPoints int32, firstTime bool) int32 {
+ if firstTime {
+ delta /= damp
+ } else {
+ delta /= 2
+ }
+ delta += delta / numPoints
+ k := int32(0)
+ for delta > ((base-tmin)*tmax)/2 {
+ delta /= base - tmin
+ k += base
+ }
+ return k + (base-tmin+1)*delta/(delta+skew)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/idna/punycode_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/idna/punycode_test.go
new file mode 100644
index 000000000..bfec81dec
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/idna/punycode_test.go
@@ -0,0 +1,198 @@
+// Copyright 2012 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 idna
+
+import (
+ "strings"
+ "testing"
+)
+
+var punycodeTestCases = [...]struct {
+ s, encoded string
+}{
+ {"", ""},
+ {"-", "--"},
+ {"-a", "-a-"},
+ {"-a-", "-a--"},
+ {"a", "a-"},
+ {"a-", "a--"},
+ {"a-b", "a-b-"},
+ {"books", "books-"},
+ {"bücher", "bcher-kva"},
+ {"Hello世界", "Hello-ck1hg65u"},
+ {"ü", "tda"},
+ {"üý", "tdac"},
+
+ // The test cases below come from RFC 3492 section 7.1 with Errata 3026.
+ {
+ // (A) Arabic (Egyptian).
+ "\u0644\u064A\u0647\u0645\u0627\u0628\u062A\u0643\u0644" +
+ "\u0645\u0648\u0634\u0639\u0631\u0628\u064A\u061F",
+ "egbpdaj6bu4bxfgehfvwxn",
+ },
+ {
+ // (B) Chinese (simplified).
+ "\u4ED6\u4EEC\u4E3A\u4EC0\u4E48\u4E0D\u8BF4\u4E2D\u6587",
+ "ihqwcrb4cv8a8dqg056pqjye",
+ },
+ {
+ // (C) Chinese (traditional).
+ "\u4ED6\u5011\u7232\u4EC0\u9EBD\u4E0D\u8AAA\u4E2D\u6587",
+ "ihqwctvzc91f659drss3x8bo0yb",
+ },
+ {
+ // (D) Czech.
+ "\u0050\u0072\u006F\u010D\u0070\u0072\u006F\u0073\u0074" +
+ "\u011B\u006E\u0065\u006D\u006C\u0075\u0076\u00ED\u010D" +
+ "\u0065\u0073\u006B\u0079",
+ "Proprostnemluvesky-uyb24dma41a",
+ },
+ {
+ // (E) Hebrew.
+ "\u05DC\u05DE\u05D4\u05D4\u05DD\u05E4\u05E9\u05D5\u05D8" +
+ "\u05DC\u05D0\u05DE\u05D3\u05D1\u05E8\u05D9\u05DD\u05E2" +
+ "\u05D1\u05E8\u05D9\u05EA",
+ "4dbcagdahymbxekheh6e0a7fei0b",
+ },
+ {
+ // (F) Hindi (Devanagari).
+ "\u092F\u0939\u0932\u094B\u0917\u0939\u093F\u0928\u094D" +
+ "\u0926\u0940\u0915\u094D\u092F\u094B\u0902\u0928\u0939" +
+ "\u0940\u0902\u092C\u094B\u0932\u0938\u0915\u0924\u0947" +
+ "\u0939\u0948\u0902",
+ "i1baa7eci9glrd9b2ae1bj0hfcgg6iyaf8o0a1dig0cd",
+ },
+ {
+ // (G) Japanese (kanji and hiragana).
+ "\u306A\u305C\u307F\u3093\u306A\u65E5\u672C\u8A9E\u3092" +
+ "\u8A71\u3057\u3066\u304F\u308C\u306A\u3044\u306E\u304B",
+ "n8jok5ay5dzabd5bym9f0cm5685rrjetr6pdxa",
+ },
+ {
+ // (H) Korean (Hangul syllables).
+ "\uC138\uACC4\uC758\uBAA8\uB4E0\uC0AC\uB78C\uB4E4\uC774" +
+ "\uD55C\uAD6D\uC5B4\uB97C\uC774\uD574\uD55C\uB2E4\uBA74" +
+ "\uC5BC\uB9C8\uB098\uC88B\uC744\uAE4C",
+ "989aomsvi5e83db1d2a355cv1e0vak1dwrv93d5xbh15a0dt30a5j" +
+ "psd879ccm6fea98c",
+ },
+ {
+ // (I) Russian (Cyrillic).
+ "\u043F\u043E\u0447\u0435\u043C\u0443\u0436\u0435\u043E" +
+ "\u043D\u0438\u043D\u0435\u0433\u043E\u0432\u043E\u0440" +
+ "\u044F\u0442\u043F\u043E\u0440\u0443\u0441\u0441\u043A" +
+ "\u0438",
+ "b1abfaaepdrnnbgefbadotcwatmq2g4l",
+ },
+ {
+ // (J) Spanish.
+ "\u0050\u006F\u0072\u0071\u0075\u00E9\u006E\u006F\u0070" +
+ "\u0075\u0065\u0064\u0065\u006E\u0073\u0069\u006D\u0070" +
+ "\u006C\u0065\u006D\u0065\u006E\u0074\u0065\u0068\u0061" +
+ "\u0062\u006C\u0061\u0072\u0065\u006E\u0045\u0073\u0070" +
+ "\u0061\u00F1\u006F\u006C",
+ "PorqunopuedensimplementehablarenEspaol-fmd56a",
+ },
+ {
+ // (K) Vietnamese.
+ "\u0054\u1EA1\u0069\u0073\u0061\u006F\u0068\u1ECD\u006B" +
+ "\u0068\u00F4\u006E\u0067\u0074\u0068\u1EC3\u0063\u0068" +
+ "\u1EC9\u006E\u00F3\u0069\u0074\u0069\u1EBF\u006E\u0067" +
+ "\u0056\u0069\u1EC7\u0074",
+ "TisaohkhngthchnitingVit-kjcr8268qyxafd2f1b9g",
+ },
+ {
+ // (L) 3<nen>B<gumi><kinpachi><sensei>.
+ "\u0033\u5E74\u0042\u7D44\u91D1\u516B\u5148\u751F",
+ "3B-ww4c5e180e575a65lsy2b",
+ },
+ {
+ // (M) <amuro><namie>-with-SUPER-MONKEYS.
+ "\u5B89\u5BA4\u5948\u7F8E\u6075\u002D\u0077\u0069\u0074" +
+ "\u0068\u002D\u0053\u0055\u0050\u0045\u0052\u002D\u004D" +
+ "\u004F\u004E\u004B\u0045\u0059\u0053",
+ "-with-SUPER-MONKEYS-pc58ag80a8qai00g7n9n",
+ },
+ {
+ // (N) Hello-Another-Way-<sorezore><no><basho>.
+ "\u0048\u0065\u006C\u006C\u006F\u002D\u0041\u006E\u006F" +
+ "\u0074\u0068\u0065\u0072\u002D\u0057\u0061\u0079\u002D" +
+ "\u305D\u308C\u305E\u308C\u306E\u5834\u6240",
+ "Hello-Another-Way--fc4qua05auwb3674vfr0b",
+ },
+ {
+ // (O) <hitotsu><yane><no><shita>2.
+ "\u3072\u3068\u3064\u5C4B\u6839\u306E\u4E0B\u0032",
+ "2-u9tlzr9756bt3uc0v",
+ },
+ {
+ // (P) Maji<de>Koi<suru>5<byou><mae>
+ "\u004D\u0061\u006A\u0069\u3067\u004B\u006F\u0069\u3059" +
+ "\u308B\u0035\u79D2\u524D",
+ "MajiKoi5-783gue6qz075azm5e",
+ },
+ {
+ // (Q) <pafii>de<runba>
+ "\u30D1\u30D5\u30A3\u30FC\u0064\u0065\u30EB\u30F3\u30D0",
+ "de-jg4avhby1noc0d",
+ },
+ {
+ // (R) <sono><supiido><de>
+ "\u305D\u306E\u30B9\u30D4\u30FC\u30C9\u3067",
+ "d9juau41awczczp",
+ },
+ {
+ // (S) -> $1.00 <-
+ "\u002D\u003E\u0020\u0024\u0031\u002E\u0030\u0030\u0020" +
+ "\u003C\u002D",
+ "-> $1.00 <--",
+ },
+}
+
+func TestPunycode(t *testing.T) {
+ for _, tc := range punycodeTestCases {
+ if got, err := decode(tc.encoded); err != nil {
+ t.Errorf("decode(%q): %v", tc.encoded, err)
+ } else if got != tc.s {
+ t.Errorf("decode(%q): got %q, want %q", tc.encoded, got, tc.s)
+ }
+
+ if got, err := encode("", tc.s); err != nil {
+ t.Errorf(`encode("", %q): %v`, tc.s, err)
+ } else if got != tc.encoded {
+ t.Errorf(`encode("", %q): got %q, want %q`, tc.s, got, tc.encoded)
+ }
+ }
+}
+
+var punycodeErrorTestCases = [...]string{
+ "decode -", // A sole '-' is invalid.
+ "decode foo\x00bar", // '\x00' is not in [0-9A-Za-z].
+ "decode foo#bar", // '#' is not in [0-9A-Za-z].
+ "decode foo\u00A3bar", // '\u00A3' is not in [0-9A-Za-z].
+ "decode 9", // "9a" decodes to codepoint \u00A3; "9" is truncated.
+ "decode 99999a", // "99999a" decodes to codepoint \U0048A3C1, which is > \U0010FFFF.
+ "decode 9999999999a", // "9999999999a" overflows the int32 calculation.
+
+ "encode " + strings.Repeat("x", 65536) + "\uff00", // int32 overflow.
+}
+
+func TestPunycodeErrors(t *testing.T) {
+ for _, tc := range punycodeErrorTestCases {
+ var err error
+ switch {
+ case strings.HasPrefix(tc, "decode "):
+ _, err = decode(tc[7:])
+ case strings.HasPrefix(tc, "encode "):
+ _, err = encode("", tc[7:])
+ }
+ if err == nil {
+ if len(tc) > 256 {
+ tc = tc[:100] + "..." + tc[len(tc)-100:]
+ }
+ t.Errorf("no error for %s", tc)
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/idna/tables.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/idna/tables.go
new file mode 100644
index 000000000..f910b2691
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/idna/tables.go
@@ -0,0 +1,4557 @@
+// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
+
+package idna
+
+// UnicodeVersion is the Unicode version from which the tables in this package are derived.
+const UnicodeVersion = "10.0.0"
+
+var mappings string = "" + // Size: 8176 bytes
+ "\x00\x01 \x03 ̈\x01a\x03 ̄\x012\x013\x03 ́\x03 ̧\x011\x01o\x051⁄4\x051⁄2" +
+ "\x053⁄4\x03i̇\x03l·\x03ʼn\x01s\x03dž\x03ⱥ\x03ⱦ\x01h\x01j\x01r\x01w\x01y" +
+ "\x03 ̆\x03 ̇\x03 ̊\x03 ̨\x03 ̃\x03 ̋\x01l\x01x\x04̈́\x03 ι\x01;\x05 ̈́" +
+ "\x04եւ\x04اٴ\x04وٴ\x04ۇٴ\x04يٴ\x06क़\x06ख़\x06ग़\x06ज़\x06ड़\x06ढ़\x06फ़" +
+ "\x06य़\x06ড়\x06ঢ়\x06য়\x06ਲ਼\x06ਸ਼\x06ਖ਼\x06ਗ਼\x06ਜ਼\x06ਫ਼\x06ଡ଼\x06ଢ଼" +
+ "\x06ํา\x06ໍາ\x06ຫນ\x06ຫມ\x06གྷ\x06ཌྷ\x06དྷ\x06བྷ\x06ཛྷ\x06ཀྵ\x06ཱི\x06ཱུ" +
+ "\x06ྲྀ\x09ྲཱྀ\x06ླྀ\x09ླཱྀ\x06ཱྀ\x06ྒྷ\x06ྜྷ\x06ྡྷ\x06ྦྷ\x06ྫྷ\x06ྐྵ\x02" +
+ "в\x02д\x02о\x02с\x02т\x02ъ\x02ѣ\x02æ\x01b\x01d\x01e\x02ǝ\x01g\x01i\x01k" +
+ "\x01m\x01n\x02ȣ\x01p\x01t\x01u\x02ɐ\x02ɑ\x02ə\x02ɛ\x02ɜ\x02ŋ\x02ɔ\x02ɯ" +
+ "\x01v\x02β\x02γ\x02δ\x02φ\x02χ\x02ρ\x02н\x02ɒ\x01c\x02ɕ\x02ð\x01f\x02ɟ" +
+ "\x02ɡ\x02ɥ\x02ɨ\x02ɩ\x02ɪ\x02ʝ\x02ɭ\x02ʟ\x02ɱ\x02ɰ\x02ɲ\x02ɳ\x02ɴ\x02ɵ" +
+ "\x02ɸ\x02ʂ\x02ʃ\x02ƫ\x02ʉ\x02ʊ\x02ʋ\x02ʌ\x01z\x02ʐ\x02ʑ\x02ʒ\x02θ\x02ss" +
+ "\x02ά\x02έ\x02ή\x02ί\x02ό\x02ύ\x02ώ\x05ἀι\x05ἁι\x05ἂι\x05ἃι\x05ἄι\x05ἅι" +
+ "\x05ἆι\x05ἇι\x05ἠι\x05ἡι\x05ἢι\x05ἣι\x05ἤι\x05ἥι\x05ἦι\x05ἧι\x05ὠι\x05ὡι" +
+ "\x05ὢι\x05ὣι\x05ὤι\x05ὥι\x05ὦι\x05ὧι\x05ὰι\x04αι\x04άι\x05ᾶι\x02ι\x05 ̈͂" +
+ "\x05ὴι\x04ηι\x04ήι\x05ῆι\x05 ̓̀\x05 ̓́\x05 ̓͂\x02ΐ\x05 ̔̀\x05 ̔́\x05 ̔͂" +
+ "\x02ΰ\x05 ̈̀\x01`\x05ὼι\x04ωι\x04ώι\x05ῶι\x06′′\x09′′′\x06‵‵\x09‵‵‵\x02!" +
+ "!\x02??\x02?!\x02!?\x0c′′′′\x010\x014\x015\x016\x017\x018\x019\x01+\x01=" +
+ "\x01(\x01)\x02rs\x02ħ\x02no\x01q\x02sm\x02tm\x02ω\x02å\x02א\x02ב\x02ג" +
+ "\x02ד\x02π\x051⁄7\x051⁄9\x061⁄10\x051⁄3\x052⁄3\x051⁄5\x052⁄5\x053⁄5\x054" +
+ "⁄5\x051⁄6\x055⁄6\x051⁄8\x053⁄8\x055⁄8\x057⁄8\x041⁄\x02ii\x02iv\x02vi" +
+ "\x04viii\x02ix\x02xi\x050⁄3\x06∫∫\x09∫∫∫\x06∮∮\x09∮∮∮\x0210\x0211\x0212" +
+ "\x0213\x0214\x0215\x0216\x0217\x0218\x0219\x0220\x04(10)\x04(11)\x04(12)" +
+ "\x04(13)\x04(14)\x04(15)\x04(16)\x04(17)\x04(18)\x04(19)\x04(20)\x0c∫∫∫∫" +
+ "\x02==\x05⫝̸\x02ɫ\x02ɽ\x02ȿ\x02ɀ\x01.\x04 ゙\x04 ゚\x06より\x06コト\x05(ᄀ)\x05" +
+ "(ᄂ)\x05(ᄃ)\x05(ᄅ)\x05(ᄆ)\x05(ᄇ)\x05(ᄉ)\x05(ᄋ)\x05(ᄌ)\x05(ᄎ)\x05(ᄏ)\x05(ᄐ" +
+ ")\x05(ᄑ)\x05(ᄒ)\x05(가)\x05(나)\x05(다)\x05(라)\x05(마)\x05(바)\x05(사)\x05(아)" +
+ "\x05(자)\x05(차)\x05(카)\x05(타)\x05(파)\x05(하)\x05(주)\x08(오전)\x08(오후)\x05(一)" +
+ "\x05(二)\x05(三)\x05(四)\x05(五)\x05(六)\x05(七)\x05(八)\x05(九)\x05(十)\x05(月)" +
+ "\x05(火)\x05(水)\x05(木)\x05(金)\x05(土)\x05(日)\x05(株)\x05(有)\x05(社)\x05(名)" +
+ "\x05(特)\x05(財)\x05(祝)\x05(労)\x05(代)\x05(呼)\x05(学)\x05(監)\x05(企)\x05(資)" +
+ "\x05(協)\x05(祭)\x05(休)\x05(自)\x05(至)\x0221\x0222\x0223\x0224\x0225\x0226" +
+ "\x0227\x0228\x0229\x0230\x0231\x0232\x0233\x0234\x0235\x06참고\x06주의\x0236" +
+ "\x0237\x0238\x0239\x0240\x0241\x0242\x0243\x0244\x0245\x0246\x0247\x0248" +
+ "\x0249\x0250\x041月\x042月\x043月\x044月\x045月\x046月\x047月\x048月\x049月\x0510" +
+ "月\x0511月\x0512月\x02hg\x02ev\x0cアパート\x0cアルファ\x0cアンペア\x09アール\x0cイニング\x09" +
+ "インチ\x09ウォン\x0fエスクード\x0cエーカー\x09オンス\x09オーム\x09カイリ\x0cカラット\x0cカロリー\x09ガロ" +
+ "ン\x09ガンマ\x06ギガ\x09ギニー\x0cキュリー\x0cギルダー\x06キロ\x0fキログラム\x12キロメートル\x0fキロワッ" +
+ "ト\x09グラム\x0fグラムトン\x0fクルゼイロ\x0cクローネ\x09ケース\x09コルナ\x09コーポ\x0cサイクル\x0fサンチ" +
+ "ーム\x0cシリング\x09センチ\x09セント\x09ダース\x06デシ\x06ドル\x06トン\x06ナノ\x09ノット\x09ハイツ" +
+ "\x0fパーセント\x09パーツ\x0cバーレル\x0fピアストル\x09ピクル\x06ピコ\x06ビル\x0fファラッド\x0cフィート" +
+ "\x0fブッシェル\x09フラン\x0fヘクタール\x06ペソ\x09ペニヒ\x09ヘルツ\x09ペンス\x09ページ\x09ベータ\x0cポイ" +
+ "ント\x09ボルト\x06ホン\x09ポンド\x09ホール\x09ホーン\x0cマイクロ\x09マイル\x09マッハ\x09マルク\x0fマ" +
+ "ンション\x0cミクロン\x06ミリ\x0fミリバール\x06メガ\x0cメガトン\x0cメートル\x09ヤード\x09ヤール\x09ユアン" +
+ "\x0cリットル\x06リラ\x09ルピー\x0cルーブル\x06レム\x0fレントゲン\x09ワット\x040点\x041点\x042点" +
+ "\x043点\x044点\x045点\x046点\x047点\x048点\x049点\x0510点\x0511点\x0512点\x0513点" +
+ "\x0514点\x0515点\x0516点\x0517点\x0518点\x0519点\x0520点\x0521点\x0522点\x0523点" +
+ "\x0524点\x02da\x02au\x02ov\x02pc\x02dm\x02iu\x06平成\x06昭和\x06大正\x06明治\x0c株" +
+ "式会社\x02pa\x02na\x02ma\x02ka\x02kb\x02mb\x02gb\x04kcal\x02pf\x02nf\x02m" +
+ "g\x02kg\x02hz\x02ml\x02dl\x02kl\x02fm\x02nm\x02mm\x02cm\x02km\x02m2\x02m" +
+ "3\x05m∕s\x06m∕s2\x07rad∕s\x08rad∕s2\x02ps\x02ns\x02ms\x02pv\x02nv\x02mv" +
+ "\x02kv\x02pw\x02nw\x02mw\x02kw\x02bq\x02cc\x02cd\x06c∕kg\x02db\x02gy\x02" +
+ "ha\x02hp\x02in\x02kk\x02kt\x02lm\x02ln\x02lx\x02ph\x02pr\x02sr\x02sv\x02" +
+ "wb\x05v∕m\x05a∕m\x041日\x042日\x043日\x044日\x045日\x046日\x047日\x048日\x049日" +
+ "\x0510日\x0511日\x0512日\x0513日\x0514日\x0515日\x0516日\x0517日\x0518日\x0519日" +
+ "\x0520日\x0521日\x0522日\x0523日\x0524日\x0525日\x0526日\x0527日\x0528日\x0529日" +
+ "\x0530日\x0531日\x02ь\x02ɦ\x02ɬ\x02ʞ\x02ʇ\x02œ\x04𤋮\x04𢡊\x04𢡄\x04𣏕\x04𥉉" +
+ "\x04𥳐\x04𧻓\x02ff\x02fi\x02fl\x02st\x04մն\x04մե\x04մի\x04վն\x04մխ\x04יִ" +
+ "\x04ײַ\x02ע\x02ה\x02כ\x02ל\x02ם\x02ר\x02ת\x04שׁ\x04שׂ\x06שּׁ\x06שּׂ\x04א" +
+ "ַ\x04אָ\x04אּ\x04בּ\x04גּ\x04דּ\x04הּ\x04וּ\x04זּ\x04טּ\x04יּ\x04ךּ\x04" +
+ "כּ\x04לּ\x04מּ\x04נּ\x04סּ\x04ףּ\x04פּ\x04צּ\x04קּ\x04רּ\x04שּ\x04תּ" +
+ "\x04וֹ\x04בֿ\x04כֿ\x04פֿ\x04אל\x02ٱ\x02ٻ\x02پ\x02ڀ\x02ٺ\x02ٿ\x02ٹ\x02ڤ" +
+ "\x02ڦ\x02ڄ\x02ڃ\x02چ\x02ڇ\x02ڍ\x02ڌ\x02ڎ\x02ڈ\x02ژ\x02ڑ\x02ک\x02گ\x02ڳ" +
+ "\x02ڱ\x02ں\x02ڻ\x02ۀ\x02ہ\x02ھ\x02ے\x02ۓ\x02ڭ\x02ۇ\x02ۆ\x02ۈ\x02ۋ\x02ۅ" +
+ "\x02ۉ\x02ې\x02ى\x04ئا\x04ئە\x04ئو\x04ئۇ\x04ئۆ\x04ئۈ\x04ئې\x04ئى\x02ی\x04" +
+ "ئج\x04ئح\x04ئم\x04ئي\x04بج\x04بح\x04بخ\x04بم\x04بى\x04بي\x04تج\x04تح" +
+ "\x04تخ\x04تم\x04تى\x04تي\x04ثج\x04ثم\x04ثى\x04ثي\x04جح\x04جم\x04حج\x04حم" +
+ "\x04خج\x04خح\x04خم\x04سج\x04سح\x04سخ\x04سم\x04صح\x04صم\x04ضج\x04ضح\x04ضخ" +
+ "\x04ضم\x04طح\x04طم\x04ظم\x04عج\x04عم\x04غج\x04غم\x04فج\x04فح\x04فخ\x04فم" +
+ "\x04فى\x04في\x04قح\x04قم\x04قى\x04قي\x04كا\x04كج\x04كح\x04كخ\x04كل\x04كم" +
+ "\x04كى\x04كي\x04لج\x04لح\x04لخ\x04لم\x04لى\x04لي\x04مج\x04مح\x04مخ\x04مم" +
+ "\x04مى\x04مي\x04نج\x04نح\x04نخ\x04نم\x04نى\x04ني\x04هج\x04هم\x04هى\x04هي" +
+ "\x04يج\x04يح\x04يخ\x04يم\x04يى\x04يي\x04ذٰ\x04رٰ\x04ىٰ\x05 ٌّ\x05 ٍّ\x05" +
+ " َّ\x05 ُّ\x05 ِّ\x05 ّٰ\x04ئر\x04ئز\x04ئن\x04بر\x04بز\x04بن\x04تر\x04تز" +
+ "\x04تن\x04ثر\x04ثز\x04ثن\x04ما\x04نر\x04نز\x04نن\x04ير\x04يز\x04ين\x04ئخ" +
+ "\x04ئه\x04به\x04ته\x04صخ\x04له\x04نه\x04هٰ\x04يه\x04ثه\x04سه\x04شم\x04شه" +
+ "\x06ـَّ\x06ـُّ\x06ـِّ\x04طى\x04طي\x04عى\x04عي\x04غى\x04غي\x04سى\x04سي" +
+ "\x04شى\x04شي\x04حى\x04حي\x04جى\x04جي\x04خى\x04خي\x04صى\x04صي\x04ضى\x04ضي" +
+ "\x04شج\x04شح\x04شخ\x04شر\x04سر\x04صر\x04ضر\x04اً\x06تجم\x06تحج\x06تحم" +
+ "\x06تخم\x06تمج\x06تمح\x06تمخ\x06جمح\x06حمي\x06حمى\x06سحج\x06سجح\x06سجى" +
+ "\x06سمح\x06سمج\x06سمم\x06صحح\x06صمم\x06شحم\x06شجي\x06شمخ\x06شمم\x06ضحى" +
+ "\x06ضخم\x06طمح\x06طمم\x06طمي\x06عجم\x06عمم\x06عمى\x06غمم\x06غمي\x06غمى" +
+ "\x06فخم\x06قمح\x06قمم\x06لحم\x06لحي\x06لحى\x06لجج\x06لخم\x06لمح\x06محج" +
+ "\x06محم\x06محي\x06مجح\x06مجم\x06مخج\x06مخم\x06مجخ\x06همج\x06همم\x06نحم" +
+ "\x06نحى\x06نجم\x06نجى\x06نمي\x06نمى\x06يمم\x06بخي\x06تجي\x06تجى\x06تخي" +
+ "\x06تخى\x06تمي\x06تمى\x06جمي\x06جحى\x06جمى\x06سخى\x06صحي\x06شحي\x06ضحي" +
+ "\x06لجي\x06لمي\x06يحي\x06يجي\x06يمي\x06ممي\x06قمي\x06نحي\x06عمي\x06كمي" +
+ "\x06نجح\x06مخي\x06لجم\x06كمم\x06جحي\x06حجي\x06مجي\x06فمي\x06بحي\x06سخي" +
+ "\x06نجي\x06صلے\x06قلے\x08الله\x08اكبر\x08محمد\x08صلعم\x08رسول\x08عليه" +
+ "\x08وسلم\x06صلى!صلى الله عليه وسلم\x0fجل جلاله\x08ریال\x01,\x01:\x01!" +
+ "\x01?\x01_\x01{\x01}\x01[\x01]\x01#\x01&\x01*\x01-\x01<\x01>\x01\\\x01$" +
+ "\x01%\x01@\x04ـً\x04ـَ\x04ـُ\x04ـِ\x04ـّ\x04ـْ\x02ء\x02آ\x02أ\x02ؤ\x02إ" +
+ "\x02ئ\x02ا\x02ب\x02ة\x02ت\x02ث\x02ج\x02ح\x02خ\x02د\x02ذ\x02ر\x02ز\x02س" +
+ "\x02ش\x02ص\x02ض\x02ط\x02ظ\x02ع\x02غ\x02ف\x02ق\x02ك\x02ل\x02م\x02ن\x02ه" +
+ "\x02و\x02ي\x04لآ\x04لأ\x04لإ\x04لا\x01\x22\x01'\x01/\x01^\x01|\x01~\x02¢" +
+ "\x02£\x02¬\x02¦\x02¥\x08𝅗𝅥\x08𝅘𝅥\x0c𝅘𝅥𝅮\x0c𝅘𝅥𝅯\x0c𝅘𝅥𝅰\x0c𝅘𝅥𝅱\x0c𝅘𝅥𝅲\x08𝆹" +
+ "𝅥\x08𝆺𝅥\x0c𝆹𝅥𝅮\x0c𝆺𝅥𝅮\x0c𝆹𝅥𝅯\x0c𝆺𝅥𝅯\x02ı\x02ȷ\x02α\x02ε\x02ζ\x02η\x02" +
+ "κ\x02λ\x02μ\x02ν\x02ξ\x02ο\x02σ\x02τ\x02υ\x02ψ\x03∇\x03∂\x02ϝ\x02ٮ\x02ڡ" +
+ "\x02ٯ\x020,\x021,\x022,\x023,\x024,\x025,\x026,\x027,\x028,\x029,\x03(a)" +
+ "\x03(b)\x03(c)\x03(d)\x03(e)\x03(f)\x03(g)\x03(h)\x03(i)\x03(j)\x03(k)" +
+ "\x03(l)\x03(m)\x03(n)\x03(o)\x03(p)\x03(q)\x03(r)\x03(s)\x03(t)\x03(u)" +
+ "\x03(v)\x03(w)\x03(x)\x03(y)\x03(z)\x07〔s〕\x02wz\x02hv\x02sd\x03ppv\x02w" +
+ "c\x02mc\x02md\x02dj\x06ほか\x06ココ\x03サ\x03手\x03字\x03双\x03デ\x03二\x03多\x03解" +
+ "\x03天\x03交\x03映\x03無\x03料\x03前\x03後\x03再\x03新\x03初\x03終\x03生\x03販\x03声" +
+ "\x03吹\x03演\x03投\x03捕\x03一\x03三\x03遊\x03左\x03中\x03右\x03指\x03走\x03打\x03禁" +
+ "\x03空\x03合\x03満\x03有\x03月\x03申\x03割\x03営\x03配\x09〔本〕\x09〔三〕\x09〔二〕\x09〔安" +
+ "〕\x09〔点〕\x09〔打〕\x09〔盗〕\x09〔勝〕\x09〔敗〕\x03得\x03可\x03丽\x03丸\x03乁\x03你\x03" +
+ "侮\x03侻\x03倂\x03偺\x03備\x03僧\x03像\x03㒞\x03免\x03兔\x03兤\x03具\x03㒹\x03內\x03" +
+ "冗\x03冤\x03仌\x03冬\x03况\x03凵\x03刃\x03㓟\x03刻\x03剆\x03剷\x03㔕\x03勇\x03勉\x03" +
+ "勤\x03勺\x03包\x03匆\x03北\x03卉\x03卑\x03博\x03即\x03卽\x03卿\x03灰\x03及\x03叟\x03" +
+ "叫\x03叱\x03吆\x03咞\x03吸\x03呈\x03周\x03咢\x03哶\x03唐\x03啓\x03啣\x03善\x03喙\x03" +
+ "喫\x03喳\x03嗂\x03圖\x03嘆\x03圗\x03噑\x03噴\x03切\x03壮\x03城\x03埴\x03堍\x03型\x03" +
+ "堲\x03報\x03墬\x03売\x03壷\x03夆\x03夢\x03奢\x03姬\x03娛\x03娧\x03姘\x03婦\x03㛮\x03" +
+ "嬈\x03嬾\x03寃\x03寘\x03寧\x03寳\x03寿\x03将\x03尢\x03㞁\x03屠\x03屮\x03峀\x03岍\x03" +
+ "嵃\x03嵮\x03嵫\x03嵼\x03巡\x03巢\x03㠯\x03巽\x03帨\x03帽\x03幩\x03㡢\x03㡼\x03庰\x03" +
+ "庳\x03庶\x03廊\x03廾\x03舁\x03弢\x03㣇\x03形\x03彫\x03㣣\x03徚\x03忍\x03志\x03忹\x03" +
+ "悁\x03㤺\x03㤜\x03悔\x03惇\x03慈\x03慌\x03慎\x03慺\x03憎\x03憲\x03憤\x03憯\x03懞\x03" +
+ "懲\x03懶\x03成\x03戛\x03扝\x03抱\x03拔\x03捐\x03挽\x03拼\x03捨\x03掃\x03揤\x03搢\x03" +
+ "揅\x03掩\x03㨮\x03摩\x03摾\x03撝\x03摷\x03㩬\x03敏\x03敬\x03旣\x03書\x03晉\x03㬙\x03" +
+ "暑\x03㬈\x03㫤\x03冒\x03冕\x03最\x03暜\x03肭\x03䏙\x03朗\x03望\x03朡\x03杞\x03杓\x03" +
+ "㭉\x03柺\x03枅\x03桒\x03梅\x03梎\x03栟\x03椔\x03㮝\x03楂\x03榣\x03槪\x03檨\x03櫛\x03" +
+ "㰘\x03次\x03歔\x03㱎\x03歲\x03殟\x03殺\x03殻\x03汎\x03沿\x03泍\x03汧\x03洖\x03派\x03" +
+ "海\x03流\x03浩\x03浸\x03涅\x03洴\x03港\x03湮\x03㴳\x03滋\x03滇\x03淹\x03潮\x03濆\x03" +
+ "瀹\x03瀞\x03瀛\x03㶖\x03灊\x03災\x03灷\x03炭\x03煅\x03熜\x03爨\x03爵\x03牐\x03犀\x03" +
+ "犕\x03獺\x03王\x03㺬\x03玥\x03㺸\x03瑇\x03瑜\x03瑱\x03璅\x03瓊\x03㼛\x03甤\x03甾\x03" +
+ "異\x03瘐\x03㿼\x03䀈\x03直\x03眞\x03真\x03睊\x03䀹\x03瞋\x03䁆\x03䂖\x03硎\x03碌\x03" +
+ "磌\x03䃣\x03祖\x03福\x03秫\x03䄯\x03穀\x03穊\x03穏\x03䈂\x03篆\x03築\x03䈧\x03糒\x03" +
+ "䊠\x03糨\x03糣\x03紀\x03絣\x03䌁\x03緇\x03縂\x03繅\x03䌴\x03䍙\x03罺\x03羕\x03翺\x03" +
+ "者\x03聠\x03聰\x03䏕\x03育\x03脃\x03䐋\x03脾\x03媵\x03舄\x03辞\x03䑫\x03芑\x03芋\x03" +
+ "芝\x03劳\x03花\x03芳\x03芽\x03苦\x03若\x03茝\x03荣\x03莭\x03茣\x03莽\x03菧\x03著\x03" +
+ "荓\x03菊\x03菌\x03菜\x03䔫\x03蓱\x03蓳\x03蔖\x03蕤\x03䕝\x03䕡\x03䕫\x03虐\x03虜\x03" +
+ "虧\x03虩\x03蚩\x03蚈\x03蜎\x03蛢\x03蝹\x03蜨\x03蝫\x03螆\x03蟡\x03蠁\x03䗹\x03衠\x03" +
+ "衣\x03裗\x03裞\x03䘵\x03裺\x03㒻\x03䚾\x03䛇\x03誠\x03諭\x03變\x03豕\x03貫\x03賁\x03" +
+ "贛\x03起\x03跋\x03趼\x03跰\x03軔\x03輸\x03邔\x03郱\x03鄑\x03鄛\x03鈸\x03鋗\x03鋘\x03" +
+ "鉼\x03鏹\x03鐕\x03開\x03䦕\x03閷\x03䧦\x03雃\x03嶲\x03霣\x03䩮\x03䩶\x03韠\x03䪲\x03" +
+ "頋\x03頩\x03飢\x03䬳\x03餩\x03馧\x03駂\x03駾\x03䯎\x03鬒\x03鱀\x03鳽\x03䳎\x03䳭\x03" +
+ "鵧\x03䳸\x03麻\x03䵖\x03黹\x03黾\x03鼅\x03鼏\x03鼖\x03鼻"
+
+var xorData string = "" + // Size: 4855 bytes
+ "\x02\x0c\x09\x02\xb0\xec\x02\xad\xd8\x02\xad\xd9\x02\x06\x07\x02\x0f\x12" +
+ "\x02\x0f\x1f\x02\x0f\x1d\x02\x01\x13\x02\x0f\x16\x02\x0f\x0b\x02\x0f3" +
+ "\x02\x0f7\x02\x0f?\x02\x0f/\x02\x0f*\x02\x0c&\x02\x0c*\x02\x0c;\x02\x0c9" +
+ "\x02\x0c%\x02\xab\xed\x02\xab\xe2\x02\xab\xe3\x02\xa9\xe0\x02\xa9\xe1" +
+ "\x02\xa9\xe6\x02\xa3\xcb\x02\xa3\xc8\x02\xa3\xc9\x02\x01#\x02\x01\x08" +
+ "\x02\x0e>\x02\x0e'\x02\x0f\x03\x02\x03\x0d\x02\x03\x09\x02\x03\x17\x02" +
+ "\x03\x0e\x02\x02\x03\x02\x011\x02\x01\x00\x02\x01\x10\x02\x03<\x02\x07" +
+ "\x0d\x02\x02\x0c\x02\x0c0\x02\x01\x03\x02\x01\x01\x02\x01 \x02\x01\x22" +
+ "\x02\x01)\x02\x01\x0a\x02\x01\x0c\x02\x02\x06\x02\x02\x02\x02\x03\x10" +
+ "\x03\x037 \x03\x0b+\x03\x02\x01\x04\x02\x01\x02\x02\x019\x02\x03\x1c\x02" +
+ "\x02$\x03\x80p$\x02\x03:\x02\x03\x0a\x03\xc1r.\x03\xc1r,\x03\xc1r\x02" +
+ "\x02\x02:\x02\x02>\x02\x02,\x02\x02\x10\x02\x02\x00\x03\xc1s<\x03\xc1s*" +
+ "\x03\xc2L$\x03\xc2L;\x02\x09)\x02\x0a\x19\x03\x83\xab\xe3\x03\x83\xab" +
+ "\xf2\x03 4\xe0\x03\x81\xab\xea\x03\x81\xab\xf3\x03 4\xef\x03\x96\xe1\xcd" +
+ "\x03\x84\xe5\xc3\x02\x0d\x11\x03\x8b\xec\xcb\x03\x94\xec\xcf\x03\x9a\xec" +
+ "\xc2\x03\x8b\xec\xdb\x03\x94\xec\xdf\x03\x9a\xec\xd2\x03\x01\x0c!\x03" +
+ "\x01\x0c#\x03ʠ\x9d\x03ʣ\x9c\x03ʢ\x9f\x03ʥ\x9e\x03ʤ\x91\x03ʧ\x90\x03ʦ\x93" +
+ "\x03ʩ\x92\x03ʨ\x95\x03\xca\xf3\xb5\x03\xca\xf0\xb4\x03\xca\xf1\xb7\x03" +
+ "\xca\xf6\xb6\x03\xca\xf7\x89\x03\xca\xf4\x88\x03\xca\xf5\x8b\x03\xca\xfa" +
+ "\x8a\x03\xca\xfb\x8d\x03\xca\xf8\x8c\x03\xca\xf9\x8f\x03\xca\xfe\x8e\x03" +
+ "\xca\xff\x81\x03\xca\xfc\x80\x03\xca\xfd\x83\x03\xca\xe2\x82\x03\xca\xe3" +
+ "\x85\x03\xca\xe0\x84\x03\xca\xe1\x87\x03\xca\xe6\x86\x03\xca\xe7\x99\x03" +
+ "\xca\xe4\x98\x03\xca\xe5\x9b\x03\xca\xea\x9a\x03\xca\xeb\x9d\x03\xca\xe8" +
+ "\x9c\x03ؓ\x89\x03ߔ\x8b\x02\x010\x03\x03\x04\x1e\x03\x04\x15\x12\x03\x0b" +
+ "\x05,\x03\x06\x04\x00\x03\x06\x04)\x03\x06\x044\x03\x06\x04<\x03\x06\x05" +
+ "\x1d\x03\x06\x06\x00\x03\x06\x06\x0a\x03\x06\x06'\x03\x06\x062\x03\x0786" +
+ "\x03\x079/\x03\x079 \x03\x07:\x0e\x03\x07:\x1b\x03\x07:%\x03\x07;/\x03" +
+ "\x07;%\x03\x074\x11\x03\x076\x09\x03\x077*\x03\x070\x01\x03\x070\x0f\x03" +
+ "\x070.\x03\x071\x16\x03\x071\x04\x03\x0710\x03\x072\x18\x03\x072-\x03" +
+ "\x073\x14\x03\x073>\x03\x07'\x09\x03\x07 \x00\x03\x07\x1f\x0b\x03\x07" +
+ "\x18#\x03\x07\x18(\x03\x07\x186\x03\x07\x18\x03\x03\x07\x19\x16\x03\x07" +
+ "\x116\x03\x07\x12'\x03\x07\x13\x10\x03\x07\x0c&\x03\x07\x0c\x08\x03\x07" +
+ "\x0c\x13\x03\x07\x0d\x02\x03\x07\x0d\x1c\x03\x07\x0b5\x03\x07\x0b\x0a" +
+ "\x03\x07\x0b\x01\x03\x07\x0b\x0f\x03\x07\x05\x00\x03\x07\x05\x09\x03\x07" +
+ "\x05\x0b\x03\x07\x07\x01\x03\x07\x07\x08\x03\x07\x00<\x03\x07\x00+\x03" +
+ "\x07\x01)\x03\x07\x01\x1b\x03\x07\x01\x08\x03\x07\x03?\x03\x0445\x03\x04" +
+ "4\x08\x03\x0454\x03\x04)/\x03\x04)5\x03\x04+\x05\x03\x04+\x14\x03\x04+ " +
+ "\x03\x04+<\x03\x04*&\x03\x04*\x22\x03\x04&8\x03\x04!\x01\x03\x04!\x22" +
+ "\x03\x04\x11+\x03\x04\x10.\x03\x04\x104\x03\x04\x13=\x03\x04\x12\x04\x03" +
+ "\x04\x12\x0a\x03\x04\x0d\x1d\x03\x04\x0d\x07\x03\x04\x0d \x03\x05<>\x03" +
+ "\x055<\x03\x055!\x03\x055#\x03\x055&\x03\x054\x1d\x03\x054\x02\x03\x054" +
+ "\x07\x03\x0571\x03\x053\x1a\x03\x053\x16\x03\x05.<\x03\x05.\x07\x03\x05)" +
+ ":\x03\x05)<\x03\x05)\x0c\x03\x05)\x15\x03\x05+-\x03\x05+5\x03\x05$\x1e" +
+ "\x03\x05$\x14\x03\x05'\x04\x03\x05'\x14\x03\x05&\x02\x03\x05\x226\x03" +
+ "\x05\x22\x0c\x03\x05\x22\x1c\x03\x05\x19\x0a\x03\x05\x1b\x09\x03\x05\x1b" +
+ "\x0c\x03\x05\x14\x07\x03\x05\x16?\x03\x05\x16\x0c\x03\x05\x0c\x05\x03" +
+ "\x05\x0e\x0f\x03\x05\x01\x0e\x03\x05\x00(\x03\x05\x030\x03\x05\x03\x06" +
+ "\x03\x0a==\x03\x0a=1\x03\x0a=,\x03\x0a=\x0c\x03\x0a??\x03\x0a<\x08\x03" +
+ "\x0a9!\x03\x0a9)\x03\x0a97\x03\x0a99\x03\x0a6\x0a\x03\x0a6\x1c\x03\x0a6" +
+ "\x17\x03\x0a7'\x03\x0a78\x03\x0a73\x03\x0a'\x01\x03\x0a'&\x03\x0a\x1f" +
+ "\x0e\x03\x0a\x1f\x03\x03\x0a\x1f3\x03\x0a\x1b/\x03\x0a\x18\x19\x03\x0a" +
+ "\x19\x01\x03\x0a\x16\x14\x03\x0a\x0e\x22\x03\x0a\x0f\x10\x03\x0a\x0f\x02" +
+ "\x03\x0a\x0f \x03\x0a\x0c\x04\x03\x0a\x0b>\x03\x0a\x0b+\x03\x0a\x08/\x03" +
+ "\x0a\x046\x03\x0a\x05\x14\x03\x0a\x00\x04\x03\x0a\x00\x10\x03\x0a\x00" +
+ "\x14\x03\x0b<3\x03\x0b;*\x03\x0b9\x22\x03\x0b9)\x03\x0b97\x03\x0b+\x10" +
+ "\x03\x0b((\x03\x0b&5\x03\x0b$\x1c\x03\x0b$\x12\x03\x0b%\x04\x03\x0b#<" +
+ "\x03\x0b#0\x03\x0b#\x0d\x03\x0b#\x19\x03\x0b!:\x03\x0b!\x1f\x03\x0b!\x00" +
+ "\x03\x0b\x1e5\x03\x0b\x1c\x1d\x03\x0b\x1d-\x03\x0b\x1d(\x03\x0b\x18.\x03" +
+ "\x0b\x18 \x03\x0b\x18\x16\x03\x0b\x14\x13\x03\x0b\x15$\x03\x0b\x15\x22" +
+ "\x03\x0b\x12\x1b\x03\x0b\x12\x10\x03\x0b\x132\x03\x0b\x13=\x03\x0b\x12" +
+ "\x18\x03\x0b\x0c&\x03\x0b\x061\x03\x0b\x06:\x03\x0b\x05#\x03\x0b\x05<" +
+ "\x03\x0b\x04\x0b\x03\x0b\x04\x04\x03\x0b\x04\x1b\x03\x0b\x042\x03\x0b" +
+ "\x041\x03\x0b\x03\x03\x03\x0b\x03\x1d\x03\x0b\x03/\x03\x0b\x03+\x03\x0b" +
+ "\x02\x1b\x03\x0b\x02\x00\x03\x0b\x01\x1e\x03\x0b\x01\x08\x03\x0b\x015" +
+ "\x03\x06\x0d9\x03\x06\x0d=\x03\x06\x0d?\x03\x02\x001\x03\x02\x003\x03" +
+ "\x02\x02\x19\x03\x02\x006\x03\x02\x02\x1b\x03\x02\x004\x03\x02\x00<\x03" +
+ "\x02\x02\x0a\x03\x02\x02\x0e\x03\x02\x01\x1a\x03\x02\x01\x07\x03\x02\x01" +
+ "\x05\x03\x02\x01\x0b\x03\x02\x01%\x03\x02\x01\x0c\x03\x02\x01\x04\x03" +
+ "\x02\x01\x1c\x03\x02\x00.\x03\x02\x002\x03\x02\x00>\x03\x02\x00\x12\x03" +
+ "\x02\x00\x16\x03\x02\x011\x03\x02\x013\x03\x02\x02 \x03\x02\x02%\x03\x02" +
+ "\x02$\x03\x02\x028\x03\x02\x02;\x03\x02\x024\x03\x02\x012\x03\x02\x022" +
+ "\x03\x02\x02/\x03\x02\x01,\x03\x02\x01\x13\x03\x02\x01\x16\x03\x02\x01" +
+ "\x11\x03\x02\x01\x1e\x03\x02\x01\x15\x03\x02\x01\x17\x03\x02\x01\x0f\x03" +
+ "\x02\x01\x08\x03\x02\x00?\x03\x02\x03\x07\x03\x02\x03\x0d\x03\x02\x03" +
+ "\x13\x03\x02\x03\x1d\x03\x02\x03\x1f\x03\x02\x00\x03\x03\x02\x00\x0d\x03" +
+ "\x02\x00\x01\x03\x02\x00\x1b\x03\x02\x00\x19\x03\x02\x00\x18\x03\x02\x00" +
+ "\x13\x03\x02\x00/\x03\x07>\x12\x03\x07<\x1f\x03\x07>\x1d\x03\x06\x1d\x0e" +
+ "\x03\x07>\x1c\x03\x07>:\x03\x07>\x13\x03\x04\x12+\x03\x07?\x03\x03\x07>" +
+ "\x02\x03\x06\x224\x03\x06\x1a.\x03\x07<%\x03\x06\x1c\x0b\x03\x0609\x03" +
+ "\x05\x1f\x01\x03\x04'\x08\x03\x93\xfd\xf5\x03\x02\x0d \x03\x02\x0d#\x03" +
+ "\x02\x0d!\x03\x02\x0d&\x03\x02\x0d\x22\x03\x02\x0d/\x03\x02\x0d,\x03\x02" +
+ "\x0d$\x03\x02\x0d'\x03\x02\x0d%\x03\x02\x0d;\x03\x02\x0d=\x03\x02\x0d?" +
+ "\x03\x099.\x03\x08\x0b7\x03\x08\x02\x14\x03\x08\x14\x0d\x03\x08.:\x03" +
+ "\x089'\x03\x0f\x0b\x18\x03\x0f\x1c1\x03\x0f\x17&\x03\x0f9\x1f\x03\x0f0" +
+ "\x0c\x03\x0e\x0a9\x03\x0e\x056\x03\x0e\x1c#\x03\x0f\x13\x0e\x03\x072\x00" +
+ "\x03\x070\x0d\x03\x072\x0b\x03\x06\x11\x18\x03\x070\x10\x03\x06\x0f(\x03" +
+ "\x072\x05\x03\x06\x0f,\x03\x073\x15\x03\x06\x07\x08\x03\x05\x16\x02\x03" +
+ "\x04\x0b \x03\x05:8\x03\x05\x16%\x03\x0a\x0d\x1f\x03\x06\x16\x10\x03\x05" +
+ "\x1d5\x03\x05*;\x03\x05\x16\x1b\x03\x04.-\x03\x06\x1a\x19\x03\x04\x03," +
+ "\x03\x0b87\x03\x04/\x0a\x03\x06\x00,\x03\x04-\x01\x03\x04\x1e-\x03\x06/(" +
+ "\x03\x0a\x0b5\x03\x06\x0e7\x03\x06\x07.\x03\x0597\x03\x0a*%\x03\x0760" +
+ "\x03\x06\x0c;\x03\x05'\x00\x03\x072.\x03\x072\x08\x03\x06=\x01\x03\x06" +
+ "\x05\x1b\x03\x06\x06\x12\x03\x06$=\x03\x06'\x0d\x03\x04\x11\x0f\x03\x076" +
+ ",\x03\x06\x07;\x03\x06.,\x03\x86\xf9\xea\x03\x8f\xff\xeb\x02\x092\x02" +
+ "\x095\x02\x094\x02\x09;\x02\x09>\x02\x098\x02\x09*\x02\x09/\x02\x09,\x02" +
+ "\x09%\x02\x09&\x02\x09#\x02\x09 \x02\x08!\x02\x08%\x02\x08$\x02\x08+\x02" +
+ "\x08.\x02\x08*\x02\x08&\x02\x088\x02\x08>\x02\x084\x02\x086\x02\x080\x02" +
+ "\x08\x10\x02\x08\x17\x02\x08\x12\x02\x08\x1d\x02\x08\x1f\x02\x08\x13\x02" +
+ "\x08\x15\x02\x08\x14\x02\x08\x0c\x03\x8b\xfd\xd0\x03\x81\xec\xc6\x03\x87" +
+ "\xe0\x8a\x03-2\xe3\x03\x80\xef\xe4\x03-2\xea\x03\x88\xe6\xeb\x03\x8e\xe6" +
+ "\xe8\x03\x84\xe6\xe9\x03\x97\xe6\xee\x03-2\xf9\x03-2\xf6\x03\x8e\xe3\xad" +
+ "\x03\x80\xe3\x92\x03\x88\xe3\x90\x03\x8e\xe3\x90\x03\x80\xe3\x97\x03\x88" +
+ "\xe3\x95\x03\x88\xfe\xcb\x03\x8e\xfe\xca\x03\x84\xfe\xcd\x03\x91\xef\xc9" +
+ "\x03-2\xc1\x03-2\xc0\x03-2\xcb\x03\x88@\x09\x03\x8e@\x08\x03\x8f\xe0\xf5" +
+ "\x03\x8e\xe6\xf9\x03\x8e\xe0\xfa\x03\x93\xff\xf4\x03\x84\xee\xd3\x03\x0b" +
+ "(\x04\x023 \x021;\x02\x01*\x03\x0b#\x10\x03\x0b 0\x03\x0b!\x10\x03\x0b!0" +
+ "\x03\x07\x15\x08\x03\x09?5\x03\x07\x1f\x08\x03\x07\x17\x0b\x03\x09\x1f" +
+ "\x15\x03\x0b\x1c7\x03\x0a+#\x03\x06\x1a\x1b\x03\x06\x1a\x14\x03\x0a\x01" +
+ "\x18\x03\x06#\x1b\x03\x0a2\x0c\x03\x0a\x01\x04\x03\x09#;\x03\x08='\x03" +
+ "\x08\x1a\x0a\x03\x07</\x03\x07:+\x03\x07\x07*\x03\x06&\x1c\x03\x09\x0c" +
+ "\x16\x03\x09\x10\x0e\x03\x08'\x0f\x03\x08+\x09\x03\x074%\x03\x06!3\x03" +
+ "\x06\x03+\x03\x0b\x1e\x19\x03\x0a))\x03\x09\x08\x19\x03\x08,\x05\x03\x07" +
+ "<2\x03\x06\x1c>\x03\x0a\x111\x03\x09\x1b\x09\x03\x073.\x03\x07\x01\x00" +
+ "\x03\x09/,\x03\x07#>\x03\x07\x048\x03\x0a\x1f\x22\x03\x098>\x03\x09\x11" +
+ "\x00\x03\x08/\x17\x03\x06'\x22\x03\x0b\x1a+\x03\x0a\x22\x19\x03\x0a/1" +
+ "\x03\x0974\x03\x09\x0f\x22\x03\x08,\x22\x03\x08?\x14\x03\x07$5\x03\x07<3" +
+ "\x03\x07=*\x03\x07\x13\x18\x03\x068\x0a\x03\x06\x09\x16\x03\x06\x13\x00" +
+ "\x03\x08\x067\x03\x08\x01\x03\x03\x08\x12\x1d\x03\x07+7\x03\x06(;\x03" +
+ "\x06\x1c?\x03\x07\x0e\x17\x03\x0a\x06\x1d\x03\x0a\x19\x07\x03\x08\x14$" +
+ "\x03\x07$;\x03\x08,$\x03\x08\x06\x0d\x03\x07\x16\x0a\x03\x06>>\x03\x0a" +
+ "\x06\x12\x03\x0a\x14)\x03\x09\x0d\x1f\x03\x09\x12\x17\x03\x09\x19\x01" +
+ "\x03\x08\x11 \x03\x08\x1d'\x03\x06<\x1a\x03\x0a.\x00\x03\x07'\x18\x03" +
+ "\x0a\x22\x08\x03\x08\x0d\x0a\x03\x08\x13)\x03\x07*)\x03\x06<,\x03\x07" +
+ "\x0b\x1a\x03\x09.\x14\x03\x09\x0d\x1e\x03\x07\x0e#\x03\x0b\x1d'\x03\x0a" +
+ "\x0a8\x03\x09%2\x03\x08+&\x03\x080\x12\x03\x0a)4\x03\x08\x06\x1f\x03\x0b" +
+ "\x1b\x1a\x03\x0a\x1b\x0f\x03\x0b\x1d*\x03\x09\x16$\x03\x090\x11\x03\x08" +
+ "\x11\x08\x03\x0a*(\x03\x0a\x042\x03\x089,\x03\x074'\x03\x07\x0f\x05\x03" +
+ "\x09\x0b\x0a\x03\x07\x1b\x01\x03\x09\x17:\x03\x09.\x0d\x03\x07.\x11\x03" +
+ "\x09+\x15\x03\x080\x13\x03\x0b\x1f\x19\x03\x0a \x11\x03\x0a\x220\x03\x09" +
+ "\x07;\x03\x08\x16\x1c\x03\x07,\x13\x03\x07\x0e/\x03\x06\x221\x03\x0a." +
+ "\x0a\x03\x0a7\x02\x03\x0a\x032\x03\x0a\x1d.\x03\x091\x06\x03\x09\x19:" +
+ "\x03\x08\x02/\x03\x060+\x03\x06\x0f-\x03\x06\x1c\x1f\x03\x06\x1d\x07\x03" +
+ "\x0a,\x11\x03\x09=\x0d\x03\x09\x0b;\x03\x07\x1b/\x03\x0a\x1f:\x03\x09 " +
+ "\x1f\x03\x09.\x10\x03\x094\x0b\x03\x09\x1a1\x03\x08#\x1a\x03\x084\x1d" +
+ "\x03\x08\x01\x1f\x03\x08\x11\x22\x03\x07'8\x03\x07\x1a>\x03\x0757\x03" +
+ "\x06&9\x03\x06+\x11\x03\x0a.\x0b\x03\x0a,>\x03\x0a4#\x03\x08%\x17\x03" +
+ "\x07\x05\x22\x03\x07\x0c\x0b\x03\x0a\x1d+\x03\x0a\x19\x16\x03\x09+\x1f" +
+ "\x03\x09\x08\x0b\x03\x08\x16\x18\x03\x08+\x12\x03\x0b\x1d\x0c\x03\x0a=" +
+ "\x10\x03\x0a\x09\x0d\x03\x0a\x10\x11\x03\x09&0\x03\x08(\x1f\x03\x087\x07" +
+ "\x03\x08\x185\x03\x07'6\x03\x06.\x05\x03\x06=\x04\x03\x06;;\x03\x06\x06," +
+ "\x03\x0b\x18>\x03\x08\x00\x18\x03\x06 \x03\x03\x06<\x00\x03\x09%\x18\x03" +
+ "\x0b\x1c<\x03\x0a%!\x03\x0a\x09\x12\x03\x0a\x16\x02\x03\x090'\x03\x09" +
+ "\x0e=\x03\x08 \x0e\x03\x08>\x03\x03\x074>\x03\x06&?\x03\x06\x19\x09\x03" +
+ "\x06?(\x03\x0a-\x0e\x03\x09:3\x03\x098:\x03\x09\x12\x0b\x03\x09\x1d\x17" +
+ "\x03\x087\x05\x03\x082\x14\x03\x08\x06%\x03\x08\x13\x1f\x03\x06\x06\x0e" +
+ "\x03\x0a\x22<\x03\x09/<\x03\x06>+\x03\x0a'?\x03\x0a\x13\x0c\x03\x09\x10<" +
+ "\x03\x07\x1b=\x03\x0a\x19\x13\x03\x09\x22\x1d\x03\x09\x07\x0d\x03\x08)" +
+ "\x1c\x03\x06=\x1a\x03\x0a/4\x03\x0a7\x11\x03\x0a\x16:\x03\x09?3\x03\x09:" +
+ "/\x03\x09\x05\x0a\x03\x09\x14\x06\x03\x087\x22\x03\x080\x07\x03\x08\x1a" +
+ "\x1f\x03\x07\x04(\x03\x07\x04\x09\x03\x06 %\x03\x06<\x08\x03\x0a+\x14" +
+ "\x03\x09\x1d\x16\x03\x0a70\x03\x08 >\x03\x0857\x03\x070\x0a\x03\x06=\x12" +
+ "\x03\x06\x16%\x03\x06\x1d,\x03\x099#\x03\x09\x10>\x03\x07 \x1e\x03\x08" +
+ "\x0c<\x03\x08\x0b\x18\x03\x08\x15+\x03\x08,:\x03\x08%\x22\x03\x07\x0a$" +
+ "\x03\x0b\x1c=\x03\x07+\x08\x03\x0a/\x05\x03\x0a \x07\x03\x0a\x12'\x03" +
+ "\x09#\x11\x03\x08\x1b\x15\x03\x0a\x06\x01\x03\x09\x1c\x1b\x03\x0922\x03" +
+ "\x07\x14<\x03\x07\x09\x04\x03\x061\x04\x03\x07\x0e\x01\x03\x0a\x13\x18" +
+ "\x03\x0a-\x0c\x03\x0a?\x0d\x03\x0a\x09\x0a\x03\x091&\x03\x0a/\x0b\x03" +
+ "\x08$<\x03\x083\x1d\x03\x08\x0c$\x03\x08\x0d\x07\x03\x08\x0d?\x03\x08" +
+ "\x0e\x14\x03\x065\x0a\x03\x08\x1a#\x03\x08\x16#\x03\x0702\x03\x07\x03" +
+ "\x1a\x03\x06(\x1d\x03\x06+\x1b\x03\x06\x0b\x05\x03\x06\x0b\x17\x03\x06" +
+ "\x0c\x04\x03\x06\x1e\x19\x03\x06+0\x03\x062\x18\x03\x0b\x16\x1e\x03\x0a+" +
+ "\x16\x03\x0a-?\x03\x0a#:\x03\x0a#\x10\x03\x0a%$\x03\x0a>+\x03\x0a01\x03" +
+ "\x0a1\x10\x03\x0a\x099\x03\x0a\x0a\x12\x03\x0a\x19\x1f\x03\x0a\x19\x12" +
+ "\x03\x09*)\x03\x09-\x16\x03\x09.1\x03\x09.2\x03\x09<\x0e\x03\x09> \x03" +
+ "\x093\x12\x03\x09\x0b\x01\x03\x09\x1c2\x03\x09\x11\x1c\x03\x09\x15%\x03" +
+ "\x08,&\x03\x08!\x22\x03\x089(\x03\x08\x0b\x1a\x03\x08\x0d2\x03\x08\x0c" +
+ "\x04\x03\x08\x0c\x06\x03\x08\x0c\x1f\x03\x08\x0c\x0c\x03\x08\x0f\x1f\x03" +
+ "\x08\x0f\x1d\x03\x08\x00\x14\x03\x08\x03\x14\x03\x08\x06\x16\x03\x08\x1e" +
+ "#\x03\x08\x11\x11\x03\x08\x10\x18\x03\x08\x14(\x03\x07)\x1e\x03\x07.1" +
+ "\x03\x07 $\x03\x07 '\x03\x078\x08\x03\x07\x0d0\x03\x07\x0f7\x03\x07\x05#" +
+ "\x03\x07\x05\x1a\x03\x07\x1a7\x03\x07\x1d-\x03\x07\x17\x10\x03\x06)\x1f" +
+ "\x03\x062\x0b\x03\x066\x16\x03\x06\x09\x11\x03\x09(\x1e\x03\x07!5\x03" +
+ "\x0b\x11\x16\x03\x0a/\x04\x03\x0a,\x1a\x03\x0b\x173\x03\x0a,1\x03\x0a/5" +
+ "\x03\x0a\x221\x03\x0a\x22\x0d\x03\x0a?%\x03\x0a<,\x03\x0a?#\x03\x0a>\x19" +
+ "\x03\x0a\x08&\x03\x0a\x0b\x0e\x03\x0a\x0c:\x03\x0a\x0c+\x03\x0a\x03\x22" +
+ "\x03\x0a\x06)\x03\x0a\x11\x10\x03\x0a\x11\x1a\x03\x0a\x17-\x03\x0a\x14(" +
+ "\x03\x09)\x1e\x03\x09/\x09\x03\x09.\x00\x03\x09,\x07\x03\x09/*\x03\x09-9" +
+ "\x03\x09\x228\x03\x09%\x09\x03\x09:\x12\x03\x09;\x1d\x03\x09?\x06\x03" +
+ "\x093%\x03\x096\x05\x03\x096\x08\x03\x097\x02\x03\x09\x07,\x03\x09\x04," +
+ "\x03\x09\x1f\x16\x03\x09\x11\x03\x03\x09\x11\x12\x03\x09\x168\x03\x08*" +
+ "\x05\x03\x08/2\x03\x084:\x03\x08\x22+\x03\x08 0\x03\x08&\x0a\x03\x08;" +
+ "\x10\x03\x08>$\x03\x08>\x18\x03\x0829\x03\x082:\x03\x081,\x03\x081<\x03" +
+ "\x081\x1c\x03\x087#\x03\x087*\x03\x08\x09'\x03\x08\x00\x1d\x03\x08\x05-" +
+ "\x03\x08\x1f4\x03\x08\x1d\x04\x03\x08\x16\x0f\x03\x07*7\x03\x07'!\x03" +
+ "\x07%\x1b\x03\x077\x0c\x03\x07\x0c1\x03\x07\x0c.\x03\x07\x00\x06\x03\x07" +
+ "\x01\x02\x03\x07\x010\x03\x07\x06=\x03\x07\x01\x03\x03\x07\x01\x13\x03" +
+ "\x07\x06\x06\x03\x07\x05\x0a\x03\x07\x1f\x09\x03\x07\x17:\x03\x06*1\x03" +
+ "\x06-\x1d\x03\x06\x223\x03\x062:\x03\x060$\x03\x066\x1e\x03\x064\x12\x03" +
+ "\x0645\x03\x06\x0b\x00\x03\x06\x0b7\x03\x06\x07\x1f\x03\x06\x15\x12\x03" +
+ "\x0c\x05\x0f\x03\x0b+\x0b\x03\x0b+-\x03\x06\x16\x1b\x03\x06\x15\x17\x03" +
+ "\x89\xca\xea\x03\x89\xca\xe8\x03\x0c8\x10\x03\x0c8\x01\x03\x0c8\x0f\x03" +
+ "\x0d8%\x03\x0d8!\x03\x0c8-\x03\x0c8/\x03\x0c8+\x03\x0c87\x03\x0c85\x03" +
+ "\x0c9\x09\x03\x0c9\x0d\x03\x0c9\x0f\x03\x0c9\x0b\x03\xcfu\x0c\x03\xcfu" +
+ "\x0f\x03\xcfu\x0e\x03\xcfu\x09\x03\x0c9\x10\x03\x0d9\x0c\x03\xcf`;\x03" +
+ "\xcf`>\x03\xcf`9\x03\xcf`8\x03\xcf`7\x03\xcf`*\x03\xcf`-\x03\xcf`,\x03" +
+ "\x0d\x1b\x1a\x03\x0d\x1b&\x03\x0c=.\x03\x0c=%\x03\x0c>\x1e\x03\x0c>\x14" +
+ "\x03\x0c?\x06\x03\x0c?\x0b\x03\x0c?\x0c\x03\x0c?\x0d\x03\x0c?\x02\x03" +
+ "\x0c>\x0f\x03\x0c>\x08\x03\x0c>\x09\x03\x0c>,\x03\x0c>\x0c\x03\x0c?\x13" +
+ "\x03\x0c?\x16\x03\x0c?\x15\x03\x0c?\x1c\x03\x0c?\x1f\x03\x0c?\x1d\x03" +
+ "\x0c?\x1a\x03\x0c?\x17\x03\x0c?\x08\x03\x0c?\x09\x03\x0c?\x0e\x03\x0c?" +
+ "\x04\x03\x0c?\x05\x03\x0c<?\x03\x0c=\x00\x03\x0c=\x06\x03\x0c=\x05\x03" +
+ "\x0c=\x0c\x03\x0c=\x0f\x03\x0c=\x0d\x03\x0c=\x0b\x03\x0c=\x07\x03\x0c=" +
+ "\x19\x03\x0c=\x15\x03\x0c=\x11\x03\x0c=1\x03\x0c=3\x03\x0c=0\x03\x0c=>" +
+ "\x03\x0c=2\x03\x0c=6\x03\x0c<\x07\x03\x0c<\x05\x03\x0e:!\x03\x0e:#\x03" +
+ "\x0e8\x09\x03\x0e:&\x03\x0e8\x0b\x03\x0e:$\x03\x0e:,\x03\x0e8\x1a\x03" +
+ "\x0e8\x1e\x03\x0e:*\x03\x0e:7\x03\x0e:5\x03\x0e:;\x03\x0e:\x15\x03\x0e:<" +
+ "\x03\x0e:4\x03\x0e:'\x03\x0e:-\x03\x0e:%\x03\x0e:?\x03\x0e:=\x03\x0e:)" +
+ "\x03\x0e:/\x03\xcfs'\x03\x0d=\x0f\x03\x0d+*\x03\x0d99\x03\x0d9;\x03\x0d9" +
+ "?\x03\x0d)\x0d\x03\x0d(%\x02\x01\x18\x02\x01(\x02\x01\x1e\x03\x0f$!\x03" +
+ "\x0f87\x03\x0f4\x0e\x03\x0f5\x1d\x03\x06'\x03\x03\x0f\x08\x18\x03\x0f" +
+ "\x0d\x1b\x03\x0e2=\x03\x0e;\x08\x03\x0e:\x0b\x03\x0e\x06$\x03\x0e\x0d)" +
+ "\x03\x0e\x16\x1f\x03\x0e\x16\x1b\x03\x0d$\x0a\x03\x05,\x1d\x03\x0d. \x03" +
+ "\x0d.#\x03\x0c(/\x03\x09%\x02\x03\x0d90\x03\x0d\x0e4\x03\x0d\x0d\x0f\x03" +
+ "\x0c#\x00\x03\x0c,\x1e\x03\x0c2\x0e\x03\x0c\x01\x17\x03\x0c\x09:\x03\x0e" +
+ "\x173\x03\x0c\x08\x03\x03\x0c\x11\x07\x03\x0c\x10\x18\x03\x0c\x1f\x1c" +
+ "\x03\x0c\x19\x0e\x03\x0c\x1a\x1f\x03\x0f0>\x03\x0b->\x03\x0b<+\x03\x0b8" +
+ "\x13\x03\x0b\x043\x03\x0b\x14\x03\x03\x0b\x16%\x03\x0d\x22&\x03\x0b\x1a" +
+ "\x1a\x03\x0b\x1a\x04\x03\x0a%9\x03\x0a&2\x03\x0a&0\x03\x0a!\x1a\x03\x0a!" +
+ "7\x03\x0a5\x10\x03\x0a=4\x03\x0a?\x0e\x03\x0a>\x10\x03\x0a\x00 \x03\x0a" +
+ "\x0f:\x03\x0a\x0f9\x03\x0a\x0b\x0a\x03\x0a\x17%\x03\x0a\x1b-\x03\x09-" +
+ "\x1a\x03\x09,4\x03\x09.,\x03\x09)\x09\x03\x096!\x03\x091\x1f\x03\x093" +
+ "\x16\x03\x0c+\x1f\x03\x098 \x03\x098=\x03\x0c(\x1a\x03\x0c(\x16\x03\x09" +
+ "\x0a+\x03\x09\x16\x12\x03\x09\x13\x0e\x03\x09\x153\x03\x08)!\x03\x09\x1a" +
+ "\x01\x03\x09\x18\x01\x03\x08%#\x03\x08>\x22\x03\x08\x05%\x03\x08\x02*" +
+ "\x03\x08\x15;\x03\x08\x1b7\x03\x0f\x07\x1d\x03\x0f\x04\x03\x03\x070\x0c" +
+ "\x03\x07;\x0b\x03\x07\x08\x17\x03\x07\x12\x06\x03\x06/-\x03\x0671\x03" +
+ "\x065+\x03\x06>7\x03\x06\x049\x03\x05+\x1e\x03\x05,\x17\x03\x05 \x1d\x03" +
+ "\x05\x22\x05\x03\x050\x1d"
+
+// lookup returns the trie value for the first UTF-8 encoding in s and
+// the width in bytes of this encoding. The size will be 0 if s does not
+// hold enough bytes to complete the encoding. len(s) must be greater than 0.
+func (t *idnaTrie) lookup(s []byte) (v uint16, sz int) {
+ c0 := s[0]
+ switch {
+ case c0 < 0x80: // is ASCII
+ return idnaValues[c0], 1
+ case c0 < 0xC2:
+ return 0, 1 // Illegal UTF-8: not a starter, not ASCII.
+ case c0 < 0xE0: // 2-byte UTF-8
+ if len(s) < 2 {
+ return 0, 0
+ }
+ i := idnaIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return 0, 1 // Illegal UTF-8: not a continuation byte.
+ }
+ return t.lookupValue(uint32(i), c1), 2
+ case c0 < 0xF0: // 3-byte UTF-8
+ if len(s) < 3 {
+ return 0, 0
+ }
+ i := idnaIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return 0, 1 // Illegal UTF-8: not a continuation byte.
+ }
+ o := uint32(i)<<6 + uint32(c1)
+ i = idnaIndex[o]
+ c2 := s[2]
+ if c2 < 0x80 || 0xC0 <= c2 {
+ return 0, 2 // Illegal UTF-8: not a continuation byte.
+ }
+ return t.lookupValue(uint32(i), c2), 3
+ case c0 < 0xF8: // 4-byte UTF-8
+ if len(s) < 4 {
+ return 0, 0
+ }
+ i := idnaIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return 0, 1 // Illegal UTF-8: not a continuation byte.
+ }
+ o := uint32(i)<<6 + uint32(c1)
+ i = idnaIndex[o]
+ c2 := s[2]
+ if c2 < 0x80 || 0xC0 <= c2 {
+ return 0, 2 // Illegal UTF-8: not a continuation byte.
+ }
+ o = uint32(i)<<6 + uint32(c2)
+ i = idnaIndex[o]
+ c3 := s[3]
+ if c3 < 0x80 || 0xC0 <= c3 {
+ return 0, 3 // Illegal UTF-8: not a continuation byte.
+ }
+ return t.lookupValue(uint32(i), c3), 4
+ }
+ // Illegal rune
+ return 0, 1
+}
+
+// lookupUnsafe returns the trie value for the first UTF-8 encoding in s.
+// s must start with a full and valid UTF-8 encoded rune.
+func (t *idnaTrie) lookupUnsafe(s []byte) uint16 {
+ c0 := s[0]
+ if c0 < 0x80 { // is ASCII
+ return idnaValues[c0]
+ }
+ i := idnaIndex[c0]
+ if c0 < 0xE0 { // 2-byte UTF-8
+ return t.lookupValue(uint32(i), s[1])
+ }
+ i = idnaIndex[uint32(i)<<6+uint32(s[1])]
+ if c0 < 0xF0 { // 3-byte UTF-8
+ return t.lookupValue(uint32(i), s[2])
+ }
+ i = idnaIndex[uint32(i)<<6+uint32(s[2])]
+ if c0 < 0xF8 { // 4-byte UTF-8
+ return t.lookupValue(uint32(i), s[3])
+ }
+ return 0
+}
+
+// lookupString returns the trie value for the first UTF-8 encoding in s and
+// the width in bytes of this encoding. The size will be 0 if s does not
+// hold enough bytes to complete the encoding. len(s) must be greater than 0.
+func (t *idnaTrie) lookupString(s string) (v uint16, sz int) {
+ c0 := s[0]
+ switch {
+ case c0 < 0x80: // is ASCII
+ return idnaValues[c0], 1
+ case c0 < 0xC2:
+ return 0, 1 // Illegal UTF-8: not a starter, not ASCII.
+ case c0 < 0xE0: // 2-byte UTF-8
+ if len(s) < 2 {
+ return 0, 0
+ }
+ i := idnaIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return 0, 1 // Illegal UTF-8: not a continuation byte.
+ }
+ return t.lookupValue(uint32(i), c1), 2
+ case c0 < 0xF0: // 3-byte UTF-8
+ if len(s) < 3 {
+ return 0, 0
+ }
+ i := idnaIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return 0, 1 // Illegal UTF-8: not a continuation byte.
+ }
+ o := uint32(i)<<6 + uint32(c1)
+ i = idnaIndex[o]
+ c2 := s[2]
+ if c2 < 0x80 || 0xC0 <= c2 {
+ return 0, 2 // Illegal UTF-8: not a continuation byte.
+ }
+ return t.lookupValue(uint32(i), c2), 3
+ case c0 < 0xF8: // 4-byte UTF-8
+ if len(s) < 4 {
+ return 0, 0
+ }
+ i := idnaIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return 0, 1 // Illegal UTF-8: not a continuation byte.
+ }
+ o := uint32(i)<<6 + uint32(c1)
+ i = idnaIndex[o]
+ c2 := s[2]
+ if c2 < 0x80 || 0xC0 <= c2 {
+ return 0, 2 // Illegal UTF-8: not a continuation byte.
+ }
+ o = uint32(i)<<6 + uint32(c2)
+ i = idnaIndex[o]
+ c3 := s[3]
+ if c3 < 0x80 || 0xC0 <= c3 {
+ return 0, 3 // Illegal UTF-8: not a continuation byte.
+ }
+ return t.lookupValue(uint32(i), c3), 4
+ }
+ // Illegal rune
+ return 0, 1
+}
+
+// lookupStringUnsafe returns the trie value for the first UTF-8 encoding in s.
+// s must start with a full and valid UTF-8 encoded rune.
+func (t *idnaTrie) lookupStringUnsafe(s string) uint16 {
+ c0 := s[0]
+ if c0 < 0x80 { // is ASCII
+ return idnaValues[c0]
+ }
+ i := idnaIndex[c0]
+ if c0 < 0xE0 { // 2-byte UTF-8
+ return t.lookupValue(uint32(i), s[1])
+ }
+ i = idnaIndex[uint32(i)<<6+uint32(s[1])]
+ if c0 < 0xF0 { // 3-byte UTF-8
+ return t.lookupValue(uint32(i), s[2])
+ }
+ i = idnaIndex[uint32(i)<<6+uint32(s[2])]
+ if c0 < 0xF8 { // 4-byte UTF-8
+ return t.lookupValue(uint32(i), s[3])
+ }
+ return 0
+}
+
+// idnaTrie. Total size: 29052 bytes (28.37 KiB). Checksum: ef06e7ecc26f36dd.
+type idnaTrie struct{}
+
+func newIdnaTrie(i int) *idnaTrie {
+ return &idnaTrie{}
+}
+
+// lookupValue determines the type of block n and looks up the value for b.
+func (t *idnaTrie) lookupValue(n uint32, b byte) uint16 {
+ switch {
+ case n < 125:
+ return uint16(idnaValues[n<<6+uint32(b)])
+ default:
+ n -= 125
+ return uint16(idnaSparse.lookup(n, b))
+ }
+}
+
+// idnaValues: 127 blocks, 8128 entries, 16256 bytes
+// The third block is the zero block.
+var idnaValues = [8128]uint16{
+ // Block 0x0, offset 0x0
+ 0x00: 0x0080, 0x01: 0x0080, 0x02: 0x0080, 0x03: 0x0080, 0x04: 0x0080, 0x05: 0x0080,
+ 0x06: 0x0080, 0x07: 0x0080, 0x08: 0x0080, 0x09: 0x0080, 0x0a: 0x0080, 0x0b: 0x0080,
+ 0x0c: 0x0080, 0x0d: 0x0080, 0x0e: 0x0080, 0x0f: 0x0080, 0x10: 0x0080, 0x11: 0x0080,
+ 0x12: 0x0080, 0x13: 0x0080, 0x14: 0x0080, 0x15: 0x0080, 0x16: 0x0080, 0x17: 0x0080,
+ 0x18: 0x0080, 0x19: 0x0080, 0x1a: 0x0080, 0x1b: 0x0080, 0x1c: 0x0080, 0x1d: 0x0080,
+ 0x1e: 0x0080, 0x1f: 0x0080, 0x20: 0x0080, 0x21: 0x0080, 0x22: 0x0080, 0x23: 0x0080,
+ 0x24: 0x0080, 0x25: 0x0080, 0x26: 0x0080, 0x27: 0x0080, 0x28: 0x0080, 0x29: 0x0080,
+ 0x2a: 0x0080, 0x2b: 0x0080, 0x2c: 0x0080, 0x2d: 0x0008, 0x2e: 0x0008, 0x2f: 0x0080,
+ 0x30: 0x0008, 0x31: 0x0008, 0x32: 0x0008, 0x33: 0x0008, 0x34: 0x0008, 0x35: 0x0008,
+ 0x36: 0x0008, 0x37: 0x0008, 0x38: 0x0008, 0x39: 0x0008, 0x3a: 0x0080, 0x3b: 0x0080,
+ 0x3c: 0x0080, 0x3d: 0x0080, 0x3e: 0x0080, 0x3f: 0x0080,
+ // Block 0x1, offset 0x40
+ 0x40: 0x0080, 0x41: 0xe105, 0x42: 0xe105, 0x43: 0xe105, 0x44: 0xe105, 0x45: 0xe105,
+ 0x46: 0xe105, 0x47: 0xe105, 0x48: 0xe105, 0x49: 0xe105, 0x4a: 0xe105, 0x4b: 0xe105,
+ 0x4c: 0xe105, 0x4d: 0xe105, 0x4e: 0xe105, 0x4f: 0xe105, 0x50: 0xe105, 0x51: 0xe105,
+ 0x52: 0xe105, 0x53: 0xe105, 0x54: 0xe105, 0x55: 0xe105, 0x56: 0xe105, 0x57: 0xe105,
+ 0x58: 0xe105, 0x59: 0xe105, 0x5a: 0xe105, 0x5b: 0x0080, 0x5c: 0x0080, 0x5d: 0x0080,
+ 0x5e: 0x0080, 0x5f: 0x0080, 0x60: 0x0080, 0x61: 0x0008, 0x62: 0x0008, 0x63: 0x0008,
+ 0x64: 0x0008, 0x65: 0x0008, 0x66: 0x0008, 0x67: 0x0008, 0x68: 0x0008, 0x69: 0x0008,
+ 0x6a: 0x0008, 0x6b: 0x0008, 0x6c: 0x0008, 0x6d: 0x0008, 0x6e: 0x0008, 0x6f: 0x0008,
+ 0x70: 0x0008, 0x71: 0x0008, 0x72: 0x0008, 0x73: 0x0008, 0x74: 0x0008, 0x75: 0x0008,
+ 0x76: 0x0008, 0x77: 0x0008, 0x78: 0x0008, 0x79: 0x0008, 0x7a: 0x0008, 0x7b: 0x0080,
+ 0x7c: 0x0080, 0x7d: 0x0080, 0x7e: 0x0080, 0x7f: 0x0080,
+ // Block 0x2, offset 0x80
+ // Block 0x3, offset 0xc0
+ 0xc0: 0x0040, 0xc1: 0x0040, 0xc2: 0x0040, 0xc3: 0x0040, 0xc4: 0x0040, 0xc5: 0x0040,
+ 0xc6: 0x0040, 0xc7: 0x0040, 0xc8: 0x0040, 0xc9: 0x0040, 0xca: 0x0040, 0xcb: 0x0040,
+ 0xcc: 0x0040, 0xcd: 0x0040, 0xce: 0x0040, 0xcf: 0x0040, 0xd0: 0x0040, 0xd1: 0x0040,
+ 0xd2: 0x0040, 0xd3: 0x0040, 0xd4: 0x0040, 0xd5: 0x0040, 0xd6: 0x0040, 0xd7: 0x0040,
+ 0xd8: 0x0040, 0xd9: 0x0040, 0xda: 0x0040, 0xdb: 0x0040, 0xdc: 0x0040, 0xdd: 0x0040,
+ 0xde: 0x0040, 0xdf: 0x0040, 0xe0: 0x000a, 0xe1: 0x0018, 0xe2: 0x0018, 0xe3: 0x0018,
+ 0xe4: 0x0018, 0xe5: 0x0018, 0xe6: 0x0018, 0xe7: 0x0018, 0xe8: 0x001a, 0xe9: 0x0018,
+ 0xea: 0x0039, 0xeb: 0x0018, 0xec: 0x0018, 0xed: 0x03c0, 0xee: 0x0018, 0xef: 0x004a,
+ 0xf0: 0x0018, 0xf1: 0x0018, 0xf2: 0x0069, 0xf3: 0x0079, 0xf4: 0x008a, 0xf5: 0x0005,
+ 0xf6: 0x0018, 0xf7: 0x0008, 0xf8: 0x00aa, 0xf9: 0x00c9, 0xfa: 0x00d9, 0xfb: 0x0018,
+ 0xfc: 0x00e9, 0xfd: 0x0119, 0xfe: 0x0149, 0xff: 0x0018,
+ // Block 0x4, offset 0x100
+ 0x100: 0xe00d, 0x101: 0x0008, 0x102: 0xe00d, 0x103: 0x0008, 0x104: 0xe00d, 0x105: 0x0008,
+ 0x106: 0xe00d, 0x107: 0x0008, 0x108: 0xe00d, 0x109: 0x0008, 0x10a: 0xe00d, 0x10b: 0x0008,
+ 0x10c: 0xe00d, 0x10d: 0x0008, 0x10e: 0xe00d, 0x10f: 0x0008, 0x110: 0xe00d, 0x111: 0x0008,
+ 0x112: 0xe00d, 0x113: 0x0008, 0x114: 0xe00d, 0x115: 0x0008, 0x116: 0xe00d, 0x117: 0x0008,
+ 0x118: 0xe00d, 0x119: 0x0008, 0x11a: 0xe00d, 0x11b: 0x0008, 0x11c: 0xe00d, 0x11d: 0x0008,
+ 0x11e: 0xe00d, 0x11f: 0x0008, 0x120: 0xe00d, 0x121: 0x0008, 0x122: 0xe00d, 0x123: 0x0008,
+ 0x124: 0xe00d, 0x125: 0x0008, 0x126: 0xe00d, 0x127: 0x0008, 0x128: 0xe00d, 0x129: 0x0008,
+ 0x12a: 0xe00d, 0x12b: 0x0008, 0x12c: 0xe00d, 0x12d: 0x0008, 0x12e: 0xe00d, 0x12f: 0x0008,
+ 0x130: 0x0179, 0x131: 0x0008, 0x132: 0x0035, 0x133: 0x004d, 0x134: 0xe00d, 0x135: 0x0008,
+ 0x136: 0xe00d, 0x137: 0x0008, 0x138: 0x0008, 0x139: 0xe01d, 0x13a: 0x0008, 0x13b: 0xe03d,
+ 0x13c: 0x0008, 0x13d: 0xe01d, 0x13e: 0x0008, 0x13f: 0x0199,
+ // Block 0x5, offset 0x140
+ 0x140: 0x0199, 0x141: 0xe01d, 0x142: 0x0008, 0x143: 0xe03d, 0x144: 0x0008, 0x145: 0xe01d,
+ 0x146: 0x0008, 0x147: 0xe07d, 0x148: 0x0008, 0x149: 0x01b9, 0x14a: 0xe00d, 0x14b: 0x0008,
+ 0x14c: 0xe00d, 0x14d: 0x0008, 0x14e: 0xe00d, 0x14f: 0x0008, 0x150: 0xe00d, 0x151: 0x0008,
+ 0x152: 0xe00d, 0x153: 0x0008, 0x154: 0xe00d, 0x155: 0x0008, 0x156: 0xe00d, 0x157: 0x0008,
+ 0x158: 0xe00d, 0x159: 0x0008, 0x15a: 0xe00d, 0x15b: 0x0008, 0x15c: 0xe00d, 0x15d: 0x0008,
+ 0x15e: 0xe00d, 0x15f: 0x0008, 0x160: 0xe00d, 0x161: 0x0008, 0x162: 0xe00d, 0x163: 0x0008,
+ 0x164: 0xe00d, 0x165: 0x0008, 0x166: 0xe00d, 0x167: 0x0008, 0x168: 0xe00d, 0x169: 0x0008,
+ 0x16a: 0xe00d, 0x16b: 0x0008, 0x16c: 0xe00d, 0x16d: 0x0008, 0x16e: 0xe00d, 0x16f: 0x0008,
+ 0x170: 0xe00d, 0x171: 0x0008, 0x172: 0xe00d, 0x173: 0x0008, 0x174: 0xe00d, 0x175: 0x0008,
+ 0x176: 0xe00d, 0x177: 0x0008, 0x178: 0x0065, 0x179: 0xe01d, 0x17a: 0x0008, 0x17b: 0xe03d,
+ 0x17c: 0x0008, 0x17d: 0xe01d, 0x17e: 0x0008, 0x17f: 0x01d9,
+ // Block 0x6, offset 0x180
+ 0x180: 0x0008, 0x181: 0x007d, 0x182: 0xe00d, 0x183: 0x0008, 0x184: 0xe00d, 0x185: 0x0008,
+ 0x186: 0x007d, 0x187: 0xe07d, 0x188: 0x0008, 0x189: 0x0095, 0x18a: 0x00ad, 0x18b: 0xe03d,
+ 0x18c: 0x0008, 0x18d: 0x0008, 0x18e: 0x00c5, 0x18f: 0x00dd, 0x190: 0x00f5, 0x191: 0xe01d,
+ 0x192: 0x0008, 0x193: 0x010d, 0x194: 0x0125, 0x195: 0x0008, 0x196: 0x013d, 0x197: 0x013d,
+ 0x198: 0xe00d, 0x199: 0x0008, 0x19a: 0x0008, 0x19b: 0x0008, 0x19c: 0x010d, 0x19d: 0x0155,
+ 0x19e: 0x0008, 0x19f: 0x016d, 0x1a0: 0xe00d, 0x1a1: 0x0008, 0x1a2: 0xe00d, 0x1a3: 0x0008,
+ 0x1a4: 0xe00d, 0x1a5: 0x0008, 0x1a6: 0x0185, 0x1a7: 0xe07d, 0x1a8: 0x0008, 0x1a9: 0x019d,
+ 0x1aa: 0x0008, 0x1ab: 0x0008, 0x1ac: 0xe00d, 0x1ad: 0x0008, 0x1ae: 0x0185, 0x1af: 0xe0fd,
+ 0x1b0: 0x0008, 0x1b1: 0x01b5, 0x1b2: 0x01cd, 0x1b3: 0xe03d, 0x1b4: 0x0008, 0x1b5: 0xe01d,
+ 0x1b6: 0x0008, 0x1b7: 0x01e5, 0x1b8: 0xe00d, 0x1b9: 0x0008, 0x1ba: 0x0008, 0x1bb: 0x0008,
+ 0x1bc: 0xe00d, 0x1bd: 0x0008, 0x1be: 0x0008, 0x1bf: 0x0008,
+ // Block 0x7, offset 0x1c0
+ 0x1c0: 0x0008, 0x1c1: 0x0008, 0x1c2: 0x0008, 0x1c3: 0x0008, 0x1c4: 0x01e9, 0x1c5: 0x01e9,
+ 0x1c6: 0x01e9, 0x1c7: 0x01fd, 0x1c8: 0x0215, 0x1c9: 0x022d, 0x1ca: 0x0245, 0x1cb: 0x025d,
+ 0x1cc: 0x0275, 0x1cd: 0xe01d, 0x1ce: 0x0008, 0x1cf: 0xe0fd, 0x1d0: 0x0008, 0x1d1: 0xe01d,
+ 0x1d2: 0x0008, 0x1d3: 0xe03d, 0x1d4: 0x0008, 0x1d5: 0xe01d, 0x1d6: 0x0008, 0x1d7: 0xe07d,
+ 0x1d8: 0x0008, 0x1d9: 0xe01d, 0x1da: 0x0008, 0x1db: 0xe03d, 0x1dc: 0x0008, 0x1dd: 0x0008,
+ 0x1de: 0xe00d, 0x1df: 0x0008, 0x1e0: 0xe00d, 0x1e1: 0x0008, 0x1e2: 0xe00d, 0x1e3: 0x0008,
+ 0x1e4: 0xe00d, 0x1e5: 0x0008, 0x1e6: 0xe00d, 0x1e7: 0x0008, 0x1e8: 0xe00d, 0x1e9: 0x0008,
+ 0x1ea: 0xe00d, 0x1eb: 0x0008, 0x1ec: 0xe00d, 0x1ed: 0x0008, 0x1ee: 0xe00d, 0x1ef: 0x0008,
+ 0x1f0: 0x0008, 0x1f1: 0x028d, 0x1f2: 0x02a5, 0x1f3: 0x02bd, 0x1f4: 0xe00d, 0x1f5: 0x0008,
+ 0x1f6: 0x02d5, 0x1f7: 0x02ed, 0x1f8: 0xe00d, 0x1f9: 0x0008, 0x1fa: 0xe00d, 0x1fb: 0x0008,
+ 0x1fc: 0xe00d, 0x1fd: 0x0008, 0x1fe: 0xe00d, 0x1ff: 0x0008,
+ // Block 0x8, offset 0x200
+ 0x200: 0xe00d, 0x201: 0x0008, 0x202: 0xe00d, 0x203: 0x0008, 0x204: 0xe00d, 0x205: 0x0008,
+ 0x206: 0xe00d, 0x207: 0x0008, 0x208: 0xe00d, 0x209: 0x0008, 0x20a: 0xe00d, 0x20b: 0x0008,
+ 0x20c: 0xe00d, 0x20d: 0x0008, 0x20e: 0xe00d, 0x20f: 0x0008, 0x210: 0xe00d, 0x211: 0x0008,
+ 0x212: 0xe00d, 0x213: 0x0008, 0x214: 0xe00d, 0x215: 0x0008, 0x216: 0xe00d, 0x217: 0x0008,
+ 0x218: 0xe00d, 0x219: 0x0008, 0x21a: 0xe00d, 0x21b: 0x0008, 0x21c: 0xe00d, 0x21d: 0x0008,
+ 0x21e: 0xe00d, 0x21f: 0x0008, 0x220: 0x0305, 0x221: 0x0008, 0x222: 0xe00d, 0x223: 0x0008,
+ 0x224: 0xe00d, 0x225: 0x0008, 0x226: 0xe00d, 0x227: 0x0008, 0x228: 0xe00d, 0x229: 0x0008,
+ 0x22a: 0xe00d, 0x22b: 0x0008, 0x22c: 0xe00d, 0x22d: 0x0008, 0x22e: 0xe00d, 0x22f: 0x0008,
+ 0x230: 0xe00d, 0x231: 0x0008, 0x232: 0xe00d, 0x233: 0x0008, 0x234: 0x0008, 0x235: 0x0008,
+ 0x236: 0x0008, 0x237: 0x0008, 0x238: 0x0008, 0x239: 0x0008, 0x23a: 0x0209, 0x23b: 0xe03d,
+ 0x23c: 0x0008, 0x23d: 0x031d, 0x23e: 0x0229, 0x23f: 0x0008,
+ // Block 0x9, offset 0x240
+ 0x240: 0x0008, 0x241: 0x0008, 0x242: 0x0018, 0x243: 0x0018, 0x244: 0x0018, 0x245: 0x0018,
+ 0x246: 0x0008, 0x247: 0x0008, 0x248: 0x0008, 0x249: 0x0008, 0x24a: 0x0008, 0x24b: 0x0008,
+ 0x24c: 0x0008, 0x24d: 0x0008, 0x24e: 0x0008, 0x24f: 0x0008, 0x250: 0x0008, 0x251: 0x0008,
+ 0x252: 0x0018, 0x253: 0x0018, 0x254: 0x0018, 0x255: 0x0018, 0x256: 0x0018, 0x257: 0x0018,
+ 0x258: 0x029a, 0x259: 0x02ba, 0x25a: 0x02da, 0x25b: 0x02fa, 0x25c: 0x031a, 0x25d: 0x033a,
+ 0x25e: 0x0018, 0x25f: 0x0018, 0x260: 0x03ad, 0x261: 0x0359, 0x262: 0x01d9, 0x263: 0x0369,
+ 0x264: 0x03c5, 0x265: 0x0018, 0x266: 0x0018, 0x267: 0x0018, 0x268: 0x0018, 0x269: 0x0018,
+ 0x26a: 0x0018, 0x26b: 0x0018, 0x26c: 0x0008, 0x26d: 0x0018, 0x26e: 0x0008, 0x26f: 0x0018,
+ 0x270: 0x0018, 0x271: 0x0018, 0x272: 0x0018, 0x273: 0x0018, 0x274: 0x0018, 0x275: 0x0018,
+ 0x276: 0x0018, 0x277: 0x0018, 0x278: 0x0018, 0x279: 0x0018, 0x27a: 0x0018, 0x27b: 0x0018,
+ 0x27c: 0x0018, 0x27d: 0x0018, 0x27e: 0x0018, 0x27f: 0x0018,
+ // Block 0xa, offset 0x280
+ 0x280: 0x03dd, 0x281: 0x03dd, 0x282: 0x3308, 0x283: 0x03f5, 0x284: 0x0379, 0x285: 0x040d,
+ 0x286: 0x3308, 0x287: 0x3308, 0x288: 0x3308, 0x289: 0x3308, 0x28a: 0x3308, 0x28b: 0x3308,
+ 0x28c: 0x3308, 0x28d: 0x3308, 0x28e: 0x3308, 0x28f: 0x33c0, 0x290: 0x3308, 0x291: 0x3308,
+ 0x292: 0x3308, 0x293: 0x3308, 0x294: 0x3308, 0x295: 0x3308, 0x296: 0x3308, 0x297: 0x3308,
+ 0x298: 0x3308, 0x299: 0x3308, 0x29a: 0x3308, 0x29b: 0x3308, 0x29c: 0x3308, 0x29d: 0x3308,
+ 0x29e: 0x3308, 0x29f: 0x3308, 0x2a0: 0x3308, 0x2a1: 0x3308, 0x2a2: 0x3308, 0x2a3: 0x3308,
+ 0x2a4: 0x3308, 0x2a5: 0x3308, 0x2a6: 0x3308, 0x2a7: 0x3308, 0x2a8: 0x3308, 0x2a9: 0x3308,
+ 0x2aa: 0x3308, 0x2ab: 0x3308, 0x2ac: 0x3308, 0x2ad: 0x3308, 0x2ae: 0x3308, 0x2af: 0x3308,
+ 0x2b0: 0xe00d, 0x2b1: 0x0008, 0x2b2: 0xe00d, 0x2b3: 0x0008, 0x2b4: 0x0425, 0x2b5: 0x0008,
+ 0x2b6: 0xe00d, 0x2b7: 0x0008, 0x2b8: 0x0040, 0x2b9: 0x0040, 0x2ba: 0x03a2, 0x2bb: 0x0008,
+ 0x2bc: 0x0008, 0x2bd: 0x0008, 0x2be: 0x03c2, 0x2bf: 0x043d,
+ // Block 0xb, offset 0x2c0
+ 0x2c0: 0x0040, 0x2c1: 0x0040, 0x2c2: 0x0040, 0x2c3: 0x0040, 0x2c4: 0x008a, 0x2c5: 0x03d2,
+ 0x2c6: 0xe155, 0x2c7: 0x0455, 0x2c8: 0xe12d, 0x2c9: 0xe13d, 0x2ca: 0xe12d, 0x2cb: 0x0040,
+ 0x2cc: 0x03dd, 0x2cd: 0x0040, 0x2ce: 0x046d, 0x2cf: 0x0485, 0x2d0: 0x0008, 0x2d1: 0xe105,
+ 0x2d2: 0xe105, 0x2d3: 0xe105, 0x2d4: 0xe105, 0x2d5: 0xe105, 0x2d6: 0xe105, 0x2d7: 0xe105,
+ 0x2d8: 0xe105, 0x2d9: 0xe105, 0x2da: 0xe105, 0x2db: 0xe105, 0x2dc: 0xe105, 0x2dd: 0xe105,
+ 0x2de: 0xe105, 0x2df: 0xe105, 0x2e0: 0x049d, 0x2e1: 0x049d, 0x2e2: 0x0040, 0x2e3: 0x049d,
+ 0x2e4: 0x049d, 0x2e5: 0x049d, 0x2e6: 0x049d, 0x2e7: 0x049d, 0x2e8: 0x049d, 0x2e9: 0x049d,
+ 0x2ea: 0x049d, 0x2eb: 0x049d, 0x2ec: 0x0008, 0x2ed: 0x0008, 0x2ee: 0x0008, 0x2ef: 0x0008,
+ 0x2f0: 0x0008, 0x2f1: 0x0008, 0x2f2: 0x0008, 0x2f3: 0x0008, 0x2f4: 0x0008, 0x2f5: 0x0008,
+ 0x2f6: 0x0008, 0x2f7: 0x0008, 0x2f8: 0x0008, 0x2f9: 0x0008, 0x2fa: 0x0008, 0x2fb: 0x0008,
+ 0x2fc: 0x0008, 0x2fd: 0x0008, 0x2fe: 0x0008, 0x2ff: 0x0008,
+ // Block 0xc, offset 0x300
+ 0x300: 0x0008, 0x301: 0x0008, 0x302: 0xe00f, 0x303: 0x0008, 0x304: 0x0008, 0x305: 0x0008,
+ 0x306: 0x0008, 0x307: 0x0008, 0x308: 0x0008, 0x309: 0x0008, 0x30a: 0x0008, 0x30b: 0x0008,
+ 0x30c: 0x0008, 0x30d: 0x0008, 0x30e: 0x0008, 0x30f: 0xe0c5, 0x310: 0x04b5, 0x311: 0x04cd,
+ 0x312: 0xe0bd, 0x313: 0xe0f5, 0x314: 0xe0fd, 0x315: 0xe09d, 0x316: 0xe0b5, 0x317: 0x0008,
+ 0x318: 0xe00d, 0x319: 0x0008, 0x31a: 0xe00d, 0x31b: 0x0008, 0x31c: 0xe00d, 0x31d: 0x0008,
+ 0x31e: 0xe00d, 0x31f: 0x0008, 0x320: 0xe00d, 0x321: 0x0008, 0x322: 0xe00d, 0x323: 0x0008,
+ 0x324: 0xe00d, 0x325: 0x0008, 0x326: 0xe00d, 0x327: 0x0008, 0x328: 0xe00d, 0x329: 0x0008,
+ 0x32a: 0xe00d, 0x32b: 0x0008, 0x32c: 0xe00d, 0x32d: 0x0008, 0x32e: 0xe00d, 0x32f: 0x0008,
+ 0x330: 0x04e5, 0x331: 0xe185, 0x332: 0xe18d, 0x333: 0x0008, 0x334: 0x04fd, 0x335: 0x03dd,
+ 0x336: 0x0018, 0x337: 0xe07d, 0x338: 0x0008, 0x339: 0xe1d5, 0x33a: 0xe00d, 0x33b: 0x0008,
+ 0x33c: 0x0008, 0x33d: 0x0515, 0x33e: 0x052d, 0x33f: 0x052d,
+ // Block 0xd, offset 0x340
+ 0x340: 0x0008, 0x341: 0x0008, 0x342: 0x0008, 0x343: 0x0008, 0x344: 0x0008, 0x345: 0x0008,
+ 0x346: 0x0008, 0x347: 0x0008, 0x348: 0x0008, 0x349: 0x0008, 0x34a: 0x0008, 0x34b: 0x0008,
+ 0x34c: 0x0008, 0x34d: 0x0008, 0x34e: 0x0008, 0x34f: 0x0008, 0x350: 0x0008, 0x351: 0x0008,
+ 0x352: 0x0008, 0x353: 0x0008, 0x354: 0x0008, 0x355: 0x0008, 0x356: 0x0008, 0x357: 0x0008,
+ 0x358: 0x0008, 0x359: 0x0008, 0x35a: 0x0008, 0x35b: 0x0008, 0x35c: 0x0008, 0x35d: 0x0008,
+ 0x35e: 0x0008, 0x35f: 0x0008, 0x360: 0xe00d, 0x361: 0x0008, 0x362: 0xe00d, 0x363: 0x0008,
+ 0x364: 0xe00d, 0x365: 0x0008, 0x366: 0xe00d, 0x367: 0x0008, 0x368: 0xe00d, 0x369: 0x0008,
+ 0x36a: 0xe00d, 0x36b: 0x0008, 0x36c: 0xe00d, 0x36d: 0x0008, 0x36e: 0xe00d, 0x36f: 0x0008,
+ 0x370: 0xe00d, 0x371: 0x0008, 0x372: 0xe00d, 0x373: 0x0008, 0x374: 0xe00d, 0x375: 0x0008,
+ 0x376: 0xe00d, 0x377: 0x0008, 0x378: 0xe00d, 0x379: 0x0008, 0x37a: 0xe00d, 0x37b: 0x0008,
+ 0x37c: 0xe00d, 0x37d: 0x0008, 0x37e: 0xe00d, 0x37f: 0x0008,
+ // Block 0xe, offset 0x380
+ 0x380: 0xe00d, 0x381: 0x0008, 0x382: 0x0018, 0x383: 0x3308, 0x384: 0x3308, 0x385: 0x3308,
+ 0x386: 0x3308, 0x387: 0x3308, 0x388: 0x3318, 0x389: 0x3318, 0x38a: 0xe00d, 0x38b: 0x0008,
+ 0x38c: 0xe00d, 0x38d: 0x0008, 0x38e: 0xe00d, 0x38f: 0x0008, 0x390: 0xe00d, 0x391: 0x0008,
+ 0x392: 0xe00d, 0x393: 0x0008, 0x394: 0xe00d, 0x395: 0x0008, 0x396: 0xe00d, 0x397: 0x0008,
+ 0x398: 0xe00d, 0x399: 0x0008, 0x39a: 0xe00d, 0x39b: 0x0008, 0x39c: 0xe00d, 0x39d: 0x0008,
+ 0x39e: 0xe00d, 0x39f: 0x0008, 0x3a0: 0xe00d, 0x3a1: 0x0008, 0x3a2: 0xe00d, 0x3a3: 0x0008,
+ 0x3a4: 0xe00d, 0x3a5: 0x0008, 0x3a6: 0xe00d, 0x3a7: 0x0008, 0x3a8: 0xe00d, 0x3a9: 0x0008,
+ 0x3aa: 0xe00d, 0x3ab: 0x0008, 0x3ac: 0xe00d, 0x3ad: 0x0008, 0x3ae: 0xe00d, 0x3af: 0x0008,
+ 0x3b0: 0xe00d, 0x3b1: 0x0008, 0x3b2: 0xe00d, 0x3b3: 0x0008, 0x3b4: 0xe00d, 0x3b5: 0x0008,
+ 0x3b6: 0xe00d, 0x3b7: 0x0008, 0x3b8: 0xe00d, 0x3b9: 0x0008, 0x3ba: 0xe00d, 0x3bb: 0x0008,
+ 0x3bc: 0xe00d, 0x3bd: 0x0008, 0x3be: 0xe00d, 0x3bf: 0x0008,
+ // Block 0xf, offset 0x3c0
+ 0x3c0: 0x0040, 0x3c1: 0xe01d, 0x3c2: 0x0008, 0x3c3: 0xe03d, 0x3c4: 0x0008, 0x3c5: 0xe01d,
+ 0x3c6: 0x0008, 0x3c7: 0xe07d, 0x3c8: 0x0008, 0x3c9: 0xe01d, 0x3ca: 0x0008, 0x3cb: 0xe03d,
+ 0x3cc: 0x0008, 0x3cd: 0xe01d, 0x3ce: 0x0008, 0x3cf: 0x0008, 0x3d0: 0xe00d, 0x3d1: 0x0008,
+ 0x3d2: 0xe00d, 0x3d3: 0x0008, 0x3d4: 0xe00d, 0x3d5: 0x0008, 0x3d6: 0xe00d, 0x3d7: 0x0008,
+ 0x3d8: 0xe00d, 0x3d9: 0x0008, 0x3da: 0xe00d, 0x3db: 0x0008, 0x3dc: 0xe00d, 0x3dd: 0x0008,
+ 0x3de: 0xe00d, 0x3df: 0x0008, 0x3e0: 0xe00d, 0x3e1: 0x0008, 0x3e2: 0xe00d, 0x3e3: 0x0008,
+ 0x3e4: 0xe00d, 0x3e5: 0x0008, 0x3e6: 0xe00d, 0x3e7: 0x0008, 0x3e8: 0xe00d, 0x3e9: 0x0008,
+ 0x3ea: 0xe00d, 0x3eb: 0x0008, 0x3ec: 0xe00d, 0x3ed: 0x0008, 0x3ee: 0xe00d, 0x3ef: 0x0008,
+ 0x3f0: 0xe00d, 0x3f1: 0x0008, 0x3f2: 0xe00d, 0x3f3: 0x0008, 0x3f4: 0xe00d, 0x3f5: 0x0008,
+ 0x3f6: 0xe00d, 0x3f7: 0x0008, 0x3f8: 0xe00d, 0x3f9: 0x0008, 0x3fa: 0xe00d, 0x3fb: 0x0008,
+ 0x3fc: 0xe00d, 0x3fd: 0x0008, 0x3fe: 0xe00d, 0x3ff: 0x0008,
+ // Block 0x10, offset 0x400
+ 0x400: 0xe00d, 0x401: 0x0008, 0x402: 0xe00d, 0x403: 0x0008, 0x404: 0xe00d, 0x405: 0x0008,
+ 0x406: 0xe00d, 0x407: 0x0008, 0x408: 0xe00d, 0x409: 0x0008, 0x40a: 0xe00d, 0x40b: 0x0008,
+ 0x40c: 0xe00d, 0x40d: 0x0008, 0x40e: 0xe00d, 0x40f: 0x0008, 0x410: 0xe00d, 0x411: 0x0008,
+ 0x412: 0xe00d, 0x413: 0x0008, 0x414: 0xe00d, 0x415: 0x0008, 0x416: 0xe00d, 0x417: 0x0008,
+ 0x418: 0xe00d, 0x419: 0x0008, 0x41a: 0xe00d, 0x41b: 0x0008, 0x41c: 0xe00d, 0x41d: 0x0008,
+ 0x41e: 0xe00d, 0x41f: 0x0008, 0x420: 0xe00d, 0x421: 0x0008, 0x422: 0xe00d, 0x423: 0x0008,
+ 0x424: 0xe00d, 0x425: 0x0008, 0x426: 0xe00d, 0x427: 0x0008, 0x428: 0xe00d, 0x429: 0x0008,
+ 0x42a: 0xe00d, 0x42b: 0x0008, 0x42c: 0xe00d, 0x42d: 0x0008, 0x42e: 0xe00d, 0x42f: 0x0008,
+ 0x430: 0x0040, 0x431: 0x03f5, 0x432: 0x03f5, 0x433: 0x03f5, 0x434: 0x03f5, 0x435: 0x03f5,
+ 0x436: 0x03f5, 0x437: 0x03f5, 0x438: 0x03f5, 0x439: 0x03f5, 0x43a: 0x03f5, 0x43b: 0x03f5,
+ 0x43c: 0x03f5, 0x43d: 0x03f5, 0x43e: 0x03f5, 0x43f: 0x03f5,
+ // Block 0x11, offset 0x440
+ 0x440: 0x0840, 0x441: 0x0840, 0x442: 0x0840, 0x443: 0x0840, 0x444: 0x0840, 0x445: 0x0840,
+ 0x446: 0x0018, 0x447: 0x0018, 0x448: 0x0818, 0x449: 0x0018, 0x44a: 0x0018, 0x44b: 0x0818,
+ 0x44c: 0x0018, 0x44d: 0x0818, 0x44e: 0x0018, 0x44f: 0x0018, 0x450: 0x3308, 0x451: 0x3308,
+ 0x452: 0x3308, 0x453: 0x3308, 0x454: 0x3308, 0x455: 0x3308, 0x456: 0x3308, 0x457: 0x3308,
+ 0x458: 0x3308, 0x459: 0x3308, 0x45a: 0x3308, 0x45b: 0x0818, 0x45c: 0x0b40, 0x45d: 0x0040,
+ 0x45e: 0x0818, 0x45f: 0x0818, 0x460: 0x0a08, 0x461: 0x0808, 0x462: 0x0c08, 0x463: 0x0c08,
+ 0x464: 0x0c08, 0x465: 0x0c08, 0x466: 0x0a08, 0x467: 0x0c08, 0x468: 0x0a08, 0x469: 0x0c08,
+ 0x46a: 0x0a08, 0x46b: 0x0a08, 0x46c: 0x0a08, 0x46d: 0x0a08, 0x46e: 0x0a08, 0x46f: 0x0c08,
+ 0x470: 0x0c08, 0x471: 0x0c08, 0x472: 0x0c08, 0x473: 0x0a08, 0x474: 0x0a08, 0x475: 0x0a08,
+ 0x476: 0x0a08, 0x477: 0x0a08, 0x478: 0x0a08, 0x479: 0x0a08, 0x47a: 0x0a08, 0x47b: 0x0a08,
+ 0x47c: 0x0a08, 0x47d: 0x0a08, 0x47e: 0x0a08, 0x47f: 0x0a08,
+ // Block 0x12, offset 0x480
+ 0x480: 0x0818, 0x481: 0x0a08, 0x482: 0x0a08, 0x483: 0x0a08, 0x484: 0x0a08, 0x485: 0x0a08,
+ 0x486: 0x0a08, 0x487: 0x0a08, 0x488: 0x0c08, 0x489: 0x0a08, 0x48a: 0x0a08, 0x48b: 0x3308,
+ 0x48c: 0x3308, 0x48d: 0x3308, 0x48e: 0x3308, 0x48f: 0x3308, 0x490: 0x3308, 0x491: 0x3308,
+ 0x492: 0x3308, 0x493: 0x3308, 0x494: 0x3308, 0x495: 0x3308, 0x496: 0x3308, 0x497: 0x3308,
+ 0x498: 0x3308, 0x499: 0x3308, 0x49a: 0x3308, 0x49b: 0x3308, 0x49c: 0x3308, 0x49d: 0x3308,
+ 0x49e: 0x3308, 0x49f: 0x3308, 0x4a0: 0x0808, 0x4a1: 0x0808, 0x4a2: 0x0808, 0x4a3: 0x0808,
+ 0x4a4: 0x0808, 0x4a5: 0x0808, 0x4a6: 0x0808, 0x4a7: 0x0808, 0x4a8: 0x0808, 0x4a9: 0x0808,
+ 0x4aa: 0x0018, 0x4ab: 0x0818, 0x4ac: 0x0818, 0x4ad: 0x0818, 0x4ae: 0x0a08, 0x4af: 0x0a08,
+ 0x4b0: 0x3308, 0x4b1: 0x0c08, 0x4b2: 0x0c08, 0x4b3: 0x0c08, 0x4b4: 0x0808, 0x4b5: 0x0429,
+ 0x4b6: 0x0451, 0x4b7: 0x0479, 0x4b8: 0x04a1, 0x4b9: 0x0a08, 0x4ba: 0x0a08, 0x4bb: 0x0a08,
+ 0x4bc: 0x0a08, 0x4bd: 0x0a08, 0x4be: 0x0a08, 0x4bf: 0x0a08,
+ // Block 0x13, offset 0x4c0
+ 0x4c0: 0x0c08, 0x4c1: 0x0a08, 0x4c2: 0x0a08, 0x4c3: 0x0c08, 0x4c4: 0x0c08, 0x4c5: 0x0c08,
+ 0x4c6: 0x0c08, 0x4c7: 0x0c08, 0x4c8: 0x0c08, 0x4c9: 0x0c08, 0x4ca: 0x0c08, 0x4cb: 0x0c08,
+ 0x4cc: 0x0a08, 0x4cd: 0x0c08, 0x4ce: 0x0a08, 0x4cf: 0x0c08, 0x4d0: 0x0a08, 0x4d1: 0x0a08,
+ 0x4d2: 0x0c08, 0x4d3: 0x0c08, 0x4d4: 0x0818, 0x4d5: 0x0c08, 0x4d6: 0x3308, 0x4d7: 0x3308,
+ 0x4d8: 0x3308, 0x4d9: 0x3308, 0x4da: 0x3308, 0x4db: 0x3308, 0x4dc: 0x3308, 0x4dd: 0x0840,
+ 0x4de: 0x0018, 0x4df: 0x3308, 0x4e0: 0x3308, 0x4e1: 0x3308, 0x4e2: 0x3308, 0x4e3: 0x3308,
+ 0x4e4: 0x3308, 0x4e5: 0x0808, 0x4e6: 0x0808, 0x4e7: 0x3308, 0x4e8: 0x3308, 0x4e9: 0x0018,
+ 0x4ea: 0x3308, 0x4eb: 0x3308, 0x4ec: 0x3308, 0x4ed: 0x3308, 0x4ee: 0x0c08, 0x4ef: 0x0c08,
+ 0x4f0: 0x0008, 0x4f1: 0x0008, 0x4f2: 0x0008, 0x4f3: 0x0008, 0x4f4: 0x0008, 0x4f5: 0x0008,
+ 0x4f6: 0x0008, 0x4f7: 0x0008, 0x4f8: 0x0008, 0x4f9: 0x0008, 0x4fa: 0x0a08, 0x4fb: 0x0a08,
+ 0x4fc: 0x0a08, 0x4fd: 0x0808, 0x4fe: 0x0808, 0x4ff: 0x0a08,
+ // Block 0x14, offset 0x500
+ 0x500: 0x0818, 0x501: 0x0818, 0x502: 0x0818, 0x503: 0x0818, 0x504: 0x0818, 0x505: 0x0818,
+ 0x506: 0x0818, 0x507: 0x0818, 0x508: 0x0818, 0x509: 0x0818, 0x50a: 0x0818, 0x50b: 0x0818,
+ 0x50c: 0x0818, 0x50d: 0x0818, 0x50e: 0x0040, 0x50f: 0x0b40, 0x510: 0x0c08, 0x511: 0x3308,
+ 0x512: 0x0a08, 0x513: 0x0a08, 0x514: 0x0a08, 0x515: 0x0c08, 0x516: 0x0c08, 0x517: 0x0c08,
+ 0x518: 0x0c08, 0x519: 0x0c08, 0x51a: 0x0a08, 0x51b: 0x0a08, 0x51c: 0x0a08, 0x51d: 0x0a08,
+ 0x51e: 0x0c08, 0x51f: 0x0a08, 0x520: 0x0a08, 0x521: 0x0a08, 0x522: 0x0a08, 0x523: 0x0a08,
+ 0x524: 0x0a08, 0x525: 0x0a08, 0x526: 0x0a08, 0x527: 0x0a08, 0x528: 0x0c08, 0x529: 0x0a08,
+ 0x52a: 0x0c08, 0x52b: 0x0a08, 0x52c: 0x0c08, 0x52d: 0x0a08, 0x52e: 0x0a08, 0x52f: 0x0c08,
+ 0x530: 0x3308, 0x531: 0x3308, 0x532: 0x3308, 0x533: 0x3308, 0x534: 0x3308, 0x535: 0x3308,
+ 0x536: 0x3308, 0x537: 0x3308, 0x538: 0x3308, 0x539: 0x3308, 0x53a: 0x3308, 0x53b: 0x3308,
+ 0x53c: 0x3308, 0x53d: 0x3308, 0x53e: 0x3308, 0x53f: 0x3308,
+ // Block 0x15, offset 0x540
+ 0x540: 0x0c08, 0x541: 0x0a08, 0x542: 0x0a08, 0x543: 0x0a08, 0x544: 0x0a08, 0x545: 0x0a08,
+ 0x546: 0x0c08, 0x547: 0x0c08, 0x548: 0x0a08, 0x549: 0x0c08, 0x54a: 0x0a08, 0x54b: 0x0a08,
+ 0x54c: 0x0a08, 0x54d: 0x0a08, 0x54e: 0x0a08, 0x54f: 0x0a08, 0x550: 0x0a08, 0x551: 0x0a08,
+ 0x552: 0x0a08, 0x553: 0x0a08, 0x554: 0x0c08, 0x555: 0x0a08, 0x556: 0x0808, 0x557: 0x0808,
+ 0x558: 0x0808, 0x559: 0x3308, 0x55a: 0x3308, 0x55b: 0x3308, 0x55c: 0x0040, 0x55d: 0x0040,
+ 0x55e: 0x0818, 0x55f: 0x0040, 0x560: 0x0a08, 0x561: 0x0808, 0x562: 0x0a08, 0x563: 0x0a08,
+ 0x564: 0x0a08, 0x565: 0x0a08, 0x566: 0x0808, 0x567: 0x0c08, 0x568: 0x0a08, 0x569: 0x0c08,
+ 0x56a: 0x0c08, 0x56b: 0x0040, 0x56c: 0x0040, 0x56d: 0x0040, 0x56e: 0x0040, 0x56f: 0x0040,
+ 0x570: 0x0040, 0x571: 0x0040, 0x572: 0x0040, 0x573: 0x0040, 0x574: 0x0040, 0x575: 0x0040,
+ 0x576: 0x0040, 0x577: 0x0040, 0x578: 0x0040, 0x579: 0x0040, 0x57a: 0x0040, 0x57b: 0x0040,
+ 0x57c: 0x0040, 0x57d: 0x0040, 0x57e: 0x0040, 0x57f: 0x0040,
+ // Block 0x16, offset 0x580
+ 0x580: 0x3008, 0x581: 0x3308, 0x582: 0x3308, 0x583: 0x3308, 0x584: 0x3308, 0x585: 0x3308,
+ 0x586: 0x3308, 0x587: 0x3308, 0x588: 0x3308, 0x589: 0x3008, 0x58a: 0x3008, 0x58b: 0x3008,
+ 0x58c: 0x3008, 0x58d: 0x3b08, 0x58e: 0x3008, 0x58f: 0x3008, 0x590: 0x0008, 0x591: 0x3308,
+ 0x592: 0x3308, 0x593: 0x3308, 0x594: 0x3308, 0x595: 0x3308, 0x596: 0x3308, 0x597: 0x3308,
+ 0x598: 0x04c9, 0x599: 0x0501, 0x59a: 0x0539, 0x59b: 0x0571, 0x59c: 0x05a9, 0x59d: 0x05e1,
+ 0x59e: 0x0619, 0x59f: 0x0651, 0x5a0: 0x0008, 0x5a1: 0x0008, 0x5a2: 0x3308, 0x5a3: 0x3308,
+ 0x5a4: 0x0018, 0x5a5: 0x0018, 0x5a6: 0x0008, 0x5a7: 0x0008, 0x5a8: 0x0008, 0x5a9: 0x0008,
+ 0x5aa: 0x0008, 0x5ab: 0x0008, 0x5ac: 0x0008, 0x5ad: 0x0008, 0x5ae: 0x0008, 0x5af: 0x0008,
+ 0x5b0: 0x0018, 0x5b1: 0x0008, 0x5b2: 0x0008, 0x5b3: 0x0008, 0x5b4: 0x0008, 0x5b5: 0x0008,
+ 0x5b6: 0x0008, 0x5b7: 0x0008, 0x5b8: 0x0008, 0x5b9: 0x0008, 0x5ba: 0x0008, 0x5bb: 0x0008,
+ 0x5bc: 0x0008, 0x5bd: 0x0008, 0x5be: 0x0008, 0x5bf: 0x0008,
+ // Block 0x17, offset 0x5c0
+ 0x5c0: 0x0008, 0x5c1: 0x3308, 0x5c2: 0x3008, 0x5c3: 0x3008, 0x5c4: 0x0040, 0x5c5: 0x0008,
+ 0x5c6: 0x0008, 0x5c7: 0x0008, 0x5c8: 0x0008, 0x5c9: 0x0008, 0x5ca: 0x0008, 0x5cb: 0x0008,
+ 0x5cc: 0x0008, 0x5cd: 0x0040, 0x5ce: 0x0040, 0x5cf: 0x0008, 0x5d0: 0x0008, 0x5d1: 0x0040,
+ 0x5d2: 0x0040, 0x5d3: 0x0008, 0x5d4: 0x0008, 0x5d5: 0x0008, 0x5d6: 0x0008, 0x5d7: 0x0008,
+ 0x5d8: 0x0008, 0x5d9: 0x0008, 0x5da: 0x0008, 0x5db: 0x0008, 0x5dc: 0x0008, 0x5dd: 0x0008,
+ 0x5de: 0x0008, 0x5df: 0x0008, 0x5e0: 0x0008, 0x5e1: 0x0008, 0x5e2: 0x0008, 0x5e3: 0x0008,
+ 0x5e4: 0x0008, 0x5e5: 0x0008, 0x5e6: 0x0008, 0x5e7: 0x0008, 0x5e8: 0x0008, 0x5e9: 0x0040,
+ 0x5ea: 0x0008, 0x5eb: 0x0008, 0x5ec: 0x0008, 0x5ed: 0x0008, 0x5ee: 0x0008, 0x5ef: 0x0008,
+ 0x5f0: 0x0008, 0x5f1: 0x0040, 0x5f2: 0x0008, 0x5f3: 0x0040, 0x5f4: 0x0040, 0x5f5: 0x0040,
+ 0x5f6: 0x0008, 0x5f7: 0x0008, 0x5f8: 0x0008, 0x5f9: 0x0008, 0x5fa: 0x0040, 0x5fb: 0x0040,
+ 0x5fc: 0x3308, 0x5fd: 0x0008, 0x5fe: 0x3008, 0x5ff: 0x3008,
+ // Block 0x18, offset 0x600
+ 0x600: 0x3008, 0x601: 0x3308, 0x602: 0x3308, 0x603: 0x3308, 0x604: 0x3308, 0x605: 0x0040,
+ 0x606: 0x0040, 0x607: 0x3008, 0x608: 0x3008, 0x609: 0x0040, 0x60a: 0x0040, 0x60b: 0x3008,
+ 0x60c: 0x3008, 0x60d: 0x3b08, 0x60e: 0x0008, 0x60f: 0x0040, 0x610: 0x0040, 0x611: 0x0040,
+ 0x612: 0x0040, 0x613: 0x0040, 0x614: 0x0040, 0x615: 0x0040, 0x616: 0x0040, 0x617: 0x3008,
+ 0x618: 0x0040, 0x619: 0x0040, 0x61a: 0x0040, 0x61b: 0x0040, 0x61c: 0x0689, 0x61d: 0x06c1,
+ 0x61e: 0x0040, 0x61f: 0x06f9, 0x620: 0x0008, 0x621: 0x0008, 0x622: 0x3308, 0x623: 0x3308,
+ 0x624: 0x0040, 0x625: 0x0040, 0x626: 0x0008, 0x627: 0x0008, 0x628: 0x0008, 0x629: 0x0008,
+ 0x62a: 0x0008, 0x62b: 0x0008, 0x62c: 0x0008, 0x62d: 0x0008, 0x62e: 0x0008, 0x62f: 0x0008,
+ 0x630: 0x0008, 0x631: 0x0008, 0x632: 0x0018, 0x633: 0x0018, 0x634: 0x0018, 0x635: 0x0018,
+ 0x636: 0x0018, 0x637: 0x0018, 0x638: 0x0018, 0x639: 0x0018, 0x63a: 0x0018, 0x63b: 0x0018,
+ 0x63c: 0x0008, 0x63d: 0x0018, 0x63e: 0x0040, 0x63f: 0x0040,
+ // Block 0x19, offset 0x640
+ 0x640: 0x0040, 0x641: 0x3308, 0x642: 0x3308, 0x643: 0x3008, 0x644: 0x0040, 0x645: 0x0008,
+ 0x646: 0x0008, 0x647: 0x0008, 0x648: 0x0008, 0x649: 0x0008, 0x64a: 0x0008, 0x64b: 0x0040,
+ 0x64c: 0x0040, 0x64d: 0x0040, 0x64e: 0x0040, 0x64f: 0x0008, 0x650: 0x0008, 0x651: 0x0040,
+ 0x652: 0x0040, 0x653: 0x0008, 0x654: 0x0008, 0x655: 0x0008, 0x656: 0x0008, 0x657: 0x0008,
+ 0x658: 0x0008, 0x659: 0x0008, 0x65a: 0x0008, 0x65b: 0x0008, 0x65c: 0x0008, 0x65d: 0x0008,
+ 0x65e: 0x0008, 0x65f: 0x0008, 0x660: 0x0008, 0x661: 0x0008, 0x662: 0x0008, 0x663: 0x0008,
+ 0x664: 0x0008, 0x665: 0x0008, 0x666: 0x0008, 0x667: 0x0008, 0x668: 0x0008, 0x669: 0x0040,
+ 0x66a: 0x0008, 0x66b: 0x0008, 0x66c: 0x0008, 0x66d: 0x0008, 0x66e: 0x0008, 0x66f: 0x0008,
+ 0x670: 0x0008, 0x671: 0x0040, 0x672: 0x0008, 0x673: 0x0731, 0x674: 0x0040, 0x675: 0x0008,
+ 0x676: 0x0769, 0x677: 0x0040, 0x678: 0x0008, 0x679: 0x0008, 0x67a: 0x0040, 0x67b: 0x0040,
+ 0x67c: 0x3308, 0x67d: 0x0040, 0x67e: 0x3008, 0x67f: 0x3008,
+ // Block 0x1a, offset 0x680
+ 0x680: 0x3008, 0x681: 0x3308, 0x682: 0x3308, 0x683: 0x0040, 0x684: 0x0040, 0x685: 0x0040,
+ 0x686: 0x0040, 0x687: 0x3308, 0x688: 0x3308, 0x689: 0x0040, 0x68a: 0x0040, 0x68b: 0x3308,
+ 0x68c: 0x3308, 0x68d: 0x3b08, 0x68e: 0x0040, 0x68f: 0x0040, 0x690: 0x0040, 0x691: 0x3308,
+ 0x692: 0x0040, 0x693: 0x0040, 0x694: 0x0040, 0x695: 0x0040, 0x696: 0x0040, 0x697: 0x0040,
+ 0x698: 0x0040, 0x699: 0x07a1, 0x69a: 0x07d9, 0x69b: 0x0811, 0x69c: 0x0008, 0x69d: 0x0040,
+ 0x69e: 0x0849, 0x69f: 0x0040, 0x6a0: 0x0040, 0x6a1: 0x0040, 0x6a2: 0x0040, 0x6a3: 0x0040,
+ 0x6a4: 0x0040, 0x6a5: 0x0040, 0x6a6: 0x0008, 0x6a7: 0x0008, 0x6a8: 0x0008, 0x6a9: 0x0008,
+ 0x6aa: 0x0008, 0x6ab: 0x0008, 0x6ac: 0x0008, 0x6ad: 0x0008, 0x6ae: 0x0008, 0x6af: 0x0008,
+ 0x6b0: 0x3308, 0x6b1: 0x3308, 0x6b2: 0x0008, 0x6b3: 0x0008, 0x6b4: 0x0008, 0x6b5: 0x3308,
+ 0x6b6: 0x0040, 0x6b7: 0x0040, 0x6b8: 0x0040, 0x6b9: 0x0040, 0x6ba: 0x0040, 0x6bb: 0x0040,
+ 0x6bc: 0x0040, 0x6bd: 0x0040, 0x6be: 0x0040, 0x6bf: 0x0040,
+ // Block 0x1b, offset 0x6c0
+ 0x6c0: 0x0040, 0x6c1: 0x3308, 0x6c2: 0x3308, 0x6c3: 0x3008, 0x6c4: 0x0040, 0x6c5: 0x0008,
+ 0x6c6: 0x0008, 0x6c7: 0x0008, 0x6c8: 0x0008, 0x6c9: 0x0008, 0x6ca: 0x0008, 0x6cb: 0x0008,
+ 0x6cc: 0x0008, 0x6cd: 0x0008, 0x6ce: 0x0040, 0x6cf: 0x0008, 0x6d0: 0x0008, 0x6d1: 0x0008,
+ 0x6d2: 0x0040, 0x6d3: 0x0008, 0x6d4: 0x0008, 0x6d5: 0x0008, 0x6d6: 0x0008, 0x6d7: 0x0008,
+ 0x6d8: 0x0008, 0x6d9: 0x0008, 0x6da: 0x0008, 0x6db: 0x0008, 0x6dc: 0x0008, 0x6dd: 0x0008,
+ 0x6de: 0x0008, 0x6df: 0x0008, 0x6e0: 0x0008, 0x6e1: 0x0008, 0x6e2: 0x0008, 0x6e3: 0x0008,
+ 0x6e4: 0x0008, 0x6e5: 0x0008, 0x6e6: 0x0008, 0x6e7: 0x0008, 0x6e8: 0x0008, 0x6e9: 0x0040,
+ 0x6ea: 0x0008, 0x6eb: 0x0008, 0x6ec: 0x0008, 0x6ed: 0x0008, 0x6ee: 0x0008, 0x6ef: 0x0008,
+ 0x6f0: 0x0008, 0x6f1: 0x0040, 0x6f2: 0x0008, 0x6f3: 0x0008, 0x6f4: 0x0040, 0x6f5: 0x0008,
+ 0x6f6: 0x0008, 0x6f7: 0x0008, 0x6f8: 0x0008, 0x6f9: 0x0008, 0x6fa: 0x0040, 0x6fb: 0x0040,
+ 0x6fc: 0x3308, 0x6fd: 0x0008, 0x6fe: 0x3008, 0x6ff: 0x3008,
+ // Block 0x1c, offset 0x700
+ 0x700: 0x3008, 0x701: 0x3308, 0x702: 0x3308, 0x703: 0x3308, 0x704: 0x3308, 0x705: 0x3308,
+ 0x706: 0x0040, 0x707: 0x3308, 0x708: 0x3308, 0x709: 0x3008, 0x70a: 0x0040, 0x70b: 0x3008,
+ 0x70c: 0x3008, 0x70d: 0x3b08, 0x70e: 0x0040, 0x70f: 0x0040, 0x710: 0x0008, 0x711: 0x0040,
+ 0x712: 0x0040, 0x713: 0x0040, 0x714: 0x0040, 0x715: 0x0040, 0x716: 0x0040, 0x717: 0x0040,
+ 0x718: 0x0040, 0x719: 0x0040, 0x71a: 0x0040, 0x71b: 0x0040, 0x71c: 0x0040, 0x71d: 0x0040,
+ 0x71e: 0x0040, 0x71f: 0x0040, 0x720: 0x0008, 0x721: 0x0008, 0x722: 0x3308, 0x723: 0x3308,
+ 0x724: 0x0040, 0x725: 0x0040, 0x726: 0x0008, 0x727: 0x0008, 0x728: 0x0008, 0x729: 0x0008,
+ 0x72a: 0x0008, 0x72b: 0x0008, 0x72c: 0x0008, 0x72d: 0x0008, 0x72e: 0x0008, 0x72f: 0x0008,
+ 0x730: 0x0018, 0x731: 0x0018, 0x732: 0x0040, 0x733: 0x0040, 0x734: 0x0040, 0x735: 0x0040,
+ 0x736: 0x0040, 0x737: 0x0040, 0x738: 0x0040, 0x739: 0x0008, 0x73a: 0x3308, 0x73b: 0x3308,
+ 0x73c: 0x3308, 0x73d: 0x3308, 0x73e: 0x3308, 0x73f: 0x3308,
+ // Block 0x1d, offset 0x740
+ 0x740: 0x0040, 0x741: 0x3308, 0x742: 0x3008, 0x743: 0x3008, 0x744: 0x0040, 0x745: 0x0008,
+ 0x746: 0x0008, 0x747: 0x0008, 0x748: 0x0008, 0x749: 0x0008, 0x74a: 0x0008, 0x74b: 0x0008,
+ 0x74c: 0x0008, 0x74d: 0x0040, 0x74e: 0x0040, 0x74f: 0x0008, 0x750: 0x0008, 0x751: 0x0040,
+ 0x752: 0x0040, 0x753: 0x0008, 0x754: 0x0008, 0x755: 0x0008, 0x756: 0x0008, 0x757: 0x0008,
+ 0x758: 0x0008, 0x759: 0x0008, 0x75a: 0x0008, 0x75b: 0x0008, 0x75c: 0x0008, 0x75d: 0x0008,
+ 0x75e: 0x0008, 0x75f: 0x0008, 0x760: 0x0008, 0x761: 0x0008, 0x762: 0x0008, 0x763: 0x0008,
+ 0x764: 0x0008, 0x765: 0x0008, 0x766: 0x0008, 0x767: 0x0008, 0x768: 0x0008, 0x769: 0x0040,
+ 0x76a: 0x0008, 0x76b: 0x0008, 0x76c: 0x0008, 0x76d: 0x0008, 0x76e: 0x0008, 0x76f: 0x0008,
+ 0x770: 0x0008, 0x771: 0x0040, 0x772: 0x0008, 0x773: 0x0008, 0x774: 0x0040, 0x775: 0x0008,
+ 0x776: 0x0008, 0x777: 0x0008, 0x778: 0x0008, 0x779: 0x0008, 0x77a: 0x0040, 0x77b: 0x0040,
+ 0x77c: 0x3308, 0x77d: 0x0008, 0x77e: 0x3008, 0x77f: 0x3308,
+ // Block 0x1e, offset 0x780
+ 0x780: 0x3008, 0x781: 0x3308, 0x782: 0x3308, 0x783: 0x3308, 0x784: 0x3308, 0x785: 0x0040,
+ 0x786: 0x0040, 0x787: 0x3008, 0x788: 0x3008, 0x789: 0x0040, 0x78a: 0x0040, 0x78b: 0x3008,
+ 0x78c: 0x3008, 0x78d: 0x3b08, 0x78e: 0x0040, 0x78f: 0x0040, 0x790: 0x0040, 0x791: 0x0040,
+ 0x792: 0x0040, 0x793: 0x0040, 0x794: 0x0040, 0x795: 0x0040, 0x796: 0x3308, 0x797: 0x3008,
+ 0x798: 0x0040, 0x799: 0x0040, 0x79a: 0x0040, 0x79b: 0x0040, 0x79c: 0x0881, 0x79d: 0x08b9,
+ 0x79e: 0x0040, 0x79f: 0x0008, 0x7a0: 0x0008, 0x7a1: 0x0008, 0x7a2: 0x3308, 0x7a3: 0x3308,
+ 0x7a4: 0x0040, 0x7a5: 0x0040, 0x7a6: 0x0008, 0x7a7: 0x0008, 0x7a8: 0x0008, 0x7a9: 0x0008,
+ 0x7aa: 0x0008, 0x7ab: 0x0008, 0x7ac: 0x0008, 0x7ad: 0x0008, 0x7ae: 0x0008, 0x7af: 0x0008,
+ 0x7b0: 0x0018, 0x7b1: 0x0008, 0x7b2: 0x0018, 0x7b3: 0x0018, 0x7b4: 0x0018, 0x7b5: 0x0018,
+ 0x7b6: 0x0018, 0x7b7: 0x0018, 0x7b8: 0x0040, 0x7b9: 0x0040, 0x7ba: 0x0040, 0x7bb: 0x0040,
+ 0x7bc: 0x0040, 0x7bd: 0x0040, 0x7be: 0x0040, 0x7bf: 0x0040,
+ // Block 0x1f, offset 0x7c0
+ 0x7c0: 0x0040, 0x7c1: 0x0040, 0x7c2: 0x3308, 0x7c3: 0x0008, 0x7c4: 0x0040, 0x7c5: 0x0008,
+ 0x7c6: 0x0008, 0x7c7: 0x0008, 0x7c8: 0x0008, 0x7c9: 0x0008, 0x7ca: 0x0008, 0x7cb: 0x0040,
+ 0x7cc: 0x0040, 0x7cd: 0x0040, 0x7ce: 0x0008, 0x7cf: 0x0008, 0x7d0: 0x0008, 0x7d1: 0x0040,
+ 0x7d2: 0x0008, 0x7d3: 0x0008, 0x7d4: 0x0008, 0x7d5: 0x0008, 0x7d6: 0x0040, 0x7d7: 0x0040,
+ 0x7d8: 0x0040, 0x7d9: 0x0008, 0x7da: 0x0008, 0x7db: 0x0040, 0x7dc: 0x0008, 0x7dd: 0x0040,
+ 0x7de: 0x0008, 0x7df: 0x0008, 0x7e0: 0x0040, 0x7e1: 0x0040, 0x7e2: 0x0040, 0x7e3: 0x0008,
+ 0x7e4: 0x0008, 0x7e5: 0x0040, 0x7e6: 0x0040, 0x7e7: 0x0040, 0x7e8: 0x0008, 0x7e9: 0x0008,
+ 0x7ea: 0x0008, 0x7eb: 0x0040, 0x7ec: 0x0040, 0x7ed: 0x0040, 0x7ee: 0x0008, 0x7ef: 0x0008,
+ 0x7f0: 0x0008, 0x7f1: 0x0008, 0x7f2: 0x0008, 0x7f3: 0x0008, 0x7f4: 0x0008, 0x7f5: 0x0008,
+ 0x7f6: 0x0008, 0x7f7: 0x0008, 0x7f8: 0x0008, 0x7f9: 0x0008, 0x7fa: 0x0040, 0x7fb: 0x0040,
+ 0x7fc: 0x0040, 0x7fd: 0x0040, 0x7fe: 0x3008, 0x7ff: 0x3008,
+ // Block 0x20, offset 0x800
+ 0x800: 0x3308, 0x801: 0x3008, 0x802: 0x3008, 0x803: 0x3008, 0x804: 0x3008, 0x805: 0x0040,
+ 0x806: 0x3308, 0x807: 0x3308, 0x808: 0x3308, 0x809: 0x0040, 0x80a: 0x3308, 0x80b: 0x3308,
+ 0x80c: 0x3308, 0x80d: 0x3b08, 0x80e: 0x0040, 0x80f: 0x0040, 0x810: 0x0040, 0x811: 0x0040,
+ 0x812: 0x0040, 0x813: 0x0040, 0x814: 0x0040, 0x815: 0x3308, 0x816: 0x3308, 0x817: 0x0040,
+ 0x818: 0x0008, 0x819: 0x0008, 0x81a: 0x0008, 0x81b: 0x0040, 0x81c: 0x0040, 0x81d: 0x0040,
+ 0x81e: 0x0040, 0x81f: 0x0040, 0x820: 0x0008, 0x821: 0x0008, 0x822: 0x3308, 0x823: 0x3308,
+ 0x824: 0x0040, 0x825: 0x0040, 0x826: 0x0008, 0x827: 0x0008, 0x828: 0x0008, 0x829: 0x0008,
+ 0x82a: 0x0008, 0x82b: 0x0008, 0x82c: 0x0008, 0x82d: 0x0008, 0x82e: 0x0008, 0x82f: 0x0008,
+ 0x830: 0x0040, 0x831: 0x0040, 0x832: 0x0040, 0x833: 0x0040, 0x834: 0x0040, 0x835: 0x0040,
+ 0x836: 0x0040, 0x837: 0x0040, 0x838: 0x0018, 0x839: 0x0018, 0x83a: 0x0018, 0x83b: 0x0018,
+ 0x83c: 0x0018, 0x83d: 0x0018, 0x83e: 0x0018, 0x83f: 0x0018,
+ // Block 0x21, offset 0x840
+ 0x840: 0x0008, 0x841: 0x3308, 0x842: 0x3008, 0x843: 0x3008, 0x844: 0x0040, 0x845: 0x0008,
+ 0x846: 0x0008, 0x847: 0x0008, 0x848: 0x0008, 0x849: 0x0008, 0x84a: 0x0008, 0x84b: 0x0008,
+ 0x84c: 0x0008, 0x84d: 0x0040, 0x84e: 0x0008, 0x84f: 0x0008, 0x850: 0x0008, 0x851: 0x0040,
+ 0x852: 0x0008, 0x853: 0x0008, 0x854: 0x0008, 0x855: 0x0008, 0x856: 0x0008, 0x857: 0x0008,
+ 0x858: 0x0008, 0x859: 0x0008, 0x85a: 0x0008, 0x85b: 0x0008, 0x85c: 0x0008, 0x85d: 0x0008,
+ 0x85e: 0x0008, 0x85f: 0x0008, 0x860: 0x0008, 0x861: 0x0008, 0x862: 0x0008, 0x863: 0x0008,
+ 0x864: 0x0008, 0x865: 0x0008, 0x866: 0x0008, 0x867: 0x0008, 0x868: 0x0008, 0x869: 0x0040,
+ 0x86a: 0x0008, 0x86b: 0x0008, 0x86c: 0x0008, 0x86d: 0x0008, 0x86e: 0x0008, 0x86f: 0x0008,
+ 0x870: 0x0008, 0x871: 0x0008, 0x872: 0x0008, 0x873: 0x0008, 0x874: 0x0040, 0x875: 0x0008,
+ 0x876: 0x0008, 0x877: 0x0008, 0x878: 0x0008, 0x879: 0x0008, 0x87a: 0x0040, 0x87b: 0x0040,
+ 0x87c: 0x3308, 0x87d: 0x0008, 0x87e: 0x3008, 0x87f: 0x3308,
+ // Block 0x22, offset 0x880
+ 0x880: 0x3008, 0x881: 0x3008, 0x882: 0x3008, 0x883: 0x3008, 0x884: 0x3008, 0x885: 0x0040,
+ 0x886: 0x3308, 0x887: 0x3008, 0x888: 0x3008, 0x889: 0x0040, 0x88a: 0x3008, 0x88b: 0x3008,
+ 0x88c: 0x3308, 0x88d: 0x3b08, 0x88e: 0x0040, 0x88f: 0x0040, 0x890: 0x0040, 0x891: 0x0040,
+ 0x892: 0x0040, 0x893: 0x0040, 0x894: 0x0040, 0x895: 0x3008, 0x896: 0x3008, 0x897: 0x0040,
+ 0x898: 0x0040, 0x899: 0x0040, 0x89a: 0x0040, 0x89b: 0x0040, 0x89c: 0x0040, 0x89d: 0x0040,
+ 0x89e: 0x0008, 0x89f: 0x0040, 0x8a0: 0x0008, 0x8a1: 0x0008, 0x8a2: 0x3308, 0x8a3: 0x3308,
+ 0x8a4: 0x0040, 0x8a5: 0x0040, 0x8a6: 0x0008, 0x8a7: 0x0008, 0x8a8: 0x0008, 0x8a9: 0x0008,
+ 0x8aa: 0x0008, 0x8ab: 0x0008, 0x8ac: 0x0008, 0x8ad: 0x0008, 0x8ae: 0x0008, 0x8af: 0x0008,
+ 0x8b0: 0x0040, 0x8b1: 0x0008, 0x8b2: 0x0008, 0x8b3: 0x0040, 0x8b4: 0x0040, 0x8b5: 0x0040,
+ 0x8b6: 0x0040, 0x8b7: 0x0040, 0x8b8: 0x0040, 0x8b9: 0x0040, 0x8ba: 0x0040, 0x8bb: 0x0040,
+ 0x8bc: 0x0040, 0x8bd: 0x0040, 0x8be: 0x0040, 0x8bf: 0x0040,
+ // Block 0x23, offset 0x8c0
+ 0x8c0: 0x3008, 0x8c1: 0x3308, 0x8c2: 0x3308, 0x8c3: 0x3308, 0x8c4: 0x3308, 0x8c5: 0x0040,
+ 0x8c6: 0x3008, 0x8c7: 0x3008, 0x8c8: 0x3008, 0x8c9: 0x0040, 0x8ca: 0x3008, 0x8cb: 0x3008,
+ 0x8cc: 0x3008, 0x8cd: 0x3b08, 0x8ce: 0x0008, 0x8cf: 0x0018, 0x8d0: 0x0040, 0x8d1: 0x0040,
+ 0x8d2: 0x0040, 0x8d3: 0x0040, 0x8d4: 0x0008, 0x8d5: 0x0008, 0x8d6: 0x0008, 0x8d7: 0x3008,
+ 0x8d8: 0x0018, 0x8d9: 0x0018, 0x8da: 0x0018, 0x8db: 0x0018, 0x8dc: 0x0018, 0x8dd: 0x0018,
+ 0x8de: 0x0018, 0x8df: 0x0008, 0x8e0: 0x0008, 0x8e1: 0x0008, 0x8e2: 0x3308, 0x8e3: 0x3308,
+ 0x8e4: 0x0040, 0x8e5: 0x0040, 0x8e6: 0x0008, 0x8e7: 0x0008, 0x8e8: 0x0008, 0x8e9: 0x0008,
+ 0x8ea: 0x0008, 0x8eb: 0x0008, 0x8ec: 0x0008, 0x8ed: 0x0008, 0x8ee: 0x0008, 0x8ef: 0x0008,
+ 0x8f0: 0x0018, 0x8f1: 0x0018, 0x8f2: 0x0018, 0x8f3: 0x0018, 0x8f4: 0x0018, 0x8f5: 0x0018,
+ 0x8f6: 0x0018, 0x8f7: 0x0018, 0x8f8: 0x0018, 0x8f9: 0x0018, 0x8fa: 0x0008, 0x8fb: 0x0008,
+ 0x8fc: 0x0008, 0x8fd: 0x0008, 0x8fe: 0x0008, 0x8ff: 0x0008,
+ // Block 0x24, offset 0x900
+ 0x900: 0x0040, 0x901: 0x0008, 0x902: 0x0008, 0x903: 0x0040, 0x904: 0x0008, 0x905: 0x0040,
+ 0x906: 0x0040, 0x907: 0x0008, 0x908: 0x0008, 0x909: 0x0040, 0x90a: 0x0008, 0x90b: 0x0040,
+ 0x90c: 0x0040, 0x90d: 0x0008, 0x90e: 0x0040, 0x90f: 0x0040, 0x910: 0x0040, 0x911: 0x0040,
+ 0x912: 0x0040, 0x913: 0x0040, 0x914: 0x0008, 0x915: 0x0008, 0x916: 0x0008, 0x917: 0x0008,
+ 0x918: 0x0040, 0x919: 0x0008, 0x91a: 0x0008, 0x91b: 0x0008, 0x91c: 0x0008, 0x91d: 0x0008,
+ 0x91e: 0x0008, 0x91f: 0x0008, 0x920: 0x0040, 0x921: 0x0008, 0x922: 0x0008, 0x923: 0x0008,
+ 0x924: 0x0040, 0x925: 0x0008, 0x926: 0x0040, 0x927: 0x0008, 0x928: 0x0040, 0x929: 0x0040,
+ 0x92a: 0x0008, 0x92b: 0x0008, 0x92c: 0x0040, 0x92d: 0x0008, 0x92e: 0x0008, 0x92f: 0x0008,
+ 0x930: 0x0008, 0x931: 0x3308, 0x932: 0x0008, 0x933: 0x0929, 0x934: 0x3308, 0x935: 0x3308,
+ 0x936: 0x3308, 0x937: 0x3308, 0x938: 0x3308, 0x939: 0x3308, 0x93a: 0x0040, 0x93b: 0x3308,
+ 0x93c: 0x3308, 0x93d: 0x0008, 0x93e: 0x0040, 0x93f: 0x0040,
+ // Block 0x25, offset 0x940
+ 0x940: 0x0008, 0x941: 0x0008, 0x942: 0x0008, 0x943: 0x09d1, 0x944: 0x0008, 0x945: 0x0008,
+ 0x946: 0x0008, 0x947: 0x0008, 0x948: 0x0040, 0x949: 0x0008, 0x94a: 0x0008, 0x94b: 0x0008,
+ 0x94c: 0x0008, 0x94d: 0x0a09, 0x94e: 0x0008, 0x94f: 0x0008, 0x950: 0x0008, 0x951: 0x0008,
+ 0x952: 0x0a41, 0x953: 0x0008, 0x954: 0x0008, 0x955: 0x0008, 0x956: 0x0008, 0x957: 0x0a79,
+ 0x958: 0x0008, 0x959: 0x0008, 0x95a: 0x0008, 0x95b: 0x0008, 0x95c: 0x0ab1, 0x95d: 0x0008,
+ 0x95e: 0x0008, 0x95f: 0x0008, 0x960: 0x0008, 0x961: 0x0008, 0x962: 0x0008, 0x963: 0x0008,
+ 0x964: 0x0008, 0x965: 0x0008, 0x966: 0x0008, 0x967: 0x0008, 0x968: 0x0008, 0x969: 0x0ae9,
+ 0x96a: 0x0008, 0x96b: 0x0008, 0x96c: 0x0008, 0x96d: 0x0040, 0x96e: 0x0040, 0x96f: 0x0040,
+ 0x970: 0x0040, 0x971: 0x3308, 0x972: 0x3308, 0x973: 0x0b21, 0x974: 0x3308, 0x975: 0x0b59,
+ 0x976: 0x0b91, 0x977: 0x0bc9, 0x978: 0x0c19, 0x979: 0x0c51, 0x97a: 0x3308, 0x97b: 0x3308,
+ 0x97c: 0x3308, 0x97d: 0x3308, 0x97e: 0x3308, 0x97f: 0x3008,
+ // Block 0x26, offset 0x980
+ 0x980: 0x3308, 0x981: 0x0ca1, 0x982: 0x3308, 0x983: 0x3308, 0x984: 0x3b08, 0x985: 0x0018,
+ 0x986: 0x3308, 0x987: 0x3308, 0x988: 0x0008, 0x989: 0x0008, 0x98a: 0x0008, 0x98b: 0x0008,
+ 0x98c: 0x0008, 0x98d: 0x3308, 0x98e: 0x3308, 0x98f: 0x3308, 0x990: 0x3308, 0x991: 0x3308,
+ 0x992: 0x3308, 0x993: 0x0cd9, 0x994: 0x3308, 0x995: 0x3308, 0x996: 0x3308, 0x997: 0x3308,
+ 0x998: 0x0040, 0x999: 0x3308, 0x99a: 0x3308, 0x99b: 0x3308, 0x99c: 0x3308, 0x99d: 0x0d11,
+ 0x99e: 0x3308, 0x99f: 0x3308, 0x9a0: 0x3308, 0x9a1: 0x3308, 0x9a2: 0x0d49, 0x9a3: 0x3308,
+ 0x9a4: 0x3308, 0x9a5: 0x3308, 0x9a6: 0x3308, 0x9a7: 0x0d81, 0x9a8: 0x3308, 0x9a9: 0x3308,
+ 0x9aa: 0x3308, 0x9ab: 0x3308, 0x9ac: 0x0db9, 0x9ad: 0x3308, 0x9ae: 0x3308, 0x9af: 0x3308,
+ 0x9b0: 0x3308, 0x9b1: 0x3308, 0x9b2: 0x3308, 0x9b3: 0x3308, 0x9b4: 0x3308, 0x9b5: 0x3308,
+ 0x9b6: 0x3308, 0x9b7: 0x3308, 0x9b8: 0x3308, 0x9b9: 0x0df1, 0x9ba: 0x3308, 0x9bb: 0x3308,
+ 0x9bc: 0x3308, 0x9bd: 0x0040, 0x9be: 0x0018, 0x9bf: 0x0018,
+ // Block 0x27, offset 0x9c0
+ 0x9c0: 0x0008, 0x9c1: 0x0008, 0x9c2: 0x0008, 0x9c3: 0x0008, 0x9c4: 0x0008, 0x9c5: 0x0008,
+ 0x9c6: 0x0008, 0x9c7: 0x0008, 0x9c8: 0x0008, 0x9c9: 0x0008, 0x9ca: 0x0008, 0x9cb: 0x0008,
+ 0x9cc: 0x0008, 0x9cd: 0x0008, 0x9ce: 0x0008, 0x9cf: 0x0008, 0x9d0: 0x0008, 0x9d1: 0x0008,
+ 0x9d2: 0x0008, 0x9d3: 0x0008, 0x9d4: 0x0008, 0x9d5: 0x0008, 0x9d6: 0x0008, 0x9d7: 0x0008,
+ 0x9d8: 0x0008, 0x9d9: 0x0008, 0x9da: 0x0008, 0x9db: 0x0008, 0x9dc: 0x0008, 0x9dd: 0x0008,
+ 0x9de: 0x0008, 0x9df: 0x0008, 0x9e0: 0x0008, 0x9e1: 0x0008, 0x9e2: 0x0008, 0x9e3: 0x0008,
+ 0x9e4: 0x0008, 0x9e5: 0x0008, 0x9e6: 0x0008, 0x9e7: 0x0008, 0x9e8: 0x0008, 0x9e9: 0x0008,
+ 0x9ea: 0x0008, 0x9eb: 0x0008, 0x9ec: 0x0039, 0x9ed: 0x0ed1, 0x9ee: 0x0ee9, 0x9ef: 0x0008,
+ 0x9f0: 0x0ef9, 0x9f1: 0x0f09, 0x9f2: 0x0f19, 0x9f3: 0x0f31, 0x9f4: 0x0249, 0x9f5: 0x0f41,
+ 0x9f6: 0x0259, 0x9f7: 0x0f51, 0x9f8: 0x0359, 0x9f9: 0x0f61, 0x9fa: 0x0f71, 0x9fb: 0x0008,
+ 0x9fc: 0x00d9, 0x9fd: 0x0f81, 0x9fe: 0x0f99, 0x9ff: 0x0269,
+ // Block 0x28, offset 0xa00
+ 0xa00: 0x0fa9, 0xa01: 0x0fb9, 0xa02: 0x0279, 0xa03: 0x0039, 0xa04: 0x0fc9, 0xa05: 0x0fe1,
+ 0xa06: 0x059d, 0xa07: 0x0ee9, 0xa08: 0x0ef9, 0xa09: 0x0f09, 0xa0a: 0x0ff9, 0xa0b: 0x1011,
+ 0xa0c: 0x1029, 0xa0d: 0x0f31, 0xa0e: 0x0008, 0xa0f: 0x0f51, 0xa10: 0x0f61, 0xa11: 0x1041,
+ 0xa12: 0x00d9, 0xa13: 0x1059, 0xa14: 0x05b5, 0xa15: 0x05b5, 0xa16: 0x0f99, 0xa17: 0x0fa9,
+ 0xa18: 0x0fb9, 0xa19: 0x059d, 0xa1a: 0x1071, 0xa1b: 0x1089, 0xa1c: 0x05cd, 0xa1d: 0x1099,
+ 0xa1e: 0x10b1, 0xa1f: 0x10c9, 0xa20: 0x10e1, 0xa21: 0x10f9, 0xa22: 0x0f41, 0xa23: 0x0269,
+ 0xa24: 0x0fb9, 0xa25: 0x1089, 0xa26: 0x1099, 0xa27: 0x10b1, 0xa28: 0x1111, 0xa29: 0x10e1,
+ 0xa2a: 0x10f9, 0xa2b: 0x0008, 0xa2c: 0x0008, 0xa2d: 0x0008, 0xa2e: 0x0008, 0xa2f: 0x0008,
+ 0xa30: 0x0008, 0xa31: 0x0008, 0xa32: 0x0008, 0xa33: 0x0008, 0xa34: 0x0008, 0xa35: 0x0008,
+ 0xa36: 0x0008, 0xa37: 0x0008, 0xa38: 0x1129, 0xa39: 0x0008, 0xa3a: 0x0008, 0xa3b: 0x0008,
+ 0xa3c: 0x0008, 0xa3d: 0x0008, 0xa3e: 0x0008, 0xa3f: 0x0008,
+ // Block 0x29, offset 0xa40
+ 0xa40: 0x0008, 0xa41: 0x0008, 0xa42: 0x0008, 0xa43: 0x0008, 0xa44: 0x0008, 0xa45: 0x0008,
+ 0xa46: 0x0008, 0xa47: 0x0008, 0xa48: 0x0008, 0xa49: 0x0008, 0xa4a: 0x0008, 0xa4b: 0x0008,
+ 0xa4c: 0x0008, 0xa4d: 0x0008, 0xa4e: 0x0008, 0xa4f: 0x0008, 0xa50: 0x0008, 0xa51: 0x0008,
+ 0xa52: 0x0008, 0xa53: 0x0008, 0xa54: 0x0008, 0xa55: 0x0008, 0xa56: 0x0008, 0xa57: 0x0008,
+ 0xa58: 0x0008, 0xa59: 0x0008, 0xa5a: 0x0008, 0xa5b: 0x1141, 0xa5c: 0x1159, 0xa5d: 0x1169,
+ 0xa5e: 0x1181, 0xa5f: 0x1029, 0xa60: 0x1199, 0xa61: 0x11a9, 0xa62: 0x11c1, 0xa63: 0x11d9,
+ 0xa64: 0x11f1, 0xa65: 0x1209, 0xa66: 0x1221, 0xa67: 0x05e5, 0xa68: 0x1239, 0xa69: 0x1251,
+ 0xa6a: 0xe17d, 0xa6b: 0x1269, 0xa6c: 0x1281, 0xa6d: 0x1299, 0xa6e: 0x12b1, 0xa6f: 0x12c9,
+ 0xa70: 0x12e1, 0xa71: 0x12f9, 0xa72: 0x1311, 0xa73: 0x1329, 0xa74: 0x1341, 0xa75: 0x1359,
+ 0xa76: 0x1371, 0xa77: 0x1389, 0xa78: 0x05fd, 0xa79: 0x13a1, 0xa7a: 0x13b9, 0xa7b: 0x13d1,
+ 0xa7c: 0x13e1, 0xa7d: 0x13f9, 0xa7e: 0x1411, 0xa7f: 0x1429,
+ // Block 0x2a, offset 0xa80
+ 0xa80: 0xe00d, 0xa81: 0x0008, 0xa82: 0xe00d, 0xa83: 0x0008, 0xa84: 0xe00d, 0xa85: 0x0008,
+ 0xa86: 0xe00d, 0xa87: 0x0008, 0xa88: 0xe00d, 0xa89: 0x0008, 0xa8a: 0xe00d, 0xa8b: 0x0008,
+ 0xa8c: 0xe00d, 0xa8d: 0x0008, 0xa8e: 0xe00d, 0xa8f: 0x0008, 0xa90: 0xe00d, 0xa91: 0x0008,
+ 0xa92: 0xe00d, 0xa93: 0x0008, 0xa94: 0xe00d, 0xa95: 0x0008, 0xa96: 0xe00d, 0xa97: 0x0008,
+ 0xa98: 0xe00d, 0xa99: 0x0008, 0xa9a: 0xe00d, 0xa9b: 0x0008, 0xa9c: 0xe00d, 0xa9d: 0x0008,
+ 0xa9e: 0xe00d, 0xa9f: 0x0008, 0xaa0: 0xe00d, 0xaa1: 0x0008, 0xaa2: 0xe00d, 0xaa3: 0x0008,
+ 0xaa4: 0xe00d, 0xaa5: 0x0008, 0xaa6: 0xe00d, 0xaa7: 0x0008, 0xaa8: 0xe00d, 0xaa9: 0x0008,
+ 0xaaa: 0xe00d, 0xaab: 0x0008, 0xaac: 0xe00d, 0xaad: 0x0008, 0xaae: 0xe00d, 0xaaf: 0x0008,
+ 0xab0: 0xe00d, 0xab1: 0x0008, 0xab2: 0xe00d, 0xab3: 0x0008, 0xab4: 0xe00d, 0xab5: 0x0008,
+ 0xab6: 0xe00d, 0xab7: 0x0008, 0xab8: 0xe00d, 0xab9: 0x0008, 0xaba: 0xe00d, 0xabb: 0x0008,
+ 0xabc: 0xe00d, 0xabd: 0x0008, 0xabe: 0xe00d, 0xabf: 0x0008,
+ // Block 0x2b, offset 0xac0
+ 0xac0: 0xe00d, 0xac1: 0x0008, 0xac2: 0xe00d, 0xac3: 0x0008, 0xac4: 0xe00d, 0xac5: 0x0008,
+ 0xac6: 0xe00d, 0xac7: 0x0008, 0xac8: 0xe00d, 0xac9: 0x0008, 0xaca: 0xe00d, 0xacb: 0x0008,
+ 0xacc: 0xe00d, 0xacd: 0x0008, 0xace: 0xe00d, 0xacf: 0x0008, 0xad0: 0xe00d, 0xad1: 0x0008,
+ 0xad2: 0xe00d, 0xad3: 0x0008, 0xad4: 0xe00d, 0xad5: 0x0008, 0xad6: 0x0008, 0xad7: 0x0008,
+ 0xad8: 0x0008, 0xad9: 0x0008, 0xada: 0x0615, 0xadb: 0x0635, 0xadc: 0x0008, 0xadd: 0x0008,
+ 0xade: 0x1441, 0xadf: 0x0008, 0xae0: 0xe00d, 0xae1: 0x0008, 0xae2: 0xe00d, 0xae3: 0x0008,
+ 0xae4: 0xe00d, 0xae5: 0x0008, 0xae6: 0xe00d, 0xae7: 0x0008, 0xae8: 0xe00d, 0xae9: 0x0008,
+ 0xaea: 0xe00d, 0xaeb: 0x0008, 0xaec: 0xe00d, 0xaed: 0x0008, 0xaee: 0xe00d, 0xaef: 0x0008,
+ 0xaf0: 0xe00d, 0xaf1: 0x0008, 0xaf2: 0xe00d, 0xaf3: 0x0008, 0xaf4: 0xe00d, 0xaf5: 0x0008,
+ 0xaf6: 0xe00d, 0xaf7: 0x0008, 0xaf8: 0xe00d, 0xaf9: 0x0008, 0xafa: 0xe00d, 0xafb: 0x0008,
+ 0xafc: 0xe00d, 0xafd: 0x0008, 0xafe: 0xe00d, 0xaff: 0x0008,
+ // Block 0x2c, offset 0xb00
+ 0xb00: 0x0008, 0xb01: 0x0008, 0xb02: 0x0008, 0xb03: 0x0008, 0xb04: 0x0008, 0xb05: 0x0008,
+ 0xb06: 0x0040, 0xb07: 0x0040, 0xb08: 0xe045, 0xb09: 0xe045, 0xb0a: 0xe045, 0xb0b: 0xe045,
+ 0xb0c: 0xe045, 0xb0d: 0xe045, 0xb0e: 0x0040, 0xb0f: 0x0040, 0xb10: 0x0008, 0xb11: 0x0008,
+ 0xb12: 0x0008, 0xb13: 0x0008, 0xb14: 0x0008, 0xb15: 0x0008, 0xb16: 0x0008, 0xb17: 0x0008,
+ 0xb18: 0x0040, 0xb19: 0xe045, 0xb1a: 0x0040, 0xb1b: 0xe045, 0xb1c: 0x0040, 0xb1d: 0xe045,
+ 0xb1e: 0x0040, 0xb1f: 0xe045, 0xb20: 0x0008, 0xb21: 0x0008, 0xb22: 0x0008, 0xb23: 0x0008,
+ 0xb24: 0x0008, 0xb25: 0x0008, 0xb26: 0x0008, 0xb27: 0x0008, 0xb28: 0xe045, 0xb29: 0xe045,
+ 0xb2a: 0xe045, 0xb2b: 0xe045, 0xb2c: 0xe045, 0xb2d: 0xe045, 0xb2e: 0xe045, 0xb2f: 0xe045,
+ 0xb30: 0x0008, 0xb31: 0x1459, 0xb32: 0x0008, 0xb33: 0x1471, 0xb34: 0x0008, 0xb35: 0x1489,
+ 0xb36: 0x0008, 0xb37: 0x14a1, 0xb38: 0x0008, 0xb39: 0x14b9, 0xb3a: 0x0008, 0xb3b: 0x14d1,
+ 0xb3c: 0x0008, 0xb3d: 0x14e9, 0xb3e: 0x0040, 0xb3f: 0x0040,
+ // Block 0x2d, offset 0xb40
+ 0xb40: 0x1501, 0xb41: 0x1531, 0xb42: 0x1561, 0xb43: 0x1591, 0xb44: 0x15c1, 0xb45: 0x15f1,
+ 0xb46: 0x1621, 0xb47: 0x1651, 0xb48: 0x1501, 0xb49: 0x1531, 0xb4a: 0x1561, 0xb4b: 0x1591,
+ 0xb4c: 0x15c1, 0xb4d: 0x15f1, 0xb4e: 0x1621, 0xb4f: 0x1651, 0xb50: 0x1681, 0xb51: 0x16b1,
+ 0xb52: 0x16e1, 0xb53: 0x1711, 0xb54: 0x1741, 0xb55: 0x1771, 0xb56: 0x17a1, 0xb57: 0x17d1,
+ 0xb58: 0x1681, 0xb59: 0x16b1, 0xb5a: 0x16e1, 0xb5b: 0x1711, 0xb5c: 0x1741, 0xb5d: 0x1771,
+ 0xb5e: 0x17a1, 0xb5f: 0x17d1, 0xb60: 0x1801, 0xb61: 0x1831, 0xb62: 0x1861, 0xb63: 0x1891,
+ 0xb64: 0x18c1, 0xb65: 0x18f1, 0xb66: 0x1921, 0xb67: 0x1951, 0xb68: 0x1801, 0xb69: 0x1831,
+ 0xb6a: 0x1861, 0xb6b: 0x1891, 0xb6c: 0x18c1, 0xb6d: 0x18f1, 0xb6e: 0x1921, 0xb6f: 0x1951,
+ 0xb70: 0x0008, 0xb71: 0x0008, 0xb72: 0x1981, 0xb73: 0x19b1, 0xb74: 0x19d9, 0xb75: 0x0040,
+ 0xb76: 0x0008, 0xb77: 0x1a01, 0xb78: 0xe045, 0xb79: 0xe045, 0xb7a: 0x064d, 0xb7b: 0x1459,
+ 0xb7c: 0x19b1, 0xb7d: 0x0666, 0xb7e: 0x1a31, 0xb7f: 0x0686,
+ // Block 0x2e, offset 0xb80
+ 0xb80: 0x06a6, 0xb81: 0x1a4a, 0xb82: 0x1a79, 0xb83: 0x1aa9, 0xb84: 0x1ad1, 0xb85: 0x0040,
+ 0xb86: 0x0008, 0xb87: 0x1af9, 0xb88: 0x06c5, 0xb89: 0x1471, 0xb8a: 0x06dd, 0xb8b: 0x1489,
+ 0xb8c: 0x1aa9, 0xb8d: 0x1b2a, 0xb8e: 0x1b5a, 0xb8f: 0x1b8a, 0xb90: 0x0008, 0xb91: 0x0008,
+ 0xb92: 0x0008, 0xb93: 0x1bb9, 0xb94: 0x0040, 0xb95: 0x0040, 0xb96: 0x0008, 0xb97: 0x0008,
+ 0xb98: 0xe045, 0xb99: 0xe045, 0xb9a: 0x06f5, 0xb9b: 0x14a1, 0xb9c: 0x0040, 0xb9d: 0x1bd2,
+ 0xb9e: 0x1c02, 0xb9f: 0x1c32, 0xba0: 0x0008, 0xba1: 0x0008, 0xba2: 0x0008, 0xba3: 0x1c61,
+ 0xba4: 0x0008, 0xba5: 0x0008, 0xba6: 0x0008, 0xba7: 0x0008, 0xba8: 0xe045, 0xba9: 0xe045,
+ 0xbaa: 0x070d, 0xbab: 0x14d1, 0xbac: 0xe04d, 0xbad: 0x1c7a, 0xbae: 0x03d2, 0xbaf: 0x1caa,
+ 0xbb0: 0x0040, 0xbb1: 0x0040, 0xbb2: 0x1cb9, 0xbb3: 0x1ce9, 0xbb4: 0x1d11, 0xbb5: 0x0040,
+ 0xbb6: 0x0008, 0xbb7: 0x1d39, 0xbb8: 0x0725, 0xbb9: 0x14b9, 0xbba: 0x0515, 0xbbb: 0x14e9,
+ 0xbbc: 0x1ce9, 0xbbd: 0x073e, 0xbbe: 0x075e, 0xbbf: 0x0040,
+ // Block 0x2f, offset 0xbc0
+ 0xbc0: 0x000a, 0xbc1: 0x000a, 0xbc2: 0x000a, 0xbc3: 0x000a, 0xbc4: 0x000a, 0xbc5: 0x000a,
+ 0xbc6: 0x000a, 0xbc7: 0x000a, 0xbc8: 0x000a, 0xbc9: 0x000a, 0xbca: 0x000a, 0xbcb: 0x03c0,
+ 0xbcc: 0x0003, 0xbcd: 0x0003, 0xbce: 0x0340, 0xbcf: 0x0b40, 0xbd0: 0x0018, 0xbd1: 0xe00d,
+ 0xbd2: 0x0018, 0xbd3: 0x0018, 0xbd4: 0x0018, 0xbd5: 0x0018, 0xbd6: 0x0018, 0xbd7: 0x077e,
+ 0xbd8: 0x0018, 0xbd9: 0x0018, 0xbda: 0x0018, 0xbdb: 0x0018, 0xbdc: 0x0018, 0xbdd: 0x0018,
+ 0xbde: 0x0018, 0xbdf: 0x0018, 0xbe0: 0x0018, 0xbe1: 0x0018, 0xbe2: 0x0018, 0xbe3: 0x0018,
+ 0xbe4: 0x0040, 0xbe5: 0x0040, 0xbe6: 0x0040, 0xbe7: 0x0018, 0xbe8: 0x0040, 0xbe9: 0x0040,
+ 0xbea: 0x0340, 0xbeb: 0x0340, 0xbec: 0x0340, 0xbed: 0x0340, 0xbee: 0x0340, 0xbef: 0x000a,
+ 0xbf0: 0x0018, 0xbf1: 0x0018, 0xbf2: 0x0018, 0xbf3: 0x1d69, 0xbf4: 0x1da1, 0xbf5: 0x0018,
+ 0xbf6: 0x1df1, 0xbf7: 0x1e29, 0xbf8: 0x0018, 0xbf9: 0x0018, 0xbfa: 0x0018, 0xbfb: 0x0018,
+ 0xbfc: 0x1e7a, 0xbfd: 0x0018, 0xbfe: 0x079e, 0xbff: 0x0018,
+ // Block 0x30, offset 0xc00
+ 0xc00: 0x0018, 0xc01: 0x0018, 0xc02: 0x0018, 0xc03: 0x0018, 0xc04: 0x0018, 0xc05: 0x0018,
+ 0xc06: 0x0018, 0xc07: 0x1e92, 0xc08: 0x1eaa, 0xc09: 0x1ec2, 0xc0a: 0x0018, 0xc0b: 0x0018,
+ 0xc0c: 0x0018, 0xc0d: 0x0018, 0xc0e: 0x0018, 0xc0f: 0x0018, 0xc10: 0x0018, 0xc11: 0x0018,
+ 0xc12: 0x0018, 0xc13: 0x0018, 0xc14: 0x0018, 0xc15: 0x0018, 0xc16: 0x0018, 0xc17: 0x1ed9,
+ 0xc18: 0x0018, 0xc19: 0x0018, 0xc1a: 0x0018, 0xc1b: 0x0018, 0xc1c: 0x0018, 0xc1d: 0x0018,
+ 0xc1e: 0x0018, 0xc1f: 0x000a, 0xc20: 0x03c0, 0xc21: 0x0340, 0xc22: 0x0340, 0xc23: 0x0340,
+ 0xc24: 0x03c0, 0xc25: 0x0040, 0xc26: 0x0040, 0xc27: 0x0040, 0xc28: 0x0040, 0xc29: 0x0040,
+ 0xc2a: 0x0340, 0xc2b: 0x0340, 0xc2c: 0x0340, 0xc2d: 0x0340, 0xc2e: 0x0340, 0xc2f: 0x0340,
+ 0xc30: 0x1f41, 0xc31: 0x0f41, 0xc32: 0x0040, 0xc33: 0x0040, 0xc34: 0x1f51, 0xc35: 0x1f61,
+ 0xc36: 0x1f71, 0xc37: 0x1f81, 0xc38: 0x1f91, 0xc39: 0x1fa1, 0xc3a: 0x1fb2, 0xc3b: 0x07bd,
+ 0xc3c: 0x1fc2, 0xc3d: 0x1fd2, 0xc3e: 0x1fe2, 0xc3f: 0x0f71,
+ // Block 0x31, offset 0xc40
+ 0xc40: 0x1f41, 0xc41: 0x00c9, 0xc42: 0x0069, 0xc43: 0x0079, 0xc44: 0x1f51, 0xc45: 0x1f61,
+ 0xc46: 0x1f71, 0xc47: 0x1f81, 0xc48: 0x1f91, 0xc49: 0x1fa1, 0xc4a: 0x1fb2, 0xc4b: 0x07d5,
+ 0xc4c: 0x1fc2, 0xc4d: 0x1fd2, 0xc4e: 0x1fe2, 0xc4f: 0x0040, 0xc50: 0x0039, 0xc51: 0x0f09,
+ 0xc52: 0x00d9, 0xc53: 0x0369, 0xc54: 0x0ff9, 0xc55: 0x0249, 0xc56: 0x0f51, 0xc57: 0x0359,
+ 0xc58: 0x0f61, 0xc59: 0x0f71, 0xc5a: 0x0f99, 0xc5b: 0x01d9, 0xc5c: 0x0fa9, 0xc5d: 0x0040,
+ 0xc5e: 0x0040, 0xc5f: 0x0040, 0xc60: 0x0018, 0xc61: 0x0018, 0xc62: 0x0018, 0xc63: 0x0018,
+ 0xc64: 0x0018, 0xc65: 0x0018, 0xc66: 0x0018, 0xc67: 0x0018, 0xc68: 0x1ff1, 0xc69: 0x0018,
+ 0xc6a: 0x0018, 0xc6b: 0x0018, 0xc6c: 0x0018, 0xc6d: 0x0018, 0xc6e: 0x0018, 0xc6f: 0x0018,
+ 0xc70: 0x0018, 0xc71: 0x0018, 0xc72: 0x0018, 0xc73: 0x0018, 0xc74: 0x0018, 0xc75: 0x0018,
+ 0xc76: 0x0018, 0xc77: 0x0018, 0xc78: 0x0018, 0xc79: 0x0018, 0xc7a: 0x0018, 0xc7b: 0x0018,
+ 0xc7c: 0x0018, 0xc7d: 0x0018, 0xc7e: 0x0018, 0xc7f: 0x0018,
+ // Block 0x32, offset 0xc80
+ 0xc80: 0x07ee, 0xc81: 0x080e, 0xc82: 0x1159, 0xc83: 0x082d, 0xc84: 0x0018, 0xc85: 0x084e,
+ 0xc86: 0x086e, 0xc87: 0x1011, 0xc88: 0x0018, 0xc89: 0x088d, 0xc8a: 0x0f31, 0xc8b: 0x0249,
+ 0xc8c: 0x0249, 0xc8d: 0x0249, 0xc8e: 0x0249, 0xc8f: 0x2009, 0xc90: 0x0f41, 0xc91: 0x0f41,
+ 0xc92: 0x0359, 0xc93: 0x0359, 0xc94: 0x0018, 0xc95: 0x0f71, 0xc96: 0x2021, 0xc97: 0x0018,
+ 0xc98: 0x0018, 0xc99: 0x0f99, 0xc9a: 0x2039, 0xc9b: 0x0269, 0xc9c: 0x0269, 0xc9d: 0x0269,
+ 0xc9e: 0x0018, 0xc9f: 0x0018, 0xca0: 0x2049, 0xca1: 0x08ad, 0xca2: 0x2061, 0xca3: 0x0018,
+ 0xca4: 0x13d1, 0xca5: 0x0018, 0xca6: 0x2079, 0xca7: 0x0018, 0xca8: 0x13d1, 0xca9: 0x0018,
+ 0xcaa: 0x0f51, 0xcab: 0x2091, 0xcac: 0x0ee9, 0xcad: 0x1159, 0xcae: 0x0018, 0xcaf: 0x0f09,
+ 0xcb0: 0x0f09, 0xcb1: 0x1199, 0xcb2: 0x0040, 0xcb3: 0x0f61, 0xcb4: 0x00d9, 0xcb5: 0x20a9,
+ 0xcb6: 0x20c1, 0xcb7: 0x20d9, 0xcb8: 0x20f1, 0xcb9: 0x0f41, 0xcba: 0x0018, 0xcbb: 0x08cd,
+ 0xcbc: 0x2109, 0xcbd: 0x10b1, 0xcbe: 0x10b1, 0xcbf: 0x2109,
+ // Block 0x33, offset 0xcc0
+ 0xcc0: 0x08ed, 0xcc1: 0x0018, 0xcc2: 0x0018, 0xcc3: 0x0018, 0xcc4: 0x0018, 0xcc5: 0x0ef9,
+ 0xcc6: 0x0ef9, 0xcc7: 0x0f09, 0xcc8: 0x0f41, 0xcc9: 0x0259, 0xcca: 0x0018, 0xccb: 0x0018,
+ 0xccc: 0x0018, 0xccd: 0x0018, 0xcce: 0x0008, 0xccf: 0x0018, 0xcd0: 0x2121, 0xcd1: 0x2151,
+ 0xcd2: 0x2181, 0xcd3: 0x21b9, 0xcd4: 0x21e9, 0xcd5: 0x2219, 0xcd6: 0x2249, 0xcd7: 0x2279,
+ 0xcd8: 0x22a9, 0xcd9: 0x22d9, 0xcda: 0x2309, 0xcdb: 0x2339, 0xcdc: 0x2369, 0xcdd: 0x2399,
+ 0xcde: 0x23c9, 0xcdf: 0x23f9, 0xce0: 0x0f41, 0xce1: 0x2421, 0xce2: 0x0905, 0xce3: 0x2439,
+ 0xce4: 0x1089, 0xce5: 0x2451, 0xce6: 0x0925, 0xce7: 0x2469, 0xce8: 0x2491, 0xce9: 0x0369,
+ 0xcea: 0x24a9, 0xceb: 0x0945, 0xcec: 0x0359, 0xced: 0x1159, 0xcee: 0x0ef9, 0xcef: 0x0f61,
+ 0xcf0: 0x0f41, 0xcf1: 0x2421, 0xcf2: 0x0965, 0xcf3: 0x2439, 0xcf4: 0x1089, 0xcf5: 0x2451,
+ 0xcf6: 0x0985, 0xcf7: 0x2469, 0xcf8: 0x2491, 0xcf9: 0x0369, 0xcfa: 0x24a9, 0xcfb: 0x09a5,
+ 0xcfc: 0x0359, 0xcfd: 0x1159, 0xcfe: 0x0ef9, 0xcff: 0x0f61,
+ // Block 0x34, offset 0xd00
+ 0xd00: 0x0018, 0xd01: 0x0018, 0xd02: 0x0018, 0xd03: 0x0018, 0xd04: 0x0018, 0xd05: 0x0018,
+ 0xd06: 0x0018, 0xd07: 0x0018, 0xd08: 0x0018, 0xd09: 0x0018, 0xd0a: 0x0018, 0xd0b: 0x0040,
+ 0xd0c: 0x0040, 0xd0d: 0x0040, 0xd0e: 0x0040, 0xd0f: 0x0040, 0xd10: 0x0040, 0xd11: 0x0040,
+ 0xd12: 0x0040, 0xd13: 0x0040, 0xd14: 0x0040, 0xd15: 0x0040, 0xd16: 0x0040, 0xd17: 0x0040,
+ 0xd18: 0x0040, 0xd19: 0x0040, 0xd1a: 0x0040, 0xd1b: 0x0040, 0xd1c: 0x0040, 0xd1d: 0x0040,
+ 0xd1e: 0x0040, 0xd1f: 0x0040, 0xd20: 0x00c9, 0xd21: 0x0069, 0xd22: 0x0079, 0xd23: 0x1f51,
+ 0xd24: 0x1f61, 0xd25: 0x1f71, 0xd26: 0x1f81, 0xd27: 0x1f91, 0xd28: 0x1fa1, 0xd29: 0x2601,
+ 0xd2a: 0x2619, 0xd2b: 0x2631, 0xd2c: 0x2649, 0xd2d: 0x2661, 0xd2e: 0x2679, 0xd2f: 0x2691,
+ 0xd30: 0x26a9, 0xd31: 0x26c1, 0xd32: 0x26d9, 0xd33: 0x26f1, 0xd34: 0x0a06, 0xd35: 0x0a26,
+ 0xd36: 0x0a46, 0xd37: 0x0a66, 0xd38: 0x0a86, 0xd39: 0x0aa6, 0xd3a: 0x0ac6, 0xd3b: 0x0ae6,
+ 0xd3c: 0x0b06, 0xd3d: 0x270a, 0xd3e: 0x2732, 0xd3f: 0x275a,
+ // Block 0x35, offset 0xd40
+ 0xd40: 0x2782, 0xd41: 0x27aa, 0xd42: 0x27d2, 0xd43: 0x27fa, 0xd44: 0x2822, 0xd45: 0x284a,
+ 0xd46: 0x2872, 0xd47: 0x289a, 0xd48: 0x0040, 0xd49: 0x0040, 0xd4a: 0x0040, 0xd4b: 0x0040,
+ 0xd4c: 0x0040, 0xd4d: 0x0040, 0xd4e: 0x0040, 0xd4f: 0x0040, 0xd50: 0x0040, 0xd51: 0x0040,
+ 0xd52: 0x0040, 0xd53: 0x0040, 0xd54: 0x0040, 0xd55: 0x0040, 0xd56: 0x0040, 0xd57: 0x0040,
+ 0xd58: 0x0040, 0xd59: 0x0040, 0xd5a: 0x0040, 0xd5b: 0x0040, 0xd5c: 0x0b26, 0xd5d: 0x0b46,
+ 0xd5e: 0x0b66, 0xd5f: 0x0b86, 0xd60: 0x0ba6, 0xd61: 0x0bc6, 0xd62: 0x0be6, 0xd63: 0x0c06,
+ 0xd64: 0x0c26, 0xd65: 0x0c46, 0xd66: 0x0c66, 0xd67: 0x0c86, 0xd68: 0x0ca6, 0xd69: 0x0cc6,
+ 0xd6a: 0x0ce6, 0xd6b: 0x0d06, 0xd6c: 0x0d26, 0xd6d: 0x0d46, 0xd6e: 0x0d66, 0xd6f: 0x0d86,
+ 0xd70: 0x0da6, 0xd71: 0x0dc6, 0xd72: 0x0de6, 0xd73: 0x0e06, 0xd74: 0x0e26, 0xd75: 0x0e46,
+ 0xd76: 0x0039, 0xd77: 0x0ee9, 0xd78: 0x1159, 0xd79: 0x0ef9, 0xd7a: 0x0f09, 0xd7b: 0x1199,
+ 0xd7c: 0x0f31, 0xd7d: 0x0249, 0xd7e: 0x0f41, 0xd7f: 0x0259,
+ // Block 0x36, offset 0xd80
+ 0xd80: 0x0f51, 0xd81: 0x0359, 0xd82: 0x0f61, 0xd83: 0x0f71, 0xd84: 0x00d9, 0xd85: 0x0f99,
+ 0xd86: 0x2039, 0xd87: 0x0269, 0xd88: 0x01d9, 0xd89: 0x0fa9, 0xd8a: 0x0fb9, 0xd8b: 0x1089,
+ 0xd8c: 0x0279, 0xd8d: 0x0369, 0xd8e: 0x0289, 0xd8f: 0x13d1, 0xd90: 0x0039, 0xd91: 0x0ee9,
+ 0xd92: 0x1159, 0xd93: 0x0ef9, 0xd94: 0x0f09, 0xd95: 0x1199, 0xd96: 0x0f31, 0xd97: 0x0249,
+ 0xd98: 0x0f41, 0xd99: 0x0259, 0xd9a: 0x0f51, 0xd9b: 0x0359, 0xd9c: 0x0f61, 0xd9d: 0x0f71,
+ 0xd9e: 0x00d9, 0xd9f: 0x0f99, 0xda0: 0x2039, 0xda1: 0x0269, 0xda2: 0x01d9, 0xda3: 0x0fa9,
+ 0xda4: 0x0fb9, 0xda5: 0x1089, 0xda6: 0x0279, 0xda7: 0x0369, 0xda8: 0x0289, 0xda9: 0x13d1,
+ 0xdaa: 0x1f41, 0xdab: 0x0018, 0xdac: 0x0018, 0xdad: 0x0018, 0xdae: 0x0018, 0xdaf: 0x0018,
+ 0xdb0: 0x0018, 0xdb1: 0x0018, 0xdb2: 0x0018, 0xdb3: 0x0018, 0xdb4: 0x0018, 0xdb5: 0x0018,
+ 0xdb6: 0x0018, 0xdb7: 0x0018, 0xdb8: 0x0018, 0xdb9: 0x0018, 0xdba: 0x0018, 0xdbb: 0x0018,
+ 0xdbc: 0x0018, 0xdbd: 0x0018, 0xdbe: 0x0018, 0xdbf: 0x0018,
+ // Block 0x37, offset 0xdc0
+ 0xdc0: 0x0008, 0xdc1: 0x0008, 0xdc2: 0x0008, 0xdc3: 0x0008, 0xdc4: 0x0008, 0xdc5: 0x0008,
+ 0xdc6: 0x0008, 0xdc7: 0x0008, 0xdc8: 0x0008, 0xdc9: 0x0008, 0xdca: 0x0008, 0xdcb: 0x0008,
+ 0xdcc: 0x0008, 0xdcd: 0x0008, 0xdce: 0x0008, 0xdcf: 0x0008, 0xdd0: 0x0008, 0xdd1: 0x0008,
+ 0xdd2: 0x0008, 0xdd3: 0x0008, 0xdd4: 0x0008, 0xdd5: 0x0008, 0xdd6: 0x0008, 0xdd7: 0x0008,
+ 0xdd8: 0x0008, 0xdd9: 0x0008, 0xdda: 0x0008, 0xddb: 0x0008, 0xddc: 0x0008, 0xddd: 0x0008,
+ 0xdde: 0x0008, 0xddf: 0x0040, 0xde0: 0xe00d, 0xde1: 0x0008, 0xde2: 0x2971, 0xde3: 0x0ebd,
+ 0xde4: 0x2989, 0xde5: 0x0008, 0xde6: 0x0008, 0xde7: 0xe07d, 0xde8: 0x0008, 0xde9: 0xe01d,
+ 0xdea: 0x0008, 0xdeb: 0xe03d, 0xdec: 0x0008, 0xded: 0x0fe1, 0xdee: 0x1281, 0xdef: 0x0fc9,
+ 0xdf0: 0x1141, 0xdf1: 0x0008, 0xdf2: 0xe00d, 0xdf3: 0x0008, 0xdf4: 0x0008, 0xdf5: 0xe01d,
+ 0xdf6: 0x0008, 0xdf7: 0x0008, 0xdf8: 0x0008, 0xdf9: 0x0008, 0xdfa: 0x0008, 0xdfb: 0x0008,
+ 0xdfc: 0x0259, 0xdfd: 0x1089, 0xdfe: 0x29a1, 0xdff: 0x29b9,
+ // Block 0x38, offset 0xe00
+ 0xe00: 0xe00d, 0xe01: 0x0008, 0xe02: 0xe00d, 0xe03: 0x0008, 0xe04: 0xe00d, 0xe05: 0x0008,
+ 0xe06: 0xe00d, 0xe07: 0x0008, 0xe08: 0xe00d, 0xe09: 0x0008, 0xe0a: 0xe00d, 0xe0b: 0x0008,
+ 0xe0c: 0xe00d, 0xe0d: 0x0008, 0xe0e: 0xe00d, 0xe0f: 0x0008, 0xe10: 0xe00d, 0xe11: 0x0008,
+ 0xe12: 0xe00d, 0xe13: 0x0008, 0xe14: 0xe00d, 0xe15: 0x0008, 0xe16: 0xe00d, 0xe17: 0x0008,
+ 0xe18: 0xe00d, 0xe19: 0x0008, 0xe1a: 0xe00d, 0xe1b: 0x0008, 0xe1c: 0xe00d, 0xe1d: 0x0008,
+ 0xe1e: 0xe00d, 0xe1f: 0x0008, 0xe20: 0xe00d, 0xe21: 0x0008, 0xe22: 0xe00d, 0xe23: 0x0008,
+ 0xe24: 0x0008, 0xe25: 0x0018, 0xe26: 0x0018, 0xe27: 0x0018, 0xe28: 0x0018, 0xe29: 0x0018,
+ 0xe2a: 0x0018, 0xe2b: 0xe03d, 0xe2c: 0x0008, 0xe2d: 0xe01d, 0xe2e: 0x0008, 0xe2f: 0x3308,
+ 0xe30: 0x3308, 0xe31: 0x3308, 0xe32: 0xe00d, 0xe33: 0x0008, 0xe34: 0x0040, 0xe35: 0x0040,
+ 0xe36: 0x0040, 0xe37: 0x0040, 0xe38: 0x0040, 0xe39: 0x0018, 0xe3a: 0x0018, 0xe3b: 0x0018,
+ 0xe3c: 0x0018, 0xe3d: 0x0018, 0xe3e: 0x0018, 0xe3f: 0x0018,
+ // Block 0x39, offset 0xe40
+ 0xe40: 0x26fd, 0xe41: 0x271d, 0xe42: 0x273d, 0xe43: 0x275d, 0xe44: 0x277d, 0xe45: 0x279d,
+ 0xe46: 0x27bd, 0xe47: 0x27dd, 0xe48: 0x27fd, 0xe49: 0x281d, 0xe4a: 0x283d, 0xe4b: 0x285d,
+ 0xe4c: 0x287d, 0xe4d: 0x289d, 0xe4e: 0x28bd, 0xe4f: 0x28dd, 0xe50: 0x28fd, 0xe51: 0x291d,
+ 0xe52: 0x293d, 0xe53: 0x295d, 0xe54: 0x297d, 0xe55: 0x299d, 0xe56: 0x0040, 0xe57: 0x0040,
+ 0xe58: 0x0040, 0xe59: 0x0040, 0xe5a: 0x0040, 0xe5b: 0x0040, 0xe5c: 0x0040, 0xe5d: 0x0040,
+ 0xe5e: 0x0040, 0xe5f: 0x0040, 0xe60: 0x0040, 0xe61: 0x0040, 0xe62: 0x0040, 0xe63: 0x0040,
+ 0xe64: 0x0040, 0xe65: 0x0040, 0xe66: 0x0040, 0xe67: 0x0040, 0xe68: 0x0040, 0xe69: 0x0040,
+ 0xe6a: 0x0040, 0xe6b: 0x0040, 0xe6c: 0x0040, 0xe6d: 0x0040, 0xe6e: 0x0040, 0xe6f: 0x0040,
+ 0xe70: 0x0040, 0xe71: 0x0040, 0xe72: 0x0040, 0xe73: 0x0040, 0xe74: 0x0040, 0xe75: 0x0040,
+ 0xe76: 0x0040, 0xe77: 0x0040, 0xe78: 0x0040, 0xe79: 0x0040, 0xe7a: 0x0040, 0xe7b: 0x0040,
+ 0xe7c: 0x0040, 0xe7d: 0x0040, 0xe7e: 0x0040, 0xe7f: 0x0040,
+ // Block 0x3a, offset 0xe80
+ 0xe80: 0x000a, 0xe81: 0x0018, 0xe82: 0x29d1, 0xe83: 0x0018, 0xe84: 0x0018, 0xe85: 0x0008,
+ 0xe86: 0x0008, 0xe87: 0x0008, 0xe88: 0x0018, 0xe89: 0x0018, 0xe8a: 0x0018, 0xe8b: 0x0018,
+ 0xe8c: 0x0018, 0xe8d: 0x0018, 0xe8e: 0x0018, 0xe8f: 0x0018, 0xe90: 0x0018, 0xe91: 0x0018,
+ 0xe92: 0x0018, 0xe93: 0x0018, 0xe94: 0x0018, 0xe95: 0x0018, 0xe96: 0x0018, 0xe97: 0x0018,
+ 0xe98: 0x0018, 0xe99: 0x0018, 0xe9a: 0x0018, 0xe9b: 0x0018, 0xe9c: 0x0018, 0xe9d: 0x0018,
+ 0xe9e: 0x0018, 0xe9f: 0x0018, 0xea0: 0x0018, 0xea1: 0x0018, 0xea2: 0x0018, 0xea3: 0x0018,
+ 0xea4: 0x0018, 0xea5: 0x0018, 0xea6: 0x0018, 0xea7: 0x0018, 0xea8: 0x0018, 0xea9: 0x0018,
+ 0xeaa: 0x3308, 0xeab: 0x3308, 0xeac: 0x3308, 0xead: 0x3308, 0xeae: 0x3018, 0xeaf: 0x3018,
+ 0xeb0: 0x0018, 0xeb1: 0x0018, 0xeb2: 0x0018, 0xeb3: 0x0018, 0xeb4: 0x0018, 0xeb5: 0x0018,
+ 0xeb6: 0xe125, 0xeb7: 0x0018, 0xeb8: 0x29bd, 0xeb9: 0x29dd, 0xeba: 0x29fd, 0xebb: 0x0018,
+ 0xebc: 0x0008, 0xebd: 0x0018, 0xebe: 0x0018, 0xebf: 0x0018,
+ // Block 0x3b, offset 0xec0
+ 0xec0: 0x2b3d, 0xec1: 0x2b5d, 0xec2: 0x2b7d, 0xec3: 0x2b9d, 0xec4: 0x2bbd, 0xec5: 0x2bdd,
+ 0xec6: 0x2bdd, 0xec7: 0x2bdd, 0xec8: 0x2bfd, 0xec9: 0x2bfd, 0xeca: 0x2bfd, 0xecb: 0x2bfd,
+ 0xecc: 0x2c1d, 0xecd: 0x2c1d, 0xece: 0x2c1d, 0xecf: 0x2c3d, 0xed0: 0x2c5d, 0xed1: 0x2c5d,
+ 0xed2: 0x2a7d, 0xed3: 0x2a7d, 0xed4: 0x2c5d, 0xed5: 0x2c5d, 0xed6: 0x2c7d, 0xed7: 0x2c7d,
+ 0xed8: 0x2c5d, 0xed9: 0x2c5d, 0xeda: 0x2a7d, 0xedb: 0x2a7d, 0xedc: 0x2c5d, 0xedd: 0x2c5d,
+ 0xede: 0x2c3d, 0xedf: 0x2c3d, 0xee0: 0x2c9d, 0xee1: 0x2c9d, 0xee2: 0x2cbd, 0xee3: 0x2cbd,
+ 0xee4: 0x0040, 0xee5: 0x2cdd, 0xee6: 0x2cfd, 0xee7: 0x2d1d, 0xee8: 0x2d1d, 0xee9: 0x2d3d,
+ 0xeea: 0x2d5d, 0xeeb: 0x2d7d, 0xeec: 0x2d9d, 0xeed: 0x2dbd, 0xeee: 0x2ddd, 0xeef: 0x2dfd,
+ 0xef0: 0x2e1d, 0xef1: 0x2e3d, 0xef2: 0x2e3d, 0xef3: 0x2e5d, 0xef4: 0x2e7d, 0xef5: 0x2e7d,
+ 0xef6: 0x2e9d, 0xef7: 0x2ebd, 0xef8: 0x2e5d, 0xef9: 0x2edd, 0xefa: 0x2efd, 0xefb: 0x2edd,
+ 0xefc: 0x2e5d, 0xefd: 0x2f1d, 0xefe: 0x2f3d, 0xeff: 0x2f5d,
+ // Block 0x3c, offset 0xf00
+ 0xf00: 0x2f7d, 0xf01: 0x2f9d, 0xf02: 0x2cfd, 0xf03: 0x2cdd, 0xf04: 0x2fbd, 0xf05: 0x2fdd,
+ 0xf06: 0x2ffd, 0xf07: 0x301d, 0xf08: 0x303d, 0xf09: 0x305d, 0xf0a: 0x307d, 0xf0b: 0x309d,
+ 0xf0c: 0x30bd, 0xf0d: 0x30dd, 0xf0e: 0x30fd, 0xf0f: 0x0040, 0xf10: 0x0018, 0xf11: 0x0018,
+ 0xf12: 0x311d, 0xf13: 0x313d, 0xf14: 0x315d, 0xf15: 0x317d, 0xf16: 0x319d, 0xf17: 0x31bd,
+ 0xf18: 0x31dd, 0xf19: 0x31fd, 0xf1a: 0x321d, 0xf1b: 0x323d, 0xf1c: 0x315d, 0xf1d: 0x325d,
+ 0xf1e: 0x327d, 0xf1f: 0x329d, 0xf20: 0x0008, 0xf21: 0x0008, 0xf22: 0x0008, 0xf23: 0x0008,
+ 0xf24: 0x0008, 0xf25: 0x0008, 0xf26: 0x0008, 0xf27: 0x0008, 0xf28: 0x0008, 0xf29: 0x0008,
+ 0xf2a: 0x0008, 0xf2b: 0x0008, 0xf2c: 0x0008, 0xf2d: 0x0008, 0xf2e: 0x0008, 0xf2f: 0x0008,
+ 0xf30: 0x0008, 0xf31: 0x0008, 0xf32: 0x0008, 0xf33: 0x0008, 0xf34: 0x0008, 0xf35: 0x0008,
+ 0xf36: 0x0008, 0xf37: 0x0008, 0xf38: 0x0008, 0xf39: 0x0008, 0xf3a: 0x0008, 0xf3b: 0x0040,
+ 0xf3c: 0x0040, 0xf3d: 0x0040, 0xf3e: 0x0040, 0xf3f: 0x0040,
+ // Block 0x3d, offset 0xf40
+ 0xf40: 0x36a2, 0xf41: 0x36d2, 0xf42: 0x3702, 0xf43: 0x3732, 0xf44: 0x32bd, 0xf45: 0x32dd,
+ 0xf46: 0x32fd, 0xf47: 0x331d, 0xf48: 0x0018, 0xf49: 0x0018, 0xf4a: 0x0018, 0xf4b: 0x0018,
+ 0xf4c: 0x0018, 0xf4d: 0x0018, 0xf4e: 0x0018, 0xf4f: 0x0018, 0xf50: 0x333d, 0xf51: 0x3761,
+ 0xf52: 0x3779, 0xf53: 0x3791, 0xf54: 0x37a9, 0xf55: 0x37c1, 0xf56: 0x37d9, 0xf57: 0x37f1,
+ 0xf58: 0x3809, 0xf59: 0x3821, 0xf5a: 0x3839, 0xf5b: 0x3851, 0xf5c: 0x3869, 0xf5d: 0x3881,
+ 0xf5e: 0x3899, 0xf5f: 0x38b1, 0xf60: 0x335d, 0xf61: 0x337d, 0xf62: 0x339d, 0xf63: 0x33bd,
+ 0xf64: 0x33dd, 0xf65: 0x33dd, 0xf66: 0x33fd, 0xf67: 0x341d, 0xf68: 0x343d, 0xf69: 0x345d,
+ 0xf6a: 0x347d, 0xf6b: 0x349d, 0xf6c: 0x34bd, 0xf6d: 0x34dd, 0xf6e: 0x34fd, 0xf6f: 0x351d,
+ 0xf70: 0x353d, 0xf71: 0x355d, 0xf72: 0x357d, 0xf73: 0x359d, 0xf74: 0x35bd, 0xf75: 0x35dd,
+ 0xf76: 0x35fd, 0xf77: 0x361d, 0xf78: 0x363d, 0xf79: 0x365d, 0xf7a: 0x367d, 0xf7b: 0x369d,
+ 0xf7c: 0x38c9, 0xf7d: 0x3901, 0xf7e: 0x36bd, 0xf7f: 0x0018,
+ // Block 0x3e, offset 0xf80
+ 0xf80: 0x36dd, 0xf81: 0x36fd, 0xf82: 0x371d, 0xf83: 0x373d, 0xf84: 0x375d, 0xf85: 0x377d,
+ 0xf86: 0x379d, 0xf87: 0x37bd, 0xf88: 0x37dd, 0xf89: 0x37fd, 0xf8a: 0x381d, 0xf8b: 0x383d,
+ 0xf8c: 0x385d, 0xf8d: 0x387d, 0xf8e: 0x389d, 0xf8f: 0x38bd, 0xf90: 0x38dd, 0xf91: 0x38fd,
+ 0xf92: 0x391d, 0xf93: 0x393d, 0xf94: 0x395d, 0xf95: 0x397d, 0xf96: 0x399d, 0xf97: 0x39bd,
+ 0xf98: 0x39dd, 0xf99: 0x39fd, 0xf9a: 0x3a1d, 0xf9b: 0x3a3d, 0xf9c: 0x3a5d, 0xf9d: 0x3a7d,
+ 0xf9e: 0x3a9d, 0xf9f: 0x3abd, 0xfa0: 0x3add, 0xfa1: 0x3afd, 0xfa2: 0x3b1d, 0xfa3: 0x3b3d,
+ 0xfa4: 0x3b5d, 0xfa5: 0x3b7d, 0xfa6: 0x127d, 0xfa7: 0x3b9d, 0xfa8: 0x3bbd, 0xfa9: 0x3bdd,
+ 0xfaa: 0x3bfd, 0xfab: 0x3c1d, 0xfac: 0x3c3d, 0xfad: 0x3c5d, 0xfae: 0x239d, 0xfaf: 0x3c7d,
+ 0xfb0: 0x3c9d, 0xfb1: 0x3939, 0xfb2: 0x3951, 0xfb3: 0x3969, 0xfb4: 0x3981, 0xfb5: 0x3999,
+ 0xfb6: 0x39b1, 0xfb7: 0x39c9, 0xfb8: 0x39e1, 0xfb9: 0x39f9, 0xfba: 0x3a11, 0xfbb: 0x3a29,
+ 0xfbc: 0x3a41, 0xfbd: 0x3a59, 0xfbe: 0x3a71, 0xfbf: 0x3a89,
+ // Block 0x3f, offset 0xfc0
+ 0xfc0: 0x3aa1, 0xfc1: 0x3ac9, 0xfc2: 0x3af1, 0xfc3: 0x3b19, 0xfc4: 0x3b41, 0xfc5: 0x3b69,
+ 0xfc6: 0x3b91, 0xfc7: 0x3bb9, 0xfc8: 0x3be1, 0xfc9: 0x3c09, 0xfca: 0x3c39, 0xfcb: 0x3c69,
+ 0xfcc: 0x3c99, 0xfcd: 0x3cbd, 0xfce: 0x3cb1, 0xfcf: 0x3cdd, 0xfd0: 0x3cfd, 0xfd1: 0x3d15,
+ 0xfd2: 0x3d2d, 0xfd3: 0x3d45, 0xfd4: 0x3d5d, 0xfd5: 0x3d5d, 0xfd6: 0x3d45, 0xfd7: 0x3d75,
+ 0xfd8: 0x07bd, 0xfd9: 0x3d8d, 0xfda: 0x3da5, 0xfdb: 0x3dbd, 0xfdc: 0x3dd5, 0xfdd: 0x3ded,
+ 0xfde: 0x3e05, 0xfdf: 0x3e1d, 0xfe0: 0x3e35, 0xfe1: 0x3e4d, 0xfe2: 0x3e65, 0xfe3: 0x3e7d,
+ 0xfe4: 0x3e95, 0xfe5: 0x3e95, 0xfe6: 0x3ead, 0xfe7: 0x3ead, 0xfe8: 0x3ec5, 0xfe9: 0x3ec5,
+ 0xfea: 0x3edd, 0xfeb: 0x3ef5, 0xfec: 0x3f0d, 0xfed: 0x3f25, 0xfee: 0x3f3d, 0xfef: 0x3f3d,
+ 0xff0: 0x3f55, 0xff1: 0x3f55, 0xff2: 0x3f55, 0xff3: 0x3f6d, 0xff4: 0x3f85, 0xff5: 0x3f9d,
+ 0xff6: 0x3fb5, 0xff7: 0x3f9d, 0xff8: 0x3fcd, 0xff9: 0x3fe5, 0xffa: 0x3f6d, 0xffb: 0x3ffd,
+ 0xffc: 0x4015, 0xffd: 0x4015, 0xffe: 0x4015, 0xfff: 0x0040,
+ // Block 0x40, offset 0x1000
+ 0x1000: 0x3cc9, 0x1001: 0x3d31, 0x1002: 0x3d99, 0x1003: 0x3e01, 0x1004: 0x3e51, 0x1005: 0x3eb9,
+ 0x1006: 0x3f09, 0x1007: 0x3f59, 0x1008: 0x3fd9, 0x1009: 0x4041, 0x100a: 0x4091, 0x100b: 0x40e1,
+ 0x100c: 0x4131, 0x100d: 0x4199, 0x100e: 0x4201, 0x100f: 0x4251, 0x1010: 0x42a1, 0x1011: 0x42d9,
+ 0x1012: 0x4329, 0x1013: 0x4391, 0x1014: 0x43f9, 0x1015: 0x4431, 0x1016: 0x44b1, 0x1017: 0x4549,
+ 0x1018: 0x45c9, 0x1019: 0x4619, 0x101a: 0x4699, 0x101b: 0x4719, 0x101c: 0x4781, 0x101d: 0x47d1,
+ 0x101e: 0x4821, 0x101f: 0x4871, 0x1020: 0x48d9, 0x1021: 0x4959, 0x1022: 0x49c1, 0x1023: 0x4a11,
+ 0x1024: 0x4a61, 0x1025: 0x4ab1, 0x1026: 0x4ae9, 0x1027: 0x4b21, 0x1028: 0x4b59, 0x1029: 0x4b91,
+ 0x102a: 0x4be1, 0x102b: 0x4c31, 0x102c: 0x4cb1, 0x102d: 0x4d01, 0x102e: 0x4d69, 0x102f: 0x4de9,
+ 0x1030: 0x4e39, 0x1031: 0x4e71, 0x1032: 0x4ea9, 0x1033: 0x4f29, 0x1034: 0x4f91, 0x1035: 0x5011,
+ 0x1036: 0x5061, 0x1037: 0x50e1, 0x1038: 0x5119, 0x1039: 0x5169, 0x103a: 0x51b9, 0x103b: 0x5209,
+ 0x103c: 0x5259, 0x103d: 0x52a9, 0x103e: 0x5311, 0x103f: 0x5361,
+ // Block 0x41, offset 0x1040
+ 0x1040: 0x5399, 0x1041: 0x53e9, 0x1042: 0x5439, 0x1043: 0x5489, 0x1044: 0x54f1, 0x1045: 0x5541,
+ 0x1046: 0x5591, 0x1047: 0x55e1, 0x1048: 0x5661, 0x1049: 0x56c9, 0x104a: 0x5701, 0x104b: 0x5781,
+ 0x104c: 0x57b9, 0x104d: 0x5821, 0x104e: 0x5889, 0x104f: 0x58d9, 0x1050: 0x5929, 0x1051: 0x5979,
+ 0x1052: 0x59e1, 0x1053: 0x5a19, 0x1054: 0x5a69, 0x1055: 0x5ad1, 0x1056: 0x5b09, 0x1057: 0x5b89,
+ 0x1058: 0x5bd9, 0x1059: 0x5c01, 0x105a: 0x5c29, 0x105b: 0x5c51, 0x105c: 0x5c79, 0x105d: 0x5ca1,
+ 0x105e: 0x5cc9, 0x105f: 0x5cf1, 0x1060: 0x5d19, 0x1061: 0x5d41, 0x1062: 0x5d69, 0x1063: 0x5d99,
+ 0x1064: 0x5dc9, 0x1065: 0x5df9, 0x1066: 0x5e29, 0x1067: 0x5e59, 0x1068: 0x5e89, 0x1069: 0x5eb9,
+ 0x106a: 0x5ee9, 0x106b: 0x5f19, 0x106c: 0x5f49, 0x106d: 0x5f79, 0x106e: 0x5fa9, 0x106f: 0x5fd9,
+ 0x1070: 0x6009, 0x1071: 0x402d, 0x1072: 0x6039, 0x1073: 0x6051, 0x1074: 0x404d, 0x1075: 0x6069,
+ 0x1076: 0x6081, 0x1077: 0x6099, 0x1078: 0x406d, 0x1079: 0x406d, 0x107a: 0x60b1, 0x107b: 0x60c9,
+ 0x107c: 0x6101, 0x107d: 0x6139, 0x107e: 0x6171, 0x107f: 0x61a9,
+ // Block 0x42, offset 0x1080
+ 0x1080: 0x6211, 0x1081: 0x6229, 0x1082: 0x408d, 0x1083: 0x6241, 0x1084: 0x6259, 0x1085: 0x6271,
+ 0x1086: 0x6289, 0x1087: 0x62a1, 0x1088: 0x40ad, 0x1089: 0x62b9, 0x108a: 0x62e1, 0x108b: 0x62f9,
+ 0x108c: 0x40cd, 0x108d: 0x40cd, 0x108e: 0x6311, 0x108f: 0x6329, 0x1090: 0x6341, 0x1091: 0x40ed,
+ 0x1092: 0x410d, 0x1093: 0x412d, 0x1094: 0x414d, 0x1095: 0x416d, 0x1096: 0x6359, 0x1097: 0x6371,
+ 0x1098: 0x6389, 0x1099: 0x63a1, 0x109a: 0x63b9, 0x109b: 0x418d, 0x109c: 0x63d1, 0x109d: 0x63e9,
+ 0x109e: 0x6401, 0x109f: 0x41ad, 0x10a0: 0x41cd, 0x10a1: 0x6419, 0x10a2: 0x41ed, 0x10a3: 0x420d,
+ 0x10a4: 0x422d, 0x10a5: 0x6431, 0x10a6: 0x424d, 0x10a7: 0x6449, 0x10a8: 0x6479, 0x10a9: 0x6211,
+ 0x10aa: 0x426d, 0x10ab: 0x428d, 0x10ac: 0x42ad, 0x10ad: 0x42cd, 0x10ae: 0x64b1, 0x10af: 0x64f1,
+ 0x10b0: 0x6539, 0x10b1: 0x6551, 0x10b2: 0x42ed, 0x10b3: 0x6569, 0x10b4: 0x6581, 0x10b5: 0x6599,
+ 0x10b6: 0x430d, 0x10b7: 0x65b1, 0x10b8: 0x65c9, 0x10b9: 0x65b1, 0x10ba: 0x65e1, 0x10bb: 0x65f9,
+ 0x10bc: 0x432d, 0x10bd: 0x6611, 0x10be: 0x6629, 0x10bf: 0x6611,
+ // Block 0x43, offset 0x10c0
+ 0x10c0: 0x434d, 0x10c1: 0x436d, 0x10c2: 0x0040, 0x10c3: 0x6641, 0x10c4: 0x6659, 0x10c5: 0x6671,
+ 0x10c6: 0x6689, 0x10c7: 0x0040, 0x10c8: 0x66c1, 0x10c9: 0x66d9, 0x10ca: 0x66f1, 0x10cb: 0x6709,
+ 0x10cc: 0x6721, 0x10cd: 0x6739, 0x10ce: 0x6401, 0x10cf: 0x6751, 0x10d0: 0x6769, 0x10d1: 0x6781,
+ 0x10d2: 0x438d, 0x10d3: 0x6799, 0x10d4: 0x6289, 0x10d5: 0x43ad, 0x10d6: 0x43cd, 0x10d7: 0x67b1,
+ 0x10d8: 0x0040, 0x10d9: 0x43ed, 0x10da: 0x67c9, 0x10db: 0x67e1, 0x10dc: 0x67f9, 0x10dd: 0x6811,
+ 0x10de: 0x6829, 0x10df: 0x6859, 0x10e0: 0x6889, 0x10e1: 0x68b1, 0x10e2: 0x68d9, 0x10e3: 0x6901,
+ 0x10e4: 0x6929, 0x10e5: 0x6951, 0x10e6: 0x6979, 0x10e7: 0x69a1, 0x10e8: 0x69c9, 0x10e9: 0x69f1,
+ 0x10ea: 0x6a21, 0x10eb: 0x6a51, 0x10ec: 0x6a81, 0x10ed: 0x6ab1, 0x10ee: 0x6ae1, 0x10ef: 0x6b11,
+ 0x10f0: 0x6b41, 0x10f1: 0x6b71, 0x10f2: 0x6ba1, 0x10f3: 0x6bd1, 0x10f4: 0x6c01, 0x10f5: 0x6c31,
+ 0x10f6: 0x6c61, 0x10f7: 0x6c91, 0x10f8: 0x6cc1, 0x10f9: 0x6cf1, 0x10fa: 0x6d21, 0x10fb: 0x6d51,
+ 0x10fc: 0x6d81, 0x10fd: 0x6db1, 0x10fe: 0x6de1, 0x10ff: 0x440d,
+ // Block 0x44, offset 0x1100
+ 0x1100: 0xe00d, 0x1101: 0x0008, 0x1102: 0xe00d, 0x1103: 0x0008, 0x1104: 0xe00d, 0x1105: 0x0008,
+ 0x1106: 0xe00d, 0x1107: 0x0008, 0x1108: 0xe00d, 0x1109: 0x0008, 0x110a: 0xe00d, 0x110b: 0x0008,
+ 0x110c: 0xe00d, 0x110d: 0x0008, 0x110e: 0xe00d, 0x110f: 0x0008, 0x1110: 0xe00d, 0x1111: 0x0008,
+ 0x1112: 0xe00d, 0x1113: 0x0008, 0x1114: 0xe00d, 0x1115: 0x0008, 0x1116: 0xe00d, 0x1117: 0x0008,
+ 0x1118: 0xe00d, 0x1119: 0x0008, 0x111a: 0xe00d, 0x111b: 0x0008, 0x111c: 0xe00d, 0x111d: 0x0008,
+ 0x111e: 0xe00d, 0x111f: 0x0008, 0x1120: 0xe00d, 0x1121: 0x0008, 0x1122: 0xe00d, 0x1123: 0x0008,
+ 0x1124: 0xe00d, 0x1125: 0x0008, 0x1126: 0xe00d, 0x1127: 0x0008, 0x1128: 0xe00d, 0x1129: 0x0008,
+ 0x112a: 0xe00d, 0x112b: 0x0008, 0x112c: 0xe00d, 0x112d: 0x0008, 0x112e: 0x0008, 0x112f: 0x3308,
+ 0x1130: 0x3318, 0x1131: 0x3318, 0x1132: 0x3318, 0x1133: 0x0018, 0x1134: 0x3308, 0x1135: 0x3308,
+ 0x1136: 0x3308, 0x1137: 0x3308, 0x1138: 0x3308, 0x1139: 0x3308, 0x113a: 0x3308, 0x113b: 0x3308,
+ 0x113c: 0x3308, 0x113d: 0x3308, 0x113e: 0x0018, 0x113f: 0x0008,
+ // Block 0x45, offset 0x1140
+ 0x1140: 0xe00d, 0x1141: 0x0008, 0x1142: 0xe00d, 0x1143: 0x0008, 0x1144: 0xe00d, 0x1145: 0x0008,
+ 0x1146: 0xe00d, 0x1147: 0x0008, 0x1148: 0xe00d, 0x1149: 0x0008, 0x114a: 0xe00d, 0x114b: 0x0008,
+ 0x114c: 0xe00d, 0x114d: 0x0008, 0x114e: 0xe00d, 0x114f: 0x0008, 0x1150: 0xe00d, 0x1151: 0x0008,
+ 0x1152: 0xe00d, 0x1153: 0x0008, 0x1154: 0xe00d, 0x1155: 0x0008, 0x1156: 0xe00d, 0x1157: 0x0008,
+ 0x1158: 0xe00d, 0x1159: 0x0008, 0x115a: 0xe00d, 0x115b: 0x0008, 0x115c: 0x0ea1, 0x115d: 0x6e11,
+ 0x115e: 0x3308, 0x115f: 0x3308, 0x1160: 0x0008, 0x1161: 0x0008, 0x1162: 0x0008, 0x1163: 0x0008,
+ 0x1164: 0x0008, 0x1165: 0x0008, 0x1166: 0x0008, 0x1167: 0x0008, 0x1168: 0x0008, 0x1169: 0x0008,
+ 0x116a: 0x0008, 0x116b: 0x0008, 0x116c: 0x0008, 0x116d: 0x0008, 0x116e: 0x0008, 0x116f: 0x0008,
+ 0x1170: 0x0008, 0x1171: 0x0008, 0x1172: 0x0008, 0x1173: 0x0008, 0x1174: 0x0008, 0x1175: 0x0008,
+ 0x1176: 0x0008, 0x1177: 0x0008, 0x1178: 0x0008, 0x1179: 0x0008, 0x117a: 0x0008, 0x117b: 0x0008,
+ 0x117c: 0x0008, 0x117d: 0x0008, 0x117e: 0x0008, 0x117f: 0x0008,
+ // Block 0x46, offset 0x1180
+ 0x1180: 0x0018, 0x1181: 0x0018, 0x1182: 0x0018, 0x1183: 0x0018, 0x1184: 0x0018, 0x1185: 0x0018,
+ 0x1186: 0x0018, 0x1187: 0x0018, 0x1188: 0x0018, 0x1189: 0x0018, 0x118a: 0x0018, 0x118b: 0x0018,
+ 0x118c: 0x0018, 0x118d: 0x0018, 0x118e: 0x0018, 0x118f: 0x0018, 0x1190: 0x0018, 0x1191: 0x0018,
+ 0x1192: 0x0018, 0x1193: 0x0018, 0x1194: 0x0018, 0x1195: 0x0018, 0x1196: 0x0018, 0x1197: 0x0008,
+ 0x1198: 0x0008, 0x1199: 0x0008, 0x119a: 0x0008, 0x119b: 0x0008, 0x119c: 0x0008, 0x119d: 0x0008,
+ 0x119e: 0x0008, 0x119f: 0x0008, 0x11a0: 0x0018, 0x11a1: 0x0018, 0x11a2: 0xe00d, 0x11a3: 0x0008,
+ 0x11a4: 0xe00d, 0x11a5: 0x0008, 0x11a6: 0xe00d, 0x11a7: 0x0008, 0x11a8: 0xe00d, 0x11a9: 0x0008,
+ 0x11aa: 0xe00d, 0x11ab: 0x0008, 0x11ac: 0xe00d, 0x11ad: 0x0008, 0x11ae: 0xe00d, 0x11af: 0x0008,
+ 0x11b0: 0x0008, 0x11b1: 0x0008, 0x11b2: 0xe00d, 0x11b3: 0x0008, 0x11b4: 0xe00d, 0x11b5: 0x0008,
+ 0x11b6: 0xe00d, 0x11b7: 0x0008, 0x11b8: 0xe00d, 0x11b9: 0x0008, 0x11ba: 0xe00d, 0x11bb: 0x0008,
+ 0x11bc: 0xe00d, 0x11bd: 0x0008, 0x11be: 0xe00d, 0x11bf: 0x0008,
+ // Block 0x47, offset 0x11c0
+ 0x11c0: 0xe00d, 0x11c1: 0x0008, 0x11c2: 0xe00d, 0x11c3: 0x0008, 0x11c4: 0xe00d, 0x11c5: 0x0008,
+ 0x11c6: 0xe00d, 0x11c7: 0x0008, 0x11c8: 0xe00d, 0x11c9: 0x0008, 0x11ca: 0xe00d, 0x11cb: 0x0008,
+ 0x11cc: 0xe00d, 0x11cd: 0x0008, 0x11ce: 0xe00d, 0x11cf: 0x0008, 0x11d0: 0xe00d, 0x11d1: 0x0008,
+ 0x11d2: 0xe00d, 0x11d3: 0x0008, 0x11d4: 0xe00d, 0x11d5: 0x0008, 0x11d6: 0xe00d, 0x11d7: 0x0008,
+ 0x11d8: 0xe00d, 0x11d9: 0x0008, 0x11da: 0xe00d, 0x11db: 0x0008, 0x11dc: 0xe00d, 0x11dd: 0x0008,
+ 0x11de: 0xe00d, 0x11df: 0x0008, 0x11e0: 0xe00d, 0x11e1: 0x0008, 0x11e2: 0xe00d, 0x11e3: 0x0008,
+ 0x11e4: 0xe00d, 0x11e5: 0x0008, 0x11e6: 0xe00d, 0x11e7: 0x0008, 0x11e8: 0xe00d, 0x11e9: 0x0008,
+ 0x11ea: 0xe00d, 0x11eb: 0x0008, 0x11ec: 0xe00d, 0x11ed: 0x0008, 0x11ee: 0xe00d, 0x11ef: 0x0008,
+ 0x11f0: 0xe0fd, 0x11f1: 0x0008, 0x11f2: 0x0008, 0x11f3: 0x0008, 0x11f4: 0x0008, 0x11f5: 0x0008,
+ 0x11f6: 0x0008, 0x11f7: 0x0008, 0x11f8: 0x0008, 0x11f9: 0xe01d, 0x11fa: 0x0008, 0x11fb: 0xe03d,
+ 0x11fc: 0x0008, 0x11fd: 0x442d, 0x11fe: 0xe00d, 0x11ff: 0x0008,
+ // Block 0x48, offset 0x1200
+ 0x1200: 0xe00d, 0x1201: 0x0008, 0x1202: 0xe00d, 0x1203: 0x0008, 0x1204: 0xe00d, 0x1205: 0x0008,
+ 0x1206: 0xe00d, 0x1207: 0x0008, 0x1208: 0x0008, 0x1209: 0x0018, 0x120a: 0x0018, 0x120b: 0xe03d,
+ 0x120c: 0x0008, 0x120d: 0x11d9, 0x120e: 0x0008, 0x120f: 0x0008, 0x1210: 0xe00d, 0x1211: 0x0008,
+ 0x1212: 0xe00d, 0x1213: 0x0008, 0x1214: 0x0008, 0x1215: 0x0008, 0x1216: 0xe00d, 0x1217: 0x0008,
+ 0x1218: 0xe00d, 0x1219: 0x0008, 0x121a: 0xe00d, 0x121b: 0x0008, 0x121c: 0xe00d, 0x121d: 0x0008,
+ 0x121e: 0xe00d, 0x121f: 0x0008, 0x1220: 0xe00d, 0x1221: 0x0008, 0x1222: 0xe00d, 0x1223: 0x0008,
+ 0x1224: 0xe00d, 0x1225: 0x0008, 0x1226: 0xe00d, 0x1227: 0x0008, 0x1228: 0xe00d, 0x1229: 0x0008,
+ 0x122a: 0x6e29, 0x122b: 0x1029, 0x122c: 0x11c1, 0x122d: 0x6e41, 0x122e: 0x1221, 0x122f: 0x0040,
+ 0x1230: 0x6e59, 0x1231: 0x6e71, 0x1232: 0x1239, 0x1233: 0x444d, 0x1234: 0xe00d, 0x1235: 0x0008,
+ 0x1236: 0xe00d, 0x1237: 0x0008, 0x1238: 0x0040, 0x1239: 0x0040, 0x123a: 0x0040, 0x123b: 0x0040,
+ 0x123c: 0x0040, 0x123d: 0x0040, 0x123e: 0x0040, 0x123f: 0x0040,
+ // Block 0x49, offset 0x1240
+ 0x1240: 0x64d5, 0x1241: 0x64f5, 0x1242: 0x6515, 0x1243: 0x6535, 0x1244: 0x6555, 0x1245: 0x6575,
+ 0x1246: 0x6595, 0x1247: 0x65b5, 0x1248: 0x65d5, 0x1249: 0x65f5, 0x124a: 0x6615, 0x124b: 0x6635,
+ 0x124c: 0x6655, 0x124d: 0x6675, 0x124e: 0x0008, 0x124f: 0x0008, 0x1250: 0x6695, 0x1251: 0x0008,
+ 0x1252: 0x66b5, 0x1253: 0x0008, 0x1254: 0x0008, 0x1255: 0x66d5, 0x1256: 0x66f5, 0x1257: 0x6715,
+ 0x1258: 0x6735, 0x1259: 0x6755, 0x125a: 0x6775, 0x125b: 0x6795, 0x125c: 0x67b5, 0x125d: 0x67d5,
+ 0x125e: 0x67f5, 0x125f: 0x0008, 0x1260: 0x6815, 0x1261: 0x0008, 0x1262: 0x6835, 0x1263: 0x0008,
+ 0x1264: 0x0008, 0x1265: 0x6855, 0x1266: 0x6875, 0x1267: 0x0008, 0x1268: 0x0008, 0x1269: 0x0008,
+ 0x126a: 0x6895, 0x126b: 0x68b5, 0x126c: 0x68d5, 0x126d: 0x68f5, 0x126e: 0x6915, 0x126f: 0x6935,
+ 0x1270: 0x6955, 0x1271: 0x6975, 0x1272: 0x6995, 0x1273: 0x69b5, 0x1274: 0x69d5, 0x1275: 0x69f5,
+ 0x1276: 0x6a15, 0x1277: 0x6a35, 0x1278: 0x6a55, 0x1279: 0x6a75, 0x127a: 0x6a95, 0x127b: 0x6ab5,
+ 0x127c: 0x6ad5, 0x127d: 0x6af5, 0x127e: 0x6b15, 0x127f: 0x6b35,
+ // Block 0x4a, offset 0x1280
+ 0x1280: 0x7a95, 0x1281: 0x7ab5, 0x1282: 0x7ad5, 0x1283: 0x7af5, 0x1284: 0x7b15, 0x1285: 0x7b35,
+ 0x1286: 0x7b55, 0x1287: 0x7b75, 0x1288: 0x7b95, 0x1289: 0x7bb5, 0x128a: 0x7bd5, 0x128b: 0x7bf5,
+ 0x128c: 0x7c15, 0x128d: 0x7c35, 0x128e: 0x7c55, 0x128f: 0x6ec9, 0x1290: 0x6ef1, 0x1291: 0x6f19,
+ 0x1292: 0x7c75, 0x1293: 0x7c95, 0x1294: 0x7cb5, 0x1295: 0x6f41, 0x1296: 0x6f69, 0x1297: 0x6f91,
+ 0x1298: 0x7cd5, 0x1299: 0x7cf5, 0x129a: 0x0040, 0x129b: 0x0040, 0x129c: 0x0040, 0x129d: 0x0040,
+ 0x129e: 0x0040, 0x129f: 0x0040, 0x12a0: 0x0040, 0x12a1: 0x0040, 0x12a2: 0x0040, 0x12a3: 0x0040,
+ 0x12a4: 0x0040, 0x12a5: 0x0040, 0x12a6: 0x0040, 0x12a7: 0x0040, 0x12a8: 0x0040, 0x12a9: 0x0040,
+ 0x12aa: 0x0040, 0x12ab: 0x0040, 0x12ac: 0x0040, 0x12ad: 0x0040, 0x12ae: 0x0040, 0x12af: 0x0040,
+ 0x12b0: 0x0040, 0x12b1: 0x0040, 0x12b2: 0x0040, 0x12b3: 0x0040, 0x12b4: 0x0040, 0x12b5: 0x0040,
+ 0x12b6: 0x0040, 0x12b7: 0x0040, 0x12b8: 0x0040, 0x12b9: 0x0040, 0x12ba: 0x0040, 0x12bb: 0x0040,
+ 0x12bc: 0x0040, 0x12bd: 0x0040, 0x12be: 0x0040, 0x12bf: 0x0040,
+ // Block 0x4b, offset 0x12c0
+ 0x12c0: 0x6fb9, 0x12c1: 0x6fd1, 0x12c2: 0x6fe9, 0x12c3: 0x7d15, 0x12c4: 0x7d35, 0x12c5: 0x7001,
+ 0x12c6: 0x7001, 0x12c7: 0x0040, 0x12c8: 0x0040, 0x12c9: 0x0040, 0x12ca: 0x0040, 0x12cb: 0x0040,
+ 0x12cc: 0x0040, 0x12cd: 0x0040, 0x12ce: 0x0040, 0x12cf: 0x0040, 0x12d0: 0x0040, 0x12d1: 0x0040,
+ 0x12d2: 0x0040, 0x12d3: 0x7019, 0x12d4: 0x7041, 0x12d5: 0x7069, 0x12d6: 0x7091, 0x12d7: 0x70b9,
+ 0x12d8: 0x0040, 0x12d9: 0x0040, 0x12da: 0x0040, 0x12db: 0x0040, 0x12dc: 0x0040, 0x12dd: 0x70e1,
+ 0x12de: 0x3308, 0x12df: 0x7109, 0x12e0: 0x7131, 0x12e1: 0x20a9, 0x12e2: 0x20f1, 0x12e3: 0x7149,
+ 0x12e4: 0x7161, 0x12e5: 0x7179, 0x12e6: 0x7191, 0x12e7: 0x71a9, 0x12e8: 0x71c1, 0x12e9: 0x1fb2,
+ 0x12ea: 0x71d9, 0x12eb: 0x7201, 0x12ec: 0x7229, 0x12ed: 0x7261, 0x12ee: 0x7299, 0x12ef: 0x72c1,
+ 0x12f0: 0x72e9, 0x12f1: 0x7311, 0x12f2: 0x7339, 0x12f3: 0x7361, 0x12f4: 0x7389, 0x12f5: 0x73b1,
+ 0x12f6: 0x73d9, 0x12f7: 0x0040, 0x12f8: 0x7401, 0x12f9: 0x7429, 0x12fa: 0x7451, 0x12fb: 0x7479,
+ 0x12fc: 0x74a1, 0x12fd: 0x0040, 0x12fe: 0x74c9, 0x12ff: 0x0040,
+ // Block 0x4c, offset 0x1300
+ 0x1300: 0x74f1, 0x1301: 0x7519, 0x1302: 0x0040, 0x1303: 0x7541, 0x1304: 0x7569, 0x1305: 0x0040,
+ 0x1306: 0x7591, 0x1307: 0x75b9, 0x1308: 0x75e1, 0x1309: 0x7609, 0x130a: 0x7631, 0x130b: 0x7659,
+ 0x130c: 0x7681, 0x130d: 0x76a9, 0x130e: 0x76d1, 0x130f: 0x76f9, 0x1310: 0x7721, 0x1311: 0x7721,
+ 0x1312: 0x7739, 0x1313: 0x7739, 0x1314: 0x7739, 0x1315: 0x7739, 0x1316: 0x7751, 0x1317: 0x7751,
+ 0x1318: 0x7751, 0x1319: 0x7751, 0x131a: 0x7769, 0x131b: 0x7769, 0x131c: 0x7769, 0x131d: 0x7769,
+ 0x131e: 0x7781, 0x131f: 0x7781, 0x1320: 0x7781, 0x1321: 0x7781, 0x1322: 0x7799, 0x1323: 0x7799,
+ 0x1324: 0x7799, 0x1325: 0x7799, 0x1326: 0x77b1, 0x1327: 0x77b1, 0x1328: 0x77b1, 0x1329: 0x77b1,
+ 0x132a: 0x77c9, 0x132b: 0x77c9, 0x132c: 0x77c9, 0x132d: 0x77c9, 0x132e: 0x77e1, 0x132f: 0x77e1,
+ 0x1330: 0x77e1, 0x1331: 0x77e1, 0x1332: 0x77f9, 0x1333: 0x77f9, 0x1334: 0x77f9, 0x1335: 0x77f9,
+ 0x1336: 0x7811, 0x1337: 0x7811, 0x1338: 0x7811, 0x1339: 0x7811, 0x133a: 0x7829, 0x133b: 0x7829,
+ 0x133c: 0x7829, 0x133d: 0x7829, 0x133e: 0x7841, 0x133f: 0x7841,
+ // Block 0x4d, offset 0x1340
+ 0x1340: 0x7841, 0x1341: 0x7841, 0x1342: 0x7859, 0x1343: 0x7859, 0x1344: 0x7871, 0x1345: 0x7871,
+ 0x1346: 0x7889, 0x1347: 0x7889, 0x1348: 0x78a1, 0x1349: 0x78a1, 0x134a: 0x78b9, 0x134b: 0x78b9,
+ 0x134c: 0x78d1, 0x134d: 0x78d1, 0x134e: 0x78e9, 0x134f: 0x78e9, 0x1350: 0x78e9, 0x1351: 0x78e9,
+ 0x1352: 0x7901, 0x1353: 0x7901, 0x1354: 0x7901, 0x1355: 0x7901, 0x1356: 0x7919, 0x1357: 0x7919,
+ 0x1358: 0x7919, 0x1359: 0x7919, 0x135a: 0x7931, 0x135b: 0x7931, 0x135c: 0x7931, 0x135d: 0x7931,
+ 0x135e: 0x7949, 0x135f: 0x7949, 0x1360: 0x7961, 0x1361: 0x7961, 0x1362: 0x7961, 0x1363: 0x7961,
+ 0x1364: 0x7979, 0x1365: 0x7979, 0x1366: 0x7991, 0x1367: 0x7991, 0x1368: 0x7991, 0x1369: 0x7991,
+ 0x136a: 0x79a9, 0x136b: 0x79a9, 0x136c: 0x79a9, 0x136d: 0x79a9, 0x136e: 0x79c1, 0x136f: 0x79c1,
+ 0x1370: 0x79d9, 0x1371: 0x79d9, 0x1372: 0x0818, 0x1373: 0x0818, 0x1374: 0x0818, 0x1375: 0x0818,
+ 0x1376: 0x0818, 0x1377: 0x0818, 0x1378: 0x0818, 0x1379: 0x0818, 0x137a: 0x0818, 0x137b: 0x0818,
+ 0x137c: 0x0818, 0x137d: 0x0818, 0x137e: 0x0818, 0x137f: 0x0818,
+ // Block 0x4e, offset 0x1380
+ 0x1380: 0x0818, 0x1381: 0x0818, 0x1382: 0x0040, 0x1383: 0x0040, 0x1384: 0x0040, 0x1385: 0x0040,
+ 0x1386: 0x0040, 0x1387: 0x0040, 0x1388: 0x0040, 0x1389: 0x0040, 0x138a: 0x0040, 0x138b: 0x0040,
+ 0x138c: 0x0040, 0x138d: 0x0040, 0x138e: 0x0040, 0x138f: 0x0040, 0x1390: 0x0040, 0x1391: 0x0040,
+ 0x1392: 0x0040, 0x1393: 0x79f1, 0x1394: 0x79f1, 0x1395: 0x79f1, 0x1396: 0x79f1, 0x1397: 0x7a09,
+ 0x1398: 0x7a09, 0x1399: 0x7a21, 0x139a: 0x7a21, 0x139b: 0x7a39, 0x139c: 0x7a39, 0x139d: 0x0479,
+ 0x139e: 0x7a51, 0x139f: 0x7a51, 0x13a0: 0x7a69, 0x13a1: 0x7a69, 0x13a2: 0x7a81, 0x13a3: 0x7a81,
+ 0x13a4: 0x7a99, 0x13a5: 0x7a99, 0x13a6: 0x7a99, 0x13a7: 0x7a99, 0x13a8: 0x7ab1, 0x13a9: 0x7ab1,
+ 0x13aa: 0x7ac9, 0x13ab: 0x7ac9, 0x13ac: 0x7af1, 0x13ad: 0x7af1, 0x13ae: 0x7b19, 0x13af: 0x7b19,
+ 0x13b0: 0x7b41, 0x13b1: 0x7b41, 0x13b2: 0x7b69, 0x13b3: 0x7b69, 0x13b4: 0x7b91, 0x13b5: 0x7b91,
+ 0x13b6: 0x7bb9, 0x13b7: 0x7bb9, 0x13b8: 0x7bb9, 0x13b9: 0x7be1, 0x13ba: 0x7be1, 0x13bb: 0x7be1,
+ 0x13bc: 0x7c09, 0x13bd: 0x7c09, 0x13be: 0x7c09, 0x13bf: 0x7c09,
+ // Block 0x4f, offset 0x13c0
+ 0x13c0: 0x85f9, 0x13c1: 0x8621, 0x13c2: 0x8649, 0x13c3: 0x8671, 0x13c4: 0x8699, 0x13c5: 0x86c1,
+ 0x13c6: 0x86e9, 0x13c7: 0x8711, 0x13c8: 0x8739, 0x13c9: 0x8761, 0x13ca: 0x8789, 0x13cb: 0x87b1,
+ 0x13cc: 0x87d9, 0x13cd: 0x8801, 0x13ce: 0x8829, 0x13cf: 0x8851, 0x13d0: 0x8879, 0x13d1: 0x88a1,
+ 0x13d2: 0x88c9, 0x13d3: 0x88f1, 0x13d4: 0x8919, 0x13d5: 0x8941, 0x13d6: 0x8969, 0x13d7: 0x8991,
+ 0x13d8: 0x89b9, 0x13d9: 0x89e1, 0x13da: 0x8a09, 0x13db: 0x8a31, 0x13dc: 0x8a59, 0x13dd: 0x8a81,
+ 0x13de: 0x8aaa, 0x13df: 0x8ada, 0x13e0: 0x8b0a, 0x13e1: 0x8b3a, 0x13e2: 0x8b6a, 0x13e3: 0x8b9a,
+ 0x13e4: 0x8bc9, 0x13e5: 0x8bf1, 0x13e6: 0x7c71, 0x13e7: 0x8c19, 0x13e8: 0x7be1, 0x13e9: 0x7c99,
+ 0x13ea: 0x8c41, 0x13eb: 0x8c69, 0x13ec: 0x7d39, 0x13ed: 0x8c91, 0x13ee: 0x7d61, 0x13ef: 0x7d89,
+ 0x13f0: 0x8cb9, 0x13f1: 0x8ce1, 0x13f2: 0x7e29, 0x13f3: 0x8d09, 0x13f4: 0x7e51, 0x13f5: 0x7e79,
+ 0x13f6: 0x8d31, 0x13f7: 0x8d59, 0x13f8: 0x7ec9, 0x13f9: 0x8d81, 0x13fa: 0x7ef1, 0x13fb: 0x7f19,
+ 0x13fc: 0x83a1, 0x13fd: 0x83c9, 0x13fe: 0x8441, 0x13ff: 0x8469,
+ // Block 0x50, offset 0x1400
+ 0x1400: 0x8491, 0x1401: 0x8531, 0x1402: 0x8559, 0x1403: 0x8581, 0x1404: 0x85a9, 0x1405: 0x8649,
+ 0x1406: 0x8671, 0x1407: 0x8699, 0x1408: 0x8da9, 0x1409: 0x8739, 0x140a: 0x8dd1, 0x140b: 0x8df9,
+ 0x140c: 0x8829, 0x140d: 0x8e21, 0x140e: 0x8851, 0x140f: 0x8879, 0x1410: 0x8a81, 0x1411: 0x8e49,
+ 0x1412: 0x8e71, 0x1413: 0x89b9, 0x1414: 0x8e99, 0x1415: 0x89e1, 0x1416: 0x8a09, 0x1417: 0x7c21,
+ 0x1418: 0x7c49, 0x1419: 0x8ec1, 0x141a: 0x7c71, 0x141b: 0x8ee9, 0x141c: 0x7cc1, 0x141d: 0x7ce9,
+ 0x141e: 0x7d11, 0x141f: 0x7d39, 0x1420: 0x8f11, 0x1421: 0x7db1, 0x1422: 0x7dd9, 0x1423: 0x7e01,
+ 0x1424: 0x7e29, 0x1425: 0x8f39, 0x1426: 0x7ec9, 0x1427: 0x7f41, 0x1428: 0x7f69, 0x1429: 0x7f91,
+ 0x142a: 0x7fb9, 0x142b: 0x7fe1, 0x142c: 0x8031, 0x142d: 0x8059, 0x142e: 0x8081, 0x142f: 0x80a9,
+ 0x1430: 0x80d1, 0x1431: 0x80f9, 0x1432: 0x8f61, 0x1433: 0x8121, 0x1434: 0x8149, 0x1435: 0x8171,
+ 0x1436: 0x8199, 0x1437: 0x81c1, 0x1438: 0x81e9, 0x1439: 0x8239, 0x143a: 0x8261, 0x143b: 0x8289,
+ 0x143c: 0x82b1, 0x143d: 0x82d9, 0x143e: 0x8301, 0x143f: 0x8329,
+ // Block 0x51, offset 0x1440
+ 0x1440: 0x8351, 0x1441: 0x8379, 0x1442: 0x83f1, 0x1443: 0x8419, 0x1444: 0x84b9, 0x1445: 0x84e1,
+ 0x1446: 0x8509, 0x1447: 0x8531, 0x1448: 0x8559, 0x1449: 0x85d1, 0x144a: 0x85f9, 0x144b: 0x8621,
+ 0x144c: 0x8649, 0x144d: 0x8f89, 0x144e: 0x86c1, 0x144f: 0x86e9, 0x1450: 0x8711, 0x1451: 0x8739,
+ 0x1452: 0x87b1, 0x1453: 0x87d9, 0x1454: 0x8801, 0x1455: 0x8829, 0x1456: 0x8fb1, 0x1457: 0x88a1,
+ 0x1458: 0x88c9, 0x1459: 0x8fd9, 0x145a: 0x8941, 0x145b: 0x8969, 0x145c: 0x8991, 0x145d: 0x89b9,
+ 0x145e: 0x9001, 0x145f: 0x7c71, 0x1460: 0x8ee9, 0x1461: 0x7d39, 0x1462: 0x8f11, 0x1463: 0x7e29,
+ 0x1464: 0x8f39, 0x1465: 0x7ec9, 0x1466: 0x9029, 0x1467: 0x80d1, 0x1468: 0x9051, 0x1469: 0x9079,
+ 0x146a: 0x90a1, 0x146b: 0x8531, 0x146c: 0x8559, 0x146d: 0x8649, 0x146e: 0x8829, 0x146f: 0x8fb1,
+ 0x1470: 0x89b9, 0x1471: 0x9001, 0x1472: 0x90c9, 0x1473: 0x9101, 0x1474: 0x9139, 0x1475: 0x9171,
+ 0x1476: 0x9199, 0x1477: 0x91c1, 0x1478: 0x91e9, 0x1479: 0x9211, 0x147a: 0x9239, 0x147b: 0x9261,
+ 0x147c: 0x9289, 0x147d: 0x92b1, 0x147e: 0x92d9, 0x147f: 0x9301,
+ // Block 0x52, offset 0x1480
+ 0x1480: 0x9329, 0x1481: 0x9351, 0x1482: 0x9379, 0x1483: 0x93a1, 0x1484: 0x93c9, 0x1485: 0x93f1,
+ 0x1486: 0x9419, 0x1487: 0x9441, 0x1488: 0x9469, 0x1489: 0x9491, 0x148a: 0x94b9, 0x148b: 0x94e1,
+ 0x148c: 0x9079, 0x148d: 0x9509, 0x148e: 0x9531, 0x148f: 0x9559, 0x1490: 0x9581, 0x1491: 0x9171,
+ 0x1492: 0x9199, 0x1493: 0x91c1, 0x1494: 0x91e9, 0x1495: 0x9211, 0x1496: 0x9239, 0x1497: 0x9261,
+ 0x1498: 0x9289, 0x1499: 0x92b1, 0x149a: 0x92d9, 0x149b: 0x9301, 0x149c: 0x9329, 0x149d: 0x9351,
+ 0x149e: 0x9379, 0x149f: 0x93a1, 0x14a0: 0x93c9, 0x14a1: 0x93f1, 0x14a2: 0x9419, 0x14a3: 0x9441,
+ 0x14a4: 0x9469, 0x14a5: 0x9491, 0x14a6: 0x94b9, 0x14a7: 0x94e1, 0x14a8: 0x9079, 0x14a9: 0x9509,
+ 0x14aa: 0x9531, 0x14ab: 0x9559, 0x14ac: 0x9581, 0x14ad: 0x9491, 0x14ae: 0x94b9, 0x14af: 0x94e1,
+ 0x14b0: 0x9079, 0x14b1: 0x9051, 0x14b2: 0x90a1, 0x14b3: 0x8211, 0x14b4: 0x8059, 0x14b5: 0x8081,
+ 0x14b6: 0x80a9, 0x14b7: 0x9491, 0x14b8: 0x94b9, 0x14b9: 0x94e1, 0x14ba: 0x8211, 0x14bb: 0x8239,
+ 0x14bc: 0x95a9, 0x14bd: 0x95a9, 0x14be: 0x0018, 0x14bf: 0x0018,
+ // Block 0x53, offset 0x14c0
+ 0x14c0: 0x0040, 0x14c1: 0x0040, 0x14c2: 0x0040, 0x14c3: 0x0040, 0x14c4: 0x0040, 0x14c5: 0x0040,
+ 0x14c6: 0x0040, 0x14c7: 0x0040, 0x14c8: 0x0040, 0x14c9: 0x0040, 0x14ca: 0x0040, 0x14cb: 0x0040,
+ 0x14cc: 0x0040, 0x14cd: 0x0040, 0x14ce: 0x0040, 0x14cf: 0x0040, 0x14d0: 0x95d1, 0x14d1: 0x9609,
+ 0x14d2: 0x9609, 0x14d3: 0x9641, 0x14d4: 0x9679, 0x14d5: 0x96b1, 0x14d6: 0x96e9, 0x14d7: 0x9721,
+ 0x14d8: 0x9759, 0x14d9: 0x9759, 0x14da: 0x9791, 0x14db: 0x97c9, 0x14dc: 0x9801, 0x14dd: 0x9839,
+ 0x14de: 0x9871, 0x14df: 0x98a9, 0x14e0: 0x98a9, 0x14e1: 0x98e1, 0x14e2: 0x9919, 0x14e3: 0x9919,
+ 0x14e4: 0x9951, 0x14e5: 0x9951, 0x14e6: 0x9989, 0x14e7: 0x99c1, 0x14e8: 0x99c1, 0x14e9: 0x99f9,
+ 0x14ea: 0x9a31, 0x14eb: 0x9a31, 0x14ec: 0x9a69, 0x14ed: 0x9a69, 0x14ee: 0x9aa1, 0x14ef: 0x9ad9,
+ 0x14f0: 0x9ad9, 0x14f1: 0x9b11, 0x14f2: 0x9b11, 0x14f3: 0x9b49, 0x14f4: 0x9b81, 0x14f5: 0x9bb9,
+ 0x14f6: 0x9bf1, 0x14f7: 0x9bf1, 0x14f8: 0x9c29, 0x14f9: 0x9c61, 0x14fa: 0x9c99, 0x14fb: 0x9cd1,
+ 0x14fc: 0x9d09, 0x14fd: 0x9d09, 0x14fe: 0x9d41, 0x14ff: 0x9d79,
+ // Block 0x54, offset 0x1500
+ 0x1500: 0xa949, 0x1501: 0xa981, 0x1502: 0xa9b9, 0x1503: 0xa8a1, 0x1504: 0x9bb9, 0x1505: 0x9989,
+ 0x1506: 0xa9f1, 0x1507: 0xaa29, 0x1508: 0x0040, 0x1509: 0x0040, 0x150a: 0x0040, 0x150b: 0x0040,
+ 0x150c: 0x0040, 0x150d: 0x0040, 0x150e: 0x0040, 0x150f: 0x0040, 0x1510: 0x0040, 0x1511: 0x0040,
+ 0x1512: 0x0040, 0x1513: 0x0040, 0x1514: 0x0040, 0x1515: 0x0040, 0x1516: 0x0040, 0x1517: 0x0040,
+ 0x1518: 0x0040, 0x1519: 0x0040, 0x151a: 0x0040, 0x151b: 0x0040, 0x151c: 0x0040, 0x151d: 0x0040,
+ 0x151e: 0x0040, 0x151f: 0x0040, 0x1520: 0x0040, 0x1521: 0x0040, 0x1522: 0x0040, 0x1523: 0x0040,
+ 0x1524: 0x0040, 0x1525: 0x0040, 0x1526: 0x0040, 0x1527: 0x0040, 0x1528: 0x0040, 0x1529: 0x0040,
+ 0x152a: 0x0040, 0x152b: 0x0040, 0x152c: 0x0040, 0x152d: 0x0040, 0x152e: 0x0040, 0x152f: 0x0040,
+ 0x1530: 0xaa61, 0x1531: 0xaa99, 0x1532: 0xaad1, 0x1533: 0xab19, 0x1534: 0xab61, 0x1535: 0xaba9,
+ 0x1536: 0xabf1, 0x1537: 0xac39, 0x1538: 0xac81, 0x1539: 0xacc9, 0x153a: 0xad02, 0x153b: 0xae12,
+ 0x153c: 0xae91, 0x153d: 0x0018, 0x153e: 0x0040, 0x153f: 0x0040,
+ // Block 0x55, offset 0x1540
+ 0x1540: 0x33c0, 0x1541: 0x33c0, 0x1542: 0x33c0, 0x1543: 0x33c0, 0x1544: 0x33c0, 0x1545: 0x33c0,
+ 0x1546: 0x33c0, 0x1547: 0x33c0, 0x1548: 0x33c0, 0x1549: 0x33c0, 0x154a: 0x33c0, 0x154b: 0x33c0,
+ 0x154c: 0x33c0, 0x154d: 0x33c0, 0x154e: 0x33c0, 0x154f: 0x33c0, 0x1550: 0xaeda, 0x1551: 0x7d55,
+ 0x1552: 0x0040, 0x1553: 0xaeea, 0x1554: 0x03c2, 0x1555: 0xaefa, 0x1556: 0xaf0a, 0x1557: 0x7d75,
+ 0x1558: 0x7d95, 0x1559: 0x0040, 0x155a: 0x0040, 0x155b: 0x0040, 0x155c: 0x0040, 0x155d: 0x0040,
+ 0x155e: 0x0040, 0x155f: 0x0040, 0x1560: 0x3308, 0x1561: 0x3308, 0x1562: 0x3308, 0x1563: 0x3308,
+ 0x1564: 0x3308, 0x1565: 0x3308, 0x1566: 0x3308, 0x1567: 0x3308, 0x1568: 0x3308, 0x1569: 0x3308,
+ 0x156a: 0x3308, 0x156b: 0x3308, 0x156c: 0x3308, 0x156d: 0x3308, 0x156e: 0x3308, 0x156f: 0x3308,
+ 0x1570: 0x0040, 0x1571: 0x7db5, 0x1572: 0x7dd5, 0x1573: 0xaf1a, 0x1574: 0xaf1a, 0x1575: 0x1fd2,
+ 0x1576: 0x1fe2, 0x1577: 0xaf2a, 0x1578: 0xaf3a, 0x1579: 0x7df5, 0x157a: 0x7e15, 0x157b: 0x7e35,
+ 0x157c: 0x7df5, 0x157d: 0x7e55, 0x157e: 0x7e75, 0x157f: 0x7e55,
+ // Block 0x56, offset 0x1580
+ 0x1580: 0x7e95, 0x1581: 0x7eb5, 0x1582: 0x7ed5, 0x1583: 0x7eb5, 0x1584: 0x7ef5, 0x1585: 0x0018,
+ 0x1586: 0x0018, 0x1587: 0xaf4a, 0x1588: 0xaf5a, 0x1589: 0x7f16, 0x158a: 0x7f36, 0x158b: 0x7f56,
+ 0x158c: 0x7f76, 0x158d: 0xaf1a, 0x158e: 0xaf1a, 0x158f: 0xaf1a, 0x1590: 0xaeda, 0x1591: 0x7f95,
+ 0x1592: 0x0040, 0x1593: 0x0040, 0x1594: 0x03c2, 0x1595: 0xaeea, 0x1596: 0xaf0a, 0x1597: 0xaefa,
+ 0x1598: 0x7fb5, 0x1599: 0x1fd2, 0x159a: 0x1fe2, 0x159b: 0xaf2a, 0x159c: 0xaf3a, 0x159d: 0x7e95,
+ 0x159e: 0x7ef5, 0x159f: 0xaf6a, 0x15a0: 0xaf7a, 0x15a1: 0xaf8a, 0x15a2: 0x1fb2, 0x15a3: 0xaf99,
+ 0x15a4: 0xafaa, 0x15a5: 0xafba, 0x15a6: 0x1fc2, 0x15a7: 0x0040, 0x15a8: 0xafca, 0x15a9: 0xafda,
+ 0x15aa: 0xafea, 0x15ab: 0xaffa, 0x15ac: 0x0040, 0x15ad: 0x0040, 0x15ae: 0x0040, 0x15af: 0x0040,
+ 0x15b0: 0x7fd6, 0x15b1: 0xb009, 0x15b2: 0x7ff6, 0x15b3: 0x0808, 0x15b4: 0x8016, 0x15b5: 0x0040,
+ 0x15b6: 0x8036, 0x15b7: 0xb031, 0x15b8: 0x8056, 0x15b9: 0xb059, 0x15ba: 0x8076, 0x15bb: 0xb081,
+ 0x15bc: 0x8096, 0x15bd: 0xb0a9, 0x15be: 0x80b6, 0x15bf: 0xb0d1,
+ // Block 0x57, offset 0x15c0
+ 0x15c0: 0xb0f9, 0x15c1: 0xb111, 0x15c2: 0xb111, 0x15c3: 0xb129, 0x15c4: 0xb129, 0x15c5: 0xb141,
+ 0x15c6: 0xb141, 0x15c7: 0xb159, 0x15c8: 0xb159, 0x15c9: 0xb171, 0x15ca: 0xb171, 0x15cb: 0xb171,
+ 0x15cc: 0xb171, 0x15cd: 0xb189, 0x15ce: 0xb189, 0x15cf: 0xb1a1, 0x15d0: 0xb1a1, 0x15d1: 0xb1a1,
+ 0x15d2: 0xb1a1, 0x15d3: 0xb1b9, 0x15d4: 0xb1b9, 0x15d5: 0xb1d1, 0x15d6: 0xb1d1, 0x15d7: 0xb1d1,
+ 0x15d8: 0xb1d1, 0x15d9: 0xb1e9, 0x15da: 0xb1e9, 0x15db: 0xb1e9, 0x15dc: 0xb1e9, 0x15dd: 0xb201,
+ 0x15de: 0xb201, 0x15df: 0xb201, 0x15e0: 0xb201, 0x15e1: 0xb219, 0x15e2: 0xb219, 0x15e3: 0xb219,
+ 0x15e4: 0xb219, 0x15e5: 0xb231, 0x15e6: 0xb231, 0x15e7: 0xb231, 0x15e8: 0xb231, 0x15e9: 0xb249,
+ 0x15ea: 0xb249, 0x15eb: 0xb261, 0x15ec: 0xb261, 0x15ed: 0xb279, 0x15ee: 0xb279, 0x15ef: 0xb291,
+ 0x15f0: 0xb291, 0x15f1: 0xb2a9, 0x15f2: 0xb2a9, 0x15f3: 0xb2a9, 0x15f4: 0xb2a9, 0x15f5: 0xb2c1,
+ 0x15f6: 0xb2c1, 0x15f7: 0xb2c1, 0x15f8: 0xb2c1, 0x15f9: 0xb2d9, 0x15fa: 0xb2d9, 0x15fb: 0xb2d9,
+ 0x15fc: 0xb2d9, 0x15fd: 0xb2f1, 0x15fe: 0xb2f1, 0x15ff: 0xb2f1,
+ // Block 0x58, offset 0x1600
+ 0x1600: 0xb2f1, 0x1601: 0xb309, 0x1602: 0xb309, 0x1603: 0xb309, 0x1604: 0xb309, 0x1605: 0xb321,
+ 0x1606: 0xb321, 0x1607: 0xb321, 0x1608: 0xb321, 0x1609: 0xb339, 0x160a: 0xb339, 0x160b: 0xb339,
+ 0x160c: 0xb339, 0x160d: 0xb351, 0x160e: 0xb351, 0x160f: 0xb351, 0x1610: 0xb351, 0x1611: 0xb369,
+ 0x1612: 0xb369, 0x1613: 0xb369, 0x1614: 0xb369, 0x1615: 0xb381, 0x1616: 0xb381, 0x1617: 0xb381,
+ 0x1618: 0xb381, 0x1619: 0xb399, 0x161a: 0xb399, 0x161b: 0xb399, 0x161c: 0xb399, 0x161d: 0xb3b1,
+ 0x161e: 0xb3b1, 0x161f: 0xb3b1, 0x1620: 0xb3b1, 0x1621: 0xb3c9, 0x1622: 0xb3c9, 0x1623: 0xb3c9,
+ 0x1624: 0xb3c9, 0x1625: 0xb3e1, 0x1626: 0xb3e1, 0x1627: 0xb3e1, 0x1628: 0xb3e1, 0x1629: 0xb3f9,
+ 0x162a: 0xb3f9, 0x162b: 0xb3f9, 0x162c: 0xb3f9, 0x162d: 0xb411, 0x162e: 0xb411, 0x162f: 0x7ab1,
+ 0x1630: 0x7ab1, 0x1631: 0xb429, 0x1632: 0xb429, 0x1633: 0xb429, 0x1634: 0xb429, 0x1635: 0xb441,
+ 0x1636: 0xb441, 0x1637: 0xb469, 0x1638: 0xb469, 0x1639: 0xb491, 0x163a: 0xb491, 0x163b: 0xb4b9,
+ 0x163c: 0xb4b9, 0x163d: 0x0040, 0x163e: 0x0040, 0x163f: 0x03c0,
+ // Block 0x59, offset 0x1640
+ 0x1640: 0x0040, 0x1641: 0xaefa, 0x1642: 0xb4e2, 0x1643: 0xaf6a, 0x1644: 0xafda, 0x1645: 0xafea,
+ 0x1646: 0xaf7a, 0x1647: 0xb4f2, 0x1648: 0x1fd2, 0x1649: 0x1fe2, 0x164a: 0xaf8a, 0x164b: 0x1fb2,
+ 0x164c: 0xaeda, 0x164d: 0xaf99, 0x164e: 0x29d1, 0x164f: 0xb502, 0x1650: 0x1f41, 0x1651: 0x00c9,
+ 0x1652: 0x0069, 0x1653: 0x0079, 0x1654: 0x1f51, 0x1655: 0x1f61, 0x1656: 0x1f71, 0x1657: 0x1f81,
+ 0x1658: 0x1f91, 0x1659: 0x1fa1, 0x165a: 0xaeea, 0x165b: 0x03c2, 0x165c: 0xafaa, 0x165d: 0x1fc2,
+ 0x165e: 0xafba, 0x165f: 0xaf0a, 0x1660: 0xaffa, 0x1661: 0x0039, 0x1662: 0x0ee9, 0x1663: 0x1159,
+ 0x1664: 0x0ef9, 0x1665: 0x0f09, 0x1666: 0x1199, 0x1667: 0x0f31, 0x1668: 0x0249, 0x1669: 0x0f41,
+ 0x166a: 0x0259, 0x166b: 0x0f51, 0x166c: 0x0359, 0x166d: 0x0f61, 0x166e: 0x0f71, 0x166f: 0x00d9,
+ 0x1670: 0x0f99, 0x1671: 0x2039, 0x1672: 0x0269, 0x1673: 0x01d9, 0x1674: 0x0fa9, 0x1675: 0x0fb9,
+ 0x1676: 0x1089, 0x1677: 0x0279, 0x1678: 0x0369, 0x1679: 0x0289, 0x167a: 0x13d1, 0x167b: 0xaf4a,
+ 0x167c: 0xafca, 0x167d: 0xaf5a, 0x167e: 0xb512, 0x167f: 0xaf1a,
+ // Block 0x5a, offset 0x1680
+ 0x1680: 0x1caa, 0x1681: 0x0039, 0x1682: 0x0ee9, 0x1683: 0x1159, 0x1684: 0x0ef9, 0x1685: 0x0f09,
+ 0x1686: 0x1199, 0x1687: 0x0f31, 0x1688: 0x0249, 0x1689: 0x0f41, 0x168a: 0x0259, 0x168b: 0x0f51,
+ 0x168c: 0x0359, 0x168d: 0x0f61, 0x168e: 0x0f71, 0x168f: 0x00d9, 0x1690: 0x0f99, 0x1691: 0x2039,
+ 0x1692: 0x0269, 0x1693: 0x01d9, 0x1694: 0x0fa9, 0x1695: 0x0fb9, 0x1696: 0x1089, 0x1697: 0x0279,
+ 0x1698: 0x0369, 0x1699: 0x0289, 0x169a: 0x13d1, 0x169b: 0xaf2a, 0x169c: 0xb522, 0x169d: 0xaf3a,
+ 0x169e: 0xb532, 0x169f: 0x80d5, 0x16a0: 0x80f5, 0x16a1: 0x29d1, 0x16a2: 0x8115, 0x16a3: 0x8115,
+ 0x16a4: 0x8135, 0x16a5: 0x8155, 0x16a6: 0x8175, 0x16a7: 0x8195, 0x16a8: 0x81b5, 0x16a9: 0x81d5,
+ 0x16aa: 0x81f5, 0x16ab: 0x8215, 0x16ac: 0x8235, 0x16ad: 0x8255, 0x16ae: 0x8275, 0x16af: 0x8295,
+ 0x16b0: 0x82b5, 0x16b1: 0x82d5, 0x16b2: 0x82f5, 0x16b3: 0x8315, 0x16b4: 0x8335, 0x16b5: 0x8355,
+ 0x16b6: 0x8375, 0x16b7: 0x8395, 0x16b8: 0x83b5, 0x16b9: 0x83d5, 0x16ba: 0x83f5, 0x16bb: 0x8415,
+ 0x16bc: 0x81b5, 0x16bd: 0x8435, 0x16be: 0x8455, 0x16bf: 0x8215,
+ // Block 0x5b, offset 0x16c0
+ 0x16c0: 0x8475, 0x16c1: 0x8495, 0x16c2: 0x84b5, 0x16c3: 0x84d5, 0x16c4: 0x84f5, 0x16c5: 0x8515,
+ 0x16c6: 0x8535, 0x16c7: 0x8555, 0x16c8: 0x84d5, 0x16c9: 0x8575, 0x16ca: 0x84d5, 0x16cb: 0x8595,
+ 0x16cc: 0x8595, 0x16cd: 0x85b5, 0x16ce: 0x85b5, 0x16cf: 0x85d5, 0x16d0: 0x8515, 0x16d1: 0x85f5,
+ 0x16d2: 0x8615, 0x16d3: 0x85f5, 0x16d4: 0x8635, 0x16d5: 0x8615, 0x16d6: 0x8655, 0x16d7: 0x8655,
+ 0x16d8: 0x8675, 0x16d9: 0x8675, 0x16da: 0x8695, 0x16db: 0x8695, 0x16dc: 0x8615, 0x16dd: 0x8115,
+ 0x16de: 0x86b5, 0x16df: 0x86d5, 0x16e0: 0x0040, 0x16e1: 0x86f5, 0x16e2: 0x8715, 0x16e3: 0x8735,
+ 0x16e4: 0x8755, 0x16e5: 0x8735, 0x16e6: 0x8775, 0x16e7: 0x8795, 0x16e8: 0x87b5, 0x16e9: 0x87b5,
+ 0x16ea: 0x87d5, 0x16eb: 0x87d5, 0x16ec: 0x87f5, 0x16ed: 0x87f5, 0x16ee: 0x87d5, 0x16ef: 0x87d5,
+ 0x16f0: 0x8815, 0x16f1: 0x8835, 0x16f2: 0x8855, 0x16f3: 0x8875, 0x16f4: 0x8895, 0x16f5: 0x88b5,
+ 0x16f6: 0x88b5, 0x16f7: 0x88b5, 0x16f8: 0x88d5, 0x16f9: 0x88d5, 0x16fa: 0x88d5, 0x16fb: 0x88d5,
+ 0x16fc: 0x87b5, 0x16fd: 0x87b5, 0x16fe: 0x87b5, 0x16ff: 0x0040,
+ // Block 0x5c, offset 0x1700
+ 0x1700: 0x0040, 0x1701: 0x0040, 0x1702: 0x8715, 0x1703: 0x86f5, 0x1704: 0x88f5, 0x1705: 0x86f5,
+ 0x1706: 0x8715, 0x1707: 0x86f5, 0x1708: 0x0040, 0x1709: 0x0040, 0x170a: 0x8915, 0x170b: 0x8715,
+ 0x170c: 0x8935, 0x170d: 0x88f5, 0x170e: 0x8935, 0x170f: 0x8715, 0x1710: 0x0040, 0x1711: 0x0040,
+ 0x1712: 0x8955, 0x1713: 0x8975, 0x1714: 0x8875, 0x1715: 0x8935, 0x1716: 0x88f5, 0x1717: 0x8935,
+ 0x1718: 0x0040, 0x1719: 0x0040, 0x171a: 0x8995, 0x171b: 0x89b5, 0x171c: 0x8995, 0x171d: 0x0040,
+ 0x171e: 0x0040, 0x171f: 0x0040, 0x1720: 0xb541, 0x1721: 0xb559, 0x1722: 0xb571, 0x1723: 0x89d6,
+ 0x1724: 0xb589, 0x1725: 0xb5a1, 0x1726: 0x89f5, 0x1727: 0x0040, 0x1728: 0x8a15, 0x1729: 0x8a35,
+ 0x172a: 0x8a55, 0x172b: 0x8a35, 0x172c: 0x8a75, 0x172d: 0x8a95, 0x172e: 0x8ab5, 0x172f: 0x0040,
+ 0x1730: 0x0040, 0x1731: 0x0040, 0x1732: 0x0040, 0x1733: 0x0040, 0x1734: 0x0040, 0x1735: 0x0040,
+ 0x1736: 0x0040, 0x1737: 0x0040, 0x1738: 0x0040, 0x1739: 0x0340, 0x173a: 0x0340, 0x173b: 0x0340,
+ 0x173c: 0x0040, 0x173d: 0x0040, 0x173e: 0x0040, 0x173f: 0x0040,
+ // Block 0x5d, offset 0x1740
+ 0x1740: 0x0a08, 0x1741: 0x0a08, 0x1742: 0x0a08, 0x1743: 0x0a08, 0x1744: 0x0a08, 0x1745: 0x0c08,
+ 0x1746: 0x0808, 0x1747: 0x0c08, 0x1748: 0x0818, 0x1749: 0x0c08, 0x174a: 0x0c08, 0x174b: 0x0808,
+ 0x174c: 0x0808, 0x174d: 0x0908, 0x174e: 0x0c08, 0x174f: 0x0c08, 0x1750: 0x0c08, 0x1751: 0x0c08,
+ 0x1752: 0x0c08, 0x1753: 0x0a08, 0x1754: 0x0a08, 0x1755: 0x0a08, 0x1756: 0x0a08, 0x1757: 0x0908,
+ 0x1758: 0x0a08, 0x1759: 0x0a08, 0x175a: 0x0a08, 0x175b: 0x0a08, 0x175c: 0x0a08, 0x175d: 0x0c08,
+ 0x175e: 0x0a08, 0x175f: 0x0a08, 0x1760: 0x0a08, 0x1761: 0x0c08, 0x1762: 0x0808, 0x1763: 0x0808,
+ 0x1764: 0x0c08, 0x1765: 0x3308, 0x1766: 0x3308, 0x1767: 0x0040, 0x1768: 0x0040, 0x1769: 0x0040,
+ 0x176a: 0x0040, 0x176b: 0x0a18, 0x176c: 0x0a18, 0x176d: 0x0a18, 0x176e: 0x0a18, 0x176f: 0x0c18,
+ 0x1770: 0x0818, 0x1771: 0x0818, 0x1772: 0x0818, 0x1773: 0x0818, 0x1774: 0x0818, 0x1775: 0x0818,
+ 0x1776: 0x0818, 0x1777: 0x0040, 0x1778: 0x0040, 0x1779: 0x0040, 0x177a: 0x0040, 0x177b: 0x0040,
+ 0x177c: 0x0040, 0x177d: 0x0040, 0x177e: 0x0040, 0x177f: 0x0040,
+ // Block 0x5e, offset 0x1780
+ 0x1780: 0x0a08, 0x1781: 0x0c08, 0x1782: 0x0a08, 0x1783: 0x0c08, 0x1784: 0x0c08, 0x1785: 0x0c08,
+ 0x1786: 0x0a08, 0x1787: 0x0a08, 0x1788: 0x0a08, 0x1789: 0x0c08, 0x178a: 0x0a08, 0x178b: 0x0a08,
+ 0x178c: 0x0c08, 0x178d: 0x0a08, 0x178e: 0x0c08, 0x178f: 0x0c08, 0x1790: 0x0a08, 0x1791: 0x0c08,
+ 0x1792: 0x0040, 0x1793: 0x0040, 0x1794: 0x0040, 0x1795: 0x0040, 0x1796: 0x0040, 0x1797: 0x0040,
+ 0x1798: 0x0040, 0x1799: 0x0818, 0x179a: 0x0818, 0x179b: 0x0818, 0x179c: 0x0818, 0x179d: 0x0040,
+ 0x179e: 0x0040, 0x179f: 0x0040, 0x17a0: 0x0040, 0x17a1: 0x0040, 0x17a2: 0x0040, 0x17a3: 0x0040,
+ 0x17a4: 0x0040, 0x17a5: 0x0040, 0x17a6: 0x0040, 0x17a7: 0x0040, 0x17a8: 0x0040, 0x17a9: 0x0c18,
+ 0x17aa: 0x0c18, 0x17ab: 0x0c18, 0x17ac: 0x0c18, 0x17ad: 0x0a18, 0x17ae: 0x0a18, 0x17af: 0x0818,
+ 0x17b0: 0x0040, 0x17b1: 0x0040, 0x17b2: 0x0040, 0x17b3: 0x0040, 0x17b4: 0x0040, 0x17b5: 0x0040,
+ 0x17b6: 0x0040, 0x17b7: 0x0040, 0x17b8: 0x0040, 0x17b9: 0x0040, 0x17ba: 0x0040, 0x17bb: 0x0040,
+ 0x17bc: 0x0040, 0x17bd: 0x0040, 0x17be: 0x0040, 0x17bf: 0x0040,
+ // Block 0x5f, offset 0x17c0
+ 0x17c0: 0x3308, 0x17c1: 0x3308, 0x17c2: 0x3008, 0x17c3: 0x3008, 0x17c4: 0x0040, 0x17c5: 0x0008,
+ 0x17c6: 0x0008, 0x17c7: 0x0008, 0x17c8: 0x0008, 0x17c9: 0x0008, 0x17ca: 0x0008, 0x17cb: 0x0008,
+ 0x17cc: 0x0008, 0x17cd: 0x0040, 0x17ce: 0x0040, 0x17cf: 0x0008, 0x17d0: 0x0008, 0x17d1: 0x0040,
+ 0x17d2: 0x0040, 0x17d3: 0x0008, 0x17d4: 0x0008, 0x17d5: 0x0008, 0x17d6: 0x0008, 0x17d7: 0x0008,
+ 0x17d8: 0x0008, 0x17d9: 0x0008, 0x17da: 0x0008, 0x17db: 0x0008, 0x17dc: 0x0008, 0x17dd: 0x0008,
+ 0x17de: 0x0008, 0x17df: 0x0008, 0x17e0: 0x0008, 0x17e1: 0x0008, 0x17e2: 0x0008, 0x17e3: 0x0008,
+ 0x17e4: 0x0008, 0x17e5: 0x0008, 0x17e6: 0x0008, 0x17e7: 0x0008, 0x17e8: 0x0008, 0x17e9: 0x0040,
+ 0x17ea: 0x0008, 0x17eb: 0x0008, 0x17ec: 0x0008, 0x17ed: 0x0008, 0x17ee: 0x0008, 0x17ef: 0x0008,
+ 0x17f0: 0x0008, 0x17f1: 0x0040, 0x17f2: 0x0008, 0x17f3: 0x0008, 0x17f4: 0x0040, 0x17f5: 0x0008,
+ 0x17f6: 0x0008, 0x17f7: 0x0008, 0x17f8: 0x0008, 0x17f9: 0x0008, 0x17fa: 0x0040, 0x17fb: 0x0040,
+ 0x17fc: 0x3308, 0x17fd: 0x0008, 0x17fe: 0x3008, 0x17ff: 0x3008,
+ // Block 0x60, offset 0x1800
+ 0x1800: 0x3308, 0x1801: 0x3008, 0x1802: 0x3008, 0x1803: 0x3008, 0x1804: 0x3008, 0x1805: 0x0040,
+ 0x1806: 0x0040, 0x1807: 0x3008, 0x1808: 0x3008, 0x1809: 0x0040, 0x180a: 0x0040, 0x180b: 0x3008,
+ 0x180c: 0x3008, 0x180d: 0x3808, 0x180e: 0x0040, 0x180f: 0x0040, 0x1810: 0x0008, 0x1811: 0x0040,
+ 0x1812: 0x0040, 0x1813: 0x0040, 0x1814: 0x0040, 0x1815: 0x0040, 0x1816: 0x0040, 0x1817: 0x3008,
+ 0x1818: 0x0040, 0x1819: 0x0040, 0x181a: 0x0040, 0x181b: 0x0040, 0x181c: 0x0040, 0x181d: 0x0008,
+ 0x181e: 0x0008, 0x181f: 0x0008, 0x1820: 0x0008, 0x1821: 0x0008, 0x1822: 0x3008, 0x1823: 0x3008,
+ 0x1824: 0x0040, 0x1825: 0x0040, 0x1826: 0x3308, 0x1827: 0x3308, 0x1828: 0x3308, 0x1829: 0x3308,
+ 0x182a: 0x3308, 0x182b: 0x3308, 0x182c: 0x3308, 0x182d: 0x0040, 0x182e: 0x0040, 0x182f: 0x0040,
+ 0x1830: 0x3308, 0x1831: 0x3308, 0x1832: 0x3308, 0x1833: 0x3308, 0x1834: 0x3308, 0x1835: 0x0040,
+ 0x1836: 0x0040, 0x1837: 0x0040, 0x1838: 0x0040, 0x1839: 0x0040, 0x183a: 0x0040, 0x183b: 0x0040,
+ 0x183c: 0x0040, 0x183d: 0x0040, 0x183e: 0x0040, 0x183f: 0x0040,
+ // Block 0x61, offset 0x1840
+ 0x1840: 0x0039, 0x1841: 0x0ee9, 0x1842: 0x1159, 0x1843: 0x0ef9, 0x1844: 0x0f09, 0x1845: 0x1199,
+ 0x1846: 0x0f31, 0x1847: 0x0249, 0x1848: 0x0f41, 0x1849: 0x0259, 0x184a: 0x0f51, 0x184b: 0x0359,
+ 0x184c: 0x0f61, 0x184d: 0x0f71, 0x184e: 0x00d9, 0x184f: 0x0f99, 0x1850: 0x2039, 0x1851: 0x0269,
+ 0x1852: 0x01d9, 0x1853: 0x0fa9, 0x1854: 0x0fb9, 0x1855: 0x1089, 0x1856: 0x0279, 0x1857: 0x0369,
+ 0x1858: 0x0289, 0x1859: 0x13d1, 0x185a: 0x0039, 0x185b: 0x0ee9, 0x185c: 0x1159, 0x185d: 0x0ef9,
+ 0x185e: 0x0f09, 0x185f: 0x1199, 0x1860: 0x0f31, 0x1861: 0x0249, 0x1862: 0x0f41, 0x1863: 0x0259,
+ 0x1864: 0x0f51, 0x1865: 0x0359, 0x1866: 0x0f61, 0x1867: 0x0f71, 0x1868: 0x00d9, 0x1869: 0x0f99,
+ 0x186a: 0x2039, 0x186b: 0x0269, 0x186c: 0x01d9, 0x186d: 0x0fa9, 0x186e: 0x0fb9, 0x186f: 0x1089,
+ 0x1870: 0x0279, 0x1871: 0x0369, 0x1872: 0x0289, 0x1873: 0x13d1, 0x1874: 0x0039, 0x1875: 0x0ee9,
+ 0x1876: 0x1159, 0x1877: 0x0ef9, 0x1878: 0x0f09, 0x1879: 0x1199, 0x187a: 0x0f31, 0x187b: 0x0249,
+ 0x187c: 0x0f41, 0x187d: 0x0259, 0x187e: 0x0f51, 0x187f: 0x0359,
+ // Block 0x62, offset 0x1880
+ 0x1880: 0x0f61, 0x1881: 0x0f71, 0x1882: 0x00d9, 0x1883: 0x0f99, 0x1884: 0x2039, 0x1885: 0x0269,
+ 0x1886: 0x01d9, 0x1887: 0x0fa9, 0x1888: 0x0fb9, 0x1889: 0x1089, 0x188a: 0x0279, 0x188b: 0x0369,
+ 0x188c: 0x0289, 0x188d: 0x13d1, 0x188e: 0x0039, 0x188f: 0x0ee9, 0x1890: 0x1159, 0x1891: 0x0ef9,
+ 0x1892: 0x0f09, 0x1893: 0x1199, 0x1894: 0x0f31, 0x1895: 0x0040, 0x1896: 0x0f41, 0x1897: 0x0259,
+ 0x1898: 0x0f51, 0x1899: 0x0359, 0x189a: 0x0f61, 0x189b: 0x0f71, 0x189c: 0x00d9, 0x189d: 0x0f99,
+ 0x189e: 0x2039, 0x189f: 0x0269, 0x18a0: 0x01d9, 0x18a1: 0x0fa9, 0x18a2: 0x0fb9, 0x18a3: 0x1089,
+ 0x18a4: 0x0279, 0x18a5: 0x0369, 0x18a6: 0x0289, 0x18a7: 0x13d1, 0x18a8: 0x0039, 0x18a9: 0x0ee9,
+ 0x18aa: 0x1159, 0x18ab: 0x0ef9, 0x18ac: 0x0f09, 0x18ad: 0x1199, 0x18ae: 0x0f31, 0x18af: 0x0249,
+ 0x18b0: 0x0f41, 0x18b1: 0x0259, 0x18b2: 0x0f51, 0x18b3: 0x0359, 0x18b4: 0x0f61, 0x18b5: 0x0f71,
+ 0x18b6: 0x00d9, 0x18b7: 0x0f99, 0x18b8: 0x2039, 0x18b9: 0x0269, 0x18ba: 0x01d9, 0x18bb: 0x0fa9,
+ 0x18bc: 0x0fb9, 0x18bd: 0x1089, 0x18be: 0x0279, 0x18bf: 0x0369,
+ // Block 0x63, offset 0x18c0
+ 0x18c0: 0x0289, 0x18c1: 0x13d1, 0x18c2: 0x0039, 0x18c3: 0x0ee9, 0x18c4: 0x1159, 0x18c5: 0x0ef9,
+ 0x18c6: 0x0f09, 0x18c7: 0x1199, 0x18c8: 0x0f31, 0x18c9: 0x0249, 0x18ca: 0x0f41, 0x18cb: 0x0259,
+ 0x18cc: 0x0f51, 0x18cd: 0x0359, 0x18ce: 0x0f61, 0x18cf: 0x0f71, 0x18d0: 0x00d9, 0x18d1: 0x0f99,
+ 0x18d2: 0x2039, 0x18d3: 0x0269, 0x18d4: 0x01d9, 0x18d5: 0x0fa9, 0x18d6: 0x0fb9, 0x18d7: 0x1089,
+ 0x18d8: 0x0279, 0x18d9: 0x0369, 0x18da: 0x0289, 0x18db: 0x13d1, 0x18dc: 0x0039, 0x18dd: 0x0040,
+ 0x18de: 0x1159, 0x18df: 0x0ef9, 0x18e0: 0x0040, 0x18e1: 0x0040, 0x18e2: 0x0f31, 0x18e3: 0x0040,
+ 0x18e4: 0x0040, 0x18e5: 0x0259, 0x18e6: 0x0f51, 0x18e7: 0x0040, 0x18e8: 0x0040, 0x18e9: 0x0f71,
+ 0x18ea: 0x00d9, 0x18eb: 0x0f99, 0x18ec: 0x2039, 0x18ed: 0x0040, 0x18ee: 0x01d9, 0x18ef: 0x0fa9,
+ 0x18f0: 0x0fb9, 0x18f1: 0x1089, 0x18f2: 0x0279, 0x18f3: 0x0369, 0x18f4: 0x0289, 0x18f5: 0x13d1,
+ 0x18f6: 0x0039, 0x18f7: 0x0ee9, 0x18f8: 0x1159, 0x18f9: 0x0ef9, 0x18fa: 0x0040, 0x18fb: 0x1199,
+ 0x18fc: 0x0040, 0x18fd: 0x0249, 0x18fe: 0x0f41, 0x18ff: 0x0259,
+ // Block 0x64, offset 0x1900
+ 0x1900: 0x0f51, 0x1901: 0x0359, 0x1902: 0x0f61, 0x1903: 0x0f71, 0x1904: 0x0040, 0x1905: 0x0f99,
+ 0x1906: 0x2039, 0x1907: 0x0269, 0x1908: 0x01d9, 0x1909: 0x0fa9, 0x190a: 0x0fb9, 0x190b: 0x1089,
+ 0x190c: 0x0279, 0x190d: 0x0369, 0x190e: 0x0289, 0x190f: 0x13d1, 0x1910: 0x0039, 0x1911: 0x0ee9,
+ 0x1912: 0x1159, 0x1913: 0x0ef9, 0x1914: 0x0f09, 0x1915: 0x1199, 0x1916: 0x0f31, 0x1917: 0x0249,
+ 0x1918: 0x0f41, 0x1919: 0x0259, 0x191a: 0x0f51, 0x191b: 0x0359, 0x191c: 0x0f61, 0x191d: 0x0f71,
+ 0x191e: 0x00d9, 0x191f: 0x0f99, 0x1920: 0x2039, 0x1921: 0x0269, 0x1922: 0x01d9, 0x1923: 0x0fa9,
+ 0x1924: 0x0fb9, 0x1925: 0x1089, 0x1926: 0x0279, 0x1927: 0x0369, 0x1928: 0x0289, 0x1929: 0x13d1,
+ 0x192a: 0x0039, 0x192b: 0x0ee9, 0x192c: 0x1159, 0x192d: 0x0ef9, 0x192e: 0x0f09, 0x192f: 0x1199,
+ 0x1930: 0x0f31, 0x1931: 0x0249, 0x1932: 0x0f41, 0x1933: 0x0259, 0x1934: 0x0f51, 0x1935: 0x0359,
+ 0x1936: 0x0f61, 0x1937: 0x0f71, 0x1938: 0x00d9, 0x1939: 0x0f99, 0x193a: 0x2039, 0x193b: 0x0269,
+ 0x193c: 0x01d9, 0x193d: 0x0fa9, 0x193e: 0x0fb9, 0x193f: 0x1089,
+ // Block 0x65, offset 0x1940
+ 0x1940: 0x0279, 0x1941: 0x0369, 0x1942: 0x0289, 0x1943: 0x13d1, 0x1944: 0x0039, 0x1945: 0x0ee9,
+ 0x1946: 0x0040, 0x1947: 0x0ef9, 0x1948: 0x0f09, 0x1949: 0x1199, 0x194a: 0x0f31, 0x194b: 0x0040,
+ 0x194c: 0x0040, 0x194d: 0x0259, 0x194e: 0x0f51, 0x194f: 0x0359, 0x1950: 0x0f61, 0x1951: 0x0f71,
+ 0x1952: 0x00d9, 0x1953: 0x0f99, 0x1954: 0x2039, 0x1955: 0x0040, 0x1956: 0x01d9, 0x1957: 0x0fa9,
+ 0x1958: 0x0fb9, 0x1959: 0x1089, 0x195a: 0x0279, 0x195b: 0x0369, 0x195c: 0x0289, 0x195d: 0x0040,
+ 0x195e: 0x0039, 0x195f: 0x0ee9, 0x1960: 0x1159, 0x1961: 0x0ef9, 0x1962: 0x0f09, 0x1963: 0x1199,
+ 0x1964: 0x0f31, 0x1965: 0x0249, 0x1966: 0x0f41, 0x1967: 0x0259, 0x1968: 0x0f51, 0x1969: 0x0359,
+ 0x196a: 0x0f61, 0x196b: 0x0f71, 0x196c: 0x00d9, 0x196d: 0x0f99, 0x196e: 0x2039, 0x196f: 0x0269,
+ 0x1970: 0x01d9, 0x1971: 0x0fa9, 0x1972: 0x0fb9, 0x1973: 0x1089, 0x1974: 0x0279, 0x1975: 0x0369,
+ 0x1976: 0x0289, 0x1977: 0x13d1, 0x1978: 0x0039, 0x1979: 0x0ee9, 0x197a: 0x0040, 0x197b: 0x0ef9,
+ 0x197c: 0x0f09, 0x197d: 0x1199, 0x197e: 0x0f31, 0x197f: 0x0040,
+ // Block 0x66, offset 0x1980
+ 0x1980: 0x0f41, 0x1981: 0x0259, 0x1982: 0x0f51, 0x1983: 0x0359, 0x1984: 0x0f61, 0x1985: 0x0040,
+ 0x1986: 0x00d9, 0x1987: 0x0040, 0x1988: 0x0040, 0x1989: 0x0040, 0x198a: 0x01d9, 0x198b: 0x0fa9,
+ 0x198c: 0x0fb9, 0x198d: 0x1089, 0x198e: 0x0279, 0x198f: 0x0369, 0x1990: 0x0289, 0x1991: 0x0040,
+ 0x1992: 0x0039, 0x1993: 0x0ee9, 0x1994: 0x1159, 0x1995: 0x0ef9, 0x1996: 0x0f09, 0x1997: 0x1199,
+ 0x1998: 0x0f31, 0x1999: 0x0249, 0x199a: 0x0f41, 0x199b: 0x0259, 0x199c: 0x0f51, 0x199d: 0x0359,
+ 0x199e: 0x0f61, 0x199f: 0x0f71, 0x19a0: 0x00d9, 0x19a1: 0x0f99, 0x19a2: 0x2039, 0x19a3: 0x0269,
+ 0x19a4: 0x01d9, 0x19a5: 0x0fa9, 0x19a6: 0x0fb9, 0x19a7: 0x1089, 0x19a8: 0x0279, 0x19a9: 0x0369,
+ 0x19aa: 0x0289, 0x19ab: 0x13d1, 0x19ac: 0x0039, 0x19ad: 0x0ee9, 0x19ae: 0x1159, 0x19af: 0x0ef9,
+ 0x19b0: 0x0f09, 0x19b1: 0x1199, 0x19b2: 0x0f31, 0x19b3: 0x0249, 0x19b4: 0x0f41, 0x19b5: 0x0259,
+ 0x19b6: 0x0f51, 0x19b7: 0x0359, 0x19b8: 0x0f61, 0x19b9: 0x0f71, 0x19ba: 0x00d9, 0x19bb: 0x0f99,
+ 0x19bc: 0x2039, 0x19bd: 0x0269, 0x19be: 0x01d9, 0x19bf: 0x0fa9,
+ // Block 0x67, offset 0x19c0
+ 0x19c0: 0x0fb9, 0x19c1: 0x1089, 0x19c2: 0x0279, 0x19c3: 0x0369, 0x19c4: 0x0289, 0x19c5: 0x13d1,
+ 0x19c6: 0x0039, 0x19c7: 0x0ee9, 0x19c8: 0x1159, 0x19c9: 0x0ef9, 0x19ca: 0x0f09, 0x19cb: 0x1199,
+ 0x19cc: 0x0f31, 0x19cd: 0x0249, 0x19ce: 0x0f41, 0x19cf: 0x0259, 0x19d0: 0x0f51, 0x19d1: 0x0359,
+ 0x19d2: 0x0f61, 0x19d3: 0x0f71, 0x19d4: 0x00d9, 0x19d5: 0x0f99, 0x19d6: 0x2039, 0x19d7: 0x0269,
+ 0x19d8: 0x01d9, 0x19d9: 0x0fa9, 0x19da: 0x0fb9, 0x19db: 0x1089, 0x19dc: 0x0279, 0x19dd: 0x0369,
+ 0x19de: 0x0289, 0x19df: 0x13d1, 0x19e0: 0x0039, 0x19e1: 0x0ee9, 0x19e2: 0x1159, 0x19e3: 0x0ef9,
+ 0x19e4: 0x0f09, 0x19e5: 0x1199, 0x19e6: 0x0f31, 0x19e7: 0x0249, 0x19e8: 0x0f41, 0x19e9: 0x0259,
+ 0x19ea: 0x0f51, 0x19eb: 0x0359, 0x19ec: 0x0f61, 0x19ed: 0x0f71, 0x19ee: 0x00d9, 0x19ef: 0x0f99,
+ 0x19f0: 0x2039, 0x19f1: 0x0269, 0x19f2: 0x01d9, 0x19f3: 0x0fa9, 0x19f4: 0x0fb9, 0x19f5: 0x1089,
+ 0x19f6: 0x0279, 0x19f7: 0x0369, 0x19f8: 0x0289, 0x19f9: 0x13d1, 0x19fa: 0x0039, 0x19fb: 0x0ee9,
+ 0x19fc: 0x1159, 0x19fd: 0x0ef9, 0x19fe: 0x0f09, 0x19ff: 0x1199,
+ // Block 0x68, offset 0x1a00
+ 0x1a00: 0x0f31, 0x1a01: 0x0249, 0x1a02: 0x0f41, 0x1a03: 0x0259, 0x1a04: 0x0f51, 0x1a05: 0x0359,
+ 0x1a06: 0x0f61, 0x1a07: 0x0f71, 0x1a08: 0x00d9, 0x1a09: 0x0f99, 0x1a0a: 0x2039, 0x1a0b: 0x0269,
+ 0x1a0c: 0x01d9, 0x1a0d: 0x0fa9, 0x1a0e: 0x0fb9, 0x1a0f: 0x1089, 0x1a10: 0x0279, 0x1a11: 0x0369,
+ 0x1a12: 0x0289, 0x1a13: 0x13d1, 0x1a14: 0x0039, 0x1a15: 0x0ee9, 0x1a16: 0x1159, 0x1a17: 0x0ef9,
+ 0x1a18: 0x0f09, 0x1a19: 0x1199, 0x1a1a: 0x0f31, 0x1a1b: 0x0249, 0x1a1c: 0x0f41, 0x1a1d: 0x0259,
+ 0x1a1e: 0x0f51, 0x1a1f: 0x0359, 0x1a20: 0x0f61, 0x1a21: 0x0f71, 0x1a22: 0x00d9, 0x1a23: 0x0f99,
+ 0x1a24: 0x2039, 0x1a25: 0x0269, 0x1a26: 0x01d9, 0x1a27: 0x0fa9, 0x1a28: 0x0fb9, 0x1a29: 0x1089,
+ 0x1a2a: 0x0279, 0x1a2b: 0x0369, 0x1a2c: 0x0289, 0x1a2d: 0x13d1, 0x1a2e: 0x0039, 0x1a2f: 0x0ee9,
+ 0x1a30: 0x1159, 0x1a31: 0x0ef9, 0x1a32: 0x0f09, 0x1a33: 0x1199, 0x1a34: 0x0f31, 0x1a35: 0x0249,
+ 0x1a36: 0x0f41, 0x1a37: 0x0259, 0x1a38: 0x0f51, 0x1a39: 0x0359, 0x1a3a: 0x0f61, 0x1a3b: 0x0f71,
+ 0x1a3c: 0x00d9, 0x1a3d: 0x0f99, 0x1a3e: 0x2039, 0x1a3f: 0x0269,
+ // Block 0x69, offset 0x1a40
+ 0x1a40: 0x01d9, 0x1a41: 0x0fa9, 0x1a42: 0x0fb9, 0x1a43: 0x1089, 0x1a44: 0x0279, 0x1a45: 0x0369,
+ 0x1a46: 0x0289, 0x1a47: 0x13d1, 0x1a48: 0x0039, 0x1a49: 0x0ee9, 0x1a4a: 0x1159, 0x1a4b: 0x0ef9,
+ 0x1a4c: 0x0f09, 0x1a4d: 0x1199, 0x1a4e: 0x0f31, 0x1a4f: 0x0249, 0x1a50: 0x0f41, 0x1a51: 0x0259,
+ 0x1a52: 0x0f51, 0x1a53: 0x0359, 0x1a54: 0x0f61, 0x1a55: 0x0f71, 0x1a56: 0x00d9, 0x1a57: 0x0f99,
+ 0x1a58: 0x2039, 0x1a59: 0x0269, 0x1a5a: 0x01d9, 0x1a5b: 0x0fa9, 0x1a5c: 0x0fb9, 0x1a5d: 0x1089,
+ 0x1a5e: 0x0279, 0x1a5f: 0x0369, 0x1a60: 0x0289, 0x1a61: 0x13d1, 0x1a62: 0x0039, 0x1a63: 0x0ee9,
+ 0x1a64: 0x1159, 0x1a65: 0x0ef9, 0x1a66: 0x0f09, 0x1a67: 0x1199, 0x1a68: 0x0f31, 0x1a69: 0x0249,
+ 0x1a6a: 0x0f41, 0x1a6b: 0x0259, 0x1a6c: 0x0f51, 0x1a6d: 0x0359, 0x1a6e: 0x0f61, 0x1a6f: 0x0f71,
+ 0x1a70: 0x00d9, 0x1a71: 0x0f99, 0x1a72: 0x2039, 0x1a73: 0x0269, 0x1a74: 0x01d9, 0x1a75: 0x0fa9,
+ 0x1a76: 0x0fb9, 0x1a77: 0x1089, 0x1a78: 0x0279, 0x1a79: 0x0369, 0x1a7a: 0x0289, 0x1a7b: 0x13d1,
+ 0x1a7c: 0x0039, 0x1a7d: 0x0ee9, 0x1a7e: 0x1159, 0x1a7f: 0x0ef9,
+ // Block 0x6a, offset 0x1a80
+ 0x1a80: 0x0f09, 0x1a81: 0x1199, 0x1a82: 0x0f31, 0x1a83: 0x0249, 0x1a84: 0x0f41, 0x1a85: 0x0259,
+ 0x1a86: 0x0f51, 0x1a87: 0x0359, 0x1a88: 0x0f61, 0x1a89: 0x0f71, 0x1a8a: 0x00d9, 0x1a8b: 0x0f99,
+ 0x1a8c: 0x2039, 0x1a8d: 0x0269, 0x1a8e: 0x01d9, 0x1a8f: 0x0fa9, 0x1a90: 0x0fb9, 0x1a91: 0x1089,
+ 0x1a92: 0x0279, 0x1a93: 0x0369, 0x1a94: 0x0289, 0x1a95: 0x13d1, 0x1a96: 0x0039, 0x1a97: 0x0ee9,
+ 0x1a98: 0x1159, 0x1a99: 0x0ef9, 0x1a9a: 0x0f09, 0x1a9b: 0x1199, 0x1a9c: 0x0f31, 0x1a9d: 0x0249,
+ 0x1a9e: 0x0f41, 0x1a9f: 0x0259, 0x1aa0: 0x0f51, 0x1aa1: 0x0359, 0x1aa2: 0x0f61, 0x1aa3: 0x0f71,
+ 0x1aa4: 0x00d9, 0x1aa5: 0x0f99, 0x1aa6: 0x2039, 0x1aa7: 0x0269, 0x1aa8: 0x01d9, 0x1aa9: 0x0fa9,
+ 0x1aaa: 0x0fb9, 0x1aab: 0x1089, 0x1aac: 0x0279, 0x1aad: 0x0369, 0x1aae: 0x0289, 0x1aaf: 0x13d1,
+ 0x1ab0: 0x0039, 0x1ab1: 0x0ee9, 0x1ab2: 0x1159, 0x1ab3: 0x0ef9, 0x1ab4: 0x0f09, 0x1ab5: 0x1199,
+ 0x1ab6: 0x0f31, 0x1ab7: 0x0249, 0x1ab8: 0x0f41, 0x1ab9: 0x0259, 0x1aba: 0x0f51, 0x1abb: 0x0359,
+ 0x1abc: 0x0f61, 0x1abd: 0x0f71, 0x1abe: 0x00d9, 0x1abf: 0x0f99,
+ // Block 0x6b, offset 0x1ac0
+ 0x1ac0: 0x2039, 0x1ac1: 0x0269, 0x1ac2: 0x01d9, 0x1ac3: 0x0fa9, 0x1ac4: 0x0fb9, 0x1ac5: 0x1089,
+ 0x1ac6: 0x0279, 0x1ac7: 0x0369, 0x1ac8: 0x0289, 0x1ac9: 0x13d1, 0x1aca: 0x0039, 0x1acb: 0x0ee9,
+ 0x1acc: 0x1159, 0x1acd: 0x0ef9, 0x1ace: 0x0f09, 0x1acf: 0x1199, 0x1ad0: 0x0f31, 0x1ad1: 0x0249,
+ 0x1ad2: 0x0f41, 0x1ad3: 0x0259, 0x1ad4: 0x0f51, 0x1ad5: 0x0359, 0x1ad6: 0x0f61, 0x1ad7: 0x0f71,
+ 0x1ad8: 0x00d9, 0x1ad9: 0x0f99, 0x1ada: 0x2039, 0x1adb: 0x0269, 0x1adc: 0x01d9, 0x1add: 0x0fa9,
+ 0x1ade: 0x0fb9, 0x1adf: 0x1089, 0x1ae0: 0x0279, 0x1ae1: 0x0369, 0x1ae2: 0x0289, 0x1ae3: 0x13d1,
+ 0x1ae4: 0xba81, 0x1ae5: 0xba99, 0x1ae6: 0x0040, 0x1ae7: 0x0040, 0x1ae8: 0xbab1, 0x1ae9: 0x1099,
+ 0x1aea: 0x10b1, 0x1aeb: 0x10c9, 0x1aec: 0xbac9, 0x1aed: 0xbae1, 0x1aee: 0xbaf9, 0x1aef: 0x1429,
+ 0x1af0: 0x1a31, 0x1af1: 0xbb11, 0x1af2: 0xbb29, 0x1af3: 0xbb41, 0x1af4: 0xbb59, 0x1af5: 0xbb71,
+ 0x1af6: 0xbb89, 0x1af7: 0x2109, 0x1af8: 0x1111, 0x1af9: 0x1429, 0x1afa: 0xbba1, 0x1afb: 0xbbb9,
+ 0x1afc: 0xbbd1, 0x1afd: 0x10e1, 0x1afe: 0x10f9, 0x1aff: 0xbbe9,
+ // Block 0x6c, offset 0x1b00
+ 0x1b00: 0x2079, 0x1b01: 0xbc01, 0x1b02: 0xbab1, 0x1b03: 0x1099, 0x1b04: 0x10b1, 0x1b05: 0x10c9,
+ 0x1b06: 0xbac9, 0x1b07: 0xbae1, 0x1b08: 0xbaf9, 0x1b09: 0x1429, 0x1b0a: 0x1a31, 0x1b0b: 0xbb11,
+ 0x1b0c: 0xbb29, 0x1b0d: 0xbb41, 0x1b0e: 0xbb59, 0x1b0f: 0xbb71, 0x1b10: 0xbb89, 0x1b11: 0x2109,
+ 0x1b12: 0x1111, 0x1b13: 0xbba1, 0x1b14: 0xbba1, 0x1b15: 0xbbb9, 0x1b16: 0xbbd1, 0x1b17: 0x10e1,
+ 0x1b18: 0x10f9, 0x1b19: 0xbbe9, 0x1b1a: 0x2079, 0x1b1b: 0xbc21, 0x1b1c: 0xbac9, 0x1b1d: 0x1429,
+ 0x1b1e: 0xbb11, 0x1b1f: 0x10e1, 0x1b20: 0x1111, 0x1b21: 0x2109, 0x1b22: 0xbab1, 0x1b23: 0x1099,
+ 0x1b24: 0x10b1, 0x1b25: 0x10c9, 0x1b26: 0xbac9, 0x1b27: 0xbae1, 0x1b28: 0xbaf9, 0x1b29: 0x1429,
+ 0x1b2a: 0x1a31, 0x1b2b: 0xbb11, 0x1b2c: 0xbb29, 0x1b2d: 0xbb41, 0x1b2e: 0xbb59, 0x1b2f: 0xbb71,
+ 0x1b30: 0xbb89, 0x1b31: 0x2109, 0x1b32: 0x1111, 0x1b33: 0x1429, 0x1b34: 0xbba1, 0x1b35: 0xbbb9,
+ 0x1b36: 0xbbd1, 0x1b37: 0x10e1, 0x1b38: 0x10f9, 0x1b39: 0xbbe9, 0x1b3a: 0x2079, 0x1b3b: 0xbc01,
+ 0x1b3c: 0xbab1, 0x1b3d: 0x1099, 0x1b3e: 0x10b1, 0x1b3f: 0x10c9,
+ // Block 0x6d, offset 0x1b40
+ 0x1b40: 0xbac9, 0x1b41: 0xbae1, 0x1b42: 0xbaf9, 0x1b43: 0x1429, 0x1b44: 0x1a31, 0x1b45: 0xbb11,
+ 0x1b46: 0xbb29, 0x1b47: 0xbb41, 0x1b48: 0xbb59, 0x1b49: 0xbb71, 0x1b4a: 0xbb89, 0x1b4b: 0x2109,
+ 0x1b4c: 0x1111, 0x1b4d: 0xbba1, 0x1b4e: 0xbba1, 0x1b4f: 0xbbb9, 0x1b50: 0xbbd1, 0x1b51: 0x10e1,
+ 0x1b52: 0x10f9, 0x1b53: 0xbbe9, 0x1b54: 0x2079, 0x1b55: 0xbc21, 0x1b56: 0xbac9, 0x1b57: 0x1429,
+ 0x1b58: 0xbb11, 0x1b59: 0x10e1, 0x1b5a: 0x1111, 0x1b5b: 0x2109, 0x1b5c: 0xbab1, 0x1b5d: 0x1099,
+ 0x1b5e: 0x10b1, 0x1b5f: 0x10c9, 0x1b60: 0xbac9, 0x1b61: 0xbae1, 0x1b62: 0xbaf9, 0x1b63: 0x1429,
+ 0x1b64: 0x1a31, 0x1b65: 0xbb11, 0x1b66: 0xbb29, 0x1b67: 0xbb41, 0x1b68: 0xbb59, 0x1b69: 0xbb71,
+ 0x1b6a: 0xbb89, 0x1b6b: 0x2109, 0x1b6c: 0x1111, 0x1b6d: 0x1429, 0x1b6e: 0xbba1, 0x1b6f: 0xbbb9,
+ 0x1b70: 0xbbd1, 0x1b71: 0x10e1, 0x1b72: 0x10f9, 0x1b73: 0xbbe9, 0x1b74: 0x2079, 0x1b75: 0xbc01,
+ 0x1b76: 0xbab1, 0x1b77: 0x1099, 0x1b78: 0x10b1, 0x1b79: 0x10c9, 0x1b7a: 0xbac9, 0x1b7b: 0xbae1,
+ 0x1b7c: 0xbaf9, 0x1b7d: 0x1429, 0x1b7e: 0x1a31, 0x1b7f: 0xbb11,
+ // Block 0x6e, offset 0x1b80
+ 0x1b80: 0xbb29, 0x1b81: 0xbb41, 0x1b82: 0xbb59, 0x1b83: 0xbb71, 0x1b84: 0xbb89, 0x1b85: 0x2109,
+ 0x1b86: 0x1111, 0x1b87: 0xbba1, 0x1b88: 0xbba1, 0x1b89: 0xbbb9, 0x1b8a: 0xbbd1, 0x1b8b: 0x10e1,
+ 0x1b8c: 0x10f9, 0x1b8d: 0xbbe9, 0x1b8e: 0x2079, 0x1b8f: 0xbc21, 0x1b90: 0xbac9, 0x1b91: 0x1429,
+ 0x1b92: 0xbb11, 0x1b93: 0x10e1, 0x1b94: 0x1111, 0x1b95: 0x2109, 0x1b96: 0xbab1, 0x1b97: 0x1099,
+ 0x1b98: 0x10b1, 0x1b99: 0x10c9, 0x1b9a: 0xbac9, 0x1b9b: 0xbae1, 0x1b9c: 0xbaf9, 0x1b9d: 0x1429,
+ 0x1b9e: 0x1a31, 0x1b9f: 0xbb11, 0x1ba0: 0xbb29, 0x1ba1: 0xbb41, 0x1ba2: 0xbb59, 0x1ba3: 0xbb71,
+ 0x1ba4: 0xbb89, 0x1ba5: 0x2109, 0x1ba6: 0x1111, 0x1ba7: 0x1429, 0x1ba8: 0xbba1, 0x1ba9: 0xbbb9,
+ 0x1baa: 0xbbd1, 0x1bab: 0x10e1, 0x1bac: 0x10f9, 0x1bad: 0xbbe9, 0x1bae: 0x2079, 0x1baf: 0xbc01,
+ 0x1bb0: 0xbab1, 0x1bb1: 0x1099, 0x1bb2: 0x10b1, 0x1bb3: 0x10c9, 0x1bb4: 0xbac9, 0x1bb5: 0xbae1,
+ 0x1bb6: 0xbaf9, 0x1bb7: 0x1429, 0x1bb8: 0x1a31, 0x1bb9: 0xbb11, 0x1bba: 0xbb29, 0x1bbb: 0xbb41,
+ 0x1bbc: 0xbb59, 0x1bbd: 0xbb71, 0x1bbe: 0xbb89, 0x1bbf: 0x2109,
+ // Block 0x6f, offset 0x1bc0
+ 0x1bc0: 0x1111, 0x1bc1: 0xbba1, 0x1bc2: 0xbba1, 0x1bc3: 0xbbb9, 0x1bc4: 0xbbd1, 0x1bc5: 0x10e1,
+ 0x1bc6: 0x10f9, 0x1bc7: 0xbbe9, 0x1bc8: 0x2079, 0x1bc9: 0xbc21, 0x1bca: 0xbac9, 0x1bcb: 0x1429,
+ 0x1bcc: 0xbb11, 0x1bcd: 0x10e1, 0x1bce: 0x1111, 0x1bcf: 0x2109, 0x1bd0: 0xbab1, 0x1bd1: 0x1099,
+ 0x1bd2: 0x10b1, 0x1bd3: 0x10c9, 0x1bd4: 0xbac9, 0x1bd5: 0xbae1, 0x1bd6: 0xbaf9, 0x1bd7: 0x1429,
+ 0x1bd8: 0x1a31, 0x1bd9: 0xbb11, 0x1bda: 0xbb29, 0x1bdb: 0xbb41, 0x1bdc: 0xbb59, 0x1bdd: 0xbb71,
+ 0x1bde: 0xbb89, 0x1bdf: 0x2109, 0x1be0: 0x1111, 0x1be1: 0x1429, 0x1be2: 0xbba1, 0x1be3: 0xbbb9,
+ 0x1be4: 0xbbd1, 0x1be5: 0x10e1, 0x1be6: 0x10f9, 0x1be7: 0xbbe9, 0x1be8: 0x2079, 0x1be9: 0xbc01,
+ 0x1bea: 0xbab1, 0x1beb: 0x1099, 0x1bec: 0x10b1, 0x1bed: 0x10c9, 0x1bee: 0xbac9, 0x1bef: 0xbae1,
+ 0x1bf0: 0xbaf9, 0x1bf1: 0x1429, 0x1bf2: 0x1a31, 0x1bf3: 0xbb11, 0x1bf4: 0xbb29, 0x1bf5: 0xbb41,
+ 0x1bf6: 0xbb59, 0x1bf7: 0xbb71, 0x1bf8: 0xbb89, 0x1bf9: 0x2109, 0x1bfa: 0x1111, 0x1bfb: 0xbba1,
+ 0x1bfc: 0xbba1, 0x1bfd: 0xbbb9, 0x1bfe: 0xbbd1, 0x1bff: 0x10e1,
+ // Block 0x70, offset 0x1c00
+ 0x1c00: 0x10f9, 0x1c01: 0xbbe9, 0x1c02: 0x2079, 0x1c03: 0xbc21, 0x1c04: 0xbac9, 0x1c05: 0x1429,
+ 0x1c06: 0xbb11, 0x1c07: 0x10e1, 0x1c08: 0x1111, 0x1c09: 0x2109, 0x1c0a: 0xbc41, 0x1c0b: 0xbc41,
+ 0x1c0c: 0x0040, 0x1c0d: 0x0040, 0x1c0e: 0x1f41, 0x1c0f: 0x00c9, 0x1c10: 0x0069, 0x1c11: 0x0079,
+ 0x1c12: 0x1f51, 0x1c13: 0x1f61, 0x1c14: 0x1f71, 0x1c15: 0x1f81, 0x1c16: 0x1f91, 0x1c17: 0x1fa1,
+ 0x1c18: 0x1f41, 0x1c19: 0x00c9, 0x1c1a: 0x0069, 0x1c1b: 0x0079, 0x1c1c: 0x1f51, 0x1c1d: 0x1f61,
+ 0x1c1e: 0x1f71, 0x1c1f: 0x1f81, 0x1c20: 0x1f91, 0x1c21: 0x1fa1, 0x1c22: 0x1f41, 0x1c23: 0x00c9,
+ 0x1c24: 0x0069, 0x1c25: 0x0079, 0x1c26: 0x1f51, 0x1c27: 0x1f61, 0x1c28: 0x1f71, 0x1c29: 0x1f81,
+ 0x1c2a: 0x1f91, 0x1c2b: 0x1fa1, 0x1c2c: 0x1f41, 0x1c2d: 0x00c9, 0x1c2e: 0x0069, 0x1c2f: 0x0079,
+ 0x1c30: 0x1f51, 0x1c31: 0x1f61, 0x1c32: 0x1f71, 0x1c33: 0x1f81, 0x1c34: 0x1f91, 0x1c35: 0x1fa1,
+ 0x1c36: 0x1f41, 0x1c37: 0x00c9, 0x1c38: 0x0069, 0x1c39: 0x0079, 0x1c3a: 0x1f51, 0x1c3b: 0x1f61,
+ 0x1c3c: 0x1f71, 0x1c3d: 0x1f81, 0x1c3e: 0x1f91, 0x1c3f: 0x1fa1,
+ // Block 0x71, offset 0x1c40
+ 0x1c40: 0xe115, 0x1c41: 0xe115, 0x1c42: 0xe135, 0x1c43: 0xe135, 0x1c44: 0xe115, 0x1c45: 0xe115,
+ 0x1c46: 0xe175, 0x1c47: 0xe175, 0x1c48: 0xe115, 0x1c49: 0xe115, 0x1c4a: 0xe135, 0x1c4b: 0xe135,
+ 0x1c4c: 0xe115, 0x1c4d: 0xe115, 0x1c4e: 0xe1f5, 0x1c4f: 0xe1f5, 0x1c50: 0xe115, 0x1c51: 0xe115,
+ 0x1c52: 0xe135, 0x1c53: 0xe135, 0x1c54: 0xe115, 0x1c55: 0xe115, 0x1c56: 0xe175, 0x1c57: 0xe175,
+ 0x1c58: 0xe115, 0x1c59: 0xe115, 0x1c5a: 0xe135, 0x1c5b: 0xe135, 0x1c5c: 0xe115, 0x1c5d: 0xe115,
+ 0x1c5e: 0x8b05, 0x1c5f: 0x8b05, 0x1c60: 0x04b5, 0x1c61: 0x04b5, 0x1c62: 0x0a08, 0x1c63: 0x0a08,
+ 0x1c64: 0x0a08, 0x1c65: 0x0a08, 0x1c66: 0x0a08, 0x1c67: 0x0a08, 0x1c68: 0x0a08, 0x1c69: 0x0a08,
+ 0x1c6a: 0x0a08, 0x1c6b: 0x0a08, 0x1c6c: 0x0a08, 0x1c6d: 0x0a08, 0x1c6e: 0x0a08, 0x1c6f: 0x0a08,
+ 0x1c70: 0x0a08, 0x1c71: 0x0a08, 0x1c72: 0x0a08, 0x1c73: 0x0a08, 0x1c74: 0x0a08, 0x1c75: 0x0a08,
+ 0x1c76: 0x0a08, 0x1c77: 0x0a08, 0x1c78: 0x0a08, 0x1c79: 0x0a08, 0x1c7a: 0x0a08, 0x1c7b: 0x0a08,
+ 0x1c7c: 0x0a08, 0x1c7d: 0x0a08, 0x1c7e: 0x0a08, 0x1c7f: 0x0a08,
+ // Block 0x72, offset 0x1c80
+ 0x1c80: 0xb189, 0x1c81: 0xb1a1, 0x1c82: 0xb201, 0x1c83: 0xb249, 0x1c84: 0x0040, 0x1c85: 0xb411,
+ 0x1c86: 0xb291, 0x1c87: 0xb219, 0x1c88: 0xb309, 0x1c89: 0xb429, 0x1c8a: 0xb399, 0x1c8b: 0xb3b1,
+ 0x1c8c: 0xb3c9, 0x1c8d: 0xb3e1, 0x1c8e: 0xb2a9, 0x1c8f: 0xb339, 0x1c90: 0xb369, 0x1c91: 0xb2d9,
+ 0x1c92: 0xb381, 0x1c93: 0xb279, 0x1c94: 0xb2c1, 0x1c95: 0xb1d1, 0x1c96: 0xb1e9, 0x1c97: 0xb231,
+ 0x1c98: 0xb261, 0x1c99: 0xb2f1, 0x1c9a: 0xb321, 0x1c9b: 0xb351, 0x1c9c: 0xbc59, 0x1c9d: 0x7949,
+ 0x1c9e: 0xbc71, 0x1c9f: 0xbc89, 0x1ca0: 0x0040, 0x1ca1: 0xb1a1, 0x1ca2: 0xb201, 0x1ca3: 0x0040,
+ 0x1ca4: 0xb3f9, 0x1ca5: 0x0040, 0x1ca6: 0x0040, 0x1ca7: 0xb219, 0x1ca8: 0x0040, 0x1ca9: 0xb429,
+ 0x1caa: 0xb399, 0x1cab: 0xb3b1, 0x1cac: 0xb3c9, 0x1cad: 0xb3e1, 0x1cae: 0xb2a9, 0x1caf: 0xb339,
+ 0x1cb0: 0xb369, 0x1cb1: 0xb2d9, 0x1cb2: 0xb381, 0x1cb3: 0x0040, 0x1cb4: 0xb2c1, 0x1cb5: 0xb1d1,
+ 0x1cb6: 0xb1e9, 0x1cb7: 0xb231, 0x1cb8: 0x0040, 0x1cb9: 0xb2f1, 0x1cba: 0x0040, 0x1cbb: 0xb351,
+ 0x1cbc: 0x0040, 0x1cbd: 0x0040, 0x1cbe: 0x0040, 0x1cbf: 0x0040,
+ // Block 0x73, offset 0x1cc0
+ 0x1cc0: 0x0040, 0x1cc1: 0x0040, 0x1cc2: 0xb201, 0x1cc3: 0x0040, 0x1cc4: 0x0040, 0x1cc5: 0x0040,
+ 0x1cc6: 0x0040, 0x1cc7: 0xb219, 0x1cc8: 0x0040, 0x1cc9: 0xb429, 0x1cca: 0x0040, 0x1ccb: 0xb3b1,
+ 0x1ccc: 0x0040, 0x1ccd: 0xb3e1, 0x1cce: 0xb2a9, 0x1ccf: 0xb339, 0x1cd0: 0x0040, 0x1cd1: 0xb2d9,
+ 0x1cd2: 0xb381, 0x1cd3: 0x0040, 0x1cd4: 0xb2c1, 0x1cd5: 0x0040, 0x1cd6: 0x0040, 0x1cd7: 0xb231,
+ 0x1cd8: 0x0040, 0x1cd9: 0xb2f1, 0x1cda: 0x0040, 0x1cdb: 0xb351, 0x1cdc: 0x0040, 0x1cdd: 0x7949,
+ 0x1cde: 0x0040, 0x1cdf: 0xbc89, 0x1ce0: 0x0040, 0x1ce1: 0xb1a1, 0x1ce2: 0xb201, 0x1ce3: 0x0040,
+ 0x1ce4: 0xb3f9, 0x1ce5: 0x0040, 0x1ce6: 0x0040, 0x1ce7: 0xb219, 0x1ce8: 0xb309, 0x1ce9: 0xb429,
+ 0x1cea: 0xb399, 0x1ceb: 0x0040, 0x1cec: 0xb3c9, 0x1ced: 0xb3e1, 0x1cee: 0xb2a9, 0x1cef: 0xb339,
+ 0x1cf0: 0xb369, 0x1cf1: 0xb2d9, 0x1cf2: 0xb381, 0x1cf3: 0x0040, 0x1cf4: 0xb2c1, 0x1cf5: 0xb1d1,
+ 0x1cf6: 0xb1e9, 0x1cf7: 0xb231, 0x1cf8: 0x0040, 0x1cf9: 0xb2f1, 0x1cfa: 0xb321, 0x1cfb: 0xb351,
+ 0x1cfc: 0xbc59, 0x1cfd: 0x0040, 0x1cfe: 0xbc71, 0x1cff: 0x0040,
+ // Block 0x74, offset 0x1d00
+ 0x1d00: 0xb189, 0x1d01: 0xb1a1, 0x1d02: 0xb201, 0x1d03: 0xb249, 0x1d04: 0xb3f9, 0x1d05: 0xb411,
+ 0x1d06: 0xb291, 0x1d07: 0xb219, 0x1d08: 0xb309, 0x1d09: 0xb429, 0x1d0a: 0x0040, 0x1d0b: 0xb3b1,
+ 0x1d0c: 0xb3c9, 0x1d0d: 0xb3e1, 0x1d0e: 0xb2a9, 0x1d0f: 0xb339, 0x1d10: 0xb369, 0x1d11: 0xb2d9,
+ 0x1d12: 0xb381, 0x1d13: 0xb279, 0x1d14: 0xb2c1, 0x1d15: 0xb1d1, 0x1d16: 0xb1e9, 0x1d17: 0xb231,
+ 0x1d18: 0xb261, 0x1d19: 0xb2f1, 0x1d1a: 0xb321, 0x1d1b: 0xb351, 0x1d1c: 0x0040, 0x1d1d: 0x0040,
+ 0x1d1e: 0x0040, 0x1d1f: 0x0040, 0x1d20: 0x0040, 0x1d21: 0xb1a1, 0x1d22: 0xb201, 0x1d23: 0xb249,
+ 0x1d24: 0x0040, 0x1d25: 0xb411, 0x1d26: 0xb291, 0x1d27: 0xb219, 0x1d28: 0xb309, 0x1d29: 0xb429,
+ 0x1d2a: 0x0040, 0x1d2b: 0xb3b1, 0x1d2c: 0xb3c9, 0x1d2d: 0xb3e1, 0x1d2e: 0xb2a9, 0x1d2f: 0xb339,
+ 0x1d30: 0xb369, 0x1d31: 0xb2d9, 0x1d32: 0xb381, 0x1d33: 0xb279, 0x1d34: 0xb2c1, 0x1d35: 0xb1d1,
+ 0x1d36: 0xb1e9, 0x1d37: 0xb231, 0x1d38: 0xb261, 0x1d39: 0xb2f1, 0x1d3a: 0xb321, 0x1d3b: 0xb351,
+ 0x1d3c: 0x0040, 0x1d3d: 0x0040, 0x1d3e: 0x0040, 0x1d3f: 0x0040,
+ // Block 0x75, offset 0x1d40
+ 0x1d40: 0x0040, 0x1d41: 0xbca2, 0x1d42: 0xbcba, 0x1d43: 0xbcd2, 0x1d44: 0xbcea, 0x1d45: 0xbd02,
+ 0x1d46: 0xbd1a, 0x1d47: 0xbd32, 0x1d48: 0xbd4a, 0x1d49: 0xbd62, 0x1d4a: 0xbd7a, 0x1d4b: 0x0018,
+ 0x1d4c: 0x0018, 0x1d4d: 0x0040, 0x1d4e: 0x0040, 0x1d4f: 0x0040, 0x1d50: 0xbd92, 0x1d51: 0xbdb2,
+ 0x1d52: 0xbdd2, 0x1d53: 0xbdf2, 0x1d54: 0xbe12, 0x1d55: 0xbe32, 0x1d56: 0xbe52, 0x1d57: 0xbe72,
+ 0x1d58: 0xbe92, 0x1d59: 0xbeb2, 0x1d5a: 0xbed2, 0x1d5b: 0xbef2, 0x1d5c: 0xbf12, 0x1d5d: 0xbf32,
+ 0x1d5e: 0xbf52, 0x1d5f: 0xbf72, 0x1d60: 0xbf92, 0x1d61: 0xbfb2, 0x1d62: 0xbfd2, 0x1d63: 0xbff2,
+ 0x1d64: 0xc012, 0x1d65: 0xc032, 0x1d66: 0xc052, 0x1d67: 0xc072, 0x1d68: 0xc092, 0x1d69: 0xc0b2,
+ 0x1d6a: 0xc0d1, 0x1d6b: 0x1159, 0x1d6c: 0x0269, 0x1d6d: 0x6671, 0x1d6e: 0xc111, 0x1d6f: 0x0040,
+ 0x1d70: 0x0039, 0x1d71: 0x0ee9, 0x1d72: 0x1159, 0x1d73: 0x0ef9, 0x1d74: 0x0f09, 0x1d75: 0x1199,
+ 0x1d76: 0x0f31, 0x1d77: 0x0249, 0x1d78: 0x0f41, 0x1d79: 0x0259, 0x1d7a: 0x0f51, 0x1d7b: 0x0359,
+ 0x1d7c: 0x0f61, 0x1d7d: 0x0f71, 0x1d7e: 0x00d9, 0x1d7f: 0x0f99,
+ // Block 0x76, offset 0x1d80
+ 0x1d80: 0x2039, 0x1d81: 0x0269, 0x1d82: 0x01d9, 0x1d83: 0x0fa9, 0x1d84: 0x0fb9, 0x1d85: 0x1089,
+ 0x1d86: 0x0279, 0x1d87: 0x0369, 0x1d88: 0x0289, 0x1d89: 0x13d1, 0x1d8a: 0xc129, 0x1d8b: 0x65b1,
+ 0x1d8c: 0xc141, 0x1d8d: 0x1441, 0x1d8e: 0xc159, 0x1d8f: 0xc179, 0x1d90: 0x0018, 0x1d91: 0x0018,
+ 0x1d92: 0x0018, 0x1d93: 0x0018, 0x1d94: 0x0018, 0x1d95: 0x0018, 0x1d96: 0x0018, 0x1d97: 0x0018,
+ 0x1d98: 0x0018, 0x1d99: 0x0018, 0x1d9a: 0x0018, 0x1d9b: 0x0018, 0x1d9c: 0x0018, 0x1d9d: 0x0018,
+ 0x1d9e: 0x0018, 0x1d9f: 0x0018, 0x1da0: 0x0018, 0x1da1: 0x0018, 0x1da2: 0x0018, 0x1da3: 0x0018,
+ 0x1da4: 0x0018, 0x1da5: 0x0018, 0x1da6: 0x0018, 0x1da7: 0x0018, 0x1da8: 0x0018, 0x1da9: 0x0018,
+ 0x1daa: 0xc191, 0x1dab: 0xc1a9, 0x1dac: 0x0040, 0x1dad: 0x0040, 0x1dae: 0x0040, 0x1daf: 0x0040,
+ 0x1db0: 0x0018, 0x1db1: 0x0018, 0x1db2: 0x0018, 0x1db3: 0x0018, 0x1db4: 0x0018, 0x1db5: 0x0018,
+ 0x1db6: 0x0018, 0x1db7: 0x0018, 0x1db8: 0x0018, 0x1db9: 0x0018, 0x1dba: 0x0018, 0x1dbb: 0x0018,
+ 0x1dbc: 0x0018, 0x1dbd: 0x0018, 0x1dbe: 0x0018, 0x1dbf: 0x0018,
+ // Block 0x77, offset 0x1dc0
+ 0x1dc0: 0xc1d9, 0x1dc1: 0xc211, 0x1dc2: 0xc249, 0x1dc3: 0x0040, 0x1dc4: 0x0040, 0x1dc5: 0x0040,
+ 0x1dc6: 0x0040, 0x1dc7: 0x0040, 0x1dc8: 0x0040, 0x1dc9: 0x0040, 0x1dca: 0x0040, 0x1dcb: 0x0040,
+ 0x1dcc: 0x0040, 0x1dcd: 0x0040, 0x1dce: 0x0040, 0x1dcf: 0x0040, 0x1dd0: 0xc269, 0x1dd1: 0xc289,
+ 0x1dd2: 0xc2a9, 0x1dd3: 0xc2c9, 0x1dd4: 0xc2e9, 0x1dd5: 0xc309, 0x1dd6: 0xc329, 0x1dd7: 0xc349,
+ 0x1dd8: 0xc369, 0x1dd9: 0xc389, 0x1dda: 0xc3a9, 0x1ddb: 0xc3c9, 0x1ddc: 0xc3e9, 0x1ddd: 0xc409,
+ 0x1dde: 0xc429, 0x1ddf: 0xc449, 0x1de0: 0xc469, 0x1de1: 0xc489, 0x1de2: 0xc4a9, 0x1de3: 0xc4c9,
+ 0x1de4: 0xc4e9, 0x1de5: 0xc509, 0x1de6: 0xc529, 0x1de7: 0xc549, 0x1de8: 0xc569, 0x1de9: 0xc589,
+ 0x1dea: 0xc5a9, 0x1deb: 0xc5c9, 0x1dec: 0xc5e9, 0x1ded: 0xc609, 0x1dee: 0xc629, 0x1def: 0xc649,
+ 0x1df0: 0xc669, 0x1df1: 0xc689, 0x1df2: 0xc6a9, 0x1df3: 0xc6c9, 0x1df4: 0xc6e9, 0x1df5: 0xc709,
+ 0x1df6: 0xc729, 0x1df7: 0xc749, 0x1df8: 0xc769, 0x1df9: 0xc789, 0x1dfa: 0xc7a9, 0x1dfb: 0xc7c9,
+ 0x1dfc: 0x0040, 0x1dfd: 0x0040, 0x1dfe: 0x0040, 0x1dff: 0x0040,
+ // Block 0x78, offset 0x1e00
+ 0x1e00: 0xcaf9, 0x1e01: 0xcb19, 0x1e02: 0xcb39, 0x1e03: 0x8b1d, 0x1e04: 0xcb59, 0x1e05: 0xcb79,
+ 0x1e06: 0xcb99, 0x1e07: 0xcbb9, 0x1e08: 0xcbd9, 0x1e09: 0xcbf9, 0x1e0a: 0xcc19, 0x1e0b: 0xcc39,
+ 0x1e0c: 0xcc59, 0x1e0d: 0x8b3d, 0x1e0e: 0xcc79, 0x1e0f: 0xcc99, 0x1e10: 0xccb9, 0x1e11: 0xccd9,
+ 0x1e12: 0x8b5d, 0x1e13: 0xccf9, 0x1e14: 0xcd19, 0x1e15: 0xc429, 0x1e16: 0x8b7d, 0x1e17: 0xcd39,
+ 0x1e18: 0xcd59, 0x1e19: 0xcd79, 0x1e1a: 0xcd99, 0x1e1b: 0xcdb9, 0x1e1c: 0x8b9d, 0x1e1d: 0xcdd9,
+ 0x1e1e: 0xcdf9, 0x1e1f: 0xce19, 0x1e20: 0xce39, 0x1e21: 0xce59, 0x1e22: 0xc789, 0x1e23: 0xce79,
+ 0x1e24: 0xce99, 0x1e25: 0xceb9, 0x1e26: 0xced9, 0x1e27: 0xcef9, 0x1e28: 0xcf19, 0x1e29: 0xcf39,
+ 0x1e2a: 0xcf59, 0x1e2b: 0xcf79, 0x1e2c: 0xcf99, 0x1e2d: 0xcfb9, 0x1e2e: 0xcfd9, 0x1e2f: 0xcff9,
+ 0x1e30: 0xd019, 0x1e31: 0xd039, 0x1e32: 0xd039, 0x1e33: 0xd039, 0x1e34: 0x8bbd, 0x1e35: 0xd059,
+ 0x1e36: 0xd079, 0x1e37: 0xd099, 0x1e38: 0x8bdd, 0x1e39: 0xd0b9, 0x1e3a: 0xd0d9, 0x1e3b: 0xd0f9,
+ 0x1e3c: 0xd119, 0x1e3d: 0xd139, 0x1e3e: 0xd159, 0x1e3f: 0xd179,
+ // Block 0x79, offset 0x1e40
+ 0x1e40: 0xd199, 0x1e41: 0xd1b9, 0x1e42: 0xd1d9, 0x1e43: 0xd1f9, 0x1e44: 0xd219, 0x1e45: 0xd239,
+ 0x1e46: 0xd239, 0x1e47: 0xd259, 0x1e48: 0xd279, 0x1e49: 0xd299, 0x1e4a: 0xd2b9, 0x1e4b: 0xd2d9,
+ 0x1e4c: 0xd2f9, 0x1e4d: 0xd319, 0x1e4e: 0xd339, 0x1e4f: 0xd359, 0x1e50: 0xd379, 0x1e51: 0xd399,
+ 0x1e52: 0xd3b9, 0x1e53: 0xd3d9, 0x1e54: 0xd3f9, 0x1e55: 0xd419, 0x1e56: 0xd439, 0x1e57: 0xd459,
+ 0x1e58: 0xd479, 0x1e59: 0x8bfd, 0x1e5a: 0xd499, 0x1e5b: 0xd4b9, 0x1e5c: 0xd4d9, 0x1e5d: 0xc309,
+ 0x1e5e: 0xd4f9, 0x1e5f: 0xd519, 0x1e60: 0x8c1d, 0x1e61: 0x8c3d, 0x1e62: 0xd539, 0x1e63: 0xd559,
+ 0x1e64: 0xd579, 0x1e65: 0xd599, 0x1e66: 0xd5b9, 0x1e67: 0xd5d9, 0x1e68: 0x2040, 0x1e69: 0xd5f9,
+ 0x1e6a: 0xd619, 0x1e6b: 0xd619, 0x1e6c: 0x8c5d, 0x1e6d: 0xd639, 0x1e6e: 0xd659, 0x1e6f: 0xd679,
+ 0x1e70: 0xd699, 0x1e71: 0x8c7d, 0x1e72: 0xd6b9, 0x1e73: 0xd6d9, 0x1e74: 0x2040, 0x1e75: 0xd6f9,
+ 0x1e76: 0xd719, 0x1e77: 0xd739, 0x1e78: 0xd759, 0x1e79: 0xd779, 0x1e7a: 0xd799, 0x1e7b: 0x8c9d,
+ 0x1e7c: 0xd7b9, 0x1e7d: 0x8cbd, 0x1e7e: 0xd7d9, 0x1e7f: 0xd7f9,
+ // Block 0x7a, offset 0x1e80
+ 0x1e80: 0xd819, 0x1e81: 0xd839, 0x1e82: 0xd859, 0x1e83: 0xd879, 0x1e84: 0xd899, 0x1e85: 0xd8b9,
+ 0x1e86: 0xd8d9, 0x1e87: 0xd8f9, 0x1e88: 0xd919, 0x1e89: 0x8cdd, 0x1e8a: 0xd939, 0x1e8b: 0xd959,
+ 0x1e8c: 0xd979, 0x1e8d: 0xd999, 0x1e8e: 0xd9b9, 0x1e8f: 0x8cfd, 0x1e90: 0xd9d9, 0x1e91: 0x8d1d,
+ 0x1e92: 0x8d3d, 0x1e93: 0xd9f9, 0x1e94: 0xda19, 0x1e95: 0xda19, 0x1e96: 0xda39, 0x1e97: 0x8d5d,
+ 0x1e98: 0x8d7d, 0x1e99: 0xda59, 0x1e9a: 0xda79, 0x1e9b: 0xda99, 0x1e9c: 0xdab9, 0x1e9d: 0xdad9,
+ 0x1e9e: 0xdaf9, 0x1e9f: 0xdb19, 0x1ea0: 0xdb39, 0x1ea1: 0xdb59, 0x1ea2: 0xdb79, 0x1ea3: 0xdb99,
+ 0x1ea4: 0x8d9d, 0x1ea5: 0xdbb9, 0x1ea6: 0xdbd9, 0x1ea7: 0xdbf9, 0x1ea8: 0xdc19, 0x1ea9: 0xdbf9,
+ 0x1eaa: 0xdc39, 0x1eab: 0xdc59, 0x1eac: 0xdc79, 0x1ead: 0xdc99, 0x1eae: 0xdcb9, 0x1eaf: 0xdcd9,
+ 0x1eb0: 0xdcf9, 0x1eb1: 0xdd19, 0x1eb2: 0xdd39, 0x1eb3: 0xdd59, 0x1eb4: 0xdd79, 0x1eb5: 0xdd99,
+ 0x1eb6: 0xddb9, 0x1eb7: 0xddd9, 0x1eb8: 0x8dbd, 0x1eb9: 0xddf9, 0x1eba: 0xde19, 0x1ebb: 0xde39,
+ 0x1ebc: 0xde59, 0x1ebd: 0xde79, 0x1ebe: 0x8ddd, 0x1ebf: 0xde99,
+ // Block 0x7b, offset 0x1ec0
+ 0x1ec0: 0xe599, 0x1ec1: 0xe5b9, 0x1ec2: 0xe5d9, 0x1ec3: 0xe5f9, 0x1ec4: 0xe619, 0x1ec5: 0xe639,
+ 0x1ec6: 0x8efd, 0x1ec7: 0xe659, 0x1ec8: 0xe679, 0x1ec9: 0xe699, 0x1eca: 0xe6b9, 0x1ecb: 0xe6d9,
+ 0x1ecc: 0xe6f9, 0x1ecd: 0x8f1d, 0x1ece: 0xe719, 0x1ecf: 0xe739, 0x1ed0: 0x8f3d, 0x1ed1: 0x8f5d,
+ 0x1ed2: 0xe759, 0x1ed3: 0xe779, 0x1ed4: 0xe799, 0x1ed5: 0xe7b9, 0x1ed6: 0xe7d9, 0x1ed7: 0xe7f9,
+ 0x1ed8: 0xe819, 0x1ed9: 0xe839, 0x1eda: 0xe859, 0x1edb: 0x8f7d, 0x1edc: 0xe879, 0x1edd: 0x8f9d,
+ 0x1ede: 0xe899, 0x1edf: 0x2040, 0x1ee0: 0xe8b9, 0x1ee1: 0xe8d9, 0x1ee2: 0xe8f9, 0x1ee3: 0x8fbd,
+ 0x1ee4: 0xe919, 0x1ee5: 0xe939, 0x1ee6: 0x8fdd, 0x1ee7: 0x8ffd, 0x1ee8: 0xe959, 0x1ee9: 0xe979,
+ 0x1eea: 0xe999, 0x1eeb: 0xe9b9, 0x1eec: 0xe9d9, 0x1eed: 0xe9d9, 0x1eee: 0xe9f9, 0x1eef: 0xea19,
+ 0x1ef0: 0xea39, 0x1ef1: 0xea59, 0x1ef2: 0xea79, 0x1ef3: 0xea99, 0x1ef4: 0xeab9, 0x1ef5: 0x901d,
+ 0x1ef6: 0xead9, 0x1ef7: 0x903d, 0x1ef8: 0xeaf9, 0x1ef9: 0x905d, 0x1efa: 0xeb19, 0x1efb: 0x907d,
+ 0x1efc: 0x909d, 0x1efd: 0x90bd, 0x1efe: 0xeb39, 0x1eff: 0xeb59,
+ // Block 0x7c, offset 0x1f00
+ 0x1f00: 0xeb79, 0x1f01: 0x90dd, 0x1f02: 0x90fd, 0x1f03: 0x911d, 0x1f04: 0x913d, 0x1f05: 0xeb99,
+ 0x1f06: 0xebb9, 0x1f07: 0xebb9, 0x1f08: 0xebd9, 0x1f09: 0xebf9, 0x1f0a: 0xec19, 0x1f0b: 0xec39,
+ 0x1f0c: 0xec59, 0x1f0d: 0x915d, 0x1f0e: 0xec79, 0x1f0f: 0xec99, 0x1f10: 0xecb9, 0x1f11: 0xecd9,
+ 0x1f12: 0x917d, 0x1f13: 0xecf9, 0x1f14: 0x919d, 0x1f15: 0x91bd, 0x1f16: 0xed19, 0x1f17: 0xed39,
+ 0x1f18: 0xed59, 0x1f19: 0xed79, 0x1f1a: 0xed99, 0x1f1b: 0xedb9, 0x1f1c: 0x91dd, 0x1f1d: 0x91fd,
+ 0x1f1e: 0x921d, 0x1f1f: 0x2040, 0x1f20: 0xedd9, 0x1f21: 0x923d, 0x1f22: 0xedf9, 0x1f23: 0xee19,
+ 0x1f24: 0xee39, 0x1f25: 0x925d, 0x1f26: 0xee59, 0x1f27: 0xee79, 0x1f28: 0xee99, 0x1f29: 0xeeb9,
+ 0x1f2a: 0xeed9, 0x1f2b: 0x927d, 0x1f2c: 0xeef9, 0x1f2d: 0xef19, 0x1f2e: 0xef39, 0x1f2f: 0xef59,
+ 0x1f30: 0xef79, 0x1f31: 0xef99, 0x1f32: 0x929d, 0x1f33: 0x92bd, 0x1f34: 0xefb9, 0x1f35: 0x92dd,
+ 0x1f36: 0xefd9, 0x1f37: 0x92fd, 0x1f38: 0xeff9, 0x1f39: 0xf019, 0x1f3a: 0xf039, 0x1f3b: 0x931d,
+ 0x1f3c: 0x933d, 0x1f3d: 0xf059, 0x1f3e: 0x935d, 0x1f3f: 0xf079,
+ // Block 0x7d, offset 0x1f40
+ 0x1f40: 0xf6b9, 0x1f41: 0xf6d9, 0x1f42: 0xf6f9, 0x1f43: 0xf719, 0x1f44: 0xf739, 0x1f45: 0x951d,
+ 0x1f46: 0xf759, 0x1f47: 0xf779, 0x1f48: 0xf799, 0x1f49: 0xf7b9, 0x1f4a: 0xf7d9, 0x1f4b: 0x953d,
+ 0x1f4c: 0x955d, 0x1f4d: 0xf7f9, 0x1f4e: 0xf819, 0x1f4f: 0xf839, 0x1f50: 0xf859, 0x1f51: 0xf879,
+ 0x1f52: 0xf899, 0x1f53: 0x957d, 0x1f54: 0xf8b9, 0x1f55: 0xf8d9, 0x1f56: 0xf8f9, 0x1f57: 0xf919,
+ 0x1f58: 0x959d, 0x1f59: 0x95bd, 0x1f5a: 0xf939, 0x1f5b: 0xf959, 0x1f5c: 0xf979, 0x1f5d: 0x95dd,
+ 0x1f5e: 0xf999, 0x1f5f: 0xf9b9, 0x1f60: 0x6815, 0x1f61: 0x95fd, 0x1f62: 0xf9d9, 0x1f63: 0xf9f9,
+ 0x1f64: 0xfa19, 0x1f65: 0x961d, 0x1f66: 0xfa39, 0x1f67: 0xfa59, 0x1f68: 0xfa79, 0x1f69: 0xfa99,
+ 0x1f6a: 0xfab9, 0x1f6b: 0xfad9, 0x1f6c: 0xfaf9, 0x1f6d: 0x963d, 0x1f6e: 0xfb19, 0x1f6f: 0xfb39,
+ 0x1f70: 0xfb59, 0x1f71: 0x965d, 0x1f72: 0xfb79, 0x1f73: 0xfb99, 0x1f74: 0xfbb9, 0x1f75: 0xfbd9,
+ 0x1f76: 0x7b35, 0x1f77: 0x967d, 0x1f78: 0xfbf9, 0x1f79: 0xfc19, 0x1f7a: 0xfc39, 0x1f7b: 0x969d,
+ 0x1f7c: 0xfc59, 0x1f7d: 0x96bd, 0x1f7e: 0xfc79, 0x1f7f: 0xfc79,
+ // Block 0x7e, offset 0x1f80
+ 0x1f80: 0xfc99, 0x1f81: 0x96dd, 0x1f82: 0xfcb9, 0x1f83: 0xfcd9, 0x1f84: 0xfcf9, 0x1f85: 0xfd19,
+ 0x1f86: 0xfd39, 0x1f87: 0xfd59, 0x1f88: 0xfd79, 0x1f89: 0x96fd, 0x1f8a: 0xfd99, 0x1f8b: 0xfdb9,
+ 0x1f8c: 0xfdd9, 0x1f8d: 0xfdf9, 0x1f8e: 0xfe19, 0x1f8f: 0xfe39, 0x1f90: 0x971d, 0x1f91: 0xfe59,
+ 0x1f92: 0x973d, 0x1f93: 0x975d, 0x1f94: 0x977d, 0x1f95: 0xfe79, 0x1f96: 0xfe99, 0x1f97: 0xfeb9,
+ 0x1f98: 0xfed9, 0x1f99: 0xfef9, 0x1f9a: 0xff19, 0x1f9b: 0xff39, 0x1f9c: 0xff59, 0x1f9d: 0x979d,
+ 0x1f9e: 0x0040, 0x1f9f: 0x0040, 0x1fa0: 0x0040, 0x1fa1: 0x0040, 0x1fa2: 0x0040, 0x1fa3: 0x0040,
+ 0x1fa4: 0x0040, 0x1fa5: 0x0040, 0x1fa6: 0x0040, 0x1fa7: 0x0040, 0x1fa8: 0x0040, 0x1fa9: 0x0040,
+ 0x1faa: 0x0040, 0x1fab: 0x0040, 0x1fac: 0x0040, 0x1fad: 0x0040, 0x1fae: 0x0040, 0x1faf: 0x0040,
+ 0x1fb0: 0x0040, 0x1fb1: 0x0040, 0x1fb2: 0x0040, 0x1fb3: 0x0040, 0x1fb4: 0x0040, 0x1fb5: 0x0040,
+ 0x1fb6: 0x0040, 0x1fb7: 0x0040, 0x1fb8: 0x0040, 0x1fb9: 0x0040, 0x1fba: 0x0040, 0x1fbb: 0x0040,
+ 0x1fbc: 0x0040, 0x1fbd: 0x0040, 0x1fbe: 0x0040, 0x1fbf: 0x0040,
+}
+
+// idnaIndex: 36 blocks, 2304 entries, 4608 bytes
+// Block 0 is the zero block.
+var idnaIndex = [2304]uint16{
+ // Block 0x0, offset 0x0
+ // Block 0x1, offset 0x40
+ // Block 0x2, offset 0x80
+ // Block 0x3, offset 0xc0
+ 0xc2: 0x01, 0xc3: 0x7d, 0xc4: 0x02, 0xc5: 0x03, 0xc6: 0x04, 0xc7: 0x05,
+ 0xc8: 0x06, 0xc9: 0x7e, 0xca: 0x7f, 0xcb: 0x07, 0xcc: 0x80, 0xcd: 0x08, 0xce: 0x09, 0xcf: 0x0a,
+ 0xd0: 0x81, 0xd1: 0x0b, 0xd2: 0x0c, 0xd3: 0x0d, 0xd4: 0x0e, 0xd5: 0x82, 0xd6: 0x83, 0xd7: 0x84,
+ 0xd8: 0x0f, 0xd9: 0x10, 0xda: 0x85, 0xdb: 0x11, 0xdc: 0x12, 0xdd: 0x86, 0xde: 0x87, 0xdf: 0x88,
+ 0xe0: 0x02, 0xe1: 0x03, 0xe2: 0x04, 0xe3: 0x05, 0xe4: 0x06, 0xe5: 0x07, 0xe6: 0x07, 0xe7: 0x07,
+ 0xe8: 0x07, 0xe9: 0x08, 0xea: 0x09, 0xeb: 0x07, 0xec: 0x07, 0xed: 0x0a, 0xee: 0x0b, 0xef: 0x0c,
+ 0xf0: 0x1d, 0xf1: 0x1e, 0xf2: 0x1e, 0xf3: 0x20, 0xf4: 0x21,
+ // Block 0x4, offset 0x100
+ 0x120: 0x89, 0x121: 0x13, 0x122: 0x8a, 0x123: 0x8b, 0x124: 0x8c, 0x125: 0x14, 0x126: 0x15, 0x127: 0x16,
+ 0x128: 0x17, 0x129: 0x18, 0x12a: 0x19, 0x12b: 0x1a, 0x12c: 0x1b, 0x12d: 0x1c, 0x12e: 0x1d, 0x12f: 0x8d,
+ 0x130: 0x8e, 0x131: 0x1e, 0x132: 0x1f, 0x133: 0x20, 0x134: 0x8f, 0x135: 0x21, 0x136: 0x90, 0x137: 0x91,
+ 0x138: 0x92, 0x139: 0x93, 0x13a: 0x22, 0x13b: 0x94, 0x13c: 0x95, 0x13d: 0x23, 0x13e: 0x24, 0x13f: 0x96,
+ // Block 0x5, offset 0x140
+ 0x140: 0x97, 0x141: 0x98, 0x142: 0x99, 0x143: 0x9a, 0x144: 0x9b, 0x145: 0x9c, 0x146: 0x9d, 0x147: 0x9e,
+ 0x148: 0x9f, 0x149: 0xa0, 0x14a: 0xa1, 0x14b: 0xa2, 0x14c: 0xa3, 0x14d: 0xa4, 0x14e: 0xa5, 0x14f: 0xa6,
+ 0x150: 0xa7, 0x151: 0x9f, 0x152: 0x9f, 0x153: 0x9f, 0x154: 0x9f, 0x155: 0x9f, 0x156: 0x9f, 0x157: 0x9f,
+ 0x158: 0x9f, 0x159: 0xa8, 0x15a: 0xa9, 0x15b: 0xaa, 0x15c: 0xab, 0x15d: 0xac, 0x15e: 0xad, 0x15f: 0xae,
+ 0x160: 0xaf, 0x161: 0xb0, 0x162: 0xb1, 0x163: 0xb2, 0x164: 0xb3, 0x165: 0xb4, 0x166: 0xb5, 0x167: 0xb6,
+ 0x168: 0xb7, 0x169: 0xb8, 0x16a: 0xb9, 0x16b: 0xba, 0x16c: 0xbb, 0x16d: 0xbc, 0x16e: 0xbd, 0x16f: 0xbe,
+ 0x170: 0xbf, 0x171: 0xc0, 0x172: 0xc1, 0x173: 0xc2, 0x174: 0x25, 0x175: 0x26, 0x176: 0x27, 0x177: 0xc3,
+ 0x178: 0x28, 0x179: 0x28, 0x17a: 0x29, 0x17b: 0x28, 0x17c: 0xc4, 0x17d: 0x2a, 0x17e: 0x2b, 0x17f: 0x2c,
+ // Block 0x6, offset 0x180
+ 0x180: 0x2d, 0x181: 0x2e, 0x182: 0x2f, 0x183: 0xc5, 0x184: 0x30, 0x185: 0x31, 0x186: 0xc6, 0x187: 0x9b,
+ 0x188: 0xc7, 0x189: 0xc8, 0x18a: 0x9b, 0x18b: 0x9b, 0x18c: 0xc9, 0x18d: 0x9b, 0x18e: 0x9b, 0x18f: 0x9b,
+ 0x190: 0xca, 0x191: 0x32, 0x192: 0x33, 0x193: 0x34, 0x194: 0x9b, 0x195: 0x9b, 0x196: 0x9b, 0x197: 0x9b,
+ 0x198: 0x9b, 0x199: 0x9b, 0x19a: 0x9b, 0x19b: 0x9b, 0x19c: 0x9b, 0x19d: 0x9b, 0x19e: 0x9b, 0x19f: 0x9b,
+ 0x1a0: 0x9b, 0x1a1: 0x9b, 0x1a2: 0x9b, 0x1a3: 0x9b, 0x1a4: 0x9b, 0x1a5: 0x9b, 0x1a6: 0x9b, 0x1a7: 0x9b,
+ 0x1a8: 0xcb, 0x1a9: 0xcc, 0x1aa: 0x9b, 0x1ab: 0xcd, 0x1ac: 0x9b, 0x1ad: 0xce, 0x1ae: 0xcf, 0x1af: 0xd0,
+ 0x1b0: 0xd1, 0x1b1: 0x35, 0x1b2: 0x28, 0x1b3: 0x36, 0x1b4: 0xd2, 0x1b5: 0xd3, 0x1b6: 0xd4, 0x1b7: 0xd5,
+ 0x1b8: 0xd6, 0x1b9: 0xd7, 0x1ba: 0xd8, 0x1bb: 0xd9, 0x1bc: 0xda, 0x1bd: 0xdb, 0x1be: 0xdc, 0x1bf: 0x37,
+ // Block 0x7, offset 0x1c0
+ 0x1c0: 0x38, 0x1c1: 0xdd, 0x1c2: 0xde, 0x1c3: 0xdf, 0x1c4: 0xe0, 0x1c5: 0x39, 0x1c6: 0x3a, 0x1c7: 0xe1,
+ 0x1c8: 0xe2, 0x1c9: 0x3b, 0x1ca: 0x3c, 0x1cb: 0x3d, 0x1cc: 0x3e, 0x1cd: 0x3f, 0x1ce: 0x40, 0x1cf: 0x41,
+ 0x1d0: 0x9f, 0x1d1: 0x9f, 0x1d2: 0x9f, 0x1d3: 0x9f, 0x1d4: 0x9f, 0x1d5: 0x9f, 0x1d6: 0x9f, 0x1d7: 0x9f,
+ 0x1d8: 0x9f, 0x1d9: 0x9f, 0x1da: 0x9f, 0x1db: 0x9f, 0x1dc: 0x9f, 0x1dd: 0x9f, 0x1de: 0x9f, 0x1df: 0x9f,
+ 0x1e0: 0x9f, 0x1e1: 0x9f, 0x1e2: 0x9f, 0x1e3: 0x9f, 0x1e4: 0x9f, 0x1e5: 0x9f, 0x1e6: 0x9f, 0x1e7: 0x9f,
+ 0x1e8: 0x9f, 0x1e9: 0x9f, 0x1ea: 0x9f, 0x1eb: 0x9f, 0x1ec: 0x9f, 0x1ed: 0x9f, 0x1ee: 0x9f, 0x1ef: 0x9f,
+ 0x1f0: 0x9f, 0x1f1: 0x9f, 0x1f2: 0x9f, 0x1f3: 0x9f, 0x1f4: 0x9f, 0x1f5: 0x9f, 0x1f6: 0x9f, 0x1f7: 0x9f,
+ 0x1f8: 0x9f, 0x1f9: 0x9f, 0x1fa: 0x9f, 0x1fb: 0x9f, 0x1fc: 0x9f, 0x1fd: 0x9f, 0x1fe: 0x9f, 0x1ff: 0x9f,
+ // Block 0x8, offset 0x200
+ 0x200: 0x9f, 0x201: 0x9f, 0x202: 0x9f, 0x203: 0x9f, 0x204: 0x9f, 0x205: 0x9f, 0x206: 0x9f, 0x207: 0x9f,
+ 0x208: 0x9f, 0x209: 0x9f, 0x20a: 0x9f, 0x20b: 0x9f, 0x20c: 0x9f, 0x20d: 0x9f, 0x20e: 0x9f, 0x20f: 0x9f,
+ 0x210: 0x9f, 0x211: 0x9f, 0x212: 0x9f, 0x213: 0x9f, 0x214: 0x9f, 0x215: 0x9f, 0x216: 0x9f, 0x217: 0x9f,
+ 0x218: 0x9f, 0x219: 0x9f, 0x21a: 0x9f, 0x21b: 0x9f, 0x21c: 0x9f, 0x21d: 0x9f, 0x21e: 0x9f, 0x21f: 0x9f,
+ 0x220: 0x9f, 0x221: 0x9f, 0x222: 0x9f, 0x223: 0x9f, 0x224: 0x9f, 0x225: 0x9f, 0x226: 0x9f, 0x227: 0x9f,
+ 0x228: 0x9f, 0x229: 0x9f, 0x22a: 0x9f, 0x22b: 0x9f, 0x22c: 0x9f, 0x22d: 0x9f, 0x22e: 0x9f, 0x22f: 0x9f,
+ 0x230: 0x9f, 0x231: 0x9f, 0x232: 0x9f, 0x233: 0x9f, 0x234: 0x9f, 0x235: 0x9f, 0x236: 0xb2, 0x237: 0x9b,
+ 0x238: 0x9f, 0x239: 0x9f, 0x23a: 0x9f, 0x23b: 0x9f, 0x23c: 0x9f, 0x23d: 0x9f, 0x23e: 0x9f, 0x23f: 0x9f,
+ // Block 0x9, offset 0x240
+ 0x240: 0x9f, 0x241: 0x9f, 0x242: 0x9f, 0x243: 0x9f, 0x244: 0x9f, 0x245: 0x9f, 0x246: 0x9f, 0x247: 0x9f,
+ 0x248: 0x9f, 0x249: 0x9f, 0x24a: 0x9f, 0x24b: 0x9f, 0x24c: 0x9f, 0x24d: 0x9f, 0x24e: 0x9f, 0x24f: 0x9f,
+ 0x250: 0x9f, 0x251: 0x9f, 0x252: 0x9f, 0x253: 0x9f, 0x254: 0x9f, 0x255: 0x9f, 0x256: 0x9f, 0x257: 0x9f,
+ 0x258: 0x9f, 0x259: 0x9f, 0x25a: 0x9f, 0x25b: 0x9f, 0x25c: 0x9f, 0x25d: 0x9f, 0x25e: 0x9f, 0x25f: 0x9f,
+ 0x260: 0x9f, 0x261: 0x9f, 0x262: 0x9f, 0x263: 0x9f, 0x264: 0x9f, 0x265: 0x9f, 0x266: 0x9f, 0x267: 0x9f,
+ 0x268: 0x9f, 0x269: 0x9f, 0x26a: 0x9f, 0x26b: 0x9f, 0x26c: 0x9f, 0x26d: 0x9f, 0x26e: 0x9f, 0x26f: 0x9f,
+ 0x270: 0x9f, 0x271: 0x9f, 0x272: 0x9f, 0x273: 0x9f, 0x274: 0x9f, 0x275: 0x9f, 0x276: 0x9f, 0x277: 0x9f,
+ 0x278: 0x9f, 0x279: 0x9f, 0x27a: 0x9f, 0x27b: 0x9f, 0x27c: 0x9f, 0x27d: 0x9f, 0x27e: 0x9f, 0x27f: 0x9f,
+ // Block 0xa, offset 0x280
+ 0x280: 0x9f, 0x281: 0x9f, 0x282: 0x9f, 0x283: 0x9f, 0x284: 0x9f, 0x285: 0x9f, 0x286: 0x9f, 0x287: 0x9f,
+ 0x288: 0x9f, 0x289: 0x9f, 0x28a: 0x9f, 0x28b: 0x9f, 0x28c: 0x9f, 0x28d: 0x9f, 0x28e: 0x9f, 0x28f: 0x9f,
+ 0x290: 0x9f, 0x291: 0x9f, 0x292: 0x9f, 0x293: 0x9f, 0x294: 0x9f, 0x295: 0x9f, 0x296: 0x9f, 0x297: 0x9f,
+ 0x298: 0x9f, 0x299: 0x9f, 0x29a: 0x9f, 0x29b: 0x9f, 0x29c: 0x9f, 0x29d: 0x9f, 0x29e: 0x9f, 0x29f: 0x9f,
+ 0x2a0: 0x9f, 0x2a1: 0x9f, 0x2a2: 0x9f, 0x2a3: 0x9f, 0x2a4: 0x9f, 0x2a5: 0x9f, 0x2a6: 0x9f, 0x2a7: 0x9f,
+ 0x2a8: 0x9f, 0x2a9: 0x9f, 0x2aa: 0x9f, 0x2ab: 0x9f, 0x2ac: 0x9f, 0x2ad: 0x9f, 0x2ae: 0x9f, 0x2af: 0x9f,
+ 0x2b0: 0x9f, 0x2b1: 0x9f, 0x2b2: 0x9f, 0x2b3: 0x9f, 0x2b4: 0x9f, 0x2b5: 0x9f, 0x2b6: 0x9f, 0x2b7: 0x9f,
+ 0x2b8: 0x9f, 0x2b9: 0x9f, 0x2ba: 0x9f, 0x2bb: 0x9f, 0x2bc: 0x9f, 0x2bd: 0x9f, 0x2be: 0x9f, 0x2bf: 0xe3,
+ // Block 0xb, offset 0x2c0
+ 0x2c0: 0x9f, 0x2c1: 0x9f, 0x2c2: 0x9f, 0x2c3: 0x9f, 0x2c4: 0x9f, 0x2c5: 0x9f, 0x2c6: 0x9f, 0x2c7: 0x9f,
+ 0x2c8: 0x9f, 0x2c9: 0x9f, 0x2ca: 0x9f, 0x2cb: 0x9f, 0x2cc: 0x9f, 0x2cd: 0x9f, 0x2ce: 0x9f, 0x2cf: 0x9f,
+ 0x2d0: 0x9f, 0x2d1: 0x9f, 0x2d2: 0xe4, 0x2d3: 0xe5, 0x2d4: 0x9f, 0x2d5: 0x9f, 0x2d6: 0x9f, 0x2d7: 0x9f,
+ 0x2d8: 0xe6, 0x2d9: 0x42, 0x2da: 0x43, 0x2db: 0xe7, 0x2dc: 0x44, 0x2dd: 0x45, 0x2de: 0x46, 0x2df: 0xe8,
+ 0x2e0: 0xe9, 0x2e1: 0xea, 0x2e2: 0xeb, 0x2e3: 0xec, 0x2e4: 0xed, 0x2e5: 0xee, 0x2e6: 0xef, 0x2e7: 0xf0,
+ 0x2e8: 0xf1, 0x2e9: 0xf2, 0x2ea: 0xf3, 0x2eb: 0xf4, 0x2ec: 0xf5, 0x2ed: 0xf6, 0x2ee: 0xf7, 0x2ef: 0xf8,
+ 0x2f0: 0x9f, 0x2f1: 0x9f, 0x2f2: 0x9f, 0x2f3: 0x9f, 0x2f4: 0x9f, 0x2f5: 0x9f, 0x2f6: 0x9f, 0x2f7: 0x9f,
+ 0x2f8: 0x9f, 0x2f9: 0x9f, 0x2fa: 0x9f, 0x2fb: 0x9f, 0x2fc: 0x9f, 0x2fd: 0x9f, 0x2fe: 0x9f, 0x2ff: 0x9f,
+ // Block 0xc, offset 0x300
+ 0x300: 0x9f, 0x301: 0x9f, 0x302: 0x9f, 0x303: 0x9f, 0x304: 0x9f, 0x305: 0x9f, 0x306: 0x9f, 0x307: 0x9f,
+ 0x308: 0x9f, 0x309: 0x9f, 0x30a: 0x9f, 0x30b: 0x9f, 0x30c: 0x9f, 0x30d: 0x9f, 0x30e: 0x9f, 0x30f: 0x9f,
+ 0x310: 0x9f, 0x311: 0x9f, 0x312: 0x9f, 0x313: 0x9f, 0x314: 0x9f, 0x315: 0x9f, 0x316: 0x9f, 0x317: 0x9f,
+ 0x318: 0x9f, 0x319: 0x9f, 0x31a: 0x9f, 0x31b: 0x9f, 0x31c: 0x9f, 0x31d: 0x9f, 0x31e: 0xf9, 0x31f: 0xfa,
+ // Block 0xd, offset 0x340
+ 0x340: 0xba, 0x341: 0xba, 0x342: 0xba, 0x343: 0xba, 0x344: 0xba, 0x345: 0xba, 0x346: 0xba, 0x347: 0xba,
+ 0x348: 0xba, 0x349: 0xba, 0x34a: 0xba, 0x34b: 0xba, 0x34c: 0xba, 0x34d: 0xba, 0x34e: 0xba, 0x34f: 0xba,
+ 0x350: 0xba, 0x351: 0xba, 0x352: 0xba, 0x353: 0xba, 0x354: 0xba, 0x355: 0xba, 0x356: 0xba, 0x357: 0xba,
+ 0x358: 0xba, 0x359: 0xba, 0x35a: 0xba, 0x35b: 0xba, 0x35c: 0xba, 0x35d: 0xba, 0x35e: 0xba, 0x35f: 0xba,
+ 0x360: 0xba, 0x361: 0xba, 0x362: 0xba, 0x363: 0xba, 0x364: 0xba, 0x365: 0xba, 0x366: 0xba, 0x367: 0xba,
+ 0x368: 0xba, 0x369: 0xba, 0x36a: 0xba, 0x36b: 0xba, 0x36c: 0xba, 0x36d: 0xba, 0x36e: 0xba, 0x36f: 0xba,
+ 0x370: 0xba, 0x371: 0xba, 0x372: 0xba, 0x373: 0xba, 0x374: 0xba, 0x375: 0xba, 0x376: 0xba, 0x377: 0xba,
+ 0x378: 0xba, 0x379: 0xba, 0x37a: 0xba, 0x37b: 0xba, 0x37c: 0xba, 0x37d: 0xba, 0x37e: 0xba, 0x37f: 0xba,
+ // Block 0xe, offset 0x380
+ 0x380: 0xba, 0x381: 0xba, 0x382: 0xba, 0x383: 0xba, 0x384: 0xba, 0x385: 0xba, 0x386: 0xba, 0x387: 0xba,
+ 0x388: 0xba, 0x389: 0xba, 0x38a: 0xba, 0x38b: 0xba, 0x38c: 0xba, 0x38d: 0xba, 0x38e: 0xba, 0x38f: 0xba,
+ 0x390: 0xba, 0x391: 0xba, 0x392: 0xba, 0x393: 0xba, 0x394: 0xba, 0x395: 0xba, 0x396: 0xba, 0x397: 0xba,
+ 0x398: 0xba, 0x399: 0xba, 0x39a: 0xba, 0x39b: 0xba, 0x39c: 0xba, 0x39d: 0xba, 0x39e: 0xba, 0x39f: 0xba,
+ 0x3a0: 0xba, 0x3a1: 0xba, 0x3a2: 0xba, 0x3a3: 0xba, 0x3a4: 0xfb, 0x3a5: 0xfc, 0x3a6: 0xfd, 0x3a7: 0xfe,
+ 0x3a8: 0x47, 0x3a9: 0xff, 0x3aa: 0x100, 0x3ab: 0x48, 0x3ac: 0x49, 0x3ad: 0x4a, 0x3ae: 0x4b, 0x3af: 0x4c,
+ 0x3b0: 0x101, 0x3b1: 0x4d, 0x3b2: 0x4e, 0x3b3: 0x4f, 0x3b4: 0x50, 0x3b5: 0x51, 0x3b6: 0x102, 0x3b7: 0x52,
+ 0x3b8: 0x53, 0x3b9: 0x54, 0x3ba: 0x55, 0x3bb: 0x56, 0x3bc: 0x57, 0x3bd: 0x58, 0x3be: 0x59, 0x3bf: 0x5a,
+ // Block 0xf, offset 0x3c0
+ 0x3c0: 0x103, 0x3c1: 0x104, 0x3c2: 0x9f, 0x3c3: 0x105, 0x3c4: 0x106, 0x3c5: 0x9b, 0x3c6: 0x107, 0x3c7: 0x108,
+ 0x3c8: 0xba, 0x3c9: 0xba, 0x3ca: 0x109, 0x3cb: 0x10a, 0x3cc: 0x10b, 0x3cd: 0x10c, 0x3ce: 0x10d, 0x3cf: 0x10e,
+ 0x3d0: 0x10f, 0x3d1: 0x9f, 0x3d2: 0x110, 0x3d3: 0x111, 0x3d4: 0x112, 0x3d5: 0x113, 0x3d6: 0xba, 0x3d7: 0xba,
+ 0x3d8: 0x9f, 0x3d9: 0x9f, 0x3da: 0x9f, 0x3db: 0x9f, 0x3dc: 0x114, 0x3dd: 0x115, 0x3de: 0xba, 0x3df: 0xba,
+ 0x3e0: 0x116, 0x3e1: 0x117, 0x3e2: 0x118, 0x3e3: 0x119, 0x3e4: 0x11a, 0x3e5: 0xba, 0x3e6: 0x11b, 0x3e7: 0x11c,
+ 0x3e8: 0x11d, 0x3e9: 0x11e, 0x3ea: 0x11f, 0x3eb: 0x5b, 0x3ec: 0x120, 0x3ed: 0x121, 0x3ee: 0x5c, 0x3ef: 0xba,
+ 0x3f0: 0x122, 0x3f1: 0x123, 0x3f2: 0x124, 0x3f3: 0x125, 0x3f4: 0xba, 0x3f5: 0xba, 0x3f6: 0xba, 0x3f7: 0xba,
+ 0x3f8: 0xba, 0x3f9: 0x126, 0x3fa: 0xba, 0x3fb: 0xba, 0x3fc: 0xba, 0x3fd: 0xba, 0x3fe: 0xba, 0x3ff: 0xba,
+ // Block 0x10, offset 0x400
+ 0x400: 0x127, 0x401: 0x128, 0x402: 0x129, 0x403: 0x12a, 0x404: 0x12b, 0x405: 0x12c, 0x406: 0x12d, 0x407: 0x12e,
+ 0x408: 0x12f, 0x409: 0xba, 0x40a: 0x130, 0x40b: 0x131, 0x40c: 0x5d, 0x40d: 0x5e, 0x40e: 0xba, 0x40f: 0xba,
+ 0x410: 0x132, 0x411: 0x133, 0x412: 0x134, 0x413: 0x135, 0x414: 0xba, 0x415: 0xba, 0x416: 0x136, 0x417: 0x137,
+ 0x418: 0x138, 0x419: 0x139, 0x41a: 0x13a, 0x41b: 0x13b, 0x41c: 0x13c, 0x41d: 0xba, 0x41e: 0xba, 0x41f: 0xba,
+ 0x420: 0xba, 0x421: 0xba, 0x422: 0x13d, 0x423: 0x13e, 0x424: 0xba, 0x425: 0xba, 0x426: 0xba, 0x427: 0xba,
+ 0x428: 0x13f, 0x429: 0x140, 0x42a: 0x141, 0x42b: 0x142, 0x42c: 0xba, 0x42d: 0xba, 0x42e: 0xba, 0x42f: 0xba,
+ 0x430: 0x143, 0x431: 0x144, 0x432: 0x145, 0x433: 0xba, 0x434: 0x146, 0x435: 0x147, 0x436: 0xba, 0x437: 0xba,
+ 0x438: 0xba, 0x439: 0xba, 0x43a: 0xba, 0x43b: 0xba, 0x43c: 0xba, 0x43d: 0xba, 0x43e: 0xba, 0x43f: 0xba,
+ // Block 0x11, offset 0x440
+ 0x440: 0x9f, 0x441: 0x9f, 0x442: 0x9f, 0x443: 0x9f, 0x444: 0x9f, 0x445: 0x9f, 0x446: 0x9f, 0x447: 0x9f,
+ 0x448: 0x9f, 0x449: 0x9f, 0x44a: 0x9f, 0x44b: 0x9f, 0x44c: 0x9f, 0x44d: 0x9f, 0x44e: 0x148, 0x44f: 0xba,
+ 0x450: 0x9b, 0x451: 0x149, 0x452: 0x9f, 0x453: 0x9f, 0x454: 0x9f, 0x455: 0x14a, 0x456: 0xba, 0x457: 0xba,
+ 0x458: 0xba, 0x459: 0xba, 0x45a: 0xba, 0x45b: 0xba, 0x45c: 0xba, 0x45d: 0xba, 0x45e: 0xba, 0x45f: 0xba,
+ 0x460: 0xba, 0x461: 0xba, 0x462: 0xba, 0x463: 0xba, 0x464: 0xba, 0x465: 0xba, 0x466: 0xba, 0x467: 0xba,
+ 0x468: 0xba, 0x469: 0xba, 0x46a: 0xba, 0x46b: 0xba, 0x46c: 0xba, 0x46d: 0xba, 0x46e: 0xba, 0x46f: 0xba,
+ 0x470: 0xba, 0x471: 0xba, 0x472: 0xba, 0x473: 0xba, 0x474: 0xba, 0x475: 0xba, 0x476: 0xba, 0x477: 0xba,
+ 0x478: 0xba, 0x479: 0xba, 0x47a: 0xba, 0x47b: 0xba, 0x47c: 0xba, 0x47d: 0xba, 0x47e: 0xba, 0x47f: 0xba,
+ // Block 0x12, offset 0x480
+ 0x480: 0x9f, 0x481: 0x9f, 0x482: 0x9f, 0x483: 0x9f, 0x484: 0x9f, 0x485: 0x9f, 0x486: 0x9f, 0x487: 0x9f,
+ 0x488: 0x9f, 0x489: 0x9f, 0x48a: 0x9f, 0x48b: 0x9f, 0x48c: 0x9f, 0x48d: 0x9f, 0x48e: 0x9f, 0x48f: 0x9f,
+ 0x490: 0x14b, 0x491: 0xba, 0x492: 0xba, 0x493: 0xba, 0x494: 0xba, 0x495: 0xba, 0x496: 0xba, 0x497: 0xba,
+ 0x498: 0xba, 0x499: 0xba, 0x49a: 0xba, 0x49b: 0xba, 0x49c: 0xba, 0x49d: 0xba, 0x49e: 0xba, 0x49f: 0xba,
+ 0x4a0: 0xba, 0x4a1: 0xba, 0x4a2: 0xba, 0x4a3: 0xba, 0x4a4: 0xba, 0x4a5: 0xba, 0x4a6: 0xba, 0x4a7: 0xba,
+ 0x4a8: 0xba, 0x4a9: 0xba, 0x4aa: 0xba, 0x4ab: 0xba, 0x4ac: 0xba, 0x4ad: 0xba, 0x4ae: 0xba, 0x4af: 0xba,
+ 0x4b0: 0xba, 0x4b1: 0xba, 0x4b2: 0xba, 0x4b3: 0xba, 0x4b4: 0xba, 0x4b5: 0xba, 0x4b6: 0xba, 0x4b7: 0xba,
+ 0x4b8: 0xba, 0x4b9: 0xba, 0x4ba: 0xba, 0x4bb: 0xba, 0x4bc: 0xba, 0x4bd: 0xba, 0x4be: 0xba, 0x4bf: 0xba,
+ // Block 0x13, offset 0x4c0
+ 0x4c0: 0xba, 0x4c1: 0xba, 0x4c2: 0xba, 0x4c3: 0xba, 0x4c4: 0xba, 0x4c5: 0xba, 0x4c6: 0xba, 0x4c7: 0xba,
+ 0x4c8: 0xba, 0x4c9: 0xba, 0x4ca: 0xba, 0x4cb: 0xba, 0x4cc: 0xba, 0x4cd: 0xba, 0x4ce: 0xba, 0x4cf: 0xba,
+ 0x4d0: 0x9f, 0x4d1: 0x9f, 0x4d2: 0x9f, 0x4d3: 0x9f, 0x4d4: 0x9f, 0x4d5: 0x9f, 0x4d6: 0x9f, 0x4d7: 0x9f,
+ 0x4d8: 0x9f, 0x4d9: 0x14c, 0x4da: 0xba, 0x4db: 0xba, 0x4dc: 0xba, 0x4dd: 0xba, 0x4de: 0xba, 0x4df: 0xba,
+ 0x4e0: 0xba, 0x4e1: 0xba, 0x4e2: 0xba, 0x4e3: 0xba, 0x4e4: 0xba, 0x4e5: 0xba, 0x4e6: 0xba, 0x4e7: 0xba,
+ 0x4e8: 0xba, 0x4e9: 0xba, 0x4ea: 0xba, 0x4eb: 0xba, 0x4ec: 0xba, 0x4ed: 0xba, 0x4ee: 0xba, 0x4ef: 0xba,
+ 0x4f0: 0xba, 0x4f1: 0xba, 0x4f2: 0xba, 0x4f3: 0xba, 0x4f4: 0xba, 0x4f5: 0xba, 0x4f6: 0xba, 0x4f7: 0xba,
+ 0x4f8: 0xba, 0x4f9: 0xba, 0x4fa: 0xba, 0x4fb: 0xba, 0x4fc: 0xba, 0x4fd: 0xba, 0x4fe: 0xba, 0x4ff: 0xba,
+ // Block 0x14, offset 0x500
+ 0x500: 0xba, 0x501: 0xba, 0x502: 0xba, 0x503: 0xba, 0x504: 0xba, 0x505: 0xba, 0x506: 0xba, 0x507: 0xba,
+ 0x508: 0xba, 0x509: 0xba, 0x50a: 0xba, 0x50b: 0xba, 0x50c: 0xba, 0x50d: 0xba, 0x50e: 0xba, 0x50f: 0xba,
+ 0x510: 0xba, 0x511: 0xba, 0x512: 0xba, 0x513: 0xba, 0x514: 0xba, 0x515: 0xba, 0x516: 0xba, 0x517: 0xba,
+ 0x518: 0xba, 0x519: 0xba, 0x51a: 0xba, 0x51b: 0xba, 0x51c: 0xba, 0x51d: 0xba, 0x51e: 0xba, 0x51f: 0xba,
+ 0x520: 0x9f, 0x521: 0x9f, 0x522: 0x9f, 0x523: 0x9f, 0x524: 0x9f, 0x525: 0x9f, 0x526: 0x9f, 0x527: 0x9f,
+ 0x528: 0x142, 0x529: 0x14d, 0x52a: 0xba, 0x52b: 0x14e, 0x52c: 0x14f, 0x52d: 0x150, 0x52e: 0x151, 0x52f: 0xba,
+ 0x530: 0xba, 0x531: 0xba, 0x532: 0xba, 0x533: 0xba, 0x534: 0xba, 0x535: 0xba, 0x536: 0xba, 0x537: 0xba,
+ 0x538: 0xba, 0x539: 0xba, 0x53a: 0xba, 0x53b: 0xba, 0x53c: 0x9f, 0x53d: 0x152, 0x53e: 0x153, 0x53f: 0x154,
+ // Block 0x15, offset 0x540
+ 0x540: 0x9f, 0x541: 0x9f, 0x542: 0x9f, 0x543: 0x9f, 0x544: 0x9f, 0x545: 0x9f, 0x546: 0x9f, 0x547: 0x9f,
+ 0x548: 0x9f, 0x549: 0x9f, 0x54a: 0x9f, 0x54b: 0x9f, 0x54c: 0x9f, 0x54d: 0x9f, 0x54e: 0x9f, 0x54f: 0x9f,
+ 0x550: 0x9f, 0x551: 0x9f, 0x552: 0x9f, 0x553: 0x9f, 0x554: 0x9f, 0x555: 0x9f, 0x556: 0x9f, 0x557: 0x9f,
+ 0x558: 0x9f, 0x559: 0x9f, 0x55a: 0x9f, 0x55b: 0x9f, 0x55c: 0x9f, 0x55d: 0x9f, 0x55e: 0x9f, 0x55f: 0x155,
+ 0x560: 0x9f, 0x561: 0x9f, 0x562: 0x9f, 0x563: 0x9f, 0x564: 0x9f, 0x565: 0x9f, 0x566: 0x9f, 0x567: 0x9f,
+ 0x568: 0x9f, 0x569: 0x9f, 0x56a: 0x9f, 0x56b: 0x156, 0x56c: 0xba, 0x56d: 0xba, 0x56e: 0xba, 0x56f: 0xba,
+ 0x570: 0xba, 0x571: 0xba, 0x572: 0xba, 0x573: 0xba, 0x574: 0xba, 0x575: 0xba, 0x576: 0xba, 0x577: 0xba,
+ 0x578: 0xba, 0x579: 0xba, 0x57a: 0xba, 0x57b: 0xba, 0x57c: 0xba, 0x57d: 0xba, 0x57e: 0xba, 0x57f: 0xba,
+ // Block 0x16, offset 0x580
+ 0x580: 0x9f, 0x581: 0x9f, 0x582: 0x9f, 0x583: 0x9f, 0x584: 0x157, 0x585: 0x158, 0x586: 0x9f, 0x587: 0x9f,
+ 0x588: 0x9f, 0x589: 0x9f, 0x58a: 0x9f, 0x58b: 0x159, 0x58c: 0xba, 0x58d: 0xba, 0x58e: 0xba, 0x58f: 0xba,
+ 0x590: 0xba, 0x591: 0xba, 0x592: 0xba, 0x593: 0xba, 0x594: 0xba, 0x595: 0xba, 0x596: 0xba, 0x597: 0xba,
+ 0x598: 0xba, 0x599: 0xba, 0x59a: 0xba, 0x59b: 0xba, 0x59c: 0xba, 0x59d: 0xba, 0x59e: 0xba, 0x59f: 0xba,
+ 0x5a0: 0xba, 0x5a1: 0xba, 0x5a2: 0xba, 0x5a3: 0xba, 0x5a4: 0xba, 0x5a5: 0xba, 0x5a6: 0xba, 0x5a7: 0xba,
+ 0x5a8: 0xba, 0x5a9: 0xba, 0x5aa: 0xba, 0x5ab: 0xba, 0x5ac: 0xba, 0x5ad: 0xba, 0x5ae: 0xba, 0x5af: 0xba,
+ 0x5b0: 0x9f, 0x5b1: 0x15a, 0x5b2: 0x15b, 0x5b3: 0xba, 0x5b4: 0xba, 0x5b5: 0xba, 0x5b6: 0xba, 0x5b7: 0xba,
+ 0x5b8: 0xba, 0x5b9: 0xba, 0x5ba: 0xba, 0x5bb: 0xba, 0x5bc: 0xba, 0x5bd: 0xba, 0x5be: 0xba, 0x5bf: 0xba,
+ // Block 0x17, offset 0x5c0
+ 0x5c0: 0x9b, 0x5c1: 0x9b, 0x5c2: 0x9b, 0x5c3: 0x15c, 0x5c4: 0x15d, 0x5c5: 0x15e, 0x5c6: 0x15f, 0x5c7: 0x160,
+ 0x5c8: 0x9b, 0x5c9: 0x161, 0x5ca: 0xba, 0x5cb: 0xba, 0x5cc: 0x9b, 0x5cd: 0x162, 0x5ce: 0xba, 0x5cf: 0xba,
+ 0x5d0: 0x5f, 0x5d1: 0x60, 0x5d2: 0x61, 0x5d3: 0x62, 0x5d4: 0x63, 0x5d5: 0x64, 0x5d6: 0x65, 0x5d7: 0x66,
+ 0x5d8: 0x67, 0x5d9: 0x68, 0x5da: 0x69, 0x5db: 0x6a, 0x5dc: 0x6b, 0x5dd: 0x6c, 0x5de: 0x6d, 0x5df: 0x6e,
+ 0x5e0: 0x9b, 0x5e1: 0x9b, 0x5e2: 0x9b, 0x5e3: 0x9b, 0x5e4: 0x9b, 0x5e5: 0x9b, 0x5e6: 0x9b, 0x5e7: 0x9b,
+ 0x5e8: 0x163, 0x5e9: 0x164, 0x5ea: 0x165, 0x5eb: 0xba, 0x5ec: 0xba, 0x5ed: 0xba, 0x5ee: 0xba, 0x5ef: 0xba,
+ 0x5f0: 0xba, 0x5f1: 0xba, 0x5f2: 0xba, 0x5f3: 0xba, 0x5f4: 0xba, 0x5f5: 0xba, 0x5f6: 0xba, 0x5f7: 0xba,
+ 0x5f8: 0xba, 0x5f9: 0xba, 0x5fa: 0xba, 0x5fb: 0xba, 0x5fc: 0xba, 0x5fd: 0xba, 0x5fe: 0xba, 0x5ff: 0xba,
+ // Block 0x18, offset 0x600
+ 0x600: 0x166, 0x601: 0xba, 0x602: 0xba, 0x603: 0xba, 0x604: 0xba, 0x605: 0xba, 0x606: 0xba, 0x607: 0xba,
+ 0x608: 0xba, 0x609: 0xba, 0x60a: 0xba, 0x60b: 0xba, 0x60c: 0xba, 0x60d: 0xba, 0x60e: 0xba, 0x60f: 0xba,
+ 0x610: 0xba, 0x611: 0xba, 0x612: 0xba, 0x613: 0xba, 0x614: 0xba, 0x615: 0xba, 0x616: 0xba, 0x617: 0xba,
+ 0x618: 0xba, 0x619: 0xba, 0x61a: 0xba, 0x61b: 0xba, 0x61c: 0xba, 0x61d: 0xba, 0x61e: 0xba, 0x61f: 0xba,
+ 0x620: 0x122, 0x621: 0x122, 0x622: 0x122, 0x623: 0x167, 0x624: 0x6f, 0x625: 0x168, 0x626: 0xba, 0x627: 0xba,
+ 0x628: 0xba, 0x629: 0xba, 0x62a: 0xba, 0x62b: 0xba, 0x62c: 0xba, 0x62d: 0xba, 0x62e: 0xba, 0x62f: 0xba,
+ 0x630: 0xba, 0x631: 0xba, 0x632: 0xba, 0x633: 0xba, 0x634: 0xba, 0x635: 0xba, 0x636: 0xba, 0x637: 0xba,
+ 0x638: 0x70, 0x639: 0x71, 0x63a: 0x72, 0x63b: 0x169, 0x63c: 0xba, 0x63d: 0xba, 0x63e: 0xba, 0x63f: 0xba,
+ // Block 0x19, offset 0x640
+ 0x640: 0x16a, 0x641: 0x9b, 0x642: 0x16b, 0x643: 0x16c, 0x644: 0x73, 0x645: 0x74, 0x646: 0x16d, 0x647: 0x16e,
+ 0x648: 0x75, 0x649: 0x16f, 0x64a: 0xba, 0x64b: 0xba, 0x64c: 0x9b, 0x64d: 0x9b, 0x64e: 0x9b, 0x64f: 0x9b,
+ 0x650: 0x9b, 0x651: 0x9b, 0x652: 0x9b, 0x653: 0x9b, 0x654: 0x9b, 0x655: 0x9b, 0x656: 0x9b, 0x657: 0x9b,
+ 0x658: 0x9b, 0x659: 0x9b, 0x65a: 0x9b, 0x65b: 0x170, 0x65c: 0x9b, 0x65d: 0x171, 0x65e: 0x9b, 0x65f: 0x172,
+ 0x660: 0x173, 0x661: 0x174, 0x662: 0x175, 0x663: 0xba, 0x664: 0x176, 0x665: 0x177, 0x666: 0x178, 0x667: 0x179,
+ 0x668: 0xba, 0x669: 0xba, 0x66a: 0xba, 0x66b: 0xba, 0x66c: 0xba, 0x66d: 0xba, 0x66e: 0xba, 0x66f: 0xba,
+ 0x670: 0xba, 0x671: 0xba, 0x672: 0xba, 0x673: 0xba, 0x674: 0xba, 0x675: 0xba, 0x676: 0xba, 0x677: 0xba,
+ 0x678: 0xba, 0x679: 0xba, 0x67a: 0xba, 0x67b: 0xba, 0x67c: 0xba, 0x67d: 0xba, 0x67e: 0xba, 0x67f: 0xba,
+ // Block 0x1a, offset 0x680
+ 0x680: 0x9f, 0x681: 0x9f, 0x682: 0x9f, 0x683: 0x9f, 0x684: 0x9f, 0x685: 0x9f, 0x686: 0x9f, 0x687: 0x9f,
+ 0x688: 0x9f, 0x689: 0x9f, 0x68a: 0x9f, 0x68b: 0x9f, 0x68c: 0x9f, 0x68d: 0x9f, 0x68e: 0x9f, 0x68f: 0x9f,
+ 0x690: 0x9f, 0x691: 0x9f, 0x692: 0x9f, 0x693: 0x9f, 0x694: 0x9f, 0x695: 0x9f, 0x696: 0x9f, 0x697: 0x9f,
+ 0x698: 0x9f, 0x699: 0x9f, 0x69a: 0x9f, 0x69b: 0x17a, 0x69c: 0x9f, 0x69d: 0x9f, 0x69e: 0x9f, 0x69f: 0x9f,
+ 0x6a0: 0x9f, 0x6a1: 0x9f, 0x6a2: 0x9f, 0x6a3: 0x9f, 0x6a4: 0x9f, 0x6a5: 0x9f, 0x6a6: 0x9f, 0x6a7: 0x9f,
+ 0x6a8: 0x9f, 0x6a9: 0x9f, 0x6aa: 0x9f, 0x6ab: 0x9f, 0x6ac: 0x9f, 0x6ad: 0x9f, 0x6ae: 0x9f, 0x6af: 0x9f,
+ 0x6b0: 0x9f, 0x6b1: 0x9f, 0x6b2: 0x9f, 0x6b3: 0x9f, 0x6b4: 0x9f, 0x6b5: 0x9f, 0x6b6: 0x9f, 0x6b7: 0x9f,
+ 0x6b8: 0x9f, 0x6b9: 0x9f, 0x6ba: 0x9f, 0x6bb: 0x9f, 0x6bc: 0x9f, 0x6bd: 0x9f, 0x6be: 0x9f, 0x6bf: 0x9f,
+ // Block 0x1b, offset 0x6c0
+ 0x6c0: 0x9f, 0x6c1: 0x9f, 0x6c2: 0x9f, 0x6c3: 0x9f, 0x6c4: 0x9f, 0x6c5: 0x9f, 0x6c6: 0x9f, 0x6c7: 0x9f,
+ 0x6c8: 0x9f, 0x6c9: 0x9f, 0x6ca: 0x9f, 0x6cb: 0x9f, 0x6cc: 0x9f, 0x6cd: 0x9f, 0x6ce: 0x9f, 0x6cf: 0x9f,
+ 0x6d0: 0x9f, 0x6d1: 0x9f, 0x6d2: 0x9f, 0x6d3: 0x9f, 0x6d4: 0x9f, 0x6d5: 0x9f, 0x6d6: 0x9f, 0x6d7: 0x9f,
+ 0x6d8: 0x9f, 0x6d9: 0x9f, 0x6da: 0x9f, 0x6db: 0x9f, 0x6dc: 0x17b, 0x6dd: 0x9f, 0x6de: 0x9f, 0x6df: 0x9f,
+ 0x6e0: 0x17c, 0x6e1: 0x9f, 0x6e2: 0x9f, 0x6e3: 0x9f, 0x6e4: 0x9f, 0x6e5: 0x9f, 0x6e6: 0x9f, 0x6e7: 0x9f,
+ 0x6e8: 0x9f, 0x6e9: 0x9f, 0x6ea: 0x9f, 0x6eb: 0x9f, 0x6ec: 0x9f, 0x6ed: 0x9f, 0x6ee: 0x9f, 0x6ef: 0x9f,
+ 0x6f0: 0x9f, 0x6f1: 0x9f, 0x6f2: 0x9f, 0x6f3: 0x9f, 0x6f4: 0x9f, 0x6f5: 0x9f, 0x6f6: 0x9f, 0x6f7: 0x9f,
+ 0x6f8: 0x9f, 0x6f9: 0x9f, 0x6fa: 0x9f, 0x6fb: 0x9f, 0x6fc: 0x9f, 0x6fd: 0x9f, 0x6fe: 0x9f, 0x6ff: 0x9f,
+ // Block 0x1c, offset 0x700
+ 0x700: 0x9f, 0x701: 0x9f, 0x702: 0x9f, 0x703: 0x9f, 0x704: 0x9f, 0x705: 0x9f, 0x706: 0x9f, 0x707: 0x9f,
+ 0x708: 0x9f, 0x709: 0x9f, 0x70a: 0x9f, 0x70b: 0x9f, 0x70c: 0x9f, 0x70d: 0x9f, 0x70e: 0x9f, 0x70f: 0x9f,
+ 0x710: 0x9f, 0x711: 0x9f, 0x712: 0x9f, 0x713: 0x9f, 0x714: 0x9f, 0x715: 0x9f, 0x716: 0x9f, 0x717: 0x9f,
+ 0x718: 0x9f, 0x719: 0x9f, 0x71a: 0x9f, 0x71b: 0x9f, 0x71c: 0x9f, 0x71d: 0x9f, 0x71e: 0x9f, 0x71f: 0x9f,
+ 0x720: 0x9f, 0x721: 0x9f, 0x722: 0x9f, 0x723: 0x9f, 0x724: 0x9f, 0x725: 0x9f, 0x726: 0x9f, 0x727: 0x9f,
+ 0x728: 0x9f, 0x729: 0x9f, 0x72a: 0x9f, 0x72b: 0x9f, 0x72c: 0x9f, 0x72d: 0x9f, 0x72e: 0x9f, 0x72f: 0x9f,
+ 0x730: 0x9f, 0x731: 0x9f, 0x732: 0x9f, 0x733: 0x9f, 0x734: 0x9f, 0x735: 0x9f, 0x736: 0x9f, 0x737: 0x9f,
+ 0x738: 0x9f, 0x739: 0x9f, 0x73a: 0x17d, 0x73b: 0x9f, 0x73c: 0x9f, 0x73d: 0x9f, 0x73e: 0x9f, 0x73f: 0x9f,
+ // Block 0x1d, offset 0x740
+ 0x740: 0x9f, 0x741: 0x9f, 0x742: 0x9f, 0x743: 0x9f, 0x744: 0x9f, 0x745: 0x9f, 0x746: 0x9f, 0x747: 0x9f,
+ 0x748: 0x9f, 0x749: 0x9f, 0x74a: 0x9f, 0x74b: 0x9f, 0x74c: 0x9f, 0x74d: 0x9f, 0x74e: 0x9f, 0x74f: 0x9f,
+ 0x750: 0x9f, 0x751: 0x9f, 0x752: 0x9f, 0x753: 0x9f, 0x754: 0x9f, 0x755: 0x9f, 0x756: 0x9f, 0x757: 0x9f,
+ 0x758: 0x9f, 0x759: 0x9f, 0x75a: 0x9f, 0x75b: 0x9f, 0x75c: 0x9f, 0x75d: 0x9f, 0x75e: 0x9f, 0x75f: 0x9f,
+ 0x760: 0x9f, 0x761: 0x9f, 0x762: 0x9f, 0x763: 0x9f, 0x764: 0x9f, 0x765: 0x9f, 0x766: 0x9f, 0x767: 0x9f,
+ 0x768: 0x9f, 0x769: 0x9f, 0x76a: 0x9f, 0x76b: 0x9f, 0x76c: 0x9f, 0x76d: 0x9f, 0x76e: 0x9f, 0x76f: 0x17e,
+ 0x770: 0xba, 0x771: 0xba, 0x772: 0xba, 0x773: 0xba, 0x774: 0xba, 0x775: 0xba, 0x776: 0xba, 0x777: 0xba,
+ 0x778: 0xba, 0x779: 0xba, 0x77a: 0xba, 0x77b: 0xba, 0x77c: 0xba, 0x77d: 0xba, 0x77e: 0xba, 0x77f: 0xba,
+ // Block 0x1e, offset 0x780
+ 0x780: 0xba, 0x781: 0xba, 0x782: 0xba, 0x783: 0xba, 0x784: 0xba, 0x785: 0xba, 0x786: 0xba, 0x787: 0xba,
+ 0x788: 0xba, 0x789: 0xba, 0x78a: 0xba, 0x78b: 0xba, 0x78c: 0xba, 0x78d: 0xba, 0x78e: 0xba, 0x78f: 0xba,
+ 0x790: 0xba, 0x791: 0xba, 0x792: 0xba, 0x793: 0xba, 0x794: 0xba, 0x795: 0xba, 0x796: 0xba, 0x797: 0xba,
+ 0x798: 0xba, 0x799: 0xba, 0x79a: 0xba, 0x79b: 0xba, 0x79c: 0xba, 0x79d: 0xba, 0x79e: 0xba, 0x79f: 0xba,
+ 0x7a0: 0x76, 0x7a1: 0x77, 0x7a2: 0x78, 0x7a3: 0x17f, 0x7a4: 0x79, 0x7a5: 0x7a, 0x7a6: 0x180, 0x7a7: 0x7b,
+ 0x7a8: 0x7c, 0x7a9: 0xba, 0x7aa: 0xba, 0x7ab: 0xba, 0x7ac: 0xba, 0x7ad: 0xba, 0x7ae: 0xba, 0x7af: 0xba,
+ 0x7b0: 0xba, 0x7b1: 0xba, 0x7b2: 0xba, 0x7b3: 0xba, 0x7b4: 0xba, 0x7b5: 0xba, 0x7b6: 0xba, 0x7b7: 0xba,
+ 0x7b8: 0xba, 0x7b9: 0xba, 0x7ba: 0xba, 0x7bb: 0xba, 0x7bc: 0xba, 0x7bd: 0xba, 0x7be: 0xba, 0x7bf: 0xba,
+ // Block 0x1f, offset 0x7c0
+ 0x7d0: 0x0d, 0x7d1: 0x0e, 0x7d2: 0x0f, 0x7d3: 0x10, 0x7d4: 0x11, 0x7d5: 0x0b, 0x7d6: 0x12, 0x7d7: 0x07,
+ 0x7d8: 0x13, 0x7d9: 0x0b, 0x7da: 0x0b, 0x7db: 0x14, 0x7dc: 0x0b, 0x7dd: 0x15, 0x7de: 0x16, 0x7df: 0x17,
+ 0x7e0: 0x07, 0x7e1: 0x07, 0x7e2: 0x07, 0x7e3: 0x07, 0x7e4: 0x07, 0x7e5: 0x07, 0x7e6: 0x07, 0x7e7: 0x07,
+ 0x7e8: 0x07, 0x7e9: 0x07, 0x7ea: 0x18, 0x7eb: 0x19, 0x7ec: 0x1a, 0x7ed: 0x07, 0x7ee: 0x1b, 0x7ef: 0x1c,
+ 0x7f0: 0x0b, 0x7f1: 0x0b, 0x7f2: 0x0b, 0x7f3: 0x0b, 0x7f4: 0x0b, 0x7f5: 0x0b, 0x7f6: 0x0b, 0x7f7: 0x0b,
+ 0x7f8: 0x0b, 0x7f9: 0x0b, 0x7fa: 0x0b, 0x7fb: 0x0b, 0x7fc: 0x0b, 0x7fd: 0x0b, 0x7fe: 0x0b, 0x7ff: 0x0b,
+ // Block 0x20, offset 0x800
+ 0x800: 0x0b, 0x801: 0x0b, 0x802: 0x0b, 0x803: 0x0b, 0x804: 0x0b, 0x805: 0x0b, 0x806: 0x0b, 0x807: 0x0b,
+ 0x808: 0x0b, 0x809: 0x0b, 0x80a: 0x0b, 0x80b: 0x0b, 0x80c: 0x0b, 0x80d: 0x0b, 0x80e: 0x0b, 0x80f: 0x0b,
+ 0x810: 0x0b, 0x811: 0x0b, 0x812: 0x0b, 0x813: 0x0b, 0x814: 0x0b, 0x815: 0x0b, 0x816: 0x0b, 0x817: 0x0b,
+ 0x818: 0x0b, 0x819: 0x0b, 0x81a: 0x0b, 0x81b: 0x0b, 0x81c: 0x0b, 0x81d: 0x0b, 0x81e: 0x0b, 0x81f: 0x0b,
+ 0x820: 0x0b, 0x821: 0x0b, 0x822: 0x0b, 0x823: 0x0b, 0x824: 0x0b, 0x825: 0x0b, 0x826: 0x0b, 0x827: 0x0b,
+ 0x828: 0x0b, 0x829: 0x0b, 0x82a: 0x0b, 0x82b: 0x0b, 0x82c: 0x0b, 0x82d: 0x0b, 0x82e: 0x0b, 0x82f: 0x0b,
+ 0x830: 0x0b, 0x831: 0x0b, 0x832: 0x0b, 0x833: 0x0b, 0x834: 0x0b, 0x835: 0x0b, 0x836: 0x0b, 0x837: 0x0b,
+ 0x838: 0x0b, 0x839: 0x0b, 0x83a: 0x0b, 0x83b: 0x0b, 0x83c: 0x0b, 0x83d: 0x0b, 0x83e: 0x0b, 0x83f: 0x0b,
+ // Block 0x21, offset 0x840
+ 0x840: 0x181, 0x841: 0x182, 0x842: 0xba, 0x843: 0xba, 0x844: 0x183, 0x845: 0x183, 0x846: 0x183, 0x847: 0x184,
+ 0x848: 0xba, 0x849: 0xba, 0x84a: 0xba, 0x84b: 0xba, 0x84c: 0xba, 0x84d: 0xba, 0x84e: 0xba, 0x84f: 0xba,
+ 0x850: 0xba, 0x851: 0xba, 0x852: 0xba, 0x853: 0xba, 0x854: 0xba, 0x855: 0xba, 0x856: 0xba, 0x857: 0xba,
+ 0x858: 0xba, 0x859: 0xba, 0x85a: 0xba, 0x85b: 0xba, 0x85c: 0xba, 0x85d: 0xba, 0x85e: 0xba, 0x85f: 0xba,
+ 0x860: 0xba, 0x861: 0xba, 0x862: 0xba, 0x863: 0xba, 0x864: 0xba, 0x865: 0xba, 0x866: 0xba, 0x867: 0xba,
+ 0x868: 0xba, 0x869: 0xba, 0x86a: 0xba, 0x86b: 0xba, 0x86c: 0xba, 0x86d: 0xba, 0x86e: 0xba, 0x86f: 0xba,
+ 0x870: 0xba, 0x871: 0xba, 0x872: 0xba, 0x873: 0xba, 0x874: 0xba, 0x875: 0xba, 0x876: 0xba, 0x877: 0xba,
+ 0x878: 0xba, 0x879: 0xba, 0x87a: 0xba, 0x87b: 0xba, 0x87c: 0xba, 0x87d: 0xba, 0x87e: 0xba, 0x87f: 0xba,
+ // Block 0x22, offset 0x880
+ 0x880: 0x0b, 0x881: 0x0b, 0x882: 0x0b, 0x883: 0x0b, 0x884: 0x0b, 0x885: 0x0b, 0x886: 0x0b, 0x887: 0x0b,
+ 0x888: 0x0b, 0x889: 0x0b, 0x88a: 0x0b, 0x88b: 0x0b, 0x88c: 0x0b, 0x88d: 0x0b, 0x88e: 0x0b, 0x88f: 0x0b,
+ 0x890: 0x0b, 0x891: 0x0b, 0x892: 0x0b, 0x893: 0x0b, 0x894: 0x0b, 0x895: 0x0b, 0x896: 0x0b, 0x897: 0x0b,
+ 0x898: 0x0b, 0x899: 0x0b, 0x89a: 0x0b, 0x89b: 0x0b, 0x89c: 0x0b, 0x89d: 0x0b, 0x89e: 0x0b, 0x89f: 0x0b,
+ 0x8a0: 0x1f, 0x8a1: 0x0b, 0x8a2: 0x0b, 0x8a3: 0x0b, 0x8a4: 0x0b, 0x8a5: 0x0b, 0x8a6: 0x0b, 0x8a7: 0x0b,
+ 0x8a8: 0x0b, 0x8a9: 0x0b, 0x8aa: 0x0b, 0x8ab: 0x0b, 0x8ac: 0x0b, 0x8ad: 0x0b, 0x8ae: 0x0b, 0x8af: 0x0b,
+ 0x8b0: 0x0b, 0x8b1: 0x0b, 0x8b2: 0x0b, 0x8b3: 0x0b, 0x8b4: 0x0b, 0x8b5: 0x0b, 0x8b6: 0x0b, 0x8b7: 0x0b,
+ 0x8b8: 0x0b, 0x8b9: 0x0b, 0x8ba: 0x0b, 0x8bb: 0x0b, 0x8bc: 0x0b, 0x8bd: 0x0b, 0x8be: 0x0b, 0x8bf: 0x0b,
+ // Block 0x23, offset 0x8c0
+ 0x8c0: 0x0b, 0x8c1: 0x0b, 0x8c2: 0x0b, 0x8c3: 0x0b, 0x8c4: 0x0b, 0x8c5: 0x0b, 0x8c6: 0x0b, 0x8c7: 0x0b,
+ 0x8c8: 0x0b, 0x8c9: 0x0b, 0x8ca: 0x0b, 0x8cb: 0x0b, 0x8cc: 0x0b, 0x8cd: 0x0b, 0x8ce: 0x0b, 0x8cf: 0x0b,
+}
+
+// idnaSparseOffset: 264 entries, 528 bytes
+var idnaSparseOffset = []uint16{0x0, 0x8, 0x19, 0x25, 0x27, 0x2c, 0x34, 0x3f, 0x4b, 0x4f, 0x5e, 0x63, 0x6b, 0x77, 0x85, 0x8a, 0x93, 0xa3, 0xb1, 0xbd, 0xc9, 0xda, 0xe4, 0xeb, 0xf8, 0x109, 0x110, 0x11b, 0x12a, 0x138, 0x142, 0x144, 0x149, 0x14c, 0x14f, 0x151, 0x15d, 0x168, 0x170, 0x176, 0x17c, 0x181, 0x186, 0x189, 0x18d, 0x193, 0x198, 0x1a4, 0x1ae, 0x1b4, 0x1c5, 0x1cf, 0x1d2, 0x1da, 0x1dd, 0x1ea, 0x1f2, 0x1f6, 0x1fd, 0x205, 0x215, 0x221, 0x223, 0x22d, 0x239, 0x245, 0x251, 0x259, 0x25e, 0x268, 0x279, 0x27d, 0x288, 0x28c, 0x295, 0x29d, 0x2a3, 0x2a8, 0x2ab, 0x2af, 0x2b5, 0x2b9, 0x2bd, 0x2c3, 0x2ca, 0x2d0, 0x2d8, 0x2df, 0x2ea, 0x2f4, 0x2f8, 0x2fb, 0x301, 0x305, 0x307, 0x30a, 0x30c, 0x30f, 0x319, 0x31c, 0x32b, 0x32f, 0x334, 0x337, 0x33b, 0x340, 0x345, 0x34b, 0x351, 0x360, 0x366, 0x36a, 0x379, 0x37e, 0x386, 0x390, 0x39b, 0x3a3, 0x3b4, 0x3bd, 0x3cd, 0x3da, 0x3e4, 0x3e9, 0x3f6, 0x3fa, 0x3ff, 0x401, 0x405, 0x407, 0x40b, 0x414, 0x41a, 0x41e, 0x42e, 0x438, 0x43d, 0x440, 0x446, 0x44d, 0x452, 0x456, 0x45c, 0x461, 0x46a, 0x46f, 0x475, 0x47c, 0x483, 0x48a, 0x48e, 0x493, 0x496, 0x49b, 0x4a7, 0x4ad, 0x4b2, 0x4b9, 0x4c1, 0x4c6, 0x4ca, 0x4da, 0x4e1, 0x4e5, 0x4e9, 0x4f0, 0x4f2, 0x4f5, 0x4f8, 0x4fc, 0x500, 0x506, 0x50f, 0x51b, 0x522, 0x52b, 0x533, 0x53a, 0x548, 0x555, 0x562, 0x56b, 0x56f, 0x57d, 0x585, 0x590, 0x599, 0x59f, 0x5a7, 0x5b0, 0x5ba, 0x5bd, 0x5c9, 0x5cc, 0x5d1, 0x5de, 0x5e7, 0x5f3, 0x5f6, 0x600, 0x609, 0x615, 0x622, 0x62a, 0x62d, 0x632, 0x635, 0x638, 0x63b, 0x642, 0x649, 0x64d, 0x658, 0x65b, 0x661, 0x666, 0x66a, 0x66d, 0x670, 0x673, 0x676, 0x679, 0x67e, 0x688, 0x68b, 0x68f, 0x69e, 0x6aa, 0x6ae, 0x6b3, 0x6b8, 0x6bc, 0x6c1, 0x6ca, 0x6d5, 0x6db, 0x6e3, 0x6e7, 0x6eb, 0x6f1, 0x6f7, 0x6fc, 0x6ff, 0x70f, 0x716, 0x719, 0x71c, 0x720, 0x726, 0x72b, 0x730, 0x735, 0x738, 0x73d, 0x740, 0x743, 0x747, 0x74b, 0x74e, 0x75e, 0x76f, 0x774, 0x776, 0x778}
+
+// idnaSparseValues: 1915 entries, 7660 bytes
+var idnaSparseValues = [1915]valueRange{
+ // Block 0x0, offset 0x0
+ {value: 0x0000, lo: 0x07},
+ {value: 0xe105, lo: 0x80, hi: 0x96},
+ {value: 0x0018, lo: 0x97, hi: 0x97},
+ {value: 0xe105, lo: 0x98, hi: 0x9e},
+ {value: 0x001f, lo: 0x9f, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xb6},
+ {value: 0x0018, lo: 0xb7, hi: 0xb7},
+ {value: 0x0008, lo: 0xb8, hi: 0xbf},
+ // Block 0x1, offset 0x8
+ {value: 0x0000, lo: 0x10},
+ {value: 0x0008, lo: 0x80, hi: 0x80},
+ {value: 0xe01d, lo: 0x81, hi: 0x81},
+ {value: 0x0008, lo: 0x82, hi: 0x82},
+ {value: 0x0335, lo: 0x83, hi: 0x83},
+ {value: 0x034d, lo: 0x84, hi: 0x84},
+ {value: 0x0365, lo: 0x85, hi: 0x85},
+ {value: 0xe00d, lo: 0x86, hi: 0x86},
+ {value: 0x0008, lo: 0x87, hi: 0x87},
+ {value: 0xe00d, lo: 0x88, hi: 0x88},
+ {value: 0x0008, lo: 0x89, hi: 0x89},
+ {value: 0xe00d, lo: 0x8a, hi: 0x8a},
+ {value: 0x0008, lo: 0x8b, hi: 0x8b},
+ {value: 0xe00d, lo: 0x8c, hi: 0x8c},
+ {value: 0x0008, lo: 0x8d, hi: 0x8d},
+ {value: 0xe00d, lo: 0x8e, hi: 0x8e},
+ {value: 0x0008, lo: 0x8f, hi: 0xbf},
+ // Block 0x2, offset 0x19
+ {value: 0x0000, lo: 0x0b},
+ {value: 0x0008, lo: 0x80, hi: 0xaf},
+ {value: 0x0249, lo: 0xb0, hi: 0xb0},
+ {value: 0x037d, lo: 0xb1, hi: 0xb1},
+ {value: 0x0259, lo: 0xb2, hi: 0xb2},
+ {value: 0x0269, lo: 0xb3, hi: 0xb3},
+ {value: 0x034d, lo: 0xb4, hi: 0xb4},
+ {value: 0x0395, lo: 0xb5, hi: 0xb5},
+ {value: 0xe1bd, lo: 0xb6, hi: 0xb6},
+ {value: 0x0279, lo: 0xb7, hi: 0xb7},
+ {value: 0x0289, lo: 0xb8, hi: 0xb8},
+ {value: 0x0008, lo: 0xb9, hi: 0xbf},
+ // Block 0x3, offset 0x25
+ {value: 0x0000, lo: 0x01},
+ {value: 0x3308, lo: 0x80, hi: 0xbf},
+ // Block 0x4, offset 0x27
+ {value: 0x0000, lo: 0x04},
+ {value: 0x03f5, lo: 0x80, hi: 0x8f},
+ {value: 0xe105, lo: 0x90, hi: 0x9f},
+ {value: 0x049d, lo: 0xa0, hi: 0xaf},
+ {value: 0x0008, lo: 0xb0, hi: 0xbf},
+ // Block 0x5, offset 0x2c
+ {value: 0x0000, lo: 0x07},
+ {value: 0xe185, lo: 0x80, hi: 0x8f},
+ {value: 0x0545, lo: 0x90, hi: 0x96},
+ {value: 0x0040, lo: 0x97, hi: 0x98},
+ {value: 0x0008, lo: 0x99, hi: 0x99},
+ {value: 0x0018, lo: 0x9a, hi: 0x9f},
+ {value: 0x0040, lo: 0xa0, hi: 0xa0},
+ {value: 0x0008, lo: 0xa1, hi: 0xbf},
+ // Block 0x6, offset 0x34
+ {value: 0x0000, lo: 0x0a},
+ {value: 0x0008, lo: 0x80, hi: 0x86},
+ {value: 0x0401, lo: 0x87, hi: 0x87},
+ {value: 0x0040, lo: 0x88, hi: 0x88},
+ {value: 0x0018, lo: 0x89, hi: 0x8a},
+ {value: 0x0040, lo: 0x8b, hi: 0x8c},
+ {value: 0x0018, lo: 0x8d, hi: 0x8f},
+ {value: 0x0040, lo: 0x90, hi: 0x90},
+ {value: 0x3308, lo: 0x91, hi: 0xbd},
+ {value: 0x0818, lo: 0xbe, hi: 0xbe},
+ {value: 0x3308, lo: 0xbf, hi: 0xbf},
+ // Block 0x7, offset 0x3f
+ {value: 0x0000, lo: 0x0b},
+ {value: 0x0818, lo: 0x80, hi: 0x80},
+ {value: 0x3308, lo: 0x81, hi: 0x82},
+ {value: 0x0818, lo: 0x83, hi: 0x83},
+ {value: 0x3308, lo: 0x84, hi: 0x85},
+ {value: 0x0818, lo: 0x86, hi: 0x86},
+ {value: 0x3308, lo: 0x87, hi: 0x87},
+ {value: 0x0040, lo: 0x88, hi: 0x8f},
+ {value: 0x0808, lo: 0x90, hi: 0xaa},
+ {value: 0x0040, lo: 0xab, hi: 0xaf},
+ {value: 0x0808, lo: 0xb0, hi: 0xb4},
+ {value: 0x0040, lo: 0xb5, hi: 0xbf},
+ // Block 0x8, offset 0x4b
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0a08, lo: 0x80, hi: 0x87},
+ {value: 0x0c08, lo: 0x88, hi: 0x99},
+ {value: 0x0a08, lo: 0x9a, hi: 0xbf},
+ // Block 0x9, offset 0x4f
+ {value: 0x0000, lo: 0x0e},
+ {value: 0x3308, lo: 0x80, hi: 0x8a},
+ {value: 0x0040, lo: 0x8b, hi: 0x8c},
+ {value: 0x0c08, lo: 0x8d, hi: 0x8d},
+ {value: 0x0a08, lo: 0x8e, hi: 0x98},
+ {value: 0x0c08, lo: 0x99, hi: 0x9b},
+ {value: 0x0a08, lo: 0x9c, hi: 0xaa},
+ {value: 0x0c08, lo: 0xab, hi: 0xac},
+ {value: 0x0a08, lo: 0xad, hi: 0xb0},
+ {value: 0x0c08, lo: 0xb1, hi: 0xb1},
+ {value: 0x0a08, lo: 0xb2, hi: 0xb2},
+ {value: 0x0c08, lo: 0xb3, hi: 0xb4},
+ {value: 0x0a08, lo: 0xb5, hi: 0xb7},
+ {value: 0x0c08, lo: 0xb8, hi: 0xb9},
+ {value: 0x0a08, lo: 0xba, hi: 0xbf},
+ // Block 0xa, offset 0x5e
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0808, lo: 0x80, hi: 0xa5},
+ {value: 0x3308, lo: 0xa6, hi: 0xb0},
+ {value: 0x0808, lo: 0xb1, hi: 0xb1},
+ {value: 0x0040, lo: 0xb2, hi: 0xbf},
+ // Block 0xb, offset 0x63
+ {value: 0x0000, lo: 0x07},
+ {value: 0x0808, lo: 0x80, hi: 0x89},
+ {value: 0x0a08, lo: 0x8a, hi: 0xaa},
+ {value: 0x3308, lo: 0xab, hi: 0xb3},
+ {value: 0x0808, lo: 0xb4, hi: 0xb5},
+ {value: 0x0018, lo: 0xb6, hi: 0xb9},
+ {value: 0x0818, lo: 0xba, hi: 0xba},
+ {value: 0x0040, lo: 0xbb, hi: 0xbf},
+ // Block 0xc, offset 0x6b
+ {value: 0x0000, lo: 0x0b},
+ {value: 0x0808, lo: 0x80, hi: 0x95},
+ {value: 0x3308, lo: 0x96, hi: 0x99},
+ {value: 0x0808, lo: 0x9a, hi: 0x9a},
+ {value: 0x3308, lo: 0x9b, hi: 0xa3},
+ {value: 0x0808, lo: 0xa4, hi: 0xa4},
+ {value: 0x3308, lo: 0xa5, hi: 0xa7},
+ {value: 0x0808, lo: 0xa8, hi: 0xa8},
+ {value: 0x3308, lo: 0xa9, hi: 0xad},
+ {value: 0x0040, lo: 0xae, hi: 0xaf},
+ {value: 0x0818, lo: 0xb0, hi: 0xbe},
+ {value: 0x0040, lo: 0xbf, hi: 0xbf},
+ // Block 0xd, offset 0x77
+ {value: 0x0000, lo: 0x0d},
+ {value: 0x0040, lo: 0x80, hi: 0x9f},
+ {value: 0x0a08, lo: 0xa0, hi: 0xa9},
+ {value: 0x0c08, lo: 0xaa, hi: 0xac},
+ {value: 0x0808, lo: 0xad, hi: 0xad},
+ {value: 0x0c08, lo: 0xae, hi: 0xae},
+ {value: 0x0a08, lo: 0xaf, hi: 0xb0},
+ {value: 0x0c08, lo: 0xb1, hi: 0xb2},
+ {value: 0x0a08, lo: 0xb3, hi: 0xb4},
+ {value: 0x0040, lo: 0xb5, hi: 0xb5},
+ {value: 0x0a08, lo: 0xb6, hi: 0xb8},
+ {value: 0x0c08, lo: 0xb9, hi: 0xb9},
+ {value: 0x0a08, lo: 0xba, hi: 0xbd},
+ {value: 0x0040, lo: 0xbe, hi: 0xbf},
+ // Block 0xe, offset 0x85
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0040, lo: 0x80, hi: 0x93},
+ {value: 0x3308, lo: 0x94, hi: 0xa1},
+ {value: 0x0840, lo: 0xa2, hi: 0xa2},
+ {value: 0x3308, lo: 0xa3, hi: 0xbf},
+ // Block 0xf, offset 0x8a
+ {value: 0x0000, lo: 0x08},
+ {value: 0x3308, lo: 0x80, hi: 0x82},
+ {value: 0x3008, lo: 0x83, hi: 0x83},
+ {value: 0x0008, lo: 0x84, hi: 0xb9},
+ {value: 0x3308, lo: 0xba, hi: 0xba},
+ {value: 0x3008, lo: 0xbb, hi: 0xbb},
+ {value: 0x3308, lo: 0xbc, hi: 0xbc},
+ {value: 0x0008, lo: 0xbd, hi: 0xbd},
+ {value: 0x3008, lo: 0xbe, hi: 0xbf},
+ // Block 0x10, offset 0x93
+ {value: 0x0000, lo: 0x0f},
+ {value: 0x3308, lo: 0x80, hi: 0x80},
+ {value: 0x3008, lo: 0x81, hi: 0x82},
+ {value: 0x0040, lo: 0x83, hi: 0x85},
+ {value: 0x3008, lo: 0x86, hi: 0x88},
+ {value: 0x0040, lo: 0x89, hi: 0x89},
+ {value: 0x3008, lo: 0x8a, hi: 0x8c},
+ {value: 0x3b08, lo: 0x8d, hi: 0x8d},
+ {value: 0x0040, lo: 0x8e, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x90},
+ {value: 0x0040, lo: 0x91, hi: 0x96},
+ {value: 0x3008, lo: 0x97, hi: 0x97},
+ {value: 0x0040, lo: 0x98, hi: 0xa5},
+ {value: 0x0008, lo: 0xa6, hi: 0xaf},
+ {value: 0x0018, lo: 0xb0, hi: 0xba},
+ {value: 0x0040, lo: 0xbb, hi: 0xbf},
+ // Block 0x11, offset 0xa3
+ {value: 0x0000, lo: 0x0d},
+ {value: 0x3308, lo: 0x80, hi: 0x80},
+ {value: 0x3008, lo: 0x81, hi: 0x83},
+ {value: 0x0040, lo: 0x84, hi: 0x84},
+ {value: 0x0008, lo: 0x85, hi: 0x8c},
+ {value: 0x0040, lo: 0x8d, hi: 0x8d},
+ {value: 0x0008, lo: 0x8e, hi: 0x90},
+ {value: 0x0040, lo: 0x91, hi: 0x91},
+ {value: 0x0008, lo: 0x92, hi: 0xa8},
+ {value: 0x0040, lo: 0xa9, hi: 0xa9},
+ {value: 0x0008, lo: 0xaa, hi: 0xb9},
+ {value: 0x0040, lo: 0xba, hi: 0xbc},
+ {value: 0x0008, lo: 0xbd, hi: 0xbd},
+ {value: 0x3308, lo: 0xbe, hi: 0xbf},
+ // Block 0x12, offset 0xb1
+ {value: 0x0000, lo: 0x0b},
+ {value: 0x3308, lo: 0x80, hi: 0x81},
+ {value: 0x3008, lo: 0x82, hi: 0x83},
+ {value: 0x0040, lo: 0x84, hi: 0x84},
+ {value: 0x0008, lo: 0x85, hi: 0x8c},
+ {value: 0x0040, lo: 0x8d, hi: 0x8d},
+ {value: 0x0008, lo: 0x8e, hi: 0x90},
+ {value: 0x0040, lo: 0x91, hi: 0x91},
+ {value: 0x0008, lo: 0x92, hi: 0xba},
+ {value: 0x3b08, lo: 0xbb, hi: 0xbc},
+ {value: 0x0008, lo: 0xbd, hi: 0xbd},
+ {value: 0x3008, lo: 0xbe, hi: 0xbf},
+ // Block 0x13, offset 0xbd
+ {value: 0x0000, lo: 0x0b},
+ {value: 0x0040, lo: 0x80, hi: 0x81},
+ {value: 0x3008, lo: 0x82, hi: 0x83},
+ {value: 0x0040, lo: 0x84, hi: 0x84},
+ {value: 0x0008, lo: 0x85, hi: 0x96},
+ {value: 0x0040, lo: 0x97, hi: 0x99},
+ {value: 0x0008, lo: 0x9a, hi: 0xb1},
+ {value: 0x0040, lo: 0xb2, hi: 0xb2},
+ {value: 0x0008, lo: 0xb3, hi: 0xbb},
+ {value: 0x0040, lo: 0xbc, hi: 0xbc},
+ {value: 0x0008, lo: 0xbd, hi: 0xbd},
+ {value: 0x0040, lo: 0xbe, hi: 0xbf},
+ // Block 0x14, offset 0xc9
+ {value: 0x0000, lo: 0x10},
+ {value: 0x0008, lo: 0x80, hi: 0x86},
+ {value: 0x0040, lo: 0x87, hi: 0x89},
+ {value: 0x3b08, lo: 0x8a, hi: 0x8a},
+ {value: 0x0040, lo: 0x8b, hi: 0x8e},
+ {value: 0x3008, lo: 0x8f, hi: 0x91},
+ {value: 0x3308, lo: 0x92, hi: 0x94},
+ {value: 0x0040, lo: 0x95, hi: 0x95},
+ {value: 0x3308, lo: 0x96, hi: 0x96},
+ {value: 0x0040, lo: 0x97, hi: 0x97},
+ {value: 0x3008, lo: 0x98, hi: 0x9f},
+ {value: 0x0040, lo: 0xa0, hi: 0xa5},
+ {value: 0x0008, lo: 0xa6, hi: 0xaf},
+ {value: 0x0040, lo: 0xb0, hi: 0xb1},
+ {value: 0x3008, lo: 0xb2, hi: 0xb3},
+ {value: 0x0018, lo: 0xb4, hi: 0xb4},
+ {value: 0x0040, lo: 0xb5, hi: 0xbf},
+ // Block 0x15, offset 0xda
+ {value: 0x0000, lo: 0x09},
+ {value: 0x0040, lo: 0x80, hi: 0x80},
+ {value: 0x0008, lo: 0x81, hi: 0xb0},
+ {value: 0x3308, lo: 0xb1, hi: 0xb1},
+ {value: 0x0008, lo: 0xb2, hi: 0xb2},
+ {value: 0x08f1, lo: 0xb3, hi: 0xb3},
+ {value: 0x3308, lo: 0xb4, hi: 0xb9},
+ {value: 0x3b08, lo: 0xba, hi: 0xba},
+ {value: 0x0040, lo: 0xbb, hi: 0xbe},
+ {value: 0x0018, lo: 0xbf, hi: 0xbf},
+ // Block 0x16, offset 0xe4
+ {value: 0x0000, lo: 0x06},
+ {value: 0x0008, lo: 0x80, hi: 0x86},
+ {value: 0x3308, lo: 0x87, hi: 0x8e},
+ {value: 0x0018, lo: 0x8f, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x99},
+ {value: 0x0018, lo: 0x9a, hi: 0x9b},
+ {value: 0x0040, lo: 0x9c, hi: 0xbf},
+ // Block 0x17, offset 0xeb
+ {value: 0x0000, lo: 0x0c},
+ {value: 0x0008, lo: 0x80, hi: 0x84},
+ {value: 0x0040, lo: 0x85, hi: 0x85},
+ {value: 0x0008, lo: 0x86, hi: 0x86},
+ {value: 0x0040, lo: 0x87, hi: 0x87},
+ {value: 0x3308, lo: 0x88, hi: 0x8d},
+ {value: 0x0040, lo: 0x8e, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x99},
+ {value: 0x0040, lo: 0x9a, hi: 0x9b},
+ {value: 0x0961, lo: 0x9c, hi: 0x9c},
+ {value: 0x0999, lo: 0x9d, hi: 0x9d},
+ {value: 0x0008, lo: 0x9e, hi: 0x9f},
+ {value: 0x0040, lo: 0xa0, hi: 0xbf},
+ // Block 0x18, offset 0xf8
+ {value: 0x0000, lo: 0x10},
+ {value: 0x0008, lo: 0x80, hi: 0x80},
+ {value: 0x0018, lo: 0x81, hi: 0x8a},
+ {value: 0x0008, lo: 0x8b, hi: 0x8b},
+ {value: 0xe03d, lo: 0x8c, hi: 0x8c},
+ {value: 0x0018, lo: 0x8d, hi: 0x97},
+ {value: 0x3308, lo: 0x98, hi: 0x99},
+ {value: 0x0018, lo: 0x9a, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xa9},
+ {value: 0x0018, lo: 0xaa, hi: 0xb4},
+ {value: 0x3308, lo: 0xb5, hi: 0xb5},
+ {value: 0x0018, lo: 0xb6, hi: 0xb6},
+ {value: 0x3308, lo: 0xb7, hi: 0xb7},
+ {value: 0x0018, lo: 0xb8, hi: 0xb8},
+ {value: 0x3308, lo: 0xb9, hi: 0xb9},
+ {value: 0x0018, lo: 0xba, hi: 0xbd},
+ {value: 0x3008, lo: 0xbe, hi: 0xbf},
+ // Block 0x19, offset 0x109
+ {value: 0x0000, lo: 0x06},
+ {value: 0x0018, lo: 0x80, hi: 0x85},
+ {value: 0x3308, lo: 0x86, hi: 0x86},
+ {value: 0x0018, lo: 0x87, hi: 0x8c},
+ {value: 0x0040, lo: 0x8d, hi: 0x8d},
+ {value: 0x0018, lo: 0x8e, hi: 0x9a},
+ {value: 0x0040, lo: 0x9b, hi: 0xbf},
+ // Block 0x1a, offset 0x110
+ {value: 0x0000, lo: 0x0a},
+ {value: 0x0008, lo: 0x80, hi: 0xaa},
+ {value: 0x3008, lo: 0xab, hi: 0xac},
+ {value: 0x3308, lo: 0xad, hi: 0xb0},
+ {value: 0x3008, lo: 0xb1, hi: 0xb1},
+ {value: 0x3308, lo: 0xb2, hi: 0xb7},
+ {value: 0x3008, lo: 0xb8, hi: 0xb8},
+ {value: 0x3b08, lo: 0xb9, hi: 0xba},
+ {value: 0x3008, lo: 0xbb, hi: 0xbc},
+ {value: 0x3308, lo: 0xbd, hi: 0xbe},
+ {value: 0x0008, lo: 0xbf, hi: 0xbf},
+ // Block 0x1b, offset 0x11b
+ {value: 0x0000, lo: 0x0e},
+ {value: 0x0008, lo: 0x80, hi: 0x89},
+ {value: 0x0018, lo: 0x8a, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x95},
+ {value: 0x3008, lo: 0x96, hi: 0x97},
+ {value: 0x3308, lo: 0x98, hi: 0x99},
+ {value: 0x0008, lo: 0x9a, hi: 0x9d},
+ {value: 0x3308, lo: 0x9e, hi: 0xa0},
+ {value: 0x0008, lo: 0xa1, hi: 0xa1},
+ {value: 0x3008, lo: 0xa2, hi: 0xa4},
+ {value: 0x0008, lo: 0xa5, hi: 0xa6},
+ {value: 0x3008, lo: 0xa7, hi: 0xad},
+ {value: 0x0008, lo: 0xae, hi: 0xb0},
+ {value: 0x3308, lo: 0xb1, hi: 0xb4},
+ {value: 0x0008, lo: 0xb5, hi: 0xbf},
+ // Block 0x1c, offset 0x12a
+ {value: 0x0000, lo: 0x0d},
+ {value: 0x0008, lo: 0x80, hi: 0x81},
+ {value: 0x3308, lo: 0x82, hi: 0x82},
+ {value: 0x3008, lo: 0x83, hi: 0x84},
+ {value: 0x3308, lo: 0x85, hi: 0x86},
+ {value: 0x3008, lo: 0x87, hi: 0x8c},
+ {value: 0x3308, lo: 0x8d, hi: 0x8d},
+ {value: 0x0008, lo: 0x8e, hi: 0x8e},
+ {value: 0x3008, lo: 0x8f, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x99},
+ {value: 0x3008, lo: 0x9a, hi: 0x9c},
+ {value: 0x3308, lo: 0x9d, hi: 0x9d},
+ {value: 0x0018, lo: 0x9e, hi: 0x9f},
+ {value: 0x0040, lo: 0xa0, hi: 0xbf},
+ // Block 0x1d, offset 0x138
+ {value: 0x0000, lo: 0x09},
+ {value: 0x0040, lo: 0x80, hi: 0x86},
+ {value: 0x055d, lo: 0x87, hi: 0x87},
+ {value: 0x0040, lo: 0x88, hi: 0x8c},
+ {value: 0x055d, lo: 0x8d, hi: 0x8d},
+ {value: 0x0040, lo: 0x8e, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0xba},
+ {value: 0x0018, lo: 0xbb, hi: 0xbb},
+ {value: 0xe105, lo: 0xbc, hi: 0xbc},
+ {value: 0x0008, lo: 0xbd, hi: 0xbf},
+ // Block 0x1e, offset 0x142
+ {value: 0x0000, lo: 0x01},
+ {value: 0x0018, lo: 0x80, hi: 0xbf},
+ // Block 0x1f, offset 0x144
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0018, lo: 0x80, hi: 0x9e},
+ {value: 0x0040, lo: 0x9f, hi: 0xa0},
+ {value: 0x2018, lo: 0xa1, hi: 0xb5},
+ {value: 0x0018, lo: 0xb6, hi: 0xbf},
+ // Block 0x20, offset 0x149
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0018, lo: 0x80, hi: 0xa7},
+ {value: 0x2018, lo: 0xa8, hi: 0xbf},
+ // Block 0x21, offset 0x14c
+ {value: 0x0000, lo: 0x02},
+ {value: 0x2018, lo: 0x80, hi: 0x82},
+ {value: 0x0018, lo: 0x83, hi: 0xbf},
+ // Block 0x22, offset 0x14f
+ {value: 0x0000, lo: 0x01},
+ {value: 0x0008, lo: 0x80, hi: 0xbf},
+ // Block 0x23, offset 0x151
+ {value: 0x0000, lo: 0x0b},
+ {value: 0x0008, lo: 0x80, hi: 0x88},
+ {value: 0x0040, lo: 0x89, hi: 0x89},
+ {value: 0x0008, lo: 0x8a, hi: 0x8d},
+ {value: 0x0040, lo: 0x8e, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x96},
+ {value: 0x0040, lo: 0x97, hi: 0x97},
+ {value: 0x0008, lo: 0x98, hi: 0x98},
+ {value: 0x0040, lo: 0x99, hi: 0x99},
+ {value: 0x0008, lo: 0x9a, hi: 0x9d},
+ {value: 0x0040, lo: 0x9e, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xbf},
+ // Block 0x24, offset 0x15d
+ {value: 0x0000, lo: 0x0a},
+ {value: 0x0008, lo: 0x80, hi: 0x88},
+ {value: 0x0040, lo: 0x89, hi: 0x89},
+ {value: 0x0008, lo: 0x8a, hi: 0x8d},
+ {value: 0x0040, lo: 0x8e, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0xb0},
+ {value: 0x0040, lo: 0xb1, hi: 0xb1},
+ {value: 0x0008, lo: 0xb2, hi: 0xb5},
+ {value: 0x0040, lo: 0xb6, hi: 0xb7},
+ {value: 0x0008, lo: 0xb8, hi: 0xbe},
+ {value: 0x0040, lo: 0xbf, hi: 0xbf},
+ // Block 0x25, offset 0x168
+ {value: 0x0000, lo: 0x07},
+ {value: 0x0008, lo: 0x80, hi: 0x80},
+ {value: 0x0040, lo: 0x81, hi: 0x81},
+ {value: 0x0008, lo: 0x82, hi: 0x85},
+ {value: 0x0040, lo: 0x86, hi: 0x87},
+ {value: 0x0008, lo: 0x88, hi: 0x96},
+ {value: 0x0040, lo: 0x97, hi: 0x97},
+ {value: 0x0008, lo: 0x98, hi: 0xbf},
+ // Block 0x26, offset 0x170
+ {value: 0x0000, lo: 0x05},
+ {value: 0x0008, lo: 0x80, hi: 0x90},
+ {value: 0x0040, lo: 0x91, hi: 0x91},
+ {value: 0x0008, lo: 0x92, hi: 0x95},
+ {value: 0x0040, lo: 0x96, hi: 0x97},
+ {value: 0x0008, lo: 0x98, hi: 0xbf},
+ // Block 0x27, offset 0x176
+ {value: 0x0000, lo: 0x05},
+ {value: 0x0008, lo: 0x80, hi: 0x9a},
+ {value: 0x0040, lo: 0x9b, hi: 0x9c},
+ {value: 0x3308, lo: 0x9d, hi: 0x9f},
+ {value: 0x0018, lo: 0xa0, hi: 0xbc},
+ {value: 0x0040, lo: 0xbd, hi: 0xbf},
+ // Block 0x28, offset 0x17c
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0008, lo: 0x80, hi: 0x8f},
+ {value: 0x0018, lo: 0x90, hi: 0x99},
+ {value: 0x0040, lo: 0x9a, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xbf},
+ // Block 0x29, offset 0x181
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0008, lo: 0x80, hi: 0xb5},
+ {value: 0x0040, lo: 0xb6, hi: 0xb7},
+ {value: 0xe045, lo: 0xb8, hi: 0xbd},
+ {value: 0x0040, lo: 0xbe, hi: 0xbf},
+ // Block 0x2a, offset 0x186
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0018, lo: 0x80, hi: 0x80},
+ {value: 0x0008, lo: 0x81, hi: 0xbf},
+ // Block 0x2b, offset 0x189
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0008, lo: 0x80, hi: 0xac},
+ {value: 0x0018, lo: 0xad, hi: 0xae},
+ {value: 0x0008, lo: 0xaf, hi: 0xbf},
+ // Block 0x2c, offset 0x18d
+ {value: 0x0000, lo: 0x05},
+ {value: 0x0040, lo: 0x80, hi: 0x80},
+ {value: 0x0008, lo: 0x81, hi: 0x9a},
+ {value: 0x0018, lo: 0x9b, hi: 0x9c},
+ {value: 0x0040, lo: 0x9d, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xbf},
+ // Block 0x2d, offset 0x193
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0008, lo: 0x80, hi: 0xaa},
+ {value: 0x0018, lo: 0xab, hi: 0xb0},
+ {value: 0x0008, lo: 0xb1, hi: 0xb8},
+ {value: 0x0040, lo: 0xb9, hi: 0xbf},
+ // Block 0x2e, offset 0x198
+ {value: 0x0000, lo: 0x0b},
+ {value: 0x0008, lo: 0x80, hi: 0x8c},
+ {value: 0x0040, lo: 0x8d, hi: 0x8d},
+ {value: 0x0008, lo: 0x8e, hi: 0x91},
+ {value: 0x3308, lo: 0x92, hi: 0x93},
+ {value: 0x3b08, lo: 0x94, hi: 0x94},
+ {value: 0x0040, lo: 0x95, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xb1},
+ {value: 0x3308, lo: 0xb2, hi: 0xb3},
+ {value: 0x3b08, lo: 0xb4, hi: 0xb4},
+ {value: 0x0018, lo: 0xb5, hi: 0xb6},
+ {value: 0x0040, lo: 0xb7, hi: 0xbf},
+ // Block 0x2f, offset 0x1a4
+ {value: 0x0000, lo: 0x09},
+ {value: 0x0008, lo: 0x80, hi: 0x91},
+ {value: 0x3308, lo: 0x92, hi: 0x93},
+ {value: 0x0040, lo: 0x94, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xac},
+ {value: 0x0040, lo: 0xad, hi: 0xad},
+ {value: 0x0008, lo: 0xae, hi: 0xb0},
+ {value: 0x0040, lo: 0xb1, hi: 0xb1},
+ {value: 0x3308, lo: 0xb2, hi: 0xb3},
+ {value: 0x0040, lo: 0xb4, hi: 0xbf},
+ // Block 0x30, offset 0x1ae
+ {value: 0x0000, lo: 0x05},
+ {value: 0x0008, lo: 0x80, hi: 0xb3},
+ {value: 0x3340, lo: 0xb4, hi: 0xb5},
+ {value: 0x3008, lo: 0xb6, hi: 0xb6},
+ {value: 0x3308, lo: 0xb7, hi: 0xbd},
+ {value: 0x3008, lo: 0xbe, hi: 0xbf},
+ // Block 0x31, offset 0x1b4
+ {value: 0x0000, lo: 0x10},
+ {value: 0x3008, lo: 0x80, hi: 0x85},
+ {value: 0x3308, lo: 0x86, hi: 0x86},
+ {value: 0x3008, lo: 0x87, hi: 0x88},
+ {value: 0x3308, lo: 0x89, hi: 0x91},
+ {value: 0x3b08, lo: 0x92, hi: 0x92},
+ {value: 0x3308, lo: 0x93, hi: 0x93},
+ {value: 0x0018, lo: 0x94, hi: 0x96},
+ {value: 0x0008, lo: 0x97, hi: 0x97},
+ {value: 0x0018, lo: 0x98, hi: 0x9b},
+ {value: 0x0008, lo: 0x9c, hi: 0x9c},
+ {value: 0x3308, lo: 0x9d, hi: 0x9d},
+ {value: 0x0040, lo: 0x9e, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xa9},
+ {value: 0x0040, lo: 0xaa, hi: 0xaf},
+ {value: 0x0018, lo: 0xb0, hi: 0xb9},
+ {value: 0x0040, lo: 0xba, hi: 0xbf},
+ // Block 0x32, offset 0x1c5
+ {value: 0x0000, lo: 0x09},
+ {value: 0x0018, lo: 0x80, hi: 0x85},
+ {value: 0x0040, lo: 0x86, hi: 0x86},
+ {value: 0x0218, lo: 0x87, hi: 0x87},
+ {value: 0x0018, lo: 0x88, hi: 0x8a},
+ {value: 0x33c0, lo: 0x8b, hi: 0x8d},
+ {value: 0x0040, lo: 0x8e, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x99},
+ {value: 0x0040, lo: 0x9a, hi: 0x9f},
+ {value: 0x0208, lo: 0xa0, hi: 0xbf},
+ // Block 0x33, offset 0x1cf
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0208, lo: 0x80, hi: 0xb7},
+ {value: 0x0040, lo: 0xb8, hi: 0xbf},
+ // Block 0x34, offset 0x1d2
+ {value: 0x0000, lo: 0x07},
+ {value: 0x0008, lo: 0x80, hi: 0x84},
+ {value: 0x3308, lo: 0x85, hi: 0x86},
+ {value: 0x0208, lo: 0x87, hi: 0xa8},
+ {value: 0x3308, lo: 0xa9, hi: 0xa9},
+ {value: 0x0208, lo: 0xaa, hi: 0xaa},
+ {value: 0x0040, lo: 0xab, hi: 0xaf},
+ {value: 0x0008, lo: 0xb0, hi: 0xbf},
+ // Block 0x35, offset 0x1da
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0008, lo: 0x80, hi: 0xb5},
+ {value: 0x0040, lo: 0xb6, hi: 0xbf},
+ // Block 0x36, offset 0x1dd
+ {value: 0x0000, lo: 0x0c},
+ {value: 0x0008, lo: 0x80, hi: 0x9e},
+ {value: 0x0040, lo: 0x9f, hi: 0x9f},
+ {value: 0x3308, lo: 0xa0, hi: 0xa2},
+ {value: 0x3008, lo: 0xa3, hi: 0xa6},
+ {value: 0x3308, lo: 0xa7, hi: 0xa8},
+ {value: 0x3008, lo: 0xa9, hi: 0xab},
+ {value: 0x0040, lo: 0xac, hi: 0xaf},
+ {value: 0x3008, lo: 0xb0, hi: 0xb1},
+ {value: 0x3308, lo: 0xb2, hi: 0xb2},
+ {value: 0x3008, lo: 0xb3, hi: 0xb8},
+ {value: 0x3308, lo: 0xb9, hi: 0xbb},
+ {value: 0x0040, lo: 0xbc, hi: 0xbf},
+ // Block 0x37, offset 0x1ea
+ {value: 0x0000, lo: 0x07},
+ {value: 0x0018, lo: 0x80, hi: 0x80},
+ {value: 0x0040, lo: 0x81, hi: 0x83},
+ {value: 0x0018, lo: 0x84, hi: 0x85},
+ {value: 0x0008, lo: 0x86, hi: 0xad},
+ {value: 0x0040, lo: 0xae, hi: 0xaf},
+ {value: 0x0008, lo: 0xb0, hi: 0xb4},
+ {value: 0x0040, lo: 0xb5, hi: 0xbf},
+ // Block 0x38, offset 0x1f2
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0008, lo: 0x80, hi: 0xab},
+ {value: 0x0040, lo: 0xac, hi: 0xaf},
+ {value: 0x0008, lo: 0xb0, hi: 0xbf},
+ // Block 0x39, offset 0x1f6
+ {value: 0x0000, lo: 0x06},
+ {value: 0x0008, lo: 0x80, hi: 0x89},
+ {value: 0x0040, lo: 0x8a, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x99},
+ {value: 0x0028, lo: 0x9a, hi: 0x9a},
+ {value: 0x0040, lo: 0x9b, hi: 0x9d},
+ {value: 0x0018, lo: 0x9e, hi: 0xbf},
+ // Block 0x3a, offset 0x1fd
+ {value: 0x0000, lo: 0x07},
+ {value: 0x0008, lo: 0x80, hi: 0x96},
+ {value: 0x3308, lo: 0x97, hi: 0x98},
+ {value: 0x3008, lo: 0x99, hi: 0x9a},
+ {value: 0x3308, lo: 0x9b, hi: 0x9b},
+ {value: 0x0040, lo: 0x9c, hi: 0x9d},
+ {value: 0x0018, lo: 0x9e, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xbf},
+ // Block 0x3b, offset 0x205
+ {value: 0x0000, lo: 0x0f},
+ {value: 0x0008, lo: 0x80, hi: 0x94},
+ {value: 0x3008, lo: 0x95, hi: 0x95},
+ {value: 0x3308, lo: 0x96, hi: 0x96},
+ {value: 0x3008, lo: 0x97, hi: 0x97},
+ {value: 0x3308, lo: 0x98, hi: 0x9e},
+ {value: 0x0040, lo: 0x9f, hi: 0x9f},
+ {value: 0x3b08, lo: 0xa0, hi: 0xa0},
+ {value: 0x3008, lo: 0xa1, hi: 0xa1},
+ {value: 0x3308, lo: 0xa2, hi: 0xa2},
+ {value: 0x3008, lo: 0xa3, hi: 0xa4},
+ {value: 0x3308, lo: 0xa5, hi: 0xac},
+ {value: 0x3008, lo: 0xad, hi: 0xb2},
+ {value: 0x3308, lo: 0xb3, hi: 0xbc},
+ {value: 0x0040, lo: 0xbd, hi: 0xbe},
+ {value: 0x3308, lo: 0xbf, hi: 0xbf},
+ // Block 0x3c, offset 0x215
+ {value: 0x0000, lo: 0x0b},
+ {value: 0x0008, lo: 0x80, hi: 0x89},
+ {value: 0x0040, lo: 0x8a, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x99},
+ {value: 0x0040, lo: 0x9a, hi: 0x9f},
+ {value: 0x0018, lo: 0xa0, hi: 0xa6},
+ {value: 0x0008, lo: 0xa7, hi: 0xa7},
+ {value: 0x0018, lo: 0xa8, hi: 0xad},
+ {value: 0x0040, lo: 0xae, hi: 0xaf},
+ {value: 0x3308, lo: 0xb0, hi: 0xbd},
+ {value: 0x3318, lo: 0xbe, hi: 0xbe},
+ {value: 0x0040, lo: 0xbf, hi: 0xbf},
+ // Block 0x3d, offset 0x221
+ {value: 0x0000, lo: 0x01},
+ {value: 0x0040, lo: 0x80, hi: 0xbf},
+ // Block 0x3e, offset 0x223
+ {value: 0x0000, lo: 0x09},
+ {value: 0x3308, lo: 0x80, hi: 0x83},
+ {value: 0x3008, lo: 0x84, hi: 0x84},
+ {value: 0x0008, lo: 0x85, hi: 0xb3},
+ {value: 0x3308, lo: 0xb4, hi: 0xb4},
+ {value: 0x3008, lo: 0xb5, hi: 0xb5},
+ {value: 0x3308, lo: 0xb6, hi: 0xba},
+ {value: 0x3008, lo: 0xbb, hi: 0xbb},
+ {value: 0x3308, lo: 0xbc, hi: 0xbc},
+ {value: 0x3008, lo: 0xbd, hi: 0xbf},
+ // Block 0x3f, offset 0x22d
+ {value: 0x0000, lo: 0x0b},
+ {value: 0x3008, lo: 0x80, hi: 0x81},
+ {value: 0x3308, lo: 0x82, hi: 0x82},
+ {value: 0x3008, lo: 0x83, hi: 0x83},
+ {value: 0x3808, lo: 0x84, hi: 0x84},
+ {value: 0x0008, lo: 0x85, hi: 0x8b},
+ {value: 0x0040, lo: 0x8c, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x99},
+ {value: 0x0018, lo: 0x9a, hi: 0xaa},
+ {value: 0x3308, lo: 0xab, hi: 0xb3},
+ {value: 0x0018, lo: 0xb4, hi: 0xbc},
+ {value: 0x0040, lo: 0xbd, hi: 0xbf},
+ // Block 0x40, offset 0x239
+ {value: 0x0000, lo: 0x0b},
+ {value: 0x3308, lo: 0x80, hi: 0x81},
+ {value: 0x3008, lo: 0x82, hi: 0x82},
+ {value: 0x0008, lo: 0x83, hi: 0xa0},
+ {value: 0x3008, lo: 0xa1, hi: 0xa1},
+ {value: 0x3308, lo: 0xa2, hi: 0xa5},
+ {value: 0x3008, lo: 0xa6, hi: 0xa7},
+ {value: 0x3308, lo: 0xa8, hi: 0xa9},
+ {value: 0x3808, lo: 0xaa, hi: 0xaa},
+ {value: 0x3b08, lo: 0xab, hi: 0xab},
+ {value: 0x3308, lo: 0xac, hi: 0xad},
+ {value: 0x0008, lo: 0xae, hi: 0xbf},
+ // Block 0x41, offset 0x245
+ {value: 0x0000, lo: 0x0b},
+ {value: 0x0008, lo: 0x80, hi: 0xa5},
+ {value: 0x3308, lo: 0xa6, hi: 0xa6},
+ {value: 0x3008, lo: 0xa7, hi: 0xa7},
+ {value: 0x3308, lo: 0xa8, hi: 0xa9},
+ {value: 0x3008, lo: 0xaa, hi: 0xac},
+ {value: 0x3308, lo: 0xad, hi: 0xad},
+ {value: 0x3008, lo: 0xae, hi: 0xae},
+ {value: 0x3308, lo: 0xaf, hi: 0xb1},
+ {value: 0x3808, lo: 0xb2, hi: 0xb3},
+ {value: 0x0040, lo: 0xb4, hi: 0xbb},
+ {value: 0x0018, lo: 0xbc, hi: 0xbf},
+ // Block 0x42, offset 0x251
+ {value: 0x0000, lo: 0x07},
+ {value: 0x0008, lo: 0x80, hi: 0xa3},
+ {value: 0x3008, lo: 0xa4, hi: 0xab},
+ {value: 0x3308, lo: 0xac, hi: 0xb3},
+ {value: 0x3008, lo: 0xb4, hi: 0xb5},
+ {value: 0x3308, lo: 0xb6, hi: 0xb7},
+ {value: 0x0040, lo: 0xb8, hi: 0xba},
+ {value: 0x0018, lo: 0xbb, hi: 0xbf},
+ // Block 0x43, offset 0x259
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0008, lo: 0x80, hi: 0x89},
+ {value: 0x0040, lo: 0x8a, hi: 0x8c},
+ {value: 0x0008, lo: 0x8d, hi: 0xbd},
+ {value: 0x0018, lo: 0xbe, hi: 0xbf},
+ // Block 0x44, offset 0x25e
+ {value: 0x0000, lo: 0x09},
+ {value: 0x0e29, lo: 0x80, hi: 0x80},
+ {value: 0x0e41, lo: 0x81, hi: 0x81},
+ {value: 0x0e59, lo: 0x82, hi: 0x82},
+ {value: 0x0e71, lo: 0x83, hi: 0x83},
+ {value: 0x0e89, lo: 0x84, hi: 0x85},
+ {value: 0x0ea1, lo: 0x86, hi: 0x86},
+ {value: 0x0eb9, lo: 0x87, hi: 0x87},
+ {value: 0x057d, lo: 0x88, hi: 0x88},
+ {value: 0x0040, lo: 0x89, hi: 0xbf},
+ // Block 0x45, offset 0x268
+ {value: 0x0000, lo: 0x10},
+ {value: 0x0018, lo: 0x80, hi: 0x87},
+ {value: 0x0040, lo: 0x88, hi: 0x8f},
+ {value: 0x3308, lo: 0x90, hi: 0x92},
+ {value: 0x0018, lo: 0x93, hi: 0x93},
+ {value: 0x3308, lo: 0x94, hi: 0xa0},
+ {value: 0x3008, lo: 0xa1, hi: 0xa1},
+ {value: 0x3308, lo: 0xa2, hi: 0xa8},
+ {value: 0x0008, lo: 0xa9, hi: 0xac},
+ {value: 0x3308, lo: 0xad, hi: 0xad},
+ {value: 0x0008, lo: 0xae, hi: 0xb1},
+ {value: 0x3008, lo: 0xb2, hi: 0xb3},
+ {value: 0x3308, lo: 0xb4, hi: 0xb4},
+ {value: 0x0008, lo: 0xb5, hi: 0xb6},
+ {value: 0x3008, lo: 0xb7, hi: 0xb7},
+ {value: 0x3308, lo: 0xb8, hi: 0xb9},
+ {value: 0x0040, lo: 0xba, hi: 0xbf},
+ // Block 0x46, offset 0x279
+ {value: 0x0000, lo: 0x03},
+ {value: 0x3308, lo: 0x80, hi: 0xb9},
+ {value: 0x0040, lo: 0xba, hi: 0xba},
+ {value: 0x3308, lo: 0xbb, hi: 0xbf},
+ // Block 0x47, offset 0x27d
+ {value: 0x0000, lo: 0x0a},
+ {value: 0x0008, lo: 0x80, hi: 0x87},
+ {value: 0xe045, lo: 0x88, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x95},
+ {value: 0x0040, lo: 0x96, hi: 0x97},
+ {value: 0xe045, lo: 0x98, hi: 0x9d},
+ {value: 0x0040, lo: 0x9e, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xa7},
+ {value: 0xe045, lo: 0xa8, hi: 0xaf},
+ {value: 0x0008, lo: 0xb0, hi: 0xb7},
+ {value: 0xe045, lo: 0xb8, hi: 0xbf},
+ // Block 0x48, offset 0x288
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0040, lo: 0x80, hi: 0x8f},
+ {value: 0x3318, lo: 0x90, hi: 0xb0},
+ {value: 0x0040, lo: 0xb1, hi: 0xbf},
+ // Block 0x49, offset 0x28c
+ {value: 0x0000, lo: 0x08},
+ {value: 0x0018, lo: 0x80, hi: 0x82},
+ {value: 0x0040, lo: 0x83, hi: 0x83},
+ {value: 0x0008, lo: 0x84, hi: 0x84},
+ {value: 0x0018, lo: 0x85, hi: 0x88},
+ {value: 0x24c1, lo: 0x89, hi: 0x89},
+ {value: 0x0018, lo: 0x8a, hi: 0x8b},
+ {value: 0x0040, lo: 0x8c, hi: 0x8f},
+ {value: 0x0018, lo: 0x90, hi: 0xbf},
+ // Block 0x4a, offset 0x295
+ {value: 0x0000, lo: 0x07},
+ {value: 0x0018, lo: 0x80, hi: 0xab},
+ {value: 0x24f1, lo: 0xac, hi: 0xac},
+ {value: 0x2529, lo: 0xad, hi: 0xad},
+ {value: 0x0018, lo: 0xae, hi: 0xae},
+ {value: 0x2579, lo: 0xaf, hi: 0xaf},
+ {value: 0x25b1, lo: 0xb0, hi: 0xb0},
+ {value: 0x0018, lo: 0xb1, hi: 0xbf},
+ // Block 0x4b, offset 0x29d
+ {value: 0x0000, lo: 0x05},
+ {value: 0x0018, lo: 0x80, hi: 0x9f},
+ {value: 0x0080, lo: 0xa0, hi: 0xa0},
+ {value: 0x0018, lo: 0xa1, hi: 0xad},
+ {value: 0x0080, lo: 0xae, hi: 0xaf},
+ {value: 0x0018, lo: 0xb0, hi: 0xbf},
+ // Block 0x4c, offset 0x2a3
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0018, lo: 0x80, hi: 0xa8},
+ {value: 0x09c5, lo: 0xa9, hi: 0xa9},
+ {value: 0x09e5, lo: 0xaa, hi: 0xaa},
+ {value: 0x0018, lo: 0xab, hi: 0xbf},
+ // Block 0x4d, offset 0x2a8
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0018, lo: 0x80, hi: 0xa6},
+ {value: 0x0040, lo: 0xa7, hi: 0xbf},
+ // Block 0x4e, offset 0x2ab
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0018, lo: 0x80, hi: 0x8b},
+ {value: 0x28c1, lo: 0x8c, hi: 0x8c},
+ {value: 0x0018, lo: 0x8d, hi: 0xbf},
+ // Block 0x4f, offset 0x2af
+ {value: 0x0000, lo: 0x05},
+ {value: 0x0018, lo: 0x80, hi: 0xb3},
+ {value: 0x0e66, lo: 0xb4, hi: 0xb4},
+ {value: 0x292a, lo: 0xb5, hi: 0xb5},
+ {value: 0x0e86, lo: 0xb6, hi: 0xb6},
+ {value: 0x0018, lo: 0xb7, hi: 0xbf},
+ // Block 0x50, offset 0x2b5
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0018, lo: 0x80, hi: 0x9b},
+ {value: 0x2941, lo: 0x9c, hi: 0x9c},
+ {value: 0x0018, lo: 0x9d, hi: 0xbf},
+ // Block 0x51, offset 0x2b9
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0018, lo: 0x80, hi: 0xb3},
+ {value: 0x0040, lo: 0xb4, hi: 0xb5},
+ {value: 0x0018, lo: 0xb6, hi: 0xbf},
+ // Block 0x52, offset 0x2bd
+ {value: 0x0000, lo: 0x05},
+ {value: 0x0018, lo: 0x80, hi: 0x95},
+ {value: 0x0040, lo: 0x96, hi: 0x97},
+ {value: 0x0018, lo: 0x98, hi: 0xb9},
+ {value: 0x0040, lo: 0xba, hi: 0xbc},
+ {value: 0x0018, lo: 0xbd, hi: 0xbf},
+ // Block 0x53, offset 0x2c3
+ {value: 0x0000, lo: 0x06},
+ {value: 0x0018, lo: 0x80, hi: 0x88},
+ {value: 0x0040, lo: 0x89, hi: 0x89},
+ {value: 0x0018, lo: 0x8a, hi: 0x92},
+ {value: 0x0040, lo: 0x93, hi: 0xab},
+ {value: 0x0018, lo: 0xac, hi: 0xaf},
+ {value: 0x0040, lo: 0xb0, hi: 0xbf},
+ // Block 0x54, offset 0x2ca
+ {value: 0x0000, lo: 0x05},
+ {value: 0xe185, lo: 0x80, hi: 0x8f},
+ {value: 0x03f5, lo: 0x90, hi: 0x9f},
+ {value: 0x0ea5, lo: 0xa0, hi: 0xae},
+ {value: 0x0040, lo: 0xaf, hi: 0xaf},
+ {value: 0x0008, lo: 0xb0, hi: 0xbf},
+ // Block 0x55, offset 0x2d0
+ {value: 0x0000, lo: 0x07},
+ {value: 0x0008, lo: 0x80, hi: 0xa5},
+ {value: 0x0040, lo: 0xa6, hi: 0xa6},
+ {value: 0x0008, lo: 0xa7, hi: 0xa7},
+ {value: 0x0040, lo: 0xa8, hi: 0xac},
+ {value: 0x0008, lo: 0xad, hi: 0xad},
+ {value: 0x0040, lo: 0xae, hi: 0xaf},
+ {value: 0x0008, lo: 0xb0, hi: 0xbf},
+ // Block 0x56, offset 0x2d8
+ {value: 0x0000, lo: 0x06},
+ {value: 0x0008, lo: 0x80, hi: 0xa7},
+ {value: 0x0040, lo: 0xa8, hi: 0xae},
+ {value: 0xe075, lo: 0xaf, hi: 0xaf},
+ {value: 0x0018, lo: 0xb0, hi: 0xb0},
+ {value: 0x0040, lo: 0xb1, hi: 0xbe},
+ {value: 0x3b08, lo: 0xbf, hi: 0xbf},
+ // Block 0x57, offset 0x2df
+ {value: 0x0000, lo: 0x0a},
+ {value: 0x0008, lo: 0x80, hi: 0x96},
+ {value: 0x0040, lo: 0x97, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xa6},
+ {value: 0x0040, lo: 0xa7, hi: 0xa7},
+ {value: 0x0008, lo: 0xa8, hi: 0xae},
+ {value: 0x0040, lo: 0xaf, hi: 0xaf},
+ {value: 0x0008, lo: 0xb0, hi: 0xb6},
+ {value: 0x0040, lo: 0xb7, hi: 0xb7},
+ {value: 0x0008, lo: 0xb8, hi: 0xbe},
+ {value: 0x0040, lo: 0xbf, hi: 0xbf},
+ // Block 0x58, offset 0x2ea
+ {value: 0x0000, lo: 0x09},
+ {value: 0x0008, lo: 0x80, hi: 0x86},
+ {value: 0x0040, lo: 0x87, hi: 0x87},
+ {value: 0x0008, lo: 0x88, hi: 0x8e},
+ {value: 0x0040, lo: 0x8f, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x96},
+ {value: 0x0040, lo: 0x97, hi: 0x97},
+ {value: 0x0008, lo: 0x98, hi: 0x9e},
+ {value: 0x0040, lo: 0x9f, hi: 0x9f},
+ {value: 0x3308, lo: 0xa0, hi: 0xbf},
+ // Block 0x59, offset 0x2f4
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0018, lo: 0x80, hi: 0xae},
+ {value: 0x0008, lo: 0xaf, hi: 0xaf},
+ {value: 0x0018, lo: 0xb0, hi: 0xbf},
+ // Block 0x5a, offset 0x2f8
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0018, lo: 0x80, hi: 0x89},
+ {value: 0x0040, lo: 0x8a, hi: 0xbf},
+ // Block 0x5b, offset 0x2fb
+ {value: 0x0000, lo: 0x05},
+ {value: 0x0018, lo: 0x80, hi: 0x99},
+ {value: 0x0040, lo: 0x9a, hi: 0x9a},
+ {value: 0x0018, lo: 0x9b, hi: 0x9e},
+ {value: 0x0edd, lo: 0x9f, hi: 0x9f},
+ {value: 0x0018, lo: 0xa0, hi: 0xbf},
+ // Block 0x5c, offset 0x301
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0018, lo: 0x80, hi: 0xb2},
+ {value: 0x0efd, lo: 0xb3, hi: 0xb3},
+ {value: 0x0040, lo: 0xb4, hi: 0xbf},
+ // Block 0x5d, offset 0x305
+ {value: 0x0020, lo: 0x01},
+ {value: 0x0f1d, lo: 0x80, hi: 0xbf},
+ // Block 0x5e, offset 0x307
+ {value: 0x0020, lo: 0x02},
+ {value: 0x171d, lo: 0x80, hi: 0x8f},
+ {value: 0x18fd, lo: 0x90, hi: 0xbf},
+ // Block 0x5f, offset 0x30a
+ {value: 0x0020, lo: 0x01},
+ {value: 0x1efd, lo: 0x80, hi: 0xbf},
+ // Block 0x60, offset 0x30c
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0040, lo: 0x80, hi: 0x80},
+ {value: 0x0008, lo: 0x81, hi: 0xbf},
+ // Block 0x61, offset 0x30f
+ {value: 0x0000, lo: 0x09},
+ {value: 0x0008, lo: 0x80, hi: 0x96},
+ {value: 0x0040, lo: 0x97, hi: 0x98},
+ {value: 0x3308, lo: 0x99, hi: 0x9a},
+ {value: 0x29e2, lo: 0x9b, hi: 0x9b},
+ {value: 0x2a0a, lo: 0x9c, hi: 0x9c},
+ {value: 0x0008, lo: 0x9d, hi: 0x9e},
+ {value: 0x2a31, lo: 0x9f, hi: 0x9f},
+ {value: 0x0018, lo: 0xa0, hi: 0xa0},
+ {value: 0x0008, lo: 0xa1, hi: 0xbf},
+ // Block 0x62, offset 0x319
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0008, lo: 0x80, hi: 0xbe},
+ {value: 0x2a69, lo: 0xbf, hi: 0xbf},
+ // Block 0x63, offset 0x31c
+ {value: 0x0000, lo: 0x0e},
+ {value: 0x0040, lo: 0x80, hi: 0x84},
+ {value: 0x0008, lo: 0x85, hi: 0xae},
+ {value: 0x0040, lo: 0xaf, hi: 0xb0},
+ {value: 0x2a1d, lo: 0xb1, hi: 0xb1},
+ {value: 0x2a3d, lo: 0xb2, hi: 0xb2},
+ {value: 0x2a5d, lo: 0xb3, hi: 0xb3},
+ {value: 0x2a7d, lo: 0xb4, hi: 0xb4},
+ {value: 0x2a5d, lo: 0xb5, hi: 0xb5},
+ {value: 0x2a9d, lo: 0xb6, hi: 0xb6},
+ {value: 0x2abd, lo: 0xb7, hi: 0xb7},
+ {value: 0x2add, lo: 0xb8, hi: 0xb9},
+ {value: 0x2afd, lo: 0xba, hi: 0xbb},
+ {value: 0x2b1d, lo: 0xbc, hi: 0xbd},
+ {value: 0x2afd, lo: 0xbe, hi: 0xbf},
+ // Block 0x64, offset 0x32b
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0018, lo: 0x80, hi: 0xa3},
+ {value: 0x0040, lo: 0xa4, hi: 0xaf},
+ {value: 0x0008, lo: 0xb0, hi: 0xbf},
+ // Block 0x65, offset 0x32f
+ {value: 0x0030, lo: 0x04},
+ {value: 0x2aa2, lo: 0x80, hi: 0x9d},
+ {value: 0x305a, lo: 0x9e, hi: 0x9e},
+ {value: 0x0040, lo: 0x9f, hi: 0x9f},
+ {value: 0x30a2, lo: 0xa0, hi: 0xbf},
+ // Block 0x66, offset 0x334
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0008, lo: 0x80, hi: 0xaa},
+ {value: 0x0040, lo: 0xab, hi: 0xbf},
+ // Block 0x67, offset 0x337
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0008, lo: 0x80, hi: 0x8c},
+ {value: 0x0040, lo: 0x8d, hi: 0x8f},
+ {value: 0x0018, lo: 0x90, hi: 0xbf},
+ // Block 0x68, offset 0x33b
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0018, lo: 0x80, hi: 0x86},
+ {value: 0x0040, lo: 0x87, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0xbd},
+ {value: 0x0018, lo: 0xbe, hi: 0xbf},
+ // Block 0x69, offset 0x340
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0008, lo: 0x80, hi: 0x8c},
+ {value: 0x0018, lo: 0x8d, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0xab},
+ {value: 0x0040, lo: 0xac, hi: 0xbf},
+ // Block 0x6a, offset 0x345
+ {value: 0x0000, lo: 0x05},
+ {value: 0x0008, lo: 0x80, hi: 0xa5},
+ {value: 0x0018, lo: 0xa6, hi: 0xaf},
+ {value: 0x3308, lo: 0xb0, hi: 0xb1},
+ {value: 0x0018, lo: 0xb2, hi: 0xb7},
+ {value: 0x0040, lo: 0xb8, hi: 0xbf},
+ // Block 0x6b, offset 0x34b
+ {value: 0x0000, lo: 0x05},
+ {value: 0x0040, lo: 0x80, hi: 0xb6},
+ {value: 0x0008, lo: 0xb7, hi: 0xb7},
+ {value: 0x2009, lo: 0xb8, hi: 0xb8},
+ {value: 0x6e89, lo: 0xb9, hi: 0xb9},
+ {value: 0x0008, lo: 0xba, hi: 0xbf},
+ // Block 0x6c, offset 0x351
+ {value: 0x0000, lo: 0x0e},
+ {value: 0x0008, lo: 0x80, hi: 0x81},
+ {value: 0x3308, lo: 0x82, hi: 0x82},
+ {value: 0x0008, lo: 0x83, hi: 0x85},
+ {value: 0x3b08, lo: 0x86, hi: 0x86},
+ {value: 0x0008, lo: 0x87, hi: 0x8a},
+ {value: 0x3308, lo: 0x8b, hi: 0x8b},
+ {value: 0x0008, lo: 0x8c, hi: 0xa2},
+ {value: 0x3008, lo: 0xa3, hi: 0xa4},
+ {value: 0x3308, lo: 0xa5, hi: 0xa6},
+ {value: 0x3008, lo: 0xa7, hi: 0xa7},
+ {value: 0x0018, lo: 0xa8, hi: 0xab},
+ {value: 0x0040, lo: 0xac, hi: 0xaf},
+ {value: 0x0018, lo: 0xb0, hi: 0xb9},
+ {value: 0x0040, lo: 0xba, hi: 0xbf},
+ // Block 0x6d, offset 0x360
+ {value: 0x0000, lo: 0x05},
+ {value: 0x0208, lo: 0x80, hi: 0xb1},
+ {value: 0x0108, lo: 0xb2, hi: 0xb2},
+ {value: 0x0008, lo: 0xb3, hi: 0xb3},
+ {value: 0x0018, lo: 0xb4, hi: 0xb7},
+ {value: 0x0040, lo: 0xb8, hi: 0xbf},
+ // Block 0x6e, offset 0x366
+ {value: 0x0000, lo: 0x03},
+ {value: 0x3008, lo: 0x80, hi: 0x81},
+ {value: 0x0008, lo: 0x82, hi: 0xb3},
+ {value: 0x3008, lo: 0xb4, hi: 0xbf},
+ // Block 0x6f, offset 0x36a
+ {value: 0x0000, lo: 0x0e},
+ {value: 0x3008, lo: 0x80, hi: 0x83},
+ {value: 0x3b08, lo: 0x84, hi: 0x84},
+ {value: 0x3308, lo: 0x85, hi: 0x85},
+ {value: 0x0040, lo: 0x86, hi: 0x8d},
+ {value: 0x0018, lo: 0x8e, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x99},
+ {value: 0x0040, lo: 0x9a, hi: 0x9f},
+ {value: 0x3308, lo: 0xa0, hi: 0xb1},
+ {value: 0x0008, lo: 0xb2, hi: 0xb7},
+ {value: 0x0018, lo: 0xb8, hi: 0xba},
+ {value: 0x0008, lo: 0xbb, hi: 0xbb},
+ {value: 0x0018, lo: 0xbc, hi: 0xbc},
+ {value: 0x0008, lo: 0xbd, hi: 0xbd},
+ {value: 0x0040, lo: 0xbe, hi: 0xbf},
+ // Block 0x70, offset 0x379
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0008, lo: 0x80, hi: 0xa5},
+ {value: 0x3308, lo: 0xa6, hi: 0xad},
+ {value: 0x0018, lo: 0xae, hi: 0xaf},
+ {value: 0x0008, lo: 0xb0, hi: 0xbf},
+ // Block 0x71, offset 0x37e
+ {value: 0x0000, lo: 0x07},
+ {value: 0x0008, lo: 0x80, hi: 0x86},
+ {value: 0x3308, lo: 0x87, hi: 0x91},
+ {value: 0x3008, lo: 0x92, hi: 0x92},
+ {value: 0x3808, lo: 0x93, hi: 0x93},
+ {value: 0x0040, lo: 0x94, hi: 0x9e},
+ {value: 0x0018, lo: 0x9f, hi: 0xbc},
+ {value: 0x0040, lo: 0xbd, hi: 0xbf},
+ // Block 0x72, offset 0x386
+ {value: 0x0000, lo: 0x09},
+ {value: 0x3308, lo: 0x80, hi: 0x82},
+ {value: 0x3008, lo: 0x83, hi: 0x83},
+ {value: 0x0008, lo: 0x84, hi: 0xb2},
+ {value: 0x3308, lo: 0xb3, hi: 0xb3},
+ {value: 0x3008, lo: 0xb4, hi: 0xb5},
+ {value: 0x3308, lo: 0xb6, hi: 0xb9},
+ {value: 0x3008, lo: 0xba, hi: 0xbb},
+ {value: 0x3308, lo: 0xbc, hi: 0xbc},
+ {value: 0x3008, lo: 0xbd, hi: 0xbf},
+ // Block 0x73, offset 0x390
+ {value: 0x0000, lo: 0x0a},
+ {value: 0x3808, lo: 0x80, hi: 0x80},
+ {value: 0x0018, lo: 0x81, hi: 0x8d},
+ {value: 0x0040, lo: 0x8e, hi: 0x8e},
+ {value: 0x0008, lo: 0x8f, hi: 0x99},
+ {value: 0x0040, lo: 0x9a, hi: 0x9d},
+ {value: 0x0018, lo: 0x9e, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xa4},
+ {value: 0x3308, lo: 0xa5, hi: 0xa5},
+ {value: 0x0008, lo: 0xa6, hi: 0xbe},
+ {value: 0x0040, lo: 0xbf, hi: 0xbf},
+ // Block 0x74, offset 0x39b
+ {value: 0x0000, lo: 0x07},
+ {value: 0x0008, lo: 0x80, hi: 0xa8},
+ {value: 0x3308, lo: 0xa9, hi: 0xae},
+ {value: 0x3008, lo: 0xaf, hi: 0xb0},
+ {value: 0x3308, lo: 0xb1, hi: 0xb2},
+ {value: 0x3008, lo: 0xb3, hi: 0xb4},
+ {value: 0x3308, lo: 0xb5, hi: 0xb6},
+ {value: 0x0040, lo: 0xb7, hi: 0xbf},
+ // Block 0x75, offset 0x3a3
+ {value: 0x0000, lo: 0x10},
+ {value: 0x0008, lo: 0x80, hi: 0x82},
+ {value: 0x3308, lo: 0x83, hi: 0x83},
+ {value: 0x0008, lo: 0x84, hi: 0x8b},
+ {value: 0x3308, lo: 0x8c, hi: 0x8c},
+ {value: 0x3008, lo: 0x8d, hi: 0x8d},
+ {value: 0x0040, lo: 0x8e, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x99},
+ {value: 0x0040, lo: 0x9a, hi: 0x9b},
+ {value: 0x0018, lo: 0x9c, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xb6},
+ {value: 0x0018, lo: 0xb7, hi: 0xb9},
+ {value: 0x0008, lo: 0xba, hi: 0xba},
+ {value: 0x3008, lo: 0xbb, hi: 0xbb},
+ {value: 0x3308, lo: 0xbc, hi: 0xbc},
+ {value: 0x3008, lo: 0xbd, hi: 0xbd},
+ {value: 0x0008, lo: 0xbe, hi: 0xbf},
+ // Block 0x76, offset 0x3b4
+ {value: 0x0000, lo: 0x08},
+ {value: 0x0008, lo: 0x80, hi: 0xaf},
+ {value: 0x3308, lo: 0xb0, hi: 0xb0},
+ {value: 0x0008, lo: 0xb1, hi: 0xb1},
+ {value: 0x3308, lo: 0xb2, hi: 0xb4},
+ {value: 0x0008, lo: 0xb5, hi: 0xb6},
+ {value: 0x3308, lo: 0xb7, hi: 0xb8},
+ {value: 0x0008, lo: 0xb9, hi: 0xbd},
+ {value: 0x3308, lo: 0xbe, hi: 0xbf},
+ // Block 0x77, offset 0x3bd
+ {value: 0x0000, lo: 0x0f},
+ {value: 0x0008, lo: 0x80, hi: 0x80},
+ {value: 0x3308, lo: 0x81, hi: 0x81},
+ {value: 0x0008, lo: 0x82, hi: 0x82},
+ {value: 0x0040, lo: 0x83, hi: 0x9a},
+ {value: 0x0008, lo: 0x9b, hi: 0x9d},
+ {value: 0x0018, lo: 0x9e, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xaa},
+ {value: 0x3008, lo: 0xab, hi: 0xab},
+ {value: 0x3308, lo: 0xac, hi: 0xad},
+ {value: 0x3008, lo: 0xae, hi: 0xaf},
+ {value: 0x0018, lo: 0xb0, hi: 0xb1},
+ {value: 0x0008, lo: 0xb2, hi: 0xb4},
+ {value: 0x3008, lo: 0xb5, hi: 0xb5},
+ {value: 0x3b08, lo: 0xb6, hi: 0xb6},
+ {value: 0x0040, lo: 0xb7, hi: 0xbf},
+ // Block 0x78, offset 0x3cd
+ {value: 0x0000, lo: 0x0c},
+ {value: 0x0040, lo: 0x80, hi: 0x80},
+ {value: 0x0008, lo: 0x81, hi: 0x86},
+ {value: 0x0040, lo: 0x87, hi: 0x88},
+ {value: 0x0008, lo: 0x89, hi: 0x8e},
+ {value: 0x0040, lo: 0x8f, hi: 0x90},
+ {value: 0x0008, lo: 0x91, hi: 0x96},
+ {value: 0x0040, lo: 0x97, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xa6},
+ {value: 0x0040, lo: 0xa7, hi: 0xa7},
+ {value: 0x0008, lo: 0xa8, hi: 0xae},
+ {value: 0x0040, lo: 0xaf, hi: 0xaf},
+ {value: 0x0008, lo: 0xb0, hi: 0xbf},
+ // Block 0x79, offset 0x3da
+ {value: 0x0000, lo: 0x09},
+ {value: 0x0008, lo: 0x80, hi: 0x9a},
+ {value: 0x0018, lo: 0x9b, hi: 0x9b},
+ {value: 0x4465, lo: 0x9c, hi: 0x9c},
+ {value: 0x447d, lo: 0x9d, hi: 0x9d},
+ {value: 0x2971, lo: 0x9e, hi: 0x9e},
+ {value: 0xe06d, lo: 0x9f, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xa5},
+ {value: 0x0040, lo: 0xa6, hi: 0xaf},
+ {value: 0x4495, lo: 0xb0, hi: 0xbf},
+ // Block 0x7a, offset 0x3e4
+ {value: 0x0000, lo: 0x04},
+ {value: 0x44b5, lo: 0x80, hi: 0x8f},
+ {value: 0x44d5, lo: 0x90, hi: 0x9f},
+ {value: 0x44f5, lo: 0xa0, hi: 0xaf},
+ {value: 0x44d5, lo: 0xb0, hi: 0xbf},
+ // Block 0x7b, offset 0x3e9
+ {value: 0x0000, lo: 0x0c},
+ {value: 0x0008, lo: 0x80, hi: 0xa2},
+ {value: 0x3008, lo: 0xa3, hi: 0xa4},
+ {value: 0x3308, lo: 0xa5, hi: 0xa5},
+ {value: 0x3008, lo: 0xa6, hi: 0xa7},
+ {value: 0x3308, lo: 0xa8, hi: 0xa8},
+ {value: 0x3008, lo: 0xa9, hi: 0xaa},
+ {value: 0x0018, lo: 0xab, hi: 0xab},
+ {value: 0x3008, lo: 0xac, hi: 0xac},
+ {value: 0x3b08, lo: 0xad, hi: 0xad},
+ {value: 0x0040, lo: 0xae, hi: 0xaf},
+ {value: 0x0008, lo: 0xb0, hi: 0xb9},
+ {value: 0x0040, lo: 0xba, hi: 0xbf},
+ // Block 0x7c, offset 0x3f6
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0008, lo: 0x80, hi: 0xa3},
+ {value: 0x0040, lo: 0xa4, hi: 0xaf},
+ {value: 0x0018, lo: 0xb0, hi: 0xbf},
+ // Block 0x7d, offset 0x3fa
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0018, lo: 0x80, hi: 0x86},
+ {value: 0x0040, lo: 0x87, hi: 0x8a},
+ {value: 0x0018, lo: 0x8b, hi: 0xbb},
+ {value: 0x0040, lo: 0xbc, hi: 0xbf},
+ // Block 0x7e, offset 0x3ff
+ {value: 0x0020, lo: 0x01},
+ {value: 0x4515, lo: 0x80, hi: 0xbf},
+ // Block 0x7f, offset 0x401
+ {value: 0x0020, lo: 0x03},
+ {value: 0x4d15, lo: 0x80, hi: 0x94},
+ {value: 0x4ad5, lo: 0x95, hi: 0x95},
+ {value: 0x4fb5, lo: 0x96, hi: 0xbf},
+ // Block 0x80, offset 0x405
+ {value: 0x0020, lo: 0x01},
+ {value: 0x54f5, lo: 0x80, hi: 0xbf},
+ // Block 0x81, offset 0x407
+ {value: 0x0020, lo: 0x03},
+ {value: 0x5cf5, lo: 0x80, hi: 0x84},
+ {value: 0x5655, lo: 0x85, hi: 0x85},
+ {value: 0x5d95, lo: 0x86, hi: 0xbf},
+ // Block 0x82, offset 0x40b
+ {value: 0x0020, lo: 0x08},
+ {value: 0x6b55, lo: 0x80, hi: 0x8f},
+ {value: 0x6d15, lo: 0x90, hi: 0x90},
+ {value: 0x6d55, lo: 0x91, hi: 0xab},
+ {value: 0x6ea1, lo: 0xac, hi: 0xac},
+ {value: 0x70b5, lo: 0xad, hi: 0xad},
+ {value: 0x0040, lo: 0xae, hi: 0xae},
+ {value: 0x0040, lo: 0xaf, hi: 0xaf},
+ {value: 0x70d5, lo: 0xb0, hi: 0xbf},
+ // Block 0x83, offset 0x414
+ {value: 0x0020, lo: 0x05},
+ {value: 0x72d5, lo: 0x80, hi: 0xad},
+ {value: 0x6535, lo: 0xae, hi: 0xae},
+ {value: 0x7895, lo: 0xaf, hi: 0xb5},
+ {value: 0x6f55, lo: 0xb6, hi: 0xb6},
+ {value: 0x7975, lo: 0xb7, hi: 0xbf},
+ // Block 0x84, offset 0x41a
+ {value: 0x0028, lo: 0x03},
+ {value: 0x7c21, lo: 0x80, hi: 0x82},
+ {value: 0x7be1, lo: 0x83, hi: 0x83},
+ {value: 0x7c99, lo: 0x84, hi: 0xbf},
+ // Block 0x85, offset 0x41e
+ {value: 0x0038, lo: 0x0f},
+ {value: 0x9db1, lo: 0x80, hi: 0x83},
+ {value: 0x9e59, lo: 0x84, hi: 0x85},
+ {value: 0x9e91, lo: 0x86, hi: 0x87},
+ {value: 0x9ec9, lo: 0x88, hi: 0x8f},
+ {value: 0x0040, lo: 0x90, hi: 0x90},
+ {value: 0x0040, lo: 0x91, hi: 0x91},
+ {value: 0xa089, lo: 0x92, hi: 0x97},
+ {value: 0xa1a1, lo: 0x98, hi: 0x9c},
+ {value: 0xa281, lo: 0x9d, hi: 0xb3},
+ {value: 0x9d41, lo: 0xb4, hi: 0xb4},
+ {value: 0x9db1, lo: 0xb5, hi: 0xb5},
+ {value: 0xa789, lo: 0xb6, hi: 0xbb},
+ {value: 0xa869, lo: 0xbc, hi: 0xbc},
+ {value: 0xa7f9, lo: 0xbd, hi: 0xbd},
+ {value: 0xa8d9, lo: 0xbe, hi: 0xbf},
+ // Block 0x86, offset 0x42e
+ {value: 0x0000, lo: 0x09},
+ {value: 0x0008, lo: 0x80, hi: 0x8b},
+ {value: 0x0040, lo: 0x8c, hi: 0x8c},
+ {value: 0x0008, lo: 0x8d, hi: 0xa6},
+ {value: 0x0040, lo: 0xa7, hi: 0xa7},
+ {value: 0x0008, lo: 0xa8, hi: 0xba},
+ {value: 0x0040, lo: 0xbb, hi: 0xbb},
+ {value: 0x0008, lo: 0xbc, hi: 0xbd},
+ {value: 0x0040, lo: 0xbe, hi: 0xbe},
+ {value: 0x0008, lo: 0xbf, hi: 0xbf},
+ // Block 0x87, offset 0x438
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0008, lo: 0x80, hi: 0x8d},
+ {value: 0x0040, lo: 0x8e, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x9d},
+ {value: 0x0040, lo: 0x9e, hi: 0xbf},
+ // Block 0x88, offset 0x43d
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0008, lo: 0x80, hi: 0xba},
+ {value: 0x0040, lo: 0xbb, hi: 0xbf},
+ // Block 0x89, offset 0x440
+ {value: 0x0000, lo: 0x05},
+ {value: 0x0018, lo: 0x80, hi: 0x82},
+ {value: 0x0040, lo: 0x83, hi: 0x86},
+ {value: 0x0018, lo: 0x87, hi: 0xb3},
+ {value: 0x0040, lo: 0xb4, hi: 0xb6},
+ {value: 0x0018, lo: 0xb7, hi: 0xbf},
+ // Block 0x8a, offset 0x446
+ {value: 0x0000, lo: 0x06},
+ {value: 0x0018, lo: 0x80, hi: 0x8e},
+ {value: 0x0040, lo: 0x8f, hi: 0x8f},
+ {value: 0x0018, lo: 0x90, hi: 0x9b},
+ {value: 0x0040, lo: 0x9c, hi: 0x9f},
+ {value: 0x0018, lo: 0xa0, hi: 0xa0},
+ {value: 0x0040, lo: 0xa1, hi: 0xbf},
+ // Block 0x8b, offset 0x44d
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0040, lo: 0x80, hi: 0x8f},
+ {value: 0x0018, lo: 0x90, hi: 0xbc},
+ {value: 0x3308, lo: 0xbd, hi: 0xbd},
+ {value: 0x0040, lo: 0xbe, hi: 0xbf},
+ // Block 0x8c, offset 0x452
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0008, lo: 0x80, hi: 0x9c},
+ {value: 0x0040, lo: 0x9d, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xbf},
+ // Block 0x8d, offset 0x456
+ {value: 0x0000, lo: 0x05},
+ {value: 0x0008, lo: 0x80, hi: 0x90},
+ {value: 0x0040, lo: 0x91, hi: 0x9f},
+ {value: 0x3308, lo: 0xa0, hi: 0xa0},
+ {value: 0x0018, lo: 0xa1, hi: 0xbb},
+ {value: 0x0040, lo: 0xbc, hi: 0xbf},
+ // Block 0x8e, offset 0x45c
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0008, lo: 0x80, hi: 0x9f},
+ {value: 0x0018, lo: 0xa0, hi: 0xa3},
+ {value: 0x0040, lo: 0xa4, hi: 0xac},
+ {value: 0x0008, lo: 0xad, hi: 0xbf},
+ // Block 0x8f, offset 0x461
+ {value: 0x0000, lo: 0x08},
+ {value: 0x0008, lo: 0x80, hi: 0x80},
+ {value: 0x0018, lo: 0x81, hi: 0x81},
+ {value: 0x0008, lo: 0x82, hi: 0x89},
+ {value: 0x0018, lo: 0x8a, hi: 0x8a},
+ {value: 0x0040, lo: 0x8b, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0xb5},
+ {value: 0x3308, lo: 0xb6, hi: 0xba},
+ {value: 0x0040, lo: 0xbb, hi: 0xbf},
+ // Block 0x90, offset 0x46a
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0008, lo: 0x80, hi: 0x9d},
+ {value: 0x0040, lo: 0x9e, hi: 0x9e},
+ {value: 0x0018, lo: 0x9f, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xbf},
+ // Block 0x91, offset 0x46f
+ {value: 0x0000, lo: 0x05},
+ {value: 0x0008, lo: 0x80, hi: 0x83},
+ {value: 0x0040, lo: 0x84, hi: 0x87},
+ {value: 0x0008, lo: 0x88, hi: 0x8f},
+ {value: 0x0018, lo: 0x90, hi: 0x95},
+ {value: 0x0040, lo: 0x96, hi: 0xbf},
+ // Block 0x92, offset 0x475
+ {value: 0x0000, lo: 0x06},
+ {value: 0xe145, lo: 0x80, hi: 0x87},
+ {value: 0xe1c5, lo: 0x88, hi: 0x8f},
+ {value: 0xe145, lo: 0x90, hi: 0x97},
+ {value: 0x8ad5, lo: 0x98, hi: 0x9f},
+ {value: 0x8aed, lo: 0xa0, hi: 0xa7},
+ {value: 0x0008, lo: 0xa8, hi: 0xbf},
+ // Block 0x93, offset 0x47c
+ {value: 0x0000, lo: 0x06},
+ {value: 0x0008, lo: 0x80, hi: 0x9d},
+ {value: 0x0040, lo: 0x9e, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xa9},
+ {value: 0x0040, lo: 0xaa, hi: 0xaf},
+ {value: 0x8aed, lo: 0xb0, hi: 0xb7},
+ {value: 0x8ad5, lo: 0xb8, hi: 0xbf},
+ // Block 0x94, offset 0x483
+ {value: 0x0000, lo: 0x06},
+ {value: 0xe145, lo: 0x80, hi: 0x87},
+ {value: 0xe1c5, lo: 0x88, hi: 0x8f},
+ {value: 0xe145, lo: 0x90, hi: 0x93},
+ {value: 0x0040, lo: 0x94, hi: 0x97},
+ {value: 0x0008, lo: 0x98, hi: 0xbb},
+ {value: 0x0040, lo: 0xbc, hi: 0xbf},
+ // Block 0x95, offset 0x48a
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0008, lo: 0x80, hi: 0xa7},
+ {value: 0x0040, lo: 0xa8, hi: 0xaf},
+ {value: 0x0008, lo: 0xb0, hi: 0xbf},
+ // Block 0x96, offset 0x48e
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0008, lo: 0x80, hi: 0xa3},
+ {value: 0x0040, lo: 0xa4, hi: 0xae},
+ {value: 0x0018, lo: 0xaf, hi: 0xaf},
+ {value: 0x0040, lo: 0xb0, hi: 0xbf},
+ // Block 0x97, offset 0x493
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0008, lo: 0x80, hi: 0xb6},
+ {value: 0x0040, lo: 0xb7, hi: 0xbf},
+ // Block 0x98, offset 0x496
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0008, lo: 0x80, hi: 0x95},
+ {value: 0x0040, lo: 0x96, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xa7},
+ {value: 0x0040, lo: 0xa8, hi: 0xbf},
+ // Block 0x99, offset 0x49b
+ {value: 0x0000, lo: 0x0b},
+ {value: 0x0808, lo: 0x80, hi: 0x85},
+ {value: 0x0040, lo: 0x86, hi: 0x87},
+ {value: 0x0808, lo: 0x88, hi: 0x88},
+ {value: 0x0040, lo: 0x89, hi: 0x89},
+ {value: 0x0808, lo: 0x8a, hi: 0xb5},
+ {value: 0x0040, lo: 0xb6, hi: 0xb6},
+ {value: 0x0808, lo: 0xb7, hi: 0xb8},
+ {value: 0x0040, lo: 0xb9, hi: 0xbb},
+ {value: 0x0808, lo: 0xbc, hi: 0xbc},
+ {value: 0x0040, lo: 0xbd, hi: 0xbe},
+ {value: 0x0808, lo: 0xbf, hi: 0xbf},
+ // Block 0x9a, offset 0x4a7
+ {value: 0x0000, lo: 0x05},
+ {value: 0x0808, lo: 0x80, hi: 0x95},
+ {value: 0x0040, lo: 0x96, hi: 0x96},
+ {value: 0x0818, lo: 0x97, hi: 0x9f},
+ {value: 0x0808, lo: 0xa0, hi: 0xb6},
+ {value: 0x0818, lo: 0xb7, hi: 0xbf},
+ // Block 0x9b, offset 0x4ad
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0808, lo: 0x80, hi: 0x9e},
+ {value: 0x0040, lo: 0x9f, hi: 0xa6},
+ {value: 0x0818, lo: 0xa7, hi: 0xaf},
+ {value: 0x0040, lo: 0xb0, hi: 0xbf},
+ // Block 0x9c, offset 0x4b2
+ {value: 0x0000, lo: 0x06},
+ {value: 0x0040, lo: 0x80, hi: 0x9f},
+ {value: 0x0808, lo: 0xa0, hi: 0xb2},
+ {value: 0x0040, lo: 0xb3, hi: 0xb3},
+ {value: 0x0808, lo: 0xb4, hi: 0xb5},
+ {value: 0x0040, lo: 0xb6, hi: 0xba},
+ {value: 0x0818, lo: 0xbb, hi: 0xbf},
+ // Block 0x9d, offset 0x4b9
+ {value: 0x0000, lo: 0x07},
+ {value: 0x0808, lo: 0x80, hi: 0x95},
+ {value: 0x0818, lo: 0x96, hi: 0x9b},
+ {value: 0x0040, lo: 0x9c, hi: 0x9e},
+ {value: 0x0018, lo: 0x9f, hi: 0x9f},
+ {value: 0x0808, lo: 0xa0, hi: 0xb9},
+ {value: 0x0040, lo: 0xba, hi: 0xbe},
+ {value: 0x0818, lo: 0xbf, hi: 0xbf},
+ // Block 0x9e, offset 0x4c1
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0808, lo: 0x80, hi: 0xb7},
+ {value: 0x0040, lo: 0xb8, hi: 0xbb},
+ {value: 0x0818, lo: 0xbc, hi: 0xbd},
+ {value: 0x0808, lo: 0xbe, hi: 0xbf},
+ // Block 0x9f, offset 0x4c6
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0818, lo: 0x80, hi: 0x8f},
+ {value: 0x0040, lo: 0x90, hi: 0x91},
+ {value: 0x0818, lo: 0x92, hi: 0xbf},
+ // Block 0xa0, offset 0x4ca
+ {value: 0x0000, lo: 0x0f},
+ {value: 0x0808, lo: 0x80, hi: 0x80},
+ {value: 0x3308, lo: 0x81, hi: 0x83},
+ {value: 0x0040, lo: 0x84, hi: 0x84},
+ {value: 0x3308, lo: 0x85, hi: 0x86},
+ {value: 0x0040, lo: 0x87, hi: 0x8b},
+ {value: 0x3308, lo: 0x8c, hi: 0x8f},
+ {value: 0x0808, lo: 0x90, hi: 0x93},
+ {value: 0x0040, lo: 0x94, hi: 0x94},
+ {value: 0x0808, lo: 0x95, hi: 0x97},
+ {value: 0x0040, lo: 0x98, hi: 0x98},
+ {value: 0x0808, lo: 0x99, hi: 0xb3},
+ {value: 0x0040, lo: 0xb4, hi: 0xb7},
+ {value: 0x3308, lo: 0xb8, hi: 0xba},
+ {value: 0x0040, lo: 0xbb, hi: 0xbe},
+ {value: 0x3b08, lo: 0xbf, hi: 0xbf},
+ // Block 0xa1, offset 0x4da
+ {value: 0x0000, lo: 0x06},
+ {value: 0x0818, lo: 0x80, hi: 0x87},
+ {value: 0x0040, lo: 0x88, hi: 0x8f},
+ {value: 0x0818, lo: 0x90, hi: 0x98},
+ {value: 0x0040, lo: 0x99, hi: 0x9f},
+ {value: 0x0808, lo: 0xa0, hi: 0xbc},
+ {value: 0x0818, lo: 0xbd, hi: 0xbf},
+ // Block 0xa2, offset 0x4e1
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0808, lo: 0x80, hi: 0x9c},
+ {value: 0x0818, lo: 0x9d, hi: 0x9f},
+ {value: 0x0040, lo: 0xa0, hi: 0xbf},
+ // Block 0xa3, offset 0x4e5
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0808, lo: 0x80, hi: 0xb5},
+ {value: 0x0040, lo: 0xb6, hi: 0xb8},
+ {value: 0x0018, lo: 0xb9, hi: 0xbf},
+ // Block 0xa4, offset 0x4e9
+ {value: 0x0000, lo: 0x06},
+ {value: 0x0808, lo: 0x80, hi: 0x95},
+ {value: 0x0040, lo: 0x96, hi: 0x97},
+ {value: 0x0818, lo: 0x98, hi: 0x9f},
+ {value: 0x0808, lo: 0xa0, hi: 0xb2},
+ {value: 0x0040, lo: 0xb3, hi: 0xb7},
+ {value: 0x0818, lo: 0xb8, hi: 0xbf},
+ // Block 0xa5, offset 0x4f0
+ {value: 0x0000, lo: 0x01},
+ {value: 0x0808, lo: 0x80, hi: 0xbf},
+ // Block 0xa6, offset 0x4f2
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0808, lo: 0x80, hi: 0x88},
+ {value: 0x0040, lo: 0x89, hi: 0xbf},
+ // Block 0xa7, offset 0x4f5
+ {value: 0x0000, lo: 0x02},
+ {value: 0x03dd, lo: 0x80, hi: 0xb2},
+ {value: 0x0040, lo: 0xb3, hi: 0xbf},
+ // Block 0xa8, offset 0x4f8
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0808, lo: 0x80, hi: 0xb2},
+ {value: 0x0040, lo: 0xb3, hi: 0xb9},
+ {value: 0x0818, lo: 0xba, hi: 0xbf},
+ // Block 0xa9, offset 0x4fc
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0040, lo: 0x80, hi: 0x9f},
+ {value: 0x0818, lo: 0xa0, hi: 0xbe},
+ {value: 0x0040, lo: 0xbf, hi: 0xbf},
+ // Block 0xaa, offset 0x500
+ {value: 0x0000, lo: 0x05},
+ {value: 0x3008, lo: 0x80, hi: 0x80},
+ {value: 0x3308, lo: 0x81, hi: 0x81},
+ {value: 0x3008, lo: 0x82, hi: 0x82},
+ {value: 0x0008, lo: 0x83, hi: 0xb7},
+ {value: 0x3308, lo: 0xb8, hi: 0xbf},
+ // Block 0xab, offset 0x506
+ {value: 0x0000, lo: 0x08},
+ {value: 0x3308, lo: 0x80, hi: 0x85},
+ {value: 0x3b08, lo: 0x86, hi: 0x86},
+ {value: 0x0018, lo: 0x87, hi: 0x8d},
+ {value: 0x0040, lo: 0x8e, hi: 0x91},
+ {value: 0x0018, lo: 0x92, hi: 0xa5},
+ {value: 0x0008, lo: 0xa6, hi: 0xaf},
+ {value: 0x0040, lo: 0xb0, hi: 0xbe},
+ {value: 0x3b08, lo: 0xbf, hi: 0xbf},
+ // Block 0xac, offset 0x50f
+ {value: 0x0000, lo: 0x0b},
+ {value: 0x3308, lo: 0x80, hi: 0x81},
+ {value: 0x3008, lo: 0x82, hi: 0x82},
+ {value: 0x0008, lo: 0x83, hi: 0xaf},
+ {value: 0x3008, lo: 0xb0, hi: 0xb2},
+ {value: 0x3308, lo: 0xb3, hi: 0xb6},
+ {value: 0x3008, lo: 0xb7, hi: 0xb8},
+ {value: 0x3b08, lo: 0xb9, hi: 0xb9},
+ {value: 0x3308, lo: 0xba, hi: 0xba},
+ {value: 0x0018, lo: 0xbb, hi: 0xbc},
+ {value: 0x0340, lo: 0xbd, hi: 0xbd},
+ {value: 0x0018, lo: 0xbe, hi: 0xbf},
+ // Block 0xad, offset 0x51b
+ {value: 0x0000, lo: 0x06},
+ {value: 0x0018, lo: 0x80, hi: 0x81},
+ {value: 0x0040, lo: 0x82, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0xa8},
+ {value: 0x0040, lo: 0xa9, hi: 0xaf},
+ {value: 0x0008, lo: 0xb0, hi: 0xb9},
+ {value: 0x0040, lo: 0xba, hi: 0xbf},
+ // Block 0xae, offset 0x522
+ {value: 0x0000, lo: 0x08},
+ {value: 0x3308, lo: 0x80, hi: 0x82},
+ {value: 0x0008, lo: 0x83, hi: 0xa6},
+ {value: 0x3308, lo: 0xa7, hi: 0xab},
+ {value: 0x3008, lo: 0xac, hi: 0xac},
+ {value: 0x3308, lo: 0xad, hi: 0xb2},
+ {value: 0x3b08, lo: 0xb3, hi: 0xb4},
+ {value: 0x0040, lo: 0xb5, hi: 0xb5},
+ {value: 0x0008, lo: 0xb6, hi: 0xbf},
+ // Block 0xaf, offset 0x52b
+ {value: 0x0000, lo: 0x07},
+ {value: 0x0018, lo: 0x80, hi: 0x83},
+ {value: 0x0040, lo: 0x84, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0xb2},
+ {value: 0x3308, lo: 0xb3, hi: 0xb3},
+ {value: 0x0018, lo: 0xb4, hi: 0xb5},
+ {value: 0x0008, lo: 0xb6, hi: 0xb6},
+ {value: 0x0040, lo: 0xb7, hi: 0xbf},
+ // Block 0xb0, offset 0x533
+ {value: 0x0000, lo: 0x06},
+ {value: 0x3308, lo: 0x80, hi: 0x81},
+ {value: 0x3008, lo: 0x82, hi: 0x82},
+ {value: 0x0008, lo: 0x83, hi: 0xb2},
+ {value: 0x3008, lo: 0xb3, hi: 0xb5},
+ {value: 0x3308, lo: 0xb6, hi: 0xbe},
+ {value: 0x3008, lo: 0xbf, hi: 0xbf},
+ // Block 0xb1, offset 0x53a
+ {value: 0x0000, lo: 0x0d},
+ {value: 0x3808, lo: 0x80, hi: 0x80},
+ {value: 0x0008, lo: 0x81, hi: 0x84},
+ {value: 0x0018, lo: 0x85, hi: 0x89},
+ {value: 0x3308, lo: 0x8a, hi: 0x8c},
+ {value: 0x0018, lo: 0x8d, hi: 0x8d},
+ {value: 0x0040, lo: 0x8e, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x9a},
+ {value: 0x0018, lo: 0x9b, hi: 0x9b},
+ {value: 0x0008, lo: 0x9c, hi: 0x9c},
+ {value: 0x0018, lo: 0x9d, hi: 0x9f},
+ {value: 0x0040, lo: 0xa0, hi: 0xa0},
+ {value: 0x0018, lo: 0xa1, hi: 0xb4},
+ {value: 0x0040, lo: 0xb5, hi: 0xbf},
+ // Block 0xb2, offset 0x548
+ {value: 0x0000, lo: 0x0c},
+ {value: 0x0008, lo: 0x80, hi: 0x91},
+ {value: 0x0040, lo: 0x92, hi: 0x92},
+ {value: 0x0008, lo: 0x93, hi: 0xab},
+ {value: 0x3008, lo: 0xac, hi: 0xae},
+ {value: 0x3308, lo: 0xaf, hi: 0xb1},
+ {value: 0x3008, lo: 0xb2, hi: 0xb3},
+ {value: 0x3308, lo: 0xb4, hi: 0xb4},
+ {value: 0x3808, lo: 0xb5, hi: 0xb5},
+ {value: 0x3308, lo: 0xb6, hi: 0xb7},
+ {value: 0x0018, lo: 0xb8, hi: 0xbd},
+ {value: 0x3308, lo: 0xbe, hi: 0xbe},
+ {value: 0x0040, lo: 0xbf, hi: 0xbf},
+ // Block 0xb3, offset 0x555
+ {value: 0x0000, lo: 0x0c},
+ {value: 0x0008, lo: 0x80, hi: 0x86},
+ {value: 0x0040, lo: 0x87, hi: 0x87},
+ {value: 0x0008, lo: 0x88, hi: 0x88},
+ {value: 0x0040, lo: 0x89, hi: 0x89},
+ {value: 0x0008, lo: 0x8a, hi: 0x8d},
+ {value: 0x0040, lo: 0x8e, hi: 0x8e},
+ {value: 0x0008, lo: 0x8f, hi: 0x9d},
+ {value: 0x0040, lo: 0x9e, hi: 0x9e},
+ {value: 0x0008, lo: 0x9f, hi: 0xa8},
+ {value: 0x0018, lo: 0xa9, hi: 0xa9},
+ {value: 0x0040, lo: 0xaa, hi: 0xaf},
+ {value: 0x0008, lo: 0xb0, hi: 0xbf},
+ // Block 0xb4, offset 0x562
+ {value: 0x0000, lo: 0x08},
+ {value: 0x0008, lo: 0x80, hi: 0x9e},
+ {value: 0x3308, lo: 0x9f, hi: 0x9f},
+ {value: 0x3008, lo: 0xa0, hi: 0xa2},
+ {value: 0x3308, lo: 0xa3, hi: 0xa9},
+ {value: 0x3b08, lo: 0xaa, hi: 0xaa},
+ {value: 0x0040, lo: 0xab, hi: 0xaf},
+ {value: 0x0008, lo: 0xb0, hi: 0xb9},
+ {value: 0x0040, lo: 0xba, hi: 0xbf},
+ // Block 0xb5, offset 0x56b
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0008, lo: 0x80, hi: 0xb4},
+ {value: 0x3008, lo: 0xb5, hi: 0xb7},
+ {value: 0x3308, lo: 0xb8, hi: 0xbf},
+ // Block 0xb6, offset 0x56f
+ {value: 0x0000, lo: 0x0d},
+ {value: 0x3008, lo: 0x80, hi: 0x81},
+ {value: 0x3b08, lo: 0x82, hi: 0x82},
+ {value: 0x3308, lo: 0x83, hi: 0x84},
+ {value: 0x3008, lo: 0x85, hi: 0x85},
+ {value: 0x3308, lo: 0x86, hi: 0x86},
+ {value: 0x0008, lo: 0x87, hi: 0x8a},
+ {value: 0x0018, lo: 0x8b, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x99},
+ {value: 0x0040, lo: 0x9a, hi: 0x9a},
+ {value: 0x0018, lo: 0x9b, hi: 0x9b},
+ {value: 0x0040, lo: 0x9c, hi: 0x9c},
+ {value: 0x0018, lo: 0x9d, hi: 0x9d},
+ {value: 0x0040, lo: 0x9e, hi: 0xbf},
+ // Block 0xb7, offset 0x57d
+ {value: 0x0000, lo: 0x07},
+ {value: 0x0008, lo: 0x80, hi: 0xaf},
+ {value: 0x3008, lo: 0xb0, hi: 0xb2},
+ {value: 0x3308, lo: 0xb3, hi: 0xb8},
+ {value: 0x3008, lo: 0xb9, hi: 0xb9},
+ {value: 0x3308, lo: 0xba, hi: 0xba},
+ {value: 0x3008, lo: 0xbb, hi: 0xbe},
+ {value: 0x3308, lo: 0xbf, hi: 0xbf},
+ // Block 0xb8, offset 0x585
+ {value: 0x0000, lo: 0x0a},
+ {value: 0x3308, lo: 0x80, hi: 0x80},
+ {value: 0x3008, lo: 0x81, hi: 0x81},
+ {value: 0x3b08, lo: 0x82, hi: 0x82},
+ {value: 0x3308, lo: 0x83, hi: 0x83},
+ {value: 0x0008, lo: 0x84, hi: 0x85},
+ {value: 0x0018, lo: 0x86, hi: 0x86},
+ {value: 0x0008, lo: 0x87, hi: 0x87},
+ {value: 0x0040, lo: 0x88, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x99},
+ {value: 0x0040, lo: 0x9a, hi: 0xbf},
+ // Block 0xb9, offset 0x590
+ {value: 0x0000, lo: 0x08},
+ {value: 0x0008, lo: 0x80, hi: 0xae},
+ {value: 0x3008, lo: 0xaf, hi: 0xb1},
+ {value: 0x3308, lo: 0xb2, hi: 0xb5},
+ {value: 0x0040, lo: 0xb6, hi: 0xb7},
+ {value: 0x3008, lo: 0xb8, hi: 0xbb},
+ {value: 0x3308, lo: 0xbc, hi: 0xbd},
+ {value: 0x3008, lo: 0xbe, hi: 0xbe},
+ {value: 0x3b08, lo: 0xbf, hi: 0xbf},
+ // Block 0xba, offset 0x599
+ {value: 0x0000, lo: 0x05},
+ {value: 0x3308, lo: 0x80, hi: 0x80},
+ {value: 0x0018, lo: 0x81, hi: 0x97},
+ {value: 0x0008, lo: 0x98, hi: 0x9b},
+ {value: 0x3308, lo: 0x9c, hi: 0x9d},
+ {value: 0x0040, lo: 0x9e, hi: 0xbf},
+ // Block 0xbb, offset 0x59f
+ {value: 0x0000, lo: 0x07},
+ {value: 0x0008, lo: 0x80, hi: 0xaf},
+ {value: 0x3008, lo: 0xb0, hi: 0xb2},
+ {value: 0x3308, lo: 0xb3, hi: 0xba},
+ {value: 0x3008, lo: 0xbb, hi: 0xbc},
+ {value: 0x3308, lo: 0xbd, hi: 0xbd},
+ {value: 0x3008, lo: 0xbe, hi: 0xbe},
+ {value: 0x3b08, lo: 0xbf, hi: 0xbf},
+ // Block 0xbc, offset 0x5a7
+ {value: 0x0000, lo: 0x08},
+ {value: 0x3308, lo: 0x80, hi: 0x80},
+ {value: 0x0018, lo: 0x81, hi: 0x83},
+ {value: 0x0008, lo: 0x84, hi: 0x84},
+ {value: 0x0040, lo: 0x85, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x99},
+ {value: 0x0040, lo: 0x9a, hi: 0x9f},
+ {value: 0x0018, lo: 0xa0, hi: 0xac},
+ {value: 0x0040, lo: 0xad, hi: 0xbf},
+ // Block 0xbd, offset 0x5b0
+ {value: 0x0000, lo: 0x09},
+ {value: 0x0008, lo: 0x80, hi: 0xaa},
+ {value: 0x3308, lo: 0xab, hi: 0xab},
+ {value: 0x3008, lo: 0xac, hi: 0xac},
+ {value: 0x3308, lo: 0xad, hi: 0xad},
+ {value: 0x3008, lo: 0xae, hi: 0xaf},
+ {value: 0x3308, lo: 0xb0, hi: 0xb5},
+ {value: 0x3808, lo: 0xb6, hi: 0xb6},
+ {value: 0x3308, lo: 0xb7, hi: 0xb7},
+ {value: 0x0040, lo: 0xb8, hi: 0xbf},
+ // Block 0xbe, offset 0x5ba
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0008, lo: 0x80, hi: 0x89},
+ {value: 0x0040, lo: 0x8a, hi: 0xbf},
+ // Block 0xbf, offset 0x5bd
+ {value: 0x0000, lo: 0x0b},
+ {value: 0x0008, lo: 0x80, hi: 0x99},
+ {value: 0x0040, lo: 0x9a, hi: 0x9c},
+ {value: 0x3308, lo: 0x9d, hi: 0x9f},
+ {value: 0x3008, lo: 0xa0, hi: 0xa1},
+ {value: 0x3308, lo: 0xa2, hi: 0xa5},
+ {value: 0x3008, lo: 0xa6, hi: 0xa6},
+ {value: 0x3308, lo: 0xa7, hi: 0xaa},
+ {value: 0x3b08, lo: 0xab, hi: 0xab},
+ {value: 0x0040, lo: 0xac, hi: 0xaf},
+ {value: 0x0008, lo: 0xb0, hi: 0xb9},
+ {value: 0x0018, lo: 0xba, hi: 0xbf},
+ // Block 0xc0, offset 0x5c9
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0040, lo: 0x80, hi: 0x9f},
+ {value: 0x049d, lo: 0xa0, hi: 0xbf},
+ // Block 0xc1, offset 0x5cc
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0008, lo: 0x80, hi: 0xa9},
+ {value: 0x0018, lo: 0xaa, hi: 0xb2},
+ {value: 0x0040, lo: 0xb3, hi: 0xbe},
+ {value: 0x0008, lo: 0xbf, hi: 0xbf},
+ // Block 0xc2, offset 0x5d1
+ {value: 0x0000, lo: 0x0c},
+ {value: 0x0008, lo: 0x80, hi: 0x80},
+ {value: 0x3308, lo: 0x81, hi: 0x86},
+ {value: 0x3008, lo: 0x87, hi: 0x88},
+ {value: 0x3308, lo: 0x89, hi: 0x8a},
+ {value: 0x0008, lo: 0x8b, hi: 0xb2},
+ {value: 0x3308, lo: 0xb3, hi: 0xb3},
+ {value: 0x3b08, lo: 0xb4, hi: 0xb4},
+ {value: 0x3308, lo: 0xb5, hi: 0xb8},
+ {value: 0x3008, lo: 0xb9, hi: 0xb9},
+ {value: 0x0008, lo: 0xba, hi: 0xba},
+ {value: 0x3308, lo: 0xbb, hi: 0xbe},
+ {value: 0x0018, lo: 0xbf, hi: 0xbf},
+ // Block 0xc3, offset 0x5de
+ {value: 0x0000, lo: 0x08},
+ {value: 0x0018, lo: 0x80, hi: 0x86},
+ {value: 0x3b08, lo: 0x87, hi: 0x87},
+ {value: 0x0040, lo: 0x88, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x90},
+ {value: 0x3308, lo: 0x91, hi: 0x96},
+ {value: 0x3008, lo: 0x97, hi: 0x98},
+ {value: 0x3308, lo: 0x99, hi: 0x9b},
+ {value: 0x0008, lo: 0x9c, hi: 0xbf},
+ // Block 0xc4, offset 0x5e7
+ {value: 0x0000, lo: 0x0b},
+ {value: 0x0008, lo: 0x80, hi: 0x83},
+ {value: 0x0040, lo: 0x84, hi: 0x85},
+ {value: 0x0008, lo: 0x86, hi: 0x89},
+ {value: 0x3308, lo: 0x8a, hi: 0x96},
+ {value: 0x3008, lo: 0x97, hi: 0x97},
+ {value: 0x3308, lo: 0x98, hi: 0x98},
+ {value: 0x3b08, lo: 0x99, hi: 0x99},
+ {value: 0x0018, lo: 0x9a, hi: 0x9c},
+ {value: 0x0040, lo: 0x9d, hi: 0x9d},
+ {value: 0x0018, lo: 0x9e, hi: 0xa2},
+ {value: 0x0040, lo: 0xa3, hi: 0xbf},
+ // Block 0xc5, offset 0x5f3
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0008, lo: 0x80, hi: 0xb8},
+ {value: 0x0040, lo: 0xb9, hi: 0xbf},
+ // Block 0xc6, offset 0x5f6
+ {value: 0x0000, lo: 0x09},
+ {value: 0x0008, lo: 0x80, hi: 0x88},
+ {value: 0x0040, lo: 0x89, hi: 0x89},
+ {value: 0x0008, lo: 0x8a, hi: 0xae},
+ {value: 0x3008, lo: 0xaf, hi: 0xaf},
+ {value: 0x3308, lo: 0xb0, hi: 0xb6},
+ {value: 0x0040, lo: 0xb7, hi: 0xb7},
+ {value: 0x3308, lo: 0xb8, hi: 0xbd},
+ {value: 0x3008, lo: 0xbe, hi: 0xbe},
+ {value: 0x3b08, lo: 0xbf, hi: 0xbf},
+ // Block 0xc7, offset 0x600
+ {value: 0x0000, lo: 0x08},
+ {value: 0x0008, lo: 0x80, hi: 0x80},
+ {value: 0x0018, lo: 0x81, hi: 0x85},
+ {value: 0x0040, lo: 0x86, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x99},
+ {value: 0x0018, lo: 0x9a, hi: 0xac},
+ {value: 0x0040, lo: 0xad, hi: 0xaf},
+ {value: 0x0018, lo: 0xb0, hi: 0xb1},
+ {value: 0x0008, lo: 0xb2, hi: 0xbf},
+ // Block 0xc8, offset 0x609
+ {value: 0x0000, lo: 0x0b},
+ {value: 0x0008, lo: 0x80, hi: 0x8f},
+ {value: 0x0040, lo: 0x90, hi: 0x91},
+ {value: 0x3308, lo: 0x92, hi: 0xa7},
+ {value: 0x0040, lo: 0xa8, hi: 0xa8},
+ {value: 0x3008, lo: 0xa9, hi: 0xa9},
+ {value: 0x3308, lo: 0xaa, hi: 0xb0},
+ {value: 0x3008, lo: 0xb1, hi: 0xb1},
+ {value: 0x3308, lo: 0xb2, hi: 0xb3},
+ {value: 0x3008, lo: 0xb4, hi: 0xb4},
+ {value: 0x3308, lo: 0xb5, hi: 0xb6},
+ {value: 0x0040, lo: 0xb7, hi: 0xbf},
+ // Block 0xc9, offset 0x615
+ {value: 0x0000, lo: 0x0c},
+ {value: 0x0008, lo: 0x80, hi: 0x86},
+ {value: 0x0040, lo: 0x87, hi: 0x87},
+ {value: 0x0008, lo: 0x88, hi: 0x89},
+ {value: 0x0040, lo: 0x8a, hi: 0x8a},
+ {value: 0x0008, lo: 0x8b, hi: 0xb0},
+ {value: 0x3308, lo: 0xb1, hi: 0xb6},
+ {value: 0x0040, lo: 0xb7, hi: 0xb9},
+ {value: 0x3308, lo: 0xba, hi: 0xba},
+ {value: 0x0040, lo: 0xbb, hi: 0xbb},
+ {value: 0x3308, lo: 0xbc, hi: 0xbd},
+ {value: 0x0040, lo: 0xbe, hi: 0xbe},
+ {value: 0x3308, lo: 0xbf, hi: 0xbf},
+ // Block 0xca, offset 0x622
+ {value: 0x0000, lo: 0x07},
+ {value: 0x3308, lo: 0x80, hi: 0x83},
+ {value: 0x3b08, lo: 0x84, hi: 0x85},
+ {value: 0x0008, lo: 0x86, hi: 0x86},
+ {value: 0x3308, lo: 0x87, hi: 0x87},
+ {value: 0x0040, lo: 0x88, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x99},
+ {value: 0x0040, lo: 0x9a, hi: 0xbf},
+ // Block 0xcb, offset 0x62a
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0008, lo: 0x80, hi: 0x99},
+ {value: 0x0040, lo: 0x9a, hi: 0xbf},
+ // Block 0xcc, offset 0x62d
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0018, lo: 0x80, hi: 0xae},
+ {value: 0x0040, lo: 0xaf, hi: 0xaf},
+ {value: 0x0018, lo: 0xb0, hi: 0xb4},
+ {value: 0x0040, lo: 0xb5, hi: 0xbf},
+ // Block 0xcd, offset 0x632
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0008, lo: 0x80, hi: 0x83},
+ {value: 0x0040, lo: 0x84, hi: 0xbf},
+ // Block 0xce, offset 0x635
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0008, lo: 0x80, hi: 0xae},
+ {value: 0x0040, lo: 0xaf, hi: 0xbf},
+ // Block 0xcf, offset 0x638
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0008, lo: 0x80, hi: 0x86},
+ {value: 0x0040, lo: 0x87, hi: 0xbf},
+ // Block 0xd0, offset 0x63b
+ {value: 0x0000, lo: 0x06},
+ {value: 0x0008, lo: 0x80, hi: 0x9e},
+ {value: 0x0040, lo: 0x9f, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xa9},
+ {value: 0x0040, lo: 0xaa, hi: 0xad},
+ {value: 0x0018, lo: 0xae, hi: 0xaf},
+ {value: 0x0040, lo: 0xb0, hi: 0xbf},
+ // Block 0xd1, offset 0x642
+ {value: 0x0000, lo: 0x06},
+ {value: 0x0040, lo: 0x80, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0xad},
+ {value: 0x0040, lo: 0xae, hi: 0xaf},
+ {value: 0x3308, lo: 0xb0, hi: 0xb4},
+ {value: 0x0018, lo: 0xb5, hi: 0xb5},
+ {value: 0x0040, lo: 0xb6, hi: 0xbf},
+ // Block 0xd2, offset 0x649
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0008, lo: 0x80, hi: 0xaf},
+ {value: 0x3308, lo: 0xb0, hi: 0xb6},
+ {value: 0x0018, lo: 0xb7, hi: 0xbf},
+ // Block 0xd3, offset 0x64d
+ {value: 0x0000, lo: 0x0a},
+ {value: 0x0008, lo: 0x80, hi: 0x83},
+ {value: 0x0018, lo: 0x84, hi: 0x85},
+ {value: 0x0040, lo: 0x86, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x99},
+ {value: 0x0040, lo: 0x9a, hi: 0x9a},
+ {value: 0x0018, lo: 0x9b, hi: 0xa1},
+ {value: 0x0040, lo: 0xa2, hi: 0xa2},
+ {value: 0x0008, lo: 0xa3, hi: 0xb7},
+ {value: 0x0040, lo: 0xb8, hi: 0xbc},
+ {value: 0x0008, lo: 0xbd, hi: 0xbf},
+ // Block 0xd4, offset 0x658
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0008, lo: 0x80, hi: 0x8f},
+ {value: 0x0040, lo: 0x90, hi: 0xbf},
+ // Block 0xd5, offset 0x65b
+ {value: 0x0000, lo: 0x05},
+ {value: 0x0008, lo: 0x80, hi: 0x84},
+ {value: 0x0040, lo: 0x85, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x90},
+ {value: 0x3008, lo: 0x91, hi: 0xbe},
+ {value: 0x0040, lo: 0xbf, hi: 0xbf},
+ // Block 0xd6, offset 0x661
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0040, lo: 0x80, hi: 0x8e},
+ {value: 0x3308, lo: 0x8f, hi: 0x92},
+ {value: 0x0008, lo: 0x93, hi: 0x9f},
+ {value: 0x0040, lo: 0xa0, hi: 0xbf},
+ // Block 0xd7, offset 0x666
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0040, lo: 0x80, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xa1},
+ {value: 0x0040, lo: 0xa2, hi: 0xbf},
+ // Block 0xd8, offset 0x66a
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0008, lo: 0x80, hi: 0xac},
+ {value: 0x0040, lo: 0xad, hi: 0xbf},
+ // Block 0xd9, offset 0x66d
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0008, lo: 0x80, hi: 0xb2},
+ {value: 0x0040, lo: 0xb3, hi: 0xbf},
+ // Block 0xda, offset 0x670
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0008, lo: 0x80, hi: 0x9e},
+ {value: 0x0040, lo: 0x9f, hi: 0xbf},
+ // Block 0xdb, offset 0x673
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0040, lo: 0x80, hi: 0xaf},
+ {value: 0x0008, lo: 0xb0, hi: 0xbf},
+ // Block 0xdc, offset 0x676
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0008, lo: 0x80, hi: 0xbb},
+ {value: 0x0040, lo: 0xbc, hi: 0xbf},
+ // Block 0xdd, offset 0x679
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0008, lo: 0x80, hi: 0xaa},
+ {value: 0x0040, lo: 0xab, hi: 0xaf},
+ {value: 0x0008, lo: 0xb0, hi: 0xbc},
+ {value: 0x0040, lo: 0xbd, hi: 0xbf},
+ // Block 0xde, offset 0x67e
+ {value: 0x0000, lo: 0x09},
+ {value: 0x0008, lo: 0x80, hi: 0x88},
+ {value: 0x0040, lo: 0x89, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x99},
+ {value: 0x0040, lo: 0x9a, hi: 0x9b},
+ {value: 0x0018, lo: 0x9c, hi: 0x9c},
+ {value: 0x3308, lo: 0x9d, hi: 0x9e},
+ {value: 0x0018, lo: 0x9f, hi: 0x9f},
+ {value: 0x03c0, lo: 0xa0, hi: 0xa3},
+ {value: 0x0040, lo: 0xa4, hi: 0xbf},
+ // Block 0xdf, offset 0x688
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0018, lo: 0x80, hi: 0xb5},
+ {value: 0x0040, lo: 0xb6, hi: 0xbf},
+ // Block 0xe0, offset 0x68b
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0018, lo: 0x80, hi: 0xa6},
+ {value: 0x0040, lo: 0xa7, hi: 0xa8},
+ {value: 0x0018, lo: 0xa9, hi: 0xbf},
+ // Block 0xe1, offset 0x68f
+ {value: 0x0000, lo: 0x0e},
+ {value: 0x0018, lo: 0x80, hi: 0x9d},
+ {value: 0xb5b9, lo: 0x9e, hi: 0x9e},
+ {value: 0xb601, lo: 0x9f, hi: 0x9f},
+ {value: 0xb649, lo: 0xa0, hi: 0xa0},
+ {value: 0xb6b1, lo: 0xa1, hi: 0xa1},
+ {value: 0xb719, lo: 0xa2, hi: 0xa2},
+ {value: 0xb781, lo: 0xa3, hi: 0xa3},
+ {value: 0xb7e9, lo: 0xa4, hi: 0xa4},
+ {value: 0x3018, lo: 0xa5, hi: 0xa6},
+ {value: 0x3318, lo: 0xa7, hi: 0xa9},
+ {value: 0x0018, lo: 0xaa, hi: 0xac},
+ {value: 0x3018, lo: 0xad, hi: 0xb2},
+ {value: 0x0340, lo: 0xb3, hi: 0xba},
+ {value: 0x3318, lo: 0xbb, hi: 0xbf},
+ // Block 0xe2, offset 0x69e
+ {value: 0x0000, lo: 0x0b},
+ {value: 0x3318, lo: 0x80, hi: 0x82},
+ {value: 0x0018, lo: 0x83, hi: 0x84},
+ {value: 0x3318, lo: 0x85, hi: 0x8b},
+ {value: 0x0018, lo: 0x8c, hi: 0xa9},
+ {value: 0x3318, lo: 0xaa, hi: 0xad},
+ {value: 0x0018, lo: 0xae, hi: 0xba},
+ {value: 0xb851, lo: 0xbb, hi: 0xbb},
+ {value: 0xb899, lo: 0xbc, hi: 0xbc},
+ {value: 0xb8e1, lo: 0xbd, hi: 0xbd},
+ {value: 0xb949, lo: 0xbe, hi: 0xbe},
+ {value: 0xb9b1, lo: 0xbf, hi: 0xbf},
+ // Block 0xe3, offset 0x6aa
+ {value: 0x0000, lo: 0x03},
+ {value: 0xba19, lo: 0x80, hi: 0x80},
+ {value: 0x0018, lo: 0x81, hi: 0xa8},
+ {value: 0x0040, lo: 0xa9, hi: 0xbf},
+ // Block 0xe4, offset 0x6ae
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0018, lo: 0x80, hi: 0x81},
+ {value: 0x3318, lo: 0x82, hi: 0x84},
+ {value: 0x0018, lo: 0x85, hi: 0x85},
+ {value: 0x0040, lo: 0x86, hi: 0xbf},
+ // Block 0xe5, offset 0x6b3
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0018, lo: 0x80, hi: 0x96},
+ {value: 0x0040, lo: 0x97, hi: 0x9f},
+ {value: 0x0018, lo: 0xa0, hi: 0xb1},
+ {value: 0x0040, lo: 0xb2, hi: 0xbf},
+ // Block 0xe6, offset 0x6b8
+ {value: 0x0000, lo: 0x03},
+ {value: 0x3308, lo: 0x80, hi: 0xb6},
+ {value: 0x0018, lo: 0xb7, hi: 0xba},
+ {value: 0x3308, lo: 0xbb, hi: 0xbf},
+ // Block 0xe7, offset 0x6bc
+ {value: 0x0000, lo: 0x04},
+ {value: 0x3308, lo: 0x80, hi: 0xac},
+ {value: 0x0018, lo: 0xad, hi: 0xb4},
+ {value: 0x3308, lo: 0xb5, hi: 0xb5},
+ {value: 0x0018, lo: 0xb6, hi: 0xbf},
+ // Block 0xe8, offset 0x6c1
+ {value: 0x0000, lo: 0x08},
+ {value: 0x0018, lo: 0x80, hi: 0x83},
+ {value: 0x3308, lo: 0x84, hi: 0x84},
+ {value: 0x0018, lo: 0x85, hi: 0x8b},
+ {value: 0x0040, lo: 0x8c, hi: 0x9a},
+ {value: 0x3308, lo: 0x9b, hi: 0x9f},
+ {value: 0x0040, lo: 0xa0, hi: 0xa0},
+ {value: 0x3308, lo: 0xa1, hi: 0xaf},
+ {value: 0x0040, lo: 0xb0, hi: 0xbf},
+ // Block 0xe9, offset 0x6ca
+ {value: 0x0000, lo: 0x0a},
+ {value: 0x3308, lo: 0x80, hi: 0x86},
+ {value: 0x0040, lo: 0x87, hi: 0x87},
+ {value: 0x3308, lo: 0x88, hi: 0x98},
+ {value: 0x0040, lo: 0x99, hi: 0x9a},
+ {value: 0x3308, lo: 0x9b, hi: 0xa1},
+ {value: 0x0040, lo: 0xa2, hi: 0xa2},
+ {value: 0x3308, lo: 0xa3, hi: 0xa4},
+ {value: 0x0040, lo: 0xa5, hi: 0xa5},
+ {value: 0x3308, lo: 0xa6, hi: 0xaa},
+ {value: 0x0040, lo: 0xab, hi: 0xbf},
+ // Block 0xea, offset 0x6d5
+ {value: 0x0000, lo: 0x05},
+ {value: 0x0808, lo: 0x80, hi: 0x84},
+ {value: 0x0040, lo: 0x85, hi: 0x86},
+ {value: 0x0818, lo: 0x87, hi: 0x8f},
+ {value: 0x3308, lo: 0x90, hi: 0x96},
+ {value: 0x0040, lo: 0x97, hi: 0xbf},
+ // Block 0xeb, offset 0x6db
+ {value: 0x0000, lo: 0x07},
+ {value: 0x0a08, lo: 0x80, hi: 0x83},
+ {value: 0x3308, lo: 0x84, hi: 0x8a},
+ {value: 0x0040, lo: 0x8b, hi: 0x8f},
+ {value: 0x0808, lo: 0x90, hi: 0x99},
+ {value: 0x0040, lo: 0x9a, hi: 0x9d},
+ {value: 0x0818, lo: 0x9e, hi: 0x9f},
+ {value: 0x0040, lo: 0xa0, hi: 0xbf},
+ // Block 0xec, offset 0x6e3
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0040, lo: 0x80, hi: 0xaf},
+ {value: 0x0018, lo: 0xb0, hi: 0xb1},
+ {value: 0x0040, lo: 0xb2, hi: 0xbf},
+ // Block 0xed, offset 0x6e7
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0018, lo: 0x80, hi: 0xab},
+ {value: 0x0040, lo: 0xac, hi: 0xaf},
+ {value: 0x0018, lo: 0xb0, hi: 0xbf},
+ // Block 0xee, offset 0x6eb
+ {value: 0x0000, lo: 0x05},
+ {value: 0x0018, lo: 0x80, hi: 0x93},
+ {value: 0x0040, lo: 0x94, hi: 0x9f},
+ {value: 0x0018, lo: 0xa0, hi: 0xae},
+ {value: 0x0040, lo: 0xaf, hi: 0xb0},
+ {value: 0x0018, lo: 0xb1, hi: 0xbf},
+ // Block 0xef, offset 0x6f1
+ {value: 0x0000, lo: 0x05},
+ {value: 0x0040, lo: 0x80, hi: 0x80},
+ {value: 0x0018, lo: 0x81, hi: 0x8f},
+ {value: 0x0040, lo: 0x90, hi: 0x90},
+ {value: 0x0018, lo: 0x91, hi: 0xb5},
+ {value: 0x0040, lo: 0xb6, hi: 0xbf},
+ // Block 0xf0, offset 0x6f7
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0018, lo: 0x80, hi: 0x8f},
+ {value: 0xc1c1, lo: 0x90, hi: 0x90},
+ {value: 0x0018, lo: 0x91, hi: 0xac},
+ {value: 0x0040, lo: 0xad, hi: 0xbf},
+ // Block 0xf1, offset 0x6fc
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0040, lo: 0x80, hi: 0xa5},
+ {value: 0x0018, lo: 0xa6, hi: 0xbf},
+ // Block 0xf2, offset 0x6ff
+ {value: 0x0000, lo: 0x0f},
+ {value: 0xc7e9, lo: 0x80, hi: 0x80},
+ {value: 0xc839, lo: 0x81, hi: 0x81},
+ {value: 0xc889, lo: 0x82, hi: 0x82},
+ {value: 0xc8d9, lo: 0x83, hi: 0x83},
+ {value: 0xc929, lo: 0x84, hi: 0x84},
+ {value: 0xc979, lo: 0x85, hi: 0x85},
+ {value: 0xc9c9, lo: 0x86, hi: 0x86},
+ {value: 0xca19, lo: 0x87, hi: 0x87},
+ {value: 0xca69, lo: 0x88, hi: 0x88},
+ {value: 0x0040, lo: 0x89, hi: 0x8f},
+ {value: 0xcab9, lo: 0x90, hi: 0x90},
+ {value: 0xcad9, lo: 0x91, hi: 0x91},
+ {value: 0x0040, lo: 0x92, hi: 0x9f},
+ {value: 0x0018, lo: 0xa0, hi: 0xa5},
+ {value: 0x0040, lo: 0xa6, hi: 0xbf},
+ // Block 0xf3, offset 0x70f
+ {value: 0x0000, lo: 0x06},
+ {value: 0x0018, lo: 0x80, hi: 0x94},
+ {value: 0x0040, lo: 0x95, hi: 0x9f},
+ {value: 0x0018, lo: 0xa0, hi: 0xac},
+ {value: 0x0040, lo: 0xad, hi: 0xaf},
+ {value: 0x0018, lo: 0xb0, hi: 0xb8},
+ {value: 0x0040, lo: 0xb9, hi: 0xbf},
+ // Block 0xf4, offset 0x716
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0018, lo: 0x80, hi: 0xb3},
+ {value: 0x0040, lo: 0xb4, hi: 0xbf},
+ // Block 0xf5, offset 0x719
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0018, lo: 0x80, hi: 0x94},
+ {value: 0x0040, lo: 0x95, hi: 0xbf},
+ // Block 0xf6, offset 0x71c
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0018, lo: 0x80, hi: 0x8b},
+ {value: 0x0040, lo: 0x8c, hi: 0x8f},
+ {value: 0x0018, lo: 0x90, hi: 0xbf},
+ // Block 0xf7, offset 0x720
+ {value: 0x0000, lo: 0x05},
+ {value: 0x0018, lo: 0x80, hi: 0x87},
+ {value: 0x0040, lo: 0x88, hi: 0x8f},
+ {value: 0x0018, lo: 0x90, hi: 0x99},
+ {value: 0x0040, lo: 0x9a, hi: 0x9f},
+ {value: 0x0018, lo: 0xa0, hi: 0xbf},
+ // Block 0xf8, offset 0x726
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0018, lo: 0x80, hi: 0x87},
+ {value: 0x0040, lo: 0x88, hi: 0x8f},
+ {value: 0x0018, lo: 0x90, hi: 0xad},
+ {value: 0x0040, lo: 0xae, hi: 0xbf},
+ // Block 0xf9, offset 0x72b
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0018, lo: 0x80, hi: 0x8b},
+ {value: 0x0040, lo: 0x8c, hi: 0x8f},
+ {value: 0x0018, lo: 0x90, hi: 0xbe},
+ {value: 0x0040, lo: 0xbf, hi: 0xbf},
+ // Block 0xfa, offset 0x730
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0018, lo: 0x80, hi: 0x8c},
+ {value: 0x0040, lo: 0x8d, hi: 0x8f},
+ {value: 0x0018, lo: 0x90, hi: 0xab},
+ {value: 0x0040, lo: 0xac, hi: 0xbf},
+ // Block 0xfb, offset 0x735
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0018, lo: 0x80, hi: 0x97},
+ {value: 0x0040, lo: 0x98, hi: 0xbf},
+ // Block 0xfc, offset 0x738
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0018, lo: 0x80, hi: 0x80},
+ {value: 0x0040, lo: 0x81, hi: 0x8f},
+ {value: 0x0018, lo: 0x90, hi: 0xa6},
+ {value: 0x0040, lo: 0xa7, hi: 0xbf},
+ // Block 0xfd, offset 0x73d
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0008, lo: 0x80, hi: 0x96},
+ {value: 0x0040, lo: 0x97, hi: 0xbf},
+ // Block 0xfe, offset 0x740
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0008, lo: 0x80, hi: 0xb4},
+ {value: 0x0040, lo: 0xb5, hi: 0xbf},
+ // Block 0xff, offset 0x743
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0008, lo: 0x80, hi: 0x9d},
+ {value: 0x0040, lo: 0x9e, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xbf},
+ // Block 0x100, offset 0x747
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0008, lo: 0x80, hi: 0xa1},
+ {value: 0x0040, lo: 0xa2, hi: 0xaf},
+ {value: 0x0008, lo: 0xb0, hi: 0xbf},
+ // Block 0x101, offset 0x74b
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0008, lo: 0x80, hi: 0xa0},
+ {value: 0x0040, lo: 0xa1, hi: 0xbf},
+ // Block 0x102, offset 0x74e
+ {value: 0x0020, lo: 0x0f},
+ {value: 0xdeb9, lo: 0x80, hi: 0x89},
+ {value: 0x8dfd, lo: 0x8a, hi: 0x8a},
+ {value: 0xdff9, lo: 0x8b, hi: 0x9c},
+ {value: 0x8e1d, lo: 0x9d, hi: 0x9d},
+ {value: 0xe239, lo: 0x9e, hi: 0xa2},
+ {value: 0x8e3d, lo: 0xa3, hi: 0xa3},
+ {value: 0xe2d9, lo: 0xa4, hi: 0xab},
+ {value: 0x7ed5, lo: 0xac, hi: 0xac},
+ {value: 0xe3d9, lo: 0xad, hi: 0xaf},
+ {value: 0x8e5d, lo: 0xb0, hi: 0xb0},
+ {value: 0xe439, lo: 0xb1, hi: 0xb6},
+ {value: 0x8e7d, lo: 0xb7, hi: 0xb9},
+ {value: 0xe4f9, lo: 0xba, hi: 0xba},
+ {value: 0x8edd, lo: 0xbb, hi: 0xbb},
+ {value: 0xe519, lo: 0xbc, hi: 0xbf},
+ // Block 0x103, offset 0x75e
+ {value: 0x0020, lo: 0x10},
+ {value: 0x937d, lo: 0x80, hi: 0x80},
+ {value: 0xf099, lo: 0x81, hi: 0x86},
+ {value: 0x939d, lo: 0x87, hi: 0x8a},
+ {value: 0xd9f9, lo: 0x8b, hi: 0x8b},
+ {value: 0xf159, lo: 0x8c, hi: 0x96},
+ {value: 0x941d, lo: 0x97, hi: 0x97},
+ {value: 0xf2b9, lo: 0x98, hi: 0xa3},
+ {value: 0x943d, lo: 0xa4, hi: 0xa6},
+ {value: 0xf439, lo: 0xa7, hi: 0xaa},
+ {value: 0x949d, lo: 0xab, hi: 0xab},
+ {value: 0xf4b9, lo: 0xac, hi: 0xac},
+ {value: 0x94bd, lo: 0xad, hi: 0xad},
+ {value: 0xf4d9, lo: 0xae, hi: 0xaf},
+ {value: 0x94dd, lo: 0xb0, hi: 0xb1},
+ {value: 0xf519, lo: 0xb2, hi: 0xbe},
+ {value: 0x2040, lo: 0xbf, hi: 0xbf},
+ // Block 0x104, offset 0x76f
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0040, lo: 0x80, hi: 0x80},
+ {value: 0x0340, lo: 0x81, hi: 0x81},
+ {value: 0x0040, lo: 0x82, hi: 0x9f},
+ {value: 0x0340, lo: 0xa0, hi: 0xbf},
+ // Block 0x105, offset 0x774
+ {value: 0x0000, lo: 0x01},
+ {value: 0x0340, lo: 0x80, hi: 0xbf},
+ // Block 0x106, offset 0x776
+ {value: 0x0000, lo: 0x01},
+ {value: 0x33c0, lo: 0x80, hi: 0xbf},
+ // Block 0x107, offset 0x778
+ {value: 0x0000, lo: 0x02},
+ {value: 0x33c0, lo: 0x80, hi: 0xaf},
+ {value: 0x0040, lo: 0xb0, hi: 0xbf},
+}
+
+// Total table size 42115 bytes (41KiB); checksum: F4A1FA4E
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/idna/trie.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/idna/trie.go
new file mode 100644
index 000000000..c4ef847e7
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/idna/trie.go
@@ -0,0 +1,72 @@
+// 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.
+
+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
+}
+
+// Sparse block handling code.
+
+type valueRange struct {
+ value uint16 // header: value:stride
+ lo, hi byte // header: lo:n
+}
+
+type sparseBlocks struct {
+ values []valueRange
+ offset []uint16
+}
+
+var idnaSparse = sparseBlocks{
+ values: idnaSparseValues[:],
+ offset: idnaSparseOffset[:],
+}
+
+// Don't use newIdnaTrie to avoid unconditional linking in of the table.
+var trie = &idnaTrie{}
+
+// lookup determines the type of block n and looks up the value for b.
+// For n < t.cutoff, the block is a simple lookup table. Otherwise, the block
+// is a list of ranges with an accompanying value. Given a matching range r,
+// the value for b is by r.value + (b - r.lo) * stride.
+func (t *sparseBlocks) lookup(n uint32, b byte) uint16 {
+ offset := t.offset[n]
+ header := t.values[offset]
+ lo := offset + 1
+ hi := lo + uint16(header.lo)
+ for lo < hi {
+ m := lo + (hi-lo)/2
+ r := t.values[m]
+ if r.lo <= b && b <= r.hi {
+ return r.value + uint16(b-r.lo)*header.value
+ }
+ if b < r.lo {
+ hi = m
+ } else {
+ lo = m + 1
+ }
+ }
+ return 0
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/idna/trieval.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/idna/trieval.go
new file mode 100644
index 000000000..7a8cf889b
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/idna/trieval.go
@@ -0,0 +1,119 @@
+// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
+
+package idna
+
+// This file contains definitions for interpreting the trie value of the idna
+// trie generated by "go run gen*.go". It is shared by both the generator
+// program and the resultant package. Sharing is achieved by the generator
+// copying gen_trieval.go to trieval.go and changing what's above this comment.
+
+// info holds information from the IDNA mapping table for a single rune. It is
+// the value returned by a trie lookup. In most cases, all information fits in
+// a 16-bit value. For mappings, this value may contain an index into a slice
+// with the mapped string. Such mappings can consist of the actual mapped value
+// or an XOR pattern to be applied to the bytes of the UTF8 encoding of the
+// input rune. This technique is used by the cases packages and reduces the
+// table size significantly.
+//
+// The per-rune values have the following format:
+//
+// if mapped {
+// if inlinedXOR {
+// 15..13 inline XOR marker
+// 12..11 unused
+// 10..3 inline XOR mask
+// } else {
+// 15..3 index into xor or mapping table
+// }
+// } else {
+// 15..14 unused
+// 13 mayNeedNorm
+// 12..11 attributes
+// 10..8 joining type
+// 7..3 category type
+// }
+// 2 use xor pattern
+// 1..0 mapped category
+//
+// See the definitions below for a more detailed description of the various
+// bits.
+type info uint16
+
+const (
+ catSmallMask = 0x3
+ catBigMask = 0xF8
+ indexShift = 3
+ xorBit = 0x4 // interpret the index as an xor pattern
+ inlineXOR = 0xE000 // These bits are set if the XOR pattern is inlined.
+
+ joinShift = 8
+ joinMask = 0x07
+
+ // Attributes
+ attributesMask = 0x1800
+ viramaModifier = 0x1800
+ modifier = 0x1000
+ rtl = 0x0800
+
+ mayNeedNorm = 0x2000
+)
+
+// A category corresponds to a category defined in the IDNA mapping table.
+type category uint16
+
+const (
+ unknown category = 0 // not currently defined in unicode.
+ mapped category = 1
+ disallowedSTD3Mapped category = 2
+ deviation category = 3
+)
+
+const (
+ valid category = 0x08
+ validNV8 category = 0x18
+ validXV8 category = 0x28
+ disallowed category = 0x40
+ disallowedSTD3Valid category = 0x80
+ ignored category = 0xC0
+)
+
+// join types and additional rune information
+const (
+ joiningL = (iota + 1)
+ joiningD
+ joiningT
+ joiningR
+
+ //the following types are derived during processing
+ joinZWJ
+ joinZWNJ
+ joinVirama
+ numJoinTypes
+)
+
+func (c info) isMapped() bool {
+ return c&0x3 != 0
+}
+
+func (c info) category() category {
+ small := c & catSmallMask
+ if small != 0 {
+ return category(small)
+ }
+ return category(c & catBigMask)
+}
+
+func (c info) joinType() info {
+ if c.isMapped() {
+ return 0
+ }
+ return (c >> joinShift) & joinMask
+}
+
+func (c info) isModifier() bool {
+ return c&(modifier|catSmallMask) == modifier
+}
+
+func (c info) isViramaModifier() bool {
+ return c&(attributesMask|catSmallMask) == viramaModifier
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/iana/const.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/iana/const.go
new file mode 100644
index 000000000..c9df24d95
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/iana/const.go
@@ -0,0 +1,180 @@
+// go generate gen.go
+// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
+
+// Package iana provides protocol number resources managed by the Internet Assigned Numbers Authority (IANA).
+package iana // import "golang.org/x/net/internal/iana"
+
+// Differentiated Services Field Codepoints (DSCP), Updated: 2017-05-12
+const (
+ DiffServCS0 = 0x0 // CS0
+ DiffServCS1 = 0x20 // CS1
+ DiffServCS2 = 0x40 // CS2
+ DiffServCS3 = 0x60 // CS3
+ DiffServCS4 = 0x80 // CS4
+ DiffServCS5 = 0xa0 // CS5
+ DiffServCS6 = 0xc0 // CS6
+ DiffServCS7 = 0xe0 // CS7
+ DiffServAF11 = 0x28 // AF11
+ DiffServAF12 = 0x30 // AF12
+ DiffServAF13 = 0x38 // AF13
+ DiffServAF21 = 0x48 // AF21
+ DiffServAF22 = 0x50 // AF22
+ DiffServAF23 = 0x58 // AF23
+ DiffServAF31 = 0x68 // AF31
+ DiffServAF32 = 0x70 // AF32
+ DiffServAF33 = 0x78 // AF33
+ DiffServAF41 = 0x88 // AF41
+ DiffServAF42 = 0x90 // AF42
+ DiffServAF43 = 0x98 // AF43
+ DiffServEF = 0xb8 // EF
+ DiffServVOICEADMIT = 0xb0 // VOICE-ADMIT
+)
+
+// IPv4 TOS Byte and IPv6 Traffic Class Octet, Updated: 2001-09-06
+const (
+ NotECNTransport = 0x0 // Not-ECT (Not ECN-Capable Transport)
+ ECNTransport1 = 0x1 // ECT(1) (ECN-Capable Transport(1))
+ ECNTransport0 = 0x2 // ECT(0) (ECN-Capable Transport(0))
+ CongestionExperienced = 0x3 // CE (Congestion Experienced)
+)
+
+// Protocol Numbers, Updated: 2016-06-22
+const (
+ ProtocolIP = 0 // IPv4 encapsulation, pseudo protocol number
+ ProtocolHOPOPT = 0 // IPv6 Hop-by-Hop Option
+ ProtocolICMP = 1 // Internet Control Message
+ ProtocolIGMP = 2 // Internet Group Management
+ ProtocolGGP = 3 // Gateway-to-Gateway
+ ProtocolIPv4 = 4 // IPv4 encapsulation
+ ProtocolST = 5 // Stream
+ ProtocolTCP = 6 // Transmission Control
+ ProtocolCBT = 7 // CBT
+ ProtocolEGP = 8 // Exterior Gateway Protocol
+ ProtocolIGP = 9 // any private interior gateway (used by Cisco for their IGRP)
+ ProtocolBBNRCCMON = 10 // BBN RCC Monitoring
+ ProtocolNVPII = 11 // Network Voice Protocol
+ ProtocolPUP = 12 // PUP
+ ProtocolEMCON = 14 // EMCON
+ ProtocolXNET = 15 // Cross Net Debugger
+ ProtocolCHAOS = 16 // Chaos
+ ProtocolUDP = 17 // User Datagram
+ ProtocolMUX = 18 // Multiplexing
+ ProtocolDCNMEAS = 19 // DCN Measurement Subsystems
+ ProtocolHMP = 20 // Host Monitoring
+ ProtocolPRM = 21 // Packet Radio Measurement
+ ProtocolXNSIDP = 22 // XEROX NS IDP
+ ProtocolTRUNK1 = 23 // Trunk-1
+ ProtocolTRUNK2 = 24 // Trunk-2
+ ProtocolLEAF1 = 25 // Leaf-1
+ ProtocolLEAF2 = 26 // Leaf-2
+ ProtocolRDP = 27 // Reliable Data Protocol
+ ProtocolIRTP = 28 // Internet Reliable Transaction
+ ProtocolISOTP4 = 29 // ISO Transport Protocol Class 4
+ ProtocolNETBLT = 30 // Bulk Data Transfer Protocol
+ ProtocolMFENSP = 31 // MFE Network Services Protocol
+ ProtocolMERITINP = 32 // MERIT Internodal Protocol
+ ProtocolDCCP = 33 // Datagram Congestion Control Protocol
+ Protocol3PC = 34 // Third Party Connect Protocol
+ ProtocolIDPR = 35 // Inter-Domain Policy Routing Protocol
+ ProtocolXTP = 36 // XTP
+ ProtocolDDP = 37 // Datagram Delivery Protocol
+ ProtocolIDPRCMTP = 38 // IDPR Control Message Transport Proto
+ ProtocolTPPP = 39 // TP++ Transport Protocol
+ ProtocolIL = 40 // IL Transport Protocol
+ ProtocolIPv6 = 41 // IPv6 encapsulation
+ ProtocolSDRP = 42 // Source Demand Routing Protocol
+ ProtocolIPv6Route = 43 // Routing Header for IPv6
+ ProtocolIPv6Frag = 44 // Fragment Header for IPv6
+ ProtocolIDRP = 45 // Inter-Domain Routing Protocol
+ ProtocolRSVP = 46 // Reservation Protocol
+ ProtocolGRE = 47 // Generic Routing Encapsulation
+ ProtocolDSR = 48 // Dynamic Source Routing Protocol
+ ProtocolBNA = 49 // BNA
+ ProtocolESP = 50 // Encap Security Payload
+ ProtocolAH = 51 // Authentication Header
+ ProtocolINLSP = 52 // Integrated Net Layer Security TUBA
+ ProtocolNARP = 54 // NBMA Address Resolution Protocol
+ ProtocolMOBILE = 55 // IP Mobility
+ ProtocolTLSP = 56 // Transport Layer Security Protocol using Kryptonet key management
+ ProtocolSKIP = 57 // SKIP
+ ProtocolIPv6ICMP = 58 // ICMP for IPv6
+ ProtocolIPv6NoNxt = 59 // No Next Header for IPv6
+ ProtocolIPv6Opts = 60 // Destination Options for IPv6
+ ProtocolCFTP = 62 // CFTP
+ ProtocolSATEXPAK = 64 // SATNET and Backroom EXPAK
+ ProtocolKRYPTOLAN = 65 // Kryptolan
+ ProtocolRVD = 66 // MIT Remote Virtual Disk Protocol
+ ProtocolIPPC = 67 // Internet Pluribus Packet Core
+ ProtocolSATMON = 69 // SATNET Monitoring
+ ProtocolVISA = 70 // VISA Protocol
+ ProtocolIPCV = 71 // Internet Packet Core Utility
+ ProtocolCPNX = 72 // Computer Protocol Network Executive
+ ProtocolCPHB = 73 // Computer Protocol Heart Beat
+ ProtocolWSN = 74 // Wang Span Network
+ ProtocolPVP = 75 // Packet Video Protocol
+ ProtocolBRSATMON = 76 // Backroom SATNET Monitoring
+ ProtocolSUNND = 77 // SUN ND PROTOCOL-Temporary
+ ProtocolWBMON = 78 // WIDEBAND Monitoring
+ ProtocolWBEXPAK = 79 // WIDEBAND EXPAK
+ ProtocolISOIP = 80 // ISO Internet Protocol
+ ProtocolVMTP = 81 // VMTP
+ ProtocolSECUREVMTP = 82 // SECURE-VMTP
+ ProtocolVINES = 83 // VINES
+ ProtocolTTP = 84 // Transaction Transport Protocol
+ ProtocolIPTM = 84 // Internet Protocol Traffic Manager
+ ProtocolNSFNETIGP = 85 // NSFNET-IGP
+ ProtocolDGP = 86 // Dissimilar Gateway Protocol
+ ProtocolTCF = 87 // TCF
+ ProtocolEIGRP = 88 // EIGRP
+ ProtocolOSPFIGP = 89 // OSPFIGP
+ ProtocolSpriteRPC = 90 // Sprite RPC Protocol
+ ProtocolLARP = 91 // Locus Address Resolution Protocol
+ ProtocolMTP = 92 // Multicast Transport Protocol
+ ProtocolAX25 = 93 // AX.25 Frames
+ ProtocolIPIP = 94 // IP-within-IP Encapsulation Protocol
+ ProtocolSCCSP = 96 // Semaphore Communications Sec. Pro.
+ ProtocolETHERIP = 97 // Ethernet-within-IP Encapsulation
+ ProtocolENCAP = 98 // Encapsulation Header
+ ProtocolGMTP = 100 // GMTP
+ ProtocolIFMP = 101 // Ipsilon Flow Management Protocol
+ ProtocolPNNI = 102 // PNNI over IP
+ ProtocolPIM = 103 // Protocol Independent Multicast
+ ProtocolARIS = 104 // ARIS
+ ProtocolSCPS = 105 // SCPS
+ ProtocolQNX = 106 // QNX
+ ProtocolAN = 107 // Active Networks
+ ProtocolIPComp = 108 // IP Payload Compression Protocol
+ ProtocolSNP = 109 // Sitara Networks Protocol
+ ProtocolCompaqPeer = 110 // Compaq Peer Protocol
+ ProtocolIPXinIP = 111 // IPX in IP
+ ProtocolVRRP = 112 // Virtual Router Redundancy Protocol
+ ProtocolPGM = 113 // PGM Reliable Transport Protocol
+ ProtocolL2TP = 115 // Layer Two Tunneling Protocol
+ ProtocolDDX = 116 // D-II Data Exchange (DDX)
+ ProtocolIATP = 117 // Interactive Agent Transfer Protocol
+ ProtocolSTP = 118 // Schedule Transfer Protocol
+ ProtocolSRP = 119 // SpectraLink Radio Protocol
+ ProtocolUTI = 120 // UTI
+ ProtocolSMP = 121 // Simple Message Protocol
+ ProtocolPTP = 123 // Performance Transparency Protocol
+ ProtocolISIS = 124 // ISIS over IPv4
+ ProtocolFIRE = 125 // FIRE
+ ProtocolCRTP = 126 // Combat Radio Transport Protocol
+ ProtocolCRUDP = 127 // Combat Radio User Datagram
+ ProtocolSSCOPMCE = 128 // SSCOPMCE
+ ProtocolIPLT = 129 // IPLT
+ ProtocolSPS = 130 // Secure Packet Shield
+ ProtocolPIPE = 131 // Private IP Encapsulation within IP
+ ProtocolSCTP = 132 // Stream Control Transmission Protocol
+ ProtocolFC = 133 // Fibre Channel
+ ProtocolRSVPE2EIGNORE = 134 // RSVP-E2E-IGNORE
+ ProtocolMobilityHeader = 135 // Mobility Header
+ ProtocolUDPLite = 136 // UDPLite
+ ProtocolMPLSinIP = 137 // MPLS-in-IP
+ ProtocolMANET = 138 // MANET Protocols
+ ProtocolHIP = 139 // Host Identity Protocol
+ ProtocolShim6 = 140 // Shim6 Protocol
+ ProtocolWESP = 141 // Wrapped Encapsulating Security Payload
+ ProtocolROHC = 142 // Robust Header Compression
+ ProtocolReserved = 255 // Reserved
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/iana/gen.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/iana/gen.go
new file mode 100644
index 000000000..86c78b3bb
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/iana/gen.go
@@ -0,0 +1,293 @@
+// Copyright 2013 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.
+
+// +build ignore
+
+//go:generate go run gen.go
+
+// This program generates internet protocol constants and tables by
+// reading IANA protocol registries.
+package main
+
+import (
+ "bytes"
+ "encoding/xml"
+ "fmt"
+ "go/format"
+ "io"
+ "io/ioutil"
+ "net/http"
+ "os"
+ "strconv"
+ "strings"
+)
+
+var registries = []struct {
+ url string
+ parse func(io.Writer, io.Reader) error
+}{
+ {
+ "http://www.iana.org/assignments/dscp-registry/dscp-registry.xml",
+ parseDSCPRegistry,
+ },
+ {
+ "http://www.iana.org/assignments/ipv4-tos-byte/ipv4-tos-byte.xml",
+ parseTOSTCByte,
+ },
+ {
+ "http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xml",
+ parseProtocolNumbers,
+ },
+}
+
+func main() {
+ var bb bytes.Buffer
+ fmt.Fprintf(&bb, "// go generate gen.go\n")
+ fmt.Fprintf(&bb, "// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT\n\n")
+ fmt.Fprintf(&bb, "// Package iana provides protocol number resources managed by the Internet Assigned Numbers Authority (IANA).\n")
+ fmt.Fprintf(&bb, `package iana // import "golang.org/x/net/internal/iana"`+"\n\n")
+ for _, r := range registries {
+ resp, err := http.Get(r.url)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+ defer resp.Body.Close()
+ if resp.StatusCode != http.StatusOK {
+ fmt.Fprintf(os.Stderr, "got HTTP status code %v for %v\n", resp.StatusCode, r.url)
+ os.Exit(1)
+ }
+ if err := r.parse(&bb, resp.Body); err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+ fmt.Fprintf(&bb, "\n")
+ }
+ b, err := format.Source(bb.Bytes())
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+ if err := ioutil.WriteFile("const.go", b, 0644); err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+}
+
+func parseDSCPRegistry(w io.Writer, r io.Reader) error {
+ dec := xml.NewDecoder(r)
+ var dr dscpRegistry
+ if err := dec.Decode(&dr); err != nil {
+ return err
+ }
+ drs := dr.escape()
+ fmt.Fprintf(w, "// %s, Updated: %s\n", dr.Title, dr.Updated)
+ fmt.Fprintf(w, "const (\n")
+ for _, dr := range drs {
+ fmt.Fprintf(w, "DiffServ%s = %#x", dr.Name, dr.Value)
+ fmt.Fprintf(w, "// %s\n", dr.OrigName)
+ }
+ fmt.Fprintf(w, ")\n")
+ return nil
+}
+
+type dscpRegistry struct {
+ XMLName xml.Name `xml:"registry"`
+ Title string `xml:"title"`
+ Updated string `xml:"updated"`
+ Note string `xml:"note"`
+ RegTitle string `xml:"registry>title"`
+ PoolRecords []struct {
+ Name string `xml:"name"`
+ Space string `xml:"space"`
+ } `xml:"registry>record"`
+ Records []struct {
+ Name string `xml:"name"`
+ Space string `xml:"space"`
+ } `xml:"registry>registry>record"`
+}
+
+type canonDSCPRecord struct {
+ OrigName string
+ Name string
+ Value int
+}
+
+func (drr *dscpRegistry) escape() []canonDSCPRecord {
+ drs := make([]canonDSCPRecord, len(drr.Records))
+ sr := strings.NewReplacer(
+ "+", "",
+ "-", "",
+ "/", "",
+ ".", "",
+ " ", "",
+ )
+ for i, dr := range drr.Records {
+ s := strings.TrimSpace(dr.Name)
+ drs[i].OrigName = s
+ drs[i].Name = sr.Replace(s)
+ n, err := strconv.ParseUint(dr.Space, 2, 8)
+ if err != nil {
+ continue
+ }
+ drs[i].Value = int(n) << 2
+ }
+ return drs
+}
+
+func parseTOSTCByte(w io.Writer, r io.Reader) error {
+ dec := xml.NewDecoder(r)
+ var ttb tosTCByte
+ if err := dec.Decode(&ttb); err != nil {
+ return err
+ }
+ trs := ttb.escape()
+ fmt.Fprintf(w, "// %s, Updated: %s\n", ttb.Title, ttb.Updated)
+ fmt.Fprintf(w, "const (\n")
+ for _, tr := range trs {
+ fmt.Fprintf(w, "%s = %#x", tr.Keyword, tr.Value)
+ fmt.Fprintf(w, "// %s\n", tr.OrigKeyword)
+ }
+ fmt.Fprintf(w, ")\n")
+ return nil
+}
+
+type tosTCByte struct {
+ XMLName xml.Name `xml:"registry"`
+ Title string `xml:"title"`
+ Updated string `xml:"updated"`
+ Note string `xml:"note"`
+ RegTitle string `xml:"registry>title"`
+ Records []struct {
+ Binary string `xml:"binary"`
+ Keyword string `xml:"keyword"`
+ } `xml:"registry>record"`
+}
+
+type canonTOSTCByteRecord struct {
+ OrigKeyword string
+ Keyword string
+ Value int
+}
+
+func (ttb *tosTCByte) escape() []canonTOSTCByteRecord {
+ trs := make([]canonTOSTCByteRecord, len(ttb.Records))
+ sr := strings.NewReplacer(
+ "Capable", "",
+ "(", "",
+ ")", "",
+ "+", "",
+ "-", "",
+ "/", "",
+ ".", "",
+ " ", "",
+ )
+ for i, tr := range ttb.Records {
+ s := strings.TrimSpace(tr.Keyword)
+ trs[i].OrigKeyword = s
+ ss := strings.Split(s, " ")
+ if len(ss) > 1 {
+ trs[i].Keyword = strings.Join(ss[1:], " ")
+ } else {
+ trs[i].Keyword = ss[0]
+ }
+ trs[i].Keyword = sr.Replace(trs[i].Keyword)
+ n, err := strconv.ParseUint(tr.Binary, 2, 8)
+ if err != nil {
+ continue
+ }
+ trs[i].Value = int(n)
+ }
+ return trs
+}
+
+func parseProtocolNumbers(w io.Writer, r io.Reader) error {
+ dec := xml.NewDecoder(r)
+ var pn protocolNumbers
+ if err := dec.Decode(&pn); err != nil {
+ return err
+ }
+ prs := pn.escape()
+ prs = append([]canonProtocolRecord{{
+ Name: "IP",
+ Descr: "IPv4 encapsulation, pseudo protocol number",
+ Value: 0,
+ }}, prs...)
+ fmt.Fprintf(w, "// %s, Updated: %s\n", pn.Title, pn.Updated)
+ fmt.Fprintf(w, "const (\n")
+ for _, pr := range prs {
+ if pr.Name == "" {
+ continue
+ }
+ fmt.Fprintf(w, "Protocol%s = %d", pr.Name, pr.Value)
+ s := pr.Descr
+ if s == "" {
+ s = pr.OrigName
+ }
+ fmt.Fprintf(w, "// %s\n", s)
+ }
+ fmt.Fprintf(w, ")\n")
+ return nil
+}
+
+type protocolNumbers struct {
+ XMLName xml.Name `xml:"registry"`
+ Title string `xml:"title"`
+ Updated string `xml:"updated"`
+ RegTitle string `xml:"registry>title"`
+ Note string `xml:"registry>note"`
+ Records []struct {
+ Value string `xml:"value"`
+ Name string `xml:"name"`
+ Descr string `xml:"description"`
+ } `xml:"registry>record"`
+}
+
+type canonProtocolRecord struct {
+ OrigName string
+ Name string
+ Descr string
+ Value int
+}
+
+func (pn *protocolNumbers) escape() []canonProtocolRecord {
+ prs := make([]canonProtocolRecord, len(pn.Records))
+ sr := strings.NewReplacer(
+ "-in-", "in",
+ "-within-", "within",
+ "-over-", "over",
+ "+", "P",
+ "-", "",
+ "/", "",
+ ".", "",
+ " ", "",
+ )
+ for i, pr := range pn.Records {
+ if strings.Contains(pr.Name, "Deprecated") ||
+ strings.Contains(pr.Name, "deprecated") {
+ continue
+ }
+ prs[i].OrigName = pr.Name
+ s := strings.TrimSpace(pr.Name)
+ switch pr.Name {
+ case "ISIS over IPv4":
+ prs[i].Name = "ISIS"
+ case "manet":
+ prs[i].Name = "MANET"
+ default:
+ prs[i].Name = sr.Replace(s)
+ }
+ ss := strings.Split(pr.Descr, "\n")
+ for i := range ss {
+ ss[i] = strings.TrimSpace(ss[i])
+ }
+ if len(ss) > 1 {
+ prs[i].Descr = strings.Join(ss, " ")
+ } else {
+ prs[i].Descr = ss[0]
+ }
+ prs[i].Value, _ = strconv.Atoi(pr.Value)
+ }
+ return prs
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/nettest/helper_bsd.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/nettest/helper_bsd.go
new file mode 100644
index 000000000..a6e433b58
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/nettest/helper_bsd.go
@@ -0,0 +1,53 @@
+// 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.
+
+// +build darwin dragonfly freebsd netbsd openbsd
+
+package nettest
+
+import (
+ "runtime"
+ "strconv"
+ "strings"
+ "syscall"
+)
+
+var darwinVersion int
+
+func init() {
+ if runtime.GOOS == "darwin" {
+ // See http://support.apple.com/kb/HT1633.
+ s, err := syscall.Sysctl("kern.osrelease")
+ if err != nil {
+ return
+ }
+ ss := strings.Split(s, ".")
+ if len(ss) == 0 {
+ return
+ }
+ darwinVersion, _ = strconv.Atoi(ss[0])
+ }
+}
+
+func supportsIPv6MulticastDeliveryOnLoopback() bool {
+ switch runtime.GOOS {
+ case "freebsd":
+ // See http://www.freebsd.org/cgi/query-pr.cgi?pr=180065.
+ // Even after the fix, it looks like the latest
+ // kernels don't deliver link-local scoped multicast
+ // packets correctly.
+ return false
+ case "darwin":
+ return !causesIPv6Crash()
+ default:
+ return true
+ }
+}
+
+func causesIPv6Crash() bool {
+ // We see some kernel crash when running IPv6 with IP-level
+ // options on Darwin kernel version 12 or below.
+ // See golang.org/issues/17015.
+ return darwinVersion < 13
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/nettest/helper_nobsd.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/nettest/helper_nobsd.go
new file mode 100644
index 000000000..bc7da5e0d
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/nettest/helper_nobsd.go
@@ -0,0 +1,15 @@
+// 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.
+
+// +build linux solaris
+
+package nettest
+
+func supportsIPv6MulticastDeliveryOnLoopback() bool {
+ return true
+}
+
+func causesIPv6Crash() bool {
+ return false
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/nettest/helper_posix.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/nettest/helper_posix.go
new file mode 100644
index 000000000..963ed9965
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/nettest/helper_posix.go
@@ -0,0 +1,31 @@
+// Copyright 2014 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.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
+
+package nettest
+
+import (
+ "os"
+ "syscall"
+)
+
+func protocolNotSupported(err error) bool {
+ switch err := err.(type) {
+ case syscall.Errno:
+ switch err {
+ case syscall.EPROTONOSUPPORT, syscall.ENOPROTOOPT:
+ return true
+ }
+ case *os.SyscallError:
+ switch err := err.Err.(type) {
+ case syscall.Errno:
+ switch err {
+ case syscall.EPROTONOSUPPORT, syscall.ENOPROTOOPT:
+ return true
+ }
+ }
+ }
+ return false
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/nettest/helper_stub.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/nettest/helper_stub.go
new file mode 100644
index 000000000..ea61b6f39
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/nettest/helper_stub.go
@@ -0,0 +1,32 @@
+// Copyright 2014 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.
+
+// +build nacl plan9
+
+package nettest
+
+import (
+ "fmt"
+ "runtime"
+)
+
+func maxOpenFiles() int {
+ return defaultMaxOpenFiles
+}
+
+func supportsRawIPSocket() (string, bool) {
+ return fmt.Sprintf("not supported on %s", runtime.GOOS), false
+}
+
+func supportsIPv6MulticastDeliveryOnLoopback() bool {
+ return false
+}
+
+func causesIPv6Crash() bool {
+ return false
+}
+
+func protocolNotSupported(err error) bool {
+ return false
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/nettest/helper_unix.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/nettest/helper_unix.go
new file mode 100644
index 000000000..ed13e448b
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/nettest/helper_unix.go
@@ -0,0 +1,29 @@
+// Copyright 2015 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.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+
+package nettest
+
+import (
+ "fmt"
+ "os"
+ "runtime"
+ "syscall"
+)
+
+func maxOpenFiles() int {
+ var rlim syscall.Rlimit
+ if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rlim); err != nil {
+ return defaultMaxOpenFiles
+ }
+ return int(rlim.Cur)
+}
+
+func supportsRawIPSocket() (string, bool) {
+ if os.Getuid() != 0 {
+ return fmt.Sprintf("must be root on %s", runtime.GOOS), false
+ }
+ return "", true
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/nettest/helper_windows.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/nettest/helper_windows.go
new file mode 100644
index 000000000..3dcb727c9
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/nettest/helper_windows.go
@@ -0,0 +1,42 @@
+// Copyright 2015 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 nettest
+
+import (
+ "fmt"
+ "runtime"
+ "syscall"
+)
+
+func maxOpenFiles() int {
+ return 4 * defaultMaxOpenFiles /* actually it's 16581375 */
+}
+
+func supportsRawIPSocket() (string, bool) {
+ // From http://msdn.microsoft.com/en-us/library/windows/desktop/ms740548.aspx:
+ // Note: To use a socket of type SOCK_RAW requires administrative privileges.
+ // Users running Winsock applications that use raw sockets must be a member of
+ // the Administrators group on the local computer, otherwise raw socket calls
+ // will fail with an error code of WSAEACCES. On Windows Vista and later, access
+ // for raw sockets is enforced at socket creation. In earlier versions of Windows,
+ // access for raw sockets is enforced during other socket operations.
+ s, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, 0)
+ if err == syscall.WSAEACCES {
+ return fmt.Sprintf("no access to raw socket allowed on %s", runtime.GOOS), false
+ }
+ if err != nil {
+ return err.Error(), false
+ }
+ syscall.Closesocket(s)
+ return "", true
+}
+
+func supportsIPv6MulticastDeliveryOnLoopback() bool {
+ return true
+}
+
+func causesIPv6Crash() bool {
+ return false
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/nettest/interface.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/nettest/interface.go
new file mode 100644
index 000000000..8e6333afe
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/nettest/interface.go
@@ -0,0 +1,94 @@
+// Copyright 2012 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 nettest
+
+import "net"
+
+// IsMulticastCapable reports whether ifi is an IP multicast-capable
+// network interface. Network must be "ip", "ip4" or "ip6".
+func IsMulticastCapable(network string, ifi *net.Interface) (net.IP, bool) {
+ switch network {
+ case "ip", "ip4", "ip6":
+ default:
+ return nil, false
+ }
+ if ifi == nil || ifi.Flags&net.FlagUp == 0 || ifi.Flags&net.FlagMulticast == 0 {
+ return nil, false
+ }
+ return hasRoutableIP(network, ifi)
+}
+
+// RoutedInterface returns a network interface that can route IP
+// traffic and satisfies flags. It returns nil when an appropriate
+// network interface is not found. Network must be "ip", "ip4" or
+// "ip6".
+func RoutedInterface(network string, flags net.Flags) *net.Interface {
+ switch network {
+ case "ip", "ip4", "ip6":
+ default:
+ return nil
+ }
+ ift, err := net.Interfaces()
+ if err != nil {
+ return nil
+ }
+ for _, ifi := range ift {
+ if ifi.Flags&flags != flags {
+ continue
+ }
+ if _, ok := hasRoutableIP(network, &ifi); !ok {
+ continue
+ }
+ return &ifi
+ }
+ return nil
+}
+
+func hasRoutableIP(network string, ifi *net.Interface) (net.IP, bool) {
+ ifat, err := ifi.Addrs()
+ if err != nil {
+ return nil, false
+ }
+ for _, ifa := range ifat {
+ switch ifa := ifa.(type) {
+ case *net.IPAddr:
+ if ip := routableIP(network, ifa.IP); ip != nil {
+ return ip, true
+ }
+ case *net.IPNet:
+ if ip := routableIP(network, ifa.IP); ip != nil {
+ return ip, true
+ }
+ }
+ }
+ return nil, false
+}
+
+func routableIP(network string, ip net.IP) net.IP {
+ if !ip.IsLoopback() && !ip.IsLinkLocalUnicast() && !ip.IsGlobalUnicast() {
+ return nil
+ }
+ switch network {
+ case "ip4":
+ if ip := ip.To4(); ip != nil {
+ return ip
+ }
+ case "ip6":
+ if ip.IsLoopback() { // addressing scope of the loopback address depends on each implementation
+ return nil
+ }
+ if ip := ip.To16(); ip != nil && ip.To4() == nil {
+ return ip
+ }
+ default:
+ if ip := ip.To4(); ip != nil {
+ return ip
+ }
+ if ip := ip.To16(); ip != nil {
+ return ip
+ }
+ }
+ return nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/nettest/rlimit.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/nettest/rlimit.go
new file mode 100644
index 000000000..bb34aec0b
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/nettest/rlimit.go
@@ -0,0 +1,11 @@
+// Copyright 2015 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 nettest
+
+const defaultMaxOpenFiles = 256
+
+// MaxOpenFiles returns the maximum number of open files for the
+// caller's process.
+func MaxOpenFiles() int { return maxOpenFiles() }
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/nettest/stack.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/nettest/stack.go
new file mode 100644
index 000000000..cc92c035b
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/nettest/stack.go
@@ -0,0 +1,147 @@
+// Copyright 2014 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 nettest provides utilities for network testing.
+package nettest // import "golang.org/x/net/internal/nettest"
+
+import (
+ "fmt"
+ "io/ioutil"
+ "net"
+ "os"
+ "runtime"
+)
+
+var (
+ supportsIPv4 bool
+ supportsIPv6 bool
+)
+
+func init() {
+ if ln, err := net.Listen("tcp4", "127.0.0.1:0"); err == nil {
+ ln.Close()
+ supportsIPv4 = true
+ }
+ if ln, err := net.Listen("tcp6", "[::1]:0"); err == nil {
+ ln.Close()
+ supportsIPv6 = true
+ }
+}
+
+// SupportsIPv4 reports whether the platform supports IPv4 networking
+// functionality.
+func SupportsIPv4() bool { return supportsIPv4 }
+
+// SupportsIPv6 reports whether the platform supports IPv6 networking
+// functionality.
+func SupportsIPv6() bool { return supportsIPv6 }
+
+// SupportsRawIPSocket reports whether the platform supports raw IP
+// sockets.
+func SupportsRawIPSocket() (string, bool) {
+ return supportsRawIPSocket()
+}
+
+// SupportsIPv6MulticastDeliveryOnLoopback reports whether the
+// platform supports IPv6 multicast packet delivery on software
+// loopback interface.
+func SupportsIPv6MulticastDeliveryOnLoopback() bool {
+ return supportsIPv6MulticastDeliveryOnLoopback()
+}
+
+// ProtocolNotSupported reports whether err is a protocol not
+// supported error.
+func ProtocolNotSupported(err error) bool {
+ return protocolNotSupported(err)
+}
+
+// TestableNetwork reports whether network is testable on the current
+// platform configuration.
+func TestableNetwork(network string) bool {
+ // This is based on logic from standard library's
+ // net/platform_test.go.
+ switch network {
+ case "unix", "unixgram":
+ switch runtime.GOOS {
+ case "android", "nacl", "plan9", "windows":
+ return false
+ }
+ if runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") {
+ return false
+ }
+ case "unixpacket":
+ switch runtime.GOOS {
+ case "android", "darwin", "freebsd", "nacl", "plan9", "windows":
+ return false
+ }
+ }
+ return true
+}
+
+// NewLocalListener returns a listener which listens to a loopback IP
+// address or local file system path.
+// Network must be "tcp", "tcp4", "tcp6", "unix" or "unixpacket".
+func NewLocalListener(network string) (net.Listener, error) {
+ switch network {
+ case "tcp":
+ if supportsIPv4 {
+ if ln, err := net.Listen("tcp4", "127.0.0.1:0"); err == nil {
+ return ln, nil
+ }
+ }
+ if supportsIPv6 {
+ return net.Listen("tcp6", "[::1]:0")
+ }
+ case "tcp4":
+ if supportsIPv4 {
+ return net.Listen("tcp4", "127.0.0.1:0")
+ }
+ case "tcp6":
+ if supportsIPv6 {
+ return net.Listen("tcp6", "[::1]:0")
+ }
+ case "unix", "unixpacket":
+ return net.Listen(network, localPath())
+ }
+ return nil, fmt.Errorf("%s is not supported", network)
+}
+
+// NewLocalPacketListener returns a packet listener which listens to a
+// loopback IP address or local file system path.
+// Network must be "udp", "udp4", "udp6" or "unixgram".
+func NewLocalPacketListener(network string) (net.PacketConn, error) {
+ switch network {
+ case "udp":
+ if supportsIPv4 {
+ if c, err := net.ListenPacket("udp4", "127.0.0.1:0"); err == nil {
+ return c, nil
+ }
+ }
+ if supportsIPv6 {
+ return net.ListenPacket("udp6", "[::1]:0")
+ }
+ case "udp4":
+ if supportsIPv4 {
+ return net.ListenPacket("udp4", "127.0.0.1:0")
+ }
+ case "udp6":
+ if supportsIPv6 {
+ return net.ListenPacket("udp6", "[::1]:0")
+ }
+ case "unixgram":
+ return net.ListenPacket(network, localPath())
+ }
+ return nil, fmt.Errorf("%s is not supported", network)
+}
+
+func localPath() string {
+ f, err := ioutil.TempFile("", "nettest")
+ if err != nil {
+ panic(err)
+ }
+ path := f.Name()
+ f.Close()
+ os.Remove(path)
+ return path
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/cmsghdr.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/cmsghdr.go
new file mode 100644
index 000000000..1eb07d26d
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/cmsghdr.go
@@ -0,0 +1,11 @@
+// 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.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+
+package socket
+
+func (h *cmsghdr) len() int { return int(h.Len) }
+func (h *cmsghdr) lvl() int { return int(h.Level) }
+func (h *cmsghdr) typ() int { return int(h.Type) }
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/cmsghdr_bsd.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/cmsghdr_bsd.go
new file mode 100644
index 000000000..d1d0c2de5
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/cmsghdr_bsd.go
@@ -0,0 +1,13 @@
+// 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.
+
+// +build darwin dragonfly freebsd netbsd openbsd
+
+package socket
+
+func (h *cmsghdr) set(l, lvl, typ int) {
+ h.Len = uint32(l)
+ h.Level = int32(lvl)
+ h.Type = int32(typ)
+}
diff --git a/vendor/github.com/miekg/dns/internal/socket/cmsghdr_linux_32bit.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/cmsghdr_linux_32bit.go
index e92e85800..bac66811d 100644
--- a/vendor/github.com/miekg/dns/internal/socket/cmsghdr_linux_32bit.go
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/cmsghdr_linux_32bit.go
@@ -1,18 +1,12 @@
+// 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.
+
// +build arm mips mipsle 386
// +build linux
package socket
-type cmsghdr struct {
- Len uint32
- Level int32
- Type int32
-}
-
-const (
- sizeofCmsghdr = 0xc
-)
-
func (h *cmsghdr) set(l, lvl, typ int) {
h.Len = uint32(l)
h.Level = int32(lvl)
diff --git a/vendor/github.com/miekg/dns/internal/socket/cmsghdr_linux_64bit.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/cmsghdr_linux_64bit.go
index ddfc9e09a..63f0534fa 100644
--- a/vendor/github.com/miekg/dns/internal/socket/cmsghdr_linux_64bit.go
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/cmsghdr_linux_64bit.go
@@ -1,18 +1,12 @@
+// 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.
+
// +build arm64 amd64 ppc64 ppc64le mips64 mips64le s390x
// +build linux
package socket
-type cmsghdr struct {
- Len uint64
- Level int32
- Type int32
-}
-
-const (
- sizeofCmsghdr = 0x10
-)
-
func (h *cmsghdr) set(l, lvl, typ int) {
h.Len = uint64(l)
h.Level = int32(lvl)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/cmsghdr_solaris_64bit.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/cmsghdr_solaris_64bit.go
new file mode 100644
index 000000000..7dedd430e
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/cmsghdr_solaris_64bit.go
@@ -0,0 +1,14 @@
+// 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.
+
+// +build amd64
+// +build solaris
+
+package socket
+
+func (h *cmsghdr) set(l, lvl, typ int) {
+ h.Len = uint32(l)
+ h.Level = int32(lvl)
+ h.Type = int32(typ)
+}
diff --git a/vendor/github.com/miekg/dns/internal/socket/cmsghdr_other.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/cmsghdr_stub.go
index 8078487c8..a4e71226f 100644
--- a/vendor/github.com/miekg/dns/internal/socket/cmsghdr_other.go
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/cmsghdr_stub.go
@@ -1,4 +1,8 @@
-// +build !linux
+// 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.
+
+// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris
package socket
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/defs_darwin.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/defs_darwin.go
new file mode 100644
index 000000000..14e28c0b4
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/defs_darwin.go
@@ -0,0 +1,44 @@
+// 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.
+
+// +build ignore
+
+// +godefs map struct_in_addr [4]byte /* in_addr */
+// +godefs map struct_in6_addr [16]byte /* in6_addr */
+
+package socket
+
+/*
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+*/
+import "C"
+
+const (
+ sysAF_UNSPEC = C.AF_UNSPEC
+ sysAF_INET = C.AF_INET
+ sysAF_INET6 = C.AF_INET6
+
+ sysSOCK_RAW = C.SOCK_RAW
+)
+
+type iovec C.struct_iovec
+
+type msghdr C.struct_msghdr
+
+type cmsghdr C.struct_cmsghdr
+
+type sockaddrInet C.struct_sockaddr_in
+
+type sockaddrInet6 C.struct_sockaddr_in6
+
+const (
+ sizeofIovec = C.sizeof_struct_iovec
+ sizeofMsghdr = C.sizeof_struct_msghdr
+ sizeofCmsghdr = C.sizeof_struct_cmsghdr
+
+ sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
+ sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/defs_dragonfly.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/defs_dragonfly.go
new file mode 100644
index 000000000..14e28c0b4
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/defs_dragonfly.go
@@ -0,0 +1,44 @@
+// 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.
+
+// +build ignore
+
+// +godefs map struct_in_addr [4]byte /* in_addr */
+// +godefs map struct_in6_addr [16]byte /* in6_addr */
+
+package socket
+
+/*
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+*/
+import "C"
+
+const (
+ sysAF_UNSPEC = C.AF_UNSPEC
+ sysAF_INET = C.AF_INET
+ sysAF_INET6 = C.AF_INET6
+
+ sysSOCK_RAW = C.SOCK_RAW
+)
+
+type iovec C.struct_iovec
+
+type msghdr C.struct_msghdr
+
+type cmsghdr C.struct_cmsghdr
+
+type sockaddrInet C.struct_sockaddr_in
+
+type sockaddrInet6 C.struct_sockaddr_in6
+
+const (
+ sizeofIovec = C.sizeof_struct_iovec
+ sizeofMsghdr = C.sizeof_struct_msghdr
+ sizeofCmsghdr = C.sizeof_struct_cmsghdr
+
+ sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
+ sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/defs_freebsd.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/defs_freebsd.go
new file mode 100644
index 000000000..14e28c0b4
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/defs_freebsd.go
@@ -0,0 +1,44 @@
+// 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.
+
+// +build ignore
+
+// +godefs map struct_in_addr [4]byte /* in_addr */
+// +godefs map struct_in6_addr [16]byte /* in6_addr */
+
+package socket
+
+/*
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+*/
+import "C"
+
+const (
+ sysAF_UNSPEC = C.AF_UNSPEC
+ sysAF_INET = C.AF_INET
+ sysAF_INET6 = C.AF_INET6
+
+ sysSOCK_RAW = C.SOCK_RAW
+)
+
+type iovec C.struct_iovec
+
+type msghdr C.struct_msghdr
+
+type cmsghdr C.struct_cmsghdr
+
+type sockaddrInet C.struct_sockaddr_in
+
+type sockaddrInet6 C.struct_sockaddr_in6
+
+const (
+ sizeofIovec = C.sizeof_struct_iovec
+ sizeofMsghdr = C.sizeof_struct_msghdr
+ sizeofCmsghdr = C.sizeof_struct_cmsghdr
+
+ sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
+ sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/defs_linux.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/defs_linux.go
new file mode 100644
index 000000000..ce9ec2f6d
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/defs_linux.go
@@ -0,0 +1,49 @@
+// 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.
+
+// +build ignore
+
+// +godefs map struct_in_addr [4]byte /* in_addr */
+// +godefs map struct_in6_addr [16]byte /* in6_addr */
+
+package socket
+
+/*
+#include <linux/in.h>
+#include <linux/in6.h>
+
+#define _GNU_SOURCE
+#include <sys/socket.h>
+*/
+import "C"
+
+const (
+ sysAF_UNSPEC = C.AF_UNSPEC
+ sysAF_INET = C.AF_INET
+ sysAF_INET6 = C.AF_INET6
+
+ sysSOCK_RAW = C.SOCK_RAW
+)
+
+type iovec C.struct_iovec
+
+type msghdr C.struct_msghdr
+
+type mmsghdr C.struct_mmsghdr
+
+type cmsghdr C.struct_cmsghdr
+
+type sockaddrInet C.struct_sockaddr_in
+
+type sockaddrInet6 C.struct_sockaddr_in6
+
+const (
+ sizeofIovec = C.sizeof_struct_iovec
+ sizeofMsghdr = C.sizeof_struct_msghdr
+ sizeofMmsghdr = C.sizeof_struct_mmsghdr
+ sizeofCmsghdr = C.sizeof_struct_cmsghdr
+
+ sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
+ sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/defs_netbsd.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/defs_netbsd.go
new file mode 100644
index 000000000..3f8433569
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/defs_netbsd.go
@@ -0,0 +1,47 @@
+// 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.
+
+// +build ignore
+
+// +godefs map struct_in_addr [4]byte /* in_addr */
+// +godefs map struct_in6_addr [16]byte /* in6_addr */
+
+package socket
+
+/*
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+*/
+import "C"
+
+const (
+ sysAF_UNSPEC = C.AF_UNSPEC
+ sysAF_INET = C.AF_INET
+ sysAF_INET6 = C.AF_INET6
+
+ sysSOCK_RAW = C.SOCK_RAW
+)
+
+type iovec C.struct_iovec
+
+type msghdr C.struct_msghdr
+
+type mmsghdr C.struct_mmsghdr
+
+type cmsghdr C.struct_cmsghdr
+
+type sockaddrInet C.struct_sockaddr_in
+
+type sockaddrInet6 C.struct_sockaddr_in6
+
+const (
+ sizeofIovec = C.sizeof_struct_iovec
+ sizeofMsghdr = C.sizeof_struct_msghdr
+ sizeofMmsghdr = C.sizeof_struct_mmsghdr
+ sizeofCmsghdr = C.sizeof_struct_cmsghdr
+
+ sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
+ sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/defs_openbsd.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/defs_openbsd.go
new file mode 100644
index 000000000..14e28c0b4
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/defs_openbsd.go
@@ -0,0 +1,44 @@
+// 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.
+
+// +build ignore
+
+// +godefs map struct_in_addr [4]byte /* in_addr */
+// +godefs map struct_in6_addr [16]byte /* in6_addr */
+
+package socket
+
+/*
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+*/
+import "C"
+
+const (
+ sysAF_UNSPEC = C.AF_UNSPEC
+ sysAF_INET = C.AF_INET
+ sysAF_INET6 = C.AF_INET6
+
+ sysSOCK_RAW = C.SOCK_RAW
+)
+
+type iovec C.struct_iovec
+
+type msghdr C.struct_msghdr
+
+type cmsghdr C.struct_cmsghdr
+
+type sockaddrInet C.struct_sockaddr_in
+
+type sockaddrInet6 C.struct_sockaddr_in6
+
+const (
+ sizeofIovec = C.sizeof_struct_iovec
+ sizeofMsghdr = C.sizeof_struct_msghdr
+ sizeofCmsghdr = C.sizeof_struct_cmsghdr
+
+ sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
+ sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/defs_solaris.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/defs_solaris.go
new file mode 100644
index 000000000..14e28c0b4
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/defs_solaris.go
@@ -0,0 +1,44 @@
+// 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.
+
+// +build ignore
+
+// +godefs map struct_in_addr [4]byte /* in_addr */
+// +godefs map struct_in6_addr [16]byte /* in6_addr */
+
+package socket
+
+/*
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+*/
+import "C"
+
+const (
+ sysAF_UNSPEC = C.AF_UNSPEC
+ sysAF_INET = C.AF_INET
+ sysAF_INET6 = C.AF_INET6
+
+ sysSOCK_RAW = C.SOCK_RAW
+)
+
+type iovec C.struct_iovec
+
+type msghdr C.struct_msghdr
+
+type cmsghdr C.struct_cmsghdr
+
+type sockaddrInet C.struct_sockaddr_in
+
+type sockaddrInet6 C.struct_sockaddr_in6
+
+const (
+ sizeofIovec = C.sizeof_struct_iovec
+ sizeofMsghdr = C.sizeof_struct_msghdr
+ sizeofCmsghdr = C.sizeof_struct_cmsghdr
+
+ sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
+ sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/error_unix.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/error_unix.go
new file mode 100644
index 000000000..93dff9180
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/error_unix.go
@@ -0,0 +1,31 @@
+// 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.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+
+package socket
+
+import "syscall"
+
+var (
+ errEAGAIN error = syscall.EAGAIN
+ errEINVAL error = syscall.EINVAL
+ errENOENT error = syscall.ENOENT
+)
+
+// errnoErr returns common boxed Errno values, to prevent allocations
+// at runtime.
+func errnoErr(errno syscall.Errno) error {
+ switch errno {
+ case 0:
+ return nil
+ case syscall.EAGAIN:
+ return errEAGAIN
+ case syscall.EINVAL:
+ return errEINVAL
+ case syscall.ENOENT:
+ return errENOENT
+ }
+ return errno
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/error_windows.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/error_windows.go
new file mode 100644
index 000000000..6a6379a8b
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/error_windows.go
@@ -0,0 +1,26 @@
+// 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 "syscall"
+
+var (
+ errERROR_IO_PENDING error = syscall.ERROR_IO_PENDING
+ errEINVAL error = syscall.EINVAL
+)
+
+// errnoErr returns common boxed Errno values, to prevent allocations
+// at runtime.
+func errnoErr(errno syscall.Errno) error {
+ switch errno {
+ case 0:
+ return nil
+ case syscall.ERROR_IO_PENDING:
+ return errERROR_IO_PENDING
+ case syscall.EINVAL:
+ return errEINVAL
+ }
+ return errno
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/iovec_32bit.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/iovec_32bit.go
new file mode 100644
index 000000000..05d6082d1
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/iovec_32bit.go
@@ -0,0 +1,19 @@
+// 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.
+
+// +build arm mips mipsle 386
+// +build darwin dragonfly freebsd linux netbsd openbsd
+
+package socket
+
+import "unsafe"
+
+func (v *iovec) set(b []byte) {
+ l := len(b)
+ if l == 0 {
+ return
+ }
+ v.Base = (*byte)(unsafe.Pointer(&b[0]))
+ v.Len = uint32(l)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/iovec_64bit.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/iovec_64bit.go
new file mode 100644
index 000000000..afb34ad58
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/iovec_64bit.go
@@ -0,0 +1,19 @@
+// 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.
+
+// +build arm64 amd64 ppc64 ppc64le mips64 mips64le s390x
+// +build darwin dragonfly freebsd linux netbsd openbsd
+
+package socket
+
+import "unsafe"
+
+func (v *iovec) set(b []byte) {
+ l := len(b)
+ if l == 0 {
+ return
+ }
+ v.Base = (*byte)(unsafe.Pointer(&b[0]))
+ v.Len = uint64(l)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/iovec_solaris_64bit.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/iovec_solaris_64bit.go
new file mode 100644
index 000000000..8d17a40c4
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/iovec_solaris_64bit.go
@@ -0,0 +1,19 @@
+// 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.
+
+// +build amd64
+// +build solaris
+
+package socket
+
+import "unsafe"
+
+func (v *iovec) set(b []byte) {
+ l := len(b)
+ if l == 0 {
+ return
+ }
+ v.Base = (*int8)(unsafe.Pointer(&b[0]))
+ v.Len = uint64(l)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/iovec_stub.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/iovec_stub.go
new file mode 100644
index 000000000..c87d2a933
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/iovec_stub.go
@@ -0,0 +1,11 @@
+// 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.
+
+// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris
+
+package socket
+
+type iovec struct{}
+
+func (v *iovec) set(b []byte) {}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/mmsghdr_stub.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/mmsghdr_stub.go
new file mode 100644
index 000000000..2e80a9cb7
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/mmsghdr_stub.go
@@ -0,0 +1,21 @@
+// 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.
+
+// +build !linux,!netbsd
+
+package socket
+
+import "net"
+
+type mmsghdr struct{}
+
+type mmsghdrs []mmsghdr
+
+func (hs mmsghdrs) pack(ms []Message, parseFn func([]byte, string) (net.Addr, error), marshalFn func(net.Addr) []byte) error {
+ return nil
+}
+
+func (hs mmsghdrs) unpack(ms []Message, parseFn func([]byte, string) (net.Addr, error), hint string) error {
+ return nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/mmsghdr_unix.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/mmsghdr_unix.go
new file mode 100644
index 000000000..3c42ea7ad
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/mmsghdr_unix.go
@@ -0,0 +1,42 @@
+// 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.
+
+// +build linux netbsd
+
+package socket
+
+import "net"
+
+type mmsghdrs []mmsghdr
+
+func (hs mmsghdrs) pack(ms []Message, parseFn func([]byte, string) (net.Addr, error), marshalFn func(net.Addr) []byte) error {
+ for i := range hs {
+ vs := make([]iovec, len(ms[i].Buffers))
+ var sa []byte
+ if parseFn != nil {
+ sa = make([]byte, sizeofSockaddrInet6)
+ }
+ if marshalFn != nil {
+ sa = marshalFn(ms[i].Addr)
+ }
+ hs[i].Hdr.pack(vs, ms[i].Buffers, ms[i].OOB, sa)
+ }
+ return nil
+}
+
+func (hs mmsghdrs) unpack(ms []Message, parseFn func([]byte, string) (net.Addr, error), hint string) error {
+ for i := range hs {
+ ms[i].N = int(hs[i].Len)
+ ms[i].NN = hs[i].Hdr.controllen()
+ ms[i].Flags = hs[i].Hdr.flags()
+ if parseFn != nil {
+ var err error
+ ms[i].Addr, err = parseFn(hs[i].Hdr.name(), hint)
+ if err != nil {
+ return err
+ }
+ }
+ }
+ return nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/msghdr_bsd.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/msghdr_bsd.go
new file mode 100644
index 000000000..5567afc88
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/msghdr_bsd.go
@@ -0,0 +1,39 @@
+// 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.
+
+// +build darwin dragonfly freebsd netbsd openbsd
+
+package socket
+
+import "unsafe"
+
+func (h *msghdr) pack(vs []iovec, bs [][]byte, oob []byte, sa []byte) {
+ for i := range vs {
+ vs[i].set(bs[i])
+ }
+ h.setIov(vs)
+ if len(oob) > 0 {
+ h.Control = (*byte)(unsafe.Pointer(&oob[0]))
+ h.Controllen = uint32(len(oob))
+ }
+ if sa != nil {
+ h.Name = (*byte)(unsafe.Pointer(&sa[0]))
+ h.Namelen = uint32(len(sa))
+ }
+}
+
+func (h *msghdr) name() []byte {
+ if h.Name != nil && h.Namelen > 0 {
+ return (*[sizeofSockaddrInet6]byte)(unsafe.Pointer(h.Name))[:h.Namelen]
+ }
+ return nil
+}
+
+func (h *msghdr) controllen() int {
+ return int(h.Controllen)
+}
+
+func (h *msghdr) flags() int {
+ return int(h.Flags)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/msghdr_bsdvar.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/msghdr_bsdvar.go
new file mode 100644
index 000000000..b8c87b72b
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/msghdr_bsdvar.go
@@ -0,0 +1,16 @@
+// 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.
+
+// +build darwin dragonfly freebsd netbsd
+
+package socket
+
+func (h *msghdr) setIov(vs []iovec) {
+ l := len(vs)
+ if l == 0 {
+ return
+ }
+ h.Iov = &vs[0]
+ h.Iovlen = int32(l)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/msghdr_linux.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/msghdr_linux.go
new file mode 100644
index 000000000..5a38798cc
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/msghdr_linux.go
@@ -0,0 +1,36 @@
+// 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 "unsafe"
+
+func (h *msghdr) pack(vs []iovec, bs [][]byte, oob []byte, sa []byte) {
+ for i := range vs {
+ vs[i].set(bs[i])
+ }
+ h.setIov(vs)
+ if len(oob) > 0 {
+ h.setControl(oob)
+ }
+ if sa != nil {
+ h.Name = (*byte)(unsafe.Pointer(&sa[0]))
+ h.Namelen = uint32(len(sa))
+ }
+}
+
+func (h *msghdr) name() []byte {
+ if h.Name != nil && h.Namelen > 0 {
+ return (*[sizeofSockaddrInet6]byte)(unsafe.Pointer(h.Name))[:h.Namelen]
+ }
+ return nil
+}
+
+func (h *msghdr) controllen() int {
+ return int(h.Controllen)
+}
+
+func (h *msghdr) flags() int {
+ return int(h.Flags)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/msghdr_linux_32bit.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/msghdr_linux_32bit.go
new file mode 100644
index 000000000..a7a5987c8
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/msghdr_linux_32bit.go
@@ -0,0 +1,24 @@
+// 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.
+
+// +build arm mips mipsle 386
+// +build linux
+
+package socket
+
+import "unsafe"
+
+func (h *msghdr) setIov(vs []iovec) {
+ l := len(vs)
+ if l == 0 {
+ return
+ }
+ h.Iov = &vs[0]
+ h.Iovlen = uint32(l)
+}
+
+func (h *msghdr) setControl(b []byte) {
+ h.Control = (*byte)(unsafe.Pointer(&b[0]))
+ h.Controllen = uint32(len(b))
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/msghdr_linux_64bit.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/msghdr_linux_64bit.go
new file mode 100644
index 000000000..610fc4f3b
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/msghdr_linux_64bit.go
@@ -0,0 +1,24 @@
+// 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.
+
+// +build arm64 amd64 ppc64 ppc64le mips64 mips64le s390x
+// +build linux
+
+package socket
+
+import "unsafe"
+
+func (h *msghdr) setIov(vs []iovec) {
+ l := len(vs)
+ if l == 0 {
+ return
+ }
+ h.Iov = &vs[0]
+ h.Iovlen = uint64(l)
+}
+
+func (h *msghdr) setControl(b []byte) {
+ h.Control = (*byte)(unsafe.Pointer(&b[0]))
+ h.Controllen = uint64(len(b))
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/msghdr_openbsd.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/msghdr_openbsd.go
new file mode 100644
index 000000000..71a69e251
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/msghdr_openbsd.go
@@ -0,0 +1,14 @@
+// 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
+
+func (h *msghdr) setIov(vs []iovec) {
+ l := len(vs)
+ if l == 0 {
+ return
+ }
+ h.Iov = &vs[0]
+ h.Iovlen = uint32(l)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/msghdr_solaris_64bit.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/msghdr_solaris_64bit.go
new file mode 100644
index 000000000..6465b2073
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/msghdr_solaris_64bit.go
@@ -0,0 +1,36 @@
+// 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.
+
+// +build amd64
+// +build solaris
+
+package socket
+
+import "unsafe"
+
+func (h *msghdr) pack(vs []iovec, bs [][]byte, oob []byte, sa []byte) {
+ for i := range vs {
+ vs[i].set(bs[i])
+ }
+ if len(vs) > 0 {
+ h.Iov = &vs[0]
+ h.Iovlen = int32(len(vs))
+ }
+ if len(oob) > 0 {
+ h.Accrights = (*int8)(unsafe.Pointer(&oob[0]))
+ h.Accrightslen = int32(len(oob))
+ }
+ if sa != nil {
+ h.Name = (*byte)(unsafe.Pointer(&sa[0]))
+ h.Namelen = uint32(len(sa))
+ }
+}
+
+func (h *msghdr) controllen() int {
+ return int(h.Accrightslen)
+}
+
+func (h *msghdr) flags() int {
+ return int(NativeEndian.Uint32(h.Pad_cgo_2[:]))
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/msghdr_stub.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/msghdr_stub.go
new file mode 100644
index 000000000..64e817335
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/msghdr_stub.go
@@ -0,0 +1,14 @@
+// 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.
+
+// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris
+
+package socket
+
+type msghdr struct{}
+
+func (h *msghdr) pack(vs []iovec, bs [][]byte, oob []byte, sa []byte) {}
+func (h *msghdr) name() []byte { return nil }
+func (h *msghdr) controllen() int { return 0 }
+func (h *msghdr) flags() int { return 0 }
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/rawconn.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/rawconn.go
new file mode 100644
index 000000000..d6871d55f
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/rawconn.go
@@ -0,0 +1,66 @@
+// 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.
+
+// +build go1.9
+
+package socket
+
+import (
+ "errors"
+ "net"
+ "os"
+ "syscall"
+)
+
+// A Conn represents a raw connection.
+type Conn struct {
+ network string
+ c syscall.RawConn
+}
+
+// NewConn returns a new raw connection.
+func NewConn(c net.Conn) (*Conn, error) {
+ var err error
+ var cc Conn
+ switch c := c.(type) {
+ case *net.TCPConn:
+ cc.network = "tcp"
+ cc.c, err = c.SyscallConn()
+ case *net.UDPConn:
+ cc.network = "udp"
+ cc.c, err = c.SyscallConn()
+ case *net.IPConn:
+ cc.network = "ip"
+ cc.c, err = c.SyscallConn()
+ default:
+ return nil, errors.New("unknown connection type")
+ }
+ if err != nil {
+ return nil, err
+ }
+ return &cc, nil
+}
+
+func (o *Option) get(c *Conn, b []byte) (int, error) {
+ var operr error
+ var n int
+ fn := func(s uintptr) {
+ n, operr = getsockopt(s, o.Level, o.Name, b)
+ }
+ if err := c.c.Control(fn); err != nil {
+ return 0, err
+ }
+ return n, os.NewSyscallError("getsockopt", operr)
+}
+
+func (o *Option) set(c *Conn, b []byte) error {
+ var operr error
+ fn := func(s uintptr) {
+ operr = setsockopt(s, o.Level, o.Name, b)
+ }
+ if err := c.c.Control(fn); err != nil {
+ return err
+ }
+ return os.NewSyscallError("setsockopt", operr)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/rawconn_mmsg.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/rawconn_mmsg.go
new file mode 100644
index 000000000..499164a3f
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/rawconn_mmsg.go
@@ -0,0 +1,74 @@
+// 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.
+
+// +build go1.9
+// +build linux
+
+package socket
+
+import (
+ "net"
+ "os"
+ "syscall"
+)
+
+func (c *Conn) recvMsgs(ms []Message, flags int) (int, error) {
+ hs := make(mmsghdrs, len(ms))
+ var parseFn func([]byte, string) (net.Addr, error)
+ if c.network != "tcp" {
+ parseFn = parseInetAddr
+ }
+ if err := hs.pack(ms, parseFn, nil); err != nil {
+ return 0, err
+ }
+ var operr error
+ var n int
+ fn := func(s uintptr) bool {
+ n, operr = recvmmsg(s, hs, flags)
+ if operr == syscall.EAGAIN {
+ return false
+ }
+ return true
+ }
+ if err := c.c.Read(fn); err != nil {
+ return n, err
+ }
+ if operr != nil {
+ return n, os.NewSyscallError("recvmmsg", operr)
+ }
+ if err := hs[:n].unpack(ms[:n], parseFn, c.network); err != nil {
+ return n, err
+ }
+ return n, nil
+}
+
+func (c *Conn) sendMsgs(ms []Message, flags int) (int, error) {
+ hs := make(mmsghdrs, len(ms))
+ var marshalFn func(net.Addr) []byte
+ if c.network != "tcp" {
+ marshalFn = marshalInetAddr
+ }
+ if err := hs.pack(ms, nil, marshalFn); err != nil {
+ return 0, err
+ }
+ var operr error
+ var n int
+ fn := func(s uintptr) bool {
+ n, operr = sendmmsg(s, hs, flags)
+ if operr == syscall.EAGAIN {
+ return false
+ }
+ return true
+ }
+ if err := c.c.Write(fn); err != nil {
+ return n, err
+ }
+ if operr != nil {
+ return n, os.NewSyscallError("sendmmsg", operr)
+ }
+ if err := hs[:n].unpack(ms[:n], nil, ""); err != nil {
+ return n, err
+ }
+ return n, nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/rawconn_msg.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/rawconn_msg.go
new file mode 100644
index 000000000..b21d2e641
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/rawconn_msg.go
@@ -0,0 +1,77 @@
+// 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.
+
+// +build go1.9
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
+
+package socket
+
+import (
+ "os"
+ "syscall"
+)
+
+func (c *Conn) recvMsg(m *Message, flags int) error {
+ var h msghdr
+ vs := make([]iovec, len(m.Buffers))
+ var sa []byte
+ if c.network != "tcp" {
+ sa = make([]byte, sizeofSockaddrInet6)
+ }
+ h.pack(vs, m.Buffers, m.OOB, sa)
+ var operr error
+ var n int
+ fn := func(s uintptr) bool {
+ n, operr = recvmsg(s, &h, flags)
+ if operr == syscall.EAGAIN {
+ return false
+ }
+ return true
+ }
+ if err := c.c.Read(fn); err != nil {
+ return err
+ }
+ if operr != nil {
+ return os.NewSyscallError("recvmsg", operr)
+ }
+ if c.network != "tcp" {
+ var err error
+ m.Addr, err = parseInetAddr(sa[:], c.network)
+ if err != nil {
+ return err
+ }
+ }
+ m.N = n
+ m.NN = h.controllen()
+ m.Flags = h.flags()
+ return nil
+}
+
+func (c *Conn) sendMsg(m *Message, flags int) error {
+ var h msghdr
+ vs := make([]iovec, len(m.Buffers))
+ var sa []byte
+ if m.Addr != nil {
+ sa = marshalInetAddr(m.Addr)
+ }
+ h.pack(vs, m.Buffers, m.OOB, sa)
+ var operr error
+ var n int
+ fn := func(s uintptr) bool {
+ n, operr = sendmsg(s, &h, flags)
+ if operr == syscall.EAGAIN {
+ return false
+ }
+ return true
+ }
+ if err := c.c.Write(fn); err != nil {
+ return err
+ }
+ if operr != nil {
+ return os.NewSyscallError("sendmsg", operr)
+ }
+ m.N = n
+ m.NN = len(m.OOB)
+ return nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/rawconn_nommsg.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/rawconn_nommsg.go
new file mode 100644
index 000000000..f78832aa4
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/rawconn_nommsg.go
@@ -0,0 +1,18 @@
+// 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.
+
+// +build go1.9
+// +build !linux
+
+package socket
+
+import "errors"
+
+func (c *Conn) recvMsgs(ms []Message, flags int) (int, error) {
+ return 0, errors.New("not implemented")
+}
+
+func (c *Conn) sendMsgs(ms []Message, flags int) (int, error) {
+ return 0, errors.New("not implemented")
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/rawconn_nomsg.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/rawconn_nomsg.go
new file mode 100644
index 000000000..96733cbe1
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/rawconn_nomsg.go
@@ -0,0 +1,18 @@
+// 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.
+
+// +build go1.9
+// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows
+
+package socket
+
+import "errors"
+
+func (c *Conn) recvMsg(m *Message, flags int) error {
+ return errors.New("not implemented")
+}
+
+func (c *Conn) sendMsg(m *Message, flags int) error {
+ return errors.New("not implemented")
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/rawconn_stub.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/rawconn_stub.go
new file mode 100644
index 000000000..d2add1a0a
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/rawconn_stub.go
@@ -0,0 +1,25 @@
+// 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.
+
+// +build !go1.9
+
+package socket
+
+import "errors"
+
+func (c *Conn) recvMsg(m *Message, flags int) error {
+ return errors.New("not implemented")
+}
+
+func (c *Conn) sendMsg(m *Message, flags int) error {
+ return errors.New("not implemented")
+}
+
+func (c *Conn) recvMsgs(ms []Message, flags int) (int, error) {
+ return 0, errors.New("not implemented")
+}
+
+func (c *Conn) sendMsgs(ms []Message, flags int) (int, error) {
+ return 0, errors.New("not implemented")
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/reflect.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/reflect.go
new file mode 100644
index 000000000..bb179f11d
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/reflect.go
@@ -0,0 +1,62 @@
+// 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.
+
+// +build !go1.9
+
+package socket
+
+import (
+ "errors"
+ "net"
+ "os"
+ "reflect"
+ "runtime"
+)
+
+// A Conn represents a raw connection.
+type Conn struct {
+ c net.Conn
+}
+
+// NewConn returns a new raw connection.
+func NewConn(c net.Conn) (*Conn, error) {
+ return &Conn{c: c}, nil
+}
+
+func (o *Option) get(c *Conn, b []byte) (int, error) {
+ s, err := socketOf(c.c)
+ if err != nil {
+ return 0, err
+ }
+ n, err := getsockopt(s, o.Level, o.Name, b)
+ return n, os.NewSyscallError("getsockopt", err)
+}
+
+func (o *Option) set(c *Conn, b []byte) error {
+ s, err := socketOf(c.c)
+ if err != nil {
+ return err
+ }
+ return os.NewSyscallError("setsockopt", setsockopt(s, o.Level, o.Name, b))
+}
+
+func socketOf(c net.Conn) (uintptr, error) {
+ switch c.(type) {
+ case *net.TCPConn, *net.UDPConn, *net.IPConn:
+ v := reflect.ValueOf(c)
+ switch e := v.Elem(); e.Kind() {
+ case reflect.Struct:
+ fd := e.FieldByName("conn").FieldByName("fd")
+ switch e := fd.Elem(); e.Kind() {
+ case reflect.Struct:
+ sysfd := e.FieldByName("sysfd")
+ if runtime.GOOS == "windows" {
+ return uintptr(sysfd.Uint()), nil
+ }
+ return uintptr(sysfd.Int()), nil
+ }
+ }
+ }
+ return 0, errors.New("invalid type")
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/socket.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/socket.go
new file mode 100644
index 000000000..729dea14b
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/socket.go
@@ -0,0 +1,285 @@
+// 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 provides a portable interface for socket system
+// calls.
+package socket // import "golang.org/x/net/internal/socket"
+
+import (
+ "errors"
+ "net"
+ "unsafe"
+)
+
+// An Option represents a sticky socket option.
+type Option struct {
+ Level int // level
+ Name int // name; must be equal or greater than 1
+ Len int // length of value in bytes; must be equal or greater than 1
+}
+
+// Get reads a value for the option from the kernel.
+// It returns the number of bytes written into b.
+func (o *Option) Get(c *Conn, b []byte) (int, error) {
+ if o.Name < 1 || o.Len < 1 {
+ return 0, errors.New("invalid option")
+ }
+ if len(b) < o.Len {
+ return 0, errors.New("short buffer")
+ }
+ return o.get(c, b)
+}
+
+// GetInt returns an integer value for the option.
+//
+// The Len field of Option must be either 1 or 4.
+func (o *Option) GetInt(c *Conn) (int, error) {
+ if o.Len != 1 && o.Len != 4 {
+ return 0, errors.New("invalid option")
+ }
+ var b []byte
+ var bb [4]byte
+ if o.Len == 1 {
+ b = bb[:1]
+ } else {
+ b = bb[:4]
+ }
+ n, err := o.get(c, b)
+ if err != nil {
+ return 0, err
+ }
+ if n != o.Len {
+ return 0, errors.New("invalid option length")
+ }
+ if o.Len == 1 {
+ return int(b[0]), nil
+ }
+ return int(NativeEndian.Uint32(b[:4])), nil
+}
+
+// Set writes the option and value to the kernel.
+func (o *Option) Set(c *Conn, b []byte) error {
+ if o.Name < 1 || o.Len < 1 {
+ return errors.New("invalid option")
+ }
+ if len(b) < o.Len {
+ return errors.New("short buffer")
+ }
+ return o.set(c, b)
+}
+
+// SetInt writes the option and value to the kernel.
+//
+// The Len field of Option must be either 1 or 4.
+func (o *Option) SetInt(c *Conn, v int) error {
+ if o.Len != 1 && o.Len != 4 {
+ return errors.New("invalid option")
+ }
+ var b []byte
+ if o.Len == 1 {
+ b = []byte{byte(v)}
+ } else {
+ var bb [4]byte
+ NativeEndian.PutUint32(bb[:o.Len], uint32(v))
+ b = bb[:4]
+ }
+ return o.set(c, b)
+}
+
+func controlHeaderLen() int {
+ return roundup(sizeofCmsghdr)
+}
+
+func controlMessageLen(dataLen int) int {
+ return roundup(sizeofCmsghdr) + dataLen
+}
+
+// ControlMessageSpace returns the whole length of control message.
+func ControlMessageSpace(dataLen int) int {
+ return roundup(sizeofCmsghdr) + roundup(dataLen)
+}
+
+// A ControlMessage represents the head message in a stream of control
+// messages.
+//
+// A control message comprises of a header, data and a few padding
+// fields to conform to the interface to the kernel.
+//
+// See RFC 3542 for further information.
+type ControlMessage []byte
+
+// Data returns the data field of the control message at the head on
+// w.
+func (m ControlMessage) Data(dataLen int) []byte {
+ l := controlHeaderLen()
+ if len(m) < l || len(m) < l+dataLen {
+ return nil
+ }
+ return m[l : l+dataLen]
+}
+
+// Next returns the control message at the next on w.
+//
+// Next works only for standard control messages.
+func (m ControlMessage) Next(dataLen int) ControlMessage {
+ l := ControlMessageSpace(dataLen)
+ if len(m) < l {
+ return nil
+ }
+ return m[l:]
+}
+
+// MarshalHeader marshals the header fields of the control message at
+// the head on w.
+func (m ControlMessage) MarshalHeader(lvl, typ, dataLen int) error {
+ if len(m) < controlHeaderLen() {
+ return errors.New("short message")
+ }
+ h := (*cmsghdr)(unsafe.Pointer(&m[0]))
+ h.set(controlMessageLen(dataLen), lvl, typ)
+ return nil
+}
+
+// ParseHeader parses and returns the header fields of the control
+// message at the head on w.
+func (m ControlMessage) ParseHeader() (lvl, typ, dataLen int, err error) {
+ l := controlHeaderLen()
+ if len(m) < l {
+ return 0, 0, 0, errors.New("short message")
+ }
+ h := (*cmsghdr)(unsafe.Pointer(&m[0]))
+ return h.lvl(), h.typ(), int(uint64(h.len()) - uint64(l)), nil
+}
+
+// Marshal marshals the control message at the head on w, and returns
+// the next control message.
+func (m ControlMessage) Marshal(lvl, typ int, data []byte) (ControlMessage, error) {
+ l := len(data)
+ if len(m) < ControlMessageSpace(l) {
+ return nil, errors.New("short message")
+ }
+ h := (*cmsghdr)(unsafe.Pointer(&m[0]))
+ h.set(controlMessageLen(l), lvl, typ)
+ if l > 0 {
+ copy(m.Data(l), data)
+ }
+ return m.Next(l), nil
+}
+
+// Parse parses w as a single or multiple control messages.
+//
+// Parse works for both standard and compatible messages.
+func (m ControlMessage) Parse() ([]ControlMessage, error) {
+ var ms []ControlMessage
+ for len(m) >= controlHeaderLen() {
+ h := (*cmsghdr)(unsafe.Pointer(&m[0]))
+ l := h.len()
+ if l <= 0 {
+ return nil, errors.New("invalid header length")
+ }
+ if uint64(l) < uint64(controlHeaderLen()) {
+ return nil, errors.New("invalid message length")
+ }
+ if uint64(l) > uint64(len(m)) {
+ return nil, errors.New("short buffer")
+ }
+ // On message reception:
+ //
+ // |<- ControlMessageSpace --------------->|
+ // |<- controlMessageLen ---------->| |
+ // |<- controlHeaderLen ->| | |
+ // +---------------+------+---------+------+
+ // | Header | PadH | Data | PadD |
+ // +---------------+------+---------+------+
+ //
+ // On compatible message reception:
+ //
+ // | ... |<- controlMessageLen ----------->|
+ // | ... |<- controlHeaderLen ->| |
+ // +-----+---------------+------+----------+
+ // | ... | Header | PadH | Data |
+ // +-----+---------------+------+----------+
+ ms = append(ms, ControlMessage(m[:l]))
+ ll := l - controlHeaderLen()
+ if len(m) >= ControlMessageSpace(ll) {
+ m = m[ControlMessageSpace(ll):]
+ } else {
+ m = m[controlMessageLen(ll):]
+ }
+ }
+ return ms, nil
+}
+
+// NewControlMessage returns a new stream of control messages.
+func NewControlMessage(dataLen []int) ControlMessage {
+ var l int
+ for i := range dataLen {
+ l += ControlMessageSpace(dataLen[i])
+ }
+ return make([]byte, l)
+}
+
+// A Message represents an IO message.
+type Message struct {
+ // When writing, the Buffers field must contain at least one
+ // byte to write.
+ // When reading, the Buffers field will always contain a byte
+ // to read.
+ Buffers [][]byte
+
+ // OOB contains protocol-specific control or miscellaneous
+ // ancillary data known as out-of-band data.
+ OOB []byte
+
+ // Addr specifies a destination address when writing.
+ // It can be nil when the underlying protocol of the raw
+ // connection uses connection-oriented communication.
+ // After a successful read, it may contain the source address
+ // on the received packet.
+ Addr net.Addr
+
+ N int // # of bytes read or written from/to Buffers
+ NN int // # of bytes read or written from/to OOB
+ Flags int // protocol-specific information on the received message
+}
+
+// RecvMsg wraps recvmsg system call.
+//
+// The provided flags is a set of platform-dependent flags, such as
+// syscall.MSG_PEEK.
+func (c *Conn) RecvMsg(m *Message, flags int) error {
+ return c.recvMsg(m, flags)
+}
+
+// SendMsg wraps sendmsg system call.
+//
+// The provided flags is a set of platform-dependent flags, such as
+// syscall.MSG_DONTROUTE.
+func (c *Conn) SendMsg(m *Message, flags int) error {
+ return c.sendMsg(m, flags)
+}
+
+// RecvMsgs wraps recvmmsg system call.
+//
+// It returns the number of processed messages.
+//
+// The provided flags is a set of platform-dependent flags, such as
+// syscall.MSG_PEEK.
+//
+// Only Linux supports this.
+func (c *Conn) RecvMsgs(ms []Message, flags int) (int, error) {
+ return c.recvMsgs(ms, flags)
+}
+
+// SendMsgs wraps sendmmsg system call.
+//
+// It returns the number of processed messages.
+//
+// The provided flags is a set of platform-dependent flags, such as
+// syscall.MSG_DONTROUTE.
+//
+// Only Linux supports this.
+func (c *Conn) SendMsgs(ms []Message, flags int) (int, error) {
+ return c.sendMsgs(ms, flags)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/socket_go1_9_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/socket_go1_9_test.go
new file mode 100644
index 000000000..c4edd4a8d
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/socket_go1_9_test.go
@@ -0,0 +1,259 @@
+// 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.
+
+// +build go1.9
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+
+package socket_test
+
+import (
+ "bytes"
+ "fmt"
+ "net"
+ "runtime"
+ "testing"
+
+ "golang.org/x/net/internal/nettest"
+ "golang.org/x/net/internal/socket"
+)
+
+type mockControl struct {
+ Level int
+ Type int
+ Data []byte
+}
+
+func TestControlMessage(t *testing.T) {
+ for _, tt := range []struct {
+ cs []mockControl
+ }{
+ {
+ []mockControl{
+ {Level: 1, Type: 1},
+ },
+ },
+ {
+ []mockControl{
+ {Level: 2, Type: 2, Data: []byte{0xfe}},
+ },
+ },
+ {
+ []mockControl{
+ {Level: 3, Type: 3, Data: []byte{0xfe, 0xff, 0xff, 0xfe}},
+ },
+ },
+ {
+ []mockControl{
+ {Level: 4, Type: 4, Data: []byte{0xfe, 0xff, 0xff, 0xfe, 0xfe, 0xff, 0xff, 0xfe}},
+ },
+ },
+ {
+ []mockControl{
+ {Level: 4, Type: 4, Data: []byte{0xfe, 0xff, 0xff, 0xfe, 0xfe, 0xff, 0xff, 0xfe}},
+ {Level: 2, Type: 2, Data: []byte{0xfe}},
+ },
+ },
+ } {
+ var w []byte
+ var tailPadLen int
+ mm := socket.NewControlMessage([]int{0})
+ for i, c := range tt.cs {
+ m := socket.NewControlMessage([]int{len(c.Data)})
+ l := len(m) - len(mm)
+ if i == len(tt.cs)-1 && l > len(c.Data) {
+ tailPadLen = l - len(c.Data)
+ }
+ w = append(w, m...)
+ }
+
+ var err error
+ ww := make([]byte, len(w))
+ copy(ww, w)
+ m := socket.ControlMessage(ww)
+ for _, c := range tt.cs {
+ if err = m.MarshalHeader(c.Level, c.Type, len(c.Data)); err != nil {
+ t.Fatalf("(%v).MarshalHeader() = %v", tt.cs, err)
+ }
+ copy(m.Data(len(c.Data)), c.Data)
+ m = m.Next(len(c.Data))
+ }
+ m = socket.ControlMessage(w)
+ for _, c := range tt.cs {
+ m, err = m.Marshal(c.Level, c.Type, c.Data)
+ if err != nil {
+ t.Fatalf("(%v).Marshal() = %v", tt.cs, err)
+ }
+ }
+ if !bytes.Equal(ww, w) {
+ t.Fatalf("got %#v; want %#v", ww, w)
+ }
+
+ ws := [][]byte{w}
+ if tailPadLen > 0 {
+ // Test a message with no tail padding.
+ nopad := w[:len(w)-tailPadLen]
+ ws = append(ws, [][]byte{nopad}...)
+ }
+ for _, w := range ws {
+ ms, err := socket.ControlMessage(w).Parse()
+ if err != nil {
+ t.Fatalf("(%v).Parse() = %v", tt.cs, err)
+ }
+ for i, m := range ms {
+ lvl, typ, dataLen, err := m.ParseHeader()
+ if err != nil {
+ t.Fatalf("(%v).ParseHeader() = %v", tt.cs, err)
+ }
+ if lvl != tt.cs[i].Level || typ != tt.cs[i].Type || dataLen != len(tt.cs[i].Data) {
+ t.Fatalf("%v: got %d, %d, %d; want %d, %d, %d", tt.cs[i], lvl, typ, dataLen, tt.cs[i].Level, tt.cs[i].Type, len(tt.cs[i].Data))
+ }
+ }
+ }
+ }
+}
+
+func TestUDP(t *testing.T) {
+ c, err := nettest.NewLocalPacketListener("udp")
+ if err != nil {
+ t.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
+ }
+ defer c.Close()
+ cc, err := socket.NewConn(c.(net.Conn))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ t.Run("Message", func(t *testing.T) {
+ data := []byte("HELLO-R-U-THERE")
+ wm := socket.Message{
+ Buffers: bytes.SplitAfter(data, []byte("-")),
+ Addr: c.LocalAddr(),
+ }
+ if err := cc.SendMsg(&wm, 0); err != nil {
+ t.Fatal(err)
+ }
+ b := make([]byte, 32)
+ rm := socket.Message{
+ Buffers: [][]byte{b[:1], b[1:3], b[3:7], b[7:11], b[11:]},
+ }
+ if err := cc.RecvMsg(&rm, 0); err != nil {
+ t.Fatal(err)
+ }
+ if !bytes.Equal(b[:rm.N], data) {
+ t.Fatalf("got %#v; want %#v", b[:rm.N], data)
+ }
+ })
+ switch runtime.GOOS {
+ case "android", "linux":
+ t.Run("Messages", func(t *testing.T) {
+ data := []byte("HELLO-R-U-THERE")
+ wmbs := bytes.SplitAfter(data, []byte("-"))
+ wms := []socket.Message{
+ {Buffers: wmbs[:1], Addr: c.LocalAddr()},
+ {Buffers: wmbs[1:], Addr: c.LocalAddr()},
+ }
+ n, err := cc.SendMsgs(wms, 0)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if n != len(wms) {
+ t.Fatalf("got %d; want %d", n, len(wms))
+ }
+ b := make([]byte, 32)
+ rmbs := [][][]byte{{b[:len(wmbs[0])]}, {b[len(wmbs[0]):]}}
+ rms := []socket.Message{
+ {Buffers: rmbs[0]},
+ {Buffers: rmbs[1]},
+ }
+ n, err = cc.RecvMsgs(rms, 0)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if n != len(rms) {
+ t.Fatalf("got %d; want %d", n, len(rms))
+ }
+ nn := 0
+ for i := 0; i < n; i++ {
+ nn += rms[i].N
+ }
+ if !bytes.Equal(b[:nn], data) {
+ t.Fatalf("got %#v; want %#v", b[:nn], data)
+ }
+ })
+ }
+
+ // The behavior of transmission for zero byte paylaod depends
+ // on each platform implementation. Some may transmit only
+ // protocol header and options, other may transmit nothing.
+ // We test only that SendMsg and SendMsgs will not crash with
+ // empty buffers.
+ wm := socket.Message{
+ Buffers: [][]byte{{}},
+ Addr: c.LocalAddr(),
+ }
+ cc.SendMsg(&wm, 0)
+ wms := []socket.Message{
+ {Buffers: [][]byte{{}}, Addr: c.LocalAddr()},
+ }
+ cc.SendMsgs(wms, 0)
+}
+
+func BenchmarkUDP(b *testing.B) {
+ c, err := nettest.NewLocalPacketListener("udp")
+ if err != nil {
+ b.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
+ }
+ defer c.Close()
+ cc, err := socket.NewConn(c.(net.Conn))
+ if err != nil {
+ b.Fatal(err)
+ }
+ data := []byte("HELLO-R-U-THERE")
+ wm := socket.Message{
+ Buffers: [][]byte{data},
+ Addr: c.LocalAddr(),
+ }
+ rm := socket.Message{
+ Buffers: [][]byte{make([]byte, 128)},
+ OOB: make([]byte, 128),
+ }
+
+ for M := 1; M <= 1<<9; M = M << 1 {
+ b.Run(fmt.Sprintf("Iter-%d", M), func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ for j := 0; j < M; j++ {
+ if err := cc.SendMsg(&wm, 0); err != nil {
+ b.Fatal(err)
+ }
+ if err := cc.RecvMsg(&rm, 0); err != nil {
+ b.Fatal(err)
+ }
+ }
+ }
+ })
+ switch runtime.GOOS {
+ case "android", "linux":
+ wms := make([]socket.Message, M)
+ for i := range wms {
+ wms[i].Buffers = [][]byte{data}
+ wms[i].Addr = c.LocalAddr()
+ }
+ rms := make([]socket.Message, M)
+ for i := range rms {
+ rms[i].Buffers = [][]byte{make([]byte, 128)}
+ rms[i].OOB = make([]byte, 128)
+ }
+ b.Run(fmt.Sprintf("Batch-%d", M), func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ if _, err := cc.SendMsgs(wms, 0); err != nil {
+ b.Fatal(err)
+ }
+ if _, err := cc.RecvMsgs(rms, 0); err != nil {
+ b.Fatal(err)
+ }
+ }
+ })
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/socket_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/socket_test.go
new file mode 100644
index 000000000..bf3751b5e
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/socket_test.go
@@ -0,0 +1,46 @@
+// 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.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
+
+package socket_test
+
+import (
+ "net"
+ "runtime"
+ "syscall"
+ "testing"
+
+ "golang.org/x/net/internal/nettest"
+ "golang.org/x/net/internal/socket"
+)
+
+func TestSocket(t *testing.T) {
+ t.Run("Option", func(t *testing.T) {
+ testSocketOption(t, &socket.Option{Level: syscall.SOL_SOCKET, Name: syscall.SO_RCVBUF, Len: 4})
+ })
+}
+
+func testSocketOption(t *testing.T, so *socket.Option) {
+ c, err := nettest.NewLocalPacketListener("udp")
+ if err != nil {
+ t.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
+ }
+ defer c.Close()
+ cc, err := socket.NewConn(c.(net.Conn))
+ if err != nil {
+ t.Fatal(err)
+ }
+ const N = 2048
+ if err := so.SetInt(cc, N); err != nil {
+ t.Fatal(err)
+ }
+ n, err := so.GetInt(cc)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if n < N {
+ t.Fatalf("got %d; want greater than or equal to %d", n, N)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys.go
new file mode 100644
index 000000000..4f0eead13
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys.go
@@ -0,0 +1,33 @@
+// 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"
+)
+
+var (
+ // NativeEndian is the machine native endian implementation of
+ // ByteOrder.
+ NativeEndian binary.ByteOrder
+
+ kernelAlign int
+)
+
+func init() {
+ i := uint32(1)
+ b := (*[4]byte)(unsafe.Pointer(&i))
+ if b[0] == 1 {
+ NativeEndian = binary.LittleEndian
+ } else {
+ NativeEndian = binary.BigEndian
+ }
+ kernelAlign = probeProtocolStack()
+}
+
+func roundup(l int) int {
+ return (l + kernelAlign - 1) & ^(kernelAlign - 1)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_bsd.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_bsd.go
new file mode 100644
index 000000000..f13e14ff3
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_bsd.go
@@ -0,0 +1,17 @@
+// 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.
+
+// +build darwin dragonfly freebsd openbsd
+
+package socket
+
+import "errors"
+
+func recvmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) {
+ return 0, errors.New("not implemented")
+}
+
+func sendmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) {
+ return 0, errors.New("not implemented")
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_bsdvar.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_bsdvar.go
new file mode 100644
index 000000000..f723fa36a
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_bsdvar.go
@@ -0,0 +1,14 @@
+// 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.
+
+// +build freebsd netbsd openbsd
+
+package socket
+
+import "unsafe"
+
+func probeProtocolStack() int {
+ var p uintptr
+ return int(unsafe.Sizeof(p))
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_darwin.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_darwin.go
new file mode 100644
index 000000000..b17d223bf
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_darwin.go
@@ -0,0 +1,7 @@
+// 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
+
+func probeProtocolStack() int { return 4 }
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_dragonfly.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_dragonfly.go
new file mode 100644
index 000000000..b17d223bf
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_dragonfly.go
@@ -0,0 +1,7 @@
+// 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
+
+func probeProtocolStack() int { return 4 }
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux.go
new file mode 100644
index 000000000..1559521e0
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux.go
@@ -0,0 +1,27 @@
+// 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.
+
+// +build linux,!s390x,!386
+
+package socket
+
+import (
+ "syscall"
+ "unsafe"
+)
+
+func probeProtocolStack() int {
+ var p uintptr
+ return int(unsafe.Sizeof(p))
+}
+
+func recvmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) {
+ n, _, errno := syscall.Syscall6(sysRECVMMSG, s, uintptr(unsafe.Pointer(&hs[0])), uintptr(len(hs)), uintptr(flags), 0, 0)
+ return int(n), errnoErr(errno)
+}
+
+func sendmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) {
+ n, _, errno := syscall.Syscall6(sysSENDMMSG, s, uintptr(unsafe.Pointer(&hs[0])), uintptr(len(hs)), uintptr(flags), 0, 0)
+ return int(n), errnoErr(errno)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_386.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_386.go
new file mode 100644
index 000000000..235b2cc08
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_386.go
@@ -0,0 +1,55 @@
+// 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 (
+ "syscall"
+ "unsafe"
+)
+
+func probeProtocolStack() int { return 4 }
+
+const (
+ sysSETSOCKOPT = 0xe
+ sysGETSOCKOPT = 0xf
+ sysSENDMSG = 0x10
+ sysRECVMSG = 0x11
+ sysRECVMMSG = 0x13
+ sysSENDMMSG = 0x14
+)
+
+func socketcall(call, a0, a1, a2, a3, a4, a5 uintptr) (uintptr, syscall.Errno)
+func rawsocketcall(call, a0, a1, a2, a3, a4, a5 uintptr) (uintptr, syscall.Errno)
+
+func getsockopt(s uintptr, level, name int, b []byte) (int, error) {
+ l := uint32(len(b))
+ _, errno := socketcall(sysGETSOCKOPT, s, uintptr(level), uintptr(name), uintptr(unsafe.Pointer(&b[0])), uintptr(unsafe.Pointer(&l)), 0)
+ return int(l), errnoErr(errno)
+}
+
+func setsockopt(s uintptr, level, name int, b []byte) error {
+ _, errno := socketcall(sysSETSOCKOPT, s, uintptr(level), uintptr(name), uintptr(unsafe.Pointer(&b[0])), uintptr(len(b)), 0)
+ return errnoErr(errno)
+}
+
+func recvmsg(s uintptr, h *msghdr, flags int) (int, error) {
+ n, errno := socketcall(sysRECVMSG, s, uintptr(unsafe.Pointer(h)), uintptr(flags), 0, 0, 0)
+ return int(n), errnoErr(errno)
+}
+
+func sendmsg(s uintptr, h *msghdr, flags int) (int, error) {
+ n, errno := socketcall(sysSENDMSG, s, uintptr(unsafe.Pointer(h)), uintptr(flags), 0, 0, 0)
+ return int(n), errnoErr(errno)
+}
+
+func recvmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) {
+ n, errno := socketcall(sysRECVMMSG, s, uintptr(unsafe.Pointer(&hs[0])), uintptr(len(hs)), uintptr(flags), 0, 0)
+ return int(n), errnoErr(errno)
+}
+
+func sendmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) {
+ n, errno := socketcall(sysSENDMMSG, s, uintptr(unsafe.Pointer(&hs[0])), uintptr(len(hs)), uintptr(flags), 0, 0)
+ return int(n), errnoErr(errno)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_386.s b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_386.s
new file mode 100644
index 000000000..93e7d75ec
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_386.s
@@ -0,0 +1,11 @@
+// Copyright 2014 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.
+
+#include "textflag.h"
+
+TEXT ·socketcall(SB),NOSPLIT,$0-36
+ JMP syscall·socketcall(SB)
+
+TEXT ·rawsocketcall(SB),NOSPLIT,$0-36
+ JMP syscall·rawsocketcall(SB)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_amd64.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_amd64.go
new file mode 100644
index 000000000..9decee2e5
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_amd64.go
@@ -0,0 +1,10 @@
+// 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
+
+const (
+ sysRECVMMSG = 0x12b
+ sysSENDMMSG = 0x133
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_arm.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_arm.go
new file mode 100644
index 000000000..d753b436d
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_arm.go
@@ -0,0 +1,10 @@
+// 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
+
+const (
+ sysRECVMMSG = 0x16d
+ sysSENDMMSG = 0x176
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_arm64.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_arm64.go
new file mode 100644
index 000000000..b67089436
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_arm64.go
@@ -0,0 +1,10 @@
+// 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
+
+const (
+ sysRECVMMSG = 0xf3
+ sysSENDMMSG = 0x10d
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_mips.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_mips.go
new file mode 100644
index 000000000..9c0d74014
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_mips.go
@@ -0,0 +1,10 @@
+// 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
+
+const (
+ sysRECVMMSG = 0x10ef
+ sysSENDMMSG = 0x10f7
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_mips64.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_mips64.go
new file mode 100644
index 000000000..071a4aba8
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_mips64.go
@@ -0,0 +1,10 @@
+// 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
+
+const (
+ sysRECVMMSG = 0x14ae
+ sysSENDMMSG = 0x14b6
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_mips64le.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_mips64le.go
new file mode 100644
index 000000000..071a4aba8
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_mips64le.go
@@ -0,0 +1,10 @@
+// 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
+
+const (
+ sysRECVMMSG = 0x14ae
+ sysSENDMMSG = 0x14b6
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_mipsle.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_mipsle.go
new file mode 100644
index 000000000..9c0d74014
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_mipsle.go
@@ -0,0 +1,10 @@
+// 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
+
+const (
+ sysRECVMMSG = 0x10ef
+ sysSENDMMSG = 0x10f7
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_ppc64.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_ppc64.go
new file mode 100644
index 000000000..21c1e3f00
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_ppc64.go
@@ -0,0 +1,10 @@
+// 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
+
+const (
+ sysRECVMMSG = 0x157
+ sysSENDMMSG = 0x15d
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_ppc64le.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_ppc64le.go
new file mode 100644
index 000000000..21c1e3f00
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_ppc64le.go
@@ -0,0 +1,10 @@
+// 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
+
+const (
+ sysRECVMMSG = 0x157
+ sysSENDMMSG = 0x15d
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_s390x.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_s390x.go
new file mode 100644
index 000000000..327979efb
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_s390x.go
@@ -0,0 +1,55 @@
+// 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 (
+ "syscall"
+ "unsafe"
+)
+
+func probeProtocolStack() int { return 8 }
+
+const (
+ sysSETSOCKOPT = 0xe
+ sysGETSOCKOPT = 0xf
+ sysSENDMSG = 0x10
+ sysRECVMSG = 0x11
+ sysRECVMMSG = 0x13
+ sysSENDMMSG = 0x14
+)
+
+func socketcall(call, a0, a1, a2, a3, a4, a5 uintptr) (uintptr, syscall.Errno)
+func rawsocketcall(call, a0, a1, a2, a3, a4, a5 uintptr) (uintptr, syscall.Errno)
+
+func getsockopt(s uintptr, level, name int, b []byte) (int, error) {
+ l := uint32(len(b))
+ _, errno := socketcall(sysGETSOCKOPT, s, uintptr(level), uintptr(name), uintptr(unsafe.Pointer(&b[0])), uintptr(unsafe.Pointer(&l)), 0)
+ return int(l), errnoErr(errno)
+}
+
+func setsockopt(s uintptr, level, name int, b []byte) error {
+ _, errno := socketcall(sysSETSOCKOPT, s, uintptr(level), uintptr(name), uintptr(unsafe.Pointer(&b[0])), uintptr(len(b)), 0)
+ return errnoErr(errno)
+}
+
+func recvmsg(s uintptr, h *msghdr, flags int) (int, error) {
+ n, errno := socketcall(sysRECVMSG, s, uintptr(unsafe.Pointer(h)), uintptr(flags), 0, 0, 0)
+ return int(n), errnoErr(errno)
+}
+
+func sendmsg(s uintptr, h *msghdr, flags int) (int, error) {
+ n, errno := socketcall(sysSENDMSG, s, uintptr(unsafe.Pointer(h)), uintptr(flags), 0, 0, 0)
+ return int(n), errnoErr(errno)
+}
+
+func recvmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) {
+ n, errno := socketcall(sysRECVMMSG, s, uintptr(unsafe.Pointer(&hs[0])), uintptr(len(hs)), uintptr(flags), 0, 0)
+ return int(n), errnoErr(errno)
+}
+
+func sendmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) {
+ n, errno := socketcall(sysSENDMMSG, s, uintptr(unsafe.Pointer(&hs[0])), uintptr(len(hs)), uintptr(flags), 0, 0)
+ return int(n), errnoErr(errno)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_s390x.s b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_s390x.s
new file mode 100644
index 000000000..06d75628c
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_linux_s390x.s
@@ -0,0 +1,11 @@
+// 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.
+
+#include "textflag.h"
+
+TEXT ·socketcall(SB),NOSPLIT,$0-72
+ JMP syscall·socketcall(SB)
+
+TEXT ·rawsocketcall(SB),NOSPLIT,$0-72
+ JMP syscall·rawsocketcall(SB)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_netbsd.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_netbsd.go
new file mode 100644
index 000000000..431851c12
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_netbsd.go
@@ -0,0 +1,25 @@
+// 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 (
+ "syscall"
+ "unsafe"
+)
+
+const (
+ sysRECVMMSG = 0x1db
+ sysSENDMMSG = 0x1dc
+)
+
+func recvmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) {
+ n, _, errno := syscall.Syscall6(sysRECVMMSG, s, uintptr(unsafe.Pointer(&hs[0])), uintptr(len(hs)), uintptr(flags), 0, 0)
+ return int(n), errnoErr(errno)
+}
+
+func sendmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) {
+ n, _, errno := syscall.Syscall6(sysSENDMMSG, s, uintptr(unsafe.Pointer(&hs[0])), uintptr(len(hs)), uintptr(flags), 0, 0)
+ return int(n), errnoErr(errno)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_posix.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_posix.go
new file mode 100644
index 000000000..dc130c27e
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_posix.go
@@ -0,0 +1,168 @@
+// 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.
+
+// +build go1.9
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
+
+package socket
+
+import (
+ "encoding/binary"
+ "errors"
+ "net"
+ "runtime"
+ "strconv"
+ "sync"
+ "time"
+)
+
+func marshalInetAddr(a net.Addr) []byte {
+ switch a := a.(type) {
+ case *net.TCPAddr:
+ return marshalSockaddr(a.IP, a.Port, a.Zone)
+ case *net.UDPAddr:
+ return marshalSockaddr(a.IP, a.Port, a.Zone)
+ case *net.IPAddr:
+ return marshalSockaddr(a.IP, 0, a.Zone)
+ default:
+ return nil
+ }
+}
+
+func marshalSockaddr(ip net.IP, port int, zone string) []byte {
+ if ip4 := ip.To4(); ip4 != nil {
+ b := make([]byte, sizeofSockaddrInet)
+ switch runtime.GOOS {
+ case "android", "linux", "solaris", "windows":
+ NativeEndian.PutUint16(b[:2], uint16(sysAF_INET))
+ default:
+ b[0] = sizeofSockaddrInet
+ b[1] = sysAF_INET
+ }
+ binary.BigEndian.PutUint16(b[2:4], uint16(port))
+ copy(b[4:8], ip4)
+ return b
+ }
+ if ip6 := ip.To16(); ip6 != nil && ip.To4() == nil {
+ b := make([]byte, sizeofSockaddrInet6)
+ switch runtime.GOOS {
+ case "android", "linux", "solaris", "windows":
+ NativeEndian.PutUint16(b[:2], uint16(sysAF_INET6))
+ default:
+ b[0] = sizeofSockaddrInet6
+ b[1] = sysAF_INET6
+ }
+ binary.BigEndian.PutUint16(b[2:4], uint16(port))
+ copy(b[8:24], ip6)
+ if zone != "" {
+ NativeEndian.PutUint32(b[24:28], uint32(zoneCache.index(zone)))
+ }
+ return b
+ }
+ return nil
+}
+
+func parseInetAddr(b []byte, network string) (net.Addr, error) {
+ if len(b) < 2 {
+ return nil, errors.New("invalid address")
+ }
+ var af int
+ switch runtime.GOOS {
+ case "android", "linux", "solaris", "windows":
+ af = int(NativeEndian.Uint16(b[:2]))
+ default:
+ af = int(b[1])
+ }
+ var ip net.IP
+ var zone string
+ if af == sysAF_INET {
+ if len(b) < sizeofSockaddrInet {
+ return nil, errors.New("short address")
+ }
+ ip = make(net.IP, net.IPv4len)
+ copy(ip, b[4:8])
+ }
+ if af == sysAF_INET6 {
+ if len(b) < sizeofSockaddrInet6 {
+ return nil, errors.New("short address")
+ }
+ ip = make(net.IP, net.IPv6len)
+ copy(ip, b[8:24])
+ if id := int(NativeEndian.Uint32(b[24:28])); id > 0 {
+ zone = zoneCache.name(id)
+ }
+ }
+ switch network {
+ case "tcp", "tcp4", "tcp6":
+ return &net.TCPAddr{IP: ip, Port: int(binary.BigEndian.Uint16(b[2:4])), Zone: zone}, nil
+ case "udp", "udp4", "udp6":
+ return &net.UDPAddr{IP: ip, Port: int(binary.BigEndian.Uint16(b[2:4])), Zone: zone}, nil
+ default:
+ return &net.IPAddr{IP: ip, Zone: zone}, nil
+ }
+}
+
+// An ipv6ZoneCache represents a cache holding partial network
+// interface information. It is used for reducing the cost of IPv6
+// addressing scope zone resolution.
+//
+// Multiple names sharing the index are managed by first-come
+// first-served basis for consistency.
+type ipv6ZoneCache struct {
+ sync.RWMutex // guard the following
+ lastFetched time.Time // last time routing information was fetched
+ toIndex map[string]int // interface name to its index
+ toName map[int]string // interface index to its name
+}
+
+var zoneCache = ipv6ZoneCache{
+ toIndex: make(map[string]int),
+ toName: make(map[int]string),
+}
+
+func (zc *ipv6ZoneCache) update(ift []net.Interface) {
+ zc.Lock()
+ defer zc.Unlock()
+ now := time.Now()
+ if zc.lastFetched.After(now.Add(-60 * time.Second)) {
+ return
+ }
+ zc.lastFetched = now
+ if len(ift) == 0 {
+ var err error
+ if ift, err = net.Interfaces(); err != nil {
+ return
+ }
+ }
+ zc.toIndex = make(map[string]int, len(ift))
+ zc.toName = make(map[int]string, len(ift))
+ for _, ifi := range ift {
+ zc.toIndex[ifi.Name] = ifi.Index
+ if _, ok := zc.toName[ifi.Index]; !ok {
+ zc.toName[ifi.Index] = ifi.Name
+ }
+ }
+}
+
+func (zc *ipv6ZoneCache) name(zone int) string {
+ zoneCache.update(nil)
+ zoneCache.RLock()
+ defer zoneCache.RUnlock()
+ name, ok := zoneCache.toName[zone]
+ if !ok {
+ name = strconv.Itoa(zone)
+ }
+ return name
+}
+
+func (zc *ipv6ZoneCache) index(zone string) int {
+ zoneCache.update(nil)
+ zoneCache.RLock()
+ defer zoneCache.RUnlock()
+ index, ok := zoneCache.toIndex[zone]
+ if !ok {
+ index, _ = strconv.Atoi(zone)
+ }
+ return index
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_solaris.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_solaris.go
new file mode 100644
index 000000000..cced74e60
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_solaris.go
@@ -0,0 +1,71 @@
+// 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 (
+ "errors"
+ "runtime"
+ "syscall"
+ "unsafe"
+)
+
+func probeProtocolStack() int {
+ switch runtime.GOARCH {
+ case "amd64":
+ return 4
+ default:
+ var p uintptr
+ return int(unsafe.Sizeof(p))
+ }
+}
+
+//go:cgo_import_dynamic libc___xnet_getsockopt __xnet_getsockopt "libsocket.so"
+//go:cgo_import_dynamic libc_setsockopt setsockopt "libsocket.so"
+//go:cgo_import_dynamic libc___xnet_recvmsg __xnet_recvmsg "libsocket.so"
+//go:cgo_import_dynamic libc___xnet_sendmsg __xnet_sendmsg "libsocket.so"
+
+//go:linkname procGetsockopt libc___xnet_getsockopt
+//go:linkname procSetsockopt libc_setsockopt
+//go:linkname procRecvmsg libc___xnet_recvmsg
+//go:linkname procSendmsg libc___xnet_sendmsg
+
+var (
+ procGetsockopt uintptr
+ procSetsockopt uintptr
+ procRecvmsg uintptr
+ procSendmsg uintptr
+)
+
+func sysvicall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (uintptr, uintptr, syscall.Errno)
+func rawSysvicall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (uintptr, uintptr, syscall.Errno)
+
+func getsockopt(s uintptr, level, name int, b []byte) (int, error) {
+ l := uint32(len(b))
+ _, _, errno := sysvicall6(uintptr(unsafe.Pointer(&procGetsockopt)), 5, s, uintptr(level), uintptr(name), uintptr(unsafe.Pointer(&b[0])), uintptr(unsafe.Pointer(&l)), 0)
+ return int(l), errnoErr(errno)
+}
+
+func setsockopt(s uintptr, level, name int, b []byte) error {
+ _, _, errno := sysvicall6(uintptr(unsafe.Pointer(&procSetsockopt)), 5, s, uintptr(level), uintptr(name), uintptr(unsafe.Pointer(&b[0])), uintptr(len(b)), 0)
+ return errnoErr(errno)
+}
+
+func recvmsg(s uintptr, h *msghdr, flags int) (int, error) {
+ n, _, errno := sysvicall6(uintptr(unsafe.Pointer(&procRecvmsg)), 3, s, uintptr(unsafe.Pointer(h)), uintptr(flags), 0, 0, 0)
+ return int(n), errnoErr(errno)
+}
+
+func sendmsg(s uintptr, h *msghdr, flags int) (int, error) {
+ n, _, errno := sysvicall6(uintptr(unsafe.Pointer(&procSendmsg)), 3, s, uintptr(unsafe.Pointer(h)), uintptr(flags), 0, 0, 0)
+ return int(n), errnoErr(errno)
+}
+
+func recvmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) {
+ return 0, errors.New("not implemented")
+}
+
+func sendmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) {
+ return 0, errors.New("not implemented")
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_solaris_amd64.s b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_solaris_amd64.s
new file mode 100644
index 000000000..a18ac5ed7
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_solaris_amd64.s
@@ -0,0 +1,11 @@
+// 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.
+
+#include "textflag.h"
+
+TEXT ·sysvicall6(SB),NOSPLIT,$0-88
+ JMP syscall·sysvicall6(SB)
+
+TEXT ·rawSysvicall6(SB),NOSPLIT,$0-88
+ JMP syscall·rawSysvicall6(SB)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_stub.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_stub.go
new file mode 100644
index 000000000..d9f06d00e
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_stub.go
@@ -0,0 +1,64 @@
+// 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.
+
+// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows
+
+package socket
+
+import (
+ "errors"
+ "net"
+ "runtime"
+ "unsafe"
+)
+
+const (
+ sysAF_UNSPEC = 0x0
+ sysAF_INET = 0x2
+ sysAF_INET6 = 0xa
+
+ sysSOCK_RAW = 0x3
+)
+
+func probeProtocolStack() int {
+ switch runtime.GOARCH {
+ case "amd64p32", "mips64p32":
+ return 4
+ default:
+ var p uintptr
+ return int(unsafe.Sizeof(p))
+ }
+}
+
+func marshalInetAddr(ip net.IP, port int, zone string) []byte {
+ return nil
+}
+
+func parseInetAddr(b []byte, network string) (net.Addr, error) {
+ return nil, errors.New("not implemented")
+}
+
+func getsockopt(s uintptr, level, name int, b []byte) (int, error) {
+ return 0, errors.New("not implemented")
+}
+
+func setsockopt(s uintptr, level, name int, b []byte) error {
+ return errors.New("not implemented")
+}
+
+func recvmsg(s uintptr, h *msghdr, flags int) (int, error) {
+ return 0, errors.New("not implemented")
+}
+
+func sendmsg(s uintptr, h *msghdr, flags int) (int, error) {
+ return 0, errors.New("not implemented")
+}
+
+func recvmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) {
+ return 0, errors.New("not implemented")
+}
+
+func sendmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) {
+ return 0, errors.New("not implemented")
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_unix.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_unix.go
new file mode 100644
index 000000000..18eba3085
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_unix.go
@@ -0,0 +1,33 @@
+// 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.
+
+// +build darwin dragonfly freebsd linux,!s390x,!386 netbsd openbsd
+
+package socket
+
+import (
+ "syscall"
+ "unsafe"
+)
+
+func getsockopt(s uintptr, level, name int, b []byte) (int, error) {
+ l := uint32(len(b))
+ _, _, errno := syscall.Syscall6(syscall.SYS_GETSOCKOPT, s, uintptr(level), uintptr(name), uintptr(unsafe.Pointer(&b[0])), uintptr(unsafe.Pointer(&l)), 0)
+ return int(l), errnoErr(errno)
+}
+
+func setsockopt(s uintptr, level, name int, b []byte) error {
+ _, _, errno := syscall.Syscall6(syscall.SYS_SETSOCKOPT, s, uintptr(level), uintptr(name), uintptr(unsafe.Pointer(&b[0])), uintptr(len(b)), 0)
+ return errnoErr(errno)
+}
+
+func recvmsg(s uintptr, h *msghdr, flags int) (int, error) {
+ n, _, errno := syscall.Syscall(syscall.SYS_RECVMSG, s, uintptr(unsafe.Pointer(h)), uintptr(flags))
+ return int(n), errnoErr(errno)
+}
+
+func sendmsg(s uintptr, h *msghdr, flags int) (int, error) {
+ n, _, errno := syscall.Syscall(syscall.SYS_SENDMSG, s, uintptr(unsafe.Pointer(h)), uintptr(flags))
+ return int(n), errnoErr(errno)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_windows.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_windows.go
new file mode 100644
index 000000000..54a470ebe
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/sys_windows.go
@@ -0,0 +1,70 @@
+// 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 (
+ "errors"
+ "syscall"
+ "unsafe"
+)
+
+func probeProtocolStack() int {
+ var p uintptr
+ return int(unsafe.Sizeof(p))
+}
+
+const (
+ sysAF_UNSPEC = 0x0
+ sysAF_INET = 0x2
+ sysAF_INET6 = 0x17
+
+ sysSOCK_RAW = 0x3
+)
+
+type sockaddrInet struct {
+ Family uint16
+ Port uint16
+ Addr [4]byte /* in_addr */
+ Zero [8]uint8
+}
+
+type sockaddrInet6 struct {
+ Family uint16
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+const (
+ sizeofSockaddrInet = 0x10
+ sizeofSockaddrInet6 = 0x1c
+)
+
+func getsockopt(s uintptr, level, name int, b []byte) (int, error) {
+ l := uint32(len(b))
+ err := syscall.Getsockopt(syscall.Handle(s), int32(level), int32(name), (*byte)(unsafe.Pointer(&b[0])), (*int32)(unsafe.Pointer(&l)))
+ return int(l), err
+}
+
+func setsockopt(s uintptr, level, name int, b []byte) error {
+ return syscall.Setsockopt(syscall.Handle(s), int32(level), int32(name), (*byte)(unsafe.Pointer(&b[0])), int32(len(b)))
+}
+
+func recvmsg(s uintptr, h *msghdr, flags int) (int, error) {
+ return 0, errors.New("not implemented")
+}
+
+func sendmsg(s uintptr, h *msghdr, flags int) (int, error) {
+ return 0, errors.New("not implemented")
+}
+
+func recvmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) {
+ return 0, errors.New("not implemented")
+}
+
+func sendmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) {
+ return 0, errors.New("not implemented")
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_darwin_386.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_darwin_386.go
new file mode 100644
index 000000000..26f8feff3
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_darwin_386.go
@@ -0,0 +1,59 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_darwin.go
+
+package socket
+
+const (
+ sysAF_UNSPEC = 0x0
+ sysAF_INET = 0x2
+ sysAF_INET6 = 0x1e
+
+ sysSOCK_RAW = 0x3
+)
+
+type iovec struct {
+ Base *byte
+ Len uint32
+}
+
+type msghdr struct {
+ Name *byte
+ Namelen uint32
+ Iov *iovec
+ Iovlen int32
+ Control *byte
+ Controllen uint32
+ Flags int32
+}
+
+type cmsghdr struct {
+ Len uint32
+ Level int32
+ Type int32
+}
+
+type sockaddrInet struct {
+ Len uint8
+ Family uint8
+ Port uint16
+ Addr [4]byte /* in_addr */
+ Zero [8]int8
+}
+
+type sockaddrInet6 struct {
+ Len uint8
+ Family uint8
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+const (
+ sizeofIovec = 0x8
+ sizeofMsghdr = 0x1c
+ sizeofCmsghdr = 0xc
+
+ sizeofSockaddrInet = 0x10
+ sizeofSockaddrInet6 = 0x1c
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_darwin_amd64.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_darwin_amd64.go
new file mode 100644
index 000000000..e2987f7db
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_darwin_amd64.go
@@ -0,0 +1,61 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_darwin.go
+
+package socket
+
+const (
+ sysAF_UNSPEC = 0x0
+ sysAF_INET = 0x2
+ sysAF_INET6 = 0x1e
+
+ sysSOCK_RAW = 0x3
+)
+
+type iovec struct {
+ Base *byte
+ Len uint64
+}
+
+type msghdr struct {
+ Name *byte
+ Namelen uint32
+ Pad_cgo_0 [4]byte
+ Iov *iovec
+ Iovlen int32
+ Pad_cgo_1 [4]byte
+ Control *byte
+ Controllen uint32
+ Flags int32
+}
+
+type cmsghdr struct {
+ Len uint32
+ Level int32
+ Type int32
+}
+
+type sockaddrInet struct {
+ Len uint8
+ Family uint8
+ Port uint16
+ Addr [4]byte /* in_addr */
+ Zero [8]int8
+}
+
+type sockaddrInet6 struct {
+ Len uint8
+ Family uint8
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+const (
+ sizeofIovec = 0x10
+ sizeofMsghdr = 0x30
+ sizeofCmsghdr = 0xc
+
+ sizeofSockaddrInet = 0x10
+ sizeofSockaddrInet6 = 0x1c
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_darwin_arm.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_darwin_arm.go
new file mode 100644
index 000000000..26f8feff3
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_darwin_arm.go
@@ -0,0 +1,59 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_darwin.go
+
+package socket
+
+const (
+ sysAF_UNSPEC = 0x0
+ sysAF_INET = 0x2
+ sysAF_INET6 = 0x1e
+
+ sysSOCK_RAW = 0x3
+)
+
+type iovec struct {
+ Base *byte
+ Len uint32
+}
+
+type msghdr struct {
+ Name *byte
+ Namelen uint32
+ Iov *iovec
+ Iovlen int32
+ Control *byte
+ Controllen uint32
+ Flags int32
+}
+
+type cmsghdr struct {
+ Len uint32
+ Level int32
+ Type int32
+}
+
+type sockaddrInet struct {
+ Len uint8
+ Family uint8
+ Port uint16
+ Addr [4]byte /* in_addr */
+ Zero [8]int8
+}
+
+type sockaddrInet6 struct {
+ Len uint8
+ Family uint8
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+const (
+ sizeofIovec = 0x8
+ sizeofMsghdr = 0x1c
+ sizeofCmsghdr = 0xc
+
+ sizeofSockaddrInet = 0x10
+ sizeofSockaddrInet6 = 0x1c
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_dragonfly_amd64.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_dragonfly_amd64.go
new file mode 100644
index 000000000..c582abd57
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_dragonfly_amd64.go
@@ -0,0 +1,61 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_dragonfly.go
+
+package socket
+
+const (
+ sysAF_UNSPEC = 0x0
+ sysAF_INET = 0x2
+ sysAF_INET6 = 0x1c
+
+ sysSOCK_RAW = 0x3
+)
+
+type iovec struct {
+ Base *byte
+ Len uint64
+}
+
+type msghdr struct {
+ Name *byte
+ Namelen uint32
+ Pad_cgo_0 [4]byte
+ Iov *iovec
+ Iovlen int32
+ Pad_cgo_1 [4]byte
+ Control *byte
+ Controllen uint32
+ Flags int32
+}
+
+type cmsghdr struct {
+ Len uint32
+ Level int32
+ Type int32
+}
+
+type sockaddrInet struct {
+ Len uint8
+ Family uint8
+ Port uint16
+ Addr [4]byte /* in_addr */
+ Zero [8]int8
+}
+
+type sockaddrInet6 struct {
+ Len uint8
+ Family uint8
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+const (
+ sizeofIovec = 0x10
+ sizeofMsghdr = 0x30
+ sizeofCmsghdr = 0xc
+
+ sizeofSockaddrInet = 0x10
+ sizeofSockaddrInet6 = 0x1c
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_freebsd_386.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_freebsd_386.go
new file mode 100644
index 000000000..04a24886c
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_freebsd_386.go
@@ -0,0 +1,59 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_freebsd.go
+
+package socket
+
+const (
+ sysAF_UNSPEC = 0x0
+ sysAF_INET = 0x2
+ sysAF_INET6 = 0x1c
+
+ sysSOCK_RAW = 0x3
+)
+
+type iovec struct {
+ Base *byte
+ Len uint32
+}
+
+type msghdr struct {
+ Name *byte
+ Namelen uint32
+ Iov *iovec
+ Iovlen int32
+ Control *byte
+ Controllen uint32
+ Flags int32
+}
+
+type cmsghdr struct {
+ Len uint32
+ Level int32
+ Type int32
+}
+
+type sockaddrInet struct {
+ Len uint8
+ Family uint8
+ Port uint16
+ Addr [4]byte /* in_addr */
+ Zero [8]int8
+}
+
+type sockaddrInet6 struct {
+ Len uint8
+ Family uint8
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+const (
+ sizeofIovec = 0x8
+ sizeofMsghdr = 0x1c
+ sizeofCmsghdr = 0xc
+
+ sizeofSockaddrInet = 0x10
+ sizeofSockaddrInet6 = 0x1c
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_freebsd_amd64.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_freebsd_amd64.go
new file mode 100644
index 000000000..35c7cb9c9
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_freebsd_amd64.go
@@ -0,0 +1,61 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_freebsd.go
+
+package socket
+
+const (
+ sysAF_UNSPEC = 0x0
+ sysAF_INET = 0x2
+ sysAF_INET6 = 0x1c
+
+ sysSOCK_RAW = 0x3
+)
+
+type iovec struct {
+ Base *byte
+ Len uint64
+}
+
+type msghdr struct {
+ Name *byte
+ Namelen uint32
+ Pad_cgo_0 [4]byte
+ Iov *iovec
+ Iovlen int32
+ Pad_cgo_1 [4]byte
+ Control *byte
+ Controllen uint32
+ Flags int32
+}
+
+type cmsghdr struct {
+ Len uint32
+ Level int32
+ Type int32
+}
+
+type sockaddrInet struct {
+ Len uint8
+ Family uint8
+ Port uint16
+ Addr [4]byte /* in_addr */
+ Zero [8]int8
+}
+
+type sockaddrInet6 struct {
+ Len uint8
+ Family uint8
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+const (
+ sizeofIovec = 0x10
+ sizeofMsghdr = 0x30
+ sizeofCmsghdr = 0xc
+
+ sizeofSockaddrInet = 0x10
+ sizeofSockaddrInet6 = 0x1c
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_freebsd_arm.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_freebsd_arm.go
new file mode 100644
index 000000000..04a24886c
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_freebsd_arm.go
@@ -0,0 +1,59 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_freebsd.go
+
+package socket
+
+const (
+ sysAF_UNSPEC = 0x0
+ sysAF_INET = 0x2
+ sysAF_INET6 = 0x1c
+
+ sysSOCK_RAW = 0x3
+)
+
+type iovec struct {
+ Base *byte
+ Len uint32
+}
+
+type msghdr struct {
+ Name *byte
+ Namelen uint32
+ Iov *iovec
+ Iovlen int32
+ Control *byte
+ Controllen uint32
+ Flags int32
+}
+
+type cmsghdr struct {
+ Len uint32
+ Level int32
+ Type int32
+}
+
+type sockaddrInet struct {
+ Len uint8
+ Family uint8
+ Port uint16
+ Addr [4]byte /* in_addr */
+ Zero [8]int8
+}
+
+type sockaddrInet6 struct {
+ Len uint8
+ Family uint8
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+const (
+ sizeofIovec = 0x8
+ sizeofMsghdr = 0x1c
+ sizeofCmsghdr = 0xc
+
+ sizeofSockaddrInet = 0x10
+ sizeofSockaddrInet6 = 0x1c
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_linux_386.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_linux_386.go
new file mode 100644
index 000000000..430206930
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_linux_386.go
@@ -0,0 +1,63 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_linux.go
+
+package socket
+
+const (
+ sysAF_UNSPEC = 0x0
+ sysAF_INET = 0x2
+ sysAF_INET6 = 0xa
+
+ sysSOCK_RAW = 0x3
+)
+
+type iovec struct {
+ Base *byte
+ Len uint32
+}
+
+type msghdr struct {
+ Name *byte
+ Namelen uint32
+ Iov *iovec
+ Iovlen uint32
+ Control *byte
+ Controllen uint32
+ Flags int32
+}
+
+type mmsghdr struct {
+ Hdr msghdr
+ Len uint32
+}
+
+type cmsghdr struct {
+ Len uint32
+ Level int32
+ Type int32
+}
+
+type sockaddrInet struct {
+ Family uint16
+ Port uint16
+ Addr [4]byte /* in_addr */
+ X__pad [8]uint8
+}
+
+type sockaddrInet6 struct {
+ Family uint16
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+const (
+ sizeofIovec = 0x8
+ sizeofMsghdr = 0x1c
+ sizeofMmsghdr = 0x20
+ sizeofCmsghdr = 0xc
+
+ sizeofSockaddrInet = 0x10
+ sizeofSockaddrInet6 = 0x1c
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_linux_amd64.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_linux_amd64.go
new file mode 100644
index 000000000..1502f6c55
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_linux_amd64.go
@@ -0,0 +1,66 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_linux.go
+
+package socket
+
+const (
+ sysAF_UNSPEC = 0x0
+ sysAF_INET = 0x2
+ sysAF_INET6 = 0xa
+
+ sysSOCK_RAW = 0x3
+)
+
+type iovec struct {
+ Base *byte
+ Len uint64
+}
+
+type msghdr struct {
+ Name *byte
+ Namelen uint32
+ Pad_cgo_0 [4]byte
+ Iov *iovec
+ Iovlen uint64
+ Control *byte
+ Controllen uint64
+ Flags int32
+ Pad_cgo_1 [4]byte
+}
+
+type mmsghdr struct {
+ Hdr msghdr
+ Len uint32
+ Pad_cgo_0 [4]byte
+}
+
+type cmsghdr struct {
+ Len uint64
+ Level int32
+ Type int32
+}
+
+type sockaddrInet struct {
+ Family uint16
+ Port uint16
+ Addr [4]byte /* in_addr */
+ X__pad [8]uint8
+}
+
+type sockaddrInet6 struct {
+ Family uint16
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+const (
+ sizeofIovec = 0x10
+ sizeofMsghdr = 0x38
+ sizeofMmsghdr = 0x40
+ sizeofCmsghdr = 0x10
+
+ sizeofSockaddrInet = 0x10
+ sizeofSockaddrInet6 = 0x1c
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_linux_arm.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_linux_arm.go
new file mode 100644
index 000000000..430206930
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_linux_arm.go
@@ -0,0 +1,63 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_linux.go
+
+package socket
+
+const (
+ sysAF_UNSPEC = 0x0
+ sysAF_INET = 0x2
+ sysAF_INET6 = 0xa
+
+ sysSOCK_RAW = 0x3
+)
+
+type iovec struct {
+ Base *byte
+ Len uint32
+}
+
+type msghdr struct {
+ Name *byte
+ Namelen uint32
+ Iov *iovec
+ Iovlen uint32
+ Control *byte
+ Controllen uint32
+ Flags int32
+}
+
+type mmsghdr struct {
+ Hdr msghdr
+ Len uint32
+}
+
+type cmsghdr struct {
+ Len uint32
+ Level int32
+ Type int32
+}
+
+type sockaddrInet struct {
+ Family uint16
+ Port uint16
+ Addr [4]byte /* in_addr */
+ X__pad [8]uint8
+}
+
+type sockaddrInet6 struct {
+ Family uint16
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+const (
+ sizeofIovec = 0x8
+ sizeofMsghdr = 0x1c
+ sizeofMmsghdr = 0x20
+ sizeofCmsghdr = 0xc
+
+ sizeofSockaddrInet = 0x10
+ sizeofSockaddrInet6 = 0x1c
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_linux_arm64.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_linux_arm64.go
new file mode 100644
index 000000000..1502f6c55
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_linux_arm64.go
@@ -0,0 +1,66 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_linux.go
+
+package socket
+
+const (
+ sysAF_UNSPEC = 0x0
+ sysAF_INET = 0x2
+ sysAF_INET6 = 0xa
+
+ sysSOCK_RAW = 0x3
+)
+
+type iovec struct {
+ Base *byte
+ Len uint64
+}
+
+type msghdr struct {
+ Name *byte
+ Namelen uint32
+ Pad_cgo_0 [4]byte
+ Iov *iovec
+ Iovlen uint64
+ Control *byte
+ Controllen uint64
+ Flags int32
+ Pad_cgo_1 [4]byte
+}
+
+type mmsghdr struct {
+ Hdr msghdr
+ Len uint32
+ Pad_cgo_0 [4]byte
+}
+
+type cmsghdr struct {
+ Len uint64
+ Level int32
+ Type int32
+}
+
+type sockaddrInet struct {
+ Family uint16
+ Port uint16
+ Addr [4]byte /* in_addr */
+ X__pad [8]uint8
+}
+
+type sockaddrInet6 struct {
+ Family uint16
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+const (
+ sizeofIovec = 0x10
+ sizeofMsghdr = 0x38
+ sizeofMmsghdr = 0x40
+ sizeofCmsghdr = 0x10
+
+ sizeofSockaddrInet = 0x10
+ sizeofSockaddrInet6 = 0x1c
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_linux_mips.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_linux_mips.go
new file mode 100644
index 000000000..430206930
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_linux_mips.go
@@ -0,0 +1,63 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_linux.go
+
+package socket
+
+const (
+ sysAF_UNSPEC = 0x0
+ sysAF_INET = 0x2
+ sysAF_INET6 = 0xa
+
+ sysSOCK_RAW = 0x3
+)
+
+type iovec struct {
+ Base *byte
+ Len uint32
+}
+
+type msghdr struct {
+ Name *byte
+ Namelen uint32
+ Iov *iovec
+ Iovlen uint32
+ Control *byte
+ Controllen uint32
+ Flags int32
+}
+
+type mmsghdr struct {
+ Hdr msghdr
+ Len uint32
+}
+
+type cmsghdr struct {
+ Len uint32
+ Level int32
+ Type int32
+}
+
+type sockaddrInet struct {
+ Family uint16
+ Port uint16
+ Addr [4]byte /* in_addr */
+ X__pad [8]uint8
+}
+
+type sockaddrInet6 struct {
+ Family uint16
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+const (
+ sizeofIovec = 0x8
+ sizeofMsghdr = 0x1c
+ sizeofMmsghdr = 0x20
+ sizeofCmsghdr = 0xc
+
+ sizeofSockaddrInet = 0x10
+ sizeofSockaddrInet6 = 0x1c
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_linux_mips64.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_linux_mips64.go
new file mode 100644
index 000000000..1502f6c55
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_linux_mips64.go
@@ -0,0 +1,66 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_linux.go
+
+package socket
+
+const (
+ sysAF_UNSPEC = 0x0
+ sysAF_INET = 0x2
+ sysAF_INET6 = 0xa
+
+ sysSOCK_RAW = 0x3
+)
+
+type iovec struct {
+ Base *byte
+ Len uint64
+}
+
+type msghdr struct {
+ Name *byte
+ Namelen uint32
+ Pad_cgo_0 [4]byte
+ Iov *iovec
+ Iovlen uint64
+ Control *byte
+ Controllen uint64
+ Flags int32
+ Pad_cgo_1 [4]byte
+}
+
+type mmsghdr struct {
+ Hdr msghdr
+ Len uint32
+ Pad_cgo_0 [4]byte
+}
+
+type cmsghdr struct {
+ Len uint64
+ Level int32
+ Type int32
+}
+
+type sockaddrInet struct {
+ Family uint16
+ Port uint16
+ Addr [4]byte /* in_addr */
+ X__pad [8]uint8
+}
+
+type sockaddrInet6 struct {
+ Family uint16
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+const (
+ sizeofIovec = 0x10
+ sizeofMsghdr = 0x38
+ sizeofMmsghdr = 0x40
+ sizeofCmsghdr = 0x10
+
+ sizeofSockaddrInet = 0x10
+ sizeofSockaddrInet6 = 0x1c
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_linux_mips64le.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_linux_mips64le.go
new file mode 100644
index 000000000..1502f6c55
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_linux_mips64le.go
@@ -0,0 +1,66 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_linux.go
+
+package socket
+
+const (
+ sysAF_UNSPEC = 0x0
+ sysAF_INET = 0x2
+ sysAF_INET6 = 0xa
+
+ sysSOCK_RAW = 0x3
+)
+
+type iovec struct {
+ Base *byte
+ Len uint64
+}
+
+type msghdr struct {
+ Name *byte
+ Namelen uint32
+ Pad_cgo_0 [4]byte
+ Iov *iovec
+ Iovlen uint64
+ Control *byte
+ Controllen uint64
+ Flags int32
+ Pad_cgo_1 [4]byte
+}
+
+type mmsghdr struct {
+ Hdr msghdr
+ Len uint32
+ Pad_cgo_0 [4]byte
+}
+
+type cmsghdr struct {
+ Len uint64
+ Level int32
+ Type int32
+}
+
+type sockaddrInet struct {
+ Family uint16
+ Port uint16
+ Addr [4]byte /* in_addr */
+ X__pad [8]uint8
+}
+
+type sockaddrInet6 struct {
+ Family uint16
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+const (
+ sizeofIovec = 0x10
+ sizeofMsghdr = 0x38
+ sizeofMmsghdr = 0x40
+ sizeofCmsghdr = 0x10
+
+ sizeofSockaddrInet = 0x10
+ sizeofSockaddrInet6 = 0x1c
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_linux_mipsle.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_linux_mipsle.go
new file mode 100644
index 000000000..430206930
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_linux_mipsle.go
@@ -0,0 +1,63 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_linux.go
+
+package socket
+
+const (
+ sysAF_UNSPEC = 0x0
+ sysAF_INET = 0x2
+ sysAF_INET6 = 0xa
+
+ sysSOCK_RAW = 0x3
+)
+
+type iovec struct {
+ Base *byte
+ Len uint32
+}
+
+type msghdr struct {
+ Name *byte
+ Namelen uint32
+ Iov *iovec
+ Iovlen uint32
+ Control *byte
+ Controllen uint32
+ Flags int32
+}
+
+type mmsghdr struct {
+ Hdr msghdr
+ Len uint32
+}
+
+type cmsghdr struct {
+ Len uint32
+ Level int32
+ Type int32
+}
+
+type sockaddrInet struct {
+ Family uint16
+ Port uint16
+ Addr [4]byte /* in_addr */
+ X__pad [8]uint8
+}
+
+type sockaddrInet6 struct {
+ Family uint16
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+const (
+ sizeofIovec = 0x8
+ sizeofMsghdr = 0x1c
+ sizeofMmsghdr = 0x20
+ sizeofCmsghdr = 0xc
+
+ sizeofSockaddrInet = 0x10
+ sizeofSockaddrInet6 = 0x1c
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_linux_ppc64.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_linux_ppc64.go
new file mode 100644
index 000000000..1502f6c55
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_linux_ppc64.go
@@ -0,0 +1,66 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_linux.go
+
+package socket
+
+const (
+ sysAF_UNSPEC = 0x0
+ sysAF_INET = 0x2
+ sysAF_INET6 = 0xa
+
+ sysSOCK_RAW = 0x3
+)
+
+type iovec struct {
+ Base *byte
+ Len uint64
+}
+
+type msghdr struct {
+ Name *byte
+ Namelen uint32
+ Pad_cgo_0 [4]byte
+ Iov *iovec
+ Iovlen uint64
+ Control *byte
+ Controllen uint64
+ Flags int32
+ Pad_cgo_1 [4]byte
+}
+
+type mmsghdr struct {
+ Hdr msghdr
+ Len uint32
+ Pad_cgo_0 [4]byte
+}
+
+type cmsghdr struct {
+ Len uint64
+ Level int32
+ Type int32
+}
+
+type sockaddrInet struct {
+ Family uint16
+ Port uint16
+ Addr [4]byte /* in_addr */
+ X__pad [8]uint8
+}
+
+type sockaddrInet6 struct {
+ Family uint16
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+const (
+ sizeofIovec = 0x10
+ sizeofMsghdr = 0x38
+ sizeofMmsghdr = 0x40
+ sizeofCmsghdr = 0x10
+
+ sizeofSockaddrInet = 0x10
+ sizeofSockaddrInet6 = 0x1c
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_linux_ppc64le.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_linux_ppc64le.go
new file mode 100644
index 000000000..1502f6c55
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_linux_ppc64le.go
@@ -0,0 +1,66 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_linux.go
+
+package socket
+
+const (
+ sysAF_UNSPEC = 0x0
+ sysAF_INET = 0x2
+ sysAF_INET6 = 0xa
+
+ sysSOCK_RAW = 0x3
+)
+
+type iovec struct {
+ Base *byte
+ Len uint64
+}
+
+type msghdr struct {
+ Name *byte
+ Namelen uint32
+ Pad_cgo_0 [4]byte
+ Iov *iovec
+ Iovlen uint64
+ Control *byte
+ Controllen uint64
+ Flags int32
+ Pad_cgo_1 [4]byte
+}
+
+type mmsghdr struct {
+ Hdr msghdr
+ Len uint32
+ Pad_cgo_0 [4]byte
+}
+
+type cmsghdr struct {
+ Len uint64
+ Level int32
+ Type int32
+}
+
+type sockaddrInet struct {
+ Family uint16
+ Port uint16
+ Addr [4]byte /* in_addr */
+ X__pad [8]uint8
+}
+
+type sockaddrInet6 struct {
+ Family uint16
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+const (
+ sizeofIovec = 0x10
+ sizeofMsghdr = 0x38
+ sizeofMmsghdr = 0x40
+ sizeofCmsghdr = 0x10
+
+ sizeofSockaddrInet = 0x10
+ sizeofSockaddrInet6 = 0x1c
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_linux_s390x.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_linux_s390x.go
new file mode 100644
index 000000000..1502f6c55
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_linux_s390x.go
@@ -0,0 +1,66 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_linux.go
+
+package socket
+
+const (
+ sysAF_UNSPEC = 0x0
+ sysAF_INET = 0x2
+ sysAF_INET6 = 0xa
+
+ sysSOCK_RAW = 0x3
+)
+
+type iovec struct {
+ Base *byte
+ Len uint64
+}
+
+type msghdr struct {
+ Name *byte
+ Namelen uint32
+ Pad_cgo_0 [4]byte
+ Iov *iovec
+ Iovlen uint64
+ Control *byte
+ Controllen uint64
+ Flags int32
+ Pad_cgo_1 [4]byte
+}
+
+type mmsghdr struct {
+ Hdr msghdr
+ Len uint32
+ Pad_cgo_0 [4]byte
+}
+
+type cmsghdr struct {
+ Len uint64
+ Level int32
+ Type int32
+}
+
+type sockaddrInet struct {
+ Family uint16
+ Port uint16
+ Addr [4]byte /* in_addr */
+ X__pad [8]uint8
+}
+
+type sockaddrInet6 struct {
+ Family uint16
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+const (
+ sizeofIovec = 0x10
+ sizeofMsghdr = 0x38
+ sizeofMmsghdr = 0x40
+ sizeofCmsghdr = 0x10
+
+ sizeofSockaddrInet = 0x10
+ sizeofSockaddrInet6 = 0x1c
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_netbsd_386.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_netbsd_386.go
new file mode 100644
index 000000000..db60491fe
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_netbsd_386.go
@@ -0,0 +1,65 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_netbsd.go
+
+package socket
+
+const (
+ sysAF_UNSPEC = 0x0
+ sysAF_INET = 0x2
+ sysAF_INET6 = 0x18
+
+ sysSOCK_RAW = 0x3
+)
+
+type iovec struct {
+ Base *byte
+ Len uint32
+}
+
+type msghdr struct {
+ Name *byte
+ Namelen uint32
+ Iov *iovec
+ Iovlen int32
+ Control *byte
+ Controllen uint32
+ Flags int32
+}
+
+type mmsghdr struct {
+ Hdr msghdr
+ Len uint32
+}
+
+type cmsghdr struct {
+ Len uint32
+ Level int32
+ Type int32
+}
+
+type sockaddrInet struct {
+ Len uint8
+ Family uint8
+ Port uint16
+ Addr [4]byte /* in_addr */
+ Zero [8]int8
+}
+
+type sockaddrInet6 struct {
+ Len uint8
+ Family uint8
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+const (
+ sizeofIovec = 0x8
+ sizeofMsghdr = 0x1c
+ sizeofMmsghdr = 0x20
+ sizeofCmsghdr = 0xc
+
+ sizeofSockaddrInet = 0x10
+ sizeofSockaddrInet6 = 0x1c
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_netbsd_amd64.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_netbsd_amd64.go
new file mode 100644
index 000000000..2a1a79985
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_netbsd_amd64.go
@@ -0,0 +1,68 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_netbsd.go
+
+package socket
+
+const (
+ sysAF_UNSPEC = 0x0
+ sysAF_INET = 0x2
+ sysAF_INET6 = 0x18
+
+ sysSOCK_RAW = 0x3
+)
+
+type iovec struct {
+ Base *byte
+ Len uint64
+}
+
+type msghdr struct {
+ Name *byte
+ Namelen uint32
+ Pad_cgo_0 [4]byte
+ Iov *iovec
+ Iovlen int32
+ Pad_cgo_1 [4]byte
+ Control *byte
+ Controllen uint32
+ Flags int32
+}
+
+type mmsghdr struct {
+ Hdr msghdr
+ Len uint32
+ Pad_cgo_0 [4]byte
+}
+
+type cmsghdr struct {
+ Len uint32
+ Level int32
+ Type int32
+}
+
+type sockaddrInet struct {
+ Len uint8
+ Family uint8
+ Port uint16
+ Addr [4]byte /* in_addr */
+ Zero [8]int8
+}
+
+type sockaddrInet6 struct {
+ Len uint8
+ Family uint8
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+const (
+ sizeofIovec = 0x10
+ sizeofMsghdr = 0x30
+ sizeofMmsghdr = 0x40
+ sizeofCmsghdr = 0xc
+
+ sizeofSockaddrInet = 0x10
+ sizeofSockaddrInet6 = 0x1c
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_netbsd_arm.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_netbsd_arm.go
new file mode 100644
index 000000000..206ea2d11
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_netbsd_arm.go
@@ -0,0 +1,59 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_netbsd.go
+
+package socket
+
+const (
+ sysAF_UNSPEC = 0x0
+ sysAF_INET = 0x2
+ sysAF_INET6 = 0x18
+
+ sysSOCK_RAW = 0x3
+)
+
+type iovec struct {
+ Base *byte
+ Len uint32
+}
+
+type msghdr struct {
+ Name *byte
+ Namelen uint32
+ Iov *iovec
+ Iovlen int32
+ Control *byte
+ Controllen uint32
+ Flags int32
+}
+
+type cmsghdr struct {
+ Len uint32
+ Level int32
+ Type int32
+}
+
+type sockaddrInet struct {
+ Len uint8
+ Family uint8
+ Port uint16
+ Addr [4]byte /* in_addr */
+ Zero [8]int8
+}
+
+type sockaddrInet6 struct {
+ Len uint8
+ Family uint8
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+const (
+ sizeofIovec = 0x8
+ sizeofMsghdr = 0x1c
+ sizeofCmsghdr = 0xc
+
+ sizeofSockaddrInet = 0x10
+ sizeofSockaddrInet6 = 0x1c
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_openbsd_386.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_openbsd_386.go
new file mode 100644
index 000000000..1c836361e
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_openbsd_386.go
@@ -0,0 +1,59 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_openbsd.go
+
+package socket
+
+const (
+ sysAF_UNSPEC = 0x0
+ sysAF_INET = 0x2
+ sysAF_INET6 = 0x18
+
+ sysSOCK_RAW = 0x3
+)
+
+type iovec struct {
+ Base *byte
+ Len uint32
+}
+
+type msghdr struct {
+ Name *byte
+ Namelen uint32
+ Iov *iovec
+ Iovlen uint32
+ Control *byte
+ Controllen uint32
+ Flags int32
+}
+
+type cmsghdr struct {
+ Len uint32
+ Level int32
+ Type int32
+}
+
+type sockaddrInet struct {
+ Len uint8
+ Family uint8
+ Port uint16
+ Addr [4]byte /* in_addr */
+ Zero [8]int8
+}
+
+type sockaddrInet6 struct {
+ Len uint8
+ Family uint8
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+const (
+ sizeofIovec = 0x8
+ sizeofMsghdr = 0x1c
+ sizeofCmsghdr = 0xc
+
+ sizeofSockaddrInet = 0x10
+ sizeofSockaddrInet6 = 0x1c
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_openbsd_amd64.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_openbsd_amd64.go
new file mode 100644
index 000000000..a6c0bf464
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_openbsd_amd64.go
@@ -0,0 +1,61 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_openbsd.go
+
+package socket
+
+const (
+ sysAF_UNSPEC = 0x0
+ sysAF_INET = 0x2
+ sysAF_INET6 = 0x18
+
+ sysSOCK_RAW = 0x3
+)
+
+type iovec struct {
+ Base *byte
+ Len uint64
+}
+
+type msghdr struct {
+ Name *byte
+ Namelen uint32
+ Pad_cgo_0 [4]byte
+ Iov *iovec
+ Iovlen uint32
+ Pad_cgo_1 [4]byte
+ Control *byte
+ Controllen uint32
+ Flags int32
+}
+
+type cmsghdr struct {
+ Len uint32
+ Level int32
+ Type int32
+}
+
+type sockaddrInet struct {
+ Len uint8
+ Family uint8
+ Port uint16
+ Addr [4]byte /* in_addr */
+ Zero [8]int8
+}
+
+type sockaddrInet6 struct {
+ Len uint8
+ Family uint8
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+const (
+ sizeofIovec = 0x10
+ sizeofMsghdr = 0x30
+ sizeofCmsghdr = 0xc
+
+ sizeofSockaddrInet = 0x10
+ sizeofSockaddrInet6 = 0x1c
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_openbsd_arm.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_openbsd_arm.go
new file mode 100644
index 000000000..1c836361e
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_openbsd_arm.go
@@ -0,0 +1,59 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_openbsd.go
+
+package socket
+
+const (
+ sysAF_UNSPEC = 0x0
+ sysAF_INET = 0x2
+ sysAF_INET6 = 0x18
+
+ sysSOCK_RAW = 0x3
+)
+
+type iovec struct {
+ Base *byte
+ Len uint32
+}
+
+type msghdr struct {
+ Name *byte
+ Namelen uint32
+ Iov *iovec
+ Iovlen uint32
+ Control *byte
+ Controllen uint32
+ Flags int32
+}
+
+type cmsghdr struct {
+ Len uint32
+ Level int32
+ Type int32
+}
+
+type sockaddrInet struct {
+ Len uint8
+ Family uint8
+ Port uint16
+ Addr [4]byte /* in_addr */
+ Zero [8]int8
+}
+
+type sockaddrInet6 struct {
+ Len uint8
+ Family uint8
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+const (
+ sizeofIovec = 0x8
+ sizeofMsghdr = 0x1c
+ sizeofCmsghdr = 0xc
+
+ sizeofSockaddrInet = 0x10
+ sizeofSockaddrInet6 = 0x1c
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_solaris_amd64.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_solaris_amd64.go
new file mode 100644
index 000000000..327c63290
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/socket/zsys_solaris_amd64.go
@@ -0,0 +1,60 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_solaris.go
+
+package socket
+
+const (
+ sysAF_UNSPEC = 0x0
+ sysAF_INET = 0x2
+ sysAF_INET6 = 0x1a
+
+ sysSOCK_RAW = 0x4
+)
+
+type iovec struct {
+ Base *int8
+ Len uint64
+}
+
+type msghdr struct {
+ Name *byte
+ Namelen uint32
+ Pad_cgo_0 [4]byte
+ Iov *iovec
+ Iovlen int32
+ Pad_cgo_1 [4]byte
+ Accrights *int8
+ Accrightslen int32
+ Pad_cgo_2 [4]byte
+}
+
+type cmsghdr struct {
+ Len uint32
+ Level int32
+ Type int32
+}
+
+type sockaddrInet struct {
+ Family uint16
+ Port uint16
+ Addr [4]byte /* in_addr */
+ Zero [8]int8
+}
+
+type sockaddrInet6 struct {
+ Family uint16
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+ X__sin6_src_id uint32
+}
+
+const (
+ sizeofIovec = 0x10
+ sizeofMsghdr = 0x30
+ sizeofCmsghdr = 0xc
+
+ sizeofSockaddrInet = 0x10
+ sizeofSockaddrInet6 = 0x20
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/timeseries/timeseries.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/timeseries/timeseries.go
new file mode 100644
index 000000000..685f0e7ea
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/timeseries/timeseries.go
@@ -0,0 +1,525 @@
+// Copyright 2015 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 timeseries implements a time series structure for stats collection.
+package timeseries // import "golang.org/x/net/internal/timeseries"
+
+import (
+ "fmt"
+ "log"
+ "time"
+)
+
+const (
+ timeSeriesNumBuckets = 64
+ minuteHourSeriesNumBuckets = 60
+)
+
+var timeSeriesResolutions = []time.Duration{
+ 1 * time.Second,
+ 10 * time.Second,
+ 1 * time.Minute,
+ 10 * time.Minute,
+ 1 * time.Hour,
+ 6 * time.Hour,
+ 24 * time.Hour, // 1 day
+ 7 * 24 * time.Hour, // 1 week
+ 4 * 7 * 24 * time.Hour, // 4 weeks
+ 16 * 7 * 24 * time.Hour, // 16 weeks
+}
+
+var minuteHourSeriesResolutions = []time.Duration{
+ 1 * time.Second,
+ 1 * time.Minute,
+}
+
+// An Observable is a kind of data that can be aggregated in a time series.
+type Observable interface {
+ Multiply(ratio float64) // Multiplies the data in self by a given ratio
+ Add(other Observable) // Adds the data from a different observation to self
+ Clear() // Clears the observation so it can be reused.
+ CopyFrom(other Observable) // Copies the contents of a given observation to self
+}
+
+// Float attaches the methods of Observable to a float64.
+type Float float64
+
+// NewFloat returns a Float.
+func NewFloat() Observable {
+ f := Float(0)
+ return &f
+}
+
+// String returns the float as a string.
+func (f *Float) String() string { return fmt.Sprintf("%g", f.Value()) }
+
+// Value returns the float's value.
+func (f *Float) Value() float64 { return float64(*f) }
+
+func (f *Float) Multiply(ratio float64) { *f *= Float(ratio) }
+
+func (f *Float) Add(other Observable) {
+ o := other.(*Float)
+ *f += *o
+}
+
+func (f *Float) Clear() { *f = 0 }
+
+func (f *Float) CopyFrom(other Observable) {
+ o := other.(*Float)
+ *f = *o
+}
+
+// A Clock tells the current time.
+type Clock interface {
+ Time() time.Time
+}
+
+type defaultClock int
+
+var defaultClockInstance defaultClock
+
+func (defaultClock) Time() time.Time { return time.Now() }
+
+// Information kept per level. Each level consists of a circular list of
+// observations. The start of the level may be derived from end and the
+// len(buckets) * sizeInMillis.
+type tsLevel struct {
+ oldest int // index to oldest bucketed Observable
+ newest int // index to newest bucketed Observable
+ end time.Time // end timestamp for this level
+ size time.Duration // duration of the bucketed Observable
+ buckets []Observable // collections of observations
+ provider func() Observable // used for creating new Observable
+}
+
+func (l *tsLevel) Clear() {
+ l.oldest = 0
+ l.newest = len(l.buckets) - 1
+ l.end = time.Time{}
+ for i := range l.buckets {
+ if l.buckets[i] != nil {
+ l.buckets[i].Clear()
+ l.buckets[i] = nil
+ }
+ }
+}
+
+func (l *tsLevel) InitLevel(size time.Duration, numBuckets int, f func() Observable) {
+ l.size = size
+ l.provider = f
+ l.buckets = make([]Observable, numBuckets)
+}
+
+// Keeps a sequence of levels. Each level is responsible for storing data at
+// a given resolution. For example, the first level stores data at a one
+// minute resolution while the second level stores data at a one hour
+// resolution.
+
+// Each level is represented by a sequence of buckets. Each bucket spans an
+// interval equal to the resolution of the level. New observations are added
+// to the last bucket.
+type timeSeries struct {
+ provider func() Observable // make more Observable
+ numBuckets int // number of buckets in each level
+ levels []*tsLevel // levels of bucketed Observable
+ lastAdd time.Time // time of last Observable tracked
+ total Observable // convenient aggregation of all Observable
+ clock Clock // Clock for getting current time
+ pending Observable // observations not yet bucketed
+ pendingTime time.Time // what time are we keeping in pending
+ dirty bool // if there are pending observations
+}
+
+// init initializes a level according to the supplied criteria.
+func (ts *timeSeries) init(resolutions []time.Duration, f func() Observable, numBuckets int, clock Clock) {
+ ts.provider = f
+ ts.numBuckets = numBuckets
+ ts.clock = clock
+ ts.levels = make([]*tsLevel, len(resolutions))
+
+ for i := range resolutions {
+ if i > 0 && resolutions[i-1] >= resolutions[i] {
+ log.Print("timeseries: resolutions must be monotonically increasing")
+ break
+ }
+ newLevel := new(tsLevel)
+ newLevel.InitLevel(resolutions[i], ts.numBuckets, ts.provider)
+ ts.levels[i] = newLevel
+ }
+
+ ts.Clear()
+}
+
+// Clear removes all observations from the time series.
+func (ts *timeSeries) Clear() {
+ ts.lastAdd = time.Time{}
+ ts.total = ts.resetObservation(ts.total)
+ ts.pending = ts.resetObservation(ts.pending)
+ ts.pendingTime = time.Time{}
+ ts.dirty = false
+
+ for i := range ts.levels {
+ ts.levels[i].Clear()
+ }
+}
+
+// Add records an observation at the current time.
+func (ts *timeSeries) Add(observation Observable) {
+ ts.AddWithTime(observation, ts.clock.Time())
+}
+
+// AddWithTime records an observation at the specified time.
+func (ts *timeSeries) AddWithTime(observation Observable, t time.Time) {
+
+ smallBucketDuration := ts.levels[0].size
+
+ if t.After(ts.lastAdd) {
+ ts.lastAdd = t
+ }
+
+ if t.After(ts.pendingTime) {
+ ts.advance(t)
+ ts.mergePendingUpdates()
+ ts.pendingTime = ts.levels[0].end
+ ts.pending.CopyFrom(observation)
+ ts.dirty = true
+ } else if t.After(ts.pendingTime.Add(-1 * smallBucketDuration)) {
+ // The observation is close enough to go into the pending bucket.
+ // This compensates for clock skewing and small scheduling delays
+ // by letting the update stay in the fast path.
+ ts.pending.Add(observation)
+ ts.dirty = true
+ } else {
+ ts.mergeValue(observation, t)
+ }
+}
+
+// mergeValue inserts the observation at the specified time in the past into all levels.
+func (ts *timeSeries) mergeValue(observation Observable, t time.Time) {
+ for _, level := range ts.levels {
+ index := (ts.numBuckets - 1) - int(level.end.Sub(t)/level.size)
+ if 0 <= index && index < ts.numBuckets {
+ bucketNumber := (level.oldest + index) % ts.numBuckets
+ if level.buckets[bucketNumber] == nil {
+ level.buckets[bucketNumber] = level.provider()
+ }
+ level.buckets[bucketNumber].Add(observation)
+ }
+ }
+ ts.total.Add(observation)
+}
+
+// mergePendingUpdates applies the pending updates into all levels.
+func (ts *timeSeries) mergePendingUpdates() {
+ if ts.dirty {
+ ts.mergeValue(ts.pending, ts.pendingTime)
+ ts.pending = ts.resetObservation(ts.pending)
+ ts.dirty = false
+ }
+}
+
+// advance cycles the buckets at each level until the latest bucket in
+// each level can hold the time specified.
+func (ts *timeSeries) advance(t time.Time) {
+ if !t.After(ts.levels[0].end) {
+ return
+ }
+ for i := 0; i < len(ts.levels); i++ {
+ level := ts.levels[i]
+ if !level.end.Before(t) {
+ break
+ }
+
+ // If the time is sufficiently far, just clear the level and advance
+ // directly.
+ if !t.Before(level.end.Add(level.size * time.Duration(ts.numBuckets))) {
+ for _, b := range level.buckets {
+ ts.resetObservation(b)
+ }
+ level.end = time.Unix(0, (t.UnixNano()/level.size.Nanoseconds())*level.size.Nanoseconds())
+ }
+
+ for t.After(level.end) {
+ level.end = level.end.Add(level.size)
+ level.newest = level.oldest
+ level.oldest = (level.oldest + 1) % ts.numBuckets
+ ts.resetObservation(level.buckets[level.newest])
+ }
+
+ t = level.end
+ }
+}
+
+// Latest returns the sum of the num latest buckets from the level.
+func (ts *timeSeries) Latest(level, num int) Observable {
+ now := ts.clock.Time()
+ if ts.levels[0].end.Before(now) {
+ ts.advance(now)
+ }
+
+ ts.mergePendingUpdates()
+
+ result := ts.provider()
+ l := ts.levels[level]
+ index := l.newest
+
+ for i := 0; i < num; i++ {
+ if l.buckets[index] != nil {
+ result.Add(l.buckets[index])
+ }
+ if index == 0 {
+ index = ts.numBuckets
+ }
+ index--
+ }
+
+ return result
+}
+
+// LatestBuckets returns a copy of the num latest buckets from level.
+func (ts *timeSeries) LatestBuckets(level, num int) []Observable {
+ if level < 0 || level > len(ts.levels) {
+ log.Print("timeseries: bad level argument: ", level)
+ return nil
+ }
+ if num < 0 || num >= ts.numBuckets {
+ log.Print("timeseries: bad num argument: ", num)
+ return nil
+ }
+
+ results := make([]Observable, num)
+ now := ts.clock.Time()
+ if ts.levels[0].end.Before(now) {
+ ts.advance(now)
+ }
+
+ ts.mergePendingUpdates()
+
+ l := ts.levels[level]
+ index := l.newest
+
+ for i := 0; i < num; i++ {
+ result := ts.provider()
+ results[i] = result
+ if l.buckets[index] != nil {
+ result.CopyFrom(l.buckets[index])
+ }
+
+ if index == 0 {
+ index = ts.numBuckets
+ }
+ index -= 1
+ }
+ return results
+}
+
+// ScaleBy updates observations by scaling by factor.
+func (ts *timeSeries) ScaleBy(factor float64) {
+ for _, l := range ts.levels {
+ for i := 0; i < ts.numBuckets; i++ {
+ l.buckets[i].Multiply(factor)
+ }
+ }
+
+ ts.total.Multiply(factor)
+ ts.pending.Multiply(factor)
+}
+
+// Range returns the sum of observations added over the specified time range.
+// If start or finish times don't fall on bucket boundaries of the same
+// level, then return values are approximate answers.
+func (ts *timeSeries) Range(start, finish time.Time) Observable {
+ return ts.ComputeRange(start, finish, 1)[0]
+}
+
+// Recent returns the sum of observations from the last delta.
+func (ts *timeSeries) Recent(delta time.Duration) Observable {
+ now := ts.clock.Time()
+ return ts.Range(now.Add(-delta), now)
+}
+
+// Total returns the total of all observations.
+func (ts *timeSeries) Total() Observable {
+ ts.mergePendingUpdates()
+ return ts.total
+}
+
+// ComputeRange computes a specified number of values into a slice using
+// the observations recorded over the specified time period. The return
+// values are approximate if the start or finish times don't fall on the
+// bucket boundaries at the same level or if the number of buckets spanning
+// the range is not an integral multiple of num.
+func (ts *timeSeries) ComputeRange(start, finish time.Time, num int) []Observable {
+ if start.After(finish) {
+ log.Printf("timeseries: start > finish, %v>%v", start, finish)
+ return nil
+ }
+
+ if num < 0 {
+ log.Printf("timeseries: num < 0, %v", num)
+ return nil
+ }
+
+ results := make([]Observable, num)
+
+ for _, l := range ts.levels {
+ if !start.Before(l.end.Add(-l.size * time.Duration(ts.numBuckets))) {
+ ts.extract(l, start, finish, num, results)
+ return results
+ }
+ }
+
+ // Failed to find a level that covers the desired range. So just
+ // extract from the last level, even if it doesn't cover the entire
+ // desired range.
+ ts.extract(ts.levels[len(ts.levels)-1], start, finish, num, results)
+
+ return results
+}
+
+// RecentList returns the specified number of values in slice over the most
+// recent time period of the specified range.
+func (ts *timeSeries) RecentList(delta time.Duration, num int) []Observable {
+ if delta < 0 {
+ return nil
+ }
+ now := ts.clock.Time()
+ return ts.ComputeRange(now.Add(-delta), now, num)
+}
+
+// extract returns a slice of specified number of observations from a given
+// level over a given range.
+func (ts *timeSeries) extract(l *tsLevel, start, finish time.Time, num int, results []Observable) {
+ ts.mergePendingUpdates()
+
+ srcInterval := l.size
+ dstInterval := finish.Sub(start) / time.Duration(num)
+ dstStart := start
+ srcStart := l.end.Add(-srcInterval * time.Duration(ts.numBuckets))
+
+ srcIndex := 0
+
+ // Where should scanning start?
+ if dstStart.After(srcStart) {
+ advance := dstStart.Sub(srcStart) / srcInterval
+ srcIndex += int(advance)
+ srcStart = srcStart.Add(advance * srcInterval)
+ }
+
+ // The i'th value is computed as show below.
+ // interval = (finish/start)/num
+ // i'th value = sum of observation in range
+ // [ start + i * interval,
+ // start + (i + 1) * interval )
+ for i := 0; i < num; i++ {
+ results[i] = ts.resetObservation(results[i])
+ dstEnd := dstStart.Add(dstInterval)
+ for srcIndex < ts.numBuckets && srcStart.Before(dstEnd) {
+ srcEnd := srcStart.Add(srcInterval)
+ if srcEnd.After(ts.lastAdd) {
+ srcEnd = ts.lastAdd
+ }
+
+ if !srcEnd.Before(dstStart) {
+ srcValue := l.buckets[(srcIndex+l.oldest)%ts.numBuckets]
+ if !srcStart.Before(dstStart) && !srcEnd.After(dstEnd) {
+ // dst completely contains src.
+ if srcValue != nil {
+ results[i].Add(srcValue)
+ }
+ } else {
+ // dst partially overlaps src.
+ overlapStart := maxTime(srcStart, dstStart)
+ overlapEnd := minTime(srcEnd, dstEnd)
+ base := srcEnd.Sub(srcStart)
+ fraction := overlapEnd.Sub(overlapStart).Seconds() / base.Seconds()
+
+ used := ts.provider()
+ if srcValue != nil {
+ used.CopyFrom(srcValue)
+ }
+ used.Multiply(fraction)
+ results[i].Add(used)
+ }
+
+ if srcEnd.After(dstEnd) {
+ break
+ }
+ }
+ srcIndex++
+ srcStart = srcStart.Add(srcInterval)
+ }
+ dstStart = dstStart.Add(dstInterval)
+ }
+}
+
+// resetObservation clears the content so the struct may be reused.
+func (ts *timeSeries) resetObservation(observation Observable) Observable {
+ if observation == nil {
+ observation = ts.provider()
+ } else {
+ observation.Clear()
+ }
+ return observation
+}
+
+// TimeSeries tracks data at granularities from 1 second to 16 weeks.
+type TimeSeries struct {
+ timeSeries
+}
+
+// NewTimeSeries creates a new TimeSeries using the function provided for creating new Observable.
+func NewTimeSeries(f func() Observable) *TimeSeries {
+ return NewTimeSeriesWithClock(f, defaultClockInstance)
+}
+
+// NewTimeSeriesWithClock creates a new TimeSeries using the function provided for creating new Observable and the clock for
+// assigning timestamps.
+func NewTimeSeriesWithClock(f func() Observable, clock Clock) *TimeSeries {
+ ts := new(TimeSeries)
+ ts.timeSeries.init(timeSeriesResolutions, f, timeSeriesNumBuckets, clock)
+ return ts
+}
+
+// MinuteHourSeries tracks data at granularities of 1 minute and 1 hour.
+type MinuteHourSeries struct {
+ timeSeries
+}
+
+// NewMinuteHourSeries creates a new MinuteHourSeries using the function provided for creating new Observable.
+func NewMinuteHourSeries(f func() Observable) *MinuteHourSeries {
+ return NewMinuteHourSeriesWithClock(f, defaultClockInstance)
+}
+
+// NewMinuteHourSeriesWithClock creates a new MinuteHourSeries using the function provided for creating new Observable and the clock for
+// assigning timestamps.
+func NewMinuteHourSeriesWithClock(f func() Observable, clock Clock) *MinuteHourSeries {
+ ts := new(MinuteHourSeries)
+ ts.timeSeries.init(minuteHourSeriesResolutions, f,
+ minuteHourSeriesNumBuckets, clock)
+ return ts
+}
+
+func (ts *MinuteHourSeries) Minute() Observable {
+ return ts.timeSeries.Latest(0, 60)
+}
+
+func (ts *MinuteHourSeries) Hour() Observable {
+ return ts.timeSeries.Latest(1, 60)
+}
+
+func minTime(a, b time.Time) time.Time {
+ if a.Before(b) {
+ return a
+ }
+ return b
+}
+
+func maxTime(a, b time.Time) time.Time {
+ if a.After(b) {
+ return a
+ }
+ return b
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/timeseries/timeseries_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/timeseries/timeseries_test.go
new file mode 100644
index 000000000..66325a912
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/internal/timeseries/timeseries_test.go
@@ -0,0 +1,170 @@
+// Copyright 2015 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 timeseries
+
+import (
+ "math"
+ "testing"
+ "time"
+)
+
+func isNear(x *Float, y float64, tolerance float64) bool {
+ return math.Abs(x.Value()-y) < tolerance
+}
+
+func isApproximate(x *Float, y float64) bool {
+ return isNear(x, y, 1e-2)
+}
+
+func checkApproximate(t *testing.T, o Observable, y float64) {
+ x := o.(*Float)
+ if !isApproximate(x, y) {
+ t.Errorf("Wanted %g, got %g", y, x.Value())
+ }
+}
+
+func checkNear(t *testing.T, o Observable, y, tolerance float64) {
+ x := o.(*Float)
+ if !isNear(x, y, tolerance) {
+ t.Errorf("Wanted %g +- %g, got %g", y, tolerance, x.Value())
+ }
+}
+
+var baseTime = time.Date(2013, 1, 1, 0, 0, 0, 0, time.UTC)
+
+func tu(s int64) time.Time {
+ return baseTime.Add(time.Duration(s) * time.Second)
+}
+
+func tu2(s int64, ns int64) time.Time {
+ return baseTime.Add(time.Duration(s)*time.Second + time.Duration(ns)*time.Nanosecond)
+}
+
+func TestBasicTimeSeries(t *testing.T) {
+ ts := NewTimeSeries(NewFloat)
+ fo := new(Float)
+ *fo = Float(10)
+ ts.AddWithTime(fo, tu(1))
+ ts.AddWithTime(fo, tu(1))
+ ts.AddWithTime(fo, tu(1))
+ ts.AddWithTime(fo, tu(1))
+ checkApproximate(t, ts.Range(tu(0), tu(1)), 40)
+ checkApproximate(t, ts.Total(), 40)
+ ts.AddWithTime(fo, tu(3))
+ ts.AddWithTime(fo, tu(3))
+ ts.AddWithTime(fo, tu(3))
+ checkApproximate(t, ts.Range(tu(0), tu(2)), 40)
+ checkApproximate(t, ts.Range(tu(2), tu(4)), 30)
+ checkApproximate(t, ts.Total(), 70)
+ ts.AddWithTime(fo, tu(1))
+ ts.AddWithTime(fo, tu(1))
+ checkApproximate(t, ts.Range(tu(0), tu(2)), 60)
+ checkApproximate(t, ts.Range(tu(2), tu(4)), 30)
+ checkApproximate(t, ts.Total(), 90)
+ *fo = Float(100)
+ ts.AddWithTime(fo, tu(100))
+ checkApproximate(t, ts.Range(tu(99), tu(100)), 100)
+ checkApproximate(t, ts.Range(tu(0), tu(4)), 36)
+ checkApproximate(t, ts.Total(), 190)
+ *fo = Float(10)
+ ts.AddWithTime(fo, tu(1))
+ ts.AddWithTime(fo, tu(1))
+ checkApproximate(t, ts.Range(tu(0), tu(4)), 44)
+ checkApproximate(t, ts.Range(tu(37), tu2(100, 100e6)), 100)
+ checkApproximate(t, ts.Range(tu(50), tu2(100, 100e6)), 100)
+ checkApproximate(t, ts.Range(tu(99), tu2(100, 100e6)), 100)
+ checkApproximate(t, ts.Total(), 210)
+
+ for i, l := range ts.ComputeRange(tu(36), tu(100), 64) {
+ if i == 63 {
+ checkApproximate(t, l, 100)
+ } else {
+ checkApproximate(t, l, 0)
+ }
+ }
+
+ checkApproximate(t, ts.Range(tu(0), tu(100)), 210)
+ checkApproximate(t, ts.Range(tu(10), tu(100)), 100)
+
+ for i, l := range ts.ComputeRange(tu(0), tu(100), 100) {
+ if i < 10 {
+ checkApproximate(t, l, 11)
+ } else if i >= 90 {
+ checkApproximate(t, l, 10)
+ } else {
+ checkApproximate(t, l, 0)
+ }
+ }
+}
+
+func TestFloat(t *testing.T) {
+ f := Float(1)
+ if g, w := f.String(), "1"; g != w {
+ t.Errorf("Float(1).String = %q; want %q", g, w)
+ }
+ f2 := Float(2)
+ var o Observable = &f2
+ f.Add(o)
+ if g, w := f.Value(), 3.0; g != w {
+ t.Errorf("Float post-add = %v; want %v", g, w)
+ }
+ f.Multiply(2)
+ if g, w := f.Value(), 6.0; g != w {
+ t.Errorf("Float post-multiply = %v; want %v", g, w)
+ }
+ f.Clear()
+ if g, w := f.Value(), 0.0; g != w {
+ t.Errorf("Float post-clear = %v; want %v", g, w)
+ }
+ f.CopyFrom(&f2)
+ if g, w := f.Value(), 2.0; g != w {
+ t.Errorf("Float post-CopyFrom = %v; want %v", g, w)
+ }
+}
+
+type mockClock struct {
+ time time.Time
+}
+
+func (m *mockClock) Time() time.Time { return m.time }
+func (m *mockClock) Set(t time.Time) { m.time = t }
+
+const buckets = 6
+
+var testResolutions = []time.Duration{
+ 10 * time.Second, // level holds one minute of observations
+ 100 * time.Second, // level holds ten minutes of observations
+ 10 * time.Minute, // level holds one hour of observations
+}
+
+// TestTimeSeries uses a small number of buckets to force a higher
+// error rate on approximations from the timeseries.
+type TestTimeSeries struct {
+ timeSeries
+}
+
+func TestExpectedErrorRate(t *testing.T) {
+ ts := new(TestTimeSeries)
+ fake := new(mockClock)
+ fake.Set(time.Now())
+ ts.timeSeries.init(testResolutions, NewFloat, buckets, fake)
+ for i := 1; i <= 61*61; i++ {
+ fake.Set(fake.Time().Add(1 * time.Second))
+ ob := Float(1)
+ ts.AddWithTime(&ob, fake.Time())
+
+ // The results should be accurate within one missing bucket (1/6) of the observations recorded.
+ checkNear(t, ts.Latest(0, buckets), min(float64(i), 60), 10)
+ checkNear(t, ts.Latest(1, buckets), min(float64(i), 600), 100)
+ checkNear(t, ts.Latest(2, buckets), min(float64(i), 3600), 600)
+ }
+}
+
+func min(a, b float64) float64 {
+ if a < b {
+ return a
+ }
+ return b
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/batch.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/batch.go
new file mode 100644
index 000000000..b44549928
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/batch.go
@@ -0,0 +1,191 @@
+// 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.
+
+// +build go1.9
+
+package ipv4
+
+import (
+ "net"
+ "runtime"
+ "syscall"
+
+ "golang.org/x/net/internal/socket"
+)
+
+// BUG(mikio): On Windows, the ReadBatch and WriteBatch methods of
+// PacketConn are not implemented.
+
+// BUG(mikio): On Windows, the ReadBatch and WriteBatch methods of
+// RawConn are not implemented.
+
+// A Message represents an IO message.
+//
+// type Message struct {
+// Buffers [][]byte
+// OOB []byte
+// Addr net.Addr
+// N int
+// NN int
+// Flags int
+// }
+//
+// The Buffers fields represents a list of contiguous buffers, which
+// can be used for vectored IO, for example, putting a header and a
+// payload in each slice.
+// When writing, the Buffers field must contain at least one byte to
+// write.
+// When reading, the Buffers field will always contain a byte to read.
+//
+// The OOB field contains protocol-specific control or miscellaneous
+// ancillary data known as out-of-band data.
+// It can be nil when not required.
+//
+// The Addr field specifies a destination address when writing.
+// It can be nil when the underlying protocol of the endpoint uses
+// connection-oriented communication.
+// After a successful read, it may contain the source address on the
+// received packet.
+//
+// The N field indicates the number of bytes read or written from/to
+// Buffers.
+//
+// The NN field indicates the number of bytes read or written from/to
+// OOB.
+//
+// The Flags field contains protocol-specific information on the
+// received message.
+type Message = socket.Message
+
+// ReadBatch reads a batch of messages.
+//
+// The provided flags is a set of platform-dependent flags, such as
+// syscall.MSG_PEEK.
+//
+// On a successful read it returns the number of messages received, up
+// to len(ms).
+//
+// On Linux, a batch read will be optimized.
+// On other platforms, this method will read only a single message.
+//
+// Unlike the ReadFrom method, it doesn't strip the IPv4 header
+// followed by option headers from the received IPv4 datagram when the
+// underlying transport is net.IPConn. Each Buffers field of Message
+// must be large enough to accommodate an IPv4 header and option
+// headers.
+func (c *payloadHandler) ReadBatch(ms []Message, flags int) (int, error) {
+ if !c.ok() {
+ return 0, syscall.EINVAL
+ }
+ switch runtime.GOOS {
+ case "linux":
+ n, err := c.RecvMsgs([]socket.Message(ms), flags)
+ if err != nil {
+ err = &net.OpError{Op: "read", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: err}
+ }
+ return n, err
+ default:
+ n := 1
+ err := c.RecvMsg(&ms[0], flags)
+ if err != nil {
+ n = 0
+ err = &net.OpError{Op: "read", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: err}
+ }
+ return n, err
+ }
+}
+
+// WriteBatch writes a batch of messages.
+//
+// The provided flags is a set of platform-dependent flags, such as
+// syscall.MSG_DONTROUTE.
+//
+// It returns the number of messages written on a successful write.
+//
+// On Linux, a batch write will be optimized.
+// On other platforms, this method will write only a single message.
+func (c *payloadHandler) WriteBatch(ms []Message, flags int) (int, error) {
+ if !c.ok() {
+ return 0, syscall.EINVAL
+ }
+ switch runtime.GOOS {
+ case "linux":
+ n, err := c.SendMsgs([]socket.Message(ms), flags)
+ if err != nil {
+ err = &net.OpError{Op: "write", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: err}
+ }
+ return n, err
+ default:
+ n := 1
+ err := c.SendMsg(&ms[0], flags)
+ if err != nil {
+ n = 0
+ err = &net.OpError{Op: "write", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: err}
+ }
+ return n, err
+ }
+}
+
+// ReadBatch reads a batch of messages.
+//
+// The provided flags is a set of platform-dependent flags, such as
+// syscall.MSG_PEEK.
+//
+// On a successful read it returns the number of messages received, up
+// to len(ms).
+//
+// On Linux, a batch read will be optimized.
+// On other platforms, this method will read only a single message.
+func (c *packetHandler) ReadBatch(ms []Message, flags int) (int, error) {
+ if !c.ok() {
+ return 0, syscall.EINVAL
+ }
+ switch runtime.GOOS {
+ case "linux":
+ n, err := c.RecvMsgs([]socket.Message(ms), flags)
+ if err != nil {
+ err = &net.OpError{Op: "read", Net: c.IPConn.LocalAddr().Network(), Source: c.IPConn.LocalAddr(), Err: err}
+ }
+ return n, err
+ default:
+ n := 1
+ err := c.RecvMsg(&ms[0], flags)
+ if err != nil {
+ n = 0
+ err = &net.OpError{Op: "read", Net: c.IPConn.LocalAddr().Network(), Source: c.IPConn.LocalAddr(), Err: err}
+ }
+ return n, err
+ }
+}
+
+// WriteBatch writes a batch of messages.
+//
+// The provided flags is a set of platform-dependent flags, such as
+// syscall.MSG_DONTROUTE.
+//
+// It returns the number of messages written on a successful write.
+//
+// On Linux, a batch write will be optimized.
+// On other platforms, this method will write only a single message.
+func (c *packetHandler) WriteBatch(ms []Message, flags int) (int, error) {
+ if !c.ok() {
+ return 0, syscall.EINVAL
+ }
+ switch runtime.GOOS {
+ case "linux":
+ n, err := c.SendMsgs([]socket.Message(ms), flags)
+ if err != nil {
+ err = &net.OpError{Op: "write", Net: c.IPConn.LocalAddr().Network(), Source: c.IPConn.LocalAddr(), Err: err}
+ }
+ return n, err
+ default:
+ n := 1
+ err := c.SendMsg(&ms[0], flags)
+ if err != nil {
+ n = 0
+ err = &net.OpError{Op: "write", Net: c.IPConn.LocalAddr().Network(), Source: c.IPConn.LocalAddr(), Err: err}
+ }
+ return n, err
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/bpf_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/bpf_test.go
new file mode 100644
index 000000000..b44da9054
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/bpf_test.go
@@ -0,0 +1,93 @@
+// 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.
+
+package ipv4_test
+
+import (
+ "net"
+ "runtime"
+ "testing"
+ "time"
+
+ "golang.org/x/net/bpf"
+ "golang.org/x/net/ipv4"
+)
+
+func TestBPF(t *testing.T) {
+ if runtime.GOOS != "linux" {
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+
+ l, err := net.ListenPacket("udp4", "127.0.0.1:0")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer l.Close()
+
+ p := ipv4.NewPacketConn(l)
+
+ // This filter accepts UDP packets whose first payload byte is
+ // even.
+ prog, err := bpf.Assemble([]bpf.Instruction{
+ // Load the first byte of the payload (skipping UDP header).
+ bpf.LoadAbsolute{Off: 8, Size: 1},
+ // Select LSB of the byte.
+ bpf.ALUOpConstant{Op: bpf.ALUOpAnd, Val: 1},
+ // Byte is even?
+ bpf.JumpIf{Cond: bpf.JumpEqual, Val: 0, SkipFalse: 1},
+ // Accept.
+ bpf.RetConstant{Val: 4096},
+ // Ignore.
+ bpf.RetConstant{Val: 0},
+ })
+ if err != nil {
+ t.Fatalf("compiling BPF: %s", err)
+ }
+
+ if err = p.SetBPF(prog); err != nil {
+ t.Fatalf("attaching filter to Conn: %s", err)
+ }
+
+ s, err := net.Dial("udp4", l.LocalAddr().String())
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer s.Close()
+ go func() {
+ for i := byte(0); i < 10; i++ {
+ s.Write([]byte{i})
+ }
+ }()
+
+ l.SetDeadline(time.Now().Add(2 * time.Second))
+ seen := make([]bool, 5)
+ for {
+ var b [512]byte
+ n, _, err := l.ReadFrom(b[:])
+ if err != nil {
+ t.Fatalf("reading from listener: %s", err)
+ }
+ if n != 1 {
+ t.Fatalf("unexpected packet length, want 1, got %d", n)
+ }
+ if b[0] >= 10 {
+ t.Fatalf("unexpected byte, want 0-9, got %d", b[0])
+ }
+ if b[0]%2 != 0 {
+ t.Fatalf("got odd byte %d, wanted only even bytes", b[0])
+ }
+ seen[b[0]/2] = true
+
+ seenAll := true
+ for _, v := range seen {
+ if !v {
+ seenAll = false
+ break
+ }
+ }
+ if seenAll {
+ break
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/control.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/control.go
new file mode 100644
index 000000000..a2b02ca95
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/control.go
@@ -0,0 +1,144 @@
+// Copyright 2012 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 ipv4
+
+import (
+ "fmt"
+ "net"
+ "sync"
+
+ "golang.org/x/net/internal/iana"
+ "golang.org/x/net/internal/socket"
+)
+
+type rawOpt struct {
+ sync.RWMutex
+ cflags ControlFlags
+}
+
+func (c *rawOpt) set(f ControlFlags) { c.cflags |= f }
+func (c *rawOpt) clear(f ControlFlags) { c.cflags &^= f }
+func (c *rawOpt) isset(f ControlFlags) bool { return c.cflags&f != 0 }
+
+type ControlFlags uint
+
+const (
+ FlagTTL ControlFlags = 1 << iota // pass the TTL on the received packet
+ FlagSrc // pass the source address on the received packet
+ FlagDst // pass the destination address on the received packet
+ FlagInterface // pass the interface index on the received packet
+)
+
+// A ControlMessage represents per packet basis IP-level socket options.
+type ControlMessage struct {
+ // Receiving socket options: SetControlMessage allows to
+ // receive the options from the protocol stack using ReadFrom
+ // method of PacketConn or RawConn.
+ //
+ // Specifying socket options: ControlMessage for WriteTo
+ // method of PacketConn or RawConn allows to send the options
+ // to the protocol stack.
+ //
+ TTL int // time-to-live, receiving only
+ Src net.IP // source address, specifying only
+ Dst net.IP // destination address, receiving only
+ IfIndex int // interface index, must be 1 <= value when specifying
+}
+
+func (cm *ControlMessage) String() string {
+ if cm == nil {
+ return "<nil>"
+ }
+ return fmt.Sprintf("ttl=%d src=%v dst=%v ifindex=%d", cm.TTL, cm.Src, cm.Dst, cm.IfIndex)
+}
+
+// Marshal returns the binary encoding of cm.
+func (cm *ControlMessage) Marshal() []byte {
+ if cm == nil {
+ return nil
+ }
+ var m socket.ControlMessage
+ if ctlOpts[ctlPacketInfo].name > 0 && (cm.Src.To4() != nil || cm.IfIndex > 0) {
+ m = socket.NewControlMessage([]int{ctlOpts[ctlPacketInfo].length})
+ }
+ if len(m) > 0 {
+ ctlOpts[ctlPacketInfo].marshal(m, cm)
+ }
+ return m
+}
+
+// Parse parses b as a control message and stores the result in cm.
+func (cm *ControlMessage) Parse(b []byte) error {
+ ms, err := socket.ControlMessage(b).Parse()
+ if err != nil {
+ return err
+ }
+ for _, m := range ms {
+ lvl, typ, l, err := m.ParseHeader()
+ if err != nil {
+ return err
+ }
+ if lvl != iana.ProtocolIP {
+ continue
+ }
+ switch {
+ case typ == ctlOpts[ctlTTL].name && l >= ctlOpts[ctlTTL].length:
+ ctlOpts[ctlTTL].parse(cm, m.Data(l))
+ case typ == ctlOpts[ctlDst].name && l >= ctlOpts[ctlDst].length:
+ ctlOpts[ctlDst].parse(cm, m.Data(l))
+ case typ == ctlOpts[ctlInterface].name && l >= ctlOpts[ctlInterface].length:
+ ctlOpts[ctlInterface].parse(cm, m.Data(l))
+ case typ == ctlOpts[ctlPacketInfo].name && l >= ctlOpts[ctlPacketInfo].length:
+ ctlOpts[ctlPacketInfo].parse(cm, m.Data(l))
+ }
+ }
+ return nil
+}
+
+// NewControlMessage returns a new control message.
+//
+// The returned message is large enough for options specified by cf.
+func NewControlMessage(cf ControlFlags) []byte {
+ opt := rawOpt{cflags: cf}
+ var l int
+ if opt.isset(FlagTTL) && ctlOpts[ctlTTL].name > 0 {
+ l += socket.ControlMessageSpace(ctlOpts[ctlTTL].length)
+ }
+ if ctlOpts[ctlPacketInfo].name > 0 {
+ if opt.isset(FlagSrc | FlagDst | FlagInterface) {
+ l += socket.ControlMessageSpace(ctlOpts[ctlPacketInfo].length)
+ }
+ } else {
+ if opt.isset(FlagDst) && ctlOpts[ctlDst].name > 0 {
+ l += socket.ControlMessageSpace(ctlOpts[ctlDst].length)
+ }
+ if opt.isset(FlagInterface) && ctlOpts[ctlInterface].name > 0 {
+ l += socket.ControlMessageSpace(ctlOpts[ctlInterface].length)
+ }
+ }
+ var b []byte
+ if l > 0 {
+ b = make([]byte, l)
+ }
+ return b
+}
+
+// Ancillary data socket options
+const (
+ ctlTTL = iota // header field
+ ctlSrc // header field
+ ctlDst // header field
+ ctlInterface // inbound or outbound interface
+ ctlPacketInfo // inbound or outbound packet path
+ ctlMax
+)
+
+// A ctlOpt represents a binding for ancillary data socket option.
+type ctlOpt struct {
+ name int // option name, must be equal or greater than 1
+ length int // option length
+ marshal func([]byte, *ControlMessage) []byte
+ parse func(*ControlMessage, []byte)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/control_bsd.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/control_bsd.go
new file mode 100644
index 000000000..77e7ad5be
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/control_bsd.go
@@ -0,0 +1,40 @@
+// Copyright 2012 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.
+
+// +build darwin dragonfly freebsd netbsd openbsd
+
+package ipv4
+
+import (
+ "net"
+ "syscall"
+ "unsafe"
+
+ "golang.org/x/net/internal/iana"
+ "golang.org/x/net/internal/socket"
+)
+
+func marshalDst(b []byte, cm *ControlMessage) []byte {
+ m := socket.ControlMessage(b)
+ m.MarshalHeader(iana.ProtocolIP, sysIP_RECVDSTADDR, net.IPv4len)
+ return m.Next(net.IPv4len)
+}
+
+func parseDst(cm *ControlMessage, b []byte) {
+ if len(cm.Dst) < net.IPv4len {
+ cm.Dst = make(net.IP, net.IPv4len)
+ }
+ copy(cm.Dst, b[:net.IPv4len])
+}
+
+func marshalInterface(b []byte, cm *ControlMessage) []byte {
+ m := socket.ControlMessage(b)
+ m.MarshalHeader(iana.ProtocolIP, sysIP_RECVIF, syscall.SizeofSockaddrDatalink)
+ return m.Next(syscall.SizeofSockaddrDatalink)
+}
+
+func parseInterface(cm *ControlMessage, b []byte) {
+ sadl := (*syscall.SockaddrDatalink)(unsafe.Pointer(&b[0]))
+ cm.IfIndex = int(sadl.Index)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/control_pktinfo.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/control_pktinfo.go
new file mode 100644
index 000000000..425338f35
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/control_pktinfo.go
@@ -0,0 +1,39 @@
+// Copyright 2014 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.
+
+// +build darwin linux solaris
+
+package ipv4
+
+import (
+ "net"
+ "unsafe"
+
+ "golang.org/x/net/internal/iana"
+ "golang.org/x/net/internal/socket"
+)
+
+func marshalPacketInfo(b []byte, cm *ControlMessage) []byte {
+ m := socket.ControlMessage(b)
+ m.MarshalHeader(iana.ProtocolIP, sysIP_PKTINFO, sizeofInetPktinfo)
+ if cm != nil {
+ pi := (*inetPktinfo)(unsafe.Pointer(&m.Data(sizeofInetPktinfo)[0]))
+ if ip := cm.Src.To4(); ip != nil {
+ copy(pi.Spec_dst[:], ip)
+ }
+ if cm.IfIndex > 0 {
+ pi.setIfindex(cm.IfIndex)
+ }
+ }
+ return m.Next(sizeofInetPktinfo)
+}
+
+func parsePacketInfo(cm *ControlMessage, b []byte) {
+ pi := (*inetPktinfo)(unsafe.Pointer(&b[0]))
+ cm.IfIndex = int(pi.Ifindex)
+ if len(cm.Dst) < net.IPv4len {
+ cm.Dst = make(net.IP, net.IPv4len)
+ }
+ copy(cm.Dst, pi.Addr[:])
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/control_stub.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/control_stub.go
new file mode 100644
index 000000000..5a2f7d8d3
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/control_stub.go
@@ -0,0 +1,13 @@
+// Copyright 2012 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.
+
+// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows
+
+package ipv4
+
+import "golang.org/x/net/internal/socket"
+
+func setControlMessage(c *socket.Conn, opt *rawOpt, cf ControlFlags, on bool) error {
+ return errOpNoSupport
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/control_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/control_test.go
new file mode 100644
index 000000000..f87fe124b
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/control_test.go
@@ -0,0 +1,21 @@
+// 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 ipv4_test
+
+import (
+ "testing"
+
+ "golang.org/x/net/ipv4"
+)
+
+func TestControlMessageParseWithFuzz(t *testing.T) {
+ var cm ipv4.ControlMessage
+ for _, fuzz := range []string{
+ "\f\x00\x00\x00\x00\x00\x00\x00\x14\x00\x00\x00",
+ "\f\x00\x00\x00\x00\x00\x00\x00\x1a\x00\x00\x00",
+ } {
+ cm.Parse([]byte(fuzz))
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/control_unix.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/control_unix.go
new file mode 100644
index 000000000..e1ae8167b
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/control_unix.go
@@ -0,0 +1,73 @@
+// Copyright 2012 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.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+
+package ipv4
+
+import (
+ "unsafe"
+
+ "golang.org/x/net/internal/iana"
+ "golang.org/x/net/internal/socket"
+)
+
+func setControlMessage(c *socket.Conn, opt *rawOpt, cf ControlFlags, on bool) error {
+ opt.Lock()
+ defer opt.Unlock()
+ if so, ok := sockOpts[ssoReceiveTTL]; ok && cf&FlagTTL != 0 {
+ if err := so.SetInt(c, boolint(on)); err != nil {
+ return err
+ }
+ if on {
+ opt.set(FlagTTL)
+ } else {
+ opt.clear(FlagTTL)
+ }
+ }
+ if so, ok := sockOpts[ssoPacketInfo]; ok {
+ if cf&(FlagSrc|FlagDst|FlagInterface) != 0 {
+ if err := so.SetInt(c, boolint(on)); err != nil {
+ return err
+ }
+ if on {
+ opt.set(cf & (FlagSrc | FlagDst | FlagInterface))
+ } else {
+ opt.clear(cf & (FlagSrc | FlagDst | FlagInterface))
+ }
+ }
+ } else {
+ if so, ok := sockOpts[ssoReceiveDst]; ok && cf&FlagDst != 0 {
+ if err := so.SetInt(c, boolint(on)); err != nil {
+ return err
+ }
+ if on {
+ opt.set(FlagDst)
+ } else {
+ opt.clear(FlagDst)
+ }
+ }
+ if so, ok := sockOpts[ssoReceiveInterface]; ok && cf&FlagInterface != 0 {
+ if err := so.SetInt(c, boolint(on)); err != nil {
+ return err
+ }
+ if on {
+ opt.set(FlagInterface)
+ } else {
+ opt.clear(FlagInterface)
+ }
+ }
+ }
+ return nil
+}
+
+func marshalTTL(b []byte, cm *ControlMessage) []byte {
+ m := socket.ControlMessage(b)
+ m.MarshalHeader(iana.ProtocolIP, sysIP_RECVTTL, 1)
+ return m.Next(1)
+}
+
+func parseTTL(cm *ControlMessage, b []byte) {
+ cm.TTL = int(*(*byte)(unsafe.Pointer(&b[:1][0])))
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/control_windows.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/control_windows.go
new file mode 100644
index 000000000..ce55c6644
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/control_windows.go
@@ -0,0 +1,16 @@
+// Copyright 2012 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 ipv4
+
+import (
+ "syscall"
+
+ "golang.org/x/net/internal/socket"
+)
+
+func setControlMessage(c *socket.Conn, opt *rawOpt, cf ControlFlags, on bool) error {
+ // TODO(mikio): implement this
+ return syscall.EWINDOWS
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/defs_darwin.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/defs_darwin.go
new file mode 100644
index 000000000..c8f2e05b8
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/defs_darwin.go
@@ -0,0 +1,77 @@
+// Copyright 2014 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.
+
+// +build ignore
+
+// +godefs map struct_in_addr [4]byte /* in_addr */
+
+package ipv4
+
+/*
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+*/
+import "C"
+
+const (
+ sysIP_OPTIONS = C.IP_OPTIONS
+ sysIP_HDRINCL = C.IP_HDRINCL
+ sysIP_TOS = C.IP_TOS
+ sysIP_TTL = C.IP_TTL
+ sysIP_RECVOPTS = C.IP_RECVOPTS
+ sysIP_RECVRETOPTS = C.IP_RECVRETOPTS
+ sysIP_RECVDSTADDR = C.IP_RECVDSTADDR
+ sysIP_RETOPTS = C.IP_RETOPTS
+ sysIP_RECVIF = C.IP_RECVIF
+ sysIP_STRIPHDR = C.IP_STRIPHDR
+ sysIP_RECVTTL = C.IP_RECVTTL
+ sysIP_BOUND_IF = C.IP_BOUND_IF
+ sysIP_PKTINFO = C.IP_PKTINFO
+ sysIP_RECVPKTINFO = C.IP_RECVPKTINFO
+
+ sysIP_MULTICAST_IF = C.IP_MULTICAST_IF
+ sysIP_MULTICAST_TTL = C.IP_MULTICAST_TTL
+ sysIP_MULTICAST_LOOP = C.IP_MULTICAST_LOOP
+ sysIP_ADD_MEMBERSHIP = C.IP_ADD_MEMBERSHIP
+ sysIP_DROP_MEMBERSHIP = C.IP_DROP_MEMBERSHIP
+ sysIP_MULTICAST_VIF = C.IP_MULTICAST_VIF
+ sysIP_MULTICAST_IFINDEX = C.IP_MULTICAST_IFINDEX
+ sysIP_ADD_SOURCE_MEMBERSHIP = C.IP_ADD_SOURCE_MEMBERSHIP
+ sysIP_DROP_SOURCE_MEMBERSHIP = C.IP_DROP_SOURCE_MEMBERSHIP
+ sysIP_BLOCK_SOURCE = C.IP_BLOCK_SOURCE
+ sysIP_UNBLOCK_SOURCE = C.IP_UNBLOCK_SOURCE
+ sysMCAST_JOIN_GROUP = C.MCAST_JOIN_GROUP
+ sysMCAST_LEAVE_GROUP = C.MCAST_LEAVE_GROUP
+ sysMCAST_JOIN_SOURCE_GROUP = C.MCAST_JOIN_SOURCE_GROUP
+ sysMCAST_LEAVE_SOURCE_GROUP = C.MCAST_LEAVE_SOURCE_GROUP
+ sysMCAST_BLOCK_SOURCE = C.MCAST_BLOCK_SOURCE
+ sysMCAST_UNBLOCK_SOURCE = C.MCAST_UNBLOCK_SOURCE
+
+ sizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage
+ sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
+ sizeofInetPktinfo = C.sizeof_struct_in_pktinfo
+
+ sizeofIPMreq = C.sizeof_struct_ip_mreq
+ sizeofIPMreqn = C.sizeof_struct_ip_mreqn
+ sizeofIPMreqSource = C.sizeof_struct_ip_mreq_source
+ sizeofGroupReq = C.sizeof_struct_group_req
+ sizeofGroupSourceReq = C.sizeof_struct_group_source_req
+)
+
+type sockaddrStorage C.struct_sockaddr_storage
+
+type sockaddrInet C.struct_sockaddr_in
+
+type inetPktinfo C.struct_in_pktinfo
+
+type ipMreq C.struct_ip_mreq
+
+type ipMreqn C.struct_ip_mreqn
+
+type ipMreqSource C.struct_ip_mreq_source
+
+type groupReq C.struct_group_req
+
+type groupSourceReq C.struct_group_source_req
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/defs_dragonfly.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/defs_dragonfly.go
new file mode 100644
index 000000000..f30544ea2
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/defs_dragonfly.go
@@ -0,0 +1,38 @@
+// Copyright 2014 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.
+
+// +build ignore
+
+// +godefs map struct_in_addr [4]byte /* in_addr */
+
+package ipv4
+
+/*
+#include <netinet/in.h>
+*/
+import "C"
+
+const (
+ sysIP_OPTIONS = C.IP_OPTIONS
+ sysIP_HDRINCL = C.IP_HDRINCL
+ sysIP_TOS = C.IP_TOS
+ sysIP_TTL = C.IP_TTL
+ sysIP_RECVOPTS = C.IP_RECVOPTS
+ sysIP_RECVRETOPTS = C.IP_RECVRETOPTS
+ sysIP_RECVDSTADDR = C.IP_RECVDSTADDR
+ sysIP_RETOPTS = C.IP_RETOPTS
+ sysIP_RECVIF = C.IP_RECVIF
+ sysIP_RECVTTL = C.IP_RECVTTL
+
+ sysIP_MULTICAST_IF = C.IP_MULTICAST_IF
+ sysIP_MULTICAST_TTL = C.IP_MULTICAST_TTL
+ sysIP_MULTICAST_LOOP = C.IP_MULTICAST_LOOP
+ sysIP_MULTICAST_VIF = C.IP_MULTICAST_VIF
+ sysIP_ADD_MEMBERSHIP = C.IP_ADD_MEMBERSHIP
+ sysIP_DROP_MEMBERSHIP = C.IP_DROP_MEMBERSHIP
+
+ sizeofIPMreq = C.sizeof_struct_ip_mreq
+)
+
+type ipMreq C.struct_ip_mreq
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/defs_freebsd.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/defs_freebsd.go
new file mode 100644
index 000000000..4dd57d865
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/defs_freebsd.go
@@ -0,0 +1,75 @@
+// Copyright 2014 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.
+
+// +build ignore
+
+// +godefs map struct_in_addr [4]byte /* in_addr */
+
+package ipv4
+
+/*
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+*/
+import "C"
+
+const (
+ sysIP_OPTIONS = C.IP_OPTIONS
+ sysIP_HDRINCL = C.IP_HDRINCL
+ sysIP_TOS = C.IP_TOS
+ sysIP_TTL = C.IP_TTL
+ sysIP_RECVOPTS = C.IP_RECVOPTS
+ sysIP_RECVRETOPTS = C.IP_RECVRETOPTS
+ sysIP_RECVDSTADDR = C.IP_RECVDSTADDR
+ sysIP_SENDSRCADDR = C.IP_SENDSRCADDR
+ sysIP_RETOPTS = C.IP_RETOPTS
+ sysIP_RECVIF = C.IP_RECVIF
+ sysIP_ONESBCAST = C.IP_ONESBCAST
+ sysIP_BINDANY = C.IP_BINDANY
+ sysIP_RECVTTL = C.IP_RECVTTL
+ sysIP_MINTTL = C.IP_MINTTL
+ sysIP_DONTFRAG = C.IP_DONTFRAG
+ sysIP_RECVTOS = C.IP_RECVTOS
+
+ sysIP_MULTICAST_IF = C.IP_MULTICAST_IF
+ sysIP_MULTICAST_TTL = C.IP_MULTICAST_TTL
+ sysIP_MULTICAST_LOOP = C.IP_MULTICAST_LOOP
+ sysIP_ADD_MEMBERSHIP = C.IP_ADD_MEMBERSHIP
+ sysIP_DROP_MEMBERSHIP = C.IP_DROP_MEMBERSHIP
+ sysIP_MULTICAST_VIF = C.IP_MULTICAST_VIF
+ sysIP_ADD_SOURCE_MEMBERSHIP = C.IP_ADD_SOURCE_MEMBERSHIP
+ sysIP_DROP_SOURCE_MEMBERSHIP = C.IP_DROP_SOURCE_MEMBERSHIP
+ sysIP_BLOCK_SOURCE = C.IP_BLOCK_SOURCE
+ sysIP_UNBLOCK_SOURCE = C.IP_UNBLOCK_SOURCE
+ sysMCAST_JOIN_GROUP = C.MCAST_JOIN_GROUP
+ sysMCAST_LEAVE_GROUP = C.MCAST_LEAVE_GROUP
+ sysMCAST_JOIN_SOURCE_GROUP = C.MCAST_JOIN_SOURCE_GROUP
+ sysMCAST_LEAVE_SOURCE_GROUP = C.MCAST_LEAVE_SOURCE_GROUP
+ sysMCAST_BLOCK_SOURCE = C.MCAST_BLOCK_SOURCE
+ sysMCAST_UNBLOCK_SOURCE = C.MCAST_UNBLOCK_SOURCE
+
+ sizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage
+ sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
+
+ sizeofIPMreq = C.sizeof_struct_ip_mreq
+ sizeofIPMreqn = C.sizeof_struct_ip_mreqn
+ sizeofIPMreqSource = C.sizeof_struct_ip_mreq_source
+ sizeofGroupReq = C.sizeof_struct_group_req
+ sizeofGroupSourceReq = C.sizeof_struct_group_source_req
+)
+
+type sockaddrStorage C.struct_sockaddr_storage
+
+type sockaddrInet C.struct_sockaddr_in
+
+type ipMreq C.struct_ip_mreq
+
+type ipMreqn C.struct_ip_mreqn
+
+type ipMreqSource C.struct_ip_mreq_source
+
+type groupReq C.struct_group_req
+
+type groupSourceReq C.struct_group_source_req
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/defs_linux.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/defs_linux.go
new file mode 100644
index 000000000..beb11071a
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/defs_linux.go
@@ -0,0 +1,122 @@
+// Copyright 2014 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.
+
+// +build ignore
+
+// +godefs map struct_in_addr [4]byte /* in_addr */
+
+package ipv4
+
+/*
+#include <time.h>
+
+#include <linux/errqueue.h>
+#include <linux/icmp.h>
+#include <linux/in.h>
+#include <linux/filter.h>
+#include <sys/socket.h>
+*/
+import "C"
+
+const (
+ sysIP_TOS = C.IP_TOS
+ sysIP_TTL = C.IP_TTL
+ sysIP_HDRINCL = C.IP_HDRINCL
+ sysIP_OPTIONS = C.IP_OPTIONS
+ sysIP_ROUTER_ALERT = C.IP_ROUTER_ALERT
+ sysIP_RECVOPTS = C.IP_RECVOPTS
+ sysIP_RETOPTS = C.IP_RETOPTS
+ sysIP_PKTINFO = C.IP_PKTINFO
+ sysIP_PKTOPTIONS = C.IP_PKTOPTIONS
+ sysIP_MTU_DISCOVER = C.IP_MTU_DISCOVER
+ sysIP_RECVERR = C.IP_RECVERR
+ sysIP_RECVTTL = C.IP_RECVTTL
+ sysIP_RECVTOS = C.IP_RECVTOS
+ sysIP_MTU = C.IP_MTU
+ sysIP_FREEBIND = C.IP_FREEBIND
+ sysIP_TRANSPARENT = C.IP_TRANSPARENT
+ sysIP_RECVRETOPTS = C.IP_RECVRETOPTS
+ sysIP_ORIGDSTADDR = C.IP_ORIGDSTADDR
+ sysIP_RECVORIGDSTADDR = C.IP_RECVORIGDSTADDR
+ sysIP_MINTTL = C.IP_MINTTL
+ sysIP_NODEFRAG = C.IP_NODEFRAG
+ sysIP_UNICAST_IF = C.IP_UNICAST_IF
+
+ sysIP_MULTICAST_IF = C.IP_MULTICAST_IF
+ sysIP_MULTICAST_TTL = C.IP_MULTICAST_TTL
+ sysIP_MULTICAST_LOOP = C.IP_MULTICAST_LOOP
+ sysIP_ADD_MEMBERSHIP = C.IP_ADD_MEMBERSHIP
+ sysIP_DROP_MEMBERSHIP = C.IP_DROP_MEMBERSHIP
+ sysIP_UNBLOCK_SOURCE = C.IP_UNBLOCK_SOURCE
+ sysIP_BLOCK_SOURCE = C.IP_BLOCK_SOURCE
+ sysIP_ADD_SOURCE_MEMBERSHIP = C.IP_ADD_SOURCE_MEMBERSHIP
+ sysIP_DROP_SOURCE_MEMBERSHIP = C.IP_DROP_SOURCE_MEMBERSHIP
+ sysIP_MSFILTER = C.IP_MSFILTER
+ sysMCAST_JOIN_GROUP = C.MCAST_JOIN_GROUP
+ sysMCAST_LEAVE_GROUP = C.MCAST_LEAVE_GROUP
+ sysMCAST_JOIN_SOURCE_GROUP = C.MCAST_JOIN_SOURCE_GROUP
+ sysMCAST_LEAVE_SOURCE_GROUP = C.MCAST_LEAVE_SOURCE_GROUP
+ sysMCAST_BLOCK_SOURCE = C.MCAST_BLOCK_SOURCE
+ sysMCAST_UNBLOCK_SOURCE = C.MCAST_UNBLOCK_SOURCE
+ sysMCAST_MSFILTER = C.MCAST_MSFILTER
+ sysIP_MULTICAST_ALL = C.IP_MULTICAST_ALL
+
+ //sysIP_PMTUDISC_DONT = C.IP_PMTUDISC_DONT
+ //sysIP_PMTUDISC_WANT = C.IP_PMTUDISC_WANT
+ //sysIP_PMTUDISC_DO = C.IP_PMTUDISC_DO
+ //sysIP_PMTUDISC_PROBE = C.IP_PMTUDISC_PROBE
+ //sysIP_PMTUDISC_INTERFACE = C.IP_PMTUDISC_INTERFACE
+ //sysIP_PMTUDISC_OMIT = C.IP_PMTUDISC_OMIT
+
+ sysICMP_FILTER = C.ICMP_FILTER
+
+ sysSO_EE_ORIGIN_NONE = C.SO_EE_ORIGIN_NONE
+ sysSO_EE_ORIGIN_LOCAL = C.SO_EE_ORIGIN_LOCAL
+ sysSO_EE_ORIGIN_ICMP = C.SO_EE_ORIGIN_ICMP
+ sysSO_EE_ORIGIN_ICMP6 = C.SO_EE_ORIGIN_ICMP6
+ sysSO_EE_ORIGIN_TXSTATUS = C.SO_EE_ORIGIN_TXSTATUS
+ sysSO_EE_ORIGIN_TIMESTAMPING = C.SO_EE_ORIGIN_TIMESTAMPING
+
+ sysSOL_SOCKET = C.SOL_SOCKET
+ sysSO_ATTACH_FILTER = C.SO_ATTACH_FILTER
+
+ sizeofKernelSockaddrStorage = C.sizeof_struct___kernel_sockaddr_storage
+ sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
+ sizeofInetPktinfo = C.sizeof_struct_in_pktinfo
+ sizeofSockExtendedErr = C.sizeof_struct_sock_extended_err
+
+ sizeofIPMreq = C.sizeof_struct_ip_mreq
+ sizeofIPMreqn = C.sizeof_struct_ip_mreqn
+ sizeofIPMreqSource = C.sizeof_struct_ip_mreq_source
+ sizeofGroupReq = C.sizeof_struct_group_req
+ sizeofGroupSourceReq = C.sizeof_struct_group_source_req
+
+ sizeofICMPFilter = C.sizeof_struct_icmp_filter
+
+ sizeofSockFprog = C.sizeof_struct_sock_fprog
+)
+
+type kernelSockaddrStorage C.struct___kernel_sockaddr_storage
+
+type sockaddrInet C.struct_sockaddr_in
+
+type inetPktinfo C.struct_in_pktinfo
+
+type sockExtendedErr C.struct_sock_extended_err
+
+type ipMreq C.struct_ip_mreq
+
+type ipMreqn C.struct_ip_mreqn
+
+type ipMreqSource C.struct_ip_mreq_source
+
+type groupReq C.struct_group_req
+
+type groupSourceReq C.struct_group_source_req
+
+type icmpFilter C.struct_icmp_filter
+
+type sockFProg C.struct_sock_fprog
+
+type sockFilter C.struct_sock_filter
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/defs_netbsd.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/defs_netbsd.go
new file mode 100644
index 000000000..8f8af1b89
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/defs_netbsd.go
@@ -0,0 +1,37 @@
+// Copyright 2014 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.
+
+// +build ignore
+
+// +godefs map struct_in_addr [4]byte /* in_addr */
+
+package ipv4
+
+/*
+#include <netinet/in.h>
+*/
+import "C"
+
+const (
+ sysIP_OPTIONS = C.IP_OPTIONS
+ sysIP_HDRINCL = C.IP_HDRINCL
+ sysIP_TOS = C.IP_TOS
+ sysIP_TTL = C.IP_TTL
+ sysIP_RECVOPTS = C.IP_RECVOPTS
+ sysIP_RECVRETOPTS = C.IP_RECVRETOPTS
+ sysIP_RECVDSTADDR = C.IP_RECVDSTADDR
+ sysIP_RETOPTS = C.IP_RETOPTS
+ sysIP_RECVIF = C.IP_RECVIF
+ sysIP_RECVTTL = C.IP_RECVTTL
+
+ sysIP_MULTICAST_IF = C.IP_MULTICAST_IF
+ sysIP_MULTICAST_TTL = C.IP_MULTICAST_TTL
+ sysIP_MULTICAST_LOOP = C.IP_MULTICAST_LOOP
+ sysIP_ADD_MEMBERSHIP = C.IP_ADD_MEMBERSHIP
+ sysIP_DROP_MEMBERSHIP = C.IP_DROP_MEMBERSHIP
+
+ sizeofIPMreq = C.sizeof_struct_ip_mreq
+)
+
+type ipMreq C.struct_ip_mreq
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/defs_openbsd.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/defs_openbsd.go
new file mode 100644
index 000000000..8f8af1b89
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/defs_openbsd.go
@@ -0,0 +1,37 @@
+// Copyright 2014 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.
+
+// +build ignore
+
+// +godefs map struct_in_addr [4]byte /* in_addr */
+
+package ipv4
+
+/*
+#include <netinet/in.h>
+*/
+import "C"
+
+const (
+ sysIP_OPTIONS = C.IP_OPTIONS
+ sysIP_HDRINCL = C.IP_HDRINCL
+ sysIP_TOS = C.IP_TOS
+ sysIP_TTL = C.IP_TTL
+ sysIP_RECVOPTS = C.IP_RECVOPTS
+ sysIP_RECVRETOPTS = C.IP_RECVRETOPTS
+ sysIP_RECVDSTADDR = C.IP_RECVDSTADDR
+ sysIP_RETOPTS = C.IP_RETOPTS
+ sysIP_RECVIF = C.IP_RECVIF
+ sysIP_RECVTTL = C.IP_RECVTTL
+
+ sysIP_MULTICAST_IF = C.IP_MULTICAST_IF
+ sysIP_MULTICAST_TTL = C.IP_MULTICAST_TTL
+ sysIP_MULTICAST_LOOP = C.IP_MULTICAST_LOOP
+ sysIP_ADD_MEMBERSHIP = C.IP_ADD_MEMBERSHIP
+ sysIP_DROP_MEMBERSHIP = C.IP_DROP_MEMBERSHIP
+
+ sizeofIPMreq = C.sizeof_struct_ip_mreq
+)
+
+type ipMreq C.struct_ip_mreq
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/defs_solaris.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/defs_solaris.go
new file mode 100644
index 000000000..aeb33e9c8
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/defs_solaris.go
@@ -0,0 +1,84 @@
+// Copyright 2014 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.
+
+// +build ignore
+
+// +godefs map struct_in_addr [4]byte /* in_addr */
+
+package ipv4
+
+/*
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+*/
+import "C"
+
+const (
+ sysIP_OPTIONS = C.IP_OPTIONS
+ sysIP_HDRINCL = C.IP_HDRINCL
+ sysIP_TOS = C.IP_TOS
+ sysIP_TTL = C.IP_TTL
+ sysIP_RECVOPTS = C.IP_RECVOPTS
+ sysIP_RECVRETOPTS = C.IP_RECVRETOPTS
+ sysIP_RECVDSTADDR = C.IP_RECVDSTADDR
+ sysIP_RETOPTS = C.IP_RETOPTS
+ sysIP_RECVIF = C.IP_RECVIF
+ sysIP_RECVSLLA = C.IP_RECVSLLA
+ sysIP_RECVTTL = C.IP_RECVTTL
+
+ sysIP_MULTICAST_IF = C.IP_MULTICAST_IF
+ sysIP_MULTICAST_TTL = C.IP_MULTICAST_TTL
+ sysIP_MULTICAST_LOOP = C.IP_MULTICAST_LOOP
+ sysIP_ADD_MEMBERSHIP = C.IP_ADD_MEMBERSHIP
+ sysIP_DROP_MEMBERSHIP = C.IP_DROP_MEMBERSHIP
+ sysIP_BLOCK_SOURCE = C.IP_BLOCK_SOURCE
+ sysIP_UNBLOCK_SOURCE = C.IP_UNBLOCK_SOURCE
+ sysIP_ADD_SOURCE_MEMBERSHIP = C.IP_ADD_SOURCE_MEMBERSHIP
+ sysIP_DROP_SOURCE_MEMBERSHIP = C.IP_DROP_SOURCE_MEMBERSHIP
+ sysIP_NEXTHOP = C.IP_NEXTHOP
+
+ sysIP_PKTINFO = C.IP_PKTINFO
+ sysIP_RECVPKTINFO = C.IP_RECVPKTINFO
+ sysIP_DONTFRAG = C.IP_DONTFRAG
+
+ sysIP_BOUND_IF = C.IP_BOUND_IF
+ sysIP_UNSPEC_SRC = C.IP_UNSPEC_SRC
+ sysIP_BROADCAST_TTL = C.IP_BROADCAST_TTL
+ sysIP_DHCPINIT_IF = C.IP_DHCPINIT_IF
+
+ sysIP_REUSEADDR = C.IP_REUSEADDR
+ sysIP_DONTROUTE = C.IP_DONTROUTE
+ sysIP_BROADCAST = C.IP_BROADCAST
+
+ sysMCAST_JOIN_GROUP = C.MCAST_JOIN_GROUP
+ sysMCAST_LEAVE_GROUP = C.MCAST_LEAVE_GROUP
+ sysMCAST_BLOCK_SOURCE = C.MCAST_BLOCK_SOURCE
+ sysMCAST_UNBLOCK_SOURCE = C.MCAST_UNBLOCK_SOURCE
+ sysMCAST_JOIN_SOURCE_GROUP = C.MCAST_JOIN_SOURCE_GROUP
+ sysMCAST_LEAVE_SOURCE_GROUP = C.MCAST_LEAVE_SOURCE_GROUP
+
+ sizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage
+ sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
+ sizeofInetPktinfo = C.sizeof_struct_in_pktinfo
+
+ sizeofIPMreq = C.sizeof_struct_ip_mreq
+ sizeofIPMreqSource = C.sizeof_struct_ip_mreq_source
+ sizeofGroupReq = C.sizeof_struct_group_req
+ sizeofGroupSourceReq = C.sizeof_struct_group_source_req
+)
+
+type sockaddrStorage C.struct_sockaddr_storage
+
+type sockaddrInet C.struct_sockaddr_in
+
+type inetPktinfo C.struct_in_pktinfo
+
+type ipMreq C.struct_ip_mreq
+
+type ipMreqSource C.struct_ip_mreq_source
+
+type groupReq C.struct_group_req
+
+type groupSourceReq C.struct_group_source_req
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/dgramopt.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/dgramopt.go
new file mode 100644
index 000000000..54d77d5fe
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/dgramopt.go
@@ -0,0 +1,265 @@
+// Copyright 2012 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 ipv4
+
+import (
+ "net"
+ "syscall"
+
+ "golang.org/x/net/bpf"
+)
+
+// MulticastTTL returns the time-to-live field value for outgoing
+// multicast packets.
+func (c *dgramOpt) MulticastTTL() (int, error) {
+ if !c.ok() {
+ return 0, syscall.EINVAL
+ }
+ so, ok := sockOpts[ssoMulticastTTL]
+ if !ok {
+ return 0, errOpNoSupport
+ }
+ return so.GetInt(c.Conn)
+}
+
+// SetMulticastTTL sets the time-to-live field value for future
+// outgoing multicast packets.
+func (c *dgramOpt) SetMulticastTTL(ttl int) error {
+ if !c.ok() {
+ return syscall.EINVAL
+ }
+ so, ok := sockOpts[ssoMulticastTTL]
+ if !ok {
+ return errOpNoSupport
+ }
+ return so.SetInt(c.Conn, ttl)
+}
+
+// MulticastInterface returns the default interface for multicast
+// packet transmissions.
+func (c *dgramOpt) MulticastInterface() (*net.Interface, error) {
+ if !c.ok() {
+ return nil, syscall.EINVAL
+ }
+ so, ok := sockOpts[ssoMulticastInterface]
+ if !ok {
+ return nil, errOpNoSupport
+ }
+ return so.getMulticastInterface(c.Conn)
+}
+
+// SetMulticastInterface sets the default interface for future
+// multicast packet transmissions.
+func (c *dgramOpt) SetMulticastInterface(ifi *net.Interface) error {
+ if !c.ok() {
+ return syscall.EINVAL
+ }
+ so, ok := sockOpts[ssoMulticastInterface]
+ if !ok {
+ return errOpNoSupport
+ }
+ return so.setMulticastInterface(c.Conn, ifi)
+}
+
+// MulticastLoopback reports whether transmitted multicast packets
+// should be copied and send back to the originator.
+func (c *dgramOpt) MulticastLoopback() (bool, error) {
+ if !c.ok() {
+ return false, syscall.EINVAL
+ }
+ so, ok := sockOpts[ssoMulticastLoopback]
+ if !ok {
+ return false, errOpNoSupport
+ }
+ on, err := so.GetInt(c.Conn)
+ if err != nil {
+ return false, err
+ }
+ return on == 1, nil
+}
+
+// SetMulticastLoopback sets whether transmitted multicast packets
+// should be copied and send back to the originator.
+func (c *dgramOpt) SetMulticastLoopback(on bool) error {
+ if !c.ok() {
+ return syscall.EINVAL
+ }
+ so, ok := sockOpts[ssoMulticastLoopback]
+ if !ok {
+ return errOpNoSupport
+ }
+ return so.SetInt(c.Conn, boolint(on))
+}
+
+// JoinGroup joins the group address group on the interface ifi.
+// By default all sources that can cast data to group are accepted.
+// It's possible to mute and unmute data transmission from a specific
+// source by using ExcludeSourceSpecificGroup and
+// IncludeSourceSpecificGroup.
+// JoinGroup uses the system assigned multicast interface when ifi is
+// nil, although this is not recommended because the assignment
+// depends on platforms and sometimes it might require routing
+// configuration.
+func (c *dgramOpt) JoinGroup(ifi *net.Interface, group net.Addr) error {
+ if !c.ok() {
+ return syscall.EINVAL
+ }
+ so, ok := sockOpts[ssoJoinGroup]
+ if !ok {
+ return errOpNoSupport
+ }
+ grp := netAddrToIP4(group)
+ if grp == nil {
+ return errMissingAddress
+ }
+ return so.setGroup(c.Conn, ifi, grp)
+}
+
+// LeaveGroup leaves the group address group on the interface ifi
+// regardless of whether the group is any-source group or
+// source-specific group.
+func (c *dgramOpt) LeaveGroup(ifi *net.Interface, group net.Addr) error {
+ if !c.ok() {
+ return syscall.EINVAL
+ }
+ so, ok := sockOpts[ssoLeaveGroup]
+ if !ok {
+ return errOpNoSupport
+ }
+ grp := netAddrToIP4(group)
+ if grp == nil {
+ return errMissingAddress
+ }
+ return so.setGroup(c.Conn, ifi, grp)
+}
+
+// JoinSourceSpecificGroup joins the source-specific group comprising
+// group and source on the interface ifi.
+// JoinSourceSpecificGroup uses the system assigned multicast
+// interface when ifi is nil, although this is not recommended because
+// the assignment depends on platforms and sometimes it might require
+// routing configuration.
+func (c *dgramOpt) JoinSourceSpecificGroup(ifi *net.Interface, group, source net.Addr) error {
+ if !c.ok() {
+ return syscall.EINVAL
+ }
+ so, ok := sockOpts[ssoJoinSourceGroup]
+ if !ok {
+ return errOpNoSupport
+ }
+ grp := netAddrToIP4(group)
+ if grp == nil {
+ return errMissingAddress
+ }
+ src := netAddrToIP4(source)
+ if src == nil {
+ return errMissingAddress
+ }
+ return so.setSourceGroup(c.Conn, ifi, grp, src)
+}
+
+// LeaveSourceSpecificGroup leaves the source-specific group on the
+// interface ifi.
+func (c *dgramOpt) LeaveSourceSpecificGroup(ifi *net.Interface, group, source net.Addr) error {
+ if !c.ok() {
+ return syscall.EINVAL
+ }
+ so, ok := sockOpts[ssoLeaveSourceGroup]
+ if !ok {
+ return errOpNoSupport
+ }
+ grp := netAddrToIP4(group)
+ if grp == nil {
+ return errMissingAddress
+ }
+ src := netAddrToIP4(source)
+ if src == nil {
+ return errMissingAddress
+ }
+ return so.setSourceGroup(c.Conn, ifi, grp, src)
+}
+
+// ExcludeSourceSpecificGroup excludes the source-specific group from
+// the already joined any-source groups by JoinGroup on the interface
+// ifi.
+func (c *dgramOpt) ExcludeSourceSpecificGroup(ifi *net.Interface, group, source net.Addr) error {
+ if !c.ok() {
+ return syscall.EINVAL
+ }
+ so, ok := sockOpts[ssoBlockSourceGroup]
+ if !ok {
+ return errOpNoSupport
+ }
+ grp := netAddrToIP4(group)
+ if grp == nil {
+ return errMissingAddress
+ }
+ src := netAddrToIP4(source)
+ if src == nil {
+ return errMissingAddress
+ }
+ return so.setSourceGroup(c.Conn, ifi, grp, src)
+}
+
+// IncludeSourceSpecificGroup includes the excluded source-specific
+// group by ExcludeSourceSpecificGroup again on the interface ifi.
+func (c *dgramOpt) IncludeSourceSpecificGroup(ifi *net.Interface, group, source net.Addr) error {
+ if !c.ok() {
+ return syscall.EINVAL
+ }
+ so, ok := sockOpts[ssoUnblockSourceGroup]
+ if !ok {
+ return errOpNoSupport
+ }
+ grp := netAddrToIP4(group)
+ if grp == nil {
+ return errMissingAddress
+ }
+ src := netAddrToIP4(source)
+ if src == nil {
+ return errMissingAddress
+ }
+ return so.setSourceGroup(c.Conn, ifi, grp, src)
+}
+
+// ICMPFilter returns an ICMP filter.
+// Currently only Linux supports this.
+func (c *dgramOpt) ICMPFilter() (*ICMPFilter, error) {
+ if !c.ok() {
+ return nil, syscall.EINVAL
+ }
+ so, ok := sockOpts[ssoICMPFilter]
+ if !ok {
+ return nil, errOpNoSupport
+ }
+ return so.getICMPFilter(c.Conn)
+}
+
+// SetICMPFilter deploys the ICMP filter.
+// Currently only Linux supports this.
+func (c *dgramOpt) SetICMPFilter(f *ICMPFilter) error {
+ if !c.ok() {
+ return syscall.EINVAL
+ }
+ so, ok := sockOpts[ssoICMPFilter]
+ if !ok {
+ return errOpNoSupport
+ }
+ return so.setICMPFilter(c.Conn, f)
+}
+
+// SetBPF attaches a BPF program to the connection.
+//
+// Only supported on Linux.
+func (c *dgramOpt) SetBPF(filter []bpf.RawInstruction) error {
+ if !c.ok() {
+ return syscall.EINVAL
+ }
+ so, ok := sockOpts[ssoAttachFilter]
+ if !ok {
+ return errOpNoSupport
+ }
+ return so.setBPF(c.Conn, filter)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/doc.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/doc.go
new file mode 100644
index 000000000..b43935a5a
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/doc.go
@@ -0,0 +1,244 @@
+// Copyright 2012 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 ipv4 implements IP-level socket options for the Internet
+// Protocol version 4.
+//
+// The package provides IP-level socket options that allow
+// manipulation of IPv4 facilities.
+//
+// The IPv4 protocol and basic host requirements for IPv4 are defined
+// in RFC 791 and RFC 1122.
+// Host extensions for multicasting and socket interface extensions
+// for multicast source filters are defined in RFC 1112 and RFC 3678.
+// IGMPv1, IGMPv2 and IGMPv3 are defined in RFC 1112, RFC 2236 and RFC
+// 3376.
+// Source-specific multicast is defined in RFC 4607.
+//
+//
+// Unicasting
+//
+// The options for unicasting are available for net.TCPConn,
+// net.UDPConn and net.IPConn which are created as network connections
+// that use the IPv4 transport. When a single TCP connection carrying
+// a data flow of multiple packets needs to indicate the flow is
+// important, Conn is used to set the type-of-service field on the
+// IPv4 header for each packet.
+//
+// ln, err := net.Listen("tcp4", "0.0.0.0:1024")
+// if err != nil {
+// // error handling
+// }
+// defer ln.Close()
+// for {
+// c, err := ln.Accept()
+// if err != nil {
+// // error handling
+// }
+// go func(c net.Conn) {
+// defer c.Close()
+//
+// The outgoing packets will be labeled DiffServ assured forwarding
+// class 1 low drop precedence, known as AF11 packets.
+//
+// if err := ipv4.NewConn(c).SetTOS(0x28); err != nil {
+// // error handling
+// }
+// if _, err := c.Write(data); err != nil {
+// // error handling
+// }
+// }(c)
+// }
+//
+//
+// Multicasting
+//
+// The options for multicasting are available for net.UDPConn and
+// net.IPconn which are created as network connections that use the
+// IPv4 transport. A few network facilities must be prepared before
+// you begin multicasting, at a minimum joining network interfaces and
+// multicast groups.
+//
+// en0, err := net.InterfaceByName("en0")
+// if err != nil {
+// // error handling
+// }
+// en1, err := net.InterfaceByIndex(911)
+// if err != nil {
+// // error handling
+// }
+// group := net.IPv4(224, 0, 0, 250)
+//
+// First, an application listens to an appropriate address with an
+// appropriate service port.
+//
+// c, err := net.ListenPacket("udp4", "0.0.0.0:1024")
+// if err != nil {
+// // error handling
+// }
+// defer c.Close()
+//
+// Second, the application joins multicast groups, starts listening to
+// the groups on the specified network interfaces. Note that the
+// service port for transport layer protocol does not matter with this
+// operation as joining groups affects only network and link layer
+// protocols, such as IPv4 and Ethernet.
+//
+// p := ipv4.NewPacketConn(c)
+// if err := p.JoinGroup(en0, &net.UDPAddr{IP: group}); err != nil {
+// // error handling
+// }
+// if err := p.JoinGroup(en1, &net.UDPAddr{IP: group}); err != nil {
+// // error handling
+// }
+//
+// The application might set per packet control message transmissions
+// between the protocol stack within the kernel. When the application
+// needs a destination address on an incoming packet,
+// SetControlMessage of PacketConn is used to enable control message
+// transmissions.
+//
+// if err := p.SetControlMessage(ipv4.FlagDst, true); err != nil {
+// // error handling
+// }
+//
+// The application could identify whether the received packets are
+// of interest by using the control message that contains the
+// destination address of the received packet.
+//
+// b := make([]byte, 1500)
+// for {
+// n, cm, src, err := p.ReadFrom(b)
+// if err != nil {
+// // error handling
+// }
+// if cm.Dst.IsMulticast() {
+// if cm.Dst.Equal(group) {
+// // joined group, do something
+// } else {
+// // unknown group, discard
+// continue
+// }
+// }
+//
+// The application can also send both unicast and multicast packets.
+//
+// p.SetTOS(0x0)
+// p.SetTTL(16)
+// if _, err := p.WriteTo(data, nil, src); err != nil {
+// // error handling
+// }
+// dst := &net.UDPAddr{IP: group, Port: 1024}
+// for _, ifi := range []*net.Interface{en0, en1} {
+// if err := p.SetMulticastInterface(ifi); err != nil {
+// // error handling
+// }
+// p.SetMulticastTTL(2)
+// if _, err := p.WriteTo(data, nil, dst); err != nil {
+// // error handling
+// }
+// }
+// }
+//
+//
+// More multicasting
+//
+// An application that uses PacketConn or RawConn may join multiple
+// multicast groups. For example, a UDP listener with port 1024 might
+// join two different groups across over two different network
+// interfaces by using:
+//
+// c, err := net.ListenPacket("udp4", "0.0.0.0:1024")
+// if err != nil {
+// // error handling
+// }
+// defer c.Close()
+// p := ipv4.NewPacketConn(c)
+// if err := p.JoinGroup(en0, &net.UDPAddr{IP: net.IPv4(224, 0, 0, 248)}); err != nil {
+// // error handling
+// }
+// if err := p.JoinGroup(en0, &net.UDPAddr{IP: net.IPv4(224, 0, 0, 249)}); err != nil {
+// // error handling
+// }
+// if err := p.JoinGroup(en1, &net.UDPAddr{IP: net.IPv4(224, 0, 0, 249)}); err != nil {
+// // error handling
+// }
+//
+// It is possible for multiple UDP listeners that listen on the same
+// UDP port to join the same multicast group. The net package will
+// provide a socket that listens to a wildcard address with reusable
+// UDP port when an appropriate multicast address prefix is passed to
+// the net.ListenPacket or net.ListenUDP.
+//
+// c1, err := net.ListenPacket("udp4", "224.0.0.0:1024")
+// if err != nil {
+// // error handling
+// }
+// defer c1.Close()
+// c2, err := net.ListenPacket("udp4", "224.0.0.0:1024")
+// if err != nil {
+// // error handling
+// }
+// defer c2.Close()
+// p1 := ipv4.NewPacketConn(c1)
+// if err := p1.JoinGroup(en0, &net.UDPAddr{IP: net.IPv4(224, 0, 0, 248)}); err != nil {
+// // error handling
+// }
+// p2 := ipv4.NewPacketConn(c2)
+// if err := p2.JoinGroup(en0, &net.UDPAddr{IP: net.IPv4(224, 0, 0, 248)}); err != nil {
+// // error handling
+// }
+//
+// Also it is possible for the application to leave or rejoin a
+// multicast group on the network interface.
+//
+// if err := p.LeaveGroup(en0, &net.UDPAddr{IP: net.IPv4(224, 0, 0, 248)}); err != nil {
+// // error handling
+// }
+// if err := p.JoinGroup(en0, &net.UDPAddr{IP: net.IPv4(224, 0, 0, 250)}); err != nil {
+// // error handling
+// }
+//
+//
+// Source-specific multicasting
+//
+// An application that uses PacketConn or RawConn on IGMPv3 supported
+// platform is able to join source-specific multicast groups.
+// The application may use JoinSourceSpecificGroup and
+// LeaveSourceSpecificGroup for the operation known as "include" mode,
+//
+// ssmgroup := net.UDPAddr{IP: net.IPv4(232, 7, 8, 9)}
+// ssmsource := net.UDPAddr{IP: net.IPv4(192, 168, 0, 1)})
+// if err := p.JoinSourceSpecificGroup(en0, &ssmgroup, &ssmsource); err != nil {
+// // error handling
+// }
+// if err := p.LeaveSourceSpecificGroup(en0, &ssmgroup, &ssmsource); err != nil {
+// // error handling
+// }
+//
+// or JoinGroup, ExcludeSourceSpecificGroup,
+// IncludeSourceSpecificGroup and LeaveGroup for the operation known
+// as "exclude" mode.
+//
+// exclsource := net.UDPAddr{IP: net.IPv4(192, 168, 0, 254)}
+// if err := p.JoinGroup(en0, &ssmgroup); err != nil {
+// // error handling
+// }
+// if err := p.ExcludeSourceSpecificGroup(en0, &ssmgroup, &exclsource); err != nil {
+// // error handling
+// }
+// if err := p.LeaveGroup(en0, &ssmgroup); err != nil {
+// // error handling
+// }
+//
+// Note that it depends on each platform implementation what happens
+// when an application which runs on IGMPv3 unsupported platform uses
+// JoinSourceSpecificGroup and LeaveSourceSpecificGroup.
+// In general the platform tries to fall back to conversations using
+// IGMPv1 or IGMPv2 and starts to listen to multicast traffic.
+// In the fallback case, ExcludeSourceSpecificGroup and
+// IncludeSourceSpecificGroup may return an error.
+package ipv4 // import "golang.org/x/net/ipv4"
+
+// BUG(mikio): This package is not implemented on NaCl and Plan 9.
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/endpoint.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/endpoint.go
new file mode 100644
index 000000000..2ab877363
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/endpoint.go
@@ -0,0 +1,187 @@
+// Copyright 2012 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 ipv4
+
+import (
+ "net"
+ "syscall"
+ "time"
+
+ "golang.org/x/net/internal/socket"
+)
+
+// BUG(mikio): On Windows, the JoinSourceSpecificGroup,
+// LeaveSourceSpecificGroup, ExcludeSourceSpecificGroup and
+// IncludeSourceSpecificGroup methods of PacketConn and RawConn are
+// not implemented.
+
+// A Conn represents a network endpoint that uses the IPv4 transport.
+// It is used to control basic IP-level socket options such as TOS and
+// TTL.
+type Conn struct {
+ genericOpt
+}
+
+type genericOpt struct {
+ *socket.Conn
+}
+
+func (c *genericOpt) ok() bool { return c != nil && c.Conn != nil }
+
+// NewConn returns a new Conn.
+func NewConn(c net.Conn) *Conn {
+ cc, _ := socket.NewConn(c)
+ return &Conn{
+ genericOpt: genericOpt{Conn: cc},
+ }
+}
+
+// A PacketConn represents a packet network endpoint that uses the
+// IPv4 transport. It is used to control several IP-level socket
+// options including multicasting. It also provides datagram based
+// network I/O methods specific to the IPv4 and higher layer protocols
+// such as UDP.
+type PacketConn struct {
+ genericOpt
+ dgramOpt
+ payloadHandler
+}
+
+type dgramOpt struct {
+ *socket.Conn
+}
+
+func (c *dgramOpt) ok() bool { return c != nil && c.Conn != nil }
+
+// SetControlMessage sets the per packet IP-level socket options.
+func (c *PacketConn) SetControlMessage(cf ControlFlags, on bool) error {
+ if !c.payloadHandler.ok() {
+ return syscall.EINVAL
+ }
+ return setControlMessage(c.dgramOpt.Conn, &c.payloadHandler.rawOpt, cf, on)
+}
+
+// SetDeadline sets the read and write deadlines associated with the
+// endpoint.
+func (c *PacketConn) SetDeadline(t time.Time) error {
+ if !c.payloadHandler.ok() {
+ return syscall.EINVAL
+ }
+ return c.payloadHandler.PacketConn.SetDeadline(t)
+}
+
+// SetReadDeadline sets the read deadline associated with the
+// endpoint.
+func (c *PacketConn) SetReadDeadline(t time.Time) error {
+ if !c.payloadHandler.ok() {
+ return syscall.EINVAL
+ }
+ return c.payloadHandler.PacketConn.SetReadDeadline(t)
+}
+
+// SetWriteDeadline sets the write deadline associated with the
+// endpoint.
+func (c *PacketConn) SetWriteDeadline(t time.Time) error {
+ if !c.payloadHandler.ok() {
+ return syscall.EINVAL
+ }
+ return c.payloadHandler.PacketConn.SetWriteDeadline(t)
+}
+
+// Close closes the endpoint.
+func (c *PacketConn) Close() error {
+ if !c.payloadHandler.ok() {
+ return syscall.EINVAL
+ }
+ return c.payloadHandler.PacketConn.Close()
+}
+
+// NewPacketConn returns a new PacketConn using c as its underlying
+// transport.
+func NewPacketConn(c net.PacketConn) *PacketConn {
+ cc, _ := socket.NewConn(c.(net.Conn))
+ p := &PacketConn{
+ genericOpt: genericOpt{Conn: cc},
+ dgramOpt: dgramOpt{Conn: cc},
+ payloadHandler: payloadHandler{PacketConn: c, Conn: cc},
+ }
+ return p
+}
+
+// A RawConn represents a packet network endpoint that uses the IPv4
+// transport. It is used to control several IP-level socket options
+// including IPv4 header manipulation. It also provides datagram
+// based network I/O methods specific to the IPv4 and higher layer
+// protocols that handle IPv4 datagram directly such as OSPF, GRE.
+type RawConn struct {
+ genericOpt
+ dgramOpt
+ packetHandler
+}
+
+// SetControlMessage sets the per packet IP-level socket options.
+func (c *RawConn) SetControlMessage(cf ControlFlags, on bool) error {
+ if !c.packetHandler.ok() {
+ return syscall.EINVAL
+ }
+ return setControlMessage(c.dgramOpt.Conn, &c.packetHandler.rawOpt, cf, on)
+}
+
+// SetDeadline sets the read and write deadlines associated with the
+// endpoint.
+func (c *RawConn) SetDeadline(t time.Time) error {
+ if !c.packetHandler.ok() {
+ return syscall.EINVAL
+ }
+ return c.packetHandler.IPConn.SetDeadline(t)
+}
+
+// SetReadDeadline sets the read deadline associated with the
+// endpoint.
+func (c *RawConn) SetReadDeadline(t time.Time) error {
+ if !c.packetHandler.ok() {
+ return syscall.EINVAL
+ }
+ return c.packetHandler.IPConn.SetReadDeadline(t)
+}
+
+// SetWriteDeadline sets the write deadline associated with the
+// endpoint.
+func (c *RawConn) SetWriteDeadline(t time.Time) error {
+ if !c.packetHandler.ok() {
+ return syscall.EINVAL
+ }
+ return c.packetHandler.IPConn.SetWriteDeadline(t)
+}
+
+// Close closes the endpoint.
+func (c *RawConn) Close() error {
+ if !c.packetHandler.ok() {
+ return syscall.EINVAL
+ }
+ return c.packetHandler.IPConn.Close()
+}
+
+// NewRawConn returns a new RawConn using c as its underlying
+// transport.
+func NewRawConn(c net.PacketConn) (*RawConn, error) {
+ cc, err := socket.NewConn(c.(net.Conn))
+ if err != nil {
+ return nil, err
+ }
+ r := &RawConn{
+ genericOpt: genericOpt{Conn: cc},
+ dgramOpt: dgramOpt{Conn: cc},
+ packetHandler: packetHandler{IPConn: c.(*net.IPConn), Conn: cc},
+ }
+ so, ok := sockOpts[ssoHeaderPrepend]
+ if !ok {
+ return nil, errOpNoSupport
+ }
+ if err := so.SetInt(r.dgramOpt.Conn, boolint(true)); err != nil {
+ return nil, err
+ }
+ return r, nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/example_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/example_test.go
new file mode 100644
index 000000000..ddc7577e8
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/example_test.go
@@ -0,0 +1,224 @@
+// Copyright 2012 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 ipv4_test
+
+import (
+ "fmt"
+ "log"
+ "net"
+ "os"
+ "runtime"
+ "time"
+
+ "golang.org/x/net/icmp"
+ "golang.org/x/net/ipv4"
+)
+
+func ExampleConn_markingTCP() {
+ ln, err := net.Listen("tcp", "0.0.0.0:1024")
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer ln.Close()
+
+ for {
+ c, err := ln.Accept()
+ if err != nil {
+ log.Fatal(err)
+ }
+ go func(c net.Conn) {
+ defer c.Close()
+ if c.RemoteAddr().(*net.TCPAddr).IP.To4() != nil {
+ p := ipv4.NewConn(c)
+ if err := p.SetTOS(0x28); err != nil { // DSCP AF11
+ log.Fatal(err)
+ }
+ if err := p.SetTTL(128); err != nil {
+ log.Fatal(err)
+ }
+ }
+ if _, err := c.Write([]byte("HELLO-R-U-THERE-ACK")); err != nil {
+ log.Fatal(err)
+ }
+ }(c)
+ }
+}
+
+func ExamplePacketConn_servingOneShotMulticastDNS() {
+ c, err := net.ListenPacket("udp4", "0.0.0.0:5353") // mDNS over UDP
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer c.Close()
+ p := ipv4.NewPacketConn(c)
+
+ en0, err := net.InterfaceByName("en0")
+ if err != nil {
+ log.Fatal(err)
+ }
+ mDNSLinkLocal := net.UDPAddr{IP: net.IPv4(224, 0, 0, 251)}
+ if err := p.JoinGroup(en0, &mDNSLinkLocal); err != nil {
+ log.Fatal(err)
+ }
+ defer p.LeaveGroup(en0, &mDNSLinkLocal)
+ if err := p.SetControlMessage(ipv4.FlagDst, true); err != nil {
+ log.Fatal(err)
+ }
+
+ b := make([]byte, 1500)
+ for {
+ _, cm, peer, err := p.ReadFrom(b)
+ if err != nil {
+ log.Fatal(err)
+ }
+ if !cm.Dst.IsMulticast() || !cm.Dst.Equal(mDNSLinkLocal.IP) {
+ continue
+ }
+ answers := []byte("FAKE-MDNS-ANSWERS") // fake mDNS answers, you need to implement this
+ if _, err := p.WriteTo(answers, nil, peer); err != nil {
+ log.Fatal(err)
+ }
+ }
+}
+
+func ExamplePacketConn_tracingIPPacketRoute() {
+ // Tracing an IP packet route to www.google.com.
+
+ const host = "www.google.com"
+ ips, err := net.LookupIP(host)
+ if err != nil {
+ log.Fatal(err)
+ }
+ var dst net.IPAddr
+ for _, ip := range ips {
+ if ip.To4() != nil {
+ dst.IP = ip
+ fmt.Printf("using %v for tracing an IP packet route to %s\n", dst.IP, host)
+ break
+ }
+ }
+ if dst.IP == nil {
+ log.Fatal("no A record found")
+ }
+
+ c, err := net.ListenPacket("ip4:1", "0.0.0.0") // ICMP for IPv4
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer c.Close()
+ p := ipv4.NewPacketConn(c)
+
+ if err := p.SetControlMessage(ipv4.FlagTTL|ipv4.FlagSrc|ipv4.FlagDst|ipv4.FlagInterface, true); err != nil {
+ log.Fatal(err)
+ }
+ wm := icmp.Message{
+ Type: ipv4.ICMPTypeEcho, Code: 0,
+ Body: &icmp.Echo{
+ ID: os.Getpid() & 0xffff,
+ Data: []byte("HELLO-R-U-THERE"),
+ },
+ }
+
+ rb := make([]byte, 1500)
+ for i := 1; i <= 64; i++ { // up to 64 hops
+ wm.Body.(*icmp.Echo).Seq = i
+ wb, err := wm.Marshal(nil)
+ if err != nil {
+ log.Fatal(err)
+ }
+ if err := p.SetTTL(i); err != nil {
+ log.Fatal(err)
+ }
+
+ // In the real world usually there are several
+ // multiple traffic-engineered paths for each hop.
+ // You may need to probe a few times to each hop.
+ begin := time.Now()
+ if _, err := p.WriteTo(wb, nil, &dst); err != nil {
+ log.Fatal(err)
+ }
+ if err := p.SetReadDeadline(time.Now().Add(3 * time.Second)); err != nil {
+ log.Fatal(err)
+ }
+ n, cm, peer, err := p.ReadFrom(rb)
+ if err != nil {
+ if err, ok := err.(net.Error); ok && err.Timeout() {
+ fmt.Printf("%v\t*\n", i)
+ continue
+ }
+ log.Fatal(err)
+ }
+ rm, err := icmp.ParseMessage(1, rb[:n])
+ if err != nil {
+ log.Fatal(err)
+ }
+ rtt := time.Since(begin)
+
+ // In the real world you need to determine whether the
+ // received message is yours using ControlMessage.Src,
+ // ControlMessage.Dst, icmp.Echo.ID and icmp.Echo.Seq.
+ switch rm.Type {
+ case ipv4.ICMPTypeTimeExceeded:
+ names, _ := net.LookupAddr(peer.String())
+ fmt.Printf("%d\t%v %+v %v\n\t%+v\n", i, peer, names, rtt, cm)
+ case ipv4.ICMPTypeEchoReply:
+ names, _ := net.LookupAddr(peer.String())
+ fmt.Printf("%d\t%v %+v %v\n\t%+v\n", i, peer, names, rtt, cm)
+ return
+ default:
+ log.Printf("unknown ICMP message: %+v\n", rm)
+ }
+ }
+}
+
+func ExampleRawConn_advertisingOSPFHello() {
+ c, err := net.ListenPacket("ip4:89", "0.0.0.0") // OSPF for IPv4
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer c.Close()
+ r, err := ipv4.NewRawConn(c)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ en0, err := net.InterfaceByName("en0")
+ if err != nil {
+ log.Fatal(err)
+ }
+ allSPFRouters := net.IPAddr{IP: net.IPv4(224, 0, 0, 5)}
+ if err := r.JoinGroup(en0, &allSPFRouters); err != nil {
+ log.Fatal(err)
+ }
+ defer r.LeaveGroup(en0, &allSPFRouters)
+
+ hello := make([]byte, 24) // fake hello data, you need to implement this
+ ospf := make([]byte, 24) // fake ospf header, you need to implement this
+ ospf[0] = 2 // version 2
+ ospf[1] = 1 // hello packet
+ ospf = append(ospf, hello...)
+ iph := &ipv4.Header{
+ Version: ipv4.Version,
+ Len: ipv4.HeaderLen,
+ TOS: 0xc0, // DSCP CS6
+ TotalLen: ipv4.HeaderLen + len(ospf),
+ TTL: 1,
+ Protocol: 89,
+ Dst: allSPFRouters.IP.To4(),
+ }
+
+ var cm *ipv4.ControlMessage
+ switch runtime.GOOS {
+ case "darwin", "linux":
+ cm = &ipv4.ControlMessage{IfIndex: en0.Index}
+ default:
+ if err := r.SetMulticastInterface(en0); err != nil {
+ log.Fatal(err)
+ }
+ }
+ if err := r.WriteTo(iph, ospf, cm); err != nil {
+ log.Fatal(err)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/gen.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/gen.go
new file mode 100644
index 000000000..ffb44fe68
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/gen.go
@@ -0,0 +1,199 @@
+// Copyright 2013 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.
+
+// +build ignore
+
+//go:generate go run gen.go
+
+// This program generates system adaptation constants and types,
+// internet protocol constants and tables by reading template files
+// and IANA protocol registries.
+package main
+
+import (
+ "bytes"
+ "encoding/xml"
+ "fmt"
+ "go/format"
+ "io"
+ "io/ioutil"
+ "net/http"
+ "os"
+ "os/exec"
+ "runtime"
+ "strconv"
+ "strings"
+)
+
+func main() {
+ if err := genzsys(); err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+ if err := geniana(); err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+}
+
+func genzsys() error {
+ defs := "defs_" + runtime.GOOS + ".go"
+ f, err := os.Open(defs)
+ if err != nil {
+ if os.IsNotExist(err) {
+ return nil
+ }
+ return err
+ }
+ f.Close()
+ cmd := exec.Command("go", "tool", "cgo", "-godefs", defs)
+ b, err := cmd.Output()
+ if err != nil {
+ return err
+ }
+ b, err = format.Source(b)
+ if err != nil {
+ return err
+ }
+ zsys := "zsys_" + runtime.GOOS + ".go"
+ switch runtime.GOOS {
+ case "freebsd", "linux":
+ zsys = "zsys_" + runtime.GOOS + "_" + runtime.GOARCH + ".go"
+ }
+ if err := ioutil.WriteFile(zsys, b, 0644); err != nil {
+ return err
+ }
+ return nil
+}
+
+var registries = []struct {
+ url string
+ parse func(io.Writer, io.Reader) error
+}{
+ {
+ "http://www.iana.org/assignments/icmp-parameters/icmp-parameters.xml",
+ parseICMPv4Parameters,
+ },
+}
+
+func geniana() error {
+ var bb bytes.Buffer
+ fmt.Fprintf(&bb, "// go generate gen.go\n")
+ fmt.Fprintf(&bb, "// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT\n\n")
+ fmt.Fprintf(&bb, "package ipv4\n\n")
+ for _, r := range registries {
+ resp, err := http.Get(r.url)
+ if err != nil {
+ return err
+ }
+ defer resp.Body.Close()
+ if resp.StatusCode != http.StatusOK {
+ return fmt.Errorf("got HTTP status code %v for %v\n", resp.StatusCode, r.url)
+ }
+ if err := r.parse(&bb, resp.Body); err != nil {
+ return err
+ }
+ fmt.Fprintf(&bb, "\n")
+ }
+ b, err := format.Source(bb.Bytes())
+ if err != nil {
+ return err
+ }
+ if err := ioutil.WriteFile("iana.go", b, 0644); err != nil {
+ return err
+ }
+ return nil
+}
+
+func parseICMPv4Parameters(w io.Writer, r io.Reader) error {
+ dec := xml.NewDecoder(r)
+ var icp icmpv4Parameters
+ if err := dec.Decode(&icp); err != nil {
+ return err
+ }
+ prs := icp.escape()
+ fmt.Fprintf(w, "// %s, Updated: %s\n", icp.Title, icp.Updated)
+ fmt.Fprintf(w, "const (\n")
+ for _, pr := range prs {
+ if pr.Descr == "" {
+ continue
+ }
+ fmt.Fprintf(w, "ICMPType%s ICMPType = %d", pr.Descr, pr.Value)
+ fmt.Fprintf(w, "// %s\n", pr.OrigDescr)
+ }
+ fmt.Fprintf(w, ")\n\n")
+ fmt.Fprintf(w, "// %s, Updated: %s\n", icp.Title, icp.Updated)
+ fmt.Fprintf(w, "var icmpTypes = map[ICMPType]string{\n")
+ for _, pr := range prs {
+ if pr.Descr == "" {
+ continue
+ }
+ fmt.Fprintf(w, "%d: %q,\n", pr.Value, strings.ToLower(pr.OrigDescr))
+ }
+ fmt.Fprintf(w, "}\n")
+ return nil
+}
+
+type icmpv4Parameters struct {
+ XMLName xml.Name `xml:"registry"`
+ Title string `xml:"title"`
+ Updated string `xml:"updated"`
+ Registries []struct {
+ Title string `xml:"title"`
+ Records []struct {
+ Value string `xml:"value"`
+ Descr string `xml:"description"`
+ } `xml:"record"`
+ } `xml:"registry"`
+}
+
+type canonICMPv4ParamRecord struct {
+ OrigDescr string
+ Descr string
+ Value int
+}
+
+func (icp *icmpv4Parameters) escape() []canonICMPv4ParamRecord {
+ id := -1
+ for i, r := range icp.Registries {
+ if strings.Contains(r.Title, "Type") || strings.Contains(r.Title, "type") {
+ id = i
+ break
+ }
+ }
+ if id < 0 {
+ return nil
+ }
+ prs := make([]canonICMPv4ParamRecord, len(icp.Registries[id].Records))
+ sr := strings.NewReplacer(
+ "Messages", "",
+ "Message", "",
+ "ICMP", "",
+ "+", "P",
+ "-", "",
+ "/", "",
+ ".", "",
+ " ", "",
+ )
+ for i, pr := range icp.Registries[id].Records {
+ if strings.Contains(pr.Descr, "Reserved") ||
+ strings.Contains(pr.Descr, "Unassigned") ||
+ strings.Contains(pr.Descr, "Deprecated") ||
+ strings.Contains(pr.Descr, "Experiment") ||
+ strings.Contains(pr.Descr, "experiment") {
+ continue
+ }
+ ss := strings.Split(pr.Descr, "\n")
+ if len(ss) > 1 {
+ prs[i].Descr = strings.Join(ss, " ")
+ } else {
+ prs[i].Descr = ss[0]
+ }
+ s := strings.TrimSpace(prs[i].Descr)
+ prs[i].OrigDescr = s
+ prs[i].Descr = sr.Replace(s)
+ prs[i].Value, _ = strconv.Atoi(pr.Value)
+ }
+ return prs
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/genericopt.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/genericopt.go
new file mode 100644
index 000000000..119bf841b
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/genericopt.go
@@ -0,0 +1,57 @@
+// Copyright 2012 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 ipv4
+
+import "syscall"
+
+// TOS returns the type-of-service field value for outgoing packets.
+func (c *genericOpt) TOS() (int, error) {
+ if !c.ok() {
+ return 0, syscall.EINVAL
+ }
+ so, ok := sockOpts[ssoTOS]
+ if !ok {
+ return 0, errOpNoSupport
+ }
+ return so.GetInt(c.Conn)
+}
+
+// SetTOS sets the type-of-service field value for future outgoing
+// packets.
+func (c *genericOpt) SetTOS(tos int) error {
+ if !c.ok() {
+ return syscall.EINVAL
+ }
+ so, ok := sockOpts[ssoTOS]
+ if !ok {
+ return errOpNoSupport
+ }
+ return so.SetInt(c.Conn, tos)
+}
+
+// TTL returns the time-to-live field value for outgoing packets.
+func (c *genericOpt) TTL() (int, error) {
+ if !c.ok() {
+ return 0, syscall.EINVAL
+ }
+ so, ok := sockOpts[ssoTTL]
+ if !ok {
+ return 0, errOpNoSupport
+ }
+ return so.GetInt(c.Conn)
+}
+
+// SetTTL sets the time-to-live field value for future outgoing
+// packets.
+func (c *genericOpt) SetTTL(ttl int) error {
+ if !c.ok() {
+ return syscall.EINVAL
+ }
+ so, ok := sockOpts[ssoTTL]
+ if !ok {
+ return errOpNoSupport
+ }
+ return so.SetInt(c.Conn, ttl)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/header.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/header.go
new file mode 100644
index 000000000..8bb0f0f4d
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/header.go
@@ -0,0 +1,159 @@
+// Copyright 2012 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 ipv4
+
+import (
+ "encoding/binary"
+ "fmt"
+ "net"
+ "runtime"
+ "syscall"
+
+ "golang.org/x/net/internal/socket"
+)
+
+const (
+ Version = 4 // protocol version
+ HeaderLen = 20 // header length without extension headers
+ maxHeaderLen = 60 // sensible default, revisit if later RFCs define new usage of version and header length fields
+)
+
+type HeaderFlags int
+
+const (
+ MoreFragments HeaderFlags = 1 << iota // more fragments flag
+ DontFragment // don't fragment flag
+)
+
+// A Header represents an IPv4 header.
+type Header struct {
+ Version int // protocol version
+ Len int // header length
+ TOS int // type-of-service
+ TotalLen int // packet total length
+ ID int // identification
+ Flags HeaderFlags // flags
+ FragOff int // fragment offset
+ TTL int // time-to-live
+ Protocol int // next protocol
+ Checksum int // checksum
+ Src net.IP // source address
+ Dst net.IP // destination address
+ Options []byte // options, extension headers
+}
+
+func (h *Header) String() string {
+ if h == nil {
+ return "<nil>"
+ }
+ return fmt.Sprintf("ver=%d hdrlen=%d tos=%#x totallen=%d id=%#x flags=%#x fragoff=%#x ttl=%d proto=%d cksum=%#x src=%v dst=%v", h.Version, h.Len, h.TOS, h.TotalLen, h.ID, h.Flags, h.FragOff, h.TTL, h.Protocol, h.Checksum, h.Src, h.Dst)
+}
+
+// Marshal returns the binary encoding of h.
+func (h *Header) Marshal() ([]byte, error) {
+ if h == nil {
+ return nil, syscall.EINVAL
+ }
+ if h.Len < HeaderLen {
+ return nil, errHeaderTooShort
+ }
+ hdrlen := HeaderLen + len(h.Options)
+ b := make([]byte, hdrlen)
+ b[0] = byte(Version<<4 | (hdrlen >> 2 & 0x0f))
+ b[1] = byte(h.TOS)
+ flagsAndFragOff := (h.FragOff & 0x1fff) | int(h.Flags<<13)
+ switch runtime.GOOS {
+ case "darwin", "dragonfly", "netbsd":
+ socket.NativeEndian.PutUint16(b[2:4], uint16(h.TotalLen))
+ socket.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))
+ } else {
+ binary.BigEndian.PutUint16(b[2:4], uint16(h.TotalLen))
+ binary.BigEndian.PutUint16(b[6:8], uint16(flagsAndFragOff))
+ }
+ default:
+ binary.BigEndian.PutUint16(b[2:4], uint16(h.TotalLen))
+ binary.BigEndian.PutUint16(b[6:8], uint16(flagsAndFragOff))
+ }
+ binary.BigEndian.PutUint16(b[4:6], uint16(h.ID))
+ b[8] = byte(h.TTL)
+ b[9] = byte(h.Protocol)
+ binary.BigEndian.PutUint16(b[10:12], uint16(h.Checksum))
+ if ip := h.Src.To4(); ip != nil {
+ copy(b[12:16], ip[:net.IPv4len])
+ }
+ if ip := h.Dst.To4(); ip != nil {
+ copy(b[16:20], ip[:net.IPv4len])
+ } else {
+ return nil, errMissingAddress
+ }
+ if len(h.Options) > 0 {
+ copy(b[HeaderLen:], h.Options)
+ }
+ return b, nil
+}
+
+// Parse parses b as an IPv4 header and sotres the result in h.
+func (h *Header) Parse(b []byte) error {
+ if h == nil || len(b) < HeaderLen {
+ return errHeaderTooShort
+ }
+ hdrlen := int(b[0]&0x0f) << 2
+ if hdrlen > len(b) {
+ return errBufferTooShort
+ }
+ h.Version = int(b[0] >> 4)
+ h.Len = hdrlen
+ h.TOS = int(b[1])
+ h.ID = int(binary.BigEndian.Uint16(b[4:6]))
+ h.TTL = int(b[8])
+ h.Protocol = int(b[9])
+ h.Checksum = int(binary.BigEndian.Uint16(b[10:12]))
+ h.Src = net.IPv4(b[12], b[13], b[14], b[15])
+ h.Dst = net.IPv4(b[16], b[17], b[18], b[19])
+ switch runtime.GOOS {
+ case "darwin", "dragonfly", "netbsd":
+ h.TotalLen = int(socket.NativeEndian.Uint16(b[2:4])) + hdrlen
+ h.FragOff = int(socket.NativeEndian.Uint16(b[6:8]))
+ case "freebsd":
+ if freebsdVersion < 1100000 {
+ h.TotalLen = int(socket.NativeEndian.Uint16(b[2:4]))
+ if freebsdVersion < 1000000 {
+ h.TotalLen += hdrlen
+ }
+ h.FragOff = int(socket.NativeEndian.Uint16(b[6:8]))
+ } else {
+ h.TotalLen = int(binary.BigEndian.Uint16(b[2:4]))
+ h.FragOff = int(binary.BigEndian.Uint16(b[6:8]))
+ }
+ default:
+ h.TotalLen = int(binary.BigEndian.Uint16(b[2:4]))
+ h.FragOff = int(binary.BigEndian.Uint16(b[6:8]))
+ }
+ h.Flags = HeaderFlags(h.FragOff&0xe000) >> 13
+ h.FragOff = h.FragOff & 0x1fff
+ optlen := hdrlen - HeaderLen
+ if optlen > 0 && len(b) >= hdrlen {
+ if cap(h.Options) < optlen {
+ h.Options = make([]byte, optlen)
+ } else {
+ h.Options = h.Options[:optlen]
+ }
+ copy(h.Options, b[HeaderLen:hdrlen])
+ }
+ return nil
+}
+
+// ParseHeader parses b as an IPv4 header.
+func ParseHeader(b []byte) (*Header, error) {
+ h := new(Header)
+ if err := h.Parse(b); err != nil {
+ return nil, err
+ }
+ return h, nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/header_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/header_test.go
new file mode 100644
index 000000000..a246aeea1
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/header_test.go
@@ -0,0 +1,228 @@
+// Copyright 2012 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 ipv4
+
+import (
+ "bytes"
+ "encoding/binary"
+ "net"
+ "reflect"
+ "runtime"
+ "strings"
+ "testing"
+
+ "golang.org/x/net/internal/socket"
+)
+
+type headerTest struct {
+ wireHeaderFromKernel []byte
+ wireHeaderToKernel []byte
+ wireHeaderFromTradBSDKernel []byte
+ wireHeaderToTradBSDKernel []byte
+ wireHeaderFromFreeBSD10Kernel []byte
+ wireHeaderToFreeBSD10Kernel []byte
+ *Header
+}
+
+var headerLittleEndianTests = []headerTest{
+ // TODO(mikio): Add platform dependent wire header formats when
+ // we support new platforms.
+ {
+ wireHeaderFromKernel: []byte{
+ 0x45, 0x01, 0xbe, 0xef,
+ 0xca, 0xfe, 0x45, 0xdc,
+ 0xff, 0x01, 0xde, 0xad,
+ 172, 16, 254, 254,
+ 192, 168, 0, 1,
+ },
+ wireHeaderToKernel: []byte{
+ 0x45, 0x01, 0xbe, 0xef,
+ 0xca, 0xfe, 0x45, 0xdc,
+ 0xff, 0x01, 0xde, 0xad,
+ 172, 16, 254, 254,
+ 192, 168, 0, 1,
+ },
+ wireHeaderFromTradBSDKernel: []byte{
+ 0x45, 0x01, 0xdb, 0xbe,
+ 0xca, 0xfe, 0xdc, 0x45,
+ 0xff, 0x01, 0xde, 0xad,
+ 172, 16, 254, 254,
+ 192, 168, 0, 1,
+ },
+ wireHeaderToTradBSDKernel: []byte{
+ 0x45, 0x01, 0xef, 0xbe,
+ 0xca, 0xfe, 0xdc, 0x45,
+ 0xff, 0x01, 0xde, 0xad,
+ 172, 16, 254, 254,
+ 192, 168, 0, 1,
+ },
+ wireHeaderFromFreeBSD10Kernel: []byte{
+ 0x45, 0x01, 0xef, 0xbe,
+ 0xca, 0xfe, 0xdc, 0x45,
+ 0xff, 0x01, 0xde, 0xad,
+ 172, 16, 254, 254,
+ 192, 168, 0, 1,
+ },
+ wireHeaderToFreeBSD10Kernel: []byte{
+ 0x45, 0x01, 0xef, 0xbe,
+ 0xca, 0xfe, 0xdc, 0x45,
+ 0xff, 0x01, 0xde, 0xad,
+ 172, 16, 254, 254,
+ 192, 168, 0, 1,
+ },
+ Header: &Header{
+ Version: Version,
+ Len: HeaderLen,
+ TOS: 1,
+ TotalLen: 0xbeef,
+ ID: 0xcafe,
+ Flags: DontFragment,
+ FragOff: 1500,
+ TTL: 255,
+ Protocol: 1,
+ Checksum: 0xdead,
+ Src: net.IPv4(172, 16, 254, 254),
+ Dst: net.IPv4(192, 168, 0, 1),
+ },
+ },
+
+ // with option headers
+ {
+ wireHeaderFromKernel: []byte{
+ 0x46, 0x01, 0xbe, 0xf3,
+ 0xca, 0xfe, 0x45, 0xdc,
+ 0xff, 0x01, 0xde, 0xad,
+ 172, 16, 254, 254,
+ 192, 168, 0, 1,
+ 0xff, 0xfe, 0xfe, 0xff,
+ },
+ wireHeaderToKernel: []byte{
+ 0x46, 0x01, 0xbe, 0xf3,
+ 0xca, 0xfe, 0x45, 0xdc,
+ 0xff, 0x01, 0xde, 0xad,
+ 172, 16, 254, 254,
+ 192, 168, 0, 1,
+ 0xff, 0xfe, 0xfe, 0xff,
+ },
+ wireHeaderFromTradBSDKernel: []byte{
+ 0x46, 0x01, 0xdb, 0xbe,
+ 0xca, 0xfe, 0xdc, 0x45,
+ 0xff, 0x01, 0xde, 0xad,
+ 172, 16, 254, 254,
+ 192, 168, 0, 1,
+ 0xff, 0xfe, 0xfe, 0xff,
+ },
+ wireHeaderToTradBSDKernel: []byte{
+ 0x46, 0x01, 0xf3, 0xbe,
+ 0xca, 0xfe, 0xdc, 0x45,
+ 0xff, 0x01, 0xde, 0xad,
+ 172, 16, 254, 254,
+ 192, 168, 0, 1,
+ 0xff, 0xfe, 0xfe, 0xff,
+ },
+ wireHeaderFromFreeBSD10Kernel: []byte{
+ 0x46, 0x01, 0xf3, 0xbe,
+ 0xca, 0xfe, 0xdc, 0x45,
+ 0xff, 0x01, 0xde, 0xad,
+ 172, 16, 254, 254,
+ 192, 168, 0, 1,
+ 0xff, 0xfe, 0xfe, 0xff,
+ },
+ wireHeaderToFreeBSD10Kernel: []byte{
+ 0x46, 0x01, 0xf3, 0xbe,
+ 0xca, 0xfe, 0xdc, 0x45,
+ 0xff, 0x01, 0xde, 0xad,
+ 172, 16, 254, 254,
+ 192, 168, 0, 1,
+ 0xff, 0xfe, 0xfe, 0xff,
+ },
+ Header: &Header{
+ Version: Version,
+ Len: HeaderLen + 4,
+ TOS: 1,
+ TotalLen: 0xbef3,
+ ID: 0xcafe,
+ Flags: DontFragment,
+ FragOff: 1500,
+ TTL: 255,
+ Protocol: 1,
+ Checksum: 0xdead,
+ Src: net.IPv4(172, 16, 254, 254),
+ Dst: net.IPv4(192, 168, 0, 1),
+ Options: []byte{0xff, 0xfe, 0xfe, 0xff},
+ },
+ },
+}
+
+func TestMarshalHeader(t *testing.T) {
+ if socket.NativeEndian != binary.LittleEndian {
+ t.Skip("no test for non-little endian machine yet")
+ }
+
+ for _, tt := range headerLittleEndianTests {
+ b, err := tt.Header.Marshal()
+ if err != nil {
+ t.Fatal(err)
+ }
+ var wh []byte
+ switch runtime.GOOS {
+ case "darwin", "dragonfly", "netbsd":
+ wh = tt.wireHeaderToTradBSDKernel
+ case "freebsd":
+ switch {
+ case freebsdVersion < 1000000:
+ wh = tt.wireHeaderToTradBSDKernel
+ case 1000000 <= freebsdVersion && freebsdVersion < 1100000:
+ wh = tt.wireHeaderToFreeBSD10Kernel
+ default:
+ wh = tt.wireHeaderToKernel
+ }
+ default:
+ wh = tt.wireHeaderToKernel
+ }
+ if !bytes.Equal(b, wh) {
+ t.Fatalf("got %#v; want %#v", b, wh)
+ }
+ }
+}
+
+func TestParseHeader(t *testing.T) {
+ if socket.NativeEndian != binary.LittleEndian {
+ t.Skip("no test for big endian machine yet")
+ }
+
+ for _, tt := range headerLittleEndianTests {
+ var wh []byte
+ switch runtime.GOOS {
+ case "darwin", "dragonfly", "netbsd":
+ wh = tt.wireHeaderFromTradBSDKernel
+ case "freebsd":
+ switch {
+ case freebsdVersion < 1000000:
+ wh = tt.wireHeaderFromTradBSDKernel
+ case 1000000 <= freebsdVersion && freebsdVersion < 1100000:
+ wh = tt.wireHeaderFromFreeBSD10Kernel
+ default:
+ wh = tt.wireHeaderFromKernel
+ }
+ default:
+ wh = tt.wireHeaderFromKernel
+ }
+ h, err := ParseHeader(wh)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := h.Parse(wh); err != nil {
+ t.Fatal(err)
+ }
+ if !reflect.DeepEqual(h, tt.Header) {
+ t.Fatalf("got %#v; want %#v", h, tt.Header)
+ }
+ s := h.String()
+ if strings.Contains(s, ",") {
+ t.Fatalf("should be space-separated values: %s", s)
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/helper.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/helper.go
new file mode 100644
index 000000000..a5052e324
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/helper.go
@@ -0,0 +1,63 @@
+// Copyright 2012 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 ipv4
+
+import (
+ "errors"
+ "net"
+)
+
+var (
+ errMissingAddress = errors.New("missing address")
+ errMissingHeader = errors.New("missing header")
+ errHeaderTooShort = errors.New("header too short")
+ errBufferTooShort = errors.New("buffer too short")
+ errInvalidConnType = errors.New("invalid conn type")
+ errOpNoSupport = errors.New("operation not supported")
+ errNoSuchInterface = errors.New("no such interface")
+ errNoSuchMulticastInterface = errors.New("no such multicast interface")
+
+ // See http://www.freebsd.org/doc/en/books/porters-handbook/freebsd-versions.html.
+ freebsdVersion uint32
+)
+
+func boolint(b bool) int {
+ if b {
+ return 1
+ }
+ return 0
+}
+
+func netAddrToIP4(a net.Addr) net.IP {
+ switch v := a.(type) {
+ case *net.UDPAddr:
+ if ip := v.IP.To4(); ip != nil {
+ return ip
+ }
+ case *net.IPAddr:
+ if ip := v.IP.To4(); ip != nil {
+ return ip
+ }
+ }
+ return nil
+}
+
+func opAddr(a net.Addr) net.Addr {
+ switch a.(type) {
+ case *net.TCPAddr:
+ if a == nil {
+ return nil
+ }
+ case *net.UDPAddr:
+ if a == nil {
+ return nil
+ }
+ case *net.IPAddr:
+ if a == nil {
+ return nil
+ }
+ }
+ return a
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/iana.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/iana.go
new file mode 100644
index 000000000..be10c9488
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/iana.go
@@ -0,0 +1,34 @@
+// go generate gen.go
+// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
+
+package ipv4
+
+// Internet Control Message Protocol (ICMP) Parameters, Updated: 2013-04-19
+const (
+ ICMPTypeEchoReply ICMPType = 0 // Echo Reply
+ ICMPTypeDestinationUnreachable ICMPType = 3 // Destination Unreachable
+ ICMPTypeRedirect ICMPType = 5 // Redirect
+ ICMPTypeEcho ICMPType = 8 // Echo
+ ICMPTypeRouterAdvertisement ICMPType = 9 // Router Advertisement
+ ICMPTypeRouterSolicitation ICMPType = 10 // Router Solicitation
+ ICMPTypeTimeExceeded ICMPType = 11 // Time Exceeded
+ ICMPTypeParameterProblem ICMPType = 12 // Parameter Problem
+ ICMPTypeTimestamp ICMPType = 13 // Timestamp
+ ICMPTypeTimestampReply ICMPType = 14 // Timestamp Reply
+ ICMPTypePhoturis ICMPType = 40 // Photuris
+)
+
+// Internet Control Message Protocol (ICMP) Parameters, Updated: 2013-04-19
+var icmpTypes = map[ICMPType]string{
+ 0: "echo reply",
+ 3: "destination unreachable",
+ 5: "redirect",
+ 8: "echo",
+ 9: "router advertisement",
+ 10: "router solicitation",
+ 11: "time exceeded",
+ 12: "parameter problem",
+ 13: "timestamp",
+ 14: "timestamp reply",
+ 40: "photuris",
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/icmp.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/icmp.go
new file mode 100644
index 000000000..9902bb3d2
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/icmp.go
@@ -0,0 +1,57 @@
+// Copyright 2013 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 ipv4
+
+import "golang.org/x/net/internal/iana"
+
+// An ICMPType represents a type of ICMP message.
+type ICMPType int
+
+func (typ ICMPType) String() string {
+ s, ok := icmpTypes[typ]
+ if !ok {
+ return "<nil>"
+ }
+ return s
+}
+
+// Protocol returns the ICMPv4 protocol number.
+func (typ ICMPType) Protocol() int {
+ return iana.ProtocolICMP
+}
+
+// An ICMPFilter represents an ICMP message filter for incoming
+// packets. The filter belongs to a packet delivery path on a host and
+// it cannot interact with forwarding packets or tunnel-outer packets.
+//
+// Note: RFC 8200 defines a reasonable role model and it works not
+// only for IPv6 but IPv4. A node means a device that implements IP.
+// A router means a node that forwards IP packets not explicitly
+// addressed to itself, and a host means a node that is not a router.
+type ICMPFilter struct {
+ icmpFilter
+}
+
+// Accept accepts incoming ICMP packets including the type field value
+// typ.
+func (f *ICMPFilter) Accept(typ ICMPType) {
+ f.accept(typ)
+}
+
+// Block blocks incoming ICMP packets including the type field value
+// typ.
+func (f *ICMPFilter) Block(typ ICMPType) {
+ f.block(typ)
+}
+
+// SetAll sets the filter action to the filter.
+func (f *ICMPFilter) SetAll(block bool) {
+ f.setAll(block)
+}
+
+// WillBlock reports whether the ICMP type will be blocked.
+func (f *ICMPFilter) WillBlock(typ ICMPType) bool {
+ return f.willBlock(typ)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/icmp_linux.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/icmp_linux.go
new file mode 100644
index 000000000..6e1c5c80a
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/icmp_linux.go
@@ -0,0 +1,25 @@
+// Copyright 2014 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 ipv4
+
+func (f *icmpFilter) accept(typ ICMPType) {
+ f.Data &^= 1 << (uint32(typ) & 31)
+}
+
+func (f *icmpFilter) block(typ ICMPType) {
+ f.Data |= 1 << (uint32(typ) & 31)
+}
+
+func (f *icmpFilter) setAll(block bool) {
+ if block {
+ f.Data = 1<<32 - 1
+ } else {
+ f.Data = 0
+ }
+}
+
+func (f *icmpFilter) willBlock(typ ICMPType) bool {
+ return f.Data&(1<<(uint32(typ)&31)) != 0
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/icmp_stub.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/icmp_stub.go
new file mode 100644
index 000000000..21bb29ab3
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/icmp_stub.go
@@ -0,0 +1,25 @@
+// Copyright 2014 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.
+
+// +build !linux
+
+package ipv4
+
+const sizeofICMPFilter = 0x0
+
+type icmpFilter struct {
+}
+
+func (f *icmpFilter) accept(typ ICMPType) {
+}
+
+func (f *icmpFilter) block(typ ICMPType) {
+}
+
+func (f *icmpFilter) setAll(block bool) {
+}
+
+func (f *icmpFilter) willBlock(typ ICMPType) bool {
+ return false
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/icmp_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/icmp_test.go
new file mode 100644
index 000000000..3324b54df
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/icmp_test.go
@@ -0,0 +1,95 @@
+// Copyright 2014 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 ipv4_test
+
+import (
+ "net"
+ "reflect"
+ "runtime"
+ "testing"
+
+ "golang.org/x/net/internal/nettest"
+ "golang.org/x/net/ipv4"
+)
+
+var icmpStringTests = []struct {
+ in ipv4.ICMPType
+ out string
+}{
+ {ipv4.ICMPTypeDestinationUnreachable, "destination unreachable"},
+
+ {256, "<nil>"},
+}
+
+func TestICMPString(t *testing.T) {
+ for _, tt := range icmpStringTests {
+ s := tt.in.String()
+ if s != tt.out {
+ t.Errorf("got %s; want %s", s, tt.out)
+ }
+ }
+}
+
+func TestICMPFilter(t *testing.T) {
+ switch runtime.GOOS {
+ case "linux":
+ default:
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+
+ var f ipv4.ICMPFilter
+ for _, toggle := range []bool{false, true} {
+ f.SetAll(toggle)
+ for _, typ := range []ipv4.ICMPType{
+ ipv4.ICMPTypeDestinationUnreachable,
+ ipv4.ICMPTypeEchoReply,
+ ipv4.ICMPTypeTimeExceeded,
+ ipv4.ICMPTypeParameterProblem,
+ } {
+ f.Accept(typ)
+ if f.WillBlock(typ) {
+ t.Errorf("ipv4.ICMPFilter.Set(%v, false) failed", typ)
+ }
+ f.Block(typ)
+ if !f.WillBlock(typ) {
+ t.Errorf("ipv4.ICMPFilter.Set(%v, true) failed", typ)
+ }
+ }
+ }
+}
+
+func TestSetICMPFilter(t *testing.T) {
+ switch runtime.GOOS {
+ case "linux":
+ default:
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+ if m, ok := nettest.SupportsRawIPSocket(); !ok {
+ t.Skip(m)
+ }
+
+ c, err := net.ListenPacket("ip4:icmp", "127.0.0.1")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer c.Close()
+
+ p := ipv4.NewPacketConn(c)
+
+ var f ipv4.ICMPFilter
+ f.SetAll(true)
+ f.Accept(ipv4.ICMPTypeEcho)
+ f.Accept(ipv4.ICMPTypeEchoReply)
+ if err := p.SetICMPFilter(&f); err != nil {
+ t.Fatal(err)
+ }
+ kf, err := p.ICMPFilter()
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !reflect.DeepEqual(kf, &f) {
+ t.Fatalf("got %#v; want %#v", kf, f)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/multicast_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/multicast_test.go
new file mode 100644
index 000000000..bcf49736b
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/multicast_test.go
@@ -0,0 +1,334 @@
+// Copyright 2012 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 ipv4_test
+
+import (
+ "bytes"
+ "net"
+ "os"
+ "runtime"
+ "testing"
+ "time"
+
+ "golang.org/x/net/icmp"
+ "golang.org/x/net/internal/iana"
+ "golang.org/x/net/internal/nettest"
+ "golang.org/x/net/ipv4"
+)
+
+var packetConnReadWriteMulticastUDPTests = []struct {
+ addr string
+ grp, src *net.UDPAddr
+}{
+ {"224.0.0.0:0", &net.UDPAddr{IP: net.IPv4(224, 0, 0, 254)}, nil}, // see RFC 4727
+
+ {"232.0.1.0:0", &net.UDPAddr{IP: net.IPv4(232, 0, 1, 254)}, &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1)}}, // see RFC 5771
+}
+
+func TestPacketConnReadWriteMulticastUDP(t *testing.T) {
+ switch runtime.GOOS {
+ case "nacl", "plan9", "solaris", "windows":
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+ ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback)
+ if ifi == nil {
+ t.Skipf("not available on %s", runtime.GOOS)
+ }
+
+ for _, tt := range packetConnReadWriteMulticastUDPTests {
+ c, err := net.ListenPacket("udp4", tt.addr)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer c.Close()
+
+ grp := *tt.grp
+ grp.Port = c.LocalAddr().(*net.UDPAddr).Port
+ p := ipv4.NewPacketConn(c)
+ defer p.Close()
+ if tt.src == nil {
+ if err := p.JoinGroup(ifi, &grp); err != nil {
+ t.Fatal(err)
+ }
+ defer p.LeaveGroup(ifi, &grp)
+ } else {
+ if err := p.JoinSourceSpecificGroup(ifi, &grp, tt.src); err != nil {
+ switch runtime.GOOS {
+ case "freebsd", "linux":
+ default: // platforms that don't support IGMPv2/3 fail here
+ t.Logf("not supported on %s", runtime.GOOS)
+ continue
+ }
+ t.Fatal(err)
+ }
+ defer p.LeaveSourceSpecificGroup(ifi, &grp, tt.src)
+ }
+ if err := p.SetMulticastInterface(ifi); err != nil {
+ t.Fatal(err)
+ }
+ if _, err := p.MulticastInterface(); err != nil {
+ t.Fatal(err)
+ }
+ if err := p.SetMulticastLoopback(true); err != nil {
+ t.Fatal(err)
+ }
+ if _, err := p.MulticastLoopback(); err != nil {
+ t.Fatal(err)
+ }
+ cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface
+ wb := []byte("HELLO-R-U-THERE")
+
+ for i, toggle := range []bool{true, false, true} {
+ if err := p.SetControlMessage(cf, toggle); err != nil {
+ if nettest.ProtocolNotSupported(err) {
+ t.Logf("not supported on %s", runtime.GOOS)
+ continue
+ }
+ t.Fatal(err)
+ }
+ if err := p.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil {
+ t.Fatal(err)
+ }
+ p.SetMulticastTTL(i + 1)
+ if n, err := p.WriteTo(wb, nil, &grp); err != nil {
+ t.Fatal(err)
+ } else if n != len(wb) {
+ t.Fatalf("got %v; want %v", n, len(wb))
+ }
+ rb := make([]byte, 128)
+ if n, _, _, err := p.ReadFrom(rb); err != nil {
+ t.Fatal(err)
+ } else if !bytes.Equal(rb[:n], wb) {
+ t.Fatalf("got %v; want %v", rb[:n], wb)
+ }
+ }
+ }
+}
+
+var packetConnReadWriteMulticastICMPTests = []struct {
+ grp, src *net.IPAddr
+}{
+ {&net.IPAddr{IP: net.IPv4(224, 0, 0, 254)}, nil}, // see RFC 4727
+
+ {&net.IPAddr{IP: net.IPv4(232, 0, 1, 254)}, &net.IPAddr{IP: net.IPv4(127, 0, 0, 1)}}, // see RFC 5771
+}
+
+func TestPacketConnReadWriteMulticastICMP(t *testing.T) {
+ switch runtime.GOOS {
+ case "nacl", "plan9", "solaris", "windows":
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+ if m, ok := nettest.SupportsRawIPSocket(); !ok {
+ t.Skip(m)
+ }
+ ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback)
+ if ifi == nil {
+ t.Skipf("not available on %s", runtime.GOOS)
+ }
+
+ for _, tt := range packetConnReadWriteMulticastICMPTests {
+ c, err := net.ListenPacket("ip4:icmp", "0.0.0.0")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer c.Close()
+
+ p := ipv4.NewPacketConn(c)
+ defer p.Close()
+ if tt.src == nil {
+ if err := p.JoinGroup(ifi, tt.grp); err != nil {
+ t.Fatal(err)
+ }
+ defer p.LeaveGroup(ifi, tt.grp)
+ } else {
+ if err := p.JoinSourceSpecificGroup(ifi, tt.grp, tt.src); err != nil {
+ switch runtime.GOOS {
+ case "freebsd", "linux":
+ default: // platforms that don't support IGMPv2/3 fail here
+ t.Logf("not supported on %s", runtime.GOOS)
+ continue
+ }
+ t.Fatal(err)
+ }
+ defer p.LeaveSourceSpecificGroup(ifi, tt.grp, tt.src)
+ }
+ if err := p.SetMulticastInterface(ifi); err != nil {
+ t.Fatal(err)
+ }
+ if _, err := p.MulticastInterface(); err != nil {
+ t.Fatal(err)
+ }
+ if err := p.SetMulticastLoopback(true); err != nil {
+ t.Fatal(err)
+ }
+ if _, err := p.MulticastLoopback(); err != nil {
+ t.Fatal(err)
+ }
+ cf := ipv4.FlagDst | ipv4.FlagInterface
+ if runtime.GOOS != "solaris" {
+ // Solaris never allows to modify ICMP properties.
+ cf |= ipv4.FlagTTL
+ }
+
+ for i, toggle := range []bool{true, false, true} {
+ wb, err := (&icmp.Message{
+ Type: ipv4.ICMPTypeEcho, Code: 0,
+ Body: &icmp.Echo{
+ ID: os.Getpid() & 0xffff, Seq: i + 1,
+ Data: []byte("HELLO-R-U-THERE"),
+ },
+ }).Marshal(nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := p.SetControlMessage(cf, toggle); err != nil {
+ if nettest.ProtocolNotSupported(err) {
+ t.Logf("not supported on %s", runtime.GOOS)
+ continue
+ }
+ t.Fatal(err)
+ }
+ if err := p.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil {
+ t.Fatal(err)
+ }
+ p.SetMulticastTTL(i + 1)
+ if n, err := p.WriteTo(wb, nil, tt.grp); err != nil {
+ t.Fatal(err)
+ } else if n != len(wb) {
+ t.Fatalf("got %v; want %v", n, len(wb))
+ }
+ rb := make([]byte, 128)
+ if n, _, _, err := p.ReadFrom(rb); err != nil {
+ t.Fatal(err)
+ } else {
+ m, err := icmp.ParseMessage(iana.ProtocolICMP, rb[:n])
+ if err != nil {
+ t.Fatal(err)
+ }
+ switch {
+ case m.Type == ipv4.ICMPTypeEchoReply && m.Code == 0: // net.inet.icmp.bmcastecho=1
+ case m.Type == ipv4.ICMPTypeEcho && m.Code == 0: // net.inet.icmp.bmcastecho=0
+ default:
+ t.Fatalf("got type=%v, code=%v; want type=%v, code=%v", m.Type, m.Code, ipv4.ICMPTypeEchoReply, 0)
+ }
+ }
+ }
+ }
+}
+
+var rawConnReadWriteMulticastICMPTests = []struct {
+ grp, src *net.IPAddr
+}{
+ {&net.IPAddr{IP: net.IPv4(224, 0, 0, 254)}, nil}, // see RFC 4727
+
+ {&net.IPAddr{IP: net.IPv4(232, 0, 1, 254)}, &net.IPAddr{IP: net.IPv4(127, 0, 0, 1)}}, // see RFC 5771
+}
+
+func TestRawConnReadWriteMulticastICMP(t *testing.T) {
+ if testing.Short() {
+ t.Skip("to avoid external network")
+ }
+ if m, ok := nettest.SupportsRawIPSocket(); !ok {
+ t.Skip(m)
+ }
+ ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback)
+ if ifi == nil {
+ t.Skipf("not available on %s", runtime.GOOS)
+ }
+
+ for _, tt := range rawConnReadWriteMulticastICMPTests {
+ c, err := net.ListenPacket("ip4:icmp", "0.0.0.0")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer c.Close()
+
+ r, err := ipv4.NewRawConn(c)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer r.Close()
+ if tt.src == nil {
+ if err := r.JoinGroup(ifi, tt.grp); err != nil {
+ t.Fatal(err)
+ }
+ defer r.LeaveGroup(ifi, tt.grp)
+ } else {
+ if err := r.JoinSourceSpecificGroup(ifi, tt.grp, tt.src); err != nil {
+ switch runtime.GOOS {
+ case "freebsd", "linux":
+ default: // platforms that don't support IGMPv2/3 fail here
+ t.Logf("not supported on %s", runtime.GOOS)
+ continue
+ }
+ t.Fatal(err)
+ }
+ defer r.LeaveSourceSpecificGroup(ifi, tt.grp, tt.src)
+ }
+ if err := r.SetMulticastInterface(ifi); err != nil {
+ t.Fatal(err)
+ }
+ if _, err := r.MulticastInterface(); err != nil {
+ t.Fatal(err)
+ }
+ if err := r.SetMulticastLoopback(true); err != nil {
+ t.Fatal(err)
+ }
+ if _, err := r.MulticastLoopback(); err != nil {
+ t.Fatal(err)
+ }
+ cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface
+
+ for i, toggle := range []bool{true, false, true} {
+ wb, err := (&icmp.Message{
+ Type: ipv4.ICMPTypeEcho, Code: 0,
+ Body: &icmp.Echo{
+ ID: os.Getpid() & 0xffff, Seq: i + 1,
+ Data: []byte("HELLO-R-U-THERE"),
+ },
+ }).Marshal(nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ wh := &ipv4.Header{
+ Version: ipv4.Version,
+ Len: ipv4.HeaderLen,
+ TOS: i + 1,
+ TotalLen: ipv4.HeaderLen + len(wb),
+ Protocol: 1,
+ Dst: tt.grp.IP,
+ }
+ if err := r.SetControlMessage(cf, toggle); err != nil {
+ if nettest.ProtocolNotSupported(err) {
+ t.Logf("not supported on %s", runtime.GOOS)
+ continue
+ }
+ t.Fatal(err)
+ }
+ if err := r.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil {
+ t.Fatal(err)
+ }
+ r.SetMulticastTTL(i + 1)
+ if err := r.WriteTo(wh, wb, nil); err != nil {
+ t.Fatal(err)
+ }
+ rb := make([]byte, ipv4.HeaderLen+128)
+ if rh, b, _, err := r.ReadFrom(rb); err != nil {
+ t.Fatal(err)
+ } else {
+ m, err := icmp.ParseMessage(iana.ProtocolICMP, b)
+ if err != nil {
+ t.Fatal(err)
+ }
+ switch {
+ case (rh.Dst.IsLoopback() || rh.Dst.IsLinkLocalUnicast() || rh.Dst.IsGlobalUnicast()) && m.Type == ipv4.ICMPTypeEchoReply && m.Code == 0: // net.inet.icmp.bmcastecho=1
+ case rh.Dst.IsMulticast() && m.Type == ipv4.ICMPTypeEcho && m.Code == 0: // net.inet.icmp.bmcastecho=0
+ default:
+ t.Fatalf("got type=%v, code=%v; want type=%v, code=%v", m.Type, m.Code, ipv4.ICMPTypeEchoReply, 0)
+ }
+ }
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/multicastlistener_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/multicastlistener_test.go
new file mode 100644
index 000000000..e43fbbe08
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/multicastlistener_test.go
@@ -0,0 +1,265 @@
+// Copyright 2012 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 ipv4_test
+
+import (
+ "net"
+ "runtime"
+ "testing"
+
+ "golang.org/x/net/internal/nettest"
+ "golang.org/x/net/ipv4"
+)
+
+var udpMultipleGroupListenerTests = []net.Addr{
+ &net.UDPAddr{IP: net.IPv4(224, 0, 0, 249)}, // see RFC 4727
+ &net.UDPAddr{IP: net.IPv4(224, 0, 0, 250)},
+ &net.UDPAddr{IP: net.IPv4(224, 0, 0, 254)},
+}
+
+func TestUDPSinglePacketConnWithMultipleGroupListeners(t *testing.T) {
+ switch runtime.GOOS {
+ case "nacl", "plan9", "windows":
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+ if testing.Short() {
+ t.Skip("to avoid external network")
+ }
+
+ for _, gaddr := range udpMultipleGroupListenerTests {
+ c, err := net.ListenPacket("udp4", "0.0.0.0:0") // wildcard address with no reusable port
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer c.Close()
+
+ p := ipv4.NewPacketConn(c)
+ var mift []*net.Interface
+
+ ift, err := net.Interfaces()
+ if err != nil {
+ t.Fatal(err)
+ }
+ for i, ifi := range ift {
+ if _, ok := nettest.IsMulticastCapable("ip4", &ifi); !ok {
+ continue
+ }
+ if err := p.JoinGroup(&ifi, gaddr); err != nil {
+ t.Fatal(err)
+ }
+ mift = append(mift, &ift[i])
+ }
+ for _, ifi := range mift {
+ if err := p.LeaveGroup(ifi, gaddr); err != nil {
+ t.Fatal(err)
+ }
+ }
+ }
+}
+
+func TestUDPMultiplePacketConnWithMultipleGroupListeners(t *testing.T) {
+ switch runtime.GOOS {
+ case "nacl", "plan9", "windows":
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+ if testing.Short() {
+ t.Skip("to avoid external network")
+ }
+
+ for _, gaddr := range udpMultipleGroupListenerTests {
+ c1, err := net.ListenPacket("udp4", "224.0.0.0:0") // wildcard address with reusable port
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer c1.Close()
+ _, port, err := net.SplitHostPort(c1.LocalAddr().String())
+ if err != nil {
+ t.Fatal(err)
+ }
+ c2, err := net.ListenPacket("udp4", net.JoinHostPort("224.0.0.0", port)) // wildcard address with reusable port
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer c2.Close()
+
+ var ps [2]*ipv4.PacketConn
+ ps[0] = ipv4.NewPacketConn(c1)
+ ps[1] = ipv4.NewPacketConn(c2)
+ var mift []*net.Interface
+
+ ift, err := net.Interfaces()
+ if err != nil {
+ t.Fatal(err)
+ }
+ for i, ifi := range ift {
+ if _, ok := nettest.IsMulticastCapable("ip4", &ifi); !ok {
+ continue
+ }
+ for _, p := range ps {
+ if err := p.JoinGroup(&ifi, gaddr); err != nil {
+ t.Fatal(err)
+ }
+ }
+ mift = append(mift, &ift[i])
+ }
+ for _, ifi := range mift {
+ for _, p := range ps {
+ if err := p.LeaveGroup(ifi, gaddr); err != nil {
+ t.Fatal(err)
+ }
+ }
+ }
+ }
+}
+
+func TestUDPPerInterfaceSinglePacketConnWithSingleGroupListener(t *testing.T) {
+ switch runtime.GOOS {
+ case "nacl", "plan9", "windows":
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+ if testing.Short() {
+ t.Skip("to avoid external network")
+ }
+
+ gaddr := net.IPAddr{IP: net.IPv4(224, 0, 0, 254)} // see RFC 4727
+ type ml struct {
+ c *ipv4.PacketConn
+ ifi *net.Interface
+ }
+ var mlt []*ml
+
+ ift, err := net.Interfaces()
+ if err != nil {
+ t.Fatal(err)
+ }
+ port := "0"
+ for i, ifi := range ift {
+ ip, ok := nettest.IsMulticastCapable("ip4", &ifi)
+ if !ok {
+ continue
+ }
+ c, err := net.ListenPacket("udp4", net.JoinHostPort(ip.String(), port)) // unicast address with non-reusable port
+ if err != nil {
+ // The listen may fail when the serivce is
+ // already in use, but it's fine because the
+ // purpose of this is not to test the
+ // bookkeeping of IP control block inside the
+ // kernel.
+ t.Log(err)
+ continue
+ }
+ defer c.Close()
+ if port == "0" {
+ _, port, err = net.SplitHostPort(c.LocalAddr().String())
+ if err != nil {
+ t.Fatal(err)
+ }
+ }
+ p := ipv4.NewPacketConn(c)
+ if err := p.JoinGroup(&ifi, &gaddr); err != nil {
+ t.Fatal(err)
+ }
+ mlt = append(mlt, &ml{p, &ift[i]})
+ }
+ for _, m := range mlt {
+ if err := m.c.LeaveGroup(m.ifi, &gaddr); err != nil {
+ t.Fatal(err)
+ }
+ }
+}
+
+func TestIPSingleRawConnWithSingleGroupListener(t *testing.T) {
+ switch runtime.GOOS {
+ case "nacl", "plan9", "windows":
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+ if testing.Short() {
+ t.Skip("to avoid external network")
+ }
+ if m, ok := nettest.SupportsRawIPSocket(); !ok {
+ t.Skip(m)
+ }
+
+ c, err := net.ListenPacket("ip4:icmp", "0.0.0.0") // wildcard address
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer c.Close()
+
+ r, err := ipv4.NewRawConn(c)
+ if err != nil {
+ t.Fatal(err)
+ }
+ gaddr := net.IPAddr{IP: net.IPv4(224, 0, 0, 254)} // see RFC 4727
+ var mift []*net.Interface
+
+ ift, err := net.Interfaces()
+ if err != nil {
+ t.Fatal(err)
+ }
+ for i, ifi := range ift {
+ if _, ok := nettest.IsMulticastCapable("ip4", &ifi); !ok {
+ continue
+ }
+ if err := r.JoinGroup(&ifi, &gaddr); err != nil {
+ t.Fatal(err)
+ }
+ mift = append(mift, &ift[i])
+ }
+ for _, ifi := range mift {
+ if err := r.LeaveGroup(ifi, &gaddr); err != nil {
+ t.Fatal(err)
+ }
+ }
+}
+
+func TestIPPerInterfaceSingleRawConnWithSingleGroupListener(t *testing.T) {
+ switch runtime.GOOS {
+ case "nacl", "plan9", "windows":
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+ if testing.Short() {
+ t.Skip("to avoid external network")
+ }
+ if m, ok := nettest.SupportsRawIPSocket(); !ok {
+ t.Skip(m)
+ }
+
+ gaddr := net.IPAddr{IP: net.IPv4(224, 0, 0, 254)} // see RFC 4727
+ type ml struct {
+ c *ipv4.RawConn
+ ifi *net.Interface
+ }
+ var mlt []*ml
+
+ ift, err := net.Interfaces()
+ if err != nil {
+ t.Fatal(err)
+ }
+ for i, ifi := range ift {
+ ip, ok := nettest.IsMulticastCapable("ip4", &ifi)
+ if !ok {
+ continue
+ }
+ c, err := net.ListenPacket("ip4:253", ip.String()) // unicast address
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer c.Close()
+ r, err := ipv4.NewRawConn(c)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := r.JoinGroup(&ifi, &gaddr); err != nil {
+ t.Fatal(err)
+ }
+ mlt = append(mlt, &ml{r, &ift[i]})
+ }
+ for _, m := range mlt {
+ if err := m.c.LeaveGroup(m.ifi, &gaddr); err != nil {
+ t.Fatal(err)
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/multicastsockopt_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/multicastsockopt_test.go
new file mode 100644
index 000000000..f7efac24c
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/multicastsockopt_test.go
@@ -0,0 +1,195 @@
+// Copyright 2012 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 ipv4_test
+
+import (
+ "net"
+ "runtime"
+ "testing"
+
+ "golang.org/x/net/internal/nettest"
+ "golang.org/x/net/ipv4"
+)
+
+var packetConnMulticastSocketOptionTests = []struct {
+ net, proto, addr string
+ grp, src net.Addr
+}{
+ {"udp4", "", "224.0.0.0:0", &net.UDPAddr{IP: net.IPv4(224, 0, 0, 249)}, nil}, // see RFC 4727
+ {"ip4", ":icmp", "0.0.0.0", &net.IPAddr{IP: net.IPv4(224, 0, 0, 250)}, nil}, // see RFC 4727
+
+ {"udp4", "", "232.0.0.0:0", &net.UDPAddr{IP: net.IPv4(232, 0, 1, 249)}, &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1)}}, // see RFC 5771
+ {"ip4", ":icmp", "0.0.0.0", &net.IPAddr{IP: net.IPv4(232, 0, 1, 250)}, &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1)}}, // see RFC 5771
+}
+
+func TestPacketConnMulticastSocketOptions(t *testing.T) {
+ switch runtime.GOOS {
+ case "nacl", "plan9":
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+ ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback)
+ if ifi == nil {
+ t.Skipf("not available on %s", runtime.GOOS)
+ }
+
+ m, ok := nettest.SupportsRawIPSocket()
+ for _, tt := range packetConnMulticastSocketOptionTests {
+ if tt.net == "ip4" && !ok {
+ t.Log(m)
+ continue
+ }
+ c, err := net.ListenPacket(tt.net+tt.proto, tt.addr)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer c.Close()
+ p := ipv4.NewPacketConn(c)
+ defer p.Close()
+
+ if tt.src == nil {
+ testMulticastSocketOptions(t, p, ifi, tt.grp)
+ } else {
+ testSourceSpecificMulticastSocketOptions(t, p, ifi, tt.grp, tt.src)
+ }
+ }
+}
+
+var rawConnMulticastSocketOptionTests = []struct {
+ grp, src net.Addr
+}{
+ {&net.IPAddr{IP: net.IPv4(224, 0, 0, 250)}, nil}, // see RFC 4727
+
+ {&net.IPAddr{IP: net.IPv4(232, 0, 1, 250)}, &net.IPAddr{IP: net.IPv4(127, 0, 0, 1)}}, // see RFC 5771
+}
+
+func TestRawConnMulticastSocketOptions(t *testing.T) {
+ switch runtime.GOOS {
+ case "nacl", "plan9":
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+ if m, ok := nettest.SupportsRawIPSocket(); !ok {
+ t.Skip(m)
+ }
+ ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback)
+ if ifi == nil {
+ t.Skipf("not available on %s", runtime.GOOS)
+ }
+
+ for _, tt := range rawConnMulticastSocketOptionTests {
+ c, err := net.ListenPacket("ip4:icmp", "0.0.0.0")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer c.Close()
+ r, err := ipv4.NewRawConn(c)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer r.Close()
+
+ if tt.src == nil {
+ testMulticastSocketOptions(t, r, ifi, tt.grp)
+ } else {
+ testSourceSpecificMulticastSocketOptions(t, r, ifi, tt.grp, tt.src)
+ }
+ }
+}
+
+type testIPv4MulticastConn interface {
+ MulticastTTL() (int, error)
+ SetMulticastTTL(ttl int) error
+ MulticastLoopback() (bool, error)
+ SetMulticastLoopback(bool) error
+ JoinGroup(*net.Interface, net.Addr) error
+ LeaveGroup(*net.Interface, net.Addr) error
+ JoinSourceSpecificGroup(*net.Interface, net.Addr, net.Addr) error
+ LeaveSourceSpecificGroup(*net.Interface, net.Addr, net.Addr) error
+ ExcludeSourceSpecificGroup(*net.Interface, net.Addr, net.Addr) error
+ IncludeSourceSpecificGroup(*net.Interface, net.Addr, net.Addr) error
+}
+
+func testMulticastSocketOptions(t *testing.T, c testIPv4MulticastConn, ifi *net.Interface, grp net.Addr) {
+ const ttl = 255
+ if err := c.SetMulticastTTL(ttl); err != nil {
+ t.Error(err)
+ return
+ }
+ if v, err := c.MulticastTTL(); err != nil {
+ t.Error(err)
+ return
+ } else if v != ttl {
+ t.Errorf("got %v; want %v", v, ttl)
+ return
+ }
+
+ for _, toggle := range []bool{true, false} {
+ if err := c.SetMulticastLoopback(toggle); err != nil {
+ t.Error(err)
+ return
+ }
+ if v, err := c.MulticastLoopback(); err != nil {
+ t.Error(err)
+ return
+ } else if v != toggle {
+ t.Errorf("got %v; want %v", v, toggle)
+ return
+ }
+ }
+
+ if err := c.JoinGroup(ifi, grp); err != nil {
+ t.Error(err)
+ return
+ }
+ if err := c.LeaveGroup(ifi, grp); err != nil {
+ t.Error(err)
+ return
+ }
+}
+
+func testSourceSpecificMulticastSocketOptions(t *testing.T, c testIPv4MulticastConn, ifi *net.Interface, grp, src net.Addr) {
+ // MCAST_JOIN_GROUP -> MCAST_BLOCK_SOURCE -> MCAST_UNBLOCK_SOURCE -> MCAST_LEAVE_GROUP
+ if err := c.JoinGroup(ifi, grp); err != nil {
+ t.Error(err)
+ return
+ }
+ if err := c.ExcludeSourceSpecificGroup(ifi, grp, src); err != nil {
+ switch runtime.GOOS {
+ case "freebsd", "linux":
+ default: // platforms that don't support IGMPv2/3 fail here
+ t.Logf("not supported on %s", runtime.GOOS)
+ return
+ }
+ t.Error(err)
+ return
+ }
+ if err := c.IncludeSourceSpecificGroup(ifi, grp, src); err != nil {
+ t.Error(err)
+ return
+ }
+ if err := c.LeaveGroup(ifi, grp); err != nil {
+ t.Error(err)
+ return
+ }
+
+ // MCAST_JOIN_SOURCE_GROUP -> MCAST_LEAVE_SOURCE_GROUP
+ if err := c.JoinSourceSpecificGroup(ifi, grp, src); err != nil {
+ t.Error(err)
+ return
+ }
+ if err := c.LeaveSourceSpecificGroup(ifi, grp, src); err != nil {
+ t.Error(err)
+ return
+ }
+
+ // MCAST_JOIN_SOURCE_GROUP -> MCAST_LEAVE_GROUP
+ if err := c.JoinSourceSpecificGroup(ifi, grp, src); err != nil {
+ t.Error(err)
+ return
+ }
+ if err := c.LeaveGroup(ifi, grp); err != nil {
+ t.Error(err)
+ return
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/packet.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/packet.go
new file mode 100644
index 000000000..f00f5b052
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/packet.go
@@ -0,0 +1,69 @@
+// Copyright 2012 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 ipv4
+
+import (
+ "net"
+ "syscall"
+
+ "golang.org/x/net/internal/socket"
+)
+
+// BUG(mikio): On Windows, the ReadFrom and WriteTo methods of RawConn
+// are not implemented.
+
+// A packetHandler represents the IPv4 datagram handler.
+type packetHandler struct {
+ *net.IPConn
+ *socket.Conn
+ rawOpt
+}
+
+func (c *packetHandler) ok() bool { return c != nil && c.IPConn != nil && c.Conn != nil }
+
+// ReadFrom reads an IPv4 datagram from the endpoint c, copying the
+// datagram into b. It returns the received datagram as the IPv4
+// header h, the payload p and the control message cm.
+func (c *packetHandler) ReadFrom(b []byte) (h *Header, p []byte, cm *ControlMessage, err error) {
+ if !c.ok() {
+ return nil, nil, nil, syscall.EINVAL
+ }
+ return c.readFrom(b)
+}
+
+func slicePacket(b []byte) (h, p []byte, err error) {
+ if len(b) < HeaderLen {
+ return nil, nil, errHeaderTooShort
+ }
+ hdrlen := int(b[0]&0x0f) << 2
+ return b[:hdrlen], b[hdrlen:], nil
+}
+
+// WriteTo writes an IPv4 datagram through the endpoint c, copying the
+// datagram from the IPv4 header h and the payload p. The control
+// message cm allows the datagram path and the outgoing interface to be
+// specified. Currently only Darwin and Linux support this. The cm
+// may be nil if control of the outgoing datagram is not required.
+//
+// The IPv4 header h must contain appropriate fields that include:
+//
+// Version = <must be specified>
+// Len = <must be specified>
+// TOS = <must be specified>
+// TotalLen = <must be specified>
+// ID = platform sets an appropriate value if ID is zero
+// FragOff = <must be specified>
+// TTL = <must be specified>
+// Protocol = <must be specified>
+// Checksum = platform sets an appropriate value if Checksum is zero
+// Src = platform sets an appropriate value if Src is nil
+// Dst = <must be specified>
+// Options = optional
+func (c *packetHandler) WriteTo(h *Header, p []byte, cm *ControlMessage) error {
+ if !c.ok() {
+ return syscall.EINVAL
+ }
+ return c.writeTo(h, p, cm)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/packet_go1_8.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/packet_go1_8.go
new file mode 100644
index 000000000..b47d18683
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/packet_go1_8.go
@@ -0,0 +1,56 @@
+// Copyright 2012 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.
+
+// +build !go1.9
+
+package ipv4
+
+import "net"
+
+func (c *packetHandler) readFrom(b []byte) (h *Header, p []byte, cm *ControlMessage, err error) {
+ c.rawOpt.RLock()
+ oob := NewControlMessage(c.rawOpt.cflags)
+ c.rawOpt.RUnlock()
+ n, nn, _, src, err := c.ReadMsgIP(b, oob)
+ if err != nil {
+ return nil, nil, nil, err
+ }
+ var hs []byte
+ if hs, p, err = slicePacket(b[:n]); err != nil {
+ return nil, nil, nil, err
+ }
+ if h, err = ParseHeader(hs); err != nil {
+ return nil, nil, nil, err
+ }
+ if nn > 0 {
+ cm = new(ControlMessage)
+ if err := cm.Parse(oob[:nn]); err != nil {
+ return nil, nil, nil, err
+ }
+ }
+ if src != nil && cm != nil {
+ cm.Src = src.IP
+ }
+ return
+}
+
+func (c *packetHandler) writeTo(h *Header, p []byte, cm *ControlMessage) error {
+ oob := cm.Marshal()
+ wh, err := h.Marshal()
+ if err != nil {
+ return err
+ }
+ dst := new(net.IPAddr)
+ if cm != nil {
+ if ip := cm.Dst.To4(); ip != nil {
+ dst.IP = ip
+ }
+ }
+ if dst.IP == nil {
+ dst.IP = h.Dst
+ }
+ wh = append(wh, p...)
+ _, _, err = c.WriteMsgIP(wh, oob, dst)
+ return err
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/packet_go1_9.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/packet_go1_9.go
new file mode 100644
index 000000000..082c36d73
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/packet_go1_9.go
@@ -0,0 +1,67 @@
+// 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.
+
+// +build go1.9
+
+package ipv4
+
+import (
+ "net"
+
+ "golang.org/x/net/internal/socket"
+)
+
+func (c *packetHandler) readFrom(b []byte) (h *Header, p []byte, cm *ControlMessage, err error) {
+ c.rawOpt.RLock()
+ m := socket.Message{
+ Buffers: [][]byte{b},
+ OOB: NewControlMessage(c.rawOpt.cflags),
+ }
+ c.rawOpt.RUnlock()
+ if err := c.RecvMsg(&m, 0); err != nil {
+ return nil, nil, nil, &net.OpError{Op: "read", Net: c.IPConn.LocalAddr().Network(), Source: c.IPConn.LocalAddr(), Err: err}
+ }
+ var hs []byte
+ if hs, p, err = slicePacket(b[:m.N]); err != nil {
+ return nil, nil, nil, &net.OpError{Op: "read", Net: c.IPConn.LocalAddr().Network(), Source: c.IPConn.LocalAddr(), Err: err}
+ }
+ if h, err = ParseHeader(hs); err != nil {
+ return nil, nil, nil, &net.OpError{Op: "read", Net: c.IPConn.LocalAddr().Network(), Source: c.IPConn.LocalAddr(), Err: err}
+ }
+ if m.NN > 0 {
+ cm = new(ControlMessage)
+ if err := cm.Parse(m.OOB[:m.NN]); err != nil {
+ return nil, nil, nil, &net.OpError{Op: "read", Net: c.IPConn.LocalAddr().Network(), Source: c.IPConn.LocalAddr(), Err: err}
+ }
+ }
+ if src, ok := m.Addr.(*net.IPAddr); ok && cm != nil {
+ cm.Src = src.IP
+ }
+ return
+}
+
+func (c *packetHandler) writeTo(h *Header, p []byte, cm *ControlMessage) error {
+ m := socket.Message{
+ OOB: cm.Marshal(),
+ }
+ wh, err := h.Marshal()
+ if err != nil {
+ return err
+ }
+ m.Buffers = [][]byte{wh, p}
+ dst := new(net.IPAddr)
+ if cm != nil {
+ if ip := cm.Dst.To4(); ip != nil {
+ dst.IP = ip
+ }
+ }
+ if dst.IP == nil {
+ dst.IP = h.Dst
+ }
+ m.Addr = dst
+ if err := c.SendMsg(&m, 0); err != nil {
+ return &net.OpError{Op: "write", Net: c.IPConn.LocalAddr().Network(), Source: c.IPConn.LocalAddr(), Addr: opAddr(dst), Err: err}
+ }
+ return nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/payload.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/payload.go
new file mode 100644
index 000000000..f95f811ac
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/payload.go
@@ -0,0 +1,23 @@
+// Copyright 2012 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 ipv4
+
+import (
+ "net"
+
+ "golang.org/x/net/internal/socket"
+)
+
+// BUG(mikio): On Windows, the ControlMessage for ReadFrom and WriteTo
+// methods of PacketConn is not implemented.
+
+// A payloadHandler represents the IPv4 datagram payload handler.
+type payloadHandler struct {
+ net.PacketConn
+ *socket.Conn
+ rawOpt
+}
+
+func (c *payloadHandler) ok() bool { return c != nil && c.PacketConn != nil && c.Conn != nil }
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/payload_cmsg.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/payload_cmsg.go
new file mode 100644
index 000000000..3f06d7606
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/payload_cmsg.go
@@ -0,0 +1,36 @@
+// Copyright 2012 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.
+
+// +build !nacl,!plan9,!windows
+
+package ipv4
+
+import (
+ "net"
+ "syscall"
+)
+
+// ReadFrom reads a payload of the received IPv4 datagram, from the
+// endpoint c, copying the payload into b. It returns the number of
+// bytes copied into b, the control message cm and the source address
+// src of the received datagram.
+func (c *payloadHandler) ReadFrom(b []byte) (n int, cm *ControlMessage, src net.Addr, err error) {
+ if !c.ok() {
+ return 0, nil, nil, syscall.EINVAL
+ }
+ return c.readFrom(b)
+}
+
+// WriteTo writes a payload of the IPv4 datagram, to the destination
+// address dst through the endpoint c, copying the payload from b. It
+// returns the number of bytes written. The control message cm allows
+// the datagram path and the outgoing interface to be specified.
+// Currently only Darwin and Linux support this. The cm may be nil if
+// control of the outgoing datagram is not required.
+func (c *payloadHandler) WriteTo(b []byte, cm *ControlMessage, dst net.Addr) (n int, err error) {
+ if !c.ok() {
+ return 0, syscall.EINVAL
+ }
+ return c.writeTo(b, cm, dst)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/payload_cmsg_go1_8.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/payload_cmsg_go1_8.go
new file mode 100644
index 000000000..d26ccd90c
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/payload_cmsg_go1_8.go
@@ -0,0 +1,59 @@
+// Copyright 2012 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.
+
+// +build !go1.9
+// +build !nacl,!plan9,!windows
+
+package ipv4
+
+import "net"
+
+func (c *payloadHandler) readFrom(b []byte) (n int, cm *ControlMessage, src net.Addr, err error) {
+ c.rawOpt.RLock()
+ oob := NewControlMessage(c.rawOpt.cflags)
+ c.rawOpt.RUnlock()
+ var nn int
+ switch c := c.PacketConn.(type) {
+ case *net.UDPConn:
+ if n, nn, _, src, err = c.ReadMsgUDP(b, oob); err != nil {
+ return 0, nil, nil, err
+ }
+ case *net.IPConn:
+ nb := make([]byte, maxHeaderLen+len(b))
+ if n, nn, _, src, err = c.ReadMsgIP(nb, oob); err != nil {
+ return 0, nil, nil, err
+ }
+ hdrlen := int(nb[0]&0x0f) << 2
+ copy(b, nb[hdrlen:])
+ n -= hdrlen
+ default:
+ return 0, nil, nil, &net.OpError{Op: "read", Net: c.LocalAddr().Network(), Source: c.LocalAddr(), Err: errInvalidConnType}
+ }
+ if nn > 0 {
+ cm = new(ControlMessage)
+ if err = cm.Parse(oob[:nn]); err != nil {
+ return 0, nil, nil, &net.OpError{Op: "read", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: err}
+ }
+ }
+ if cm != nil {
+ cm.Src = netAddrToIP4(src)
+ }
+ return
+}
+
+func (c *payloadHandler) writeTo(b []byte, cm *ControlMessage, dst net.Addr) (n int, err error) {
+ oob := cm.Marshal()
+ if dst == nil {
+ return 0, &net.OpError{Op: "write", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: errMissingAddress}
+ }
+ switch c := c.PacketConn.(type) {
+ case *net.UDPConn:
+ n, _, err = c.WriteMsgUDP(b, oob, dst.(*net.UDPAddr))
+ case *net.IPConn:
+ n, _, err = c.WriteMsgIP(b, oob, dst.(*net.IPAddr))
+ default:
+ return 0, &net.OpError{Op: "write", Net: c.LocalAddr().Network(), Source: c.LocalAddr(), Addr: opAddr(dst), Err: errInvalidConnType}
+ }
+ return
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/payload_cmsg_go1_9.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/payload_cmsg_go1_9.go
new file mode 100644
index 000000000..2f1931183
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/payload_cmsg_go1_9.go
@@ -0,0 +1,67 @@
+// 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.
+
+// +build go1.9
+// +build !nacl,!plan9,!windows
+
+package ipv4
+
+import (
+ "net"
+
+ "golang.org/x/net/internal/socket"
+)
+
+func (c *payloadHandler) readFrom(b []byte) (int, *ControlMessage, net.Addr, error) {
+ c.rawOpt.RLock()
+ m := socket.Message{
+ OOB: NewControlMessage(c.rawOpt.cflags),
+ }
+ c.rawOpt.RUnlock()
+ switch c.PacketConn.(type) {
+ case *net.UDPConn:
+ m.Buffers = [][]byte{b}
+ if err := c.RecvMsg(&m, 0); err != nil {
+ return 0, nil, nil, &net.OpError{Op: "read", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: err}
+ }
+ case *net.IPConn:
+ h := make([]byte, HeaderLen)
+ m.Buffers = [][]byte{h, b}
+ if err := c.RecvMsg(&m, 0); err != nil {
+ return 0, nil, nil, &net.OpError{Op: "read", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: err}
+ }
+ hdrlen := int(h[0]&0x0f) << 2
+ if hdrlen > len(h) {
+ d := hdrlen - len(h)
+ copy(b, b[d:])
+ m.N -= d
+ } else {
+ m.N -= hdrlen
+ }
+ default:
+ return 0, nil, nil, &net.OpError{Op: "read", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: errInvalidConnType}
+ }
+ var cm *ControlMessage
+ if m.NN > 0 {
+ cm = new(ControlMessage)
+ if err := cm.Parse(m.OOB[:m.NN]); err != nil {
+ return 0, nil, nil, &net.OpError{Op: "read", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: err}
+ }
+ cm.Src = netAddrToIP4(m.Addr)
+ }
+ return m.N, cm, m.Addr, nil
+}
+
+func (c *payloadHandler) writeTo(b []byte, cm *ControlMessage, dst net.Addr) (int, error) {
+ m := socket.Message{
+ Buffers: [][]byte{b},
+ OOB: cm.Marshal(),
+ Addr: dst,
+ }
+ err := c.SendMsg(&m, 0)
+ if err != nil {
+ err = &net.OpError{Op: "write", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Addr: opAddr(dst), Err: err}
+ }
+ return m.N, err
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/payload_nocmsg.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/payload_nocmsg.go
new file mode 100644
index 000000000..3926de70b
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/payload_nocmsg.go
@@ -0,0 +1,42 @@
+// Copyright 2012 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.
+
+// +build nacl plan9 windows
+
+package ipv4
+
+import (
+ "net"
+ "syscall"
+)
+
+// ReadFrom reads a payload of the received IPv4 datagram, from the
+// endpoint c, copying the payload into b. It returns the number of
+// bytes copied into b, the control message cm and the source address
+// src of the received datagram.
+func (c *payloadHandler) ReadFrom(b []byte) (n int, cm *ControlMessage, src net.Addr, err error) {
+ if !c.ok() {
+ return 0, nil, nil, syscall.EINVAL
+ }
+ if n, src, err = c.PacketConn.ReadFrom(b); err != nil {
+ return 0, nil, nil, err
+ }
+ return
+}
+
+// WriteTo writes a payload of the IPv4 datagram, to the destination
+// address dst through the endpoint c, copying the payload from b. It
+// returns the number of bytes written. The control message cm allows
+// the datagram path and the outgoing interface to be specified.
+// Currently only Darwin and Linux support this. The cm may be nil if
+// control of the outgoing datagram is not required.
+func (c *payloadHandler) WriteTo(b []byte, cm *ControlMessage, dst net.Addr) (n int, err error) {
+ if !c.ok() {
+ return 0, syscall.EINVAL
+ }
+ if dst == nil {
+ return 0, errMissingAddress
+ }
+ return c.PacketConn.WriteTo(b, dst)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/readwrite_go1_8_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/readwrite_go1_8_test.go
new file mode 100644
index 000000000..1cd926e7f
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/readwrite_go1_8_test.go
@@ -0,0 +1,248 @@
+// Copyright 2012 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.
+
+// +build !go1.9
+
+package ipv4_test
+
+import (
+ "bytes"
+ "fmt"
+ "net"
+ "runtime"
+ "strings"
+ "sync"
+ "testing"
+
+ "golang.org/x/net/internal/iana"
+ "golang.org/x/net/internal/nettest"
+ "golang.org/x/net/ipv4"
+)
+
+func BenchmarkPacketConnReadWriteUnicast(b *testing.B) {
+ switch runtime.GOOS {
+ case "nacl", "plan9", "windows":
+ b.Skipf("not supported on %s", runtime.GOOS)
+ }
+
+ payload := []byte("HELLO-R-U-THERE")
+ iph, err := (&ipv4.Header{
+ Version: ipv4.Version,
+ Len: ipv4.HeaderLen,
+ TotalLen: ipv4.HeaderLen + len(payload),
+ TTL: 1,
+ Protocol: iana.ProtocolReserved,
+ Src: net.IPv4(192, 0, 2, 1),
+ Dst: net.IPv4(192, 0, 2, 254),
+ }).Marshal()
+ if err != nil {
+ b.Fatal(err)
+ }
+ greh := []byte{0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00}
+ datagram := append(greh, append(iph, payload...)...)
+ bb := make([]byte, 128)
+ cm := ipv4.ControlMessage{
+ Src: net.IPv4(127, 0, 0, 1),
+ }
+ if ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback); ifi != nil {
+ cm.IfIndex = ifi.Index
+ }
+
+ b.Run("UDP", func(b *testing.B) {
+ c, err := nettest.NewLocalPacketListener("udp4")
+ if err != nil {
+ b.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
+ }
+ defer c.Close()
+ p := ipv4.NewPacketConn(c)
+ dst := c.LocalAddr()
+ cf := ipv4.FlagTTL | ipv4.FlagInterface
+ if err := p.SetControlMessage(cf, true); err != nil {
+ b.Fatal(err)
+ }
+ b.Run("Net", func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ if _, err := c.WriteTo(payload, dst); err != nil {
+ b.Fatal(err)
+ }
+ if _, _, err := c.ReadFrom(bb); err != nil {
+ b.Fatal(err)
+ }
+ }
+ })
+ b.Run("ToFrom", func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ if _, err := p.WriteTo(payload, &cm, dst); err != nil {
+ b.Fatal(err)
+ }
+ if _, _, _, err := p.ReadFrom(bb); err != nil {
+ b.Fatal(err)
+ }
+ }
+ })
+ })
+ b.Run("IP", func(b *testing.B) {
+ switch runtime.GOOS {
+ case "netbsd":
+ b.Skip("need to configure gre on netbsd")
+ case "openbsd":
+ b.Skip("net.inet.gre.allow=0 by default on openbsd")
+ }
+
+ c, err := net.ListenPacket(fmt.Sprintf("ip4:%d", iana.ProtocolGRE), "127.0.0.1")
+ if err != nil {
+ b.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
+ }
+ defer c.Close()
+ p := ipv4.NewPacketConn(c)
+ dst := c.LocalAddr()
+ cf := ipv4.FlagTTL | ipv4.FlagInterface
+ if err := p.SetControlMessage(cf, true); err != nil {
+ b.Fatal(err)
+ }
+ b.Run("Net", func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ if _, err := c.WriteTo(datagram, dst); err != nil {
+ b.Fatal(err)
+ }
+ if _, _, err := c.ReadFrom(bb); err != nil {
+ b.Fatal(err)
+ }
+ }
+ })
+ b.Run("ToFrom", func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ if _, err := p.WriteTo(datagram, &cm, dst); err != nil {
+ b.Fatal(err)
+ }
+ if _, _, _, err := p.ReadFrom(bb); err != nil {
+ b.Fatal(err)
+ }
+ }
+ })
+ })
+}
+
+func TestPacketConnConcurrentReadWriteUnicast(t *testing.T) {
+ switch runtime.GOOS {
+ case "nacl", "plan9", "windows":
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+
+ payload := []byte("HELLO-R-U-THERE")
+ iph, err := (&ipv4.Header{
+ Version: ipv4.Version,
+ Len: ipv4.HeaderLen,
+ TotalLen: ipv4.HeaderLen + len(payload),
+ TTL: 1,
+ Protocol: iana.ProtocolReserved,
+ Src: net.IPv4(192, 0, 2, 1),
+ Dst: net.IPv4(192, 0, 2, 254),
+ }).Marshal()
+ if err != nil {
+ t.Fatal(err)
+ }
+ greh := []byte{0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00}
+ datagram := append(greh, append(iph, payload...)...)
+
+ t.Run("UDP", func(t *testing.T) {
+ c, err := nettest.NewLocalPacketListener("udp4")
+ if err != nil {
+ t.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
+ }
+ defer c.Close()
+ p := ipv4.NewPacketConn(c)
+ t.Run("ToFrom", func(t *testing.T) {
+ testPacketConnConcurrentReadWriteUnicast(t, p, payload, c.LocalAddr())
+ })
+ })
+ t.Run("IP", func(t *testing.T) {
+ switch runtime.GOOS {
+ case "netbsd":
+ t.Skip("need to configure gre on netbsd")
+ case "openbsd":
+ t.Skip("net.inet.gre.allow=0 by default on openbsd")
+ }
+
+ c, err := net.ListenPacket(fmt.Sprintf("ip4:%d", iana.ProtocolGRE), "127.0.0.1")
+ if err != nil {
+ t.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
+ }
+ defer c.Close()
+ p := ipv4.NewPacketConn(c)
+ t.Run("ToFrom", func(t *testing.T) {
+ testPacketConnConcurrentReadWriteUnicast(t, p, datagram, c.LocalAddr())
+ })
+ })
+}
+
+func testPacketConnConcurrentReadWriteUnicast(t *testing.T, p *ipv4.PacketConn, data []byte, dst net.Addr) {
+ ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback)
+ cf := ipv4.FlagTTL | ipv4.FlagSrc | ipv4.FlagDst | ipv4.FlagInterface
+
+ if err := p.SetControlMessage(cf, true); err != nil { // probe before test
+ if nettest.ProtocolNotSupported(err) {
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+ t.Fatal(err)
+ }
+
+ var wg sync.WaitGroup
+ reader := func() {
+ defer wg.Done()
+ b := make([]byte, 128)
+ n, cm, _, err := p.ReadFrom(b)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ if !bytes.Equal(b[:n], data) {
+ t.Errorf("got %#v; want %#v", b[:n], data)
+ return
+ }
+ s := cm.String()
+ if strings.Contains(s, ",") {
+ t.Errorf("should be space-separated values: %s", s)
+ return
+ }
+ }
+ writer := func(toggle bool) {
+ defer wg.Done()
+ cm := ipv4.ControlMessage{
+ Src: net.IPv4(127, 0, 0, 1),
+ }
+ if ifi != nil {
+ cm.IfIndex = ifi.Index
+ }
+ if err := p.SetControlMessage(cf, toggle); err != nil {
+ t.Error(err)
+ return
+ }
+ n, err := p.WriteTo(data, &cm, dst)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ if n != len(data) {
+ t.Errorf("got %d; want %d", n, len(data))
+ return
+ }
+ }
+
+ const N = 10
+ wg.Add(N)
+ for i := 0; i < N; i++ {
+ go reader()
+ }
+ wg.Add(2 * N)
+ for i := 0; i < 2*N; i++ {
+ go writer(i%2 != 0)
+
+ }
+ wg.Add(N)
+ for i := 0; i < N; i++ {
+ go reader()
+ }
+ wg.Wait()
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/readwrite_go1_9_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/readwrite_go1_9_test.go
new file mode 100644
index 000000000..365de022a
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/readwrite_go1_9_test.go
@@ -0,0 +1,388 @@
+// 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.
+
+// +build go1.9
+
+package ipv4_test
+
+import (
+ "bytes"
+ "fmt"
+ "net"
+ "runtime"
+ "strings"
+ "sync"
+ "testing"
+
+ "golang.org/x/net/internal/iana"
+ "golang.org/x/net/internal/nettest"
+ "golang.org/x/net/ipv4"
+)
+
+func BenchmarkPacketConnReadWriteUnicast(b *testing.B) {
+ switch runtime.GOOS {
+ case "nacl", "plan9", "windows":
+ b.Skipf("not supported on %s", runtime.GOOS)
+ }
+
+ payload := []byte("HELLO-R-U-THERE")
+ iph, err := (&ipv4.Header{
+ Version: ipv4.Version,
+ Len: ipv4.HeaderLen,
+ TotalLen: ipv4.HeaderLen + len(payload),
+ TTL: 1,
+ Protocol: iana.ProtocolReserved,
+ Src: net.IPv4(192, 0, 2, 1),
+ Dst: net.IPv4(192, 0, 2, 254),
+ }).Marshal()
+ if err != nil {
+ b.Fatal(err)
+ }
+ greh := []byte{0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00}
+ datagram := append(greh, append(iph, payload...)...)
+ bb := make([]byte, 128)
+ cm := ipv4.ControlMessage{
+ Src: net.IPv4(127, 0, 0, 1),
+ }
+ if ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback); ifi != nil {
+ cm.IfIndex = ifi.Index
+ }
+
+ b.Run("UDP", func(b *testing.B) {
+ c, err := nettest.NewLocalPacketListener("udp4")
+ if err != nil {
+ b.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
+ }
+ defer c.Close()
+ p := ipv4.NewPacketConn(c)
+ dst := c.LocalAddr()
+ cf := ipv4.FlagTTL | ipv4.FlagInterface
+ if err := p.SetControlMessage(cf, true); err != nil {
+ b.Fatal(err)
+ }
+ wms := []ipv4.Message{
+ {
+ Buffers: [][]byte{payload},
+ Addr: dst,
+ OOB: cm.Marshal(),
+ },
+ }
+ rms := []ipv4.Message{
+ {
+ Buffers: [][]byte{bb},
+ OOB: ipv4.NewControlMessage(cf),
+ },
+ }
+ b.Run("Net", func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ if _, err := c.WriteTo(payload, dst); err != nil {
+ b.Fatal(err)
+ }
+ if _, _, err := c.ReadFrom(bb); err != nil {
+ b.Fatal(err)
+ }
+ }
+ })
+ b.Run("ToFrom", func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ if _, err := p.WriteTo(payload, &cm, dst); err != nil {
+ b.Fatal(err)
+ }
+ if _, _, _, err := p.ReadFrom(bb); err != nil {
+ b.Fatal(err)
+ }
+ }
+ })
+ b.Run("Batch", func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ if _, err := p.WriteBatch(wms, 0); err != nil {
+ b.Fatal(err)
+ }
+ if _, err := p.ReadBatch(rms, 0); err != nil {
+ b.Fatal(err)
+ }
+ }
+ })
+ })
+ b.Run("IP", func(b *testing.B) {
+ switch runtime.GOOS {
+ case "netbsd":
+ b.Skip("need to configure gre on netbsd")
+ case "openbsd":
+ b.Skip("net.inet.gre.allow=0 by default on openbsd")
+ }
+
+ c, err := net.ListenPacket(fmt.Sprintf("ip4:%d", iana.ProtocolGRE), "127.0.0.1")
+ if err != nil {
+ b.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
+ }
+ defer c.Close()
+ p := ipv4.NewPacketConn(c)
+ dst := c.LocalAddr()
+ cf := ipv4.FlagTTL | ipv4.FlagInterface
+ if err := p.SetControlMessage(cf, true); err != nil {
+ b.Fatal(err)
+ }
+ wms := []ipv4.Message{
+ {
+ Buffers: [][]byte{datagram},
+ Addr: dst,
+ OOB: cm.Marshal(),
+ },
+ }
+ rms := []ipv4.Message{
+ {
+ Buffers: [][]byte{bb},
+ OOB: ipv4.NewControlMessage(cf),
+ },
+ }
+ b.Run("Net", func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ if _, err := c.WriteTo(datagram, dst); err != nil {
+ b.Fatal(err)
+ }
+ if _, _, err := c.ReadFrom(bb); err != nil {
+ b.Fatal(err)
+ }
+ }
+ })
+ b.Run("ToFrom", func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ if _, err := p.WriteTo(datagram, &cm, dst); err != nil {
+ b.Fatal(err)
+ }
+ if _, _, _, err := p.ReadFrom(bb); err != nil {
+ b.Fatal(err)
+ }
+ }
+ })
+ b.Run("Batch", func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ if _, err := p.WriteBatch(wms, 0); err != nil {
+ b.Fatal(err)
+ }
+ if _, err := p.ReadBatch(rms, 0); err != nil {
+ b.Fatal(err)
+ }
+ }
+ })
+ })
+}
+
+func TestPacketConnConcurrentReadWriteUnicast(t *testing.T) {
+ switch runtime.GOOS {
+ case "nacl", "plan9", "windows":
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+
+ payload := []byte("HELLO-R-U-THERE")
+ iph, err := (&ipv4.Header{
+ Version: ipv4.Version,
+ Len: ipv4.HeaderLen,
+ TotalLen: ipv4.HeaderLen + len(payload),
+ TTL: 1,
+ Protocol: iana.ProtocolReserved,
+ Src: net.IPv4(192, 0, 2, 1),
+ Dst: net.IPv4(192, 0, 2, 254),
+ }).Marshal()
+ if err != nil {
+ t.Fatal(err)
+ }
+ greh := []byte{0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00}
+ datagram := append(greh, append(iph, payload...)...)
+
+ t.Run("UDP", func(t *testing.T) {
+ c, err := nettest.NewLocalPacketListener("udp4")
+ if err != nil {
+ t.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
+ }
+ defer c.Close()
+ p := ipv4.NewPacketConn(c)
+ t.Run("ToFrom", func(t *testing.T) {
+ testPacketConnConcurrentReadWriteUnicast(t, p, payload, c.LocalAddr(), false)
+ })
+ t.Run("Batch", func(t *testing.T) {
+ testPacketConnConcurrentReadWriteUnicast(t, p, payload, c.LocalAddr(), true)
+ })
+ })
+ t.Run("IP", func(t *testing.T) {
+ switch runtime.GOOS {
+ case "netbsd":
+ t.Skip("need to configure gre on netbsd")
+ case "openbsd":
+ t.Skip("net.inet.gre.allow=0 by default on openbsd")
+ }
+
+ c, err := net.ListenPacket(fmt.Sprintf("ip4:%d", iana.ProtocolGRE), "127.0.0.1")
+ if err != nil {
+ t.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
+ }
+ defer c.Close()
+ p := ipv4.NewPacketConn(c)
+ t.Run("ToFrom", func(t *testing.T) {
+ testPacketConnConcurrentReadWriteUnicast(t, p, datagram, c.LocalAddr(), false)
+ })
+ t.Run("Batch", func(t *testing.T) {
+ testPacketConnConcurrentReadWriteUnicast(t, p, datagram, c.LocalAddr(), true)
+ })
+ })
+}
+
+func testPacketConnConcurrentReadWriteUnicast(t *testing.T, p *ipv4.PacketConn, data []byte, dst net.Addr, batch bool) {
+ ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback)
+ cf := ipv4.FlagTTL | ipv4.FlagSrc | ipv4.FlagDst | ipv4.FlagInterface
+
+ if err := p.SetControlMessage(cf, true); err != nil { // probe before test
+ if nettest.ProtocolNotSupported(err) {
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+ t.Fatal(err)
+ }
+
+ var wg sync.WaitGroup
+ reader := func() {
+ defer wg.Done()
+ b := make([]byte, 128)
+ n, cm, _, err := p.ReadFrom(b)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ if !bytes.Equal(b[:n], data) {
+ t.Errorf("got %#v; want %#v", b[:n], data)
+ return
+ }
+ s := cm.String()
+ if strings.Contains(s, ",") {
+ t.Errorf("should be space-separated values: %s", s)
+ return
+ }
+ }
+ batchReader := func() {
+ defer wg.Done()
+ ms := []ipv4.Message{
+ {
+ Buffers: [][]byte{make([]byte, 128)},
+ OOB: ipv4.NewControlMessage(cf),
+ },
+ }
+ n, err := p.ReadBatch(ms, 0)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ if n != len(ms) {
+ t.Errorf("got %d; want %d", n, len(ms))
+ return
+ }
+ var cm ipv4.ControlMessage
+ if err := cm.Parse(ms[0].OOB[:ms[0].NN]); err != nil {
+ t.Error(err)
+ return
+ }
+ var b []byte
+ if _, ok := dst.(*net.IPAddr); ok {
+ var h ipv4.Header
+ if err := h.Parse(ms[0].Buffers[0][:ms[0].N]); err != nil {
+ t.Error(err)
+ return
+ }
+ b = ms[0].Buffers[0][h.Len:ms[0].N]
+ } else {
+ b = ms[0].Buffers[0][:ms[0].N]
+ }
+ if !bytes.Equal(b, data) {
+ t.Errorf("got %#v; want %#v", b, data)
+ return
+ }
+ s := cm.String()
+ if strings.Contains(s, ",") {
+ t.Errorf("should be space-separated values: %s", s)
+ return
+ }
+ }
+ writer := func(toggle bool) {
+ defer wg.Done()
+ cm := ipv4.ControlMessage{
+ Src: net.IPv4(127, 0, 0, 1),
+ }
+ if ifi != nil {
+ cm.IfIndex = ifi.Index
+ }
+ if err := p.SetControlMessage(cf, toggle); err != nil {
+ t.Error(err)
+ return
+ }
+ n, err := p.WriteTo(data, &cm, dst)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ if n != len(data) {
+ t.Errorf("got %d; want %d", n, len(data))
+ return
+ }
+ }
+ batchWriter := func(toggle bool) {
+ defer wg.Done()
+ cm := ipv4.ControlMessage{
+ Src: net.IPv4(127, 0, 0, 1),
+ }
+ if ifi != nil {
+ cm.IfIndex = ifi.Index
+ }
+ if err := p.SetControlMessage(cf, toggle); err != nil {
+ t.Error(err)
+ return
+ }
+ ms := []ipv4.Message{
+ {
+ Buffers: [][]byte{data},
+ OOB: cm.Marshal(),
+ Addr: dst,
+ },
+ }
+ n, err := p.WriteBatch(ms, 0)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ if n != len(ms) {
+ t.Errorf("got %d; want %d", n, len(ms))
+ return
+ }
+ if ms[0].N != len(data) {
+ t.Errorf("got %d; want %d", ms[0].N, len(data))
+ return
+ }
+ }
+
+ const N = 10
+ wg.Add(N)
+ for i := 0; i < N; i++ {
+ if batch {
+ go batchReader()
+ } else {
+ go reader()
+ }
+ }
+ wg.Add(2 * N)
+ for i := 0; i < 2*N; i++ {
+ if batch {
+ go batchWriter(i%2 != 0)
+ } else {
+ go writer(i%2 != 0)
+ }
+
+ }
+ wg.Add(N)
+ for i := 0; i < N; i++ {
+ if batch {
+ go batchReader()
+ } else {
+ go reader()
+ }
+ }
+ wg.Wait()
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/readwrite_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/readwrite_test.go
new file mode 100644
index 000000000..3896a8ae4
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/readwrite_test.go
@@ -0,0 +1,140 @@
+// Copyright 2012 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 ipv4_test
+
+import (
+ "bytes"
+ "net"
+ "runtime"
+ "strings"
+ "sync"
+ "testing"
+
+ "golang.org/x/net/internal/nettest"
+ "golang.org/x/net/ipv4"
+)
+
+func BenchmarkReadWriteUnicast(b *testing.B) {
+ c, err := nettest.NewLocalPacketListener("udp4")
+ if err != nil {
+ b.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
+ }
+ defer c.Close()
+
+ dst := c.LocalAddr()
+ wb, rb := []byte("HELLO-R-U-THERE"), make([]byte, 128)
+
+ b.Run("NetUDP", func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ if _, err := c.WriteTo(wb, dst); err != nil {
+ b.Fatal(err)
+ }
+ if _, _, err := c.ReadFrom(rb); err != nil {
+ b.Fatal(err)
+ }
+ }
+ })
+ b.Run("IPv4UDP", func(b *testing.B) {
+ p := ipv4.NewPacketConn(c)
+ cf := ipv4.FlagTTL | ipv4.FlagInterface
+ if err := p.SetControlMessage(cf, true); err != nil {
+ b.Fatal(err)
+ }
+ cm := ipv4.ControlMessage{TTL: 1}
+ ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback)
+ if ifi != nil {
+ cm.IfIndex = ifi.Index
+ }
+
+ for i := 0; i < b.N; i++ {
+ if _, err := p.WriteTo(wb, &cm, dst); err != nil {
+ b.Fatal(err)
+ }
+ if _, _, _, err := p.ReadFrom(rb); err != nil {
+ b.Fatal(err)
+ }
+ }
+ })
+}
+
+func TestPacketConnConcurrentReadWriteUnicastUDP(t *testing.T) {
+ switch runtime.GOOS {
+ case "nacl", "plan9", "windows":
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+
+ c, err := nettest.NewLocalPacketListener("udp4")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer c.Close()
+ p := ipv4.NewPacketConn(c)
+ defer p.Close()
+
+ dst := c.LocalAddr()
+ ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback)
+ cf := ipv4.FlagTTL | ipv4.FlagSrc | ipv4.FlagDst | ipv4.FlagInterface
+ wb := []byte("HELLO-R-U-THERE")
+
+ if err := p.SetControlMessage(cf, true); err != nil { // probe before test
+ if nettest.ProtocolNotSupported(err) {
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+ t.Fatal(err)
+ }
+
+ var wg sync.WaitGroup
+ reader := func() {
+ defer wg.Done()
+ rb := make([]byte, 128)
+ if n, cm, _, err := p.ReadFrom(rb); err != nil {
+ t.Error(err)
+ return
+ } else if !bytes.Equal(rb[:n], wb) {
+ t.Errorf("got %v; want %v", rb[:n], wb)
+ return
+ } else {
+ s := cm.String()
+ if strings.Contains(s, ",") {
+ t.Errorf("should be space-separated values: %s", s)
+ }
+ }
+ }
+ writer := func(toggle bool) {
+ defer wg.Done()
+ cm := ipv4.ControlMessage{
+ Src: net.IPv4(127, 0, 0, 1),
+ }
+ if ifi != nil {
+ cm.IfIndex = ifi.Index
+ }
+ if err := p.SetControlMessage(cf, toggle); err != nil {
+ t.Error(err)
+ return
+ }
+ if n, err := p.WriteTo(wb, &cm, dst); err != nil {
+ t.Error(err)
+ return
+ } else if n != len(wb) {
+ t.Errorf("got %d; want %d", n, len(wb))
+ return
+ }
+ }
+
+ const N = 10
+ wg.Add(N)
+ for i := 0; i < N; i++ {
+ go reader()
+ }
+ wg.Add(2 * N)
+ for i := 0; i < 2*N; i++ {
+ go writer(i%2 != 0)
+ }
+ wg.Add(N)
+ for i := 0; i < N; i++ {
+ go reader()
+ }
+ wg.Wait()
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sockopt.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sockopt.go
new file mode 100644
index 000000000..22e90c039
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sockopt.go
@@ -0,0 +1,44 @@
+// Copyright 2014 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 ipv4
+
+import "golang.org/x/net/internal/socket"
+
+// Sticky socket options
+const (
+ ssoTOS = iota // header field for unicast packet
+ ssoTTL // header field for unicast packet
+ ssoMulticastTTL // header field for multicast packet
+ ssoMulticastInterface // outbound interface for multicast packet
+ ssoMulticastLoopback // loopback for multicast packet
+ ssoReceiveTTL // header field on received packet
+ ssoReceiveDst // header field on received packet
+ ssoReceiveInterface // inbound interface on received packet
+ ssoPacketInfo // incbound or outbound packet path
+ ssoHeaderPrepend // ipv4 header prepend
+ ssoStripHeader // strip ipv4 header
+ ssoICMPFilter // icmp filter
+ ssoJoinGroup // any-source multicast
+ ssoLeaveGroup // any-source multicast
+ ssoJoinSourceGroup // source-specific multicast
+ ssoLeaveSourceGroup // source-specific multicast
+ ssoBlockSourceGroup // any-source or source-specific multicast
+ ssoUnblockSourceGroup // any-source or source-specific multicast
+ ssoAttachFilter // attach BPF for filtering inbound traffic
+)
+
+// Sticky socket option value types
+const (
+ ssoTypeIPMreq = iota + 1
+ ssoTypeIPMreqn
+ ssoTypeGroupReq
+ ssoTypeGroupSourceReq
+)
+
+// A sockOpt represents a binding for sticky socket option.
+type sockOpt struct {
+ socket.Option
+ typ int // hint for option value type; optional
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sockopt_posix.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sockopt_posix.go
new file mode 100644
index 000000000..e96955bc1
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sockopt_posix.go
@@ -0,0 +1,71 @@
+// Copyright 2012 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.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
+
+package ipv4
+
+import (
+ "net"
+ "unsafe"
+
+ "golang.org/x/net/bpf"
+ "golang.org/x/net/internal/socket"
+)
+
+func (so *sockOpt) getMulticastInterface(c *socket.Conn) (*net.Interface, error) {
+ switch so.typ {
+ case ssoTypeIPMreqn:
+ return so.getIPMreqn(c)
+ default:
+ return so.getMulticastIf(c)
+ }
+}
+
+func (so *sockOpt) setMulticastInterface(c *socket.Conn, ifi *net.Interface) error {
+ switch so.typ {
+ case ssoTypeIPMreqn:
+ return so.setIPMreqn(c, ifi, nil)
+ default:
+ return so.setMulticastIf(c, ifi)
+ }
+}
+
+func (so *sockOpt) getICMPFilter(c *socket.Conn) (*ICMPFilter, error) {
+ b := make([]byte, so.Len)
+ n, err := so.Get(c, b)
+ if err != nil {
+ return nil, err
+ }
+ if n != sizeofICMPFilter {
+ return nil, errOpNoSupport
+ }
+ return (*ICMPFilter)(unsafe.Pointer(&b[0])), nil
+}
+
+func (so *sockOpt) setICMPFilter(c *socket.Conn, f *ICMPFilter) error {
+ b := (*[sizeofICMPFilter]byte)(unsafe.Pointer(f))[:sizeofICMPFilter]
+ return so.Set(c, b)
+}
+
+func (so *sockOpt) setGroup(c *socket.Conn, ifi *net.Interface, grp net.IP) error {
+ switch so.typ {
+ case ssoTypeIPMreq:
+ return so.setIPMreq(c, ifi, grp)
+ case ssoTypeIPMreqn:
+ return so.setIPMreqn(c, ifi, grp)
+ case ssoTypeGroupReq:
+ return so.setGroupReq(c, ifi, grp)
+ default:
+ return errOpNoSupport
+ }
+}
+
+func (so *sockOpt) setSourceGroup(c *socket.Conn, ifi *net.Interface, grp, src net.IP) error {
+ return so.setGroupSourceReq(c, ifi, grp, src)
+}
+
+func (so *sockOpt) setBPF(c *socket.Conn, f []bpf.RawInstruction) error {
+ return so.setAttachFilter(c, f)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sockopt_stub.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sockopt_stub.go
new file mode 100644
index 000000000..23249b782
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sockopt_stub.go
@@ -0,0 +1,42 @@
+// Copyright 2012 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.
+
+// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows
+
+package ipv4
+
+import (
+ "net"
+
+ "golang.org/x/net/bpf"
+ "golang.org/x/net/internal/socket"
+)
+
+func (so *sockOpt) getMulticastInterface(c *socket.Conn) (*net.Interface, error) {
+ return nil, errOpNoSupport
+}
+
+func (so *sockOpt) setMulticastInterface(c *socket.Conn, ifi *net.Interface) error {
+ return errOpNoSupport
+}
+
+func (so *sockOpt) getICMPFilter(c *socket.Conn) (*ICMPFilter, error) {
+ return nil, errOpNoSupport
+}
+
+func (so *sockOpt) setICMPFilter(c *socket.Conn, f *ICMPFilter) error {
+ return errOpNoSupport
+}
+
+func (so *sockOpt) setGroup(c *socket.Conn, ifi *net.Interface, grp net.IP) error {
+ return errOpNoSupport
+}
+
+func (so *sockOpt) setSourceGroup(c *socket.Conn, ifi *net.Interface, grp, src net.IP) error {
+ return errOpNoSupport
+}
+
+func (so *sockOpt) setBPF(c *socket.Conn, f []bpf.RawInstruction) error {
+ return errOpNoSupport
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_asmreq.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_asmreq.go
new file mode 100644
index 000000000..0388cba00
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_asmreq.go
@@ -0,0 +1,119 @@
+// Copyright 2012 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.
+
+// +build darwin dragonfly freebsd netbsd openbsd solaris windows
+
+package ipv4
+
+import (
+ "net"
+ "unsafe"
+
+ "golang.org/x/net/internal/socket"
+)
+
+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 {
+ return err
+ }
+ b := (*[sizeofIPMreq]byte)(unsafe.Pointer(&mreq))[:sizeofIPMreq]
+ return so.Set(c, b)
+}
+
+func (so *sockOpt) getMulticastIf(c *socket.Conn) (*net.Interface, error) {
+ var b [4]byte
+ if _, err := so.Get(c, b[:]); err != nil {
+ return nil, err
+ }
+ ifi, err := netIP4ToInterface(net.IPv4(b[0], b[1], b[2], b[3]))
+ if err != nil {
+ return nil, err
+ }
+ return ifi, nil
+}
+
+func (so *sockOpt) setMulticastIf(c *socket.Conn, ifi *net.Interface) error {
+ ip, err := netInterfaceToIP4(ifi)
+ if err != nil {
+ return err
+ }
+ var b [4]byte
+ copy(b[:], ip)
+ return so.Set(c, b[:])
+}
+
+func setIPMreqInterface(mreq *ipMreq, ifi *net.Interface) error {
+ if ifi == nil {
+ return nil
+ }
+ ifat, err := ifi.Addrs()
+ if err != nil {
+ return err
+ }
+ for _, ifa := range ifat {
+ switch ifa := ifa.(type) {
+ case *net.IPAddr:
+ if ip := ifa.IP.To4(); ip != nil {
+ copy(mreq.Interface[:], ip)
+ return nil
+ }
+ case *net.IPNet:
+ if ip := ifa.IP.To4(); ip != nil {
+ copy(mreq.Interface[:], ip)
+ return nil
+ }
+ }
+ }
+ return errNoSuchInterface
+}
+
+func netIP4ToInterface(ip net.IP) (*net.Interface, error) {
+ ift, err := net.Interfaces()
+ if err != nil {
+ return nil, err
+ }
+ for _, ifi := range ift {
+ ifat, err := ifi.Addrs()
+ if err != nil {
+ return nil, err
+ }
+ for _, ifa := range ifat {
+ switch ifa := ifa.(type) {
+ case *net.IPAddr:
+ if ip.Equal(ifa.IP) {
+ return &ifi, nil
+ }
+ case *net.IPNet:
+ if ip.Equal(ifa.IP) {
+ return &ifi, nil
+ }
+ }
+ }
+ }
+ return nil, errNoSuchInterface
+}
+
+func netInterfaceToIP4(ifi *net.Interface) (net.IP, error) {
+ if ifi == nil {
+ return net.IPv4zero.To4(), nil
+ }
+ ifat, err := ifi.Addrs()
+ if err != nil {
+ return nil, err
+ }
+ for _, ifa := range ifat {
+ switch ifa := ifa.(type) {
+ case *net.IPAddr:
+ if ip := ifa.IP.To4(); ip != nil {
+ return ip, nil
+ }
+ case *net.IPNet:
+ if ip := ifa.IP.To4(); ip != nil {
+ return ip, nil
+ }
+ }
+ }
+ return nil, errNoSuchInterface
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_asmreq_stub.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_asmreq_stub.go
new file mode 100644
index 000000000..f3919208b
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_asmreq_stub.go
@@ -0,0 +1,25 @@
+// 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.
+
+// +build !darwin,!dragonfly,!freebsd,!netbsd,!openbsd,!solaris,!windows
+
+package ipv4
+
+import (
+ "net"
+
+ "golang.org/x/net/internal/socket"
+)
+
+func (so *sockOpt) setIPMreq(c *socket.Conn, ifi *net.Interface, grp net.IP) error {
+ return errOpNoSupport
+}
+
+func (so *sockOpt) getMulticastIf(c *socket.Conn) (*net.Interface, error) {
+ return nil, errOpNoSupport
+}
+
+func (so *sockOpt) setMulticastIf(c *socket.Conn, ifi *net.Interface) error {
+ return errOpNoSupport
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_asmreqn.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_asmreqn.go
new file mode 100644
index 000000000..1f24f69f3
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_asmreqn.go
@@ -0,0 +1,42 @@
+// Copyright 2014 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.
+
+// +build darwin freebsd linux
+
+package ipv4
+
+import (
+ "net"
+ "unsafe"
+
+ "golang.org/x/net/internal/socket"
+)
+
+func (so *sockOpt) getIPMreqn(c *socket.Conn) (*net.Interface, error) {
+ b := make([]byte, so.Len)
+ if _, err := so.Get(c, b); err != nil {
+ return nil, err
+ }
+ mreqn := (*ipMreqn)(unsafe.Pointer(&b[0]))
+ if mreqn.Ifindex == 0 {
+ return nil, nil
+ }
+ ifi, err := net.InterfaceByIndex(int(mreqn.Ifindex))
+ if err != nil {
+ return nil, err
+ }
+ return ifi, nil
+}
+
+func (so *sockOpt) setIPMreqn(c *socket.Conn, ifi *net.Interface, grp net.IP) error {
+ var mreqn ipMreqn
+ if ifi != nil {
+ mreqn.Ifindex = int32(ifi.Index)
+ }
+ if grp != nil {
+ mreqn.Multiaddr = [4]byte{grp[0], grp[1], grp[2], grp[3]}
+ }
+ b := (*[sizeofIPMreqn]byte)(unsafe.Pointer(&mreqn))[:sizeofIPMreqn]
+ return so.Set(c, b)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_asmreqn_stub.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_asmreqn_stub.go
new file mode 100644
index 000000000..0711d3d78
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_asmreqn_stub.go
@@ -0,0 +1,21 @@
+// Copyright 2014 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.
+
+// +build !darwin,!freebsd,!linux
+
+package ipv4
+
+import (
+ "net"
+
+ "golang.org/x/net/internal/socket"
+)
+
+func (so *sockOpt) getIPMreqn(c *socket.Conn) (*net.Interface, error) {
+ return nil, errOpNoSupport
+}
+
+func (so *sockOpt) setIPMreqn(c *socket.Conn, ifi *net.Interface, grp net.IP) error {
+ return errOpNoSupport
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_bpf.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_bpf.go
new file mode 100644
index 000000000..9f30b7308
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_bpf.go
@@ -0,0 +1,23 @@
+// 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.
+
+// +build linux
+
+package ipv4
+
+import (
+ "unsafe"
+
+ "golang.org/x/net/bpf"
+ "golang.org/x/net/internal/socket"
+)
+
+func (so *sockOpt) setAttachFilter(c *socket.Conn, f []bpf.RawInstruction) error {
+ prog := sockFProg{
+ Len: uint16(len(f)),
+ Filter: (*sockFilter)(unsafe.Pointer(&f[0])),
+ }
+ b := (*[sizeofSockFprog]byte)(unsafe.Pointer(&prog))[:sizeofSockFprog]
+ return so.Set(c, b)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_bpf_stub.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_bpf_stub.go
new file mode 100644
index 000000000..9a2132093
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_bpf_stub.go
@@ -0,0 +1,16 @@
+// 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.
+
+// +build !linux
+
+package ipv4
+
+import (
+ "golang.org/x/net/bpf"
+ "golang.org/x/net/internal/socket"
+)
+
+func (so *sockOpt) setAttachFilter(c *socket.Conn, f []bpf.RawInstruction) error {
+ return errOpNoSupport
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_bsd.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_bsd.go
new file mode 100644
index 000000000..58256dd9d
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_bsd.go
@@ -0,0 +1,37 @@
+// Copyright 2014 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.
+
+// +build netbsd openbsd
+
+package ipv4
+
+import (
+ "net"
+ "syscall"
+
+ "golang.org/x/net/internal/iana"
+ "golang.org/x/net/internal/socket"
+)
+
+var (
+ ctlOpts = [ctlMax]ctlOpt{
+ ctlTTL: {sysIP_RECVTTL, 1, marshalTTL, parseTTL},
+ ctlDst: {sysIP_RECVDSTADDR, net.IPv4len, marshalDst, parseDst},
+ ctlInterface: {sysIP_RECVIF, syscall.SizeofSockaddrDatalink, marshalInterface, parseInterface},
+ }
+
+ sockOpts = map[int]*sockOpt{
+ ssoTOS: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_TOS, Len: 4}},
+ ssoTTL: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_TTL, Len: 4}},
+ ssoMulticastTTL: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_TTL, Len: 1}},
+ ssoMulticastInterface: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_IF, Len: 4}},
+ ssoMulticastLoopback: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_LOOP, Len: 1}},
+ ssoReceiveTTL: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_RECVTTL, Len: 4}},
+ ssoReceiveDst: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_RECVDSTADDR, Len: 4}},
+ ssoReceiveInterface: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_RECVIF, Len: 4}},
+ ssoHeaderPrepend: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_HDRINCL, Len: 4}},
+ ssoJoinGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_ADD_MEMBERSHIP, Len: sizeofIPMreq}, typ: ssoTypeIPMreq},
+ ssoLeaveGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_DROP_MEMBERSHIP, Len: sizeofIPMreq}, typ: ssoTypeIPMreq},
+ }
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_darwin.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_darwin.go
new file mode 100644
index 000000000..e8fb19169
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_darwin.go
@@ -0,0 +1,93 @@
+// Copyright 2014 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 ipv4
+
+import (
+ "net"
+ "strconv"
+ "strings"
+ "syscall"
+ "unsafe"
+
+ "golang.org/x/net/internal/iana"
+ "golang.org/x/net/internal/socket"
+)
+
+var (
+ ctlOpts = [ctlMax]ctlOpt{
+ ctlTTL: {sysIP_RECVTTL, 1, marshalTTL, parseTTL},
+ ctlDst: {sysIP_RECVDSTADDR, net.IPv4len, marshalDst, parseDst},
+ ctlInterface: {sysIP_RECVIF, syscall.SizeofSockaddrDatalink, marshalInterface, parseInterface},
+ }
+
+ sockOpts = map[int]*sockOpt{
+ ssoTOS: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_TOS, Len: 4}},
+ ssoTTL: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_TTL, Len: 4}},
+ ssoMulticastTTL: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_TTL, Len: 1}},
+ ssoMulticastInterface: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_IF, Len: 4}},
+ ssoMulticastLoopback: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_LOOP, Len: 4}},
+ ssoReceiveTTL: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_RECVTTL, Len: 4}},
+ ssoReceiveDst: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_RECVDSTADDR, Len: 4}},
+ ssoReceiveInterface: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_RECVIF, Len: 4}},
+ ssoHeaderPrepend: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_HDRINCL, Len: 4}},
+ ssoStripHeader: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_STRIPHDR, Len: 4}},
+ ssoJoinGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_ADD_MEMBERSHIP, Len: sizeofIPMreq}, typ: ssoTypeIPMreq},
+ ssoLeaveGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_DROP_MEMBERSHIP, Len: sizeofIPMreq}, typ: ssoTypeIPMreq},
+ }
+)
+
+func init() {
+ // Seems like kern.osreldate is veiled on latest OS X. We use
+ // kern.osrelease instead.
+ s, err := syscall.Sysctl("kern.osrelease")
+ if err != nil {
+ return
+ }
+ ss := strings.Split(s, ".")
+ if len(ss) == 0 {
+ return
+ }
+ // The IP_PKTINFO and protocol-independent multicast API were
+ // introduced in OS X 10.7 (Darwin 11). But it looks like
+ // those features require OS X 10.8 (Darwin 12) or above.
+ // See http://support.apple.com/kb/HT1633.
+ if mjver, err := strconv.Atoi(ss[0]); err != nil || mjver < 12 {
+ return
+ }
+ ctlOpts[ctlPacketInfo].name = sysIP_PKTINFO
+ ctlOpts[ctlPacketInfo].length = sizeofInetPktinfo
+ ctlOpts[ctlPacketInfo].marshal = marshalPacketInfo
+ ctlOpts[ctlPacketInfo].parse = parsePacketInfo
+ sockOpts[ssoPacketInfo] = &sockOpt{Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_RECVPKTINFO, Len: 4}}
+ sockOpts[ssoMulticastInterface] = &sockOpt{Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_IF, Len: sizeofIPMreqn}, typ: ssoTypeIPMreqn}
+ sockOpts[ssoJoinGroup] = &sockOpt{Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_JOIN_GROUP, Len: sizeofGroupReq}, typ: ssoTypeGroupReq}
+ sockOpts[ssoLeaveGroup] = &sockOpt{Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_LEAVE_GROUP, Len: sizeofGroupReq}, typ: ssoTypeGroupReq}
+ sockOpts[ssoJoinSourceGroup] = &sockOpt{Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_JOIN_SOURCE_GROUP, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq}
+ sockOpts[ssoLeaveSourceGroup] = &sockOpt{Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_LEAVE_SOURCE_GROUP, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq}
+ sockOpts[ssoBlockSourceGroup] = &sockOpt{Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_BLOCK_SOURCE, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq}
+ sockOpts[ssoUnblockSourceGroup] = &sockOpt{Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_UNBLOCK_SOURCE, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq}
+}
+
+func (pi *inetPktinfo) setIfindex(i int) {
+ pi.Ifindex = uint32(i)
+}
+
+func (gr *groupReq) setGroup(grp net.IP) {
+ sa := (*sockaddrInet)(unsafe.Pointer(uintptr(unsafe.Pointer(gr)) + 4))
+ sa.Len = sizeofSockaddrInet
+ sa.Family = syscall.AF_INET
+ copy(sa.Addr[:], grp)
+}
+
+func (gsr *groupSourceReq) setSourceGroup(grp, src net.IP) {
+ sa := (*sockaddrInet)(unsafe.Pointer(uintptr(unsafe.Pointer(gsr)) + 4))
+ sa.Len = sizeofSockaddrInet
+ sa.Family = syscall.AF_INET
+ copy(sa.Addr[:], grp)
+ sa = (*sockaddrInet)(unsafe.Pointer(uintptr(unsafe.Pointer(gsr)) + 132))
+ sa.Len = sizeofSockaddrInet
+ sa.Family = syscall.AF_INET
+ copy(sa.Addr[:], src)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_dragonfly.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_dragonfly.go
new file mode 100644
index 000000000..859764f33
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_dragonfly.go
@@ -0,0 +1,35 @@
+// 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 ipv4
+
+import (
+ "net"
+ "syscall"
+
+ "golang.org/x/net/internal/iana"
+ "golang.org/x/net/internal/socket"
+)
+
+var (
+ ctlOpts = [ctlMax]ctlOpt{
+ ctlTTL: {sysIP_RECVTTL, 1, marshalTTL, parseTTL},
+ ctlDst: {sysIP_RECVDSTADDR, net.IPv4len, marshalDst, parseDst},
+ ctlInterface: {sysIP_RECVIF, syscall.SizeofSockaddrDatalink, marshalInterface, parseInterface},
+ }
+
+ sockOpts = map[int]*sockOpt{
+ ssoTOS: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_TOS, Len: 4}},
+ ssoTTL: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_TTL, Len: 4}},
+ ssoMulticastTTL: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_TTL, Len: 1}},
+ ssoMulticastInterface: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_IF, Len: 4}},
+ ssoMulticastLoopback: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_LOOP, Len: 4}},
+ ssoReceiveTTL: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_RECVTTL, Len: 4}},
+ ssoReceiveDst: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_RECVDSTADDR, Len: 4}},
+ ssoReceiveInterface: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_RECVIF, Len: 4}},
+ ssoHeaderPrepend: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_HDRINCL, Len: 4}},
+ ssoJoinGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_ADD_MEMBERSHIP, Len: sizeofIPMreq}, typ: ssoTypeIPMreq},
+ ssoLeaveGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_DROP_MEMBERSHIP, Len: sizeofIPMreq}, typ: ssoTypeIPMreq},
+ }
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_freebsd.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_freebsd.go
new file mode 100644
index 000000000..b80032454
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_freebsd.go
@@ -0,0 +1,76 @@
+// Copyright 2014 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 ipv4
+
+import (
+ "net"
+ "runtime"
+ "strings"
+ "syscall"
+ "unsafe"
+
+ "golang.org/x/net/internal/iana"
+ "golang.org/x/net/internal/socket"
+)
+
+var (
+ ctlOpts = [ctlMax]ctlOpt{
+ ctlTTL: {sysIP_RECVTTL, 1, marshalTTL, parseTTL},
+ ctlDst: {sysIP_RECVDSTADDR, net.IPv4len, marshalDst, parseDst},
+ ctlInterface: {sysIP_RECVIF, syscall.SizeofSockaddrDatalink, marshalInterface, parseInterface},
+ }
+
+ sockOpts = map[int]*sockOpt{
+ ssoTOS: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_TOS, Len: 4}},
+ ssoTTL: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_TTL, Len: 4}},
+ ssoMulticastTTL: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_TTL, Len: 1}},
+ ssoMulticastInterface: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_IF, Len: 4}},
+ ssoMulticastLoopback: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_LOOP, Len: 4}},
+ ssoReceiveTTL: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_RECVTTL, Len: 4}},
+ ssoReceiveDst: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_RECVDSTADDR, Len: 4}},
+ ssoReceiveInterface: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_RECVIF, Len: 4}},
+ ssoHeaderPrepend: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_HDRINCL, Len: 4}},
+ ssoJoinGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_JOIN_GROUP, Len: sizeofGroupReq}, typ: ssoTypeGroupReq},
+ ssoLeaveGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_LEAVE_GROUP, Len: sizeofGroupReq}, typ: ssoTypeGroupReq},
+ ssoJoinSourceGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_JOIN_SOURCE_GROUP, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq},
+ ssoLeaveSourceGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_LEAVE_SOURCE_GROUP, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq},
+ ssoBlockSourceGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_BLOCK_SOURCE, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq},
+ ssoUnblockSourceGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_UNBLOCK_SOURCE, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq},
+ }
+)
+
+func init() {
+ freebsdVersion, _ = syscall.SysctlUint32("kern.osreldate")
+ if freebsdVersion >= 1000000 {
+ sockOpts[ssoMulticastInterface] = &sockOpt{Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_IF, Len: sizeofIPMreqn}, typ: ssoTypeIPMreqn}
+ }
+ if runtime.GOOS == "freebsd" && runtime.GOARCH == "386" {
+ archs, _ := syscall.Sysctl("kern.supported_archs")
+ for _, s := range strings.Fields(archs) {
+ if s == "amd64" {
+ freebsd32o64 = true
+ break
+ }
+ }
+ }
+}
+
+func (gr *groupReq) setGroup(grp net.IP) {
+ sa := (*sockaddrInet)(unsafe.Pointer(&gr.Group))
+ sa.Len = sizeofSockaddrInet
+ sa.Family = syscall.AF_INET
+ copy(sa.Addr[:], grp)
+}
+
+func (gsr *groupSourceReq) setSourceGroup(grp, src net.IP) {
+ sa := (*sockaddrInet)(unsafe.Pointer(&gsr.Group))
+ sa.Len = sizeofSockaddrInet
+ sa.Family = syscall.AF_INET
+ copy(sa.Addr[:], grp)
+ sa = (*sockaddrInet)(unsafe.Pointer(&gsr.Source))
+ sa.Len = sizeofSockaddrInet
+ sa.Family = syscall.AF_INET
+ copy(sa.Addr[:], src)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_linux.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_linux.go
new file mode 100644
index 000000000..60defe132
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_linux.go
@@ -0,0 +1,59 @@
+// Copyright 2014 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 ipv4
+
+import (
+ "net"
+ "syscall"
+ "unsafe"
+
+ "golang.org/x/net/internal/iana"
+ "golang.org/x/net/internal/socket"
+)
+
+var (
+ ctlOpts = [ctlMax]ctlOpt{
+ ctlTTL: {sysIP_TTL, 1, marshalTTL, parseTTL},
+ ctlPacketInfo: {sysIP_PKTINFO, sizeofInetPktinfo, marshalPacketInfo, parsePacketInfo},
+ }
+
+ sockOpts = map[int]*sockOpt{
+ ssoTOS: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_TOS, Len: 4}},
+ ssoTTL: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_TTL, Len: 4}},
+ ssoMulticastTTL: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_TTL, Len: 4}},
+ ssoMulticastInterface: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_IF, Len: sizeofIPMreqn}, typ: ssoTypeIPMreqn},
+ ssoMulticastLoopback: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_LOOP, Len: 4}},
+ ssoReceiveTTL: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_RECVTTL, Len: 4}},
+ ssoPacketInfo: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_PKTINFO, Len: 4}},
+ ssoHeaderPrepend: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_HDRINCL, Len: 4}},
+ ssoICMPFilter: {Option: socket.Option{Level: iana.ProtocolReserved, Name: sysICMP_FILTER, Len: sizeofICMPFilter}},
+ ssoJoinGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_JOIN_GROUP, Len: sizeofGroupReq}, typ: ssoTypeGroupReq},
+ ssoLeaveGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_LEAVE_GROUP, Len: sizeofGroupReq}, typ: ssoTypeGroupReq},
+ ssoJoinSourceGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_JOIN_SOURCE_GROUP, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq},
+ ssoLeaveSourceGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_LEAVE_SOURCE_GROUP, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq},
+ ssoBlockSourceGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_BLOCK_SOURCE, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq},
+ ssoUnblockSourceGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_UNBLOCK_SOURCE, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq},
+ ssoAttachFilter: {Option: socket.Option{Level: sysSOL_SOCKET, Name: sysSO_ATTACH_FILTER, Len: sizeofSockFprog}},
+ }
+)
+
+func (pi *inetPktinfo) setIfindex(i int) {
+ pi.Ifindex = int32(i)
+}
+
+func (gr *groupReq) setGroup(grp net.IP) {
+ sa := (*sockaddrInet)(unsafe.Pointer(&gr.Group))
+ sa.Family = syscall.AF_INET
+ copy(sa.Addr[:], grp)
+}
+
+func (gsr *groupSourceReq) setSourceGroup(grp, src net.IP) {
+ sa := (*sockaddrInet)(unsafe.Pointer(&gsr.Group))
+ sa.Family = syscall.AF_INET
+ copy(sa.Addr[:], grp)
+ sa = (*sockaddrInet)(unsafe.Pointer(&gsr.Source))
+ sa.Family = syscall.AF_INET
+ copy(sa.Addr[:], src)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_solaris.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_solaris.go
new file mode 100644
index 000000000..832fef1e2
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_solaris.go
@@ -0,0 +1,57 @@
+// 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.
+
+package ipv4
+
+import (
+ "net"
+ "syscall"
+ "unsafe"
+
+ "golang.org/x/net/internal/iana"
+ "golang.org/x/net/internal/socket"
+)
+
+var (
+ ctlOpts = [ctlMax]ctlOpt{
+ ctlTTL: {sysIP_RECVTTL, 4, marshalTTL, parseTTL},
+ ctlPacketInfo: {sysIP_PKTINFO, sizeofInetPktinfo, marshalPacketInfo, parsePacketInfo},
+ }
+
+ sockOpts = map[int]sockOpt{
+ ssoTOS: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_TOS, Len: 4}},
+ ssoTTL: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_TTL, Len: 4}},
+ ssoMulticastTTL: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_TTL, Len: 1}},
+ ssoMulticastInterface: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_IF, Len: 4}},
+ ssoMulticastLoopback: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_LOOP, Len: 1}},
+ ssoReceiveTTL: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_RECVTTL, Len: 4}},
+ ssoPacketInfo: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_RECVPKTINFO, Len: 4}},
+ ssoHeaderPrepend: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_HDRINCL, Len: 4}},
+ ssoJoinGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_JOIN_GROUP, Len: sizeofGroupReq}, typ: ssoTypeGroupReq},
+ ssoLeaveGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_LEAVE_GROUP, Len: sizeofGroupReq}, typ: ssoTypeGroupReq},
+ ssoJoinSourceGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_JOIN_SOURCE_GROUP, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq},
+ ssoLeaveSourceGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_LEAVE_SOURCE_GROUP, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq},
+ ssoBlockSourceGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_BLOCK_SOURCE, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq},
+ ssoUnblockSourceGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_UNBLOCK_SOURCE, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq},
+ }
+)
+
+func (pi *inetPktinfo) setIfindex(i int) {
+ pi.Ifindex = uint32(i)
+}
+
+func (gr *groupReq) setGroup(grp net.IP) {
+ sa := (*sockaddrInet)(unsafe.Pointer(uintptr(unsafe.Pointer(gr)) + 4))
+ sa.Family = syscall.AF_INET
+ copy(sa.Addr[:], grp)
+}
+
+func (gsr *groupSourceReq) setSourceGroup(grp, src net.IP) {
+ sa := (*sockaddrInet)(unsafe.Pointer(uintptr(unsafe.Pointer(gsr)) + 4))
+ sa.Family = syscall.AF_INET
+ copy(sa.Addr[:], grp)
+ sa = (*sockaddrInet)(unsafe.Pointer(uintptr(unsafe.Pointer(gsr)) + 260))
+ sa.Family = syscall.AF_INET
+ copy(sa.Addr[:], src)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_ssmreq.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_ssmreq.go
new file mode 100644
index 000000000..ae5704e77
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_ssmreq.go
@@ -0,0 +1,54 @@
+// Copyright 2014 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.
+
+// +build darwin freebsd linux solaris
+
+package ipv4
+
+import (
+ "net"
+ "unsafe"
+
+ "golang.org/x/net/internal/socket"
+)
+
+var freebsd32o64 bool
+
+func (so *sockOpt) setGroupReq(c *socket.Conn, ifi *net.Interface, grp net.IP) error {
+ var gr groupReq
+ if ifi != nil {
+ gr.Interface = uint32(ifi.Index)
+ }
+ gr.setGroup(grp)
+ var b []byte
+ if freebsd32o64 {
+ var d [sizeofGroupReq + 4]byte
+ s := (*[sizeofGroupReq]byte)(unsafe.Pointer(&gr))
+ copy(d[:4], s[:4])
+ copy(d[8:], s[4:])
+ b = d[:]
+ } else {
+ b = (*[sizeofGroupReq]byte)(unsafe.Pointer(&gr))[:sizeofGroupReq]
+ }
+ return so.Set(c, b)
+}
+
+func (so *sockOpt) setGroupSourceReq(c *socket.Conn, ifi *net.Interface, grp, src net.IP) error {
+ var gsr groupSourceReq
+ if ifi != nil {
+ gsr.Interface = uint32(ifi.Index)
+ }
+ gsr.setSourceGroup(grp, src)
+ var b []byte
+ if freebsd32o64 {
+ var d [sizeofGroupSourceReq + 4]byte
+ s := (*[sizeofGroupSourceReq]byte)(unsafe.Pointer(&gsr))
+ copy(d[:4], s[:4])
+ copy(d[8:], s[4:])
+ b = d[:]
+ } else {
+ b = (*[sizeofGroupSourceReq]byte)(unsafe.Pointer(&gsr))[:sizeofGroupSourceReq]
+ }
+ return so.Set(c, b)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_ssmreq_stub.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_ssmreq_stub.go
new file mode 100644
index 000000000..e6b7623d0
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_ssmreq_stub.go
@@ -0,0 +1,21 @@
+// Copyright 2014 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.
+
+// +build !darwin,!freebsd,!linux,!solaris
+
+package ipv4
+
+import (
+ "net"
+
+ "golang.org/x/net/internal/socket"
+)
+
+func (so *sockOpt) setGroupReq(c *socket.Conn, ifi *net.Interface, grp net.IP) error {
+ return errOpNoSupport
+}
+
+func (so *sockOpt) setGroupSourceReq(c *socket.Conn, ifi *net.Interface, grp, src net.IP) error {
+ return errOpNoSupport
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_stub.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_stub.go
new file mode 100644
index 000000000..4f076473b
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_stub.go
@@ -0,0 +1,13 @@
+// Copyright 2014 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.
+
+// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows
+
+package ipv4
+
+var (
+ ctlOpts = [ctlMax]ctlOpt{}
+
+ sockOpts = map[int]*sockOpt{}
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_windows.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_windows.go
new file mode 100644
index 000000000..b0913d539
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/sys_windows.go
@@ -0,0 +1,67 @@
+// Copyright 2014 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 ipv4
+
+import (
+ "golang.org/x/net/internal/iana"
+ "golang.org/x/net/internal/socket"
+)
+
+const (
+ // See ws2tcpip.h.
+ sysIP_OPTIONS = 0x1
+ sysIP_HDRINCL = 0x2
+ sysIP_TOS = 0x3
+ sysIP_TTL = 0x4
+ sysIP_MULTICAST_IF = 0x9
+ sysIP_MULTICAST_TTL = 0xa
+ sysIP_MULTICAST_LOOP = 0xb
+ sysIP_ADD_MEMBERSHIP = 0xc
+ sysIP_DROP_MEMBERSHIP = 0xd
+ sysIP_DONTFRAGMENT = 0xe
+ sysIP_ADD_SOURCE_MEMBERSHIP = 0xf
+ sysIP_DROP_SOURCE_MEMBERSHIP = 0x10
+ sysIP_PKTINFO = 0x13
+
+ sizeofInetPktinfo = 0x8
+ sizeofIPMreq = 0x8
+ sizeofIPMreqSource = 0xc
+)
+
+type inetPktinfo struct {
+ Addr [4]byte
+ Ifindex int32
+}
+
+type ipMreq struct {
+ Multiaddr [4]byte
+ Interface [4]byte
+}
+
+type ipMreqSource struct {
+ Multiaddr [4]byte
+ Sourceaddr [4]byte
+ Interface [4]byte
+}
+
+// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms738586(v=vs.85).aspx
+var (
+ ctlOpts = [ctlMax]ctlOpt{}
+
+ sockOpts = map[int]*sockOpt{
+ ssoTOS: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_TOS, Len: 4}},
+ ssoTTL: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_TTL, Len: 4}},
+ ssoMulticastTTL: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_TTL, Len: 4}},
+ ssoMulticastInterface: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_IF, Len: 4}},
+ ssoMulticastLoopback: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_LOOP, Len: 4}},
+ ssoHeaderPrepend: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_HDRINCL, Len: 4}},
+ ssoJoinGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_ADD_MEMBERSHIP, Len: sizeofIPMreq}, typ: ssoTypeIPMreq},
+ ssoLeaveGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_DROP_MEMBERSHIP, Len: sizeofIPMreq}, typ: ssoTypeIPMreq},
+ }
+)
+
+func (pi *inetPktinfo) setIfindex(i int) {
+ pi.Ifindex = int32(i)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/unicast_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/unicast_test.go
new file mode 100644
index 000000000..02c089f00
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/unicast_test.go
@@ -0,0 +1,247 @@
+// Copyright 2012 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 ipv4_test
+
+import (
+ "bytes"
+ "net"
+ "os"
+ "runtime"
+ "testing"
+ "time"
+
+ "golang.org/x/net/icmp"
+ "golang.org/x/net/internal/iana"
+ "golang.org/x/net/internal/nettest"
+ "golang.org/x/net/ipv4"
+)
+
+func TestPacketConnReadWriteUnicastUDP(t *testing.T) {
+ switch runtime.GOOS {
+ case "nacl", "plan9", "windows":
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+ ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback)
+ if ifi == nil {
+ t.Skipf("not available on %s", runtime.GOOS)
+ }
+
+ c, err := nettest.NewLocalPacketListener("udp4")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer c.Close()
+ p := ipv4.NewPacketConn(c)
+ defer p.Close()
+
+ dst := c.LocalAddr()
+ cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface
+ wb := []byte("HELLO-R-U-THERE")
+
+ for i, toggle := range []bool{true, false, true} {
+ if err := p.SetControlMessage(cf, toggle); err != nil {
+ if nettest.ProtocolNotSupported(err) {
+ t.Logf("not supported on %s", runtime.GOOS)
+ continue
+ }
+ t.Fatal(err)
+ }
+ p.SetTTL(i + 1)
+ if err := p.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
+ t.Fatal(err)
+ }
+ if n, err := p.WriteTo(wb, nil, dst); err != nil {
+ t.Fatal(err)
+ } else if n != len(wb) {
+ t.Fatalf("got %v; want %v", n, len(wb))
+ }
+ rb := make([]byte, 128)
+ if err := p.SetReadDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
+ t.Fatal(err)
+ }
+ if n, _, _, err := p.ReadFrom(rb); err != nil {
+ t.Fatal(err)
+ } else if !bytes.Equal(rb[:n], wb) {
+ t.Fatalf("got %v; want %v", rb[:n], wb)
+ }
+ }
+}
+
+func TestPacketConnReadWriteUnicastICMP(t *testing.T) {
+ switch runtime.GOOS {
+ case "nacl", "plan9", "windows":
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+ if m, ok := nettest.SupportsRawIPSocket(); !ok {
+ t.Skip(m)
+ }
+ ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback)
+ if ifi == nil {
+ t.Skipf("not available on %s", runtime.GOOS)
+ }
+
+ c, err := net.ListenPacket("ip4:icmp", "0.0.0.0")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer c.Close()
+
+ dst, err := net.ResolveIPAddr("ip4", "127.0.0.1")
+ if err != nil {
+ t.Fatal(err)
+ }
+ p := ipv4.NewPacketConn(c)
+ defer p.Close()
+ cf := ipv4.FlagDst | ipv4.FlagInterface
+ if runtime.GOOS != "solaris" {
+ // Solaris never allows to modify ICMP properties.
+ cf |= ipv4.FlagTTL
+ }
+
+ for i, toggle := range []bool{true, false, true} {
+ wb, err := (&icmp.Message{
+ Type: ipv4.ICMPTypeEcho, Code: 0,
+ Body: &icmp.Echo{
+ ID: os.Getpid() & 0xffff, Seq: i + 1,
+ Data: []byte("HELLO-R-U-THERE"),
+ },
+ }).Marshal(nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := p.SetControlMessage(cf, toggle); err != nil {
+ if nettest.ProtocolNotSupported(err) {
+ t.Logf("not supported on %s", runtime.GOOS)
+ continue
+ }
+ t.Fatal(err)
+ }
+ p.SetTTL(i + 1)
+ if err := p.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
+ t.Fatal(err)
+ }
+ if n, err := p.WriteTo(wb, nil, dst); err != nil {
+ t.Fatal(err)
+ } else if n != len(wb) {
+ t.Fatalf("got %v; want %v", n, len(wb))
+ }
+ rb := make([]byte, 128)
+ loop:
+ if err := p.SetReadDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
+ t.Fatal(err)
+ }
+ if n, _, _, err := p.ReadFrom(rb); err != nil {
+ switch runtime.GOOS {
+ case "darwin": // older darwin kernels have some limitation on receiving icmp packet through raw socket
+ t.Logf("not supported on %s", runtime.GOOS)
+ continue
+ }
+ t.Fatal(err)
+ } else {
+ m, err := icmp.ParseMessage(iana.ProtocolICMP, rb[:n])
+ if err != nil {
+ t.Fatal(err)
+ }
+ if runtime.GOOS == "linux" && m.Type == ipv4.ICMPTypeEcho {
+ // On Linux we must handle own sent packets.
+ goto loop
+ }
+ if m.Type != ipv4.ICMPTypeEchoReply || m.Code != 0 {
+ t.Fatalf("got type=%v, code=%v; want type=%v, code=%v", m.Type, m.Code, ipv4.ICMPTypeEchoReply, 0)
+ }
+ }
+ }
+}
+
+func TestRawConnReadWriteUnicastICMP(t *testing.T) {
+ switch runtime.GOOS {
+ case "nacl", "plan9", "windows":
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+ if m, ok := nettest.SupportsRawIPSocket(); !ok {
+ t.Skip(m)
+ }
+ ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback)
+ if ifi == nil {
+ t.Skipf("not available on %s", runtime.GOOS)
+ }
+
+ c, err := net.ListenPacket("ip4:icmp", "0.0.0.0")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer c.Close()
+
+ dst, err := net.ResolveIPAddr("ip4", "127.0.0.1")
+ if err != nil {
+ t.Fatal(err)
+ }
+ r, err := ipv4.NewRawConn(c)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer r.Close()
+ cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface
+
+ for i, toggle := range []bool{true, false, true} {
+ wb, err := (&icmp.Message{
+ Type: ipv4.ICMPTypeEcho, Code: 0,
+ Body: &icmp.Echo{
+ ID: os.Getpid() & 0xffff, Seq: i + 1,
+ Data: []byte("HELLO-R-U-THERE"),
+ },
+ }).Marshal(nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ wh := &ipv4.Header{
+ Version: ipv4.Version,
+ Len: ipv4.HeaderLen,
+ TOS: i + 1,
+ TotalLen: ipv4.HeaderLen + len(wb),
+ TTL: i + 1,
+ Protocol: 1,
+ Dst: dst.IP,
+ }
+ if err := r.SetControlMessage(cf, toggle); err != nil {
+ if nettest.ProtocolNotSupported(err) {
+ t.Logf("not supported on %s", runtime.GOOS)
+ continue
+ }
+ t.Fatal(err)
+ }
+ if err := r.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
+ t.Fatal(err)
+ }
+ if err := r.WriteTo(wh, wb, nil); err != nil {
+ t.Fatal(err)
+ }
+ rb := make([]byte, ipv4.HeaderLen+128)
+ loop:
+ if err := r.SetReadDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
+ t.Fatal(err)
+ }
+ if _, b, _, err := r.ReadFrom(rb); err != nil {
+ switch runtime.GOOS {
+ case "darwin": // older darwin kernels have some limitation on receiving icmp packet through raw socket
+ t.Logf("not supported on %s", runtime.GOOS)
+ continue
+ }
+ t.Fatal(err)
+ } else {
+ m, err := icmp.ParseMessage(iana.ProtocolICMP, b)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if runtime.GOOS == "linux" && m.Type == ipv4.ICMPTypeEcho {
+ // On Linux we must handle own sent packets.
+ goto loop
+ }
+ if m.Type != ipv4.ICMPTypeEchoReply || m.Code != 0 {
+ t.Fatalf("got type=%v, code=%v; want type=%v, code=%v", m.Type, m.Code, ipv4.ICMPTypeEchoReply, 0)
+ }
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/unicastsockopt_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/unicastsockopt_test.go
new file mode 100644
index 000000000..db5213b91
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/unicastsockopt_test.go
@@ -0,0 +1,148 @@
+// Copyright 2012 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 ipv4_test
+
+import (
+ "net"
+ "runtime"
+ "testing"
+
+ "golang.org/x/net/internal/iana"
+ "golang.org/x/net/internal/nettest"
+ "golang.org/x/net/ipv4"
+)
+
+func TestConnUnicastSocketOptions(t *testing.T) {
+ switch runtime.GOOS {
+ case "nacl", "plan9", "windows":
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+ ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback)
+ if ifi == nil {
+ t.Skipf("not available on %s", runtime.GOOS)
+ }
+
+ ln, err := net.Listen("tcp4", "127.0.0.1:0")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer ln.Close()
+
+ errc := make(chan error, 1)
+ go func() {
+ c, err := ln.Accept()
+ if err != nil {
+ errc <- err
+ return
+ }
+ errc <- c.Close()
+ }()
+
+ c, err := net.Dial("tcp4", ln.Addr().String())
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer c.Close()
+
+ testUnicastSocketOptions(t, ipv4.NewConn(c))
+
+ if err := <-errc; err != nil {
+ t.Errorf("server: %v", err)
+ }
+}
+
+var packetConnUnicastSocketOptionTests = []struct {
+ net, proto, addr string
+}{
+ {"udp4", "", "127.0.0.1:0"},
+ {"ip4", ":icmp", "127.0.0.1"},
+}
+
+func TestPacketConnUnicastSocketOptions(t *testing.T) {
+ switch runtime.GOOS {
+ case "nacl", "plan9", "windows":
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+ ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback)
+ if ifi == nil {
+ t.Skipf("not available on %s", runtime.GOOS)
+ }
+
+ m, ok := nettest.SupportsRawIPSocket()
+ for _, tt := range packetConnUnicastSocketOptionTests {
+ if tt.net == "ip4" && !ok {
+ t.Log(m)
+ continue
+ }
+ c, err := net.ListenPacket(tt.net+tt.proto, tt.addr)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer c.Close()
+
+ testUnicastSocketOptions(t, ipv4.NewPacketConn(c))
+ }
+}
+
+func TestRawConnUnicastSocketOptions(t *testing.T) {
+ switch runtime.GOOS {
+ case "nacl", "plan9", "windows":
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+ if m, ok := nettest.SupportsRawIPSocket(); !ok {
+ t.Skip(m)
+ }
+ ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback)
+ if ifi == nil {
+ t.Skipf("not available on %s", runtime.GOOS)
+ }
+
+ c, err := net.ListenPacket("ip4:icmp", "127.0.0.1")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer c.Close()
+
+ r, err := ipv4.NewRawConn(c)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ testUnicastSocketOptions(t, r)
+}
+
+type testIPv4UnicastConn interface {
+ TOS() (int, error)
+ SetTOS(int) error
+ TTL() (int, error)
+ SetTTL(int) error
+}
+
+func testUnicastSocketOptions(t *testing.T, c testIPv4UnicastConn) {
+ tos := iana.DiffServCS0 | iana.NotECNTransport
+ switch runtime.GOOS {
+ case "windows":
+ // IP_TOS option is supported on Windows 8 and beyond.
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+
+ if err := c.SetTOS(tos); err != nil {
+ t.Fatal(err)
+ }
+ if v, err := c.TOS(); err != nil {
+ t.Fatal(err)
+ } else if v != tos {
+ t.Fatalf("got %v; want %v", v, tos)
+ }
+ const ttl = 255
+ if err := c.SetTTL(ttl); err != nil {
+ t.Fatal(err)
+ }
+ if v, err := c.TTL(); err != nil {
+ t.Fatal(err)
+ } else if v != ttl {
+ t.Fatalf("got %v; want %v", v, ttl)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_darwin.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_darwin.go
new file mode 100644
index 000000000..c07cc883f
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_darwin.go
@@ -0,0 +1,99 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_darwin.go
+
+package ipv4
+
+const (
+ sysIP_OPTIONS = 0x1
+ sysIP_HDRINCL = 0x2
+ sysIP_TOS = 0x3
+ sysIP_TTL = 0x4
+ sysIP_RECVOPTS = 0x5
+ sysIP_RECVRETOPTS = 0x6
+ sysIP_RECVDSTADDR = 0x7
+ sysIP_RETOPTS = 0x8
+ sysIP_RECVIF = 0x14
+ sysIP_STRIPHDR = 0x17
+ sysIP_RECVTTL = 0x18
+ sysIP_BOUND_IF = 0x19
+ sysIP_PKTINFO = 0x1a
+ sysIP_RECVPKTINFO = 0x1a
+
+ sysIP_MULTICAST_IF = 0x9
+ sysIP_MULTICAST_TTL = 0xa
+ sysIP_MULTICAST_LOOP = 0xb
+ sysIP_ADD_MEMBERSHIP = 0xc
+ sysIP_DROP_MEMBERSHIP = 0xd
+ sysIP_MULTICAST_VIF = 0xe
+ sysIP_MULTICAST_IFINDEX = 0x42
+ sysIP_ADD_SOURCE_MEMBERSHIP = 0x46
+ sysIP_DROP_SOURCE_MEMBERSHIP = 0x47
+ sysIP_BLOCK_SOURCE = 0x48
+ sysIP_UNBLOCK_SOURCE = 0x49
+ sysMCAST_JOIN_GROUP = 0x50
+ sysMCAST_LEAVE_GROUP = 0x51
+ sysMCAST_JOIN_SOURCE_GROUP = 0x52
+ sysMCAST_LEAVE_SOURCE_GROUP = 0x53
+ sysMCAST_BLOCK_SOURCE = 0x54
+ sysMCAST_UNBLOCK_SOURCE = 0x55
+
+ sizeofSockaddrStorage = 0x80
+ sizeofSockaddrInet = 0x10
+ sizeofInetPktinfo = 0xc
+
+ sizeofIPMreq = 0x8
+ sizeofIPMreqn = 0xc
+ sizeofIPMreqSource = 0xc
+ sizeofGroupReq = 0x84
+ sizeofGroupSourceReq = 0x104
+)
+
+type sockaddrStorage struct {
+ Len uint8
+ Family uint8
+ X__ss_pad1 [6]int8
+ X__ss_align int64
+ X__ss_pad2 [112]int8
+}
+
+type sockaddrInet struct {
+ Len uint8
+ Family uint8
+ Port uint16
+ Addr [4]byte /* in_addr */
+ Zero [8]int8
+}
+
+type inetPktinfo struct {
+ Ifindex uint32
+ Spec_dst [4]byte /* in_addr */
+ Addr [4]byte /* in_addr */
+}
+
+type ipMreq struct {
+ Multiaddr [4]byte /* in_addr */
+ Interface [4]byte /* in_addr */
+}
+
+type ipMreqn struct {
+ Multiaddr [4]byte /* in_addr */
+ Address [4]byte /* in_addr */
+ Ifindex int32
+}
+
+type ipMreqSource struct {
+ Multiaddr [4]byte /* in_addr */
+ Sourceaddr [4]byte /* in_addr */
+ Interface [4]byte /* in_addr */
+}
+
+type groupReq struct {
+ Interface uint32
+ Pad_cgo_0 [128]byte
+}
+
+type groupSourceReq struct {
+ Interface uint32
+ Pad_cgo_0 [128]byte
+ Pad_cgo_1 [128]byte
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_dragonfly.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_dragonfly.go
new file mode 100644
index 000000000..c4365e9e7
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_dragonfly.go
@@ -0,0 +1,31 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_dragonfly.go
+
+package ipv4
+
+const (
+ sysIP_OPTIONS = 0x1
+ sysIP_HDRINCL = 0x2
+ sysIP_TOS = 0x3
+ sysIP_TTL = 0x4
+ sysIP_RECVOPTS = 0x5
+ sysIP_RECVRETOPTS = 0x6
+ sysIP_RECVDSTADDR = 0x7
+ sysIP_RETOPTS = 0x8
+ sysIP_RECVIF = 0x14
+ sysIP_RECVTTL = 0x41
+
+ sysIP_MULTICAST_IF = 0x9
+ sysIP_MULTICAST_TTL = 0xa
+ sysIP_MULTICAST_LOOP = 0xb
+ sysIP_MULTICAST_VIF = 0xe
+ sysIP_ADD_MEMBERSHIP = 0xc
+ sysIP_DROP_MEMBERSHIP = 0xd
+
+ sizeofIPMreq = 0x8
+)
+
+type ipMreq struct {
+ Multiaddr [4]byte /* in_addr */
+ Interface [4]byte /* in_addr */
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_freebsd_386.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_freebsd_386.go
new file mode 100644
index 000000000..8c4aec94c
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_freebsd_386.go
@@ -0,0 +1,93 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_freebsd.go
+
+package ipv4
+
+const (
+ sysIP_OPTIONS = 0x1
+ sysIP_HDRINCL = 0x2
+ sysIP_TOS = 0x3
+ sysIP_TTL = 0x4
+ sysIP_RECVOPTS = 0x5
+ sysIP_RECVRETOPTS = 0x6
+ sysIP_RECVDSTADDR = 0x7
+ sysIP_SENDSRCADDR = 0x7
+ sysIP_RETOPTS = 0x8
+ sysIP_RECVIF = 0x14
+ sysIP_ONESBCAST = 0x17
+ sysIP_BINDANY = 0x18
+ sysIP_RECVTTL = 0x41
+ sysIP_MINTTL = 0x42
+ sysIP_DONTFRAG = 0x43
+ sysIP_RECVTOS = 0x44
+
+ sysIP_MULTICAST_IF = 0x9
+ sysIP_MULTICAST_TTL = 0xa
+ sysIP_MULTICAST_LOOP = 0xb
+ sysIP_ADD_MEMBERSHIP = 0xc
+ sysIP_DROP_MEMBERSHIP = 0xd
+ sysIP_MULTICAST_VIF = 0xe
+ sysIP_ADD_SOURCE_MEMBERSHIP = 0x46
+ sysIP_DROP_SOURCE_MEMBERSHIP = 0x47
+ sysIP_BLOCK_SOURCE = 0x48
+ sysIP_UNBLOCK_SOURCE = 0x49
+ sysMCAST_JOIN_GROUP = 0x50
+ sysMCAST_LEAVE_GROUP = 0x51
+ sysMCAST_JOIN_SOURCE_GROUP = 0x52
+ sysMCAST_LEAVE_SOURCE_GROUP = 0x53
+ sysMCAST_BLOCK_SOURCE = 0x54
+ sysMCAST_UNBLOCK_SOURCE = 0x55
+
+ sizeofSockaddrStorage = 0x80
+ sizeofSockaddrInet = 0x10
+
+ sizeofIPMreq = 0x8
+ sizeofIPMreqn = 0xc
+ sizeofIPMreqSource = 0xc
+ sizeofGroupReq = 0x84
+ sizeofGroupSourceReq = 0x104
+)
+
+type sockaddrStorage struct {
+ Len uint8
+ Family uint8
+ X__ss_pad1 [6]int8
+ X__ss_align int64
+ X__ss_pad2 [112]int8
+}
+
+type sockaddrInet struct {
+ Len uint8
+ Family uint8
+ Port uint16
+ Addr [4]byte /* in_addr */
+ Zero [8]int8
+}
+
+type ipMreq struct {
+ Multiaddr [4]byte /* in_addr */
+ Interface [4]byte /* in_addr */
+}
+
+type ipMreqn struct {
+ Multiaddr [4]byte /* in_addr */
+ Address [4]byte /* in_addr */
+ Ifindex int32
+}
+
+type ipMreqSource struct {
+ Multiaddr [4]byte /* in_addr */
+ Sourceaddr [4]byte /* in_addr */
+ Interface [4]byte /* in_addr */
+}
+
+type groupReq struct {
+ Interface uint32
+ Group sockaddrStorage
+}
+
+type groupSourceReq struct {
+ Interface uint32
+ Group sockaddrStorage
+ Source sockaddrStorage
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_freebsd_amd64.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_freebsd_amd64.go
new file mode 100644
index 000000000..4b10b7c57
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_freebsd_amd64.go
@@ -0,0 +1,95 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_freebsd.go
+
+package ipv4
+
+const (
+ sysIP_OPTIONS = 0x1
+ sysIP_HDRINCL = 0x2
+ sysIP_TOS = 0x3
+ sysIP_TTL = 0x4
+ sysIP_RECVOPTS = 0x5
+ sysIP_RECVRETOPTS = 0x6
+ sysIP_RECVDSTADDR = 0x7
+ sysIP_SENDSRCADDR = 0x7
+ sysIP_RETOPTS = 0x8
+ sysIP_RECVIF = 0x14
+ sysIP_ONESBCAST = 0x17
+ sysIP_BINDANY = 0x18
+ sysIP_RECVTTL = 0x41
+ sysIP_MINTTL = 0x42
+ sysIP_DONTFRAG = 0x43
+ sysIP_RECVTOS = 0x44
+
+ sysIP_MULTICAST_IF = 0x9
+ sysIP_MULTICAST_TTL = 0xa
+ sysIP_MULTICAST_LOOP = 0xb
+ sysIP_ADD_MEMBERSHIP = 0xc
+ sysIP_DROP_MEMBERSHIP = 0xd
+ sysIP_MULTICAST_VIF = 0xe
+ sysIP_ADD_SOURCE_MEMBERSHIP = 0x46
+ sysIP_DROP_SOURCE_MEMBERSHIP = 0x47
+ sysIP_BLOCK_SOURCE = 0x48
+ sysIP_UNBLOCK_SOURCE = 0x49
+ sysMCAST_JOIN_GROUP = 0x50
+ sysMCAST_LEAVE_GROUP = 0x51
+ sysMCAST_JOIN_SOURCE_GROUP = 0x52
+ sysMCAST_LEAVE_SOURCE_GROUP = 0x53
+ sysMCAST_BLOCK_SOURCE = 0x54
+ sysMCAST_UNBLOCK_SOURCE = 0x55
+
+ sizeofSockaddrStorage = 0x80
+ sizeofSockaddrInet = 0x10
+
+ sizeofIPMreq = 0x8
+ sizeofIPMreqn = 0xc
+ sizeofIPMreqSource = 0xc
+ sizeofGroupReq = 0x88
+ sizeofGroupSourceReq = 0x108
+)
+
+type sockaddrStorage struct {
+ Len uint8
+ Family uint8
+ X__ss_pad1 [6]int8
+ X__ss_align int64
+ X__ss_pad2 [112]int8
+}
+
+type sockaddrInet struct {
+ Len uint8
+ Family uint8
+ Port uint16
+ Addr [4]byte /* in_addr */
+ Zero [8]int8
+}
+
+type ipMreq struct {
+ Multiaddr [4]byte /* in_addr */
+ Interface [4]byte /* in_addr */
+}
+
+type ipMreqn struct {
+ Multiaddr [4]byte /* in_addr */
+ Address [4]byte /* in_addr */
+ Ifindex int32
+}
+
+type ipMreqSource struct {
+ Multiaddr [4]byte /* in_addr */
+ Sourceaddr [4]byte /* in_addr */
+ Interface [4]byte /* in_addr */
+}
+
+type groupReq struct {
+ Interface uint32
+ Pad_cgo_0 [4]byte
+ Group sockaddrStorage
+}
+
+type groupSourceReq struct {
+ Interface uint32
+ Pad_cgo_0 [4]byte
+ Group sockaddrStorage
+ Source sockaddrStorage
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_freebsd_arm.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_freebsd_arm.go
new file mode 100644
index 000000000..4b10b7c57
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_freebsd_arm.go
@@ -0,0 +1,95 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_freebsd.go
+
+package ipv4
+
+const (
+ sysIP_OPTIONS = 0x1
+ sysIP_HDRINCL = 0x2
+ sysIP_TOS = 0x3
+ sysIP_TTL = 0x4
+ sysIP_RECVOPTS = 0x5
+ sysIP_RECVRETOPTS = 0x6
+ sysIP_RECVDSTADDR = 0x7
+ sysIP_SENDSRCADDR = 0x7
+ sysIP_RETOPTS = 0x8
+ sysIP_RECVIF = 0x14
+ sysIP_ONESBCAST = 0x17
+ sysIP_BINDANY = 0x18
+ sysIP_RECVTTL = 0x41
+ sysIP_MINTTL = 0x42
+ sysIP_DONTFRAG = 0x43
+ sysIP_RECVTOS = 0x44
+
+ sysIP_MULTICAST_IF = 0x9
+ sysIP_MULTICAST_TTL = 0xa
+ sysIP_MULTICAST_LOOP = 0xb
+ sysIP_ADD_MEMBERSHIP = 0xc
+ sysIP_DROP_MEMBERSHIP = 0xd
+ sysIP_MULTICAST_VIF = 0xe
+ sysIP_ADD_SOURCE_MEMBERSHIP = 0x46
+ sysIP_DROP_SOURCE_MEMBERSHIP = 0x47
+ sysIP_BLOCK_SOURCE = 0x48
+ sysIP_UNBLOCK_SOURCE = 0x49
+ sysMCAST_JOIN_GROUP = 0x50
+ sysMCAST_LEAVE_GROUP = 0x51
+ sysMCAST_JOIN_SOURCE_GROUP = 0x52
+ sysMCAST_LEAVE_SOURCE_GROUP = 0x53
+ sysMCAST_BLOCK_SOURCE = 0x54
+ sysMCAST_UNBLOCK_SOURCE = 0x55
+
+ sizeofSockaddrStorage = 0x80
+ sizeofSockaddrInet = 0x10
+
+ sizeofIPMreq = 0x8
+ sizeofIPMreqn = 0xc
+ sizeofIPMreqSource = 0xc
+ sizeofGroupReq = 0x88
+ sizeofGroupSourceReq = 0x108
+)
+
+type sockaddrStorage struct {
+ Len uint8
+ Family uint8
+ X__ss_pad1 [6]int8
+ X__ss_align int64
+ X__ss_pad2 [112]int8
+}
+
+type sockaddrInet struct {
+ Len uint8
+ Family uint8
+ Port uint16
+ Addr [4]byte /* in_addr */
+ Zero [8]int8
+}
+
+type ipMreq struct {
+ Multiaddr [4]byte /* in_addr */
+ Interface [4]byte /* in_addr */
+}
+
+type ipMreqn struct {
+ Multiaddr [4]byte /* in_addr */
+ Address [4]byte /* in_addr */
+ Ifindex int32
+}
+
+type ipMreqSource struct {
+ Multiaddr [4]byte /* in_addr */
+ Sourceaddr [4]byte /* in_addr */
+ Interface [4]byte /* in_addr */
+}
+
+type groupReq struct {
+ Interface uint32
+ Pad_cgo_0 [4]byte
+ Group sockaddrStorage
+}
+
+type groupSourceReq struct {
+ Interface uint32
+ Pad_cgo_0 [4]byte
+ Group sockaddrStorage
+ Source sockaddrStorage
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_linux_386.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_linux_386.go
new file mode 100644
index 000000000..c0260f0ce
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_linux_386.go
@@ -0,0 +1,148 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_linux.go
+
+package ipv4
+
+const (
+ sysIP_TOS = 0x1
+ sysIP_TTL = 0x2
+ sysIP_HDRINCL = 0x3
+ sysIP_OPTIONS = 0x4
+ sysIP_ROUTER_ALERT = 0x5
+ sysIP_RECVOPTS = 0x6
+ sysIP_RETOPTS = 0x7
+ sysIP_PKTINFO = 0x8
+ sysIP_PKTOPTIONS = 0x9
+ sysIP_MTU_DISCOVER = 0xa
+ sysIP_RECVERR = 0xb
+ sysIP_RECVTTL = 0xc
+ sysIP_RECVTOS = 0xd
+ sysIP_MTU = 0xe
+ sysIP_FREEBIND = 0xf
+ sysIP_TRANSPARENT = 0x13
+ sysIP_RECVRETOPTS = 0x7
+ sysIP_ORIGDSTADDR = 0x14
+ sysIP_RECVORIGDSTADDR = 0x14
+ sysIP_MINTTL = 0x15
+ sysIP_NODEFRAG = 0x16
+ sysIP_UNICAST_IF = 0x32
+
+ sysIP_MULTICAST_IF = 0x20
+ sysIP_MULTICAST_TTL = 0x21
+ sysIP_MULTICAST_LOOP = 0x22
+ sysIP_ADD_MEMBERSHIP = 0x23
+ sysIP_DROP_MEMBERSHIP = 0x24
+ sysIP_UNBLOCK_SOURCE = 0x25
+ sysIP_BLOCK_SOURCE = 0x26
+ sysIP_ADD_SOURCE_MEMBERSHIP = 0x27
+ sysIP_DROP_SOURCE_MEMBERSHIP = 0x28
+ sysIP_MSFILTER = 0x29
+ sysMCAST_JOIN_GROUP = 0x2a
+ sysMCAST_LEAVE_GROUP = 0x2d
+ sysMCAST_JOIN_SOURCE_GROUP = 0x2e
+ sysMCAST_LEAVE_SOURCE_GROUP = 0x2f
+ sysMCAST_BLOCK_SOURCE = 0x2b
+ sysMCAST_UNBLOCK_SOURCE = 0x2c
+ sysMCAST_MSFILTER = 0x30
+ sysIP_MULTICAST_ALL = 0x31
+
+ sysICMP_FILTER = 0x1
+
+ sysSO_EE_ORIGIN_NONE = 0x0
+ sysSO_EE_ORIGIN_LOCAL = 0x1
+ sysSO_EE_ORIGIN_ICMP = 0x2
+ sysSO_EE_ORIGIN_ICMP6 = 0x3
+ sysSO_EE_ORIGIN_TXSTATUS = 0x4
+ sysSO_EE_ORIGIN_TIMESTAMPING = 0x4
+
+ sysSOL_SOCKET = 0x1
+ sysSO_ATTACH_FILTER = 0x1a
+
+ sizeofKernelSockaddrStorage = 0x80
+ sizeofSockaddrInet = 0x10
+ sizeofInetPktinfo = 0xc
+ sizeofSockExtendedErr = 0x10
+
+ sizeofIPMreq = 0x8
+ sizeofIPMreqn = 0xc
+ sizeofIPMreqSource = 0xc
+ sizeofGroupReq = 0x84
+ sizeofGroupSourceReq = 0x104
+
+ sizeofICMPFilter = 0x4
+
+ sizeofSockFprog = 0x8
+)
+
+type kernelSockaddrStorage struct {
+ Family uint16
+ X__data [126]int8
+}
+
+type sockaddrInet struct {
+ Family uint16
+ Port uint16
+ Addr [4]byte /* in_addr */
+ X__pad [8]uint8
+}
+
+type inetPktinfo struct {
+ Ifindex int32
+ Spec_dst [4]byte /* in_addr */
+ Addr [4]byte /* in_addr */
+}
+
+type sockExtendedErr struct {
+ Errno uint32
+ Origin uint8
+ Type uint8
+ Code uint8
+ Pad uint8
+ Info uint32
+ Data uint32
+}
+
+type ipMreq struct {
+ Multiaddr [4]byte /* in_addr */
+ Interface [4]byte /* in_addr */
+}
+
+type ipMreqn struct {
+ Multiaddr [4]byte /* in_addr */
+ Address [4]byte /* in_addr */
+ Ifindex int32
+}
+
+type ipMreqSource struct {
+ Multiaddr uint32
+ Interface uint32
+ Sourceaddr uint32
+}
+
+type groupReq struct {
+ Interface uint32
+ Group kernelSockaddrStorage
+}
+
+type groupSourceReq struct {
+ Interface uint32
+ Group kernelSockaddrStorage
+ Source kernelSockaddrStorage
+}
+
+type icmpFilter struct {
+ Data uint32
+}
+
+type sockFProg struct {
+ Len uint16
+ Pad_cgo_0 [2]byte
+ Filter *sockFilter
+}
+
+type sockFilter struct {
+ Code uint16
+ Jt uint8
+ Jf uint8
+ K uint32
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_linux_amd64.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_linux_amd64.go
new file mode 100644
index 000000000..9c967eaa6
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_linux_amd64.go
@@ -0,0 +1,150 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_linux.go
+
+package ipv4
+
+const (
+ sysIP_TOS = 0x1
+ sysIP_TTL = 0x2
+ sysIP_HDRINCL = 0x3
+ sysIP_OPTIONS = 0x4
+ sysIP_ROUTER_ALERT = 0x5
+ sysIP_RECVOPTS = 0x6
+ sysIP_RETOPTS = 0x7
+ sysIP_PKTINFO = 0x8
+ sysIP_PKTOPTIONS = 0x9
+ sysIP_MTU_DISCOVER = 0xa
+ sysIP_RECVERR = 0xb
+ sysIP_RECVTTL = 0xc
+ sysIP_RECVTOS = 0xd
+ sysIP_MTU = 0xe
+ sysIP_FREEBIND = 0xf
+ sysIP_TRANSPARENT = 0x13
+ sysIP_RECVRETOPTS = 0x7
+ sysIP_ORIGDSTADDR = 0x14
+ sysIP_RECVORIGDSTADDR = 0x14
+ sysIP_MINTTL = 0x15
+ sysIP_NODEFRAG = 0x16
+ sysIP_UNICAST_IF = 0x32
+
+ sysIP_MULTICAST_IF = 0x20
+ sysIP_MULTICAST_TTL = 0x21
+ sysIP_MULTICAST_LOOP = 0x22
+ sysIP_ADD_MEMBERSHIP = 0x23
+ sysIP_DROP_MEMBERSHIP = 0x24
+ sysIP_UNBLOCK_SOURCE = 0x25
+ sysIP_BLOCK_SOURCE = 0x26
+ sysIP_ADD_SOURCE_MEMBERSHIP = 0x27
+ sysIP_DROP_SOURCE_MEMBERSHIP = 0x28
+ sysIP_MSFILTER = 0x29
+ sysMCAST_JOIN_GROUP = 0x2a
+ sysMCAST_LEAVE_GROUP = 0x2d
+ sysMCAST_JOIN_SOURCE_GROUP = 0x2e
+ sysMCAST_LEAVE_SOURCE_GROUP = 0x2f
+ sysMCAST_BLOCK_SOURCE = 0x2b
+ sysMCAST_UNBLOCK_SOURCE = 0x2c
+ sysMCAST_MSFILTER = 0x30
+ sysIP_MULTICAST_ALL = 0x31
+
+ sysICMP_FILTER = 0x1
+
+ sysSO_EE_ORIGIN_NONE = 0x0
+ sysSO_EE_ORIGIN_LOCAL = 0x1
+ sysSO_EE_ORIGIN_ICMP = 0x2
+ sysSO_EE_ORIGIN_ICMP6 = 0x3
+ sysSO_EE_ORIGIN_TXSTATUS = 0x4
+ sysSO_EE_ORIGIN_TIMESTAMPING = 0x4
+
+ sysSOL_SOCKET = 0x1
+ sysSO_ATTACH_FILTER = 0x1a
+
+ sizeofKernelSockaddrStorage = 0x80
+ sizeofSockaddrInet = 0x10
+ sizeofInetPktinfo = 0xc
+ sizeofSockExtendedErr = 0x10
+
+ sizeofIPMreq = 0x8
+ sizeofIPMreqn = 0xc
+ sizeofIPMreqSource = 0xc
+ sizeofGroupReq = 0x88
+ sizeofGroupSourceReq = 0x108
+
+ sizeofICMPFilter = 0x4
+
+ sizeofSockFprog = 0x10
+)
+
+type kernelSockaddrStorage struct {
+ Family uint16
+ X__data [126]int8
+}
+
+type sockaddrInet struct {
+ Family uint16
+ Port uint16
+ Addr [4]byte /* in_addr */
+ X__pad [8]uint8
+}
+
+type inetPktinfo struct {
+ Ifindex int32
+ Spec_dst [4]byte /* in_addr */
+ Addr [4]byte /* in_addr */
+}
+
+type sockExtendedErr struct {
+ Errno uint32
+ Origin uint8
+ Type uint8
+ Code uint8
+ Pad uint8
+ Info uint32
+ Data uint32
+}
+
+type ipMreq struct {
+ Multiaddr [4]byte /* in_addr */
+ Interface [4]byte /* in_addr */
+}
+
+type ipMreqn struct {
+ Multiaddr [4]byte /* in_addr */
+ Address [4]byte /* in_addr */
+ Ifindex int32
+}
+
+type ipMreqSource struct {
+ Multiaddr uint32
+ Interface uint32
+ Sourceaddr uint32
+}
+
+type groupReq struct {
+ Interface uint32
+ Pad_cgo_0 [4]byte
+ Group kernelSockaddrStorage
+}
+
+type groupSourceReq struct {
+ Interface uint32
+ Pad_cgo_0 [4]byte
+ Group kernelSockaddrStorage
+ Source kernelSockaddrStorage
+}
+
+type icmpFilter struct {
+ Data uint32
+}
+
+type sockFProg struct {
+ Len uint16
+ Pad_cgo_0 [6]byte
+ Filter *sockFilter
+}
+
+type sockFilter struct {
+ Code uint16
+ Jt uint8
+ Jf uint8
+ K uint32
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_linux_arm.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_linux_arm.go
new file mode 100644
index 000000000..c0260f0ce
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_linux_arm.go
@@ -0,0 +1,148 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_linux.go
+
+package ipv4
+
+const (
+ sysIP_TOS = 0x1
+ sysIP_TTL = 0x2
+ sysIP_HDRINCL = 0x3
+ sysIP_OPTIONS = 0x4
+ sysIP_ROUTER_ALERT = 0x5
+ sysIP_RECVOPTS = 0x6
+ sysIP_RETOPTS = 0x7
+ sysIP_PKTINFO = 0x8
+ sysIP_PKTOPTIONS = 0x9
+ sysIP_MTU_DISCOVER = 0xa
+ sysIP_RECVERR = 0xb
+ sysIP_RECVTTL = 0xc
+ sysIP_RECVTOS = 0xd
+ sysIP_MTU = 0xe
+ sysIP_FREEBIND = 0xf
+ sysIP_TRANSPARENT = 0x13
+ sysIP_RECVRETOPTS = 0x7
+ sysIP_ORIGDSTADDR = 0x14
+ sysIP_RECVORIGDSTADDR = 0x14
+ sysIP_MINTTL = 0x15
+ sysIP_NODEFRAG = 0x16
+ sysIP_UNICAST_IF = 0x32
+
+ sysIP_MULTICAST_IF = 0x20
+ sysIP_MULTICAST_TTL = 0x21
+ sysIP_MULTICAST_LOOP = 0x22
+ sysIP_ADD_MEMBERSHIP = 0x23
+ sysIP_DROP_MEMBERSHIP = 0x24
+ sysIP_UNBLOCK_SOURCE = 0x25
+ sysIP_BLOCK_SOURCE = 0x26
+ sysIP_ADD_SOURCE_MEMBERSHIP = 0x27
+ sysIP_DROP_SOURCE_MEMBERSHIP = 0x28
+ sysIP_MSFILTER = 0x29
+ sysMCAST_JOIN_GROUP = 0x2a
+ sysMCAST_LEAVE_GROUP = 0x2d
+ sysMCAST_JOIN_SOURCE_GROUP = 0x2e
+ sysMCAST_LEAVE_SOURCE_GROUP = 0x2f
+ sysMCAST_BLOCK_SOURCE = 0x2b
+ sysMCAST_UNBLOCK_SOURCE = 0x2c
+ sysMCAST_MSFILTER = 0x30
+ sysIP_MULTICAST_ALL = 0x31
+
+ sysICMP_FILTER = 0x1
+
+ sysSO_EE_ORIGIN_NONE = 0x0
+ sysSO_EE_ORIGIN_LOCAL = 0x1
+ sysSO_EE_ORIGIN_ICMP = 0x2
+ sysSO_EE_ORIGIN_ICMP6 = 0x3
+ sysSO_EE_ORIGIN_TXSTATUS = 0x4
+ sysSO_EE_ORIGIN_TIMESTAMPING = 0x4
+
+ sysSOL_SOCKET = 0x1
+ sysSO_ATTACH_FILTER = 0x1a
+
+ sizeofKernelSockaddrStorage = 0x80
+ sizeofSockaddrInet = 0x10
+ sizeofInetPktinfo = 0xc
+ sizeofSockExtendedErr = 0x10
+
+ sizeofIPMreq = 0x8
+ sizeofIPMreqn = 0xc
+ sizeofIPMreqSource = 0xc
+ sizeofGroupReq = 0x84
+ sizeofGroupSourceReq = 0x104
+
+ sizeofICMPFilter = 0x4
+
+ sizeofSockFprog = 0x8
+)
+
+type kernelSockaddrStorage struct {
+ Family uint16
+ X__data [126]int8
+}
+
+type sockaddrInet struct {
+ Family uint16
+ Port uint16
+ Addr [4]byte /* in_addr */
+ X__pad [8]uint8
+}
+
+type inetPktinfo struct {
+ Ifindex int32
+ Spec_dst [4]byte /* in_addr */
+ Addr [4]byte /* in_addr */
+}
+
+type sockExtendedErr struct {
+ Errno uint32
+ Origin uint8
+ Type uint8
+ Code uint8
+ Pad uint8
+ Info uint32
+ Data uint32
+}
+
+type ipMreq struct {
+ Multiaddr [4]byte /* in_addr */
+ Interface [4]byte /* in_addr */
+}
+
+type ipMreqn struct {
+ Multiaddr [4]byte /* in_addr */
+ Address [4]byte /* in_addr */
+ Ifindex int32
+}
+
+type ipMreqSource struct {
+ Multiaddr uint32
+ Interface uint32
+ Sourceaddr uint32
+}
+
+type groupReq struct {
+ Interface uint32
+ Group kernelSockaddrStorage
+}
+
+type groupSourceReq struct {
+ Interface uint32
+ Group kernelSockaddrStorage
+ Source kernelSockaddrStorage
+}
+
+type icmpFilter struct {
+ Data uint32
+}
+
+type sockFProg struct {
+ Len uint16
+ Pad_cgo_0 [2]byte
+ Filter *sockFilter
+}
+
+type sockFilter struct {
+ Code uint16
+ Jt uint8
+ Jf uint8
+ K uint32
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_linux_arm64.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_linux_arm64.go
new file mode 100644
index 000000000..9c967eaa6
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_linux_arm64.go
@@ -0,0 +1,150 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_linux.go
+
+package ipv4
+
+const (
+ sysIP_TOS = 0x1
+ sysIP_TTL = 0x2
+ sysIP_HDRINCL = 0x3
+ sysIP_OPTIONS = 0x4
+ sysIP_ROUTER_ALERT = 0x5
+ sysIP_RECVOPTS = 0x6
+ sysIP_RETOPTS = 0x7
+ sysIP_PKTINFO = 0x8
+ sysIP_PKTOPTIONS = 0x9
+ sysIP_MTU_DISCOVER = 0xa
+ sysIP_RECVERR = 0xb
+ sysIP_RECVTTL = 0xc
+ sysIP_RECVTOS = 0xd
+ sysIP_MTU = 0xe
+ sysIP_FREEBIND = 0xf
+ sysIP_TRANSPARENT = 0x13
+ sysIP_RECVRETOPTS = 0x7
+ sysIP_ORIGDSTADDR = 0x14
+ sysIP_RECVORIGDSTADDR = 0x14
+ sysIP_MINTTL = 0x15
+ sysIP_NODEFRAG = 0x16
+ sysIP_UNICAST_IF = 0x32
+
+ sysIP_MULTICAST_IF = 0x20
+ sysIP_MULTICAST_TTL = 0x21
+ sysIP_MULTICAST_LOOP = 0x22
+ sysIP_ADD_MEMBERSHIP = 0x23
+ sysIP_DROP_MEMBERSHIP = 0x24
+ sysIP_UNBLOCK_SOURCE = 0x25
+ sysIP_BLOCK_SOURCE = 0x26
+ sysIP_ADD_SOURCE_MEMBERSHIP = 0x27
+ sysIP_DROP_SOURCE_MEMBERSHIP = 0x28
+ sysIP_MSFILTER = 0x29
+ sysMCAST_JOIN_GROUP = 0x2a
+ sysMCAST_LEAVE_GROUP = 0x2d
+ sysMCAST_JOIN_SOURCE_GROUP = 0x2e
+ sysMCAST_LEAVE_SOURCE_GROUP = 0x2f
+ sysMCAST_BLOCK_SOURCE = 0x2b
+ sysMCAST_UNBLOCK_SOURCE = 0x2c
+ sysMCAST_MSFILTER = 0x30
+ sysIP_MULTICAST_ALL = 0x31
+
+ sysICMP_FILTER = 0x1
+
+ sysSO_EE_ORIGIN_NONE = 0x0
+ sysSO_EE_ORIGIN_LOCAL = 0x1
+ sysSO_EE_ORIGIN_ICMP = 0x2
+ sysSO_EE_ORIGIN_ICMP6 = 0x3
+ sysSO_EE_ORIGIN_TXSTATUS = 0x4
+ sysSO_EE_ORIGIN_TIMESTAMPING = 0x4
+
+ sysSOL_SOCKET = 0x1
+ sysSO_ATTACH_FILTER = 0x1a
+
+ sizeofKernelSockaddrStorage = 0x80
+ sizeofSockaddrInet = 0x10
+ sizeofInetPktinfo = 0xc
+ sizeofSockExtendedErr = 0x10
+
+ sizeofIPMreq = 0x8
+ sizeofIPMreqn = 0xc
+ sizeofIPMreqSource = 0xc
+ sizeofGroupReq = 0x88
+ sizeofGroupSourceReq = 0x108
+
+ sizeofICMPFilter = 0x4
+
+ sizeofSockFprog = 0x10
+)
+
+type kernelSockaddrStorage struct {
+ Family uint16
+ X__data [126]int8
+}
+
+type sockaddrInet struct {
+ Family uint16
+ Port uint16
+ Addr [4]byte /* in_addr */
+ X__pad [8]uint8
+}
+
+type inetPktinfo struct {
+ Ifindex int32
+ Spec_dst [4]byte /* in_addr */
+ Addr [4]byte /* in_addr */
+}
+
+type sockExtendedErr struct {
+ Errno uint32
+ Origin uint8
+ Type uint8
+ Code uint8
+ Pad uint8
+ Info uint32
+ Data uint32
+}
+
+type ipMreq struct {
+ Multiaddr [4]byte /* in_addr */
+ Interface [4]byte /* in_addr */
+}
+
+type ipMreqn struct {
+ Multiaddr [4]byte /* in_addr */
+ Address [4]byte /* in_addr */
+ Ifindex int32
+}
+
+type ipMreqSource struct {
+ Multiaddr uint32
+ Interface uint32
+ Sourceaddr uint32
+}
+
+type groupReq struct {
+ Interface uint32
+ Pad_cgo_0 [4]byte
+ Group kernelSockaddrStorage
+}
+
+type groupSourceReq struct {
+ Interface uint32
+ Pad_cgo_0 [4]byte
+ Group kernelSockaddrStorage
+ Source kernelSockaddrStorage
+}
+
+type icmpFilter struct {
+ Data uint32
+}
+
+type sockFProg struct {
+ Len uint16
+ Pad_cgo_0 [6]byte
+ Filter *sockFilter
+}
+
+type sockFilter struct {
+ Code uint16
+ Jt uint8
+ Jf uint8
+ K uint32
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_linux_mips.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_linux_mips.go
new file mode 100644
index 000000000..c0260f0ce
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_linux_mips.go
@@ -0,0 +1,148 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_linux.go
+
+package ipv4
+
+const (
+ sysIP_TOS = 0x1
+ sysIP_TTL = 0x2
+ sysIP_HDRINCL = 0x3
+ sysIP_OPTIONS = 0x4
+ sysIP_ROUTER_ALERT = 0x5
+ sysIP_RECVOPTS = 0x6
+ sysIP_RETOPTS = 0x7
+ sysIP_PKTINFO = 0x8
+ sysIP_PKTOPTIONS = 0x9
+ sysIP_MTU_DISCOVER = 0xa
+ sysIP_RECVERR = 0xb
+ sysIP_RECVTTL = 0xc
+ sysIP_RECVTOS = 0xd
+ sysIP_MTU = 0xe
+ sysIP_FREEBIND = 0xf
+ sysIP_TRANSPARENT = 0x13
+ sysIP_RECVRETOPTS = 0x7
+ sysIP_ORIGDSTADDR = 0x14
+ sysIP_RECVORIGDSTADDR = 0x14
+ sysIP_MINTTL = 0x15
+ sysIP_NODEFRAG = 0x16
+ sysIP_UNICAST_IF = 0x32
+
+ sysIP_MULTICAST_IF = 0x20
+ sysIP_MULTICAST_TTL = 0x21
+ sysIP_MULTICAST_LOOP = 0x22
+ sysIP_ADD_MEMBERSHIP = 0x23
+ sysIP_DROP_MEMBERSHIP = 0x24
+ sysIP_UNBLOCK_SOURCE = 0x25
+ sysIP_BLOCK_SOURCE = 0x26
+ sysIP_ADD_SOURCE_MEMBERSHIP = 0x27
+ sysIP_DROP_SOURCE_MEMBERSHIP = 0x28
+ sysIP_MSFILTER = 0x29
+ sysMCAST_JOIN_GROUP = 0x2a
+ sysMCAST_LEAVE_GROUP = 0x2d
+ sysMCAST_JOIN_SOURCE_GROUP = 0x2e
+ sysMCAST_LEAVE_SOURCE_GROUP = 0x2f
+ sysMCAST_BLOCK_SOURCE = 0x2b
+ sysMCAST_UNBLOCK_SOURCE = 0x2c
+ sysMCAST_MSFILTER = 0x30
+ sysIP_MULTICAST_ALL = 0x31
+
+ sysICMP_FILTER = 0x1
+
+ sysSO_EE_ORIGIN_NONE = 0x0
+ sysSO_EE_ORIGIN_LOCAL = 0x1
+ sysSO_EE_ORIGIN_ICMP = 0x2
+ sysSO_EE_ORIGIN_ICMP6 = 0x3
+ sysSO_EE_ORIGIN_TXSTATUS = 0x4
+ sysSO_EE_ORIGIN_TIMESTAMPING = 0x4
+
+ sysSOL_SOCKET = 0x1
+ sysSO_ATTACH_FILTER = 0x1a
+
+ sizeofKernelSockaddrStorage = 0x80
+ sizeofSockaddrInet = 0x10
+ sizeofInetPktinfo = 0xc
+ sizeofSockExtendedErr = 0x10
+
+ sizeofIPMreq = 0x8
+ sizeofIPMreqn = 0xc
+ sizeofIPMreqSource = 0xc
+ sizeofGroupReq = 0x84
+ sizeofGroupSourceReq = 0x104
+
+ sizeofICMPFilter = 0x4
+
+ sizeofSockFprog = 0x8
+)
+
+type kernelSockaddrStorage struct {
+ Family uint16
+ X__data [126]int8
+}
+
+type sockaddrInet struct {
+ Family uint16
+ Port uint16
+ Addr [4]byte /* in_addr */
+ X__pad [8]uint8
+}
+
+type inetPktinfo struct {
+ Ifindex int32
+ Spec_dst [4]byte /* in_addr */
+ Addr [4]byte /* in_addr */
+}
+
+type sockExtendedErr struct {
+ Errno uint32
+ Origin uint8
+ Type uint8
+ Code uint8
+ Pad uint8
+ Info uint32
+ Data uint32
+}
+
+type ipMreq struct {
+ Multiaddr [4]byte /* in_addr */
+ Interface [4]byte /* in_addr */
+}
+
+type ipMreqn struct {
+ Multiaddr [4]byte /* in_addr */
+ Address [4]byte /* in_addr */
+ Ifindex int32
+}
+
+type ipMreqSource struct {
+ Multiaddr uint32
+ Interface uint32
+ Sourceaddr uint32
+}
+
+type groupReq struct {
+ Interface uint32
+ Group kernelSockaddrStorage
+}
+
+type groupSourceReq struct {
+ Interface uint32
+ Group kernelSockaddrStorage
+ Source kernelSockaddrStorage
+}
+
+type icmpFilter struct {
+ Data uint32
+}
+
+type sockFProg struct {
+ Len uint16
+ Pad_cgo_0 [2]byte
+ Filter *sockFilter
+}
+
+type sockFilter struct {
+ Code uint16
+ Jt uint8
+ Jf uint8
+ K uint32
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_linux_mips64.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_linux_mips64.go
new file mode 100644
index 000000000..9c967eaa6
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_linux_mips64.go
@@ -0,0 +1,150 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_linux.go
+
+package ipv4
+
+const (
+ sysIP_TOS = 0x1
+ sysIP_TTL = 0x2
+ sysIP_HDRINCL = 0x3
+ sysIP_OPTIONS = 0x4
+ sysIP_ROUTER_ALERT = 0x5
+ sysIP_RECVOPTS = 0x6
+ sysIP_RETOPTS = 0x7
+ sysIP_PKTINFO = 0x8
+ sysIP_PKTOPTIONS = 0x9
+ sysIP_MTU_DISCOVER = 0xa
+ sysIP_RECVERR = 0xb
+ sysIP_RECVTTL = 0xc
+ sysIP_RECVTOS = 0xd
+ sysIP_MTU = 0xe
+ sysIP_FREEBIND = 0xf
+ sysIP_TRANSPARENT = 0x13
+ sysIP_RECVRETOPTS = 0x7
+ sysIP_ORIGDSTADDR = 0x14
+ sysIP_RECVORIGDSTADDR = 0x14
+ sysIP_MINTTL = 0x15
+ sysIP_NODEFRAG = 0x16
+ sysIP_UNICAST_IF = 0x32
+
+ sysIP_MULTICAST_IF = 0x20
+ sysIP_MULTICAST_TTL = 0x21
+ sysIP_MULTICAST_LOOP = 0x22
+ sysIP_ADD_MEMBERSHIP = 0x23
+ sysIP_DROP_MEMBERSHIP = 0x24
+ sysIP_UNBLOCK_SOURCE = 0x25
+ sysIP_BLOCK_SOURCE = 0x26
+ sysIP_ADD_SOURCE_MEMBERSHIP = 0x27
+ sysIP_DROP_SOURCE_MEMBERSHIP = 0x28
+ sysIP_MSFILTER = 0x29
+ sysMCAST_JOIN_GROUP = 0x2a
+ sysMCAST_LEAVE_GROUP = 0x2d
+ sysMCAST_JOIN_SOURCE_GROUP = 0x2e
+ sysMCAST_LEAVE_SOURCE_GROUP = 0x2f
+ sysMCAST_BLOCK_SOURCE = 0x2b
+ sysMCAST_UNBLOCK_SOURCE = 0x2c
+ sysMCAST_MSFILTER = 0x30
+ sysIP_MULTICAST_ALL = 0x31
+
+ sysICMP_FILTER = 0x1
+
+ sysSO_EE_ORIGIN_NONE = 0x0
+ sysSO_EE_ORIGIN_LOCAL = 0x1
+ sysSO_EE_ORIGIN_ICMP = 0x2
+ sysSO_EE_ORIGIN_ICMP6 = 0x3
+ sysSO_EE_ORIGIN_TXSTATUS = 0x4
+ sysSO_EE_ORIGIN_TIMESTAMPING = 0x4
+
+ sysSOL_SOCKET = 0x1
+ sysSO_ATTACH_FILTER = 0x1a
+
+ sizeofKernelSockaddrStorage = 0x80
+ sizeofSockaddrInet = 0x10
+ sizeofInetPktinfo = 0xc
+ sizeofSockExtendedErr = 0x10
+
+ sizeofIPMreq = 0x8
+ sizeofIPMreqn = 0xc
+ sizeofIPMreqSource = 0xc
+ sizeofGroupReq = 0x88
+ sizeofGroupSourceReq = 0x108
+
+ sizeofICMPFilter = 0x4
+
+ sizeofSockFprog = 0x10
+)
+
+type kernelSockaddrStorage struct {
+ Family uint16
+ X__data [126]int8
+}
+
+type sockaddrInet struct {
+ Family uint16
+ Port uint16
+ Addr [4]byte /* in_addr */
+ X__pad [8]uint8
+}
+
+type inetPktinfo struct {
+ Ifindex int32
+ Spec_dst [4]byte /* in_addr */
+ Addr [4]byte /* in_addr */
+}
+
+type sockExtendedErr struct {
+ Errno uint32
+ Origin uint8
+ Type uint8
+ Code uint8
+ Pad uint8
+ Info uint32
+ Data uint32
+}
+
+type ipMreq struct {
+ Multiaddr [4]byte /* in_addr */
+ Interface [4]byte /* in_addr */
+}
+
+type ipMreqn struct {
+ Multiaddr [4]byte /* in_addr */
+ Address [4]byte /* in_addr */
+ Ifindex int32
+}
+
+type ipMreqSource struct {
+ Multiaddr uint32
+ Interface uint32
+ Sourceaddr uint32
+}
+
+type groupReq struct {
+ Interface uint32
+ Pad_cgo_0 [4]byte
+ Group kernelSockaddrStorage
+}
+
+type groupSourceReq struct {
+ Interface uint32
+ Pad_cgo_0 [4]byte
+ Group kernelSockaddrStorage
+ Source kernelSockaddrStorage
+}
+
+type icmpFilter struct {
+ Data uint32
+}
+
+type sockFProg struct {
+ Len uint16
+ Pad_cgo_0 [6]byte
+ Filter *sockFilter
+}
+
+type sockFilter struct {
+ Code uint16
+ Jt uint8
+ Jf uint8
+ K uint32
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_linux_mips64le.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_linux_mips64le.go
new file mode 100644
index 000000000..9c967eaa6
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_linux_mips64le.go
@@ -0,0 +1,150 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_linux.go
+
+package ipv4
+
+const (
+ sysIP_TOS = 0x1
+ sysIP_TTL = 0x2
+ sysIP_HDRINCL = 0x3
+ sysIP_OPTIONS = 0x4
+ sysIP_ROUTER_ALERT = 0x5
+ sysIP_RECVOPTS = 0x6
+ sysIP_RETOPTS = 0x7
+ sysIP_PKTINFO = 0x8
+ sysIP_PKTOPTIONS = 0x9
+ sysIP_MTU_DISCOVER = 0xa
+ sysIP_RECVERR = 0xb
+ sysIP_RECVTTL = 0xc
+ sysIP_RECVTOS = 0xd
+ sysIP_MTU = 0xe
+ sysIP_FREEBIND = 0xf
+ sysIP_TRANSPARENT = 0x13
+ sysIP_RECVRETOPTS = 0x7
+ sysIP_ORIGDSTADDR = 0x14
+ sysIP_RECVORIGDSTADDR = 0x14
+ sysIP_MINTTL = 0x15
+ sysIP_NODEFRAG = 0x16
+ sysIP_UNICAST_IF = 0x32
+
+ sysIP_MULTICAST_IF = 0x20
+ sysIP_MULTICAST_TTL = 0x21
+ sysIP_MULTICAST_LOOP = 0x22
+ sysIP_ADD_MEMBERSHIP = 0x23
+ sysIP_DROP_MEMBERSHIP = 0x24
+ sysIP_UNBLOCK_SOURCE = 0x25
+ sysIP_BLOCK_SOURCE = 0x26
+ sysIP_ADD_SOURCE_MEMBERSHIP = 0x27
+ sysIP_DROP_SOURCE_MEMBERSHIP = 0x28
+ sysIP_MSFILTER = 0x29
+ sysMCAST_JOIN_GROUP = 0x2a
+ sysMCAST_LEAVE_GROUP = 0x2d
+ sysMCAST_JOIN_SOURCE_GROUP = 0x2e
+ sysMCAST_LEAVE_SOURCE_GROUP = 0x2f
+ sysMCAST_BLOCK_SOURCE = 0x2b
+ sysMCAST_UNBLOCK_SOURCE = 0x2c
+ sysMCAST_MSFILTER = 0x30
+ sysIP_MULTICAST_ALL = 0x31
+
+ sysICMP_FILTER = 0x1
+
+ sysSO_EE_ORIGIN_NONE = 0x0
+ sysSO_EE_ORIGIN_LOCAL = 0x1
+ sysSO_EE_ORIGIN_ICMP = 0x2
+ sysSO_EE_ORIGIN_ICMP6 = 0x3
+ sysSO_EE_ORIGIN_TXSTATUS = 0x4
+ sysSO_EE_ORIGIN_TIMESTAMPING = 0x4
+
+ sysSOL_SOCKET = 0x1
+ sysSO_ATTACH_FILTER = 0x1a
+
+ sizeofKernelSockaddrStorage = 0x80
+ sizeofSockaddrInet = 0x10
+ sizeofInetPktinfo = 0xc
+ sizeofSockExtendedErr = 0x10
+
+ sizeofIPMreq = 0x8
+ sizeofIPMreqn = 0xc
+ sizeofIPMreqSource = 0xc
+ sizeofGroupReq = 0x88
+ sizeofGroupSourceReq = 0x108
+
+ sizeofICMPFilter = 0x4
+
+ sizeofSockFprog = 0x10
+)
+
+type kernelSockaddrStorage struct {
+ Family uint16
+ X__data [126]int8
+}
+
+type sockaddrInet struct {
+ Family uint16
+ Port uint16
+ Addr [4]byte /* in_addr */
+ X__pad [8]uint8
+}
+
+type inetPktinfo struct {
+ Ifindex int32
+ Spec_dst [4]byte /* in_addr */
+ Addr [4]byte /* in_addr */
+}
+
+type sockExtendedErr struct {
+ Errno uint32
+ Origin uint8
+ Type uint8
+ Code uint8
+ Pad uint8
+ Info uint32
+ Data uint32
+}
+
+type ipMreq struct {
+ Multiaddr [4]byte /* in_addr */
+ Interface [4]byte /* in_addr */
+}
+
+type ipMreqn struct {
+ Multiaddr [4]byte /* in_addr */
+ Address [4]byte /* in_addr */
+ Ifindex int32
+}
+
+type ipMreqSource struct {
+ Multiaddr uint32
+ Interface uint32
+ Sourceaddr uint32
+}
+
+type groupReq struct {
+ Interface uint32
+ Pad_cgo_0 [4]byte
+ Group kernelSockaddrStorage
+}
+
+type groupSourceReq struct {
+ Interface uint32
+ Pad_cgo_0 [4]byte
+ Group kernelSockaddrStorage
+ Source kernelSockaddrStorage
+}
+
+type icmpFilter struct {
+ Data uint32
+}
+
+type sockFProg struct {
+ Len uint16
+ Pad_cgo_0 [6]byte
+ Filter *sockFilter
+}
+
+type sockFilter struct {
+ Code uint16
+ Jt uint8
+ Jf uint8
+ K uint32
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_linux_mipsle.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_linux_mipsle.go
new file mode 100644
index 000000000..c0260f0ce
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_linux_mipsle.go
@@ -0,0 +1,148 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_linux.go
+
+package ipv4
+
+const (
+ sysIP_TOS = 0x1
+ sysIP_TTL = 0x2
+ sysIP_HDRINCL = 0x3
+ sysIP_OPTIONS = 0x4
+ sysIP_ROUTER_ALERT = 0x5
+ sysIP_RECVOPTS = 0x6
+ sysIP_RETOPTS = 0x7
+ sysIP_PKTINFO = 0x8
+ sysIP_PKTOPTIONS = 0x9
+ sysIP_MTU_DISCOVER = 0xa
+ sysIP_RECVERR = 0xb
+ sysIP_RECVTTL = 0xc
+ sysIP_RECVTOS = 0xd
+ sysIP_MTU = 0xe
+ sysIP_FREEBIND = 0xf
+ sysIP_TRANSPARENT = 0x13
+ sysIP_RECVRETOPTS = 0x7
+ sysIP_ORIGDSTADDR = 0x14
+ sysIP_RECVORIGDSTADDR = 0x14
+ sysIP_MINTTL = 0x15
+ sysIP_NODEFRAG = 0x16
+ sysIP_UNICAST_IF = 0x32
+
+ sysIP_MULTICAST_IF = 0x20
+ sysIP_MULTICAST_TTL = 0x21
+ sysIP_MULTICAST_LOOP = 0x22
+ sysIP_ADD_MEMBERSHIP = 0x23
+ sysIP_DROP_MEMBERSHIP = 0x24
+ sysIP_UNBLOCK_SOURCE = 0x25
+ sysIP_BLOCK_SOURCE = 0x26
+ sysIP_ADD_SOURCE_MEMBERSHIP = 0x27
+ sysIP_DROP_SOURCE_MEMBERSHIP = 0x28
+ sysIP_MSFILTER = 0x29
+ sysMCAST_JOIN_GROUP = 0x2a
+ sysMCAST_LEAVE_GROUP = 0x2d
+ sysMCAST_JOIN_SOURCE_GROUP = 0x2e
+ sysMCAST_LEAVE_SOURCE_GROUP = 0x2f
+ sysMCAST_BLOCK_SOURCE = 0x2b
+ sysMCAST_UNBLOCK_SOURCE = 0x2c
+ sysMCAST_MSFILTER = 0x30
+ sysIP_MULTICAST_ALL = 0x31
+
+ sysICMP_FILTER = 0x1
+
+ sysSO_EE_ORIGIN_NONE = 0x0
+ sysSO_EE_ORIGIN_LOCAL = 0x1
+ sysSO_EE_ORIGIN_ICMP = 0x2
+ sysSO_EE_ORIGIN_ICMP6 = 0x3
+ sysSO_EE_ORIGIN_TXSTATUS = 0x4
+ sysSO_EE_ORIGIN_TIMESTAMPING = 0x4
+
+ sysSOL_SOCKET = 0x1
+ sysSO_ATTACH_FILTER = 0x1a
+
+ sizeofKernelSockaddrStorage = 0x80
+ sizeofSockaddrInet = 0x10
+ sizeofInetPktinfo = 0xc
+ sizeofSockExtendedErr = 0x10
+
+ sizeofIPMreq = 0x8
+ sizeofIPMreqn = 0xc
+ sizeofIPMreqSource = 0xc
+ sizeofGroupReq = 0x84
+ sizeofGroupSourceReq = 0x104
+
+ sizeofICMPFilter = 0x4
+
+ sizeofSockFprog = 0x8
+)
+
+type kernelSockaddrStorage struct {
+ Family uint16
+ X__data [126]int8
+}
+
+type sockaddrInet struct {
+ Family uint16
+ Port uint16
+ Addr [4]byte /* in_addr */
+ X__pad [8]uint8
+}
+
+type inetPktinfo struct {
+ Ifindex int32
+ Spec_dst [4]byte /* in_addr */
+ Addr [4]byte /* in_addr */
+}
+
+type sockExtendedErr struct {
+ Errno uint32
+ Origin uint8
+ Type uint8
+ Code uint8
+ Pad uint8
+ Info uint32
+ Data uint32
+}
+
+type ipMreq struct {
+ Multiaddr [4]byte /* in_addr */
+ Interface [4]byte /* in_addr */
+}
+
+type ipMreqn struct {
+ Multiaddr [4]byte /* in_addr */
+ Address [4]byte /* in_addr */
+ Ifindex int32
+}
+
+type ipMreqSource struct {
+ Multiaddr uint32
+ Interface uint32
+ Sourceaddr uint32
+}
+
+type groupReq struct {
+ Interface uint32
+ Group kernelSockaddrStorage
+}
+
+type groupSourceReq struct {
+ Interface uint32
+ Group kernelSockaddrStorage
+ Source kernelSockaddrStorage
+}
+
+type icmpFilter struct {
+ Data uint32
+}
+
+type sockFProg struct {
+ Len uint16
+ Pad_cgo_0 [2]byte
+ Filter *sockFilter
+}
+
+type sockFilter struct {
+ Code uint16
+ Jt uint8
+ Jf uint8
+ K uint32
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_linux_ppc.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_linux_ppc.go
new file mode 100644
index 000000000..f65bd9a7a
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_linux_ppc.go
@@ -0,0 +1,148 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_linux.go
+
+package ipv4
+
+const (
+ sysIP_TOS = 0x1
+ sysIP_TTL = 0x2
+ sysIP_HDRINCL = 0x3
+ sysIP_OPTIONS = 0x4
+ sysIP_ROUTER_ALERT = 0x5
+ sysIP_RECVOPTS = 0x6
+ sysIP_RETOPTS = 0x7
+ sysIP_PKTINFO = 0x8
+ sysIP_PKTOPTIONS = 0x9
+ sysIP_MTU_DISCOVER = 0xa
+ sysIP_RECVERR = 0xb
+ sysIP_RECVTTL = 0xc
+ sysIP_RECVTOS = 0xd
+ sysIP_MTU = 0xe
+ sysIP_FREEBIND = 0xf
+ sysIP_TRANSPARENT = 0x13
+ sysIP_RECVRETOPTS = 0x7
+ sysIP_ORIGDSTADDR = 0x14
+ sysIP_RECVORIGDSTADDR = 0x14
+ sysIP_MINTTL = 0x15
+ sysIP_NODEFRAG = 0x16
+ sysIP_UNICAST_IF = 0x32
+
+ sysIP_MULTICAST_IF = 0x20
+ sysIP_MULTICAST_TTL = 0x21
+ sysIP_MULTICAST_LOOP = 0x22
+ sysIP_ADD_MEMBERSHIP = 0x23
+ sysIP_DROP_MEMBERSHIP = 0x24
+ sysIP_UNBLOCK_SOURCE = 0x25
+ sysIP_BLOCK_SOURCE = 0x26
+ sysIP_ADD_SOURCE_MEMBERSHIP = 0x27
+ sysIP_DROP_SOURCE_MEMBERSHIP = 0x28
+ sysIP_MSFILTER = 0x29
+ sysMCAST_JOIN_GROUP = 0x2a
+ sysMCAST_LEAVE_GROUP = 0x2d
+ sysMCAST_JOIN_SOURCE_GROUP = 0x2e
+ sysMCAST_LEAVE_SOURCE_GROUP = 0x2f
+ sysMCAST_BLOCK_SOURCE = 0x2b
+ sysMCAST_UNBLOCK_SOURCE = 0x2c
+ sysMCAST_MSFILTER = 0x30
+ sysIP_MULTICAST_ALL = 0x31
+
+ sysICMP_FILTER = 0x1
+
+ sysSO_EE_ORIGIN_NONE = 0x0
+ sysSO_EE_ORIGIN_LOCAL = 0x1
+ sysSO_EE_ORIGIN_ICMP = 0x2
+ sysSO_EE_ORIGIN_ICMP6 = 0x3
+ sysSO_EE_ORIGIN_TXSTATUS = 0x4
+ sysSO_EE_ORIGIN_TIMESTAMPING = 0x4
+
+ sysSOL_SOCKET = 0x1
+ sysSO_ATTACH_FILTER = 0x1a
+
+ sizeofKernelSockaddrStorage = 0x80
+ sizeofSockaddrInet = 0x10
+ sizeofInetPktinfo = 0xc
+ sizeofSockExtendedErr = 0x10
+
+ sizeofIPMreq = 0x8
+ sizeofIPMreqn = 0xc
+ sizeofIPMreqSource = 0xc
+ sizeofGroupReq = 0x84
+ sizeofGroupSourceReq = 0x104
+
+ sizeofICMPFilter = 0x4
+
+ sizeofSockFprog = 0x8
+)
+
+type kernelSockaddrStorage struct {
+ Family uint16
+ X__data [126]uint8
+}
+
+type sockaddrInet struct {
+ Family uint16
+ Port uint16
+ Addr [4]byte /* in_addr */
+ X__pad [8]uint8
+}
+
+type inetPktinfo struct {
+ Ifindex int32
+ Spec_dst [4]byte /* in_addr */
+ Addr [4]byte /* in_addr */
+}
+
+type sockExtendedErr struct {
+ Errno uint32
+ Origin uint8
+ Type uint8
+ Code uint8
+ Pad uint8
+ Info uint32
+ Data uint32
+}
+
+type ipMreq struct {
+ Multiaddr [4]byte /* in_addr */
+ Interface [4]byte /* in_addr */
+}
+
+type ipMreqn struct {
+ Multiaddr [4]byte /* in_addr */
+ Address [4]byte /* in_addr */
+ Ifindex int32
+}
+
+type ipMreqSource struct {
+ Multiaddr uint32
+ Interface uint32
+ Sourceaddr uint32
+}
+
+type groupReq struct {
+ Interface uint32
+ Group kernelSockaddrStorage
+}
+
+type groupSourceReq struct {
+ Interface uint32
+ Group kernelSockaddrStorage
+ Source kernelSockaddrStorage
+}
+
+type icmpFilter struct {
+ Data uint32
+}
+
+type sockFProg struct {
+ Len uint16
+ Pad_cgo_0 [2]byte
+ Filter *sockFilter
+}
+
+type sockFilter struct {
+ Code uint16
+ Jt uint8
+ Jf uint8
+ K uint32
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_linux_ppc64.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_linux_ppc64.go
new file mode 100644
index 000000000..9c967eaa6
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_linux_ppc64.go
@@ -0,0 +1,150 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_linux.go
+
+package ipv4
+
+const (
+ sysIP_TOS = 0x1
+ sysIP_TTL = 0x2
+ sysIP_HDRINCL = 0x3
+ sysIP_OPTIONS = 0x4
+ sysIP_ROUTER_ALERT = 0x5
+ sysIP_RECVOPTS = 0x6
+ sysIP_RETOPTS = 0x7
+ sysIP_PKTINFO = 0x8
+ sysIP_PKTOPTIONS = 0x9
+ sysIP_MTU_DISCOVER = 0xa
+ sysIP_RECVERR = 0xb
+ sysIP_RECVTTL = 0xc
+ sysIP_RECVTOS = 0xd
+ sysIP_MTU = 0xe
+ sysIP_FREEBIND = 0xf
+ sysIP_TRANSPARENT = 0x13
+ sysIP_RECVRETOPTS = 0x7
+ sysIP_ORIGDSTADDR = 0x14
+ sysIP_RECVORIGDSTADDR = 0x14
+ sysIP_MINTTL = 0x15
+ sysIP_NODEFRAG = 0x16
+ sysIP_UNICAST_IF = 0x32
+
+ sysIP_MULTICAST_IF = 0x20
+ sysIP_MULTICAST_TTL = 0x21
+ sysIP_MULTICAST_LOOP = 0x22
+ sysIP_ADD_MEMBERSHIP = 0x23
+ sysIP_DROP_MEMBERSHIP = 0x24
+ sysIP_UNBLOCK_SOURCE = 0x25
+ sysIP_BLOCK_SOURCE = 0x26
+ sysIP_ADD_SOURCE_MEMBERSHIP = 0x27
+ sysIP_DROP_SOURCE_MEMBERSHIP = 0x28
+ sysIP_MSFILTER = 0x29
+ sysMCAST_JOIN_GROUP = 0x2a
+ sysMCAST_LEAVE_GROUP = 0x2d
+ sysMCAST_JOIN_SOURCE_GROUP = 0x2e
+ sysMCAST_LEAVE_SOURCE_GROUP = 0x2f
+ sysMCAST_BLOCK_SOURCE = 0x2b
+ sysMCAST_UNBLOCK_SOURCE = 0x2c
+ sysMCAST_MSFILTER = 0x30
+ sysIP_MULTICAST_ALL = 0x31
+
+ sysICMP_FILTER = 0x1
+
+ sysSO_EE_ORIGIN_NONE = 0x0
+ sysSO_EE_ORIGIN_LOCAL = 0x1
+ sysSO_EE_ORIGIN_ICMP = 0x2
+ sysSO_EE_ORIGIN_ICMP6 = 0x3
+ sysSO_EE_ORIGIN_TXSTATUS = 0x4
+ sysSO_EE_ORIGIN_TIMESTAMPING = 0x4
+
+ sysSOL_SOCKET = 0x1
+ sysSO_ATTACH_FILTER = 0x1a
+
+ sizeofKernelSockaddrStorage = 0x80
+ sizeofSockaddrInet = 0x10
+ sizeofInetPktinfo = 0xc
+ sizeofSockExtendedErr = 0x10
+
+ sizeofIPMreq = 0x8
+ sizeofIPMreqn = 0xc
+ sizeofIPMreqSource = 0xc
+ sizeofGroupReq = 0x88
+ sizeofGroupSourceReq = 0x108
+
+ sizeofICMPFilter = 0x4
+
+ sizeofSockFprog = 0x10
+)
+
+type kernelSockaddrStorage struct {
+ Family uint16
+ X__data [126]int8
+}
+
+type sockaddrInet struct {
+ Family uint16
+ Port uint16
+ Addr [4]byte /* in_addr */
+ X__pad [8]uint8
+}
+
+type inetPktinfo struct {
+ Ifindex int32
+ Spec_dst [4]byte /* in_addr */
+ Addr [4]byte /* in_addr */
+}
+
+type sockExtendedErr struct {
+ Errno uint32
+ Origin uint8
+ Type uint8
+ Code uint8
+ Pad uint8
+ Info uint32
+ Data uint32
+}
+
+type ipMreq struct {
+ Multiaddr [4]byte /* in_addr */
+ Interface [4]byte /* in_addr */
+}
+
+type ipMreqn struct {
+ Multiaddr [4]byte /* in_addr */
+ Address [4]byte /* in_addr */
+ Ifindex int32
+}
+
+type ipMreqSource struct {
+ Multiaddr uint32
+ Interface uint32
+ Sourceaddr uint32
+}
+
+type groupReq struct {
+ Interface uint32
+ Pad_cgo_0 [4]byte
+ Group kernelSockaddrStorage
+}
+
+type groupSourceReq struct {
+ Interface uint32
+ Pad_cgo_0 [4]byte
+ Group kernelSockaddrStorage
+ Source kernelSockaddrStorage
+}
+
+type icmpFilter struct {
+ Data uint32
+}
+
+type sockFProg struct {
+ Len uint16
+ Pad_cgo_0 [6]byte
+ Filter *sockFilter
+}
+
+type sockFilter struct {
+ Code uint16
+ Jt uint8
+ Jf uint8
+ K uint32
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_linux_ppc64le.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_linux_ppc64le.go
new file mode 100644
index 000000000..9c967eaa6
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_linux_ppc64le.go
@@ -0,0 +1,150 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_linux.go
+
+package ipv4
+
+const (
+ sysIP_TOS = 0x1
+ sysIP_TTL = 0x2
+ sysIP_HDRINCL = 0x3
+ sysIP_OPTIONS = 0x4
+ sysIP_ROUTER_ALERT = 0x5
+ sysIP_RECVOPTS = 0x6
+ sysIP_RETOPTS = 0x7
+ sysIP_PKTINFO = 0x8
+ sysIP_PKTOPTIONS = 0x9
+ sysIP_MTU_DISCOVER = 0xa
+ sysIP_RECVERR = 0xb
+ sysIP_RECVTTL = 0xc
+ sysIP_RECVTOS = 0xd
+ sysIP_MTU = 0xe
+ sysIP_FREEBIND = 0xf
+ sysIP_TRANSPARENT = 0x13
+ sysIP_RECVRETOPTS = 0x7
+ sysIP_ORIGDSTADDR = 0x14
+ sysIP_RECVORIGDSTADDR = 0x14
+ sysIP_MINTTL = 0x15
+ sysIP_NODEFRAG = 0x16
+ sysIP_UNICAST_IF = 0x32
+
+ sysIP_MULTICAST_IF = 0x20
+ sysIP_MULTICAST_TTL = 0x21
+ sysIP_MULTICAST_LOOP = 0x22
+ sysIP_ADD_MEMBERSHIP = 0x23
+ sysIP_DROP_MEMBERSHIP = 0x24
+ sysIP_UNBLOCK_SOURCE = 0x25
+ sysIP_BLOCK_SOURCE = 0x26
+ sysIP_ADD_SOURCE_MEMBERSHIP = 0x27
+ sysIP_DROP_SOURCE_MEMBERSHIP = 0x28
+ sysIP_MSFILTER = 0x29
+ sysMCAST_JOIN_GROUP = 0x2a
+ sysMCAST_LEAVE_GROUP = 0x2d
+ sysMCAST_JOIN_SOURCE_GROUP = 0x2e
+ sysMCAST_LEAVE_SOURCE_GROUP = 0x2f
+ sysMCAST_BLOCK_SOURCE = 0x2b
+ sysMCAST_UNBLOCK_SOURCE = 0x2c
+ sysMCAST_MSFILTER = 0x30
+ sysIP_MULTICAST_ALL = 0x31
+
+ sysICMP_FILTER = 0x1
+
+ sysSO_EE_ORIGIN_NONE = 0x0
+ sysSO_EE_ORIGIN_LOCAL = 0x1
+ sysSO_EE_ORIGIN_ICMP = 0x2
+ sysSO_EE_ORIGIN_ICMP6 = 0x3
+ sysSO_EE_ORIGIN_TXSTATUS = 0x4
+ sysSO_EE_ORIGIN_TIMESTAMPING = 0x4
+
+ sysSOL_SOCKET = 0x1
+ sysSO_ATTACH_FILTER = 0x1a
+
+ sizeofKernelSockaddrStorage = 0x80
+ sizeofSockaddrInet = 0x10
+ sizeofInetPktinfo = 0xc
+ sizeofSockExtendedErr = 0x10
+
+ sizeofIPMreq = 0x8
+ sizeofIPMreqn = 0xc
+ sizeofIPMreqSource = 0xc
+ sizeofGroupReq = 0x88
+ sizeofGroupSourceReq = 0x108
+
+ sizeofICMPFilter = 0x4
+
+ sizeofSockFprog = 0x10
+)
+
+type kernelSockaddrStorage struct {
+ Family uint16
+ X__data [126]int8
+}
+
+type sockaddrInet struct {
+ Family uint16
+ Port uint16
+ Addr [4]byte /* in_addr */
+ X__pad [8]uint8
+}
+
+type inetPktinfo struct {
+ Ifindex int32
+ Spec_dst [4]byte /* in_addr */
+ Addr [4]byte /* in_addr */
+}
+
+type sockExtendedErr struct {
+ Errno uint32
+ Origin uint8
+ Type uint8
+ Code uint8
+ Pad uint8
+ Info uint32
+ Data uint32
+}
+
+type ipMreq struct {
+ Multiaddr [4]byte /* in_addr */
+ Interface [4]byte /* in_addr */
+}
+
+type ipMreqn struct {
+ Multiaddr [4]byte /* in_addr */
+ Address [4]byte /* in_addr */
+ Ifindex int32
+}
+
+type ipMreqSource struct {
+ Multiaddr uint32
+ Interface uint32
+ Sourceaddr uint32
+}
+
+type groupReq struct {
+ Interface uint32
+ Pad_cgo_0 [4]byte
+ Group kernelSockaddrStorage
+}
+
+type groupSourceReq struct {
+ Interface uint32
+ Pad_cgo_0 [4]byte
+ Group kernelSockaddrStorage
+ Source kernelSockaddrStorage
+}
+
+type icmpFilter struct {
+ Data uint32
+}
+
+type sockFProg struct {
+ Len uint16
+ Pad_cgo_0 [6]byte
+ Filter *sockFilter
+}
+
+type sockFilter struct {
+ Code uint16
+ Jt uint8
+ Jf uint8
+ K uint32
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_linux_s390x.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_linux_s390x.go
new file mode 100644
index 000000000..9c967eaa6
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_linux_s390x.go
@@ -0,0 +1,150 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_linux.go
+
+package ipv4
+
+const (
+ sysIP_TOS = 0x1
+ sysIP_TTL = 0x2
+ sysIP_HDRINCL = 0x3
+ sysIP_OPTIONS = 0x4
+ sysIP_ROUTER_ALERT = 0x5
+ sysIP_RECVOPTS = 0x6
+ sysIP_RETOPTS = 0x7
+ sysIP_PKTINFO = 0x8
+ sysIP_PKTOPTIONS = 0x9
+ sysIP_MTU_DISCOVER = 0xa
+ sysIP_RECVERR = 0xb
+ sysIP_RECVTTL = 0xc
+ sysIP_RECVTOS = 0xd
+ sysIP_MTU = 0xe
+ sysIP_FREEBIND = 0xf
+ sysIP_TRANSPARENT = 0x13
+ sysIP_RECVRETOPTS = 0x7
+ sysIP_ORIGDSTADDR = 0x14
+ sysIP_RECVORIGDSTADDR = 0x14
+ sysIP_MINTTL = 0x15
+ sysIP_NODEFRAG = 0x16
+ sysIP_UNICAST_IF = 0x32
+
+ sysIP_MULTICAST_IF = 0x20
+ sysIP_MULTICAST_TTL = 0x21
+ sysIP_MULTICAST_LOOP = 0x22
+ sysIP_ADD_MEMBERSHIP = 0x23
+ sysIP_DROP_MEMBERSHIP = 0x24
+ sysIP_UNBLOCK_SOURCE = 0x25
+ sysIP_BLOCK_SOURCE = 0x26
+ sysIP_ADD_SOURCE_MEMBERSHIP = 0x27
+ sysIP_DROP_SOURCE_MEMBERSHIP = 0x28
+ sysIP_MSFILTER = 0x29
+ sysMCAST_JOIN_GROUP = 0x2a
+ sysMCAST_LEAVE_GROUP = 0x2d
+ sysMCAST_JOIN_SOURCE_GROUP = 0x2e
+ sysMCAST_LEAVE_SOURCE_GROUP = 0x2f
+ sysMCAST_BLOCK_SOURCE = 0x2b
+ sysMCAST_UNBLOCK_SOURCE = 0x2c
+ sysMCAST_MSFILTER = 0x30
+ sysIP_MULTICAST_ALL = 0x31
+
+ sysICMP_FILTER = 0x1
+
+ sysSO_EE_ORIGIN_NONE = 0x0
+ sysSO_EE_ORIGIN_LOCAL = 0x1
+ sysSO_EE_ORIGIN_ICMP = 0x2
+ sysSO_EE_ORIGIN_ICMP6 = 0x3
+ sysSO_EE_ORIGIN_TXSTATUS = 0x4
+ sysSO_EE_ORIGIN_TIMESTAMPING = 0x4
+
+ sysSOL_SOCKET = 0x1
+ sysSO_ATTACH_FILTER = 0x1a
+
+ sizeofKernelSockaddrStorage = 0x80
+ sizeofSockaddrInet = 0x10
+ sizeofInetPktinfo = 0xc
+ sizeofSockExtendedErr = 0x10
+
+ sizeofIPMreq = 0x8
+ sizeofIPMreqn = 0xc
+ sizeofIPMreqSource = 0xc
+ sizeofGroupReq = 0x88
+ sizeofGroupSourceReq = 0x108
+
+ sizeofICMPFilter = 0x4
+
+ sizeofSockFprog = 0x10
+)
+
+type kernelSockaddrStorage struct {
+ Family uint16
+ X__data [126]int8
+}
+
+type sockaddrInet struct {
+ Family uint16
+ Port uint16
+ Addr [4]byte /* in_addr */
+ X__pad [8]uint8
+}
+
+type inetPktinfo struct {
+ Ifindex int32
+ Spec_dst [4]byte /* in_addr */
+ Addr [4]byte /* in_addr */
+}
+
+type sockExtendedErr struct {
+ Errno uint32
+ Origin uint8
+ Type uint8
+ Code uint8
+ Pad uint8
+ Info uint32
+ Data uint32
+}
+
+type ipMreq struct {
+ Multiaddr [4]byte /* in_addr */
+ Interface [4]byte /* in_addr */
+}
+
+type ipMreqn struct {
+ Multiaddr [4]byte /* in_addr */
+ Address [4]byte /* in_addr */
+ Ifindex int32
+}
+
+type ipMreqSource struct {
+ Multiaddr uint32
+ Interface uint32
+ Sourceaddr uint32
+}
+
+type groupReq struct {
+ Interface uint32
+ Pad_cgo_0 [4]byte
+ Group kernelSockaddrStorage
+}
+
+type groupSourceReq struct {
+ Interface uint32
+ Pad_cgo_0 [4]byte
+ Group kernelSockaddrStorage
+ Source kernelSockaddrStorage
+}
+
+type icmpFilter struct {
+ Data uint32
+}
+
+type sockFProg struct {
+ Len uint16
+ Pad_cgo_0 [6]byte
+ Filter *sockFilter
+}
+
+type sockFilter struct {
+ Code uint16
+ Jt uint8
+ Jf uint8
+ K uint32
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_netbsd.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_netbsd.go
new file mode 100644
index 000000000..fd3624d93
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_netbsd.go
@@ -0,0 +1,30 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_netbsd.go
+
+package ipv4
+
+const (
+ sysIP_OPTIONS = 0x1
+ sysIP_HDRINCL = 0x2
+ sysIP_TOS = 0x3
+ sysIP_TTL = 0x4
+ sysIP_RECVOPTS = 0x5
+ sysIP_RECVRETOPTS = 0x6
+ sysIP_RECVDSTADDR = 0x7
+ sysIP_RETOPTS = 0x8
+ sysIP_RECVIF = 0x14
+ sysIP_RECVTTL = 0x17
+
+ sysIP_MULTICAST_IF = 0x9
+ sysIP_MULTICAST_TTL = 0xa
+ sysIP_MULTICAST_LOOP = 0xb
+ sysIP_ADD_MEMBERSHIP = 0xc
+ sysIP_DROP_MEMBERSHIP = 0xd
+
+ sizeofIPMreq = 0x8
+)
+
+type ipMreq struct {
+ Multiaddr [4]byte /* in_addr */
+ Interface [4]byte /* in_addr */
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_openbsd.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_openbsd.go
new file mode 100644
index 000000000..12f36be75
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_openbsd.go
@@ -0,0 +1,30 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_openbsd.go
+
+package ipv4
+
+const (
+ sysIP_OPTIONS = 0x1
+ sysIP_HDRINCL = 0x2
+ sysIP_TOS = 0x3
+ sysIP_TTL = 0x4
+ sysIP_RECVOPTS = 0x5
+ sysIP_RECVRETOPTS = 0x6
+ sysIP_RECVDSTADDR = 0x7
+ sysIP_RETOPTS = 0x8
+ sysIP_RECVIF = 0x1e
+ sysIP_RECVTTL = 0x1f
+
+ sysIP_MULTICAST_IF = 0x9
+ sysIP_MULTICAST_TTL = 0xa
+ sysIP_MULTICAST_LOOP = 0xb
+ sysIP_ADD_MEMBERSHIP = 0xc
+ sysIP_DROP_MEMBERSHIP = 0xd
+
+ sizeofIPMreq = 0x8
+)
+
+type ipMreq struct {
+ Multiaddr [4]byte /* in_addr */
+ Interface [4]byte /* in_addr */
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_solaris.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_solaris.go
new file mode 100644
index 000000000..0a3875cc4
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv4/zsys_solaris.go
@@ -0,0 +1,100 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_solaris.go
+
+package ipv4
+
+const (
+ sysIP_OPTIONS = 0x1
+ sysIP_HDRINCL = 0x2
+ sysIP_TOS = 0x3
+ sysIP_TTL = 0x4
+ sysIP_RECVOPTS = 0x5
+ sysIP_RECVRETOPTS = 0x6
+ sysIP_RECVDSTADDR = 0x7
+ sysIP_RETOPTS = 0x8
+ sysIP_RECVIF = 0x9
+ sysIP_RECVSLLA = 0xa
+ sysIP_RECVTTL = 0xb
+
+ sysIP_MULTICAST_IF = 0x10
+ sysIP_MULTICAST_TTL = 0x11
+ sysIP_MULTICAST_LOOP = 0x12
+ sysIP_ADD_MEMBERSHIP = 0x13
+ sysIP_DROP_MEMBERSHIP = 0x14
+ sysIP_BLOCK_SOURCE = 0x15
+ sysIP_UNBLOCK_SOURCE = 0x16
+ sysIP_ADD_SOURCE_MEMBERSHIP = 0x17
+ sysIP_DROP_SOURCE_MEMBERSHIP = 0x18
+ sysIP_NEXTHOP = 0x19
+
+ sysIP_PKTINFO = 0x1a
+ sysIP_RECVPKTINFO = 0x1a
+ sysIP_DONTFRAG = 0x1b
+
+ sysIP_BOUND_IF = 0x41
+ sysIP_UNSPEC_SRC = 0x42
+ sysIP_BROADCAST_TTL = 0x43
+ sysIP_DHCPINIT_IF = 0x45
+
+ sysIP_REUSEADDR = 0x104
+ sysIP_DONTROUTE = 0x105
+ sysIP_BROADCAST = 0x106
+
+ sysMCAST_JOIN_GROUP = 0x29
+ sysMCAST_LEAVE_GROUP = 0x2a
+ sysMCAST_BLOCK_SOURCE = 0x2b
+ sysMCAST_UNBLOCK_SOURCE = 0x2c
+ sysMCAST_JOIN_SOURCE_GROUP = 0x2d
+ sysMCAST_LEAVE_SOURCE_GROUP = 0x2e
+
+ sizeofSockaddrStorage = 0x100
+ sizeofSockaddrInet = 0x10
+ sizeofInetPktinfo = 0xc
+
+ sizeofIPMreq = 0x8
+ sizeofIPMreqSource = 0xc
+ sizeofGroupReq = 0x104
+ sizeofGroupSourceReq = 0x204
+)
+
+type sockaddrStorage struct {
+ Family uint16
+ X_ss_pad1 [6]int8
+ X_ss_align float64
+ X_ss_pad2 [240]int8
+}
+
+type sockaddrInet struct {
+ Family uint16
+ Port uint16
+ Addr [4]byte /* in_addr */
+ Zero [8]int8
+}
+
+type inetPktinfo struct {
+ Ifindex uint32
+ Spec_dst [4]byte /* in_addr */
+ Addr [4]byte /* in_addr */
+}
+
+type ipMreq struct {
+ Multiaddr [4]byte /* in_addr */
+ Interface [4]byte /* in_addr */
+}
+
+type ipMreqSource struct {
+ Multiaddr [4]byte /* in_addr */
+ Sourceaddr [4]byte /* in_addr */
+ Interface [4]byte /* in_addr */
+}
+
+type groupReq struct {
+ Interface uint32
+ Pad_cgo_0 [256]byte
+}
+
+type groupSourceReq struct {
+ Interface uint32
+ Pad_cgo_0 [256]byte
+ Pad_cgo_1 [256]byte
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/batch.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/batch.go
new file mode 100644
index 000000000..4f5fe683d
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/batch.go
@@ -0,0 +1,119 @@
+// 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.
+
+// +build go1.9
+
+package ipv6
+
+import (
+ "net"
+ "runtime"
+ "syscall"
+
+ "golang.org/x/net/internal/socket"
+)
+
+// BUG(mikio): On Windows, the ReadBatch and WriteBatch methods of
+// PacketConn are not implemented.
+
+// A Message represents an IO message.
+//
+// type Message struct {
+// Buffers [][]byte
+// OOB []byte
+// Addr net.Addr
+// N int
+// NN int
+// Flags int
+// }
+//
+// The Buffers fields represents a list of contiguous buffers, which
+// can be used for vectored IO, for example, putting a header and a
+// payload in each slice.
+// When writing, the Buffers field must contain at least one byte to
+// write.
+// When reading, the Buffers field will always contain a byte to read.
+//
+// The OOB field contains protocol-specific control or miscellaneous
+// ancillary data known as out-of-band data.
+// It can be nil when not required.
+//
+// The Addr field specifies a destination address when writing.
+// It can be nil when the underlying protocol of the endpoint uses
+// connection-oriented communication.
+// After a successful read, it may contain the source address on the
+// received packet.
+//
+// The N field indicates the number of bytes read or written from/to
+// Buffers.
+//
+// The NN field indicates the number of bytes read or written from/to
+// OOB.
+//
+// The Flags field contains protocol-specific information on the
+// received message.
+type Message = socket.Message
+
+// ReadBatch reads a batch of messages.
+//
+// The provided flags is a set of platform-dependent flags, such as
+// syscall.MSG_PEEK.
+//
+// On a successful read it returns the number of messages received, up
+// to len(ms).
+//
+// On Linux, a batch read will be optimized.
+// On other platforms, this method will read only a single message.
+func (c *payloadHandler) ReadBatch(ms []Message, flags int) (int, error) {
+ if !c.ok() {
+ return 0, syscall.EINVAL
+ }
+ switch runtime.GOOS {
+ case "linux":
+ n, err := c.RecvMsgs([]socket.Message(ms), flags)
+ if err != nil {
+ err = &net.OpError{Op: "read", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: err}
+ }
+ return n, err
+ default:
+ n := 1
+ err := c.RecvMsg(&ms[0], flags)
+ if err != nil {
+ n = 0
+ err = &net.OpError{Op: "read", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: err}
+ }
+ return n, err
+ }
+}
+
+// WriteBatch writes a batch of messages.
+//
+// The provided flags is a set of platform-dependent flags, such as
+// syscall.MSG_DONTROUTE.
+//
+// It returns the number of messages written on a successful write.
+//
+// On Linux, a batch write will be optimized.
+// On other platforms, this method will write only a single message.
+func (c *payloadHandler) WriteBatch(ms []Message, flags int) (int, error) {
+ if !c.ok() {
+ return 0, syscall.EINVAL
+ }
+ switch runtime.GOOS {
+ case "linux":
+ n, err := c.SendMsgs([]socket.Message(ms), flags)
+ if err != nil {
+ err = &net.OpError{Op: "write", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: err}
+ }
+ return n, err
+ default:
+ n := 1
+ err := c.SendMsg(&ms[0], flags)
+ if err != nil {
+ n = 0
+ err = &net.OpError{Op: "write", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: err}
+ }
+ return n, err
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/bpf_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/bpf_test.go
new file mode 100644
index 000000000..8253e1f42
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/bpf_test.go
@@ -0,0 +1,96 @@
+// 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.
+
+package ipv6_test
+
+import (
+ "net"
+ "runtime"
+ "testing"
+ "time"
+
+ "golang.org/x/net/bpf"
+ "golang.org/x/net/ipv6"
+)
+
+func TestBPF(t *testing.T) {
+ if runtime.GOOS != "linux" {
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+ if !supportsIPv6 {
+ t.Skip("ipv6 is not supported")
+ }
+
+ l, err := net.ListenPacket("udp6", "[::1]:0")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer l.Close()
+
+ p := ipv6.NewPacketConn(l)
+
+ // This filter accepts UDP packets whose first payload byte is
+ // even.
+ prog, err := bpf.Assemble([]bpf.Instruction{
+ // Load the first byte of the payload (skipping UDP header).
+ bpf.LoadAbsolute{Off: 8, Size: 1},
+ // Select LSB of the byte.
+ bpf.ALUOpConstant{Op: bpf.ALUOpAnd, Val: 1},
+ // Byte is even?
+ bpf.JumpIf{Cond: bpf.JumpEqual, Val: 0, SkipFalse: 1},
+ // Accept.
+ bpf.RetConstant{Val: 4096},
+ // Ignore.
+ bpf.RetConstant{Val: 0},
+ })
+ if err != nil {
+ t.Fatalf("compiling BPF: %s", err)
+ }
+
+ if err = p.SetBPF(prog); err != nil {
+ t.Fatalf("attaching filter to Conn: %s", err)
+ }
+
+ s, err := net.Dial("udp6", l.LocalAddr().String())
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer s.Close()
+ go func() {
+ for i := byte(0); i < 10; i++ {
+ s.Write([]byte{i})
+ }
+ }()
+
+ l.SetDeadline(time.Now().Add(2 * time.Second))
+ seen := make([]bool, 5)
+ for {
+ var b [512]byte
+ n, _, err := l.ReadFrom(b[:])
+ if err != nil {
+ t.Fatalf("reading from listener: %s", err)
+ }
+ if n != 1 {
+ t.Fatalf("unexpected packet length, want 1, got %d", n)
+ }
+ if b[0] >= 10 {
+ t.Fatalf("unexpected byte, want 0-9, got %d", b[0])
+ }
+ if b[0]%2 != 0 {
+ t.Fatalf("got odd byte %d, wanted only even bytes", b[0])
+ }
+ seen[b[0]/2] = true
+
+ seenAll := true
+ for _, v := range seen {
+ if !v {
+ seenAll = false
+ break
+ }
+ }
+ if seenAll {
+ break
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/control.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/control.go
new file mode 100644
index 000000000..2da644413
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/control.go
@@ -0,0 +1,187 @@
+// Copyright 2013 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 ipv6
+
+import (
+ "fmt"
+ "net"
+ "sync"
+
+ "golang.org/x/net/internal/iana"
+ "golang.org/x/net/internal/socket"
+)
+
+// Note that RFC 3542 obsoletes RFC 2292 but OS X Snow Leopard and the
+// former still support RFC 2292 only. Please be aware that almost
+// all protocol implementations prohibit using a combination of RFC
+// 2292 and RFC 3542 for some practical reasons.
+
+type rawOpt struct {
+ sync.RWMutex
+ cflags ControlFlags
+}
+
+func (c *rawOpt) set(f ControlFlags) { c.cflags |= f }
+func (c *rawOpt) clear(f ControlFlags) { c.cflags &^= f }
+func (c *rawOpt) isset(f ControlFlags) bool { return c.cflags&f != 0 }
+
+// A ControlFlags represents per packet basis IP-level socket option
+// control flags.
+type ControlFlags uint
+
+const (
+ FlagTrafficClass ControlFlags = 1 << iota // pass the traffic class on the received packet
+ FlagHopLimit // pass the hop limit on the received packet
+ FlagSrc // pass the source address on the received packet
+ FlagDst // pass the destination address on the received packet
+ FlagInterface // pass the interface index on the received packet
+ FlagPathMTU // pass the path MTU on the received packet path
+)
+
+const flagPacketInfo = FlagDst | FlagInterface
+
+// A ControlMessage represents per packet basis IP-level socket
+// options.
+type ControlMessage struct {
+ // Receiving socket options: SetControlMessage allows to
+ // receive the options from the protocol stack using ReadFrom
+ // method of PacketConn.
+ //
+ // Specifying socket options: ControlMessage for WriteTo
+ // method of PacketConn allows to send the options to the
+ // protocol stack.
+ //
+ TrafficClass int // traffic class, must be 1 <= value <= 255 when specifying
+ HopLimit int // hop limit, must be 1 <= value <= 255 when specifying
+ Src net.IP // source address, specifying only
+ Dst net.IP // destination address, receiving only
+ IfIndex int // interface index, must be 1 <= value when specifying
+ NextHop net.IP // next hop address, specifying only
+ MTU int // path MTU, receiving only
+}
+
+func (cm *ControlMessage) String() string {
+ if cm == nil {
+ return "<nil>"
+ }
+ return fmt.Sprintf("tclass=%#x hoplim=%d src=%v dst=%v ifindex=%d nexthop=%v mtu=%d", cm.TrafficClass, cm.HopLimit, cm.Src, cm.Dst, cm.IfIndex, cm.NextHop, cm.MTU)
+}
+
+// Marshal returns the binary encoding of cm.
+func (cm *ControlMessage) Marshal() []byte {
+ if cm == nil {
+ return nil
+ }
+ var l int
+ tclass := false
+ if ctlOpts[ctlTrafficClass].name > 0 && cm.TrafficClass > 0 {
+ tclass = true
+ l += socket.ControlMessageSpace(ctlOpts[ctlTrafficClass].length)
+ }
+ hoplimit := false
+ if ctlOpts[ctlHopLimit].name > 0 && cm.HopLimit > 0 {
+ hoplimit = true
+ l += socket.ControlMessageSpace(ctlOpts[ctlHopLimit].length)
+ }
+ pktinfo := false
+ if ctlOpts[ctlPacketInfo].name > 0 && (cm.Src.To16() != nil && cm.Src.To4() == nil || cm.IfIndex > 0) {
+ pktinfo = true
+ l += socket.ControlMessageSpace(ctlOpts[ctlPacketInfo].length)
+ }
+ nexthop := false
+ if ctlOpts[ctlNextHop].name > 0 && cm.NextHop.To16() != nil && cm.NextHop.To4() == nil {
+ nexthop = true
+ l += socket.ControlMessageSpace(ctlOpts[ctlNextHop].length)
+ }
+ var b []byte
+ if l > 0 {
+ b = make([]byte, l)
+ bb := b
+ if tclass {
+ bb = ctlOpts[ctlTrafficClass].marshal(bb, cm)
+ }
+ if hoplimit {
+ bb = ctlOpts[ctlHopLimit].marshal(bb, cm)
+ }
+ if pktinfo {
+ bb = ctlOpts[ctlPacketInfo].marshal(bb, cm)
+ }
+ if nexthop {
+ bb = ctlOpts[ctlNextHop].marshal(bb, cm)
+ }
+ }
+ return b
+}
+
+// Parse parses b as a control message and stores the result in cm.
+func (cm *ControlMessage) Parse(b []byte) error {
+ ms, err := socket.ControlMessage(b).Parse()
+ if err != nil {
+ return err
+ }
+ for _, m := range ms {
+ lvl, typ, l, err := m.ParseHeader()
+ if err != nil {
+ return err
+ }
+ if lvl != iana.ProtocolIPv6 {
+ continue
+ }
+ switch {
+ case typ == ctlOpts[ctlTrafficClass].name && l >= ctlOpts[ctlTrafficClass].length:
+ ctlOpts[ctlTrafficClass].parse(cm, m.Data(l))
+ case typ == ctlOpts[ctlHopLimit].name && l >= ctlOpts[ctlHopLimit].length:
+ ctlOpts[ctlHopLimit].parse(cm, m.Data(l))
+ case typ == ctlOpts[ctlPacketInfo].name && l >= ctlOpts[ctlPacketInfo].length:
+ ctlOpts[ctlPacketInfo].parse(cm, m.Data(l))
+ case typ == ctlOpts[ctlPathMTU].name && l >= ctlOpts[ctlPathMTU].length:
+ ctlOpts[ctlPathMTU].parse(cm, m.Data(l))
+ }
+ }
+ return nil
+}
+
+// NewControlMessage returns a new control message.
+//
+// The returned message is large enough for options specified by cf.
+func NewControlMessage(cf ControlFlags) []byte {
+ opt := rawOpt{cflags: cf}
+ var l int
+ if opt.isset(FlagTrafficClass) && ctlOpts[ctlTrafficClass].name > 0 {
+ l += socket.ControlMessageSpace(ctlOpts[ctlTrafficClass].length)
+ }
+ if opt.isset(FlagHopLimit) && ctlOpts[ctlHopLimit].name > 0 {
+ l += socket.ControlMessageSpace(ctlOpts[ctlHopLimit].length)
+ }
+ if opt.isset(flagPacketInfo) && ctlOpts[ctlPacketInfo].name > 0 {
+ l += socket.ControlMessageSpace(ctlOpts[ctlPacketInfo].length)
+ }
+ if opt.isset(FlagPathMTU) && ctlOpts[ctlPathMTU].name > 0 {
+ l += socket.ControlMessageSpace(ctlOpts[ctlPathMTU].length)
+ }
+ var b []byte
+ if l > 0 {
+ b = make([]byte, l)
+ }
+ return b
+}
+
+// Ancillary data socket options
+const (
+ ctlTrafficClass = iota // header field
+ ctlHopLimit // header field
+ ctlPacketInfo // inbound or outbound packet path
+ ctlNextHop // nexthop
+ ctlPathMTU // path mtu
+ ctlMax
+)
+
+// A ctlOpt represents a binding for ancillary data socket option.
+type ctlOpt struct {
+ name int // option name, must be equal or greater than 1
+ length int // option length
+ marshal func([]byte, *ControlMessage) []byte
+ parse func(*ControlMessage, []byte)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/control_rfc2292_unix.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/control_rfc2292_unix.go
new file mode 100644
index 000000000..9fd9eb15e
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/control_rfc2292_unix.go
@@ -0,0 +1,48 @@
+// Copyright 2013 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.
+
+// +build darwin
+
+package ipv6
+
+import (
+ "unsafe"
+
+ "golang.org/x/net/internal/iana"
+ "golang.org/x/net/internal/socket"
+)
+
+func marshal2292HopLimit(b []byte, cm *ControlMessage) []byte {
+ m := socket.ControlMessage(b)
+ m.MarshalHeader(iana.ProtocolIPv6, sysIPV6_2292HOPLIMIT, 4)
+ if cm != nil {
+ socket.NativeEndian.PutUint32(m.Data(4), uint32(cm.HopLimit))
+ }
+ return m.Next(4)
+}
+
+func marshal2292PacketInfo(b []byte, cm *ControlMessage) []byte {
+ m := socket.ControlMessage(b)
+ m.MarshalHeader(iana.ProtocolIPv6, sysIPV6_2292PKTINFO, sizeofInet6Pktinfo)
+ if cm != nil {
+ pi := (*inet6Pktinfo)(unsafe.Pointer(&m.Data(sizeofInet6Pktinfo)[0]))
+ if ip := cm.Src.To16(); ip != nil && ip.To4() == nil {
+ copy(pi.Addr[:], ip)
+ }
+ if cm.IfIndex > 0 {
+ pi.setIfindex(cm.IfIndex)
+ }
+ }
+ return m.Next(sizeofInet6Pktinfo)
+}
+
+func marshal2292NextHop(b []byte, cm *ControlMessage) []byte {
+ m := socket.ControlMessage(b)
+ m.MarshalHeader(iana.ProtocolIPv6, sysIPV6_2292NEXTHOP, sizeofSockaddrInet6)
+ if cm != nil {
+ sa := (*sockaddrInet6)(unsafe.Pointer(&m.Data(sizeofSockaddrInet6)[0]))
+ sa.setSockaddr(cm.NextHop, cm.IfIndex)
+ }
+ return m.Next(sizeofSockaddrInet6)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/control_rfc3542_unix.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/control_rfc3542_unix.go
new file mode 100644
index 000000000..eec529c20
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/control_rfc3542_unix.go
@@ -0,0 +1,94 @@
+// Copyright 2013 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.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+
+package ipv6
+
+import (
+ "net"
+ "unsafe"
+
+ "golang.org/x/net/internal/iana"
+ "golang.org/x/net/internal/socket"
+)
+
+func marshalTrafficClass(b []byte, cm *ControlMessage) []byte {
+ m := socket.ControlMessage(b)
+ m.MarshalHeader(iana.ProtocolIPv6, sysIPV6_TCLASS, 4)
+ if cm != nil {
+ socket.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]))
+}
+
+func marshalHopLimit(b []byte, cm *ControlMessage) []byte {
+ m := socket.ControlMessage(b)
+ m.MarshalHeader(iana.ProtocolIPv6, sysIPV6_HOPLIMIT, 4)
+ if cm != nil {
+ socket.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]))
+}
+
+func marshalPacketInfo(b []byte, cm *ControlMessage) []byte {
+ m := socket.ControlMessage(b)
+ m.MarshalHeader(iana.ProtocolIPv6, sysIPV6_PKTINFO, sizeofInet6Pktinfo)
+ if cm != nil {
+ pi := (*inet6Pktinfo)(unsafe.Pointer(&m.Data(sizeofInet6Pktinfo)[0]))
+ if ip := cm.Src.To16(); ip != nil && ip.To4() == nil {
+ copy(pi.Addr[:], ip)
+ }
+ if cm.IfIndex > 0 {
+ pi.setIfindex(cm.IfIndex)
+ }
+ }
+ return m.Next(sizeofInet6Pktinfo)
+}
+
+func parsePacketInfo(cm *ControlMessage, b []byte) {
+ pi := (*inet6Pktinfo)(unsafe.Pointer(&b[0]))
+ if len(cm.Dst) < net.IPv6len {
+ cm.Dst = make(net.IP, net.IPv6len)
+ }
+ copy(cm.Dst, pi.Addr[:])
+ cm.IfIndex = int(pi.Ifindex)
+}
+
+func marshalNextHop(b []byte, cm *ControlMessage) []byte {
+ m := socket.ControlMessage(b)
+ m.MarshalHeader(iana.ProtocolIPv6, sysIPV6_NEXTHOP, sizeofSockaddrInet6)
+ if cm != nil {
+ sa := (*sockaddrInet6)(unsafe.Pointer(&m.Data(sizeofSockaddrInet6)[0]))
+ sa.setSockaddr(cm.NextHop, cm.IfIndex)
+ }
+ return m.Next(sizeofSockaddrInet6)
+}
+
+func parseNextHop(cm *ControlMessage, b []byte) {
+}
+
+func marshalPathMTU(b []byte, cm *ControlMessage) []byte {
+ m := socket.ControlMessage(b)
+ m.MarshalHeader(iana.ProtocolIPv6, sysIPV6_PATHMTU, sizeofIPv6Mtuinfo)
+ return m.Next(sizeofIPv6Mtuinfo)
+}
+
+func parsePathMTU(cm *ControlMessage, b []byte) {
+ mi := (*ipv6Mtuinfo)(unsafe.Pointer(&b[0]))
+ if len(cm.Dst) < net.IPv6len {
+ cm.Dst = make(net.IP, net.IPv6len)
+ }
+ copy(cm.Dst, mi.Addr.Addr[:])
+ cm.IfIndex = int(mi.Addr.Scope_id)
+ cm.MTU = int(mi.Mtu)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/control_stub.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/control_stub.go
new file mode 100644
index 000000000..a045f28f7
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/control_stub.go
@@ -0,0 +1,13 @@
+// Copyright 2013 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.
+
+// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows
+
+package ipv6
+
+import "golang.org/x/net/internal/socket"
+
+func setControlMessage(c *socket.Conn, opt *rawOpt, cf ControlFlags, on bool) error {
+ return errOpNoSupport
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/control_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/control_test.go
new file mode 100644
index 000000000..c186ca99f
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/control_test.go
@@ -0,0 +1,21 @@
+// 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 ipv6_test
+
+import (
+ "testing"
+
+ "golang.org/x/net/ipv6"
+)
+
+func TestControlMessageParseWithFuzz(t *testing.T) {
+ var cm ipv6.ControlMessage
+ for _, fuzz := range []string{
+ "\f\x00\x00\x00)\x00\x00\x00.\x00\x00\x00",
+ "\f\x00\x00\x00)\x00\x00\x00,\x00\x00\x00",
+ } {
+ cm.Parse([]byte(fuzz))
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/control_unix.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/control_unix.go
new file mode 100644
index 000000000..66515060a
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/control_unix.go
@@ -0,0 +1,55 @@
+// Copyright 2013 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.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+
+package ipv6
+
+import "golang.org/x/net/internal/socket"
+
+func setControlMessage(c *socket.Conn, opt *rawOpt, cf ControlFlags, on bool) error {
+ opt.Lock()
+ defer opt.Unlock()
+ if so, ok := sockOpts[ssoReceiveTrafficClass]; ok && cf&FlagTrafficClass != 0 {
+ if err := so.SetInt(c, boolint(on)); err != nil {
+ return err
+ }
+ if on {
+ opt.set(FlagTrafficClass)
+ } else {
+ opt.clear(FlagTrafficClass)
+ }
+ }
+ if so, ok := sockOpts[ssoReceiveHopLimit]; ok && cf&FlagHopLimit != 0 {
+ if err := so.SetInt(c, boolint(on)); err != nil {
+ return err
+ }
+ if on {
+ opt.set(FlagHopLimit)
+ } else {
+ opt.clear(FlagHopLimit)
+ }
+ }
+ if so, ok := sockOpts[ssoReceivePacketInfo]; ok && cf&flagPacketInfo != 0 {
+ if err := so.SetInt(c, boolint(on)); err != nil {
+ return err
+ }
+ if on {
+ opt.set(cf & flagPacketInfo)
+ } else {
+ opt.clear(cf & flagPacketInfo)
+ }
+ }
+ if so, ok := sockOpts[ssoReceivePathMTU]; ok && cf&FlagPathMTU != 0 {
+ if err := so.SetInt(c, boolint(on)); err != nil {
+ return err
+ }
+ if on {
+ opt.set(FlagPathMTU)
+ } else {
+ opt.clear(FlagPathMTU)
+ }
+ }
+ return nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/control_windows.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/control_windows.go
new file mode 100644
index 000000000..ef2563b3f
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/control_windows.go
@@ -0,0 +1,16 @@
+// Copyright 2013 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 ipv6
+
+import (
+ "syscall"
+
+ "golang.org/x/net/internal/socket"
+)
+
+func setControlMessage(c *socket.Conn, opt *rawOpt, cf ControlFlags, on bool) error {
+ // TODO(mikio): implement this
+ return syscall.EWINDOWS
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/defs_darwin.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/defs_darwin.go
new file mode 100644
index 000000000..55ddc116f
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/defs_darwin.go
@@ -0,0 +1,112 @@
+// Copyright 2014 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.
+
+// +build ignore
+
+// +godefs map struct_in6_addr [16]byte /* in6_addr */
+
+package ipv6
+
+/*
+#define __APPLE_USE_RFC_3542
+#include <netinet/in.h>
+#include <netinet/icmp6.h>
+*/
+import "C"
+
+const (
+ sysIPV6_UNICAST_HOPS = C.IPV6_UNICAST_HOPS
+ sysIPV6_MULTICAST_IF = C.IPV6_MULTICAST_IF
+ sysIPV6_MULTICAST_HOPS = C.IPV6_MULTICAST_HOPS
+ sysIPV6_MULTICAST_LOOP = C.IPV6_MULTICAST_LOOP
+ sysIPV6_JOIN_GROUP = C.IPV6_JOIN_GROUP
+ sysIPV6_LEAVE_GROUP = C.IPV6_LEAVE_GROUP
+
+ sysIPV6_PORTRANGE = C.IPV6_PORTRANGE
+ sysICMP6_FILTER = C.ICMP6_FILTER
+ sysIPV6_2292PKTINFO = C.IPV6_2292PKTINFO
+ sysIPV6_2292HOPLIMIT = C.IPV6_2292HOPLIMIT
+ sysIPV6_2292NEXTHOP = C.IPV6_2292NEXTHOP
+ sysIPV6_2292HOPOPTS = C.IPV6_2292HOPOPTS
+ sysIPV6_2292DSTOPTS = C.IPV6_2292DSTOPTS
+ sysIPV6_2292RTHDR = C.IPV6_2292RTHDR
+
+ sysIPV6_2292PKTOPTIONS = C.IPV6_2292PKTOPTIONS
+
+ sysIPV6_CHECKSUM = C.IPV6_CHECKSUM
+ sysIPV6_V6ONLY = C.IPV6_V6ONLY
+
+ sysIPV6_IPSEC_POLICY = C.IPV6_IPSEC_POLICY
+
+ sysIPV6_RECVTCLASS = C.IPV6_RECVTCLASS
+ sysIPV6_TCLASS = C.IPV6_TCLASS
+
+ sysIPV6_RTHDRDSTOPTS = C.IPV6_RTHDRDSTOPTS
+
+ sysIPV6_RECVPKTINFO = C.IPV6_RECVPKTINFO
+
+ sysIPV6_RECVHOPLIMIT = C.IPV6_RECVHOPLIMIT
+ sysIPV6_RECVRTHDR = C.IPV6_RECVRTHDR
+ sysIPV6_RECVHOPOPTS = C.IPV6_RECVHOPOPTS
+ sysIPV6_RECVDSTOPTS = C.IPV6_RECVDSTOPTS
+
+ sysIPV6_USE_MIN_MTU = C.IPV6_USE_MIN_MTU
+ sysIPV6_RECVPATHMTU = C.IPV6_RECVPATHMTU
+
+ sysIPV6_PATHMTU = C.IPV6_PATHMTU
+
+ sysIPV6_PKTINFO = C.IPV6_PKTINFO
+ sysIPV6_HOPLIMIT = C.IPV6_HOPLIMIT
+ sysIPV6_NEXTHOP = C.IPV6_NEXTHOP
+ sysIPV6_HOPOPTS = C.IPV6_HOPOPTS
+ sysIPV6_DSTOPTS = C.IPV6_DSTOPTS
+ sysIPV6_RTHDR = C.IPV6_RTHDR
+
+ sysIPV6_AUTOFLOWLABEL = C.IPV6_AUTOFLOWLABEL
+
+ sysIPV6_DONTFRAG = C.IPV6_DONTFRAG
+
+ sysIPV6_PREFER_TEMPADDR = C.IPV6_PREFER_TEMPADDR
+
+ sysIPV6_MSFILTER = C.IPV6_MSFILTER
+ sysMCAST_JOIN_GROUP = C.MCAST_JOIN_GROUP
+ sysMCAST_LEAVE_GROUP = C.MCAST_LEAVE_GROUP
+ sysMCAST_JOIN_SOURCE_GROUP = C.MCAST_JOIN_SOURCE_GROUP
+ sysMCAST_LEAVE_SOURCE_GROUP = C.MCAST_LEAVE_SOURCE_GROUP
+ sysMCAST_BLOCK_SOURCE = C.MCAST_BLOCK_SOURCE
+ sysMCAST_UNBLOCK_SOURCE = C.MCAST_UNBLOCK_SOURCE
+
+ sysIPV6_BOUND_IF = C.IPV6_BOUND_IF
+
+ sysIPV6_PORTRANGE_DEFAULT = C.IPV6_PORTRANGE_DEFAULT
+ sysIPV6_PORTRANGE_HIGH = C.IPV6_PORTRANGE_HIGH
+ sysIPV6_PORTRANGE_LOW = C.IPV6_PORTRANGE_LOW
+
+ sizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage
+ sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
+ sizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
+ sizeofIPv6Mtuinfo = C.sizeof_struct_ip6_mtuinfo
+
+ sizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
+ sizeofGroupReq = C.sizeof_struct_group_req
+ sizeofGroupSourceReq = C.sizeof_struct_group_source_req
+
+ sizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
+)
+
+type sockaddrStorage C.struct_sockaddr_storage
+
+type sockaddrInet6 C.struct_sockaddr_in6
+
+type inet6Pktinfo C.struct_in6_pktinfo
+
+type ipv6Mtuinfo C.struct_ip6_mtuinfo
+
+type ipv6Mreq C.struct_ipv6_mreq
+
+type icmpv6Filter C.struct_icmp6_filter
+
+type groupReq C.struct_group_req
+
+type groupSourceReq C.struct_group_source_req
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/defs_dragonfly.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/defs_dragonfly.go
new file mode 100644
index 000000000..a4c383a51
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/defs_dragonfly.go
@@ -0,0 +1,84 @@
+// Copyright 2014 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.
+
+// +build ignore
+
+// +godefs map struct_in6_addr [16]byte /* in6_addr */
+
+package ipv6
+
+/*
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <netinet/icmp6.h>
+*/
+import "C"
+
+const (
+ sysIPV6_UNICAST_HOPS = C.IPV6_UNICAST_HOPS
+ sysIPV6_MULTICAST_IF = C.IPV6_MULTICAST_IF
+ sysIPV6_MULTICAST_HOPS = C.IPV6_MULTICAST_HOPS
+ sysIPV6_MULTICAST_LOOP = C.IPV6_MULTICAST_LOOP
+ sysIPV6_JOIN_GROUP = C.IPV6_JOIN_GROUP
+ sysIPV6_LEAVE_GROUP = C.IPV6_LEAVE_GROUP
+ sysIPV6_PORTRANGE = C.IPV6_PORTRANGE
+ sysICMP6_FILTER = C.ICMP6_FILTER
+
+ sysIPV6_CHECKSUM = C.IPV6_CHECKSUM
+ sysIPV6_V6ONLY = C.IPV6_V6ONLY
+
+ sysIPV6_IPSEC_POLICY = C.IPV6_IPSEC_POLICY
+
+ sysIPV6_RTHDRDSTOPTS = C.IPV6_RTHDRDSTOPTS
+ sysIPV6_RECVPKTINFO = C.IPV6_RECVPKTINFO
+ sysIPV6_RECVHOPLIMIT = C.IPV6_RECVHOPLIMIT
+ sysIPV6_RECVRTHDR = C.IPV6_RECVRTHDR
+ sysIPV6_RECVHOPOPTS = C.IPV6_RECVHOPOPTS
+ sysIPV6_RECVDSTOPTS = C.IPV6_RECVDSTOPTS
+
+ sysIPV6_USE_MIN_MTU = C.IPV6_USE_MIN_MTU
+ sysIPV6_RECVPATHMTU = C.IPV6_RECVPATHMTU
+
+ sysIPV6_PATHMTU = C.IPV6_PATHMTU
+
+ sysIPV6_PKTINFO = C.IPV6_PKTINFO
+ sysIPV6_HOPLIMIT = C.IPV6_HOPLIMIT
+ sysIPV6_NEXTHOP = C.IPV6_NEXTHOP
+ sysIPV6_HOPOPTS = C.IPV6_HOPOPTS
+ sysIPV6_DSTOPTS = C.IPV6_DSTOPTS
+ sysIPV6_RTHDR = C.IPV6_RTHDR
+
+ sysIPV6_RECVTCLASS = C.IPV6_RECVTCLASS
+
+ sysIPV6_AUTOFLOWLABEL = C.IPV6_AUTOFLOWLABEL
+
+ sysIPV6_TCLASS = C.IPV6_TCLASS
+ sysIPV6_DONTFRAG = C.IPV6_DONTFRAG
+
+ sysIPV6_PREFER_TEMPADDR = C.IPV6_PREFER_TEMPADDR
+
+ sysIPV6_PORTRANGE_DEFAULT = C.IPV6_PORTRANGE_DEFAULT
+ sysIPV6_PORTRANGE_HIGH = C.IPV6_PORTRANGE_HIGH
+ sysIPV6_PORTRANGE_LOW = C.IPV6_PORTRANGE_LOW
+
+ sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
+ sizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
+ sizeofIPv6Mtuinfo = C.sizeof_struct_ip6_mtuinfo
+
+ sizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
+
+ sizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
+)
+
+type sockaddrInet6 C.struct_sockaddr_in6
+
+type inet6Pktinfo C.struct_in6_pktinfo
+
+type ipv6Mtuinfo C.struct_ip6_mtuinfo
+
+type ipv6Mreq C.struct_ipv6_mreq
+
+type icmpv6Filter C.struct_icmp6_filter
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/defs_freebsd.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/defs_freebsd.go
new file mode 100644
index 000000000..53e625389
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/defs_freebsd.go
@@ -0,0 +1,105 @@
+// Copyright 2014 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.
+
+// +build ignore
+
+// +godefs map struct_in6_addr [16]byte /* in6_addr */
+
+package ipv6
+
+/*
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <netinet/icmp6.h>
+*/
+import "C"
+
+const (
+ sysIPV6_UNICAST_HOPS = C.IPV6_UNICAST_HOPS
+ sysIPV6_MULTICAST_IF = C.IPV6_MULTICAST_IF
+ sysIPV6_MULTICAST_HOPS = C.IPV6_MULTICAST_HOPS
+ sysIPV6_MULTICAST_LOOP = C.IPV6_MULTICAST_LOOP
+ sysIPV6_JOIN_GROUP = C.IPV6_JOIN_GROUP
+ sysIPV6_LEAVE_GROUP = C.IPV6_LEAVE_GROUP
+ sysIPV6_PORTRANGE = C.IPV6_PORTRANGE
+ sysICMP6_FILTER = C.ICMP6_FILTER
+
+ sysIPV6_CHECKSUM = C.IPV6_CHECKSUM
+ sysIPV6_V6ONLY = C.IPV6_V6ONLY
+
+ sysIPV6_IPSEC_POLICY = C.IPV6_IPSEC_POLICY
+
+ sysIPV6_RTHDRDSTOPTS = C.IPV6_RTHDRDSTOPTS
+
+ sysIPV6_RECVPKTINFO = C.IPV6_RECVPKTINFO
+ sysIPV6_RECVHOPLIMIT = C.IPV6_RECVHOPLIMIT
+ sysIPV6_RECVRTHDR = C.IPV6_RECVRTHDR
+ sysIPV6_RECVHOPOPTS = C.IPV6_RECVHOPOPTS
+ sysIPV6_RECVDSTOPTS = C.IPV6_RECVDSTOPTS
+
+ sysIPV6_USE_MIN_MTU = C.IPV6_USE_MIN_MTU
+ sysIPV6_RECVPATHMTU = C.IPV6_RECVPATHMTU
+
+ sysIPV6_PATHMTU = C.IPV6_PATHMTU
+
+ sysIPV6_PKTINFO = C.IPV6_PKTINFO
+ sysIPV6_HOPLIMIT = C.IPV6_HOPLIMIT
+ sysIPV6_NEXTHOP = C.IPV6_NEXTHOP
+ sysIPV6_HOPOPTS = C.IPV6_HOPOPTS
+ sysIPV6_DSTOPTS = C.IPV6_DSTOPTS
+ sysIPV6_RTHDR = C.IPV6_RTHDR
+
+ sysIPV6_RECVTCLASS = C.IPV6_RECVTCLASS
+
+ sysIPV6_AUTOFLOWLABEL = C.IPV6_AUTOFLOWLABEL
+
+ sysIPV6_TCLASS = C.IPV6_TCLASS
+ sysIPV6_DONTFRAG = C.IPV6_DONTFRAG
+
+ sysIPV6_PREFER_TEMPADDR = C.IPV6_PREFER_TEMPADDR
+
+ sysIPV6_BINDANY = C.IPV6_BINDANY
+
+ sysIPV6_MSFILTER = C.IPV6_MSFILTER
+
+ sysMCAST_JOIN_GROUP = C.MCAST_JOIN_GROUP
+ sysMCAST_LEAVE_GROUP = C.MCAST_LEAVE_GROUP
+ sysMCAST_JOIN_SOURCE_GROUP = C.MCAST_JOIN_SOURCE_GROUP
+ sysMCAST_LEAVE_SOURCE_GROUP = C.MCAST_LEAVE_SOURCE_GROUP
+ sysMCAST_BLOCK_SOURCE = C.MCAST_BLOCK_SOURCE
+ sysMCAST_UNBLOCK_SOURCE = C.MCAST_UNBLOCK_SOURCE
+
+ sysIPV6_PORTRANGE_DEFAULT = C.IPV6_PORTRANGE_DEFAULT
+ sysIPV6_PORTRANGE_HIGH = C.IPV6_PORTRANGE_HIGH
+ sysIPV6_PORTRANGE_LOW = C.IPV6_PORTRANGE_LOW
+
+ sizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage
+ sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
+ sizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
+ sizeofIPv6Mtuinfo = C.sizeof_struct_ip6_mtuinfo
+
+ sizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
+ sizeofGroupReq = C.sizeof_struct_group_req
+ sizeofGroupSourceReq = C.sizeof_struct_group_source_req
+
+ sizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
+)
+
+type sockaddrStorage C.struct_sockaddr_storage
+
+type sockaddrInet6 C.struct_sockaddr_in6
+
+type inet6Pktinfo C.struct_in6_pktinfo
+
+type ipv6Mtuinfo C.struct_ip6_mtuinfo
+
+type ipv6Mreq C.struct_ipv6_mreq
+
+type groupReq C.struct_group_req
+
+type groupSourceReq C.struct_group_source_req
+
+type icmpv6Filter C.struct_icmp6_filter
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/defs_linux.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/defs_linux.go
new file mode 100644
index 000000000..3308cb2c3
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/defs_linux.go
@@ -0,0 +1,147 @@
+// Copyright 2014 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.
+
+// +build ignore
+
+// +godefs map struct_in6_addr [16]byte /* in6_addr */
+
+package ipv6
+
+/*
+#include <linux/in.h>
+#include <linux/in6.h>
+#include <linux/ipv6.h>
+#include <linux/icmpv6.h>
+#include <linux/filter.h>
+#include <sys/socket.h>
+*/
+import "C"
+
+const (
+ sysIPV6_ADDRFORM = C.IPV6_ADDRFORM
+ sysIPV6_2292PKTINFO = C.IPV6_2292PKTINFO
+ sysIPV6_2292HOPOPTS = C.IPV6_2292HOPOPTS
+ sysIPV6_2292DSTOPTS = C.IPV6_2292DSTOPTS
+ sysIPV6_2292RTHDR = C.IPV6_2292RTHDR
+ sysIPV6_2292PKTOPTIONS = C.IPV6_2292PKTOPTIONS
+ sysIPV6_CHECKSUM = C.IPV6_CHECKSUM
+ sysIPV6_2292HOPLIMIT = C.IPV6_2292HOPLIMIT
+ sysIPV6_NEXTHOP = C.IPV6_NEXTHOP
+ sysIPV6_FLOWINFO = C.IPV6_FLOWINFO
+
+ sysIPV6_UNICAST_HOPS = C.IPV6_UNICAST_HOPS
+ sysIPV6_MULTICAST_IF = C.IPV6_MULTICAST_IF
+ sysIPV6_MULTICAST_HOPS = C.IPV6_MULTICAST_HOPS
+ sysIPV6_MULTICAST_LOOP = C.IPV6_MULTICAST_LOOP
+ sysIPV6_ADD_MEMBERSHIP = C.IPV6_ADD_MEMBERSHIP
+ sysIPV6_DROP_MEMBERSHIP = C.IPV6_DROP_MEMBERSHIP
+ sysMCAST_JOIN_GROUP = C.MCAST_JOIN_GROUP
+ sysMCAST_LEAVE_GROUP = C.MCAST_LEAVE_GROUP
+ sysMCAST_JOIN_SOURCE_GROUP = C.MCAST_JOIN_SOURCE_GROUP
+ sysMCAST_LEAVE_SOURCE_GROUP = C.MCAST_LEAVE_SOURCE_GROUP
+ sysMCAST_BLOCK_SOURCE = C.MCAST_BLOCK_SOURCE
+ sysMCAST_UNBLOCK_SOURCE = C.MCAST_UNBLOCK_SOURCE
+ sysMCAST_MSFILTER = C.MCAST_MSFILTER
+ sysIPV6_ROUTER_ALERT = C.IPV6_ROUTER_ALERT
+ sysIPV6_MTU_DISCOVER = C.IPV6_MTU_DISCOVER
+ sysIPV6_MTU = C.IPV6_MTU
+ sysIPV6_RECVERR = C.IPV6_RECVERR
+ sysIPV6_V6ONLY = C.IPV6_V6ONLY
+ sysIPV6_JOIN_ANYCAST = C.IPV6_JOIN_ANYCAST
+ sysIPV6_LEAVE_ANYCAST = C.IPV6_LEAVE_ANYCAST
+
+ //sysIPV6_PMTUDISC_DONT = C.IPV6_PMTUDISC_DONT
+ //sysIPV6_PMTUDISC_WANT = C.IPV6_PMTUDISC_WANT
+ //sysIPV6_PMTUDISC_DO = C.IPV6_PMTUDISC_DO
+ //sysIPV6_PMTUDISC_PROBE = C.IPV6_PMTUDISC_PROBE
+ //sysIPV6_PMTUDISC_INTERFACE = C.IPV6_PMTUDISC_INTERFACE
+ //sysIPV6_PMTUDISC_OMIT = C.IPV6_PMTUDISC_OMIT
+
+ sysIPV6_FLOWLABEL_MGR = C.IPV6_FLOWLABEL_MGR
+ sysIPV6_FLOWINFO_SEND = C.IPV6_FLOWINFO_SEND
+
+ sysIPV6_IPSEC_POLICY = C.IPV6_IPSEC_POLICY
+ sysIPV6_XFRM_POLICY = C.IPV6_XFRM_POLICY
+
+ sysIPV6_RECVPKTINFO = C.IPV6_RECVPKTINFO
+ sysIPV6_PKTINFO = C.IPV6_PKTINFO
+ sysIPV6_RECVHOPLIMIT = C.IPV6_RECVHOPLIMIT
+ sysIPV6_HOPLIMIT = C.IPV6_HOPLIMIT
+ sysIPV6_RECVHOPOPTS = C.IPV6_RECVHOPOPTS
+ sysIPV6_HOPOPTS = C.IPV6_HOPOPTS
+ sysIPV6_RTHDRDSTOPTS = C.IPV6_RTHDRDSTOPTS
+ sysIPV6_RECVRTHDR = C.IPV6_RECVRTHDR
+ sysIPV6_RTHDR = C.IPV6_RTHDR
+ sysIPV6_RECVDSTOPTS = C.IPV6_RECVDSTOPTS
+ sysIPV6_DSTOPTS = C.IPV6_DSTOPTS
+ sysIPV6_RECVPATHMTU = C.IPV6_RECVPATHMTU
+ sysIPV6_PATHMTU = C.IPV6_PATHMTU
+ sysIPV6_DONTFRAG = C.IPV6_DONTFRAG
+
+ sysIPV6_RECVTCLASS = C.IPV6_RECVTCLASS
+ sysIPV6_TCLASS = C.IPV6_TCLASS
+
+ sysIPV6_ADDR_PREFERENCES = C.IPV6_ADDR_PREFERENCES
+
+ sysIPV6_PREFER_SRC_TMP = C.IPV6_PREFER_SRC_TMP
+ sysIPV6_PREFER_SRC_PUBLIC = C.IPV6_PREFER_SRC_PUBLIC
+ sysIPV6_PREFER_SRC_PUBTMP_DEFAULT = C.IPV6_PREFER_SRC_PUBTMP_DEFAULT
+ sysIPV6_PREFER_SRC_COA = C.IPV6_PREFER_SRC_COA
+ sysIPV6_PREFER_SRC_HOME = C.IPV6_PREFER_SRC_HOME
+ sysIPV6_PREFER_SRC_CGA = C.IPV6_PREFER_SRC_CGA
+ sysIPV6_PREFER_SRC_NONCGA = C.IPV6_PREFER_SRC_NONCGA
+
+ sysIPV6_MINHOPCOUNT = C.IPV6_MINHOPCOUNT
+
+ sysIPV6_ORIGDSTADDR = C.IPV6_ORIGDSTADDR
+ sysIPV6_RECVORIGDSTADDR = C.IPV6_RECVORIGDSTADDR
+ sysIPV6_TRANSPARENT = C.IPV6_TRANSPARENT
+ sysIPV6_UNICAST_IF = C.IPV6_UNICAST_IF
+
+ sysICMPV6_FILTER = C.ICMPV6_FILTER
+
+ sysICMPV6_FILTER_BLOCK = C.ICMPV6_FILTER_BLOCK
+ sysICMPV6_FILTER_PASS = C.ICMPV6_FILTER_PASS
+ sysICMPV6_FILTER_BLOCKOTHERS = C.ICMPV6_FILTER_BLOCKOTHERS
+ sysICMPV6_FILTER_PASSONLY = C.ICMPV6_FILTER_PASSONLY
+
+ sysSOL_SOCKET = C.SOL_SOCKET
+ sysSO_ATTACH_FILTER = C.SO_ATTACH_FILTER
+
+ sizeofKernelSockaddrStorage = C.sizeof_struct___kernel_sockaddr_storage
+ sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
+ sizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
+ sizeofIPv6Mtuinfo = C.sizeof_struct_ip6_mtuinfo
+ sizeofIPv6FlowlabelReq = C.sizeof_struct_in6_flowlabel_req
+
+ sizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
+ sizeofGroupReq = C.sizeof_struct_group_req
+ sizeofGroupSourceReq = C.sizeof_struct_group_source_req
+
+ sizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
+
+ sizeofSockFprog = C.sizeof_struct_sock_fprog
+)
+
+type kernelSockaddrStorage C.struct___kernel_sockaddr_storage
+
+type sockaddrInet6 C.struct_sockaddr_in6
+
+type inet6Pktinfo C.struct_in6_pktinfo
+
+type ipv6Mtuinfo C.struct_ip6_mtuinfo
+
+type ipv6FlowlabelReq C.struct_in6_flowlabel_req
+
+type ipv6Mreq C.struct_ipv6_mreq
+
+type groupReq C.struct_group_req
+
+type groupSourceReq C.struct_group_source_req
+
+type icmpv6Filter C.struct_icmp6_filter
+
+type sockFProg C.struct_sock_fprog
+
+type sockFilter C.struct_sock_filter
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/defs_netbsd.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/defs_netbsd.go
new file mode 100644
index 000000000..be9ceb9cc
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/defs_netbsd.go
@@ -0,0 +1,80 @@
+// Copyright 2014 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.
+
+// +build ignore
+
+// +godefs map struct_in6_addr [16]byte /* in6_addr */
+
+package ipv6
+
+/*
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <netinet/icmp6.h>
+*/
+import "C"
+
+const (
+ sysIPV6_UNICAST_HOPS = C.IPV6_UNICAST_HOPS
+ sysIPV6_MULTICAST_IF = C.IPV6_MULTICAST_IF
+ sysIPV6_MULTICAST_HOPS = C.IPV6_MULTICAST_HOPS
+ sysIPV6_MULTICAST_LOOP = C.IPV6_MULTICAST_LOOP
+ sysIPV6_JOIN_GROUP = C.IPV6_JOIN_GROUP
+ sysIPV6_LEAVE_GROUP = C.IPV6_LEAVE_GROUP
+ sysIPV6_PORTRANGE = C.IPV6_PORTRANGE
+ sysICMP6_FILTER = C.ICMP6_FILTER
+
+ sysIPV6_CHECKSUM = C.IPV6_CHECKSUM
+ sysIPV6_V6ONLY = C.IPV6_V6ONLY
+
+ sysIPV6_IPSEC_POLICY = C.IPV6_IPSEC_POLICY
+
+ sysIPV6_RTHDRDSTOPTS = C.IPV6_RTHDRDSTOPTS
+
+ sysIPV6_RECVPKTINFO = C.IPV6_RECVPKTINFO
+ sysIPV6_RECVHOPLIMIT = C.IPV6_RECVHOPLIMIT
+ sysIPV6_RECVRTHDR = C.IPV6_RECVRTHDR
+ sysIPV6_RECVHOPOPTS = C.IPV6_RECVHOPOPTS
+ sysIPV6_RECVDSTOPTS = C.IPV6_RECVDSTOPTS
+
+ sysIPV6_USE_MIN_MTU = C.IPV6_USE_MIN_MTU
+ sysIPV6_RECVPATHMTU = C.IPV6_RECVPATHMTU
+ sysIPV6_PATHMTU = C.IPV6_PATHMTU
+
+ sysIPV6_PKTINFO = C.IPV6_PKTINFO
+ sysIPV6_HOPLIMIT = C.IPV6_HOPLIMIT
+ sysIPV6_NEXTHOP = C.IPV6_NEXTHOP
+ sysIPV6_HOPOPTS = C.IPV6_HOPOPTS
+ sysIPV6_DSTOPTS = C.IPV6_DSTOPTS
+ sysIPV6_RTHDR = C.IPV6_RTHDR
+
+ sysIPV6_RECVTCLASS = C.IPV6_RECVTCLASS
+
+ sysIPV6_TCLASS = C.IPV6_TCLASS
+ sysIPV6_DONTFRAG = C.IPV6_DONTFRAG
+
+ sysIPV6_PORTRANGE_DEFAULT = C.IPV6_PORTRANGE_DEFAULT
+ sysIPV6_PORTRANGE_HIGH = C.IPV6_PORTRANGE_HIGH
+ sysIPV6_PORTRANGE_LOW = C.IPV6_PORTRANGE_LOW
+
+ sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
+ sizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
+ sizeofIPv6Mtuinfo = C.sizeof_struct_ip6_mtuinfo
+
+ sizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
+
+ sizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
+)
+
+type sockaddrInet6 C.struct_sockaddr_in6
+
+type inet6Pktinfo C.struct_in6_pktinfo
+
+type ipv6Mtuinfo C.struct_ip6_mtuinfo
+
+type ipv6Mreq C.struct_ipv6_mreq
+
+type icmpv6Filter C.struct_icmp6_filter
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/defs_openbsd.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/defs_openbsd.go
new file mode 100644
index 000000000..177ddf87d
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/defs_openbsd.go
@@ -0,0 +1,89 @@
+// Copyright 2014 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.
+
+// +build ignore
+
+// +godefs map struct_in6_addr [16]byte /* in6_addr */
+
+package ipv6
+
+/*
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <netinet/icmp6.h>
+*/
+import "C"
+
+const (
+ sysIPV6_UNICAST_HOPS = C.IPV6_UNICAST_HOPS
+ sysIPV6_MULTICAST_IF = C.IPV6_MULTICAST_IF
+ sysIPV6_MULTICAST_HOPS = C.IPV6_MULTICAST_HOPS
+ sysIPV6_MULTICAST_LOOP = C.IPV6_MULTICAST_LOOP
+ sysIPV6_JOIN_GROUP = C.IPV6_JOIN_GROUP
+ sysIPV6_LEAVE_GROUP = C.IPV6_LEAVE_GROUP
+ sysIPV6_PORTRANGE = C.IPV6_PORTRANGE
+ sysICMP6_FILTER = C.ICMP6_FILTER
+
+ sysIPV6_CHECKSUM = C.IPV6_CHECKSUM
+ sysIPV6_V6ONLY = C.IPV6_V6ONLY
+
+ sysIPV6_RTHDRDSTOPTS = C.IPV6_RTHDRDSTOPTS
+
+ sysIPV6_RECVPKTINFO = C.IPV6_RECVPKTINFO
+ sysIPV6_RECVHOPLIMIT = C.IPV6_RECVHOPLIMIT
+ sysIPV6_RECVRTHDR = C.IPV6_RECVRTHDR
+ sysIPV6_RECVHOPOPTS = C.IPV6_RECVHOPOPTS
+ sysIPV6_RECVDSTOPTS = C.IPV6_RECVDSTOPTS
+
+ sysIPV6_USE_MIN_MTU = C.IPV6_USE_MIN_MTU
+ sysIPV6_RECVPATHMTU = C.IPV6_RECVPATHMTU
+
+ sysIPV6_PATHMTU = C.IPV6_PATHMTU
+
+ sysIPV6_PKTINFO = C.IPV6_PKTINFO
+ sysIPV6_HOPLIMIT = C.IPV6_HOPLIMIT
+ sysIPV6_NEXTHOP = C.IPV6_NEXTHOP
+ sysIPV6_HOPOPTS = C.IPV6_HOPOPTS
+ sysIPV6_DSTOPTS = C.IPV6_DSTOPTS
+ sysIPV6_RTHDR = C.IPV6_RTHDR
+
+ sysIPV6_AUTH_LEVEL = C.IPV6_AUTH_LEVEL
+ sysIPV6_ESP_TRANS_LEVEL = C.IPV6_ESP_TRANS_LEVEL
+ sysIPV6_ESP_NETWORK_LEVEL = C.IPV6_ESP_NETWORK_LEVEL
+ sysIPSEC6_OUTSA = C.IPSEC6_OUTSA
+ sysIPV6_RECVTCLASS = C.IPV6_RECVTCLASS
+
+ sysIPV6_AUTOFLOWLABEL = C.IPV6_AUTOFLOWLABEL
+ sysIPV6_IPCOMP_LEVEL = C.IPV6_IPCOMP_LEVEL
+
+ sysIPV6_TCLASS = C.IPV6_TCLASS
+ sysIPV6_DONTFRAG = C.IPV6_DONTFRAG
+ sysIPV6_PIPEX = C.IPV6_PIPEX
+
+ sysIPV6_RTABLE = C.IPV6_RTABLE
+
+ sysIPV6_PORTRANGE_DEFAULT = C.IPV6_PORTRANGE_DEFAULT
+ sysIPV6_PORTRANGE_HIGH = C.IPV6_PORTRANGE_HIGH
+ sysIPV6_PORTRANGE_LOW = C.IPV6_PORTRANGE_LOW
+
+ sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
+ sizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
+ sizeofIPv6Mtuinfo = C.sizeof_struct_ip6_mtuinfo
+
+ sizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
+
+ sizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
+)
+
+type sockaddrInet6 C.struct_sockaddr_in6
+
+type inet6Pktinfo C.struct_in6_pktinfo
+
+type ipv6Mtuinfo C.struct_ip6_mtuinfo
+
+type ipv6Mreq C.struct_ipv6_mreq
+
+type icmpv6Filter C.struct_icmp6_filter
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/defs_solaris.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/defs_solaris.go
new file mode 100644
index 000000000..0f8ce2b46
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/defs_solaris.go
@@ -0,0 +1,114 @@
+// Copyright 2014 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.
+
+// +build ignore
+
+// +godefs map struct_in6_addr [16]byte /* in6_addr */
+
+package ipv6
+
+/*
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <netinet/icmp6.h>
+*/
+import "C"
+
+const (
+ sysIPV6_UNICAST_HOPS = C.IPV6_UNICAST_HOPS
+ sysIPV6_MULTICAST_IF = C.IPV6_MULTICAST_IF
+ sysIPV6_MULTICAST_HOPS = C.IPV6_MULTICAST_HOPS
+ sysIPV6_MULTICAST_LOOP = C.IPV6_MULTICAST_LOOP
+ sysIPV6_JOIN_GROUP = C.IPV6_JOIN_GROUP
+ sysIPV6_LEAVE_GROUP = C.IPV6_LEAVE_GROUP
+
+ sysIPV6_PKTINFO = C.IPV6_PKTINFO
+
+ sysIPV6_HOPLIMIT = C.IPV6_HOPLIMIT
+ sysIPV6_NEXTHOP = C.IPV6_NEXTHOP
+ sysIPV6_HOPOPTS = C.IPV6_HOPOPTS
+ sysIPV6_DSTOPTS = C.IPV6_DSTOPTS
+
+ sysIPV6_RTHDR = C.IPV6_RTHDR
+ sysIPV6_RTHDRDSTOPTS = C.IPV6_RTHDRDSTOPTS
+
+ sysIPV6_RECVPKTINFO = C.IPV6_RECVPKTINFO
+ sysIPV6_RECVHOPLIMIT = C.IPV6_RECVHOPLIMIT
+ sysIPV6_RECVHOPOPTS = C.IPV6_RECVHOPOPTS
+
+ sysIPV6_RECVRTHDR = C.IPV6_RECVRTHDR
+
+ sysIPV6_RECVRTHDRDSTOPTS = C.IPV6_RECVRTHDRDSTOPTS
+
+ sysIPV6_CHECKSUM = C.IPV6_CHECKSUM
+ sysIPV6_RECVTCLASS = C.IPV6_RECVTCLASS
+ sysIPV6_USE_MIN_MTU = C.IPV6_USE_MIN_MTU
+ sysIPV6_DONTFRAG = C.IPV6_DONTFRAG
+ sysIPV6_SEC_OPT = C.IPV6_SEC_OPT
+ sysIPV6_SRC_PREFERENCES = C.IPV6_SRC_PREFERENCES
+ sysIPV6_RECVPATHMTU = C.IPV6_RECVPATHMTU
+ sysIPV6_PATHMTU = C.IPV6_PATHMTU
+ sysIPV6_TCLASS = C.IPV6_TCLASS
+ sysIPV6_V6ONLY = C.IPV6_V6ONLY
+
+ sysIPV6_RECVDSTOPTS = C.IPV6_RECVDSTOPTS
+
+ sysMCAST_JOIN_GROUP = C.MCAST_JOIN_GROUP
+ sysMCAST_LEAVE_GROUP = C.MCAST_LEAVE_GROUP
+ sysMCAST_BLOCK_SOURCE = C.MCAST_BLOCK_SOURCE
+ sysMCAST_UNBLOCK_SOURCE = C.MCAST_UNBLOCK_SOURCE
+ sysMCAST_JOIN_SOURCE_GROUP = C.MCAST_JOIN_SOURCE_GROUP
+ sysMCAST_LEAVE_SOURCE_GROUP = C.MCAST_LEAVE_SOURCE_GROUP
+
+ sysIPV6_PREFER_SRC_HOME = C.IPV6_PREFER_SRC_HOME
+ sysIPV6_PREFER_SRC_COA = C.IPV6_PREFER_SRC_COA
+ sysIPV6_PREFER_SRC_PUBLIC = C.IPV6_PREFER_SRC_PUBLIC
+ sysIPV6_PREFER_SRC_TMP = C.IPV6_PREFER_SRC_TMP
+ sysIPV6_PREFER_SRC_NONCGA = C.IPV6_PREFER_SRC_NONCGA
+ sysIPV6_PREFER_SRC_CGA = C.IPV6_PREFER_SRC_CGA
+
+ sysIPV6_PREFER_SRC_MIPMASK = C.IPV6_PREFER_SRC_MIPMASK
+ sysIPV6_PREFER_SRC_MIPDEFAULT = C.IPV6_PREFER_SRC_MIPDEFAULT
+ sysIPV6_PREFER_SRC_TMPMASK = C.IPV6_PREFER_SRC_TMPMASK
+ sysIPV6_PREFER_SRC_TMPDEFAULT = C.IPV6_PREFER_SRC_TMPDEFAULT
+ sysIPV6_PREFER_SRC_CGAMASK = C.IPV6_PREFER_SRC_CGAMASK
+ sysIPV6_PREFER_SRC_CGADEFAULT = C.IPV6_PREFER_SRC_CGADEFAULT
+
+ sysIPV6_PREFER_SRC_MASK = C.IPV6_PREFER_SRC_MASK
+
+ sysIPV6_PREFER_SRC_DEFAULT = C.IPV6_PREFER_SRC_DEFAULT
+
+ sysIPV6_BOUND_IF = C.IPV6_BOUND_IF
+ sysIPV6_UNSPEC_SRC = C.IPV6_UNSPEC_SRC
+
+ sysICMP6_FILTER = C.ICMP6_FILTER
+
+ sizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage
+ sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
+ sizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
+ sizeofIPv6Mtuinfo = C.sizeof_struct_ip6_mtuinfo
+
+ sizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
+ sizeofGroupReq = C.sizeof_struct_group_req
+ sizeofGroupSourceReq = C.sizeof_struct_group_source_req
+
+ sizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
+)
+
+type sockaddrStorage C.struct_sockaddr_storage
+
+type sockaddrInet6 C.struct_sockaddr_in6
+
+type inet6Pktinfo C.struct_in6_pktinfo
+
+type ipv6Mtuinfo C.struct_ip6_mtuinfo
+
+type ipv6Mreq C.struct_ipv6_mreq
+
+type groupReq C.struct_group_req
+
+type groupSourceReq C.struct_group_source_req
+
+type icmpv6Filter C.struct_icmp6_filter
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/dgramopt.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/dgramopt.go
new file mode 100644
index 000000000..703dafe84
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/dgramopt.go
@@ -0,0 +1,302 @@
+// Copyright 2013 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 ipv6
+
+import (
+ "net"
+ "syscall"
+
+ "golang.org/x/net/bpf"
+)
+
+// MulticastHopLimit returns the hop limit field value for outgoing
+// multicast packets.
+func (c *dgramOpt) MulticastHopLimit() (int, error) {
+ if !c.ok() {
+ return 0, syscall.EINVAL
+ }
+ so, ok := sockOpts[ssoMulticastHopLimit]
+ if !ok {
+ return 0, errOpNoSupport
+ }
+ return so.GetInt(c.Conn)
+}
+
+// SetMulticastHopLimit sets the hop limit field value for future
+// outgoing multicast packets.
+func (c *dgramOpt) SetMulticastHopLimit(hoplim int) error {
+ if !c.ok() {
+ return syscall.EINVAL
+ }
+ so, ok := sockOpts[ssoMulticastHopLimit]
+ if !ok {
+ return errOpNoSupport
+ }
+ return so.SetInt(c.Conn, hoplim)
+}
+
+// MulticastInterface returns the default interface for multicast
+// packet transmissions.
+func (c *dgramOpt) MulticastInterface() (*net.Interface, error) {
+ if !c.ok() {
+ return nil, syscall.EINVAL
+ }
+ so, ok := sockOpts[ssoMulticastInterface]
+ if !ok {
+ return nil, errOpNoSupport
+ }
+ return so.getMulticastInterface(c.Conn)
+}
+
+// SetMulticastInterface sets the default interface for future
+// multicast packet transmissions.
+func (c *dgramOpt) SetMulticastInterface(ifi *net.Interface) error {
+ if !c.ok() {
+ return syscall.EINVAL
+ }
+ so, ok := sockOpts[ssoMulticastInterface]
+ if !ok {
+ return errOpNoSupport
+ }
+ return so.setMulticastInterface(c.Conn, ifi)
+}
+
+// MulticastLoopback reports whether transmitted multicast packets
+// should be copied and send back to the originator.
+func (c *dgramOpt) MulticastLoopback() (bool, error) {
+ if !c.ok() {
+ return false, syscall.EINVAL
+ }
+ so, ok := sockOpts[ssoMulticastLoopback]
+ if !ok {
+ return false, errOpNoSupport
+ }
+ on, err := so.GetInt(c.Conn)
+ if err != nil {
+ return false, err
+ }
+ return on == 1, nil
+}
+
+// SetMulticastLoopback sets whether transmitted multicast packets
+// should be copied and send back to the originator.
+func (c *dgramOpt) SetMulticastLoopback(on bool) error {
+ if !c.ok() {
+ return syscall.EINVAL
+ }
+ so, ok := sockOpts[ssoMulticastLoopback]
+ if !ok {
+ return errOpNoSupport
+ }
+ return so.SetInt(c.Conn, boolint(on))
+}
+
+// JoinGroup joins the group address group on the interface ifi.
+// By default all sources that can cast data to group are accepted.
+// It's possible to mute and unmute data transmission from a specific
+// source by using ExcludeSourceSpecificGroup and
+// IncludeSourceSpecificGroup.
+// JoinGroup uses the system assigned multicast interface when ifi is
+// nil, although this is not recommended because the assignment
+// depends on platforms and sometimes it might require routing
+// configuration.
+func (c *dgramOpt) JoinGroup(ifi *net.Interface, group net.Addr) error {
+ if !c.ok() {
+ return syscall.EINVAL
+ }
+ so, ok := sockOpts[ssoJoinGroup]
+ if !ok {
+ return errOpNoSupport
+ }
+ grp := netAddrToIP16(group)
+ if grp == nil {
+ return errMissingAddress
+ }
+ return so.setGroup(c.Conn, ifi, grp)
+}
+
+// LeaveGroup leaves the group address group on the interface ifi
+// regardless of whether the group is any-source group or
+// source-specific group.
+func (c *dgramOpt) LeaveGroup(ifi *net.Interface, group net.Addr) error {
+ if !c.ok() {
+ return syscall.EINVAL
+ }
+ so, ok := sockOpts[ssoLeaveGroup]
+ if !ok {
+ return errOpNoSupport
+ }
+ grp := netAddrToIP16(group)
+ if grp == nil {
+ return errMissingAddress
+ }
+ return so.setGroup(c.Conn, ifi, grp)
+}
+
+// JoinSourceSpecificGroup joins the source-specific group comprising
+// group and source on the interface ifi.
+// JoinSourceSpecificGroup uses the system assigned multicast
+// interface when ifi is nil, although this is not recommended because
+// the assignment depends on platforms and sometimes it might require
+// routing configuration.
+func (c *dgramOpt) JoinSourceSpecificGroup(ifi *net.Interface, group, source net.Addr) error {
+ if !c.ok() {
+ return syscall.EINVAL
+ }
+ so, ok := sockOpts[ssoJoinSourceGroup]
+ if !ok {
+ return errOpNoSupport
+ }
+ grp := netAddrToIP16(group)
+ if grp == nil {
+ return errMissingAddress
+ }
+ src := netAddrToIP16(source)
+ if src == nil {
+ return errMissingAddress
+ }
+ return so.setSourceGroup(c.Conn, ifi, grp, src)
+}
+
+// LeaveSourceSpecificGroup leaves the source-specific group on the
+// interface ifi.
+func (c *dgramOpt) LeaveSourceSpecificGroup(ifi *net.Interface, group, source net.Addr) error {
+ if !c.ok() {
+ return syscall.EINVAL
+ }
+ so, ok := sockOpts[ssoLeaveSourceGroup]
+ if !ok {
+ return errOpNoSupport
+ }
+ grp := netAddrToIP16(group)
+ if grp == nil {
+ return errMissingAddress
+ }
+ src := netAddrToIP16(source)
+ if src == nil {
+ return errMissingAddress
+ }
+ return so.setSourceGroup(c.Conn, ifi, grp, src)
+}
+
+// ExcludeSourceSpecificGroup excludes the source-specific group from
+// the already joined any-source groups by JoinGroup on the interface
+// ifi.
+func (c *dgramOpt) ExcludeSourceSpecificGroup(ifi *net.Interface, group, source net.Addr) error {
+ if !c.ok() {
+ return syscall.EINVAL
+ }
+ so, ok := sockOpts[ssoBlockSourceGroup]
+ if !ok {
+ return errOpNoSupport
+ }
+ grp := netAddrToIP16(group)
+ if grp == nil {
+ return errMissingAddress
+ }
+ src := netAddrToIP16(source)
+ if src == nil {
+ return errMissingAddress
+ }
+ return so.setSourceGroup(c.Conn, ifi, grp, src)
+}
+
+// IncludeSourceSpecificGroup includes the excluded source-specific
+// group by ExcludeSourceSpecificGroup again on the interface ifi.
+func (c *dgramOpt) IncludeSourceSpecificGroup(ifi *net.Interface, group, source net.Addr) error {
+ if !c.ok() {
+ return syscall.EINVAL
+ }
+ so, ok := sockOpts[ssoUnblockSourceGroup]
+ if !ok {
+ return errOpNoSupport
+ }
+ grp := netAddrToIP16(group)
+ if grp == nil {
+ return errMissingAddress
+ }
+ src := netAddrToIP16(source)
+ if src == nil {
+ return errMissingAddress
+ }
+ return so.setSourceGroup(c.Conn, ifi, grp, src)
+}
+
+// Checksum reports whether the kernel will compute, store or verify a
+// checksum for both incoming and outgoing packets. If on is true, it
+// returns an offset in bytes into the data of where the checksum
+// field is located.
+func (c *dgramOpt) Checksum() (on bool, offset int, err error) {
+ if !c.ok() {
+ return false, 0, syscall.EINVAL
+ }
+ so, ok := sockOpts[ssoChecksum]
+ if !ok {
+ return false, 0, errOpNoSupport
+ }
+ offset, err = so.GetInt(c.Conn)
+ if err != nil {
+ return false, 0, err
+ }
+ if offset < 0 {
+ return false, 0, nil
+ }
+ return true, offset, nil
+}
+
+// SetChecksum enables the kernel checksum processing. If on is ture,
+// the offset should be an offset in bytes into the data of where the
+// checksum field is located.
+func (c *dgramOpt) SetChecksum(on bool, offset int) error {
+ if !c.ok() {
+ return syscall.EINVAL
+ }
+ so, ok := sockOpts[ssoChecksum]
+ if !ok {
+ return errOpNoSupport
+ }
+ if !on {
+ offset = -1
+ }
+ return so.SetInt(c.Conn, offset)
+}
+
+// ICMPFilter returns an ICMP filter.
+func (c *dgramOpt) ICMPFilter() (*ICMPFilter, error) {
+ if !c.ok() {
+ return nil, syscall.EINVAL
+ }
+ so, ok := sockOpts[ssoICMPFilter]
+ if !ok {
+ return nil, errOpNoSupport
+ }
+ return so.getICMPFilter(c.Conn)
+}
+
+// SetICMPFilter deploys the ICMP filter.
+func (c *dgramOpt) SetICMPFilter(f *ICMPFilter) error {
+ if !c.ok() {
+ return syscall.EINVAL
+ }
+ so, ok := sockOpts[ssoICMPFilter]
+ if !ok {
+ return errOpNoSupport
+ }
+ return so.setICMPFilter(c.Conn, f)
+}
+
+// SetBPF attaches a BPF program to the connection.
+//
+// Only supported on Linux.
+func (c *dgramOpt) SetBPF(filter []bpf.RawInstruction) error {
+ if !c.ok() {
+ return syscall.EINVAL
+ }
+ so, ok := sockOpts[ssoAttachFilter]
+ if !ok {
+ return errOpNoSupport
+ }
+ return so.setBPF(c.Conn, filter)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/doc.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/doc.go
new file mode 100644
index 000000000..664a97dea
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/doc.go
@@ -0,0 +1,243 @@
+// Copyright 2013 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 ipv6 implements IP-level socket options for the Internet
+// Protocol version 6.
+//
+// The package provides IP-level socket options that allow
+// manipulation of IPv6 facilities.
+//
+// The IPv6 protocol is defined in RFC 8200.
+// Socket interface extensions are defined in RFC 3493, RFC 3542 and
+// RFC 3678.
+// MLDv1 and MLDv2 are defined in RFC 2710 and RFC 3810.
+// Source-specific multicast is defined in RFC 4607.
+//
+// On Darwin, this package requires OS X Mavericks version 10.9 or
+// above, or equivalent.
+//
+//
+// Unicasting
+//
+// The options for unicasting are available for net.TCPConn,
+// net.UDPConn and net.IPConn which are created as network connections
+// that use the IPv6 transport. When a single TCP connection carrying
+// a data flow of multiple packets needs to indicate the flow is
+// important, Conn is used to set the traffic class field on the IPv6
+// header for each packet.
+//
+// ln, err := net.Listen("tcp6", "[::]:1024")
+// if err != nil {
+// // error handling
+// }
+// defer ln.Close()
+// for {
+// c, err := ln.Accept()
+// if err != nil {
+// // error handling
+// }
+// go func(c net.Conn) {
+// defer c.Close()
+//
+// The outgoing packets will be labeled DiffServ assured forwarding
+// class 1 low drop precedence, known as AF11 packets.
+//
+// if err := ipv6.NewConn(c).SetTrafficClass(0x28); err != nil {
+// // error handling
+// }
+// if _, err := c.Write(data); err != nil {
+// // error handling
+// }
+// }(c)
+// }
+//
+//
+// Multicasting
+//
+// The options for multicasting are available for net.UDPConn and
+// net.IPconn which are created as network connections that use the
+// IPv6 transport. A few network facilities must be prepared before
+// you begin multicasting, at a minimum joining network interfaces and
+// multicast groups.
+//
+// en0, err := net.InterfaceByName("en0")
+// if err != nil {
+// // error handling
+// }
+// en1, err := net.InterfaceByIndex(911)
+// if err != nil {
+// // error handling
+// }
+// group := net.ParseIP("ff02::114")
+//
+// First, an application listens to an appropriate address with an
+// appropriate service port.
+//
+// c, err := net.ListenPacket("udp6", "[::]:1024")
+// if err != nil {
+// // error handling
+// }
+// defer c.Close()
+//
+// Second, the application joins multicast groups, starts listening to
+// the groups on the specified network interfaces. Note that the
+// service port for transport layer protocol does not matter with this
+// operation as joining groups affects only network and link layer
+// protocols, such as IPv6 and Ethernet.
+//
+// p := ipv6.NewPacketConn(c)
+// if err := p.JoinGroup(en0, &net.UDPAddr{IP: group}); err != nil {
+// // error handling
+// }
+// if err := p.JoinGroup(en1, &net.UDPAddr{IP: group}); err != nil {
+// // error handling
+// }
+//
+// The application might set per packet control message transmissions
+// between the protocol stack within the kernel. When the application
+// needs a destination address on an incoming packet,
+// SetControlMessage of PacketConn is used to enable control message
+// transmissions.
+//
+// if err := p.SetControlMessage(ipv6.FlagDst, true); err != nil {
+// // error handling
+// }
+//
+// The application could identify whether the received packets are
+// of interest by using the control message that contains the
+// destination address of the received packet.
+//
+// b := make([]byte, 1500)
+// for {
+// n, rcm, src, err := p.ReadFrom(b)
+// if err != nil {
+// // error handling
+// }
+// if rcm.Dst.IsMulticast() {
+// if rcm.Dst.Equal(group) {
+// // joined group, do something
+// } else {
+// // unknown group, discard
+// continue
+// }
+// }
+//
+// The application can also send both unicast and multicast packets.
+//
+// p.SetTrafficClass(0x0)
+// p.SetHopLimit(16)
+// if _, err := p.WriteTo(data[:n], nil, src); err != nil {
+// // error handling
+// }
+// dst := &net.UDPAddr{IP: group, Port: 1024}
+// wcm := ipv6.ControlMessage{TrafficClass: 0xe0, HopLimit: 1}
+// for _, ifi := range []*net.Interface{en0, en1} {
+// wcm.IfIndex = ifi.Index
+// if _, err := p.WriteTo(data[:n], &wcm, dst); err != nil {
+// // error handling
+// }
+// }
+// }
+//
+//
+// More multicasting
+//
+// An application that uses PacketConn may join multiple multicast
+// groups. For example, a UDP listener with port 1024 might join two
+// different groups across over two different network interfaces by
+// using:
+//
+// c, err := net.ListenPacket("udp6", "[::]:1024")
+// if err != nil {
+// // error handling
+// }
+// defer c.Close()
+// p := ipv6.NewPacketConn(c)
+// if err := p.JoinGroup(en0, &net.UDPAddr{IP: net.ParseIP("ff02::1:114")}); err != nil {
+// // error handling
+// }
+// if err := p.JoinGroup(en0, &net.UDPAddr{IP: net.ParseIP("ff02::2:114")}); err != nil {
+// // error handling
+// }
+// if err := p.JoinGroup(en1, &net.UDPAddr{IP: net.ParseIP("ff02::2:114")}); err != nil {
+// // error handling
+// }
+//
+// It is possible for multiple UDP listeners that listen on the same
+// UDP port to join the same multicast group. The net package will
+// provide a socket that listens to a wildcard address with reusable
+// UDP port when an appropriate multicast address prefix is passed to
+// the net.ListenPacket or net.ListenUDP.
+//
+// c1, err := net.ListenPacket("udp6", "[ff02::]:1024")
+// if err != nil {
+// // error handling
+// }
+// defer c1.Close()
+// c2, err := net.ListenPacket("udp6", "[ff02::]:1024")
+// if err != nil {
+// // error handling
+// }
+// defer c2.Close()
+// p1 := ipv6.NewPacketConn(c1)
+// if err := p1.JoinGroup(en0, &net.UDPAddr{IP: net.ParseIP("ff02::114")}); err != nil {
+// // error handling
+// }
+// p2 := ipv6.NewPacketConn(c2)
+// if err := p2.JoinGroup(en0, &net.UDPAddr{IP: net.ParseIP("ff02::114")}); err != nil {
+// // error handling
+// }
+//
+// Also it is possible for the application to leave or rejoin a
+// multicast group on the network interface.
+//
+// if err := p.LeaveGroup(en0, &net.UDPAddr{IP: net.ParseIP("ff02::114")}); err != nil {
+// // error handling
+// }
+// if err := p.JoinGroup(en0, &net.UDPAddr{IP: net.ParseIP("ff01::114")}); err != nil {
+// // error handling
+// }
+//
+//
+// Source-specific multicasting
+//
+// An application that uses PacketConn on MLDv2 supported platform is
+// able to join source-specific multicast groups.
+// The application may use JoinSourceSpecificGroup and
+// LeaveSourceSpecificGroup for the operation known as "include" mode,
+//
+// ssmgroup := net.UDPAddr{IP: net.ParseIP("ff32::8000:9")}
+// ssmsource := net.UDPAddr{IP: net.ParseIP("fe80::cafe")}
+// if err := p.JoinSourceSpecificGroup(en0, &ssmgroup, &ssmsource); err != nil {
+// // error handling
+// }
+// if err := p.LeaveSourceSpecificGroup(en0, &ssmgroup, &ssmsource); err != nil {
+// // error handling
+// }
+//
+// or JoinGroup, ExcludeSourceSpecificGroup,
+// IncludeSourceSpecificGroup and LeaveGroup for the operation known
+// as "exclude" mode.
+//
+// exclsource := net.UDPAddr{IP: net.ParseIP("fe80::dead")}
+// if err := p.JoinGroup(en0, &ssmgroup); err != nil {
+// // error handling
+// }
+// if err := p.ExcludeSourceSpecificGroup(en0, &ssmgroup, &exclsource); err != nil {
+// // error handling
+// }
+// if err := p.LeaveGroup(en0, &ssmgroup); err != nil {
+// // error handling
+// }
+//
+// Note that it depends on each platform implementation what happens
+// when an application which runs on MLDv2 unsupported platform uses
+// JoinSourceSpecificGroup and LeaveSourceSpecificGroup.
+// In general the platform tries to fall back to conversations using
+// MLDv1 and starts to listen to multicast traffic.
+// In the fallback case, ExcludeSourceSpecificGroup and
+// IncludeSourceSpecificGroup may return an error.
+package ipv6 // import "golang.org/x/net/ipv6"
+
+// BUG(mikio): This package is not implemented on NaCl and Plan 9.
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/endpoint.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/endpoint.go
new file mode 100644
index 000000000..0624c1740
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/endpoint.go
@@ -0,0 +1,128 @@
+// Copyright 2013 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 ipv6
+
+import (
+ "net"
+ "syscall"
+ "time"
+
+ "golang.org/x/net/internal/socket"
+)
+
+// BUG(mikio): On Windows, the JoinSourceSpecificGroup,
+// LeaveSourceSpecificGroup, ExcludeSourceSpecificGroup and
+// IncludeSourceSpecificGroup methods of PacketConn are not
+// implemented.
+
+// A Conn represents a network endpoint that uses IPv6 transport.
+// It allows to set basic IP-level socket options such as traffic
+// class and hop limit.
+type Conn struct {
+ genericOpt
+}
+
+type genericOpt struct {
+ *socket.Conn
+}
+
+func (c *genericOpt) ok() bool { return c != nil && c.Conn != nil }
+
+// PathMTU returns a path MTU value for the destination associated
+// with the endpoint.
+func (c *Conn) PathMTU() (int, error) {
+ if !c.ok() {
+ return 0, syscall.EINVAL
+ }
+ so, ok := sockOpts[ssoPathMTU]
+ if !ok {
+ return 0, errOpNoSupport
+ }
+ _, mtu, err := so.getMTUInfo(c.Conn)
+ if err != nil {
+ return 0, err
+ }
+ return mtu, nil
+}
+
+// NewConn returns a new Conn.
+func NewConn(c net.Conn) *Conn {
+ cc, _ := socket.NewConn(c)
+ return &Conn{
+ genericOpt: genericOpt{Conn: cc},
+ }
+}
+
+// A PacketConn represents a packet network endpoint that uses IPv6
+// transport. It is used to control several IP-level socket options
+// including IPv6 header manipulation. It also provides datagram
+// based network I/O methods specific to the IPv6 and higher layer
+// protocols such as OSPF, GRE, and UDP.
+type PacketConn struct {
+ genericOpt
+ dgramOpt
+ payloadHandler
+}
+
+type dgramOpt struct {
+ *socket.Conn
+}
+
+func (c *dgramOpt) ok() bool { return c != nil && c.Conn != nil }
+
+// SetControlMessage allows to receive the per packet basis IP-level
+// socket options.
+func (c *PacketConn) SetControlMessage(cf ControlFlags, on bool) error {
+ if !c.payloadHandler.ok() {
+ return syscall.EINVAL
+ }
+ return setControlMessage(c.dgramOpt.Conn, &c.payloadHandler.rawOpt, cf, on)
+}
+
+// SetDeadline sets the read and write deadlines associated with the
+// endpoint.
+func (c *PacketConn) SetDeadline(t time.Time) error {
+ if !c.payloadHandler.ok() {
+ return syscall.EINVAL
+ }
+ return c.payloadHandler.SetDeadline(t)
+}
+
+// SetReadDeadline sets the read deadline associated with the
+// endpoint.
+func (c *PacketConn) SetReadDeadline(t time.Time) error {
+ if !c.payloadHandler.ok() {
+ return syscall.EINVAL
+ }
+ return c.payloadHandler.SetReadDeadline(t)
+}
+
+// SetWriteDeadline sets the write deadline associated with the
+// endpoint.
+func (c *PacketConn) SetWriteDeadline(t time.Time) error {
+ if !c.payloadHandler.ok() {
+ return syscall.EINVAL
+ }
+ return c.payloadHandler.SetWriteDeadline(t)
+}
+
+// Close closes the endpoint.
+func (c *PacketConn) Close() error {
+ if !c.payloadHandler.ok() {
+ return syscall.EINVAL
+ }
+ return c.payloadHandler.Close()
+}
+
+// NewPacketConn returns a new PacketConn using c as its underlying
+// transport.
+func NewPacketConn(c net.PacketConn) *PacketConn {
+ cc, _ := socket.NewConn(c.(net.Conn))
+ return &PacketConn{
+ genericOpt: genericOpt{Conn: cc},
+ dgramOpt: dgramOpt{Conn: cc},
+ payloadHandler: payloadHandler{PacketConn: c, Conn: cc},
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/example_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/example_test.go
new file mode 100644
index 000000000..e761aa2a1
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/example_test.go
@@ -0,0 +1,216 @@
+// Copyright 2014 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 ipv6_test
+
+import (
+ "fmt"
+ "log"
+ "net"
+ "os"
+ "time"
+
+ "golang.org/x/net/icmp"
+ "golang.org/x/net/ipv6"
+)
+
+func ExampleConn_markingTCP() {
+ ln, err := net.Listen("tcp", "[::]:1024")
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer ln.Close()
+
+ for {
+ c, err := ln.Accept()
+ if err != nil {
+ log.Fatal(err)
+ }
+ go func(c net.Conn) {
+ defer c.Close()
+ if c.RemoteAddr().(*net.TCPAddr).IP.To16() != nil && c.RemoteAddr().(*net.TCPAddr).IP.To4() == nil {
+ p := ipv6.NewConn(c)
+ if err := p.SetTrafficClass(0x28); err != nil { // DSCP AF11
+ log.Fatal(err)
+ }
+ if err := p.SetHopLimit(128); err != nil {
+ log.Fatal(err)
+ }
+ }
+ if _, err := c.Write([]byte("HELLO-R-U-THERE-ACK")); err != nil {
+ log.Fatal(err)
+ }
+ }(c)
+ }
+}
+
+func ExamplePacketConn_servingOneShotMulticastDNS() {
+ c, err := net.ListenPacket("udp6", "[::]:5353") // mDNS over UDP
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer c.Close()
+ p := ipv6.NewPacketConn(c)
+
+ en0, err := net.InterfaceByName("en0")
+ if err != nil {
+ log.Fatal(err)
+ }
+ mDNSLinkLocal := net.UDPAddr{IP: net.ParseIP("ff02::fb")}
+ if err := p.JoinGroup(en0, &mDNSLinkLocal); err != nil {
+ log.Fatal(err)
+ }
+ defer p.LeaveGroup(en0, &mDNSLinkLocal)
+ if err := p.SetControlMessage(ipv6.FlagDst|ipv6.FlagInterface, true); err != nil {
+ log.Fatal(err)
+ }
+
+ var wcm ipv6.ControlMessage
+ b := make([]byte, 1500)
+ for {
+ _, rcm, peer, err := p.ReadFrom(b)
+ if err != nil {
+ log.Fatal(err)
+ }
+ if !rcm.Dst.IsMulticast() || !rcm.Dst.Equal(mDNSLinkLocal.IP) {
+ continue
+ }
+ wcm.IfIndex = rcm.IfIndex
+ answers := []byte("FAKE-MDNS-ANSWERS") // fake mDNS answers, you need to implement this
+ if _, err := p.WriteTo(answers, &wcm, peer); err != nil {
+ log.Fatal(err)
+ }
+ }
+}
+
+func ExamplePacketConn_tracingIPPacketRoute() {
+ // Tracing an IP packet route to www.google.com.
+
+ const host = "www.google.com"
+ ips, err := net.LookupIP(host)
+ if err != nil {
+ log.Fatal(err)
+ }
+ var dst net.IPAddr
+ for _, ip := range ips {
+ if ip.To16() != nil && ip.To4() == nil {
+ dst.IP = ip
+ fmt.Printf("using %v for tracing an IP packet route to %s\n", dst.IP, host)
+ break
+ }
+ }
+ if dst.IP == nil {
+ log.Fatal("no AAAA record found")
+ }
+
+ c, err := net.ListenPacket("ip6:58", "::") // ICMP for IPv6
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer c.Close()
+ p := ipv6.NewPacketConn(c)
+
+ if err := p.SetControlMessage(ipv6.FlagHopLimit|ipv6.FlagSrc|ipv6.FlagDst|ipv6.FlagInterface, true); err != nil {
+ log.Fatal(err)
+ }
+ wm := icmp.Message{
+ Type: ipv6.ICMPTypeEchoRequest, Code: 0,
+ Body: &icmp.Echo{
+ ID: os.Getpid() & 0xffff,
+ Data: []byte("HELLO-R-U-THERE"),
+ },
+ }
+ var f ipv6.ICMPFilter
+ f.SetAll(true)
+ f.Accept(ipv6.ICMPTypeTimeExceeded)
+ f.Accept(ipv6.ICMPTypeEchoReply)
+ if err := p.SetICMPFilter(&f); err != nil {
+ log.Fatal(err)
+ }
+
+ var wcm ipv6.ControlMessage
+ rb := make([]byte, 1500)
+ for i := 1; i <= 64; i++ { // up to 64 hops
+ wm.Body.(*icmp.Echo).Seq = i
+ wb, err := wm.Marshal(nil)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ // In the real world usually there are several
+ // multiple traffic-engineered paths for each hop.
+ // You may need to probe a few times to each hop.
+ begin := time.Now()
+ wcm.HopLimit = i
+ if _, err := p.WriteTo(wb, &wcm, &dst); err != nil {
+ log.Fatal(err)
+ }
+ if err := p.SetReadDeadline(time.Now().Add(3 * time.Second)); err != nil {
+ log.Fatal(err)
+ }
+ n, rcm, peer, err := p.ReadFrom(rb)
+ if err != nil {
+ if err, ok := err.(net.Error); ok && err.Timeout() {
+ fmt.Printf("%v\t*\n", i)
+ continue
+ }
+ log.Fatal(err)
+ }
+ rm, err := icmp.ParseMessage(58, rb[:n])
+ if err != nil {
+ log.Fatal(err)
+ }
+ rtt := time.Since(begin)
+
+ // In the real world you need to determine whether the
+ // received message is yours using ControlMessage.Src,
+ // ControlMesage.Dst, icmp.Echo.ID and icmp.Echo.Seq.
+ switch rm.Type {
+ case ipv6.ICMPTypeTimeExceeded:
+ names, _ := net.LookupAddr(peer.String())
+ fmt.Printf("%d\t%v %+v %v\n\t%+v\n", i, peer, names, rtt, rcm)
+ case ipv6.ICMPTypeEchoReply:
+ names, _ := net.LookupAddr(peer.String())
+ fmt.Printf("%d\t%v %+v %v\n\t%+v\n", i, peer, names, rtt, rcm)
+ return
+ }
+ }
+}
+
+func ExamplePacketConn_advertisingOSPFHello() {
+ c, err := net.ListenPacket("ip6:89", "::") // OSPF for IPv6
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer c.Close()
+ p := ipv6.NewPacketConn(c)
+
+ en0, err := net.InterfaceByName("en0")
+ if err != nil {
+ log.Fatal(err)
+ }
+ allSPFRouters := net.IPAddr{IP: net.ParseIP("ff02::5")}
+ if err := p.JoinGroup(en0, &allSPFRouters); err != nil {
+ log.Fatal(err)
+ }
+ defer p.LeaveGroup(en0, &allSPFRouters)
+
+ hello := make([]byte, 24) // fake hello data, you need to implement this
+ ospf := make([]byte, 16) // fake ospf header, you need to implement this
+ ospf[0] = 3 // version 3
+ ospf[1] = 1 // hello packet
+ ospf = append(ospf, hello...)
+ if err := p.SetChecksum(true, 12); err != nil {
+ log.Fatal(err)
+ }
+
+ cm := ipv6.ControlMessage{
+ TrafficClass: 0xc0, // DSCP CS6
+ HopLimit: 1,
+ IfIndex: en0.Index,
+ }
+ if _, err := p.WriteTo(ospf, &cm, &allSPFRouters); err != nil {
+ log.Fatal(err)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/gen.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/gen.go
new file mode 100644
index 000000000..41886ec72
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/gen.go
@@ -0,0 +1,199 @@
+// Copyright 2013 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.
+
+// +build ignore
+
+//go:generate go run gen.go
+
+// This program generates system adaptation constants and types,
+// internet protocol constants and tables by reading template files
+// and IANA protocol registries.
+package main
+
+import (
+ "bytes"
+ "encoding/xml"
+ "fmt"
+ "go/format"
+ "io"
+ "io/ioutil"
+ "net/http"
+ "os"
+ "os/exec"
+ "runtime"
+ "strconv"
+ "strings"
+)
+
+func main() {
+ if err := genzsys(); err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+ if err := geniana(); err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+}
+
+func genzsys() error {
+ defs := "defs_" + runtime.GOOS + ".go"
+ f, err := os.Open(defs)
+ if err != nil {
+ if os.IsNotExist(err) {
+ return nil
+ }
+ return err
+ }
+ f.Close()
+ cmd := exec.Command("go", "tool", "cgo", "-godefs", defs)
+ b, err := cmd.Output()
+ if err != nil {
+ return err
+ }
+ b, err = format.Source(b)
+ if err != nil {
+ return err
+ }
+ zsys := "zsys_" + runtime.GOOS + ".go"
+ switch runtime.GOOS {
+ case "freebsd", "linux":
+ zsys = "zsys_" + runtime.GOOS + "_" + runtime.GOARCH + ".go"
+ }
+ if err := ioutil.WriteFile(zsys, b, 0644); err != nil {
+ return err
+ }
+ return nil
+}
+
+var registries = []struct {
+ url string
+ parse func(io.Writer, io.Reader) error
+}{
+ {
+ "http://www.iana.org/assignments/icmpv6-parameters/icmpv6-parameters.xml",
+ parseICMPv6Parameters,
+ },
+}
+
+func geniana() error {
+ var bb bytes.Buffer
+ fmt.Fprintf(&bb, "// go generate gen.go\n")
+ fmt.Fprintf(&bb, "// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT\n\n")
+ fmt.Fprintf(&bb, "package ipv6\n\n")
+ for _, r := range registries {
+ resp, err := http.Get(r.url)
+ if err != nil {
+ return err
+ }
+ defer resp.Body.Close()
+ if resp.StatusCode != http.StatusOK {
+ return fmt.Errorf("got HTTP status code %v for %v\n", resp.StatusCode, r.url)
+ }
+ if err := r.parse(&bb, resp.Body); err != nil {
+ return err
+ }
+ fmt.Fprintf(&bb, "\n")
+ }
+ b, err := format.Source(bb.Bytes())
+ if err != nil {
+ return err
+ }
+ if err := ioutil.WriteFile("iana.go", b, 0644); err != nil {
+ return err
+ }
+ return nil
+}
+
+func parseICMPv6Parameters(w io.Writer, r io.Reader) error {
+ dec := xml.NewDecoder(r)
+ var icp icmpv6Parameters
+ if err := dec.Decode(&icp); err != nil {
+ return err
+ }
+ prs := icp.escape()
+ fmt.Fprintf(w, "// %s, Updated: %s\n", icp.Title, icp.Updated)
+ fmt.Fprintf(w, "const (\n")
+ for _, pr := range prs {
+ if pr.Name == "" {
+ continue
+ }
+ fmt.Fprintf(w, "ICMPType%s ICMPType = %d", pr.Name, pr.Value)
+ fmt.Fprintf(w, "// %s\n", pr.OrigName)
+ }
+ fmt.Fprintf(w, ")\n\n")
+ fmt.Fprintf(w, "// %s, Updated: %s\n", icp.Title, icp.Updated)
+ fmt.Fprintf(w, "var icmpTypes = map[ICMPType]string{\n")
+ for _, pr := range prs {
+ if pr.Name == "" {
+ continue
+ }
+ fmt.Fprintf(w, "%d: %q,\n", pr.Value, strings.ToLower(pr.OrigName))
+ }
+ fmt.Fprintf(w, "}\n")
+ return nil
+}
+
+type icmpv6Parameters struct {
+ XMLName xml.Name `xml:"registry"`
+ Title string `xml:"title"`
+ Updated string `xml:"updated"`
+ Registries []struct {
+ Title string `xml:"title"`
+ Records []struct {
+ Value string `xml:"value"`
+ Name string `xml:"name"`
+ } `xml:"record"`
+ } `xml:"registry"`
+}
+
+type canonICMPv6ParamRecord struct {
+ OrigName string
+ Name string
+ Value int
+}
+
+func (icp *icmpv6Parameters) escape() []canonICMPv6ParamRecord {
+ id := -1
+ for i, r := range icp.Registries {
+ if strings.Contains(r.Title, "Type") || strings.Contains(r.Title, "type") {
+ id = i
+ break
+ }
+ }
+ if id < 0 {
+ return nil
+ }
+ prs := make([]canonICMPv6ParamRecord, len(icp.Registries[id].Records))
+ sr := strings.NewReplacer(
+ "Messages", "",
+ "Message", "",
+ "ICMP", "",
+ "+", "P",
+ "-", "",
+ "/", "",
+ ".", "",
+ " ", "",
+ )
+ for i, pr := range icp.Registries[id].Records {
+ if strings.Contains(pr.Name, "Reserved") ||
+ strings.Contains(pr.Name, "Unassigned") ||
+ strings.Contains(pr.Name, "Deprecated") ||
+ strings.Contains(pr.Name, "Experiment") ||
+ strings.Contains(pr.Name, "experiment") {
+ continue
+ }
+ ss := strings.Split(pr.Name, "\n")
+ if len(ss) > 1 {
+ prs[i].Name = strings.Join(ss, " ")
+ } else {
+ prs[i].Name = ss[0]
+ }
+ s := strings.TrimSpace(prs[i].Name)
+ prs[i].OrigName = s
+ prs[i].Name = sr.Replace(s)
+ prs[i].Value, _ = strconv.Atoi(pr.Value)
+ }
+ return prs
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/genericopt.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/genericopt.go
new file mode 100644
index 000000000..e9dbc2e18
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/genericopt.go
@@ -0,0 +1,58 @@
+// Copyright 2013 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 ipv6
+
+import "syscall"
+
+// TrafficClass returns the traffic class field value for outgoing
+// packets.
+func (c *genericOpt) TrafficClass() (int, error) {
+ if !c.ok() {
+ return 0, syscall.EINVAL
+ }
+ so, ok := sockOpts[ssoTrafficClass]
+ if !ok {
+ return 0, errOpNoSupport
+ }
+ return so.GetInt(c.Conn)
+}
+
+// SetTrafficClass sets the traffic class field value for future
+// outgoing packets.
+func (c *genericOpt) SetTrafficClass(tclass int) error {
+ if !c.ok() {
+ return syscall.EINVAL
+ }
+ so, ok := sockOpts[ssoTrafficClass]
+ if !ok {
+ return errOpNoSupport
+ }
+ return so.SetInt(c.Conn, tclass)
+}
+
+// HopLimit returns the hop limit field value for outgoing packets.
+func (c *genericOpt) HopLimit() (int, error) {
+ if !c.ok() {
+ return 0, syscall.EINVAL
+ }
+ so, ok := sockOpts[ssoHopLimit]
+ if !ok {
+ return 0, errOpNoSupport
+ }
+ return so.GetInt(c.Conn)
+}
+
+// SetHopLimit sets the hop limit field value for future outgoing
+// packets.
+func (c *genericOpt) SetHopLimit(hoplim int) error {
+ if !c.ok() {
+ return syscall.EINVAL
+ }
+ so, ok := sockOpts[ssoHopLimit]
+ if !ok {
+ return errOpNoSupport
+ }
+ return so.SetInt(c.Conn, hoplim)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/header.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/header.go
new file mode 100644
index 000000000..e05cb08b2
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/header.go
@@ -0,0 +1,55 @@
+// Copyright 2014 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 ipv6
+
+import (
+ "encoding/binary"
+ "fmt"
+ "net"
+)
+
+const (
+ Version = 6 // protocol version
+ HeaderLen = 40 // header length
+)
+
+// A Header represents an IPv6 base header.
+type Header struct {
+ Version int // protocol version
+ TrafficClass int // traffic class
+ FlowLabel int // flow label
+ PayloadLen int // payload length
+ NextHeader int // next header
+ HopLimit int // hop limit
+ Src net.IP // source address
+ Dst net.IP // destination address
+}
+
+func (h *Header) String() string {
+ if h == nil {
+ return "<nil>"
+ }
+ return fmt.Sprintf("ver=%d tclass=%#x flowlbl=%#x payloadlen=%d nxthdr=%d hoplim=%d src=%v dst=%v", h.Version, h.TrafficClass, h.FlowLabel, h.PayloadLen, h.NextHeader, h.HopLimit, h.Src, h.Dst)
+}
+
+// ParseHeader parses b as an IPv6 base header.
+func ParseHeader(b []byte) (*Header, error) {
+ if len(b) < HeaderLen {
+ return nil, errHeaderTooShort
+ }
+ h := &Header{
+ Version: int(b[0]) >> 4,
+ TrafficClass: int(b[0]&0x0f)<<4 | int(b[1])>>4,
+ FlowLabel: int(b[1]&0x0f)<<16 | int(b[2])<<8 | int(b[3]),
+ PayloadLen: int(binary.BigEndian.Uint16(b[4:6])),
+ NextHeader: int(b[6]),
+ HopLimit: int(b[7]),
+ }
+ h.Src = make(net.IP, net.IPv6len)
+ copy(h.Src, b[8:24])
+ h.Dst = make(net.IP, net.IPv6len)
+ copy(h.Dst, b[24:40])
+ return h, nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/header_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/header_test.go
new file mode 100644
index 000000000..ca11dc23d
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/header_test.go
@@ -0,0 +1,55 @@
+// Copyright 2014 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 ipv6_test
+
+import (
+ "net"
+ "reflect"
+ "strings"
+ "testing"
+
+ "golang.org/x/net/internal/iana"
+ "golang.org/x/net/ipv6"
+)
+
+var (
+ wireHeaderFromKernel = [ipv6.HeaderLen]byte{
+ 0x69, 0x8b, 0xee, 0xf1,
+ 0xca, 0xfe, 0x2c, 0x01,
+ 0x20, 0x01, 0x0d, 0xb8,
+ 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01,
+ 0x20, 0x01, 0x0d, 0xb8,
+ 0x00, 0x02, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01,
+ }
+
+ testHeader = &ipv6.Header{
+ Version: ipv6.Version,
+ TrafficClass: iana.DiffServAF43,
+ FlowLabel: 0xbeef1,
+ PayloadLen: 0xcafe,
+ NextHeader: iana.ProtocolIPv6Frag,
+ HopLimit: 1,
+ Src: net.ParseIP("2001:db8:1::1"),
+ Dst: net.ParseIP("2001:db8:2::1"),
+ }
+)
+
+func TestParseHeader(t *testing.T) {
+ h, err := ipv6.ParseHeader(wireHeaderFromKernel[:])
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !reflect.DeepEqual(h, testHeader) {
+ t.Fatalf("got %#v; want %#v", h, testHeader)
+ }
+ s := h.String()
+ if strings.Contains(s, ",") {
+ t.Fatalf("should be space-separated values: %s", s)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/helper.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/helper.go
new file mode 100644
index 000000000..259740132
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/helper.go
@@ -0,0 +1,57 @@
+// Copyright 2013 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 ipv6
+
+import (
+ "errors"
+ "net"
+)
+
+var (
+ errMissingAddress = errors.New("missing address")
+ errHeaderTooShort = errors.New("header too short")
+ errInvalidConnType = errors.New("invalid conn type")
+ errOpNoSupport = errors.New("operation not supported")
+ errNoSuchInterface = errors.New("no such interface")
+)
+
+func boolint(b bool) int {
+ if b {
+ return 1
+ }
+ return 0
+}
+
+func netAddrToIP16(a net.Addr) net.IP {
+ switch v := a.(type) {
+ case *net.UDPAddr:
+ if ip := v.IP.To16(); ip != nil && ip.To4() == nil {
+ return ip
+ }
+ case *net.IPAddr:
+ if ip := v.IP.To16(); ip != nil && ip.To4() == nil {
+ return ip
+ }
+ }
+ return nil
+}
+
+func opAddr(a net.Addr) net.Addr {
+ switch a.(type) {
+ case *net.TCPAddr:
+ if a == nil {
+ return nil
+ }
+ case *net.UDPAddr:
+ if a == nil {
+ return nil
+ }
+ case *net.IPAddr:
+ if a == nil {
+ return nil
+ }
+ }
+ return a
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/iana.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/iana.go
new file mode 100644
index 000000000..3c6214fb6
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/iana.go
@@ -0,0 +1,82 @@
+// go generate gen.go
+// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
+
+package ipv6
+
+// Internet Control Message Protocol version 6 (ICMPv6) Parameters, Updated: 2015-07-07
+const (
+ ICMPTypeDestinationUnreachable ICMPType = 1 // Destination Unreachable
+ ICMPTypePacketTooBig ICMPType = 2 // Packet Too Big
+ ICMPTypeTimeExceeded ICMPType = 3 // Time Exceeded
+ ICMPTypeParameterProblem ICMPType = 4 // Parameter Problem
+ ICMPTypeEchoRequest ICMPType = 128 // Echo Request
+ ICMPTypeEchoReply ICMPType = 129 // Echo Reply
+ ICMPTypeMulticastListenerQuery ICMPType = 130 // Multicast Listener Query
+ ICMPTypeMulticastListenerReport ICMPType = 131 // Multicast Listener Report
+ ICMPTypeMulticastListenerDone ICMPType = 132 // Multicast Listener Done
+ ICMPTypeRouterSolicitation ICMPType = 133 // Router Solicitation
+ ICMPTypeRouterAdvertisement ICMPType = 134 // Router Advertisement
+ ICMPTypeNeighborSolicitation ICMPType = 135 // Neighbor Solicitation
+ ICMPTypeNeighborAdvertisement ICMPType = 136 // Neighbor Advertisement
+ ICMPTypeRedirect ICMPType = 137 // Redirect Message
+ ICMPTypeRouterRenumbering ICMPType = 138 // Router Renumbering
+ ICMPTypeNodeInformationQuery ICMPType = 139 // ICMP Node Information Query
+ ICMPTypeNodeInformationResponse ICMPType = 140 // ICMP Node Information Response
+ ICMPTypeInverseNeighborDiscoverySolicitation ICMPType = 141 // Inverse Neighbor Discovery Solicitation Message
+ ICMPTypeInverseNeighborDiscoveryAdvertisement ICMPType = 142 // Inverse Neighbor Discovery Advertisement Message
+ ICMPTypeVersion2MulticastListenerReport ICMPType = 143 // Version 2 Multicast Listener Report
+ ICMPTypeHomeAgentAddressDiscoveryRequest ICMPType = 144 // Home Agent Address Discovery Request Message
+ ICMPTypeHomeAgentAddressDiscoveryReply ICMPType = 145 // Home Agent Address Discovery Reply Message
+ ICMPTypeMobilePrefixSolicitation ICMPType = 146 // Mobile Prefix Solicitation
+ ICMPTypeMobilePrefixAdvertisement ICMPType = 147 // Mobile Prefix Advertisement
+ ICMPTypeCertificationPathSolicitation ICMPType = 148 // Certification Path Solicitation Message
+ ICMPTypeCertificationPathAdvertisement ICMPType = 149 // Certification Path Advertisement Message
+ ICMPTypeMulticastRouterAdvertisement ICMPType = 151 // Multicast Router Advertisement
+ ICMPTypeMulticastRouterSolicitation ICMPType = 152 // Multicast Router Solicitation
+ ICMPTypeMulticastRouterTermination ICMPType = 153 // Multicast Router Termination
+ ICMPTypeFMIPv6 ICMPType = 154 // FMIPv6 Messages
+ ICMPTypeRPLControl ICMPType = 155 // RPL Control Message
+ ICMPTypeILNPv6LocatorUpdate ICMPType = 156 // ILNPv6 Locator Update Message
+ ICMPTypeDuplicateAddressRequest ICMPType = 157 // Duplicate Address Request
+ ICMPTypeDuplicateAddressConfirmation ICMPType = 158 // Duplicate Address Confirmation
+ ICMPTypeMPLControl ICMPType = 159 // MPL Control Message
+)
+
+// Internet Control Message Protocol version 6 (ICMPv6) Parameters, Updated: 2015-07-07
+var icmpTypes = map[ICMPType]string{
+ 1: "destination unreachable",
+ 2: "packet too big",
+ 3: "time exceeded",
+ 4: "parameter problem",
+ 128: "echo request",
+ 129: "echo reply",
+ 130: "multicast listener query",
+ 131: "multicast listener report",
+ 132: "multicast listener done",
+ 133: "router solicitation",
+ 134: "router advertisement",
+ 135: "neighbor solicitation",
+ 136: "neighbor advertisement",
+ 137: "redirect message",
+ 138: "router renumbering",
+ 139: "icmp node information query",
+ 140: "icmp node information response",
+ 141: "inverse neighbor discovery solicitation message",
+ 142: "inverse neighbor discovery advertisement message",
+ 143: "version 2 multicast listener report",
+ 144: "home agent address discovery request message",
+ 145: "home agent address discovery reply message",
+ 146: "mobile prefix solicitation",
+ 147: "mobile prefix advertisement",
+ 148: "certification path solicitation message",
+ 149: "certification path advertisement message",
+ 151: "multicast router advertisement",
+ 152: "multicast router solicitation",
+ 153: "multicast router termination",
+ 154: "fmipv6 messages",
+ 155: "rpl control message",
+ 156: "ilnpv6 locator update message",
+ 157: "duplicate address request",
+ 158: "duplicate address confirmation",
+ 159: "mpl control message",
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/icmp.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/icmp.go
new file mode 100644
index 000000000..b7f48e27b
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/icmp.go
@@ -0,0 +1,60 @@
+// Copyright 2013 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 ipv6
+
+import "golang.org/x/net/internal/iana"
+
+// BUG(mikio): On Windows, methods related to ICMPFilter are not
+// implemented.
+
+// An ICMPType represents a type of ICMP message.
+type ICMPType int
+
+func (typ ICMPType) String() string {
+ s, ok := icmpTypes[typ]
+ if !ok {
+ return "<nil>"
+ }
+ return s
+}
+
+// Protocol returns the ICMPv6 protocol number.
+func (typ ICMPType) Protocol() int {
+ return iana.ProtocolIPv6ICMP
+}
+
+// An ICMPFilter represents an ICMP message filter for incoming
+// packets. The filter belongs to a packet delivery path on a host and
+// it cannot interact with forwarding packets or tunnel-outer packets.
+//
+// Note: RFC 8200 defines a reasonable role model. A node means a
+// device that implements IP. A router means a node that forwards IP
+// packets not explicitly addressed to itself, and a host means a node
+// that is not a router.
+type ICMPFilter struct {
+ icmpv6Filter
+}
+
+// Accept accepts incoming ICMP packets including the type field value
+// typ.
+func (f *ICMPFilter) Accept(typ ICMPType) {
+ f.accept(typ)
+}
+
+// Block blocks incoming ICMP packets including the type field value
+// typ.
+func (f *ICMPFilter) Block(typ ICMPType) {
+ f.block(typ)
+}
+
+// SetAll sets the filter action to the filter.
+func (f *ICMPFilter) SetAll(block bool) {
+ f.setAll(block)
+}
+
+// WillBlock reports whether the ICMP type will be blocked.
+func (f *ICMPFilter) WillBlock(typ ICMPType) bool {
+ return f.willBlock(typ)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/icmp_bsd.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/icmp_bsd.go
new file mode 100644
index 000000000..e1a791de4
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/icmp_bsd.go
@@ -0,0 +1,29 @@
+// Copyright 2013 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.
+
+// +build darwin dragonfly freebsd netbsd openbsd
+
+package ipv6
+
+func (f *icmpv6Filter) accept(typ ICMPType) {
+ f.Filt[typ>>5] |= 1 << (uint32(typ) & 31)
+}
+
+func (f *icmpv6Filter) block(typ ICMPType) {
+ f.Filt[typ>>5] &^= 1 << (uint32(typ) & 31)
+}
+
+func (f *icmpv6Filter) setAll(block bool) {
+ for i := range f.Filt {
+ if block {
+ f.Filt[i] = 0
+ } else {
+ f.Filt[i] = 1<<32 - 1
+ }
+ }
+}
+
+func (f *icmpv6Filter) willBlock(typ ICMPType) bool {
+ return f.Filt[typ>>5]&(1<<(uint32(typ)&31)) == 0
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/icmp_linux.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/icmp_linux.go
new file mode 100644
index 000000000..647f6b44f
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/icmp_linux.go
@@ -0,0 +1,27 @@
+// Copyright 2013 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 ipv6
+
+func (f *icmpv6Filter) accept(typ ICMPType) {
+ f.Data[typ>>5] &^= 1 << (uint32(typ) & 31)
+}
+
+func (f *icmpv6Filter) block(typ ICMPType) {
+ f.Data[typ>>5] |= 1 << (uint32(typ) & 31)
+}
+
+func (f *icmpv6Filter) setAll(block bool) {
+ for i := range f.Data {
+ if block {
+ f.Data[i] = 1<<32 - 1
+ } else {
+ f.Data[i] = 0
+ }
+ }
+}
+
+func (f *icmpv6Filter) willBlock(typ ICMPType) bool {
+ return f.Data[typ>>5]&(1<<(uint32(typ)&31)) != 0
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/icmp_solaris.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/icmp_solaris.go
new file mode 100644
index 000000000..7c23bb1cf
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/icmp_solaris.go
@@ -0,0 +1,27 @@
+// Copyright 2013 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 ipv6
+
+func (f *icmpv6Filter) accept(typ ICMPType) {
+ f.X__icmp6_filt[typ>>5] |= 1 << (uint32(typ) & 31)
+}
+
+func (f *icmpv6Filter) block(typ ICMPType) {
+ f.X__icmp6_filt[typ>>5] &^= 1 << (uint32(typ) & 31)
+}
+
+func (f *icmpv6Filter) setAll(block bool) {
+ for i := range f.X__icmp6_filt {
+ if block {
+ f.X__icmp6_filt[i] = 0
+ } else {
+ f.X__icmp6_filt[i] = 1<<32 - 1
+ }
+ }
+}
+
+func (f *icmpv6Filter) willBlock(typ ICMPType) bool {
+ return f.X__icmp6_filt[typ>>5]&(1<<(uint32(typ)&31)) == 0
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/icmp_stub.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/icmp_stub.go
new file mode 100644
index 000000000..c4b9be6db
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/icmp_stub.go
@@ -0,0 +1,23 @@
+// Copyright 2013 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.
+
+// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows
+
+package ipv6
+
+type icmpv6Filter struct {
+}
+
+func (f *icmpv6Filter) accept(typ ICMPType) {
+}
+
+func (f *icmpv6Filter) block(typ ICMPType) {
+}
+
+func (f *icmpv6Filter) setAll(block bool) {
+}
+
+func (f *icmpv6Filter) willBlock(typ ICMPType) bool {
+ return false
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/icmp_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/icmp_test.go
new file mode 100644
index 000000000..d8e9675dc
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/icmp_test.go
@@ -0,0 +1,96 @@
+// Copyright 2013 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 ipv6_test
+
+import (
+ "net"
+ "reflect"
+ "runtime"
+ "testing"
+
+ "golang.org/x/net/internal/nettest"
+ "golang.org/x/net/ipv6"
+)
+
+var icmpStringTests = []struct {
+ in ipv6.ICMPType
+ out string
+}{
+ {ipv6.ICMPTypeDestinationUnreachable, "destination unreachable"},
+
+ {256, "<nil>"},
+}
+
+func TestICMPString(t *testing.T) {
+ for _, tt := range icmpStringTests {
+ s := tt.in.String()
+ if s != tt.out {
+ t.Errorf("got %s; want %s", s, tt.out)
+ }
+ }
+}
+
+func TestICMPFilter(t *testing.T) {
+ switch runtime.GOOS {
+ case "nacl", "plan9", "windows":
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+
+ var f ipv6.ICMPFilter
+ for _, toggle := range []bool{false, true} {
+ f.SetAll(toggle)
+ for _, typ := range []ipv6.ICMPType{
+ ipv6.ICMPTypeDestinationUnreachable,
+ ipv6.ICMPTypeEchoReply,
+ ipv6.ICMPTypeNeighborSolicitation,
+ ipv6.ICMPTypeDuplicateAddressConfirmation,
+ } {
+ f.Accept(typ)
+ if f.WillBlock(typ) {
+ t.Errorf("ipv6.ICMPFilter.Set(%v, false) failed", typ)
+ }
+ f.Block(typ)
+ if !f.WillBlock(typ) {
+ t.Errorf("ipv6.ICMPFilter.Set(%v, true) failed", typ)
+ }
+ }
+ }
+}
+
+func TestSetICMPFilter(t *testing.T) {
+ switch runtime.GOOS {
+ case "nacl", "plan9", "windows":
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+ if !supportsIPv6 {
+ t.Skip("ipv6 is not supported")
+ }
+ if m, ok := nettest.SupportsRawIPSocket(); !ok {
+ t.Skip(m)
+ }
+
+ c, err := net.ListenPacket("ip6:ipv6-icmp", "::1")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer c.Close()
+
+ p := ipv6.NewPacketConn(c)
+
+ var f ipv6.ICMPFilter
+ f.SetAll(true)
+ f.Accept(ipv6.ICMPTypeEchoRequest)
+ f.Accept(ipv6.ICMPTypeEchoReply)
+ if err := p.SetICMPFilter(&f); err != nil {
+ t.Fatal(err)
+ }
+ kf, err := p.ICMPFilter()
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !reflect.DeepEqual(kf, &f) {
+ t.Fatalf("got %#v; want %#v", kf, f)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/icmp_windows.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/icmp_windows.go
new file mode 100644
index 000000000..443cd0736
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/icmp_windows.go
@@ -0,0 +1,22 @@
+// Copyright 2013 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 ipv6
+
+func (f *icmpv6Filter) accept(typ ICMPType) {
+ // TODO(mikio): implement this
+}
+
+func (f *icmpv6Filter) block(typ ICMPType) {
+ // TODO(mikio): implement this
+}
+
+func (f *icmpv6Filter) setAll(block bool) {
+ // TODO(mikio): implement this
+}
+
+func (f *icmpv6Filter) willBlock(typ ICMPType) bool {
+ // TODO(mikio): implement this
+ return false
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/mocktransponder_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/mocktransponder_test.go
new file mode 100644
index 000000000..6efe56c68
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/mocktransponder_test.go
@@ -0,0 +1,32 @@
+// Copyright 2013 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 ipv6_test
+
+import (
+ "net"
+ "testing"
+)
+
+func connector(t *testing.T, network, addr string, done chan<- bool) {
+ defer func() { done <- true }()
+
+ c, err := net.Dial(network, addr)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ c.Close()
+}
+
+func acceptor(t *testing.T, ln net.Listener, done chan<- bool) {
+ defer func() { done <- true }()
+
+ c, err := ln.Accept()
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ c.Close()
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/multicast_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/multicast_test.go
new file mode 100644
index 000000000..69a21cd38
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/multicast_test.go
@@ -0,0 +1,264 @@
+// Copyright 2013 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 ipv6_test
+
+import (
+ "bytes"
+ "net"
+ "os"
+ "runtime"
+ "testing"
+ "time"
+
+ "golang.org/x/net/icmp"
+ "golang.org/x/net/internal/iana"
+ "golang.org/x/net/internal/nettest"
+ "golang.org/x/net/ipv6"
+)
+
+var packetConnReadWriteMulticastUDPTests = []struct {
+ addr string
+ grp, src *net.UDPAddr
+}{
+ {"[ff02::]:0", &net.UDPAddr{IP: net.ParseIP("ff02::114")}, nil}, // see RFC 4727
+
+ {"[ff30::8000:0]:0", &net.UDPAddr{IP: net.ParseIP("ff30::8000:1")}, &net.UDPAddr{IP: net.IPv6loopback}}, // see RFC 5771
+}
+
+func TestPacketConnReadWriteMulticastUDP(t *testing.T) {
+ switch runtime.GOOS {
+ case "nacl", "plan9", "windows":
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+ if !supportsIPv6 {
+ t.Skip("ipv6 is not supported")
+ }
+ if !nettest.SupportsIPv6MulticastDeliveryOnLoopback() {
+ t.Skipf("multicast delivery doesn't work correctly on %s", runtime.GOOS)
+ }
+ ifi := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagMulticast|net.FlagLoopback)
+ if ifi == nil {
+ t.Skipf("not available on %s", runtime.GOOS)
+ }
+
+ for _, tt := range packetConnReadWriteMulticastUDPTests {
+ c, err := net.ListenPacket("udp6", tt.addr)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer c.Close()
+
+ grp := *tt.grp
+ grp.Port = c.LocalAddr().(*net.UDPAddr).Port
+ p := ipv6.NewPacketConn(c)
+ defer p.Close()
+ if tt.src == nil {
+ if err := p.JoinGroup(ifi, &grp); err != nil {
+ t.Fatal(err)
+ }
+ defer p.LeaveGroup(ifi, &grp)
+ } else {
+ if err := p.JoinSourceSpecificGroup(ifi, &grp, tt.src); err != nil {
+ switch runtime.GOOS {
+ case "freebsd", "linux":
+ default: // platforms that don't support MLDv2 fail here
+ t.Logf("not supported on %s", runtime.GOOS)
+ continue
+ }
+ t.Fatal(err)
+ }
+ defer p.LeaveSourceSpecificGroup(ifi, &grp, tt.src)
+ }
+ if err := p.SetMulticastInterface(ifi); err != nil {
+ t.Fatal(err)
+ }
+ if _, err := p.MulticastInterface(); err != nil {
+ t.Fatal(err)
+ }
+ if err := p.SetMulticastLoopback(true); err != nil {
+ t.Fatal(err)
+ }
+ if _, err := p.MulticastLoopback(); err != nil {
+ t.Fatal(err)
+ }
+
+ cm := ipv6.ControlMessage{
+ TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced,
+ Src: net.IPv6loopback,
+ IfIndex: ifi.Index,
+ }
+ cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU
+ wb := []byte("HELLO-R-U-THERE")
+
+ for i, toggle := range []bool{true, false, true} {
+ if err := p.SetControlMessage(cf, toggle); err != nil {
+ if nettest.ProtocolNotSupported(err) {
+ t.Logf("not supported on %s", runtime.GOOS)
+ continue
+ }
+ t.Fatal(err)
+ }
+ if err := p.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil {
+ t.Fatal(err)
+ }
+ cm.HopLimit = i + 1
+ if n, err := p.WriteTo(wb, &cm, &grp); err != nil {
+ t.Fatal(err)
+ } else if n != len(wb) {
+ t.Fatal(err)
+ }
+ rb := make([]byte, 128)
+ if n, _, _, err := p.ReadFrom(rb); err != nil {
+ t.Fatal(err)
+ } else if !bytes.Equal(rb[:n], wb) {
+ t.Fatalf("got %v; want %v", rb[:n], wb)
+ }
+ }
+ }
+}
+
+var packetConnReadWriteMulticastICMPTests = []struct {
+ grp, src *net.IPAddr
+}{
+ {&net.IPAddr{IP: net.ParseIP("ff02::114")}, nil}, // see RFC 4727
+
+ {&net.IPAddr{IP: net.ParseIP("ff30::8000:1")}, &net.IPAddr{IP: net.IPv6loopback}}, // see RFC 5771
+}
+
+func TestPacketConnReadWriteMulticastICMP(t *testing.T) {
+ switch runtime.GOOS {
+ case "nacl", "plan9", "windows":
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+ if !supportsIPv6 {
+ t.Skip("ipv6 is not supported")
+ }
+ if !nettest.SupportsIPv6MulticastDeliveryOnLoopback() {
+ t.Skipf("multicast delivery doesn't work correctly on %s", runtime.GOOS)
+ }
+ if m, ok := nettest.SupportsRawIPSocket(); !ok {
+ t.Skip(m)
+ }
+ ifi := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagMulticast|net.FlagLoopback)
+ if ifi == nil {
+ t.Skipf("not available on %s", runtime.GOOS)
+ }
+
+ for _, tt := range packetConnReadWriteMulticastICMPTests {
+ c, err := net.ListenPacket("ip6:ipv6-icmp", "::")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer c.Close()
+
+ pshicmp := icmp.IPv6PseudoHeader(c.LocalAddr().(*net.IPAddr).IP, tt.grp.IP)
+ p := ipv6.NewPacketConn(c)
+ defer p.Close()
+ if tt.src == nil {
+ if err := p.JoinGroup(ifi, tt.grp); err != nil {
+ t.Fatal(err)
+ }
+ defer p.LeaveGroup(ifi, tt.grp)
+ } else {
+ if err := p.JoinSourceSpecificGroup(ifi, tt.grp, tt.src); err != nil {
+ switch runtime.GOOS {
+ case "freebsd", "linux":
+ default: // platforms that don't support MLDv2 fail here
+ t.Logf("not supported on %s", runtime.GOOS)
+ continue
+ }
+ t.Fatal(err)
+ }
+ defer p.LeaveSourceSpecificGroup(ifi, tt.grp, tt.src)
+ }
+ if err := p.SetMulticastInterface(ifi); err != nil {
+ t.Fatal(err)
+ }
+ if _, err := p.MulticastInterface(); err != nil {
+ t.Fatal(err)
+ }
+ if err := p.SetMulticastLoopback(true); err != nil {
+ t.Fatal(err)
+ }
+ if _, err := p.MulticastLoopback(); err != nil {
+ t.Fatal(err)
+ }
+
+ cm := ipv6.ControlMessage{
+ TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced,
+ Src: net.IPv6loopback,
+ IfIndex: ifi.Index,
+ }
+ cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU
+
+ var f ipv6.ICMPFilter
+ f.SetAll(true)
+ f.Accept(ipv6.ICMPTypeEchoReply)
+ if err := p.SetICMPFilter(&f); err != nil {
+ t.Fatal(err)
+ }
+
+ var psh []byte
+ for i, toggle := range []bool{true, false, true} {
+ if toggle {
+ psh = nil
+ if err := p.SetChecksum(true, 2); err != nil {
+ // Solaris never allows to
+ // modify ICMP properties.
+ if runtime.GOOS != "solaris" {
+ t.Fatal(err)
+ }
+ }
+ } else {
+ psh = pshicmp
+ // Some platforms never allow to
+ // disable the kernel checksum
+ // processing.
+ p.SetChecksum(false, -1)
+ }
+ wb, err := (&icmp.Message{
+ Type: ipv6.ICMPTypeEchoRequest, Code: 0,
+ Body: &icmp.Echo{
+ ID: os.Getpid() & 0xffff, Seq: i + 1,
+ Data: []byte("HELLO-R-U-THERE"),
+ },
+ }).Marshal(psh)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := p.SetControlMessage(cf, toggle); err != nil {
+ if nettest.ProtocolNotSupported(err) {
+ t.Logf("not supported on %s", runtime.GOOS)
+ continue
+ }
+ t.Fatal(err)
+ }
+ if err := p.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil {
+ t.Fatal(err)
+ }
+ cm.HopLimit = i + 1
+ if n, err := p.WriteTo(wb, &cm, tt.grp); err != nil {
+ t.Fatal(err)
+ } else if n != len(wb) {
+ t.Fatalf("got %v; want %v", n, len(wb))
+ }
+ rb := make([]byte, 128)
+ if n, _, _, err := p.ReadFrom(rb); err != nil {
+ switch runtime.GOOS {
+ case "darwin": // older darwin kernels have some limitation on receiving icmp packet through raw socket
+ t.Logf("not supported on %s", runtime.GOOS)
+ continue
+ }
+ t.Fatal(err)
+ } else {
+ if m, err := icmp.ParseMessage(iana.ProtocolIPv6ICMP, rb[:n]); err != nil {
+ t.Fatal(err)
+ } else if m.Type != ipv6.ICMPTypeEchoReply || m.Code != 0 {
+ t.Fatalf("got type=%v, code=%v; want type=%v, code=%v", m.Type, m.Code, ipv6.ICMPTypeEchoReply, 0)
+ }
+ }
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/multicastlistener_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/multicastlistener_test.go
new file mode 100644
index 000000000..b27713e2f
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/multicastlistener_test.go
@@ -0,0 +1,261 @@
+// Copyright 2013 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 ipv6_test
+
+import (
+ "net"
+ "runtime"
+ "testing"
+
+ "golang.org/x/net/internal/nettest"
+ "golang.org/x/net/ipv6"
+)
+
+var udpMultipleGroupListenerTests = []net.Addr{
+ &net.UDPAddr{IP: net.ParseIP("ff02::114")}, // see RFC 4727
+ &net.UDPAddr{IP: net.ParseIP("ff02::1:114")},
+ &net.UDPAddr{IP: net.ParseIP("ff02::2:114")},
+}
+
+func TestUDPSinglePacketConnWithMultipleGroupListeners(t *testing.T) {
+ switch runtime.GOOS {
+ case "nacl", "plan9", "windows":
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+ if !supportsIPv6 {
+ t.Skip("ipv6 is not supported")
+ }
+
+ for _, gaddr := range udpMultipleGroupListenerTests {
+ c, err := net.ListenPacket("udp6", "[::]:0") // wildcard address with non-reusable port
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer c.Close()
+
+ p := ipv6.NewPacketConn(c)
+ var mift []*net.Interface
+
+ ift, err := net.Interfaces()
+ if err != nil {
+ t.Fatal(err)
+ }
+ for i, ifi := range ift {
+ if _, ok := nettest.IsMulticastCapable("ip6", &ifi); !ok {
+ continue
+ }
+ if err := p.JoinGroup(&ifi, gaddr); err != nil {
+ t.Fatal(err)
+ }
+ mift = append(mift, &ift[i])
+ }
+ for _, ifi := range mift {
+ if err := p.LeaveGroup(ifi, gaddr); err != nil {
+ t.Fatal(err)
+ }
+ }
+ }
+}
+
+func TestUDPMultiplePacketConnWithMultipleGroupListeners(t *testing.T) {
+ switch runtime.GOOS {
+ case "nacl", "plan9", "windows":
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+ if !supportsIPv6 {
+ t.Skip("ipv6 is not supported")
+ }
+
+ for _, gaddr := range udpMultipleGroupListenerTests {
+ c1, err := net.ListenPacket("udp6", "[ff02::]:0") // wildcard address with reusable port
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer c1.Close()
+ _, port, err := net.SplitHostPort(c1.LocalAddr().String())
+ if err != nil {
+ t.Fatal(err)
+ }
+ c2, err := net.ListenPacket("udp6", net.JoinHostPort("ff02::", port)) // wildcard address with reusable port
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer c2.Close()
+
+ var ps [2]*ipv6.PacketConn
+ ps[0] = ipv6.NewPacketConn(c1)
+ ps[1] = ipv6.NewPacketConn(c2)
+ var mift []*net.Interface
+
+ ift, err := net.Interfaces()
+ if err != nil {
+ t.Fatal(err)
+ }
+ for i, ifi := range ift {
+ if _, ok := nettest.IsMulticastCapable("ip6", &ifi); !ok {
+ continue
+ }
+ for _, p := range ps {
+ if err := p.JoinGroup(&ifi, gaddr); err != nil {
+ t.Fatal(err)
+ }
+ }
+ mift = append(mift, &ift[i])
+ }
+ for _, ifi := range mift {
+ for _, p := range ps {
+ if err := p.LeaveGroup(ifi, gaddr); err != nil {
+ t.Fatal(err)
+ }
+ }
+ }
+ }
+}
+
+func TestUDPPerInterfaceSinglePacketConnWithSingleGroupListener(t *testing.T) {
+ switch runtime.GOOS {
+ case "nacl", "plan9", "windows":
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+ if !supportsIPv6 {
+ t.Skip("ipv6 is not supported")
+ }
+
+ gaddr := net.IPAddr{IP: net.ParseIP("ff02::114")} // see RFC 4727
+ type ml struct {
+ c *ipv6.PacketConn
+ ifi *net.Interface
+ }
+ var mlt []*ml
+
+ ift, err := net.Interfaces()
+ if err != nil {
+ t.Fatal(err)
+ }
+ port := "0"
+ for i, ifi := range ift {
+ ip, ok := nettest.IsMulticastCapable("ip6", &ifi)
+ if !ok {
+ continue
+ }
+ c, err := net.ListenPacket("udp6", net.JoinHostPort(ip.String()+"%"+ifi.Name, port)) // unicast address with non-reusable port
+ if err != nil {
+ // The listen may fail when the serivce is
+ // already in use, but it's fine because the
+ // purpose of this is not to test the
+ // bookkeeping of IP control block inside the
+ // kernel.
+ t.Log(err)
+ continue
+ }
+ defer c.Close()
+ if port == "0" {
+ _, port, err = net.SplitHostPort(c.LocalAddr().String())
+ if err != nil {
+ t.Fatal(err)
+ }
+ }
+ p := ipv6.NewPacketConn(c)
+ if err := p.JoinGroup(&ifi, &gaddr); err != nil {
+ t.Fatal(err)
+ }
+ mlt = append(mlt, &ml{p, &ift[i]})
+ }
+ for _, m := range mlt {
+ if err := m.c.LeaveGroup(m.ifi, &gaddr); err != nil {
+ t.Fatal(err)
+ }
+ }
+}
+
+func TestIPSinglePacketConnWithSingleGroupListener(t *testing.T) {
+ switch runtime.GOOS {
+ case "nacl", "plan9", "windows":
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+ if !supportsIPv6 {
+ t.Skip("ipv6 is not supported")
+ }
+ if m, ok := nettest.SupportsRawIPSocket(); !ok {
+ t.Skip(m)
+ }
+
+ c, err := net.ListenPacket("ip6:ipv6-icmp", "::") // wildcard address
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer c.Close()
+
+ p := ipv6.NewPacketConn(c)
+ gaddr := net.IPAddr{IP: net.ParseIP("ff02::114")} // see RFC 4727
+ var mift []*net.Interface
+
+ ift, err := net.Interfaces()
+ if err != nil {
+ t.Fatal(err)
+ }
+ for i, ifi := range ift {
+ if _, ok := nettest.IsMulticastCapable("ip6", &ifi); !ok {
+ continue
+ }
+ if err := p.JoinGroup(&ifi, &gaddr); err != nil {
+ t.Fatal(err)
+ }
+ mift = append(mift, &ift[i])
+ }
+ for _, ifi := range mift {
+ if err := p.LeaveGroup(ifi, &gaddr); err != nil {
+ t.Fatal(err)
+ }
+ }
+}
+
+func TestIPPerInterfaceSinglePacketConnWithSingleGroupListener(t *testing.T) {
+ switch runtime.GOOS {
+ case "darwin", "dragonfly", "openbsd": // platforms that return fe80::1%lo0: bind: can't assign requested address
+ t.Skipf("not supported on %s", runtime.GOOS)
+ case "nacl", "plan9", "windows":
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+ if !supportsIPv6 {
+ t.Skip("ipv6 is not supported")
+ }
+ if m, ok := nettest.SupportsRawIPSocket(); !ok {
+ t.Skip(m)
+ }
+
+ gaddr := net.IPAddr{IP: net.ParseIP("ff02::114")} // see RFC 4727
+ type ml struct {
+ c *ipv6.PacketConn
+ ifi *net.Interface
+ }
+ var mlt []*ml
+
+ ift, err := net.Interfaces()
+ if err != nil {
+ t.Fatal(err)
+ }
+ for i, ifi := range ift {
+ ip, ok := nettest.IsMulticastCapable("ip6", &ifi)
+ if !ok {
+ continue
+ }
+ c, err := net.ListenPacket("ip6:ipv6-icmp", ip.String()+"%"+ifi.Name) // unicast address
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer c.Close()
+ p := ipv6.NewPacketConn(c)
+ if err := p.JoinGroup(&ifi, &gaddr); err != nil {
+ t.Fatal(err)
+ }
+ mlt = append(mlt, &ml{p, &ift[i]})
+ }
+ for _, m := range mlt {
+ if err := m.c.LeaveGroup(m.ifi, &gaddr); err != nil {
+ t.Fatal(err)
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/multicastsockopt_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/multicastsockopt_test.go
new file mode 100644
index 000000000..9e6b902d7
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/multicastsockopt_test.go
@@ -0,0 +1,157 @@
+// Copyright 2013 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 ipv6_test
+
+import (
+ "net"
+ "runtime"
+ "testing"
+
+ "golang.org/x/net/internal/nettest"
+ "golang.org/x/net/ipv6"
+)
+
+var packetConnMulticastSocketOptionTests = []struct {
+ net, proto, addr string
+ grp, src net.Addr
+}{
+ {"udp6", "", "[ff02::]:0", &net.UDPAddr{IP: net.ParseIP("ff02::114")}, nil}, // see RFC 4727
+ {"ip6", ":ipv6-icmp", "::", &net.IPAddr{IP: net.ParseIP("ff02::115")}, nil}, // see RFC 4727
+
+ {"udp6", "", "[ff30::8000:0]:0", &net.UDPAddr{IP: net.ParseIP("ff30::8000:1")}, &net.UDPAddr{IP: net.IPv6loopback}}, // see RFC 5771
+ {"ip6", ":ipv6-icmp", "::", &net.IPAddr{IP: net.ParseIP("ff30::8000:2")}, &net.IPAddr{IP: net.IPv6loopback}}, // see RFC 5771
+}
+
+func TestPacketConnMulticastSocketOptions(t *testing.T) {
+ switch runtime.GOOS {
+ case "nacl", "plan9", "windows":
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+ if !supportsIPv6 {
+ t.Skip("ipv6 is not supported")
+ }
+ ifi := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagMulticast|net.FlagLoopback)
+ if ifi == nil {
+ t.Skipf("not available on %s", runtime.GOOS)
+ }
+
+ m, ok := nettest.SupportsRawIPSocket()
+ for _, tt := range packetConnMulticastSocketOptionTests {
+ if tt.net == "ip6" && !ok {
+ t.Log(m)
+ continue
+ }
+ c, err := net.ListenPacket(tt.net+tt.proto, tt.addr)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer c.Close()
+ p := ipv6.NewPacketConn(c)
+ defer p.Close()
+
+ if tt.src == nil {
+ testMulticastSocketOptions(t, p, ifi, tt.grp)
+ } else {
+ testSourceSpecificMulticastSocketOptions(t, p, ifi, tt.grp, tt.src)
+ }
+ }
+}
+
+type testIPv6MulticastConn interface {
+ MulticastHopLimit() (int, error)
+ SetMulticastHopLimit(ttl int) error
+ MulticastLoopback() (bool, error)
+ SetMulticastLoopback(bool) error
+ JoinGroup(*net.Interface, net.Addr) error
+ LeaveGroup(*net.Interface, net.Addr) error
+ JoinSourceSpecificGroup(*net.Interface, net.Addr, net.Addr) error
+ LeaveSourceSpecificGroup(*net.Interface, net.Addr, net.Addr) error
+ ExcludeSourceSpecificGroup(*net.Interface, net.Addr, net.Addr) error
+ IncludeSourceSpecificGroup(*net.Interface, net.Addr, net.Addr) error
+}
+
+func testMulticastSocketOptions(t *testing.T, c testIPv6MulticastConn, ifi *net.Interface, grp net.Addr) {
+ const hoplim = 255
+ if err := c.SetMulticastHopLimit(hoplim); err != nil {
+ t.Error(err)
+ return
+ }
+ if v, err := c.MulticastHopLimit(); err != nil {
+ t.Error(err)
+ return
+ } else if v != hoplim {
+ t.Errorf("got %v; want %v", v, hoplim)
+ return
+ }
+
+ for _, toggle := range []bool{true, false} {
+ if err := c.SetMulticastLoopback(toggle); err != nil {
+ t.Error(err)
+ return
+ }
+ if v, err := c.MulticastLoopback(); err != nil {
+ t.Error(err)
+ return
+ } else if v != toggle {
+ t.Errorf("got %v; want %v", v, toggle)
+ return
+ }
+ }
+
+ if err := c.JoinGroup(ifi, grp); err != nil {
+ t.Error(err)
+ return
+ }
+ if err := c.LeaveGroup(ifi, grp); err != nil {
+ t.Error(err)
+ return
+ }
+}
+
+func testSourceSpecificMulticastSocketOptions(t *testing.T, c testIPv6MulticastConn, ifi *net.Interface, grp, src net.Addr) {
+ // MCAST_JOIN_GROUP -> MCAST_BLOCK_SOURCE -> MCAST_UNBLOCK_SOURCE -> MCAST_LEAVE_GROUP
+ if err := c.JoinGroup(ifi, grp); err != nil {
+ t.Error(err)
+ return
+ }
+ if err := c.ExcludeSourceSpecificGroup(ifi, grp, src); err != nil {
+ switch runtime.GOOS {
+ case "freebsd", "linux":
+ default: // platforms that don't support MLDv2 fail here
+ t.Logf("not supported on %s", runtime.GOOS)
+ return
+ }
+ t.Error(err)
+ return
+ }
+ if err := c.IncludeSourceSpecificGroup(ifi, grp, src); err != nil {
+ t.Error(err)
+ return
+ }
+ if err := c.LeaveGroup(ifi, grp); err != nil {
+ t.Error(err)
+ return
+ }
+
+ // MCAST_JOIN_SOURCE_GROUP -> MCAST_LEAVE_SOURCE_GROUP
+ if err := c.JoinSourceSpecificGroup(ifi, grp, src); err != nil {
+ t.Error(err)
+ return
+ }
+ if err := c.LeaveSourceSpecificGroup(ifi, grp, src); err != nil {
+ t.Error(err)
+ return
+ }
+
+ // MCAST_JOIN_SOURCE_GROUP -> MCAST_LEAVE_GROUP
+ if err := c.JoinSourceSpecificGroup(ifi, grp, src); err != nil {
+ t.Error(err)
+ return
+ }
+ if err := c.LeaveGroup(ifi, grp); err != nil {
+ t.Error(err)
+ return
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/payload.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/payload.go
new file mode 100644
index 000000000..a8197f169
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/payload.go
@@ -0,0 +1,23 @@
+// Copyright 2013 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 ipv6
+
+import (
+ "net"
+
+ "golang.org/x/net/internal/socket"
+)
+
+// BUG(mikio): On Windows, the ControlMessage for ReadFrom and WriteTo
+// methods of PacketConn is not implemented.
+
+// A payloadHandler represents the IPv6 datagram payload handler.
+type payloadHandler struct {
+ net.PacketConn
+ *socket.Conn
+ rawOpt
+}
+
+func (c *payloadHandler) ok() bool { return c != nil && c.PacketConn != nil && c.Conn != nil }
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/payload_cmsg.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/payload_cmsg.go
new file mode 100644
index 000000000..4ee4b062c
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/payload_cmsg.go
@@ -0,0 +1,35 @@
+// Copyright 2013 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.
+
+// +build !nacl,!plan9,!windows
+
+package ipv6
+
+import (
+ "net"
+ "syscall"
+)
+
+// ReadFrom reads a payload of the received IPv6 datagram, from the
+// endpoint c, copying the payload into b. It returns the number of
+// bytes copied into b, the control message cm and the source address
+// src of the received datagram.
+func (c *payloadHandler) ReadFrom(b []byte) (n int, cm *ControlMessage, src net.Addr, err error) {
+ if !c.ok() {
+ return 0, nil, nil, syscall.EINVAL
+ }
+ return c.readFrom(b)
+}
+
+// WriteTo writes a payload of the IPv6 datagram, to the destination
+// address dst through the endpoint c, copying the payload from b. It
+// returns the number of bytes written. The control message cm allows
+// the IPv6 header fields and the datagram path to be specified. The
+// cm may be nil if control of the outgoing datagram is not required.
+func (c *payloadHandler) WriteTo(b []byte, cm *ControlMessage, dst net.Addr) (n int, err error) {
+ if !c.ok() {
+ return 0, syscall.EINVAL
+ }
+ return c.writeTo(b, cm, dst)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/payload_cmsg_go1_8.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/payload_cmsg_go1_8.go
new file mode 100644
index 000000000..fdc6c3994
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/payload_cmsg_go1_8.go
@@ -0,0 +1,55 @@
+// Copyright 2013 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.
+
+// +build !go1.9
+// +build !nacl,!plan9,!windows
+
+package ipv6
+
+import "net"
+
+func (c *payloadHandler) readFrom(b []byte) (n int, cm *ControlMessage, src net.Addr, err error) {
+ c.rawOpt.RLock()
+ oob := NewControlMessage(c.rawOpt.cflags)
+ c.rawOpt.RUnlock()
+ var nn int
+ switch c := c.PacketConn.(type) {
+ case *net.UDPConn:
+ if n, nn, _, src, err = c.ReadMsgUDP(b, oob); err != nil {
+ return 0, nil, nil, err
+ }
+ case *net.IPConn:
+ if n, nn, _, src, err = c.ReadMsgIP(b, oob); err != nil {
+ return 0, nil, nil, err
+ }
+ default:
+ return 0, nil, nil, &net.OpError{Op: "read", Net: c.LocalAddr().Network(), Source: c.LocalAddr(), Err: errInvalidConnType}
+ }
+ if nn > 0 {
+ cm = new(ControlMessage)
+ if err = cm.Parse(oob[:nn]); err != nil {
+ return 0, nil, nil, &net.OpError{Op: "read", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: err}
+ }
+ }
+ if cm != nil {
+ cm.Src = netAddrToIP16(src)
+ }
+ return
+}
+
+func (c *payloadHandler) writeTo(b []byte, cm *ControlMessage, dst net.Addr) (n int, err error) {
+ oob := cm.Marshal()
+ if dst == nil {
+ return 0, &net.OpError{Op: "write", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: errMissingAddress}
+ }
+ switch c := c.PacketConn.(type) {
+ case *net.UDPConn:
+ n, _, err = c.WriteMsgUDP(b, oob, dst.(*net.UDPAddr))
+ case *net.IPConn:
+ n, _, err = c.WriteMsgIP(b, oob, dst.(*net.IPAddr))
+ default:
+ return 0, &net.OpError{Op: "write", Net: c.LocalAddr().Network(), Source: c.LocalAddr(), Addr: opAddr(dst), Err: errInvalidConnType}
+ }
+ return
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/payload_cmsg_go1_9.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/payload_cmsg_go1_9.go
new file mode 100644
index 000000000..8f6d02e2f
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/payload_cmsg_go1_9.go
@@ -0,0 +1,57 @@
+// 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.
+
+// +build go1.9
+// +build !nacl,!plan9,!windows
+
+package ipv6
+
+import (
+ "net"
+
+ "golang.org/x/net/internal/socket"
+)
+
+func (c *payloadHandler) readFrom(b []byte) (int, *ControlMessage, net.Addr, error) {
+ c.rawOpt.RLock()
+ m := socket.Message{
+ Buffers: [][]byte{b},
+ OOB: NewControlMessage(c.rawOpt.cflags),
+ }
+ c.rawOpt.RUnlock()
+ switch c.PacketConn.(type) {
+ case *net.UDPConn:
+ if err := c.RecvMsg(&m, 0); err != nil {
+ return 0, nil, nil, &net.OpError{Op: "read", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: err}
+ }
+ case *net.IPConn:
+ if err := c.RecvMsg(&m, 0); err != nil {
+ return 0, nil, nil, &net.OpError{Op: "read", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: err}
+ }
+ default:
+ return 0, nil, nil, &net.OpError{Op: "read", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: errInvalidConnType}
+ }
+ var cm *ControlMessage
+ if m.NN > 0 {
+ cm = new(ControlMessage)
+ if err := cm.Parse(m.OOB[:m.NN]); err != nil {
+ return 0, nil, nil, &net.OpError{Op: "read", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: err}
+ }
+ cm.Src = netAddrToIP16(m.Addr)
+ }
+ return m.N, cm, m.Addr, nil
+}
+
+func (c *payloadHandler) writeTo(b []byte, cm *ControlMessage, dst net.Addr) (int, error) {
+ m := socket.Message{
+ Buffers: [][]byte{b},
+ OOB: cm.Marshal(),
+ Addr: dst,
+ }
+ err := c.SendMsg(&m, 0)
+ if err != nil {
+ err = &net.OpError{Op: "write", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Addr: opAddr(dst), Err: err}
+ }
+ return m.N, err
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/payload_nocmsg.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/payload_nocmsg.go
new file mode 100644
index 000000000..99a43542b
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/payload_nocmsg.go
@@ -0,0 +1,41 @@
+// Copyright 2013 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.
+
+// +build nacl plan9 windows
+
+package ipv6
+
+import (
+ "net"
+ "syscall"
+)
+
+// ReadFrom reads a payload of the received IPv6 datagram, from the
+// endpoint c, copying the payload into b. It returns the number of
+// bytes copied into b, the control message cm and the source address
+// src of the received datagram.
+func (c *payloadHandler) ReadFrom(b []byte) (n int, cm *ControlMessage, src net.Addr, err error) {
+ if !c.ok() {
+ return 0, nil, nil, syscall.EINVAL
+ }
+ if n, src, err = c.PacketConn.ReadFrom(b); err != nil {
+ return 0, nil, nil, err
+ }
+ return
+}
+
+// WriteTo writes a payload of the IPv6 datagram, to the destination
+// address dst through the endpoint c, copying the payload from b. It
+// returns the number of bytes written. The control message cm allows
+// the IPv6 header fields and the datagram path to be specified. The
+// cm may be nil if control of the outgoing datagram is not required.
+func (c *payloadHandler) WriteTo(b []byte, cm *ControlMessage, dst net.Addr) (n int, err error) {
+ if !c.ok() {
+ return 0, syscall.EINVAL
+ }
+ if dst == nil {
+ return 0, errMissingAddress
+ }
+ return c.PacketConn.WriteTo(b, dst)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/readwrite_go1_8_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/readwrite_go1_8_test.go
new file mode 100644
index 000000000..c11d92ae9
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/readwrite_go1_8_test.go
@@ -0,0 +1,242 @@
+// Copyright 2013 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.
+
+// +build !go1.9
+
+package ipv6_test
+
+import (
+ "bytes"
+ "fmt"
+ "net"
+ "runtime"
+ "strings"
+ "sync"
+ "testing"
+
+ "golang.org/x/net/internal/iana"
+ "golang.org/x/net/internal/nettest"
+ "golang.org/x/net/ipv6"
+)
+
+func BenchmarkPacketConnReadWriteUnicast(b *testing.B) {
+ switch runtime.GOOS {
+ case "nacl", "plan9", "windows":
+ b.Skipf("not supported on %s", runtime.GOOS)
+ }
+
+ payload := []byte("HELLO-R-U-THERE")
+ iph := []byte{
+ 0x69, 0x8b, 0xee, 0xf1, 0xca, 0xfe, 0xff, 0x01,
+ 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x02, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ }
+ greh := []byte{0x00, 0x00, 0x86, 0xdd, 0x00, 0x00, 0x00, 0x00}
+ datagram := append(greh, append(iph, payload...)...)
+ bb := make([]byte, 128)
+ cm := ipv6.ControlMessage{
+ TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced,
+ HopLimit: 1,
+ Src: net.IPv6loopback,
+ }
+ if ifi := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback); ifi != nil {
+ cm.IfIndex = ifi.Index
+ }
+
+ b.Run("UDP", func(b *testing.B) {
+ c, err := nettest.NewLocalPacketListener("udp6")
+ if err != nil {
+ b.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
+ }
+ defer c.Close()
+ p := ipv6.NewPacketConn(c)
+ dst := c.LocalAddr()
+ cf := ipv6.FlagHopLimit | ipv6.FlagInterface
+ if err := p.SetControlMessage(cf, true); err != nil {
+ b.Fatal(err)
+ }
+ b.Run("Net", func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ if _, err := c.WriteTo(payload, dst); err != nil {
+ b.Fatal(err)
+ }
+ if _, _, err := c.ReadFrom(bb); err != nil {
+ b.Fatal(err)
+ }
+ }
+ })
+ b.Run("ToFrom", func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ if _, err := p.WriteTo(payload, &cm, dst); err != nil {
+ b.Fatal(err)
+ }
+ if _, _, _, err := p.ReadFrom(bb); err != nil {
+ b.Fatal(err)
+ }
+ }
+ })
+ })
+ b.Run("IP", func(b *testing.B) {
+ switch runtime.GOOS {
+ case "netbsd":
+ b.Skip("need to configure gre on netbsd")
+ case "openbsd":
+ b.Skip("net.inet.gre.allow=0 by default on openbsd")
+ }
+
+ c, err := net.ListenPacket(fmt.Sprintf("ip6:%d", iana.ProtocolGRE), "::1")
+ if err != nil {
+ b.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
+ }
+ defer c.Close()
+ p := ipv6.NewPacketConn(c)
+ dst := c.LocalAddr()
+ cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU
+ if err := p.SetControlMessage(cf, true); err != nil {
+ b.Fatal(err)
+ }
+ b.Run("Net", func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ if _, err := c.WriteTo(datagram, dst); err != nil {
+ b.Fatal(err)
+ }
+ if _, _, err := c.ReadFrom(bb); err != nil {
+ b.Fatal(err)
+ }
+ }
+ })
+ b.Run("ToFrom", func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ if _, err := p.WriteTo(datagram, &cm, dst); err != nil {
+ b.Fatal(err)
+ }
+ if _, _, _, err := p.ReadFrom(bb); err != nil {
+ b.Fatal(err)
+ }
+ }
+ })
+ })
+}
+
+func TestPacketConnConcurrentReadWriteUnicast(t *testing.T) {
+ switch runtime.GOOS {
+ case "nacl", "plan9", "windows":
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+
+ payload := []byte("HELLO-R-U-THERE")
+ iph := []byte{
+ 0x69, 0x8b, 0xee, 0xf1, 0xca, 0xfe, 0xff, 0x01,
+ 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x02, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ }
+ greh := []byte{0x00, 0x00, 0x86, 0xdd, 0x00, 0x00, 0x00, 0x00}
+ datagram := append(greh, append(iph, payload...)...)
+
+ t.Run("UDP", func(t *testing.T) {
+ c, err := nettest.NewLocalPacketListener("udp6")
+ if err != nil {
+ t.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
+ }
+ defer c.Close()
+ p := ipv6.NewPacketConn(c)
+ t.Run("ToFrom", func(t *testing.T) {
+ testPacketConnConcurrentReadWriteUnicast(t, p, payload, c.LocalAddr())
+ })
+ })
+ t.Run("IP", func(t *testing.T) {
+ switch runtime.GOOS {
+ case "netbsd":
+ t.Skip("need to configure gre on netbsd")
+ case "openbsd":
+ t.Skip("net.inet.gre.allow=0 by default on openbsd")
+ }
+
+ c, err := net.ListenPacket(fmt.Sprintf("ip6:%d", iana.ProtocolGRE), "::1")
+ if err != nil {
+ t.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
+ }
+ defer c.Close()
+ p := ipv6.NewPacketConn(c)
+ t.Run("ToFrom", func(t *testing.T) {
+ testPacketConnConcurrentReadWriteUnicast(t, p, datagram, c.LocalAddr())
+ })
+ })
+}
+
+func testPacketConnConcurrentReadWriteUnicast(t *testing.T, p *ipv6.PacketConn, data []byte, dst net.Addr) {
+ ifi := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback)
+ cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU
+
+ if err := p.SetControlMessage(cf, true); err != nil { // probe before test
+ if nettest.ProtocolNotSupported(err) {
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+ t.Fatal(err)
+ }
+
+ var wg sync.WaitGroup
+ reader := func() {
+ defer wg.Done()
+ b := make([]byte, 128)
+ n, cm, _, err := p.ReadFrom(b)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ if !bytes.Equal(b[:n], data) {
+ t.Errorf("got %#v; want %#v", b[:n], data)
+ return
+ }
+ s := cm.String()
+ if strings.Contains(s, ",") {
+ t.Errorf("should be space-separated values: %s", s)
+ return
+ }
+ }
+ writer := func(toggle bool) {
+ defer wg.Done()
+ cm := ipv6.ControlMessage{
+ TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced,
+ HopLimit: 1,
+ Src: net.IPv6loopback,
+ }
+ if ifi != nil {
+ cm.IfIndex = ifi.Index
+ }
+ if err := p.SetControlMessage(cf, toggle); err != nil {
+ t.Error(err)
+ return
+ }
+ n, err := p.WriteTo(data, &cm, dst)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ if n != len(data) {
+ t.Errorf("got %d; want %d", n, len(data))
+ return
+ }
+ }
+
+ const N = 10
+ wg.Add(N)
+ for i := 0; i < N; i++ {
+ go reader()
+ }
+ wg.Add(2 * N)
+ for i := 0; i < 2*N; i++ {
+ go writer(i%2 != 0)
+
+ }
+ wg.Add(N)
+ for i := 0; i < N; i++ {
+ go reader()
+ }
+ wg.Wait()
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/readwrite_go1_9_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/readwrite_go1_9_test.go
new file mode 100644
index 000000000..e2fd73370
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/readwrite_go1_9_test.go
@@ -0,0 +1,373 @@
+// 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.
+
+// +build go1.9
+
+package ipv6_test
+
+import (
+ "bytes"
+ "fmt"
+ "net"
+ "runtime"
+ "strings"
+ "sync"
+ "testing"
+
+ "golang.org/x/net/internal/iana"
+ "golang.org/x/net/internal/nettest"
+ "golang.org/x/net/ipv6"
+)
+
+func BenchmarkPacketConnReadWriteUnicast(b *testing.B) {
+ switch runtime.GOOS {
+ case "nacl", "plan9", "windows":
+ b.Skipf("not supported on %s", runtime.GOOS)
+ }
+
+ payload := []byte("HELLO-R-U-THERE")
+ iph := []byte{
+ 0x69, 0x8b, 0xee, 0xf1, 0xca, 0xfe, 0xff, 0x01,
+ 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x02, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ }
+ greh := []byte{0x00, 0x00, 0x86, 0xdd, 0x00, 0x00, 0x00, 0x00}
+ datagram := append(greh, append(iph, payload...)...)
+ bb := make([]byte, 128)
+ cm := ipv6.ControlMessage{
+ TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced,
+ HopLimit: 1,
+ Src: net.IPv6loopback,
+ }
+ if ifi := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback); ifi != nil {
+ cm.IfIndex = ifi.Index
+ }
+
+ b.Run("UDP", func(b *testing.B) {
+ c, err := nettest.NewLocalPacketListener("udp6")
+ if err != nil {
+ b.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
+ }
+ defer c.Close()
+ p := ipv6.NewPacketConn(c)
+ dst := c.LocalAddr()
+ cf := ipv6.FlagHopLimit | ipv6.FlagInterface
+ if err := p.SetControlMessage(cf, true); err != nil {
+ b.Fatal(err)
+ }
+ wms := []ipv6.Message{
+ {
+ Buffers: [][]byte{payload},
+ Addr: dst,
+ OOB: cm.Marshal(),
+ },
+ }
+ rms := []ipv6.Message{
+ {
+ Buffers: [][]byte{bb},
+ OOB: ipv6.NewControlMessage(cf),
+ },
+ }
+ b.Run("Net", func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ if _, err := c.WriteTo(payload, dst); err != nil {
+ b.Fatal(err)
+ }
+ if _, _, err := c.ReadFrom(bb); err != nil {
+ b.Fatal(err)
+ }
+ }
+ })
+ b.Run("ToFrom", func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ if _, err := p.WriteTo(payload, &cm, dst); err != nil {
+ b.Fatal(err)
+ }
+ if _, _, _, err := p.ReadFrom(bb); err != nil {
+ b.Fatal(err)
+ }
+ }
+ })
+ b.Run("Batch", func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ if _, err := p.WriteBatch(wms, 0); err != nil {
+ b.Fatal(err)
+ }
+ if _, err := p.ReadBatch(rms, 0); err != nil {
+ b.Fatal(err)
+ }
+ }
+ })
+ })
+ b.Run("IP", func(b *testing.B) {
+ switch runtime.GOOS {
+ case "netbsd":
+ b.Skip("need to configure gre on netbsd")
+ case "openbsd":
+ b.Skip("net.inet.gre.allow=0 by default on openbsd")
+ }
+
+ c, err := net.ListenPacket(fmt.Sprintf("ip6:%d", iana.ProtocolGRE), "::1")
+ if err != nil {
+ b.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
+ }
+ defer c.Close()
+ p := ipv6.NewPacketConn(c)
+ dst := c.LocalAddr()
+ cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU
+ if err := p.SetControlMessage(cf, true); err != nil {
+ b.Fatal(err)
+ }
+ wms := []ipv6.Message{
+ {
+ Buffers: [][]byte{datagram},
+ Addr: dst,
+ OOB: cm.Marshal(),
+ },
+ }
+ rms := []ipv6.Message{
+ {
+ Buffers: [][]byte{bb},
+ OOB: ipv6.NewControlMessage(cf),
+ },
+ }
+ b.Run("Net", func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ if _, err := c.WriteTo(datagram, dst); err != nil {
+ b.Fatal(err)
+ }
+ if _, _, err := c.ReadFrom(bb); err != nil {
+ b.Fatal(err)
+ }
+ }
+ })
+ b.Run("ToFrom", func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ if _, err := p.WriteTo(datagram, &cm, dst); err != nil {
+ b.Fatal(err)
+ }
+ if _, _, _, err := p.ReadFrom(bb); err != nil {
+ b.Fatal(err)
+ }
+ }
+ })
+ b.Run("Batch", func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ if _, err := p.WriteBatch(wms, 0); err != nil {
+ b.Fatal(err)
+ }
+ if _, err := p.ReadBatch(rms, 0); err != nil {
+ b.Fatal(err)
+ }
+ }
+ })
+ })
+}
+
+func TestPacketConnConcurrentReadWriteUnicast(t *testing.T) {
+ switch runtime.GOOS {
+ case "nacl", "plan9", "windows":
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+
+ payload := []byte("HELLO-R-U-THERE")
+ iph := []byte{
+ 0x69, 0x8b, 0xee, 0xf1, 0xca, 0xfe, 0xff, 0x01,
+ 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x02, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ }
+ greh := []byte{0x00, 0x00, 0x86, 0xdd, 0x00, 0x00, 0x00, 0x00}
+ datagram := append(greh, append(iph, payload...)...)
+
+ t.Run("UDP", func(t *testing.T) {
+ c, err := nettest.NewLocalPacketListener("udp6")
+ if err != nil {
+ t.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
+ }
+ defer c.Close()
+ p := ipv6.NewPacketConn(c)
+ t.Run("ToFrom", func(t *testing.T) {
+ testPacketConnConcurrentReadWriteUnicast(t, p, payload, c.LocalAddr(), false)
+ })
+ t.Run("Batch", func(t *testing.T) {
+ testPacketConnConcurrentReadWriteUnicast(t, p, payload, c.LocalAddr(), true)
+ })
+ })
+ t.Run("IP", func(t *testing.T) {
+ switch runtime.GOOS {
+ case "netbsd":
+ t.Skip("need to configure gre on netbsd")
+ case "openbsd":
+ t.Skip("net.inet.gre.allow=0 by default on openbsd")
+ }
+
+ c, err := net.ListenPacket(fmt.Sprintf("ip6:%d", iana.ProtocolGRE), "::1")
+ if err != nil {
+ t.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
+ }
+ defer c.Close()
+ p := ipv6.NewPacketConn(c)
+ t.Run("ToFrom", func(t *testing.T) {
+ testPacketConnConcurrentReadWriteUnicast(t, p, datagram, c.LocalAddr(), false)
+ })
+ t.Run("Batch", func(t *testing.T) {
+ testPacketConnConcurrentReadWriteUnicast(t, p, datagram, c.LocalAddr(), true)
+ })
+ })
+}
+
+func testPacketConnConcurrentReadWriteUnicast(t *testing.T, p *ipv6.PacketConn, data []byte, dst net.Addr, batch bool) {
+ ifi := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback)
+ cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU
+
+ if err := p.SetControlMessage(cf, true); err != nil { // probe before test
+ if nettest.ProtocolNotSupported(err) {
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+ t.Fatal(err)
+ }
+
+ var wg sync.WaitGroup
+ reader := func() {
+ defer wg.Done()
+ b := make([]byte, 128)
+ n, cm, _, err := p.ReadFrom(b)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ if !bytes.Equal(b[:n], data) {
+ t.Errorf("got %#v; want %#v", b[:n], data)
+ return
+ }
+ s := cm.String()
+ if strings.Contains(s, ",") {
+ t.Errorf("should be space-separated values: %s", s)
+ return
+ }
+ }
+ batchReader := func() {
+ defer wg.Done()
+ ms := []ipv6.Message{
+ {
+ Buffers: [][]byte{make([]byte, 128)},
+ OOB: ipv6.NewControlMessage(cf),
+ },
+ }
+ n, err := p.ReadBatch(ms, 0)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ if n != len(ms) {
+ t.Errorf("got %d; want %d", n, len(ms))
+ return
+ }
+ var cm ipv6.ControlMessage
+ if err := cm.Parse(ms[0].OOB[:ms[0].NN]); err != nil {
+ t.Error(err)
+ return
+ }
+ b := ms[0].Buffers[0][:ms[0].N]
+ if !bytes.Equal(b, data) {
+ t.Errorf("got %#v; want %#v", b, data)
+ return
+ }
+ s := cm.String()
+ if strings.Contains(s, ",") {
+ t.Errorf("should be space-separated values: %s", s)
+ return
+ }
+ }
+ writer := func(toggle bool) {
+ defer wg.Done()
+ cm := ipv6.ControlMessage{
+ TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced,
+ HopLimit: 1,
+ Src: net.IPv6loopback,
+ }
+ if ifi != nil {
+ cm.IfIndex = ifi.Index
+ }
+ if err := p.SetControlMessage(cf, toggle); err != nil {
+ t.Error(err)
+ return
+ }
+ n, err := p.WriteTo(data, &cm, dst)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ if n != len(data) {
+ t.Errorf("got %d; want %d", n, len(data))
+ return
+ }
+ }
+ batchWriter := func(toggle bool) {
+ defer wg.Done()
+ cm := ipv6.ControlMessage{
+ TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced,
+ HopLimit: 1,
+ Src: net.IPv6loopback,
+ }
+ if ifi != nil {
+ cm.IfIndex = ifi.Index
+ }
+ if err := p.SetControlMessage(cf, toggle); err != nil {
+ t.Error(err)
+ return
+ }
+ ms := []ipv6.Message{
+ {
+ Buffers: [][]byte{data},
+ OOB: cm.Marshal(),
+ Addr: dst,
+ },
+ }
+ n, err := p.WriteBatch(ms, 0)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ if n != len(ms) {
+ t.Errorf("got %d; want %d", n, len(ms))
+ return
+ }
+ if ms[0].N != len(data) {
+ t.Errorf("got %d; want %d", ms[0].N, len(data))
+ return
+ }
+ }
+
+ const N = 10
+ wg.Add(N)
+ for i := 0; i < N; i++ {
+ if batch {
+ go batchReader()
+ } else {
+ go reader()
+ }
+ }
+ wg.Add(2 * N)
+ for i := 0; i < 2*N; i++ {
+ if batch {
+ go batchWriter(i%2 != 0)
+ } else {
+ go writer(i%2 != 0)
+ }
+ }
+ wg.Add(N)
+ for i := 0; i < N; i++ {
+ if batch {
+ go batchReader()
+ } else {
+ go reader()
+ }
+ }
+ wg.Wait()
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/readwrite_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/readwrite_test.go
new file mode 100644
index 000000000..206b915ce
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/readwrite_test.go
@@ -0,0 +1,148 @@
+// Copyright 2013 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 ipv6_test
+
+import (
+ "bytes"
+ "net"
+ "runtime"
+ "strings"
+ "sync"
+ "testing"
+
+ "golang.org/x/net/internal/iana"
+ "golang.org/x/net/internal/nettest"
+ "golang.org/x/net/ipv6"
+)
+
+func BenchmarkReadWriteUnicast(b *testing.B) {
+ c, err := nettest.NewLocalPacketListener("udp6")
+ if err != nil {
+ b.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
+ }
+ defer c.Close()
+
+ dst := c.LocalAddr()
+ wb, rb := []byte("HELLO-R-U-THERE"), make([]byte, 128)
+
+ b.Run("NetUDP", func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ if _, err := c.WriteTo(wb, dst); err != nil {
+ b.Fatal(err)
+ }
+ if _, _, err := c.ReadFrom(rb); err != nil {
+ b.Fatal(err)
+ }
+ }
+ })
+ b.Run("IPv6UDP", func(b *testing.B) {
+ p := ipv6.NewPacketConn(c)
+ cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU
+ if err := p.SetControlMessage(cf, true); err != nil {
+ b.Fatal(err)
+ }
+ cm := ipv6.ControlMessage{
+ TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced,
+ HopLimit: 1,
+ }
+ ifi := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback)
+ if ifi != nil {
+ cm.IfIndex = ifi.Index
+ }
+
+ for i := 0; i < b.N; i++ {
+ if _, err := p.WriteTo(wb, &cm, dst); err != nil {
+ b.Fatal(err)
+ }
+ if _, _, _, err := p.ReadFrom(rb); err != nil {
+ b.Fatal(err)
+ }
+ }
+ })
+}
+
+func TestPacketConnConcurrentReadWriteUnicastUDP(t *testing.T) {
+ switch runtime.GOOS {
+ case "nacl", "plan9", "windows":
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+ if !supportsIPv6 {
+ t.Skip("ipv6 is not supported")
+ }
+
+ c, err := nettest.NewLocalPacketListener("udp6")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer c.Close()
+ p := ipv6.NewPacketConn(c)
+ defer p.Close()
+
+ dst := c.LocalAddr()
+ ifi := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback)
+ cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU
+ wb := []byte("HELLO-R-U-THERE")
+
+ if err := p.SetControlMessage(cf, true); err != nil { // probe before test
+ if nettest.ProtocolNotSupported(err) {
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+ t.Fatal(err)
+ }
+
+ var wg sync.WaitGroup
+ reader := func() {
+ defer wg.Done()
+ rb := make([]byte, 128)
+ if n, cm, _, err := p.ReadFrom(rb); err != nil {
+ t.Error(err)
+ return
+ } else if !bytes.Equal(rb[:n], wb) {
+ t.Errorf("got %v; want %v", rb[:n], wb)
+ return
+ } else {
+ s := cm.String()
+ if strings.Contains(s, ",") {
+ t.Errorf("should be space-separated values: %s", s)
+ }
+ }
+ }
+ writer := func(toggle bool) {
+ defer wg.Done()
+ cm := ipv6.ControlMessage{
+ TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced,
+ Src: net.IPv6loopback,
+ }
+ if ifi != nil {
+ cm.IfIndex = ifi.Index
+ }
+ if err := p.SetControlMessage(cf, toggle); err != nil {
+ t.Error(err)
+ return
+ }
+ if n, err := p.WriteTo(wb, &cm, dst); err != nil {
+ t.Error(err)
+ return
+ } else if n != len(wb) {
+ t.Errorf("got %d; want %d", n, len(wb))
+ return
+ }
+ }
+
+ const N = 10
+ wg.Add(N)
+ for i := 0; i < N; i++ {
+ go reader()
+ }
+ wg.Add(2 * N)
+ for i := 0; i < 2*N; i++ {
+ go writer(i%2 != 0)
+ }
+ wg.Add(N)
+ for i := 0; i < N; i++ {
+ go reader()
+ }
+ wg.Wait()
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sockopt.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sockopt.go
new file mode 100644
index 000000000..cc3907df3
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sockopt.go
@@ -0,0 +1,43 @@
+// Copyright 2014 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 ipv6
+
+import "golang.org/x/net/internal/socket"
+
+// Sticky socket options
+const (
+ ssoTrafficClass = iota // header field for unicast packet, RFC 3542
+ ssoHopLimit // header field for unicast packet, RFC 3493
+ ssoMulticastInterface // outbound interface for multicast packet, RFC 3493
+ ssoMulticastHopLimit // header field for multicast packet, RFC 3493
+ ssoMulticastLoopback // loopback for multicast packet, RFC 3493
+ ssoReceiveTrafficClass // header field on received packet, RFC 3542
+ ssoReceiveHopLimit // header field on received packet, RFC 2292 or 3542
+ ssoReceivePacketInfo // incbound or outbound packet path, RFC 2292 or 3542
+ ssoReceivePathMTU // path mtu, RFC 3542
+ ssoPathMTU // path mtu, RFC 3542
+ ssoChecksum // packet checksum, RFC 2292 or 3542
+ ssoICMPFilter // icmp filter, RFC 2292 or 3542
+ ssoJoinGroup // any-source multicast, RFC 3493
+ ssoLeaveGroup // any-source multicast, RFC 3493
+ ssoJoinSourceGroup // source-specific multicast
+ ssoLeaveSourceGroup // source-specific multicast
+ ssoBlockSourceGroup // any-source or source-specific multicast
+ ssoUnblockSourceGroup // any-source or source-specific multicast
+ ssoAttachFilter // attach BPF for filtering inbound traffic
+)
+
+// Sticky socket option value types
+const (
+ ssoTypeIPMreq = iota + 1
+ ssoTypeGroupReq
+ ssoTypeGroupSourceReq
+)
+
+// A sockOpt represents a binding for sticky socket option.
+type sockOpt struct {
+ socket.Option
+ typ int // hint for option value type; optional
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sockopt_posix.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sockopt_posix.go
new file mode 100644
index 000000000..0eac86eb8
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sockopt_posix.go
@@ -0,0 +1,87 @@
+// Copyright 2013 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.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
+
+package ipv6
+
+import (
+ "net"
+ "unsafe"
+
+ "golang.org/x/net/bpf"
+ "golang.org/x/net/internal/socket"
+)
+
+func (so *sockOpt) getMulticastInterface(c *socket.Conn) (*net.Interface, error) {
+ n, err := so.GetInt(c)
+ if err != nil {
+ return nil, err
+ }
+ return net.InterfaceByIndex(n)
+}
+
+func (so *sockOpt) setMulticastInterface(c *socket.Conn, ifi *net.Interface) error {
+ var n int
+ if ifi != nil {
+ n = ifi.Index
+ }
+ return so.SetInt(c, n)
+}
+
+func (so *sockOpt) getICMPFilter(c *socket.Conn) (*ICMPFilter, error) {
+ b := make([]byte, so.Len)
+ n, err := so.Get(c, b)
+ if err != nil {
+ return nil, err
+ }
+ if n != sizeofICMPv6Filter {
+ return nil, errOpNoSupport
+ }
+ return (*ICMPFilter)(unsafe.Pointer(&b[0])), nil
+}
+
+func (so *sockOpt) setICMPFilter(c *socket.Conn, f *ICMPFilter) error {
+ b := (*[sizeofICMPv6Filter]byte)(unsafe.Pointer(f))[:sizeofICMPv6Filter]
+ return so.Set(c, b)
+}
+
+func (so *sockOpt) getMTUInfo(c *socket.Conn) (*net.Interface, int, error) {
+ b := make([]byte, so.Len)
+ n, err := so.Get(c, b)
+ if err != nil {
+ return nil, 0, err
+ }
+ if n != sizeofIPv6Mtuinfo {
+ return nil, 0, errOpNoSupport
+ }
+ mi := (*ipv6Mtuinfo)(unsafe.Pointer(&b[0]))
+ if mi.Addr.Scope_id == 0 {
+ return nil, int(mi.Mtu), nil
+ }
+ ifi, err := net.InterfaceByIndex(int(mi.Addr.Scope_id))
+ if err != nil {
+ return nil, 0, err
+ }
+ return ifi, int(mi.Mtu), nil
+}
+
+func (so *sockOpt) setGroup(c *socket.Conn, ifi *net.Interface, grp net.IP) error {
+ switch so.typ {
+ case ssoTypeIPMreq:
+ return so.setIPMreq(c, ifi, grp)
+ case ssoTypeGroupReq:
+ return so.setGroupReq(c, ifi, grp)
+ default:
+ return errOpNoSupport
+ }
+}
+
+func (so *sockOpt) setSourceGroup(c *socket.Conn, ifi *net.Interface, grp, src net.IP) error {
+ return so.setGroupSourceReq(c, ifi, grp, src)
+}
+
+func (so *sockOpt) setBPF(c *socket.Conn, f []bpf.RawInstruction) error {
+ return so.setAttachFilter(c, f)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sockopt_stub.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sockopt_stub.go
new file mode 100644
index 000000000..1f4a273e4
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sockopt_stub.go
@@ -0,0 +1,46 @@
+// Copyright 2013 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.
+
+// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows
+
+package ipv6
+
+import (
+ "net"
+
+ "golang.org/x/net/bpf"
+ "golang.org/x/net/internal/socket"
+)
+
+func (so *sockOpt) getMulticastInterface(c *socket.Conn) (*net.Interface, error) {
+ return nil, errOpNoSupport
+}
+
+func (so *sockOpt) setMulticastInterface(c *socket.Conn, ifi *net.Interface) error {
+ return errOpNoSupport
+}
+
+func (so *sockOpt) getICMPFilter(c *socket.Conn) (*ICMPFilter, error) {
+ return nil, errOpNoSupport
+}
+
+func (so *sockOpt) setICMPFilter(c *socket.Conn, f *ICMPFilter) error {
+ return errOpNoSupport
+}
+
+func (so *sockOpt) getMTUInfo(c *socket.Conn) (*net.Interface, int, error) {
+ return nil, 0, errOpNoSupport
+}
+
+func (so *sockOpt) setGroup(c *socket.Conn, ifi *net.Interface, grp net.IP) error {
+ return errOpNoSupport
+}
+
+func (so *sockOpt) setSourceGroup(c *socket.Conn, ifi *net.Interface, grp, src net.IP) error {
+ return errOpNoSupport
+}
+
+func (so *sockOpt) setBPF(c *socket.Conn, f []bpf.RawInstruction) error {
+ return errOpNoSupport
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sockopt_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sockopt_test.go
new file mode 100644
index 000000000..774338dbf
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sockopt_test.go
@@ -0,0 +1,133 @@
+// Copyright 2013 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 ipv6_test
+
+import (
+ "fmt"
+ "net"
+ "runtime"
+ "testing"
+
+ "golang.org/x/net/internal/iana"
+ "golang.org/x/net/internal/nettest"
+ "golang.org/x/net/ipv6"
+)
+
+var supportsIPv6 bool = nettest.SupportsIPv6()
+
+func TestConnInitiatorPathMTU(t *testing.T) {
+ switch runtime.GOOS {
+ case "nacl", "plan9", "windows":
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+ if !supportsIPv6 {
+ t.Skip("ipv6 is not supported")
+ }
+
+ ln, err := net.Listen("tcp6", "[::1]:0")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer ln.Close()
+
+ done := make(chan bool)
+ go acceptor(t, ln, done)
+
+ c, err := net.Dial("tcp6", ln.Addr().String())
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer c.Close()
+
+ if pmtu, err := ipv6.NewConn(c).PathMTU(); err != nil {
+ switch runtime.GOOS {
+ case "darwin": // older darwin kernels don't support IPV6_PATHMTU option
+ t.Logf("not supported on %s", runtime.GOOS)
+ default:
+ t.Fatal(err)
+ }
+ } else {
+ t.Logf("path mtu for %v: %v", c.RemoteAddr(), pmtu)
+ }
+
+ <-done
+}
+
+func TestConnResponderPathMTU(t *testing.T) {
+ switch runtime.GOOS {
+ case "nacl", "plan9", "windows":
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+ if !supportsIPv6 {
+ t.Skip("ipv6 is not supported")
+ }
+
+ ln, err := net.Listen("tcp6", "[::1]:0")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer ln.Close()
+
+ done := make(chan bool)
+ go connector(t, "tcp6", ln.Addr().String(), done)
+
+ c, err := ln.Accept()
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer c.Close()
+
+ if pmtu, err := ipv6.NewConn(c).PathMTU(); err != nil {
+ switch runtime.GOOS {
+ case "darwin": // older darwin kernels don't support IPV6_PATHMTU option
+ t.Logf("not supported on %s", runtime.GOOS)
+ default:
+ t.Fatal(err)
+ }
+ } else {
+ t.Logf("path mtu for %v: %v", c.RemoteAddr(), pmtu)
+ }
+
+ <-done
+}
+
+func TestPacketConnChecksum(t *testing.T) {
+ switch runtime.GOOS {
+ case "nacl", "plan9", "windows":
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+ if !supportsIPv6 {
+ t.Skip("ipv6 is not supported")
+ }
+ if m, ok := nettest.SupportsRawIPSocket(); !ok {
+ t.Skip(m)
+ }
+
+ c, err := net.ListenPacket(fmt.Sprintf("ip6:%d", iana.ProtocolOSPFIGP), "::") // OSPF for IPv6
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer c.Close()
+
+ p := ipv6.NewPacketConn(c)
+ offset := 12 // see RFC 5340
+
+ for _, toggle := range []bool{false, true} {
+ if err := p.SetChecksum(toggle, offset); err != nil {
+ if toggle {
+ t.Fatalf("ipv6.PacketConn.SetChecksum(%v, %v) failed: %v", toggle, offset, err)
+ } else {
+ // Some platforms never allow to disable the kernel
+ // checksum processing.
+ t.Logf("ipv6.PacketConn.SetChecksum(%v, %v) failed: %v", toggle, offset, err)
+ }
+ }
+ if on, offset, err := p.Checksum(); err != nil {
+ t.Fatal(err)
+ } else {
+ t.Logf("kernel checksum processing enabled=%v, offset=%v", on, offset)
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_asmreq.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_asmreq.go
new file mode 100644
index 000000000..b0510c0b5
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_asmreq.go
@@ -0,0 +1,24 @@
+// Copyright 2013 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.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
+
+package ipv6
+
+import (
+ "net"
+ "unsafe"
+
+ "golang.org/x/net/internal/socket"
+)
+
+func (so *sockOpt) setIPMreq(c *socket.Conn, ifi *net.Interface, grp net.IP) error {
+ var mreq ipv6Mreq
+ copy(mreq.Multiaddr[:], grp)
+ if ifi != nil {
+ mreq.setIfindex(ifi.Index)
+ }
+ b := (*[sizeofIPv6Mreq]byte)(unsafe.Pointer(&mreq))[:sizeofIPv6Mreq]
+ return so.Set(c, b)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_asmreq_stub.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_asmreq_stub.go
new file mode 100644
index 000000000..eece96187
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_asmreq_stub.go
@@ -0,0 +1,17 @@
+// Copyright 2013 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.
+
+// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows
+
+package ipv6
+
+import (
+ "net"
+
+ "golang.org/x/net/internal/socket"
+)
+
+func (so *sockOpt) setIPMreq(c *socket.Conn, ifi *net.Interface, grp net.IP) error {
+ return errOpNoSupport
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_bpf.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_bpf.go
new file mode 100644
index 000000000..b2dbcb2f2
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_bpf.go
@@ -0,0 +1,23 @@
+// 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.
+
+// +build linux
+
+package ipv6
+
+import (
+ "unsafe"
+
+ "golang.org/x/net/bpf"
+ "golang.org/x/net/internal/socket"
+)
+
+func (so *sockOpt) setAttachFilter(c *socket.Conn, f []bpf.RawInstruction) error {
+ prog := sockFProg{
+ Len: uint16(len(f)),
+ Filter: (*sockFilter)(unsafe.Pointer(&f[0])),
+ }
+ b := (*[sizeofSockFprog]byte)(unsafe.Pointer(&prog))[:sizeofSockFprog]
+ return so.Set(c, b)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_bpf_stub.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_bpf_stub.go
new file mode 100644
index 000000000..676bea555
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_bpf_stub.go
@@ -0,0 +1,16 @@
+// 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.
+
+// +build !linux
+
+package ipv6
+
+import (
+ "golang.org/x/net/bpf"
+ "golang.org/x/net/internal/socket"
+)
+
+func (so *sockOpt) setAttachFilter(c *socket.Conn, f []bpf.RawInstruction) error {
+ return errOpNoSupport
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_bsd.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_bsd.go
new file mode 100644
index 000000000..e416eaa1f
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_bsd.go
@@ -0,0 +1,57 @@
+// Copyright 2013 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.
+
+// +build dragonfly netbsd openbsd
+
+package ipv6
+
+import (
+ "net"
+ "syscall"
+
+ "golang.org/x/net/internal/iana"
+ "golang.org/x/net/internal/socket"
+)
+
+var (
+ ctlOpts = [ctlMax]ctlOpt{
+ ctlTrafficClass: {sysIPV6_TCLASS, 4, marshalTrafficClass, parseTrafficClass},
+ ctlHopLimit: {sysIPV6_HOPLIMIT, 4, marshalHopLimit, parseHopLimit},
+ ctlPacketInfo: {sysIPV6_PKTINFO, sizeofInet6Pktinfo, marshalPacketInfo, parsePacketInfo},
+ ctlNextHop: {sysIPV6_NEXTHOP, sizeofSockaddrInet6, marshalNextHop, parseNextHop},
+ ctlPathMTU: {sysIPV6_PATHMTU, sizeofIPv6Mtuinfo, marshalPathMTU, parsePathMTU},
+ }
+
+ sockOpts = map[int]*sockOpt{
+ ssoTrafficClass: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_TCLASS, Len: 4}},
+ ssoHopLimit: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_UNICAST_HOPS, Len: 4}},
+ ssoMulticastInterface: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_MULTICAST_IF, Len: 4}},
+ ssoMulticastHopLimit: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_MULTICAST_HOPS, Len: 4}},
+ ssoMulticastLoopback: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_MULTICAST_LOOP, Len: 4}},
+ ssoReceiveTrafficClass: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_RECVTCLASS, Len: 4}},
+ ssoReceiveHopLimit: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_RECVHOPLIMIT, Len: 4}},
+ ssoReceivePacketInfo: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_RECVPKTINFO, Len: 4}},
+ ssoReceivePathMTU: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_RECVPATHMTU, Len: 4}},
+ ssoPathMTU: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_PATHMTU, Len: sizeofIPv6Mtuinfo}},
+ ssoChecksum: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_CHECKSUM, Len: 4}},
+ ssoICMPFilter: {Option: socket.Option{Level: iana.ProtocolIPv6ICMP, Name: sysICMP6_FILTER, Len: sizeofICMPv6Filter}},
+ ssoJoinGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_JOIN_GROUP, Len: sizeofIPv6Mreq}, typ: ssoTypeIPMreq},
+ ssoLeaveGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_LEAVE_GROUP, Len: sizeofIPv6Mreq}, typ: ssoTypeIPMreq},
+ }
+)
+
+func (sa *sockaddrInet6) setSockaddr(ip net.IP, i int) {
+ sa.Len = sizeofSockaddrInet6
+ sa.Family = syscall.AF_INET6
+ copy(sa.Addr[:], ip)
+ sa.Scope_id = uint32(i)
+}
+
+func (pi *inet6Pktinfo) setIfindex(i int) {
+ pi.Ifindex = uint32(i)
+}
+
+func (mreq *ipv6Mreq) setIfindex(i int) {
+ mreq.Interface = uint32(i)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_darwin.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_darwin.go
new file mode 100644
index 000000000..e3d044392
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_darwin.go
@@ -0,0 +1,106 @@
+// Copyright 2013 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 ipv6
+
+import (
+ "net"
+ "strconv"
+ "strings"
+ "syscall"
+ "unsafe"
+
+ "golang.org/x/net/internal/iana"
+ "golang.org/x/net/internal/socket"
+)
+
+var (
+ ctlOpts = [ctlMax]ctlOpt{
+ ctlHopLimit: {sysIPV6_2292HOPLIMIT, 4, marshal2292HopLimit, parseHopLimit},
+ ctlPacketInfo: {sysIPV6_2292PKTINFO, sizeofInet6Pktinfo, marshal2292PacketInfo, parsePacketInfo},
+ }
+
+ sockOpts = map[int]*sockOpt{
+ ssoHopLimit: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_UNICAST_HOPS, Len: 4}},
+ ssoMulticastInterface: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_MULTICAST_IF, Len: 4}},
+ ssoMulticastHopLimit: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_MULTICAST_HOPS, Len: 4}},
+ ssoMulticastLoopback: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_MULTICAST_LOOP, Len: 4}},
+ ssoReceiveHopLimit: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_2292HOPLIMIT, Len: 4}},
+ ssoReceivePacketInfo: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_2292PKTINFO, Len: 4}},
+ ssoChecksum: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_CHECKSUM, Len: 4}},
+ ssoICMPFilter: {Option: socket.Option{Level: iana.ProtocolIPv6ICMP, Name: sysICMP6_FILTER, Len: sizeofICMPv6Filter}},
+ ssoJoinGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_JOIN_GROUP, Len: sizeofIPv6Mreq}, typ: ssoTypeIPMreq},
+ ssoLeaveGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_LEAVE_GROUP, Len: sizeofIPv6Mreq}, typ: ssoTypeIPMreq},
+ }
+)
+
+func init() {
+ // Seems like kern.osreldate is veiled on latest OS X. We use
+ // kern.osrelease instead.
+ s, err := syscall.Sysctl("kern.osrelease")
+ if err != nil {
+ return
+ }
+ ss := strings.Split(s, ".")
+ if len(ss) == 0 {
+ return
+ }
+ // The IP_PKTINFO and protocol-independent multicast API were
+ // introduced in OS X 10.7 (Darwin 11). But it looks like
+ // those features require OS X 10.8 (Darwin 12) or above.
+ // See http://support.apple.com/kb/HT1633.
+ if mjver, err := strconv.Atoi(ss[0]); err != nil || mjver < 12 {
+ return
+ }
+ ctlOpts[ctlTrafficClass] = ctlOpt{sysIPV6_TCLASS, 4, marshalTrafficClass, parseTrafficClass}
+ ctlOpts[ctlHopLimit] = ctlOpt{sysIPV6_HOPLIMIT, 4, marshalHopLimit, parseHopLimit}
+ ctlOpts[ctlPacketInfo] = ctlOpt{sysIPV6_PKTINFO, sizeofInet6Pktinfo, marshalPacketInfo, parsePacketInfo}
+ ctlOpts[ctlNextHop] = ctlOpt{sysIPV6_NEXTHOP, sizeofSockaddrInet6, marshalNextHop, parseNextHop}
+ ctlOpts[ctlPathMTU] = ctlOpt{sysIPV6_PATHMTU, sizeofIPv6Mtuinfo, marshalPathMTU, parsePathMTU}
+ sockOpts[ssoTrafficClass] = &sockOpt{Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_TCLASS, Len: 4}}
+ sockOpts[ssoReceiveTrafficClass] = &sockOpt{Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_RECVTCLASS, Len: 4}}
+ sockOpts[ssoReceiveHopLimit] = &sockOpt{Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_RECVHOPLIMIT, Len: 4}}
+ sockOpts[ssoReceivePacketInfo] = &sockOpt{Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_RECVPKTINFO, Len: 4}}
+ sockOpts[ssoReceivePathMTU] = &sockOpt{Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_RECVPATHMTU, Len: 4}}
+ sockOpts[ssoPathMTU] = &sockOpt{Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_PATHMTU, Len: sizeofIPv6Mtuinfo}}
+ sockOpts[ssoJoinGroup] = &sockOpt{Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysMCAST_JOIN_GROUP, Len: sizeofGroupReq}, typ: ssoTypeGroupReq}
+ sockOpts[ssoLeaveGroup] = &sockOpt{Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysMCAST_LEAVE_GROUP, Len: sizeofGroupReq}, typ: ssoTypeGroupReq}
+ sockOpts[ssoJoinSourceGroup] = &sockOpt{Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysMCAST_JOIN_SOURCE_GROUP, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq}
+ sockOpts[ssoLeaveSourceGroup] = &sockOpt{Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysMCAST_LEAVE_SOURCE_GROUP, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq}
+ sockOpts[ssoBlockSourceGroup] = &sockOpt{Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysMCAST_BLOCK_SOURCE, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq}
+ sockOpts[ssoUnblockSourceGroup] = &sockOpt{Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysMCAST_UNBLOCK_SOURCE, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq}
+}
+
+func (sa *sockaddrInet6) setSockaddr(ip net.IP, i int) {
+ sa.Len = sizeofSockaddrInet6
+ sa.Family = syscall.AF_INET6
+ copy(sa.Addr[:], ip)
+ sa.Scope_id = uint32(i)
+}
+
+func (pi *inet6Pktinfo) setIfindex(i int) {
+ pi.Ifindex = uint32(i)
+}
+
+func (mreq *ipv6Mreq) setIfindex(i int) {
+ mreq.Interface = uint32(i)
+}
+
+func (gr *groupReq) setGroup(grp net.IP) {
+ sa := (*sockaddrInet6)(unsafe.Pointer(uintptr(unsafe.Pointer(gr)) + 4))
+ sa.Len = sizeofSockaddrInet6
+ sa.Family = syscall.AF_INET6
+ copy(sa.Addr[:], grp)
+}
+
+func (gsr *groupSourceReq) setSourceGroup(grp, src net.IP) {
+ sa := (*sockaddrInet6)(unsafe.Pointer(uintptr(unsafe.Pointer(gsr)) + 4))
+ sa.Len = sizeofSockaddrInet6
+ sa.Family = syscall.AF_INET6
+ copy(sa.Addr[:], grp)
+ sa = (*sockaddrInet6)(unsafe.Pointer(uintptr(unsafe.Pointer(gsr)) + 132))
+ sa.Len = sizeofSockaddrInet6
+ sa.Family = syscall.AF_INET6
+ copy(sa.Addr[:], src)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_freebsd.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_freebsd.go
new file mode 100644
index 000000000..e9349dc2c
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_freebsd.go
@@ -0,0 +1,92 @@
+// Copyright 2013 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 ipv6
+
+import (
+ "net"
+ "runtime"
+ "strings"
+ "syscall"
+ "unsafe"
+
+ "golang.org/x/net/internal/iana"
+ "golang.org/x/net/internal/socket"
+)
+
+var (
+ ctlOpts = [ctlMax]ctlOpt{
+ ctlTrafficClass: {sysIPV6_TCLASS, 4, marshalTrafficClass, parseTrafficClass},
+ ctlHopLimit: {sysIPV6_HOPLIMIT, 4, marshalHopLimit, parseHopLimit},
+ ctlPacketInfo: {sysIPV6_PKTINFO, sizeofInet6Pktinfo, marshalPacketInfo, parsePacketInfo},
+ ctlNextHop: {sysIPV6_NEXTHOP, sizeofSockaddrInet6, marshalNextHop, parseNextHop},
+ ctlPathMTU: {sysIPV6_PATHMTU, sizeofIPv6Mtuinfo, marshalPathMTU, parsePathMTU},
+ }
+
+ sockOpts = map[int]sockOpt{
+ ssoTrafficClass: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_TCLASS, Len: 4}},
+ ssoHopLimit: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_UNICAST_HOPS, Len: 4}},
+ ssoMulticastInterface: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_MULTICAST_IF, Len: 4}},
+ ssoMulticastHopLimit: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_MULTICAST_HOPS, Len: 4}},
+ ssoMulticastLoopback: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_MULTICAST_LOOP, Len: 4}},
+ ssoReceiveTrafficClass: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_RECVTCLASS, Len: 4}},
+ ssoReceiveHopLimit: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_RECVHOPLIMIT, Len: 4}},
+ ssoReceivePacketInfo: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_RECVPKTINFO, Len: 4}},
+ ssoReceivePathMTU: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_RECVPATHMTU, Len: 4}},
+ ssoPathMTU: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_PATHMTU, Len: sizeofIPv6Mtuinfo}},
+ ssoChecksum: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_CHECKSUM, Len: 4}},
+ ssoICMPFilter: {Option: socket.Option{Level: iana.ProtocolIPv6ICMP, Name: sysICMP6_FILTER, Len: sizeofICMPv6Filter}},
+ ssoJoinGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysMCAST_JOIN_GROUP, Len: sizeofGroupReq}, typ: ssoTypeGroupReq},
+ ssoLeaveGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysMCAST_LEAVE_GROUP, Len: sizeofGroupReq}, typ: ssoTypeGroupReq},
+ ssoJoinSourceGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysMCAST_JOIN_SOURCE_GROUP, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq},
+ ssoLeaveSourceGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysMCAST_LEAVE_SOURCE_GROUP, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq},
+ ssoBlockSourceGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysMCAST_BLOCK_SOURCE, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq},
+ ssoUnblockSourceGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysMCAST_UNBLOCK_SOURCE, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq},
+ }
+)
+
+func init() {
+ if runtime.GOOS == "freebsd" && runtime.GOARCH == "386" {
+ archs, _ := syscall.Sysctl("kern.supported_archs")
+ for _, s := range strings.Fields(archs) {
+ if s == "amd64" {
+ freebsd32o64 = true
+ break
+ }
+ }
+ }
+}
+
+func (sa *sockaddrInet6) setSockaddr(ip net.IP, i int) {
+ sa.Len = sizeofSockaddrInet6
+ sa.Family = syscall.AF_INET6
+ copy(sa.Addr[:], ip)
+ sa.Scope_id = uint32(i)
+}
+
+func (pi *inet6Pktinfo) setIfindex(i int) {
+ pi.Ifindex = uint32(i)
+}
+
+func (mreq *ipv6Mreq) setIfindex(i int) {
+ mreq.Interface = uint32(i)
+}
+
+func (gr *groupReq) setGroup(grp net.IP) {
+ sa := (*sockaddrInet6)(unsafe.Pointer(&gr.Group))
+ sa.Len = sizeofSockaddrInet6
+ sa.Family = syscall.AF_INET6
+ copy(sa.Addr[:], grp)
+}
+
+func (gsr *groupSourceReq) setSourceGroup(grp, src net.IP) {
+ sa := (*sockaddrInet6)(unsafe.Pointer(&gsr.Group))
+ sa.Len = sizeofSockaddrInet6
+ sa.Family = syscall.AF_INET6
+ copy(sa.Addr[:], grp)
+ sa = (*sockaddrInet6)(unsafe.Pointer(&gsr.Source))
+ sa.Len = sizeofSockaddrInet6
+ sa.Family = syscall.AF_INET6
+ copy(sa.Addr[:], src)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_linux.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_linux.go
new file mode 100644
index 000000000..bc218103c
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_linux.go
@@ -0,0 +1,74 @@
+// Copyright 2013 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 ipv6
+
+import (
+ "net"
+ "syscall"
+ "unsafe"
+
+ "golang.org/x/net/internal/iana"
+ "golang.org/x/net/internal/socket"
+)
+
+var (
+ ctlOpts = [ctlMax]ctlOpt{
+ ctlTrafficClass: {sysIPV6_TCLASS, 4, marshalTrafficClass, parseTrafficClass},
+ ctlHopLimit: {sysIPV6_HOPLIMIT, 4, marshalHopLimit, parseHopLimit},
+ ctlPacketInfo: {sysIPV6_PKTINFO, sizeofInet6Pktinfo, marshalPacketInfo, parsePacketInfo},
+ ctlPathMTU: {sysIPV6_PATHMTU, sizeofIPv6Mtuinfo, marshalPathMTU, parsePathMTU},
+ }
+
+ sockOpts = map[int]*sockOpt{
+ ssoTrafficClass: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_TCLASS, Len: 4}},
+ ssoHopLimit: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_UNICAST_HOPS, Len: 4}},
+ ssoMulticastInterface: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_MULTICAST_IF, Len: 4}},
+ ssoMulticastHopLimit: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_MULTICAST_HOPS, Len: 4}},
+ ssoMulticastLoopback: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_MULTICAST_LOOP, Len: 4}},
+ ssoReceiveTrafficClass: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_RECVTCLASS, Len: 4}},
+ ssoReceiveHopLimit: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_RECVHOPLIMIT, Len: 4}},
+ ssoReceivePacketInfo: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_RECVPKTINFO, Len: 4}},
+ ssoReceivePathMTU: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_RECVPATHMTU, Len: 4}},
+ ssoPathMTU: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_PATHMTU, Len: sizeofIPv6Mtuinfo}},
+ ssoChecksum: {Option: socket.Option{Level: iana.ProtocolReserved, Name: sysIPV6_CHECKSUM, Len: 4}},
+ ssoICMPFilter: {Option: socket.Option{Level: iana.ProtocolIPv6ICMP, Name: sysICMPV6_FILTER, Len: sizeofICMPv6Filter}},
+ ssoJoinGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysMCAST_JOIN_GROUP, Len: sizeofGroupReq}, typ: ssoTypeGroupReq},
+ ssoLeaveGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysMCAST_LEAVE_GROUP, Len: sizeofGroupReq}, typ: ssoTypeGroupReq},
+ ssoJoinSourceGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysMCAST_JOIN_SOURCE_GROUP, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq},
+ ssoLeaveSourceGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysMCAST_LEAVE_SOURCE_GROUP, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq},
+ ssoBlockSourceGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysMCAST_BLOCK_SOURCE, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq},
+ ssoUnblockSourceGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysMCAST_UNBLOCK_SOURCE, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq},
+ ssoAttachFilter: {Option: socket.Option{Level: sysSOL_SOCKET, Name: sysSO_ATTACH_FILTER, Len: sizeofSockFprog}},
+ }
+)
+
+func (sa *sockaddrInet6) setSockaddr(ip net.IP, i int) {
+ sa.Family = syscall.AF_INET6
+ copy(sa.Addr[:], ip)
+ sa.Scope_id = uint32(i)
+}
+
+func (pi *inet6Pktinfo) setIfindex(i int) {
+ pi.Ifindex = int32(i)
+}
+
+func (mreq *ipv6Mreq) setIfindex(i int) {
+ mreq.Ifindex = int32(i)
+}
+
+func (gr *groupReq) setGroup(grp net.IP) {
+ sa := (*sockaddrInet6)(unsafe.Pointer(&gr.Group))
+ sa.Family = syscall.AF_INET6
+ copy(sa.Addr[:], grp)
+}
+
+func (gsr *groupSourceReq) setSourceGroup(grp, src net.IP) {
+ sa := (*sockaddrInet6)(unsafe.Pointer(&gsr.Group))
+ sa.Family = syscall.AF_INET6
+ copy(sa.Addr[:], grp)
+ sa = (*sockaddrInet6)(unsafe.Pointer(&gsr.Source))
+ sa.Family = syscall.AF_INET6
+ copy(sa.Addr[:], src)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_solaris.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_solaris.go
new file mode 100644
index 000000000..d348b5f6e
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_solaris.go
@@ -0,0 +1,74 @@
+// 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.
+
+package ipv6
+
+import (
+ "net"
+ "syscall"
+ "unsafe"
+
+ "golang.org/x/net/internal/iana"
+ "golang.org/x/net/internal/socket"
+)
+
+var (
+ ctlOpts = [ctlMax]ctlOpt{
+ ctlTrafficClass: {sysIPV6_TCLASS, 4, marshalTrafficClass, parseTrafficClass},
+ ctlHopLimit: {sysIPV6_HOPLIMIT, 4, marshalHopLimit, parseHopLimit},
+ ctlPacketInfo: {sysIPV6_PKTINFO, sizeofInet6Pktinfo, marshalPacketInfo, parsePacketInfo},
+ ctlNextHop: {sysIPV6_NEXTHOP, sizeofSockaddrInet6, marshalNextHop, parseNextHop},
+ ctlPathMTU: {sysIPV6_PATHMTU, sizeofIPv6Mtuinfo, marshalPathMTU, parsePathMTU},
+ }
+
+ sockOpts = map[int]*sockOpt{
+ ssoTrafficClass: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_TCLASS, Len: 4}},
+ ssoHopLimit: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_UNICAST_HOPS, Len: 4}},
+ ssoMulticastInterface: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_MULTICAST_IF, Len: 4}},
+ ssoMulticastHopLimit: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_MULTICAST_HOPS, Len: 4}},
+ ssoMulticastLoopback: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_MULTICAST_LOOP, Len: 4}},
+ ssoReceiveTrafficClass: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_RECVTCLASS, Len: 4}},
+ ssoReceiveHopLimit: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_RECVHOPLIMIT, Len: 4}},
+ ssoReceivePacketInfo: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_RECVPKTINFO, Len: 4}},
+ ssoReceivePathMTU: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_RECVPATHMTU, Len: 4}},
+ ssoPathMTU: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_PATHMTU, Len: sizeofIPv6Mtuinfo}},
+ ssoChecksum: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_CHECKSUM, Len: 4}},
+ ssoICMPFilter: {Option: socket.Option{Level: iana.ProtocolIPv6ICMP, Name: sysICMP6_FILTER, Len: sizeofICMPv6Filter}},
+ ssoJoinGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysMCAST_JOIN_GROUP, Len: sizeofGroupReq}, typ: ssoTypeGroupReq},
+ ssoLeaveGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysMCAST_LEAVE_GROUP, Len: sizeofGroupReq}, typ: ssoTypeGroupReq},
+ ssoJoinSourceGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysMCAST_JOIN_SOURCE_GROUP, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq},
+ ssoLeaveSourceGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysMCAST_LEAVE_SOURCE_GROUP, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq},
+ ssoBlockSourceGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysMCAST_BLOCK_SOURCE, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq},
+ ssoUnblockSourceGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysMCAST_UNBLOCK_SOURCE, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq},
+ }
+)
+
+func (sa *sockaddrInet6) setSockaddr(ip net.IP, i int) {
+ sa.Family = syscall.AF_INET6
+ copy(sa.Addr[:], ip)
+ sa.Scope_id = uint32(i)
+}
+
+func (pi *inet6Pktinfo) setIfindex(i int) {
+ pi.Ifindex = uint32(i)
+}
+
+func (mreq *ipv6Mreq) setIfindex(i int) {
+ mreq.Interface = uint32(i)
+}
+
+func (gr *groupReq) setGroup(grp net.IP) {
+ sa := (*sockaddrInet6)(unsafe.Pointer(uintptr(unsafe.Pointer(gr)) + 4))
+ sa.Family = syscall.AF_INET6
+ copy(sa.Addr[:], grp)
+}
+
+func (gsr *groupSourceReq) setSourceGroup(grp, src net.IP) {
+ sa := (*sockaddrInet6)(unsafe.Pointer(uintptr(unsafe.Pointer(gsr)) + 4))
+ sa.Family = syscall.AF_INET6
+ copy(sa.Addr[:], grp)
+ sa = (*sockaddrInet6)(unsafe.Pointer(uintptr(unsafe.Pointer(gsr)) + 260))
+ sa.Family = syscall.AF_INET6
+ copy(sa.Addr[:], src)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_ssmreq.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_ssmreq.go
new file mode 100644
index 000000000..add8ccc0b
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_ssmreq.go
@@ -0,0 +1,54 @@
+// Copyright 2014 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.
+
+// +build darwin freebsd linux solaris
+
+package ipv6
+
+import (
+ "net"
+ "unsafe"
+
+ "golang.org/x/net/internal/socket"
+)
+
+var freebsd32o64 bool
+
+func (so *sockOpt) setGroupReq(c *socket.Conn, ifi *net.Interface, grp net.IP) error {
+ var gr groupReq
+ if ifi != nil {
+ gr.Interface = uint32(ifi.Index)
+ }
+ gr.setGroup(grp)
+ var b []byte
+ if freebsd32o64 {
+ var d [sizeofGroupReq + 4]byte
+ s := (*[sizeofGroupReq]byte)(unsafe.Pointer(&gr))
+ copy(d[:4], s[:4])
+ copy(d[8:], s[4:])
+ b = d[:]
+ } else {
+ b = (*[sizeofGroupReq]byte)(unsafe.Pointer(&gr))[:sizeofGroupReq]
+ }
+ return so.Set(c, b)
+}
+
+func (so *sockOpt) setGroupSourceReq(c *socket.Conn, ifi *net.Interface, grp, src net.IP) error {
+ var gsr groupSourceReq
+ if ifi != nil {
+ gsr.Interface = uint32(ifi.Index)
+ }
+ gsr.setSourceGroup(grp, src)
+ var b []byte
+ if freebsd32o64 {
+ var d [sizeofGroupSourceReq + 4]byte
+ s := (*[sizeofGroupSourceReq]byte)(unsafe.Pointer(&gsr))
+ copy(d[:4], s[:4])
+ copy(d[8:], s[4:])
+ b = d[:]
+ } else {
+ b = (*[sizeofGroupSourceReq]byte)(unsafe.Pointer(&gsr))[:sizeofGroupSourceReq]
+ }
+ return so.Set(c, b)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_ssmreq_stub.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_ssmreq_stub.go
new file mode 100644
index 000000000..581ee490f
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_ssmreq_stub.go
@@ -0,0 +1,21 @@
+// Copyright 2014 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.
+
+// +build !darwin,!freebsd,!linux,!solaris
+
+package ipv6
+
+import (
+ "net"
+
+ "golang.org/x/net/internal/socket"
+)
+
+func (so *sockOpt) setGroupReq(c *socket.Conn, ifi *net.Interface, grp net.IP) error {
+ return errOpNoSupport
+}
+
+func (so *sockOpt) setGroupSourceReq(c *socket.Conn, ifi *net.Interface, grp, src net.IP) error {
+ return errOpNoSupport
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_stub.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_stub.go
new file mode 100644
index 000000000..b845388ea
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_stub.go
@@ -0,0 +1,13 @@
+// Copyright 2014 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.
+
+// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows
+
+package ipv6
+
+var (
+ ctlOpts = [ctlMax]ctlOpt{}
+
+ sockOpts = map[int]*sockOpt{}
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_windows.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_windows.go
new file mode 100644
index 000000000..fc36b018b
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/sys_windows.go
@@ -0,0 +1,75 @@
+// Copyright 2013 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 ipv6
+
+import (
+ "net"
+ "syscall"
+
+ "golang.org/x/net/internal/iana"
+ "golang.org/x/net/internal/socket"
+)
+
+const (
+ // See ws2tcpip.h.
+ sysIPV6_UNICAST_HOPS = 0x4
+ sysIPV6_MULTICAST_IF = 0x9
+ sysIPV6_MULTICAST_HOPS = 0xa
+ sysIPV6_MULTICAST_LOOP = 0xb
+ sysIPV6_JOIN_GROUP = 0xc
+ sysIPV6_LEAVE_GROUP = 0xd
+ sysIPV6_PKTINFO = 0x13
+
+ sizeofSockaddrInet6 = 0x1c
+
+ sizeofIPv6Mreq = 0x14
+ sizeofIPv6Mtuinfo = 0x20
+ sizeofICMPv6Filter = 0
+)
+
+type sockaddrInet6 struct {
+ Family uint16
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+type ipv6Mreq struct {
+ Multiaddr [16]byte /* in6_addr */
+ Interface uint32
+}
+
+type ipv6Mtuinfo struct {
+ Addr sockaddrInet6
+ Mtu uint32
+}
+
+type icmpv6Filter struct {
+ // TODO(mikio): implement this
+}
+
+var (
+ ctlOpts = [ctlMax]ctlOpt{}
+
+ sockOpts = map[int]*sockOpt{
+ ssoHopLimit: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_UNICAST_HOPS, Len: 4}},
+ ssoMulticastInterface: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_MULTICAST_IF, Len: 4}},
+ ssoMulticastHopLimit: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_MULTICAST_HOPS, Len: 4}},
+ ssoMulticastLoopback: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_MULTICAST_LOOP, Len: 4}},
+ ssoJoinGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_JOIN_GROUP, Len: sizeofIPv6Mreq}, typ: ssoTypeIPMreq},
+ ssoLeaveGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_LEAVE_GROUP, Len: sizeofIPv6Mreq}, typ: ssoTypeIPMreq},
+ }
+)
+
+func (sa *sockaddrInet6) setSockaddr(ip net.IP, i int) {
+ sa.Family = syscall.AF_INET6
+ copy(sa.Addr[:], ip)
+ sa.Scope_id = uint32(i)
+}
+
+func (mreq *ipv6Mreq) setIfindex(i int) {
+ mreq.Interface = uint32(i)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/unicast_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/unicast_test.go
new file mode 100644
index 000000000..a0b7d9550
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/unicast_test.go
@@ -0,0 +1,184 @@
+// Copyright 2013 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 ipv6_test
+
+import (
+ "bytes"
+ "net"
+ "os"
+ "runtime"
+ "testing"
+ "time"
+
+ "golang.org/x/net/icmp"
+ "golang.org/x/net/internal/iana"
+ "golang.org/x/net/internal/nettest"
+ "golang.org/x/net/ipv6"
+)
+
+func TestPacketConnReadWriteUnicastUDP(t *testing.T) {
+ switch runtime.GOOS {
+ case "nacl", "plan9", "windows":
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+ if !supportsIPv6 {
+ t.Skip("ipv6 is not supported")
+ }
+
+ c, err := nettest.NewLocalPacketListener("udp6")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer c.Close()
+ p := ipv6.NewPacketConn(c)
+ defer p.Close()
+
+ dst := c.LocalAddr()
+ cm := ipv6.ControlMessage{
+ TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced,
+ Src: net.IPv6loopback,
+ }
+ cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU
+ ifi := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback)
+ if ifi != nil {
+ cm.IfIndex = ifi.Index
+ }
+ wb := []byte("HELLO-R-U-THERE")
+
+ for i, toggle := range []bool{true, false, true} {
+ if err := p.SetControlMessage(cf, toggle); err != nil {
+ if nettest.ProtocolNotSupported(err) {
+ t.Logf("not supported on %s", runtime.GOOS)
+ continue
+ }
+ t.Fatal(err)
+ }
+ cm.HopLimit = i + 1
+ if err := p.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
+ t.Fatal(err)
+ }
+ if n, err := p.WriteTo(wb, &cm, dst); err != nil {
+ t.Fatal(err)
+ } else if n != len(wb) {
+ t.Fatalf("got %v; want %v", n, len(wb))
+ }
+ rb := make([]byte, 128)
+ if err := p.SetReadDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
+ t.Fatal(err)
+ }
+ if n, _, _, err := p.ReadFrom(rb); err != nil {
+ t.Fatal(err)
+ } else if !bytes.Equal(rb[:n], wb) {
+ t.Fatalf("got %v; want %v", rb[:n], wb)
+ }
+ }
+}
+
+func TestPacketConnReadWriteUnicastICMP(t *testing.T) {
+ switch runtime.GOOS {
+ case "nacl", "plan9", "windows":
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+ if !supportsIPv6 {
+ t.Skip("ipv6 is not supported")
+ }
+ if m, ok := nettest.SupportsRawIPSocket(); !ok {
+ t.Skip(m)
+ }
+
+ c, err := net.ListenPacket("ip6:ipv6-icmp", "::1")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer c.Close()
+ p := ipv6.NewPacketConn(c)
+ defer p.Close()
+
+ dst, err := net.ResolveIPAddr("ip6", "::1")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ pshicmp := icmp.IPv6PseudoHeader(c.LocalAddr().(*net.IPAddr).IP, dst.IP)
+ cm := ipv6.ControlMessage{
+ TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced,
+ Src: net.IPv6loopback,
+ }
+ cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU
+ ifi := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback)
+ if ifi != nil {
+ cm.IfIndex = ifi.Index
+ }
+
+ var f ipv6.ICMPFilter
+ f.SetAll(true)
+ f.Accept(ipv6.ICMPTypeEchoReply)
+ if err := p.SetICMPFilter(&f); err != nil {
+ t.Fatal(err)
+ }
+
+ var psh []byte
+ for i, toggle := range []bool{true, false, true} {
+ if toggle {
+ psh = nil
+ if err := p.SetChecksum(true, 2); err != nil {
+ // Solaris never allows to modify
+ // ICMP properties.
+ if runtime.GOOS != "solaris" {
+ t.Fatal(err)
+ }
+ }
+ } else {
+ psh = pshicmp
+ // Some platforms never allow to disable the
+ // kernel checksum processing.
+ p.SetChecksum(false, -1)
+ }
+ wb, err := (&icmp.Message{
+ Type: ipv6.ICMPTypeEchoRequest, Code: 0,
+ Body: &icmp.Echo{
+ ID: os.Getpid() & 0xffff, Seq: i + 1,
+ Data: []byte("HELLO-R-U-THERE"),
+ },
+ }).Marshal(psh)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := p.SetControlMessage(cf, toggle); err != nil {
+ if nettest.ProtocolNotSupported(err) {
+ t.Logf("not supported on %s", runtime.GOOS)
+ continue
+ }
+ t.Fatal(err)
+ }
+ cm.HopLimit = i + 1
+ if err := p.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
+ t.Fatal(err)
+ }
+ if n, err := p.WriteTo(wb, &cm, dst); err != nil {
+ t.Fatal(err)
+ } else if n != len(wb) {
+ t.Fatalf("got %v; want %v", n, len(wb))
+ }
+ rb := make([]byte, 128)
+ if err := p.SetReadDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
+ t.Fatal(err)
+ }
+ if n, _, _, err := p.ReadFrom(rb); err != nil {
+ switch runtime.GOOS {
+ case "darwin": // older darwin kernels have some limitation on receiving icmp packet through raw socket
+ t.Logf("not supported on %s", runtime.GOOS)
+ continue
+ }
+ t.Fatal(err)
+ } else {
+ if m, err := icmp.ParseMessage(iana.ProtocolIPv6ICMP, rb[:n]); err != nil {
+ t.Fatal(err)
+ } else if m.Type != ipv6.ICMPTypeEchoReply || m.Code != 0 {
+ t.Fatalf("got type=%v, code=%v; want type=%v, code=%v", m.Type, m.Code, ipv6.ICMPTypeEchoReply, 0)
+ }
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/unicastsockopt_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/unicastsockopt_test.go
new file mode 100644
index 000000000..e175dccf5
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/unicastsockopt_test.go
@@ -0,0 +1,120 @@
+// Copyright 2013 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 ipv6_test
+
+import (
+ "net"
+ "runtime"
+ "testing"
+
+ "golang.org/x/net/internal/iana"
+ "golang.org/x/net/internal/nettest"
+ "golang.org/x/net/ipv6"
+)
+
+func TestConnUnicastSocketOptions(t *testing.T) {
+ switch runtime.GOOS {
+ case "nacl", "plan9", "windows":
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+ if !supportsIPv6 {
+ t.Skip("ipv6 is not supported")
+ }
+
+ ln, err := net.Listen("tcp6", "[::1]:0")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer ln.Close()
+
+ errc := make(chan error, 1)
+ go func() {
+ c, err := ln.Accept()
+ if err != nil {
+ errc <- err
+ return
+ }
+ errc <- c.Close()
+ }()
+
+ c, err := net.Dial("tcp6", ln.Addr().String())
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer c.Close()
+
+ testUnicastSocketOptions(t, ipv6.NewConn(c))
+
+ if err := <-errc; err != nil {
+ t.Errorf("server: %v", err)
+ }
+}
+
+var packetConnUnicastSocketOptionTests = []struct {
+ net, proto, addr string
+}{
+ {"udp6", "", "[::1]:0"},
+ {"ip6", ":ipv6-icmp", "::1"},
+}
+
+func TestPacketConnUnicastSocketOptions(t *testing.T) {
+ switch runtime.GOOS {
+ case "nacl", "plan9", "windows":
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+ if !supportsIPv6 {
+ t.Skip("ipv6 is not supported")
+ }
+
+ m, ok := nettest.SupportsRawIPSocket()
+ for _, tt := range packetConnUnicastSocketOptionTests {
+ if tt.net == "ip6" && !ok {
+ t.Log(m)
+ continue
+ }
+ c, err := net.ListenPacket(tt.net+tt.proto, tt.addr)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer c.Close()
+
+ testUnicastSocketOptions(t, ipv6.NewPacketConn(c))
+ }
+}
+
+type testIPv6UnicastConn interface {
+ TrafficClass() (int, error)
+ SetTrafficClass(int) error
+ HopLimit() (int, error)
+ SetHopLimit(int) error
+}
+
+func testUnicastSocketOptions(t *testing.T, c testIPv6UnicastConn) {
+ tclass := iana.DiffServCS0 | iana.NotECNTransport
+ if err := c.SetTrafficClass(tclass); err != nil {
+ switch runtime.GOOS {
+ case "darwin": // older darwin kernels don't support IPV6_TCLASS option
+ t.Logf("not supported on %s", runtime.GOOS)
+ goto next
+ }
+ t.Fatal(err)
+ }
+ if v, err := c.TrafficClass(); err != nil {
+ t.Fatal(err)
+ } else if v != tclass {
+ t.Fatalf("got %v; want %v", v, tclass)
+ }
+
+next:
+ hoplim := 255
+ if err := c.SetHopLimit(hoplim); err != nil {
+ t.Fatal(err)
+ }
+ if v, err := c.HopLimit(); err != nil {
+ t.Fatal(err)
+ } else if v != hoplim {
+ t.Fatalf("got %v; want %v", v, hoplim)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_darwin.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_darwin.go
new file mode 100644
index 000000000..6aab1dfab
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_darwin.go
@@ -0,0 +1,131 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_darwin.go
+
+package ipv6
+
+const (
+ sysIPV6_UNICAST_HOPS = 0x4
+ sysIPV6_MULTICAST_IF = 0x9
+ sysIPV6_MULTICAST_HOPS = 0xa
+ sysIPV6_MULTICAST_LOOP = 0xb
+ sysIPV6_JOIN_GROUP = 0xc
+ sysIPV6_LEAVE_GROUP = 0xd
+
+ sysIPV6_PORTRANGE = 0xe
+ sysICMP6_FILTER = 0x12
+ sysIPV6_2292PKTINFO = 0x13
+ sysIPV6_2292HOPLIMIT = 0x14
+ sysIPV6_2292NEXTHOP = 0x15
+ sysIPV6_2292HOPOPTS = 0x16
+ sysIPV6_2292DSTOPTS = 0x17
+ sysIPV6_2292RTHDR = 0x18
+
+ sysIPV6_2292PKTOPTIONS = 0x19
+
+ sysIPV6_CHECKSUM = 0x1a
+ sysIPV6_V6ONLY = 0x1b
+
+ sysIPV6_IPSEC_POLICY = 0x1c
+
+ sysIPV6_RECVTCLASS = 0x23
+ sysIPV6_TCLASS = 0x24
+
+ sysIPV6_RTHDRDSTOPTS = 0x39
+
+ sysIPV6_RECVPKTINFO = 0x3d
+
+ sysIPV6_RECVHOPLIMIT = 0x25
+ sysIPV6_RECVRTHDR = 0x26
+ sysIPV6_RECVHOPOPTS = 0x27
+ sysIPV6_RECVDSTOPTS = 0x28
+
+ sysIPV6_USE_MIN_MTU = 0x2a
+ sysIPV6_RECVPATHMTU = 0x2b
+
+ sysIPV6_PATHMTU = 0x2c
+
+ sysIPV6_PKTINFO = 0x2e
+ sysIPV6_HOPLIMIT = 0x2f
+ sysIPV6_NEXTHOP = 0x30
+ sysIPV6_HOPOPTS = 0x31
+ sysIPV6_DSTOPTS = 0x32
+ sysIPV6_RTHDR = 0x33
+
+ sysIPV6_AUTOFLOWLABEL = 0x3b
+
+ sysIPV6_DONTFRAG = 0x3e
+
+ sysIPV6_PREFER_TEMPADDR = 0x3f
+
+ sysIPV6_MSFILTER = 0x4a
+ sysMCAST_JOIN_GROUP = 0x50
+ sysMCAST_LEAVE_GROUP = 0x51
+ sysMCAST_JOIN_SOURCE_GROUP = 0x52
+ sysMCAST_LEAVE_SOURCE_GROUP = 0x53
+ sysMCAST_BLOCK_SOURCE = 0x54
+ sysMCAST_UNBLOCK_SOURCE = 0x55
+
+ sysIPV6_BOUND_IF = 0x7d
+
+ sysIPV6_PORTRANGE_DEFAULT = 0x0
+ sysIPV6_PORTRANGE_HIGH = 0x1
+ sysIPV6_PORTRANGE_LOW = 0x2
+
+ sizeofSockaddrStorage = 0x80
+ sizeofSockaddrInet6 = 0x1c
+ sizeofInet6Pktinfo = 0x14
+ sizeofIPv6Mtuinfo = 0x20
+
+ sizeofIPv6Mreq = 0x14
+ sizeofGroupReq = 0x84
+ sizeofGroupSourceReq = 0x104
+
+ sizeofICMPv6Filter = 0x20
+)
+
+type sockaddrStorage struct {
+ Len uint8
+ Family uint8
+ X__ss_pad1 [6]int8
+ X__ss_align int64
+ X__ss_pad2 [112]int8
+}
+
+type sockaddrInet6 struct {
+ Len uint8
+ Family uint8
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+type inet6Pktinfo struct {
+ Addr [16]byte /* in6_addr */
+ Ifindex uint32
+}
+
+type ipv6Mtuinfo struct {
+ Addr sockaddrInet6
+ Mtu uint32
+}
+
+type ipv6Mreq struct {
+ Multiaddr [16]byte /* in6_addr */
+ Interface uint32
+}
+
+type icmpv6Filter struct {
+ Filt [8]uint32
+}
+
+type groupReq struct {
+ Interface uint32
+ Pad_cgo_0 [128]byte
+}
+
+type groupSourceReq struct {
+ Interface uint32
+ Pad_cgo_0 [128]byte
+ Pad_cgo_1 [128]byte
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_dragonfly.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_dragonfly.go
new file mode 100644
index 000000000..d2de804d8
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_dragonfly.go
@@ -0,0 +1,88 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_dragonfly.go
+
+package ipv6
+
+const (
+ sysIPV6_UNICAST_HOPS = 0x4
+ sysIPV6_MULTICAST_IF = 0x9
+ sysIPV6_MULTICAST_HOPS = 0xa
+ sysIPV6_MULTICAST_LOOP = 0xb
+ sysIPV6_JOIN_GROUP = 0xc
+ sysIPV6_LEAVE_GROUP = 0xd
+ sysIPV6_PORTRANGE = 0xe
+ sysICMP6_FILTER = 0x12
+
+ sysIPV6_CHECKSUM = 0x1a
+ sysIPV6_V6ONLY = 0x1b
+
+ sysIPV6_IPSEC_POLICY = 0x1c
+
+ sysIPV6_RTHDRDSTOPTS = 0x23
+ sysIPV6_RECVPKTINFO = 0x24
+ sysIPV6_RECVHOPLIMIT = 0x25
+ sysIPV6_RECVRTHDR = 0x26
+ sysIPV6_RECVHOPOPTS = 0x27
+ sysIPV6_RECVDSTOPTS = 0x28
+
+ sysIPV6_USE_MIN_MTU = 0x2a
+ sysIPV6_RECVPATHMTU = 0x2b
+
+ sysIPV6_PATHMTU = 0x2c
+
+ sysIPV6_PKTINFO = 0x2e
+ sysIPV6_HOPLIMIT = 0x2f
+ sysIPV6_NEXTHOP = 0x30
+ sysIPV6_HOPOPTS = 0x31
+ sysIPV6_DSTOPTS = 0x32
+ sysIPV6_RTHDR = 0x33
+
+ sysIPV6_RECVTCLASS = 0x39
+
+ sysIPV6_AUTOFLOWLABEL = 0x3b
+
+ sysIPV6_TCLASS = 0x3d
+ sysIPV6_DONTFRAG = 0x3e
+
+ sysIPV6_PREFER_TEMPADDR = 0x3f
+
+ sysIPV6_PORTRANGE_DEFAULT = 0x0
+ sysIPV6_PORTRANGE_HIGH = 0x1
+ sysIPV6_PORTRANGE_LOW = 0x2
+
+ sizeofSockaddrInet6 = 0x1c
+ sizeofInet6Pktinfo = 0x14
+ sizeofIPv6Mtuinfo = 0x20
+
+ sizeofIPv6Mreq = 0x14
+
+ sizeofICMPv6Filter = 0x20
+)
+
+type sockaddrInet6 struct {
+ Len uint8
+ Family uint8
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+type inet6Pktinfo struct {
+ Addr [16]byte /* in6_addr */
+ Ifindex uint32
+}
+
+type ipv6Mtuinfo struct {
+ Addr sockaddrInet6
+ Mtu uint32
+}
+
+type ipv6Mreq struct {
+ Multiaddr [16]byte /* in6_addr */
+ Interface uint32
+}
+
+type icmpv6Filter struct {
+ Filt [8]uint32
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_freebsd_386.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_freebsd_386.go
new file mode 100644
index 000000000..919e572d4
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_freebsd_386.go
@@ -0,0 +1,122 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_freebsd.go
+
+package ipv6
+
+const (
+ sysIPV6_UNICAST_HOPS = 0x4
+ sysIPV6_MULTICAST_IF = 0x9
+ sysIPV6_MULTICAST_HOPS = 0xa
+ sysIPV6_MULTICAST_LOOP = 0xb
+ sysIPV6_JOIN_GROUP = 0xc
+ sysIPV6_LEAVE_GROUP = 0xd
+ sysIPV6_PORTRANGE = 0xe
+ sysICMP6_FILTER = 0x12
+
+ sysIPV6_CHECKSUM = 0x1a
+ sysIPV6_V6ONLY = 0x1b
+
+ sysIPV6_IPSEC_POLICY = 0x1c
+
+ sysIPV6_RTHDRDSTOPTS = 0x23
+
+ sysIPV6_RECVPKTINFO = 0x24
+ sysIPV6_RECVHOPLIMIT = 0x25
+ sysIPV6_RECVRTHDR = 0x26
+ sysIPV6_RECVHOPOPTS = 0x27
+ sysIPV6_RECVDSTOPTS = 0x28
+
+ sysIPV6_USE_MIN_MTU = 0x2a
+ sysIPV6_RECVPATHMTU = 0x2b
+
+ sysIPV6_PATHMTU = 0x2c
+
+ sysIPV6_PKTINFO = 0x2e
+ sysIPV6_HOPLIMIT = 0x2f
+ sysIPV6_NEXTHOP = 0x30
+ sysIPV6_HOPOPTS = 0x31
+ sysIPV6_DSTOPTS = 0x32
+ sysIPV6_RTHDR = 0x33
+
+ sysIPV6_RECVTCLASS = 0x39
+
+ sysIPV6_AUTOFLOWLABEL = 0x3b
+
+ sysIPV6_TCLASS = 0x3d
+ sysIPV6_DONTFRAG = 0x3e
+
+ sysIPV6_PREFER_TEMPADDR = 0x3f
+
+ sysIPV6_BINDANY = 0x40
+
+ sysIPV6_MSFILTER = 0x4a
+
+ sysMCAST_JOIN_GROUP = 0x50
+ sysMCAST_LEAVE_GROUP = 0x51
+ sysMCAST_JOIN_SOURCE_GROUP = 0x52
+ sysMCAST_LEAVE_SOURCE_GROUP = 0x53
+ sysMCAST_BLOCK_SOURCE = 0x54
+ sysMCAST_UNBLOCK_SOURCE = 0x55
+
+ sysIPV6_PORTRANGE_DEFAULT = 0x0
+ sysIPV6_PORTRANGE_HIGH = 0x1
+ sysIPV6_PORTRANGE_LOW = 0x2
+
+ sizeofSockaddrStorage = 0x80
+ sizeofSockaddrInet6 = 0x1c
+ sizeofInet6Pktinfo = 0x14
+ sizeofIPv6Mtuinfo = 0x20
+
+ sizeofIPv6Mreq = 0x14
+ sizeofGroupReq = 0x84
+ sizeofGroupSourceReq = 0x104
+
+ sizeofICMPv6Filter = 0x20
+)
+
+type sockaddrStorage struct {
+ Len uint8
+ Family uint8
+ X__ss_pad1 [6]int8
+ X__ss_align int64
+ X__ss_pad2 [112]int8
+}
+
+type sockaddrInet6 struct {
+ Len uint8
+ Family uint8
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+type inet6Pktinfo struct {
+ Addr [16]byte /* in6_addr */
+ Ifindex uint32
+}
+
+type ipv6Mtuinfo struct {
+ Addr sockaddrInet6
+ Mtu uint32
+}
+
+type ipv6Mreq struct {
+ Multiaddr [16]byte /* in6_addr */
+ Interface uint32
+}
+
+type groupReq struct {
+ Interface uint32
+ Group sockaddrStorage
+}
+
+type groupSourceReq struct {
+ Interface uint32
+ Group sockaddrStorage
+ Source sockaddrStorage
+}
+
+type icmpv6Filter struct {
+ Filt [8]uint32
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_freebsd_amd64.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_freebsd_amd64.go
new file mode 100644
index 000000000..cb8141f9c
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_freebsd_amd64.go
@@ -0,0 +1,124 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_freebsd.go
+
+package ipv6
+
+const (
+ sysIPV6_UNICAST_HOPS = 0x4
+ sysIPV6_MULTICAST_IF = 0x9
+ sysIPV6_MULTICAST_HOPS = 0xa
+ sysIPV6_MULTICAST_LOOP = 0xb
+ sysIPV6_JOIN_GROUP = 0xc
+ sysIPV6_LEAVE_GROUP = 0xd
+ sysIPV6_PORTRANGE = 0xe
+ sysICMP6_FILTER = 0x12
+
+ sysIPV6_CHECKSUM = 0x1a
+ sysIPV6_V6ONLY = 0x1b
+
+ sysIPV6_IPSEC_POLICY = 0x1c
+
+ sysIPV6_RTHDRDSTOPTS = 0x23
+
+ sysIPV6_RECVPKTINFO = 0x24
+ sysIPV6_RECVHOPLIMIT = 0x25
+ sysIPV6_RECVRTHDR = 0x26
+ sysIPV6_RECVHOPOPTS = 0x27
+ sysIPV6_RECVDSTOPTS = 0x28
+
+ sysIPV6_USE_MIN_MTU = 0x2a
+ sysIPV6_RECVPATHMTU = 0x2b
+
+ sysIPV6_PATHMTU = 0x2c
+
+ sysIPV6_PKTINFO = 0x2e
+ sysIPV6_HOPLIMIT = 0x2f
+ sysIPV6_NEXTHOP = 0x30
+ sysIPV6_HOPOPTS = 0x31
+ sysIPV6_DSTOPTS = 0x32
+ sysIPV6_RTHDR = 0x33
+
+ sysIPV6_RECVTCLASS = 0x39
+
+ sysIPV6_AUTOFLOWLABEL = 0x3b
+
+ sysIPV6_TCLASS = 0x3d
+ sysIPV6_DONTFRAG = 0x3e
+
+ sysIPV6_PREFER_TEMPADDR = 0x3f
+
+ sysIPV6_BINDANY = 0x40
+
+ sysIPV6_MSFILTER = 0x4a
+
+ sysMCAST_JOIN_GROUP = 0x50
+ sysMCAST_LEAVE_GROUP = 0x51
+ sysMCAST_JOIN_SOURCE_GROUP = 0x52
+ sysMCAST_LEAVE_SOURCE_GROUP = 0x53
+ sysMCAST_BLOCK_SOURCE = 0x54
+ sysMCAST_UNBLOCK_SOURCE = 0x55
+
+ sysIPV6_PORTRANGE_DEFAULT = 0x0
+ sysIPV6_PORTRANGE_HIGH = 0x1
+ sysIPV6_PORTRANGE_LOW = 0x2
+
+ sizeofSockaddrStorage = 0x80
+ sizeofSockaddrInet6 = 0x1c
+ sizeofInet6Pktinfo = 0x14
+ sizeofIPv6Mtuinfo = 0x20
+
+ sizeofIPv6Mreq = 0x14
+ sizeofGroupReq = 0x88
+ sizeofGroupSourceReq = 0x108
+
+ sizeofICMPv6Filter = 0x20
+)
+
+type sockaddrStorage struct {
+ Len uint8
+ Family uint8
+ X__ss_pad1 [6]int8
+ X__ss_align int64
+ X__ss_pad2 [112]int8
+}
+
+type sockaddrInet6 struct {
+ Len uint8
+ Family uint8
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+type inet6Pktinfo struct {
+ Addr [16]byte /* in6_addr */
+ Ifindex uint32
+}
+
+type ipv6Mtuinfo struct {
+ Addr sockaddrInet6
+ Mtu uint32
+}
+
+type ipv6Mreq struct {
+ Multiaddr [16]byte /* in6_addr */
+ Interface uint32
+}
+
+type groupReq struct {
+ Interface uint32
+ Pad_cgo_0 [4]byte
+ Group sockaddrStorage
+}
+
+type groupSourceReq struct {
+ Interface uint32
+ Pad_cgo_0 [4]byte
+ Group sockaddrStorage
+ Source sockaddrStorage
+}
+
+type icmpv6Filter struct {
+ Filt [8]uint32
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_freebsd_arm.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_freebsd_arm.go
new file mode 100644
index 000000000..cb8141f9c
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_freebsd_arm.go
@@ -0,0 +1,124 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_freebsd.go
+
+package ipv6
+
+const (
+ sysIPV6_UNICAST_HOPS = 0x4
+ sysIPV6_MULTICAST_IF = 0x9
+ sysIPV6_MULTICAST_HOPS = 0xa
+ sysIPV6_MULTICAST_LOOP = 0xb
+ sysIPV6_JOIN_GROUP = 0xc
+ sysIPV6_LEAVE_GROUP = 0xd
+ sysIPV6_PORTRANGE = 0xe
+ sysICMP6_FILTER = 0x12
+
+ sysIPV6_CHECKSUM = 0x1a
+ sysIPV6_V6ONLY = 0x1b
+
+ sysIPV6_IPSEC_POLICY = 0x1c
+
+ sysIPV6_RTHDRDSTOPTS = 0x23
+
+ sysIPV6_RECVPKTINFO = 0x24
+ sysIPV6_RECVHOPLIMIT = 0x25
+ sysIPV6_RECVRTHDR = 0x26
+ sysIPV6_RECVHOPOPTS = 0x27
+ sysIPV6_RECVDSTOPTS = 0x28
+
+ sysIPV6_USE_MIN_MTU = 0x2a
+ sysIPV6_RECVPATHMTU = 0x2b
+
+ sysIPV6_PATHMTU = 0x2c
+
+ sysIPV6_PKTINFO = 0x2e
+ sysIPV6_HOPLIMIT = 0x2f
+ sysIPV6_NEXTHOP = 0x30
+ sysIPV6_HOPOPTS = 0x31
+ sysIPV6_DSTOPTS = 0x32
+ sysIPV6_RTHDR = 0x33
+
+ sysIPV6_RECVTCLASS = 0x39
+
+ sysIPV6_AUTOFLOWLABEL = 0x3b
+
+ sysIPV6_TCLASS = 0x3d
+ sysIPV6_DONTFRAG = 0x3e
+
+ sysIPV6_PREFER_TEMPADDR = 0x3f
+
+ sysIPV6_BINDANY = 0x40
+
+ sysIPV6_MSFILTER = 0x4a
+
+ sysMCAST_JOIN_GROUP = 0x50
+ sysMCAST_LEAVE_GROUP = 0x51
+ sysMCAST_JOIN_SOURCE_GROUP = 0x52
+ sysMCAST_LEAVE_SOURCE_GROUP = 0x53
+ sysMCAST_BLOCK_SOURCE = 0x54
+ sysMCAST_UNBLOCK_SOURCE = 0x55
+
+ sysIPV6_PORTRANGE_DEFAULT = 0x0
+ sysIPV6_PORTRANGE_HIGH = 0x1
+ sysIPV6_PORTRANGE_LOW = 0x2
+
+ sizeofSockaddrStorage = 0x80
+ sizeofSockaddrInet6 = 0x1c
+ sizeofInet6Pktinfo = 0x14
+ sizeofIPv6Mtuinfo = 0x20
+
+ sizeofIPv6Mreq = 0x14
+ sizeofGroupReq = 0x88
+ sizeofGroupSourceReq = 0x108
+
+ sizeofICMPv6Filter = 0x20
+)
+
+type sockaddrStorage struct {
+ Len uint8
+ Family uint8
+ X__ss_pad1 [6]int8
+ X__ss_align int64
+ X__ss_pad2 [112]int8
+}
+
+type sockaddrInet6 struct {
+ Len uint8
+ Family uint8
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+type inet6Pktinfo struct {
+ Addr [16]byte /* in6_addr */
+ Ifindex uint32
+}
+
+type ipv6Mtuinfo struct {
+ Addr sockaddrInet6
+ Mtu uint32
+}
+
+type ipv6Mreq struct {
+ Multiaddr [16]byte /* in6_addr */
+ Interface uint32
+}
+
+type groupReq struct {
+ Interface uint32
+ Pad_cgo_0 [4]byte
+ Group sockaddrStorage
+}
+
+type groupSourceReq struct {
+ Interface uint32
+ Pad_cgo_0 [4]byte
+ Group sockaddrStorage
+ Source sockaddrStorage
+}
+
+type icmpv6Filter struct {
+ Filt [8]uint32
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_linux_386.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_linux_386.go
new file mode 100644
index 000000000..73aa8c6df
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_linux_386.go
@@ -0,0 +1,170 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_linux.go
+
+package ipv6
+
+const (
+ sysIPV6_ADDRFORM = 0x1
+ sysIPV6_2292PKTINFO = 0x2
+ sysIPV6_2292HOPOPTS = 0x3
+ sysIPV6_2292DSTOPTS = 0x4
+ sysIPV6_2292RTHDR = 0x5
+ sysIPV6_2292PKTOPTIONS = 0x6
+ sysIPV6_CHECKSUM = 0x7
+ sysIPV6_2292HOPLIMIT = 0x8
+ sysIPV6_NEXTHOP = 0x9
+ sysIPV6_FLOWINFO = 0xb
+
+ sysIPV6_UNICAST_HOPS = 0x10
+ sysIPV6_MULTICAST_IF = 0x11
+ sysIPV6_MULTICAST_HOPS = 0x12
+ sysIPV6_MULTICAST_LOOP = 0x13
+ sysIPV6_ADD_MEMBERSHIP = 0x14
+ sysIPV6_DROP_MEMBERSHIP = 0x15
+ sysMCAST_JOIN_GROUP = 0x2a
+ sysMCAST_LEAVE_GROUP = 0x2d
+ sysMCAST_JOIN_SOURCE_GROUP = 0x2e
+ sysMCAST_LEAVE_SOURCE_GROUP = 0x2f
+ sysMCAST_BLOCK_SOURCE = 0x2b
+ sysMCAST_UNBLOCK_SOURCE = 0x2c
+ sysMCAST_MSFILTER = 0x30
+ sysIPV6_ROUTER_ALERT = 0x16
+ sysIPV6_MTU_DISCOVER = 0x17
+ sysIPV6_MTU = 0x18
+ sysIPV6_RECVERR = 0x19
+ sysIPV6_V6ONLY = 0x1a
+ sysIPV6_JOIN_ANYCAST = 0x1b
+ sysIPV6_LEAVE_ANYCAST = 0x1c
+
+ sysIPV6_FLOWLABEL_MGR = 0x20
+ sysIPV6_FLOWINFO_SEND = 0x21
+
+ sysIPV6_IPSEC_POLICY = 0x22
+ sysIPV6_XFRM_POLICY = 0x23
+
+ sysIPV6_RECVPKTINFO = 0x31
+ sysIPV6_PKTINFO = 0x32
+ sysIPV6_RECVHOPLIMIT = 0x33
+ sysIPV6_HOPLIMIT = 0x34
+ sysIPV6_RECVHOPOPTS = 0x35
+ sysIPV6_HOPOPTS = 0x36
+ sysIPV6_RTHDRDSTOPTS = 0x37
+ sysIPV6_RECVRTHDR = 0x38
+ sysIPV6_RTHDR = 0x39
+ sysIPV6_RECVDSTOPTS = 0x3a
+ sysIPV6_DSTOPTS = 0x3b
+ sysIPV6_RECVPATHMTU = 0x3c
+ sysIPV6_PATHMTU = 0x3d
+ sysIPV6_DONTFRAG = 0x3e
+
+ sysIPV6_RECVTCLASS = 0x42
+ sysIPV6_TCLASS = 0x43
+
+ sysIPV6_ADDR_PREFERENCES = 0x48
+
+ sysIPV6_PREFER_SRC_TMP = 0x1
+ sysIPV6_PREFER_SRC_PUBLIC = 0x2
+ sysIPV6_PREFER_SRC_PUBTMP_DEFAULT = 0x100
+ sysIPV6_PREFER_SRC_COA = 0x4
+ sysIPV6_PREFER_SRC_HOME = 0x400
+ sysIPV6_PREFER_SRC_CGA = 0x8
+ sysIPV6_PREFER_SRC_NONCGA = 0x800
+
+ sysIPV6_MINHOPCOUNT = 0x49
+
+ sysIPV6_ORIGDSTADDR = 0x4a
+ sysIPV6_RECVORIGDSTADDR = 0x4a
+ sysIPV6_TRANSPARENT = 0x4b
+ sysIPV6_UNICAST_IF = 0x4c
+
+ sysICMPV6_FILTER = 0x1
+
+ sysICMPV6_FILTER_BLOCK = 0x1
+ sysICMPV6_FILTER_PASS = 0x2
+ sysICMPV6_FILTER_BLOCKOTHERS = 0x3
+ sysICMPV6_FILTER_PASSONLY = 0x4
+
+ sysSOL_SOCKET = 0x1
+ sysSO_ATTACH_FILTER = 0x1a
+
+ sizeofKernelSockaddrStorage = 0x80
+ sizeofSockaddrInet6 = 0x1c
+ sizeofInet6Pktinfo = 0x14
+ sizeofIPv6Mtuinfo = 0x20
+ sizeofIPv6FlowlabelReq = 0x20
+
+ sizeofIPv6Mreq = 0x14
+ sizeofGroupReq = 0x84
+ sizeofGroupSourceReq = 0x104
+
+ sizeofICMPv6Filter = 0x20
+
+ sizeofSockFprog = 0x8
+)
+
+type kernelSockaddrStorage struct {
+ Family uint16
+ X__data [126]int8
+}
+
+type sockaddrInet6 struct {
+ Family uint16
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+type inet6Pktinfo struct {
+ Addr [16]byte /* in6_addr */
+ Ifindex int32
+}
+
+type ipv6Mtuinfo struct {
+ Addr sockaddrInet6
+ Mtu uint32
+}
+
+type ipv6FlowlabelReq struct {
+ Dst [16]byte /* in6_addr */
+ Label uint32
+ Action uint8
+ Share uint8
+ Flags uint16
+ Expires uint16
+ Linger uint16
+ X__flr_pad uint32
+}
+
+type ipv6Mreq struct {
+ Multiaddr [16]byte /* in6_addr */
+ Ifindex int32
+}
+
+type groupReq struct {
+ Interface uint32
+ Group kernelSockaddrStorage
+}
+
+type groupSourceReq struct {
+ Interface uint32
+ Group kernelSockaddrStorage
+ Source kernelSockaddrStorage
+}
+
+type icmpv6Filter struct {
+ Data [8]uint32
+}
+
+type sockFProg struct {
+ Len uint16
+ Pad_cgo_0 [2]byte
+ Filter *sockFilter
+}
+
+type sockFilter struct {
+ Code uint16
+ Jt uint8
+ Jf uint8
+ K uint32
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_linux_amd64.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_linux_amd64.go
new file mode 100644
index 000000000..b64f0157d
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_linux_amd64.go
@@ -0,0 +1,172 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_linux.go
+
+package ipv6
+
+const (
+ sysIPV6_ADDRFORM = 0x1
+ sysIPV6_2292PKTINFO = 0x2
+ sysIPV6_2292HOPOPTS = 0x3
+ sysIPV6_2292DSTOPTS = 0x4
+ sysIPV6_2292RTHDR = 0x5
+ sysIPV6_2292PKTOPTIONS = 0x6
+ sysIPV6_CHECKSUM = 0x7
+ sysIPV6_2292HOPLIMIT = 0x8
+ sysIPV6_NEXTHOP = 0x9
+ sysIPV6_FLOWINFO = 0xb
+
+ sysIPV6_UNICAST_HOPS = 0x10
+ sysIPV6_MULTICAST_IF = 0x11
+ sysIPV6_MULTICAST_HOPS = 0x12
+ sysIPV6_MULTICAST_LOOP = 0x13
+ sysIPV6_ADD_MEMBERSHIP = 0x14
+ sysIPV6_DROP_MEMBERSHIP = 0x15
+ sysMCAST_JOIN_GROUP = 0x2a
+ sysMCAST_LEAVE_GROUP = 0x2d
+ sysMCAST_JOIN_SOURCE_GROUP = 0x2e
+ sysMCAST_LEAVE_SOURCE_GROUP = 0x2f
+ sysMCAST_BLOCK_SOURCE = 0x2b
+ sysMCAST_UNBLOCK_SOURCE = 0x2c
+ sysMCAST_MSFILTER = 0x30
+ sysIPV6_ROUTER_ALERT = 0x16
+ sysIPV6_MTU_DISCOVER = 0x17
+ sysIPV6_MTU = 0x18
+ sysIPV6_RECVERR = 0x19
+ sysIPV6_V6ONLY = 0x1a
+ sysIPV6_JOIN_ANYCAST = 0x1b
+ sysIPV6_LEAVE_ANYCAST = 0x1c
+
+ sysIPV6_FLOWLABEL_MGR = 0x20
+ sysIPV6_FLOWINFO_SEND = 0x21
+
+ sysIPV6_IPSEC_POLICY = 0x22
+ sysIPV6_XFRM_POLICY = 0x23
+
+ sysIPV6_RECVPKTINFO = 0x31
+ sysIPV6_PKTINFO = 0x32
+ sysIPV6_RECVHOPLIMIT = 0x33
+ sysIPV6_HOPLIMIT = 0x34
+ sysIPV6_RECVHOPOPTS = 0x35
+ sysIPV6_HOPOPTS = 0x36
+ sysIPV6_RTHDRDSTOPTS = 0x37
+ sysIPV6_RECVRTHDR = 0x38
+ sysIPV6_RTHDR = 0x39
+ sysIPV6_RECVDSTOPTS = 0x3a
+ sysIPV6_DSTOPTS = 0x3b
+ sysIPV6_RECVPATHMTU = 0x3c
+ sysIPV6_PATHMTU = 0x3d
+ sysIPV6_DONTFRAG = 0x3e
+
+ sysIPV6_RECVTCLASS = 0x42
+ sysIPV6_TCLASS = 0x43
+
+ sysIPV6_ADDR_PREFERENCES = 0x48
+
+ sysIPV6_PREFER_SRC_TMP = 0x1
+ sysIPV6_PREFER_SRC_PUBLIC = 0x2
+ sysIPV6_PREFER_SRC_PUBTMP_DEFAULT = 0x100
+ sysIPV6_PREFER_SRC_COA = 0x4
+ sysIPV6_PREFER_SRC_HOME = 0x400
+ sysIPV6_PREFER_SRC_CGA = 0x8
+ sysIPV6_PREFER_SRC_NONCGA = 0x800
+
+ sysIPV6_MINHOPCOUNT = 0x49
+
+ sysIPV6_ORIGDSTADDR = 0x4a
+ sysIPV6_RECVORIGDSTADDR = 0x4a
+ sysIPV6_TRANSPARENT = 0x4b
+ sysIPV6_UNICAST_IF = 0x4c
+
+ sysICMPV6_FILTER = 0x1
+
+ sysICMPV6_FILTER_BLOCK = 0x1
+ sysICMPV6_FILTER_PASS = 0x2
+ sysICMPV6_FILTER_BLOCKOTHERS = 0x3
+ sysICMPV6_FILTER_PASSONLY = 0x4
+
+ sysSOL_SOCKET = 0x1
+ sysSO_ATTACH_FILTER = 0x1a
+
+ sizeofKernelSockaddrStorage = 0x80
+ sizeofSockaddrInet6 = 0x1c
+ sizeofInet6Pktinfo = 0x14
+ sizeofIPv6Mtuinfo = 0x20
+ sizeofIPv6FlowlabelReq = 0x20
+
+ sizeofIPv6Mreq = 0x14
+ sizeofGroupReq = 0x88
+ sizeofGroupSourceReq = 0x108
+
+ sizeofICMPv6Filter = 0x20
+
+ sizeofSockFprog = 0x10
+)
+
+type kernelSockaddrStorage struct {
+ Family uint16
+ X__data [126]int8
+}
+
+type sockaddrInet6 struct {
+ Family uint16
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+type inet6Pktinfo struct {
+ Addr [16]byte /* in6_addr */
+ Ifindex int32
+}
+
+type ipv6Mtuinfo struct {
+ Addr sockaddrInet6
+ Mtu uint32
+}
+
+type ipv6FlowlabelReq struct {
+ Dst [16]byte /* in6_addr */
+ Label uint32
+ Action uint8
+ Share uint8
+ Flags uint16
+ Expires uint16
+ Linger uint16
+ X__flr_pad uint32
+}
+
+type ipv6Mreq struct {
+ Multiaddr [16]byte /* in6_addr */
+ Ifindex int32
+}
+
+type groupReq struct {
+ Interface uint32
+ Pad_cgo_0 [4]byte
+ Group kernelSockaddrStorage
+}
+
+type groupSourceReq struct {
+ Interface uint32
+ Pad_cgo_0 [4]byte
+ Group kernelSockaddrStorage
+ Source kernelSockaddrStorage
+}
+
+type icmpv6Filter struct {
+ Data [8]uint32
+}
+
+type sockFProg struct {
+ Len uint16
+ Pad_cgo_0 [6]byte
+ Filter *sockFilter
+}
+
+type sockFilter struct {
+ Code uint16
+ Jt uint8
+ Jf uint8
+ K uint32
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_linux_arm.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_linux_arm.go
new file mode 100644
index 000000000..73aa8c6df
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_linux_arm.go
@@ -0,0 +1,170 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_linux.go
+
+package ipv6
+
+const (
+ sysIPV6_ADDRFORM = 0x1
+ sysIPV6_2292PKTINFO = 0x2
+ sysIPV6_2292HOPOPTS = 0x3
+ sysIPV6_2292DSTOPTS = 0x4
+ sysIPV6_2292RTHDR = 0x5
+ sysIPV6_2292PKTOPTIONS = 0x6
+ sysIPV6_CHECKSUM = 0x7
+ sysIPV6_2292HOPLIMIT = 0x8
+ sysIPV6_NEXTHOP = 0x9
+ sysIPV6_FLOWINFO = 0xb
+
+ sysIPV6_UNICAST_HOPS = 0x10
+ sysIPV6_MULTICAST_IF = 0x11
+ sysIPV6_MULTICAST_HOPS = 0x12
+ sysIPV6_MULTICAST_LOOP = 0x13
+ sysIPV6_ADD_MEMBERSHIP = 0x14
+ sysIPV6_DROP_MEMBERSHIP = 0x15
+ sysMCAST_JOIN_GROUP = 0x2a
+ sysMCAST_LEAVE_GROUP = 0x2d
+ sysMCAST_JOIN_SOURCE_GROUP = 0x2e
+ sysMCAST_LEAVE_SOURCE_GROUP = 0x2f
+ sysMCAST_BLOCK_SOURCE = 0x2b
+ sysMCAST_UNBLOCK_SOURCE = 0x2c
+ sysMCAST_MSFILTER = 0x30
+ sysIPV6_ROUTER_ALERT = 0x16
+ sysIPV6_MTU_DISCOVER = 0x17
+ sysIPV6_MTU = 0x18
+ sysIPV6_RECVERR = 0x19
+ sysIPV6_V6ONLY = 0x1a
+ sysIPV6_JOIN_ANYCAST = 0x1b
+ sysIPV6_LEAVE_ANYCAST = 0x1c
+
+ sysIPV6_FLOWLABEL_MGR = 0x20
+ sysIPV6_FLOWINFO_SEND = 0x21
+
+ sysIPV6_IPSEC_POLICY = 0x22
+ sysIPV6_XFRM_POLICY = 0x23
+
+ sysIPV6_RECVPKTINFO = 0x31
+ sysIPV6_PKTINFO = 0x32
+ sysIPV6_RECVHOPLIMIT = 0x33
+ sysIPV6_HOPLIMIT = 0x34
+ sysIPV6_RECVHOPOPTS = 0x35
+ sysIPV6_HOPOPTS = 0x36
+ sysIPV6_RTHDRDSTOPTS = 0x37
+ sysIPV6_RECVRTHDR = 0x38
+ sysIPV6_RTHDR = 0x39
+ sysIPV6_RECVDSTOPTS = 0x3a
+ sysIPV6_DSTOPTS = 0x3b
+ sysIPV6_RECVPATHMTU = 0x3c
+ sysIPV6_PATHMTU = 0x3d
+ sysIPV6_DONTFRAG = 0x3e
+
+ sysIPV6_RECVTCLASS = 0x42
+ sysIPV6_TCLASS = 0x43
+
+ sysIPV6_ADDR_PREFERENCES = 0x48
+
+ sysIPV6_PREFER_SRC_TMP = 0x1
+ sysIPV6_PREFER_SRC_PUBLIC = 0x2
+ sysIPV6_PREFER_SRC_PUBTMP_DEFAULT = 0x100
+ sysIPV6_PREFER_SRC_COA = 0x4
+ sysIPV6_PREFER_SRC_HOME = 0x400
+ sysIPV6_PREFER_SRC_CGA = 0x8
+ sysIPV6_PREFER_SRC_NONCGA = 0x800
+
+ sysIPV6_MINHOPCOUNT = 0x49
+
+ sysIPV6_ORIGDSTADDR = 0x4a
+ sysIPV6_RECVORIGDSTADDR = 0x4a
+ sysIPV6_TRANSPARENT = 0x4b
+ sysIPV6_UNICAST_IF = 0x4c
+
+ sysICMPV6_FILTER = 0x1
+
+ sysICMPV6_FILTER_BLOCK = 0x1
+ sysICMPV6_FILTER_PASS = 0x2
+ sysICMPV6_FILTER_BLOCKOTHERS = 0x3
+ sysICMPV6_FILTER_PASSONLY = 0x4
+
+ sysSOL_SOCKET = 0x1
+ sysSO_ATTACH_FILTER = 0x1a
+
+ sizeofKernelSockaddrStorage = 0x80
+ sizeofSockaddrInet6 = 0x1c
+ sizeofInet6Pktinfo = 0x14
+ sizeofIPv6Mtuinfo = 0x20
+ sizeofIPv6FlowlabelReq = 0x20
+
+ sizeofIPv6Mreq = 0x14
+ sizeofGroupReq = 0x84
+ sizeofGroupSourceReq = 0x104
+
+ sizeofICMPv6Filter = 0x20
+
+ sizeofSockFprog = 0x8
+)
+
+type kernelSockaddrStorage struct {
+ Family uint16
+ X__data [126]int8
+}
+
+type sockaddrInet6 struct {
+ Family uint16
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+type inet6Pktinfo struct {
+ Addr [16]byte /* in6_addr */
+ Ifindex int32
+}
+
+type ipv6Mtuinfo struct {
+ Addr sockaddrInet6
+ Mtu uint32
+}
+
+type ipv6FlowlabelReq struct {
+ Dst [16]byte /* in6_addr */
+ Label uint32
+ Action uint8
+ Share uint8
+ Flags uint16
+ Expires uint16
+ Linger uint16
+ X__flr_pad uint32
+}
+
+type ipv6Mreq struct {
+ Multiaddr [16]byte /* in6_addr */
+ Ifindex int32
+}
+
+type groupReq struct {
+ Interface uint32
+ Group kernelSockaddrStorage
+}
+
+type groupSourceReq struct {
+ Interface uint32
+ Group kernelSockaddrStorage
+ Source kernelSockaddrStorage
+}
+
+type icmpv6Filter struct {
+ Data [8]uint32
+}
+
+type sockFProg struct {
+ Len uint16
+ Pad_cgo_0 [2]byte
+ Filter *sockFilter
+}
+
+type sockFilter struct {
+ Code uint16
+ Jt uint8
+ Jf uint8
+ K uint32
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_linux_arm64.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_linux_arm64.go
new file mode 100644
index 000000000..b64f0157d
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_linux_arm64.go
@@ -0,0 +1,172 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_linux.go
+
+package ipv6
+
+const (
+ sysIPV6_ADDRFORM = 0x1
+ sysIPV6_2292PKTINFO = 0x2
+ sysIPV6_2292HOPOPTS = 0x3
+ sysIPV6_2292DSTOPTS = 0x4
+ sysIPV6_2292RTHDR = 0x5
+ sysIPV6_2292PKTOPTIONS = 0x6
+ sysIPV6_CHECKSUM = 0x7
+ sysIPV6_2292HOPLIMIT = 0x8
+ sysIPV6_NEXTHOP = 0x9
+ sysIPV6_FLOWINFO = 0xb
+
+ sysIPV6_UNICAST_HOPS = 0x10
+ sysIPV6_MULTICAST_IF = 0x11
+ sysIPV6_MULTICAST_HOPS = 0x12
+ sysIPV6_MULTICAST_LOOP = 0x13
+ sysIPV6_ADD_MEMBERSHIP = 0x14
+ sysIPV6_DROP_MEMBERSHIP = 0x15
+ sysMCAST_JOIN_GROUP = 0x2a
+ sysMCAST_LEAVE_GROUP = 0x2d
+ sysMCAST_JOIN_SOURCE_GROUP = 0x2e
+ sysMCAST_LEAVE_SOURCE_GROUP = 0x2f
+ sysMCAST_BLOCK_SOURCE = 0x2b
+ sysMCAST_UNBLOCK_SOURCE = 0x2c
+ sysMCAST_MSFILTER = 0x30
+ sysIPV6_ROUTER_ALERT = 0x16
+ sysIPV6_MTU_DISCOVER = 0x17
+ sysIPV6_MTU = 0x18
+ sysIPV6_RECVERR = 0x19
+ sysIPV6_V6ONLY = 0x1a
+ sysIPV6_JOIN_ANYCAST = 0x1b
+ sysIPV6_LEAVE_ANYCAST = 0x1c
+
+ sysIPV6_FLOWLABEL_MGR = 0x20
+ sysIPV6_FLOWINFO_SEND = 0x21
+
+ sysIPV6_IPSEC_POLICY = 0x22
+ sysIPV6_XFRM_POLICY = 0x23
+
+ sysIPV6_RECVPKTINFO = 0x31
+ sysIPV6_PKTINFO = 0x32
+ sysIPV6_RECVHOPLIMIT = 0x33
+ sysIPV6_HOPLIMIT = 0x34
+ sysIPV6_RECVHOPOPTS = 0x35
+ sysIPV6_HOPOPTS = 0x36
+ sysIPV6_RTHDRDSTOPTS = 0x37
+ sysIPV6_RECVRTHDR = 0x38
+ sysIPV6_RTHDR = 0x39
+ sysIPV6_RECVDSTOPTS = 0x3a
+ sysIPV6_DSTOPTS = 0x3b
+ sysIPV6_RECVPATHMTU = 0x3c
+ sysIPV6_PATHMTU = 0x3d
+ sysIPV6_DONTFRAG = 0x3e
+
+ sysIPV6_RECVTCLASS = 0x42
+ sysIPV6_TCLASS = 0x43
+
+ sysIPV6_ADDR_PREFERENCES = 0x48
+
+ sysIPV6_PREFER_SRC_TMP = 0x1
+ sysIPV6_PREFER_SRC_PUBLIC = 0x2
+ sysIPV6_PREFER_SRC_PUBTMP_DEFAULT = 0x100
+ sysIPV6_PREFER_SRC_COA = 0x4
+ sysIPV6_PREFER_SRC_HOME = 0x400
+ sysIPV6_PREFER_SRC_CGA = 0x8
+ sysIPV6_PREFER_SRC_NONCGA = 0x800
+
+ sysIPV6_MINHOPCOUNT = 0x49
+
+ sysIPV6_ORIGDSTADDR = 0x4a
+ sysIPV6_RECVORIGDSTADDR = 0x4a
+ sysIPV6_TRANSPARENT = 0x4b
+ sysIPV6_UNICAST_IF = 0x4c
+
+ sysICMPV6_FILTER = 0x1
+
+ sysICMPV6_FILTER_BLOCK = 0x1
+ sysICMPV6_FILTER_PASS = 0x2
+ sysICMPV6_FILTER_BLOCKOTHERS = 0x3
+ sysICMPV6_FILTER_PASSONLY = 0x4
+
+ sysSOL_SOCKET = 0x1
+ sysSO_ATTACH_FILTER = 0x1a
+
+ sizeofKernelSockaddrStorage = 0x80
+ sizeofSockaddrInet6 = 0x1c
+ sizeofInet6Pktinfo = 0x14
+ sizeofIPv6Mtuinfo = 0x20
+ sizeofIPv6FlowlabelReq = 0x20
+
+ sizeofIPv6Mreq = 0x14
+ sizeofGroupReq = 0x88
+ sizeofGroupSourceReq = 0x108
+
+ sizeofICMPv6Filter = 0x20
+
+ sizeofSockFprog = 0x10
+)
+
+type kernelSockaddrStorage struct {
+ Family uint16
+ X__data [126]int8
+}
+
+type sockaddrInet6 struct {
+ Family uint16
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+type inet6Pktinfo struct {
+ Addr [16]byte /* in6_addr */
+ Ifindex int32
+}
+
+type ipv6Mtuinfo struct {
+ Addr sockaddrInet6
+ Mtu uint32
+}
+
+type ipv6FlowlabelReq struct {
+ Dst [16]byte /* in6_addr */
+ Label uint32
+ Action uint8
+ Share uint8
+ Flags uint16
+ Expires uint16
+ Linger uint16
+ X__flr_pad uint32
+}
+
+type ipv6Mreq struct {
+ Multiaddr [16]byte /* in6_addr */
+ Ifindex int32
+}
+
+type groupReq struct {
+ Interface uint32
+ Pad_cgo_0 [4]byte
+ Group kernelSockaddrStorage
+}
+
+type groupSourceReq struct {
+ Interface uint32
+ Pad_cgo_0 [4]byte
+ Group kernelSockaddrStorage
+ Source kernelSockaddrStorage
+}
+
+type icmpv6Filter struct {
+ Data [8]uint32
+}
+
+type sockFProg struct {
+ Len uint16
+ Pad_cgo_0 [6]byte
+ Filter *sockFilter
+}
+
+type sockFilter struct {
+ Code uint16
+ Jt uint8
+ Jf uint8
+ K uint32
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_linux_mips.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_linux_mips.go
new file mode 100644
index 000000000..73aa8c6df
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_linux_mips.go
@@ -0,0 +1,170 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_linux.go
+
+package ipv6
+
+const (
+ sysIPV6_ADDRFORM = 0x1
+ sysIPV6_2292PKTINFO = 0x2
+ sysIPV6_2292HOPOPTS = 0x3
+ sysIPV6_2292DSTOPTS = 0x4
+ sysIPV6_2292RTHDR = 0x5
+ sysIPV6_2292PKTOPTIONS = 0x6
+ sysIPV6_CHECKSUM = 0x7
+ sysIPV6_2292HOPLIMIT = 0x8
+ sysIPV6_NEXTHOP = 0x9
+ sysIPV6_FLOWINFO = 0xb
+
+ sysIPV6_UNICAST_HOPS = 0x10
+ sysIPV6_MULTICAST_IF = 0x11
+ sysIPV6_MULTICAST_HOPS = 0x12
+ sysIPV6_MULTICAST_LOOP = 0x13
+ sysIPV6_ADD_MEMBERSHIP = 0x14
+ sysIPV6_DROP_MEMBERSHIP = 0x15
+ sysMCAST_JOIN_GROUP = 0x2a
+ sysMCAST_LEAVE_GROUP = 0x2d
+ sysMCAST_JOIN_SOURCE_GROUP = 0x2e
+ sysMCAST_LEAVE_SOURCE_GROUP = 0x2f
+ sysMCAST_BLOCK_SOURCE = 0x2b
+ sysMCAST_UNBLOCK_SOURCE = 0x2c
+ sysMCAST_MSFILTER = 0x30
+ sysIPV6_ROUTER_ALERT = 0x16
+ sysIPV6_MTU_DISCOVER = 0x17
+ sysIPV6_MTU = 0x18
+ sysIPV6_RECVERR = 0x19
+ sysIPV6_V6ONLY = 0x1a
+ sysIPV6_JOIN_ANYCAST = 0x1b
+ sysIPV6_LEAVE_ANYCAST = 0x1c
+
+ sysIPV6_FLOWLABEL_MGR = 0x20
+ sysIPV6_FLOWINFO_SEND = 0x21
+
+ sysIPV6_IPSEC_POLICY = 0x22
+ sysIPV6_XFRM_POLICY = 0x23
+
+ sysIPV6_RECVPKTINFO = 0x31
+ sysIPV6_PKTINFO = 0x32
+ sysIPV6_RECVHOPLIMIT = 0x33
+ sysIPV6_HOPLIMIT = 0x34
+ sysIPV6_RECVHOPOPTS = 0x35
+ sysIPV6_HOPOPTS = 0x36
+ sysIPV6_RTHDRDSTOPTS = 0x37
+ sysIPV6_RECVRTHDR = 0x38
+ sysIPV6_RTHDR = 0x39
+ sysIPV6_RECVDSTOPTS = 0x3a
+ sysIPV6_DSTOPTS = 0x3b
+ sysIPV6_RECVPATHMTU = 0x3c
+ sysIPV6_PATHMTU = 0x3d
+ sysIPV6_DONTFRAG = 0x3e
+
+ sysIPV6_RECVTCLASS = 0x42
+ sysIPV6_TCLASS = 0x43
+
+ sysIPV6_ADDR_PREFERENCES = 0x48
+
+ sysIPV6_PREFER_SRC_TMP = 0x1
+ sysIPV6_PREFER_SRC_PUBLIC = 0x2
+ sysIPV6_PREFER_SRC_PUBTMP_DEFAULT = 0x100
+ sysIPV6_PREFER_SRC_COA = 0x4
+ sysIPV6_PREFER_SRC_HOME = 0x400
+ sysIPV6_PREFER_SRC_CGA = 0x8
+ sysIPV6_PREFER_SRC_NONCGA = 0x800
+
+ sysIPV6_MINHOPCOUNT = 0x49
+
+ sysIPV6_ORIGDSTADDR = 0x4a
+ sysIPV6_RECVORIGDSTADDR = 0x4a
+ sysIPV6_TRANSPARENT = 0x4b
+ sysIPV6_UNICAST_IF = 0x4c
+
+ sysICMPV6_FILTER = 0x1
+
+ sysICMPV6_FILTER_BLOCK = 0x1
+ sysICMPV6_FILTER_PASS = 0x2
+ sysICMPV6_FILTER_BLOCKOTHERS = 0x3
+ sysICMPV6_FILTER_PASSONLY = 0x4
+
+ sysSOL_SOCKET = 0x1
+ sysSO_ATTACH_FILTER = 0x1a
+
+ sizeofKernelSockaddrStorage = 0x80
+ sizeofSockaddrInet6 = 0x1c
+ sizeofInet6Pktinfo = 0x14
+ sizeofIPv6Mtuinfo = 0x20
+ sizeofIPv6FlowlabelReq = 0x20
+
+ sizeofIPv6Mreq = 0x14
+ sizeofGroupReq = 0x84
+ sizeofGroupSourceReq = 0x104
+
+ sizeofICMPv6Filter = 0x20
+
+ sizeofSockFprog = 0x8
+)
+
+type kernelSockaddrStorage struct {
+ Family uint16
+ X__data [126]int8
+}
+
+type sockaddrInet6 struct {
+ Family uint16
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+type inet6Pktinfo struct {
+ Addr [16]byte /* in6_addr */
+ Ifindex int32
+}
+
+type ipv6Mtuinfo struct {
+ Addr sockaddrInet6
+ Mtu uint32
+}
+
+type ipv6FlowlabelReq struct {
+ Dst [16]byte /* in6_addr */
+ Label uint32
+ Action uint8
+ Share uint8
+ Flags uint16
+ Expires uint16
+ Linger uint16
+ X__flr_pad uint32
+}
+
+type ipv6Mreq struct {
+ Multiaddr [16]byte /* in6_addr */
+ Ifindex int32
+}
+
+type groupReq struct {
+ Interface uint32
+ Group kernelSockaddrStorage
+}
+
+type groupSourceReq struct {
+ Interface uint32
+ Group kernelSockaddrStorage
+ Source kernelSockaddrStorage
+}
+
+type icmpv6Filter struct {
+ Data [8]uint32
+}
+
+type sockFProg struct {
+ Len uint16
+ Pad_cgo_0 [2]byte
+ Filter *sockFilter
+}
+
+type sockFilter struct {
+ Code uint16
+ Jt uint8
+ Jf uint8
+ K uint32
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_linux_mips64.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_linux_mips64.go
new file mode 100644
index 000000000..b64f0157d
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_linux_mips64.go
@@ -0,0 +1,172 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_linux.go
+
+package ipv6
+
+const (
+ sysIPV6_ADDRFORM = 0x1
+ sysIPV6_2292PKTINFO = 0x2
+ sysIPV6_2292HOPOPTS = 0x3
+ sysIPV6_2292DSTOPTS = 0x4
+ sysIPV6_2292RTHDR = 0x5
+ sysIPV6_2292PKTOPTIONS = 0x6
+ sysIPV6_CHECKSUM = 0x7
+ sysIPV6_2292HOPLIMIT = 0x8
+ sysIPV6_NEXTHOP = 0x9
+ sysIPV6_FLOWINFO = 0xb
+
+ sysIPV6_UNICAST_HOPS = 0x10
+ sysIPV6_MULTICAST_IF = 0x11
+ sysIPV6_MULTICAST_HOPS = 0x12
+ sysIPV6_MULTICAST_LOOP = 0x13
+ sysIPV6_ADD_MEMBERSHIP = 0x14
+ sysIPV6_DROP_MEMBERSHIP = 0x15
+ sysMCAST_JOIN_GROUP = 0x2a
+ sysMCAST_LEAVE_GROUP = 0x2d
+ sysMCAST_JOIN_SOURCE_GROUP = 0x2e
+ sysMCAST_LEAVE_SOURCE_GROUP = 0x2f
+ sysMCAST_BLOCK_SOURCE = 0x2b
+ sysMCAST_UNBLOCK_SOURCE = 0x2c
+ sysMCAST_MSFILTER = 0x30
+ sysIPV6_ROUTER_ALERT = 0x16
+ sysIPV6_MTU_DISCOVER = 0x17
+ sysIPV6_MTU = 0x18
+ sysIPV6_RECVERR = 0x19
+ sysIPV6_V6ONLY = 0x1a
+ sysIPV6_JOIN_ANYCAST = 0x1b
+ sysIPV6_LEAVE_ANYCAST = 0x1c
+
+ sysIPV6_FLOWLABEL_MGR = 0x20
+ sysIPV6_FLOWINFO_SEND = 0x21
+
+ sysIPV6_IPSEC_POLICY = 0x22
+ sysIPV6_XFRM_POLICY = 0x23
+
+ sysIPV6_RECVPKTINFO = 0x31
+ sysIPV6_PKTINFO = 0x32
+ sysIPV6_RECVHOPLIMIT = 0x33
+ sysIPV6_HOPLIMIT = 0x34
+ sysIPV6_RECVHOPOPTS = 0x35
+ sysIPV6_HOPOPTS = 0x36
+ sysIPV6_RTHDRDSTOPTS = 0x37
+ sysIPV6_RECVRTHDR = 0x38
+ sysIPV6_RTHDR = 0x39
+ sysIPV6_RECVDSTOPTS = 0x3a
+ sysIPV6_DSTOPTS = 0x3b
+ sysIPV6_RECVPATHMTU = 0x3c
+ sysIPV6_PATHMTU = 0x3d
+ sysIPV6_DONTFRAG = 0x3e
+
+ sysIPV6_RECVTCLASS = 0x42
+ sysIPV6_TCLASS = 0x43
+
+ sysIPV6_ADDR_PREFERENCES = 0x48
+
+ sysIPV6_PREFER_SRC_TMP = 0x1
+ sysIPV6_PREFER_SRC_PUBLIC = 0x2
+ sysIPV6_PREFER_SRC_PUBTMP_DEFAULT = 0x100
+ sysIPV6_PREFER_SRC_COA = 0x4
+ sysIPV6_PREFER_SRC_HOME = 0x400
+ sysIPV6_PREFER_SRC_CGA = 0x8
+ sysIPV6_PREFER_SRC_NONCGA = 0x800
+
+ sysIPV6_MINHOPCOUNT = 0x49
+
+ sysIPV6_ORIGDSTADDR = 0x4a
+ sysIPV6_RECVORIGDSTADDR = 0x4a
+ sysIPV6_TRANSPARENT = 0x4b
+ sysIPV6_UNICAST_IF = 0x4c
+
+ sysICMPV6_FILTER = 0x1
+
+ sysICMPV6_FILTER_BLOCK = 0x1
+ sysICMPV6_FILTER_PASS = 0x2
+ sysICMPV6_FILTER_BLOCKOTHERS = 0x3
+ sysICMPV6_FILTER_PASSONLY = 0x4
+
+ sysSOL_SOCKET = 0x1
+ sysSO_ATTACH_FILTER = 0x1a
+
+ sizeofKernelSockaddrStorage = 0x80
+ sizeofSockaddrInet6 = 0x1c
+ sizeofInet6Pktinfo = 0x14
+ sizeofIPv6Mtuinfo = 0x20
+ sizeofIPv6FlowlabelReq = 0x20
+
+ sizeofIPv6Mreq = 0x14
+ sizeofGroupReq = 0x88
+ sizeofGroupSourceReq = 0x108
+
+ sizeofICMPv6Filter = 0x20
+
+ sizeofSockFprog = 0x10
+)
+
+type kernelSockaddrStorage struct {
+ Family uint16
+ X__data [126]int8
+}
+
+type sockaddrInet6 struct {
+ Family uint16
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+type inet6Pktinfo struct {
+ Addr [16]byte /* in6_addr */
+ Ifindex int32
+}
+
+type ipv6Mtuinfo struct {
+ Addr sockaddrInet6
+ Mtu uint32
+}
+
+type ipv6FlowlabelReq struct {
+ Dst [16]byte /* in6_addr */
+ Label uint32
+ Action uint8
+ Share uint8
+ Flags uint16
+ Expires uint16
+ Linger uint16
+ X__flr_pad uint32
+}
+
+type ipv6Mreq struct {
+ Multiaddr [16]byte /* in6_addr */
+ Ifindex int32
+}
+
+type groupReq struct {
+ Interface uint32
+ Pad_cgo_0 [4]byte
+ Group kernelSockaddrStorage
+}
+
+type groupSourceReq struct {
+ Interface uint32
+ Pad_cgo_0 [4]byte
+ Group kernelSockaddrStorage
+ Source kernelSockaddrStorage
+}
+
+type icmpv6Filter struct {
+ Data [8]uint32
+}
+
+type sockFProg struct {
+ Len uint16
+ Pad_cgo_0 [6]byte
+ Filter *sockFilter
+}
+
+type sockFilter struct {
+ Code uint16
+ Jt uint8
+ Jf uint8
+ K uint32
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_linux_mips64le.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_linux_mips64le.go
new file mode 100644
index 000000000..b64f0157d
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_linux_mips64le.go
@@ -0,0 +1,172 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_linux.go
+
+package ipv6
+
+const (
+ sysIPV6_ADDRFORM = 0x1
+ sysIPV6_2292PKTINFO = 0x2
+ sysIPV6_2292HOPOPTS = 0x3
+ sysIPV6_2292DSTOPTS = 0x4
+ sysIPV6_2292RTHDR = 0x5
+ sysIPV6_2292PKTOPTIONS = 0x6
+ sysIPV6_CHECKSUM = 0x7
+ sysIPV6_2292HOPLIMIT = 0x8
+ sysIPV6_NEXTHOP = 0x9
+ sysIPV6_FLOWINFO = 0xb
+
+ sysIPV6_UNICAST_HOPS = 0x10
+ sysIPV6_MULTICAST_IF = 0x11
+ sysIPV6_MULTICAST_HOPS = 0x12
+ sysIPV6_MULTICAST_LOOP = 0x13
+ sysIPV6_ADD_MEMBERSHIP = 0x14
+ sysIPV6_DROP_MEMBERSHIP = 0x15
+ sysMCAST_JOIN_GROUP = 0x2a
+ sysMCAST_LEAVE_GROUP = 0x2d
+ sysMCAST_JOIN_SOURCE_GROUP = 0x2e
+ sysMCAST_LEAVE_SOURCE_GROUP = 0x2f
+ sysMCAST_BLOCK_SOURCE = 0x2b
+ sysMCAST_UNBLOCK_SOURCE = 0x2c
+ sysMCAST_MSFILTER = 0x30
+ sysIPV6_ROUTER_ALERT = 0x16
+ sysIPV6_MTU_DISCOVER = 0x17
+ sysIPV6_MTU = 0x18
+ sysIPV6_RECVERR = 0x19
+ sysIPV6_V6ONLY = 0x1a
+ sysIPV6_JOIN_ANYCAST = 0x1b
+ sysIPV6_LEAVE_ANYCAST = 0x1c
+
+ sysIPV6_FLOWLABEL_MGR = 0x20
+ sysIPV6_FLOWINFO_SEND = 0x21
+
+ sysIPV6_IPSEC_POLICY = 0x22
+ sysIPV6_XFRM_POLICY = 0x23
+
+ sysIPV6_RECVPKTINFO = 0x31
+ sysIPV6_PKTINFO = 0x32
+ sysIPV6_RECVHOPLIMIT = 0x33
+ sysIPV6_HOPLIMIT = 0x34
+ sysIPV6_RECVHOPOPTS = 0x35
+ sysIPV6_HOPOPTS = 0x36
+ sysIPV6_RTHDRDSTOPTS = 0x37
+ sysIPV6_RECVRTHDR = 0x38
+ sysIPV6_RTHDR = 0x39
+ sysIPV6_RECVDSTOPTS = 0x3a
+ sysIPV6_DSTOPTS = 0x3b
+ sysIPV6_RECVPATHMTU = 0x3c
+ sysIPV6_PATHMTU = 0x3d
+ sysIPV6_DONTFRAG = 0x3e
+
+ sysIPV6_RECVTCLASS = 0x42
+ sysIPV6_TCLASS = 0x43
+
+ sysIPV6_ADDR_PREFERENCES = 0x48
+
+ sysIPV6_PREFER_SRC_TMP = 0x1
+ sysIPV6_PREFER_SRC_PUBLIC = 0x2
+ sysIPV6_PREFER_SRC_PUBTMP_DEFAULT = 0x100
+ sysIPV6_PREFER_SRC_COA = 0x4
+ sysIPV6_PREFER_SRC_HOME = 0x400
+ sysIPV6_PREFER_SRC_CGA = 0x8
+ sysIPV6_PREFER_SRC_NONCGA = 0x800
+
+ sysIPV6_MINHOPCOUNT = 0x49
+
+ sysIPV6_ORIGDSTADDR = 0x4a
+ sysIPV6_RECVORIGDSTADDR = 0x4a
+ sysIPV6_TRANSPARENT = 0x4b
+ sysIPV6_UNICAST_IF = 0x4c
+
+ sysICMPV6_FILTER = 0x1
+
+ sysICMPV6_FILTER_BLOCK = 0x1
+ sysICMPV6_FILTER_PASS = 0x2
+ sysICMPV6_FILTER_BLOCKOTHERS = 0x3
+ sysICMPV6_FILTER_PASSONLY = 0x4
+
+ sysSOL_SOCKET = 0x1
+ sysSO_ATTACH_FILTER = 0x1a
+
+ sizeofKernelSockaddrStorage = 0x80
+ sizeofSockaddrInet6 = 0x1c
+ sizeofInet6Pktinfo = 0x14
+ sizeofIPv6Mtuinfo = 0x20
+ sizeofIPv6FlowlabelReq = 0x20
+
+ sizeofIPv6Mreq = 0x14
+ sizeofGroupReq = 0x88
+ sizeofGroupSourceReq = 0x108
+
+ sizeofICMPv6Filter = 0x20
+
+ sizeofSockFprog = 0x10
+)
+
+type kernelSockaddrStorage struct {
+ Family uint16
+ X__data [126]int8
+}
+
+type sockaddrInet6 struct {
+ Family uint16
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+type inet6Pktinfo struct {
+ Addr [16]byte /* in6_addr */
+ Ifindex int32
+}
+
+type ipv6Mtuinfo struct {
+ Addr sockaddrInet6
+ Mtu uint32
+}
+
+type ipv6FlowlabelReq struct {
+ Dst [16]byte /* in6_addr */
+ Label uint32
+ Action uint8
+ Share uint8
+ Flags uint16
+ Expires uint16
+ Linger uint16
+ X__flr_pad uint32
+}
+
+type ipv6Mreq struct {
+ Multiaddr [16]byte /* in6_addr */
+ Ifindex int32
+}
+
+type groupReq struct {
+ Interface uint32
+ Pad_cgo_0 [4]byte
+ Group kernelSockaddrStorage
+}
+
+type groupSourceReq struct {
+ Interface uint32
+ Pad_cgo_0 [4]byte
+ Group kernelSockaddrStorage
+ Source kernelSockaddrStorage
+}
+
+type icmpv6Filter struct {
+ Data [8]uint32
+}
+
+type sockFProg struct {
+ Len uint16
+ Pad_cgo_0 [6]byte
+ Filter *sockFilter
+}
+
+type sockFilter struct {
+ Code uint16
+ Jt uint8
+ Jf uint8
+ K uint32
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_linux_mipsle.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_linux_mipsle.go
new file mode 100644
index 000000000..73aa8c6df
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_linux_mipsle.go
@@ -0,0 +1,170 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_linux.go
+
+package ipv6
+
+const (
+ sysIPV6_ADDRFORM = 0x1
+ sysIPV6_2292PKTINFO = 0x2
+ sysIPV6_2292HOPOPTS = 0x3
+ sysIPV6_2292DSTOPTS = 0x4
+ sysIPV6_2292RTHDR = 0x5
+ sysIPV6_2292PKTOPTIONS = 0x6
+ sysIPV6_CHECKSUM = 0x7
+ sysIPV6_2292HOPLIMIT = 0x8
+ sysIPV6_NEXTHOP = 0x9
+ sysIPV6_FLOWINFO = 0xb
+
+ sysIPV6_UNICAST_HOPS = 0x10
+ sysIPV6_MULTICAST_IF = 0x11
+ sysIPV6_MULTICAST_HOPS = 0x12
+ sysIPV6_MULTICAST_LOOP = 0x13
+ sysIPV6_ADD_MEMBERSHIP = 0x14
+ sysIPV6_DROP_MEMBERSHIP = 0x15
+ sysMCAST_JOIN_GROUP = 0x2a
+ sysMCAST_LEAVE_GROUP = 0x2d
+ sysMCAST_JOIN_SOURCE_GROUP = 0x2e
+ sysMCAST_LEAVE_SOURCE_GROUP = 0x2f
+ sysMCAST_BLOCK_SOURCE = 0x2b
+ sysMCAST_UNBLOCK_SOURCE = 0x2c
+ sysMCAST_MSFILTER = 0x30
+ sysIPV6_ROUTER_ALERT = 0x16
+ sysIPV6_MTU_DISCOVER = 0x17
+ sysIPV6_MTU = 0x18
+ sysIPV6_RECVERR = 0x19
+ sysIPV6_V6ONLY = 0x1a
+ sysIPV6_JOIN_ANYCAST = 0x1b
+ sysIPV6_LEAVE_ANYCAST = 0x1c
+
+ sysIPV6_FLOWLABEL_MGR = 0x20
+ sysIPV6_FLOWINFO_SEND = 0x21
+
+ sysIPV6_IPSEC_POLICY = 0x22
+ sysIPV6_XFRM_POLICY = 0x23
+
+ sysIPV6_RECVPKTINFO = 0x31
+ sysIPV6_PKTINFO = 0x32
+ sysIPV6_RECVHOPLIMIT = 0x33
+ sysIPV6_HOPLIMIT = 0x34
+ sysIPV6_RECVHOPOPTS = 0x35
+ sysIPV6_HOPOPTS = 0x36
+ sysIPV6_RTHDRDSTOPTS = 0x37
+ sysIPV6_RECVRTHDR = 0x38
+ sysIPV6_RTHDR = 0x39
+ sysIPV6_RECVDSTOPTS = 0x3a
+ sysIPV6_DSTOPTS = 0x3b
+ sysIPV6_RECVPATHMTU = 0x3c
+ sysIPV6_PATHMTU = 0x3d
+ sysIPV6_DONTFRAG = 0x3e
+
+ sysIPV6_RECVTCLASS = 0x42
+ sysIPV6_TCLASS = 0x43
+
+ sysIPV6_ADDR_PREFERENCES = 0x48
+
+ sysIPV6_PREFER_SRC_TMP = 0x1
+ sysIPV6_PREFER_SRC_PUBLIC = 0x2
+ sysIPV6_PREFER_SRC_PUBTMP_DEFAULT = 0x100
+ sysIPV6_PREFER_SRC_COA = 0x4
+ sysIPV6_PREFER_SRC_HOME = 0x400
+ sysIPV6_PREFER_SRC_CGA = 0x8
+ sysIPV6_PREFER_SRC_NONCGA = 0x800
+
+ sysIPV6_MINHOPCOUNT = 0x49
+
+ sysIPV6_ORIGDSTADDR = 0x4a
+ sysIPV6_RECVORIGDSTADDR = 0x4a
+ sysIPV6_TRANSPARENT = 0x4b
+ sysIPV6_UNICAST_IF = 0x4c
+
+ sysICMPV6_FILTER = 0x1
+
+ sysICMPV6_FILTER_BLOCK = 0x1
+ sysICMPV6_FILTER_PASS = 0x2
+ sysICMPV6_FILTER_BLOCKOTHERS = 0x3
+ sysICMPV6_FILTER_PASSONLY = 0x4
+
+ sysSOL_SOCKET = 0x1
+ sysSO_ATTACH_FILTER = 0x1a
+
+ sizeofKernelSockaddrStorage = 0x80
+ sizeofSockaddrInet6 = 0x1c
+ sizeofInet6Pktinfo = 0x14
+ sizeofIPv6Mtuinfo = 0x20
+ sizeofIPv6FlowlabelReq = 0x20
+
+ sizeofIPv6Mreq = 0x14
+ sizeofGroupReq = 0x84
+ sizeofGroupSourceReq = 0x104
+
+ sizeofICMPv6Filter = 0x20
+
+ sizeofSockFprog = 0x8
+)
+
+type kernelSockaddrStorage struct {
+ Family uint16
+ X__data [126]int8
+}
+
+type sockaddrInet6 struct {
+ Family uint16
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+type inet6Pktinfo struct {
+ Addr [16]byte /* in6_addr */
+ Ifindex int32
+}
+
+type ipv6Mtuinfo struct {
+ Addr sockaddrInet6
+ Mtu uint32
+}
+
+type ipv6FlowlabelReq struct {
+ Dst [16]byte /* in6_addr */
+ Label uint32
+ Action uint8
+ Share uint8
+ Flags uint16
+ Expires uint16
+ Linger uint16
+ X__flr_pad uint32
+}
+
+type ipv6Mreq struct {
+ Multiaddr [16]byte /* in6_addr */
+ Ifindex int32
+}
+
+type groupReq struct {
+ Interface uint32
+ Group kernelSockaddrStorage
+}
+
+type groupSourceReq struct {
+ Interface uint32
+ Group kernelSockaddrStorage
+ Source kernelSockaddrStorage
+}
+
+type icmpv6Filter struct {
+ Data [8]uint32
+}
+
+type sockFProg struct {
+ Len uint16
+ Pad_cgo_0 [2]byte
+ Filter *sockFilter
+}
+
+type sockFilter struct {
+ Code uint16
+ Jt uint8
+ Jf uint8
+ K uint32
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_linux_ppc.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_linux_ppc.go
new file mode 100644
index 000000000..c9bf6a87e
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_linux_ppc.go
@@ -0,0 +1,170 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_linux.go
+
+package ipv6
+
+const (
+ sysIPV6_ADDRFORM = 0x1
+ sysIPV6_2292PKTINFO = 0x2
+ sysIPV6_2292HOPOPTS = 0x3
+ sysIPV6_2292DSTOPTS = 0x4
+ sysIPV6_2292RTHDR = 0x5
+ sysIPV6_2292PKTOPTIONS = 0x6
+ sysIPV6_CHECKSUM = 0x7
+ sysIPV6_2292HOPLIMIT = 0x8
+ sysIPV6_NEXTHOP = 0x9
+ sysIPV6_FLOWINFO = 0xb
+
+ sysIPV6_UNICAST_HOPS = 0x10
+ sysIPV6_MULTICAST_IF = 0x11
+ sysIPV6_MULTICAST_HOPS = 0x12
+ sysIPV6_MULTICAST_LOOP = 0x13
+ sysIPV6_ADD_MEMBERSHIP = 0x14
+ sysIPV6_DROP_MEMBERSHIP = 0x15
+ sysMCAST_JOIN_GROUP = 0x2a
+ sysMCAST_LEAVE_GROUP = 0x2d
+ sysMCAST_JOIN_SOURCE_GROUP = 0x2e
+ sysMCAST_LEAVE_SOURCE_GROUP = 0x2f
+ sysMCAST_BLOCK_SOURCE = 0x2b
+ sysMCAST_UNBLOCK_SOURCE = 0x2c
+ sysMCAST_MSFILTER = 0x30
+ sysIPV6_ROUTER_ALERT = 0x16
+ sysIPV6_MTU_DISCOVER = 0x17
+ sysIPV6_MTU = 0x18
+ sysIPV6_RECVERR = 0x19
+ sysIPV6_V6ONLY = 0x1a
+ sysIPV6_JOIN_ANYCAST = 0x1b
+ sysIPV6_LEAVE_ANYCAST = 0x1c
+
+ sysIPV6_FLOWLABEL_MGR = 0x20
+ sysIPV6_FLOWINFO_SEND = 0x21
+
+ sysIPV6_IPSEC_POLICY = 0x22
+ sysIPV6_XFRM_POLICY = 0x23
+
+ sysIPV6_RECVPKTINFO = 0x31
+ sysIPV6_PKTINFO = 0x32
+ sysIPV6_RECVHOPLIMIT = 0x33
+ sysIPV6_HOPLIMIT = 0x34
+ sysIPV6_RECVHOPOPTS = 0x35
+ sysIPV6_HOPOPTS = 0x36
+ sysIPV6_RTHDRDSTOPTS = 0x37
+ sysIPV6_RECVRTHDR = 0x38
+ sysIPV6_RTHDR = 0x39
+ sysIPV6_RECVDSTOPTS = 0x3a
+ sysIPV6_DSTOPTS = 0x3b
+ sysIPV6_RECVPATHMTU = 0x3c
+ sysIPV6_PATHMTU = 0x3d
+ sysIPV6_DONTFRAG = 0x3e
+
+ sysIPV6_RECVTCLASS = 0x42
+ sysIPV6_TCLASS = 0x43
+
+ sysIPV6_ADDR_PREFERENCES = 0x48
+
+ sysIPV6_PREFER_SRC_TMP = 0x1
+ sysIPV6_PREFER_SRC_PUBLIC = 0x2
+ sysIPV6_PREFER_SRC_PUBTMP_DEFAULT = 0x100
+ sysIPV6_PREFER_SRC_COA = 0x4
+ sysIPV6_PREFER_SRC_HOME = 0x400
+ sysIPV6_PREFER_SRC_CGA = 0x8
+ sysIPV6_PREFER_SRC_NONCGA = 0x800
+
+ sysIPV6_MINHOPCOUNT = 0x49
+
+ sysIPV6_ORIGDSTADDR = 0x4a
+ sysIPV6_RECVORIGDSTADDR = 0x4a
+ sysIPV6_TRANSPARENT = 0x4b
+ sysIPV6_UNICAST_IF = 0x4c
+
+ sysICMPV6_FILTER = 0x1
+
+ sysICMPV6_FILTER_BLOCK = 0x1
+ sysICMPV6_FILTER_PASS = 0x2
+ sysICMPV6_FILTER_BLOCKOTHERS = 0x3
+ sysICMPV6_FILTER_PASSONLY = 0x4
+
+ sysSOL_SOCKET = 0x1
+ sysSO_ATTACH_FILTER = 0x1a
+
+ sizeofKernelSockaddrStorage = 0x80
+ sizeofSockaddrInet6 = 0x1c
+ sizeofInet6Pktinfo = 0x14
+ sizeofIPv6Mtuinfo = 0x20
+ sizeofIPv6FlowlabelReq = 0x20
+
+ sizeofIPv6Mreq = 0x14
+ sizeofGroupReq = 0x84
+ sizeofGroupSourceReq = 0x104
+
+ sizeofICMPv6Filter = 0x20
+
+ sizeofSockFprog = 0x8
+)
+
+type kernelSockaddrStorage struct {
+ Family uint16
+ X__data [126]uint8
+}
+
+type sockaddrInet6 struct {
+ Family uint16
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+type inet6Pktinfo struct {
+ Addr [16]byte /* in6_addr */
+ Ifindex int32
+}
+
+type ipv6Mtuinfo struct {
+ Addr sockaddrInet6
+ Mtu uint32
+}
+
+type ipv6FlowlabelReq struct {
+ Dst [16]byte /* in6_addr */
+ Label uint32
+ Action uint8
+ Share uint8
+ Flags uint16
+ Expires uint16
+ Linger uint16
+ X__flr_pad uint32
+}
+
+type ipv6Mreq struct {
+ Multiaddr [16]byte /* in6_addr */
+ Ifindex int32
+}
+
+type groupReq struct {
+ Interface uint32
+ Group kernelSockaddrStorage
+}
+
+type groupSourceReq struct {
+ Interface uint32
+ Group kernelSockaddrStorage
+ Source kernelSockaddrStorage
+}
+
+type icmpv6Filter struct {
+ Data [8]uint32
+}
+
+type sockFProg struct {
+ Len uint16
+ Pad_cgo_0 [2]byte
+ Filter *sockFilter
+}
+
+type sockFilter struct {
+ Code uint16
+ Jt uint8
+ Jf uint8
+ K uint32
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_linux_ppc64.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_linux_ppc64.go
new file mode 100644
index 000000000..b64f0157d
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_linux_ppc64.go
@@ -0,0 +1,172 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_linux.go
+
+package ipv6
+
+const (
+ sysIPV6_ADDRFORM = 0x1
+ sysIPV6_2292PKTINFO = 0x2
+ sysIPV6_2292HOPOPTS = 0x3
+ sysIPV6_2292DSTOPTS = 0x4
+ sysIPV6_2292RTHDR = 0x5
+ sysIPV6_2292PKTOPTIONS = 0x6
+ sysIPV6_CHECKSUM = 0x7
+ sysIPV6_2292HOPLIMIT = 0x8
+ sysIPV6_NEXTHOP = 0x9
+ sysIPV6_FLOWINFO = 0xb
+
+ sysIPV6_UNICAST_HOPS = 0x10
+ sysIPV6_MULTICAST_IF = 0x11
+ sysIPV6_MULTICAST_HOPS = 0x12
+ sysIPV6_MULTICAST_LOOP = 0x13
+ sysIPV6_ADD_MEMBERSHIP = 0x14
+ sysIPV6_DROP_MEMBERSHIP = 0x15
+ sysMCAST_JOIN_GROUP = 0x2a
+ sysMCAST_LEAVE_GROUP = 0x2d
+ sysMCAST_JOIN_SOURCE_GROUP = 0x2e
+ sysMCAST_LEAVE_SOURCE_GROUP = 0x2f
+ sysMCAST_BLOCK_SOURCE = 0x2b
+ sysMCAST_UNBLOCK_SOURCE = 0x2c
+ sysMCAST_MSFILTER = 0x30
+ sysIPV6_ROUTER_ALERT = 0x16
+ sysIPV6_MTU_DISCOVER = 0x17
+ sysIPV6_MTU = 0x18
+ sysIPV6_RECVERR = 0x19
+ sysIPV6_V6ONLY = 0x1a
+ sysIPV6_JOIN_ANYCAST = 0x1b
+ sysIPV6_LEAVE_ANYCAST = 0x1c
+
+ sysIPV6_FLOWLABEL_MGR = 0x20
+ sysIPV6_FLOWINFO_SEND = 0x21
+
+ sysIPV6_IPSEC_POLICY = 0x22
+ sysIPV6_XFRM_POLICY = 0x23
+
+ sysIPV6_RECVPKTINFO = 0x31
+ sysIPV6_PKTINFO = 0x32
+ sysIPV6_RECVHOPLIMIT = 0x33
+ sysIPV6_HOPLIMIT = 0x34
+ sysIPV6_RECVHOPOPTS = 0x35
+ sysIPV6_HOPOPTS = 0x36
+ sysIPV6_RTHDRDSTOPTS = 0x37
+ sysIPV6_RECVRTHDR = 0x38
+ sysIPV6_RTHDR = 0x39
+ sysIPV6_RECVDSTOPTS = 0x3a
+ sysIPV6_DSTOPTS = 0x3b
+ sysIPV6_RECVPATHMTU = 0x3c
+ sysIPV6_PATHMTU = 0x3d
+ sysIPV6_DONTFRAG = 0x3e
+
+ sysIPV6_RECVTCLASS = 0x42
+ sysIPV6_TCLASS = 0x43
+
+ sysIPV6_ADDR_PREFERENCES = 0x48
+
+ sysIPV6_PREFER_SRC_TMP = 0x1
+ sysIPV6_PREFER_SRC_PUBLIC = 0x2
+ sysIPV6_PREFER_SRC_PUBTMP_DEFAULT = 0x100
+ sysIPV6_PREFER_SRC_COA = 0x4
+ sysIPV6_PREFER_SRC_HOME = 0x400
+ sysIPV6_PREFER_SRC_CGA = 0x8
+ sysIPV6_PREFER_SRC_NONCGA = 0x800
+
+ sysIPV6_MINHOPCOUNT = 0x49
+
+ sysIPV6_ORIGDSTADDR = 0x4a
+ sysIPV6_RECVORIGDSTADDR = 0x4a
+ sysIPV6_TRANSPARENT = 0x4b
+ sysIPV6_UNICAST_IF = 0x4c
+
+ sysICMPV6_FILTER = 0x1
+
+ sysICMPV6_FILTER_BLOCK = 0x1
+ sysICMPV6_FILTER_PASS = 0x2
+ sysICMPV6_FILTER_BLOCKOTHERS = 0x3
+ sysICMPV6_FILTER_PASSONLY = 0x4
+
+ sysSOL_SOCKET = 0x1
+ sysSO_ATTACH_FILTER = 0x1a
+
+ sizeofKernelSockaddrStorage = 0x80
+ sizeofSockaddrInet6 = 0x1c
+ sizeofInet6Pktinfo = 0x14
+ sizeofIPv6Mtuinfo = 0x20
+ sizeofIPv6FlowlabelReq = 0x20
+
+ sizeofIPv6Mreq = 0x14
+ sizeofGroupReq = 0x88
+ sizeofGroupSourceReq = 0x108
+
+ sizeofICMPv6Filter = 0x20
+
+ sizeofSockFprog = 0x10
+)
+
+type kernelSockaddrStorage struct {
+ Family uint16
+ X__data [126]int8
+}
+
+type sockaddrInet6 struct {
+ Family uint16
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+type inet6Pktinfo struct {
+ Addr [16]byte /* in6_addr */
+ Ifindex int32
+}
+
+type ipv6Mtuinfo struct {
+ Addr sockaddrInet6
+ Mtu uint32
+}
+
+type ipv6FlowlabelReq struct {
+ Dst [16]byte /* in6_addr */
+ Label uint32
+ Action uint8
+ Share uint8
+ Flags uint16
+ Expires uint16
+ Linger uint16
+ X__flr_pad uint32
+}
+
+type ipv6Mreq struct {
+ Multiaddr [16]byte /* in6_addr */
+ Ifindex int32
+}
+
+type groupReq struct {
+ Interface uint32
+ Pad_cgo_0 [4]byte
+ Group kernelSockaddrStorage
+}
+
+type groupSourceReq struct {
+ Interface uint32
+ Pad_cgo_0 [4]byte
+ Group kernelSockaddrStorage
+ Source kernelSockaddrStorage
+}
+
+type icmpv6Filter struct {
+ Data [8]uint32
+}
+
+type sockFProg struct {
+ Len uint16
+ Pad_cgo_0 [6]byte
+ Filter *sockFilter
+}
+
+type sockFilter struct {
+ Code uint16
+ Jt uint8
+ Jf uint8
+ K uint32
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_linux_ppc64le.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_linux_ppc64le.go
new file mode 100644
index 000000000..b64f0157d
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_linux_ppc64le.go
@@ -0,0 +1,172 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_linux.go
+
+package ipv6
+
+const (
+ sysIPV6_ADDRFORM = 0x1
+ sysIPV6_2292PKTINFO = 0x2
+ sysIPV6_2292HOPOPTS = 0x3
+ sysIPV6_2292DSTOPTS = 0x4
+ sysIPV6_2292RTHDR = 0x5
+ sysIPV6_2292PKTOPTIONS = 0x6
+ sysIPV6_CHECKSUM = 0x7
+ sysIPV6_2292HOPLIMIT = 0x8
+ sysIPV6_NEXTHOP = 0x9
+ sysIPV6_FLOWINFO = 0xb
+
+ sysIPV6_UNICAST_HOPS = 0x10
+ sysIPV6_MULTICAST_IF = 0x11
+ sysIPV6_MULTICAST_HOPS = 0x12
+ sysIPV6_MULTICAST_LOOP = 0x13
+ sysIPV6_ADD_MEMBERSHIP = 0x14
+ sysIPV6_DROP_MEMBERSHIP = 0x15
+ sysMCAST_JOIN_GROUP = 0x2a
+ sysMCAST_LEAVE_GROUP = 0x2d
+ sysMCAST_JOIN_SOURCE_GROUP = 0x2e
+ sysMCAST_LEAVE_SOURCE_GROUP = 0x2f
+ sysMCAST_BLOCK_SOURCE = 0x2b
+ sysMCAST_UNBLOCK_SOURCE = 0x2c
+ sysMCAST_MSFILTER = 0x30
+ sysIPV6_ROUTER_ALERT = 0x16
+ sysIPV6_MTU_DISCOVER = 0x17
+ sysIPV6_MTU = 0x18
+ sysIPV6_RECVERR = 0x19
+ sysIPV6_V6ONLY = 0x1a
+ sysIPV6_JOIN_ANYCAST = 0x1b
+ sysIPV6_LEAVE_ANYCAST = 0x1c
+
+ sysIPV6_FLOWLABEL_MGR = 0x20
+ sysIPV6_FLOWINFO_SEND = 0x21
+
+ sysIPV6_IPSEC_POLICY = 0x22
+ sysIPV6_XFRM_POLICY = 0x23
+
+ sysIPV6_RECVPKTINFO = 0x31
+ sysIPV6_PKTINFO = 0x32
+ sysIPV6_RECVHOPLIMIT = 0x33
+ sysIPV6_HOPLIMIT = 0x34
+ sysIPV6_RECVHOPOPTS = 0x35
+ sysIPV6_HOPOPTS = 0x36
+ sysIPV6_RTHDRDSTOPTS = 0x37
+ sysIPV6_RECVRTHDR = 0x38
+ sysIPV6_RTHDR = 0x39
+ sysIPV6_RECVDSTOPTS = 0x3a
+ sysIPV6_DSTOPTS = 0x3b
+ sysIPV6_RECVPATHMTU = 0x3c
+ sysIPV6_PATHMTU = 0x3d
+ sysIPV6_DONTFRAG = 0x3e
+
+ sysIPV6_RECVTCLASS = 0x42
+ sysIPV6_TCLASS = 0x43
+
+ sysIPV6_ADDR_PREFERENCES = 0x48
+
+ sysIPV6_PREFER_SRC_TMP = 0x1
+ sysIPV6_PREFER_SRC_PUBLIC = 0x2
+ sysIPV6_PREFER_SRC_PUBTMP_DEFAULT = 0x100
+ sysIPV6_PREFER_SRC_COA = 0x4
+ sysIPV6_PREFER_SRC_HOME = 0x400
+ sysIPV6_PREFER_SRC_CGA = 0x8
+ sysIPV6_PREFER_SRC_NONCGA = 0x800
+
+ sysIPV6_MINHOPCOUNT = 0x49
+
+ sysIPV6_ORIGDSTADDR = 0x4a
+ sysIPV6_RECVORIGDSTADDR = 0x4a
+ sysIPV6_TRANSPARENT = 0x4b
+ sysIPV6_UNICAST_IF = 0x4c
+
+ sysICMPV6_FILTER = 0x1
+
+ sysICMPV6_FILTER_BLOCK = 0x1
+ sysICMPV6_FILTER_PASS = 0x2
+ sysICMPV6_FILTER_BLOCKOTHERS = 0x3
+ sysICMPV6_FILTER_PASSONLY = 0x4
+
+ sysSOL_SOCKET = 0x1
+ sysSO_ATTACH_FILTER = 0x1a
+
+ sizeofKernelSockaddrStorage = 0x80
+ sizeofSockaddrInet6 = 0x1c
+ sizeofInet6Pktinfo = 0x14
+ sizeofIPv6Mtuinfo = 0x20
+ sizeofIPv6FlowlabelReq = 0x20
+
+ sizeofIPv6Mreq = 0x14
+ sizeofGroupReq = 0x88
+ sizeofGroupSourceReq = 0x108
+
+ sizeofICMPv6Filter = 0x20
+
+ sizeofSockFprog = 0x10
+)
+
+type kernelSockaddrStorage struct {
+ Family uint16
+ X__data [126]int8
+}
+
+type sockaddrInet6 struct {
+ Family uint16
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+type inet6Pktinfo struct {
+ Addr [16]byte /* in6_addr */
+ Ifindex int32
+}
+
+type ipv6Mtuinfo struct {
+ Addr sockaddrInet6
+ Mtu uint32
+}
+
+type ipv6FlowlabelReq struct {
+ Dst [16]byte /* in6_addr */
+ Label uint32
+ Action uint8
+ Share uint8
+ Flags uint16
+ Expires uint16
+ Linger uint16
+ X__flr_pad uint32
+}
+
+type ipv6Mreq struct {
+ Multiaddr [16]byte /* in6_addr */
+ Ifindex int32
+}
+
+type groupReq struct {
+ Interface uint32
+ Pad_cgo_0 [4]byte
+ Group kernelSockaddrStorage
+}
+
+type groupSourceReq struct {
+ Interface uint32
+ Pad_cgo_0 [4]byte
+ Group kernelSockaddrStorage
+ Source kernelSockaddrStorage
+}
+
+type icmpv6Filter struct {
+ Data [8]uint32
+}
+
+type sockFProg struct {
+ Len uint16
+ Pad_cgo_0 [6]byte
+ Filter *sockFilter
+}
+
+type sockFilter struct {
+ Code uint16
+ Jt uint8
+ Jf uint8
+ K uint32
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_linux_s390x.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_linux_s390x.go
new file mode 100644
index 000000000..b64f0157d
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_linux_s390x.go
@@ -0,0 +1,172 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_linux.go
+
+package ipv6
+
+const (
+ sysIPV6_ADDRFORM = 0x1
+ sysIPV6_2292PKTINFO = 0x2
+ sysIPV6_2292HOPOPTS = 0x3
+ sysIPV6_2292DSTOPTS = 0x4
+ sysIPV6_2292RTHDR = 0x5
+ sysIPV6_2292PKTOPTIONS = 0x6
+ sysIPV6_CHECKSUM = 0x7
+ sysIPV6_2292HOPLIMIT = 0x8
+ sysIPV6_NEXTHOP = 0x9
+ sysIPV6_FLOWINFO = 0xb
+
+ sysIPV6_UNICAST_HOPS = 0x10
+ sysIPV6_MULTICAST_IF = 0x11
+ sysIPV6_MULTICAST_HOPS = 0x12
+ sysIPV6_MULTICAST_LOOP = 0x13
+ sysIPV6_ADD_MEMBERSHIP = 0x14
+ sysIPV6_DROP_MEMBERSHIP = 0x15
+ sysMCAST_JOIN_GROUP = 0x2a
+ sysMCAST_LEAVE_GROUP = 0x2d
+ sysMCAST_JOIN_SOURCE_GROUP = 0x2e
+ sysMCAST_LEAVE_SOURCE_GROUP = 0x2f
+ sysMCAST_BLOCK_SOURCE = 0x2b
+ sysMCAST_UNBLOCK_SOURCE = 0x2c
+ sysMCAST_MSFILTER = 0x30
+ sysIPV6_ROUTER_ALERT = 0x16
+ sysIPV6_MTU_DISCOVER = 0x17
+ sysIPV6_MTU = 0x18
+ sysIPV6_RECVERR = 0x19
+ sysIPV6_V6ONLY = 0x1a
+ sysIPV6_JOIN_ANYCAST = 0x1b
+ sysIPV6_LEAVE_ANYCAST = 0x1c
+
+ sysIPV6_FLOWLABEL_MGR = 0x20
+ sysIPV6_FLOWINFO_SEND = 0x21
+
+ sysIPV6_IPSEC_POLICY = 0x22
+ sysIPV6_XFRM_POLICY = 0x23
+
+ sysIPV6_RECVPKTINFO = 0x31
+ sysIPV6_PKTINFO = 0x32
+ sysIPV6_RECVHOPLIMIT = 0x33
+ sysIPV6_HOPLIMIT = 0x34
+ sysIPV6_RECVHOPOPTS = 0x35
+ sysIPV6_HOPOPTS = 0x36
+ sysIPV6_RTHDRDSTOPTS = 0x37
+ sysIPV6_RECVRTHDR = 0x38
+ sysIPV6_RTHDR = 0x39
+ sysIPV6_RECVDSTOPTS = 0x3a
+ sysIPV6_DSTOPTS = 0x3b
+ sysIPV6_RECVPATHMTU = 0x3c
+ sysIPV6_PATHMTU = 0x3d
+ sysIPV6_DONTFRAG = 0x3e
+
+ sysIPV6_RECVTCLASS = 0x42
+ sysIPV6_TCLASS = 0x43
+
+ sysIPV6_ADDR_PREFERENCES = 0x48
+
+ sysIPV6_PREFER_SRC_TMP = 0x1
+ sysIPV6_PREFER_SRC_PUBLIC = 0x2
+ sysIPV6_PREFER_SRC_PUBTMP_DEFAULT = 0x100
+ sysIPV6_PREFER_SRC_COA = 0x4
+ sysIPV6_PREFER_SRC_HOME = 0x400
+ sysIPV6_PREFER_SRC_CGA = 0x8
+ sysIPV6_PREFER_SRC_NONCGA = 0x800
+
+ sysIPV6_MINHOPCOUNT = 0x49
+
+ sysIPV6_ORIGDSTADDR = 0x4a
+ sysIPV6_RECVORIGDSTADDR = 0x4a
+ sysIPV6_TRANSPARENT = 0x4b
+ sysIPV6_UNICAST_IF = 0x4c
+
+ sysICMPV6_FILTER = 0x1
+
+ sysICMPV6_FILTER_BLOCK = 0x1
+ sysICMPV6_FILTER_PASS = 0x2
+ sysICMPV6_FILTER_BLOCKOTHERS = 0x3
+ sysICMPV6_FILTER_PASSONLY = 0x4
+
+ sysSOL_SOCKET = 0x1
+ sysSO_ATTACH_FILTER = 0x1a
+
+ sizeofKernelSockaddrStorage = 0x80
+ sizeofSockaddrInet6 = 0x1c
+ sizeofInet6Pktinfo = 0x14
+ sizeofIPv6Mtuinfo = 0x20
+ sizeofIPv6FlowlabelReq = 0x20
+
+ sizeofIPv6Mreq = 0x14
+ sizeofGroupReq = 0x88
+ sizeofGroupSourceReq = 0x108
+
+ sizeofICMPv6Filter = 0x20
+
+ sizeofSockFprog = 0x10
+)
+
+type kernelSockaddrStorage struct {
+ Family uint16
+ X__data [126]int8
+}
+
+type sockaddrInet6 struct {
+ Family uint16
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+type inet6Pktinfo struct {
+ Addr [16]byte /* in6_addr */
+ Ifindex int32
+}
+
+type ipv6Mtuinfo struct {
+ Addr sockaddrInet6
+ Mtu uint32
+}
+
+type ipv6FlowlabelReq struct {
+ Dst [16]byte /* in6_addr */
+ Label uint32
+ Action uint8
+ Share uint8
+ Flags uint16
+ Expires uint16
+ Linger uint16
+ X__flr_pad uint32
+}
+
+type ipv6Mreq struct {
+ Multiaddr [16]byte /* in6_addr */
+ Ifindex int32
+}
+
+type groupReq struct {
+ Interface uint32
+ Pad_cgo_0 [4]byte
+ Group kernelSockaddrStorage
+}
+
+type groupSourceReq struct {
+ Interface uint32
+ Pad_cgo_0 [4]byte
+ Group kernelSockaddrStorage
+ Source kernelSockaddrStorage
+}
+
+type icmpv6Filter struct {
+ Data [8]uint32
+}
+
+type sockFProg struct {
+ Len uint16
+ Pad_cgo_0 [6]byte
+ Filter *sockFilter
+}
+
+type sockFilter struct {
+ Code uint16
+ Jt uint8
+ Jf uint8
+ K uint32
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_netbsd.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_netbsd.go
new file mode 100644
index 000000000..bcada13b7
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_netbsd.go
@@ -0,0 +1,84 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_netbsd.go
+
+package ipv6
+
+const (
+ sysIPV6_UNICAST_HOPS = 0x4
+ sysIPV6_MULTICAST_IF = 0x9
+ sysIPV6_MULTICAST_HOPS = 0xa
+ sysIPV6_MULTICAST_LOOP = 0xb
+ sysIPV6_JOIN_GROUP = 0xc
+ sysIPV6_LEAVE_GROUP = 0xd
+ sysIPV6_PORTRANGE = 0xe
+ sysICMP6_FILTER = 0x12
+
+ sysIPV6_CHECKSUM = 0x1a
+ sysIPV6_V6ONLY = 0x1b
+
+ sysIPV6_IPSEC_POLICY = 0x1c
+
+ sysIPV6_RTHDRDSTOPTS = 0x23
+
+ sysIPV6_RECVPKTINFO = 0x24
+ sysIPV6_RECVHOPLIMIT = 0x25
+ sysIPV6_RECVRTHDR = 0x26
+ sysIPV6_RECVHOPOPTS = 0x27
+ sysIPV6_RECVDSTOPTS = 0x28
+
+ sysIPV6_USE_MIN_MTU = 0x2a
+ sysIPV6_RECVPATHMTU = 0x2b
+ sysIPV6_PATHMTU = 0x2c
+
+ sysIPV6_PKTINFO = 0x2e
+ sysIPV6_HOPLIMIT = 0x2f
+ sysIPV6_NEXTHOP = 0x30
+ sysIPV6_HOPOPTS = 0x31
+ sysIPV6_DSTOPTS = 0x32
+ sysIPV6_RTHDR = 0x33
+
+ sysIPV6_RECVTCLASS = 0x39
+
+ sysIPV6_TCLASS = 0x3d
+ sysIPV6_DONTFRAG = 0x3e
+
+ sysIPV6_PORTRANGE_DEFAULT = 0x0
+ sysIPV6_PORTRANGE_HIGH = 0x1
+ sysIPV6_PORTRANGE_LOW = 0x2
+
+ sizeofSockaddrInet6 = 0x1c
+ sizeofInet6Pktinfo = 0x14
+ sizeofIPv6Mtuinfo = 0x20
+
+ sizeofIPv6Mreq = 0x14
+
+ sizeofICMPv6Filter = 0x20
+)
+
+type sockaddrInet6 struct {
+ Len uint8
+ Family uint8
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+type inet6Pktinfo struct {
+ Addr [16]byte /* in6_addr */
+ Ifindex uint32
+}
+
+type ipv6Mtuinfo struct {
+ Addr sockaddrInet6
+ Mtu uint32
+}
+
+type ipv6Mreq struct {
+ Multiaddr [16]byte /* in6_addr */
+ Interface uint32
+}
+
+type icmpv6Filter struct {
+ Filt [8]uint32
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_openbsd.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_openbsd.go
new file mode 100644
index 000000000..86cf3c637
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_openbsd.go
@@ -0,0 +1,93 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_openbsd.go
+
+package ipv6
+
+const (
+ sysIPV6_UNICAST_HOPS = 0x4
+ sysIPV6_MULTICAST_IF = 0x9
+ sysIPV6_MULTICAST_HOPS = 0xa
+ sysIPV6_MULTICAST_LOOP = 0xb
+ sysIPV6_JOIN_GROUP = 0xc
+ sysIPV6_LEAVE_GROUP = 0xd
+ sysIPV6_PORTRANGE = 0xe
+ sysICMP6_FILTER = 0x12
+
+ sysIPV6_CHECKSUM = 0x1a
+ sysIPV6_V6ONLY = 0x1b
+
+ sysIPV6_RTHDRDSTOPTS = 0x23
+
+ sysIPV6_RECVPKTINFO = 0x24
+ sysIPV6_RECVHOPLIMIT = 0x25
+ sysIPV6_RECVRTHDR = 0x26
+ sysIPV6_RECVHOPOPTS = 0x27
+ sysIPV6_RECVDSTOPTS = 0x28
+
+ sysIPV6_USE_MIN_MTU = 0x2a
+ sysIPV6_RECVPATHMTU = 0x2b
+
+ sysIPV6_PATHMTU = 0x2c
+
+ sysIPV6_PKTINFO = 0x2e
+ sysIPV6_HOPLIMIT = 0x2f
+ sysIPV6_NEXTHOP = 0x30
+ sysIPV6_HOPOPTS = 0x31
+ sysIPV6_DSTOPTS = 0x32
+ sysIPV6_RTHDR = 0x33
+
+ sysIPV6_AUTH_LEVEL = 0x35
+ sysIPV6_ESP_TRANS_LEVEL = 0x36
+ sysIPV6_ESP_NETWORK_LEVEL = 0x37
+ sysIPSEC6_OUTSA = 0x38
+ sysIPV6_RECVTCLASS = 0x39
+
+ sysIPV6_AUTOFLOWLABEL = 0x3b
+ sysIPV6_IPCOMP_LEVEL = 0x3c
+
+ sysIPV6_TCLASS = 0x3d
+ sysIPV6_DONTFRAG = 0x3e
+ sysIPV6_PIPEX = 0x3f
+
+ sysIPV6_RTABLE = 0x1021
+
+ sysIPV6_PORTRANGE_DEFAULT = 0x0
+ sysIPV6_PORTRANGE_HIGH = 0x1
+ sysIPV6_PORTRANGE_LOW = 0x2
+
+ sizeofSockaddrInet6 = 0x1c
+ sizeofInet6Pktinfo = 0x14
+ sizeofIPv6Mtuinfo = 0x20
+
+ sizeofIPv6Mreq = 0x14
+
+ sizeofICMPv6Filter = 0x20
+)
+
+type sockaddrInet6 struct {
+ Len uint8
+ Family uint8
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+type inet6Pktinfo struct {
+ Addr [16]byte /* in6_addr */
+ Ifindex uint32
+}
+
+type ipv6Mtuinfo struct {
+ Addr sockaddrInet6
+ Mtu uint32
+}
+
+type ipv6Mreq struct {
+ Multiaddr [16]byte /* in6_addr */
+ Interface uint32
+}
+
+type icmpv6Filter struct {
+ Filt [8]uint32
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_solaris.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_solaris.go
new file mode 100644
index 000000000..cf1837dd2
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/ipv6/zsys_solaris.go
@@ -0,0 +1,131 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_solaris.go
+
+package ipv6
+
+const (
+ sysIPV6_UNICAST_HOPS = 0x5
+ sysIPV6_MULTICAST_IF = 0x6
+ sysIPV6_MULTICAST_HOPS = 0x7
+ sysIPV6_MULTICAST_LOOP = 0x8
+ sysIPV6_JOIN_GROUP = 0x9
+ sysIPV6_LEAVE_GROUP = 0xa
+
+ sysIPV6_PKTINFO = 0xb
+
+ sysIPV6_HOPLIMIT = 0xc
+ sysIPV6_NEXTHOP = 0xd
+ sysIPV6_HOPOPTS = 0xe
+ sysIPV6_DSTOPTS = 0xf
+
+ sysIPV6_RTHDR = 0x10
+ sysIPV6_RTHDRDSTOPTS = 0x11
+
+ sysIPV6_RECVPKTINFO = 0x12
+ sysIPV6_RECVHOPLIMIT = 0x13
+ sysIPV6_RECVHOPOPTS = 0x14
+
+ sysIPV6_RECVRTHDR = 0x16
+
+ sysIPV6_RECVRTHDRDSTOPTS = 0x17
+
+ sysIPV6_CHECKSUM = 0x18
+ sysIPV6_RECVTCLASS = 0x19
+ sysIPV6_USE_MIN_MTU = 0x20
+ sysIPV6_DONTFRAG = 0x21
+ sysIPV6_SEC_OPT = 0x22
+ sysIPV6_SRC_PREFERENCES = 0x23
+ sysIPV6_RECVPATHMTU = 0x24
+ sysIPV6_PATHMTU = 0x25
+ sysIPV6_TCLASS = 0x26
+ sysIPV6_V6ONLY = 0x27
+
+ sysIPV6_RECVDSTOPTS = 0x28
+
+ sysMCAST_JOIN_GROUP = 0x29
+ sysMCAST_LEAVE_GROUP = 0x2a
+ sysMCAST_BLOCK_SOURCE = 0x2b
+ sysMCAST_UNBLOCK_SOURCE = 0x2c
+ sysMCAST_JOIN_SOURCE_GROUP = 0x2d
+ sysMCAST_LEAVE_SOURCE_GROUP = 0x2e
+
+ sysIPV6_PREFER_SRC_HOME = 0x1
+ sysIPV6_PREFER_SRC_COA = 0x2
+ sysIPV6_PREFER_SRC_PUBLIC = 0x4
+ sysIPV6_PREFER_SRC_TMP = 0x8
+ sysIPV6_PREFER_SRC_NONCGA = 0x10
+ sysIPV6_PREFER_SRC_CGA = 0x20
+
+ sysIPV6_PREFER_SRC_MIPMASK = 0x3
+ sysIPV6_PREFER_SRC_MIPDEFAULT = 0x1
+ sysIPV6_PREFER_SRC_TMPMASK = 0xc
+ sysIPV6_PREFER_SRC_TMPDEFAULT = 0x4
+ sysIPV6_PREFER_SRC_CGAMASK = 0x30
+ sysIPV6_PREFER_SRC_CGADEFAULT = 0x10
+
+ sysIPV6_PREFER_SRC_MASK = 0x3f
+
+ sysIPV6_PREFER_SRC_DEFAULT = 0x15
+
+ sysIPV6_BOUND_IF = 0x41
+ sysIPV6_UNSPEC_SRC = 0x42
+
+ sysICMP6_FILTER = 0x1
+
+ sizeofSockaddrStorage = 0x100
+ sizeofSockaddrInet6 = 0x20
+ sizeofInet6Pktinfo = 0x14
+ sizeofIPv6Mtuinfo = 0x24
+
+ sizeofIPv6Mreq = 0x14
+ sizeofGroupReq = 0x104
+ sizeofGroupSourceReq = 0x204
+
+ sizeofICMPv6Filter = 0x20
+)
+
+type sockaddrStorage struct {
+ Family uint16
+ X_ss_pad1 [6]int8
+ X_ss_align float64
+ X_ss_pad2 [240]int8
+}
+
+type sockaddrInet6 struct {
+ Family uint16
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+ X__sin6_src_id uint32
+}
+
+type inet6Pktinfo struct {
+ Addr [16]byte /* in6_addr */
+ Ifindex uint32
+}
+
+type ipv6Mtuinfo struct {
+ Addr sockaddrInet6
+ Mtu uint32
+}
+
+type ipv6Mreq struct {
+ Multiaddr [16]byte /* in6_addr */
+ Interface uint32
+}
+
+type groupReq struct {
+ Interface uint32
+ Pad_cgo_0 [256]byte
+}
+
+type groupSourceReq struct {
+ Interface uint32
+ Pad_cgo_0 [256]byte
+ Pad_cgo_1 [256]byte
+}
+
+type icmpv6Filter struct {
+ X__icmp6_filt [8]uint32
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/lex/httplex/httplex.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/lex/httplex/httplex.go
new file mode 100644
index 000000000..20f2b8940
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/lex/httplex/httplex.go
@@ -0,0 +1,351 @@
+// 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.
+
+// Package httplex contains rules around lexical matters of various
+// HTTP-related specifications.
+//
+// This package is shared by the standard library (which vendors it)
+// and x/net/http2. It comes with no API stability promise.
+package httplex
+
+import (
+ "net"
+ "strings"
+ "unicode/utf8"
+
+ "golang.org/x/net/idna"
+)
+
+var isTokenTable = [127]bool{
+ '!': true,
+ '#': true,
+ '$': true,
+ '%': true,
+ '&': true,
+ '\'': true,
+ '*': true,
+ '+': true,
+ '-': true,
+ '.': true,
+ '0': true,
+ '1': true,
+ '2': true,
+ '3': true,
+ '4': true,
+ '5': true,
+ '6': true,
+ '7': true,
+ '8': true,
+ '9': true,
+ 'A': true,
+ 'B': true,
+ 'C': true,
+ 'D': true,
+ 'E': true,
+ 'F': true,
+ 'G': true,
+ 'H': true,
+ 'I': true,
+ 'J': true,
+ 'K': true,
+ 'L': true,
+ 'M': true,
+ 'N': true,
+ 'O': true,
+ 'P': true,
+ 'Q': true,
+ 'R': true,
+ 'S': true,
+ 'T': true,
+ 'U': true,
+ 'W': true,
+ 'V': true,
+ 'X': true,
+ 'Y': true,
+ 'Z': true,
+ '^': true,
+ '_': true,
+ '`': true,
+ 'a': true,
+ 'b': true,
+ 'c': true,
+ 'd': true,
+ 'e': true,
+ 'f': true,
+ 'g': true,
+ 'h': true,
+ 'i': true,
+ 'j': true,
+ 'k': true,
+ 'l': true,
+ 'm': true,
+ 'n': true,
+ 'o': true,
+ 'p': true,
+ 'q': true,
+ 'r': true,
+ 's': true,
+ 't': true,
+ 'u': true,
+ 'v': true,
+ 'w': true,
+ 'x': true,
+ 'y': true,
+ 'z': true,
+ '|': true,
+ '~': true,
+}
+
+func IsTokenRune(r rune) bool {
+ i := int(r)
+ return i < len(isTokenTable) && isTokenTable[i]
+}
+
+func isNotToken(r rune) bool {
+ return !IsTokenRune(r)
+}
+
+// HeaderValuesContainsToken reports whether any string in values
+// contains the provided token, ASCII case-insensitively.
+func HeaderValuesContainsToken(values []string, token string) bool {
+ for _, v := range values {
+ if headerValueContainsToken(v, token) {
+ return true
+ }
+ }
+ return false
+}
+
+// isOWS reports whether b is an optional whitespace byte, as defined
+// by RFC 7230 section 3.2.3.
+func isOWS(b byte) bool { return b == ' ' || b == '\t' }
+
+// trimOWS returns x with all optional whitespace removes from the
+// beginning and end.
+func trimOWS(x string) string {
+ // TODO: consider using strings.Trim(x, " \t") instead,
+ // if and when it's fast enough. See issue 10292.
+ // But this ASCII-only code will probably always beat UTF-8
+ // aware code.
+ for len(x) > 0 && isOWS(x[0]) {
+ x = x[1:]
+ }
+ for len(x) > 0 && isOWS(x[len(x)-1]) {
+ x = x[:len(x)-1]
+ }
+ return x
+}
+
+// headerValueContainsToken reports whether v (assumed to be a
+// 0#element, in the ABNF extension described in RFC 7230 section 7)
+// contains token amongst its comma-separated tokens, ASCII
+// case-insensitively.
+func headerValueContainsToken(v string, token string) bool {
+ v = trimOWS(v)
+ if comma := strings.IndexByte(v, ','); comma != -1 {
+ return tokenEqual(trimOWS(v[:comma]), token) || headerValueContainsToken(v[comma+1:], token)
+ }
+ return tokenEqual(v, token)
+}
+
+// lowerASCII returns the ASCII lowercase version of b.
+func lowerASCII(b byte) byte {
+ if 'A' <= b && b <= 'Z' {
+ return b + ('a' - 'A')
+ }
+ return b
+}
+
+// tokenEqual reports whether t1 and t2 are equal, ASCII case-insensitively.
+func tokenEqual(t1, t2 string) bool {
+ if len(t1) != len(t2) {
+ return false
+ }
+ for i, b := range t1 {
+ if b >= utf8.RuneSelf {
+ // No UTF-8 or non-ASCII allowed in tokens.
+ return false
+ }
+ if lowerASCII(byte(b)) != lowerASCII(t2[i]) {
+ return false
+ }
+ }
+ return true
+}
+
+// isLWS reports whether b is linear white space, according
+// to http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2.2
+// LWS = [CRLF] 1*( SP | HT )
+func isLWS(b byte) bool { return b == ' ' || b == '\t' }
+
+// isCTL reports whether b is a control byte, according
+// to http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2.2
+// CTL = <any US-ASCII control character
+// (octets 0 - 31) and DEL (127)>
+func isCTL(b byte) bool {
+ const del = 0x7f // a CTL
+ return b < ' ' || b == del
+}
+
+// ValidHeaderFieldName reports whether v is a valid HTTP/1.x header name.
+// HTTP/2 imposes the additional restriction that uppercase ASCII
+// letters are not allowed.
+//
+// RFC 7230 says:
+// header-field = field-name ":" OWS field-value OWS
+// field-name = token
+// token = 1*tchar
+// tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." /
+// "^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA
+func ValidHeaderFieldName(v string) bool {
+ if len(v) == 0 {
+ return false
+ }
+ for _, r := range v {
+ if !IsTokenRune(r) {
+ return false
+ }
+ }
+ return true
+}
+
+// ValidHostHeader reports whether h is a valid host header.
+func ValidHostHeader(h string) bool {
+ // The latest spec is actually this:
+ //
+ // http://tools.ietf.org/html/rfc7230#section-5.4
+ // Host = uri-host [ ":" port ]
+ //
+ // Where uri-host is:
+ // http://tools.ietf.org/html/rfc3986#section-3.2.2
+ //
+ // But we're going to be much more lenient for now and just
+ // search for any byte that's not a valid byte in any of those
+ // expressions.
+ for i := 0; i < len(h); i++ {
+ if !validHostByte[h[i]] {
+ return false
+ }
+ }
+ return true
+}
+
+// See the validHostHeader comment.
+var validHostByte = [256]bool{
+ '0': true, '1': true, '2': true, '3': true, '4': true, '5': true, '6': true, '7': true,
+ '8': true, '9': true,
+
+ 'a': true, 'b': true, 'c': true, 'd': true, 'e': true, 'f': true, 'g': true, 'h': true,
+ 'i': true, 'j': true, 'k': true, 'l': true, 'm': true, 'n': true, 'o': true, 'p': true,
+ 'q': true, 'r': true, 's': true, 't': true, 'u': true, 'v': true, 'w': true, 'x': true,
+ 'y': true, 'z': true,
+
+ 'A': true, 'B': true, 'C': true, 'D': true, 'E': true, 'F': true, 'G': true, 'H': true,
+ 'I': true, 'J': true, 'K': true, 'L': true, 'M': true, 'N': true, 'O': true, 'P': true,
+ 'Q': true, 'R': true, 'S': true, 'T': true, 'U': true, 'V': true, 'W': true, 'X': true,
+ 'Y': true, 'Z': true,
+
+ '!': true, // sub-delims
+ '$': true, // sub-delims
+ '%': true, // pct-encoded (and used in IPv6 zones)
+ '&': true, // sub-delims
+ '(': true, // sub-delims
+ ')': true, // sub-delims
+ '*': true, // sub-delims
+ '+': true, // sub-delims
+ ',': true, // sub-delims
+ '-': true, // unreserved
+ '.': true, // unreserved
+ ':': true, // IPv6address + Host expression's optional port
+ ';': true, // sub-delims
+ '=': true, // sub-delims
+ '[': true,
+ '\'': true, // sub-delims
+ ']': true,
+ '_': true, // unreserved
+ '~': true, // unreserved
+}
+
+// ValidHeaderFieldValue reports whether v is a valid "field-value" according to
+// http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2 :
+//
+// message-header = field-name ":" [ field-value ]
+// field-value = *( field-content | LWS )
+// field-content = <the OCTETs making up the field-value
+// and consisting of either *TEXT or combinations
+// of token, separators, and quoted-string>
+//
+// http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2.2 :
+//
+// TEXT = <any OCTET except CTLs,
+// but including LWS>
+// LWS = [CRLF] 1*( SP | HT )
+// CTL = <any US-ASCII control character
+// (octets 0 - 31) and DEL (127)>
+//
+// RFC 7230 says:
+// field-value = *( field-content / obs-fold )
+// obj-fold = N/A to http2, and deprecated
+// field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
+// field-vchar = VCHAR / obs-text
+// obs-text = %x80-FF
+// VCHAR = "any visible [USASCII] character"
+//
+// http2 further says: "Similarly, HTTP/2 allows header field values
+// that are not valid. While most of the values that can be encoded
+// will not alter header field parsing, carriage return (CR, ASCII
+// 0xd), line feed (LF, ASCII 0xa), and the zero character (NUL, ASCII
+// 0x0) might be exploited by an attacker if they are translated
+// verbatim. Any request or response that contains a character not
+// permitted in a header field value MUST be treated as malformed
+// (Section 8.1.2.6). Valid characters are defined by the
+// field-content ABNF rule in Section 3.2 of [RFC7230]."
+//
+// This function does not (yet?) properly handle the rejection of
+// strings that begin or end with SP or HTAB.
+func ValidHeaderFieldValue(v string) bool {
+ for i := 0; i < len(v); i++ {
+ b := v[i]
+ if isCTL(b) && !isLWS(b) {
+ return false
+ }
+ }
+ return true
+}
+
+func isASCII(s string) bool {
+ for i := 0; i < len(s); i++ {
+ if s[i] >= utf8.RuneSelf {
+ return false
+ }
+ }
+ return true
+}
+
+// PunycodeHostPort returns the IDNA Punycode version
+// of the provided "host" or "host:port" string.
+func PunycodeHostPort(v string) (string, error) {
+ if isASCII(v) {
+ return v, nil
+ }
+
+ host, port, err := net.SplitHostPort(v)
+ if err != nil {
+ // The input 'v' argument was just a "host" argument,
+ // without a port. This error should not be returned
+ // to the caller.
+ host = v
+ port = ""
+ }
+ host, err = idna.ToASCII(host)
+ if err != nil {
+ // Non-UTF-8? Not representable in Punycode, in any
+ // case.
+ return "", err
+ }
+ if port == "" {
+ return host, nil
+ }
+ return net.JoinHostPort(host, port), nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/lex/httplex/httplex_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/lex/httplex/httplex_test.go
new file mode 100644
index 000000000..f47adc939
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/lex/httplex/httplex_test.go
@@ -0,0 +1,119 @@
+// Copyright 2009 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 httplex
+
+import (
+ "testing"
+)
+
+func isChar(c rune) bool { return c <= 127 }
+
+func isCtl(c rune) bool { return c <= 31 || c == 127 }
+
+func isSeparator(c rune) bool {
+ switch c {
+ case '(', ')', '<', '>', '@', ',', ';', ':', '\\', '"', '/', '[', ']', '?', '=', '{', '}', ' ', '\t':
+ return true
+ }
+ return false
+}
+
+func TestIsToken(t *testing.T) {
+ for i := 0; i <= 130; i++ {
+ r := rune(i)
+ expected := isChar(r) && !isCtl(r) && !isSeparator(r)
+ if IsTokenRune(r) != expected {
+ t.Errorf("isToken(0x%x) = %v", r, !expected)
+ }
+ }
+}
+
+func TestHeaderValuesContainsToken(t *testing.T) {
+ tests := []struct {
+ vals []string
+ token string
+ want bool
+ }{
+ {
+ vals: []string{"foo"},
+ token: "foo",
+ want: true,
+ },
+ {
+ vals: []string{"bar", "foo"},
+ token: "foo",
+ want: true,
+ },
+ {
+ vals: []string{"foo"},
+ token: "FOO",
+ want: true,
+ },
+ {
+ vals: []string{"foo"},
+ token: "bar",
+ want: false,
+ },
+ {
+ vals: []string{" foo "},
+ token: "FOO",
+ want: true,
+ },
+ {
+ vals: []string{"foo,bar"},
+ token: "FOO",
+ want: true,
+ },
+ {
+ vals: []string{"bar,foo,bar"},
+ token: "FOO",
+ want: true,
+ },
+ {
+ vals: []string{"bar , foo"},
+ token: "FOO",
+ want: true,
+ },
+ {
+ vals: []string{"foo ,bar "},
+ token: "FOO",
+ want: true,
+ },
+ {
+ vals: []string{"bar, foo ,bar"},
+ token: "FOO",
+ want: true,
+ },
+ {
+ vals: []string{"bar , foo"},
+ token: "FOO",
+ want: true,
+ },
+ }
+ for _, tt := range tests {
+ got := HeaderValuesContainsToken(tt.vals, tt.token)
+ if got != tt.want {
+ t.Errorf("headerValuesContainsToken(%q, %q) = %v; want %v", tt.vals, tt.token, got, tt.want)
+ }
+ }
+}
+
+func TestPunycodeHostPort(t *testing.T) {
+ tests := []struct {
+ in, want string
+ }{
+ {"www.google.com", "www.google.com"},
+ {"гофер.рф", "xn--c1ae0ajs.xn--p1ai"},
+ {"bücher.de", "xn--bcher-kva.de"},
+ {"bücher.de:8080", "xn--bcher-kva.de:8080"},
+ {"[1::6]:8080", "[1::6]:8080"},
+ }
+ for _, tt := range tests {
+ got, err := PunycodeHostPort(tt.in)
+ if tt.want != got || err != nil {
+ t.Errorf("PunycodeHostPort(%q) = %q, %v, want %q, nil", tt.in, got, err, tt.want)
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/lif/address.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/lif/address.go
new file mode 100644
index 000000000..afb957fd8
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/lif/address.go
@@ -0,0 +1,105 @@
+// 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.
+
+// +build solaris
+
+package lif
+
+import (
+ "errors"
+ "unsafe"
+)
+
+// An Addr represents an address associated with packet routing.
+type Addr interface {
+ // Family returns an address family.
+ Family() int
+}
+
+// An Inet4Addr represents an internet address for IPv4.
+type Inet4Addr struct {
+ IP [4]byte // IP address
+ PrefixLen int // address prefix length
+}
+
+// Family implements the Family method of Addr interface.
+func (a *Inet4Addr) Family() int { return sysAF_INET }
+
+// An Inet6Addr represents an internet address for IPv6.
+type Inet6Addr struct {
+ IP [16]byte // IP address
+ PrefixLen int // address prefix length
+ ZoneID int // zone identifier
+}
+
+// Family implements the Family method of Addr interface.
+func (a *Inet6Addr) Family() int { return sysAF_INET6 }
+
+// Addrs returns a list of interface addresses.
+//
+// The provided af must be an address family and name must be a data
+// link name. The zero value of af or name means a wildcard.
+func Addrs(af int, name string) ([]Addr, error) {
+ eps, err := newEndpoints(af)
+ if len(eps) == 0 {
+ return nil, err
+ }
+ defer func() {
+ for _, ep := range eps {
+ ep.close()
+ }
+ }()
+ lls, err := links(eps, name)
+ if len(lls) == 0 {
+ return nil, err
+ }
+ var as []Addr
+ for _, ll := range lls {
+ var lifr lifreq
+ for i := 0; i < len(ll.Name); i++ {
+ lifr.Name[i] = int8(ll.Name[i])
+ }
+ for _, ep := range eps {
+ ioc := int64(sysSIOCGLIFADDR)
+ err := ioctl(ep.s, uintptr(ioc), unsafe.Pointer(&lifr))
+ if err != nil {
+ continue
+ }
+ sa := (*sockaddrStorage)(unsafe.Pointer(&lifr.Lifru[0]))
+ l := int(nativeEndian.Uint32(lifr.Lifru1[:4]))
+ if l == 0 {
+ continue
+ }
+ switch sa.Family {
+ case sysAF_INET:
+ a := &Inet4Addr{PrefixLen: l}
+ copy(a.IP[:], lifr.Lifru[4:8])
+ as = append(as, a)
+ case sysAF_INET6:
+ a := &Inet6Addr{PrefixLen: l, ZoneID: int(nativeEndian.Uint32(lifr.Lifru[24:28]))}
+ copy(a.IP[:], lifr.Lifru[8:24])
+ as = append(as, a)
+ }
+ }
+ }
+ return as, nil
+}
+
+func parseLinkAddr(b []byte) ([]byte, error) {
+ nlen, alen, slen := int(b[1]), int(b[2]), int(b[3])
+ l := 4 + nlen + alen + slen
+ if len(b) < l {
+ return nil, errors.New("invalid address")
+ }
+ b = b[4:]
+ var addr []byte
+ if nlen > 0 {
+ b = b[nlen:]
+ }
+ if alen > 0 {
+ addr = make([]byte, alen)
+ copy(addr, b[:alen])
+ }
+ return addr, nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/lif/address_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/lif/address_test.go
new file mode 100644
index 000000000..a25f10b67
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/lif/address_test.go
@@ -0,0 +1,123 @@
+// 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.
+
+// +build solaris
+
+package lif
+
+import (
+ "fmt"
+ "testing"
+)
+
+type addrFamily int
+
+func (af addrFamily) String() string {
+ switch af {
+ case sysAF_UNSPEC:
+ return "unspec"
+ case sysAF_INET:
+ return "inet4"
+ case sysAF_INET6:
+ return "inet6"
+ default:
+ return fmt.Sprintf("%d", af)
+ }
+}
+
+const hexDigit = "0123456789abcdef"
+
+type llAddr []byte
+
+func (a llAddr) String() string {
+ if len(a) == 0 {
+ return ""
+ }
+ buf := make([]byte, 0, len(a)*3-1)
+ for i, b := range a {
+ if i > 0 {
+ buf = append(buf, ':')
+ }
+ buf = append(buf, hexDigit[b>>4])
+ buf = append(buf, hexDigit[b&0xF])
+ }
+ return string(buf)
+}
+
+type ipAddr []byte
+
+func (a ipAddr) String() string {
+ if len(a) == 0 {
+ return "<nil>"
+ }
+ if len(a) == 4 {
+ return fmt.Sprintf("%d.%d.%d.%d", a[0], a[1], a[2], a[3])
+ }
+ if len(a) == 16 {
+ return fmt.Sprintf("%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15])
+ }
+ s := make([]byte, len(a)*2)
+ for i, tn := range a {
+ s[i*2], s[i*2+1] = hexDigit[tn>>4], hexDigit[tn&0xf]
+ }
+ return string(s)
+}
+
+func (a *Inet4Addr) String() string {
+ return fmt.Sprintf("(%s %s %d)", addrFamily(a.Family()), ipAddr(a.IP[:]), a.PrefixLen)
+}
+
+func (a *Inet6Addr) String() string {
+ return fmt.Sprintf("(%s %s %d %d)", addrFamily(a.Family()), ipAddr(a.IP[:]), a.PrefixLen, a.ZoneID)
+}
+
+type addrPack struct {
+ af int
+ as []Addr
+}
+
+func addrPacks() ([]addrPack, error) {
+ var lastErr error
+ var aps []addrPack
+ for _, af := range [...]int{sysAF_UNSPEC, sysAF_INET, sysAF_INET6} {
+ as, err := Addrs(af, "")
+ if err != nil {
+ lastErr = err
+ continue
+ }
+ aps = append(aps, addrPack{af: af, as: as})
+ }
+ return aps, lastErr
+}
+
+func TestAddrs(t *testing.T) {
+ aps, err := addrPacks()
+ if len(aps) == 0 && err != nil {
+ t.Fatal(err)
+ }
+ lps, err := linkPacks()
+ if len(lps) == 0 && err != nil {
+ t.Fatal(err)
+ }
+ for _, lp := range lps {
+ n := 0
+ for _, ll := range lp.lls {
+ as, err := Addrs(lp.af, ll.Name)
+ if err != nil {
+ t.Fatal(lp.af, ll.Name, err)
+ }
+ t.Logf("af=%s name=%s %v", addrFamily(lp.af), ll.Name, as)
+ n += len(as)
+ }
+ for _, ap := range aps {
+ if ap.af != lp.af {
+ continue
+ }
+ if n != len(ap.as) {
+ t.Errorf("af=%s got %d; want %d", addrFamily(lp.af), n, len(ap.as))
+ continue
+ }
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/lif/binary.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/lif/binary.go
new file mode 100644
index 000000000..738a94f42
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/lif/binary.go
@@ -0,0 +1,115 @@
+// 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.
+
+// +build solaris
+
+package lif
+
+// This file contains duplicates of encoding/binary package.
+//
+// This package is supposed to be used by the net package of standard
+// library. Therefore the package set used in the package must be the
+// same as net package.
+
+var (
+ littleEndian binaryLittleEndian
+ bigEndian binaryBigEndian
+)
+
+type binaryByteOrder interface {
+ Uint16([]byte) uint16
+ Uint32([]byte) uint32
+ Uint64([]byte) uint64
+ PutUint16([]byte, uint16)
+ PutUint32([]byte, uint32)
+ PutUint64([]byte, uint64)
+}
+
+type binaryLittleEndian struct{}
+
+func (binaryLittleEndian) Uint16(b []byte) uint16 {
+ _ = b[1] // bounds check hint to compiler; see golang.org/issue/14808
+ return uint16(b[0]) | uint16(b[1])<<8
+}
+
+func (binaryLittleEndian) PutUint16(b []byte, v uint16) {
+ _ = b[1] // early bounds check to guarantee safety of writes below
+ b[0] = byte(v)
+ b[1] = byte(v >> 8)
+}
+
+func (binaryLittleEndian) Uint32(b []byte) uint32 {
+ _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
+ return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
+}
+
+func (binaryLittleEndian) PutUint32(b []byte, v uint32) {
+ _ = b[3] // early bounds check to guarantee safety of writes below
+ b[0] = byte(v)
+ b[1] = byte(v >> 8)
+ b[2] = byte(v >> 16)
+ b[3] = byte(v >> 24)
+}
+
+func (binaryLittleEndian) Uint64(b []byte) uint64 {
+ _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
+ return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
+ uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
+}
+
+func (binaryLittleEndian) PutUint64(b []byte, v uint64) {
+ _ = b[7] // early bounds check to guarantee safety of writes below
+ b[0] = byte(v)
+ b[1] = byte(v >> 8)
+ b[2] = byte(v >> 16)
+ b[3] = byte(v >> 24)
+ b[4] = byte(v >> 32)
+ b[5] = byte(v >> 40)
+ b[6] = byte(v >> 48)
+ b[7] = byte(v >> 56)
+}
+
+type binaryBigEndian struct{}
+
+func (binaryBigEndian) Uint16(b []byte) uint16 {
+ _ = b[1] // bounds check hint to compiler; see golang.org/issue/14808
+ return uint16(b[1]) | uint16(b[0])<<8
+}
+
+func (binaryBigEndian) PutUint16(b []byte, v uint16) {
+ _ = b[1] // early bounds check to guarantee safety of writes below
+ b[0] = byte(v >> 8)
+ b[1] = byte(v)
+}
+
+func (binaryBigEndian) Uint32(b []byte) uint32 {
+ _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
+ return uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24
+}
+
+func (binaryBigEndian) PutUint32(b []byte, v uint32) {
+ _ = b[3] // early bounds check to guarantee safety of writes below
+ b[0] = byte(v >> 24)
+ b[1] = byte(v >> 16)
+ b[2] = byte(v >> 8)
+ b[3] = byte(v)
+}
+
+func (binaryBigEndian) Uint64(b []byte) uint64 {
+ _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
+ return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
+ uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
+}
+
+func (binaryBigEndian) PutUint64(b []byte, v uint64) {
+ _ = b[7] // early bounds check to guarantee safety of writes below
+ b[0] = byte(v >> 56)
+ b[1] = byte(v >> 48)
+ b[2] = byte(v >> 40)
+ b[3] = byte(v >> 32)
+ b[4] = byte(v >> 24)
+ b[5] = byte(v >> 16)
+ b[6] = byte(v >> 8)
+ b[7] = byte(v)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/lif/defs_solaris.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/lif/defs_solaris.go
new file mode 100644
index 000000000..02c19981d
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/lif/defs_solaris.go
@@ -0,0 +1,90 @@
+// 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.
+
+// +build ignore
+
+// +godefs map struct_in_addr [4]byte /* in_addr */
+// +godefs map struct_in6_addr [16]byte /* in6_addr */
+
+package lif
+
+/*
+#include <sys/socket.h>
+#include <sys/sockio.h>
+
+#include <net/if.h>
+#include <net/if_types.h>
+*/
+import "C"
+
+const (
+ sysAF_UNSPEC = C.AF_UNSPEC
+ sysAF_INET = C.AF_INET
+ sysAF_INET6 = C.AF_INET6
+
+ sysSOCK_DGRAM = C.SOCK_DGRAM
+)
+
+type sockaddrStorage C.struct_sockaddr_storage
+
+const (
+ sysLIFC_NOXMIT = C.LIFC_NOXMIT
+ sysLIFC_EXTERNAL_SOURCE = C.LIFC_EXTERNAL_SOURCE
+ sysLIFC_TEMPORARY = C.LIFC_TEMPORARY
+ sysLIFC_ALLZONES = C.LIFC_ALLZONES
+ sysLIFC_UNDER_IPMP = C.LIFC_UNDER_IPMP
+ sysLIFC_ENABLED = C.LIFC_ENABLED
+
+ sysSIOCGLIFADDR = C.SIOCGLIFADDR
+ sysSIOCGLIFDSTADDR = C.SIOCGLIFDSTADDR
+ sysSIOCGLIFFLAGS = C.SIOCGLIFFLAGS
+ sysSIOCGLIFMTU = C.SIOCGLIFMTU
+ sysSIOCGLIFNETMASK = C.SIOCGLIFNETMASK
+ sysSIOCGLIFMETRIC = C.SIOCGLIFMETRIC
+ sysSIOCGLIFNUM = C.SIOCGLIFNUM
+ sysSIOCGLIFINDEX = C.SIOCGLIFINDEX
+ sysSIOCGLIFSUBNET = C.SIOCGLIFSUBNET
+ sysSIOCGLIFLNKINFO = C.SIOCGLIFLNKINFO
+ sysSIOCGLIFCONF = C.SIOCGLIFCONF
+ sysSIOCGLIFHWADDR = C.SIOCGLIFHWADDR
+)
+
+const (
+ sysIFF_UP = C.IFF_UP
+ sysIFF_BROADCAST = C.IFF_BROADCAST
+ sysIFF_DEBUG = C.IFF_DEBUG
+ sysIFF_LOOPBACK = C.IFF_LOOPBACK
+ sysIFF_POINTOPOINT = C.IFF_POINTOPOINT
+ sysIFF_NOTRAILERS = C.IFF_NOTRAILERS
+ sysIFF_RUNNING = C.IFF_RUNNING
+ sysIFF_NOARP = C.IFF_NOARP
+ sysIFF_PROMISC = C.IFF_PROMISC
+ sysIFF_ALLMULTI = C.IFF_ALLMULTI
+ sysIFF_INTELLIGENT = C.IFF_INTELLIGENT
+ sysIFF_MULTICAST = C.IFF_MULTICAST
+ sysIFF_MULTI_BCAST = C.IFF_MULTI_BCAST
+ sysIFF_UNNUMBERED = C.IFF_UNNUMBERED
+ sysIFF_PRIVATE = C.IFF_PRIVATE
+)
+
+const (
+ sizeofLifnum = C.sizeof_struct_lifnum
+ sizeofLifreq = C.sizeof_struct_lifreq
+ sizeofLifconf = C.sizeof_struct_lifconf
+ sizeofLifIfinfoReq = C.sizeof_struct_lif_ifinfo_req
+)
+
+type lifnum C.struct_lifnum
+
+type lifreq C.struct_lifreq
+
+type lifconf C.struct_lifconf
+
+type lifIfinfoReq C.struct_lif_ifinfo_req
+
+const (
+ sysIFT_IPV4 = C.IFT_IPV4
+ sysIFT_IPV6 = C.IFT_IPV6
+ sysIFT_6TO4 = C.IFT_6TO4
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/lif/lif.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/lif/lif.go
new file mode 100644
index 000000000..6e81f81f1
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/lif/lif.go
@@ -0,0 +1,43 @@
+// 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.
+
+// +build solaris
+
+// Package lif provides basic functions for the manipulation of
+// logical network interfaces and interface addresses on Solaris.
+//
+// The package supports Solaris 11 or above.
+package lif
+
+import "syscall"
+
+type endpoint struct {
+ af int
+ s uintptr
+}
+
+func (ep *endpoint) close() error {
+ return syscall.Close(int(ep.s))
+}
+
+func newEndpoints(af int) ([]endpoint, error) {
+ var lastErr error
+ var eps []endpoint
+ afs := []int{sysAF_INET, sysAF_INET6}
+ if af != sysAF_UNSPEC {
+ afs = []int{af}
+ }
+ for _, af := range afs {
+ s, err := syscall.Socket(af, sysSOCK_DGRAM, 0)
+ if err != nil {
+ lastErr = err
+ continue
+ }
+ eps = append(eps, endpoint{af: af, s: uintptr(s)})
+ }
+ if len(eps) == 0 {
+ return nil, lastErr
+ }
+ return eps, nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/lif/link.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/lif/link.go
new file mode 100644
index 000000000..913a53e11
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/lif/link.go
@@ -0,0 +1,126 @@
+// 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.
+
+// +build solaris
+
+package lif
+
+import "unsafe"
+
+// A Link represents logical data link information.
+//
+// It also represents base information for logical network interface.
+// On Solaris, each logical network interface represents network layer
+// adjacency information and the interface has a only single network
+// address or address pair for tunneling. It's usual that multiple
+// logical network interfaces share the same logical data link.
+type Link struct {
+ Name string // name, equivalent to IP interface name
+ Index int // index, equivalent to IP interface index
+ Type int // type
+ Flags int // flags
+ MTU int // maximum transmission unit, basically link MTU but may differ between IP address families
+ Addr []byte // address
+}
+
+func (ll *Link) fetch(s uintptr) {
+ var lifr lifreq
+ for i := 0; i < len(ll.Name); i++ {
+ lifr.Name[i] = int8(ll.Name[i])
+ }
+ ioc := int64(sysSIOCGLIFINDEX)
+ if err := ioctl(s, uintptr(ioc), unsafe.Pointer(&lifr)); err == nil {
+ ll.Index = int(nativeEndian.Uint32(lifr.Lifru[:4]))
+ }
+ ioc = int64(sysSIOCGLIFFLAGS)
+ if err := ioctl(s, uintptr(ioc), unsafe.Pointer(&lifr)); err == nil {
+ ll.Flags = int(nativeEndian.Uint64(lifr.Lifru[:8]))
+ }
+ ioc = int64(sysSIOCGLIFMTU)
+ if err := ioctl(s, uintptr(ioc), unsafe.Pointer(&lifr)); err == nil {
+ ll.MTU = int(nativeEndian.Uint32(lifr.Lifru[:4]))
+ }
+ switch ll.Type {
+ case sysIFT_IPV4, sysIFT_IPV6, sysIFT_6TO4:
+ default:
+ ioc = int64(sysSIOCGLIFHWADDR)
+ if err := ioctl(s, uintptr(ioc), unsafe.Pointer(&lifr)); err == nil {
+ ll.Addr, _ = parseLinkAddr(lifr.Lifru[4:])
+ }
+ }
+}
+
+// Links returns a list of logical data links.
+//
+// The provided af must be an address family and name must be a data
+// link name. The zero value of af or name means a wildcard.
+func Links(af int, name string) ([]Link, error) {
+ eps, err := newEndpoints(af)
+ if len(eps) == 0 {
+ return nil, err
+ }
+ defer func() {
+ for _, ep := range eps {
+ ep.close()
+ }
+ }()
+ return links(eps, name)
+}
+
+func links(eps []endpoint, name string) ([]Link, error) {
+ var lls []Link
+ lifn := lifnum{Flags: sysLIFC_NOXMIT | sysLIFC_TEMPORARY | sysLIFC_ALLZONES | sysLIFC_UNDER_IPMP}
+ lifc := lifconf{Flags: sysLIFC_NOXMIT | sysLIFC_TEMPORARY | sysLIFC_ALLZONES | sysLIFC_UNDER_IPMP}
+ for _, ep := range eps {
+ lifn.Family = uint16(ep.af)
+ ioc := int64(sysSIOCGLIFNUM)
+ if err := ioctl(ep.s, uintptr(ioc), unsafe.Pointer(&lifn)); err != nil {
+ continue
+ }
+ if lifn.Count == 0 {
+ continue
+ }
+ b := make([]byte, lifn.Count*sizeofLifreq)
+ lifc.Family = uint16(ep.af)
+ lifc.Len = lifn.Count * sizeofLifreq
+ if len(lifc.Lifcu) == 8 {
+ nativeEndian.PutUint64(lifc.Lifcu[:], uint64(uintptr(unsafe.Pointer(&b[0]))))
+ } else {
+ nativeEndian.PutUint32(lifc.Lifcu[:], uint32(uintptr(unsafe.Pointer(&b[0]))))
+ }
+ ioc = int64(sysSIOCGLIFCONF)
+ if err := ioctl(ep.s, uintptr(ioc), unsafe.Pointer(&lifc)); err != nil {
+ continue
+ }
+ nb := make([]byte, 32) // see LIFNAMSIZ in net/if.h
+ for i := 0; i < int(lifn.Count); i++ {
+ lifr := (*lifreq)(unsafe.Pointer(&b[i*sizeofLifreq]))
+ for i := 0; i < 32; i++ {
+ if lifr.Name[i] == 0 {
+ nb = nb[:i]
+ break
+ }
+ nb[i] = byte(lifr.Name[i])
+ }
+ llname := string(nb)
+ nb = nb[:32]
+ if isDupLink(lls, llname) || name != "" && name != llname {
+ continue
+ }
+ ll := Link{Name: llname, Type: int(lifr.Type)}
+ ll.fetch(ep.s)
+ lls = append(lls, ll)
+ }
+ }
+ return lls, nil
+}
+
+func isDupLink(lls []Link, name string) bool {
+ for _, ll := range lls {
+ if ll.Name == name {
+ return true
+ }
+ }
+ return false
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/lif/link_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/lif/link_test.go
new file mode 100644
index 000000000..0cb9b95c6
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/lif/link_test.go
@@ -0,0 +1,63 @@
+// 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.
+
+// +build solaris
+
+package lif
+
+import (
+ "fmt"
+ "testing"
+)
+
+func (ll *Link) String() string {
+ return fmt.Sprintf("name=%s index=%d type=%d flags=%#x mtu=%d addr=%v", ll.Name, ll.Index, ll.Type, ll.Flags, ll.MTU, llAddr(ll.Addr))
+}
+
+type linkPack struct {
+ af int
+ lls []Link
+}
+
+func linkPacks() ([]linkPack, error) {
+ var lastErr error
+ var lps []linkPack
+ for _, af := range [...]int{sysAF_UNSPEC, sysAF_INET, sysAF_INET6} {
+ lls, err := Links(af, "")
+ if err != nil {
+ lastErr = err
+ continue
+ }
+ lps = append(lps, linkPack{af: af, lls: lls})
+ }
+ return lps, lastErr
+}
+
+func TestLinks(t *testing.T) {
+ lps, err := linkPacks()
+ if len(lps) == 0 && err != nil {
+ t.Fatal(err)
+ }
+ for _, lp := range lps {
+ n := 0
+ for _, sll := range lp.lls {
+ lls, err := Links(lp.af, sll.Name)
+ if err != nil {
+ t.Fatal(lp.af, sll.Name, err)
+ }
+ for _, ll := range lls {
+ if ll.Name != sll.Name || ll.Index != sll.Index {
+ t.Errorf("af=%s got %v; want %v", addrFamily(lp.af), &ll, &sll)
+ continue
+ }
+ t.Logf("af=%s name=%s %v", addrFamily(lp.af), sll.Name, &ll)
+ n++
+ }
+ }
+ if n != len(lp.lls) {
+ t.Errorf("af=%s got %d; want %d", addrFamily(lp.af), n, len(lp.lls))
+ continue
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/lif/sys.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/lif/sys.go
new file mode 100644
index 000000000..c896041b7
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/lif/sys.go
@@ -0,0 +1,21 @@
+// 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.
+
+// +build solaris
+
+package lif
+
+import "unsafe"
+
+var nativeEndian binaryByteOrder
+
+func init() {
+ i := uint32(1)
+ b := (*[4]byte)(unsafe.Pointer(&i))
+ if b[0] == 1 {
+ nativeEndian = littleEndian
+ } else {
+ nativeEndian = bigEndian
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/lif/sys_solaris_amd64.s b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/lif/sys_solaris_amd64.s
new file mode 100644
index 000000000..39d76af79
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/lif/sys_solaris_amd64.s
@@ -0,0 +1,8 @@
+// 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.
+
+#include "textflag.h"
+
+TEXT ·sysvicall6(SB),NOSPLIT,$0-88
+ JMP syscall·sysvicall6(SB)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/lif/syscall.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/lif/syscall.go
new file mode 100644
index 000000000..aadab2e14
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/lif/syscall.go
@@ -0,0 +1,28 @@
+// 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.
+
+// +build solaris
+
+package lif
+
+import (
+ "syscall"
+ "unsafe"
+)
+
+//go:cgo_import_dynamic libc_ioctl ioctl "libc.so"
+
+//go:linkname procIoctl libc_ioctl
+
+var procIoctl uintptr
+
+func sysvicall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (uintptr, uintptr, syscall.Errno)
+
+func ioctl(s, ioc uintptr, arg unsafe.Pointer) error {
+ _, _, errno := sysvicall6(uintptr(unsafe.Pointer(&procIoctl)), 3, s, ioc, uintptr(arg), 0, 0, 0)
+ if errno != 0 {
+ return error(errno)
+ }
+ return nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/lif/zsys_solaris_amd64.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/lif/zsys_solaris_amd64.go
new file mode 100644
index 000000000..b5e999bec
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/lif/zsys_solaris_amd64.go
@@ -0,0 +1,103 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_solaris.go
+
+package lif
+
+const (
+ sysAF_UNSPEC = 0x0
+ sysAF_INET = 0x2
+ sysAF_INET6 = 0x1a
+
+ sysSOCK_DGRAM = 0x1
+)
+
+type sockaddrStorage struct {
+ Family uint16
+ X_ss_pad1 [6]int8
+ X_ss_align float64
+ X_ss_pad2 [240]int8
+}
+
+const (
+ sysLIFC_NOXMIT = 0x1
+ sysLIFC_EXTERNAL_SOURCE = 0x2
+ sysLIFC_TEMPORARY = 0x4
+ sysLIFC_ALLZONES = 0x8
+ sysLIFC_UNDER_IPMP = 0x10
+ sysLIFC_ENABLED = 0x20
+
+ sysSIOCGLIFADDR = -0x3f87968f
+ sysSIOCGLIFDSTADDR = -0x3f87968d
+ sysSIOCGLIFFLAGS = -0x3f87968b
+ sysSIOCGLIFMTU = -0x3f879686
+ sysSIOCGLIFNETMASK = -0x3f879683
+ sysSIOCGLIFMETRIC = -0x3f879681
+ sysSIOCGLIFNUM = -0x3ff3967e
+ sysSIOCGLIFINDEX = -0x3f87967b
+ sysSIOCGLIFSUBNET = -0x3f879676
+ sysSIOCGLIFLNKINFO = -0x3f879674
+ sysSIOCGLIFCONF = -0x3fef965b
+ sysSIOCGLIFHWADDR = -0x3f879640
+)
+
+const (
+ sysIFF_UP = 0x1
+ sysIFF_BROADCAST = 0x2
+ sysIFF_DEBUG = 0x4
+ sysIFF_LOOPBACK = 0x8
+ sysIFF_POINTOPOINT = 0x10
+ sysIFF_NOTRAILERS = 0x20
+ sysIFF_RUNNING = 0x40
+ sysIFF_NOARP = 0x80
+ sysIFF_PROMISC = 0x100
+ sysIFF_ALLMULTI = 0x200
+ sysIFF_INTELLIGENT = 0x400
+ sysIFF_MULTICAST = 0x800
+ sysIFF_MULTI_BCAST = 0x1000
+ sysIFF_UNNUMBERED = 0x2000
+ sysIFF_PRIVATE = 0x8000
+)
+
+const (
+ sizeofLifnum = 0xc
+ sizeofLifreq = 0x178
+ sizeofLifconf = 0x18
+ sizeofLifIfinfoReq = 0x10
+)
+
+type lifnum struct {
+ Family uint16
+ Pad_cgo_0 [2]byte
+ Flags int32
+ Count int32
+}
+
+type lifreq struct {
+ Name [32]int8
+ Lifru1 [4]byte
+ Type uint32
+ Lifru [336]byte
+}
+
+type lifconf struct {
+ Family uint16
+ Pad_cgo_0 [2]byte
+ Flags int32
+ Len int32
+ Pad_cgo_1 [4]byte
+ Lifcu [8]byte
+}
+
+type lifIfinfoReq struct {
+ Maxhops uint8
+ Pad_cgo_0 [3]byte
+ Reachtime uint32
+ Reachretrans uint32
+ Maxmtu uint32
+}
+
+const (
+ sysIFT_IPV4 = 0xc8
+ sysIFT_IPV6 = 0xc9
+ sysIFT_6TO4 = 0xca
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/nettest/conntest.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/nettest/conntest.go
new file mode 100644
index 000000000..5bd3a8c68
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/nettest/conntest.go
@@ -0,0 +1,456 @@
+// 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.
+
+// Package nettest provides utilities for network testing.
+package nettest
+
+import (
+ "bytes"
+ "encoding/binary"
+ "io"
+ "io/ioutil"
+ "math/rand"
+ "net"
+ "runtime"
+ "sync"
+ "testing"
+ "time"
+)
+
+var (
+ aLongTimeAgo = time.Unix(233431200, 0)
+ neverTimeout = time.Time{}
+)
+
+// MakePipe creates a connection between two endpoints and returns the pair
+// as c1 and c2, such that anything written to c1 is read by c2 and vice-versa.
+// The stop function closes all resources, including c1, c2, and the underlying
+// net.Listener (if there is one), and should not be nil.
+type MakePipe func() (c1, c2 net.Conn, stop func(), err error)
+
+// TestConn tests that a net.Conn implementation properly satisfies the interface.
+// The tests should not produce any false positives, but may experience
+// false negatives. Thus, some issues may only be detected when the test is
+// run multiple times. For maximal effectiveness, run the tests under the
+// race detector.
+func TestConn(t *testing.T, mp MakePipe) {
+ testConn(t, mp)
+}
+
+type connTester func(t *testing.T, c1, c2 net.Conn)
+
+func timeoutWrapper(t *testing.T, mp MakePipe, f connTester) {
+ c1, c2, stop, err := mp()
+ if err != nil {
+ t.Fatalf("unable to make pipe: %v", err)
+ }
+ var once sync.Once
+ defer once.Do(func() { stop() })
+ timer := time.AfterFunc(time.Minute, func() {
+ once.Do(func() {
+ t.Error("test timed out; terminating pipe")
+ stop()
+ })
+ })
+ defer timer.Stop()
+ f(t, c1, c2)
+}
+
+// testBasicIO tests that the data sent on c1 is properly received on c2.
+func testBasicIO(t *testing.T, c1, c2 net.Conn) {
+ want := make([]byte, 1<<20)
+ rand.New(rand.NewSource(0)).Read(want)
+
+ dataCh := make(chan []byte)
+ go func() {
+ rd := bytes.NewReader(want)
+ if err := chunkedCopy(c1, rd); err != nil {
+ t.Errorf("unexpected c1.Write error: %v", err)
+ }
+ if err := c1.Close(); err != nil {
+ t.Errorf("unexpected c1.Close error: %v", err)
+ }
+ }()
+
+ go func() {
+ wr := new(bytes.Buffer)
+ if err := chunkedCopy(wr, c2); err != nil {
+ t.Errorf("unexpected c2.Read error: %v", err)
+ }
+ if err := c2.Close(); err != nil {
+ t.Errorf("unexpected c2.Close error: %v", err)
+ }
+ dataCh <- wr.Bytes()
+ }()
+
+ if got := <-dataCh; !bytes.Equal(got, want) {
+ t.Errorf("transmitted data differs")
+ }
+}
+
+// testPingPong tests that the two endpoints can synchronously send data to
+// each other in a typical request-response pattern.
+func testPingPong(t *testing.T, c1, c2 net.Conn) {
+ var wg sync.WaitGroup
+ defer wg.Wait()
+
+ pingPonger := func(c net.Conn) {
+ defer wg.Done()
+ buf := make([]byte, 8)
+ var prev uint64
+ for {
+ if _, err := io.ReadFull(c, buf); err != nil {
+ if err == io.EOF {
+ break
+ }
+ t.Errorf("unexpected Read error: %v", err)
+ }
+
+ v := binary.LittleEndian.Uint64(buf)
+ binary.LittleEndian.PutUint64(buf, v+1)
+ if prev != 0 && prev+2 != v {
+ t.Errorf("mismatching value: got %d, want %d", v, prev+2)
+ }
+ prev = v
+ if v == 1000 {
+ break
+ }
+
+ if _, err := c.Write(buf); err != nil {
+ t.Errorf("unexpected Write error: %v", err)
+ break
+ }
+ }
+ if err := c.Close(); err != nil {
+ t.Errorf("unexpected Close error: %v", err)
+ }
+ }
+
+ wg.Add(2)
+ go pingPonger(c1)
+ go pingPonger(c2)
+
+ // Start off the chain reaction.
+ if _, err := c1.Write(make([]byte, 8)); err != nil {
+ t.Errorf("unexpected c1.Write error: %v", err)
+ }
+}
+
+// testRacyRead tests that it is safe to mutate the input Read buffer
+// immediately after cancelation has occurred.
+func testRacyRead(t *testing.T, c1, c2 net.Conn) {
+ go chunkedCopy(c2, rand.New(rand.NewSource(0)))
+
+ var wg sync.WaitGroup
+ defer wg.Wait()
+
+ c1.SetReadDeadline(time.Now().Add(time.Millisecond))
+ for i := 0; i < 10; i++ {
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+
+ b1 := make([]byte, 1024)
+ b2 := make([]byte, 1024)
+ for j := 0; j < 100; j++ {
+ _, err := c1.Read(b1)
+ copy(b1, b2) // Mutate b1 to trigger potential race
+ if err != nil {
+ checkForTimeoutError(t, err)
+ c1.SetReadDeadline(time.Now().Add(time.Millisecond))
+ }
+ }
+ }()
+ }
+}
+
+// testRacyWrite tests that it is safe to mutate the input Write buffer
+// immediately after cancelation has occurred.
+func testRacyWrite(t *testing.T, c1, c2 net.Conn) {
+ go chunkedCopy(ioutil.Discard, c2)
+
+ var wg sync.WaitGroup
+ defer wg.Wait()
+
+ c1.SetWriteDeadline(time.Now().Add(time.Millisecond))
+ for i := 0; i < 10; i++ {
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+
+ b1 := make([]byte, 1024)
+ b2 := make([]byte, 1024)
+ for j := 0; j < 100; j++ {
+ _, err := c1.Write(b1)
+ copy(b1, b2) // Mutate b1 to trigger potential race
+ if err != nil {
+ checkForTimeoutError(t, err)
+ c1.SetWriteDeadline(time.Now().Add(time.Millisecond))
+ }
+ }
+ }()
+ }
+}
+
+// testReadTimeout tests that Read timeouts do not affect Write.
+func testReadTimeout(t *testing.T, c1, c2 net.Conn) {
+ go chunkedCopy(ioutil.Discard, c2)
+
+ c1.SetReadDeadline(aLongTimeAgo)
+ _, err := c1.Read(make([]byte, 1024))
+ checkForTimeoutError(t, err)
+ if _, err := c1.Write(make([]byte, 1024)); err != nil {
+ t.Errorf("unexpected Write error: %v", err)
+ }
+}
+
+// testWriteTimeout tests that Write timeouts do not affect Read.
+func testWriteTimeout(t *testing.T, c1, c2 net.Conn) {
+ go chunkedCopy(c2, rand.New(rand.NewSource(0)))
+
+ c1.SetWriteDeadline(aLongTimeAgo)
+ _, err := c1.Write(make([]byte, 1024))
+ checkForTimeoutError(t, err)
+ if _, err := c1.Read(make([]byte, 1024)); err != nil {
+ t.Errorf("unexpected Read error: %v", err)
+ }
+}
+
+// testPastTimeout tests that a deadline set in the past immediately times out
+// Read and Write requests.
+func testPastTimeout(t *testing.T, c1, c2 net.Conn) {
+ go chunkedCopy(c2, c2)
+
+ testRoundtrip(t, c1)
+
+ c1.SetDeadline(aLongTimeAgo)
+ n, err := c1.Write(make([]byte, 1024))
+ if n != 0 {
+ t.Errorf("unexpected Write count: got %d, want 0", n)
+ }
+ checkForTimeoutError(t, err)
+ n, err = c1.Read(make([]byte, 1024))
+ if n != 0 {
+ t.Errorf("unexpected Read count: got %d, want 0", n)
+ }
+ checkForTimeoutError(t, err)
+
+ testRoundtrip(t, c1)
+}
+
+// testPresentTimeout tests that a deadline set while there are pending
+// Read and Write operations immediately times out those operations.
+func testPresentTimeout(t *testing.T, c1, c2 net.Conn) {
+ var wg sync.WaitGroup
+ defer wg.Wait()
+ wg.Add(3)
+
+ deadlineSet := make(chan bool, 1)
+ go func() {
+ defer wg.Done()
+ time.Sleep(100 * time.Millisecond)
+ deadlineSet <- true
+ c1.SetReadDeadline(aLongTimeAgo)
+ c1.SetWriteDeadline(aLongTimeAgo)
+ }()
+ go func() {
+ defer wg.Done()
+ n, err := c1.Read(make([]byte, 1024))
+ if n != 0 {
+ t.Errorf("unexpected Read count: got %d, want 0", n)
+ }
+ checkForTimeoutError(t, err)
+ if len(deadlineSet) == 0 {
+ t.Error("Read timed out before deadline is set")
+ }
+ }()
+ go func() {
+ defer wg.Done()
+ var err error
+ for err == nil {
+ _, err = c1.Write(make([]byte, 1024))
+ }
+ checkForTimeoutError(t, err)
+ if len(deadlineSet) == 0 {
+ t.Error("Write timed out before deadline is set")
+ }
+ }()
+}
+
+// testFutureTimeout tests that a future deadline will eventually time out
+// Read and Write operations.
+func testFutureTimeout(t *testing.T, c1, c2 net.Conn) {
+ var wg sync.WaitGroup
+ wg.Add(2)
+
+ c1.SetDeadline(time.Now().Add(100 * time.Millisecond))
+ go func() {
+ defer wg.Done()
+ _, err := c1.Read(make([]byte, 1024))
+ checkForTimeoutError(t, err)
+ }()
+ go func() {
+ defer wg.Done()
+ var err error
+ for err == nil {
+ _, err = c1.Write(make([]byte, 1024))
+ }
+ checkForTimeoutError(t, err)
+ }()
+ wg.Wait()
+
+ go chunkedCopy(c2, c2)
+ resyncConn(t, c1)
+ testRoundtrip(t, c1)
+}
+
+// testCloseTimeout tests that calling Close immediately times out pending
+// Read and Write operations.
+func testCloseTimeout(t *testing.T, c1, c2 net.Conn) {
+ go chunkedCopy(c2, c2)
+
+ var wg sync.WaitGroup
+ defer wg.Wait()
+ wg.Add(3)
+
+ // Test for cancelation upon connection closure.
+ c1.SetDeadline(neverTimeout)
+ go func() {
+ defer wg.Done()
+ time.Sleep(100 * time.Millisecond)
+ c1.Close()
+ }()
+ go func() {
+ defer wg.Done()
+ var err error
+ buf := make([]byte, 1024)
+ for err == nil {
+ _, err = c1.Read(buf)
+ }
+ }()
+ go func() {
+ defer wg.Done()
+ var err error
+ buf := make([]byte, 1024)
+ for err == nil {
+ _, err = c1.Write(buf)
+ }
+ }()
+}
+
+// testConcurrentMethods tests that the methods of net.Conn can safely
+// be called concurrently.
+func testConcurrentMethods(t *testing.T, c1, c2 net.Conn) {
+ if runtime.GOOS == "plan9" {
+ t.Skip("skipping on plan9; see https://golang.org/issue/20489")
+ }
+ go chunkedCopy(c2, c2)
+
+ // The results of the calls may be nonsensical, but this should
+ // not trigger a race detector warning.
+ var wg sync.WaitGroup
+ for i := 0; i < 100; i++ {
+ wg.Add(7)
+ go func() {
+ defer wg.Done()
+ c1.Read(make([]byte, 1024))
+ }()
+ go func() {
+ defer wg.Done()
+ c1.Write(make([]byte, 1024))
+ }()
+ go func() {
+ defer wg.Done()
+ c1.SetDeadline(time.Now().Add(10 * time.Millisecond))
+ }()
+ go func() {
+ defer wg.Done()
+ c1.SetReadDeadline(aLongTimeAgo)
+ }()
+ go func() {
+ defer wg.Done()
+ c1.SetWriteDeadline(aLongTimeAgo)
+ }()
+ go func() {
+ defer wg.Done()
+ c1.LocalAddr()
+ }()
+ go func() {
+ defer wg.Done()
+ c1.RemoteAddr()
+ }()
+ }
+ wg.Wait() // At worst, the deadline is set 10ms into the future
+
+ resyncConn(t, c1)
+ testRoundtrip(t, c1)
+}
+
+// checkForTimeoutError checks that the error satisfies the Error interface
+// and that Timeout returns true.
+func checkForTimeoutError(t *testing.T, err error) {
+ if nerr, ok := err.(net.Error); ok {
+ if !nerr.Timeout() {
+ t.Errorf("err.Timeout() = false, want true")
+ }
+ } else {
+ t.Errorf("got %T, want net.Error", err)
+ }
+}
+
+// testRoundtrip writes something into c and reads it back.
+// It assumes that everything written into c is echoed back to itself.
+func testRoundtrip(t *testing.T, c net.Conn) {
+ if err := c.SetDeadline(neverTimeout); err != nil {
+ t.Errorf("roundtrip SetDeadline error: %v", err)
+ }
+
+ const s = "Hello, world!"
+ buf := []byte(s)
+ if _, err := c.Write(buf); err != nil {
+ t.Errorf("roundtrip Write error: %v", err)
+ }
+ if _, err := io.ReadFull(c, buf); err != nil {
+ t.Errorf("roundtrip Read error: %v", err)
+ }
+ if string(buf) != s {
+ t.Errorf("roundtrip data mismatch: got %q, want %q", buf, s)
+ }
+}
+
+// resyncConn resynchronizes the connection into a sane state.
+// It assumes that everything written into c is echoed back to itself.
+// It assumes that 0xff is not currently on the wire or in the read buffer.
+func resyncConn(t *testing.T, c net.Conn) {
+ c.SetDeadline(neverTimeout)
+ errCh := make(chan error)
+ go func() {
+ _, err := c.Write([]byte{0xff})
+ errCh <- err
+ }()
+ buf := make([]byte, 1024)
+ for {
+ n, err := c.Read(buf)
+ if n > 0 && bytes.IndexByte(buf[:n], 0xff) == n-1 {
+ break
+ }
+ if err != nil {
+ t.Errorf("unexpected Read error: %v", err)
+ break
+ }
+ }
+ if err := <-errCh; err != nil {
+ t.Errorf("unexpected Write error: %v", err)
+ }
+}
+
+// chunkedCopy copies from r to w in fixed-width chunks to avoid
+// causing a Write that exceeds the maximum packet size for packet-based
+// connections like "unixpacket".
+// We assume that the maximum packet size is at least 1024.
+func chunkedCopy(w io.Writer, r io.Reader) error {
+ b := make([]byte, 1024)
+ _, err := io.CopyBuffer(struct{ io.Writer }{w}, struct{ io.Reader }{r}, b)
+ return err
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/nettest/conntest_go16.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/nettest/conntest_go16.go
new file mode 100644
index 000000000..4cbf48e35
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/nettest/conntest_go16.go
@@ -0,0 +1,24 @@
+// 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.
+
+// +build !go1.7
+
+package nettest
+
+import "testing"
+
+func testConn(t *testing.T, mp MakePipe) {
+ // Avoid using subtests on Go 1.6 and below.
+ timeoutWrapper(t, mp, testBasicIO)
+ timeoutWrapper(t, mp, testPingPong)
+ timeoutWrapper(t, mp, testRacyRead)
+ timeoutWrapper(t, mp, testRacyWrite)
+ timeoutWrapper(t, mp, testReadTimeout)
+ timeoutWrapper(t, mp, testWriteTimeout)
+ timeoutWrapper(t, mp, testPastTimeout)
+ timeoutWrapper(t, mp, testPresentTimeout)
+ timeoutWrapper(t, mp, testFutureTimeout)
+ timeoutWrapper(t, mp, testCloseTimeout)
+ timeoutWrapper(t, mp, testConcurrentMethods)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/nettest/conntest_go17.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/nettest/conntest_go17.go
new file mode 100644
index 000000000..fa039f03f
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/nettest/conntest_go17.go
@@ -0,0 +1,24 @@
+// 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.
+
+// +build go1.7
+
+package nettest
+
+import "testing"
+
+func testConn(t *testing.T, mp MakePipe) {
+ // Use subtests on Go 1.7 and above since it is better organized.
+ t.Run("BasicIO", func(t *testing.T) { timeoutWrapper(t, mp, testBasicIO) })
+ t.Run("PingPong", func(t *testing.T) { timeoutWrapper(t, mp, testPingPong) })
+ t.Run("RacyRead", func(t *testing.T) { timeoutWrapper(t, mp, testRacyRead) })
+ t.Run("RacyWrite", func(t *testing.T) { timeoutWrapper(t, mp, testRacyWrite) })
+ t.Run("ReadTimeout", func(t *testing.T) { timeoutWrapper(t, mp, testReadTimeout) })
+ t.Run("WriteTimeout", func(t *testing.T) { timeoutWrapper(t, mp, testWriteTimeout) })
+ t.Run("PastTimeout", func(t *testing.T) { timeoutWrapper(t, mp, testPastTimeout) })
+ t.Run("PresentTimeout", func(t *testing.T) { timeoutWrapper(t, mp, testPresentTimeout) })
+ t.Run("FutureTimeout", func(t *testing.T) { timeoutWrapper(t, mp, testFutureTimeout) })
+ t.Run("CloseTimeout", func(t *testing.T) { timeoutWrapper(t, mp, testCloseTimeout) })
+ t.Run("ConcurrentMethods", func(t *testing.T) { timeoutWrapper(t, mp, testConcurrentMethods) })
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/nettest/conntest_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/nettest/conntest_test.go
new file mode 100644
index 000000000..9f9453fb5
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/nettest/conntest_test.go
@@ -0,0 +1,76 @@
+// 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.
+
+// +build go1.8
+
+package nettest
+
+import (
+ "net"
+ "os"
+ "runtime"
+ "testing"
+
+ "golang.org/x/net/internal/nettest"
+)
+
+func TestTestConn(t *testing.T) {
+ tests := []struct{ name, network string }{
+ {"TCP", "tcp"},
+ {"UnixPipe", "unix"},
+ {"UnixPacketPipe", "unixpacket"},
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if !nettest.TestableNetwork(tt.network) {
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+
+ mp := func() (c1, c2 net.Conn, stop func(), err error) {
+ ln, err := nettest.NewLocalListener(tt.network)
+ if err != nil {
+ return nil, nil, nil, err
+ }
+
+ // Start a connection between two endpoints.
+ var err1, err2 error
+ done := make(chan bool)
+ go func() {
+ c2, err2 = ln.Accept()
+ close(done)
+ }()
+ c1, err1 = net.Dial(ln.Addr().Network(), ln.Addr().String())
+ <-done
+
+ stop = func() {
+ if err1 == nil {
+ c1.Close()
+ }
+ if err2 == nil {
+ c2.Close()
+ }
+ ln.Close()
+ switch tt.network {
+ case "unix", "unixpacket":
+ os.Remove(ln.Addr().String())
+ }
+ }
+
+ switch {
+ case err1 != nil:
+ stop()
+ return nil, nil, nil, err1
+ case err2 != nil:
+ stop()
+ return nil, nil, nil, err2
+ default:
+ return c1, c2, stop, nil
+ }
+ }
+
+ TestConn(t, mp)
+ })
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/netutil/listen.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/netutil/listen.go
new file mode 100644
index 000000000..56f43bf65
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/netutil/listen.go
@@ -0,0 +1,48 @@
+// Copyright 2013 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 netutil provides network utility functions, complementing the more
+// common ones in the net package.
+package netutil // import "golang.org/x/net/netutil"
+
+import (
+ "net"
+ "sync"
+)
+
+// LimitListener returns a Listener that accepts at most n simultaneous
+// connections from the provided Listener.
+func LimitListener(l net.Listener, n int) net.Listener {
+ return &limitListener{l, make(chan struct{}, n)}
+}
+
+type limitListener struct {
+ net.Listener
+ sem chan struct{}
+}
+
+func (l *limitListener) acquire() { l.sem <- struct{}{} }
+func (l *limitListener) release() { <-l.sem }
+
+func (l *limitListener) Accept() (net.Conn, error) {
+ l.acquire()
+ c, err := l.Listener.Accept()
+ if err != nil {
+ l.release()
+ return nil, err
+ }
+ return &limitListenerConn{Conn: c, release: l.release}, nil
+}
+
+type limitListenerConn struct {
+ net.Conn
+ releaseOnce sync.Once
+ release func()
+}
+
+func (l *limitListenerConn) Close() error {
+ err := l.Conn.Close()
+ l.releaseOnce.Do(l.release)
+ return err
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/netutil/listen_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/netutil/listen_test.go
new file mode 100644
index 000000000..5e07d7bea
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/netutil/listen_test.go
@@ -0,0 +1,101 @@
+// Copyright 2013 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 netutil
+
+import (
+ "errors"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "net"
+ "net/http"
+ "sync"
+ "sync/atomic"
+ "testing"
+ "time"
+
+ "golang.org/x/net/internal/nettest"
+)
+
+func TestLimitListener(t *testing.T) {
+ const max = 5
+ attempts := (nettest.MaxOpenFiles() - max) / 2
+ if attempts > 256 { // maximum length of accept queue is 128 by default
+ attempts = 256
+ }
+
+ l, err := net.Listen("tcp", "127.0.0.1:0")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer l.Close()
+ l = LimitListener(l, max)
+
+ var open int32
+ go http.Serve(l, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if n := atomic.AddInt32(&open, 1); n > max {
+ t.Errorf("%d open connections, want <= %d", n, max)
+ }
+ defer atomic.AddInt32(&open, -1)
+ time.Sleep(10 * time.Millisecond)
+ fmt.Fprint(w, "some body")
+ }))
+
+ var wg sync.WaitGroup
+ var failed int32
+ for i := 0; i < attempts; i++ {
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ c := http.Client{Timeout: 3 * time.Second}
+ r, err := c.Get("http://" + l.Addr().String())
+ if err != nil {
+ t.Log(err)
+ atomic.AddInt32(&failed, 1)
+ return
+ }
+ defer r.Body.Close()
+ io.Copy(ioutil.Discard, r.Body)
+ }()
+ }
+ wg.Wait()
+
+ // We expect some Gets to fail as the kernel's accept queue is filled,
+ // but most should succeed.
+ if int(failed) >= attempts/2 {
+ t.Errorf("%d requests failed within %d attempts", failed, attempts)
+ }
+}
+
+type errorListener struct {
+ net.Listener
+}
+
+func (errorListener) Accept() (net.Conn, error) {
+ return nil, errFake
+}
+
+var errFake = errors.New("fake error from errorListener")
+
+// This used to hang.
+func TestLimitListenerError(t *testing.T) {
+ donec := make(chan bool, 1)
+ go func() {
+ const n = 2
+ ll := LimitListener(errorListener{}, n)
+ for i := 0; i < n+1; i++ {
+ _, err := ll.Accept()
+ if err != errFake {
+ t.Fatalf("Accept error = %v; want errFake", err)
+ }
+ }
+ donec <- true
+ }()
+ select {
+ case <-donec:
+ case <-time.After(5 * time.Second):
+ t.Fatal("timeout. deadlock?")
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/proxy/direct.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/proxy/direct.go
new file mode 100644
index 000000000..4c5ad88b1
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/proxy/direct.go
@@ -0,0 +1,18 @@
+// Copyright 2011 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 proxy
+
+import (
+ "net"
+)
+
+type direct struct{}
+
+// Direct is a direct proxy: one that makes network connections directly.
+var Direct = direct{}
+
+func (direct) Dial(network, addr string) (net.Conn, error) {
+ return net.Dial(network, addr)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/proxy/per_host.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/proxy/per_host.go
new file mode 100644
index 000000000..0689bb6a7
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/proxy/per_host.go
@@ -0,0 +1,140 @@
+// Copyright 2011 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 proxy
+
+import (
+ "net"
+ "strings"
+)
+
+// A PerHost directs connections to a default Dialer unless the host name
+// requested matches one of a number of exceptions.
+type PerHost struct {
+ def, bypass Dialer
+
+ bypassNetworks []*net.IPNet
+ bypassIPs []net.IP
+ bypassZones []string
+ bypassHosts []string
+}
+
+// NewPerHost returns a PerHost Dialer that directs connections to either
+// defaultDialer or bypass, depending on whether the connection matches one of
+// the configured rules.
+func NewPerHost(defaultDialer, bypass Dialer) *PerHost {
+ return &PerHost{
+ def: defaultDialer,
+ bypass: bypass,
+ }
+}
+
+// Dial connects to the address addr on the given network through either
+// defaultDialer or bypass.
+func (p *PerHost) Dial(network, addr string) (c net.Conn, err error) {
+ host, _, err := net.SplitHostPort(addr)
+ if err != nil {
+ return nil, err
+ }
+
+ return p.dialerForRequest(host).Dial(network, addr)
+}
+
+func (p *PerHost) dialerForRequest(host string) Dialer {
+ if ip := net.ParseIP(host); ip != nil {
+ for _, net := range p.bypassNetworks {
+ if net.Contains(ip) {
+ return p.bypass
+ }
+ }
+ for _, bypassIP := range p.bypassIPs {
+ if bypassIP.Equal(ip) {
+ return p.bypass
+ }
+ }
+ return p.def
+ }
+
+ for _, zone := range p.bypassZones {
+ if strings.HasSuffix(host, zone) {
+ return p.bypass
+ }
+ if host == zone[1:] {
+ // For a zone ".example.com", we match "example.com"
+ // too.
+ return p.bypass
+ }
+ }
+ for _, bypassHost := range p.bypassHosts {
+ if bypassHost == host {
+ return p.bypass
+ }
+ }
+ return p.def
+}
+
+// AddFromString parses a string that contains comma-separated values
+// specifying hosts that should use the bypass proxy. Each value is either an
+// IP address, a CIDR range, a zone (*.example.com) or a host name
+// (localhost). A best effort is made to parse the string and errors are
+// ignored.
+func (p *PerHost) AddFromString(s string) {
+ hosts := strings.Split(s, ",")
+ for _, host := range hosts {
+ host = strings.TrimSpace(host)
+ if len(host) == 0 {
+ continue
+ }
+ if strings.Contains(host, "/") {
+ // We assume that it's a CIDR address like 127.0.0.0/8
+ if _, net, err := net.ParseCIDR(host); err == nil {
+ p.AddNetwork(net)
+ }
+ continue
+ }
+ if ip := net.ParseIP(host); ip != nil {
+ p.AddIP(ip)
+ continue
+ }
+ if strings.HasPrefix(host, "*.") {
+ p.AddZone(host[1:])
+ continue
+ }
+ p.AddHost(host)
+ }
+}
+
+// AddIP specifies an IP address that will use the bypass proxy. Note that
+// this will only take effect if a literal IP address is dialed. A connection
+// to a named host will never match an IP.
+func (p *PerHost) AddIP(ip net.IP) {
+ p.bypassIPs = append(p.bypassIPs, ip)
+}
+
+// AddNetwork specifies an IP range that will use the bypass proxy. Note that
+// this will only take effect if a literal IP address is dialed. A connection
+// to a named host will never match.
+func (p *PerHost) AddNetwork(net *net.IPNet) {
+ p.bypassNetworks = append(p.bypassNetworks, net)
+}
+
+// AddZone specifies a DNS suffix that will use the bypass proxy. A zone of
+// "example.com" matches "example.com" and all of its subdomains.
+func (p *PerHost) AddZone(zone string) {
+ if strings.HasSuffix(zone, ".") {
+ zone = zone[:len(zone)-1]
+ }
+ if !strings.HasPrefix(zone, ".") {
+ zone = "." + zone
+ }
+ p.bypassZones = append(p.bypassZones, zone)
+}
+
+// AddHost specifies a host name that will use the bypass proxy.
+func (p *PerHost) AddHost(host string) {
+ if strings.HasSuffix(host, ".") {
+ host = host[:len(host)-1]
+ }
+ p.bypassHosts = append(p.bypassHosts, host)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/proxy/per_host_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/proxy/per_host_test.go
new file mode 100644
index 000000000..a7d809571
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/proxy/per_host_test.go
@@ -0,0 +1,55 @@
+// Copyright 2011 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 proxy
+
+import (
+ "errors"
+ "net"
+ "reflect"
+ "testing"
+)
+
+type recordingProxy struct {
+ addrs []string
+}
+
+func (r *recordingProxy) Dial(network, addr string) (net.Conn, error) {
+ r.addrs = append(r.addrs, addr)
+ return nil, errors.New("recordingProxy")
+}
+
+func TestPerHost(t *testing.T) {
+ var def, bypass recordingProxy
+ perHost := NewPerHost(&def, &bypass)
+ perHost.AddFromString("localhost,*.zone,127.0.0.1,10.0.0.1/8,1000::/16")
+
+ expectedDef := []string{
+ "example.com:123",
+ "1.2.3.4:123",
+ "[1001::]:123",
+ }
+ expectedBypass := []string{
+ "localhost:123",
+ "zone:123",
+ "foo.zone:123",
+ "127.0.0.1:123",
+ "10.1.2.3:123",
+ "[1000::]:123",
+ }
+
+ for _, addr := range expectedDef {
+ perHost.Dial("tcp", addr)
+ }
+ for _, addr := range expectedBypass {
+ perHost.Dial("tcp", addr)
+ }
+
+ if !reflect.DeepEqual(expectedDef, def.addrs) {
+ t.Errorf("Hosts which went to the default proxy didn't match. Got %v, want %v", def.addrs, expectedDef)
+ }
+ if !reflect.DeepEqual(expectedBypass, bypass.addrs) {
+ t.Errorf("Hosts which went to the bypass proxy didn't match. Got %v, want %v", bypass.addrs, expectedBypass)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/proxy/proxy.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/proxy/proxy.go
new file mode 100644
index 000000000..553ead7cf
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/proxy/proxy.go
@@ -0,0 +1,134 @@
+// Copyright 2011 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 proxy provides support for a variety of protocols to proxy network
+// data.
+package proxy // import "golang.org/x/net/proxy"
+
+import (
+ "errors"
+ "net"
+ "net/url"
+ "os"
+ "sync"
+)
+
+// A Dialer is a means to establish a connection.
+type Dialer interface {
+ // Dial connects to the given address via the proxy.
+ Dial(network, addr string) (c net.Conn, err error)
+}
+
+// Auth contains authentication parameters that specific Dialers may require.
+type Auth struct {
+ User, Password string
+}
+
+// FromEnvironment returns the dialer specified by the proxy related variables in
+// the environment.
+func FromEnvironment() Dialer {
+ allProxy := allProxyEnv.Get()
+ if len(allProxy) == 0 {
+ return Direct
+ }
+
+ proxyURL, err := url.Parse(allProxy)
+ if err != nil {
+ return Direct
+ }
+ proxy, err := FromURL(proxyURL, Direct)
+ if err != nil {
+ return Direct
+ }
+
+ noProxy := noProxyEnv.Get()
+ if len(noProxy) == 0 {
+ return proxy
+ }
+
+ perHost := NewPerHost(proxy, Direct)
+ perHost.AddFromString(noProxy)
+ return perHost
+}
+
+// proxySchemes is a map from URL schemes to a function that creates a Dialer
+// from a URL with such a scheme.
+var proxySchemes map[string]func(*url.URL, Dialer) (Dialer, error)
+
+// RegisterDialerType takes a URL scheme and a function to generate Dialers from
+// a URL with that scheme and a forwarding Dialer. Registered schemes are used
+// by FromURL.
+func RegisterDialerType(scheme string, f func(*url.URL, Dialer) (Dialer, error)) {
+ if proxySchemes == nil {
+ proxySchemes = make(map[string]func(*url.URL, Dialer) (Dialer, error))
+ }
+ proxySchemes[scheme] = f
+}
+
+// FromURL returns a Dialer given a URL specification and an underlying
+// Dialer for it to make network requests.
+func FromURL(u *url.URL, forward Dialer) (Dialer, error) {
+ var auth *Auth
+ if u.User != nil {
+ auth = new(Auth)
+ auth.User = u.User.Username()
+ if p, ok := u.User.Password(); ok {
+ auth.Password = p
+ }
+ }
+
+ switch u.Scheme {
+ case "socks5":
+ return SOCKS5("tcp", u.Host, auth, forward)
+ }
+
+ // If the scheme doesn't match any of the built-in schemes, see if it
+ // was registered by another package.
+ if proxySchemes != nil {
+ if f, ok := proxySchemes[u.Scheme]; ok {
+ return f(u, forward)
+ }
+ }
+
+ return nil, errors.New("proxy: unknown scheme: " + u.Scheme)
+}
+
+var (
+ allProxyEnv = &envOnce{
+ names: []string{"ALL_PROXY", "all_proxy"},
+ }
+ noProxyEnv = &envOnce{
+ names: []string{"NO_PROXY", "no_proxy"},
+ }
+)
+
+// envOnce looks up an environment variable (optionally by multiple
+// names) once. It mitigates expensive lookups on some platforms
+// (e.g. Windows).
+// (Borrowed from net/http/transport.go)
+type envOnce struct {
+ names []string
+ once sync.Once
+ val string
+}
+
+func (e *envOnce) Get() string {
+ e.once.Do(e.init)
+ return e.val
+}
+
+func (e *envOnce) init() {
+ for _, n := range e.names {
+ e.val = os.Getenv(n)
+ if e.val != "" {
+ return
+ }
+ }
+}
+
+// reset is used by tests
+func (e *envOnce) reset() {
+ e.once = sync.Once{}
+ e.val = ""
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/proxy/proxy_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/proxy/proxy_test.go
new file mode 100644
index 000000000..0f31e211c
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/proxy/proxy_test.go
@@ -0,0 +1,215 @@
+// Copyright 2011 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 proxy
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "net"
+ "net/url"
+ "os"
+ "strconv"
+ "strings"
+ "sync"
+ "testing"
+)
+
+type proxyFromEnvTest struct {
+ allProxyEnv string
+ noProxyEnv string
+ wantTypeOf Dialer
+}
+
+func (t proxyFromEnvTest) String() string {
+ var buf bytes.Buffer
+ space := func() {
+ if buf.Len() > 0 {
+ buf.WriteByte(' ')
+ }
+ }
+ if t.allProxyEnv != "" {
+ fmt.Fprintf(&buf, "all_proxy=%q", t.allProxyEnv)
+ }
+ if t.noProxyEnv != "" {
+ space()
+ fmt.Fprintf(&buf, "no_proxy=%q", t.noProxyEnv)
+ }
+ return strings.TrimSpace(buf.String())
+}
+
+func TestFromEnvironment(t *testing.T) {
+ ResetProxyEnv()
+
+ type dummyDialer struct {
+ direct
+ }
+
+ RegisterDialerType("irc", func(_ *url.URL, _ Dialer) (Dialer, error) {
+ return dummyDialer{}, nil
+ })
+
+ proxyFromEnvTests := []proxyFromEnvTest{
+ {allProxyEnv: "127.0.0.1:8080", noProxyEnv: "localhost, 127.0.0.1", wantTypeOf: direct{}},
+ {allProxyEnv: "ftp://example.com:8000", noProxyEnv: "localhost, 127.0.0.1", wantTypeOf: direct{}},
+ {allProxyEnv: "socks5://example.com:8080", noProxyEnv: "localhost, 127.0.0.1", wantTypeOf: &PerHost{}},
+ {allProxyEnv: "irc://example.com:8000", wantTypeOf: dummyDialer{}},
+ {noProxyEnv: "localhost, 127.0.0.1", wantTypeOf: direct{}},
+ {wantTypeOf: direct{}},
+ }
+
+ for _, tt := range proxyFromEnvTests {
+ os.Setenv("ALL_PROXY", tt.allProxyEnv)
+ os.Setenv("NO_PROXY", tt.noProxyEnv)
+ ResetCachedEnvironment()
+
+ d := FromEnvironment()
+ if got, want := fmt.Sprintf("%T", d), fmt.Sprintf("%T", tt.wantTypeOf); got != want {
+ t.Errorf("%v: got type = %T, want %T", tt, d, tt.wantTypeOf)
+ }
+ }
+}
+
+func TestFromURL(t *testing.T) {
+ endSystem, err := net.Listen("tcp", "127.0.0.1:0")
+ if err != nil {
+ t.Fatalf("net.Listen failed: %v", err)
+ }
+ defer endSystem.Close()
+ gateway, err := net.Listen("tcp", "127.0.0.1:0")
+ if err != nil {
+ t.Fatalf("net.Listen failed: %v", err)
+ }
+ defer gateway.Close()
+
+ var wg sync.WaitGroup
+ wg.Add(1)
+ go socks5Gateway(t, gateway, endSystem, socks5Domain, &wg)
+
+ url, err := url.Parse("socks5://user:password@" + gateway.Addr().String())
+ if err != nil {
+ t.Fatalf("url.Parse failed: %v", err)
+ }
+ proxy, err := FromURL(url, Direct)
+ if err != nil {
+ t.Fatalf("FromURL failed: %v", err)
+ }
+ _, port, err := net.SplitHostPort(endSystem.Addr().String())
+ if err != nil {
+ t.Fatalf("net.SplitHostPort failed: %v", err)
+ }
+ if c, err := proxy.Dial("tcp", "localhost:"+port); err != nil {
+ t.Fatalf("FromURL.Dial failed: %v", err)
+ } else {
+ c.Close()
+ }
+
+ wg.Wait()
+}
+
+func TestSOCKS5(t *testing.T) {
+ endSystem, err := net.Listen("tcp", "127.0.0.1:0")
+ if err != nil {
+ t.Fatalf("net.Listen failed: %v", err)
+ }
+ defer endSystem.Close()
+ gateway, err := net.Listen("tcp", "127.0.0.1:0")
+ if err != nil {
+ t.Fatalf("net.Listen failed: %v", err)
+ }
+ defer gateway.Close()
+
+ var wg sync.WaitGroup
+ wg.Add(1)
+ go socks5Gateway(t, gateway, endSystem, socks5IP4, &wg)
+
+ proxy, err := SOCKS5("tcp", gateway.Addr().String(), nil, Direct)
+ if err != nil {
+ t.Fatalf("SOCKS5 failed: %v", err)
+ }
+ if c, err := proxy.Dial("tcp", endSystem.Addr().String()); err != nil {
+ t.Fatalf("SOCKS5.Dial failed: %v", err)
+ } else {
+ c.Close()
+ }
+
+ wg.Wait()
+}
+
+func socks5Gateway(t *testing.T, gateway, endSystem net.Listener, typ byte, wg *sync.WaitGroup) {
+ defer wg.Done()
+
+ c, err := gateway.Accept()
+ if err != nil {
+ t.Errorf("net.Listener.Accept failed: %v", err)
+ return
+ }
+ defer c.Close()
+
+ b := make([]byte, 32)
+ var n int
+ if typ == socks5Domain {
+ n = 4
+ } else {
+ n = 3
+ }
+ if _, err := io.ReadFull(c, b[:n]); err != nil {
+ t.Errorf("io.ReadFull failed: %v", err)
+ return
+ }
+ if _, err := c.Write([]byte{socks5Version, socks5AuthNone}); err != nil {
+ t.Errorf("net.Conn.Write failed: %v", err)
+ return
+ }
+ if typ == socks5Domain {
+ n = 16
+ } else {
+ n = 10
+ }
+ if _, err := io.ReadFull(c, b[:n]); err != nil {
+ t.Errorf("io.ReadFull failed: %v", err)
+ return
+ }
+ if b[0] != socks5Version || b[1] != socks5Connect || b[2] != 0x00 || b[3] != typ {
+ t.Errorf("got an unexpected packet: %#02x %#02x %#02x %#02x", b[0], b[1], b[2], b[3])
+ return
+ }
+ if typ == socks5Domain {
+ copy(b[:5], []byte{socks5Version, 0x00, 0x00, socks5Domain, 9})
+ b = append(b, []byte("localhost")...)
+ } else {
+ copy(b[:4], []byte{socks5Version, 0x00, 0x00, socks5IP4})
+ }
+ host, port, err := net.SplitHostPort(endSystem.Addr().String())
+ if err != nil {
+ t.Errorf("net.SplitHostPort failed: %v", err)
+ return
+ }
+ b = append(b, []byte(net.ParseIP(host).To4())...)
+ p, err := strconv.Atoi(port)
+ if err != nil {
+ t.Errorf("strconv.Atoi failed: %v", err)
+ return
+ }
+ b = append(b, []byte{byte(p >> 8), byte(p)}...)
+ if _, err := c.Write(b); err != nil {
+ t.Errorf("net.Conn.Write failed: %v", err)
+ return
+ }
+}
+
+func ResetProxyEnv() {
+ for _, env := range []*envOnce{allProxyEnv, noProxyEnv} {
+ for _, v := range env.names {
+ os.Setenv(v, "")
+ }
+ }
+ ResetCachedEnvironment()
+}
+
+func ResetCachedEnvironment() {
+ allProxyEnv.reset()
+ noProxyEnv.reset()
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/proxy/socks5.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/proxy/socks5.go
new file mode 100644
index 000000000..3fed38ef1
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/proxy/socks5.go
@@ -0,0 +1,214 @@
+// Copyright 2011 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 proxy
+
+import (
+ "errors"
+ "io"
+ "net"
+ "strconv"
+)
+
+// SOCKS5 returns a Dialer that makes SOCKSv5 connections to the given address
+// with an optional username and password. See RFC 1928 and RFC 1929.
+func SOCKS5(network, addr string, auth *Auth, forward Dialer) (Dialer, error) {
+ s := &socks5{
+ network: network,
+ addr: addr,
+ forward: forward,
+ }
+ if auth != nil {
+ s.user = auth.User
+ s.password = auth.Password
+ }
+
+ return s, nil
+}
+
+type socks5 struct {
+ user, password string
+ network, addr string
+ forward Dialer
+}
+
+const socks5Version = 5
+
+const (
+ socks5AuthNone = 0
+ socks5AuthPassword = 2
+)
+
+const socks5Connect = 1
+
+const (
+ socks5IP4 = 1
+ socks5Domain = 3
+ socks5IP6 = 4
+)
+
+var socks5Errors = []string{
+ "",
+ "general failure",
+ "connection forbidden",
+ "network unreachable",
+ "host unreachable",
+ "connection refused",
+ "TTL expired",
+ "command not supported",
+ "address type not supported",
+}
+
+// Dial connects to the address addr on the given network via the SOCKS5 proxy.
+func (s *socks5) Dial(network, addr string) (net.Conn, error) {
+ switch network {
+ case "tcp", "tcp6", "tcp4":
+ default:
+ return nil, errors.New("proxy: no support for SOCKS5 proxy connections of type " + network)
+ }
+
+ conn, err := s.forward.Dial(s.network, s.addr)
+ if err != nil {
+ return nil, err
+ }
+ if err := s.connect(conn, addr); err != nil {
+ conn.Close()
+ return nil, err
+ }
+ return conn, nil
+}
+
+// connect takes an existing connection to a socks5 proxy server,
+// and commands the server to extend that connection to target,
+// which must be a canonical address with a host and port.
+func (s *socks5) connect(conn net.Conn, target string) error {
+ host, portStr, err := net.SplitHostPort(target)
+ if err != nil {
+ return err
+ }
+
+ port, err := strconv.Atoi(portStr)
+ if err != nil {
+ return errors.New("proxy: failed to parse port number: " + portStr)
+ }
+ if port < 1 || port > 0xffff {
+ return errors.New("proxy: port number out of range: " + portStr)
+ }
+
+ // the size here is just an estimate
+ buf := make([]byte, 0, 6+len(host))
+
+ buf = append(buf, socks5Version)
+ if len(s.user) > 0 && len(s.user) < 256 && len(s.password) < 256 {
+ buf = append(buf, 2 /* num auth methods */, socks5AuthNone, socks5AuthPassword)
+ } else {
+ buf = append(buf, 1 /* num auth methods */, socks5AuthNone)
+ }
+
+ if _, err := conn.Write(buf); err != nil {
+ return errors.New("proxy: failed to write greeting to SOCKS5 proxy at " + s.addr + ": " + err.Error())
+ }
+
+ if _, err := io.ReadFull(conn, buf[:2]); err != nil {
+ return errors.New("proxy: failed to read greeting from SOCKS5 proxy at " + s.addr + ": " + err.Error())
+ }
+ if buf[0] != 5 {
+ return errors.New("proxy: SOCKS5 proxy at " + s.addr + " has unexpected version " + strconv.Itoa(int(buf[0])))
+ }
+ if buf[1] == 0xff {
+ return errors.New("proxy: SOCKS5 proxy at " + s.addr + " requires authentication")
+ }
+
+ // See RFC 1929
+ if buf[1] == socks5AuthPassword {
+ buf = buf[:0]
+ buf = append(buf, 1 /* password protocol version */)
+ buf = append(buf, uint8(len(s.user)))
+ buf = append(buf, s.user...)
+ buf = append(buf, uint8(len(s.password)))
+ buf = append(buf, s.password...)
+
+ if _, err := conn.Write(buf); err != nil {
+ return errors.New("proxy: failed to write authentication request to SOCKS5 proxy at " + s.addr + ": " + err.Error())
+ }
+
+ if _, err := io.ReadFull(conn, buf[:2]); err != nil {
+ return errors.New("proxy: failed to read authentication reply from SOCKS5 proxy at " + s.addr + ": " + err.Error())
+ }
+
+ if buf[1] != 0 {
+ return errors.New("proxy: SOCKS5 proxy at " + s.addr + " rejected username/password")
+ }
+ }
+
+ buf = buf[:0]
+ buf = append(buf, socks5Version, socks5Connect, 0 /* reserved */)
+
+ if ip := net.ParseIP(host); ip != nil {
+ if ip4 := ip.To4(); ip4 != nil {
+ buf = append(buf, socks5IP4)
+ ip = ip4
+ } else {
+ buf = append(buf, socks5IP6)
+ }
+ buf = append(buf, ip...)
+ } else {
+ if len(host) > 255 {
+ return errors.New("proxy: destination host name too long: " + host)
+ }
+ buf = append(buf, socks5Domain)
+ buf = append(buf, byte(len(host)))
+ buf = append(buf, host...)
+ }
+ buf = append(buf, byte(port>>8), byte(port))
+
+ if _, err := conn.Write(buf); err != nil {
+ return errors.New("proxy: failed to write connect request to SOCKS5 proxy at " + s.addr + ": " + err.Error())
+ }
+
+ if _, err := io.ReadFull(conn, buf[:4]); err != nil {
+ return errors.New("proxy: failed to read connect reply from SOCKS5 proxy at " + s.addr + ": " + err.Error())
+ }
+
+ failure := "unknown error"
+ if int(buf[1]) < len(socks5Errors) {
+ failure = socks5Errors[buf[1]]
+ }
+
+ if len(failure) > 0 {
+ return errors.New("proxy: SOCKS5 proxy at " + s.addr + " failed to connect: " + failure)
+ }
+
+ bytesToDiscard := 0
+ switch buf[3] {
+ case socks5IP4:
+ bytesToDiscard = net.IPv4len
+ case socks5IP6:
+ bytesToDiscard = net.IPv6len
+ case socks5Domain:
+ _, err := io.ReadFull(conn, buf[:1])
+ if err != nil {
+ return errors.New("proxy: failed to read domain length from SOCKS5 proxy at " + s.addr + ": " + err.Error())
+ }
+ bytesToDiscard = int(buf[0])
+ default:
+ return errors.New("proxy: got unknown address type " + strconv.Itoa(int(buf[3])) + " from SOCKS5 proxy at " + s.addr)
+ }
+
+ if cap(buf) < bytesToDiscard {
+ buf = make([]byte, bytesToDiscard)
+ } else {
+ buf = buf[:bytesToDiscard]
+ }
+ if _, err := io.ReadFull(conn, buf); err != nil {
+ return errors.New("proxy: failed to read address from SOCKS5 proxy at " + s.addr + ": " + err.Error())
+ }
+
+ // Also need to discard the port number
+ if _, err := io.ReadFull(conn, buf[:2]); err != nil {
+ return errors.New("proxy: failed to read port from SOCKS5 proxy at " + s.addr + ": " + err.Error())
+ }
+
+ return nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/publicsuffix/gen.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/publicsuffix/gen.go
new file mode 100644
index 000000000..f85a3c32b
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/publicsuffix/gen.go
@@ -0,0 +1,713 @@
+// Copyright 2012 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.
+
+// +build ignore
+
+package main
+
+// This program generates table.go and table_test.go based on the authoritative
+// public suffix list at https://publicsuffix.org/list/effective_tld_names.dat
+//
+// The version is derived from
+// https://api.github.com/repos/publicsuffix/list/commits?path=public_suffix_list.dat
+// and a human-readable form is at
+// https://github.com/publicsuffix/list/commits/master/public_suffix_list.dat
+//
+// To fetch a particular git revision, such as 5c70ccd250, pass
+// -url "https://raw.githubusercontent.com/publicsuffix/list/5c70ccd250/public_suffix_list.dat"
+// and -version "an explicit version string".
+
+import (
+ "bufio"
+ "bytes"
+ "flag"
+ "fmt"
+ "go/format"
+ "io"
+ "io/ioutil"
+ "net/http"
+ "os"
+ "regexp"
+ "sort"
+ "strings"
+
+ "golang.org/x/net/idna"
+)
+
+const (
+ // These sum of these four values must be no greater than 32.
+ nodesBitsChildren = 10
+ nodesBitsICANN = 1
+ nodesBitsTextOffset = 15
+ nodesBitsTextLength = 6
+
+ // These sum of these four values must be no greater than 32.
+ childrenBitsWildcard = 1
+ childrenBitsNodeType = 2
+ childrenBitsHi = 14
+ childrenBitsLo = 14
+)
+
+var (
+ maxChildren int
+ maxTextOffset int
+ maxTextLength int
+ maxHi uint32
+ maxLo uint32
+)
+
+func max(a, b int) int {
+ if a < b {
+ return b
+ }
+ return a
+}
+
+func u32max(a, b uint32) uint32 {
+ if a < b {
+ return b
+ }
+ return a
+}
+
+const (
+ nodeTypeNormal = 0
+ nodeTypeException = 1
+ nodeTypeParentOnly = 2
+ numNodeType = 3
+)
+
+func nodeTypeStr(n int) string {
+ switch n {
+ case nodeTypeNormal:
+ return "+"
+ case nodeTypeException:
+ return "!"
+ case nodeTypeParentOnly:
+ return "o"
+ }
+ panic("unreachable")
+}
+
+const (
+ defaultURL = "https://publicsuffix.org/list/effective_tld_names.dat"
+ gitCommitURL = "https://api.github.com/repos/publicsuffix/list/commits?path=public_suffix_list.dat"
+)
+
+var (
+ labelEncoding = map[string]uint32{}
+ labelsList = []string{}
+ labelsMap = map[string]bool{}
+ rules = []string{}
+
+ // validSuffixRE is used to check that the entries in the public suffix
+ // list are in canonical form (after Punycode encoding). Specifically,
+ // capital letters are not allowed.
+ validSuffixRE = regexp.MustCompile(`^[a-z0-9_\!\*\-\.]+$`)
+
+ shaRE = regexp.MustCompile(`"sha":"([^"]+)"`)
+ dateRE = regexp.MustCompile(`"committer":{[^{]+"date":"([^"]+)"`)
+
+ comments = flag.Bool("comments", false, "generate table.go comments, for debugging")
+ subset = flag.Bool("subset", false, "generate only a subset of the full table, for debugging")
+ url = flag.String("url", defaultURL, "URL of the publicsuffix.org list. If empty, stdin is read instead")
+ v = flag.Bool("v", false, "verbose output (to stderr)")
+ version = flag.String("version", "", "the effective_tld_names.dat version")
+)
+
+func main() {
+ if err := main1(); err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+}
+
+func main1() error {
+ flag.Parse()
+ if nodesBitsTextLength+nodesBitsTextOffset+nodesBitsICANN+nodesBitsChildren > 32 {
+ return fmt.Errorf("not enough bits to encode the nodes table")
+ }
+ if childrenBitsLo+childrenBitsHi+childrenBitsNodeType+childrenBitsWildcard > 32 {
+ return fmt.Errorf("not enough bits to encode the children table")
+ }
+ if *version == "" {
+ if *url != defaultURL {
+ return fmt.Errorf("-version was not specified, and the -url is not the default one")
+ }
+ sha, date, err := gitCommit()
+ if err != nil {
+ return err
+ }
+ *version = fmt.Sprintf("publicsuffix.org's public_suffix_list.dat, git revision %s (%s)", sha, date)
+ }
+ var r io.Reader = os.Stdin
+ if *url != "" {
+ res, err := http.Get(*url)
+ if err != nil {
+ return err
+ }
+ if res.StatusCode != http.StatusOK {
+ return fmt.Errorf("bad GET status for %s: %d", *url, res.Status)
+ }
+ r = res.Body
+ defer res.Body.Close()
+ }
+
+ var root node
+ icann := false
+ br := bufio.NewReader(r)
+ for {
+ s, err := br.ReadString('\n')
+ if err != nil {
+ if err == io.EOF {
+ break
+ }
+ return err
+ }
+ s = strings.TrimSpace(s)
+ if strings.Contains(s, "BEGIN ICANN DOMAINS") {
+ icann = true
+ continue
+ }
+ if strings.Contains(s, "END ICANN DOMAINS") {
+ icann = false
+ continue
+ }
+ if s == "" || strings.HasPrefix(s, "//") {
+ continue
+ }
+ s, err = idna.ToASCII(s)
+ if err != nil {
+ return err
+ }
+ if !validSuffixRE.MatchString(s) {
+ return fmt.Errorf("bad publicsuffix.org list data: %q", s)
+ }
+
+ if *subset {
+ switch {
+ case s == "ac.jp" || strings.HasSuffix(s, ".ac.jp"):
+ case s == "ak.us" || strings.HasSuffix(s, ".ak.us"):
+ case s == "ao" || strings.HasSuffix(s, ".ao"):
+ case s == "ar" || strings.HasSuffix(s, ".ar"):
+ case s == "arpa" || strings.HasSuffix(s, ".arpa"):
+ case s == "cy" || strings.HasSuffix(s, ".cy"):
+ case s == "dyndns.org" || strings.HasSuffix(s, ".dyndns.org"):
+ case s == "jp":
+ case s == "kobe.jp" || strings.HasSuffix(s, ".kobe.jp"):
+ case s == "kyoto.jp" || strings.HasSuffix(s, ".kyoto.jp"):
+ case s == "om" || strings.HasSuffix(s, ".om"):
+ case s == "uk" || strings.HasSuffix(s, ".uk"):
+ case s == "uk.com" || strings.HasSuffix(s, ".uk.com"):
+ case s == "tw" || strings.HasSuffix(s, ".tw"):
+ case s == "zw" || strings.HasSuffix(s, ".zw"):
+ case s == "xn--p1ai" || strings.HasSuffix(s, ".xn--p1ai"):
+ // xn--p1ai is Russian-Cyrillic "рф".
+ default:
+ continue
+ }
+ }
+
+ rules = append(rules, s)
+
+ nt, wildcard := nodeTypeNormal, false
+ switch {
+ case strings.HasPrefix(s, "*."):
+ s, nt = s[2:], nodeTypeParentOnly
+ wildcard = true
+ case strings.HasPrefix(s, "!"):
+ s, nt = s[1:], nodeTypeException
+ }
+ labels := strings.Split(s, ".")
+ for n, i := &root, len(labels)-1; i >= 0; i-- {
+ label := labels[i]
+ n = n.child(label)
+ if i == 0 {
+ if nt != nodeTypeParentOnly && n.nodeType == nodeTypeParentOnly {
+ n.nodeType = nt
+ }
+ n.icann = n.icann && icann
+ n.wildcard = n.wildcard || wildcard
+ }
+ labelsMap[label] = true
+ }
+ }
+ labelsList = make([]string, 0, len(labelsMap))
+ for label := range labelsMap {
+ labelsList = append(labelsList, label)
+ }
+ sort.Strings(labelsList)
+
+ if err := generate(printReal, &root, "table.go"); err != nil {
+ return err
+ }
+ if err := generate(printTest, &root, "table_test.go"); err != nil {
+ return err
+ }
+ return nil
+}
+
+func generate(p func(io.Writer, *node) error, root *node, filename string) error {
+ buf := new(bytes.Buffer)
+ if err := p(buf, root); err != nil {
+ return err
+ }
+ b, err := format.Source(buf.Bytes())
+ if err != nil {
+ return err
+ }
+ return ioutil.WriteFile(filename, b, 0644)
+}
+
+func gitCommit() (sha, date string, retErr error) {
+ res, err := http.Get(gitCommitURL)
+ if err != nil {
+ return "", "", err
+ }
+ if res.StatusCode != http.StatusOK {
+ return "", "", fmt.Errorf("bad GET status for %s: %d", gitCommitURL, res.Status)
+ }
+ defer res.Body.Close()
+ b, err := ioutil.ReadAll(res.Body)
+ if err != nil {
+ return "", "", err
+ }
+ if m := shaRE.FindSubmatch(b); m != nil {
+ sha = string(m[1])
+ }
+ if m := dateRE.FindSubmatch(b); m != nil {
+ date = string(m[1])
+ }
+ if sha == "" || date == "" {
+ retErr = fmt.Errorf("could not find commit SHA and date in %s", gitCommitURL)
+ }
+ return sha, date, retErr
+}
+
+func printTest(w io.Writer, n *node) error {
+ fmt.Fprintf(w, "// generated by go run gen.go; DO NOT EDIT\n\n")
+ fmt.Fprintf(w, "package publicsuffix\n\nvar rules = [...]string{\n")
+ for _, rule := range rules {
+ fmt.Fprintf(w, "%q,\n", rule)
+ }
+ fmt.Fprintf(w, "}\n\nvar nodeLabels = [...]string{\n")
+ if err := n.walk(w, printNodeLabel); err != nil {
+ return err
+ }
+ fmt.Fprintf(w, "}\n")
+ return nil
+}
+
+func printReal(w io.Writer, n *node) error {
+ const header = `// generated by go run gen.go; DO NOT EDIT
+
+package publicsuffix
+
+const version = %q
+
+const (
+ nodesBitsChildren = %d
+ nodesBitsICANN = %d
+ nodesBitsTextOffset = %d
+ nodesBitsTextLength = %d
+
+ childrenBitsWildcard = %d
+ childrenBitsNodeType = %d
+ childrenBitsHi = %d
+ childrenBitsLo = %d
+)
+
+const (
+ nodeTypeNormal = %d
+ nodeTypeException = %d
+ nodeTypeParentOnly = %d
+)
+
+// numTLD is the number of top level domains.
+const numTLD = %d
+
+`
+ fmt.Fprintf(w, header, *version,
+ nodesBitsChildren, nodesBitsICANN, nodesBitsTextOffset, nodesBitsTextLength,
+ childrenBitsWildcard, childrenBitsNodeType, childrenBitsHi, childrenBitsLo,
+ nodeTypeNormal, nodeTypeException, nodeTypeParentOnly, len(n.children))
+
+ text := combineText(labelsList)
+ if text == "" {
+ return fmt.Errorf("internal error: makeText returned no text")
+ }
+ for _, label := range labelsList {
+ offset, length := strings.Index(text, label), len(label)
+ if offset < 0 {
+ return fmt.Errorf("internal error: could not find %q in text %q", label, text)
+ }
+ maxTextOffset, maxTextLength = max(maxTextOffset, offset), max(maxTextLength, length)
+ if offset >= 1<<nodesBitsTextOffset {
+ return fmt.Errorf("text offset %d is too large, or nodeBitsTextOffset is too small", offset)
+ }
+ if length >= 1<<nodesBitsTextLength {
+ return fmt.Errorf("text length %d is too large, or nodeBitsTextLength is too small", length)
+ }
+ labelEncoding[label] = uint32(offset)<<nodesBitsTextLength | uint32(length)
+ }
+ fmt.Fprintf(w, "// Text is the combined text of all labels.\nconst text = ")
+ for len(text) > 0 {
+ n, plus := len(text), ""
+ if n > 64 {
+ n, plus = 64, " +"
+ }
+ fmt.Fprintf(w, "%q%s\n", text[:n], plus)
+ text = text[n:]
+ }
+
+ if err := n.walk(w, assignIndexes); err != nil {
+ return err
+ }
+
+ fmt.Fprintf(w, `
+
+// nodes is the list of nodes. Each node is represented as a uint32, which
+// encodes the node's children, wildcard bit and node type (as an index into
+// the children array), ICANN bit and text.
+//
+// If the table was generated with the -comments flag, there is a //-comment
+// after each node's data. In it is the nodes-array indexes of the children,
+// formatted as (n0x1234-n0x1256), with * denoting the wildcard bit. The
+// nodeType is printed as + for normal, ! for exception, and o for parent-only
+// nodes that have children but don't match a domain label in their own right.
+// An I denotes an ICANN domain.
+//
+// The layout within the uint32, from MSB to LSB, is:
+// [%2d bits] unused
+// [%2d bits] children index
+// [%2d bits] ICANN bit
+// [%2d bits] text index
+// [%2d bits] text length
+var nodes = [...]uint32{
+`,
+ 32-nodesBitsChildren-nodesBitsICANN-nodesBitsTextOffset-nodesBitsTextLength,
+ nodesBitsChildren, nodesBitsICANN, nodesBitsTextOffset, nodesBitsTextLength)
+ if err := n.walk(w, printNode); err != nil {
+ return err
+ }
+ fmt.Fprintf(w, `}
+
+// children is the list of nodes' children, the parent's wildcard bit and the
+// parent's node type. If a node has no children then their children index
+// will be in the range [0, 6), depending on the wildcard bit and node type.
+//
+// The layout within the uint32, from MSB to LSB, is:
+// [%2d bits] unused
+// [%2d bits] wildcard bit
+// [%2d bits] node type
+// [%2d bits] high nodes index (exclusive) of children
+// [%2d bits] low nodes index (inclusive) of children
+var children=[...]uint32{
+`,
+ 32-childrenBitsWildcard-childrenBitsNodeType-childrenBitsHi-childrenBitsLo,
+ childrenBitsWildcard, childrenBitsNodeType, childrenBitsHi, childrenBitsLo)
+ for i, c := range childrenEncoding {
+ s := "---------------"
+ lo := c & (1<<childrenBitsLo - 1)
+ hi := (c >> childrenBitsLo) & (1<<childrenBitsHi - 1)
+ if lo != hi {
+ s = fmt.Sprintf("n0x%04x-n0x%04x", lo, hi)
+ }
+ nodeType := int(c>>(childrenBitsLo+childrenBitsHi)) & (1<<childrenBitsNodeType - 1)
+ wildcard := c>>(childrenBitsLo+childrenBitsHi+childrenBitsNodeType) != 0
+ if *comments {
+ fmt.Fprintf(w, "0x%08x, // c0x%04x (%s)%s %s\n",
+ c, i, s, wildcardStr(wildcard), nodeTypeStr(nodeType))
+ } else {
+ fmt.Fprintf(w, "0x%x,\n", c)
+ }
+ }
+ fmt.Fprintf(w, "}\n\n")
+ fmt.Fprintf(w, "// max children %d (capacity %d)\n", maxChildren, 1<<nodesBitsChildren-1)
+ fmt.Fprintf(w, "// max text offset %d (capacity %d)\n", maxTextOffset, 1<<nodesBitsTextOffset-1)
+ fmt.Fprintf(w, "// max text length %d (capacity %d)\n", maxTextLength, 1<<nodesBitsTextLength-1)
+ fmt.Fprintf(w, "// max hi %d (capacity %d)\n", maxHi, 1<<childrenBitsHi-1)
+ fmt.Fprintf(w, "// max lo %d (capacity %d)\n", maxLo, 1<<childrenBitsLo-1)
+ return nil
+}
+
+type node struct {
+ label string
+ nodeType int
+ icann bool
+ wildcard bool
+ // nodesIndex and childrenIndex are the index of this node in the nodes
+ // and the index of its children offset/length in the children arrays.
+ nodesIndex, childrenIndex int
+ // firstChild is the index of this node's first child, or zero if this
+ // node has no children.
+ firstChild int
+ // children are the node's children, in strictly increasing node label order.
+ children []*node
+}
+
+func (n *node) walk(w io.Writer, f func(w1 io.Writer, n1 *node) error) error {
+ if err := f(w, n); err != nil {
+ return err
+ }
+ for _, c := range n.children {
+ if err := c.walk(w, f); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// child returns the child of n with the given label. The child is created if
+// it did not exist beforehand.
+func (n *node) child(label string) *node {
+ for _, c := range n.children {
+ if c.label == label {
+ return c
+ }
+ }
+ c := &node{
+ label: label,
+ nodeType: nodeTypeParentOnly,
+ icann: true,
+ }
+ n.children = append(n.children, c)
+ sort.Sort(byLabel(n.children))
+ return c
+}
+
+type byLabel []*node
+
+func (b byLabel) Len() int { return len(b) }
+func (b byLabel) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
+func (b byLabel) Less(i, j int) bool { return b[i].label < b[j].label }
+
+var nextNodesIndex int
+
+// childrenEncoding are the encoded entries in the generated children array.
+// All these pre-defined entries have no children.
+var childrenEncoding = []uint32{
+ 0 << (childrenBitsLo + childrenBitsHi), // Without wildcard bit, nodeTypeNormal.
+ 1 << (childrenBitsLo + childrenBitsHi), // Without wildcard bit, nodeTypeException.
+ 2 << (childrenBitsLo + childrenBitsHi), // Without wildcard bit, nodeTypeParentOnly.
+ 4 << (childrenBitsLo + childrenBitsHi), // With wildcard bit, nodeTypeNormal.
+ 5 << (childrenBitsLo + childrenBitsHi), // With wildcard bit, nodeTypeException.
+ 6 << (childrenBitsLo + childrenBitsHi), // With wildcard bit, nodeTypeParentOnly.
+}
+
+var firstCallToAssignIndexes = true
+
+func assignIndexes(w io.Writer, n *node) error {
+ if len(n.children) != 0 {
+ // Assign nodesIndex.
+ n.firstChild = nextNodesIndex
+ for _, c := range n.children {
+ c.nodesIndex = nextNodesIndex
+ nextNodesIndex++
+ }
+
+ // The root node's children is implicit.
+ if firstCallToAssignIndexes {
+ firstCallToAssignIndexes = false
+ return nil
+ }
+
+ // Assign childrenIndex.
+ maxChildren = max(maxChildren, len(childrenEncoding))
+ if len(childrenEncoding) >= 1<<nodesBitsChildren {
+ return fmt.Errorf("children table size %d is too large, or nodeBitsChildren is too small", len(childrenEncoding))
+ }
+ n.childrenIndex = len(childrenEncoding)
+ lo := uint32(n.firstChild)
+ hi := lo + uint32(len(n.children))
+ maxLo, maxHi = u32max(maxLo, lo), u32max(maxHi, hi)
+ if lo >= 1<<childrenBitsLo {
+ return fmt.Errorf("children lo %d is too large, or childrenBitsLo is too small", lo)
+ }
+ if hi >= 1<<childrenBitsHi {
+ return fmt.Errorf("children hi %d is too large, or childrenBitsHi is too small", hi)
+ }
+ enc := hi<<childrenBitsLo | lo
+ enc |= uint32(n.nodeType) << (childrenBitsLo + childrenBitsHi)
+ if n.wildcard {
+ enc |= 1 << (childrenBitsLo + childrenBitsHi + childrenBitsNodeType)
+ }
+ childrenEncoding = append(childrenEncoding, enc)
+ } else {
+ n.childrenIndex = n.nodeType
+ if n.wildcard {
+ n.childrenIndex += numNodeType
+ }
+ }
+ return nil
+}
+
+func printNode(w io.Writer, n *node) error {
+ for _, c := range n.children {
+ s := "---------------"
+ if len(c.children) != 0 {
+ s = fmt.Sprintf("n0x%04x-n0x%04x", c.firstChild, c.firstChild+len(c.children))
+ }
+ encoding := labelEncoding[c.label]
+ if c.icann {
+ encoding |= 1 << (nodesBitsTextLength + nodesBitsTextOffset)
+ }
+ encoding |= uint32(c.childrenIndex) << (nodesBitsTextLength + nodesBitsTextOffset + nodesBitsICANN)
+ if *comments {
+ fmt.Fprintf(w, "0x%08x, // n0x%04x c0x%04x (%s)%s %s %s %s\n",
+ encoding, c.nodesIndex, c.childrenIndex, s, wildcardStr(c.wildcard),
+ nodeTypeStr(c.nodeType), icannStr(c.icann), c.label,
+ )
+ } else {
+ fmt.Fprintf(w, "0x%x,\n", encoding)
+ }
+ }
+ return nil
+}
+
+func printNodeLabel(w io.Writer, n *node) error {
+ for _, c := range n.children {
+ fmt.Fprintf(w, "%q,\n", c.label)
+ }
+ return nil
+}
+
+func icannStr(icann bool) string {
+ if icann {
+ return "I"
+ }
+ return " "
+}
+
+func wildcardStr(wildcard bool) string {
+ if wildcard {
+ return "*"
+ }
+ return " "
+}
+
+// combineText combines all the strings in labelsList to form one giant string.
+// Overlapping strings will be merged: "arpa" and "parliament" could yield
+// "arparliament".
+func combineText(labelsList []string) string {
+ beforeLength := 0
+ for _, s := range labelsList {
+ beforeLength += len(s)
+ }
+
+ text := crush(removeSubstrings(labelsList))
+ if *v {
+ fmt.Fprintf(os.Stderr, "crushed %d bytes to become %d bytes\n", beforeLength, len(text))
+ }
+ return text
+}
+
+type byLength []string
+
+func (s byLength) Len() int { return len(s) }
+func (s byLength) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+func (s byLength) Less(i, j int) bool { return len(s[i]) < len(s[j]) }
+
+// removeSubstrings returns a copy of its input with any strings removed
+// that are substrings of other provided strings.
+func removeSubstrings(input []string) []string {
+ // Make a copy of input.
+ ss := append(make([]string, 0, len(input)), input...)
+ sort.Sort(byLength(ss))
+
+ for i, shortString := range ss {
+ // For each string, only consider strings higher than it in sort order, i.e.
+ // of equal length or greater.
+ for _, longString := range ss[i+1:] {
+ if strings.Contains(longString, shortString) {
+ ss[i] = ""
+ break
+ }
+ }
+ }
+
+ // Remove the empty strings.
+ sort.Strings(ss)
+ for len(ss) > 0 && ss[0] == "" {
+ ss = ss[1:]
+ }
+ return ss
+}
+
+// crush combines a list of strings, taking advantage of overlaps. It returns a
+// single string that contains each input string as a substring.
+func crush(ss []string) string {
+ maxLabelLen := 0
+ for _, s := range ss {
+ if maxLabelLen < len(s) {
+ maxLabelLen = len(s)
+ }
+ }
+
+ for prefixLen := maxLabelLen; prefixLen > 0; prefixLen-- {
+ prefixes := makePrefixMap(ss, prefixLen)
+ for i, s := range ss {
+ if len(s) <= prefixLen {
+ continue
+ }
+ mergeLabel(ss, i, prefixLen, prefixes)
+ }
+ }
+
+ return strings.Join(ss, "")
+}
+
+// mergeLabel merges the label at ss[i] with the first available matching label
+// in prefixMap, where the last "prefixLen" characters in ss[i] match the first
+// "prefixLen" characters in the matching label.
+// It will merge ss[i] repeatedly until no more matches are available.
+// All matching labels merged into ss[i] are replaced by "".
+func mergeLabel(ss []string, i, prefixLen int, prefixes prefixMap) {
+ s := ss[i]
+ suffix := s[len(s)-prefixLen:]
+ for _, j := range prefixes[suffix] {
+ // Empty strings mean "already used." Also avoid merging with self.
+ if ss[j] == "" || i == j {
+ continue
+ }
+ if *v {
+ fmt.Fprintf(os.Stderr, "%d-length overlap at (%4d,%4d): %q and %q share %q\n",
+ prefixLen, i, j, ss[i], ss[j], suffix)
+ }
+ ss[i] += ss[j][prefixLen:]
+ ss[j] = ""
+ // ss[i] has a new suffix, so merge again if possible.
+ // Note: we only have to merge again at the same prefix length. Shorter
+ // prefix lengths will be handled in the next iteration of crush's for loop.
+ // Can there be matches for longer prefix lengths, introduced by the merge?
+ // I believe that any such matches would by necessity have been eliminated
+ // during substring removal or merged at a higher prefix length. For
+ // instance, in crush("abc", "cde", "bcdef"), combining "abc" and "cde"
+ // would yield "abcde", which could be merged with "bcdef." However, in
+ // practice "cde" would already have been elimintated by removeSubstrings.
+ mergeLabel(ss, i, prefixLen, prefixes)
+ return
+ }
+}
+
+// prefixMap maps from a prefix to a list of strings containing that prefix. The
+// list of strings is represented as indexes into a slice of strings stored
+// elsewhere.
+type prefixMap map[string][]int
+
+// makePrefixMap constructs a prefixMap from a slice of strings.
+func makePrefixMap(ss []string, prefixLen int) prefixMap {
+ prefixes := make(prefixMap)
+ for i, s := range ss {
+ // We use < rather than <= because if a label matches on a prefix equal to
+ // its full length, that's actually a substring match handled by
+ // removeSubstrings.
+ if prefixLen < len(s) {
+ prefix := s[:prefixLen]
+ prefixes[prefix] = append(prefixes[prefix], i)
+ }
+ }
+
+ return prefixes
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/publicsuffix/list.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/publicsuffix/list.go
new file mode 100644
index 000000000..8bbf3bcd7
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/publicsuffix/list.go
@@ -0,0 +1,135 @@
+// Copyright 2012 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:generate go run gen.go
+
+// Package publicsuffix provides a public suffix list based on data from
+// http://publicsuffix.org/. A public suffix is one under which Internet users
+// can directly register names.
+package publicsuffix // import "golang.org/x/net/publicsuffix"
+
+// TODO: specify case sensitivity and leading/trailing dot behavior for
+// func PublicSuffix and func EffectiveTLDPlusOne.
+
+import (
+ "fmt"
+ "net/http/cookiejar"
+ "strings"
+)
+
+// List implements the cookiejar.PublicSuffixList interface by calling the
+// PublicSuffix function.
+var List cookiejar.PublicSuffixList = list{}
+
+type list struct{}
+
+func (list) PublicSuffix(domain string) string {
+ ps, _ := PublicSuffix(domain)
+ return ps
+}
+
+func (list) String() string {
+ return version
+}
+
+// PublicSuffix returns the public suffix of the domain using a copy of the
+// publicsuffix.org database compiled into the library.
+//
+// icann is whether the public suffix is managed by the Internet Corporation
+// for Assigned Names and Numbers. If not, the public suffix is privately
+// managed. For example, foo.org and foo.co.uk are ICANN domains,
+// foo.dyndns.org and foo.blogspot.co.uk are private domains.
+//
+// Use cases for distinguishing ICANN domains like foo.com from private
+// domains like foo.appspot.com can be found at
+// https://wiki.mozilla.org/Public_Suffix_List/Use_Cases
+func PublicSuffix(domain string) (publicSuffix string, icann bool) {
+ lo, hi := uint32(0), uint32(numTLD)
+ s, suffix, wildcard := domain, len(domain), false
+loop:
+ for {
+ dot := strings.LastIndex(s, ".")
+ if wildcard {
+ suffix = 1 + dot
+ }
+ if lo == hi {
+ break
+ }
+ f := find(s[1+dot:], lo, hi)
+ if f == notFound {
+ break
+ }
+
+ u := nodes[f] >> (nodesBitsTextOffset + nodesBitsTextLength)
+ icann = u&(1<<nodesBitsICANN-1) != 0
+ u >>= nodesBitsICANN
+ u = children[u&(1<<nodesBitsChildren-1)]
+ lo = u & (1<<childrenBitsLo - 1)
+ u >>= childrenBitsLo
+ hi = u & (1<<childrenBitsHi - 1)
+ u >>= childrenBitsHi
+ switch u & (1<<childrenBitsNodeType - 1) {
+ case nodeTypeNormal:
+ suffix = 1 + dot
+ case nodeTypeException:
+ suffix = 1 + len(s)
+ break loop
+ }
+ u >>= childrenBitsNodeType
+ wildcard = u&(1<<childrenBitsWildcard-1) != 0
+
+ if dot == -1 {
+ break
+ }
+ s = s[:dot]
+ }
+ if suffix == len(domain) {
+ // If no rules match, the prevailing rule is "*".
+ return domain[1+strings.LastIndex(domain, "."):], icann
+ }
+ return domain[suffix:], icann
+}
+
+const notFound uint32 = 1<<32 - 1
+
+// find returns the index of the node in the range [lo, hi) whose label equals
+// label, or notFound if there is no such node. The range is assumed to be in
+// strictly increasing node label order.
+func find(label string, lo, hi uint32) uint32 {
+ for lo < hi {
+ mid := lo + (hi-lo)/2
+ s := nodeLabel(mid)
+ if s < label {
+ lo = mid + 1
+ } else if s == label {
+ return mid
+ } else {
+ hi = mid
+ }
+ }
+ return notFound
+}
+
+// nodeLabel returns the label for the i'th node.
+func nodeLabel(i uint32) string {
+ x := nodes[i]
+ length := x & (1<<nodesBitsTextLength - 1)
+ x >>= nodesBitsTextLength
+ offset := x & (1<<nodesBitsTextOffset - 1)
+ return text[offset : offset+length]
+}
+
+// EffectiveTLDPlusOne returns the effective top level domain plus one more
+// label. For example, the eTLD+1 for "foo.bar.golang.org" is "golang.org".
+func EffectiveTLDPlusOne(domain string) (string, error) {
+ suffix, _ := PublicSuffix(domain)
+ if len(domain) <= len(suffix) {
+ return "", fmt.Errorf("publicsuffix: cannot derive eTLD+1 for domain %q", domain)
+ }
+ i := len(domain) - len(suffix) - 1
+ if domain[i] != '.' {
+ return "", fmt.Errorf("publicsuffix: invalid public suffix %q for domain %q", suffix, domain)
+ }
+ return domain[1+strings.LastIndex(domain[:i], "."):], nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/publicsuffix/list_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/publicsuffix/list_test.go
new file mode 100644
index 000000000..42d79cc43
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/publicsuffix/list_test.go
@@ -0,0 +1,416 @@
+// Copyright 2012 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 publicsuffix
+
+import (
+ "sort"
+ "strings"
+ "testing"
+)
+
+func TestNodeLabel(t *testing.T) {
+ for i, want := range nodeLabels {
+ got := nodeLabel(uint32(i))
+ if got != want {
+ t.Errorf("%d: got %q, want %q", i, got, want)
+ }
+ }
+}
+
+func TestFind(t *testing.T) {
+ testCases := []string{
+ "",
+ "a",
+ "a0",
+ "aaaa",
+ "ao",
+ "ap",
+ "ar",
+ "aro",
+ "arp",
+ "arpa",
+ "arpaa",
+ "arpb",
+ "az",
+ "b",
+ "b0",
+ "ba",
+ "z",
+ "zu",
+ "zv",
+ "zw",
+ "zx",
+ "zy",
+ "zz",
+ "zzzz",
+ }
+ for _, tc := range testCases {
+ got := find(tc, 0, numTLD)
+ want := notFound
+ for i := uint32(0); i < numTLD; i++ {
+ if tc == nodeLabel(i) {
+ want = i
+ break
+ }
+ }
+ if got != want {
+ t.Errorf("%q: got %d, want %d", tc, got, want)
+ }
+ }
+}
+
+func TestICANN(t *testing.T) {
+ testCases := map[string]bool{
+ "foo.org": true,
+ "foo.co.uk": true,
+ "foo.dyndns.org": false,
+ "foo.go.dyndns.org": false,
+ "foo.blogspot.co.uk": false,
+ "foo.intranet": false,
+ }
+ for domain, want := range testCases {
+ _, got := PublicSuffix(domain)
+ if got != want {
+ t.Errorf("%q: got %v, want %v", domain, got, want)
+ }
+ }
+}
+
+var publicSuffixTestCases = []struct {
+ domain, want string
+}{
+ // Empty string.
+ {"", ""},
+
+ // The .ao rules are:
+ // ao
+ // ed.ao
+ // gv.ao
+ // og.ao
+ // co.ao
+ // pb.ao
+ // it.ao
+ {"ao", "ao"},
+ {"www.ao", "ao"},
+ {"pb.ao", "pb.ao"},
+ {"www.pb.ao", "pb.ao"},
+ {"www.xxx.yyy.zzz.pb.ao", "pb.ao"},
+
+ // The .ar rules are:
+ // ar
+ // com.ar
+ // edu.ar
+ // gob.ar
+ // gov.ar
+ // int.ar
+ // mil.ar
+ // net.ar
+ // org.ar
+ // tur.ar
+ // blogspot.com.ar
+ {"ar", "ar"},
+ {"www.ar", "ar"},
+ {"nic.ar", "ar"},
+ {"www.nic.ar", "ar"},
+ {"com.ar", "com.ar"},
+ {"www.com.ar", "com.ar"},
+ {"blogspot.com.ar", "blogspot.com.ar"},
+ {"www.blogspot.com.ar", "blogspot.com.ar"},
+ {"www.xxx.yyy.zzz.blogspot.com.ar", "blogspot.com.ar"},
+ {"logspot.com.ar", "com.ar"},
+ {"zlogspot.com.ar", "com.ar"},
+ {"zblogspot.com.ar", "com.ar"},
+
+ // The .arpa rules are:
+ // arpa
+ // e164.arpa
+ // in-addr.arpa
+ // ip6.arpa
+ // iris.arpa
+ // uri.arpa
+ // urn.arpa
+ {"arpa", "arpa"},
+ {"www.arpa", "arpa"},
+ {"urn.arpa", "urn.arpa"},
+ {"www.urn.arpa", "urn.arpa"},
+ {"www.xxx.yyy.zzz.urn.arpa", "urn.arpa"},
+
+ // The relevant {kobe,kyoto}.jp rules are:
+ // jp
+ // *.kobe.jp
+ // !city.kobe.jp
+ // kyoto.jp
+ // ide.kyoto.jp
+ {"jp", "jp"},
+ {"kobe.jp", "jp"},
+ {"c.kobe.jp", "c.kobe.jp"},
+ {"b.c.kobe.jp", "c.kobe.jp"},
+ {"a.b.c.kobe.jp", "c.kobe.jp"},
+ {"city.kobe.jp", "kobe.jp"},
+ {"www.city.kobe.jp", "kobe.jp"},
+ {"kyoto.jp", "kyoto.jp"},
+ {"test.kyoto.jp", "kyoto.jp"},
+ {"ide.kyoto.jp", "ide.kyoto.jp"},
+ {"b.ide.kyoto.jp", "ide.kyoto.jp"},
+ {"a.b.ide.kyoto.jp", "ide.kyoto.jp"},
+
+ // The .tw rules are:
+ // tw
+ // edu.tw
+ // gov.tw
+ // mil.tw
+ // com.tw
+ // net.tw
+ // org.tw
+ // idv.tw
+ // game.tw
+ // ebiz.tw
+ // club.tw
+ // 網路.tw (xn--zf0ao64a.tw)
+ // 組織.tw (xn--uc0atv.tw)
+ // 商業.tw (xn--czrw28b.tw)
+ // blogspot.tw
+ {"tw", "tw"},
+ {"aaa.tw", "tw"},
+ {"www.aaa.tw", "tw"},
+ {"xn--czrw28b.aaa.tw", "tw"},
+ {"edu.tw", "edu.tw"},
+ {"www.edu.tw", "edu.tw"},
+ {"xn--czrw28b.edu.tw", "edu.tw"},
+ {"xn--czrw28b.tw", "xn--czrw28b.tw"},
+ {"www.xn--czrw28b.tw", "xn--czrw28b.tw"},
+ {"xn--uc0atv.xn--czrw28b.tw", "xn--czrw28b.tw"},
+ {"xn--kpry57d.tw", "tw"},
+
+ // The .uk rules are:
+ // uk
+ // ac.uk
+ // co.uk
+ // gov.uk
+ // ltd.uk
+ // me.uk
+ // net.uk
+ // nhs.uk
+ // org.uk
+ // plc.uk
+ // police.uk
+ // *.sch.uk
+ // blogspot.co.uk
+ {"uk", "uk"},
+ {"aaa.uk", "uk"},
+ {"www.aaa.uk", "uk"},
+ {"mod.uk", "uk"},
+ {"www.mod.uk", "uk"},
+ {"sch.uk", "uk"},
+ {"mod.sch.uk", "mod.sch.uk"},
+ {"www.sch.uk", "www.sch.uk"},
+ {"blogspot.co.uk", "blogspot.co.uk"},
+ {"blogspot.nic.uk", "uk"},
+ {"blogspot.sch.uk", "blogspot.sch.uk"},
+
+ // The .рф rules are
+ // рф (xn--p1ai)
+ {"xn--p1ai", "xn--p1ai"},
+ {"aaa.xn--p1ai", "xn--p1ai"},
+ {"www.xxx.yyy.xn--p1ai", "xn--p1ai"},
+
+ // The .bd rules are:
+ // *.bd
+ {"bd", "bd"},
+ {"www.bd", "www.bd"},
+ {"zzz.bd", "zzz.bd"},
+ {"www.zzz.bd", "zzz.bd"},
+ {"www.xxx.yyy.zzz.bd", "zzz.bd"},
+
+ // There are no .nosuchtld rules.
+ {"nosuchtld", "nosuchtld"},
+ {"foo.nosuchtld", "nosuchtld"},
+ {"bar.foo.nosuchtld", "nosuchtld"},
+}
+
+func BenchmarkPublicSuffix(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ for _, tc := range publicSuffixTestCases {
+ List.PublicSuffix(tc.domain)
+ }
+ }
+}
+
+func TestPublicSuffix(t *testing.T) {
+ for _, tc := range publicSuffixTestCases {
+ got := List.PublicSuffix(tc.domain)
+ if got != tc.want {
+ t.Errorf("%q: got %q, want %q", tc.domain, got, tc.want)
+ }
+ }
+}
+
+func TestSlowPublicSuffix(t *testing.T) {
+ for _, tc := range publicSuffixTestCases {
+ got := slowPublicSuffix(tc.domain)
+ if got != tc.want {
+ t.Errorf("%q: got %q, want %q", tc.domain, got, tc.want)
+ }
+ }
+}
+
+// slowPublicSuffix implements the canonical (but O(number of rules)) public
+// suffix algorithm described at http://publicsuffix.org/list/.
+//
+// 1. Match domain against all rules and take note of the matching ones.
+// 2. If no rules match, the prevailing rule is "*".
+// 3. If more than one rule matches, the prevailing rule is the one which is an exception rule.
+// 4. If there is no matching exception rule, the prevailing rule is the one with the most labels.
+// 5. If the prevailing rule is a exception rule, modify it by removing the leftmost label.
+// 6. The public suffix is the set of labels from the domain which directly match the labels of the prevailing rule (joined by dots).
+// 7. The registered or registrable domain is the public suffix plus one additional label.
+//
+// This function returns the public suffix, not the registrable domain, and so
+// it stops after step 6.
+func slowPublicSuffix(domain string) string {
+ match := func(rulePart, domainPart string) bool {
+ switch rulePart[0] {
+ case '*':
+ return true
+ case '!':
+ return rulePart[1:] == domainPart
+ }
+ return rulePart == domainPart
+ }
+
+ domainParts := strings.Split(domain, ".")
+ var matchingRules [][]string
+
+loop:
+ for _, rule := range rules {
+ ruleParts := strings.Split(rule, ".")
+ if len(domainParts) < len(ruleParts) {
+ continue
+ }
+ for i := range ruleParts {
+ rulePart := ruleParts[len(ruleParts)-1-i]
+ domainPart := domainParts[len(domainParts)-1-i]
+ if !match(rulePart, domainPart) {
+ continue loop
+ }
+ }
+ matchingRules = append(matchingRules, ruleParts)
+ }
+ if len(matchingRules) == 0 {
+ matchingRules = append(matchingRules, []string{"*"})
+ } else {
+ sort.Sort(byPriority(matchingRules))
+ }
+ prevailing := matchingRules[0]
+ if prevailing[0][0] == '!' {
+ prevailing = prevailing[1:]
+ }
+ if prevailing[0][0] == '*' {
+ replaced := domainParts[len(domainParts)-len(prevailing)]
+ prevailing = append([]string{replaced}, prevailing[1:]...)
+ }
+ return strings.Join(prevailing, ".")
+}
+
+type byPriority [][]string
+
+func (b byPriority) Len() int { return len(b) }
+func (b byPriority) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
+func (b byPriority) Less(i, j int) bool {
+ if b[i][0][0] == '!' {
+ return true
+ }
+ if b[j][0][0] == '!' {
+ return false
+ }
+ return len(b[i]) > len(b[j])
+}
+
+// eTLDPlusOneTestCases come from
+// https://github.com/publicsuffix/list/blob/master/tests/test_psl.txt
+var eTLDPlusOneTestCases = []struct {
+ domain, want string
+}{
+ // Empty input.
+ {"", ""},
+ // Unlisted TLD.
+ {"example", ""},
+ {"example.example", "example.example"},
+ {"b.example.example", "example.example"},
+ {"a.b.example.example", "example.example"},
+ // TLD with only 1 rule.
+ {"biz", ""},
+ {"domain.biz", "domain.biz"},
+ {"b.domain.biz", "domain.biz"},
+ {"a.b.domain.biz", "domain.biz"},
+ // TLD with some 2-level rules.
+ {"com", ""},
+ {"example.com", "example.com"},
+ {"b.example.com", "example.com"},
+ {"a.b.example.com", "example.com"},
+ {"uk.com", ""},
+ {"example.uk.com", "example.uk.com"},
+ {"b.example.uk.com", "example.uk.com"},
+ {"a.b.example.uk.com", "example.uk.com"},
+ {"test.ac", "test.ac"},
+ // TLD with only 1 (wildcard) rule.
+ {"mm", ""},
+ {"c.mm", ""},
+ {"b.c.mm", "b.c.mm"},
+ {"a.b.c.mm", "b.c.mm"},
+ // More complex TLD.
+ {"jp", ""},
+ {"test.jp", "test.jp"},
+ {"www.test.jp", "test.jp"},
+ {"ac.jp", ""},
+ {"test.ac.jp", "test.ac.jp"},
+ {"www.test.ac.jp", "test.ac.jp"},
+ {"kyoto.jp", ""},
+ {"test.kyoto.jp", "test.kyoto.jp"},
+ {"ide.kyoto.jp", ""},
+ {"b.ide.kyoto.jp", "b.ide.kyoto.jp"},
+ {"a.b.ide.kyoto.jp", "b.ide.kyoto.jp"},
+ {"c.kobe.jp", ""},
+ {"b.c.kobe.jp", "b.c.kobe.jp"},
+ {"a.b.c.kobe.jp", "b.c.kobe.jp"},
+ {"city.kobe.jp", "city.kobe.jp"},
+ {"www.city.kobe.jp", "city.kobe.jp"},
+ // TLD with a wildcard rule and exceptions.
+ {"ck", ""},
+ {"test.ck", ""},
+ {"b.test.ck", "b.test.ck"},
+ {"a.b.test.ck", "b.test.ck"},
+ {"www.ck", "www.ck"},
+ {"www.www.ck", "www.ck"},
+ // US K12.
+ {"us", ""},
+ {"test.us", "test.us"},
+ {"www.test.us", "test.us"},
+ {"ak.us", ""},
+ {"test.ak.us", "test.ak.us"},
+ {"www.test.ak.us", "test.ak.us"},
+ {"k12.ak.us", ""},
+ {"test.k12.ak.us", "test.k12.ak.us"},
+ {"www.test.k12.ak.us", "test.k12.ak.us"},
+ // Punycoded IDN labels
+ {"xn--85x722f.com.cn", "xn--85x722f.com.cn"},
+ {"xn--85x722f.xn--55qx5d.cn", "xn--85x722f.xn--55qx5d.cn"},
+ {"www.xn--85x722f.xn--55qx5d.cn", "xn--85x722f.xn--55qx5d.cn"},
+ {"shishi.xn--55qx5d.cn", "shishi.xn--55qx5d.cn"},
+ {"xn--55qx5d.cn", ""},
+ {"xn--85x722f.xn--fiqs8s", "xn--85x722f.xn--fiqs8s"},
+ {"www.xn--85x722f.xn--fiqs8s", "xn--85x722f.xn--fiqs8s"},
+ {"shishi.xn--fiqs8s", "shishi.xn--fiqs8s"},
+ {"xn--fiqs8s", ""},
+}
+
+func TestEffectiveTLDPlusOne(t *testing.T) {
+ for _, tc := range eTLDPlusOneTestCases {
+ got, _ := EffectiveTLDPlusOne(tc.domain)
+ if got != tc.want {
+ t.Errorf("%q: got %q, want %q", tc.domain, got, tc.want)
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/publicsuffix/table.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/publicsuffix/table.go
new file mode 100644
index 000000000..549511c88
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/publicsuffix/table.go
@@ -0,0 +1,9419 @@
+// generated by go run gen.go; DO NOT EDIT
+
+package publicsuffix
+
+const version = "publicsuffix.org's public_suffix_list.dat, git revision 38b238d6324042f2c2e6270459d1f4ccfe789fba (2017-08-28T20:09:01Z)"
+
+const (
+ nodesBitsChildren = 10
+ nodesBitsICANN = 1
+ nodesBitsTextOffset = 15
+ nodesBitsTextLength = 6
+
+ childrenBitsWildcard = 1
+ childrenBitsNodeType = 2
+ childrenBitsHi = 14
+ childrenBitsLo = 14
+)
+
+const (
+ nodeTypeNormal = 0
+ nodeTypeException = 1
+ nodeTypeParentOnly = 2
+)
+
+// numTLD is the number of top level domains.
+const numTLD = 1557
+
+// Text is the combined text of all labels.
+const text = "bifukagawalterbihorologyukuhashimoichinosekigaharaxastronomy-gat" +
+ "ewaybomloans3-ca-central-1bikedagestangeorgeorgiabilbaogakihokum" +
+ "akogengerdalces3-website-us-west-1billustrationikinuyamashinashi" +
+ "kitchenikkoebenhavnikolaevents3-website-us-west-2bioddabirdartce" +
+ "nterprisesakikugawarszawashingtondclkariyameldalindesnesakurainv" +
+ "estmentsakyotanabellunord-odalivornomutashinainzais-a-candidateb" +
+ "irkenesoddtangenovaraumalopolskanlandrayddnsfreebox-oslocus-3bir" +
+ "thplacebitballooningladefinimakanegasakindlegokasells-for-lessal" +
+ "angenikonantankarlsoyurihonjoyentattoolsztynsettlersalondonetska" +
+ "rmoyusuharabjarkoyusuisserveexchangebjerkreimbalsfjordgcahcesuol" +
+ "ocalhostrodawaraugustowadaegubalsanagochihayaakasakawaharanzanne" +
+ "frankfurtarumizusawabkhaziamallamagazineat-url-o-g-i-naturalhist" +
+ "orymuseumcentereviewskrakowebredirectmeteorappaleobihirosakikami" +
+ "jimabogadocscbgdyniabruzzoologicalvinklein-addrammenuernberggfar" +
+ "merseinebinagisochildrensgardenaturalsciencesnaturelles3-ap-nort" +
+ "heast-2ixboxenapponazure-mobileastcoastaldefenceatonsberg12000em" +
+ "mafanconagawakayamadridvagsoyericssonyoursidealerimo-i-ranaamesj" +
+ "evuemielno-ip6bjugninohekinannestadraydnsaltdalombardiamondsalva" +
+ "dordalibabalatinord-frontierblockbustermezjavald-aostaplesalzbur" +
+ "glassassinationalheritagematsubarakawagoebloombergbauerninomiyak" +
+ "onojosoyrorosamegawabloxcmsamnangerbluedancebmoattachmentsamsclu" +
+ "bindalombardynamisches-dnsamsungleezebmsandvikcoromantovalle-d-a" +
+ "ostathellebmwedeployuufcfanirasakis-a-catererbnpparibaselburgliw" +
+ "icebnrwegroweibolzanorddalomzaporizhzheguris-a-celticsfanishiaza" +
+ "is-a-chefarmsteadrivelandrobaknoluoktachikawalbrzycharternidrudu" +
+ "nsanfranciscofreakunedre-eikerbonnishigoppdalorenskoglobalashovh" +
+ "achinohedmarkarpaczeladzlglobodoes-itvedestrandupontariobookingl" +
+ "ogoweirboomladbrokesangobootsanjournalismailillesandefjordurbana" +
+ "mexnetlifyis-a-conservativefsnillfjordurhamburgloppenzaogashimad" +
+ "achicagoboatsannanishiharaboschaefflerdalotenkawabostikaruizawab" +
+ "ostonakijinsekikogentingmbhartiffanyuzawabotanicalgardenishiizun" +
+ "azukis-a-cpadualstackspace-to-rentalstomakomaibarabotanicgardeni" +
+ "shikatakayamatta-varjjataxihuanishikatsuragit-repostfoldnavybota" +
+ "nybouncemerckmsdnipropetrovskjervoyagebounty-fullensakerryproper" +
+ "tiesannohelplfinancialotteboutiquebecngminakamichiharabozentsuji" +
+ "iebplacedekagaminordkappgafanpachigasakievennodesashibetsukumiya" +
+ "mazonawsaarlandyndns-at-workinggroupalmspringsakerbrandywinevall" +
+ "eybrasiliabresciabrindisibenikebristoloseyouripirangapartmentsan" +
+ "okarumaifarsundyndns-blogdnsantabarbarabritishcolumbialowiezachp" +
+ "omorskienishikawazukamitsuebroadcastlefrakkestadyndns-freeboxost" +
+ "rowwlkpmgmodenakatombetsumitakagiizebroadwaybroke-itgorybrokerbr" +
+ "onnoysundyndns-homednsantacruzsantafedjeffersonishimerabrotherme" +
+ "saverdeatnurembergmxfinitybrowsersafetymarketsanukis-a-cubicle-s" +
+ "lavellinotteroybrumunddalottokonamegatakasugais-a-democratjeldsu" +
+ "ndyndns-ipamperedchefashionishinomiyashironobrunelasticbeanstalk" +
+ "asaokaminoyamaxunusualpersonishinoomotegobrusselsaotomeloyalistj" +
+ "ordalshalsenishinoshimattelefonicarbonia-iglesias-carboniaiglesi" +
+ "ascarboniabruxellesapodlasiellaktyubinskiptveterinairealtorlandy" +
+ "ndns-mailouvrehabmerbryanskleppanamabrynewjerseybuskerudinewport" +
+ "lligatjmaxxxjaworznowtv-infoodnetworkshoppingrimstadyndns-office" +
+ "-on-the-webcambulancebuzenishiokoppegardyndns-picsapporobuzzpana" +
+ "sonicateringebugattipschlesischesardegnamsskoganeis-a-designerim" +
+ "arumorimachidabwfastlylbaltimore-og-romsdalillyokozehimejibigawa" +
+ "ukraanghkeymachinewhampshirebungoonord-aurdalpha-myqnapcloudacce" +
+ "sscambridgestonemurorangeiseiyoichippubetsubetsugaruhrhcloudns3-" +
+ "eu-central-1bzhitomirumalselvendrellowiczest-le-patronishitosash" +
+ "imizunaminamiashigaracompute-1computerhistoryofscience-fictionco" +
+ "msecuritytacticsaseboknowsitallvivano-frankivskasuyanagawacondos" +
+ "hichinohealth-carereformitakeharaconferenceconstructionconsulado" +
+ "esntexistanbullensvanguardyndns-workisboringrueconsultanthropolo" +
+ "gyconsultingvollcontactoyonocontemporaryarteducationalchikugodoh" +
+ "aruovatoyookannamifunecontractorskenconventureshinodearthdfcbank" +
+ "aszubycookingchannelsdvrdnsdojoetsuwanouchikujogaszczytnordreisa" +
+ "-geekatowicecoolkuszkolahppiacenzaganquannakadomarineustarhubsas" +
+ "katchewancooperaunitemp-dnsassaris-a-gurulsandoycopenhagencyclop" +
+ "edichernihivanovodkagoshimalvikashibatakashimaseratis-a-financia" +
+ "ladvisor-aurdalucaniacorsicagliaridagawashtenawdev-myqnapcloudap" +
+ "plebtimnetzwhoswhokksundyndns1corvettenrightathomeftparliamentoy" +
+ "osatoyakokonoecosenzakopanerairguardiann-arboretumbriacosidnsfor" +
+ "-better-thanawatchesatxn--12c1fe0bradescorporationcostumedio-cam" +
+ "pidano-mediocampidanomediocouchpotatofriesaudacouncilcouponsauhe" +
+ "radynnsavannahgacoursesaves-the-whalessandria-trani-barletta-and" +
+ "riatranibarlettaandriacqhachiojiyahoooshikamaishimodatecranbrook" +
+ "uwanalyticsavonaplesaxocreditcardynulvikatsushikabeeldengeluidyn" +
+ "v6creditunioncremonashgabadaddjambylcrewiiheyakagecricketrzyncri" +
+ "meast-kazakhstanangercrotonexus-2crownprovidercrsvparmacruisesbs" +
+ "chokoladencryptonomichigangwoncuisinellair-traffic-controlleycul" +
+ "turalcentertainmentoyotaris-a-hard-workercuneocupcakecxn--12cfi8" +
+ "ixb8lcyberlevagangaviikanonjis-a-huntercymrussiacyonabarunzencyo" +
+ "utheworkpccwildlifedorainfracloudcontrolledogawarabikomaezakirun" +
+ "orfolkebibleikangerfidonnakaniikawatanagurafieldfiguerestauranto" +
+ "yotsukaidownloadfilateliafilegearfilminamiechizenfinalfinancefin" +
+ "eartscientistockholmestrandfinlandfinnoyfirebaseapparscjohnsonfi" +
+ "renzefirestonefirmdaleirvikatsuyamasfjordenfishingolffanscotland" +
+ "fitjarfitnessettlementoyourafjalerflesbergulenflickragerotikakeg" +
+ "awaflightscrapper-siteflirflogintogurafloraflorencefloridavvesii" +
+ "dazaifudaigojomedizinhistorischescrappingunmarburguovdageaidnusl" +
+ "ivinghistoryfloripaderbornfloristanohatakahamangyshlakasamatsudo" +
+ "ntexisteingeekaufenflorogerserveftpartis-a-landscaperflowerserve" +
+ "game-serversicherungushikamifuranortonflynnhostingxn--1ck2e1bamb" +
+ "leclercasadelamonedatingjerstadotsuruokakudamatsuemrflynnhubanan" +
+ "arepublicaseihichisobetsuitainairforcechirealmetlifeinsuranceu-1" +
+ "fndfor-ourfor-someethnologyfor-theaterforexrothachirogatakahatak" +
+ "aishimogosenforgotdnservehalflifestyleforli-cesena-forlicesenafo" +
+ "rlikescandynamic-dnservehttpartnerservehumourforsaleitungsenfors" +
+ "andasuolodingenfortmissoulancashireggio-calabriafortworthadanose" +
+ "gawaforuminamifuranofosneserveirchernovtsykkylvenetogakushimotog" +
+ "anewyorkshirecipesaro-urbino-pesarourbinopesaromasvuotnaharimamu" +
+ "rogawassamukawataricohdatsunanjoburgriwataraidyndns-remotewdyndn" +
+ "s-serverdaluccapitalonewspaperfotaruis-a-lawyerfoxfordebianfredr" +
+ "ikstadtvserveminecraftoystre-slidrettozawafreeddnsgeekgalaxyfree" +
+ "masonryfreesitexascolipicenogiftservemp3freetlservep2partservepi" +
+ "cservequakefreiburgfreightcminamiiselectozsdeloittevadsoccertifi" +
+ "cationfresenius-4fribourgfriuli-v-giuliafriuli-ve-giuliafriuli-v" +
+ "egiuliafriuli-venezia-giuliafriuli-veneziagiuliafriuli-vgiuliafr" +
+ "iuliv-giuliafriulive-giuliafriulivegiuliafriulivenezia-giuliafri" +
+ "uliveneziagiuliafriulivgiuliafrlfroganservesarcasmatartanddesign" +
+ "frognfrolandfrom-akrehamnfrom-alfrom-arfrom-azfrom-capebretonami" +
+ "astalowa-wolayangroupartyfrom-coguchikuzenfrom-ctrani-andria-bar" +
+ "letta-trani-andriafrom-dchirurgiens-dentistes-en-francefrom-dedy" +
+ "n-ip24from-flanderservicesettsurgeonshalloffamemergencyachtsevas" +
+ "topolefrom-gausdalfrom-higashiagatsumagoizumizakirkenesevenassis" +
+ "icilyfrom-iafrom-idfrom-ilfrom-incheonfrom-ksewilliamhillfrom-ky" +
+ "owariasahikawafrom-lancasterfrom-maniwakuratextileksvikautokeino" +
+ "from-mdfrom-megurokunohealthcareersharis-a-liberalfrom-microsoft" +
+ "bankazofrom-mnfrom-modellingfrom-msharpasadenamsosnowiechiryukyu" +
+ "ragifuchungbukharafrom-mtnfrom-nchitachinakagawatchandclockashih" +
+ "arafrom-ndfrom-nefrom-nhktraniandriabarlettatraniandriafrom-njcb" +
+ "nlfrom-nminamiizukamishihoronobeauxartsandcraftshawaiijimarugame" +
+ "-hostrolekamikitayamatsuris-a-libertarianfrom-nvalled-aostatoilf" +
+ "rom-nyfrom-ohkurafrom-oketohmannorth-kazakhstanfrom-orfrom-padov" +
+ "aksdalfrom-pratohnoshooguyfrom-rivnefrom-schoenbrunnfrom-sdfrom-" +
+ "tnfrom-txn--1ctwolominamatakkokamiokamiminershellaspeziafrom-uta" +
+ "zuerichardlillehammerfeste-ipassagenshimojis-a-linux-useranishia" +
+ "ritabashijonawatefrom-val-daostavalleyfrom-vtranoyfrom-wafrom-wi" +
+ "elunnerfrom-wvalledaostavangerfrom-wyfrosinonefrostalbanshimokaw" +
+ "afroyahikobeardubaiduckdnshimokitayamafstavernfujiiderafujikawag" +
+ "uchikonefujiminohtawaramotoineppubolognakanotoddenfujinomiyadafu" +
+ "jiokayamansionshimonitayanagithubusercontentransportransurlfujis" +
+ "atoshonairtelecitychyattorneyagawakuyabukidsmynasushiobaragusart" +
+ "shimonosekikawafujisawafujishiroishidakabiratoridefenseljordfuji" +
+ "tsurugashimaritimekeepingfujixeroxn--1lqs03nfujiyoshidafukayabea" +
+ "tshimosuwalkis-a-llamarylandfukuchiyamadafukudominichitosetogits" +
+ "uldalucernefukuis-a-musicianfukumitsubishigakirovogradoyfukuokaz" +
+ "akiryuohadselfipassenger-associationfukuroishikarikaturindalfuku" +
+ "sakisarazurewebsiteshikagamiishibukawafukuyamagatakaharufunabash" +
+ "iriuchinadafunagatakahashimamakishiwadafunahashikamiamakusatsuma" +
+ "sendaisennangonohejis-a-nascarfanfundaciofuoiskujukuriyamanxn--1" +
+ "lqs71dfuosskoczowinbarcelonagasakikonaikawachinaganoharamcoacham" +
+ "pionshiphoptobishimaizurugbydgoszczecinemakeupowiathletajimabari" +
+ "akembuchikumagayagawakkanaibetsubamericanfamilydscloudcontrolapp" +
+ "spotagerfurnitureggio-emilia-romagnakasatsunairtrafficplexus-1fu" +
+ "rubiraquarellebesbyenglandfurudonostiaarpaviancarrierfurukawais-" +
+ "a-nurservebbshimotsukefusodegaurafussagamiharafutabayamaguchinom" +
+ "igawafutboldlygoingnowhere-for-moregontrailroadfuttsurugimperiaf" +
+ "uturecmshimotsumafuturehostingfuturemailingfvgfylkesbiblackfrida" +
+ "yfyresdalhangglidinghangoutsystemscloudfunctionshinichinanhannan" +
+ "mokuizumodernhannotaireshinjournalisteinkjerusalembroideryhanyuz" +
+ "enhapmirhareidsbergenharstadharvestcelebrationhasamarcheapgfoggi" +
+ "ahasaminami-alpssells-itrapaniimimatakatoris-a-playerhashbanghas" +
+ "udahasura-appharmacienshinjukumanohasvikazunohatogayaitakamoriok" +
+ "aluganskolevangerhatoyamazakitahiroshimarnardalhatsukaichikaisei" +
+ "s-a-republicancerresearchaeologicaliforniahattfjelldalhayashimam" +
+ "otobungotakadapliernewmexicodyn-vpnplusterhazuminobusellsyourhom" +
+ "egoodshinkamigotoyohashimotoshimahboehringerikehelsinkitakamiizu" +
+ "misanofidelityhembygdsforbundhemneshinshinotsurgeryhemsedalhepfo" +
+ "rgeherokussldheroyhgtvallee-aosteroyhigashichichibunkyonanaoshim" +
+ "ageandsoundandvisionhigashihiroshimanehigashiizumozakitakatakana" +
+ "beautysfjordhigashikagawahigashikagurasoedahigashikawakitaaikita" +
+ "kyushuaiahigashikurumeiwamarriottravelchannelhigashimatsushimars" +
+ "hallstatebankddielddanuorrikuzentakataiwanairlinebraskaunjargals" +
+ "aceohigashimatsuyamakitaakitadaitoigawahigashimurayamamotorcycle" +
+ "shinshirohigashinarusembokukitamidoris-a-rockstarachowicehigashi" +
+ "nehigashiomihachimanchesterhigashiosakasayamanakakogawahigashish" +
+ "irakawamatakanezawahigashisumiyoshikawaminamiaikitamotosumy-rout" +
+ "erhigashitsunotogawahigashiurausukitanakagusukumoduminamiminowah" +
+ "igashiyamatokoriyamanashifteditchyouripharmacyshintokushimahigas" +
+ "hiyodogawahigashiyoshinogaris-a-socialistmein-vigorgehiraizumisa" +
+ "tohobby-sitehirakatashinagawahiranais-a-soxfanhirarahiratsukagaw" +
+ "ahirayaizuwakamatsubushikusakadogawahistorichouseshintomikasahar" +
+ "ahitachiomiyagildeskaliszhitachiotagooglecodespotravelersinsuran" +
+ "cehitraeumtgeradellogliastradinghjartdalhjelmelandholeckobierzyc" +
+ "eholidayhomeiphdhomelinkfhappouhomelinuxn--1qqw23ahomeofficehome" +
+ "securitymaceratakaokamakurazakitashiobarahomesecuritypchloehomes" +
+ "enseminehomeunixn--2m4a15ehondahoneywellbeingzonehongopocznorthw" +
+ "esternmutualhonjyoitakarazukameokameyamatotakadahornindalhorseou" +
+ "lminamiogunicomcastresistancehortendofinternet-dnshinyoshitomiok" +
+ "amogawahospitalhoteleshiojirishirifujiedahotmailhoyangerhoylande" +
+ "troitskydivinghumanitieshioyanaizuhurdalhurumajis-a-studentalhyl" +
+ "lestadhyogoris-a-teacherkassymantechnologyhyugawarahyundaiwafune" +
+ "hzchocolatemasekashiwarajewishartgalleryjfkharkovalleeaosteigenj" +
+ "gorajlcube-serverrankoshigayakumoldelmenhorstagejlljmphilipsynol" +
+ "ogy-diskstationjnjcphilatelyjoyokaichibahccavuotnagareyamalborkd" +
+ "alwaysdatabaseballangenoamishirasatochigiessensiositelemarkherso" +
+ "njpmorganjpnjprshiraokananporovigotpantheonsitejuniperjurkoshuna" +
+ "ntokigawakosugekotohiradomainshiratakahagitlaborkotourakouhokuta" +
+ "makis-an-artistcgrouphiladelphiaareadmyblogsitekounosupplieshish" +
+ "ikuis-an-engineeringkouyamashikokuchuokouzushimasoykozagawakozak" +
+ "is-an-entertainerkozowindmillkpnkppspdnshisognekrasnodarkredston" +
+ "ekristiansandcatshisuifuelblagdenesnaaseralingenkainanaejrietisa" +
+ "latinabenonichoshibuyachiyodavvenjargaulardalutskasukabedzin-the" +
+ "-bandaioiraseeklogest-mon-blogueurovisionisshingugekristiansundk" +
+ "rodsheradkrokstadelvaldaostarnbergkryminamisanrikubetsupportrent" +
+ "ino-alto-adigekumatorinokumejimasudakumenanyokkaichiropractichoy" +
+ "odobashichikashukujitawarakunisakis-bykunitachiarailwaykunitomig" +
+ "usukumamotoyamassa-carrara-massacarraramassabusinessebyklegalloc" +
+ "alhistoryggeelvinckhmelnytskyivanylvenicekunneppulawykunstsammlu" +
+ "ngkunstunddesignkuokgrouphoenixn--30rr7ykureggioemiliaromagnakay" +
+ "amatsumaebashikshacknetrentino-altoadigekurgankurobelaudiblebork" +
+ "angerkurogimilanokuroisoftwarendalenugkuromatsunais-certifieduca" +
+ "torahimeshimamateramochizukirakurotakikawasakis-foundationkushir" +
+ "ogawakustanais-gonekusupplykutchanelkutnokuzumakis-into-animelbo" +
+ "urnekvafjordkvalsundkvamlidlugolekafjordkvanangenkvinesdalkvinnh" +
+ "eradkviteseidskogkvitsoykwpspiegelkzmisugitokorozawamitourismola" +
+ "ngevagrarchaeologyeongbuknx-serveronakatsugawamitoyoakemiuramiya" +
+ "zumiyotamanomjondalenmlbfanmonstermonticellolmontrealestatefarme" +
+ "quipmentrentino-s-tirollagrigentomologyeonggiehtavuoatnagaivuotn" +
+ "agaokakyotambabia-goracleaningatlantabusebastopologyeongnamegawa" +
+ "keisenbahnmonza-brianzaporizhzhiamonza-e-della-brianzapposhitara" +
+ "mamonzabrianzaptokuyamatsusakahoginankokubunjis-leetnedalmonzaeb" +
+ "rianzaramonzaedellabrianzamoonscalezajskolobrzegersundmoparachut" +
+ "ingmordoviajessheiminamitanemoriyamatsushigemoriyoshimilitarymor" +
+ "monmouthagakhanamigawamoroyamatsuuramortgagemoscowindowshizukuis" +
+ "himofusaintlouis-a-bruinsfanmoseushistorymosjoenmoskeneshizuokan" +
+ "azawamosshoujis-lostre-toteneis-an-accountantshirahamatonbetsurn" +
+ "adalmosvikomaganemoteginowaniihamatamakawajimaoris-not-certified" +
+ "unetbankhakassiamoviemovistargardmtpchristiansburgrondarmtranbym" +
+ "uenstermuginozawaonsenmuikamisunagawamukochikushinonsenergymulho" +
+ "uservebeermunakatanemuncieszynmuosattemuphonefosshowamurmanskoma" +
+ "kiyosunndalmurotorcraftrentino-stirolmusashimurayamatsuzakis-sav" +
+ "edmusashinoharamuseetrentino-sud-tirolmuseumverenigingmusicargod" +
+ "addynaliascoli-picenogataijis-slickharkivgucciprianiigataishinom" +
+ "akinderoymutsuzawamy-vigorlicemy-wanggouvicenzamyactivedirectory" +
+ "myasustor-elvdalmycdn77-securecifedexhibitionmyddnskingmydissent" +
+ "rentino-sudtirolmydrobofagemydshowtimemorialmyeffectrentino-sued" +
+ "-tirolmyfirewallonieruchomoscienceandindustrynmyfritzmyftpaccess" +
+ "hriramsterdamnserverbaniamyfusionmyhome-serversaillesienarashino" +
+ "mykolaivaolbia-tempio-olbiatempioolbialystokkepnoduminamiuonumat" +
+ "sumotofukemymailermymediapchristmasakimobetsuliguriamyokohamamat" +
+ "sudamypephotographysiomypetsigdalmyphotoshibajddarchitecturealty" +
+ "dalipaymypsxn--32vp30hagebostadmysecuritycamerakermyshopblocksil" +
+ "komatsushimashikizunokunimihoboleslawiechonanbuilderschmidtre-ga" +
+ "uldalukowhalingroks-thisayamanobeokalmykiamytis-a-bloggermytulea" +
+ "piagetmyipictetrentino-suedtirolmyvnchromedicaltanissettairamywi" +
+ "reitrentinoa-adigepinkomforbarclays3-us-east-2pioneerpippupictur" +
+ "esimple-urlpiszpittsburghofauskedsmokorsetagayasells-for-usgarde" +
+ "npiwatepixolinopizzapkommunalforbundplanetariuminamiyamashirokaw" +
+ "anabelembetsukubanklabudhabikinokawabarthaebaruminamimakis-a-pai" +
+ "nteractivegarsheis-a-patsfanplantationplantslingplatformshangril" +
+ "anslupskommuneplaystationplazaplchryslerplumbingopmnpodzonepohlp" +
+ "oivronpokerpokrovskomonopolitiendapolkowicepoltavalle-aostarostw" +
+ "odzislawinnersnoasaitamatsukuris-uberleetrdpomorzeszowiosokaneya" +
+ "mazoepordenonepornporsangerporsanguidell-ogliastraderporsgrunnan" +
+ "poznanpraxis-a-bookkeeperugiaprdpreservationpresidioprgmrprimelh" +
+ "uscultureisenprincipeprivatizehealthinsuranceprochowiceproductio" +
+ "nsokndalprofbsbxn--12co0c3b4evalleaostaticschuleprogressivegasia" +
+ "promombetsurfbx-oschwarzgwangjuifminamidaitomangotsukisofukushim" +
+ "aparocherkasyno-dschweizpropertyprotectionprotonetrentinoaadigep" +
+ "rudentialpruszkowitdkomorotsukamisatokamachintaifun-dnsaliasdabu" +
+ "rprzeworskogptplusdecorativeartsolarssonpvtrentinoalto-adigepwch" +
+ "ungnamdalseidfjordyndns-weberlincolniyodogawapzqldqponqslgbtrent" +
+ "inoaltoadigequicksytesolognequipelementsolundbeckomvuxn--2scrj9c" +
+ "hoseiroumuenchenissandnessjoenissayokoshibahikariwanumatakazakis" +
+ "-a-greenissedaluroyqvchurchaseljeepsongdalenviknagatorodoystufft" +
+ "oread-booksnesomnaritakurashikis-very-badajozorastuttgartrentino" +
+ "sudtirolsusakis-very-evillagesusonosuzakaniepcesuzukanmakiwakuni" +
+ "gamidsundsuzukis-very-goodhandsonsvalbardunloppacificirclegnicaf" +
+ "ederationsveiosvelvikongsvingersvizzerasvn-reposooswedenswidnica" +
+ "rtierswiebodzindianapolis-a-anarchistoireggiocalabriaswiftcovers" +
+ "winoujscienceandhistoryswisshikis-very-nicesynology-dsopotrentin" +
+ "os-tirolturystykanoyaltakasakiwientuscanytushuissier-justicetuva" +
+ "lle-daostatic-accessorreisahayakawakamiichikawamisatotaltuxfamil" +
+ "ytwmailvbargainstitutelevisionaustdalimanowarudaustevollavangena" +
+ "turbruksgymnaturhistorisches3-eu-west-1venneslaskerrylogisticsor" +
+ "tlandvestfoldvestnesoruminanovestre-slidreamhostersouthcarolinaz" +
+ "awavestre-totennishiawakuravestvagoyvevelstadvibo-valentiavibova" +
+ "lentiavideovillaskimitsubatamicable-modemoneyvinnicartoonartdeco" +
+ "ffeedbackplaneapplinzis-very-sweetpeppervinnytsiavipsinaappilots" +
+ "irdalvirginiavirtualvirtueeldomeindianmarketingvirtuelvisakataki" +
+ "nouevistaprinternationalfirearmsouthwestfalenviterboltrevisohugh" +
+ "esor-odalvivoldavixn--3bst00mincommbankmpspbarclaycards3-sa-east" +
+ "-1vlaanderenvladikavkazimierz-dolnyvladimirvlogoipimientaketomis" +
+ "atolgavolkswagentsowavologdanskonskowolawavolvolkenkundenvolyngd" +
+ "alvossevangenvotevotingvotoyonakagyokutourspjelkavikongsbergwloc" +
+ "lawekonsulatrobeepilepsydneywmflabspreadbettingworldworse-thanda" +
+ "wowithgoogleapisa-hockeynutsiracusakakinokiawpdevcloudwritesthis" +
+ "blogsytewroclawithyoutubeneventoeidsvollwtcircustomerwtfbxoscien" +
+ "cecentersciencehistorywuozuwwwiwatsukiyonowruzhgorodeowzmiuwajim" +
+ "axn--42c2d9axn--45br5cylxn--45brj9citadeliveryxn--45q11citicatho" +
+ "licheltenham-radio-opencraftrainingripescaravantaaxn--4gbriminin" +
+ "gxn--4it168dxn--4it797kooris-an-actorxn--4pvxs4allxn--54b7fta0cc" +
+ "ivilaviationxn--55qw42gxn--55qx5dxn--5js045dxn--5rtp49civilisati" +
+ "onxn--5rtq34kopervikhmelnitskiyamashikexn--5su34j936bgsgxn--5tzm" +
+ "5gxn--6btw5axn--6frz82gxn--6orx2rxn--6qq986b3xlxn--7t0a264civili" +
+ "zationxn--80adxhkspydebergxn--80ao21axn--80aqecdr1axn--80asehdba" +
+ "rreauctionaval-d-aosta-valleyolasiteu-2xn--80aswgxn--80audnedaln" +
+ "xn--8ltr62koryokamikawanehonbetsurutaharaxn--8pvr4uxn--8y0a063ax" +
+ "n--90a3academy-firewall-gatewayxn--90aeroportalaheadjudaicaaarbo" +
+ "rteaches-yogasawaracingroks-theatreexn--90aishobaraomoriguchihar" +
+ "ahkkeravjuedischesapeakebayernrtritonxn--90azhytomyrxn--9dbhblg6" +
+ "dietcimdbarrel-of-knowledgemologicallimitediscountysvardolls3-us" +
+ "-gov-west-1xn--9dbq2axn--9et52uxn--9krt00axn--andy-iraxn--aropor" +
+ "t-byandexn--3ds443gxn--asky-iraxn--aurskog-hland-jnbarrell-of-kn" +
+ "owledgeologyombondiscoveryomitanobninskarasjohkaminokawanishiaiz" +
+ "ubangeu-3utilitiesquare7xn--avery-yuasakegawaxn--b-5gaxn--b4w605" +
+ "ferdxn--bck1b9a5dre4civilwarmanagementjxn--0trq7p7nnxn--bdddj-mr" +
+ "abdxn--bearalvhki-y4axn--berlevg-jxaxn--bhcavuotna-s4axn--bhccav" +
+ "uotna-k7axn--bidr-5nachikatsuuraxn--bievt-0qa2xn--bjarky-fyaotsu" +
+ "rreyxn--bjddar-ptamayufuettertdasnetzxn--blt-elabourxn--bmlo-gra" +
+ "ingerxn--bod-2naroyxn--brnny-wuaccident-investigation-aptiblease" +
+ "ating-organicbcn-north-1xn--brnnysund-m8accident-prevention-webh" +
+ "openairbusantiquest-a-la-maisondre-landebudapest-a-la-masionionj" +
+ "ukudoyamagentositelekommunikationthewifiat-band-campaniaxn--brum" +
+ "-voagatroandinosaurepbodynathomebuiltrentinosued-tirolxn--btsfjo" +
+ "rd-9zaxn--c1avgxn--c2br7gxn--c3s14minnesotaketakatsukis-into-car" +
+ "shiranukanagawaxn--cck2b3barsyonlinewhollandishakotanavigationav" +
+ "oibmdisrechtranakaiwamizawaweddingjesdalimoliserniaustinnatuurwe" +
+ "tenschappenaumburgjerdrumckinseyokosukanzakiyokawaragrocerybnika" +
+ "hokutobamaintenancebetsuikicks-assedic66xn--cg4bkis-with-theband" +
+ "ovre-eikerxn--ciqpnxn--clchc0ea0b2g2a9gcdn77-sslattumintelligenc" +
+ "exn--comunicaes-v6a2oxn--correios-e-telecomunicaes-ghc29axn--czr" +
+ "694bashkiriaustraliaisondriodejaneirochesterxn--czrs0trogstadxn-" +
+ "-czru2dxn--czrw28basilicataniaustrheimatunduhrennesoyokotebinore" +
+ "-og-uvdalaziobiraskvolloabathsbcasacamdvrcampobassociatestingjem" +
+ "nes3-ap-southeast-1xn--d1acj3basketballyngenavuotnaklodzkodairau" +
+ "thordalandroiddnss3-eu-west-2xn--d1alfaromeoxn--d1atromsaitomobe" +
+ "llevuelosangelesjaguarmeniaxn--d5qv7z876claimsardiniaxn--davvenj" +
+ "rga-y4axn--djrs72d6uyxn--djty4kosaigawaxn--dnna-grajewolterskluw" +
+ "erxn--drbak-wuaxn--dyry-iraxn--e1a4clanbibaidarq-axn--eckvdtc9dx" +
+ "n--efvn9srlxn--efvy88haibarakisosakitagawaxn--ehqz56nxn--elqq16h" +
+ "air-surveillancexn--estv75gxn--eveni-0qa01gaxn--f6qx53axn--fct42" +
+ "9kosakaerodromegallupinbarefootballfinanzgoraurskog-holandroverh" +
+ "alla-speziaetnagahamaroygardenebakkeshibechambagriculturennebude" +
+ "jjudygarlandd-dnshome-webservercellikes-piedmontblancomeeres3-ap" +
+ "-south-1kappchizippodhaleangaviikadenadexetereport3l3p0rtargets-" +
+ "itargivestbytomaritimobaravennagasuke12hpalace164lima-cityeatsel" +
+ "inogradultarnobrzegyptianativeamericanantiques3-ap-northeast-133" +
+ "7xn--fhbeiarnxn--finny-yuaxn--fiq228c5hsrtrentinostirolxn--fiq64" +
+ "batodayonagoyautomotivecoalvdalaskanittedallasalleasinglesurance" +
+ "rtmgretagajoboji234xn--fiqs8srvaporcloudxn--fiqz9storagexn--fjor" +
+ "d-lraxn--fjq720axn--fl-ziaxn--flor-jraxn--flw351exn--fpcrj9c3dxn" +
+ "--frde-grandrapidstordalxn--frna-woaraisaijotromsojampagefrontap" +
+ "piemontexn--frya-hraxn--fzc2c9e2cldmailuxembourgrongaxn--fzys8d6" +
+ "9uvgmailxn--g2xx48clickasumigaurawa-mazowszextraspacekitagatajir" +
+ "issagaeroclubmedecincinnationwidealstahaugesunderseaportsinfolld" +
+ "alabamagasakishimabarackmazerbaijan-mayendoftheinternetflixilove" +
+ "collegefantasyleaguernseyxn--gckr3f0fedorapeopleirfjordynvpncher" +
+ "nivtsiciliaxn--gecrj9clinichernigovernmentjometacentruminamiawaj" +
+ "ikis-a-doctorayxn--ggaviika-8ya47hakatanoshiroomuraxn--gildeskl-" +
+ "g0axn--givuotna-8yasakaiminatoyonezawaxn--gjvik-wuaxn--gk3at1exn" +
+ "--gls-elacaixaxn--gmq050isleofmandalxn--gmqw5axn--h-2failxn--h1a" +
+ "eghakodatexn--h2breg3evenestorepaircraftrentinosud-tirolxn--h2br" +
+ "j9c8cliniquenoharaxn--h3cuzk1digitalxn--hbmer-xqaxn--hcesuolo-7y" +
+ "a35batsfjordivtasvuodnakamagayahababyglandivttasvuotnakamurataji" +
+ "mibuildingjovikarasjokarasuyamarylhurstjohnayorovnoceanographics" +
+ "3-us-west-1xn--hery-iraxn--hgebostad-g3axn--hmmrfeasta-s4acctrus" +
+ "teexn--hnefoss-q1axn--hobl-iraxn--holtlen-hxaxn--hpmir-xqaxn--hx" +
+ "t814exn--hyanger-q1axn--hylandet-54axn--i1b6b1a6a2exn--imr513nxn" +
+ "--indery-fyasugivingxn--io0a7issmarterthanyouxn--j1aefedoraproje" +
+ "ctoyotomiyazakis-a-knightpointtokaizukamikoaniikappugliaxn--j1am" +
+ "hakonexn--j6w193gxn--jlq61u9w7bauhausposts-and-telecommunication" +
+ "sncfdiyonaguniversityoriikarateu-4xn--jlster-byasuokanraxn--jrpe" +
+ "land-54axn--jvr189misakis-into-cartoonshiraois-a-techietis-a-the" +
+ "rapistoiaxn--k7yn95exn--karmy-yuaxn--kbrq7oxn--kcrx77d1x4axn--kf" +
+ "jord-iuaxn--klbu-woaxn--klt787dxn--kltp7dxn--kltx9axn--klty5xn--" +
+ "3e0b707exn--koluokta-7ya57hakubaghdadxn--kprw13dxn--kpry57dxn--k" +
+ "pu716fermodalenxn--kput3iwchofunatoriginsurecreationishiwakis-a-" +
+ "geekashiwazakiyosatokashikiyosemitexn--krager-gyatomitamamuraxn-" +
+ "-kranghke-b0axn--krdsherad-m8axn--krehamn-dxaxn--krjohka-hwab49j" +
+ "elenia-goraxn--ksnes-uuaxn--kvfjord-nxaxn--kvitsy-fyatsukanumazu" +
+ "ryxn--kvnangen-k0axn--l-1fairwindstorfjordxn--l1accentureklambor" +
+ "ghiniizaxn--laheadju-7yatsushiroxn--langevg-jxaxn--lcvr32dxn--ld" +
+ "ingen-q1axn--leagaviika-52bbcasertaipeiheijiitatebayashiibahcavu" +
+ "otnagaraholtalenvironmentalconservationflfanfshostrowiecasinordl" +
+ "andnpalermomahachijorpelandrangedalindashorokanaieverbankaratsug" +
+ "inamikatagamiharuconnectashkentatamotors3-us-west-2xn--lesund-hu" +
+ "axn--lgbbat1ad8jeonnamerikawauexn--lgrd-poaclintonoshoesarluxury" +
+ "xn--lhppi-xqaxn--linds-pramericanartrvareserveblogspotrentinosue" +
+ "dtirolxn--lns-qlapyatigorskypexn--loabt-0qaxn--lrdal-sraxn--lren" +
+ "skog-54axn--lt-liaclothingdustkakamigaharaxn--lten-granexn--lury" +
+ "-iraxn--m3ch0j3axn--mely-iraxn--merker-kuaxn--mgb2ddestorjdevclo" +
+ "udfrontdoorxn--mgb9awbferraraxn--mgba3a3ejtrysiljanxn--mgba3a4f1" +
+ "6axn--mgba3a4franamizuholdingsmilelverumisasaguris-into-gamessin" +
+ "atsukigatakasagotembaixadaxn--mgba7c0bbn0axn--mgbaakc7dvferrarit" +
+ "togoldpoint2thisamitsukexn--mgbaam7a8hakuis-a-personaltrainerxn-" +
+ "-mgbab2bdxn--mgbai9a5eva00bbtatarantottoriiyamanouchikuhokuryuga" +
+ "sakitaurayasudautoscanadaejeonbukaragandasnesoddenmarkhangelskja" +
+ "kdnepropetrovskiervaapsteiermark12xn--mgbai9azgqp6jetztrentino-a" +
+ "-adigexn--mgbayh7gpagespeedmobilizeroxn--mgbb9fbpobanazawaxn--mg" +
+ "bbh1a71exn--mgbc0a9azcgxn--mgbca7dzdoxn--mgberp4a5d4a87gxn--mgbe" +
+ "rp4a5d4arxn--mgbgu82axn--mgbi4ecexposedxn--mgbpl2fhskodjejuegosh" +
+ "ikiminokamoenairportland-4-salernoboribetsuckstpetersburgxn--mgb" +
+ "qly7c0a67fbcnsarpsborgrossetouchijiwadegreexn--mgbqly7cvafranzis" +
+ "kanerdpolicexn--mgbt3dhdxn--mgbtf8flatangerxn--mgbtx2bbvacations" +
+ "watch-and-clockerxn--mgbx4cd0abbottulanxessor-varangerxn--mix082" +
+ "ferreroticanonoichinomiyakexn--mix891fetsundyroyrvikinguitarscho" +
+ "larshipschoolxn--mjndalen-64axn--mk0axindustriesteamfamberkeleyx" +
+ "n--mk1bu44cntkmaxxn--11b4c3dyndns-wikinkobayashikaoirminamibosog" +
+ "ndaluzernxn--mkru45ixn--mlatvuopmi-s4axn--mli-tlaquilanciaxn--ml" +
+ "selv-iuaxn--moreke-juaxn--mori-qsakuhokkaidoomdnsiskinkyotobetsu" +
+ "midatlanticolognextdirectmparaglidingroundhandlingroznyxn--mosje" +
+ "n-eyawaraxn--mot-tlarvikoseis-an-actresshirakofuefukihaboromskog" +
+ "xn--mre-og-romsdal-qqbentleyoshiokaracoldwarmiamihamadaveroykeni" +
+ "waizumiotsukuibestadds3-external-1xn--msy-ula0hakusandiegoodyear" +
+ "xn--mtta-vrjjat-k7afamilycompanycolonialwilliamsburgrparisor-fro" +
+ "nxn--muost-0qaxn--mxtq1misawaxn--ngbc5azdxn--ngbe9e0axn--ngbrxn-" +
+ "-3hcrj9cistrondheimmobilienxn--nit225kosherbrookegawaxn--nmesjev" +
+ "uemie-tcbalestrandabergamoarekexn--nnx388axn--nodessakuragawaxn-" +
+ "-nqv7fs00emaxn--nry-yla5gxn--ntso0iqx3axn--ntsq17gxn--nttery-bya" +
+ "eservecounterstrikexn--nvuotna-hwaxn--nyqy26axn--o1achattanoogan" +
+ "ordre-landxn--o3cw4haldenxn--o3cyx2axn--od0algxn--od0aq3beppubli" +
+ "shproxyzgorzeleccollectionhlfanhs3-website-ap-northeast-1xn--ogb" +
+ "pf8flekkefjordxn--oppegrd-ixaxn--ostery-fyawatahamaxn--osyro-wua" +
+ "xn--p1acfgujolsterxn--p1aixn--pbt977coloradoplateaudioxn--pgbs0d" +
+ "hlxn--porsgu-sta26fhvalerxn--pssu33lxn--pssy2uxn--q9jyb4columbus" +
+ "heyxn--qcka1pmcdonaldstreamuneuesolutionsomaxn--qqqt11misconfuse" +
+ "dxn--qxamusementunesorfoldxn--rady-iraxn--rdal-poaxn--rde-ulavag" +
+ "iskexn--rdy-0nabarixn--rennesy-v1axn--rhkkervju-01aflakstadaokag" +
+ "akibichuoxn--rholt-mragowoodsideltaitogliattirestudioxn--rhqv96g" +
+ "xn--rht27zxn--rht3dxn--rht61exn--risa-5narusawaxn--risr-iraxn--r" +
+ "land-uuaxn--rlingen-mxaxn--rmskog-byaxn--rny31halsaikitahatakama" +
+ "tsukawaxn--rovu88bernuorockartuzyukinfinitintuitateshinanomachim" +
+ "kentateyamavocatanzarowebspacebizenakanojohanamakinoharassnasaba" +
+ "erobatickets3-ap-southeast-2xn--rros-granvindafjordxn--rskog-uua" +
+ "xn--rst-0narutokyotangovtunkoninjamisonxn--rsta-francaiseharaxn-" +
+ "-rvc1e0am3exn--ryken-vuaxn--ryrvik-byaxn--s-1faithruheredumbrell" +
+ "ajollamericanexpressexyxn--s9brj9communitysnesarufutsunomiyawaka" +
+ "saikaitakoelnxn--sandnessjen-ogbizxn--sandy-yuaxn--seral-lraxn--" +
+ "ses554gxn--sgne-gratangenxn--skierv-utazaskoyabearalvahkijobserv" +
+ "erisignieznoipifonymishimatsunoxn--skjervy-v1axn--skjk-soaxn--sk" +
+ "nit-yqaxn--sknland-fxaxn--slat-5narviikamitondabayashiogamagoriz" +
+ "iaxn--slt-elabbvieeexn--smla-hraxn--smna-gratis-a-bulls-fanxn--s" +
+ "nase-nraxn--sndre-land-0cbremangerxn--snes-poaxn--snsa-roaxn--sr" +
+ "-aurdal-l8axn--sr-fron-q1axn--sr-odal-q1axn--sr-varanger-ggbeski" +
+ "dyn-o-saurlandes3-website-ap-southeast-1xn--srfold-byaxn--srreis" +
+ "a-q1axn--srum-grazxn--stfold-9xaxn--stjrdal-s1axn--stjrdalshalse" +
+ "n-sqbestbuyshouses3-website-ap-southeast-2xn--stre-toten-zcbstud" +
+ "yndns-at-homedepotenzamamicrolightingxn--t60b56axn--tckweatherch" +
+ "annelxn--tiq49xqyjevnakershuscountryestateofdelawarezzoologyxn--" +
+ "tjme-hraxn--tn0agrinet-freakstuff-4-salexn--tnsberg-q1axn--tor13" +
+ "1oxn--trany-yuaxn--trgstad-r1axn--trna-woaxn--troms-zuaxn--tysvr" +
+ "-vraxn--uc0atvarggatrentoyokawaxn--uc0ay4axn--uist22hammarfeasta" +
+ "fricapetownnews-stagingxn--uisz3gxn--unjrga-rtaobaokinawashirosa" +
+ "tochiokinoshimalatvuopmiasakuchinotsuchiurakawalesundxn--unup4yx" +
+ "n--uuwu58axn--vads-jraxn--vard-jraxn--vegrshei-c0axn--vermgensbe" +
+ "rater-ctbetainaboxfusejnynysadodgeometre-experts-comptables3-web" +
+ "site-eu-west-1xn--vermgensberatung-pwbieigersundray-dnsupdaterno" +
+ "pilawavoues3-fips-us-gov-west-1xn--vestvgy-ixa6oxn--vg-yiabcgxn-" +
+ "-vgan-qoaxn--vgsy-qoa0jewelryxn--vgu402comobilyxn--vhquvaroyxn--" +
+ "vler-qoaxn--vre-eiker-k8axn--vrggt-xqadxn--vry-yla5gxn--vuq861bi" +
+ "elawalmartatsunoceanographiquevje-og-hornnes3-website-sa-east-1x" +
+ "n--w4r85el8fhu5dnraxn--w4rs40lxn--wcvs22dxn--wgbh1comparemarkerr" +
+ "yhotelsasayamaxn--wgbl6axn--xhq521biellaakesvuemieleccexn--xkc2a" +
+ "l3hye2axn--xkc2dl3a5ee0hamurakamigoris-a-photographerokuappfizer" +
+ "xn--y9a3aquariumissilewismillerxn--yer-znarvikoshimizumakis-an-a" +
+ "narchistoricalsocietyxn--yfro4i67oxn--ygarden-p1axn--ygbi2ammxn-" +
+ "-3oq18vl8pn36axn--ystre-slidre-ujbieszczadygeyachimataikikuchiku" +
+ "seikarugamvikareliancexn--zbx025dxn--zf0ao64axn--zf0avxn--3pxu8k" +
+ "onyveloftrentino-aadigexn--zfr164bievatmallorcadaques3-website-u" +
+ "s-east-1xperiaxz"
+
+// nodes is the list of nodes. Each node is represented as a uint32, which
+// encodes the node's children, wildcard bit and node type (as an index into
+// the children array), ICANN bit and text.
+//
+// If the table was generated with the -comments flag, there is a //-comment
+// after each node's data. In it is the nodes-array indexes of the children,
+// formatted as (n0x1234-n0x1256), with * denoting the wildcard bit. The
+// nodeType is printed as + for normal, ! for exception, and o for parent-only
+// nodes that have children but don't match a domain label in their own right.
+// An I denotes an ICANN domain.
+//
+// The layout within the uint32, from MSB to LSB, is:
+// [ 0 bits] unused
+// [10 bits] children index
+// [ 1 bits] ICANN bit
+// [15 bits] text index
+// [ 6 bits] text length
+var nodes = [...]uint32{
+ 0x31fe83,
+ 0x28e944,
+ 0x2ed8c6,
+ 0x380743,
+ 0x380746,
+ 0x3a5306,
+ 0x3b5e43,
+ 0x30a7c4,
+ 0x20d0c7,
+ 0x2ed508,
+ 0x1a07102,
+ 0x31f1c7,
+ 0x368c09,
+ 0x2d68ca,
+ 0x2d68cb,
+ 0x238503,
+ 0x2dec46,
+ 0x23d6c5,
+ 0x1e07542,
+ 0x21cf84,
+ 0x266d03,
+ 0x346145,
+ 0x22035c2,
+ 0x20a643,
+ 0x271f944,
+ 0x342285,
+ 0x2a10042,
+ 0x38a48e,
+ 0x255083,
+ 0x3affc6,
+ 0x2e00142,
+ 0x2d4207,
+ 0x240d86,
+ 0x3204f02,
+ 0x22ee43,
+ 0x256204,
+ 0x32d106,
+ 0x25b788,
+ 0x2811c6,
+ 0x378fc4,
+ 0x3600242,
+ 0x33b8c9,
+ 0x212107,
+ 0x2e6046,
+ 0x341809,
+ 0x2a0048,
+ 0x33a904,
+ 0x2a0f46,
+ 0x21f886,
+ 0x3a02d42,
+ 0x3a014f,
+ 0x28c84e,
+ 0x21bfc4,
+ 0x382c85,
+ 0x30a6c5,
+ 0x2e2109,
+ 0x249089,
+ 0x33b1c7,
+ 0x23f8c6,
+ 0x20ae43,
+ 0x3e01d42,
+ 0x2e3203,
+ 0x225d0a,
+ 0x20cac3,
+ 0x242f85,
+ 0x28e142,
+ 0x28e149,
+ 0x4200bc2,
+ 0x209204,
+ 0x28ad46,
+ 0x2e5c05,
+ 0x361644,
+ 0x4a1a344,
+ 0x203ec3,
+ 0x218d04,
+ 0x4e00702,
+ 0x2f8e84,
+ 0x52f5f04,
+ 0x339bca,
+ 0x5600f82,
+ 0x28bc47,
+ 0x281548,
+ 0x6206502,
+ 0x31d0c7,
+ 0x2c6d44,
+ 0x2c6d47,
+ 0x393c45,
+ 0x35e887,
+ 0x33af86,
+ 0x271dc4,
+ 0x378385,
+ 0x28ea47,
+ 0x72001c2,
+ 0x224143,
+ 0x200c42,
+ 0x200c43,
+ 0x760b5c2,
+ 0x20f4c5,
+ 0x7a01d02,
+ 0x357844,
+ 0x27e405,
+ 0x21bf07,
+ 0x25aece,
+ 0x2bf044,
+ 0x23df04,
+ 0x211c43,
+ 0x28a4c9,
+ 0x30eacb,
+ 0x2ea6c8,
+ 0x3415c8,
+ 0x306208,
+ 0x2b7288,
+ 0x33a74a,
+ 0x35e787,
+ 0x321606,
+ 0x7e8f282,
+ 0x36a683,
+ 0x377683,
+ 0x37fd44,
+ 0x3b5e83,
+ 0x32c343,
+ 0x1727e02,
+ 0x8203302,
+ 0x283f45,
+ 0x29e006,
+ 0x2da184,
+ 0x388547,
+ 0x2fa686,
+ 0x389384,
+ 0x3aa107,
+ 0x223d43,
+ 0x86cd5c2,
+ 0x8a0d342,
+ 0x8e1e642,
+ 0x21e646,
+ 0x9200002,
+ 0x2501c5,
+ 0x329343,
+ 0x201684,
+ 0x2efb04,
+ 0x2efb05,
+ 0x203c43,
+ 0x979c783,
+ 0x9a092c2,
+ 0x291d85,
+ 0x291d8b,
+ 0x343c06,
+ 0x21270b,
+ 0x226544,
+ 0x213a49,
+ 0x2148c4,
+ 0x9e14b02,
+ 0x215943,
+ 0x216283,
+ 0x1616b42,
+ 0x275fc3,
+ 0x216b4a,
+ 0xa201102,
+ 0x21d205,
+ 0x29a88a,
+ 0x2e0544,
+ 0x201103,
+ 0x325384,
+ 0x21ae03,
+ 0x21ae04,
+ 0x21ae07,
+ 0x21b605,
+ 0x21d685,
+ 0x21dc46,
+ 0x21dfc6,
+ 0x21ea43,
+ 0x222688,
+ 0x206c03,
+ 0xa60c702,
+ 0x245848,
+ 0x23614b,
+ 0x228908,
+ 0x228e06,
+ 0x229dc7,
+ 0x22da48,
+ 0xb6024c2,
+ 0xba430c2,
+ 0x32da08,
+ 0x233347,
+ 0x2e7b45,
+ 0x2e7b48,
+ 0x2c3b08,
+ 0x2be483,
+ 0x232e04,
+ 0x37fd82,
+ 0xbe34382,
+ 0xc23e102,
+ 0xca37302,
+ 0x237303,
+ 0xce01382,
+ 0x30a783,
+ 0x300f44,
+ 0x20a043,
+ 0x322844,
+ 0x20d7cb,
+ 0x2322c3,
+ 0x2e6a46,
+ 0x245f44,
+ 0x2982ce,
+ 0x381245,
+ 0x3b00c8,
+ 0x263347,
+ 0x26334a,
+ 0x22e803,
+ 0x317a07,
+ 0x30ec85,
+ 0x23a384,
+ 0x272706,
+ 0x272707,
+ 0x330f44,
+ 0x301f87,
+ 0x25a184,
+ 0x25b204,
+ 0x25b206,
+ 0x25f704,
+ 0x36bdc6,
+ 0x216983,
+ 0x233108,
+ 0x316ec8,
+ 0x23dec3,
+ 0x275f83,
+ 0x3a6604,
+ 0x3aae83,
+ 0xd235f42,
+ 0xd6df482,
+ 0x207143,
+ 0x203f86,
+ 0x2a1043,
+ 0x285184,
+ 0xda165c2,
+ 0x2165c3,
+ 0x35f083,
+ 0x21fe02,
+ 0xde008c2,
+ 0x2c9786,
+ 0x23e347,
+ 0x2fd645,
+ 0x38fd04,
+ 0x294d45,
+ 0x2f8a47,
+ 0x2add85,
+ 0x2e4689,
+ 0x2e9906,
+ 0x2ef808,
+ 0x2fd546,
+ 0xe20e982,
+ 0x2ddb08,
+ 0x300d06,
+ 0x219205,
+ 0x316887,
+ 0x316dc4,
+ 0x316dc5,
+ 0x281384,
+ 0x345d88,
+ 0xe6127c2,
+ 0xea04882,
+ 0x33ca06,
+ 0x2cf588,
+ 0x34d485,
+ 0x351546,
+ 0x356108,
+ 0x371488,
+ 0xee35dc5,
+ 0xf214f44,
+ 0x34e247,
+ 0xf614602,
+ 0xfa22902,
+ 0x10e0f882,
+ 0x28ae45,
+ 0x2aaa45,
+ 0x30af86,
+ 0x350007,
+ 0x386287,
+ 0x11638543,
+ 0x2b0307,
+ 0x30e7c8,
+ 0x3a0849,
+ 0x38a647,
+ 0x3b9c87,
+ 0x238788,
+ 0x238f86,
+ 0x239e86,
+ 0x23aacc,
+ 0x23c08a,
+ 0x23c407,
+ 0x23d58b,
+ 0x23e187,
+ 0x23e18e,
+ 0x19a3f304,
+ 0x240244,
+ 0x242547,
+ 0x3ac747,
+ 0x246d46,
+ 0x246d47,
+ 0x247407,
+ 0x19e29682,
+ 0x2495c6,
+ 0x2495ca,
+ 0x24a08b,
+ 0x24ac87,
+ 0x24b845,
+ 0x24bb83,
+ 0x24bdc6,
+ 0x24bdc7,
+ 0x20d283,
+ 0x1a206e02,
+ 0x24c78a,
+ 0x1a769d02,
+ 0x1aa4f282,
+ 0x1ae4dd42,
+ 0x1b240e82,
+ 0x24e9c5,
+ 0x24ef44,
+ 0x1ba1a442,
+ 0x2f8f05,
+ 0x24a683,
+ 0x2149c5,
+ 0x2b7184,
+ 0x205ec4,
+ 0x25a486,
+ 0x262586,
+ 0x291f83,
+ 0x204844,
+ 0x3894c3,
+ 0x1c204c82,
+ 0x210ac4,
+ 0x210ac6,
+ 0x34e7c5,
+ 0x37e946,
+ 0x316988,
+ 0x273544,
+ 0x266ac8,
+ 0x398785,
+ 0x22bc88,
+ 0x2b2dc6,
+ 0x26d907,
+ 0x233d84,
+ 0x233d86,
+ 0x242bc3,
+ 0x393fc3,
+ 0x211d08,
+ 0x322004,
+ 0x356747,
+ 0x20c7c6,
+ 0x2dedc9,
+ 0x322a88,
+ 0x325448,
+ 0x331ac4,
+ 0x35f103,
+ 0x229942,
+ 0x1d2234c2,
+ 0x1d61a202,
+ 0x36c083,
+ 0x1da08e02,
+ 0x20d204,
+ 0x3521c6,
+ 0x3b3745,
+ 0x24fa83,
+ 0x23cf44,
+ 0x2b95c7,
+ 0x25a783,
+ 0x251208,
+ 0x218405,
+ 0x264143,
+ 0x27e385,
+ 0x27e4c4,
+ 0x300a06,
+ 0x218f84,
+ 0x21ab86,
+ 0x21be46,
+ 0x210584,
+ 0x23e543,
+ 0x1de1a582,
+ 0x23dd05,
+ 0x20b9c3,
+ 0x1e20c882,
+ 0x23aa83,
+ 0x2231c5,
+ 0x23cac3,
+ 0x23cac9,
+ 0x1e606b82,
+ 0x1ee07842,
+ 0x2918c5,
+ 0x2211c6,
+ 0x2d9d46,
+ 0x2bb248,
+ 0x2bb24b,
+ 0x203fcb,
+ 0x220bc5,
+ 0x2fd845,
+ 0x2cdfc9,
+ 0x1600302,
+ 0x210748,
+ 0x213d44,
+ 0x1f601842,
+ 0x326403,
+ 0x1fecdd46,
+ 0x348e08,
+ 0x20208b42,
+ 0x2bdec8,
+ 0x2060c182,
+ 0x2bf7ca,
+ 0x20a3fd03,
+ 0x203606,
+ 0x36cc48,
+ 0x209708,
+ 0x3b3a46,
+ 0x37c807,
+ 0x3a0347,
+ 0x34daca,
+ 0x2e05c4,
+ 0x354d44,
+ 0x368649,
+ 0x2139fb45,
+ 0x28ca46,
+ 0x210083,
+ 0x253d44,
+ 0x2160df44,
+ 0x20df47,
+ 0x22c507,
+ 0x234404,
+ 0x2df805,
+ 0x30b048,
+ 0x375e07,
+ 0x381007,
+ 0x21a07602,
+ 0x32e984,
+ 0x29b188,
+ 0x2504c4,
+ 0x251844,
+ 0x251c45,
+ 0x251d87,
+ 0x222349,
+ 0x252a04,
+ 0x253149,
+ 0x253388,
+ 0x253ac4,
+ 0x253ac7,
+ 0x21e54003,
+ 0x254187,
+ 0x1609c42,
+ 0x16b4a42,
+ 0x254b86,
+ 0x2550c7,
+ 0x255584,
+ 0x257687,
+ 0x258d47,
+ 0x259983,
+ 0x2f6802,
+ 0x207d82,
+ 0x231683,
+ 0x231684,
+ 0x23168b,
+ 0x3416c8,
+ 0x263c84,
+ 0x25c985,
+ 0x25eb47,
+ 0x260105,
+ 0x2c8c0a,
+ 0x263bc3,
+ 0x22206b02,
+ 0x206b04,
+ 0x267189,
+ 0x26a743,
+ 0x26a807,
+ 0x373089,
+ 0x212508,
+ 0x2db543,
+ 0x282f07,
+ 0x283649,
+ 0x23d483,
+ 0x289844,
+ 0x28d209,
+ 0x290146,
+ 0x21c203,
+ 0x200182,
+ 0x264d83,
+ 0x2b4847,
+ 0x2c3e85,
+ 0x3413c6,
+ 0x259004,
+ 0x374e05,
+ 0x225cc3,
+ 0x20e646,
+ 0x213c42,
+ 0x3a1784,
+ 0x2260d382,
+ 0x226603,
+ 0x22a01802,
+ 0x251743,
+ 0x21e444,
+ 0x21e447,
+ 0x201986,
+ 0x20df02,
+ 0x22e0dec2,
+ 0x2c4244,
+ 0x23235182,
+ 0x23601b82,
+ 0x265704,
+ 0x265705,
+ 0x345105,
+ 0x35c386,
+ 0x23a074c2,
+ 0x2074c5,
+ 0x213005,
+ 0x2157c3,
+ 0x219d06,
+ 0x21a645,
+ 0x21e5c2,
+ 0x34d0c5,
+ 0x21e5c4,
+ 0x228203,
+ 0x22a443,
+ 0x23e11442,
+ 0x2dcf47,
+ 0x376084,
+ 0x376089,
+ 0x253c44,
+ 0x2357c3,
+ 0x300589,
+ 0x389e08,
+ 0x242aa8c4,
+ 0x2aa8c6,
+ 0x219983,
+ 0x25d3c3,
+ 0x323043,
+ 0x246eebc2,
+ 0x379b82,
+ 0x24a17202,
+ 0x32af48,
+ 0x358e08,
+ 0x3a5a46,
+ 0x2fd0c5,
+ 0x317885,
+ 0x333d07,
+ 0x2247c5,
+ 0x210642,
+ 0x24e04742,
+ 0x160a442,
+ 0x2447c8,
+ 0x2dda45,
+ 0x2bfbc4,
+ 0x2f2845,
+ 0x381d87,
+ 0x240944,
+ 0x24c682,
+ 0x25200582,
+ 0x33ffc4,
+ 0x21ca07,
+ 0x292507,
+ 0x35e844,
+ 0x29a843,
+ 0x23de04,
+ 0x23de08,
+ 0x23a1c6,
+ 0x27258a,
+ 0x222204,
+ 0x29abc8,
+ 0x290584,
+ 0x229ec6,
+ 0x29c484,
+ 0x28b146,
+ 0x376349,
+ 0x274847,
+ 0x241243,
+ 0x256351c2,
+ 0x2755c3,
+ 0x214d02,
+ 0x25a52e42,
+ 0x313486,
+ 0x374588,
+ 0x2ac047,
+ 0x3ab249,
+ 0x299f49,
+ 0x2acf05,
+ 0x2adec9,
+ 0x2ae685,
+ 0x2ae7c9,
+ 0x2afe45,
+ 0x2b11c8,
+ 0x25e0a104,
+ 0x26259ac7,
+ 0x2b13c3,
+ 0x2b13c7,
+ 0x3ba046,
+ 0x2b1a47,
+ 0x2a9b05,
+ 0x2a2cc3,
+ 0x26636d02,
+ 0x339704,
+ 0x26a42a42,
+ 0x266603,
+ 0x26e206c2,
+ 0x30df06,
+ 0x2814c5,
+ 0x2b3cc7,
+ 0x332043,
+ 0x32c2c4,
+ 0x217003,
+ 0x342c43,
+ 0x27205e82,
+ 0x27a0c442,
+ 0x3a5404,
+ 0x2f67c3,
+ 0x24e545,
+ 0x27e01c82,
+ 0x286007c2,
+ 0x2c8286,
+ 0x322144,
+ 0x38c444,
+ 0x38c44a,
+ 0x28e00942,
+ 0x38298a,
+ 0x39b8c8,
+ 0x29231604,
+ 0x2046c3,
+ 0x20d8c3,
+ 0x306349,
+ 0x25bd09,
+ 0x364986,
+ 0x29655783,
+ 0x335d45,
+ 0x30d2cd,
+ 0x39ba86,
+ 0x204f4b,
+ 0x29a02b02,
+ 0x225b48,
+ 0x2be22782,
+ 0x2c203e02,
+ 0x2b1685,
+ 0x2c604182,
+ 0x266847,
+ 0x21b987,
+ 0x20bf43,
+ 0x23b188,
+ 0x2ca02542,
+ 0x3780c4,
+ 0x21a8c3,
+ 0x348505,
+ 0x364603,
+ 0x33c406,
+ 0x212a84,
+ 0x275f43,
+ 0x2b6443,
+ 0x2ce09942,
+ 0x2fd7c4,
+ 0x379c85,
+ 0x3b6587,
+ 0x280003,
+ 0x2b5103,
+ 0x2b5c03,
+ 0x1631182,
+ 0x2b5cc3,
+ 0x2b63c3,
+ 0x2d2086c2,
+ 0x3a2e44,
+ 0x262786,
+ 0x34ba83,
+ 0x2086c3,
+ 0x2d6b8042,
+ 0x2b8048,
+ 0x2b8304,
+ 0x37ce46,
+ 0x2b8bc7,
+ 0x258346,
+ 0x2a0304,
+ 0x3b201702,
+ 0x3b9f0b,
+ 0x307c0e,
+ 0x221d4f,
+ 0x2ac5c3,
+ 0x3ba64d42,
+ 0x160b542,
+ 0x3be00a82,
+ 0x2e89c3,
+ 0x2e4903,
+ 0x2de046,
+ 0x207986,
+ 0x203007,
+ 0x304704,
+ 0x3c221302,
+ 0x3c618742,
+ 0x3a1205,
+ 0x2e7007,
+ 0x38c946,
+ 0x3ca28142,
+ 0x228144,
+ 0x2bc743,
+ 0x3ce09a02,
+ 0x3d366443,
+ 0x2bce04,
+ 0x2c5409,
+ 0x16cb602,
+ 0x3d605242,
+ 0x385d85,
+ 0x3dacb882,
+ 0x3de03582,
+ 0x3541c7,
+ 0x21b2c9,
+ 0x368e8b,
+ 0x3a0105,
+ 0x2714c9,
+ 0x384d06,
+ 0x343c47,
+ 0x3e206844,
+ 0x341d89,
+ 0x380907,
+ 0x348ac7,
+ 0x2122c3,
+ 0x2122c6,
+ 0x312247,
+ 0x263a43,
+ 0x263a46,
+ 0x3ea01cc2,
+ 0x3ee022c2,
+ 0x22bf03,
+ 0x32bec5,
+ 0x25a007,
+ 0x227906,
+ 0x2c3e05,
+ 0x207a84,
+ 0x28ddc5,
+ 0x2fae04,
+ 0x3f204bc2,
+ 0x337447,
+ 0x2ca604,
+ 0x24f3c4,
+ 0x25bc0d,
+ 0x25d749,
+ 0x3ab748,
+ 0x25e044,
+ 0x234a85,
+ 0x322907,
+ 0x3329c4,
+ 0x2fa747,
+ 0x204bc5,
+ 0x3f6ac504,
+ 0x2b5e05,
+ 0x269404,
+ 0x256fc6,
+ 0x34fe05,
+ 0x3fa048c2,
+ 0x2011c4,
+ 0x2011c5,
+ 0x3802c6,
+ 0x206d85,
+ 0x3c0144,
+ 0x2cda83,
+ 0x208d46,
+ 0x222545,
+ 0x22b605,
+ 0x34ff04,
+ 0x222283,
+ 0x22228c,
+ 0x3fe90a82,
+ 0x40206702,
+ 0x40600282,
+ 0x211a83,
+ 0x211a84,
+ 0x40a02942,
+ 0x2fba48,
+ 0x341485,
+ 0x34c984,
+ 0x36ee86,
+ 0x40e0d842,
+ 0x41234502,
+ 0x41601fc2,
+ 0x2a6a85,
+ 0x210446,
+ 0x226144,
+ 0x32d646,
+ 0x28ba06,
+ 0x215c83,
+ 0x41b2770a,
+ 0x2f6b05,
+ 0x2f6fc3,
+ 0x22a9c6,
+ 0x30c989,
+ 0x22a9c7,
+ 0x29f648,
+ 0x29ff09,
+ 0x241b08,
+ 0x22e546,
+ 0x209b03,
+ 0x41e0c202,
+ 0x395343,
+ 0x395349,
+ 0x333608,
+ 0x42253442,
+ 0x42604a82,
+ 0x229443,
+ 0x2e4505,
+ 0x25c404,
+ 0x2c9ec9,
+ 0x26eb44,
+ 0x2e0908,
+ 0x2050c3,
+ 0x20dc44,
+ 0x2acd03,
+ 0x221208,
+ 0x25bb47,
+ 0x42e281c2,
+ 0x270d02,
+ 0x388b05,
+ 0x272dc9,
+ 0x28cac3,
+ 0x284bc4,
+ 0x335d04,
+ 0x227543,
+ 0x28580a,
+ 0x43382842,
+ 0x43601182,
+ 0x2cd543,
+ 0x384f83,
+ 0x160dc02,
+ 0x20ffc3,
+ 0x43a14702,
+ 0x43e00802,
+ 0x4420f644,
+ 0x20f646,
+ 0x3b6a46,
+ 0x248c44,
+ 0x37d243,
+ 0x200803,
+ 0x2f60c3,
+ 0x24a406,
+ 0x30aa05,
+ 0x2cd6c7,
+ 0x343b09,
+ 0x2d2d85,
+ 0x2d3f46,
+ 0x2d4908,
+ 0x2d4b06,
+ 0x260ec4,
+ 0x2a1d8b,
+ 0x2d8403,
+ 0x2d8405,
+ 0x2d8548,
+ 0x22c2c2,
+ 0x3544c2,
+ 0x4464ea42,
+ 0x44a14642,
+ 0x221343,
+ 0x44e745c2,
+ 0x2745c3,
+ 0x2d8844,
+ 0x2d8e03,
+ 0x45605902,
+ 0x45a0c0c6,
+ 0x2af186,
+ 0x45edcac2,
+ 0x462162c2,
+ 0x4662a482,
+ 0x46a00e82,
+ 0x46e176c2,
+ 0x47202ec2,
+ 0x205383,
+ 0x344905,
+ 0x348206,
+ 0x4761bf84,
+ 0x34e5ca,
+ 0x20bd46,
+ 0x220e04,
+ 0x28a483,
+ 0x4820ea42,
+ 0x204d42,
+ 0x23d503,
+ 0x48608e83,
+ 0x2d8047,
+ 0x34fd07,
+ 0x49e31787,
+ 0x23fcc7,
+ 0x2309c3,
+ 0x33188a,
+ 0x263544,
+ 0x3863c4,
+ 0x3863ca,
+ 0x24b685,
+ 0x4a2190c2,
+ 0x254b43,
+ 0x4a601942,
+ 0x21b543,
+ 0x275583,
+ 0x4ae02b82,
+ 0x2b0284,
+ 0x2256c4,
+ 0x208105,
+ 0x39e745,
+ 0x2fc3c6,
+ 0x2fc746,
+ 0x4b206802,
+ 0x4b600982,
+ 0x3139c5,
+ 0x2aee92,
+ 0x259806,
+ 0x231483,
+ 0x315a06,
+ 0x231485,
+ 0x1616b82,
+ 0x53a17102,
+ 0x35fd43,
+ 0x217103,
+ 0x35d703,
+ 0x53e02c82,
+ 0x38a783,
+ 0x54205b82,
+ 0x20cc43,
+ 0x3a2e88,
+ 0x231e83,
+ 0x231e86,
+ 0x3b0c87,
+ 0x26c286,
+ 0x26c28b,
+ 0x220d47,
+ 0x339504,
+ 0x54a00e42,
+ 0x341305,
+ 0x54e08e43,
+ 0x2aec83,
+ 0x32de85,
+ 0x331783,
+ 0x55331786,
+ 0x2108ca,
+ 0x2488c3,
+ 0x240c44,
+ 0x2cf4c6,
+ 0x2364c6,
+ 0x55601a03,
+ 0x32c187,
+ 0x364887,
+ 0x2a3885,
+ 0x251046,
+ 0x222583,
+ 0x57619f43,
+ 0x57a0cb42,
+ 0x34bd44,
+ 0x22c24c,
+ 0x232f09,
+ 0x2445c7,
+ 0x38ad45,
+ 0x252c84,
+ 0x25e6c8,
+ 0x265d45,
+ 0x57e6c505,
+ 0x27b709,
+ 0x2e6103,
+ 0x24f204,
+ 0x5821cc82,
+ 0x221543,
+ 0x5869bf42,
+ 0x3bbe86,
+ 0x16235c2,
+ 0x58a35b42,
+ 0x2a6988,
+ 0x2ac343,
+ 0x2b5d47,
+ 0x2daa05,
+ 0x2e5205,
+ 0x2e520b,
+ 0x2e58c6,
+ 0x2e5406,
+ 0x2e9006,
+ 0x232b84,
+ 0x2e9246,
+ 0x58eeae88,
+ 0x246003,
+ 0x231a43,
+ 0x231a44,
+ 0x2ea484,
+ 0x2eab87,
+ 0x2ec3c5,
+ 0x592ec502,
+ 0x59607082,
+ 0x207085,
+ 0x295bc4,
+ 0x2ef38b,
+ 0x2efa08,
+ 0x2998c4,
+ 0x228182,
+ 0x59e99842,
+ 0x350e83,
+ 0x2efec4,
+ 0x2f0185,
+ 0x2f0607,
+ 0x2f2384,
+ 0x220c04,
+ 0x5a204102,
+ 0x36f5c9,
+ 0x2f3185,
+ 0x3a03c5,
+ 0x2f3e45,
+ 0x5a621483,
+ 0x2f4dc4,
+ 0x2f4dcb,
+ 0x2f5204,
+ 0x2f5c0b,
+ 0x2f6005,
+ 0x221e8a,
+ 0x2f7608,
+ 0x2f780a,
+ 0x2f7fc3,
+ 0x2f7fca,
+ 0x5aa33502,
+ 0x5ae2fa42,
+ 0x236903,
+ 0x5b2f9f02,
+ 0x2f9f03,
+ 0x5b71c482,
+ 0x5bb29ac2,
+ 0x2fac84,
+ 0x2227c6,
+ 0x32d385,
+ 0x2fd4c3,
+ 0x320446,
+ 0x317345,
+ 0x262a84,
+ 0x5be06b42,
+ 0x2ba844,
+ 0x2cdc4a,
+ 0x22fd07,
+ 0x2e5e86,
+ 0x2612c7,
+ 0x20c743,
+ 0x2bce48,
+ 0x39fd8b,
+ 0x230305,
+ 0x2f41c5,
+ 0x2f41c6,
+ 0x2ea004,
+ 0x3bf388,
+ 0x20e543,
+ 0x21f784,
+ 0x21f787,
+ 0x355746,
+ 0x344b06,
+ 0x29810a,
+ 0x250d44,
+ 0x250d4a,
+ 0x5c20c386,
+ 0x20c387,
+ 0x25ca07,
+ 0x27b0c4,
+ 0x27b0c9,
+ 0x262445,
+ 0x2439cb,
+ 0x2eef43,
+ 0x21ad43,
+ 0x5c625b03,
+ 0x23a584,
+ 0x5ca00482,
+ 0x2f70c6,
+ 0x5cea2a45,
+ 0x315c45,
+ 0x258586,
+ 0x352b04,
+ 0x5d2044c2,
+ 0x24bbc4,
+ 0x5d60b282,
+ 0x28b5c5,
+ 0x236c84,
+ 0x22cb43,
+ 0x5de17142,
+ 0x217143,
+ 0x273e86,
+ 0x5e204242,
+ 0x2241c8,
+ 0x22a844,
+ 0x22a846,
+ 0x204dc6,
+ 0x25ec04,
+ 0x208cc5,
+ 0x214e48,
+ 0x215647,
+ 0x2159c7,
+ 0x2159cf,
+ 0x29b086,
+ 0x22f483,
+ 0x22f484,
+ 0x36edc4,
+ 0x213103,
+ 0x22a004,
+ 0x2494c4,
+ 0x5e60fd02,
+ 0x291cc3,
+ 0x24bf43,
+ 0x5ea0d2c2,
+ 0x22f043,
+ 0x20d2c3,
+ 0x21d70a,
+ 0x2e7d07,
+ 0x381f0c,
+ 0x3821c6,
+ 0x2f5a86,
+ 0x2f6447,
+ 0x5ee0e947,
+ 0x252d49,
+ 0x245984,
+ 0x253e04,
+ 0x5f221382,
+ 0x5f600a02,
+ 0x2984c6,
+ 0x32bf84,
+ 0x2df606,
+ 0x239048,
+ 0x2bf2c4,
+ 0x266886,
+ 0x2d9d05,
+ 0x26e488,
+ 0x2041c3,
+ 0x26fd85,
+ 0x270b03,
+ 0x3a04c3,
+ 0x3a04c4,
+ 0x206ac3,
+ 0x5fa0e602,
+ 0x5fe00742,
+ 0x2eee09,
+ 0x273885,
+ 0x276bc4,
+ 0x27ab05,
+ 0x217e84,
+ 0x2c62c7,
+ 0x36ecc5,
+ 0x231944,
+ 0x231948,
+ 0x2d6206,
+ 0x2dac04,
+ 0x2e0788,
+ 0x2e1fc7,
+ 0x60202502,
+ 0x2e6f44,
+ 0x2131c4,
+ 0x348cc7,
+ 0x60602504,
+ 0x210f82,
+ 0x60a06742,
+ 0x227103,
+ 0x2dfc84,
+ 0x2b2143,
+ 0x370645,
+ 0x60e06d42,
+ 0x2eeac5,
+ 0x21b9c2,
+ 0x35c7c5,
+ 0x374745,
+ 0x61204d02,
+ 0x35f004,
+ 0x61606182,
+ 0x266d86,
+ 0x2a7806,
+ 0x272f08,
+ 0x2c7588,
+ 0x30de84,
+ 0x2f97c5,
+ 0x395809,
+ 0x2fd8c4,
+ 0x210884,
+ 0x208483,
+ 0x61a1f545,
+ 0x2cb6c7,
+ 0x28d004,
+ 0x31288d,
+ 0x332182,
+ 0x33f203,
+ 0x3479c3,
+ 0x61e00d02,
+ 0x397dc5,
+ 0x212cc7,
+ 0x23fd84,
+ 0x23fd87,
+ 0x2a0109,
+ 0x2cdd89,
+ 0x277e07,
+ 0x20f803,
+ 0x2ba348,
+ 0x2522c9,
+ 0x349c47,
+ 0x355685,
+ 0x395546,
+ 0x398bc6,
+ 0x3aaf05,
+ 0x25d845,
+ 0x62209142,
+ 0x37da45,
+ 0x2bad08,
+ 0x2c9546,
+ 0x626c0d47,
+ 0x2f6244,
+ 0x29bb07,
+ 0x300246,
+ 0x62a3b442,
+ 0x37ffc6,
+ 0x302d4a,
+ 0x3035c5,
+ 0x62ee6282,
+ 0x63260a02,
+ 0x312586,
+ 0x2b36c8,
+ 0x636926c7,
+ 0x63a04502,
+ 0x226783,
+ 0x36a846,
+ 0x22cf04,
+ 0x3b0b46,
+ 0x344e06,
+ 0x36d78a,
+ 0x377705,
+ 0x208806,
+ 0x2205c3,
+ 0x2205c4,
+ 0x203082,
+ 0x314a43,
+ 0x63e11ac2,
+ 0x2f8483,
+ 0x382c04,
+ 0x2b3804,
+ 0x2b380a,
+ 0x22e603,
+ 0x281288,
+ 0x22e60a,
+ 0x2b4247,
+ 0x309306,
+ 0x266c44,
+ 0x220cc2,
+ 0x228cc2,
+ 0x64207002,
+ 0x23ddc3,
+ 0x25c7c7,
+ 0x320707,
+ 0x28e8c4,
+ 0x39d147,
+ 0x2f0706,
+ 0x21e747,
+ 0x233484,
+ 0x398ac5,
+ 0x2ce485,
+ 0x6462be42,
+ 0x231146,
+ 0x327943,
+ 0x371742,
+ 0x383306,
+ 0x64a08bc2,
+ 0x64e05082,
+ 0x3c0985,
+ 0x6522a202,
+ 0x65604782,
+ 0x348085,
+ 0x39e345,
+ 0x2088c5,
+ 0x26f003,
+ 0x352285,
+ 0x2e5987,
+ 0x305cc5,
+ 0x311985,
+ 0x3b01c4,
+ 0x24d486,
+ 0x264544,
+ 0x65a00d42,
+ 0x666f2bc5,
+ 0x2ab647,
+ 0x3176c8,
+ 0x29f806,
+ 0x29f80d,
+ 0x2aac09,
+ 0x2aac12,
+ 0x359f05,
+ 0x36f8c3,
+ 0x66a08882,
+ 0x314544,
+ 0x39bb03,
+ 0x3963c5,
+ 0x304a45,
+ 0x66e1a902,
+ 0x264183,
+ 0x67231802,
+ 0x67a43242,
+ 0x67e1f342,
+ 0x2ed385,
+ 0x23fec3,
+ 0x36d408,
+ 0x68204382,
+ 0x686000c2,
+ 0x2b0246,
+ 0x35f2ca,
+ 0x205503,
+ 0x209f43,
+ 0x2ef103,
+ 0x69202642,
+ 0x77602cc2,
+ 0x77e0d582,
+ 0x206442,
+ 0x37fdc9,
+ 0x2caa44,
+ 0x23b488,
+ 0x782fd502,
+ 0x78603642,
+ 0x2f5e45,
+ 0x23d9c8,
+ 0x3a2fc8,
+ 0x25920c,
+ 0x22fac3,
+ 0x78a68dc2,
+ 0x78e0c402,
+ 0x2d3206,
+ 0x30a185,
+ 0x2a7b83,
+ 0x381c46,
+ 0x30a2c6,
+ 0x20d883,
+ 0x30bc43,
+ 0x30c146,
+ 0x30cd84,
+ 0x29d386,
+ 0x2d85c5,
+ 0x30d10a,
+ 0x2397c4,
+ 0x30e244,
+ 0x30f08a,
+ 0x79203442,
+ 0x2413c5,
+ 0x31018a,
+ 0x310a85,
+ 0x311344,
+ 0x311446,
+ 0x3115c4,
+ 0x221806,
+ 0x79611042,
+ 0x33c0c6,
+ 0x3b1b45,
+ 0x3b80c7,
+ 0x200206,
+ 0x2de844,
+ 0x2de847,
+ 0x327646,
+ 0x245345,
+ 0x245347,
+ 0x3abdc7,
+ 0x3abdce,
+ 0x232206,
+ 0x2fa605,
+ 0x202447,
+ 0x216303,
+ 0x3326c7,
+ 0x2172c5,
+ 0x21b0c4,
+ 0x2343c2,
+ 0x2432c7,
+ 0x304784,
+ 0x383884,
+ 0x270b8b,
+ 0x224e03,
+ 0x2d4c47,
+ 0x224e04,
+ 0x2f11c7,
+ 0x299543,
+ 0x33dd4d,
+ 0x398608,
+ 0x224604,
+ 0x231845,
+ 0x312bc5,
+ 0x313003,
+ 0x79a0c4c2,
+ 0x314a03,
+ 0x314d43,
+ 0x20f204,
+ 0x283745,
+ 0x22a4c7,
+ 0x220646,
+ 0x382943,
+ 0x38344b,
+ 0x259c8b,
+ 0x2ac9cb,
+ 0x2fbd4b,
+ 0x2c578a,
+ 0x30e48b,
+ 0x32420b,
+ 0x362f0c,
+ 0x38bf4b,
+ 0x3bdf51,
+ 0x3bfd8a,
+ 0x31604b,
+ 0x31630c,
+ 0x31660b,
+ 0x316b8a,
+ 0x317c8a,
+ 0x318c8e,
+ 0x31930b,
+ 0x3195ca,
+ 0x31a9d1,
+ 0x31ae0a,
+ 0x31b30b,
+ 0x31b84e,
+ 0x31c18c,
+ 0x31c68b,
+ 0x31c94e,
+ 0x31cccc,
+ 0x31d9ca,
+ 0x31eccc,
+ 0x79f1efca,
+ 0x31f7c8,
+ 0x320909,
+ 0x3232ca,
+ 0x32354a,
+ 0x3237cb,
+ 0x326d8e,
+ 0x327111,
+ 0x330189,
+ 0x3303ca,
+ 0x3313cb,
+ 0x334a0a,
+ 0x3354d6,
+ 0x336e4b,
+ 0x337b0a,
+ 0x337f4a,
+ 0x33a4cb,
+ 0x33b749,
+ 0x33e6c9,
+ 0x33ec8d,
+ 0x33f2cb,
+ 0x34040b,
+ 0x340dcb,
+ 0x347049,
+ 0x34768e,
+ 0x347dca,
+ 0x3494ca,
+ 0x349a0a,
+ 0x34a14b,
+ 0x34a98b,
+ 0x34ac4d,
+ 0x34c50d,
+ 0x34cd50,
+ 0x34d20b,
+ 0x35064c,
+ 0x3512cb,
+ 0x353ccb,
+ 0x35528e,
+ 0x355e0b,
+ 0x355e0d,
+ 0x35ae8b,
+ 0x35b90f,
+ 0x35bccb,
+ 0x35c50a,
+ 0x35cb49,
+ 0x35de09,
+ 0x35e18b,
+ 0x35e44e,
+ 0x36020b,
+ 0x361acf,
+ 0x36394b,
+ 0x363c0b,
+ 0x363ecb,
+ 0x3643ca,
+ 0x368a89,
+ 0x36e04f,
+ 0x372a8c,
+ 0x3732cc,
+ 0x37374e,
+ 0x373ccf,
+ 0x37408e,
+ 0x375690,
+ 0x375a8f,
+ 0x37660e,
+ 0x376f4c,
+ 0x377252,
+ 0x379891,
+ 0x37a18e,
+ 0x37a94e,
+ 0x37ae8e,
+ 0x37b20f,
+ 0x37b5ce,
+ 0x37b953,
+ 0x37be11,
+ 0x37c24c,
+ 0x37c54e,
+ 0x37c9cc,
+ 0x37de53,
+ 0x37ead0,
+ 0x37f30c,
+ 0x37f60c,
+ 0x37facb,
+ 0x38044e,
+ 0x380d8b,
+ 0x3816cb,
+ 0x382fcc,
+ 0x38b38a,
+ 0x38b74c,
+ 0x38ba4c,
+ 0x38bd49,
+ 0x38d7cb,
+ 0x38da88,
+ 0x38df49,
+ 0x38df4f,
+ 0x38f88b,
+ 0x7a39028a,
+ 0x391e4c,
+ 0x393009,
+ 0x393488,
+ 0x39368b,
+ 0x393d8b,
+ 0x39490a,
+ 0x394b8b,
+ 0x3950cc,
+ 0x396048,
+ 0x398d4b,
+ 0x39b1cb,
+ 0x39ef4e,
+ 0x3a05cb,
+ 0x3a1f0b,
+ 0x3ab94b,
+ 0x3abc09,
+ 0x3ac14d,
+ 0x3b1d4a,
+ 0x3b2c97,
+ 0x3b4398,
+ 0x3b6bc9,
+ 0x3b7d0b,
+ 0x3b8fd4,
+ 0x3b94cb,
+ 0x3b9a4a,
+ 0x3ba38a,
+ 0x3ba60b,
+ 0x3badd0,
+ 0x3bb1d1,
+ 0x3bc00a,
+ 0x3bd54d,
+ 0x3bdc4d,
+ 0x3c05cb,
+ 0x3c1206,
+ 0x231243,
+ 0x7a791143,
+ 0x26ed86,
+ 0x248805,
+ 0x22d287,
+ 0x3240c6,
+ 0x1608742,
+ 0x2c1fc9,
+ 0x320244,
+ 0x2e4d48,
+ 0x210943,
+ 0x314487,
+ 0x239202,
+ 0x2b3d03,
+ 0x7aa04542,
+ 0x2d0d06,
+ 0x2d2104,
+ 0x37a844,
+ 0x3443c3,
+ 0x3443c5,
+ 0x7b2cb8c2,
+ 0x7b6aeb44,
+ 0x27b007,
+ 0x7ba43282,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x28cac3,
+ 0x208e83,
+ 0x201a03,
+ 0x200e03,
+ 0x207102,
+ 0x16fb88,
+ 0x20f882,
+ 0x323043,
+ 0x28cac3,
+ 0x208e83,
+ 0xe03,
+ 0x201a03,
+ 0x215443,
+ 0x32b7d6,
+ 0x32ca13,
+ 0x39cfc9,
+ 0x34e148,
+ 0x341189,
+ 0x310306,
+ 0x340010,
+ 0x24c9d3,
+ 0x355808,
+ 0x2a0a87,
+ 0x37d347,
+ 0x28db0a,
+ 0x232309,
+ 0x3961c9,
+ 0x28664b,
+ 0x33af86,
+ 0x20728a,
+ 0x228e06,
+ 0x31fe43,
+ 0x2dce85,
+ 0x233108,
+ 0x266e4d,
+ 0x28af0c,
+ 0x218c87,
+ 0x318fcd,
+ 0x214f44,
+ 0x23a84a,
+ 0x23bbca,
+ 0x23c08a,
+ 0x24ccc7,
+ 0x246b87,
+ 0x24a904,
+ 0x233d86,
+ 0x209d44,
+ 0x2c7ec8,
+ 0x26eb89,
+ 0x2bb246,
+ 0x2bb248,
+ 0x24d18d,
+ 0x2cdfc9,
+ 0x209708,
+ 0x3a0347,
+ 0x300fca,
+ 0x2550c6,
+ 0x2664c7,
+ 0x2bd584,
+ 0x292347,
+ 0x35180a,
+ 0x38690e,
+ 0x2247c5,
+ 0x29224b,
+ 0x32f709,
+ 0x25bd09,
+ 0x21b7c7,
+ 0x2936ca,
+ 0x348c07,
+ 0x307d49,
+ 0x20b808,
+ 0x33420b,
+ 0x2e4505,
+ 0x3ab60a,
+ 0x2734c9,
+ 0x331d0a,
+ 0x2d2e0b,
+ 0x38668b,
+ 0x2863d5,
+ 0x30be85,
+ 0x3a03c5,
+ 0x2f4dca,
+ 0x364a8a,
+ 0x32f487,
+ 0x2252c3,
+ 0x298448,
+ 0x2db34a,
+ 0x22a846,
+ 0x252109,
+ 0x26e488,
+ 0x2dac04,
+ 0x2b2149,
+ 0x2c7588,
+ 0x2b2d07,
+ 0x2f2bc6,
+ 0x2ab647,
+ 0x376d87,
+ 0x24a205,
+ 0x22460c,
+ 0x231845,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x208e83,
+ 0x201a03,
+ 0x20f882,
+ 0x238543,
+ 0x208e83,
+ 0x200e03,
+ 0x201a03,
+ 0x238543,
+ 0x208e83,
+ 0xe03,
+ 0x231e83,
+ 0x201a03,
+ 0x16fb88,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x28cac3,
+ 0x208e83,
+ 0xe03,
+ 0x201a03,
+ 0x16fb88,
+ 0x20f882,
+ 0x201742,
+ 0x23c2c2,
+ 0x202542,
+ 0x200542,
+ 0x2e6dc2,
+ 0x4638543,
+ 0x23cac3,
+ 0x21b583,
+ 0x323043,
+ 0x255783,
+ 0x28cac3,
+ 0x2dcd86,
+ 0x208e83,
+ 0x201a03,
+ 0x20bdc3,
+ 0x16fb88,
+ 0x345b44,
+ 0x20da07,
+ 0x2112c3,
+ 0x2b1684,
+ 0x208543,
+ 0x21b843,
+ 0x323043,
+ 0x36dc7,
+ 0x145944,
+ 0xf183,
+ 0x145c05,
+ 0x207102,
+ 0x19c783,
+ 0x5a0f882,
+ 0x1490fc9,
+ 0x9144d,
+ 0x9178d,
+ 0x23c2c2,
+ 0x31604,
+ 0x145c49,
+ 0x200442,
+ 0x5f4ed48,
+ 0xf4544,
+ 0x16fb88,
+ 0x1409702,
+ 0x1510cc6,
+ 0x239283,
+ 0x2bcc43,
+ 0x6638543,
+ 0x23a844,
+ 0x6a3cac3,
+ 0x6f23043,
+ 0x205e82,
+ 0x231604,
+ 0x208e83,
+ 0x301dc3,
+ 0x2014c2,
+ 0x201a03,
+ 0x222dc2,
+ 0x2fabc3,
+ 0x204242,
+ 0x205983,
+ 0x26e543,
+ 0x200202,
+ 0x16fb88,
+ 0x239283,
+ 0x301dc3,
+ 0x2014c2,
+ 0x2fabc3,
+ 0x204242,
+ 0x205983,
+ 0x26e543,
+ 0x200202,
+ 0x2fabc3,
+ 0x204242,
+ 0x205983,
+ 0x26e543,
+ 0x200202,
+ 0x238543,
+ 0x39c783,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x231604,
+ 0x255783,
+ 0x28cac3,
+ 0x21bf84,
+ 0x208e83,
+ 0x201a03,
+ 0x20cb02,
+ 0x221483,
+ 0x16fb88,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x28cac3,
+ 0x208e83,
+ 0x201a03,
+ 0x39c783,
+ 0x20f882,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x231604,
+ 0x208e83,
+ 0x201a03,
+ 0x355685,
+ 0x21a902,
+ 0x207102,
+ 0x16fb88,
+ 0x1480cc8,
+ 0x323043,
+ 0x20fec1,
+ 0x201641,
+ 0x203c01,
+ 0x201301,
+ 0x267401,
+ 0x2ae601,
+ 0x211341,
+ 0x28a0c1,
+ 0x24dfc1,
+ 0x2fbf81,
+ 0x200141,
+ 0x200001,
+ 0x131645,
+ 0x16fb88,
+ 0x2008c1,
+ 0x201781,
+ 0x200301,
+ 0x200081,
+ 0x200181,
+ 0x200401,
+ 0x200041,
+ 0x2086c1,
+ 0x200101,
+ 0x200281,
+ 0x200801,
+ 0x200981,
+ 0x200441,
+ 0x204101,
+ 0x2227c1,
+ 0x200341,
+ 0x200741,
+ 0x2002c1,
+ 0x2000c1,
+ 0x203441,
+ 0x200201,
+ 0x200c81,
+ 0x2005c1,
+ 0x204541,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x208e83,
+ 0x201a03,
+ 0x20f882,
+ 0x238543,
+ 0x23cac3,
+ 0x200442,
+ 0x201a03,
+ 0x36dc7,
+ 0x8cbc7,
+ 0x24386,
+ 0x44f4a,
+ 0x906c8,
+ 0x5c288,
+ 0x5c6c7,
+ 0xffc6,
+ 0xe1d45,
+ 0x11205,
+ 0x86286,
+ 0x12cf06,
+ 0x286644,
+ 0x31cf87,
+ 0x16fb88,
+ 0x2de944,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x208e83,
+ 0x201a03,
+ 0x238543,
+ 0x23cac3,
+ 0x21b583,
+ 0x323043,
+ 0x255783,
+ 0x28cac3,
+ 0x208e83,
+ 0x201a03,
+ 0x21a902,
+ 0x2ba8c3,
+ 0x242043,
+ 0x2cc103,
+ 0x202d42,
+ 0x33eb43,
+ 0x203ec3,
+ 0x20fc03,
+ 0x200001,
+ 0x2ed0c5,
+ 0x203c43,
+ 0x226544,
+ 0x332083,
+ 0x322103,
+ 0x222903,
+ 0x383283,
+ 0xaa38543,
+ 0x240244,
+ 0x24ac83,
+ 0x207583,
+ 0x2228c3,
+ 0x23aa83,
+ 0x23cac3,
+ 0x23c803,
+ 0x202103,
+ 0x2aab03,
+ 0x322083,
+ 0x2bdec3,
+ 0x20df43,
+ 0x255684,
+ 0x257307,
+ 0x2f6802,
+ 0x25c003,
+ 0x263783,
+ 0x27e983,
+ 0x20fe03,
+ 0x20dec3,
+ 0xaf23043,
+ 0x209ac3,
+ 0x204c03,
+ 0x231603,
+ 0x34bc85,
+ 0x209c83,
+ 0x304d43,
+ 0xb207a83,
+ 0x374803,
+ 0x213643,
+ 0x229443,
+ 0x28cac3,
+ 0x22c2c2,
+ 0x20c0c3,
+ 0x208e83,
+ 0x1600e03,
+ 0x22b1c3,
+ 0x2014c3,
+ 0x21a743,
+ 0x201a03,
+ 0x36ea03,
+ 0x223583,
+ 0x221483,
+ 0x233503,
+ 0x30bcc3,
+ 0x2fad83,
+ 0x317345,
+ 0x20c843,
+ 0x2df706,
+ 0x2fadc3,
+ 0x349703,
+ 0x2205c4,
+ 0x20c9c3,
+ 0x386603,
+ 0x2f1a03,
+ 0x20bdc3,
+ 0x21a902,
+ 0x22fac3,
+ 0x30e403,
+ 0x30fac4,
+ 0x383884,
+ 0x21a5c3,
+ 0x16fb88,
+ 0x207102,
+ 0x200242,
+ 0x202d42,
+ 0x20cac2,
+ 0x201d02,
+ 0x201442,
+ 0x23de42,
+ 0x201842,
+ 0x207b02,
+ 0x201fc2,
+ 0x2281c2,
+ 0x214642,
+ 0x2745c2,
+ 0x20cb42,
+ 0x2e6dc2,
+ 0x21cc82,
+ 0x225b82,
+ 0x204102,
+ 0x2204c2,
+ 0x205842,
+ 0x200482,
+ 0x221dc2,
+ 0x2044c2,
+ 0x20d2c2,
+ 0x200a02,
+ 0x21f542,
+ 0x204782,
+ 0x7102,
+ 0x242,
+ 0x2d42,
+ 0xcac2,
+ 0x1d02,
+ 0x1442,
+ 0x3de42,
+ 0x1842,
+ 0x7b02,
+ 0x1fc2,
+ 0x281c2,
+ 0x14642,
+ 0x745c2,
+ 0xcb42,
+ 0xe6dc2,
+ 0x1cc82,
+ 0x25b82,
+ 0x4102,
+ 0x204c2,
+ 0x5842,
+ 0x482,
+ 0x21dc2,
+ 0x44c2,
+ 0xd2c2,
+ 0xa02,
+ 0x1f542,
+ 0x4782,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x208e83,
+ 0x201a03,
+ 0x2442,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x208e83,
+ 0x201a03,
+ 0x20f882,
+ 0x201a03,
+ 0xc638543,
+ 0x323043,
+ 0x28cac3,
+ 0x1a3443,
+ 0x219302,
+ 0x16fb88,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x208e83,
+ 0x1a3443,
+ 0x201a03,
+ 0x4542,
+ 0x201c02,
+ 0x1442b45,
+ 0x232282,
+ 0x16fb88,
+ 0xf882,
+ 0x209d82,
+ 0x209b02,
+ 0x20ddc2,
+ 0x2190c2,
+ 0x206802,
+ 0x11205,
+ 0x201282,
+ 0x2014c2,
+ 0x202c82,
+ 0x200dc2,
+ 0x21cc82,
+ 0x3951c2,
+ 0x206742,
+ 0x260a42,
+ 0x36dc7,
+ 0x1501cd,
+ 0xe1dc9,
+ 0x5900b,
+ 0xe5848,
+ 0x56809,
+ 0x106046,
+ 0x323043,
+ 0x16fb88,
+ 0x145944,
+ 0xf183,
+ 0x145c05,
+ 0x16fb88,
+ 0x5d3c6,
+ 0x145c49,
+ 0x126447,
+ 0x207102,
+ 0x286644,
+ 0x20f882,
+ 0x238543,
+ 0x201742,
+ 0x23cac3,
+ 0x207b02,
+ 0x2de944,
+ 0x255783,
+ 0x253442,
+ 0x208e83,
+ 0x200442,
+ 0x201a03,
+ 0x3a03c6,
+ 0x323d8f,
+ 0x7156c3,
+ 0x16fb88,
+ 0x20f882,
+ 0x21b583,
+ 0x323043,
+ 0x28cac3,
+ 0xe03,
+ 0x152e1cb,
+ 0xe2648,
+ 0x14b7aca,
+ 0x14f5907,
+ 0x8dbcb,
+ 0x149785,
+ 0x36dc7,
+ 0x20f882,
+ 0x238543,
+ 0x323043,
+ 0x208e83,
+ 0x207102,
+ 0x200b42,
+ 0x2092c2,
+ 0xfe38543,
+ 0x248582,
+ 0x23cac3,
+ 0x209c42,
+ 0x20d382,
+ 0x323043,
+ 0x210642,
+ 0x259c42,
+ 0x2aeb02,
+ 0x2006c2,
+ 0x295e02,
+ 0x203102,
+ 0x200782,
+ 0x2351c2,
+ 0x2335c2,
+ 0x252e42,
+ 0x2b5102,
+ 0x2d2942,
+ 0x327982,
+ 0x2111c2,
+ 0x28cac3,
+ 0x200802,
+ 0x208e83,
+ 0x24d382,
+ 0x289e82,
+ 0x201a03,
+ 0x2485c2,
+ 0x20d2c2,
+ 0x221382,
+ 0x200742,
+ 0x204d02,
+ 0x2e6282,
+ 0x22be42,
+ 0x231802,
+ 0x2312c2,
+ 0x3195ca,
+ 0x35c50a,
+ 0x39090a,
+ 0x3c1382,
+ 0x208a82,
+ 0x212a42,
+ 0x10223fc9,
+ 0x1072c38a,
+ 0x1438547,
+ 0x10a02482,
+ 0x1416dc3,
+ 0x12c2,
+ 0x12c38a,
+ 0x252044,
+ 0x11238543,
+ 0x23cac3,
+ 0x253384,
+ 0x323043,
+ 0x231604,
+ 0x255783,
+ 0x28cac3,
+ 0x208e83,
+ 0xe3bc5,
+ 0x200e03,
+ 0x201a03,
+ 0x20c843,
+ 0x202443,
+ 0x16fb88,
+ 0x140ff44,
+ 0x1441c5,
+ 0x12620a,
+ 0x11ec42,
+ 0x1affc6,
+ 0x35ad1,
+ 0x11a23fc9,
+ 0x144248,
+ 0x10b388,
+ 0x8cf47,
+ 0xbc2,
+ 0x13164b,
+ 0x1b320a,
+ 0x71ca,
+ 0x26547,
+ 0x16fb88,
+ 0x114008,
+ 0x14507,
+ 0x17c2198b,
+ 0x23087,
+ 0xc702,
+ 0x5b907,
+ 0x1920a,
+ 0x8cc4f,
+ 0x4f70f,
+ 0x22902,
+ 0xf882,
+ 0xaaa48,
+ 0xe228a,
+ 0x6a08,
+ 0x64b88,
+ 0xdfbc8,
+ 0x4c82,
+ 0x42bcf,
+ 0xa670b,
+ 0xf8d08,
+ 0x3e607,
+ 0x185b8a,
+ 0x3af8b,
+ 0x57f89,
+ 0x185a87,
+ 0x6908,
+ 0x1089cc,
+ 0x81a87,
+ 0x1a800a,
+ 0xdd088,
+ 0x1aafce,
+ 0x2438e,
+ 0x2638b,
+ 0x27bcb,
+ 0x2920b,
+ 0x2c049,
+ 0x2ff8b,
+ 0x31ccd,
+ 0x329cb,
+ 0x62b4d,
+ 0x62ecd,
+ 0xfa44a,
+ 0x1836cb,
+ 0x3b64b,
+ 0x47085,
+ 0x1802cc10,
+ 0x12d40f,
+ 0x12db4f,
+ 0x37a4d,
+ 0xbf490,
+ 0xc182,
+ 0x18623a08,
+ 0x8ca48,
+ 0x18af52c5,
+ 0x52a0b,
+ 0x11f3d0,
+ 0x5ad08,
+ 0x6b0a,
+ 0x27d89,
+ 0x6b307,
+ 0x6b647,
+ 0x6b807,
+ 0x6bb87,
+ 0x6ca87,
+ 0x6d487,
+ 0x6ddc7,
+ 0x6e187,
+ 0x6f187,
+ 0x6f487,
+ 0x70147,
+ 0x70307,
+ 0x704c7,
+ 0x70687,
+ 0x70987,
+ 0x70e47,
+ 0x71707,
+ 0x72007,
+ 0x72c87,
+ 0x731c7,
+ 0x73387,
+ 0x73707,
+ 0x74487,
+ 0x74687,
+ 0x750c7,
+ 0x75287,
+ 0x75447,
+ 0x75dc7,
+ 0x76087,
+ 0x77a47,
+ 0x78187,
+ 0x78447,
+ 0x78bc7,
+ 0x78d87,
+ 0x79187,
+ 0x79687,
+ 0x79907,
+ 0x79d07,
+ 0x79ec7,
+ 0x7a087,
+ 0x7ae07,
+ 0x7c447,
+ 0x7c987,
+ 0x7cc87,
+ 0x7ce47,
+ 0x7d1c7,
+ 0x7d787,
+ 0x13c42,
+ 0x64c8a,
+ 0xe90c7,
+ 0x287c5,
+ 0x806d1,
+ 0x157c6,
+ 0x11318a,
+ 0xaa8ca,
+ 0x5d3c6,
+ 0xb880b,
+ 0x17202,
+ 0x3a1d1,
+ 0x1bbc89,
+ 0x9c0c9,
+ 0x351c2,
+ 0xa808a,
+ 0xac7c9,
+ 0xacf0f,
+ 0xada4e,
+ 0xae208,
+ 0x206c2,
+ 0xb649,
+ 0x1025ce,
+ 0xe8b4c,
+ 0xf328f,
+ 0x1a5b4e,
+ 0x1684c,
+ 0x18009,
+ 0x1c291,
+ 0x1f108,
+ 0x2ac92,
+ 0x2bb4d,
+ 0x33c4d,
+ 0x15208b,
+ 0x41cd5,
+ 0x164ec9,
+ 0xfcf8a,
+ 0x40809,
+ 0x4d650,
+ 0x4e70b,
+ 0x5898f,
+ 0x6390b,
+ 0x7298c,
+ 0x77650,
+ 0x8430a,
+ 0x853cd,
+ 0x894ce,
+ 0x8ef4a,
+ 0xede0c,
+ 0x176a54,
+ 0x1bb911,
+ 0x95a8b,
+ 0x97fcf,
+ 0xa290d,
+ 0xa76ce,
+ 0xb2bcc,
+ 0xb330c,
+ 0x160b0b,
+ 0x160e0e,
+ 0xd6750,
+ 0x11868b,
+ 0x1876cd,
+ 0x1bce4f,
+ 0xba0cc,
+ 0xbb0ce,
+ 0xbc011,
+ 0xc7c4c,
+ 0xc9307,
+ 0xc9c0d,
+ 0x130d4c,
+ 0x1605d0,
+ 0x174c0d,
+ 0xd1b47,
+ 0xd7c10,
+ 0xdd6c8,
+ 0xf178b,
+ 0x134c4f,
+ 0x3ef48,
+ 0x11338d,
+ 0x15c750,
+ 0x172e49,
+ 0x18e086c6,
+ 0xb8243,
+ 0xbc445,
+ 0x9a02,
+ 0x143889,
+ 0x5e04a,
+ 0x10fb06,
+ 0x2594a,
+ 0x1900c949,
+ 0x1c003,
+ 0xdebd1,
+ 0xdf009,
+ 0xe0407,
+ 0x35c4b,
+ 0xe67d0,
+ 0xe6c8c,
+ 0xe8e48,
+ 0xe9805,
+ 0xb988,
+ 0x1ad4ca,
+ 0x1c0c7,
+ 0x16bac7,
+ 0x982,
+ 0x12bcca,
+ 0x12e7c9,
+ 0x79545,
+ 0x402ca,
+ 0x9260f,
+ 0x4b8cb,
+ 0x14bd4c,
+ 0x17a492,
+ 0x94e45,
+ 0xec1c8,
+ 0x17618a,
+ 0x196f3d05,
+ 0x190ecc,
+ 0x129ac3,
+ 0x1951c2,
+ 0xfb30a,
+ 0x14fb70c,
+ 0x14f508,
+ 0x62d08,
+ 0x36d47,
+ 0xb282,
+ 0x4242,
+ 0x47590,
+ 0xa02,
+ 0x3904f,
+ 0x86286,
+ 0x7c0e,
+ 0xebbcb,
+ 0x8f148,
+ 0xda049,
+ 0x18f052,
+ 0x95cd,
+ 0x586c8,
+ 0x58ec9,
+ 0x5d50d,
+ 0x5e4c9,
+ 0x5e88b,
+ 0x60648,
+ 0x65808,
+ 0x65b88,
+ 0x65e49,
+ 0x6604a,
+ 0x6a98c,
+ 0xeb04a,
+ 0x10bd07,
+ 0x1f54d,
+ 0xfde8b,
+ 0x12004c,
+ 0x404c8,
+ 0x4f049,
+ 0x1b01d0,
+ 0xc2,
+ 0x2d3cd,
+ 0x2642,
+ 0x2cc2,
+ 0x10bc4a,
+ 0x11308a,
+ 0x11438b,
+ 0x3b80c,
+ 0x113b0a,
+ 0x113d8e,
+ 0xf2cd,
+ 0x11d708,
+ 0x4542,
+ 0x11f46c0e,
+ 0x1260ee4e,
+ 0x12f43f8a,
+ 0x1373a14e,
+ 0x13f9d38e,
+ 0x1460138c,
+ 0x1438547,
+ 0x1438549,
+ 0x1416dc3,
+ 0x14e3700c,
+ 0x15707789,
+ 0x15f3b509,
+ 0x12c2,
+ 0x146b51,
+ 0xed91,
+ 0x143ecd,
+ 0x13a091,
+ 0x19d2d1,
+ 0x12cf,
+ 0x36f4f,
+ 0x1076cc,
+ 0x13b44c,
+ 0x18954d,
+ 0x1b5295,
+ 0x10ed8c,
+ 0xea88c,
+ 0x122ed0,
+ 0x158fcc,
+ 0x16d9cc,
+ 0x191819,
+ 0x1a83d9,
+ 0x1aa459,
+ 0x1b3e94,
+ 0x1b8ad4,
+ 0x1c0d14,
+ 0x2394,
+ 0x3754,
+ 0x1670ee49,
+ 0x16dc0fc9,
+ 0x176ea949,
+ 0x1221f309,
+ 0x12c2,
+ 0x12a1f309,
+ 0x12c2,
+ 0x238a,
+ 0x12c2,
+ 0x1321f309,
+ 0x12c2,
+ 0x238a,
+ 0x12c2,
+ 0x13a1f309,
+ 0x12c2,
+ 0x1421f309,
+ 0x12c2,
+ 0x14a1f309,
+ 0x12c2,
+ 0x238a,
+ 0x12c2,
+ 0x1521f309,
+ 0x12c2,
+ 0x238a,
+ 0x12c2,
+ 0x15a1f309,
+ 0x12c2,
+ 0x1621f309,
+ 0x12c2,
+ 0x238a,
+ 0x12c2,
+ 0x16a1f309,
+ 0x12c2,
+ 0x1721f309,
+ 0x12c2,
+ 0x17a1f309,
+ 0x12c2,
+ 0x238a,
+ 0x12c2,
+ 0x35ac5,
+ 0x1b3204,
+ 0x146c0e,
+ 0xee4e,
+ 0x143f8a,
+ 0x13a14e,
+ 0x19d38e,
+ 0x138c,
+ 0x3700c,
+ 0x107789,
+ 0x13b509,
+ 0x10ee49,
+ 0x1c0fc9,
+ 0xea949,
+ 0x122f8d,
+ 0x2649,
+ 0x3a09,
+ 0x5bf04,
+ 0x11d8c4,
+ 0x126144,
+ 0x15f784,
+ 0x8de84,
+ 0x4b744,
+ 0x6e44,
+ 0x67344,
+ 0x8cf44,
+ 0x157e2c3,
+ 0xc182,
+ 0xf2c3,
+ 0x4c82,
+ 0x207102,
+ 0x20f882,
+ 0x201742,
+ 0x207602,
+ 0x207b02,
+ 0x200442,
+ 0x204242,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x231603,
+ 0x208e83,
+ 0x201a03,
+ 0x16fb88,
+ 0x238543,
+ 0x23cac3,
+ 0x208e83,
+ 0x201a03,
+ 0x160c3,
+ 0x323043,
+ 0x31604,
+ 0x207102,
+ 0x39c783,
+ 0x1b638543,
+ 0x2bf347,
+ 0x323043,
+ 0x211a83,
+ 0x21bf84,
+ 0x208e83,
+ 0x201a03,
+ 0x243d0a,
+ 0x3a03c5,
+ 0x221483,
+ 0x205082,
+ 0x16fb88,
+ 0x16fb88,
+ 0xf882,
+ 0x127482,
+ 0x1bf51b0b,
+ 0x5ba45,
+ 0x35dc5,
+ 0x114b46,
+ 0x145944,
+ 0xf183,
+ 0x145c05,
+ 0x131645,
+ 0x16fb88,
+ 0x23087,
+ 0x38543,
+ 0x1c644d87,
+ 0x1432c6,
+ 0x1c93b345,
+ 0x143387,
+ 0x1b4d0a,
+ 0x1b4bc8,
+ 0x11887,
+ 0x6df88,
+ 0x99707,
+ 0x152cf,
+ 0x435c7,
+ 0x150d86,
+ 0x11f3d0,
+ 0x12a58f,
+ 0x20a89,
+ 0x10fb84,
+ 0x1cd4344e,
+ 0xb098c,
+ 0x5810a,
+ 0xa7987,
+ 0x3520a,
+ 0xbb49,
+ 0xb514c,
+ 0x4304a,
+ 0x5ec8a,
+ 0x145c49,
+ 0x10fb06,
+ 0xa7a4a,
+ 0xe8a,
+ 0xa4e49,
+ 0xde488,
+ 0xde786,
+ 0xe284d,
+ 0xbc8c5,
+ 0x126447,
+ 0x1019c9,
+ 0xf72c7,
+ 0xb5ed4,
+ 0x103acb,
+ 0xf8b4a,
+ 0xab10d,
+ 0xd3c3,
+ 0xd3c3,
+ 0x24386,
+ 0xd3c3,
+ 0x19c783,
+ 0x16fb88,
+ 0xf882,
+ 0x53384,
+ 0x5f843,
+ 0x155685,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x208e83,
+ 0x201a03,
+ 0x203ec3,
+ 0x238543,
+ 0x23cac3,
+ 0x21b583,
+ 0x323043,
+ 0x28cac3,
+ 0x208e83,
+ 0x201a03,
+ 0x29c283,
+ 0x202443,
+ 0x203ec3,
+ 0x286644,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x208e83,
+ 0x201a03,
+ 0x206683,
+ 0x238543,
+ 0x23cac3,
+ 0x207603,
+ 0x21b583,
+ 0x323043,
+ 0x231604,
+ 0x3797c3,
+ 0x229443,
+ 0x28cac3,
+ 0x208e83,
+ 0x201a03,
+ 0x221483,
+ 0x36a883,
+ 0x1ea38543,
+ 0x23cac3,
+ 0x250ac3,
+ 0x323043,
+ 0x212143,
+ 0x229443,
+ 0x201a03,
+ 0x204103,
+ 0x35f584,
+ 0x16fb88,
+ 0x1f238543,
+ 0x23cac3,
+ 0x2ae2c3,
+ 0x323043,
+ 0x28cac3,
+ 0x21bf84,
+ 0x208e83,
+ 0x201a03,
+ 0x20e943,
+ 0x16fb88,
+ 0x1fa38543,
+ 0x23cac3,
+ 0x21b583,
+ 0x200e03,
+ 0x201a03,
+ 0x16fb88,
+ 0x1438547,
+ 0x39c783,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x231604,
+ 0x21bf84,
+ 0x208e83,
+ 0x201a03,
+ 0x131645,
+ 0x36dc7,
+ 0xb610b,
+ 0xdf404,
+ 0xbc8c5,
+ 0x1480cc8,
+ 0xae90d,
+ 0x20e6c505,
+ 0x7bd44,
+ 0x10c3,
+ 0x172d45,
+ 0x33b145,
+ 0x16fb88,
+ 0xd3c2,
+ 0x2bc3,
+ 0xf9306,
+ 0x31f948,
+ 0x3347c7,
+ 0x286644,
+ 0x39c286,
+ 0x3b5146,
+ 0x16fb88,
+ 0x2ddac3,
+ 0x342a49,
+ 0x26d615,
+ 0x6d61f,
+ 0x238543,
+ 0x3b3a52,
+ 0xf6306,
+ 0x114dc5,
+ 0x6b0a,
+ 0x27d89,
+ 0x3b380f,
+ 0x2de944,
+ 0x3490c5,
+ 0x304b10,
+ 0x34e347,
+ 0x200e03,
+ 0x293408,
+ 0x12ce46,
+ 0x29630a,
+ 0x230f04,
+ 0x2f3743,
+ 0x3a03c6,
+ 0x205082,
+ 0x22facb,
+ 0xe03,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x28cac3,
+ 0x208e83,
+ 0x201a03,
+ 0x2f9a03,
+ 0x20f882,
+ 0x6ed43,
+ 0x208e83,
+ 0x201a03,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x28cac3,
+ 0x201a03,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x211a83,
+ 0x228243,
+ 0x201a03,
+ 0x20f882,
+ 0x238543,
+ 0x23cac3,
+ 0x208e83,
+ 0xe03,
+ 0x201a03,
+ 0x207102,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x208e83,
+ 0x201a03,
+ 0x35dc5,
+ 0x286644,
+ 0x238543,
+ 0x23cac3,
+ 0x20f644,
+ 0x208e83,
+ 0x201a03,
+ 0x16fb88,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x208e83,
+ 0x1a3443,
+ 0x201a03,
+ 0x238543,
+ 0x23cac3,
+ 0x21b583,
+ 0x204c03,
+ 0x28cac3,
+ 0x208e83,
+ 0xe03,
+ 0x201a03,
+ 0x20f882,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x208e83,
+ 0x201a03,
+ 0x16fb88,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x210543,
+ 0x707c3,
+ 0x11a83,
+ 0x208e83,
+ 0x201a03,
+ 0x3195ca,
+ 0x335289,
+ 0x35438b,
+ 0x35490a,
+ 0x35c50a,
+ 0x369bcb,
+ 0x38274a,
+ 0x38b38a,
+ 0x39090a,
+ 0x390b8b,
+ 0x3ad209,
+ 0x3af10a,
+ 0x3af7cb,
+ 0x3b978b,
+ 0x3bfb4a,
+ 0x238543,
+ 0x23cac3,
+ 0x21b583,
+ 0x28cac3,
+ 0x208e83,
+ 0xe03,
+ 0x201a03,
+ 0x35dcb,
+ 0x651c8,
+ 0x1174c9,
+ 0x16fb88,
+ 0x238543,
+ 0x26b304,
+ 0x20b342,
+ 0x21bf84,
+ 0x346145,
+ 0x203ec3,
+ 0x286644,
+ 0x238543,
+ 0x240244,
+ 0x23cac3,
+ 0x253384,
+ 0x2de944,
+ 0x231604,
+ 0x229443,
+ 0x208e83,
+ 0x201a03,
+ 0x22d585,
+ 0x206683,
+ 0x221483,
+ 0x20ec43,
+ 0x231944,
+ 0x20fe84,
+ 0x2cc105,
+ 0x16fb88,
+ 0x30dc84,
+ 0x36bdc6,
+ 0x281384,
+ 0x20f882,
+ 0x381107,
+ 0x254d87,
+ 0x251844,
+ 0x260105,
+ 0x374e05,
+ 0x2b13c5,
+ 0x231604,
+ 0x2cf6c8,
+ 0x23eb46,
+ 0x3bffc8,
+ 0x257cc5,
+ 0x2e4505,
+ 0x263544,
+ 0x201a03,
+ 0x2f4544,
+ 0x368dc6,
+ 0x3a04c3,
+ 0x231944,
+ 0x280bc5,
+ 0x2e4ac4,
+ 0x34da44,
+ 0x205082,
+ 0x2669c6,
+ 0x3a2906,
+ 0x30a185,
+ 0x207102,
+ 0x39c783,
+ 0x2760f882,
+ 0x223b84,
+ 0x207b02,
+ 0x28cac3,
+ 0x200e82,
+ 0x208e83,
+ 0x200442,
+ 0x215443,
+ 0x202443,
+ 0x16fb88,
+ 0x16fb88,
+ 0x323043,
+ 0x207102,
+ 0x2820f882,
+ 0x323043,
+ 0x270443,
+ 0x3797c3,
+ 0x32e5c4,
+ 0x208e83,
+ 0x201a03,
+ 0x16fb88,
+ 0x207102,
+ 0x28a0f882,
+ 0x238543,
+ 0x208e83,
+ 0xe03,
+ 0x201a03,
+ 0x482,
+ 0x208882,
+ 0x21a902,
+ 0x211a83,
+ 0x2ef783,
+ 0x207102,
+ 0x131645,
+ 0x16fb88,
+ 0x36dc7,
+ 0x20f882,
+ 0x23cac3,
+ 0x253384,
+ 0x2020c3,
+ 0x323043,
+ 0x204c03,
+ 0x28cac3,
+ 0x208e83,
+ 0x21eb43,
+ 0x201a03,
+ 0x2252c3,
+ 0x122213,
+ 0x124cd4,
+ 0x36dc7,
+ 0x139986,
+ 0x5e24b,
+ 0x24386,
+ 0x5c0c7,
+ 0x120589,
+ 0xe838a,
+ 0x9058d,
+ 0x14fecc,
+ 0x3954a,
+ 0x11205,
+ 0x1b4d48,
+ 0x86286,
+ 0x31586,
+ 0x12cf06,
+ 0x20c182,
+ 0x10b14c,
+ 0x1b33c7,
+ 0x2a691,
+ 0x238543,
+ 0x6df05,
+ 0x7588,
+ 0x18ec4,
+ 0x29cbe1c6,
+ 0x806c6,
+ 0xb9a06,
+ 0x960ca,
+ 0xb4003,
+ 0x2a24c984,
+ 0xe8345,
+ 0x18e43,
+ 0x2a63dc47,
+ 0xe3bc5,
+ 0xb88cc,
+ 0xf7a88,
+ 0xbd248,
+ 0xa6589,
+ 0x14dc08,
+ 0x1425886,
+ 0x2ab71549,
+ 0x14978a,
+ 0x16308,
+ 0x114b48,
+ 0x8cf44,
+ 0xb5ac5,
+ 0x2ae42bc3,
+ 0x2b332106,
+ 0x2b6f4dc4,
+ 0x2bb39d87,
+ 0x114b44,
+ 0x114b44,
+ 0x114b44,
+ 0x114b44,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x28cac3,
+ 0x208e83,
+ 0x201a03,
+ 0x207102,
+ 0x20f882,
+ 0x323043,
+ 0x205e82,
+ 0x208e83,
+ 0x201a03,
+ 0x215443,
+ 0x373ccf,
+ 0x37408e,
+ 0x16fb88,
+ 0x238543,
+ 0x4db87,
+ 0x23cac3,
+ 0x323043,
+ 0x255783,
+ 0x208e83,
+ 0x201a03,
+ 0x20d4c3,
+ 0x20d4c7,
+ 0x200142,
+ 0x2ce609,
+ 0x200242,
+ 0x24788b,
+ 0x2c110a,
+ 0x2c67c9,
+ 0x201242,
+ 0x2100c6,
+ 0x26cd95,
+ 0x2479d5,
+ 0x275793,
+ 0x247f53,
+ 0x201d42,
+ 0x212c45,
+ 0x31d44c,
+ 0x27c6cb,
+ 0x29c705,
+ 0x20cac2,
+ 0x28e142,
+ 0x384c06,
+ 0x200bc2,
+ 0x3acc46,
+ 0x2dd20d,
+ 0x26540c,
+ 0x22cc84,
+ 0x200f82,
+ 0x203402,
+ 0x22b048,
+ 0x201d02,
+ 0x20a746,
+ 0x28bf04,
+ 0x26cf55,
+ 0x275913,
+ 0x216d03,
+ 0x33844a,
+ 0x205407,
+ 0x3145c9,
+ 0x38d4c7,
+ 0x20d342,
+ 0x200002,
+ 0x3ba886,
+ 0x212702,
+ 0x16fb88,
+ 0x216b42,
+ 0x201102,
+ 0x27f847,
+ 0x217387,
+ 0x222d85,
+ 0x20c702,
+ 0x225287,
+ 0x225448,
+ 0x2024c2,
+ 0x2430c2,
+ 0x237302,
+ 0x201382,
+ 0x242688,
+ 0x20a043,
+ 0x25fa08,
+ 0x2e9b0d,
+ 0x2322c3,
+ 0x32ec08,
+ 0x245f4f,
+ 0x24630e,
+ 0x339a4a,
+ 0x22e811,
+ 0x22ec90,
+ 0x2c34cd,
+ 0x2c380c,
+ 0x36a707,
+ 0x3385c7,
+ 0x39c349,
+ 0x20d302,
+ 0x201442,
+ 0x25db0c,
+ 0x25de0b,
+ 0x2008c2,
+ 0x360cc6,
+ 0x20e982,
+ 0x204882,
+ 0x222902,
+ 0x20f882,
+ 0x3b69c4,
+ 0x244387,
+ 0x229682,
+ 0x24a347,
+ 0x24b547,
+ 0x20d282,
+ 0x20c8c2,
+ 0x24da45,
+ 0x21a442,
+ 0x2f290e,
+ 0x2ab3cd,
+ 0x23cac3,
+ 0x28d58e,
+ 0x2c5c0d,
+ 0x25ac43,
+ 0x201482,
+ 0x2891c4,
+ 0x216582,
+ 0x20fac2,
+ 0x364145,
+ 0x373587,
+ 0x393202,
+ 0x207602,
+ 0x252f87,
+ 0x255ac8,
+ 0x2f6802,
+ 0x294ec6,
+ 0x25d98c,
+ 0x25dccb,
+ 0x206b02,
+ 0x26764f,
+ 0x267a10,
+ 0x267e0f,
+ 0x2681d5,
+ 0x268714,
+ 0x268c0e,
+ 0x268f8e,
+ 0x26930f,
+ 0x2696ce,
+ 0x269a54,
+ 0x269f53,
+ 0x26a40d,
+ 0x27d949,
+ 0x291ac3,
+ 0x201802,
+ 0x2b7505,
+ 0x206346,
+ 0x207b02,
+ 0x3a4ec7,
+ 0x323043,
+ 0x217202,
+ 0x37e548,
+ 0x22ea51,
+ 0x22ee90,
+ 0x2007c2,
+ 0x290e07,
+ 0x204182,
+ 0x332b07,
+ 0x209a02,
+ 0x342089,
+ 0x384bc7,
+ 0x27ac08,
+ 0x2be006,
+ 0x2ef683,
+ 0x339205,
+ 0x2022c2,
+ 0x207a82,
+ 0x3bac85,
+ 0x391345,
+ 0x204bc2,
+ 0x231043,
+ 0x2e4b47,
+ 0x205747,
+ 0x200502,
+ 0x25f1c4,
+ 0x211b83,
+ 0x211b89,
+ 0x215148,
+ 0x200282,
+ 0x202942,
+ 0x242387,
+ 0x263285,
+ 0x2ad208,
+ 0x215c87,
+ 0x21a243,
+ 0x294c86,
+ 0x2c334d,
+ 0x2c36cc,
+ 0x2c8346,
+ 0x209b02,
+ 0x20c202,
+ 0x204a82,
+ 0x245dcf,
+ 0x2461ce,
+ 0x374e87,
+ 0x20b302,
+ 0x2c72c5,
+ 0x2c72c6,
+ 0x214702,
+ 0x200802,
+ 0x228246,
+ 0x2b57c3,
+ 0x332a46,
+ 0x2d0285,
+ 0x2d028d,
+ 0x2d0855,
+ 0x2d108c,
+ 0x2d1e4d,
+ 0x2d2212,
+ 0x214642,
+ 0x2745c2,
+ 0x202ec2,
+ 0x249386,
+ 0x302486,
+ 0x200982,
+ 0x2063c6,
+ 0x202c82,
+ 0x39b505,
+ 0x200542,
+ 0x2ab4c9,
+ 0x2e324c,
+ 0x2e358b,
+ 0x200442,
+ 0x257708,
+ 0x2052c2,
+ 0x20cb42,
+ 0x278ec6,
+ 0x21f285,
+ 0x36c107,
+ 0x24bc85,
+ 0x28ea05,
+ 0x235d82,
+ 0x219a42,
+ 0x21cc82,
+ 0x2f3587,
+ 0x2613cd,
+ 0x26174c,
+ 0x317947,
+ 0x2235c2,
+ 0x225b82,
+ 0x23f688,
+ 0x343a08,
+ 0x34c008,
+ 0x313344,
+ 0x361087,
+ 0x2efc43,
+ 0x299842,
+ 0x206682,
+ 0x2f2149,
+ 0x3ab3c7,
+ 0x204102,
+ 0x2792c5,
+ 0x22fa42,
+ 0x236902,
+ 0x35dc83,
+ 0x35dc86,
+ 0x2f9a02,
+ 0x2fab42,
+ 0x200c02,
+ 0x281e06,
+ 0x345607,
+ 0x221282,
+ 0x206b42,
+ 0x25f84f,
+ 0x28d3cd,
+ 0x3029ce,
+ 0x2c5a8c,
+ 0x201a42,
+ 0x204142,
+ 0x2bde45,
+ 0x317e46,
+ 0x209002,
+ 0x205842,
+ 0x200482,
+ 0x215c04,
+ 0x2e9984,
+ 0x2b8706,
+ 0x204242,
+ 0x37d6c7,
+ 0x233803,
+ 0x233808,
+ 0x33cb48,
+ 0x240687,
+ 0x249286,
+ 0x202502,
+ 0x242603,
+ 0x351107,
+ 0x26ffc6,
+ 0x2e2d05,
+ 0x3136c8,
+ 0x206182,
+ 0x337547,
+ 0x21f542,
+ 0x332182,
+ 0x207f02,
+ 0x2e95c9,
+ 0x23b442,
+ 0x2018c2,
+ 0x248383,
+ 0x377787,
+ 0x2002c2,
+ 0x2e33cc,
+ 0x2e36cb,
+ 0x2c83c6,
+ 0x218d85,
+ 0x22a202,
+ 0x204782,
+ 0x2c1486,
+ 0x237e83,
+ 0x378407,
+ 0x243cc2,
+ 0x200d42,
+ 0x26cc15,
+ 0x247b95,
+ 0x275653,
+ 0x2480d3,
+ 0x2955c7,
+ 0x2c0ec8,
+ 0x379d90,
+ 0x3c020f,
+ 0x2c0ed3,
+ 0x2c6592,
+ 0x2ce1d0,
+ 0x2db58f,
+ 0x2dc512,
+ 0x2dffd1,
+ 0x2e0cd3,
+ 0x2e9392,
+ 0x2ea0cf,
+ 0x2f7c4e,
+ 0x2f9a92,
+ 0x2faed1,
+ 0x303e4f,
+ 0x347a4e,
+ 0x3559d1,
+ 0x2fee10,
+ 0x32f912,
+ 0x36fd51,
+ 0x3af4c6,
+ 0x30dd47,
+ 0x382ac7,
+ 0x203702,
+ 0x286d05,
+ 0x304887,
+ 0x21a902,
+ 0x218f42,
+ 0x230d85,
+ 0x226c43,
+ 0x244c06,
+ 0x26158d,
+ 0x2618cc,
+ 0x206442,
+ 0x31d2cb,
+ 0x27c58a,
+ 0x212b0a,
+ 0x2c04c9,
+ 0x2f0c0b,
+ 0x215dcd,
+ 0x304f8c,
+ 0x2f574a,
+ 0x277bcc,
+ 0x27d34b,
+ 0x29c54c,
+ 0x2b4c0b,
+ 0x2e31c3,
+ 0x36f946,
+ 0x3061c2,
+ 0x2fd502,
+ 0x256d03,
+ 0x203642,
+ 0x203643,
+ 0x260b86,
+ 0x268387,
+ 0x2c48c6,
+ 0x2e2448,
+ 0x343708,
+ 0x2cc7c6,
+ 0x20c402,
+ 0x309b4d,
+ 0x309e8c,
+ 0x2dea07,
+ 0x30db47,
+ 0x2302c2,
+ 0x221682,
+ 0x260982,
+ 0x255e82,
+ 0x20f882,
+ 0x208e83,
+ 0x201a03,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x28cac3,
+ 0x21bf84,
+ 0x208e83,
+ 0x201a03,
+ 0x215443,
+ 0x207102,
+ 0x207542,
+ 0x2da97d45,
+ 0x2de97685,
+ 0x2e320c86,
+ 0x16fb88,
+ 0x2e6b68c5,
+ 0x20f882,
+ 0x201742,
+ 0x2ea34cc5,
+ 0x2ee852c5,
+ 0x2f285e07,
+ 0x2f6f6e09,
+ 0x2fa74084,
+ 0x207b02,
+ 0x217202,
+ 0x2fe56a05,
+ 0x302977c9,
+ 0x30785908,
+ 0x30ab3185,
+ 0x30f3f5c7,
+ 0x31227248,
+ 0x316ec085,
+ 0x31a00106,
+ 0x31e41489,
+ 0x323311c8,
+ 0x326c8988,
+ 0x32a9ef0a,
+ 0x32e7e204,
+ 0x332d99c5,
+ 0x336c30c8,
+ 0x33b85d85,
+ 0x21a602,
+ 0x33e11103,
+ 0x342aa246,
+ 0x3475d1c8,
+ 0x34a8ab86,
+ 0x34e8a688,
+ 0x35348206,
+ 0x356e2dc4,
+ 0x204d42,
+ 0x35addc87,
+ 0x35eaf444,
+ 0x36280087,
+ 0x367b0c87,
+ 0x200442,
+ 0x36aa3885,
+ 0x36e8f904,
+ 0x372f1447,
+ 0x37632c47,
+ 0x37a89006,
+ 0x37e38385,
+ 0x3829d7c7,
+ 0x386d5dc8,
+ 0x38ab7887,
+ 0x38ea6c89,
+ 0x3939e345,
+ 0x397778c7,
+ 0x39a974c6,
+ 0x39e102c8,
+ 0x3279cd,
+ 0x27a209,
+ 0x28384b,
+ 0x289ecb,
+ 0x2ae3cb,
+ 0x2e62cb,
+ 0x31804b,
+ 0x31830b,
+ 0x318949,
+ 0x31984b,
+ 0x319b0b,
+ 0x31a08b,
+ 0x31b08a,
+ 0x31b5ca,
+ 0x31bbcc,
+ 0x31e00b,
+ 0x31ea4a,
+ 0x33064a,
+ 0x33c6ce,
+ 0x33d1ce,
+ 0x33d54a,
+ 0x33efca,
+ 0x33fa8b,
+ 0x33fd4b,
+ 0x340b0b,
+ 0x36124b,
+ 0x36184a,
+ 0x36250b,
+ 0x3627ca,
+ 0x362a4a,
+ 0x362cca,
+ 0x38424b,
+ 0x38c6cb,
+ 0x38e64e,
+ 0x38e9cb,
+ 0x39464b,
+ 0x395b0b,
+ 0x39900a,
+ 0x399289,
+ 0x3994ca,
+ 0x39a94a,
+ 0x3addcb,
+ 0x3afa8b,
+ 0x3b05ca,
+ 0x3b1fcb,
+ 0x3b674b,
+ 0x3bf58b,
+ 0x3a287a88,
+ 0x3a68fd09,
+ 0x3aaa6409,
+ 0x3aee4d48,
+ 0x34b945,
+ 0x202d43,
+ 0x21b744,
+ 0x345805,
+ 0x273dc6,
+ 0x274805,
+ 0x28f584,
+ 0x3a4dc8,
+ 0x312ec5,
+ 0x299a84,
+ 0x211587,
+ 0x2a550a,
+ 0x3813ca,
+ 0x308f07,
+ 0x202c47,
+ 0x303647,
+ 0x271907,
+ 0x2ff9c5,
+ 0x204906,
+ 0x22b9c7,
+ 0x2c8684,
+ 0x2db006,
+ 0x2daf06,
+ 0x208185,
+ 0x331c04,
+ 0x388bc6,
+ 0x2a4707,
+ 0x232646,
+ 0x2bfa07,
+ 0x232dc3,
+ 0x26c7c6,
+ 0x23cf85,
+ 0x285f07,
+ 0x27100a,
+ 0x284e04,
+ 0x220808,
+ 0x2a2009,
+ 0x2d0e47,
+ 0x31e8c6,
+ 0x257988,
+ 0x28b2c9,
+ 0x314784,
+ 0x376004,
+ 0x35d785,
+ 0x22b6c8,
+ 0x2ccc07,
+ 0x29a3c9,
+ 0x3af5c8,
+ 0x353706,
+ 0x24d486,
+ 0x29fd88,
+ 0x365bc6,
+ 0x297685,
+ 0x2890c6,
+ 0x280ec8,
+ 0x256286,
+ 0x25cb8b,
+ 0x2ac646,
+ 0x2a224d,
+ 0x208605,
+ 0x2af306,
+ 0x218a05,
+ 0x35d949,
+ 0x27a787,
+ 0x36d148,
+ 0x2969c6,
+ 0x2a1509,
+ 0x341046,
+ 0x270f85,
+ 0x2a7f06,
+ 0x2d3586,
+ 0x2d3b09,
+ 0x333f06,
+ 0x3529c7,
+ 0x248c85,
+ 0x201d83,
+ 0x25cd05,
+ 0x2a2507,
+ 0x338d06,
+ 0x208509,
+ 0x320c86,
+ 0x289306,
+ 0x219fc9,
+ 0x288ac9,
+ 0x2a8747,
+ 0x20cd08,
+ 0x280509,
+ 0x286988,
+ 0x38b5c6,
+ 0x2de245,
+ 0x23fa4a,
+ 0x289386,
+ 0x2bf1c6,
+ 0x2d7605,
+ 0x272408,
+ 0x2220c7,
+ 0x239fca,
+ 0x253b46,
+ 0x27a645,
+ 0x20a506,
+ 0x236b47,
+ 0x31e787,
+ 0x24fc45,
+ 0x271145,
+ 0x2e79c6,
+ 0x2fbfc6,
+ 0x2be306,
+ 0x2bb884,
+ 0x287e09,
+ 0x290bc6,
+ 0x2d430a,
+ 0x222b88,
+ 0x3059c8,
+ 0x3813ca,
+ 0x205b45,
+ 0x2a4645,
+ 0x3575c8,
+ 0x2b0fc8,
+ 0x2b43c7,
+ 0x295946,
+ 0x329608,
+ 0x30a447,
+ 0x287088,
+ 0x2bbec6,
+ 0x289b88,
+ 0x29cd06,
+ 0x257e47,
+ 0x2a27c6,
+ 0x388bc6,
+ 0x383d4a,
+ 0x345506,
+ 0x2de249,
+ 0x36b086,
+ 0x2b6c0a,
+ 0x2e2dc9,
+ 0x2fe406,
+ 0x2bccc4,
+ 0x2b75cd,
+ 0x28ff87,
+ 0x32df46,
+ 0x2c8845,
+ 0x3410c5,
+ 0x204dc6,
+ 0x2d4fc9,
+ 0x3879c7,
+ 0x2826c6,
+ 0x2bd406,
+ 0x28f609,
+ 0x33f784,
+ 0x3a1184,
+ 0x39c0c8,
+ 0x260f46,
+ 0x279388,
+ 0x30fec8,
+ 0x378187,
+ 0x3beb49,
+ 0x2be507,
+ 0x2b678a,
+ 0x2fc88f,
+ 0x25100a,
+ 0x2bdc45,
+ 0x281105,
+ 0x220085,
+ 0x28be47,
+ 0x236703,
+ 0x20cf08,
+ 0x201e46,
+ 0x201f49,
+ 0x2e4806,
+ 0x3a3607,
+ 0x2a12c9,
+ 0x36d048,
+ 0x2d76c7,
+ 0x315603,
+ 0x34b9c5,
+ 0x236685,
+ 0x2bb6cb,
+ 0x385e44,
+ 0x30ad44,
+ 0x27f006,
+ 0x315e87,
+ 0x392a4a,
+ 0x251a87,
+ 0x36a947,
+ 0x2852c5,
+ 0x2016c5,
+ 0x253689,
+ 0x388bc6,
+ 0x25190d,
+ 0x334145,
+ 0x2a10c3,
+ 0x200dc3,
+ 0x39cf05,
+ 0x3534c5,
+ 0x257988,
+ 0x283007,
+ 0x3a0f06,
+ 0x2a6086,
+ 0x232545,
+ 0x23cd87,
+ 0x377c87,
+ 0x23ea07,
+ 0x2d9a4a,
+ 0x26c888,
+ 0x2bb884,
+ 0x256007,
+ 0x284707,
+ 0x352846,
+ 0x26f5c7,
+ 0x2ece48,
+ 0x2e8548,
+ 0x276346,
+ 0x374f88,
+ 0x2d1704,
+ 0x22b9c6,
+ 0x239b86,
+ 0x333b86,
+ 0x2d0006,
+ 0x233ac4,
+ 0x2719c6,
+ 0x2c7146,
+ 0x29f406,
+ 0x2381c6,
+ 0x213ec6,
+ 0x223f06,
+ 0x3a0e08,
+ 0x3bcc88,
+ 0x2da288,
+ 0x274a08,
+ 0x357546,
+ 0x217e05,
+ 0x2dd4c6,
+ 0x2b3205,
+ 0x397f07,
+ 0x27df05,
+ 0x21ae83,
+ 0x2058c5,
+ 0x34cc44,
+ 0x214005,
+ 0x22dc83,
+ 0x33d807,
+ 0x374a48,
+ 0x2bfac6,
+ 0x2b0c4d,
+ 0x2810c6,
+ 0x29e985,
+ 0x227603,
+ 0x2c2a89,
+ 0x33f906,
+ 0x29dd86,
+ 0x2a8004,
+ 0x250f87,
+ 0x334546,
+ 0x387c85,
+ 0x20b2c3,
+ 0x209484,
+ 0x2848c6,
+ 0x204a04,
+ 0x239c88,
+ 0x2005c9,
+ 0x325f49,
+ 0x2a7e0a,
+ 0x2a918d,
+ 0x20abc7,
+ 0x2bf046,
+ 0x205ec4,
+ 0x2f6e09,
+ 0x28e688,
+ 0x28fb86,
+ 0x245246,
+ 0x26f5c7,
+ 0x2b9786,
+ 0x22c986,
+ 0x36aac6,
+ 0x3b0d0a,
+ 0x227248,
+ 0x364dc5,
+ 0x26fa09,
+ 0x28758a,
+ 0x2f1e88,
+ 0x2a40c8,
+ 0x29dd08,
+ 0x2ad74c,
+ 0x318585,
+ 0x2a6308,
+ 0x2e7546,
+ 0x36d2c6,
+ 0x3a34c7,
+ 0x251985,
+ 0x289245,
+ 0x325e09,
+ 0x219847,
+ 0x201f05,
+ 0x22d887,
+ 0x200dc3,
+ 0x2cd145,
+ 0x214308,
+ 0x25d087,
+ 0x2a3f89,
+ 0x2dac05,
+ 0x395a04,
+ 0x2a8e48,
+ 0x2dddc7,
+ 0x2d7888,
+ 0x2508c8,
+ 0x2d6645,
+ 0x281906,
+ 0x2a6186,
+ 0x277449,
+ 0x2b26c7,
+ 0x2b3ac6,
+ 0x2236c7,
+ 0x20e743,
+ 0x274084,
+ 0x2d1805,
+ 0x23cec4,
+ 0x393244,
+ 0x288547,
+ 0x25b347,
+ 0x234284,
+ 0x2a3dd0,
+ 0x234e47,
+ 0x2016c5,
+ 0x37178c,
+ 0x250684,
+ 0x2a9e48,
+ 0x257d49,
+ 0x36e646,
+ 0x34dd48,
+ 0x223384,
+ 0x37d0c8,
+ 0x23a5c6,
+ 0x238048,
+ 0x2a4cc6,
+ 0x2cc8cb,
+ 0x201d85,
+ 0x2d1688,
+ 0x200a04,
+ 0x200a0a,
+ 0x2a3f89,
+ 0x357f06,
+ 0x220148,
+ 0x263805,
+ 0x2b9044,
+ 0x2a9d46,
+ 0x23e8c8,
+ 0x287a88,
+ 0x329e86,
+ 0x358b04,
+ 0x23f9c6,
+ 0x2be587,
+ 0x27ff87,
+ 0x26f5cf,
+ 0x204187,
+ 0x2fe4c7,
+ 0x23d2c5,
+ 0x35fcc5,
+ 0x2a8409,
+ 0x2ed806,
+ 0x286045,
+ 0x288dc7,
+ 0x2c6188,
+ 0x29f505,
+ 0x2a27c6,
+ 0x2229c8,
+ 0x28ab8a,
+ 0x39c888,
+ 0x292f47,
+ 0x2fccc6,
+ 0x26f9c6,
+ 0x20ca43,
+ 0x2052c3,
+ 0x287749,
+ 0x280389,
+ 0x2a6b86,
+ 0x2dac05,
+ 0x304588,
+ 0x220148,
+ 0x365d48,
+ 0x36ab4b,
+ 0x2b0e87,
+ 0x315849,
+ 0x26f848,
+ 0x356284,
+ 0x3886c8,
+ 0x295089,
+ 0x2b3dc5,
+ 0x28bd47,
+ 0x274105,
+ 0x287988,
+ 0x297bcb,
+ 0x29d510,
+ 0x2aec45,
+ 0x21e20c,
+ 0x3a10c5,
+ 0x285343,
+ 0x296706,
+ 0x2c5a04,
+ 0x28fa06,
+ 0x2a4707,
+ 0x222a44,
+ 0x24c3c8,
+ 0x20cdcd,
+ 0x330a05,
+ 0x20ac04,
+ 0x241b84,
+ 0x27bd89,
+ 0x292bc8,
+ 0x320b07,
+ 0x23a648,
+ 0x287ec8,
+ 0x2829c5,
+ 0x28c647,
+ 0x282947,
+ 0x342807,
+ 0x271149,
+ 0x223c49,
+ 0x36c986,
+ 0x2c3a06,
+ 0x26f806,
+ 0x33e9c5,
+ 0x3b4944,
+ 0x200006,
+ 0x200386,
+ 0x282a08,
+ 0x23680b,
+ 0x284cc7,
+ 0x205ec4,
+ 0x334486,
+ 0x2ed187,
+ 0x388f45,
+ 0x210bc5,
+ 0x21b484,
+ 0x223bc6,
+ 0x200088,
+ 0x2f6e09,
+ 0x259706,
+ 0x28df88,
+ 0x387d46,
+ 0x355088,
+ 0x2d6c8c,
+ 0x282886,
+ 0x29e64d,
+ 0x29eacb,
+ 0x352a85,
+ 0x377dc7,
+ 0x334006,
+ 0x31e648,
+ 0x36ca09,
+ 0x276608,
+ 0x2016c5,
+ 0x2076c7,
+ 0x286a88,
+ 0x332489,
+ 0x2a0986,
+ 0x25960a,
+ 0x31e3c8,
+ 0x27644b,
+ 0x2d964c,
+ 0x37d1c8,
+ 0x283e46,
+ 0x28c048,
+ 0x28a807,
+ 0x2e4909,
+ 0x2976cd,
+ 0x2a26c6,
+ 0x365308,
+ 0x3bcb49,
+ 0x2c4a48,
+ 0x289c88,
+ 0x2c798c,
+ 0x2c8e87,
+ 0x2c96c7,
+ 0x270f85,
+ 0x31a807,
+ 0x2c6048,
+ 0x2a9dc6,
+ 0x26020c,
+ 0x2f60c8,
+ 0x2d5708,
+ 0x262246,
+ 0x236407,
+ 0x36cb84,
+ 0x274a08,
+ 0x28d88c,
+ 0x22834c,
+ 0x2bdcc5,
+ 0x2b85c7,
+ 0x358a86,
+ 0x236386,
+ 0x35db08,
+ 0x202b84,
+ 0x23264b,
+ 0x37d80b,
+ 0x2fccc6,
+ 0x20cc47,
+ 0x339305,
+ 0x278585,
+ 0x232786,
+ 0x2637c5,
+ 0x385e05,
+ 0x2e40c7,
+ 0x27f609,
+ 0x2fc184,
+ 0x2feac5,
+ 0x2ead45,
+ 0x2b5448,
+ 0x235685,
+ 0x2c0b89,
+ 0x2b16c7,
+ 0x2b16cb,
+ 0x261ac6,
+ 0x3a0b49,
+ 0x331b48,
+ 0x272885,
+ 0x342908,
+ 0x223c88,
+ 0x249b07,
+ 0x383b47,
+ 0x2885c9,
+ 0x237f87,
+ 0x27de09,
+ 0x29b88c,
+ 0x2a6b88,
+ 0x331009,
+ 0x360987,
+ 0x287f89,
+ 0x25b487,
+ 0x2d9748,
+ 0x3bed05,
+ 0x22b946,
+ 0x2c8888,
+ 0x30cf08,
+ 0x287449,
+ 0x385e47,
+ 0x278645,
+ 0x21f949,
+ 0x345306,
+ 0x2440c4,
+ 0x2440c6,
+ 0x35d048,
+ 0x254547,
+ 0x236a08,
+ 0x375049,
+ 0x3b1a07,
+ 0x2a56c6,
+ 0x377e84,
+ 0x205949,
+ 0x28c4c8,
+ 0x262107,
+ 0x2b56c6,
+ 0x236746,
+ 0x2bf144,
+ 0x241986,
+ 0x202003,
+ 0x34f109,
+ 0x201d46,
+ 0x3752c5,
+ 0x2a6086,
+ 0x2d79c5,
+ 0x286f08,
+ 0x37cf07,
+ 0x261e06,
+ 0x234d06,
+ 0x3059c8,
+ 0x2a8587,
+ 0x2a2705,
+ 0x2a3bc8,
+ 0x3bb748,
+ 0x31e3c8,
+ 0x3a0f85,
+ 0x22b9c6,
+ 0x325d09,
+ 0x2772c4,
+ 0x351d8b,
+ 0x22c68b,
+ 0x364cc9,
+ 0x200dc3,
+ 0x25efc5,
+ 0x21d306,
+ 0x3ba188,
+ 0x2fc804,
+ 0x2bfac6,
+ 0x2d9b89,
+ 0x2bc9c5,
+ 0x2e4006,
+ 0x2dddc6,
+ 0x220144,
+ 0x2af4ca,
+ 0x375208,
+ 0x30cf06,
+ 0x2cf245,
+ 0x3b8247,
+ 0x23d187,
+ 0x281904,
+ 0x22c8c7,
+ 0x2b6784,
+ 0x333b06,
+ 0x20cf43,
+ 0x271145,
+ 0x334f05,
+ 0x3beec8,
+ 0x2561c5,
+ 0x2825c9,
+ 0x274847,
+ 0x27484b,
+ 0x2aa04c,
+ 0x2aa64a,
+ 0x33f5c7,
+ 0x202e83,
+ 0x202e88,
+ 0x3a1145,
+ 0x29f585,
+ 0x2140c4,
+ 0x2d9646,
+ 0x257d46,
+ 0x2419c7,
+ 0x34d58b,
+ 0x233ac4,
+ 0x2e7644,
+ 0x2cbd04,
+ 0x2d3706,
+ 0x222a44,
+ 0x22b7c8,
+ 0x34b885,
+ 0x24fac5,
+ 0x365c87,
+ 0x377ec9,
+ 0x3534c5,
+ 0x38dcca,
+ 0x248b89,
+ 0x2911ca,
+ 0x3b0e49,
+ 0x310444,
+ 0x2bd4c5,
+ 0x2b9888,
+ 0x2f150b,
+ 0x35d785,
+ 0x33be86,
+ 0x236304,
+ 0x282b06,
+ 0x3b1889,
+ 0x2ed287,
+ 0x320e48,
+ 0x2a9506,
+ 0x2be507,
+ 0x287a88,
+ 0x3870c6,
+ 0x39b804,
+ 0x3743c7,
+ 0x376945,
+ 0x389b87,
+ 0x200104,
+ 0x333f86,
+ 0x2d5f48,
+ 0x29ec88,
+ 0x2e7007,
+ 0x27f988,
+ 0x29cdc5,
+ 0x213e44,
+ 0x3812c8,
+ 0x27fa84,
+ 0x220005,
+ 0x2ffbc4,
+ 0x30a547,
+ 0x290c87,
+ 0x2880c8,
+ 0x2d7a06,
+ 0x256145,
+ 0x2823c8,
+ 0x39ca88,
+ 0x2a7d49,
+ 0x22c986,
+ 0x23a048,
+ 0x20088a,
+ 0x388fc8,
+ 0x2ec085,
+ 0x349286,
+ 0x248a48,
+ 0x20778a,
+ 0x226047,
+ 0x28ee45,
+ 0x29ad48,
+ 0x2c2404,
+ 0x272486,
+ 0x2c9a48,
+ 0x213ec6,
+ 0x20b308,
+ 0x296e87,
+ 0x211486,
+ 0x2bccc4,
+ 0x364707,
+ 0x2b8e84,
+ 0x3b1847,
+ 0x2a064d,
+ 0x288805,
+ 0x2d4dcb,
+ 0x2285c6,
+ 0x257808,
+ 0x24c384,
+ 0x357746,
+ 0x2848c6,
+ 0x28c387,
+ 0x29e30d,
+ 0x24e587,
+ 0x2b93c8,
+ 0x278705,
+ 0x276e08,
+ 0x2ccb86,
+ 0x29ce48,
+ 0x22ab46,
+ 0x25a707,
+ 0x39ae89,
+ 0x36ebc7,
+ 0x28fe48,
+ 0x27af45,
+ 0x222e08,
+ 0x219405,
+ 0x3ab545,
+ 0x3b10c5,
+ 0x23ef43,
+ 0x289144,
+ 0x26fa05,
+ 0x241489,
+ 0x3043c6,
+ 0x2ecf48,
+ 0x383905,
+ 0x2bb507,
+ 0x2ad54a,
+ 0x2e3f49,
+ 0x2d348a,
+ 0x2da308,
+ 0x22d6cc,
+ 0x288e4d,
+ 0x301bc3,
+ 0x20b208,
+ 0x209445,
+ 0x28a946,
+ 0x36cec6,
+ 0x2ebb05,
+ 0x2237c9,
+ 0x20e1c5,
+ 0x2823c8,
+ 0x25fe06,
+ 0x35e006,
+ 0x2a8d09,
+ 0x39ed87,
+ 0x297e86,
+ 0x2ad4c8,
+ 0x333a88,
+ 0x2e4f47,
+ 0x2381ce,
+ 0x2ccdc5,
+ 0x332385,
+ 0x213dc8,
+ 0x20a247,
+ 0x200842,
+ 0x2c7504,
+ 0x28f90a,
+ 0x2621c8,
+ 0x389206,
+ 0x2a1408,
+ 0x2a6186,
+ 0x3337c8,
+ 0x2b3ac8,
+ 0x3ab504,
+ 0x2bba45,
+ 0x681384,
+ 0x681384,
+ 0x681384,
+ 0x201e03,
+ 0x2365c6,
+ 0x282886,
+ 0x2a508c,
+ 0x200943,
+ 0x223286,
+ 0x20cf04,
+ 0x33f888,
+ 0x2d99c5,
+ 0x28fa06,
+ 0x2c31c8,
+ 0x2db2c6,
+ 0x261d86,
+ 0x357d08,
+ 0x2d1887,
+ 0x237d49,
+ 0x2fa8ca,
+ 0x20a944,
+ 0x27df05,
+ 0x29a385,
+ 0x2f6c06,
+ 0x20ac06,
+ 0x2a5ac6,
+ 0x2ff206,
+ 0x237e84,
+ 0x237e8b,
+ 0x23c584,
+ 0x2a5245,
+ 0x2b2ac5,
+ 0x378246,
+ 0x2090c8,
+ 0x288d07,
+ 0x320c04,
+ 0x232fc3,
+ 0x2c1f05,
+ 0x311847,
+ 0x288c0b,
+ 0x3bedc7,
+ 0x2c30c8,
+ 0x2e7287,
+ 0x23d406,
+ 0x27a4c8,
+ 0x2b004b,
+ 0x345746,
+ 0x21d449,
+ 0x2b01c5,
+ 0x315603,
+ 0x2e4006,
+ 0x296d88,
+ 0x21f083,
+ 0x271e03,
+ 0x287a86,
+ 0x2a6186,
+ 0x36958a,
+ 0x283e85,
+ 0x28470b,
+ 0x2a5fcb,
+ 0x210a83,
+ 0x20b943,
+ 0x2b6704,
+ 0x2af6c7,
+ 0x296e04,
+ 0x277344,
+ 0x2e73c4,
+ 0x223e88,
+ 0x2cf188,
+ 0x205249,
+ 0x39e3c8,
+ 0x28b487,
+ 0x2381c6,
+ 0x2ecb8f,
+ 0x2ccf06,
+ 0x2d9944,
+ 0x2cefca,
+ 0x311747,
+ 0x208206,
+ 0x297509,
+ 0x2051c5,
+ 0x3bf005,
+ 0x205306,
+ 0x222f43,
+ 0x2c2449,
+ 0x2273c6,
+ 0x202d09,
+ 0x392a46,
+ 0x271145,
+ 0x2be0c5,
+ 0x204183,
+ 0x2af808,
+ 0x213887,
+ 0x201e44,
+ 0x33f708,
+ 0x2ffe04,
+ 0x2f0486,
+ 0x296706,
+ 0x248fc6,
+ 0x2d1549,
+ 0x29f505,
+ 0x388bc6,
+ 0x2666c9,
+ 0x2cb906,
+ 0x223f06,
+ 0x397346,
+ 0x21ce85,
+ 0x2ffbc6,
+ 0x25a704,
+ 0x3bed05,
+ 0x2c8884,
+ 0x2b9f86,
+ 0x334104,
+ 0x2136c3,
+ 0x28e745,
+ 0x23dac8,
+ 0x262987,
+ 0x2c1ac9,
+ 0x28ed48,
+ 0x29fb51,
+ 0x2dde4a,
+ 0x2fcc07,
+ 0x25a986,
+ 0x20cf04,
+ 0x2c8988,
+ 0x233fc8,
+ 0x29fd0a,
+ 0x2c094d,
+ 0x2a7f06,
+ 0x357e06,
+ 0x3647c6,
+ 0x24fac7,
+ 0x2b9485,
+ 0x210187,
+ 0x20cdc5,
+ 0x2b1804,
+ 0x2ae086,
+ 0x241807,
+ 0x2c214d,
+ 0x248987,
+ 0x3a4cc8,
+ 0x2826c9,
+ 0x349186,
+ 0x2a0905,
+ 0x22dcc4,
+ 0x35d146,
+ 0x281806,
+ 0x262346,
+ 0x2a1c88,
+ 0x21cd43,
+ 0x20aa83,
+ 0x338e45,
+ 0x207b06,
+ 0x2b3a85,
+ 0x2a9708,
+ 0x2a48ca,
+ 0x3a2dc4,
+ 0x33f888,
+ 0x29dd08,
+ 0x378087,
+ 0x3839c9,
+ 0x2c2dc8,
+ 0x2a6d07,
+ 0x2957c6,
+ 0x213eca,
+ 0x35d1c8,
+ 0x2f8589,
+ 0x292c88,
+ 0x229b89,
+ 0x2e8747,
+ 0x33bdc5,
+ 0x36ad46,
+ 0x2a9c48,
+ 0x287c08,
+ 0x29de88,
+ 0x2fcdc8,
+ 0x2a5245,
+ 0x218944,
+ 0x213588,
+ 0x24b384,
+ 0x3b0c44,
+ 0x271145,
+ 0x299ac7,
+ 0x377c89,
+ 0x28c187,
+ 0x2008c5,
+ 0x27f206,
+ 0x363686,
+ 0x200b84,
+ 0x2a9046,
+ 0x255f84,
+ 0x276d06,
+ 0x377a46,
+ 0x21eec6,
+ 0x2016c5,
+ 0x2a95c7,
+ 0x202e83,
+ 0x21dd89,
+ 0x3057c8,
+ 0x2f6d04,
+ 0x2f6d0d,
+ 0x29ed88,
+ 0x2d7248,
+ 0x2f8506,
+ 0x39af89,
+ 0x2e3f49,
+ 0x3b1585,
+ 0x2a49ca,
+ 0x2edbca,
+ 0x2a5ccc,
+ 0x2a5e46,
+ 0x27fe06,
+ 0x2cd086,
+ 0x2c84c9,
+ 0x28ab86,
+ 0x2101c6,
+ 0x20e286,
+ 0x274a08,
+ 0x27f986,
+ 0x2d92cb,
+ 0x299c45,
+ 0x24fac5,
+ 0x280085,
+ 0x39be46,
+ 0x213e83,
+ 0x248f46,
+ 0x248907,
+ 0x2c8845,
+ 0x24d545,
+ 0x3410c5,
+ 0x313846,
+ 0x204dc4,
+ 0x385806,
+ 0x284049,
+ 0x39bccc,
+ 0x2b1548,
+ 0x23e844,
+ 0x2ff8c6,
+ 0x2286c6,
+ 0x296d88,
+ 0x220148,
+ 0x39bbc9,
+ 0x3b8247,
+ 0x260c89,
+ 0x255806,
+ 0x237404,
+ 0x214944,
+ 0x20a584,
+ 0x287a88,
+ 0x377aca,
+ 0x353446,
+ 0x35fb87,
+ 0x37e787,
+ 0x3a0c45,
+ 0x29a344,
+ 0x295046,
+ 0x2b94c6,
+ 0x202bc3,
+ 0x305607,
+ 0x2507c8,
+ 0x3b16ca,
+ 0x2d4708,
+ 0x28a688,
+ 0x334145,
+ 0x352b85,
+ 0x284dc5,
+ 0x3a1006,
+ 0x2393c6,
+ 0x25b285,
+ 0x34f349,
+ 0x29a14c,
+ 0x284e87,
+ 0x29fd88,
+ 0x24ee05,
+ 0x681384,
+ 0x240ac4,
+ 0x25d1c4,
+ 0x217946,
+ 0x2a728e,
+ 0x3bf087,
+ 0x24fcc5,
+ 0x27724c,
+ 0x2ffcc7,
+ 0x241787,
+ 0x274e89,
+ 0x2208c9,
+ 0x28ee45,
+ 0x3057c8,
+ 0x325d09,
+ 0x31e285,
+ 0x2c8788,
+ 0x227546,
+ 0x381546,
+ 0x2e2dc4,
+ 0x25ff08,
+ 0x248743,
+ 0x235e44,
+ 0x2c1f85,
+ 0x204dc7,
+ 0x21b4c5,
+ 0x200749,
+ 0x27e64d,
+ 0x2935c6,
+ 0x229b04,
+ 0x2958c8,
+ 0x27f44a,
+ 0x21da87,
+ 0x243905,
+ 0x235e83,
+ 0x2a618e,
+ 0x2af90c,
+ 0x2f1f87,
+ 0x2a7447,
+ 0x200143,
+ 0x28abc5,
+ 0x25d1c5,
+ 0x2a17c8,
+ 0x29db49,
+ 0x23e746,
+ 0x296e04,
+ 0x2fcb46,
+ 0x3650cb,
+ 0x2e3ccc,
+ 0x376447,
+ 0x2d9585,
+ 0x3bb648,
+ 0x2e4d05,
+ 0x2cefc7,
+ 0x2ddc87,
+ 0x248745,
+ 0x213e83,
+ 0x3b36c4,
+ 0x21b705,
+ 0x2fc085,
+ 0x2fc086,
+ 0x2821c8,
+ 0x241807,
+ 0x36d1c6,
+ 0x25b686,
+ 0x3b1006,
+ 0x2f88c9,
+ 0x28c747,
+ 0x262606,
+ 0x2e3e46,
+ 0x27e106,
+ 0x2af405,
+ 0x21e8c6,
+ 0x390e05,
+ 0x235708,
+ 0x2990cb,
+ 0x294b86,
+ 0x37e7c4,
+ 0x2c8109,
+ 0x274844,
+ 0x2274c8,
+ 0x2441c7,
+ 0x289b84,
+ 0x2c2688,
+ 0x2c94c4,
+ 0x2af444,
+ 0x39ac45,
+ 0x330a46,
+ 0x223dc7,
+ 0x20b3c3,
+ 0x2a5785,
+ 0x32a504,
+ 0x3323c6,
+ 0x3b1608,
+ 0x39c785,
+ 0x298d89,
+ 0x21fb45,
+ 0x223288,
+ 0x22cfc7,
+ 0x398048,
+ 0x2c1907,
+ 0x2fe589,
+ 0x271846,
+ 0x360486,
+ 0x20e284,
+ 0x295705,
+ 0x3093cc,
+ 0x280087,
+ 0x280fc7,
+ 0x37e648,
+ 0x2935c6,
+ 0x2794c4,
+ 0x34bc04,
+ 0x288449,
+ 0x2cd186,
+ 0x253707,
+ 0x2cff84,
+ 0x24ab06,
+ 0x35f245,
+ 0x2d7547,
+ 0x2d9246,
+ 0x2594c9,
+ 0x2eda07,
+ 0x26f5c7,
+ 0x2a8b86,
+ 0x24aa45,
+ 0x285988,
+ 0x227248,
+ 0x2f6a46,
+ 0x39c7c5,
+ 0x344806,
+ 0x202c03,
+ 0x2a1649,
+ 0x2a584e,
+ 0x2c1608,
+ 0x2fff08,
+ 0x2f684b,
+ 0x298fc6,
+ 0x20a884,
+ 0x261d84,
+ 0x2a594a,
+ 0x21e107,
+ 0x2626c5,
+ 0x21d449,
+ 0x2c7205,
+ 0x3b0c87,
+ 0x250584,
+ 0x27b907,
+ 0x30fdc8,
+ 0x2d0f06,
+ 0x365489,
+ 0x2c2eca,
+ 0x21e086,
+ 0x29e8c6,
+ 0x2b2a45,
+ 0x38ef85,
+ 0x325647,
+ 0x24ec48,
+ 0x35f188,
+ 0x3ab506,
+ 0x2be145,
+ 0x20a98e,
+ 0x2bb884,
+ 0x2a1745,
+ 0x27eb89,
+ 0x2ed608,
+ 0x292e86,
+ 0x2a36cc,
+ 0x2a44d0,
+ 0x2a6ecf,
+ 0x2a8308,
+ 0x33f5c7,
+ 0x2016c5,
+ 0x26fa05,
+ 0x389089,
+ 0x29af49,
+ 0x23fac6,
+ 0x35d807,
+ 0x2b8545,
+ 0x2b43c9,
+ 0x3528c6,
+ 0x28a9cd,
+ 0x288789,
+ 0x277344,
+ 0x2c1388,
+ 0x213649,
+ 0x353606,
+ 0x27f305,
+ 0x360486,
+ 0x320d09,
+ 0x281688,
+ 0x217e05,
+ 0x200984,
+ 0x2a388b,
+ 0x3534c5,
+ 0x2a39c6,
+ 0x289186,
+ 0x26e646,
+ 0x27c18b,
+ 0x298e89,
+ 0x25b5c5,
+ 0x397e07,
+ 0x2dddc6,
+ 0x34dec6,
+ 0x25cf48,
+ 0x330b49,
+ 0x3a4a8c,
+ 0x311648,
+ 0x23c586,
+ 0x329e83,
+ 0x28bf46,
+ 0x27bfc5,
+ 0x284a48,
+ 0x2bdb46,
+ 0x2d7788,
+ 0x251b05,
+ 0x283245,
+ 0x27a8c8,
+ 0x333947,
+ 0x36ce07,
+ 0x2419c7,
+ 0x34dd48,
+ 0x39ad08,
+ 0x31a706,
+ 0x2b9dc7,
+ 0x273f47,
+ 0x27be8a,
+ 0x20d703,
+ 0x39be46,
+ 0x23e985,
+ 0x28f904,
+ 0x2826c9,
+ 0x2fe504,
+ 0x262a04,
+ 0x2a4d44,
+ 0x2a744b,
+ 0x2137c7,
+ 0x20abc5,
+ 0x29cac8,
+ 0x27f206,
+ 0x27f208,
+ 0x283dc6,
+ 0x293345,
+ 0x293e85,
+ 0x295f46,
+ 0x296b48,
+ 0x297448,
+ 0x282886,
+ 0x29c90f,
+ 0x2a1110,
+ 0x208605,
+ 0x202e83,
+ 0x2374c5,
+ 0x315788,
+ 0x29ae49,
+ 0x31e3c8,
+ 0x2f8748,
+ 0x2bec08,
+ 0x213887,
+ 0x27eec9,
+ 0x2d7988,
+ 0x2730c4,
+ 0x2a4bc8,
+ 0x2b5509,
+ 0x2babc7,
+ 0x2a2644,
+ 0x28c248,
+ 0x2a938a,
+ 0x3085c6,
+ 0x2a7f06,
+ 0x22c849,
+ 0x2a4707,
+ 0x2d4588,
+ 0x2fdbc8,
+ 0x2cfe08,
+ 0x3690c5,
+ 0x38ff05,
+ 0x24fac5,
+ 0x25d185,
+ 0x38cb87,
+ 0x213e85,
+ 0x2c8845,
+ 0x20ae06,
+ 0x31e307,
+ 0x2f1447,
+ 0x2a9686,
+ 0x2da845,
+ 0x2a39c6,
+ 0x202f45,
+ 0x2b83c8,
+ 0x2f1e04,
+ 0x2cb986,
+ 0x348084,
+ 0x2b9048,
+ 0x2cba8a,
+ 0x28300c,
+ 0x34d785,
+ 0x24fb86,
+ 0x3a4c46,
+ 0x234b86,
+ 0x23c604,
+ 0x35f505,
+ 0x283c07,
+ 0x2a4789,
+ 0x2d3c07,
+ 0x681384,
+ 0x681384,
+ 0x320a85,
+ 0x38d584,
+ 0x2a308a,
+ 0x27f086,
+ 0x27a704,
+ 0x208185,
+ 0x3875c5,
+ 0x2b93c4,
+ 0x288dc7,
+ 0x21fac7,
+ 0x2d3708,
+ 0x342348,
+ 0x217e09,
+ 0x2a5308,
+ 0x2a324b,
+ 0x251044,
+ 0x375f45,
+ 0x2860c5,
+ 0x241949,
+ 0x330b49,
+ 0x2c8008,
+ 0x243f48,
+ 0x2df044,
+ 0x228705,
+ 0x202d43,
+ 0x2f6bc5,
+ 0x388c46,
+ 0x29d98c,
+ 0x2189c6,
+ 0x37cfc6,
+ 0x293105,
+ 0x3138c8,
+ 0x2c1786,
+ 0x25ab06,
+ 0x2a7f06,
+ 0x22e2cc,
+ 0x262504,
+ 0x3b114a,
+ 0x293048,
+ 0x29d7c7,
+ 0x32a406,
+ 0x23e807,
+ 0x2f2ec5,
+ 0x2b56c6,
+ 0x35c286,
+ 0x367cc7,
+ 0x262a44,
+ 0x30a645,
+ 0x27eb84,
+ 0x2b1887,
+ 0x27edc8,
+ 0x27fc8a,
+ 0x286907,
+ 0x375387,
+ 0x33f547,
+ 0x2e4e49,
+ 0x29d98a,
+ 0x2373c3,
+ 0x262945,
+ 0x20b343,
+ 0x2e7409,
+ 0x254ec8,
+ 0x23d2c7,
+ 0x31e4c9,
+ 0x227346,
+ 0x2042c8,
+ 0x33d785,
+ 0x39cb8a,
+ 0x2dbc89,
+ 0x276209,
+ 0x3a34c7,
+ 0x2340c9,
+ 0x21edc8,
+ 0x367e86,
+ 0x24fd48,
+ 0x21ce87,
+ 0x237f87,
+ 0x248b87,
+ 0x2d5dc8,
+ 0x2ff746,
+ 0x2a9145,
+ 0x283c07,
+ 0x29e3c8,
+ 0x348004,
+ 0x2d41c4,
+ 0x297d87,
+ 0x2b3e47,
+ 0x325b8a,
+ 0x367e06,
+ 0x35854a,
+ 0x2c7447,
+ 0x2bb647,
+ 0x358004,
+ 0x27dec4,
+ 0x2d7446,
+ 0x281b84,
+ 0x281b8c,
+ 0x203185,
+ 0x21ff89,
+ 0x265684,
+ 0x2b9485,
+ 0x27f3c8,
+ 0x22d245,
+ 0x204dc6,
+ 0x225f44,
+ 0x28f30a,
+ 0x2b25c6,
+ 0x2a424a,
+ 0x2b7887,
+ 0x236b45,
+ 0x222f45,
+ 0x3a0c8a,
+ 0x296cc5,
+ 0x2a7e06,
+ 0x24b384,
+ 0x2b6886,
+ 0x325705,
+ 0x2bdc06,
+ 0x2e700c,
+ 0x2d388a,
+ 0x2957c4,
+ 0x2381c6,
+ 0x2a4707,
+ 0x2d91c4,
+ 0x274a08,
+ 0x39e246,
+ 0x20a809,
+ 0x2baec9,
+ 0x2a6c89,
+ 0x351f46,
+ 0x21cf86,
+ 0x24fe87,
+ 0x34f288,
+ 0x21cd89,
+ 0x2137c7,
+ 0x29cc46,
+ 0x2be587,
+ 0x364685,
+ 0x2bb884,
+ 0x24fa47,
+ 0x274105,
+ 0x28f845,
+ 0x36c347,
+ 0x248608,
+ 0x3bb5c6,
+ 0x29f24d,
+ 0x2a19cf,
+ 0x2a5fcd,
+ 0x200904,
+ 0x23dbc6,
+ 0x2dc1c8,
+ 0x20e245,
+ 0x27c048,
+ 0x2499ca,
+ 0x277344,
+ 0x365646,
+ 0x33ae07,
+ 0x233ac7,
+ 0x2d1949,
+ 0x24fd05,
+ 0x2b93c4,
+ 0x2bb98a,
+ 0x2c2989,
+ 0x2341c7,
+ 0x272306,
+ 0x353606,
+ 0x228646,
+ 0x374486,
+ 0x2db94f,
+ 0x2dc089,
+ 0x27f986,
+ 0x233ec6,
+ 0x320289,
+ 0x2b9ec7,
+ 0x229403,
+ 0x22e446,
+ 0x2052c3,
+ 0x2eb9c8,
+ 0x2be3c7,
+ 0x2a8509,
+ 0x296588,
+ 0x36cf48,
+ 0x385f86,
+ 0x218909,
+ 0x398845,
+ 0x2b9f84,
+ 0x29a687,
+ 0x2c8545,
+ 0x200904,
+ 0x20ac88,
+ 0x202044,
+ 0x2b9c07,
+ 0x3749c6,
+ 0x2e7a85,
+ 0x292c88,
+ 0x3534cb,
+ 0x3778c7,
+ 0x3a0f06,
+ 0x2ccf84,
+ 0x348186,
+ 0x271145,
+ 0x274105,
+ 0x285709,
+ 0x2889c9,
+ 0x237fc4,
+ 0x238005,
+ 0x238205,
+ 0x39ca06,
+ 0x3058c8,
+ 0x2c6b86,
+ 0x25060b,
+ 0x36e4ca,
+ 0x2b8f85,
+ 0x293f06,
+ 0x3a2ac5,
+ 0x2e9dc5,
+ 0x2ad387,
+ 0x39c0c8,
+ 0x260c84,
+ 0x26be86,
+ 0x2974c6,
+ 0x21ef87,
+ 0x3155c4,
+ 0x2848c6,
+ 0x2427c5,
+ 0x2427c9,
+ 0x21b584,
+ 0x29a4c9,
+ 0x282886,
+ 0x2c8f48,
+ 0x238205,
+ 0x37e885,
+ 0x2bdc06,
+ 0x3a4989,
+ 0x2208c9,
+ 0x37d046,
+ 0x2ed708,
+ 0x277348,
+ 0x3a2a84,
+ 0x2bbcc4,
+ 0x2bbcc8,
+ 0x32e048,
+ 0x260d89,
+ 0x388bc6,
+ 0x2a7f06,
+ 0x3294cd,
+ 0x2bfac6,
+ 0x2d6b49,
+ 0x2dd5c5,
+ 0x205306,
+ 0x2102c8,
+ 0x326885,
+ 0x273f84,
+ 0x271145,
+ 0x2882c8,
+ 0x2a2e49,
+ 0x27ec44,
+ 0x333f86,
+ 0x22d10a,
+ 0x2f1e88,
+ 0x325d09,
+ 0x261f0a,
+ 0x31e446,
+ 0x2a1b88,
+ 0x2ced85,
+ 0x2c5ec8,
+ 0x2c1a05,
+ 0x227209,
+ 0x37ac49,
+ 0x203282,
+ 0x2b01c5,
+ 0x2782c6,
+ 0x2827c7,
+ 0x34e085,
+ 0x30ce06,
+ 0x326948,
+ 0x2935c6,
+ 0x2b9749,
+ 0x2810c6,
+ 0x25cdc8,
+ 0x2b0805,
+ 0x264906,
+ 0x25a808,
+ 0x287a88,
+ 0x2e8648,
+ 0x353788,
+ 0x21e8c4,
+ 0x281943,
+ 0x2b9984,
+ 0x286b06,
+ 0x3646c4,
+ 0x2ffe47,
+ 0x25aa09,
+ 0x2cbd05,
+ 0x2fdbc6,
+ 0x22e446,
+ 0x28200b,
+ 0x2b8ec6,
+ 0x2cf8c6,
+ 0x2d13c8,
+ 0x24d486,
+ 0x236943,
+ 0x2164c3,
+ 0x2bb884,
+ 0x239f45,
+ 0x387b87,
+ 0x27edc8,
+ 0x27edcf,
+ 0x283b0b,
+ 0x3056c8,
+ 0x334006,
+ 0x3059ce,
+ 0x251143,
+ 0x387b04,
+ 0x2b8e45,
+ 0x2b9246,
+ 0x29514b,
+ 0x299b86,
+ 0x222a49,
+ 0x2e7a85,
+ 0x3999c8,
+ 0x216688,
+ 0x22078c,
+ 0x2a7486,
+ 0x2f6c06,
+ 0x2dac05,
+ 0x28fc08,
+ 0x25a805,
+ 0x356288,
+ 0x2a3a4a,
+ 0x2a6409,
+ 0x681384,
+ 0x3b60f882,
+ 0x16fb88,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x28cac3,
+ 0x208e83,
+ 0x201a03,
+ 0x39c783,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x231604,
+ 0x208e83,
+ 0x201a03,
+ 0x213083,
+ 0x286644,
+ 0x238543,
+ 0x240244,
+ 0x23cac3,
+ 0x2de944,
+ 0x323043,
+ 0x34e347,
+ 0x28cac3,
+ 0x200e03,
+ 0x293408,
+ 0x201a03,
+ 0x29630b,
+ 0x2f3743,
+ 0x3a03c6,
+ 0x205082,
+ 0x22facb,
+ 0x23cac3,
+ 0x323043,
+ 0x208e83,
+ 0x201a03,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x201a03,
+ 0x220b83,
+ 0x201503,
+ 0x207102,
+ 0x16fb88,
+ 0x32d1c5,
+ 0x274188,
+ 0x2f9f88,
+ 0x20f882,
+ 0x20a605,
+ 0x3785c7,
+ 0x201842,
+ 0x24c5c7,
+ 0x207b02,
+ 0x2f6607,
+ 0x2cc409,
+ 0x2ce948,
+ 0x2cfc89,
+ 0x24b2c2,
+ 0x2707c7,
+ 0x37cdc4,
+ 0x378687,
+ 0x36e3c7,
+ 0x264d42,
+ 0x28cac3,
+ 0x214642,
+ 0x204d42,
+ 0x200442,
+ 0x21cc82,
+ 0x206b42,
+ 0x20d2c2,
+ 0x2aff05,
+ 0x240a05,
+ 0xf882,
+ 0x3cac3,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x208e83,
+ 0x201a03,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x28cac3,
+ 0x208e83,
+ 0x1a3443,
+ 0x201a03,
+ 0x170c3,
+ 0x8c1,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x231604,
+ 0x255783,
+ 0x208e83,
+ 0x1a3443,
+ 0x201a03,
+ 0x221f43,
+ 0x3e4f5906,
+ 0x42bc3,
+ 0x873c5,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x208e83,
+ 0x201a03,
+ 0x20f882,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x208e83,
+ 0x201a03,
+ 0x84c2,
+ 0x16fb88,
+ 0xe03,
+ 0x1a3443,
+ 0x4ec04,
+ 0xe5105,
+ 0x207102,
+ 0x39cdc4,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x38acc3,
+ 0x2b13c5,
+ 0x255783,
+ 0x211a83,
+ 0x208e83,
+ 0x21b543,
+ 0x201a03,
+ 0x215443,
+ 0x20e383,
+ 0x202443,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x208e83,
+ 0x201a03,
+ 0x20f882,
+ 0x201a03,
+ 0x16fb88,
+ 0x323043,
+ 0x1a3443,
+ 0x16fb88,
+ 0x1a3443,
+ 0x2bcc43,
+ 0x238543,
+ 0x23a844,
+ 0x23cac3,
+ 0x323043,
+ 0x205e82,
+ 0x28cac3,
+ 0x208e83,
+ 0x201a03,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x205e82,
+ 0x229443,
+ 0x208e83,
+ 0x201a03,
+ 0x2ef783,
+ 0x215443,
+ 0x207102,
+ 0x20f882,
+ 0x323043,
+ 0x208e83,
+ 0x201a03,
+ 0x3a03c5,
+ 0xa4f06,
+ 0x286644,
+ 0x205082,
+ 0x16fb88,
+ 0x207102,
+ 0x25088,
+ 0x134943,
+ 0x20f882,
+ 0x42899306,
+ 0x6a04,
+ 0xb610b,
+ 0x44e86,
+ 0x8cbc7,
+ 0x23cac3,
+ 0x51648,
+ 0x323043,
+ 0x8b205,
+ 0x1493c4,
+ 0x227583,
+ 0x556c7,
+ 0xe06c4,
+ 0x208e83,
+ 0x1a3284,
+ 0x1a3443,
+ 0x201a03,
+ 0x2f4544,
+ 0xb5ec8,
+ 0x12cf06,
+ 0x16308,
+ 0x1252c5,
+ 0x9fc9,
+ 0x20f882,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x28cac3,
+ 0x200e03,
+ 0x201a03,
+ 0x2f3743,
+ 0x205082,
+ 0x16fb88,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x231603,
+ 0x21bf84,
+ 0x208e83,
+ 0xe03,
+ 0x201a03,
+ 0x238543,
+ 0x23cac3,
+ 0x2de944,
+ 0x323043,
+ 0x208e83,
+ 0x201a03,
+ 0x3a03c6,
+ 0x23cac3,
+ 0x323043,
+ 0x18a783,
+ 0x201a03,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x208e83,
+ 0x201a03,
+ 0x8cbc7,
+ 0x16fb88,
+ 0x323043,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x208e83,
+ 0x201a03,
+ 0x45238543,
+ 0x23cac3,
+ 0x208e83,
+ 0x201a03,
+ 0x16fb88,
+ 0x207102,
+ 0x20f882,
+ 0x238543,
+ 0x323043,
+ 0x208e83,
+ 0x200442,
+ 0x201a03,
+ 0x31f1c7,
+ 0x342b8b,
+ 0x22fc83,
+ 0x244708,
+ 0x34f007,
+ 0x348746,
+ 0x382d45,
+ 0x232309,
+ 0x28c848,
+ 0x346789,
+ 0x346790,
+ 0x36f64b,
+ 0x2e2109,
+ 0x205dc3,
+ 0x20af09,
+ 0x23bd86,
+ 0x23bd8c,
+ 0x32d288,
+ 0x3bc208,
+ 0x244a49,
+ 0x29854e,
+ 0x2cc1cb,
+ 0x2e5c0c,
+ 0x203ec3,
+ 0x26ad0c,
+ 0x203ec9,
+ 0x30ae47,
+ 0x23ca0c,
+ 0x2b478a,
+ 0x252044,
+ 0x2768cd,
+ 0x26abc8,
+ 0x21308d,
+ 0x26fec6,
+ 0x28664b,
+ 0x200cc9,
+ 0x2cf787,
+ 0x332c86,
+ 0x3372c9,
+ 0x34834a,
+ 0x319108,
+ 0x2f3204,
+ 0x2fe987,
+ 0x363787,
+ 0x2d0184,
+ 0x38d204,
+ 0x2345c9,
+ 0x28a4c9,
+ 0x2b7288,
+ 0x216d05,
+ 0x339645,
+ 0x213c86,
+ 0x276789,
+ 0x249c4d,
+ 0x33bf88,
+ 0x213b87,
+ 0x382dc8,
+ 0x2fa686,
+ 0x39b444,
+ 0x2501c5,
+ 0x201c46,
+ 0x202884,
+ 0x203dc7,
+ 0x206f4a,
+ 0x219784,
+ 0x21dfc6,
+ 0x21ea49,
+ 0x21ea4f,
+ 0x21fc8d,
+ 0x220f06,
+ 0x224c90,
+ 0x225086,
+ 0x2257c7,
+ 0x2269c7,
+ 0x2269cf,
+ 0x2276c9,
+ 0x22cb06,
+ 0x22da47,
+ 0x22da48,
+ 0x22f289,
+ 0x358088,
+ 0x2eb507,
+ 0x212843,
+ 0x394f46,
+ 0x3c0b48,
+ 0x29880a,
+ 0x236089,
+ 0x205d83,
+ 0x3784c6,
+ 0x26bcca,
+ 0x28eb87,
+ 0x30ac8a,
+ 0x25a18e,
+ 0x227806,
+ 0x2b03c7,
+ 0x217bc6,
+ 0x203f86,
+ 0x38fd0b,
+ 0x31708a,
+ 0x32138d,
+ 0x21d047,
+ 0x20e408,
+ 0x20e409,
+ 0x20e40f,
+ 0x2c1c4c,
+ 0x2b4089,
+ 0x2d890e,
+ 0x34e44a,
+ 0x28b906,
+ 0x314a86,
+ 0x319d8c,
+ 0x31be8c,
+ 0x327508,
+ 0x36eac7,
+ 0x274d85,
+ 0x3485c4,
+ 0x20f88e,
+ 0x299684,
+ 0x388947,
+ 0x39140a,
+ 0x38a814,
+ 0x39390f,
+ 0x226b88,
+ 0x394e08,
+ 0x35eccd,
+ 0x35ecce,
+ 0x3a0849,
+ 0x238788,
+ 0x23878f,
+ 0x23c70c,
+ 0x23c70f,
+ 0x23d907,
+ 0x240c0a,
+ 0x2459cb,
+ 0x243788,
+ 0x245c87,
+ 0x3ac74d,
+ 0x322b46,
+ 0x276a86,
+ 0x248dc9,
+ 0x364b08,
+ 0x24cf48,
+ 0x24cf4e,
+ 0x2f4087,
+ 0x24e145,
+ 0x24e9c5,
+ 0x204b44,
+ 0x348a06,
+ 0x2b7188,
+ 0x20db03,
+ 0x2f948e,
+ 0x3acb08,
+ 0x2b588b,
+ 0x378bc7,
+ 0x3ab345,
+ 0x233d86,
+ 0x2b1f87,
+ 0x32f2c8,
+ 0x325449,
+ 0x322dc5,
+ 0x28e788,
+ 0x21c946,
+ 0x3afeca,
+ 0x20f789,
+ 0x23cac9,
+ 0x23cacb,
+ 0x346448,
+ 0x2d0049,
+ 0x216dc6,
+ 0x23768a,
+ 0x293c0a,
+ 0x240e0c,
+ 0x28e4c7,
+ 0x2ce74a,
+ 0x36b38b,
+ 0x36b399,
+ 0x312408,
+ 0x3a0445,
+ 0x2cdd46,
+ 0x25c489,
+ 0x3449c6,
+ 0x2df8ca,
+ 0x28ca46,
+ 0x20df44,
+ 0x2cdecd,
+ 0x20df47,
+ 0x218209,
+ 0x250ac5,
+ 0x250c08,
+ 0x251409,
+ 0x251844,
+ 0x251f47,
+ 0x251f48,
+ 0x2526c7,
+ 0x26e2c8,
+ 0x255cc7,
+ 0x25b845,
+ 0x25f3cc,
+ 0x25fc09,
+ 0x2c8c0a,
+ 0x39ec09,
+ 0x20b009,
+ 0x37ee4c,
+ 0x264f0b,
+ 0x2662c8,
+ 0x267448,
+ 0x26a804,
+ 0x289848,
+ 0x28d209,
+ 0x2b4847,
+ 0x20e646,
+ 0x200f47,
+ 0x2c4289,
+ 0x32264b,
+ 0x325147,
+ 0x201a87,
+ 0x2b79c7,
+ 0x213004,
+ 0x213005,
+ 0x2a7c05,
+ 0x34b1cb,
+ 0x3a9384,
+ 0x350448,
+ 0x26e94a,
+ 0x21ca07,
+ 0x300687,
+ 0x294712,
+ 0x276c06,
+ 0x23a1c6,
+ 0x33888e,
+ 0x27ab46,
+ 0x29abc8,
+ 0x29b38f,
+ 0x213448,
+ 0x302848,
+ 0x3bd10a,
+ 0x3bd111,
+ 0x2a990e,
+ 0x25654a,
+ 0x25654c,
+ 0x20bf07,
+ 0x238990,
+ 0x200408,
+ 0x2a9b05,
+ 0x2b238a,
+ 0x2028cc,
+ 0x29cf8d,
+ 0x302346,
+ 0x302347,
+ 0x30234c,
+ 0x30c80c,
+ 0x335d4c,
+ 0x2edfcb,
+ 0x28e0c4,
+ 0x22c9c4,
+ 0x354609,
+ 0x39e807,
+ 0x229989,
+ 0x293a49,
+ 0x3b6587,
+ 0x2b4606,
+ 0x2b4609,
+ 0x2b4a03,
+ 0x21b7ca,
+ 0x31fd07,
+ 0x34304b,
+ 0x32120a,
+ 0x2f6744,
+ 0x35f646,
+ 0x286b89,
+ 0x281a04,
+ 0x20324a,
+ 0x3a1205,
+ 0x2c4d45,
+ 0x2c4d4d,
+ 0x2c508e,
+ 0x2b9ac5,
+ 0x32ab86,
+ 0x39ffc7,
+ 0x25f64a,
+ 0x3a8286,
+ 0x2eefc4,
+ 0x2f9847,
+ 0x3bc50b,
+ 0x2fa747,
+ 0x30b444,
+ 0x256fc6,
+ 0x256fcd,
+ 0x2c3f4c,
+ 0x208d46,
+ 0x33c18a,
+ 0x230206,
+ 0x22ddc8,
+ 0x285107,
+ 0x34c98a,
+ 0x3840c6,
+ 0x210443,
+ 0x210446,
+ 0x3c09c8,
+ 0x2a344a,
+ 0x2801c7,
+ 0x2801c8,
+ 0x289e04,
+ 0x256ac7,
+ 0x283288,
+ 0x345388,
+ 0x284508,
+ 0x35874a,
+ 0x2e4505,
+ 0x2e9a07,
+ 0x256393,
+ 0x343d86,
+ 0x2e0908,
+ 0x229f89,
+ 0x24c488,
+ 0x38600b,
+ 0x2d3d48,
+ 0x2bc644,
+ 0x27a9c6,
+ 0x317ec6,
+ 0x330889,
+ 0x3bc3c7,
+ 0x25f4c8,
+ 0x2931c6,
+ 0x36c244,
+ 0x30aa05,
+ 0x2d4008,
+ 0x2cd88a,
+ 0x2cdb48,
+ 0x2d4b06,
+ 0x2a1d8a,
+ 0x2fc208,
+ 0x2d8fc8,
+ 0x2d9ec8,
+ 0x2da506,
+ 0x2dc3c6,
+ 0x20c0cc,
+ 0x2dc990,
+ 0x285505,
+ 0x213248,
+ 0x30d410,
+ 0x213250,
+ 0x34660e,
+ 0x20bd4e,
+ 0x20bd54,
+ 0x20e78f,
+ 0x20eb46,
+ 0x3072d1,
+ 0x332e13,
+ 0x333288,
+ 0x31d245,
+ 0x2a0bc8,
+ 0x395705,
+ 0x23540c,
+ 0x2309c9,
+ 0x2994c9,
+ 0x230e47,
+ 0x263549,
+ 0x261047,
+ 0x2ffa46,
+ 0x24ffc7,
+ 0x20ef05,
+ 0x217103,
+ 0x20dcc9,
+ 0x22a249,
+ 0x38a783,
+ 0x3b35c4,
+ 0x358c8d,
+ 0x3b83cf,
+ 0x36c285,
+ 0x331786,
+ 0x21ac47,
+ 0x32d007,
+ 0x290806,
+ 0x29080b,
+ 0x2aa805,
+ 0x263c06,
+ 0x300b87,
+ 0x257449,
+ 0x345a06,
+ 0x20cb45,
+ 0x2248cb,
+ 0x230786,
+ 0x38ad45,
+ 0x273988,
+ 0x2a6988,
+ 0x2ba50c,
+ 0x2ba510,
+ 0x2b64c9,
+ 0x2c5607,
+ 0x2e520b,
+ 0x30be86,
+ 0x2eb3ca,
+ 0x2ec90b,
+ 0x2ee70a,
+ 0x2ee986,
+ 0x2ef645,
+ 0x31fa46,
+ 0x37d408,
+ 0x230f0a,
+ 0x35e95c,
+ 0x2f380c,
+ 0x2f3b08,
+ 0x3a03c5,
+ 0x35cec7,
+ 0x25b0c6,
+ 0x27f7c5,
+ 0x2227c6,
+ 0x2909c8,
+ 0x2c2c07,
+ 0x298448,
+ 0x2b04ca,
+ 0x33764c,
+ 0x3378c9,
+ 0x39b5c7,
+ 0x215c04,
+ 0x24ea86,
+ 0x2d518a,
+ 0x293b45,
+ 0x211ecc,
+ 0x212e48,
+ 0x389c88,
+ 0x21904c,
+ 0x2266cc,
+ 0x229549,
+ 0x229787,
+ 0x23ff4c,
+ 0x2454c4,
+ 0x24718a,
+ 0x23354c,
+ 0x279a4b,
+ 0x24bfcb,
+ 0x3821c6,
+ 0x2f7447,
+ 0x20e947,
+ 0x238bcf,
+ 0x303191,
+ 0x2e16d2,
+ 0x314ecd,
+ 0x314ece,
+ 0x31520e,
+ 0x20e948,
+ 0x20e952,
+ 0x253e08,
+ 0x34ec47,
+ 0x25430a,
+ 0x208b08,
+ 0x27ab05,
+ 0x38c9ca,
+ 0x2255c7,
+ 0x2e6f44,
+ 0x227103,
+ 0x297185,
+ 0x3bd387,
+ 0x2fb547,
+ 0x29d18e,
+ 0x308c8d,
+ 0x30d7c9,
+ 0x21f545,
+ 0x31c443,
+ 0x326446,
+ 0x264085,
+ 0x27dc48,
+ 0x2c0649,
+ 0x2a0105,
+ 0x3ac94f,
+ 0x2b6207,
+ 0x382bc5,
+ 0x37958a,
+ 0x358946,
+ 0x2522c9,
+ 0x37db4c,
+ 0x2fec09,
+ 0x2094c6,
+ 0x26e74c,
+ 0x329f86,
+ 0x3017c8,
+ 0x301c86,
+ 0x312586,
+ 0x2082c4,
+ 0x266643,
+ 0x2b380a,
+ 0x32e411,
+ 0x30650a,
+ 0x265345,
+ 0x271ac7,
+ 0x25c7c7,
+ 0x283384,
+ 0x28338b,
+ 0x2cfb08,
+ 0x2c1486,
+ 0x37e6c5,
+ 0x3b01c4,
+ 0x280ac9,
+ 0x320804,
+ 0x24cd87,
+ 0x359f05,
+ 0x359f07,
+ 0x338ac5,
+ 0x2affc3,
+ 0x34eb08,
+ 0x35f2ca,
+ 0x20b3c3,
+ 0x32d20a,
+ 0x281ec6,
+ 0x3ac6cf,
+ 0x2f4009,
+ 0x2f9410,
+ 0x2ebe48,
+ 0x2d5809,
+ 0x29f087,
+ 0x256f4f,
+ 0x31e884,
+ 0x2de9c4,
+ 0x224f06,
+ 0x317b06,
+ 0x2e2aca,
+ 0x381c46,
+ 0x2ff587,
+ 0x30c148,
+ 0x30c347,
+ 0x30cbc7,
+ 0x30f08a,
+ 0x310b4b,
+ 0x3b1b45,
+ 0x2e1308,
+ 0x204443,
+ 0x2045cc,
+ 0x38000f,
+ 0x274b8d,
+ 0x2aefc7,
+ 0x30d909,
+ 0x2e8207,
+ 0x24f2c8,
+ 0x38aa0c,
+ 0x2bc548,
+ 0x231848,
+ 0x321d0e,
+ 0x336054,
+ 0x336564,
+ 0x354e4a,
+ 0x37018b,
+ 0x261104,
+ 0x261109,
+ 0x3656c8,
+ 0x24ef85,
+ 0x20d60a,
+ 0x3acd47,
+ 0x31f944,
+ 0x39c783,
+ 0x238543,
+ 0x240244,
+ 0x23cac3,
+ 0x323043,
+ 0x231604,
+ 0x255783,
+ 0x28cac3,
+ 0x20c0c6,
+ 0x21bf84,
+ 0x208e83,
+ 0x201a03,
+ 0x221483,
+ 0x207102,
+ 0x39c783,
+ 0x20f882,
+ 0x238543,
+ 0x240244,
+ 0x23cac3,
+ 0x323043,
+ 0x255783,
+ 0x20c0c6,
+ 0x208e83,
+ 0x201a03,
+ 0x16fb88,
+ 0x238543,
+ 0x23cac3,
+ 0x21b583,
+ 0x208e83,
+ 0x1a3443,
+ 0x201a03,
+ 0x16fb88,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x28cac3,
+ 0x21bf84,
+ 0x208e83,
+ 0x201a03,
+ 0x207102,
+ 0x242043,
+ 0x20f882,
+ 0x23cac3,
+ 0x323043,
+ 0x28cac3,
+ 0x208e83,
+ 0x201a03,
+ 0x201382,
+ 0x235f42,
+ 0x20f882,
+ 0x238543,
+ 0x206902,
+ 0x200942,
+ 0x231604,
+ 0x20f644,
+ 0x22a482,
+ 0x21bf84,
+ 0x200442,
+ 0x201a03,
+ 0x221483,
+ 0x3821c6,
+ 0x21a902,
+ 0x202642,
+ 0x20c4c2,
+ 0x47a13443,
+ 0x47e0bf03,
+ 0x5d306,
+ 0x5d306,
+ 0x286644,
+ 0x200e03,
+ 0x14b700a,
+ 0x12ea0c,
+ 0xf4cc,
+ 0x871cd,
+ 0x131645,
+ 0x26547,
+ 0x1b1c6,
+ 0x21088,
+ 0x23087,
+ 0x28b08,
+ 0x1aa20a,
+ 0x1397c7,
+ 0x48adf485,
+ 0x1359c9,
+ 0x3e34b,
+ 0x35dcb,
+ 0x42e48,
+ 0x172f4a,
+ 0x9288e,
+ 0x144c28b,
+ 0x6a04,
+ 0x63d46,
+ 0x7588,
+ 0xf8d08,
+ 0x3e607,
+ 0x1a787,
+ 0x57f89,
+ 0x81a87,
+ 0xdd088,
+ 0x12f5c9,
+ 0x49804,
+ 0x49f45,
+ 0x12bfce,
+ 0xb084d,
+ 0x8ca48,
+ 0x48e34406,
+ 0x49834408,
+ 0x7b548,
+ 0x11f3d0,
+ 0x5998c,
+ 0x6b9c7,
+ 0x6c647,
+ 0x71387,
+ 0x77fc7,
+ 0x13c42,
+ 0x144ec7,
+ 0x11724c,
+ 0x43b87,
+ 0xac206,
+ 0xac7c9,
+ 0xae208,
+ 0x206c2,
+ 0x942,
+ 0xbee8b,
+ 0x1a3307,
+ 0x18009,
+ 0x164ec9,
+ 0x3ef48,
+ 0xb8042,
+ 0x134649,
+ 0xcc60a,
+ 0xd2689,
+ 0xdfdc9,
+ 0xe0b08,
+ 0xe1b87,
+ 0xe4489,
+ 0xe61c5,
+ 0xe67d0,
+ 0x191646,
+ 0x11205,
+ 0x31e8d,
+ 0x235c6,
+ 0xefd07,
+ 0xf4558,
+ 0x14f508,
+ 0xc74a,
+ 0xb282,
+ 0x5524d,
+ 0xa02,
+ 0x86286,
+ 0x95408,
+ 0x8f148,
+ 0x16fa49,
+ 0x586c8,
+ 0x6420e,
+ 0x126447,
+ 0x1051cd,
+ 0xfb445,
+ 0x144c48,
+ 0x19fc08,
+ 0x106046,
+ 0xc2,
+ 0x12cf06,
+ 0x4542,
+ 0x341,
+ 0x65a07,
+ 0xf6fc3,
+ 0x492f4dc4,
+ 0x4969c243,
+ 0x141,
+ 0x19d06,
+ 0x141,
+ 0x1,
+ 0x19d06,
+ 0xf6fc3,
+ 0x1402285,
+ 0x252044,
+ 0x238543,
+ 0x253384,
+ 0x231604,
+ 0x208e83,
+ 0x229e45,
+ 0x221f43,
+ 0x20c843,
+ 0x355685,
+ 0x202443,
+ 0x4aa38543,
+ 0x23cac3,
+ 0x323043,
+ 0x200041,
+ 0x28cac3,
+ 0x20f644,
+ 0x21bf84,
+ 0x208e83,
+ 0x201a03,
+ 0x215443,
+ 0x16fb88,
+ 0x207102,
+ 0x39c783,
+ 0x20f882,
+ 0x238543,
+ 0x23cac3,
+ 0x21b583,
+ 0x200942,
+ 0x231604,
+ 0x255783,
+ 0x28cac3,
+ 0x208e83,
+ 0x200e03,
+ 0x201a03,
+ 0x202443,
+ 0x16fb88,
+ 0x37fd82,
+ 0x18c1c7,
+ 0xf882,
+ 0x10a985,
+ 0x1480cc8,
+ 0x10c50e,
+ 0x4ba0ab02,
+ 0x31fec8,
+ 0x2bdd86,
+ 0x2ca186,
+ 0x2bd707,
+ 0x4be00b42,
+ 0x4c3ac548,
+ 0x21870a,
+ 0x26b448,
+ 0x200242,
+ 0x31fb49,
+ 0x3b1b87,
+ 0x21ec06,
+ 0x34e849,
+ 0x2e9b44,
+ 0x348646,
+ 0x2ca584,
+ 0x27f584,
+ 0x25f009,
+ 0x32d906,
+ 0x240ac5,
+ 0x297a85,
+ 0x3b9d87,
+ 0x2c76c7,
+ 0x2979c4,
+ 0x2bd946,
+ 0x307b85,
+ 0x30a3c5,
+ 0x3a2a05,
+ 0x339407,
+ 0x378a05,
+ 0x31ddc9,
+ 0x234fc5,
+ 0x32f404,
+ 0x3a81c7,
+ 0x341b0e,
+ 0x306bc9,
+ 0x338749,
+ 0x388d86,
+ 0x24a608,
+ 0x36ae4b,
+ 0x2b698c,
+ 0x33ea46,
+ 0x2e5ac7,
+ 0x212245,
+ 0x38d20a,
+ 0x2b7389,
+ 0x209b49,
+ 0x259f06,
+ 0x300945,
+ 0x2edac5,
+ 0x3570c9,
+ 0x3a2b8b,
+ 0x27e286,
+ 0x3471c6,
+ 0x20de04,
+ 0x2943c6,
+ 0x24e1c8,
+ 0x3c0846,
+ 0x215006,
+ 0x205fc8,
+ 0x2092c7,
+ 0x209909,
+ 0x211385,
+ 0x16fb88,
+ 0x21a704,
+ 0x2394c4,
+ 0x201105,
+ 0x3a6649,
+ 0x228f87,
+ 0x228f8b,
+ 0x22b3ca,
+ 0x230905,
+ 0x4c612842,
+ 0x342f07,
+ 0x4ca30c08,
+ 0x3578c7,
+ 0x2c3d45,
+ 0x209dca,
+ 0xf882,
+ 0x2be6cb,
+ 0x255e0a,
+ 0x22a146,
+ 0x216383,
+ 0x2a038d,
+ 0x3572cc,
+ 0x357a4d,
+ 0x250545,
+ 0x334fc5,
+ 0x20db47,
+ 0x36c689,
+ 0x218606,
+ 0x381ac5,
+ 0x2d2b88,
+ 0x2942c3,
+ 0x2fa288,
+ 0x2942c8,
+ 0x2cb287,
+ 0x314808,
+ 0x3b49c9,
+ 0x374847,
+ 0x342707,
+ 0x202108,
+ 0x2d1c84,
+ 0x2d1c87,
+ 0x26fdc8,
+ 0x355546,
+ 0x3b874f,
+ 0x226207,
+ 0x2eb686,
+ 0x2298c5,
+ 0x22a8c3,
+ 0x381947,
+ 0x37cc43,
+ 0x252886,
+ 0x254006,
+ 0x254706,
+ 0x298b85,
+ 0x26e2c3,
+ 0x397cc8,
+ 0x37f889,
+ 0x3920cb,
+ 0x254888,
+ 0x255985,
+ 0x2584c5,
+ 0x4cef6802,
+ 0x250089,
+ 0x34eec7,
+ 0x263c85,
+ 0x25ef07,
+ 0x260506,
+ 0x374345,
+ 0x263ecb,
+ 0x2662c4,
+ 0x26b005,
+ 0x26b147,
+ 0x27db86,
+ 0x27e045,
+ 0x289a47,
+ 0x28a187,
+ 0x2d5104,
+ 0x291b8a,
+ 0x292048,
+ 0x2cee09,
+ 0x2a0f05,
+ 0x3bf1c6,
+ 0x24e38a,
+ 0x2be906,
+ 0x26f2c7,
+ 0x2ceacd,
+ 0x2aa349,
+ 0x396fc5,
+ 0x339f07,
+ 0x333448,
+ 0x25a5c8,
+ 0x332847,
+ 0x358246,
+ 0x21cb87,
+ 0x253c43,
+ 0x34b1c4,
+ 0x371cc5,
+ 0x39d947,
+ 0x3a2409,
+ 0x231b08,
+ 0x34cbc5,
+ 0x23bac4,
+ 0x254a45,
+ 0x256c4d,
+ 0x2006c2,
+ 0x230386,
+ 0x2861c6,
+ 0x2e654a,
+ 0x3904c6,
+ 0x39ab85,
+ 0x342445,
+ 0x342447,
+ 0x3afd0c,
+ 0x27b3ca,
+ 0x294086,
+ 0x28ad05,
+ 0x294206,
+ 0x294547,
+ 0x296886,
+ 0x298a8c,
+ 0x34e989,
+ 0x4d21a187,
+ 0x29b745,
+ 0x29b746,
+ 0x29bcc8,
+ 0x246f85,
+ 0x2ab085,
+ 0x2ab808,
+ 0x2aba0a,
+ 0x4d6335c2,
+ 0x4da14d02,
+ 0x2e76c5,
+ 0x2eb603,
+ 0x243408,
+ 0x252403,
+ 0x2abc84,
+ 0x25240b,
+ 0x36b208,
+ 0x2daa48,
+ 0x4df3b049,
+ 0x2afc09,
+ 0x2b0746,
+ 0x2b1c08,
+ 0x2b1e09,
+ 0x2b2886,
+ 0x2b2a05,
+ 0x3944c6,
+ 0x2b2f49,
+ 0x389347,
+ 0x2647c6,
+ 0x2de087,
+ 0x218487,
+ 0x2dd9c4,
+ 0x4e34f809,
+ 0x2d32c8,
+ 0x3ac448,
+ 0x3932c7,
+ 0x2cd346,
+ 0x36c489,
+ 0x2ca847,
+ 0x32598a,
+ 0x358388,
+ 0x208387,
+ 0x208f86,
+ 0x271d8a,
+ 0x26fbc8,
+ 0x2ed485,
+ 0x230685,
+ 0x2ef1c7,
+ 0x311cc9,
+ 0x30150b,
+ 0x31a308,
+ 0x235049,
+ 0x254c87,
+ 0x2bd04c,
+ 0x2bfccc,
+ 0x2bffca,
+ 0x2c024c,
+ 0x2ca108,
+ 0x2ca308,
+ 0x2ca504,
+ 0x2caa09,
+ 0x2cac49,
+ 0x2cae8a,
+ 0x2cb109,
+ 0x2cb447,
+ 0x3ba98c,
+ 0x23f586,
+ 0x2cbf88,
+ 0x2be9c6,
+ 0x387486,
+ 0x396ec7,
+ 0x306dc8,
+ 0x3445cb,
+ 0x28e307,
+ 0x250289,
+ 0x350b89,
+ 0x253507,
+ 0x2771c4,
+ 0x271c07,
+ 0x2fda46,
+ 0x21d8c6,
+ 0x33c345,
+ 0x297248,
+ 0x2993c4,
+ 0x2993c6,
+ 0x27b28b,
+ 0x21bac9,
+ 0x36c886,
+ 0x204bc9,
+ 0x339586,
+ 0x25f1c8,
+ 0x211b83,
+ 0x300ac5,
+ 0x219b09,
+ 0x21da05,
+ 0x2fba44,
+ 0x27d046,
+ 0x2fd385,
+ 0x299906,
+ 0x310ec7,
+ 0x33a986,
+ 0x3b134b,
+ 0x237587,
+ 0x241646,
+ 0x354786,
+ 0x3b9e46,
+ 0x297989,
+ 0x25384a,
+ 0x2bbb85,
+ 0x2202cd,
+ 0x2abb06,
+ 0x204a86,
+ 0x2f3f06,
+ 0x22dd45,
+ 0x2e6ac7,
+ 0x300087,
+ 0x2e7dce,
+ 0x28cac3,
+ 0x2cd309,
+ 0x210c89,
+ 0x38d607,
+ 0x364207,
+ 0x2a5bc5,
+ 0x2b57c5,
+ 0x4e63470f,
+ 0x2d5a47,
+ 0x2d5c08,
+ 0x2d6144,
+ 0x2d7106,
+ 0x4ea4ea42,
+ 0x2da786,
+ 0x20c0c6,
+ 0x210e4e,
+ 0x2fa0ca,
+ 0x273b06,
+ 0x23398a,
+ 0x211689,
+ 0x32b385,
+ 0x3a4808,
+ 0x3bca06,
+ 0x306748,
+ 0x33aac8,
+ 0x2194cb,
+ 0x2bd805,
+ 0x378a88,
+ 0x20610c,
+ 0x2c3c07,
+ 0x254246,
+ 0x2fd1c8,
+ 0x3488c8,
+ 0x4ee06802,
+ 0x23588b,
+ 0x2123c9,
+ 0x205549,
+ 0x2174c7,
+ 0x223408,
+ 0x4f36bec8,
+ 0x38ffcb,
+ 0x23edc9,
+ 0x338f0d,
+ 0x27fa88,
+ 0x22b1c8,
+ 0x4f6014c2,
+ 0x203cc4,
+ 0x4fa19302,
+ 0x2fe206,
+ 0x4fe004c2,
+ 0x261b8a,
+ 0x2199c6,
+ 0x232808,
+ 0x2c6f48,
+ 0x2b6f06,
+ 0x22fe46,
+ 0x2f9186,
+ 0x2b5a45,
+ 0x2443c4,
+ 0x50206d04,
+ 0x214106,
+ 0x29c747,
+ 0x50620c47,
+ 0x2d644b,
+ 0x341ec9,
+ 0x33500a,
+ 0x2106c4,
+ 0x342588,
+ 0x26458d,
+ 0x2f2489,
+ 0x2f26c8,
+ 0x2f2d49,
+ 0x2f4544,
+ 0x245884,
+ 0x285cc5,
+ 0x320fcb,
+ 0x36b186,
+ 0x34b905,
+ 0x2279c9,
+ 0x2bda08,
+ 0x210dc4,
+ 0x38d389,
+ 0x2064c5,
+ 0x2c7708,
+ 0x342dc7,
+ 0x338b48,
+ 0x286d86,
+ 0x233207,
+ 0x29a989,
+ 0x224a49,
+ 0x38adc5,
+ 0x34dfc5,
+ 0x50a08402,
+ 0x32f1c4,
+ 0x2fdd45,
+ 0x2ce506,
+ 0x33bd05,
+ 0x387e47,
+ 0x214205,
+ 0x27dbc4,
+ 0x388e46,
+ 0x381b47,
+ 0x23d046,
+ 0x2c41c5,
+ 0x207f48,
+ 0x2bdf85,
+ 0x211a07,
+ 0x214689,
+ 0x21bc0a,
+ 0x2fc487,
+ 0x2fc48c,
+ 0x240a86,
+ 0x37e349,
+ 0x246a45,
+ 0x246ec8,
+ 0x207c03,
+ 0x216d85,
+ 0x2fd705,
+ 0x282d47,
+ 0x50e06ac2,
+ 0x22f647,
+ 0x2e56c6,
+ 0x373b46,
+ 0x30bfc6,
+ 0x348806,
+ 0x206748,
+ 0x2a0d05,
+ 0x2eb747,
+ 0x2eb74d,
+ 0x227103,
+ 0x227105,
+ 0x379347,
+ 0x22f988,
+ 0x378f05,
+ 0x2216c8,
+ 0x37ccc6,
+ 0x335b87,
+ 0x2cbec5,
+ 0x2bd886,
+ 0x39ce45,
+ 0x21c70a,
+ 0x2f1346,
+ 0x383f47,
+ 0x2bca85,
+ 0x2f5047,
+ 0x2f97c4,
+ 0x2fb9c6,
+ 0x2fe345,
+ 0x32d70b,
+ 0x2fd8c9,
+ 0x24214a,
+ 0x38ae48,
+ 0x30e048,
+ 0x380a8c,
+ 0x3964c7,
+ 0x3054c8,
+ 0x307f48,
+ 0x3084c5,
+ 0x311a8a,
+ 0x31c449,
+ 0x51200d02,
+ 0x201886,
+ 0x216044,
+ 0x216049,
+ 0x27d549,
+ 0x27e9c7,
+ 0x2b4e07,
+ 0x2938c9,
+ 0x22df48,
+ 0x22df4f,
+ 0x2e3a06,
+ 0x2df14b,
+ 0x34b445,
+ 0x34b447,
+ 0x368849,
+ 0x21aa46,
+ 0x38d307,
+ 0x2e1a45,
+ 0x23ae84,
+ 0x284fc6,
+ 0x2262c4,
+ 0x2db107,
+ 0x2d6f08,
+ 0x51700848,
+ 0x301245,
+ 0x301387,
+ 0x260a09,
+ 0x205304,
+ 0x24b348,
+ 0x51ab7cc8,
+ 0x283384,
+ 0x23c208,
+ 0x332d44,
+ 0x22be49,
+ 0x351a45,
+ 0x51e05082,
+ 0x2e3a45,
+ 0x310045,
+ 0x20fc48,
+ 0x23d747,
+ 0x52200d42,
+ 0x3322c5,
+ 0x2d8e46,
+ 0x27cb06,
+ 0x32f188,
+ 0x337d48,
+ 0x33bcc6,
+ 0x34bb06,
+ 0x38c289,
+ 0x373a86,
+ 0x21a90b,
+ 0x2e5f85,
+ 0x208a46,
+ 0x29e108,
+ 0x3a0a06,
+ 0x322c46,
+ 0x221b8a,
+ 0x23b30a,
+ 0x2498c5,
+ 0x2a0dc7,
+ 0x313646,
+ 0x52606442,
+ 0x379487,
+ 0x266cc5,
+ 0x24e304,
+ 0x24e305,
+ 0x2105c6,
+ 0x278fc7,
+ 0x215dc5,
+ 0x23b484,
+ 0x2c4788,
+ 0x322d05,
+ 0x3af347,
+ 0x3b6dc5,
+ 0x21c645,
+ 0x258f84,
+ 0x2ee209,
+ 0x3079c8,
+ 0x263146,
+ 0x2b5386,
+ 0x345186,
+ 0x52b08148,
+ 0x308347,
+ 0x30874d,
+ 0x3090cc,
+ 0x3096c9,
+ 0x309909,
+ 0x52f67742,
+ 0x3b6343,
+ 0x215ac3,
+ 0x2fdb05,
+ 0x39da4a,
+ 0x32f046,
+ 0x30e2c5,
+ 0x311084,
+ 0x31108b,
+ 0x323a8c,
+ 0x3244cc,
+ 0x3247d5,
+ 0x32660d,
+ 0x327d0f,
+ 0x3280d2,
+ 0x32854f,
+ 0x328912,
+ 0x328d93,
+ 0x32924d,
+ 0x32980d,
+ 0x329b8e,
+ 0x32a10e,
+ 0x32a94c,
+ 0x32ad0c,
+ 0x32b14b,
+ 0x32b4ce,
+ 0x32c612,
+ 0x32ee0c,
+ 0x32fd90,
+ 0x33cd52,
+ 0x33d9cc,
+ 0x33e08d,
+ 0x33e3cc,
+ 0x3406d1,
+ 0x34734d,
+ 0x349e0d,
+ 0x34a40a,
+ 0x34a68c,
+ 0x34af8c,
+ 0x34b60c,
+ 0x34c20c,
+ 0x3523d3,
+ 0x352cd0,
+ 0x3530d0,
+ 0x35398d,
+ 0x353f8c,
+ 0x354b89,
+ 0x35690d,
+ 0x356c53,
+ 0x3595d1,
+ 0x359a13,
+ 0x35a0cf,
+ 0x35a48c,
+ 0x35a78f,
+ 0x35ab4d,
+ 0x35b14f,
+ 0x35b510,
+ 0x35bf8e,
+ 0x35f88e,
+ 0x35fe10,
+ 0x36150d,
+ 0x361e8e,
+ 0x36220c,
+ 0x363213,
+ 0x3658ce,
+ 0x365f50,
+ 0x366351,
+ 0x36678f,
+ 0x366b53,
+ 0x3672cd,
+ 0x36760f,
+ 0x3679ce,
+ 0x368090,
+ 0x368489,
+ 0x369210,
+ 0x36980f,
+ 0x369e8f,
+ 0x36a252,
+ 0x36dcce,
+ 0x36e7cd,
+ 0x36f00d,
+ 0x36f34d,
+ 0x37078d,
+ 0x370acd,
+ 0x370e10,
+ 0x37120b,
+ 0x371a8c,
+ 0x371e0c,
+ 0x37240c,
+ 0x37270e,
+ 0x382350,
+ 0x384512,
+ 0x38498b,
+ 0x384e8e,
+ 0x38520e,
+ 0x386dce,
+ 0x38724b,
+ 0x53388016,
+ 0x38988d,
+ 0x38a014,
+ 0x38b04d,
+ 0x38cd55,
+ 0x38e30d,
+ 0x38ec8f,
+ 0x38f4cf,
+ 0x39238f,
+ 0x39274e,
+ 0x392ccd,
+ 0x394091,
+ 0x39668c,
+ 0x39698c,
+ 0x396c8b,
+ 0x39710c,
+ 0x3974cf,
+ 0x397892,
+ 0x39824d,
+ 0x39974c,
+ 0x399bcc,
+ 0x399ecd,
+ 0x39a20f,
+ 0x39a5ce,
+ 0x39d70c,
+ 0x39dccd,
+ 0x39e00b,
+ 0x39e9cc,
+ 0x39f2cd,
+ 0x39f60e,
+ 0x39f989,
+ 0x3a1353,
+ 0x3a188d,
+ 0x3a1bcd,
+ 0x3a21cc,
+ 0x3a264e,
+ 0x3a37cf,
+ 0x3a3b8c,
+ 0x3a3e8d,
+ 0x3a41cf,
+ 0x3a458c,
+ 0x3a508c,
+ 0x3a550c,
+ 0x3a580c,
+ 0x3a5ecd,
+ 0x3a6212,
+ 0x3a688c,
+ 0x3a6b8c,
+ 0x3a6e91,
+ 0x3a72cf,
+ 0x3a768f,
+ 0x3a7a53,
+ 0x3a8a0e,
+ 0x3a8d8f,
+ 0x3a914c,
+ 0x537a948e,
+ 0x3a980f,
+ 0x3a9bd6,
+ 0x3aaa92,
+ 0x3acf0c,
+ 0x3ada0f,
+ 0x3ae08d,
+ 0x3ae3cf,
+ 0x3ae78c,
+ 0x3aea8d,
+ 0x3aedcd,
+ 0x3b084e,
+ 0x3b228c,
+ 0x3b258c,
+ 0x3b2890,
+ 0x3b57d1,
+ 0x3b5c0b,
+ 0x3b5f4c,
+ 0x3b624e,
+ 0x3b7211,
+ 0x3b764e,
+ 0x3b79cd,
+ 0x3bc7cb,
+ 0x3bd88f,
+ 0x3be394,
+ 0x210642,
+ 0x210642,
+ 0x204d43,
+ 0x210642,
+ 0x204d43,
+ 0x210642,
+ 0x2009c2,
+ 0x394505,
+ 0x3b6f0c,
+ 0x210642,
+ 0x210642,
+ 0x2009c2,
+ 0x210642,
+ 0x29c345,
+ 0x21bc05,
+ 0x210642,
+ 0x210642,
+ 0x201102,
+ 0x29c345,
+ 0x326b49,
+ 0x3592cc,
+ 0x210642,
+ 0x210642,
+ 0x210642,
+ 0x210642,
+ 0x394505,
+ 0x210642,
+ 0x210642,
+ 0x210642,
+ 0x210642,
+ 0x201102,
+ 0x326b49,
+ 0x210642,
+ 0x210642,
+ 0x210642,
+ 0x21bc05,
+ 0x210642,
+ 0x21bc05,
+ 0x3592cc,
+ 0x3b6f0c,
+ 0x39c783,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x231604,
+ 0x208e83,
+ 0x201a03,
+ 0xe008,
+ 0x64344,
+ 0xe03,
+ 0xc63c8,
+ 0x207102,
+ 0x5460f882,
+ 0x24ac83,
+ 0x23f044,
+ 0x2020c3,
+ 0x39e544,
+ 0x23a1c6,
+ 0x216f83,
+ 0x304704,
+ 0x2d7b05,
+ 0x28cac3,
+ 0x208e83,
+ 0x1a3443,
+ 0x201a03,
+ 0x243d0a,
+ 0x3821c6,
+ 0x38558c,
+ 0x16fb88,
+ 0x20f882,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x229443,
+ 0x20c0c6,
+ 0x208e83,
+ 0x201a03,
+ 0x221483,
+ 0xac408,
+ 0x131645,
+ 0x35f09,
+ 0x35c2,
+ 0x55b95645,
+ 0x26547,
+ 0xba9c8,
+ 0x14b0e,
+ 0x90212,
+ 0x10a78b,
+ 0x1398c6,
+ 0x55edf485,
+ 0x562df48c,
+ 0x148f87,
+ 0x36dc7,
+ 0x15000a,
+ 0x46690,
+ 0x13b345,
+ 0xb610b,
+ 0xf8d08,
+ 0x3e607,
+ 0x3af8b,
+ 0x57f89,
+ 0x185a87,
+ 0x81a87,
+ 0x7e4c7,
+ 0x3e546,
+ 0xdd088,
+ 0x56824386,
+ 0xb084d,
+ 0x14f9d0,
+ 0x56c0c182,
+ 0x8ca48,
+ 0x4f450,
+ 0x15090c,
+ 0x5735cd4d,
+ 0x64a88,
+ 0x721c7,
+ 0x76f09,
+ 0x5d3c6,
+ 0x9bec8,
+ 0x351c2,
+ 0xa808a,
+ 0x293c7,
+ 0x43b87,
+ 0xac7c9,
+ 0xae208,
+ 0x8b205,
+ 0xd538e,
+ 0x5c4e,
+ 0x17a8f,
+ 0x18009,
+ 0x164ec9,
+ 0x15d38b,
+ 0x7ba8f,
+ 0xee40c,
+ 0xa88cb,
+ 0xc8b48,
+ 0xd6347,
+ 0xdbe88,
+ 0xfe78b,
+ 0xff34c,
+ 0x10038c,
+ 0x1037cc,
+ 0x10b54d,
+ 0x3ef48,
+ 0xd2942,
+ 0x134649,
+ 0x195d8b,
+ 0xcd546,
+ 0x11f30b,
+ 0xe118a,
+ 0xe1d45,
+ 0xe67d0,
+ 0xe9f06,
+ 0x16b986,
+ 0x11205,
+ 0x10fc48,
+ 0xefd07,
+ 0xeffc7,
+ 0x8d047,
+ 0xfe04a,
+ 0xba84a,
+ 0x86286,
+ 0x99d0d,
+ 0x8f148,
+ 0x586c8,
+ 0x58ec9,
+ 0xbc8c5,
+ 0x1ad70c,
+ 0x10b74b,
+ 0x19e604,
+ 0x105e09,
+ 0x106046,
+ 0x16546,
+ 0x2642,
+ 0x12cf06,
+ 0xc68b,
+ 0x112707,
+ 0x4542,
+ 0xd1305,
+ 0x2e604,
+ 0x8c1,
+ 0x52d03,
+ 0x56764886,
+ 0x9c243,
+ 0x7b02,
+ 0x293c4,
+ 0x242,
+ 0x86644,
+ 0xf82,
+ 0x6502,
+ 0x3302,
+ 0xd342,
+ 0x1382,
+ 0xdf482,
+ 0x8c2,
+ 0x22902,
+ 0x40e82,
+ 0x1a442,
+ 0x4c82,
+ 0x234c2,
+ 0x3cac3,
+ 0x6b82,
+ 0x1842,
+ 0x7602,
+ 0x6b02,
+ 0x17202,
+ 0x36d02,
+ 0x206c2,
+ 0xc442,
+ 0x1c82,
+ 0x942,
+ 0x55783,
+ 0x4182,
+ 0x2542,
+ 0xb8042,
+ 0x9a02,
+ 0x282,
+ 0x2942,
+ 0xd842,
+ 0xc202,
+ 0x4a82,
+ 0x182842,
+ 0x745c2,
+ 0xe82,
+ 0x8e83,
+ 0x1942,
+ 0x6802,
+ 0x982,
+ 0x5b82,
+ 0x18ad45,
+ 0x7082,
+ 0x2fa42,
+ 0x13ebc3,
+ 0x482,
+ 0xb282,
+ 0xa02,
+ 0x2502,
+ 0x6742,
+ 0xd42,
+ 0xc2,
+ 0x2642,
+ 0x35dc5,
+ 0x17f087,
+ 0x20d0c3,
+ 0x207102,
+ 0x238543,
+ 0x23cac3,
+ 0x21b583,
+ 0x2046c3,
+ 0x229443,
+ 0x208e83,
+ 0x200e03,
+ 0x201a03,
+ 0x29c283,
+ 0x10c3,
+ 0x16fb88,
+ 0x238543,
+ 0x23cac3,
+ 0x21b583,
+ 0x28cac3,
+ 0x208e83,
+ 0x200e03,
+ 0x1a3443,
+ 0x201a03,
+ 0x238543,
+ 0x23cac3,
+ 0x201a03,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x200041,
+ 0x28cac3,
+ 0x208e83,
+ 0x21b543,
+ 0x201a03,
+ 0x146f44,
+ 0x39c783,
+ 0x238543,
+ 0x23cac3,
+ 0x26eac3,
+ 0x21b583,
+ 0x207b03,
+ 0x289303,
+ 0x219983,
+ 0x241503,
+ 0x323043,
+ 0x231604,
+ 0x208e83,
+ 0x201a03,
+ 0x202443,
+ 0x333cc4,
+ 0x251183,
+ 0x3ec3,
+ 0x3c0943,
+ 0x20a3c8,
+ 0x271dc4,
+ 0x2cf30a,
+ 0x2bed86,
+ 0x112384,
+ 0x3a7ec7,
+ 0x226cca,
+ 0x2e38c9,
+ 0x3b7f87,
+ 0x3be84a,
+ 0x39c783,
+ 0x2e774b,
+ 0x28b689,
+ 0x345285,
+ 0x2da5c7,
+ 0xf882,
+ 0x238543,
+ 0x21a447,
+ 0x2379c5,
+ 0x2ca689,
+ 0x23cac3,
+ 0x2bd606,
+ 0x2c9883,
+ 0xe5743,
+ 0x110646,
+ 0xd386,
+ 0x16f07,
+ 0x21af86,
+ 0x222985,
+ 0x3a3147,
+ 0x2de5c7,
+ 0x59b23043,
+ 0x33dc07,
+ 0x374703,
+ 0x3b5045,
+ 0x231604,
+ 0x231308,
+ 0x366fcc,
+ 0x2b4fc5,
+ 0x2aa4c6,
+ 0x21a307,
+ 0x39b687,
+ 0x23dfc7,
+ 0x23f108,
+ 0x30f50f,
+ 0x2e3b05,
+ 0x24ad87,
+ 0x33acc7,
+ 0x2abdca,
+ 0x2d29c9,
+ 0x39e6c5,
+ 0x31078a,
+ 0xc546,
+ 0x2c9905,
+ 0x3703c4,
+ 0x2c6e86,
+ 0x300e07,
+ 0x2d2847,
+ 0x306908,
+ 0x217645,
+ 0x2378c6,
+ 0x214f85,
+ 0x2e8105,
+ 0x21ba04,
+ 0x2b6e07,
+ 0x20658a,
+ 0x34d908,
+ 0x367f06,
+ 0x29443,
+ 0x2e4505,
+ 0x26bf86,
+ 0x3babc6,
+ 0x211106,
+ 0x28cac3,
+ 0x3984c7,
+ 0x33ac45,
+ 0x208e83,
+ 0x2e144d,
+ 0x200e03,
+ 0x306a08,
+ 0x3b3644,
+ 0x310945,
+ 0x2abcc6,
+ 0x23f386,
+ 0x208947,
+ 0x2aed47,
+ 0x26f045,
+ 0x201a03,
+ 0x20a147,
+ 0x277089,
+ 0x36bbc9,
+ 0x227f4a,
+ 0x235d82,
+ 0x3b5004,
+ 0x2eb2c4,
+ 0x344487,
+ 0x22f508,
+ 0x2f0889,
+ 0x226fc9,
+ 0x2f1ac7,
+ 0x28bb46,
+ 0xf3006,
+ 0x2f4544,
+ 0x2f4b4a,
+ 0x2f8248,
+ 0x2f9049,
+ 0x2c4bc6,
+ 0x2b9545,
+ 0x34d7c8,
+ 0x2cdc4a,
+ 0x20ec43,
+ 0x333e46,
+ 0x2f1bc7,
+ 0x225f45,
+ 0x3b3505,
+ 0x3a04c3,
+ 0x231944,
+ 0x230645,
+ 0x28a287,
+ 0x307b05,
+ 0x2ef086,
+ 0x103d45,
+ 0x273bc3,
+ 0x273bc9,
+ 0x26c04c,
+ 0x2a2b4c,
+ 0x2d8648,
+ 0x284187,
+ 0x301e08,
+ 0x30214a,
+ 0x302fcb,
+ 0x28b7c8,
+ 0x23ec48,
+ 0x23f486,
+ 0x345045,
+ 0x34624a,
+ 0x228cc5,
+ 0x205082,
+ 0x2cbd87,
+ 0x29f806,
+ 0x368d45,
+ 0x304209,
+ 0x281405,
+ 0x3716c5,
+ 0x218ac9,
+ 0x388a46,
+ 0x204448,
+ 0x332643,
+ 0x217186,
+ 0x27cf86,
+ 0x311f05,
+ 0x311f09,
+ 0x2f0fc9,
+ 0x27a3c7,
+ 0x114204,
+ 0x314207,
+ 0x226ec9,
+ 0x23f805,
+ 0x444c8,
+ 0x39c485,
+ 0x341a05,
+ 0x3911c9,
+ 0x20cac2,
+ 0x2628c4,
+ 0x200882,
+ 0x204182,
+ 0x30e985,
+ 0x312108,
+ 0x2bc805,
+ 0x2cb603,
+ 0x2cb605,
+ 0x2da983,
+ 0x2162c2,
+ 0x383c84,
+ 0x2fc183,
+ 0x20cb42,
+ 0x341504,
+ 0x2ec043,
+ 0x206682,
+ 0x28cfc3,
+ 0x295384,
+ 0x2eae03,
+ 0x2f6584,
+ 0x204242,
+ 0x221383,
+ 0x219c43,
+ 0x206182,
+ 0x332182,
+ 0x2f0e09,
+ 0x204382,
+ 0x290d84,
+ 0x201f82,
+ 0x34d644,
+ 0x28bb04,
+ 0x2c0d84,
+ 0x202642,
+ 0x23e882,
+ 0x229703,
+ 0x302d83,
+ 0x24a9c4,
+ 0x28a404,
+ 0x2f1d44,
+ 0x2f8404,
+ 0x315743,
+ 0x224183,
+ 0x20c4c4,
+ 0x315584,
+ 0x315d86,
+ 0x232ec2,
+ 0x20f882,
+ 0x23cac3,
+ 0x323043,
+ 0x208e83,
+ 0x201a03,
+ 0x207102,
+ 0x39c783,
+ 0x238543,
+ 0x23cac3,
+ 0x201843,
+ 0x323043,
+ 0x231604,
+ 0x2f10c4,
+ 0x21bf84,
+ 0x208e83,
+ 0x201a03,
+ 0x221483,
+ 0x2f5204,
+ 0x31fe83,
+ 0x2c37c3,
+ 0x359e44,
+ 0x39c286,
+ 0x211c43,
+ 0x36dc7,
+ 0x21f243,
+ 0x202103,
+ 0x2b8d83,
+ 0x263a43,
+ 0x229443,
+ 0x3321c5,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x208e83,
+ 0x201a03,
+ 0x216403,
+ 0x239043,
+ 0x16fb88,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x255783,
+ 0x208e83,
+ 0x2464c4,
+ 0x1a3443,
+ 0x201a03,
+ 0x25b0c4,
+ 0x2c6c85,
+ 0x36dc7,
+ 0x20f882,
+ 0x201742,
+ 0x207b02,
+ 0x204d42,
+ 0xe03,
+ 0x200442,
+ 0x238543,
+ 0x240244,
+ 0x23cac3,
+ 0x323043,
+ 0x28cac3,
+ 0x208e83,
+ 0x201a03,
+ 0x16fb88,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x28cac3,
+ 0x21bf84,
+ 0x208e83,
+ 0xe03,
+ 0x201a03,
+ 0x215443,
+ 0x286644,
+ 0x16fb88,
+ 0x238543,
+ 0x200e03,
+ 0x10c3,
+ 0x13e8c4,
+ 0x252044,
+ 0x16fb88,
+ 0x238543,
+ 0x253384,
+ 0x231604,
+ 0x200e03,
+ 0x2014c2,
+ 0x201a03,
+ 0x20c843,
+ 0x31944,
+ 0x355685,
+ 0x205082,
+ 0x3156c3,
+ 0x145c49,
+ 0xdfb46,
+ 0x19c588,
+ 0x207102,
+ 0x16fb88,
+ 0x20f882,
+ 0x23cac3,
+ 0x323043,
+ 0x200942,
+ 0xe03,
+ 0x201a03,
+ 0x207102,
+ 0x1bea07,
+ 0x1370c9,
+ 0x3dc3,
+ 0x16fb88,
+ 0xd303,
+ 0x5db4c807,
+ 0x38543,
+ 0x1788,
+ 0x23cac3,
+ 0x323043,
+ 0x186c46,
+ 0x255783,
+ 0xe8888,
+ 0xc9148,
+ 0x3fbc6,
+ 0x28cac3,
+ 0xd30c8,
+ 0x187ec3,
+ 0xe8a85,
+ 0x3ccc7,
+ 0x8e83,
+ 0x63c3,
+ 0x1a03,
+ 0xcb02,
+ 0x17044a,
+ 0x10ea43,
+ 0x313e44,
+ 0x10f30b,
+ 0x10f8c8,
+ 0x95e02,
+ 0x207102,
+ 0x20f882,
+ 0x238543,
+ 0x23cac3,
+ 0x2de944,
+ 0x323043,
+ 0x255783,
+ 0x28cac3,
+ 0x208e83,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x229443,
+ 0x208e83,
+ 0x201a03,
+ 0x236903,
+ 0x215443,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x208e83,
+ 0x201a03,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x208e83,
+ 0x201a03,
+ 0x10c3,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x231604,
+ 0x229443,
+ 0x208e83,
+ 0x201a03,
+ 0x21a902,
+ 0x200141,
+ 0x207102,
+ 0x200001,
+ 0x327e02,
+ 0x16fb88,
+ 0x224c85,
+ 0x2008c1,
+ 0x38543,
+ 0x201781,
+ 0x200301,
+ 0x200081,
+ 0x2ac602,
+ 0x37cc44,
+ 0x394483,
+ 0x200181,
+ 0x200401,
+ 0x200041,
+ 0x200101,
+ 0x2ea547,
+ 0x2ec54f,
+ 0x2fbc06,
+ 0x200281,
+ 0x33e906,
+ 0x200801,
+ 0x200981,
+ 0x306f8e,
+ 0x200441,
+ 0x201a03,
+ 0x204101,
+ 0x258885,
+ 0x20cb02,
+ 0x3a03c5,
+ 0x200341,
+ 0x200741,
+ 0x2002c1,
+ 0x205082,
+ 0x2000c1,
+ 0x200201,
+ 0x200c81,
+ 0x2005c1,
+ 0x204541,
+ 0x16fb88,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x208e83,
+ 0x201a03,
+ 0x221f43,
+ 0x238543,
+ 0x323043,
+ 0x95d48,
+ 0x28cac3,
+ 0x208e83,
+ 0x31483,
+ 0x201a03,
+ 0x14eec08,
+ 0x16308,
+ 0x16fb88,
+ 0xe03,
+ 0x8e444,
+ 0x4ec04,
+ 0x14eec0a,
+ 0x16fb88,
+ 0x1a3443,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x208e83,
+ 0x201a03,
+ 0x203ec3,
+ 0x16fb88,
+ 0x238543,
+ 0x23cac3,
+ 0x2de944,
+ 0x201a03,
+ 0x22d585,
+ 0x35f2c4,
+ 0x238543,
+ 0x208e83,
+ 0x201a03,
+ 0x1f40a,
+ 0xf1844,
+ 0x118b06,
+ 0x20f882,
+ 0x238543,
+ 0x23adc9,
+ 0x23cac3,
+ 0x375449,
+ 0x323043,
+ 0x28cac3,
+ 0x208e83,
+ 0x201a03,
+ 0x2f4348,
+ 0x22dc07,
+ 0x355685,
+ 0xb4c8,
+ 0x1bea07,
+ 0x2f78a,
+ 0x178ccb,
+ 0x13c507,
+ 0x4a4c8,
+ 0x14f64a,
+ 0x19dc8,
+ 0x1370c9,
+ 0x30507,
+ 0x742c7,
+ 0x19bf08,
+ 0x1788,
+ 0x4b04f,
+ 0x1c045,
+ 0x1a87,
+ 0x186c46,
+ 0x41287,
+ 0x4a786,
+ 0xe8888,
+ 0x96fc6,
+ 0x188847,
+ 0x178809,
+ 0x1bf307,
+ 0xd81c9,
+ 0xbcbc9,
+ 0xc6a06,
+ 0xc9148,
+ 0xc7845,
+ 0x57b0a,
+ 0xd30c8,
+ 0x187ec3,
+ 0xdad48,
+ 0x3ccc7,
+ 0x131f45,
+ 0x787d0,
+ 0x63c3,
+ 0x1a3443,
+ 0x125807,
+ 0x1cc85,
+ 0xf02c8,
+ 0xe385,
+ 0x10ea43,
+ 0x16d5c8,
+ 0x12906,
+ 0x198909,
+ 0xb2007,
+ 0x145f0b,
+ 0x180884,
+ 0x104f04,
+ 0x10f30b,
+ 0x10f8c8,
+ 0x110547,
+ 0x131645,
+ 0x238543,
+ 0x23cac3,
+ 0x21b583,
+ 0x201a03,
+ 0x20c743,
+ 0x323043,
+ 0x1a3443,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x28cac3,
+ 0x208e83,
+ 0x201a03,
+ 0x15d4cb,
+ 0x207102,
+ 0x20f882,
+ 0x201a03,
+ 0x16fb88,
+ 0x207102,
+ 0x20f882,
+ 0x207b02,
+ 0x200942,
+ 0x20b302,
+ 0x208e83,
+ 0x200442,
+ 0x207102,
+ 0x39c783,
+ 0x20f882,
+ 0x238543,
+ 0x23cac3,
+ 0x207b02,
+ 0x323043,
+ 0x255783,
+ 0x28cac3,
+ 0x21bf84,
+ 0x208e83,
+ 0x21eb43,
+ 0x201a03,
+ 0x313e44,
+ 0x202443,
+ 0x323043,
+ 0x20f882,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x28cac3,
+ 0x208e83,
+ 0x200e03,
+ 0x201a03,
+ 0x3ad3c7,
+ 0x238543,
+ 0x282c07,
+ 0x2d7f86,
+ 0x20e583,
+ 0x207603,
+ 0x323043,
+ 0x204c03,
+ 0x231604,
+ 0x2d5204,
+ 0x30e706,
+ 0x20bd43,
+ 0x208e83,
+ 0x201a03,
+ 0x22d585,
+ 0x321704,
+ 0x350503,
+ 0x39b4c3,
+ 0x2cbd87,
+ 0x342d45,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x28cac3,
+ 0x208e83,
+ 0x201a03,
+ 0x99807,
+ 0x203402,
+ 0x28f283,
+ 0x205403,
+ 0x39c783,
+ 0x65e38543,
+ 0x206902,
+ 0x23cac3,
+ 0x2020c3,
+ 0x323043,
+ 0x231604,
+ 0x3797c3,
+ 0x2e3b03,
+ 0x28cac3,
+ 0x21bf84,
+ 0x6620ea42,
+ 0x208e83,
+ 0x201a03,
+ 0x206683,
+ 0x22e603,
+ 0x21a902,
+ 0x202443,
+ 0x16fb88,
+ 0x323043,
+ 0x10c3,
+ 0x31f944,
+ 0x39c783,
+ 0x20f882,
+ 0x238543,
+ 0x240244,
+ 0x23cac3,
+ 0x323043,
+ 0x231604,
+ 0x255783,
+ 0x3a2e44,
+ 0x20f644,
+ 0x20c0c6,
+ 0x21bf84,
+ 0x208e83,
+ 0x201a03,
+ 0x221483,
+ 0x29f806,
+ 0x4504b,
+ 0x24386,
+ 0x3204a,
+ 0x112d0a,
+ 0x16fb88,
+ 0x214f44,
+ 0x67638543,
+ 0x39c744,
+ 0x23cac3,
+ 0x259004,
+ 0x323043,
+ 0x210543,
+ 0x28cac3,
+ 0x208e83,
+ 0x1a3443,
+ 0x201a03,
+ 0xbac3,
+ 0x3381cb,
+ 0x3af10a,
+ 0x3bf84c,
+ 0xe4288,
+ 0x207102,
+ 0x20f882,
+ 0x207b02,
+ 0x2b13c5,
+ 0x231604,
+ 0x204a82,
+ 0x28cac3,
+ 0x20f644,
+ 0x204d42,
+ 0x200442,
+ 0x20d2c2,
+ 0x21a902,
+ 0x19c783,
+ 0x35f42,
+ 0x2b3509,
+ 0x2f7148,
+ 0x351689,
+ 0x2410c9,
+ 0x350f0a,
+ 0x26080a,
+ 0x2127c2,
+ 0x222902,
+ 0xf882,
+ 0x238543,
+ 0x229682,
+ 0x24af46,
+ 0x369d02,
+ 0x206a42,
+ 0x37904e,
+ 0x2213ce,
+ 0x284b47,
+ 0x208e07,
+ 0x2ec8c2,
+ 0x23cac3,
+ 0x323043,
+ 0x200042,
+ 0x200942,
+ 0x31603,
+ 0x23980f,
+ 0x20b542,
+ 0x2dd887,
+ 0x2b4a87,
+ 0x2b7e87,
+ 0x31a4cc,
+ 0x2c448c,
+ 0x223984,
+ 0x285b0a,
+ 0x221302,
+ 0x209a02,
+ 0x2c0884,
+ 0x21f502,
+ 0x2ca102,
+ 0x2c46c4,
+ 0x21a602,
+ 0x200282,
+ 0x11a83,
+ 0x297047,
+ 0x2beb05,
+ 0x20d842,
+ 0x239784,
+ 0x382842,
+ 0x2e3008,
+ 0x208e83,
+ 0x203488,
+ 0x203cc2,
+ 0x223b45,
+ 0x38dbc6,
+ 0x201a03,
+ 0x207082,
+ 0x2f0ac7,
+ 0xcb02,
+ 0x2797c5,
+ 0x358b85,
+ 0x209642,
+ 0x20fd02,
+ 0x2cf9ca,
+ 0x26eeca,
+ 0x21b9c2,
+ 0x2a4dc4,
+ 0x2002c2,
+ 0x3b4ec8,
+ 0x20d582,
+ 0x315b08,
+ 0x30ab47,
+ 0x30ba09,
+ 0x203442,
+ 0x310e45,
+ 0x3044c5,
+ 0x21770b,
+ 0x2d054c,
+ 0x237348,
+ 0x321b08,
+ 0x232ec2,
+ 0x208a02,
+ 0x207102,
+ 0x16fb88,
+ 0x20f882,
+ 0x238543,
+ 0x207b02,
+ 0x204d42,
+ 0xe03,
+ 0x200442,
+ 0x201a03,
+ 0x20d2c2,
+ 0x207102,
+ 0x68a0f882,
+ 0x68f23043,
+ 0x211a83,
+ 0x204a82,
+ 0x208e83,
+ 0x391783,
+ 0x201a03,
+ 0x2ef783,
+ 0x37f186,
+ 0x1615443,
+ 0x16fb88,
+ 0x11205,
+ 0xae90d,
+ 0xacc8a,
+ 0x6e487,
+ 0x69601e02,
+ 0x69a00242,
+ 0x69e00bc2,
+ 0x6a200702,
+ 0x6a60b5c2,
+ 0x6aa01382,
+ 0x36dc7,
+ 0x6ae0f882,
+ 0x6b20c8c2,
+ 0x6b604842,
+ 0x6ba04c82,
+ 0x2213c3,
+ 0x18ec4,
+ 0x2298c3,
+ 0x6be1d882,
+ 0x6c200182,
+ 0x53c47,
+ 0x6c60a442,
+ 0x6ca00782,
+ 0x6ce01bc2,
+ 0x6d205e82,
+ 0x6d601c82,
+ 0x6da00942,
+ 0xc2845,
+ 0x23ef43,
+ 0x281a04,
+ 0x6de1f502,
+ 0x6e205242,
+ 0x6e603582,
+ 0x17d50b,
+ 0x6ea01fc2,
+ 0x6f253442,
+ 0x6f604a82,
+ 0x6fa0b302,
+ 0x6fe14702,
+ 0x70200802,
+ 0x70614642,
+ 0x70a745c2,
+ 0x70e0ea42,
+ 0x71204802,
+ 0x71604d42,
+ 0x71a03382,
+ 0x71e08682,
+ 0x7224d382,
+ 0x1a3284,
+ 0x35efc3,
+ 0x72604f82,
+ 0x72a10902,
+ 0x72e11542,
+ 0x73201f02,
+ 0x73600442,
+ 0x73a0cb42,
+ 0x15d647,
+ 0x73e04102,
+ 0x74204142,
+ 0x7460d2c2,
+ 0x74a21382,
+ 0x1ad70c,
+ 0x74e2a202,
+ 0x75245542,
+ 0x75605942,
+ 0x75a06442,
+ 0x75e0c402,
+ 0x76260982,
+ 0x76600202,
+ 0x76a16fc2,
+ 0x76e7d302,
+ 0x772610c2,
+ 0x235f42,
+ 0x3797c3,
+ 0x212143,
+ 0x235f42,
+ 0x3797c3,
+ 0x212143,
+ 0x235f42,
+ 0x3797c3,
+ 0x212143,
+ 0x235f42,
+ 0x3797c3,
+ 0x212143,
+ 0x235f42,
+ 0x3797c3,
+ 0x212143,
+ 0x235f42,
+ 0x3797c3,
+ 0x212143,
+ 0x235f42,
+ 0x3797c3,
+ 0x212143,
+ 0x235f42,
+ 0x3797c3,
+ 0x212143,
+ 0x235f42,
+ 0x3797c3,
+ 0x212143,
+ 0x235f42,
+ 0x3797c3,
+ 0x12143,
+ 0x235f42,
+ 0x3797c3,
+ 0x212143,
+ 0x235f42,
+ 0x3797c3,
+ 0x212143,
+ 0x235f42,
+ 0x3797c3,
+ 0x212143,
+ 0x235f42,
+ 0x212143,
+ 0x235f42,
+ 0x3797c3,
+ 0x212143,
+ 0x235f42,
+ 0x3797c3,
+ 0x212143,
+ 0x235f42,
+ 0x3797c3,
+ 0x212143,
+ 0x235f42,
+ 0x3797c3,
+ 0x212143,
+ 0x235f42,
+ 0x3797c3,
+ 0x212143,
+ 0x235f42,
+ 0x3797c3,
+ 0x212143,
+ 0x235f42,
+ 0x3797c3,
+ 0x212143,
+ 0x235f42,
+ 0x6ef797c3,
+ 0x212143,
+ 0x332244,
+ 0x2f7046,
+ 0x2f9a03,
+ 0x235f42,
+ 0x3797c3,
+ 0x212143,
+ 0x235f42,
+ 0x3797c3,
+ 0x212143,
+ 0x244949,
+ 0x235f42,
+ 0x26c783,
+ 0x2bcec3,
+ 0x20fbc5,
+ 0x2020c3,
+ 0x3797c3,
+ 0x212143,
+ 0x20c0c3,
+ 0x248d43,
+ 0x242989,
+ 0x235f42,
+ 0x3797c3,
+ 0x212143,
+ 0x235f42,
+ 0x3797c3,
+ 0x212143,
+ 0x235f42,
+ 0x3797c3,
+ 0x212143,
+ 0x235f42,
+ 0x3797c3,
+ 0x212143,
+ 0x235f42,
+ 0x3797c3,
+ 0x212143,
+ 0x235f42,
+ 0x212143,
+ 0x235f42,
+ 0x3797c3,
+ 0x212143,
+ 0x235f42,
+ 0x3797c3,
+ 0x212143,
+ 0x235f42,
+ 0x3797c3,
+ 0x212143,
+ 0x235f42,
+ 0x3797c3,
+ 0x212143,
+ 0x235f42,
+ 0x3797c3,
+ 0x212143,
+ 0x235f42,
+ 0x3797c3,
+ 0x212143,
+ 0x235f42,
+ 0x3797c3,
+ 0x212143,
+ 0x235f42,
+ 0x3797c3,
+ 0x212143,
+ 0x235f42,
+ 0x3797c3,
+ 0x212143,
+ 0x235f42,
+ 0x3797c3,
+ 0x212143,
+ 0x235f42,
+ 0x3797c3,
+ 0x212143,
+ 0x235f42,
+ 0x3797c3,
+ 0x212143,
+ 0x235f42,
+ 0x3797c3,
+ 0x212143,
+ 0x235f42,
+ 0x212143,
+ 0x235f42,
+ 0x3797c3,
+ 0x212143,
+ 0x235f42,
+ 0x3797c3,
+ 0x212143,
+ 0x235f42,
+ 0x3797c3,
+ 0x212143,
+ 0x235f42,
+ 0x3797c3,
+ 0x212143,
+ 0x235f42,
+ 0x3797c3,
+ 0x212143,
+ 0x235f42,
+ 0x3797c3,
+ 0x212143,
+ 0x235f42,
+ 0x3797c3,
+ 0x212143,
+ 0x235f42,
+ 0x3797c3,
+ 0x212143,
+ 0x235f42,
+ 0x235f42,
+ 0x3797c3,
+ 0x212143,
+ 0x77a38543,
+ 0x23cac3,
+ 0x20a6c3,
+ 0x28cac3,
+ 0x208e83,
+ 0xe03,
+ 0x201a03,
+ 0x16fb88,
+ 0x20f882,
+ 0x238543,
+ 0x208e83,
+ 0x201a03,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x28cac3,
+ 0x208e83,
+ 0xe03,
+ 0x201a03,
+ 0x252044,
+ 0x20f882,
+ 0x238543,
+ 0x345903,
+ 0x23cac3,
+ 0x253384,
+ 0x21b583,
+ 0x323043,
+ 0x231604,
+ 0x255783,
+ 0x28cac3,
+ 0x208e83,
+ 0x201a03,
+ 0x20c843,
+ 0x355685,
+ 0x248d43,
+ 0x202443,
+ 0xe03,
+ 0x20f882,
+ 0x238543,
+ 0x3797c3,
+ 0x208e83,
+ 0x201a03,
+ 0x207102,
+ 0x39c783,
+ 0x16fb88,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x23a1c6,
+ 0x231604,
+ 0x255783,
+ 0x21bf84,
+ 0x208e83,
+ 0x201a03,
+ 0x221483,
+ 0x238543,
+ 0x23cac3,
+ 0x208e83,
+ 0x201a03,
+ 0x1442047,
+ 0x238543,
+ 0x24386,
+ 0x23cac3,
+ 0x323043,
+ 0xe5586,
+ 0x208e83,
+ 0x201a03,
+ 0x31dc48,
+ 0x321949,
+ 0x330189,
+ 0x33bb08,
+ 0x38fb48,
+ 0x38fb49,
+ 0x24558d,
+ 0x24dd8f,
+ 0x2f53d0,
+ 0x35648d,
+ 0x37210c,
+ 0x39064b,
+ 0xba9c8,
+ 0xac605,
+ 0x207102,
+ 0x342b85,
+ 0x200243,
+ 0x7ae0f882,
+ 0x23cac3,
+ 0x323043,
+ 0x2d8c47,
+ 0x263a43,
+ 0x28cac3,
+ 0x208e83,
+ 0x21b543,
+ 0x217e03,
+ 0x200e03,
+ 0x201a03,
+ 0x3821c6,
+ 0x205082,
+ 0x202443,
+ 0x16fb88,
+ 0x207102,
+ 0x39c783,
+ 0x20f882,
+ 0x238543,
+ 0x23cac3,
+ 0x323043,
+ 0x231604,
+ 0x28cac3,
+ 0x208e83,
+ 0x201a03,
+ 0x215443,
+ 0x106904,
+ 0x15217c6,
+ 0x207102,
+ 0x20f882,
+ 0x323043,
+ 0x28cac3,
+ 0x201a03,
+}
+
+// children is the list of nodes' children, the parent's wildcard bit and the
+// parent's node type. If a node has no children then their children index
+// will be in the range [0, 6), depending on the wildcard bit and node type.
+//
+// The layout within the uint32, from MSB to LSB, is:
+// [ 1 bits] unused
+// [ 1 bits] wildcard bit
+// [ 2 bits] node type
+// [14 bits] high nodes index (exclusive) of children
+// [14 bits] low nodes index (inclusive) of children
+var children = [...]uint32{
+ 0x0,
+ 0x10000000,
+ 0x20000000,
+ 0x40000000,
+ 0x50000000,
+ 0x60000000,
+ 0x186c615,
+ 0x187061b,
+ 0x189461c,
+ 0x19f0625,
+ 0x1a0467c,
+ 0x1a18681,
+ 0x1a2c686,
+ 0x1a4c68b,
+ 0x1a50693,
+ 0x1a68694,
+ 0x1a9069a,
+ 0x1a946a4,
+ 0x1aac6a5,
+ 0x1ab06ab,
+ 0x1ab46ac,
+ 0x1af06ad,
+ 0x1af46bc,
+ 0x21afc6bd,
+ 0x1b446bf,
+ 0x1b486d1,
+ 0x1b686d2,
+ 0x1b7c6da,
+ 0x1b806df,
+ 0x1bb06e0,
+ 0x1bcc6ec,
+ 0x1bf46f3,
+ 0x1c006fd,
+ 0x1c04700,
+ 0x1c9c701,
+ 0x1cb0727,
+ 0x1cc472c,
+ 0x1cf4731,
+ 0x1d0473d,
+ 0x1d18741,
+ 0x1d3c746,
+ 0x1e7474f,
+ 0x1e7879d,
+ 0x1ee479e,
+ 0x1f507b9,
+ 0x1f687d4,
+ 0x1f7c7da,
+ 0x1f847df,
+ 0x1f987e1,
+ 0x1f9c7e6,
+ 0x1fb87e7,
+ 0x20047ee,
+ 0x2020801,
+ 0x2024808,
+ 0x2028809,
+ 0x204480a,
+ 0x2080811,
+ 0x62084820,
+ 0x209c821,
+ 0x20b4827,
+ 0x20b882d,
+ 0x20c882e,
+ 0x2178832,
+ 0x217c85e,
+ 0x2218c85f,
+ 0x22190863,
+ 0x22194864,
+ 0x21cc865,
+ 0x21d0873,
+ 0x2658874,
+ 0x226f8996,
+ 0x226fc9be,
+ 0x227009bf,
+ 0x2270c9c0,
+ 0x227109c3,
+ 0x2271c9c4,
+ 0x227209c7,
+ 0x227249c8,
+ 0x227289c9,
+ 0x2272c9ca,
+ 0x227309cb,
+ 0x2273c9cc,
+ 0x227409cf,
+ 0x2274c9d0,
+ 0x227509d3,
+ 0x227549d4,
+ 0x227589d5,
+ 0x227649d6,
+ 0x227689d9,
+ 0x2276c9da,
+ 0x227709db,
+ 0x27749dc,
+ 0x227789dd,
+ 0x227849de,
+ 0x227889e1,
+ 0x27909e2,
+ 0x27cc9e4,
+ 0x227ec9f3,
+ 0x227f09fb,
+ 0x227f49fc,
+ 0x27f89fd,
+ 0x227fc9fe,
+ 0x28009ff,
+ 0x281ca00,
+ 0x2834a07,
+ 0x2838a0d,
+ 0x2848a0e,
+ 0x2854a12,
+ 0x2888a15,
+ 0x288ca22,
+ 0x28a0a23,
+ 0x228a8a28,
+ 0x2968a2a,
+ 0x2296ca5a,
+ 0x2974a5b,
+ 0x2978a5d,
+ 0x2990a5e,
+ 0x29a4a64,
+ 0x29cca69,
+ 0x29eca73,
+ 0x2a1ca7b,
+ 0x2a44a87,
+ 0x2a48a91,
+ 0x2a6ca92,
+ 0x2a70a9b,
+ 0x2a84a9c,
+ 0x2a88aa1,
+ 0x2a8caa2,
+ 0x2aacaa3,
+ 0x2ac8aab,
+ 0x2accab2,
+ 0x22ad0ab3,
+ 0x2ad4ab4,
+ 0x2ad8ab5,
+ 0x2ae8ab6,
+ 0x2aecaba,
+ 0x2b64abb,
+ 0x2b68ad9,
+ 0x2b84ada,
+ 0x2b94ae1,
+ 0x2ba8ae5,
+ 0x2bc0aea,
+ 0x2bd8af0,
+ 0x2bf0af6,
+ 0x2bf4afc,
+ 0x2c0cafd,
+ 0x2c28b03,
+ 0x2c48b0a,
+ 0x2c60b12,
+ 0x2cc0b18,
+ 0x2cdcb30,
+ 0x2ce4b37,
+ 0x2ce8b39,
+ 0x2cfcb3a,
+ 0x2d40b3f,
+ 0x2dc0b50,
+ 0x2decb70,
+ 0x2df0b7b,
+ 0x2df8b7c,
+ 0x2e18b7e,
+ 0x2e1cb86,
+ 0x2e40b87,
+ 0x2e48b90,
+ 0x2e84b92,
+ 0x2ec8ba1,
+ 0x2eccbb2,
+ 0x2f34bb3,
+ 0x2f38bcd,
+ 0x22f3cbce,
+ 0x22f40bcf,
+ 0x22f50bd0,
+ 0x22f54bd4,
+ 0x22f58bd5,
+ 0x22f5cbd6,
+ 0x22f60bd7,
+ 0x2f78bd8,
+ 0x2f9cbde,
+ 0x2fbcbe7,
+ 0x3580bef,
+ 0x358cd60,
+ 0x35acd63,
+ 0x3768d6b,
+ 0x3838dda,
+ 0x38a8e0e,
+ 0x3900e2a,
+ 0x39e8e40,
+ 0x3a40e7a,
+ 0x3a7ce90,
+ 0x3b78e9f,
+ 0x3c44ede,
+ 0x3cdcf11,
+ 0x3d6cf37,
+ 0x3dd0f5b,
+ 0x4008f74,
+ 0x40c1002,
+ 0x418d030,
+ 0x41d9063,
+ 0x4261076,
+ 0x429d098,
+ 0x42ed0a7,
+ 0x43650bb,
+ 0x643690d9,
+ 0x6436d0da,
+ 0x643710db,
+ 0x43ed0dc,
+ 0x44490fb,
+ 0x44c5112,
+ 0x453d131,
+ 0x45bd14f,
+ 0x462916f,
+ 0x475518a,
+ 0x47ad1d5,
+ 0x647b11eb,
+ 0x48491ec,
+ 0x48d1212,
+ 0x491d234,
+ 0x4985247,
+ 0x4a2d261,
+ 0x4af528b,
+ 0x4b5d2bd,
+ 0x4c712d7,
+ 0x64c7531c,
+ 0x64c7931d,
+ 0x4cd531e,
+ 0x4d31335,
+ 0x4dc134c,
+ 0x4e3d370,
+ 0x4e8138f,
+ 0x4f653a0,
+ 0x4f993d9,
+ 0x4ff93e6,
+ 0x506d3fe,
+ 0x50f541b,
+ 0x513543d,
+ 0x51a544d,
+ 0x651a9469,
+ 0x651ad46a,
+ 0x251b146b,
+ 0x51c946c,
+ 0x51e5472,
+ 0x5229479,
+ 0x523948a,
+ 0x525148e,
+ 0x52c9494,
+ 0x52d14b2,
+ 0x52e54b4,
+ 0x53014b9,
+ 0x532d4c0,
+ 0x53314cb,
+ 0x53394cc,
+ 0x534d4ce,
+ 0x53694d3,
+ 0x53754da,
+ 0x537d4dd,
+ 0x53b94df,
+ 0x53cd4ee,
+ 0x53d54f3,
+ 0x53e14f5,
+ 0x53e94f8,
+ 0x540d4fa,
+ 0x5431503,
+ 0x544950c,
+ 0x544d512,
+ 0x5455513,
+ 0x5459515,
+ 0x54c1516,
+ 0x54c5530,
+ 0x54e9531,
+ 0x550d53a,
+ 0x5529543,
+ 0x553954a,
+ 0x554d54e,
+ 0x5551553,
+ 0x5559554,
+ 0x556d556,
+ 0x557d55b,
+ 0x558155f,
+ 0x559d560,
+ 0x5e2d567,
+ 0x5e6578b,
+ 0x5e91799,
+ 0x5ead7a4,
+ 0x5ecd7ab,
+ 0x5eed7b3,
+ 0x5f317bb,
+ 0x5f397cc,
+ 0x25f3d7ce,
+ 0x25f417cf,
+ 0x5f497d0,
+ 0x60c17d2,
+ 0x260c5830,
+ 0x260d5831,
+ 0x260dd835,
+ 0x260e9837,
+ 0x60ed83a,
+ 0x60f183b,
+ 0x611983c,
+ 0x6141846,
+ 0x6145850,
+ 0x617d851,
+ 0x619985f,
+ 0x6cf1866,
+ 0x6cf5b3c,
+ 0x6cf9b3d,
+ 0x26cfdb3e,
+ 0x6d01b3f,
+ 0x26d05b40,
+ 0x6d09b41,
+ 0x26d15b42,
+ 0x6d19b45,
+ 0x6d1db46,
+ 0x26d21b47,
+ 0x6d25b48,
+ 0x26d2db49,
+ 0x6d31b4b,
+ 0x6d35b4c,
+ 0x26d45b4d,
+ 0x6d49b51,
+ 0x6d4db52,
+ 0x6d51b53,
+ 0x6d55b54,
+ 0x26d59b55,
+ 0x6d5db56,
+ 0x6d61b57,
+ 0x6d65b58,
+ 0x6d69b59,
+ 0x26d71b5a,
+ 0x6d75b5c,
+ 0x6d79b5d,
+ 0x6d7db5e,
+ 0x26d81b5f,
+ 0x6d85b60,
+ 0x26d8db61,
+ 0x26d91b63,
+ 0x6dadb64,
+ 0x6dbdb6b,
+ 0x6e01b6f,
+ 0x6e05b80,
+ 0x6e29b81,
+ 0x6e2db8a,
+ 0x6e31b8b,
+ 0x6fbdb8c,
+ 0x26fc1bef,
+ 0x26fc9bf0,
+ 0x26fcdbf2,
+ 0x26fd1bf3,
+ 0x6fd9bf4,
+ 0x70b5bf6,
+ 0x270b9c2d,
+ 0x70bdc2e,
+ 0x70e9c2f,
+ 0x70edc3a,
+ 0x7111c3b,
+ 0x711dc44,
+ 0x713dc47,
+ 0x7141c4f,
+ 0x7179c50,
+ 0x7411c5e,
+ 0x74cdd04,
+ 0x74e1d33,
+ 0x7515d38,
+ 0x7545d45,
+ 0x7561d51,
+ 0x7589d58,
+ 0x75a9d62,
+ 0x75c5d6a,
+ 0x75edd71,
+ 0x75fdd7b,
+ 0x7601d7f,
+ 0x7605d80,
+ 0x7639d81,
+ 0x7645d8e,
+ 0x7665d91,
+ 0x76ddd99,
+ 0x276e1db7,
+ 0x7705db8,
+ 0x7725dc1,
+ 0x7739dc9,
+ 0x774ddce,
+ 0x7751dd3,
+ 0x7771dd4,
+ 0x7815ddc,
+ 0x7831e05,
+ 0x7855e0c,
+ 0x785de15,
+ 0x7869e17,
+ 0x7871e1a,
+ 0x7885e1c,
+ 0x78a5e21,
+ 0x78b1e29,
+ 0x78bde2c,
+ 0x78ede2f,
+ 0x79c1e3b,
+ 0x79c5e70,
+ 0x79d9e71,
+ 0x79e1e76,
+ 0x79f9e78,
+ 0x79fde7e,
+ 0x7a09e7f,
+ 0x7a0de82,
+ 0x7a29e83,
+ 0x7a65e8a,
+ 0x7a69e99,
+ 0x7a89e9a,
+ 0x7ad9ea2,
+ 0x7af5eb6,
+ 0x7b49ebd,
+ 0x7b4ded2,
+ 0x7b51ed3,
+ 0x7b55ed4,
+ 0x7b99ed5,
+ 0x7ba9ee6,
+ 0x7be9eea,
+ 0x7bedefa,
+ 0x7c1defb,
+ 0x7d65f07,
+ 0x7d8df59,
+ 0x7db9f63,
+ 0x7dc5f6e,
+ 0x7dcdf71,
+ 0x7eddf73,
+ 0x7ee9fb7,
+ 0x7ef5fba,
+ 0x7f01fbd,
+ 0x7f0dfc0,
+ 0x7f19fc3,
+ 0x7f25fc6,
+ 0x7f31fc9,
+ 0x7f3dfcc,
+ 0x7f49fcf,
+ 0x7f55fd2,
+ 0x7f61fd5,
+ 0x7f6dfd8,
+ 0x7f79fdb,
+ 0x7f81fde,
+ 0x7f8dfe0,
+ 0x7f99fe3,
+ 0x7fa5fe6,
+ 0x7fb1fe9,
+ 0x7fbdfec,
+ 0x7fc9fef,
+ 0x7fd5ff2,
+ 0x7fe1ff5,
+ 0x7fedff8,
+ 0x7ff9ffb,
+ 0x8005ffe,
+ 0x8032001,
+ 0x803e00c,
+ 0x804a00f,
+ 0x8056012,
+ 0x8062015,
+ 0x806e018,
+ 0x807601b,
+ 0x808201d,
+ 0x808e020,
+ 0x809a023,
+ 0x80a6026,
+ 0x80b2029,
+ 0x80be02c,
+ 0x80ca02f,
+ 0x80d6032,
+ 0x80e2035,
+ 0x80ee038,
+ 0x80fa03b,
+ 0x810603e,
+ 0x8112041,
+ 0x811a044,
+ 0x8126046,
+ 0x8132049,
+ 0x813e04c,
+ 0x814a04f,
+ 0x8156052,
+ 0x8162055,
+ 0x816e058,
+ 0x817a05b,
+ 0x817e05e,
+ 0x818a05f,
+ 0x81a6062,
+ 0x81aa069,
+ 0x81ba06a,
+ 0x81d606e,
+ 0x821a075,
+ 0x821e086,
+ 0x8232087,
+ 0x826608c,
+ 0x8276099,
+ 0x829609d,
+ 0x82ae0a5,
+ 0x82c60ab,
+ 0x82ce0b1,
+ 0x283120b3,
+ 0x83160c4,
+ 0x83420c5,
+ 0x834a0d0,
+ 0x835e0d2,
+}
+
+// max children 494 (capacity 1023)
+// max text offset 28750 (capacity 32767)
+// max text length 36 (capacity 63)
+// max hi 8407 (capacity 16383)
+// max lo 8402 (capacity 16383)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/publicsuffix/table_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/publicsuffix/table_test.go
new file mode 100644
index 000000000..62610185b
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/publicsuffix/table_test.go
@@ -0,0 +1,16756 @@
+// generated by go run gen.go; DO NOT EDIT
+
+package publicsuffix
+
+var rules = [...]string{
+ "ac",
+ "com.ac",
+ "edu.ac",
+ "gov.ac",
+ "net.ac",
+ "mil.ac",
+ "org.ac",
+ "ad",
+ "nom.ad",
+ "ae",
+ "co.ae",
+ "net.ae",
+ "org.ae",
+ "sch.ae",
+ "ac.ae",
+ "gov.ae",
+ "mil.ae",
+ "aero",
+ "accident-investigation.aero",
+ "accident-prevention.aero",
+ "aerobatic.aero",
+ "aeroclub.aero",
+ "aerodrome.aero",
+ "agents.aero",
+ "aircraft.aero",
+ "airline.aero",
+ "airport.aero",
+ "air-surveillance.aero",
+ "airtraffic.aero",
+ "air-traffic-control.aero",
+ "ambulance.aero",
+ "amusement.aero",
+ "association.aero",
+ "author.aero",
+ "ballooning.aero",
+ "broker.aero",
+ "caa.aero",
+ "cargo.aero",
+ "catering.aero",
+ "certification.aero",
+ "championship.aero",
+ "charter.aero",
+ "civilaviation.aero",
+ "club.aero",
+ "conference.aero",
+ "consultant.aero",
+ "consulting.aero",
+ "control.aero",
+ "council.aero",
+ "crew.aero",
+ "design.aero",
+ "dgca.aero",
+ "educator.aero",
+ "emergency.aero",
+ "engine.aero",
+ "engineer.aero",
+ "entertainment.aero",
+ "equipment.aero",
+ "exchange.aero",
+ "express.aero",
+ "federation.aero",
+ "flight.aero",
+ "freight.aero",
+ "fuel.aero",
+ "gliding.aero",
+ "government.aero",
+ "groundhandling.aero",
+ "group.aero",
+ "hanggliding.aero",
+ "homebuilt.aero",
+ "insurance.aero",
+ "journal.aero",
+ "journalist.aero",
+ "leasing.aero",
+ "logistics.aero",
+ "magazine.aero",
+ "maintenance.aero",
+ "media.aero",
+ "microlight.aero",
+ "modelling.aero",
+ "navigation.aero",
+ "parachuting.aero",
+ "paragliding.aero",
+ "passenger-association.aero",
+ "pilot.aero",
+ "press.aero",
+ "production.aero",
+ "recreation.aero",
+ "repbody.aero",
+ "res.aero",
+ "research.aero",
+ "rotorcraft.aero",
+ "safety.aero",
+ "scientist.aero",
+ "services.aero",
+ "show.aero",
+ "skydiving.aero",
+ "software.aero",
+ "student.aero",
+ "trader.aero",
+ "trading.aero",
+ "trainer.aero",
+ "union.aero",
+ "workinggroup.aero",
+ "works.aero",
+ "af",
+ "gov.af",
+ "com.af",
+ "org.af",
+ "net.af",
+ "edu.af",
+ "ag",
+ "com.ag",
+ "org.ag",
+ "net.ag",
+ "co.ag",
+ "nom.ag",
+ "ai",
+ "off.ai",
+ "com.ai",
+ "net.ai",
+ "org.ai",
+ "al",
+ "com.al",
+ "edu.al",
+ "gov.al",
+ "mil.al",
+ "net.al",
+ "org.al",
+ "am",
+ "ao",
+ "ed.ao",
+ "gv.ao",
+ "og.ao",
+ "co.ao",
+ "pb.ao",
+ "it.ao",
+ "aq",
+ "ar",
+ "com.ar",
+ "edu.ar",
+ "gob.ar",
+ "gov.ar",
+ "int.ar",
+ "mil.ar",
+ "musica.ar",
+ "net.ar",
+ "org.ar",
+ "tur.ar",
+ "arpa",
+ "e164.arpa",
+ "in-addr.arpa",
+ "ip6.arpa",
+ "iris.arpa",
+ "uri.arpa",
+ "urn.arpa",
+ "as",
+ "gov.as",
+ "asia",
+ "at",
+ "ac.at",
+ "co.at",
+ "gv.at",
+ "or.at",
+ "au",
+ "com.au",
+ "net.au",
+ "org.au",
+ "edu.au",
+ "gov.au",
+ "asn.au",
+ "id.au",
+ "info.au",
+ "conf.au",
+ "oz.au",
+ "act.au",
+ "nsw.au",
+ "nt.au",
+ "qld.au",
+ "sa.au",
+ "tas.au",
+ "vic.au",
+ "wa.au",
+ "act.edu.au",
+ "nsw.edu.au",
+ "nt.edu.au",
+ "qld.edu.au",
+ "sa.edu.au",
+ "tas.edu.au",
+ "vic.edu.au",
+ "wa.edu.au",
+ "qld.gov.au",
+ "sa.gov.au",
+ "tas.gov.au",
+ "vic.gov.au",
+ "wa.gov.au",
+ "aw",
+ "com.aw",
+ "ax",
+ "az",
+ "com.az",
+ "net.az",
+ "int.az",
+ "gov.az",
+ "org.az",
+ "edu.az",
+ "info.az",
+ "pp.az",
+ "mil.az",
+ "name.az",
+ "pro.az",
+ "biz.az",
+ "ba",
+ "com.ba",
+ "edu.ba",
+ "gov.ba",
+ "mil.ba",
+ "net.ba",
+ "org.ba",
+ "bb",
+ "biz.bb",
+ "co.bb",
+ "com.bb",
+ "edu.bb",
+ "gov.bb",
+ "info.bb",
+ "net.bb",
+ "org.bb",
+ "store.bb",
+ "tv.bb",
+ "*.bd",
+ "be",
+ "ac.be",
+ "bf",
+ "gov.bf",
+ "bg",
+ "a.bg",
+ "b.bg",
+ "c.bg",
+ "d.bg",
+ "e.bg",
+ "f.bg",
+ "g.bg",
+ "h.bg",
+ "i.bg",
+ "j.bg",
+ "k.bg",
+ "l.bg",
+ "m.bg",
+ "n.bg",
+ "o.bg",
+ "p.bg",
+ "q.bg",
+ "r.bg",
+ "s.bg",
+ "t.bg",
+ "u.bg",
+ "v.bg",
+ "w.bg",
+ "x.bg",
+ "y.bg",
+ "z.bg",
+ "0.bg",
+ "1.bg",
+ "2.bg",
+ "3.bg",
+ "4.bg",
+ "5.bg",
+ "6.bg",
+ "7.bg",
+ "8.bg",
+ "9.bg",
+ "bh",
+ "com.bh",
+ "edu.bh",
+ "net.bh",
+ "org.bh",
+ "gov.bh",
+ "bi",
+ "co.bi",
+ "com.bi",
+ "edu.bi",
+ "or.bi",
+ "org.bi",
+ "biz",
+ "bj",
+ "asso.bj",
+ "barreau.bj",
+ "gouv.bj",
+ "bm",
+ "com.bm",
+ "edu.bm",
+ "gov.bm",
+ "net.bm",
+ "org.bm",
+ "*.bn",
+ "bo",
+ "com.bo",
+ "edu.bo",
+ "gov.bo",
+ "gob.bo",
+ "int.bo",
+ "org.bo",
+ "net.bo",
+ "mil.bo",
+ "tv.bo",
+ "br",
+ "adm.br",
+ "adv.br",
+ "agr.br",
+ "am.br",
+ "arq.br",
+ "art.br",
+ "ato.br",
+ "b.br",
+ "belem.br",
+ "bio.br",
+ "blog.br",
+ "bmd.br",
+ "cim.br",
+ "cng.br",
+ "cnt.br",
+ "com.br",
+ "coop.br",
+ "cri.br",
+ "def.br",
+ "ecn.br",
+ "eco.br",
+ "edu.br",
+ "emp.br",
+ "eng.br",
+ "esp.br",
+ "etc.br",
+ "eti.br",
+ "far.br",
+ "flog.br",
+ "floripa.br",
+ "fm.br",
+ "fnd.br",
+ "fot.br",
+ "fst.br",
+ "g12.br",
+ "ggf.br",
+ "gov.br",
+ "ac.gov.br",
+ "al.gov.br",
+ "am.gov.br",
+ "ap.gov.br",
+ "ba.gov.br",
+ "ce.gov.br",
+ "df.gov.br",
+ "es.gov.br",
+ "go.gov.br",
+ "ma.gov.br",
+ "mg.gov.br",
+ "ms.gov.br",
+ "mt.gov.br",
+ "pa.gov.br",
+ "pb.gov.br",
+ "pe.gov.br",
+ "pi.gov.br",
+ "pr.gov.br",
+ "rj.gov.br",
+ "rn.gov.br",
+ "ro.gov.br",
+ "rr.gov.br",
+ "rs.gov.br",
+ "sc.gov.br",
+ "se.gov.br",
+ "sp.gov.br",
+ "to.gov.br",
+ "imb.br",
+ "ind.br",
+ "inf.br",
+ "jampa.br",
+ "jor.br",
+ "jus.br",
+ "leg.br",
+ "lel.br",
+ "mat.br",
+ "med.br",
+ "mil.br",
+ "mp.br",
+ "mus.br",
+ "net.br",
+ "*.nom.br",
+ "not.br",
+ "ntr.br",
+ "odo.br",
+ "org.br",
+ "poa.br",
+ "ppg.br",
+ "pro.br",
+ "psc.br",
+ "psi.br",
+ "qsl.br",
+ "radio.br",
+ "rec.br",
+ "recife.br",
+ "slg.br",
+ "srv.br",
+ "taxi.br",
+ "teo.br",
+ "tmp.br",
+ "trd.br",
+ "tur.br",
+ "tv.br",
+ "vet.br",
+ "vix.br",
+ "vlog.br",
+ "wiki.br",
+ "zlg.br",
+ "bs",
+ "com.bs",
+ "net.bs",
+ "org.bs",
+ "edu.bs",
+ "gov.bs",
+ "bt",
+ "com.bt",
+ "edu.bt",
+ "gov.bt",
+ "net.bt",
+ "org.bt",
+ "bv",
+ "bw",
+ "co.bw",
+ "org.bw",
+ "by",
+ "gov.by",
+ "mil.by",
+ "com.by",
+ "of.by",
+ "bz",
+ "com.bz",
+ "net.bz",
+ "org.bz",
+ "edu.bz",
+ "gov.bz",
+ "ca",
+ "ab.ca",
+ "bc.ca",
+ "mb.ca",
+ "nb.ca",
+ "nf.ca",
+ "nl.ca",
+ "ns.ca",
+ "nt.ca",
+ "nu.ca",
+ "on.ca",
+ "pe.ca",
+ "qc.ca",
+ "sk.ca",
+ "yk.ca",
+ "gc.ca",
+ "cat",
+ "cc",
+ "cd",
+ "gov.cd",
+ "cf",
+ "cg",
+ "ch",
+ "ci",
+ "org.ci",
+ "or.ci",
+ "com.ci",
+ "co.ci",
+ "edu.ci",
+ "ed.ci",
+ "ac.ci",
+ "net.ci",
+ "go.ci",
+ "asso.ci",
+ "xn--aroport-bya.ci",
+ "int.ci",
+ "presse.ci",
+ "md.ci",
+ "gouv.ci",
+ "*.ck",
+ "!www.ck",
+ "cl",
+ "gov.cl",
+ "gob.cl",
+ "co.cl",
+ "mil.cl",
+ "cm",
+ "co.cm",
+ "com.cm",
+ "gov.cm",
+ "net.cm",
+ "cn",
+ "ac.cn",
+ "com.cn",
+ "edu.cn",
+ "gov.cn",
+ "net.cn",
+ "org.cn",
+ "mil.cn",
+ "xn--55qx5d.cn",
+ "xn--io0a7i.cn",
+ "xn--od0alg.cn",
+ "ah.cn",
+ "bj.cn",
+ "cq.cn",
+ "fj.cn",
+ "gd.cn",
+ "gs.cn",
+ "gz.cn",
+ "gx.cn",
+ "ha.cn",
+ "hb.cn",
+ "he.cn",
+ "hi.cn",
+ "hl.cn",
+ "hn.cn",
+ "jl.cn",
+ "js.cn",
+ "jx.cn",
+ "ln.cn",
+ "nm.cn",
+ "nx.cn",
+ "qh.cn",
+ "sc.cn",
+ "sd.cn",
+ "sh.cn",
+ "sn.cn",
+ "sx.cn",
+ "tj.cn",
+ "xj.cn",
+ "xz.cn",
+ "yn.cn",
+ "zj.cn",
+ "hk.cn",
+ "mo.cn",
+ "tw.cn",
+ "co",
+ "arts.co",
+ "com.co",
+ "edu.co",
+ "firm.co",
+ "gov.co",
+ "info.co",
+ "int.co",
+ "mil.co",
+ "net.co",
+ "nom.co",
+ "org.co",
+ "rec.co",
+ "web.co",
+ "com",
+ "coop",
+ "cr",
+ "ac.cr",
+ "co.cr",
+ "ed.cr",
+ "fi.cr",
+ "go.cr",
+ "or.cr",
+ "sa.cr",
+ "cu",
+ "com.cu",
+ "edu.cu",
+ "org.cu",
+ "net.cu",
+ "gov.cu",
+ "inf.cu",
+ "cv",
+ "cw",
+ "com.cw",
+ "edu.cw",
+ "net.cw",
+ "org.cw",
+ "cx",
+ "gov.cx",
+ "cy",
+ "ac.cy",
+ "biz.cy",
+ "com.cy",
+ "ekloges.cy",
+ "gov.cy",
+ "ltd.cy",
+ "name.cy",
+ "net.cy",
+ "org.cy",
+ "parliament.cy",
+ "press.cy",
+ "pro.cy",
+ "tm.cy",
+ "cz",
+ "de",
+ "dj",
+ "dk",
+ "dm",
+ "com.dm",
+ "net.dm",
+ "org.dm",
+ "edu.dm",
+ "gov.dm",
+ "do",
+ "art.do",
+ "com.do",
+ "edu.do",
+ "gob.do",
+ "gov.do",
+ "mil.do",
+ "net.do",
+ "org.do",
+ "sld.do",
+ "web.do",
+ "dz",
+ "com.dz",
+ "org.dz",
+ "net.dz",
+ "gov.dz",
+ "edu.dz",
+ "asso.dz",
+ "pol.dz",
+ "art.dz",
+ "ec",
+ "com.ec",
+ "info.ec",
+ "net.ec",
+ "fin.ec",
+ "k12.ec",
+ "med.ec",
+ "pro.ec",
+ "org.ec",
+ "edu.ec",
+ "gov.ec",
+ "gob.ec",
+ "mil.ec",
+ "edu",
+ "ee",
+ "edu.ee",
+ "gov.ee",
+ "riik.ee",
+ "lib.ee",
+ "med.ee",
+ "com.ee",
+ "pri.ee",
+ "aip.ee",
+ "org.ee",
+ "fie.ee",
+ "eg",
+ "com.eg",
+ "edu.eg",
+ "eun.eg",
+ "gov.eg",
+ "mil.eg",
+ "name.eg",
+ "net.eg",
+ "org.eg",
+ "sci.eg",
+ "*.er",
+ "es",
+ "com.es",
+ "nom.es",
+ "org.es",
+ "gob.es",
+ "edu.es",
+ "et",
+ "com.et",
+ "gov.et",
+ "org.et",
+ "edu.et",
+ "biz.et",
+ "name.et",
+ "info.et",
+ "net.et",
+ "eu",
+ "fi",
+ "aland.fi",
+ "*.fj",
+ "*.fk",
+ "fm",
+ "fo",
+ "fr",
+ "com.fr",
+ "asso.fr",
+ "nom.fr",
+ "prd.fr",
+ "presse.fr",
+ "tm.fr",
+ "aeroport.fr",
+ "assedic.fr",
+ "avocat.fr",
+ "avoues.fr",
+ "cci.fr",
+ "chambagri.fr",
+ "chirurgiens-dentistes.fr",
+ "experts-comptables.fr",
+ "geometre-expert.fr",
+ "gouv.fr",
+ "greta.fr",
+ "huissier-justice.fr",
+ "medecin.fr",
+ "notaires.fr",
+ "pharmacien.fr",
+ "port.fr",
+ "veterinaire.fr",
+ "ga",
+ "gb",
+ "gd",
+ "ge",
+ "com.ge",
+ "edu.ge",
+ "gov.ge",
+ "org.ge",
+ "mil.ge",
+ "net.ge",
+ "pvt.ge",
+ "gf",
+ "gg",
+ "co.gg",
+ "net.gg",
+ "org.gg",
+ "gh",
+ "com.gh",
+ "edu.gh",
+ "gov.gh",
+ "org.gh",
+ "mil.gh",
+ "gi",
+ "com.gi",
+ "ltd.gi",
+ "gov.gi",
+ "mod.gi",
+ "edu.gi",
+ "org.gi",
+ "gl",
+ "co.gl",
+ "com.gl",
+ "edu.gl",
+ "net.gl",
+ "org.gl",
+ "gm",
+ "gn",
+ "ac.gn",
+ "com.gn",
+ "edu.gn",
+ "gov.gn",
+ "org.gn",
+ "net.gn",
+ "gov",
+ "gp",
+ "com.gp",
+ "net.gp",
+ "mobi.gp",
+ "edu.gp",
+ "org.gp",
+ "asso.gp",
+ "gq",
+ "gr",
+ "com.gr",
+ "edu.gr",
+ "net.gr",
+ "org.gr",
+ "gov.gr",
+ "gs",
+ "gt",
+ "com.gt",
+ "edu.gt",
+ "gob.gt",
+ "ind.gt",
+ "mil.gt",
+ "net.gt",
+ "org.gt",
+ "*.gu",
+ "gw",
+ "gy",
+ "co.gy",
+ "com.gy",
+ "edu.gy",
+ "gov.gy",
+ "net.gy",
+ "org.gy",
+ "hk",
+ "com.hk",
+ "edu.hk",
+ "gov.hk",
+ "idv.hk",
+ "net.hk",
+ "org.hk",
+ "xn--55qx5d.hk",
+ "xn--wcvs22d.hk",
+ "xn--lcvr32d.hk",
+ "xn--mxtq1m.hk",
+ "xn--gmqw5a.hk",
+ "xn--ciqpn.hk",
+ "xn--gmq050i.hk",
+ "xn--zf0avx.hk",
+ "xn--io0a7i.hk",
+ "xn--mk0axi.hk",
+ "xn--od0alg.hk",
+ "xn--od0aq3b.hk",
+ "xn--tn0ag.hk",
+ "xn--uc0atv.hk",
+ "xn--uc0ay4a.hk",
+ "hm",
+ "hn",
+ "com.hn",
+ "edu.hn",
+ "org.hn",
+ "net.hn",
+ "mil.hn",
+ "gob.hn",
+ "hr",
+ "iz.hr",
+ "from.hr",
+ "name.hr",
+ "com.hr",
+ "ht",
+ "com.ht",
+ "shop.ht",
+ "firm.ht",
+ "info.ht",
+ "adult.ht",
+ "net.ht",
+ "pro.ht",
+ "org.ht",
+ "med.ht",
+ "art.ht",
+ "coop.ht",
+ "pol.ht",
+ "asso.ht",
+ "edu.ht",
+ "rel.ht",
+ "gouv.ht",
+ "perso.ht",
+ "hu",
+ "co.hu",
+ "info.hu",
+ "org.hu",
+ "priv.hu",
+ "sport.hu",
+ "tm.hu",
+ "2000.hu",
+ "agrar.hu",
+ "bolt.hu",
+ "casino.hu",
+ "city.hu",
+ "erotica.hu",
+ "erotika.hu",
+ "film.hu",
+ "forum.hu",
+ "games.hu",
+ "hotel.hu",
+ "ingatlan.hu",
+ "jogasz.hu",
+ "konyvelo.hu",
+ "lakas.hu",
+ "media.hu",
+ "news.hu",
+ "reklam.hu",
+ "sex.hu",
+ "shop.hu",
+ "suli.hu",
+ "szex.hu",
+ "tozsde.hu",
+ "utazas.hu",
+ "video.hu",
+ "id",
+ "ac.id",
+ "biz.id",
+ "co.id",
+ "desa.id",
+ "go.id",
+ "mil.id",
+ "my.id",
+ "net.id",
+ "or.id",
+ "sch.id",
+ "web.id",
+ "ie",
+ "gov.ie",
+ "il",
+ "ac.il",
+ "co.il",
+ "gov.il",
+ "idf.il",
+ "k12.il",
+ "muni.il",
+ "net.il",
+ "org.il",
+ "im",
+ "ac.im",
+ "co.im",
+ "com.im",
+ "ltd.co.im",
+ "net.im",
+ "org.im",
+ "plc.co.im",
+ "tt.im",
+ "tv.im",
+ "in",
+ "co.in",
+ "firm.in",
+ "net.in",
+ "org.in",
+ "gen.in",
+ "ind.in",
+ "nic.in",
+ "ac.in",
+ "edu.in",
+ "res.in",
+ "gov.in",
+ "mil.in",
+ "info",
+ "int",
+ "eu.int",
+ "io",
+ "com.io",
+ "iq",
+ "gov.iq",
+ "edu.iq",
+ "mil.iq",
+ "com.iq",
+ "org.iq",
+ "net.iq",
+ "ir",
+ "ac.ir",
+ "co.ir",
+ "gov.ir",
+ "id.ir",
+ "net.ir",
+ "org.ir",
+ "sch.ir",
+ "xn--mgba3a4f16a.ir",
+ "xn--mgba3a4fra.ir",
+ "is",
+ "net.is",
+ "com.is",
+ "edu.is",
+ "gov.is",
+ "org.is",
+ "int.is",
+ "it",
+ "gov.it",
+ "edu.it",
+ "abr.it",
+ "abruzzo.it",
+ "aosta-valley.it",
+ "aostavalley.it",
+ "bas.it",
+ "basilicata.it",
+ "cal.it",
+ "calabria.it",
+ "cam.it",
+ "campania.it",
+ "emilia-romagna.it",
+ "emiliaromagna.it",
+ "emr.it",
+ "friuli-v-giulia.it",
+ "friuli-ve-giulia.it",
+ "friuli-vegiulia.it",
+ "friuli-venezia-giulia.it",
+ "friuli-veneziagiulia.it",
+ "friuli-vgiulia.it",
+ "friuliv-giulia.it",
+ "friulive-giulia.it",
+ "friulivegiulia.it",
+ "friulivenezia-giulia.it",
+ "friuliveneziagiulia.it",
+ "friulivgiulia.it",
+ "fvg.it",
+ "laz.it",
+ "lazio.it",
+ "lig.it",
+ "liguria.it",
+ "lom.it",
+ "lombardia.it",
+ "lombardy.it",
+ "lucania.it",
+ "mar.it",
+ "marche.it",
+ "mol.it",
+ "molise.it",
+ "piedmont.it",
+ "piemonte.it",
+ "pmn.it",
+ "pug.it",
+ "puglia.it",
+ "sar.it",
+ "sardegna.it",
+ "sardinia.it",
+ "sic.it",
+ "sicilia.it",
+ "sicily.it",
+ "taa.it",
+ "tos.it",
+ "toscana.it",
+ "trentino-a-adige.it",
+ "trentino-aadige.it",
+ "trentino-alto-adige.it",
+ "trentino-altoadige.it",
+ "trentino-s-tirol.it",
+ "trentino-stirol.it",
+ "trentino-sud-tirol.it",
+ "trentino-sudtirol.it",
+ "trentino-sued-tirol.it",
+ "trentino-suedtirol.it",
+ "trentinoa-adige.it",
+ "trentinoaadige.it",
+ "trentinoalto-adige.it",
+ "trentinoaltoadige.it",
+ "trentinos-tirol.it",
+ "trentinostirol.it",
+ "trentinosud-tirol.it",
+ "trentinosudtirol.it",
+ "trentinosued-tirol.it",
+ "trentinosuedtirol.it",
+ "tuscany.it",
+ "umb.it",
+ "umbria.it",
+ "val-d-aosta.it",
+ "val-daosta.it",
+ "vald-aosta.it",
+ "valdaosta.it",
+ "valle-aosta.it",
+ "valle-d-aosta.it",
+ "valle-daosta.it",
+ "valleaosta.it",
+ "valled-aosta.it",
+ "valledaosta.it",
+ "vallee-aoste.it",
+ "valleeaoste.it",
+ "vao.it",
+ "vda.it",
+ "ven.it",
+ "veneto.it",
+ "ag.it",
+ "agrigento.it",
+ "al.it",
+ "alessandria.it",
+ "alto-adige.it",
+ "altoadige.it",
+ "an.it",
+ "ancona.it",
+ "andria-barletta-trani.it",
+ "andria-trani-barletta.it",
+ "andriabarlettatrani.it",
+ "andriatranibarletta.it",
+ "ao.it",
+ "aosta.it",
+ "aoste.it",
+ "ap.it",
+ "aq.it",
+ "aquila.it",
+ "ar.it",
+ "arezzo.it",
+ "ascoli-piceno.it",
+ "ascolipiceno.it",
+ "asti.it",
+ "at.it",
+ "av.it",
+ "avellino.it",
+ "ba.it",
+ "balsan.it",
+ "bari.it",
+ "barletta-trani-andria.it",
+ "barlettatraniandria.it",
+ "belluno.it",
+ "benevento.it",
+ "bergamo.it",
+ "bg.it",
+ "bi.it",
+ "biella.it",
+ "bl.it",
+ "bn.it",
+ "bo.it",
+ "bologna.it",
+ "bolzano.it",
+ "bozen.it",
+ "br.it",
+ "brescia.it",
+ "brindisi.it",
+ "bs.it",
+ "bt.it",
+ "bz.it",
+ "ca.it",
+ "cagliari.it",
+ "caltanissetta.it",
+ "campidano-medio.it",
+ "campidanomedio.it",
+ "campobasso.it",
+ "carbonia-iglesias.it",
+ "carboniaiglesias.it",
+ "carrara-massa.it",
+ "carraramassa.it",
+ "caserta.it",
+ "catania.it",
+ "catanzaro.it",
+ "cb.it",
+ "ce.it",
+ "cesena-forli.it",
+ "cesenaforli.it",
+ "ch.it",
+ "chieti.it",
+ "ci.it",
+ "cl.it",
+ "cn.it",
+ "co.it",
+ "como.it",
+ "cosenza.it",
+ "cr.it",
+ "cremona.it",
+ "crotone.it",
+ "cs.it",
+ "ct.it",
+ "cuneo.it",
+ "cz.it",
+ "dell-ogliastra.it",
+ "dellogliastra.it",
+ "en.it",
+ "enna.it",
+ "fc.it",
+ "fe.it",
+ "fermo.it",
+ "ferrara.it",
+ "fg.it",
+ "fi.it",
+ "firenze.it",
+ "florence.it",
+ "fm.it",
+ "foggia.it",
+ "forli-cesena.it",
+ "forlicesena.it",
+ "fr.it",
+ "frosinone.it",
+ "ge.it",
+ "genoa.it",
+ "genova.it",
+ "go.it",
+ "gorizia.it",
+ "gr.it",
+ "grosseto.it",
+ "iglesias-carbonia.it",
+ "iglesiascarbonia.it",
+ "im.it",
+ "imperia.it",
+ "is.it",
+ "isernia.it",
+ "kr.it",
+ "la-spezia.it",
+ "laquila.it",
+ "laspezia.it",
+ "latina.it",
+ "lc.it",
+ "le.it",
+ "lecce.it",
+ "lecco.it",
+ "li.it",
+ "livorno.it",
+ "lo.it",
+ "lodi.it",
+ "lt.it",
+ "lu.it",
+ "lucca.it",
+ "macerata.it",
+ "mantova.it",
+ "massa-carrara.it",
+ "massacarrara.it",
+ "matera.it",
+ "mb.it",
+ "mc.it",
+ "me.it",
+ "medio-campidano.it",
+ "mediocampidano.it",
+ "messina.it",
+ "mi.it",
+ "milan.it",
+ "milano.it",
+ "mn.it",
+ "mo.it",
+ "modena.it",
+ "monza-brianza.it",
+ "monza-e-della-brianza.it",
+ "monza.it",
+ "monzabrianza.it",
+ "monzaebrianza.it",
+ "monzaedellabrianza.it",
+ "ms.it",
+ "mt.it",
+ "na.it",
+ "naples.it",
+ "napoli.it",
+ "no.it",
+ "novara.it",
+ "nu.it",
+ "nuoro.it",
+ "og.it",
+ "ogliastra.it",
+ "olbia-tempio.it",
+ "olbiatempio.it",
+ "or.it",
+ "oristano.it",
+ "ot.it",
+ "pa.it",
+ "padova.it",
+ "padua.it",
+ "palermo.it",
+ "parma.it",
+ "pavia.it",
+ "pc.it",
+ "pd.it",
+ "pe.it",
+ "perugia.it",
+ "pesaro-urbino.it",
+ "pesarourbino.it",
+ "pescara.it",
+ "pg.it",
+ "pi.it",
+ "piacenza.it",
+ "pisa.it",
+ "pistoia.it",
+ "pn.it",
+ "po.it",
+ "pordenone.it",
+ "potenza.it",
+ "pr.it",
+ "prato.it",
+ "pt.it",
+ "pu.it",
+ "pv.it",
+ "pz.it",
+ "ra.it",
+ "ragusa.it",
+ "ravenna.it",
+ "rc.it",
+ "re.it",
+ "reggio-calabria.it",
+ "reggio-emilia.it",
+ "reggiocalabria.it",
+ "reggioemilia.it",
+ "rg.it",
+ "ri.it",
+ "rieti.it",
+ "rimini.it",
+ "rm.it",
+ "rn.it",
+ "ro.it",
+ "roma.it",
+ "rome.it",
+ "rovigo.it",
+ "sa.it",
+ "salerno.it",
+ "sassari.it",
+ "savona.it",
+ "si.it",
+ "siena.it",
+ "siracusa.it",
+ "so.it",
+ "sondrio.it",
+ "sp.it",
+ "sr.it",
+ "ss.it",
+ "suedtirol.it",
+ "sv.it",
+ "ta.it",
+ "taranto.it",
+ "te.it",
+ "tempio-olbia.it",
+ "tempioolbia.it",
+ "teramo.it",
+ "terni.it",
+ "tn.it",
+ "to.it",
+ "torino.it",
+ "tp.it",
+ "tr.it",
+ "trani-andria-barletta.it",
+ "trani-barletta-andria.it",
+ "traniandriabarletta.it",
+ "tranibarlettaandria.it",
+ "trapani.it",
+ "trentino.it",
+ "trento.it",
+ "treviso.it",
+ "trieste.it",
+ "ts.it",
+ "turin.it",
+ "tv.it",
+ "ud.it",
+ "udine.it",
+ "urbino-pesaro.it",
+ "urbinopesaro.it",
+ "va.it",
+ "varese.it",
+ "vb.it",
+ "vc.it",
+ "ve.it",
+ "venezia.it",
+ "venice.it",
+ "verbania.it",
+ "vercelli.it",
+ "verona.it",
+ "vi.it",
+ "vibo-valentia.it",
+ "vibovalentia.it",
+ "vicenza.it",
+ "viterbo.it",
+ "vr.it",
+ "vs.it",
+ "vt.it",
+ "vv.it",
+ "je",
+ "co.je",
+ "net.je",
+ "org.je",
+ "*.jm",
+ "jo",
+ "com.jo",
+ "org.jo",
+ "net.jo",
+ "edu.jo",
+ "sch.jo",
+ "gov.jo",
+ "mil.jo",
+ "name.jo",
+ "jobs",
+ "jp",
+ "ac.jp",
+ "ad.jp",
+ "co.jp",
+ "ed.jp",
+ "go.jp",
+ "gr.jp",
+ "lg.jp",
+ "ne.jp",
+ "or.jp",
+ "aichi.jp",
+ "akita.jp",
+ "aomori.jp",
+ "chiba.jp",
+ "ehime.jp",
+ "fukui.jp",
+ "fukuoka.jp",
+ "fukushima.jp",
+ "gifu.jp",
+ "gunma.jp",
+ "hiroshima.jp",
+ "hokkaido.jp",
+ "hyogo.jp",
+ "ibaraki.jp",
+ "ishikawa.jp",
+ "iwate.jp",
+ "kagawa.jp",
+ "kagoshima.jp",
+ "kanagawa.jp",
+ "kochi.jp",
+ "kumamoto.jp",
+ "kyoto.jp",
+ "mie.jp",
+ "miyagi.jp",
+ "miyazaki.jp",
+ "nagano.jp",
+ "nagasaki.jp",
+ "nara.jp",
+ "niigata.jp",
+ "oita.jp",
+ "okayama.jp",
+ "okinawa.jp",
+ "osaka.jp",
+ "saga.jp",
+ "saitama.jp",
+ "shiga.jp",
+ "shimane.jp",
+ "shizuoka.jp",
+ "tochigi.jp",
+ "tokushima.jp",
+ "tokyo.jp",
+ "tottori.jp",
+ "toyama.jp",
+ "wakayama.jp",
+ "yamagata.jp",
+ "yamaguchi.jp",
+ "yamanashi.jp",
+ "xn--4pvxs.jp",
+ "xn--vgu402c.jp",
+ "xn--c3s14m.jp",
+ "xn--f6qx53a.jp",
+ "xn--8pvr4u.jp",
+ "xn--uist22h.jp",
+ "xn--djrs72d6uy.jp",
+ "xn--mkru45i.jp",
+ "xn--0trq7p7nn.jp",
+ "xn--8ltr62k.jp",
+ "xn--2m4a15e.jp",
+ "xn--efvn9s.jp",
+ "xn--32vp30h.jp",
+ "xn--4it797k.jp",
+ "xn--1lqs71d.jp",
+ "xn--5rtp49c.jp",
+ "xn--5js045d.jp",
+ "xn--ehqz56n.jp",
+ "xn--1lqs03n.jp",
+ "xn--qqqt11m.jp",
+ "xn--kbrq7o.jp",
+ "xn--pssu33l.jp",
+ "xn--ntsq17g.jp",
+ "xn--uisz3g.jp",
+ "xn--6btw5a.jp",
+ "xn--1ctwo.jp",
+ "xn--6orx2r.jp",
+ "xn--rht61e.jp",
+ "xn--rht27z.jp",
+ "xn--djty4k.jp",
+ "xn--nit225k.jp",
+ "xn--rht3d.jp",
+ "xn--klty5x.jp",
+ "xn--kltx9a.jp",
+ "xn--kltp7d.jp",
+ "xn--uuwu58a.jp",
+ "xn--zbx025d.jp",
+ "xn--ntso0iqx3a.jp",
+ "xn--elqq16h.jp",
+ "xn--4it168d.jp",
+ "xn--klt787d.jp",
+ "xn--rny31h.jp",
+ "xn--7t0a264c.jp",
+ "xn--5rtq34k.jp",
+ "xn--k7yn95e.jp",
+ "xn--tor131o.jp",
+ "xn--d5qv7z876c.jp",
+ "*.kawasaki.jp",
+ "*.kitakyushu.jp",
+ "*.kobe.jp",
+ "*.nagoya.jp",
+ "*.sapporo.jp",
+ "*.sendai.jp",
+ "*.yokohama.jp",
+ "!city.kawasaki.jp",
+ "!city.kitakyushu.jp",
+ "!city.kobe.jp",
+ "!city.nagoya.jp",
+ "!city.sapporo.jp",
+ "!city.sendai.jp",
+ "!city.yokohama.jp",
+ "aisai.aichi.jp",
+ "ama.aichi.jp",
+ "anjo.aichi.jp",
+ "asuke.aichi.jp",
+ "chiryu.aichi.jp",
+ "chita.aichi.jp",
+ "fuso.aichi.jp",
+ "gamagori.aichi.jp",
+ "handa.aichi.jp",
+ "hazu.aichi.jp",
+ "hekinan.aichi.jp",
+ "higashiura.aichi.jp",
+ "ichinomiya.aichi.jp",
+ "inazawa.aichi.jp",
+ "inuyama.aichi.jp",
+ "isshiki.aichi.jp",
+ "iwakura.aichi.jp",
+ "kanie.aichi.jp",
+ "kariya.aichi.jp",
+ "kasugai.aichi.jp",
+ "kira.aichi.jp",
+ "kiyosu.aichi.jp",
+ "komaki.aichi.jp",
+ "konan.aichi.jp",
+ "kota.aichi.jp",
+ "mihama.aichi.jp",
+ "miyoshi.aichi.jp",
+ "nishio.aichi.jp",
+ "nisshin.aichi.jp",
+ "obu.aichi.jp",
+ "oguchi.aichi.jp",
+ "oharu.aichi.jp",
+ "okazaki.aichi.jp",
+ "owariasahi.aichi.jp",
+ "seto.aichi.jp",
+ "shikatsu.aichi.jp",
+ "shinshiro.aichi.jp",
+ "shitara.aichi.jp",
+ "tahara.aichi.jp",
+ "takahama.aichi.jp",
+ "tobishima.aichi.jp",
+ "toei.aichi.jp",
+ "togo.aichi.jp",
+ "tokai.aichi.jp",
+ "tokoname.aichi.jp",
+ "toyoake.aichi.jp",
+ "toyohashi.aichi.jp",
+ "toyokawa.aichi.jp",
+ "toyone.aichi.jp",
+ "toyota.aichi.jp",
+ "tsushima.aichi.jp",
+ "yatomi.aichi.jp",
+ "akita.akita.jp",
+ "daisen.akita.jp",
+ "fujisato.akita.jp",
+ "gojome.akita.jp",
+ "hachirogata.akita.jp",
+ "happou.akita.jp",
+ "higashinaruse.akita.jp",
+ "honjo.akita.jp",
+ "honjyo.akita.jp",
+ "ikawa.akita.jp",
+ "kamikoani.akita.jp",
+ "kamioka.akita.jp",
+ "katagami.akita.jp",
+ "kazuno.akita.jp",
+ "kitaakita.akita.jp",
+ "kosaka.akita.jp",
+ "kyowa.akita.jp",
+ "misato.akita.jp",
+ "mitane.akita.jp",
+ "moriyoshi.akita.jp",
+ "nikaho.akita.jp",
+ "noshiro.akita.jp",
+ "odate.akita.jp",
+ "oga.akita.jp",
+ "ogata.akita.jp",
+ "semboku.akita.jp",
+ "yokote.akita.jp",
+ "yurihonjo.akita.jp",
+ "aomori.aomori.jp",
+ "gonohe.aomori.jp",
+ "hachinohe.aomori.jp",
+ "hashikami.aomori.jp",
+ "hiranai.aomori.jp",
+ "hirosaki.aomori.jp",
+ "itayanagi.aomori.jp",
+ "kuroishi.aomori.jp",
+ "misawa.aomori.jp",
+ "mutsu.aomori.jp",
+ "nakadomari.aomori.jp",
+ "noheji.aomori.jp",
+ "oirase.aomori.jp",
+ "owani.aomori.jp",
+ "rokunohe.aomori.jp",
+ "sannohe.aomori.jp",
+ "shichinohe.aomori.jp",
+ "shingo.aomori.jp",
+ "takko.aomori.jp",
+ "towada.aomori.jp",
+ "tsugaru.aomori.jp",
+ "tsuruta.aomori.jp",
+ "abiko.chiba.jp",
+ "asahi.chiba.jp",
+ "chonan.chiba.jp",
+ "chosei.chiba.jp",
+ "choshi.chiba.jp",
+ "chuo.chiba.jp",
+ "funabashi.chiba.jp",
+ "futtsu.chiba.jp",
+ "hanamigawa.chiba.jp",
+ "ichihara.chiba.jp",
+ "ichikawa.chiba.jp",
+ "ichinomiya.chiba.jp",
+ "inzai.chiba.jp",
+ "isumi.chiba.jp",
+ "kamagaya.chiba.jp",
+ "kamogawa.chiba.jp",
+ "kashiwa.chiba.jp",
+ "katori.chiba.jp",
+ "katsuura.chiba.jp",
+ "kimitsu.chiba.jp",
+ "kisarazu.chiba.jp",
+ "kozaki.chiba.jp",
+ "kujukuri.chiba.jp",
+ "kyonan.chiba.jp",
+ "matsudo.chiba.jp",
+ "midori.chiba.jp",
+ "mihama.chiba.jp",
+ "minamiboso.chiba.jp",
+ "mobara.chiba.jp",
+ "mutsuzawa.chiba.jp",
+ "nagara.chiba.jp",
+ "nagareyama.chiba.jp",
+ "narashino.chiba.jp",
+ "narita.chiba.jp",
+ "noda.chiba.jp",
+ "oamishirasato.chiba.jp",
+ "omigawa.chiba.jp",
+ "onjuku.chiba.jp",
+ "otaki.chiba.jp",
+ "sakae.chiba.jp",
+ "sakura.chiba.jp",
+ "shimofusa.chiba.jp",
+ "shirako.chiba.jp",
+ "shiroi.chiba.jp",
+ "shisui.chiba.jp",
+ "sodegaura.chiba.jp",
+ "sosa.chiba.jp",
+ "tako.chiba.jp",
+ "tateyama.chiba.jp",
+ "togane.chiba.jp",
+ "tohnosho.chiba.jp",
+ "tomisato.chiba.jp",
+ "urayasu.chiba.jp",
+ "yachimata.chiba.jp",
+ "yachiyo.chiba.jp",
+ "yokaichiba.chiba.jp",
+ "yokoshibahikari.chiba.jp",
+ "yotsukaido.chiba.jp",
+ "ainan.ehime.jp",
+ "honai.ehime.jp",
+ "ikata.ehime.jp",
+ "imabari.ehime.jp",
+ "iyo.ehime.jp",
+ "kamijima.ehime.jp",
+ "kihoku.ehime.jp",
+ "kumakogen.ehime.jp",
+ "masaki.ehime.jp",
+ "matsuno.ehime.jp",
+ "matsuyama.ehime.jp",
+ "namikata.ehime.jp",
+ "niihama.ehime.jp",
+ "ozu.ehime.jp",
+ "saijo.ehime.jp",
+ "seiyo.ehime.jp",
+ "shikokuchuo.ehime.jp",
+ "tobe.ehime.jp",
+ "toon.ehime.jp",
+ "uchiko.ehime.jp",
+ "uwajima.ehime.jp",
+ "yawatahama.ehime.jp",
+ "echizen.fukui.jp",
+ "eiheiji.fukui.jp",
+ "fukui.fukui.jp",
+ "ikeda.fukui.jp",
+ "katsuyama.fukui.jp",
+ "mihama.fukui.jp",
+ "minamiechizen.fukui.jp",
+ "obama.fukui.jp",
+ "ohi.fukui.jp",
+ "ono.fukui.jp",
+ "sabae.fukui.jp",
+ "sakai.fukui.jp",
+ "takahama.fukui.jp",
+ "tsuruga.fukui.jp",
+ "wakasa.fukui.jp",
+ "ashiya.fukuoka.jp",
+ "buzen.fukuoka.jp",
+ "chikugo.fukuoka.jp",
+ "chikuho.fukuoka.jp",
+ "chikujo.fukuoka.jp",
+ "chikushino.fukuoka.jp",
+ "chikuzen.fukuoka.jp",
+ "chuo.fukuoka.jp",
+ "dazaifu.fukuoka.jp",
+ "fukuchi.fukuoka.jp",
+ "hakata.fukuoka.jp",
+ "higashi.fukuoka.jp",
+ "hirokawa.fukuoka.jp",
+ "hisayama.fukuoka.jp",
+ "iizuka.fukuoka.jp",
+ "inatsuki.fukuoka.jp",
+ "kaho.fukuoka.jp",
+ "kasuga.fukuoka.jp",
+ "kasuya.fukuoka.jp",
+ "kawara.fukuoka.jp",
+ "keisen.fukuoka.jp",
+ "koga.fukuoka.jp",
+ "kurate.fukuoka.jp",
+ "kurogi.fukuoka.jp",
+ "kurume.fukuoka.jp",
+ "minami.fukuoka.jp",
+ "miyako.fukuoka.jp",
+ "miyama.fukuoka.jp",
+ "miyawaka.fukuoka.jp",
+ "mizumaki.fukuoka.jp",
+ "munakata.fukuoka.jp",
+ "nakagawa.fukuoka.jp",
+ "nakama.fukuoka.jp",
+ "nishi.fukuoka.jp",
+ "nogata.fukuoka.jp",
+ "ogori.fukuoka.jp",
+ "okagaki.fukuoka.jp",
+ "okawa.fukuoka.jp",
+ "oki.fukuoka.jp",
+ "omuta.fukuoka.jp",
+ "onga.fukuoka.jp",
+ "onojo.fukuoka.jp",
+ "oto.fukuoka.jp",
+ "saigawa.fukuoka.jp",
+ "sasaguri.fukuoka.jp",
+ "shingu.fukuoka.jp",
+ "shinyoshitomi.fukuoka.jp",
+ "shonai.fukuoka.jp",
+ "soeda.fukuoka.jp",
+ "sue.fukuoka.jp",
+ "tachiarai.fukuoka.jp",
+ "tagawa.fukuoka.jp",
+ "takata.fukuoka.jp",
+ "toho.fukuoka.jp",
+ "toyotsu.fukuoka.jp",
+ "tsuiki.fukuoka.jp",
+ "ukiha.fukuoka.jp",
+ "umi.fukuoka.jp",
+ "usui.fukuoka.jp",
+ "yamada.fukuoka.jp",
+ "yame.fukuoka.jp",
+ "yanagawa.fukuoka.jp",
+ "yukuhashi.fukuoka.jp",
+ "aizubange.fukushima.jp",
+ "aizumisato.fukushima.jp",
+ "aizuwakamatsu.fukushima.jp",
+ "asakawa.fukushima.jp",
+ "bandai.fukushima.jp",
+ "date.fukushima.jp",
+ "fukushima.fukushima.jp",
+ "furudono.fukushima.jp",
+ "futaba.fukushima.jp",
+ "hanawa.fukushima.jp",
+ "higashi.fukushima.jp",
+ "hirata.fukushima.jp",
+ "hirono.fukushima.jp",
+ "iitate.fukushima.jp",
+ "inawashiro.fukushima.jp",
+ "ishikawa.fukushima.jp",
+ "iwaki.fukushima.jp",
+ "izumizaki.fukushima.jp",
+ "kagamiishi.fukushima.jp",
+ "kaneyama.fukushima.jp",
+ "kawamata.fukushima.jp",
+ "kitakata.fukushima.jp",
+ "kitashiobara.fukushima.jp",
+ "koori.fukushima.jp",
+ "koriyama.fukushima.jp",
+ "kunimi.fukushima.jp",
+ "miharu.fukushima.jp",
+ "mishima.fukushima.jp",
+ "namie.fukushima.jp",
+ "nango.fukushima.jp",
+ "nishiaizu.fukushima.jp",
+ "nishigo.fukushima.jp",
+ "okuma.fukushima.jp",
+ "omotego.fukushima.jp",
+ "ono.fukushima.jp",
+ "otama.fukushima.jp",
+ "samegawa.fukushima.jp",
+ "shimogo.fukushima.jp",
+ "shirakawa.fukushima.jp",
+ "showa.fukushima.jp",
+ "soma.fukushima.jp",
+ "sukagawa.fukushima.jp",
+ "taishin.fukushima.jp",
+ "tamakawa.fukushima.jp",
+ "tanagura.fukushima.jp",
+ "tenei.fukushima.jp",
+ "yabuki.fukushima.jp",
+ "yamato.fukushima.jp",
+ "yamatsuri.fukushima.jp",
+ "yanaizu.fukushima.jp",
+ "yugawa.fukushima.jp",
+ "anpachi.gifu.jp",
+ "ena.gifu.jp",
+ "gifu.gifu.jp",
+ "ginan.gifu.jp",
+ "godo.gifu.jp",
+ "gujo.gifu.jp",
+ "hashima.gifu.jp",
+ "hichiso.gifu.jp",
+ "hida.gifu.jp",
+ "higashishirakawa.gifu.jp",
+ "ibigawa.gifu.jp",
+ "ikeda.gifu.jp",
+ "kakamigahara.gifu.jp",
+ "kani.gifu.jp",
+ "kasahara.gifu.jp",
+ "kasamatsu.gifu.jp",
+ "kawaue.gifu.jp",
+ "kitagata.gifu.jp",
+ "mino.gifu.jp",
+ "minokamo.gifu.jp",
+ "mitake.gifu.jp",
+ "mizunami.gifu.jp",
+ "motosu.gifu.jp",
+ "nakatsugawa.gifu.jp",
+ "ogaki.gifu.jp",
+ "sakahogi.gifu.jp",
+ "seki.gifu.jp",
+ "sekigahara.gifu.jp",
+ "shirakawa.gifu.jp",
+ "tajimi.gifu.jp",
+ "takayama.gifu.jp",
+ "tarui.gifu.jp",
+ "toki.gifu.jp",
+ "tomika.gifu.jp",
+ "wanouchi.gifu.jp",
+ "yamagata.gifu.jp",
+ "yaotsu.gifu.jp",
+ "yoro.gifu.jp",
+ "annaka.gunma.jp",
+ "chiyoda.gunma.jp",
+ "fujioka.gunma.jp",
+ "higashiagatsuma.gunma.jp",
+ "isesaki.gunma.jp",
+ "itakura.gunma.jp",
+ "kanna.gunma.jp",
+ "kanra.gunma.jp",
+ "katashina.gunma.jp",
+ "kawaba.gunma.jp",
+ "kiryu.gunma.jp",
+ "kusatsu.gunma.jp",
+ "maebashi.gunma.jp",
+ "meiwa.gunma.jp",
+ "midori.gunma.jp",
+ "minakami.gunma.jp",
+ "naganohara.gunma.jp",
+ "nakanojo.gunma.jp",
+ "nanmoku.gunma.jp",
+ "numata.gunma.jp",
+ "oizumi.gunma.jp",
+ "ora.gunma.jp",
+ "ota.gunma.jp",
+ "shibukawa.gunma.jp",
+ "shimonita.gunma.jp",
+ "shinto.gunma.jp",
+ "showa.gunma.jp",
+ "takasaki.gunma.jp",
+ "takayama.gunma.jp",
+ "tamamura.gunma.jp",
+ "tatebayashi.gunma.jp",
+ "tomioka.gunma.jp",
+ "tsukiyono.gunma.jp",
+ "tsumagoi.gunma.jp",
+ "ueno.gunma.jp",
+ "yoshioka.gunma.jp",
+ "asaminami.hiroshima.jp",
+ "daiwa.hiroshima.jp",
+ "etajima.hiroshima.jp",
+ "fuchu.hiroshima.jp",
+ "fukuyama.hiroshima.jp",
+ "hatsukaichi.hiroshima.jp",
+ "higashihiroshima.hiroshima.jp",
+ "hongo.hiroshima.jp",
+ "jinsekikogen.hiroshima.jp",
+ "kaita.hiroshima.jp",
+ "kui.hiroshima.jp",
+ "kumano.hiroshima.jp",
+ "kure.hiroshima.jp",
+ "mihara.hiroshima.jp",
+ "miyoshi.hiroshima.jp",
+ "naka.hiroshima.jp",
+ "onomichi.hiroshima.jp",
+ "osakikamijima.hiroshima.jp",
+ "otake.hiroshima.jp",
+ "saka.hiroshima.jp",
+ "sera.hiroshima.jp",
+ "seranishi.hiroshima.jp",
+ "shinichi.hiroshima.jp",
+ "shobara.hiroshima.jp",
+ "takehara.hiroshima.jp",
+ "abashiri.hokkaido.jp",
+ "abira.hokkaido.jp",
+ "aibetsu.hokkaido.jp",
+ "akabira.hokkaido.jp",
+ "akkeshi.hokkaido.jp",
+ "asahikawa.hokkaido.jp",
+ "ashibetsu.hokkaido.jp",
+ "ashoro.hokkaido.jp",
+ "assabu.hokkaido.jp",
+ "atsuma.hokkaido.jp",
+ "bibai.hokkaido.jp",
+ "biei.hokkaido.jp",
+ "bifuka.hokkaido.jp",
+ "bihoro.hokkaido.jp",
+ "biratori.hokkaido.jp",
+ "chippubetsu.hokkaido.jp",
+ "chitose.hokkaido.jp",
+ "date.hokkaido.jp",
+ "ebetsu.hokkaido.jp",
+ "embetsu.hokkaido.jp",
+ "eniwa.hokkaido.jp",
+ "erimo.hokkaido.jp",
+ "esan.hokkaido.jp",
+ "esashi.hokkaido.jp",
+ "fukagawa.hokkaido.jp",
+ "fukushima.hokkaido.jp",
+ "furano.hokkaido.jp",
+ "furubira.hokkaido.jp",
+ "haboro.hokkaido.jp",
+ "hakodate.hokkaido.jp",
+ "hamatonbetsu.hokkaido.jp",
+ "hidaka.hokkaido.jp",
+ "higashikagura.hokkaido.jp",
+ "higashikawa.hokkaido.jp",
+ "hiroo.hokkaido.jp",
+ "hokuryu.hokkaido.jp",
+ "hokuto.hokkaido.jp",
+ "honbetsu.hokkaido.jp",
+ "horokanai.hokkaido.jp",
+ "horonobe.hokkaido.jp",
+ "ikeda.hokkaido.jp",
+ "imakane.hokkaido.jp",
+ "ishikari.hokkaido.jp",
+ "iwamizawa.hokkaido.jp",
+ "iwanai.hokkaido.jp",
+ "kamifurano.hokkaido.jp",
+ "kamikawa.hokkaido.jp",
+ "kamishihoro.hokkaido.jp",
+ "kamisunagawa.hokkaido.jp",
+ "kamoenai.hokkaido.jp",
+ "kayabe.hokkaido.jp",
+ "kembuchi.hokkaido.jp",
+ "kikonai.hokkaido.jp",
+ "kimobetsu.hokkaido.jp",
+ "kitahiroshima.hokkaido.jp",
+ "kitami.hokkaido.jp",
+ "kiyosato.hokkaido.jp",
+ "koshimizu.hokkaido.jp",
+ "kunneppu.hokkaido.jp",
+ "kuriyama.hokkaido.jp",
+ "kuromatsunai.hokkaido.jp",
+ "kushiro.hokkaido.jp",
+ "kutchan.hokkaido.jp",
+ "kyowa.hokkaido.jp",
+ "mashike.hokkaido.jp",
+ "matsumae.hokkaido.jp",
+ "mikasa.hokkaido.jp",
+ "minamifurano.hokkaido.jp",
+ "mombetsu.hokkaido.jp",
+ "moseushi.hokkaido.jp",
+ "mukawa.hokkaido.jp",
+ "muroran.hokkaido.jp",
+ "naie.hokkaido.jp",
+ "nakagawa.hokkaido.jp",
+ "nakasatsunai.hokkaido.jp",
+ "nakatombetsu.hokkaido.jp",
+ "nanae.hokkaido.jp",
+ "nanporo.hokkaido.jp",
+ "nayoro.hokkaido.jp",
+ "nemuro.hokkaido.jp",
+ "niikappu.hokkaido.jp",
+ "niki.hokkaido.jp",
+ "nishiokoppe.hokkaido.jp",
+ "noboribetsu.hokkaido.jp",
+ "numata.hokkaido.jp",
+ "obihiro.hokkaido.jp",
+ "obira.hokkaido.jp",
+ "oketo.hokkaido.jp",
+ "okoppe.hokkaido.jp",
+ "otaru.hokkaido.jp",
+ "otobe.hokkaido.jp",
+ "otofuke.hokkaido.jp",
+ "otoineppu.hokkaido.jp",
+ "oumu.hokkaido.jp",
+ "ozora.hokkaido.jp",
+ "pippu.hokkaido.jp",
+ "rankoshi.hokkaido.jp",
+ "rebun.hokkaido.jp",
+ "rikubetsu.hokkaido.jp",
+ "rishiri.hokkaido.jp",
+ "rishirifuji.hokkaido.jp",
+ "saroma.hokkaido.jp",
+ "sarufutsu.hokkaido.jp",
+ "shakotan.hokkaido.jp",
+ "shari.hokkaido.jp",
+ "shibecha.hokkaido.jp",
+ "shibetsu.hokkaido.jp",
+ "shikabe.hokkaido.jp",
+ "shikaoi.hokkaido.jp",
+ "shimamaki.hokkaido.jp",
+ "shimizu.hokkaido.jp",
+ "shimokawa.hokkaido.jp",
+ "shinshinotsu.hokkaido.jp",
+ "shintoku.hokkaido.jp",
+ "shiranuka.hokkaido.jp",
+ "shiraoi.hokkaido.jp",
+ "shiriuchi.hokkaido.jp",
+ "sobetsu.hokkaido.jp",
+ "sunagawa.hokkaido.jp",
+ "taiki.hokkaido.jp",
+ "takasu.hokkaido.jp",
+ "takikawa.hokkaido.jp",
+ "takinoue.hokkaido.jp",
+ "teshikaga.hokkaido.jp",
+ "tobetsu.hokkaido.jp",
+ "tohma.hokkaido.jp",
+ "tomakomai.hokkaido.jp",
+ "tomari.hokkaido.jp",
+ "toya.hokkaido.jp",
+ "toyako.hokkaido.jp",
+ "toyotomi.hokkaido.jp",
+ "toyoura.hokkaido.jp",
+ "tsubetsu.hokkaido.jp",
+ "tsukigata.hokkaido.jp",
+ "urakawa.hokkaido.jp",
+ "urausu.hokkaido.jp",
+ "uryu.hokkaido.jp",
+ "utashinai.hokkaido.jp",
+ "wakkanai.hokkaido.jp",
+ "wassamu.hokkaido.jp",
+ "yakumo.hokkaido.jp",
+ "yoichi.hokkaido.jp",
+ "aioi.hyogo.jp",
+ "akashi.hyogo.jp",
+ "ako.hyogo.jp",
+ "amagasaki.hyogo.jp",
+ "aogaki.hyogo.jp",
+ "asago.hyogo.jp",
+ "ashiya.hyogo.jp",
+ "awaji.hyogo.jp",
+ "fukusaki.hyogo.jp",
+ "goshiki.hyogo.jp",
+ "harima.hyogo.jp",
+ "himeji.hyogo.jp",
+ "ichikawa.hyogo.jp",
+ "inagawa.hyogo.jp",
+ "itami.hyogo.jp",
+ "kakogawa.hyogo.jp",
+ "kamigori.hyogo.jp",
+ "kamikawa.hyogo.jp",
+ "kasai.hyogo.jp",
+ "kasuga.hyogo.jp",
+ "kawanishi.hyogo.jp",
+ "miki.hyogo.jp",
+ "minamiawaji.hyogo.jp",
+ "nishinomiya.hyogo.jp",
+ "nishiwaki.hyogo.jp",
+ "ono.hyogo.jp",
+ "sanda.hyogo.jp",
+ "sannan.hyogo.jp",
+ "sasayama.hyogo.jp",
+ "sayo.hyogo.jp",
+ "shingu.hyogo.jp",
+ "shinonsen.hyogo.jp",
+ "shiso.hyogo.jp",
+ "sumoto.hyogo.jp",
+ "taishi.hyogo.jp",
+ "taka.hyogo.jp",
+ "takarazuka.hyogo.jp",
+ "takasago.hyogo.jp",
+ "takino.hyogo.jp",
+ "tamba.hyogo.jp",
+ "tatsuno.hyogo.jp",
+ "toyooka.hyogo.jp",
+ "yabu.hyogo.jp",
+ "yashiro.hyogo.jp",
+ "yoka.hyogo.jp",
+ "yokawa.hyogo.jp",
+ "ami.ibaraki.jp",
+ "asahi.ibaraki.jp",
+ "bando.ibaraki.jp",
+ "chikusei.ibaraki.jp",
+ "daigo.ibaraki.jp",
+ "fujishiro.ibaraki.jp",
+ "hitachi.ibaraki.jp",
+ "hitachinaka.ibaraki.jp",
+ "hitachiomiya.ibaraki.jp",
+ "hitachiota.ibaraki.jp",
+ "ibaraki.ibaraki.jp",
+ "ina.ibaraki.jp",
+ "inashiki.ibaraki.jp",
+ "itako.ibaraki.jp",
+ "iwama.ibaraki.jp",
+ "joso.ibaraki.jp",
+ "kamisu.ibaraki.jp",
+ "kasama.ibaraki.jp",
+ "kashima.ibaraki.jp",
+ "kasumigaura.ibaraki.jp",
+ "koga.ibaraki.jp",
+ "miho.ibaraki.jp",
+ "mito.ibaraki.jp",
+ "moriya.ibaraki.jp",
+ "naka.ibaraki.jp",
+ "namegata.ibaraki.jp",
+ "oarai.ibaraki.jp",
+ "ogawa.ibaraki.jp",
+ "omitama.ibaraki.jp",
+ "ryugasaki.ibaraki.jp",
+ "sakai.ibaraki.jp",
+ "sakuragawa.ibaraki.jp",
+ "shimodate.ibaraki.jp",
+ "shimotsuma.ibaraki.jp",
+ "shirosato.ibaraki.jp",
+ "sowa.ibaraki.jp",
+ "suifu.ibaraki.jp",
+ "takahagi.ibaraki.jp",
+ "tamatsukuri.ibaraki.jp",
+ "tokai.ibaraki.jp",
+ "tomobe.ibaraki.jp",
+ "tone.ibaraki.jp",
+ "toride.ibaraki.jp",
+ "tsuchiura.ibaraki.jp",
+ "tsukuba.ibaraki.jp",
+ "uchihara.ibaraki.jp",
+ "ushiku.ibaraki.jp",
+ "yachiyo.ibaraki.jp",
+ "yamagata.ibaraki.jp",
+ "yawara.ibaraki.jp",
+ "yuki.ibaraki.jp",
+ "anamizu.ishikawa.jp",
+ "hakui.ishikawa.jp",
+ "hakusan.ishikawa.jp",
+ "kaga.ishikawa.jp",
+ "kahoku.ishikawa.jp",
+ "kanazawa.ishikawa.jp",
+ "kawakita.ishikawa.jp",
+ "komatsu.ishikawa.jp",
+ "nakanoto.ishikawa.jp",
+ "nanao.ishikawa.jp",
+ "nomi.ishikawa.jp",
+ "nonoichi.ishikawa.jp",
+ "noto.ishikawa.jp",
+ "shika.ishikawa.jp",
+ "suzu.ishikawa.jp",
+ "tsubata.ishikawa.jp",
+ "tsurugi.ishikawa.jp",
+ "uchinada.ishikawa.jp",
+ "wajima.ishikawa.jp",
+ "fudai.iwate.jp",
+ "fujisawa.iwate.jp",
+ "hanamaki.iwate.jp",
+ "hiraizumi.iwate.jp",
+ "hirono.iwate.jp",
+ "ichinohe.iwate.jp",
+ "ichinoseki.iwate.jp",
+ "iwaizumi.iwate.jp",
+ "iwate.iwate.jp",
+ "joboji.iwate.jp",
+ "kamaishi.iwate.jp",
+ "kanegasaki.iwate.jp",
+ "karumai.iwate.jp",
+ "kawai.iwate.jp",
+ "kitakami.iwate.jp",
+ "kuji.iwate.jp",
+ "kunohe.iwate.jp",
+ "kuzumaki.iwate.jp",
+ "miyako.iwate.jp",
+ "mizusawa.iwate.jp",
+ "morioka.iwate.jp",
+ "ninohe.iwate.jp",
+ "noda.iwate.jp",
+ "ofunato.iwate.jp",
+ "oshu.iwate.jp",
+ "otsuchi.iwate.jp",
+ "rikuzentakata.iwate.jp",
+ "shiwa.iwate.jp",
+ "shizukuishi.iwate.jp",
+ "sumita.iwate.jp",
+ "tanohata.iwate.jp",
+ "tono.iwate.jp",
+ "yahaba.iwate.jp",
+ "yamada.iwate.jp",
+ "ayagawa.kagawa.jp",
+ "higashikagawa.kagawa.jp",
+ "kanonji.kagawa.jp",
+ "kotohira.kagawa.jp",
+ "manno.kagawa.jp",
+ "marugame.kagawa.jp",
+ "mitoyo.kagawa.jp",
+ "naoshima.kagawa.jp",
+ "sanuki.kagawa.jp",
+ "tadotsu.kagawa.jp",
+ "takamatsu.kagawa.jp",
+ "tonosho.kagawa.jp",
+ "uchinomi.kagawa.jp",
+ "utazu.kagawa.jp",
+ "zentsuji.kagawa.jp",
+ "akune.kagoshima.jp",
+ "amami.kagoshima.jp",
+ "hioki.kagoshima.jp",
+ "isa.kagoshima.jp",
+ "isen.kagoshima.jp",
+ "izumi.kagoshima.jp",
+ "kagoshima.kagoshima.jp",
+ "kanoya.kagoshima.jp",
+ "kawanabe.kagoshima.jp",
+ "kinko.kagoshima.jp",
+ "kouyama.kagoshima.jp",
+ "makurazaki.kagoshima.jp",
+ "matsumoto.kagoshima.jp",
+ "minamitane.kagoshima.jp",
+ "nakatane.kagoshima.jp",
+ "nishinoomote.kagoshima.jp",
+ "satsumasendai.kagoshima.jp",
+ "soo.kagoshima.jp",
+ "tarumizu.kagoshima.jp",
+ "yusui.kagoshima.jp",
+ "aikawa.kanagawa.jp",
+ "atsugi.kanagawa.jp",
+ "ayase.kanagawa.jp",
+ "chigasaki.kanagawa.jp",
+ "ebina.kanagawa.jp",
+ "fujisawa.kanagawa.jp",
+ "hadano.kanagawa.jp",
+ "hakone.kanagawa.jp",
+ "hiratsuka.kanagawa.jp",
+ "isehara.kanagawa.jp",
+ "kaisei.kanagawa.jp",
+ "kamakura.kanagawa.jp",
+ "kiyokawa.kanagawa.jp",
+ "matsuda.kanagawa.jp",
+ "minamiashigara.kanagawa.jp",
+ "miura.kanagawa.jp",
+ "nakai.kanagawa.jp",
+ "ninomiya.kanagawa.jp",
+ "odawara.kanagawa.jp",
+ "oi.kanagawa.jp",
+ "oiso.kanagawa.jp",
+ "sagamihara.kanagawa.jp",
+ "samukawa.kanagawa.jp",
+ "tsukui.kanagawa.jp",
+ "yamakita.kanagawa.jp",
+ "yamato.kanagawa.jp",
+ "yokosuka.kanagawa.jp",
+ "yugawara.kanagawa.jp",
+ "zama.kanagawa.jp",
+ "zushi.kanagawa.jp",
+ "aki.kochi.jp",
+ "geisei.kochi.jp",
+ "hidaka.kochi.jp",
+ "higashitsuno.kochi.jp",
+ "ino.kochi.jp",
+ "kagami.kochi.jp",
+ "kami.kochi.jp",
+ "kitagawa.kochi.jp",
+ "kochi.kochi.jp",
+ "mihara.kochi.jp",
+ "motoyama.kochi.jp",
+ "muroto.kochi.jp",
+ "nahari.kochi.jp",
+ "nakamura.kochi.jp",
+ "nankoku.kochi.jp",
+ "nishitosa.kochi.jp",
+ "niyodogawa.kochi.jp",
+ "ochi.kochi.jp",
+ "okawa.kochi.jp",
+ "otoyo.kochi.jp",
+ "otsuki.kochi.jp",
+ "sakawa.kochi.jp",
+ "sukumo.kochi.jp",
+ "susaki.kochi.jp",
+ "tosa.kochi.jp",
+ "tosashimizu.kochi.jp",
+ "toyo.kochi.jp",
+ "tsuno.kochi.jp",
+ "umaji.kochi.jp",
+ "yasuda.kochi.jp",
+ "yusuhara.kochi.jp",
+ "amakusa.kumamoto.jp",
+ "arao.kumamoto.jp",
+ "aso.kumamoto.jp",
+ "choyo.kumamoto.jp",
+ "gyokuto.kumamoto.jp",
+ "kamiamakusa.kumamoto.jp",
+ "kikuchi.kumamoto.jp",
+ "kumamoto.kumamoto.jp",
+ "mashiki.kumamoto.jp",
+ "mifune.kumamoto.jp",
+ "minamata.kumamoto.jp",
+ "minamioguni.kumamoto.jp",
+ "nagasu.kumamoto.jp",
+ "nishihara.kumamoto.jp",
+ "oguni.kumamoto.jp",
+ "ozu.kumamoto.jp",
+ "sumoto.kumamoto.jp",
+ "takamori.kumamoto.jp",
+ "uki.kumamoto.jp",
+ "uto.kumamoto.jp",
+ "yamaga.kumamoto.jp",
+ "yamato.kumamoto.jp",
+ "yatsushiro.kumamoto.jp",
+ "ayabe.kyoto.jp",
+ "fukuchiyama.kyoto.jp",
+ "higashiyama.kyoto.jp",
+ "ide.kyoto.jp",
+ "ine.kyoto.jp",
+ "joyo.kyoto.jp",
+ "kameoka.kyoto.jp",
+ "kamo.kyoto.jp",
+ "kita.kyoto.jp",
+ "kizu.kyoto.jp",
+ "kumiyama.kyoto.jp",
+ "kyotamba.kyoto.jp",
+ "kyotanabe.kyoto.jp",
+ "kyotango.kyoto.jp",
+ "maizuru.kyoto.jp",
+ "minami.kyoto.jp",
+ "minamiyamashiro.kyoto.jp",
+ "miyazu.kyoto.jp",
+ "muko.kyoto.jp",
+ "nagaokakyo.kyoto.jp",
+ "nakagyo.kyoto.jp",
+ "nantan.kyoto.jp",
+ "oyamazaki.kyoto.jp",
+ "sakyo.kyoto.jp",
+ "seika.kyoto.jp",
+ "tanabe.kyoto.jp",
+ "uji.kyoto.jp",
+ "ujitawara.kyoto.jp",
+ "wazuka.kyoto.jp",
+ "yamashina.kyoto.jp",
+ "yawata.kyoto.jp",
+ "asahi.mie.jp",
+ "inabe.mie.jp",
+ "ise.mie.jp",
+ "kameyama.mie.jp",
+ "kawagoe.mie.jp",
+ "kiho.mie.jp",
+ "kisosaki.mie.jp",
+ "kiwa.mie.jp",
+ "komono.mie.jp",
+ "kumano.mie.jp",
+ "kuwana.mie.jp",
+ "matsusaka.mie.jp",
+ "meiwa.mie.jp",
+ "mihama.mie.jp",
+ "minamiise.mie.jp",
+ "misugi.mie.jp",
+ "miyama.mie.jp",
+ "nabari.mie.jp",
+ "shima.mie.jp",
+ "suzuka.mie.jp",
+ "tado.mie.jp",
+ "taiki.mie.jp",
+ "taki.mie.jp",
+ "tamaki.mie.jp",
+ "toba.mie.jp",
+ "tsu.mie.jp",
+ "udono.mie.jp",
+ "ureshino.mie.jp",
+ "watarai.mie.jp",
+ "yokkaichi.mie.jp",
+ "furukawa.miyagi.jp",
+ "higashimatsushima.miyagi.jp",
+ "ishinomaki.miyagi.jp",
+ "iwanuma.miyagi.jp",
+ "kakuda.miyagi.jp",
+ "kami.miyagi.jp",
+ "kawasaki.miyagi.jp",
+ "marumori.miyagi.jp",
+ "matsushima.miyagi.jp",
+ "minamisanriku.miyagi.jp",
+ "misato.miyagi.jp",
+ "murata.miyagi.jp",
+ "natori.miyagi.jp",
+ "ogawara.miyagi.jp",
+ "ohira.miyagi.jp",
+ "onagawa.miyagi.jp",
+ "osaki.miyagi.jp",
+ "rifu.miyagi.jp",
+ "semine.miyagi.jp",
+ "shibata.miyagi.jp",
+ "shichikashuku.miyagi.jp",
+ "shikama.miyagi.jp",
+ "shiogama.miyagi.jp",
+ "shiroishi.miyagi.jp",
+ "tagajo.miyagi.jp",
+ "taiwa.miyagi.jp",
+ "tome.miyagi.jp",
+ "tomiya.miyagi.jp",
+ "wakuya.miyagi.jp",
+ "watari.miyagi.jp",
+ "yamamoto.miyagi.jp",
+ "zao.miyagi.jp",
+ "aya.miyazaki.jp",
+ "ebino.miyazaki.jp",
+ "gokase.miyazaki.jp",
+ "hyuga.miyazaki.jp",
+ "kadogawa.miyazaki.jp",
+ "kawaminami.miyazaki.jp",
+ "kijo.miyazaki.jp",
+ "kitagawa.miyazaki.jp",
+ "kitakata.miyazaki.jp",
+ "kitaura.miyazaki.jp",
+ "kobayashi.miyazaki.jp",
+ "kunitomi.miyazaki.jp",
+ "kushima.miyazaki.jp",
+ "mimata.miyazaki.jp",
+ "miyakonojo.miyazaki.jp",
+ "miyazaki.miyazaki.jp",
+ "morotsuka.miyazaki.jp",
+ "nichinan.miyazaki.jp",
+ "nishimera.miyazaki.jp",
+ "nobeoka.miyazaki.jp",
+ "saito.miyazaki.jp",
+ "shiiba.miyazaki.jp",
+ "shintomi.miyazaki.jp",
+ "takaharu.miyazaki.jp",
+ "takanabe.miyazaki.jp",
+ "takazaki.miyazaki.jp",
+ "tsuno.miyazaki.jp",
+ "achi.nagano.jp",
+ "agematsu.nagano.jp",
+ "anan.nagano.jp",
+ "aoki.nagano.jp",
+ "asahi.nagano.jp",
+ "azumino.nagano.jp",
+ "chikuhoku.nagano.jp",
+ "chikuma.nagano.jp",
+ "chino.nagano.jp",
+ "fujimi.nagano.jp",
+ "hakuba.nagano.jp",
+ "hara.nagano.jp",
+ "hiraya.nagano.jp",
+ "iida.nagano.jp",
+ "iijima.nagano.jp",
+ "iiyama.nagano.jp",
+ "iizuna.nagano.jp",
+ "ikeda.nagano.jp",
+ "ikusaka.nagano.jp",
+ "ina.nagano.jp",
+ "karuizawa.nagano.jp",
+ "kawakami.nagano.jp",
+ "kiso.nagano.jp",
+ "kisofukushima.nagano.jp",
+ "kitaaiki.nagano.jp",
+ "komagane.nagano.jp",
+ "komoro.nagano.jp",
+ "matsukawa.nagano.jp",
+ "matsumoto.nagano.jp",
+ "miasa.nagano.jp",
+ "minamiaiki.nagano.jp",
+ "minamimaki.nagano.jp",
+ "minamiminowa.nagano.jp",
+ "minowa.nagano.jp",
+ "miyada.nagano.jp",
+ "miyota.nagano.jp",
+ "mochizuki.nagano.jp",
+ "nagano.nagano.jp",
+ "nagawa.nagano.jp",
+ "nagiso.nagano.jp",
+ "nakagawa.nagano.jp",
+ "nakano.nagano.jp",
+ "nozawaonsen.nagano.jp",
+ "obuse.nagano.jp",
+ "ogawa.nagano.jp",
+ "okaya.nagano.jp",
+ "omachi.nagano.jp",
+ "omi.nagano.jp",
+ "ookuwa.nagano.jp",
+ "ooshika.nagano.jp",
+ "otaki.nagano.jp",
+ "otari.nagano.jp",
+ "sakae.nagano.jp",
+ "sakaki.nagano.jp",
+ "saku.nagano.jp",
+ "sakuho.nagano.jp",
+ "shimosuwa.nagano.jp",
+ "shinanomachi.nagano.jp",
+ "shiojiri.nagano.jp",
+ "suwa.nagano.jp",
+ "suzaka.nagano.jp",
+ "takagi.nagano.jp",
+ "takamori.nagano.jp",
+ "takayama.nagano.jp",
+ "tateshina.nagano.jp",
+ "tatsuno.nagano.jp",
+ "togakushi.nagano.jp",
+ "togura.nagano.jp",
+ "tomi.nagano.jp",
+ "ueda.nagano.jp",
+ "wada.nagano.jp",
+ "yamagata.nagano.jp",
+ "yamanouchi.nagano.jp",
+ "yasaka.nagano.jp",
+ "yasuoka.nagano.jp",
+ "chijiwa.nagasaki.jp",
+ "futsu.nagasaki.jp",
+ "goto.nagasaki.jp",
+ "hasami.nagasaki.jp",
+ "hirado.nagasaki.jp",
+ "iki.nagasaki.jp",
+ "isahaya.nagasaki.jp",
+ "kawatana.nagasaki.jp",
+ "kuchinotsu.nagasaki.jp",
+ "matsuura.nagasaki.jp",
+ "nagasaki.nagasaki.jp",
+ "obama.nagasaki.jp",
+ "omura.nagasaki.jp",
+ "oseto.nagasaki.jp",
+ "saikai.nagasaki.jp",
+ "sasebo.nagasaki.jp",
+ "seihi.nagasaki.jp",
+ "shimabara.nagasaki.jp",
+ "shinkamigoto.nagasaki.jp",
+ "togitsu.nagasaki.jp",
+ "tsushima.nagasaki.jp",
+ "unzen.nagasaki.jp",
+ "ando.nara.jp",
+ "gose.nara.jp",
+ "heguri.nara.jp",
+ "higashiyoshino.nara.jp",
+ "ikaruga.nara.jp",
+ "ikoma.nara.jp",
+ "kamikitayama.nara.jp",
+ "kanmaki.nara.jp",
+ "kashiba.nara.jp",
+ "kashihara.nara.jp",
+ "katsuragi.nara.jp",
+ "kawai.nara.jp",
+ "kawakami.nara.jp",
+ "kawanishi.nara.jp",
+ "koryo.nara.jp",
+ "kurotaki.nara.jp",
+ "mitsue.nara.jp",
+ "miyake.nara.jp",
+ "nara.nara.jp",
+ "nosegawa.nara.jp",
+ "oji.nara.jp",
+ "ouda.nara.jp",
+ "oyodo.nara.jp",
+ "sakurai.nara.jp",
+ "sango.nara.jp",
+ "shimoichi.nara.jp",
+ "shimokitayama.nara.jp",
+ "shinjo.nara.jp",
+ "soni.nara.jp",
+ "takatori.nara.jp",
+ "tawaramoto.nara.jp",
+ "tenkawa.nara.jp",
+ "tenri.nara.jp",
+ "uda.nara.jp",
+ "yamatokoriyama.nara.jp",
+ "yamatotakada.nara.jp",
+ "yamazoe.nara.jp",
+ "yoshino.nara.jp",
+ "aga.niigata.jp",
+ "agano.niigata.jp",
+ "gosen.niigata.jp",
+ "itoigawa.niigata.jp",
+ "izumozaki.niigata.jp",
+ "joetsu.niigata.jp",
+ "kamo.niigata.jp",
+ "kariwa.niigata.jp",
+ "kashiwazaki.niigata.jp",
+ "minamiuonuma.niigata.jp",
+ "mitsuke.niigata.jp",
+ "muika.niigata.jp",
+ "murakami.niigata.jp",
+ "myoko.niigata.jp",
+ "nagaoka.niigata.jp",
+ "niigata.niigata.jp",
+ "ojiya.niigata.jp",
+ "omi.niigata.jp",
+ "sado.niigata.jp",
+ "sanjo.niigata.jp",
+ "seiro.niigata.jp",
+ "seirou.niigata.jp",
+ "sekikawa.niigata.jp",
+ "shibata.niigata.jp",
+ "tagami.niigata.jp",
+ "tainai.niigata.jp",
+ "tochio.niigata.jp",
+ "tokamachi.niigata.jp",
+ "tsubame.niigata.jp",
+ "tsunan.niigata.jp",
+ "uonuma.niigata.jp",
+ "yahiko.niigata.jp",
+ "yoita.niigata.jp",
+ "yuzawa.niigata.jp",
+ "beppu.oita.jp",
+ "bungoono.oita.jp",
+ "bungotakada.oita.jp",
+ "hasama.oita.jp",
+ "hiji.oita.jp",
+ "himeshima.oita.jp",
+ "hita.oita.jp",
+ "kamitsue.oita.jp",
+ "kokonoe.oita.jp",
+ "kuju.oita.jp",
+ "kunisaki.oita.jp",
+ "kusu.oita.jp",
+ "oita.oita.jp",
+ "saiki.oita.jp",
+ "taketa.oita.jp",
+ "tsukumi.oita.jp",
+ "usa.oita.jp",
+ "usuki.oita.jp",
+ "yufu.oita.jp",
+ "akaiwa.okayama.jp",
+ "asakuchi.okayama.jp",
+ "bizen.okayama.jp",
+ "hayashima.okayama.jp",
+ "ibara.okayama.jp",
+ "kagamino.okayama.jp",
+ "kasaoka.okayama.jp",
+ "kibichuo.okayama.jp",
+ "kumenan.okayama.jp",
+ "kurashiki.okayama.jp",
+ "maniwa.okayama.jp",
+ "misaki.okayama.jp",
+ "nagi.okayama.jp",
+ "niimi.okayama.jp",
+ "nishiawakura.okayama.jp",
+ "okayama.okayama.jp",
+ "satosho.okayama.jp",
+ "setouchi.okayama.jp",
+ "shinjo.okayama.jp",
+ "shoo.okayama.jp",
+ "soja.okayama.jp",
+ "takahashi.okayama.jp",
+ "tamano.okayama.jp",
+ "tsuyama.okayama.jp",
+ "wake.okayama.jp",
+ "yakage.okayama.jp",
+ "aguni.okinawa.jp",
+ "ginowan.okinawa.jp",
+ "ginoza.okinawa.jp",
+ "gushikami.okinawa.jp",
+ "haebaru.okinawa.jp",
+ "higashi.okinawa.jp",
+ "hirara.okinawa.jp",
+ "iheya.okinawa.jp",
+ "ishigaki.okinawa.jp",
+ "ishikawa.okinawa.jp",
+ "itoman.okinawa.jp",
+ "izena.okinawa.jp",
+ "kadena.okinawa.jp",
+ "kin.okinawa.jp",
+ "kitadaito.okinawa.jp",
+ "kitanakagusuku.okinawa.jp",
+ "kumejima.okinawa.jp",
+ "kunigami.okinawa.jp",
+ "minamidaito.okinawa.jp",
+ "motobu.okinawa.jp",
+ "nago.okinawa.jp",
+ "naha.okinawa.jp",
+ "nakagusuku.okinawa.jp",
+ "nakijin.okinawa.jp",
+ "nanjo.okinawa.jp",
+ "nishihara.okinawa.jp",
+ "ogimi.okinawa.jp",
+ "okinawa.okinawa.jp",
+ "onna.okinawa.jp",
+ "shimoji.okinawa.jp",
+ "taketomi.okinawa.jp",
+ "tarama.okinawa.jp",
+ "tokashiki.okinawa.jp",
+ "tomigusuku.okinawa.jp",
+ "tonaki.okinawa.jp",
+ "urasoe.okinawa.jp",
+ "uruma.okinawa.jp",
+ "yaese.okinawa.jp",
+ "yomitan.okinawa.jp",
+ "yonabaru.okinawa.jp",
+ "yonaguni.okinawa.jp",
+ "zamami.okinawa.jp",
+ "abeno.osaka.jp",
+ "chihayaakasaka.osaka.jp",
+ "chuo.osaka.jp",
+ "daito.osaka.jp",
+ "fujiidera.osaka.jp",
+ "habikino.osaka.jp",
+ "hannan.osaka.jp",
+ "higashiosaka.osaka.jp",
+ "higashisumiyoshi.osaka.jp",
+ "higashiyodogawa.osaka.jp",
+ "hirakata.osaka.jp",
+ "ibaraki.osaka.jp",
+ "ikeda.osaka.jp",
+ "izumi.osaka.jp",
+ "izumiotsu.osaka.jp",
+ "izumisano.osaka.jp",
+ "kadoma.osaka.jp",
+ "kaizuka.osaka.jp",
+ "kanan.osaka.jp",
+ "kashiwara.osaka.jp",
+ "katano.osaka.jp",
+ "kawachinagano.osaka.jp",
+ "kishiwada.osaka.jp",
+ "kita.osaka.jp",
+ "kumatori.osaka.jp",
+ "matsubara.osaka.jp",
+ "minato.osaka.jp",
+ "minoh.osaka.jp",
+ "misaki.osaka.jp",
+ "moriguchi.osaka.jp",
+ "neyagawa.osaka.jp",
+ "nishi.osaka.jp",
+ "nose.osaka.jp",
+ "osakasayama.osaka.jp",
+ "sakai.osaka.jp",
+ "sayama.osaka.jp",
+ "sennan.osaka.jp",
+ "settsu.osaka.jp",
+ "shijonawate.osaka.jp",
+ "shimamoto.osaka.jp",
+ "suita.osaka.jp",
+ "tadaoka.osaka.jp",
+ "taishi.osaka.jp",
+ "tajiri.osaka.jp",
+ "takaishi.osaka.jp",
+ "takatsuki.osaka.jp",
+ "tondabayashi.osaka.jp",
+ "toyonaka.osaka.jp",
+ "toyono.osaka.jp",
+ "yao.osaka.jp",
+ "ariake.saga.jp",
+ "arita.saga.jp",
+ "fukudomi.saga.jp",
+ "genkai.saga.jp",
+ "hamatama.saga.jp",
+ "hizen.saga.jp",
+ "imari.saga.jp",
+ "kamimine.saga.jp",
+ "kanzaki.saga.jp",
+ "karatsu.saga.jp",
+ "kashima.saga.jp",
+ "kitagata.saga.jp",
+ "kitahata.saga.jp",
+ "kiyama.saga.jp",
+ "kouhoku.saga.jp",
+ "kyuragi.saga.jp",
+ "nishiarita.saga.jp",
+ "ogi.saga.jp",
+ "omachi.saga.jp",
+ "ouchi.saga.jp",
+ "saga.saga.jp",
+ "shiroishi.saga.jp",
+ "taku.saga.jp",
+ "tara.saga.jp",
+ "tosu.saga.jp",
+ "yoshinogari.saga.jp",
+ "arakawa.saitama.jp",
+ "asaka.saitama.jp",
+ "chichibu.saitama.jp",
+ "fujimi.saitama.jp",
+ "fujimino.saitama.jp",
+ "fukaya.saitama.jp",
+ "hanno.saitama.jp",
+ "hanyu.saitama.jp",
+ "hasuda.saitama.jp",
+ "hatogaya.saitama.jp",
+ "hatoyama.saitama.jp",
+ "hidaka.saitama.jp",
+ "higashichichibu.saitama.jp",
+ "higashimatsuyama.saitama.jp",
+ "honjo.saitama.jp",
+ "ina.saitama.jp",
+ "iruma.saitama.jp",
+ "iwatsuki.saitama.jp",
+ "kamiizumi.saitama.jp",
+ "kamikawa.saitama.jp",
+ "kamisato.saitama.jp",
+ "kasukabe.saitama.jp",
+ "kawagoe.saitama.jp",
+ "kawaguchi.saitama.jp",
+ "kawajima.saitama.jp",
+ "kazo.saitama.jp",
+ "kitamoto.saitama.jp",
+ "koshigaya.saitama.jp",
+ "kounosu.saitama.jp",
+ "kuki.saitama.jp",
+ "kumagaya.saitama.jp",
+ "matsubushi.saitama.jp",
+ "minano.saitama.jp",
+ "misato.saitama.jp",
+ "miyashiro.saitama.jp",
+ "miyoshi.saitama.jp",
+ "moroyama.saitama.jp",
+ "nagatoro.saitama.jp",
+ "namegawa.saitama.jp",
+ "niiza.saitama.jp",
+ "ogano.saitama.jp",
+ "ogawa.saitama.jp",
+ "ogose.saitama.jp",
+ "okegawa.saitama.jp",
+ "omiya.saitama.jp",
+ "otaki.saitama.jp",
+ "ranzan.saitama.jp",
+ "ryokami.saitama.jp",
+ "saitama.saitama.jp",
+ "sakado.saitama.jp",
+ "satte.saitama.jp",
+ "sayama.saitama.jp",
+ "shiki.saitama.jp",
+ "shiraoka.saitama.jp",
+ "soka.saitama.jp",
+ "sugito.saitama.jp",
+ "toda.saitama.jp",
+ "tokigawa.saitama.jp",
+ "tokorozawa.saitama.jp",
+ "tsurugashima.saitama.jp",
+ "urawa.saitama.jp",
+ "warabi.saitama.jp",
+ "yashio.saitama.jp",
+ "yokoze.saitama.jp",
+ "yono.saitama.jp",
+ "yorii.saitama.jp",
+ "yoshida.saitama.jp",
+ "yoshikawa.saitama.jp",
+ "yoshimi.saitama.jp",
+ "aisho.shiga.jp",
+ "gamo.shiga.jp",
+ "higashiomi.shiga.jp",
+ "hikone.shiga.jp",
+ "koka.shiga.jp",
+ "konan.shiga.jp",
+ "kosei.shiga.jp",
+ "koto.shiga.jp",
+ "kusatsu.shiga.jp",
+ "maibara.shiga.jp",
+ "moriyama.shiga.jp",
+ "nagahama.shiga.jp",
+ "nishiazai.shiga.jp",
+ "notogawa.shiga.jp",
+ "omihachiman.shiga.jp",
+ "otsu.shiga.jp",
+ "ritto.shiga.jp",
+ "ryuoh.shiga.jp",
+ "takashima.shiga.jp",
+ "takatsuki.shiga.jp",
+ "torahime.shiga.jp",
+ "toyosato.shiga.jp",
+ "yasu.shiga.jp",
+ "akagi.shimane.jp",
+ "ama.shimane.jp",
+ "gotsu.shimane.jp",
+ "hamada.shimane.jp",
+ "higashiizumo.shimane.jp",
+ "hikawa.shimane.jp",
+ "hikimi.shimane.jp",
+ "izumo.shimane.jp",
+ "kakinoki.shimane.jp",
+ "masuda.shimane.jp",
+ "matsue.shimane.jp",
+ "misato.shimane.jp",
+ "nishinoshima.shimane.jp",
+ "ohda.shimane.jp",
+ "okinoshima.shimane.jp",
+ "okuizumo.shimane.jp",
+ "shimane.shimane.jp",
+ "tamayu.shimane.jp",
+ "tsuwano.shimane.jp",
+ "unnan.shimane.jp",
+ "yakumo.shimane.jp",
+ "yasugi.shimane.jp",
+ "yatsuka.shimane.jp",
+ "arai.shizuoka.jp",
+ "atami.shizuoka.jp",
+ "fuji.shizuoka.jp",
+ "fujieda.shizuoka.jp",
+ "fujikawa.shizuoka.jp",
+ "fujinomiya.shizuoka.jp",
+ "fukuroi.shizuoka.jp",
+ "gotemba.shizuoka.jp",
+ "haibara.shizuoka.jp",
+ "hamamatsu.shizuoka.jp",
+ "higashiizu.shizuoka.jp",
+ "ito.shizuoka.jp",
+ "iwata.shizuoka.jp",
+ "izu.shizuoka.jp",
+ "izunokuni.shizuoka.jp",
+ "kakegawa.shizuoka.jp",
+ "kannami.shizuoka.jp",
+ "kawanehon.shizuoka.jp",
+ "kawazu.shizuoka.jp",
+ "kikugawa.shizuoka.jp",
+ "kosai.shizuoka.jp",
+ "makinohara.shizuoka.jp",
+ "matsuzaki.shizuoka.jp",
+ "minamiizu.shizuoka.jp",
+ "mishima.shizuoka.jp",
+ "morimachi.shizuoka.jp",
+ "nishiizu.shizuoka.jp",
+ "numazu.shizuoka.jp",
+ "omaezaki.shizuoka.jp",
+ "shimada.shizuoka.jp",
+ "shimizu.shizuoka.jp",
+ "shimoda.shizuoka.jp",
+ "shizuoka.shizuoka.jp",
+ "susono.shizuoka.jp",
+ "yaizu.shizuoka.jp",
+ "yoshida.shizuoka.jp",
+ "ashikaga.tochigi.jp",
+ "bato.tochigi.jp",
+ "haga.tochigi.jp",
+ "ichikai.tochigi.jp",
+ "iwafune.tochigi.jp",
+ "kaminokawa.tochigi.jp",
+ "kanuma.tochigi.jp",
+ "karasuyama.tochigi.jp",
+ "kuroiso.tochigi.jp",
+ "mashiko.tochigi.jp",
+ "mibu.tochigi.jp",
+ "moka.tochigi.jp",
+ "motegi.tochigi.jp",
+ "nasu.tochigi.jp",
+ "nasushiobara.tochigi.jp",
+ "nikko.tochigi.jp",
+ "nishikata.tochigi.jp",
+ "nogi.tochigi.jp",
+ "ohira.tochigi.jp",
+ "ohtawara.tochigi.jp",
+ "oyama.tochigi.jp",
+ "sakura.tochigi.jp",
+ "sano.tochigi.jp",
+ "shimotsuke.tochigi.jp",
+ "shioya.tochigi.jp",
+ "takanezawa.tochigi.jp",
+ "tochigi.tochigi.jp",
+ "tsuga.tochigi.jp",
+ "ujiie.tochigi.jp",
+ "utsunomiya.tochigi.jp",
+ "yaita.tochigi.jp",
+ "aizumi.tokushima.jp",
+ "anan.tokushima.jp",
+ "ichiba.tokushima.jp",
+ "itano.tokushima.jp",
+ "kainan.tokushima.jp",
+ "komatsushima.tokushima.jp",
+ "matsushige.tokushima.jp",
+ "mima.tokushima.jp",
+ "minami.tokushima.jp",
+ "miyoshi.tokushima.jp",
+ "mugi.tokushima.jp",
+ "nakagawa.tokushima.jp",
+ "naruto.tokushima.jp",
+ "sanagochi.tokushima.jp",
+ "shishikui.tokushima.jp",
+ "tokushima.tokushima.jp",
+ "wajiki.tokushima.jp",
+ "adachi.tokyo.jp",
+ "akiruno.tokyo.jp",
+ "akishima.tokyo.jp",
+ "aogashima.tokyo.jp",
+ "arakawa.tokyo.jp",
+ "bunkyo.tokyo.jp",
+ "chiyoda.tokyo.jp",
+ "chofu.tokyo.jp",
+ "chuo.tokyo.jp",
+ "edogawa.tokyo.jp",
+ "fuchu.tokyo.jp",
+ "fussa.tokyo.jp",
+ "hachijo.tokyo.jp",
+ "hachioji.tokyo.jp",
+ "hamura.tokyo.jp",
+ "higashikurume.tokyo.jp",
+ "higashimurayama.tokyo.jp",
+ "higashiyamato.tokyo.jp",
+ "hino.tokyo.jp",
+ "hinode.tokyo.jp",
+ "hinohara.tokyo.jp",
+ "inagi.tokyo.jp",
+ "itabashi.tokyo.jp",
+ "katsushika.tokyo.jp",
+ "kita.tokyo.jp",
+ "kiyose.tokyo.jp",
+ "kodaira.tokyo.jp",
+ "koganei.tokyo.jp",
+ "kokubunji.tokyo.jp",
+ "komae.tokyo.jp",
+ "koto.tokyo.jp",
+ "kouzushima.tokyo.jp",
+ "kunitachi.tokyo.jp",
+ "machida.tokyo.jp",
+ "meguro.tokyo.jp",
+ "minato.tokyo.jp",
+ "mitaka.tokyo.jp",
+ "mizuho.tokyo.jp",
+ "musashimurayama.tokyo.jp",
+ "musashino.tokyo.jp",
+ "nakano.tokyo.jp",
+ "nerima.tokyo.jp",
+ "ogasawara.tokyo.jp",
+ "okutama.tokyo.jp",
+ "ome.tokyo.jp",
+ "oshima.tokyo.jp",
+ "ota.tokyo.jp",
+ "setagaya.tokyo.jp",
+ "shibuya.tokyo.jp",
+ "shinagawa.tokyo.jp",
+ "shinjuku.tokyo.jp",
+ "suginami.tokyo.jp",
+ "sumida.tokyo.jp",
+ "tachikawa.tokyo.jp",
+ "taito.tokyo.jp",
+ "tama.tokyo.jp",
+ "toshima.tokyo.jp",
+ "chizu.tottori.jp",
+ "hino.tottori.jp",
+ "kawahara.tottori.jp",
+ "koge.tottori.jp",
+ "kotoura.tottori.jp",
+ "misasa.tottori.jp",
+ "nanbu.tottori.jp",
+ "nichinan.tottori.jp",
+ "sakaiminato.tottori.jp",
+ "tottori.tottori.jp",
+ "wakasa.tottori.jp",
+ "yazu.tottori.jp",
+ "yonago.tottori.jp",
+ "asahi.toyama.jp",
+ "fuchu.toyama.jp",
+ "fukumitsu.toyama.jp",
+ "funahashi.toyama.jp",
+ "himi.toyama.jp",
+ "imizu.toyama.jp",
+ "inami.toyama.jp",
+ "johana.toyama.jp",
+ "kamiichi.toyama.jp",
+ "kurobe.toyama.jp",
+ "nakaniikawa.toyama.jp",
+ "namerikawa.toyama.jp",
+ "nanto.toyama.jp",
+ "nyuzen.toyama.jp",
+ "oyabe.toyama.jp",
+ "taira.toyama.jp",
+ "takaoka.toyama.jp",
+ "tateyama.toyama.jp",
+ "toga.toyama.jp",
+ "tonami.toyama.jp",
+ "toyama.toyama.jp",
+ "unazuki.toyama.jp",
+ "uozu.toyama.jp",
+ "yamada.toyama.jp",
+ "arida.wakayama.jp",
+ "aridagawa.wakayama.jp",
+ "gobo.wakayama.jp",
+ "hashimoto.wakayama.jp",
+ "hidaka.wakayama.jp",
+ "hirogawa.wakayama.jp",
+ "inami.wakayama.jp",
+ "iwade.wakayama.jp",
+ "kainan.wakayama.jp",
+ "kamitonda.wakayama.jp",
+ "katsuragi.wakayama.jp",
+ "kimino.wakayama.jp",
+ "kinokawa.wakayama.jp",
+ "kitayama.wakayama.jp",
+ "koya.wakayama.jp",
+ "koza.wakayama.jp",
+ "kozagawa.wakayama.jp",
+ "kudoyama.wakayama.jp",
+ "kushimoto.wakayama.jp",
+ "mihama.wakayama.jp",
+ "misato.wakayama.jp",
+ "nachikatsuura.wakayama.jp",
+ "shingu.wakayama.jp",
+ "shirahama.wakayama.jp",
+ "taiji.wakayama.jp",
+ "tanabe.wakayama.jp",
+ "wakayama.wakayama.jp",
+ "yuasa.wakayama.jp",
+ "yura.wakayama.jp",
+ "asahi.yamagata.jp",
+ "funagata.yamagata.jp",
+ "higashine.yamagata.jp",
+ "iide.yamagata.jp",
+ "kahoku.yamagata.jp",
+ "kaminoyama.yamagata.jp",
+ "kaneyama.yamagata.jp",
+ "kawanishi.yamagata.jp",
+ "mamurogawa.yamagata.jp",
+ "mikawa.yamagata.jp",
+ "murayama.yamagata.jp",
+ "nagai.yamagata.jp",
+ "nakayama.yamagata.jp",
+ "nanyo.yamagata.jp",
+ "nishikawa.yamagata.jp",
+ "obanazawa.yamagata.jp",
+ "oe.yamagata.jp",
+ "oguni.yamagata.jp",
+ "ohkura.yamagata.jp",
+ "oishida.yamagata.jp",
+ "sagae.yamagata.jp",
+ "sakata.yamagata.jp",
+ "sakegawa.yamagata.jp",
+ "shinjo.yamagata.jp",
+ "shirataka.yamagata.jp",
+ "shonai.yamagata.jp",
+ "takahata.yamagata.jp",
+ "tendo.yamagata.jp",
+ "tozawa.yamagata.jp",
+ "tsuruoka.yamagata.jp",
+ "yamagata.yamagata.jp",
+ "yamanobe.yamagata.jp",
+ "yonezawa.yamagata.jp",
+ "yuza.yamagata.jp",
+ "abu.yamaguchi.jp",
+ "hagi.yamaguchi.jp",
+ "hikari.yamaguchi.jp",
+ "hofu.yamaguchi.jp",
+ "iwakuni.yamaguchi.jp",
+ "kudamatsu.yamaguchi.jp",
+ "mitou.yamaguchi.jp",
+ "nagato.yamaguchi.jp",
+ "oshima.yamaguchi.jp",
+ "shimonoseki.yamaguchi.jp",
+ "shunan.yamaguchi.jp",
+ "tabuse.yamaguchi.jp",
+ "tokuyama.yamaguchi.jp",
+ "toyota.yamaguchi.jp",
+ "ube.yamaguchi.jp",
+ "yuu.yamaguchi.jp",
+ "chuo.yamanashi.jp",
+ "doshi.yamanashi.jp",
+ "fuefuki.yamanashi.jp",
+ "fujikawa.yamanashi.jp",
+ "fujikawaguchiko.yamanashi.jp",
+ "fujiyoshida.yamanashi.jp",
+ "hayakawa.yamanashi.jp",
+ "hokuto.yamanashi.jp",
+ "ichikawamisato.yamanashi.jp",
+ "kai.yamanashi.jp",
+ "kofu.yamanashi.jp",
+ "koshu.yamanashi.jp",
+ "kosuge.yamanashi.jp",
+ "minami-alps.yamanashi.jp",
+ "minobu.yamanashi.jp",
+ "nakamichi.yamanashi.jp",
+ "nanbu.yamanashi.jp",
+ "narusawa.yamanashi.jp",
+ "nirasaki.yamanashi.jp",
+ "nishikatsura.yamanashi.jp",
+ "oshino.yamanashi.jp",
+ "otsuki.yamanashi.jp",
+ "showa.yamanashi.jp",
+ "tabayama.yamanashi.jp",
+ "tsuru.yamanashi.jp",
+ "uenohara.yamanashi.jp",
+ "yamanakako.yamanashi.jp",
+ "yamanashi.yamanashi.jp",
+ "*.ke",
+ "kg",
+ "org.kg",
+ "net.kg",
+ "com.kg",
+ "edu.kg",
+ "gov.kg",
+ "mil.kg",
+ "*.kh",
+ "ki",
+ "edu.ki",
+ "biz.ki",
+ "net.ki",
+ "org.ki",
+ "gov.ki",
+ "info.ki",
+ "com.ki",
+ "km",
+ "org.km",
+ "nom.km",
+ "gov.km",
+ "prd.km",
+ "tm.km",
+ "edu.km",
+ "mil.km",
+ "ass.km",
+ "com.km",
+ "coop.km",
+ "asso.km",
+ "presse.km",
+ "medecin.km",
+ "notaires.km",
+ "pharmaciens.km",
+ "veterinaire.km",
+ "gouv.km",
+ "kn",
+ "net.kn",
+ "org.kn",
+ "edu.kn",
+ "gov.kn",
+ "kp",
+ "com.kp",
+ "edu.kp",
+ "gov.kp",
+ "org.kp",
+ "rep.kp",
+ "tra.kp",
+ "kr",
+ "ac.kr",
+ "co.kr",
+ "es.kr",
+ "go.kr",
+ "hs.kr",
+ "kg.kr",
+ "mil.kr",
+ "ms.kr",
+ "ne.kr",
+ "or.kr",
+ "pe.kr",
+ "re.kr",
+ "sc.kr",
+ "busan.kr",
+ "chungbuk.kr",
+ "chungnam.kr",
+ "daegu.kr",
+ "daejeon.kr",
+ "gangwon.kr",
+ "gwangju.kr",
+ "gyeongbuk.kr",
+ "gyeonggi.kr",
+ "gyeongnam.kr",
+ "incheon.kr",
+ "jeju.kr",
+ "jeonbuk.kr",
+ "jeonnam.kr",
+ "seoul.kr",
+ "ulsan.kr",
+ "*.kw",
+ "ky",
+ "edu.ky",
+ "gov.ky",
+ "com.ky",
+ "org.ky",
+ "net.ky",
+ "kz",
+ "org.kz",
+ "edu.kz",
+ "net.kz",
+ "gov.kz",
+ "mil.kz",
+ "com.kz",
+ "la",
+ "int.la",
+ "net.la",
+ "info.la",
+ "edu.la",
+ "gov.la",
+ "per.la",
+ "com.la",
+ "org.la",
+ "lb",
+ "com.lb",
+ "edu.lb",
+ "gov.lb",
+ "net.lb",
+ "org.lb",
+ "lc",
+ "com.lc",
+ "net.lc",
+ "co.lc",
+ "org.lc",
+ "edu.lc",
+ "gov.lc",
+ "li",
+ "lk",
+ "gov.lk",
+ "sch.lk",
+ "net.lk",
+ "int.lk",
+ "com.lk",
+ "org.lk",
+ "edu.lk",
+ "ngo.lk",
+ "soc.lk",
+ "web.lk",
+ "ltd.lk",
+ "assn.lk",
+ "grp.lk",
+ "hotel.lk",
+ "ac.lk",
+ "lr",
+ "com.lr",
+ "edu.lr",
+ "gov.lr",
+ "org.lr",
+ "net.lr",
+ "ls",
+ "co.ls",
+ "org.ls",
+ "lt",
+ "gov.lt",
+ "lu",
+ "lv",
+ "com.lv",
+ "edu.lv",
+ "gov.lv",
+ "org.lv",
+ "mil.lv",
+ "id.lv",
+ "net.lv",
+ "asn.lv",
+ "conf.lv",
+ "ly",
+ "com.ly",
+ "net.ly",
+ "gov.ly",
+ "plc.ly",
+ "edu.ly",
+ "sch.ly",
+ "med.ly",
+ "org.ly",
+ "id.ly",
+ "ma",
+ "co.ma",
+ "net.ma",
+ "gov.ma",
+ "org.ma",
+ "ac.ma",
+ "press.ma",
+ "mc",
+ "tm.mc",
+ "asso.mc",
+ "md",
+ "me",
+ "co.me",
+ "net.me",
+ "org.me",
+ "edu.me",
+ "ac.me",
+ "gov.me",
+ "its.me",
+ "priv.me",
+ "mg",
+ "org.mg",
+ "nom.mg",
+ "gov.mg",
+ "prd.mg",
+ "tm.mg",
+ "edu.mg",
+ "mil.mg",
+ "com.mg",
+ "co.mg",
+ "mh",
+ "mil",
+ "mk",
+ "com.mk",
+ "org.mk",
+ "net.mk",
+ "edu.mk",
+ "gov.mk",
+ "inf.mk",
+ "name.mk",
+ "ml",
+ "com.ml",
+ "edu.ml",
+ "gouv.ml",
+ "gov.ml",
+ "net.ml",
+ "org.ml",
+ "presse.ml",
+ "*.mm",
+ "mn",
+ "gov.mn",
+ "edu.mn",
+ "org.mn",
+ "mo",
+ "com.mo",
+ "net.mo",
+ "org.mo",
+ "edu.mo",
+ "gov.mo",
+ "mobi",
+ "mp",
+ "mq",
+ "mr",
+ "gov.mr",
+ "ms",
+ "com.ms",
+ "edu.ms",
+ "gov.ms",
+ "net.ms",
+ "org.ms",
+ "mt",
+ "com.mt",
+ "edu.mt",
+ "net.mt",
+ "org.mt",
+ "mu",
+ "com.mu",
+ "net.mu",
+ "org.mu",
+ "gov.mu",
+ "ac.mu",
+ "co.mu",
+ "or.mu",
+ "museum",
+ "academy.museum",
+ "agriculture.museum",
+ "air.museum",
+ "airguard.museum",
+ "alabama.museum",
+ "alaska.museum",
+ "amber.museum",
+ "ambulance.museum",
+ "american.museum",
+ "americana.museum",
+ "americanantiques.museum",
+ "americanart.museum",
+ "amsterdam.museum",
+ "and.museum",
+ "annefrank.museum",
+ "anthro.museum",
+ "anthropology.museum",
+ "antiques.museum",
+ "aquarium.museum",
+ "arboretum.museum",
+ "archaeological.museum",
+ "archaeology.museum",
+ "architecture.museum",
+ "art.museum",
+ "artanddesign.museum",
+ "artcenter.museum",
+ "artdeco.museum",
+ "arteducation.museum",
+ "artgallery.museum",
+ "arts.museum",
+ "artsandcrafts.museum",
+ "asmatart.museum",
+ "assassination.museum",
+ "assisi.museum",
+ "association.museum",
+ "astronomy.museum",
+ "atlanta.museum",
+ "austin.museum",
+ "australia.museum",
+ "automotive.museum",
+ "aviation.museum",
+ "axis.museum",
+ "badajoz.museum",
+ "baghdad.museum",
+ "bahn.museum",
+ "bale.museum",
+ "baltimore.museum",
+ "barcelona.museum",
+ "baseball.museum",
+ "basel.museum",
+ "baths.museum",
+ "bauern.museum",
+ "beauxarts.museum",
+ "beeldengeluid.museum",
+ "bellevue.museum",
+ "bergbau.museum",
+ "berkeley.museum",
+ "berlin.museum",
+ "bern.museum",
+ "bible.museum",
+ "bilbao.museum",
+ "bill.museum",
+ "birdart.museum",
+ "birthplace.museum",
+ "bonn.museum",
+ "boston.museum",
+ "botanical.museum",
+ "botanicalgarden.museum",
+ "botanicgarden.museum",
+ "botany.museum",
+ "brandywinevalley.museum",
+ "brasil.museum",
+ "bristol.museum",
+ "british.museum",
+ "britishcolumbia.museum",
+ "broadcast.museum",
+ "brunel.museum",
+ "brussel.museum",
+ "brussels.museum",
+ "bruxelles.museum",
+ "building.museum",
+ "burghof.museum",
+ "bus.museum",
+ "bushey.museum",
+ "cadaques.museum",
+ "california.museum",
+ "cambridge.museum",
+ "can.museum",
+ "canada.museum",
+ "capebreton.museum",
+ "carrier.museum",
+ "cartoonart.museum",
+ "casadelamoneda.museum",
+ "castle.museum",
+ "castres.museum",
+ "celtic.museum",
+ "center.museum",
+ "chattanooga.museum",
+ "cheltenham.museum",
+ "chesapeakebay.museum",
+ "chicago.museum",
+ "children.museum",
+ "childrens.museum",
+ "childrensgarden.museum",
+ "chiropractic.museum",
+ "chocolate.museum",
+ "christiansburg.museum",
+ "cincinnati.museum",
+ "cinema.museum",
+ "circus.museum",
+ "civilisation.museum",
+ "civilization.museum",
+ "civilwar.museum",
+ "clinton.museum",
+ "clock.museum",
+ "coal.museum",
+ "coastaldefence.museum",
+ "cody.museum",
+ "coldwar.museum",
+ "collection.museum",
+ "colonialwilliamsburg.museum",
+ "coloradoplateau.museum",
+ "columbia.museum",
+ "columbus.museum",
+ "communication.museum",
+ "communications.museum",
+ "community.museum",
+ "computer.museum",
+ "computerhistory.museum",
+ "xn--comunicaes-v6a2o.museum",
+ "contemporary.museum",
+ "contemporaryart.museum",
+ "convent.museum",
+ "copenhagen.museum",
+ "corporation.museum",
+ "xn--correios-e-telecomunicaes-ghc29a.museum",
+ "corvette.museum",
+ "costume.museum",
+ "countryestate.museum",
+ "county.museum",
+ "crafts.museum",
+ "cranbrook.museum",
+ "creation.museum",
+ "cultural.museum",
+ "culturalcenter.museum",
+ "culture.museum",
+ "cyber.museum",
+ "cymru.museum",
+ "dali.museum",
+ "dallas.museum",
+ "database.museum",
+ "ddr.museum",
+ "decorativearts.museum",
+ "delaware.museum",
+ "delmenhorst.museum",
+ "denmark.museum",
+ "depot.museum",
+ "design.museum",
+ "detroit.museum",
+ "dinosaur.museum",
+ "discovery.museum",
+ "dolls.museum",
+ "donostia.museum",
+ "durham.museum",
+ "eastafrica.museum",
+ "eastcoast.museum",
+ "education.museum",
+ "educational.museum",
+ "egyptian.museum",
+ "eisenbahn.museum",
+ "elburg.museum",
+ "elvendrell.museum",
+ "embroidery.museum",
+ "encyclopedic.museum",
+ "england.museum",
+ "entomology.museum",
+ "environment.museum",
+ "environmentalconservation.museum",
+ "epilepsy.museum",
+ "essex.museum",
+ "estate.museum",
+ "ethnology.museum",
+ "exeter.museum",
+ "exhibition.museum",
+ "family.museum",
+ "farm.museum",
+ "farmequipment.museum",
+ "farmers.museum",
+ "farmstead.museum",
+ "field.museum",
+ "figueres.museum",
+ "filatelia.museum",
+ "film.museum",
+ "fineart.museum",
+ "finearts.museum",
+ "finland.museum",
+ "flanders.museum",
+ "florida.museum",
+ "force.museum",
+ "fortmissoula.museum",
+ "fortworth.museum",
+ "foundation.museum",
+ "francaise.museum",
+ "frankfurt.museum",
+ "franziskaner.museum",
+ "freemasonry.museum",
+ "freiburg.museum",
+ "fribourg.museum",
+ "frog.museum",
+ "fundacio.museum",
+ "furniture.museum",
+ "gallery.museum",
+ "garden.museum",
+ "gateway.museum",
+ "geelvinck.museum",
+ "gemological.museum",
+ "geology.museum",
+ "georgia.museum",
+ "giessen.museum",
+ "glas.museum",
+ "glass.museum",
+ "gorge.museum",
+ "grandrapids.museum",
+ "graz.museum",
+ "guernsey.museum",
+ "halloffame.museum",
+ "hamburg.museum",
+ "handson.museum",
+ "harvestcelebration.museum",
+ "hawaii.museum",
+ "health.museum",
+ "heimatunduhren.museum",
+ "hellas.museum",
+ "helsinki.museum",
+ "hembygdsforbund.museum",
+ "heritage.museum",
+ "histoire.museum",
+ "historical.museum",
+ "historicalsociety.museum",
+ "historichouses.museum",
+ "historisch.museum",
+ "historisches.museum",
+ "history.museum",
+ "historyofscience.museum",
+ "horology.museum",
+ "house.museum",
+ "humanities.museum",
+ "illustration.museum",
+ "imageandsound.museum",
+ "indian.museum",
+ "indiana.museum",
+ "indianapolis.museum",
+ "indianmarket.museum",
+ "intelligence.museum",
+ "interactive.museum",
+ "iraq.museum",
+ "iron.museum",
+ "isleofman.museum",
+ "jamison.museum",
+ "jefferson.museum",
+ "jerusalem.museum",
+ "jewelry.museum",
+ "jewish.museum",
+ "jewishart.museum",
+ "jfk.museum",
+ "journalism.museum",
+ "judaica.museum",
+ "judygarland.museum",
+ "juedisches.museum",
+ "juif.museum",
+ "karate.museum",
+ "karikatur.museum",
+ "kids.museum",
+ "koebenhavn.museum",
+ "koeln.museum",
+ "kunst.museum",
+ "kunstsammlung.museum",
+ "kunstunddesign.museum",
+ "labor.museum",
+ "labour.museum",
+ "lajolla.museum",
+ "lancashire.museum",
+ "landes.museum",
+ "lans.museum",
+ "xn--lns-qla.museum",
+ "larsson.museum",
+ "lewismiller.museum",
+ "lincoln.museum",
+ "linz.museum",
+ "living.museum",
+ "livinghistory.museum",
+ "localhistory.museum",
+ "london.museum",
+ "losangeles.museum",
+ "louvre.museum",
+ "loyalist.museum",
+ "lucerne.museum",
+ "luxembourg.museum",
+ "luzern.museum",
+ "mad.museum",
+ "madrid.museum",
+ "mallorca.museum",
+ "manchester.museum",
+ "mansion.museum",
+ "mansions.museum",
+ "manx.museum",
+ "marburg.museum",
+ "maritime.museum",
+ "maritimo.museum",
+ "maryland.museum",
+ "marylhurst.museum",
+ "media.museum",
+ "medical.museum",
+ "medizinhistorisches.museum",
+ "meeres.museum",
+ "memorial.museum",
+ "mesaverde.museum",
+ "michigan.museum",
+ "midatlantic.museum",
+ "military.museum",
+ "mill.museum",
+ "miners.museum",
+ "mining.museum",
+ "minnesota.museum",
+ "missile.museum",
+ "missoula.museum",
+ "modern.museum",
+ "moma.museum",
+ "money.museum",
+ "monmouth.museum",
+ "monticello.museum",
+ "montreal.museum",
+ "moscow.museum",
+ "motorcycle.museum",
+ "muenchen.museum",
+ "muenster.museum",
+ "mulhouse.museum",
+ "muncie.museum",
+ "museet.museum",
+ "museumcenter.museum",
+ "museumvereniging.museum",
+ "music.museum",
+ "national.museum",
+ "nationalfirearms.museum",
+ "nationalheritage.museum",
+ "nativeamerican.museum",
+ "naturalhistory.museum",
+ "naturalhistorymuseum.museum",
+ "naturalsciences.museum",
+ "nature.museum",
+ "naturhistorisches.museum",
+ "natuurwetenschappen.museum",
+ "naumburg.museum",
+ "naval.museum",
+ "nebraska.museum",
+ "neues.museum",
+ "newhampshire.museum",
+ "newjersey.museum",
+ "newmexico.museum",
+ "newport.museum",
+ "newspaper.museum",
+ "newyork.museum",
+ "niepce.museum",
+ "norfolk.museum",
+ "north.museum",
+ "nrw.museum",
+ "nuernberg.museum",
+ "nuremberg.museum",
+ "nyc.museum",
+ "nyny.museum",
+ "oceanographic.museum",
+ "oceanographique.museum",
+ "omaha.museum",
+ "online.museum",
+ "ontario.museum",
+ "openair.museum",
+ "oregon.museum",
+ "oregontrail.museum",
+ "otago.museum",
+ "oxford.museum",
+ "pacific.museum",
+ "paderborn.museum",
+ "palace.museum",
+ "paleo.museum",
+ "palmsprings.museum",
+ "panama.museum",
+ "paris.museum",
+ "pasadena.museum",
+ "pharmacy.museum",
+ "philadelphia.museum",
+ "philadelphiaarea.museum",
+ "philately.museum",
+ "phoenix.museum",
+ "photography.museum",
+ "pilots.museum",
+ "pittsburgh.museum",
+ "planetarium.museum",
+ "plantation.museum",
+ "plants.museum",
+ "plaza.museum",
+ "portal.museum",
+ "portland.museum",
+ "portlligat.museum",
+ "posts-and-telecommunications.museum",
+ "preservation.museum",
+ "presidio.museum",
+ "press.museum",
+ "project.museum",
+ "public.museum",
+ "pubol.museum",
+ "quebec.museum",
+ "railroad.museum",
+ "railway.museum",
+ "research.museum",
+ "resistance.museum",
+ "riodejaneiro.museum",
+ "rochester.museum",
+ "rockart.museum",
+ "roma.museum",
+ "russia.museum",
+ "saintlouis.museum",
+ "salem.museum",
+ "salvadordali.museum",
+ "salzburg.museum",
+ "sandiego.museum",
+ "sanfrancisco.museum",
+ "santabarbara.museum",
+ "santacruz.museum",
+ "santafe.museum",
+ "saskatchewan.museum",
+ "satx.museum",
+ "savannahga.museum",
+ "schlesisches.museum",
+ "schoenbrunn.museum",
+ "schokoladen.museum",
+ "school.museum",
+ "schweiz.museum",
+ "science.museum",
+ "scienceandhistory.museum",
+ "scienceandindustry.museum",
+ "sciencecenter.museum",
+ "sciencecenters.museum",
+ "science-fiction.museum",
+ "sciencehistory.museum",
+ "sciences.museum",
+ "sciencesnaturelles.museum",
+ "scotland.museum",
+ "seaport.museum",
+ "settlement.museum",
+ "settlers.museum",
+ "shell.museum",
+ "sherbrooke.museum",
+ "sibenik.museum",
+ "silk.museum",
+ "ski.museum",
+ "skole.museum",
+ "society.museum",
+ "sologne.museum",
+ "soundandvision.museum",
+ "southcarolina.museum",
+ "southwest.museum",
+ "space.museum",
+ "spy.museum",
+ "square.museum",
+ "stadt.museum",
+ "stalbans.museum",
+ "starnberg.museum",
+ "state.museum",
+ "stateofdelaware.museum",
+ "station.museum",
+ "steam.museum",
+ "steiermark.museum",
+ "stjohn.museum",
+ "stockholm.museum",
+ "stpetersburg.museum",
+ "stuttgart.museum",
+ "suisse.museum",
+ "surgeonshall.museum",
+ "surrey.museum",
+ "svizzera.museum",
+ "sweden.museum",
+ "sydney.museum",
+ "tank.museum",
+ "tcm.museum",
+ "technology.museum",
+ "telekommunikation.museum",
+ "television.museum",
+ "texas.museum",
+ "textile.museum",
+ "theater.museum",
+ "time.museum",
+ "timekeeping.museum",
+ "topology.museum",
+ "torino.museum",
+ "touch.museum",
+ "town.museum",
+ "transport.museum",
+ "tree.museum",
+ "trolley.museum",
+ "trust.museum",
+ "trustee.museum",
+ "uhren.museum",
+ "ulm.museum",
+ "undersea.museum",
+ "university.museum",
+ "usa.museum",
+ "usantiques.museum",
+ "usarts.museum",
+ "uscountryestate.museum",
+ "usculture.museum",
+ "usdecorativearts.museum",
+ "usgarden.museum",
+ "ushistory.museum",
+ "ushuaia.museum",
+ "uslivinghistory.museum",
+ "utah.museum",
+ "uvic.museum",
+ "valley.museum",
+ "vantaa.museum",
+ "versailles.museum",
+ "viking.museum",
+ "village.museum",
+ "virginia.museum",
+ "virtual.museum",
+ "virtuel.museum",
+ "vlaanderen.museum",
+ "volkenkunde.museum",
+ "wales.museum",
+ "wallonie.museum",
+ "war.museum",
+ "washingtondc.museum",
+ "watchandclock.museum",
+ "watch-and-clock.museum",
+ "western.museum",
+ "westfalen.museum",
+ "whaling.museum",
+ "wildlife.museum",
+ "williamsburg.museum",
+ "windmill.museum",
+ "workshop.museum",
+ "york.museum",
+ "yorkshire.museum",
+ "yosemite.museum",
+ "youth.museum",
+ "zoological.museum",
+ "zoology.museum",
+ "xn--9dbhblg6di.museum",
+ "xn--h1aegh.museum",
+ "mv",
+ "aero.mv",
+ "biz.mv",
+ "com.mv",
+ "coop.mv",
+ "edu.mv",
+ "gov.mv",
+ "info.mv",
+ "int.mv",
+ "mil.mv",
+ "museum.mv",
+ "name.mv",
+ "net.mv",
+ "org.mv",
+ "pro.mv",
+ "mw",
+ "ac.mw",
+ "biz.mw",
+ "co.mw",
+ "com.mw",
+ "coop.mw",
+ "edu.mw",
+ "gov.mw",
+ "int.mw",
+ "museum.mw",
+ "net.mw",
+ "org.mw",
+ "mx",
+ "com.mx",
+ "org.mx",
+ "gob.mx",
+ "edu.mx",
+ "net.mx",
+ "my",
+ "com.my",
+ "net.my",
+ "org.my",
+ "gov.my",
+ "edu.my",
+ "mil.my",
+ "name.my",
+ "mz",
+ "ac.mz",
+ "adv.mz",
+ "co.mz",
+ "edu.mz",
+ "gov.mz",
+ "mil.mz",
+ "net.mz",
+ "org.mz",
+ "na",
+ "info.na",
+ "pro.na",
+ "name.na",
+ "school.na",
+ "or.na",
+ "dr.na",
+ "us.na",
+ "mx.na",
+ "ca.na",
+ "in.na",
+ "cc.na",
+ "tv.na",
+ "ws.na",
+ "mobi.na",
+ "co.na",
+ "com.na",
+ "org.na",
+ "name",
+ "nc",
+ "asso.nc",
+ "nom.nc",
+ "ne",
+ "net",
+ "nf",
+ "com.nf",
+ "net.nf",
+ "per.nf",
+ "rec.nf",
+ "web.nf",
+ "arts.nf",
+ "firm.nf",
+ "info.nf",
+ "other.nf",
+ "store.nf",
+ "ng",
+ "com.ng",
+ "edu.ng",
+ "gov.ng",
+ "i.ng",
+ "mil.ng",
+ "mobi.ng",
+ "name.ng",
+ "net.ng",
+ "org.ng",
+ "sch.ng",
+ "ni",
+ "ac.ni",
+ "biz.ni",
+ "co.ni",
+ "com.ni",
+ "edu.ni",
+ "gob.ni",
+ "in.ni",
+ "info.ni",
+ "int.ni",
+ "mil.ni",
+ "net.ni",
+ "nom.ni",
+ "org.ni",
+ "web.ni",
+ "nl",
+ "bv.nl",
+ "no",
+ "fhs.no",
+ "vgs.no",
+ "fylkesbibl.no",
+ "folkebibl.no",
+ "museum.no",
+ "idrett.no",
+ "priv.no",
+ "mil.no",
+ "stat.no",
+ "dep.no",
+ "kommune.no",
+ "herad.no",
+ "aa.no",
+ "ah.no",
+ "bu.no",
+ "fm.no",
+ "hl.no",
+ "hm.no",
+ "jan-mayen.no",
+ "mr.no",
+ "nl.no",
+ "nt.no",
+ "of.no",
+ "ol.no",
+ "oslo.no",
+ "rl.no",
+ "sf.no",
+ "st.no",
+ "svalbard.no",
+ "tm.no",
+ "tr.no",
+ "va.no",
+ "vf.no",
+ "gs.aa.no",
+ "gs.ah.no",
+ "gs.bu.no",
+ "gs.fm.no",
+ "gs.hl.no",
+ "gs.hm.no",
+ "gs.jan-mayen.no",
+ "gs.mr.no",
+ "gs.nl.no",
+ "gs.nt.no",
+ "gs.of.no",
+ "gs.ol.no",
+ "gs.oslo.no",
+ "gs.rl.no",
+ "gs.sf.no",
+ "gs.st.no",
+ "gs.svalbard.no",
+ "gs.tm.no",
+ "gs.tr.no",
+ "gs.va.no",
+ "gs.vf.no",
+ "akrehamn.no",
+ "xn--krehamn-dxa.no",
+ "algard.no",
+ "xn--lgrd-poac.no",
+ "arna.no",
+ "brumunddal.no",
+ "bryne.no",
+ "bronnoysund.no",
+ "xn--brnnysund-m8ac.no",
+ "drobak.no",
+ "xn--drbak-wua.no",
+ "egersund.no",
+ "fetsund.no",
+ "floro.no",
+ "xn--flor-jra.no",
+ "fredrikstad.no",
+ "hokksund.no",
+ "honefoss.no",
+ "xn--hnefoss-q1a.no",
+ "jessheim.no",
+ "jorpeland.no",
+ "xn--jrpeland-54a.no",
+ "kirkenes.no",
+ "kopervik.no",
+ "krokstadelva.no",
+ "langevag.no",
+ "xn--langevg-jxa.no",
+ "leirvik.no",
+ "mjondalen.no",
+ "xn--mjndalen-64a.no",
+ "mo-i-rana.no",
+ "mosjoen.no",
+ "xn--mosjen-eya.no",
+ "nesoddtangen.no",
+ "orkanger.no",
+ "osoyro.no",
+ "xn--osyro-wua.no",
+ "raholt.no",
+ "xn--rholt-mra.no",
+ "sandnessjoen.no",
+ "xn--sandnessjen-ogb.no",
+ "skedsmokorset.no",
+ "slattum.no",
+ "spjelkavik.no",
+ "stathelle.no",
+ "stavern.no",
+ "stjordalshalsen.no",
+ "xn--stjrdalshalsen-sqb.no",
+ "tananger.no",
+ "tranby.no",
+ "vossevangen.no",
+ "afjord.no",
+ "xn--fjord-lra.no",
+ "agdenes.no",
+ "al.no",
+ "xn--l-1fa.no",
+ "alesund.no",
+ "xn--lesund-hua.no",
+ "alstahaug.no",
+ "alta.no",
+ "xn--lt-liac.no",
+ "alaheadju.no",
+ "xn--laheadju-7ya.no",
+ "alvdal.no",
+ "amli.no",
+ "xn--mli-tla.no",
+ "amot.no",
+ "xn--mot-tla.no",
+ "andebu.no",
+ "andoy.no",
+ "xn--andy-ira.no",
+ "andasuolo.no",
+ "ardal.no",
+ "xn--rdal-poa.no",
+ "aremark.no",
+ "arendal.no",
+ "xn--s-1fa.no",
+ "aseral.no",
+ "xn--seral-lra.no",
+ "asker.no",
+ "askim.no",
+ "askvoll.no",
+ "askoy.no",
+ "xn--asky-ira.no",
+ "asnes.no",
+ "xn--snes-poa.no",
+ "audnedaln.no",
+ "aukra.no",
+ "aure.no",
+ "aurland.no",
+ "aurskog-holand.no",
+ "xn--aurskog-hland-jnb.no",
+ "austevoll.no",
+ "austrheim.no",
+ "averoy.no",
+ "xn--avery-yua.no",
+ "balestrand.no",
+ "ballangen.no",
+ "balat.no",
+ "xn--blt-elab.no",
+ "balsfjord.no",
+ "bahccavuotna.no",
+ "xn--bhccavuotna-k7a.no",
+ "bamble.no",
+ "bardu.no",
+ "beardu.no",
+ "beiarn.no",
+ "bajddar.no",
+ "xn--bjddar-pta.no",
+ "baidar.no",
+ "xn--bidr-5nac.no",
+ "berg.no",
+ "bergen.no",
+ "berlevag.no",
+ "xn--berlevg-jxa.no",
+ "bearalvahki.no",
+ "xn--bearalvhki-y4a.no",
+ "bindal.no",
+ "birkenes.no",
+ "bjarkoy.no",
+ "xn--bjarky-fya.no",
+ "bjerkreim.no",
+ "bjugn.no",
+ "bodo.no",
+ "xn--bod-2na.no",
+ "badaddja.no",
+ "xn--bdddj-mrabd.no",
+ "budejju.no",
+ "bokn.no",
+ "bremanger.no",
+ "bronnoy.no",
+ "xn--brnny-wuac.no",
+ "bygland.no",
+ "bykle.no",
+ "barum.no",
+ "xn--brum-voa.no",
+ "bo.telemark.no",
+ "xn--b-5ga.telemark.no",
+ "bo.nordland.no",
+ "xn--b-5ga.nordland.no",
+ "bievat.no",
+ "xn--bievt-0qa.no",
+ "bomlo.no",
+ "xn--bmlo-gra.no",
+ "batsfjord.no",
+ "xn--btsfjord-9za.no",
+ "bahcavuotna.no",
+ "xn--bhcavuotna-s4a.no",
+ "dovre.no",
+ "drammen.no",
+ "drangedal.no",
+ "dyroy.no",
+ "xn--dyry-ira.no",
+ "donna.no",
+ "xn--dnna-gra.no",
+ "eid.no",
+ "eidfjord.no",
+ "eidsberg.no",
+ "eidskog.no",
+ "eidsvoll.no",
+ "eigersund.no",
+ "elverum.no",
+ "enebakk.no",
+ "engerdal.no",
+ "etne.no",
+ "etnedal.no",
+ "evenes.no",
+ "evenassi.no",
+ "xn--eveni-0qa01ga.no",
+ "evje-og-hornnes.no",
+ "farsund.no",
+ "fauske.no",
+ "fuossko.no",
+ "fuoisku.no",
+ "fedje.no",
+ "fet.no",
+ "finnoy.no",
+ "xn--finny-yua.no",
+ "fitjar.no",
+ "fjaler.no",
+ "fjell.no",
+ "flakstad.no",
+ "flatanger.no",
+ "flekkefjord.no",
+ "flesberg.no",
+ "flora.no",
+ "fla.no",
+ "xn--fl-zia.no",
+ "folldal.no",
+ "forsand.no",
+ "fosnes.no",
+ "frei.no",
+ "frogn.no",
+ "froland.no",
+ "frosta.no",
+ "frana.no",
+ "xn--frna-woa.no",
+ "froya.no",
+ "xn--frya-hra.no",
+ "fusa.no",
+ "fyresdal.no",
+ "forde.no",
+ "xn--frde-gra.no",
+ "gamvik.no",
+ "gangaviika.no",
+ "xn--ggaviika-8ya47h.no",
+ "gaular.no",
+ "gausdal.no",
+ "gildeskal.no",
+ "xn--gildeskl-g0a.no",
+ "giske.no",
+ "gjemnes.no",
+ "gjerdrum.no",
+ "gjerstad.no",
+ "gjesdal.no",
+ "gjovik.no",
+ "xn--gjvik-wua.no",
+ "gloppen.no",
+ "gol.no",
+ "gran.no",
+ "grane.no",
+ "granvin.no",
+ "gratangen.no",
+ "grimstad.no",
+ "grong.no",
+ "kraanghke.no",
+ "xn--kranghke-b0a.no",
+ "grue.no",
+ "gulen.no",
+ "hadsel.no",
+ "halden.no",
+ "halsa.no",
+ "hamar.no",
+ "hamaroy.no",
+ "habmer.no",
+ "xn--hbmer-xqa.no",
+ "hapmir.no",
+ "xn--hpmir-xqa.no",
+ "hammerfest.no",
+ "hammarfeasta.no",
+ "xn--hmmrfeasta-s4ac.no",
+ "haram.no",
+ "hareid.no",
+ "harstad.no",
+ "hasvik.no",
+ "aknoluokta.no",
+ "xn--koluokta-7ya57h.no",
+ "hattfjelldal.no",
+ "aarborte.no",
+ "haugesund.no",
+ "hemne.no",
+ "hemnes.no",
+ "hemsedal.no",
+ "heroy.more-og-romsdal.no",
+ "xn--hery-ira.xn--mre-og-romsdal-qqb.no",
+ "heroy.nordland.no",
+ "xn--hery-ira.nordland.no",
+ "hitra.no",
+ "hjartdal.no",
+ "hjelmeland.no",
+ "hobol.no",
+ "xn--hobl-ira.no",
+ "hof.no",
+ "hol.no",
+ "hole.no",
+ "holmestrand.no",
+ "holtalen.no",
+ "xn--holtlen-hxa.no",
+ "hornindal.no",
+ "horten.no",
+ "hurdal.no",
+ "hurum.no",
+ "hvaler.no",
+ "hyllestad.no",
+ "hagebostad.no",
+ "xn--hgebostad-g3a.no",
+ "hoyanger.no",
+ "xn--hyanger-q1a.no",
+ "hoylandet.no",
+ "xn--hylandet-54a.no",
+ "ha.no",
+ "xn--h-2fa.no",
+ "ibestad.no",
+ "inderoy.no",
+ "xn--indery-fya.no",
+ "iveland.no",
+ "jevnaker.no",
+ "jondal.no",
+ "jolster.no",
+ "xn--jlster-bya.no",
+ "karasjok.no",
+ "karasjohka.no",
+ "xn--krjohka-hwab49j.no",
+ "karlsoy.no",
+ "galsa.no",
+ "xn--gls-elac.no",
+ "karmoy.no",
+ "xn--karmy-yua.no",
+ "kautokeino.no",
+ "guovdageaidnu.no",
+ "klepp.no",
+ "klabu.no",
+ "xn--klbu-woa.no",
+ "kongsberg.no",
+ "kongsvinger.no",
+ "kragero.no",
+ "xn--krager-gya.no",
+ "kristiansand.no",
+ "kristiansund.no",
+ "krodsherad.no",
+ "xn--krdsherad-m8a.no",
+ "kvalsund.no",
+ "rahkkeravju.no",
+ "xn--rhkkervju-01af.no",
+ "kvam.no",
+ "kvinesdal.no",
+ "kvinnherad.no",
+ "kviteseid.no",
+ "kvitsoy.no",
+ "xn--kvitsy-fya.no",
+ "kvafjord.no",
+ "xn--kvfjord-nxa.no",
+ "giehtavuoatna.no",
+ "kvanangen.no",
+ "xn--kvnangen-k0a.no",
+ "navuotna.no",
+ "xn--nvuotna-hwa.no",
+ "kafjord.no",
+ "xn--kfjord-iua.no",
+ "gaivuotna.no",
+ "xn--givuotna-8ya.no",
+ "larvik.no",
+ "lavangen.no",
+ "lavagis.no",
+ "loabat.no",
+ "xn--loabt-0qa.no",
+ "lebesby.no",
+ "davvesiida.no",
+ "leikanger.no",
+ "leirfjord.no",
+ "leka.no",
+ "leksvik.no",
+ "lenvik.no",
+ "leangaviika.no",
+ "xn--leagaviika-52b.no",
+ "lesja.no",
+ "levanger.no",
+ "lier.no",
+ "lierne.no",
+ "lillehammer.no",
+ "lillesand.no",
+ "lindesnes.no",
+ "lindas.no",
+ "xn--linds-pra.no",
+ "lom.no",
+ "loppa.no",
+ "lahppi.no",
+ "xn--lhppi-xqa.no",
+ "lund.no",
+ "lunner.no",
+ "luroy.no",
+ "xn--lury-ira.no",
+ "luster.no",
+ "lyngdal.no",
+ "lyngen.no",
+ "ivgu.no",
+ "lardal.no",
+ "lerdal.no",
+ "xn--lrdal-sra.no",
+ "lodingen.no",
+ "xn--ldingen-q1a.no",
+ "lorenskog.no",
+ "xn--lrenskog-54a.no",
+ "loten.no",
+ "xn--lten-gra.no",
+ "malvik.no",
+ "masoy.no",
+ "xn--msy-ula0h.no",
+ "muosat.no",
+ "xn--muost-0qa.no",
+ "mandal.no",
+ "marker.no",
+ "marnardal.no",
+ "masfjorden.no",
+ "meland.no",
+ "meldal.no",
+ "melhus.no",
+ "meloy.no",
+ "xn--mely-ira.no",
+ "meraker.no",
+ "xn--merker-kua.no",
+ "moareke.no",
+ "xn--moreke-jua.no",
+ "midsund.no",
+ "midtre-gauldal.no",
+ "modalen.no",
+ "modum.no",
+ "molde.no",
+ "moskenes.no",
+ "moss.no",
+ "mosvik.no",
+ "malselv.no",
+ "xn--mlselv-iua.no",
+ "malatvuopmi.no",
+ "xn--mlatvuopmi-s4a.no",
+ "namdalseid.no",
+ "aejrie.no",
+ "namsos.no",
+ "namsskogan.no",
+ "naamesjevuemie.no",
+ "xn--nmesjevuemie-tcba.no",
+ "laakesvuemie.no",
+ "nannestad.no",
+ "narvik.no",
+ "narviika.no",
+ "naustdal.no",
+ "nedre-eiker.no",
+ "nes.akershus.no",
+ "nes.buskerud.no",
+ "nesna.no",
+ "nesodden.no",
+ "nesseby.no",
+ "unjarga.no",
+ "xn--unjrga-rta.no",
+ "nesset.no",
+ "nissedal.no",
+ "nittedal.no",
+ "nord-aurdal.no",
+ "nord-fron.no",
+ "nord-odal.no",
+ "norddal.no",
+ "nordkapp.no",
+ "davvenjarga.no",
+ "xn--davvenjrga-y4a.no",
+ "nordre-land.no",
+ "nordreisa.no",
+ "raisa.no",
+ "xn--risa-5na.no",
+ "nore-og-uvdal.no",
+ "notodden.no",
+ "naroy.no",
+ "xn--nry-yla5g.no",
+ "notteroy.no",
+ "xn--nttery-byae.no",
+ "odda.no",
+ "oksnes.no",
+ "xn--ksnes-uua.no",
+ "oppdal.no",
+ "oppegard.no",
+ "xn--oppegrd-ixa.no",
+ "orkdal.no",
+ "orland.no",
+ "xn--rland-uua.no",
+ "orskog.no",
+ "xn--rskog-uua.no",
+ "orsta.no",
+ "xn--rsta-fra.no",
+ "os.hedmark.no",
+ "os.hordaland.no",
+ "osen.no",
+ "osteroy.no",
+ "xn--ostery-fya.no",
+ "ostre-toten.no",
+ "xn--stre-toten-zcb.no",
+ "overhalla.no",
+ "ovre-eiker.no",
+ "xn--vre-eiker-k8a.no",
+ "oyer.no",
+ "xn--yer-zna.no",
+ "oygarden.no",
+ "xn--ygarden-p1a.no",
+ "oystre-slidre.no",
+ "xn--ystre-slidre-ujb.no",
+ "porsanger.no",
+ "porsangu.no",
+ "xn--porsgu-sta26f.no",
+ "porsgrunn.no",
+ "radoy.no",
+ "xn--rady-ira.no",
+ "rakkestad.no",
+ "rana.no",
+ "ruovat.no",
+ "randaberg.no",
+ "rauma.no",
+ "rendalen.no",
+ "rennebu.no",
+ "rennesoy.no",
+ "xn--rennesy-v1a.no",
+ "rindal.no",
+ "ringebu.no",
+ "ringerike.no",
+ "ringsaker.no",
+ "rissa.no",
+ "risor.no",
+ "xn--risr-ira.no",
+ "roan.no",
+ "rollag.no",
+ "rygge.no",
+ "ralingen.no",
+ "xn--rlingen-mxa.no",
+ "rodoy.no",
+ "xn--rdy-0nab.no",
+ "romskog.no",
+ "xn--rmskog-bya.no",
+ "roros.no",
+ "xn--rros-gra.no",
+ "rost.no",
+ "xn--rst-0na.no",
+ "royken.no",
+ "xn--ryken-vua.no",
+ "royrvik.no",
+ "xn--ryrvik-bya.no",
+ "rade.no",
+ "xn--rde-ula.no",
+ "salangen.no",
+ "siellak.no",
+ "saltdal.no",
+ "salat.no",
+ "xn--slt-elab.no",
+ "xn--slat-5na.no",
+ "samnanger.no",
+ "sande.more-og-romsdal.no",
+ "sande.xn--mre-og-romsdal-qqb.no",
+ "sande.vestfold.no",
+ "sandefjord.no",
+ "sandnes.no",
+ "sandoy.no",
+ "xn--sandy-yua.no",
+ "sarpsborg.no",
+ "sauda.no",
+ "sauherad.no",
+ "sel.no",
+ "selbu.no",
+ "selje.no",
+ "seljord.no",
+ "sigdal.no",
+ "siljan.no",
+ "sirdal.no",
+ "skaun.no",
+ "skedsmo.no",
+ "ski.no",
+ "skien.no",
+ "skiptvet.no",
+ "skjervoy.no",
+ "xn--skjervy-v1a.no",
+ "skierva.no",
+ "xn--skierv-uta.no",
+ "skjak.no",
+ "xn--skjk-soa.no",
+ "skodje.no",
+ "skanland.no",
+ "xn--sknland-fxa.no",
+ "skanit.no",
+ "xn--sknit-yqa.no",
+ "smola.no",
+ "xn--smla-hra.no",
+ "snillfjord.no",
+ "snasa.no",
+ "xn--snsa-roa.no",
+ "snoasa.no",
+ "snaase.no",
+ "xn--snase-nra.no",
+ "sogndal.no",
+ "sokndal.no",
+ "sola.no",
+ "solund.no",
+ "songdalen.no",
+ "sortland.no",
+ "spydeberg.no",
+ "stange.no",
+ "stavanger.no",
+ "steigen.no",
+ "steinkjer.no",
+ "stjordal.no",
+ "xn--stjrdal-s1a.no",
+ "stokke.no",
+ "stor-elvdal.no",
+ "stord.no",
+ "stordal.no",
+ "storfjord.no",
+ "omasvuotna.no",
+ "strand.no",
+ "stranda.no",
+ "stryn.no",
+ "sula.no",
+ "suldal.no",
+ "sund.no",
+ "sunndal.no",
+ "surnadal.no",
+ "sveio.no",
+ "svelvik.no",
+ "sykkylven.no",
+ "sogne.no",
+ "xn--sgne-gra.no",
+ "somna.no",
+ "xn--smna-gra.no",
+ "sondre-land.no",
+ "xn--sndre-land-0cb.no",
+ "sor-aurdal.no",
+ "xn--sr-aurdal-l8a.no",
+ "sor-fron.no",
+ "xn--sr-fron-q1a.no",
+ "sor-odal.no",
+ "xn--sr-odal-q1a.no",
+ "sor-varanger.no",
+ "xn--sr-varanger-ggb.no",
+ "matta-varjjat.no",
+ "xn--mtta-vrjjat-k7af.no",
+ "sorfold.no",
+ "xn--srfold-bya.no",
+ "sorreisa.no",
+ "xn--srreisa-q1a.no",
+ "sorum.no",
+ "xn--srum-gra.no",
+ "tana.no",
+ "deatnu.no",
+ "time.no",
+ "tingvoll.no",
+ "tinn.no",
+ "tjeldsund.no",
+ "dielddanuorri.no",
+ "tjome.no",
+ "xn--tjme-hra.no",
+ "tokke.no",
+ "tolga.no",
+ "torsken.no",
+ "tranoy.no",
+ "xn--trany-yua.no",
+ "tromso.no",
+ "xn--troms-zua.no",
+ "tromsa.no",
+ "romsa.no",
+ "trondheim.no",
+ "troandin.no",
+ "trysil.no",
+ "trana.no",
+ "xn--trna-woa.no",
+ "trogstad.no",
+ "xn--trgstad-r1a.no",
+ "tvedestrand.no",
+ "tydal.no",
+ "tynset.no",
+ "tysfjord.no",
+ "divtasvuodna.no",
+ "divttasvuotna.no",
+ "tysnes.no",
+ "tysvar.no",
+ "xn--tysvr-vra.no",
+ "tonsberg.no",
+ "xn--tnsberg-q1a.no",
+ "ullensaker.no",
+ "ullensvang.no",
+ "ulvik.no",
+ "utsira.no",
+ "vadso.no",
+ "xn--vads-jra.no",
+ "cahcesuolo.no",
+ "xn--hcesuolo-7ya35b.no",
+ "vaksdal.no",
+ "valle.no",
+ "vang.no",
+ "vanylven.no",
+ "vardo.no",
+ "xn--vard-jra.no",
+ "varggat.no",
+ "xn--vrggt-xqad.no",
+ "vefsn.no",
+ "vaapste.no",
+ "vega.no",
+ "vegarshei.no",
+ "xn--vegrshei-c0a.no",
+ "vennesla.no",
+ "verdal.no",
+ "verran.no",
+ "vestby.no",
+ "vestnes.no",
+ "vestre-slidre.no",
+ "vestre-toten.no",
+ "vestvagoy.no",
+ "xn--vestvgy-ixa6o.no",
+ "vevelstad.no",
+ "vik.no",
+ "vikna.no",
+ "vindafjord.no",
+ "volda.no",
+ "voss.no",
+ "varoy.no",
+ "xn--vry-yla5g.no",
+ "vagan.no",
+ "xn--vgan-qoa.no",
+ "voagat.no",
+ "vagsoy.no",
+ "xn--vgsy-qoa0j.no",
+ "vaga.no",
+ "xn--vg-yiab.no",
+ "valer.ostfold.no",
+ "xn--vler-qoa.xn--stfold-9xa.no",
+ "valer.hedmark.no",
+ "xn--vler-qoa.hedmark.no",
+ "*.np",
+ "nr",
+ "biz.nr",
+ "info.nr",
+ "gov.nr",
+ "edu.nr",
+ "org.nr",
+ "net.nr",
+ "com.nr",
+ "nu",
+ "nz",
+ "ac.nz",
+ "co.nz",
+ "cri.nz",
+ "geek.nz",
+ "gen.nz",
+ "govt.nz",
+ "health.nz",
+ "iwi.nz",
+ "kiwi.nz",
+ "maori.nz",
+ "mil.nz",
+ "xn--mori-qsa.nz",
+ "net.nz",
+ "org.nz",
+ "parliament.nz",
+ "school.nz",
+ "om",
+ "co.om",
+ "com.om",
+ "edu.om",
+ "gov.om",
+ "med.om",
+ "museum.om",
+ "net.om",
+ "org.om",
+ "pro.om",
+ "onion",
+ "org",
+ "pa",
+ "ac.pa",
+ "gob.pa",
+ "com.pa",
+ "org.pa",
+ "sld.pa",
+ "edu.pa",
+ "net.pa",
+ "ing.pa",
+ "abo.pa",
+ "med.pa",
+ "nom.pa",
+ "pe",
+ "edu.pe",
+ "gob.pe",
+ "nom.pe",
+ "mil.pe",
+ "org.pe",
+ "com.pe",
+ "net.pe",
+ "pf",
+ "com.pf",
+ "org.pf",
+ "edu.pf",
+ "*.pg",
+ "ph",
+ "com.ph",
+ "net.ph",
+ "org.ph",
+ "gov.ph",
+ "edu.ph",
+ "ngo.ph",
+ "mil.ph",
+ "i.ph",
+ "pk",
+ "com.pk",
+ "net.pk",
+ "edu.pk",
+ "org.pk",
+ "fam.pk",
+ "biz.pk",
+ "web.pk",
+ "gov.pk",
+ "gob.pk",
+ "gok.pk",
+ "gon.pk",
+ "gop.pk",
+ "gos.pk",
+ "info.pk",
+ "pl",
+ "com.pl",
+ "net.pl",
+ "org.pl",
+ "aid.pl",
+ "agro.pl",
+ "atm.pl",
+ "auto.pl",
+ "biz.pl",
+ "edu.pl",
+ "gmina.pl",
+ "gsm.pl",
+ "info.pl",
+ "mail.pl",
+ "miasta.pl",
+ "media.pl",
+ "mil.pl",
+ "nieruchomosci.pl",
+ "nom.pl",
+ "pc.pl",
+ "powiat.pl",
+ "priv.pl",
+ "realestate.pl",
+ "rel.pl",
+ "sex.pl",
+ "shop.pl",
+ "sklep.pl",
+ "sos.pl",
+ "szkola.pl",
+ "targi.pl",
+ "tm.pl",
+ "tourism.pl",
+ "travel.pl",
+ "turystyka.pl",
+ "gov.pl",
+ "ap.gov.pl",
+ "ic.gov.pl",
+ "is.gov.pl",
+ "us.gov.pl",
+ "kmpsp.gov.pl",
+ "kppsp.gov.pl",
+ "kwpsp.gov.pl",
+ "psp.gov.pl",
+ "wskr.gov.pl",
+ "kwp.gov.pl",
+ "mw.gov.pl",
+ "ug.gov.pl",
+ "um.gov.pl",
+ "umig.gov.pl",
+ "ugim.gov.pl",
+ "upow.gov.pl",
+ "uw.gov.pl",
+ "starostwo.gov.pl",
+ "pa.gov.pl",
+ "po.gov.pl",
+ "psse.gov.pl",
+ "pup.gov.pl",
+ "rzgw.gov.pl",
+ "sa.gov.pl",
+ "so.gov.pl",
+ "sr.gov.pl",
+ "wsa.gov.pl",
+ "sko.gov.pl",
+ "uzs.gov.pl",
+ "wiih.gov.pl",
+ "winb.gov.pl",
+ "pinb.gov.pl",
+ "wios.gov.pl",
+ "witd.gov.pl",
+ "wzmiuw.gov.pl",
+ "piw.gov.pl",
+ "wiw.gov.pl",
+ "griw.gov.pl",
+ "wif.gov.pl",
+ "oum.gov.pl",
+ "sdn.gov.pl",
+ "zp.gov.pl",
+ "uppo.gov.pl",
+ "mup.gov.pl",
+ "wuoz.gov.pl",
+ "konsulat.gov.pl",
+ "oirm.gov.pl",
+ "augustow.pl",
+ "babia-gora.pl",
+ "bedzin.pl",
+ "beskidy.pl",
+ "bialowieza.pl",
+ "bialystok.pl",
+ "bielawa.pl",
+ "bieszczady.pl",
+ "boleslawiec.pl",
+ "bydgoszcz.pl",
+ "bytom.pl",
+ "cieszyn.pl",
+ "czeladz.pl",
+ "czest.pl",
+ "dlugoleka.pl",
+ "elblag.pl",
+ "elk.pl",
+ "glogow.pl",
+ "gniezno.pl",
+ "gorlice.pl",
+ "grajewo.pl",
+ "ilawa.pl",
+ "jaworzno.pl",
+ "jelenia-gora.pl",
+ "jgora.pl",
+ "kalisz.pl",
+ "kazimierz-dolny.pl",
+ "karpacz.pl",
+ "kartuzy.pl",
+ "kaszuby.pl",
+ "katowice.pl",
+ "kepno.pl",
+ "ketrzyn.pl",
+ "klodzko.pl",
+ "kobierzyce.pl",
+ "kolobrzeg.pl",
+ "konin.pl",
+ "konskowola.pl",
+ "kutno.pl",
+ "lapy.pl",
+ "lebork.pl",
+ "legnica.pl",
+ "lezajsk.pl",
+ "limanowa.pl",
+ "lomza.pl",
+ "lowicz.pl",
+ "lubin.pl",
+ "lukow.pl",
+ "malbork.pl",
+ "malopolska.pl",
+ "mazowsze.pl",
+ "mazury.pl",
+ "mielec.pl",
+ "mielno.pl",
+ "mragowo.pl",
+ "naklo.pl",
+ "nowaruda.pl",
+ "nysa.pl",
+ "olawa.pl",
+ "olecko.pl",
+ "olkusz.pl",
+ "olsztyn.pl",
+ "opoczno.pl",
+ "opole.pl",
+ "ostroda.pl",
+ "ostroleka.pl",
+ "ostrowiec.pl",
+ "ostrowwlkp.pl",
+ "pila.pl",
+ "pisz.pl",
+ "podhale.pl",
+ "podlasie.pl",
+ "polkowice.pl",
+ "pomorze.pl",
+ "pomorskie.pl",
+ "prochowice.pl",
+ "pruszkow.pl",
+ "przeworsk.pl",
+ "pulawy.pl",
+ "radom.pl",
+ "rawa-maz.pl",
+ "rybnik.pl",
+ "rzeszow.pl",
+ "sanok.pl",
+ "sejny.pl",
+ "slask.pl",
+ "slupsk.pl",
+ "sosnowiec.pl",
+ "stalowa-wola.pl",
+ "skoczow.pl",
+ "starachowice.pl",
+ "stargard.pl",
+ "suwalki.pl",
+ "swidnica.pl",
+ "swiebodzin.pl",
+ "swinoujscie.pl",
+ "szczecin.pl",
+ "szczytno.pl",
+ "tarnobrzeg.pl",
+ "tgory.pl",
+ "turek.pl",
+ "tychy.pl",
+ "ustka.pl",
+ "walbrzych.pl",
+ "warmia.pl",
+ "warszawa.pl",
+ "waw.pl",
+ "wegrow.pl",
+ "wielun.pl",
+ "wlocl.pl",
+ "wloclawek.pl",
+ "wodzislaw.pl",
+ "wolomin.pl",
+ "wroclaw.pl",
+ "zachpomor.pl",
+ "zagan.pl",
+ "zarow.pl",
+ "zgora.pl",
+ "zgorzelec.pl",
+ "pm",
+ "pn",
+ "gov.pn",
+ "co.pn",
+ "org.pn",
+ "edu.pn",
+ "net.pn",
+ "post",
+ "pr",
+ "com.pr",
+ "net.pr",
+ "org.pr",
+ "gov.pr",
+ "edu.pr",
+ "isla.pr",
+ "pro.pr",
+ "biz.pr",
+ "info.pr",
+ "name.pr",
+ "est.pr",
+ "prof.pr",
+ "ac.pr",
+ "pro",
+ "aaa.pro",
+ "aca.pro",
+ "acct.pro",
+ "avocat.pro",
+ "bar.pro",
+ "cpa.pro",
+ "eng.pro",
+ "jur.pro",
+ "law.pro",
+ "med.pro",
+ "recht.pro",
+ "ps",
+ "edu.ps",
+ "gov.ps",
+ "sec.ps",
+ "plo.ps",
+ "com.ps",
+ "org.ps",
+ "net.ps",
+ "pt",
+ "net.pt",
+ "gov.pt",
+ "org.pt",
+ "edu.pt",
+ "int.pt",
+ "publ.pt",
+ "com.pt",
+ "nome.pt",
+ "pw",
+ "co.pw",
+ "ne.pw",
+ "or.pw",
+ "ed.pw",
+ "go.pw",
+ "belau.pw",
+ "py",
+ "com.py",
+ "coop.py",
+ "edu.py",
+ "gov.py",
+ "mil.py",
+ "net.py",
+ "org.py",
+ "qa",
+ "com.qa",
+ "edu.qa",
+ "gov.qa",
+ "mil.qa",
+ "name.qa",
+ "net.qa",
+ "org.qa",
+ "sch.qa",
+ "re",
+ "asso.re",
+ "com.re",
+ "nom.re",
+ "ro",
+ "arts.ro",
+ "com.ro",
+ "firm.ro",
+ "info.ro",
+ "nom.ro",
+ "nt.ro",
+ "org.ro",
+ "rec.ro",
+ "store.ro",
+ "tm.ro",
+ "www.ro",
+ "rs",
+ "ac.rs",
+ "co.rs",
+ "edu.rs",
+ "gov.rs",
+ "in.rs",
+ "org.rs",
+ "ru",
+ "ac.ru",
+ "edu.ru",
+ "gov.ru",
+ "int.ru",
+ "mil.ru",
+ "test.ru",
+ "rw",
+ "gov.rw",
+ "net.rw",
+ "edu.rw",
+ "ac.rw",
+ "com.rw",
+ "co.rw",
+ "int.rw",
+ "mil.rw",
+ "gouv.rw",
+ "sa",
+ "com.sa",
+ "net.sa",
+ "org.sa",
+ "gov.sa",
+ "med.sa",
+ "pub.sa",
+ "edu.sa",
+ "sch.sa",
+ "sb",
+ "com.sb",
+ "edu.sb",
+ "gov.sb",
+ "net.sb",
+ "org.sb",
+ "sc",
+ "com.sc",
+ "gov.sc",
+ "net.sc",
+ "org.sc",
+ "edu.sc",
+ "sd",
+ "com.sd",
+ "net.sd",
+ "org.sd",
+ "edu.sd",
+ "med.sd",
+ "tv.sd",
+ "gov.sd",
+ "info.sd",
+ "se",
+ "a.se",
+ "ac.se",
+ "b.se",
+ "bd.se",
+ "brand.se",
+ "c.se",
+ "d.se",
+ "e.se",
+ "f.se",
+ "fh.se",
+ "fhsk.se",
+ "fhv.se",
+ "g.se",
+ "h.se",
+ "i.se",
+ "k.se",
+ "komforb.se",
+ "kommunalforbund.se",
+ "komvux.se",
+ "l.se",
+ "lanbib.se",
+ "m.se",
+ "n.se",
+ "naturbruksgymn.se",
+ "o.se",
+ "org.se",
+ "p.se",
+ "parti.se",
+ "pp.se",
+ "press.se",
+ "r.se",
+ "s.se",
+ "t.se",
+ "tm.se",
+ "u.se",
+ "w.se",
+ "x.se",
+ "y.se",
+ "z.se",
+ "sg",
+ "com.sg",
+ "net.sg",
+ "org.sg",
+ "gov.sg",
+ "edu.sg",
+ "per.sg",
+ "sh",
+ "com.sh",
+ "net.sh",
+ "gov.sh",
+ "org.sh",
+ "mil.sh",
+ "si",
+ "sj",
+ "sk",
+ "sl",
+ "com.sl",
+ "net.sl",
+ "edu.sl",
+ "gov.sl",
+ "org.sl",
+ "sm",
+ "sn",
+ "art.sn",
+ "com.sn",
+ "edu.sn",
+ "gouv.sn",
+ "org.sn",
+ "perso.sn",
+ "univ.sn",
+ "so",
+ "com.so",
+ "net.so",
+ "org.so",
+ "sr",
+ "st",
+ "co.st",
+ "com.st",
+ "consulado.st",
+ "edu.st",
+ "embaixada.st",
+ "gov.st",
+ "mil.st",
+ "net.st",
+ "org.st",
+ "principe.st",
+ "saotome.st",
+ "store.st",
+ "su",
+ "sv",
+ "com.sv",
+ "edu.sv",
+ "gob.sv",
+ "org.sv",
+ "red.sv",
+ "sx",
+ "gov.sx",
+ "sy",
+ "edu.sy",
+ "gov.sy",
+ "net.sy",
+ "mil.sy",
+ "com.sy",
+ "org.sy",
+ "sz",
+ "co.sz",
+ "ac.sz",
+ "org.sz",
+ "tc",
+ "td",
+ "tel",
+ "tf",
+ "tg",
+ "th",
+ "ac.th",
+ "co.th",
+ "go.th",
+ "in.th",
+ "mi.th",
+ "net.th",
+ "or.th",
+ "tj",
+ "ac.tj",
+ "biz.tj",
+ "co.tj",
+ "com.tj",
+ "edu.tj",
+ "go.tj",
+ "gov.tj",
+ "int.tj",
+ "mil.tj",
+ "name.tj",
+ "net.tj",
+ "nic.tj",
+ "org.tj",
+ "test.tj",
+ "web.tj",
+ "tk",
+ "tl",
+ "gov.tl",
+ "tm",
+ "com.tm",
+ "co.tm",
+ "org.tm",
+ "net.tm",
+ "nom.tm",
+ "gov.tm",
+ "mil.tm",
+ "edu.tm",
+ "tn",
+ "com.tn",
+ "ens.tn",
+ "fin.tn",
+ "gov.tn",
+ "ind.tn",
+ "intl.tn",
+ "nat.tn",
+ "net.tn",
+ "org.tn",
+ "info.tn",
+ "perso.tn",
+ "tourism.tn",
+ "edunet.tn",
+ "rnrt.tn",
+ "rns.tn",
+ "rnu.tn",
+ "mincom.tn",
+ "agrinet.tn",
+ "defense.tn",
+ "turen.tn",
+ "to",
+ "com.to",
+ "gov.to",
+ "net.to",
+ "org.to",
+ "edu.to",
+ "mil.to",
+ "tr",
+ "com.tr",
+ "info.tr",
+ "biz.tr",
+ "net.tr",
+ "org.tr",
+ "web.tr",
+ "gen.tr",
+ "tv.tr",
+ "av.tr",
+ "dr.tr",
+ "bbs.tr",
+ "name.tr",
+ "tel.tr",
+ "gov.tr",
+ "bel.tr",
+ "pol.tr",
+ "mil.tr",
+ "k12.tr",
+ "edu.tr",
+ "kep.tr",
+ "nc.tr",
+ "gov.nc.tr",
+ "travel",
+ "tt",
+ "co.tt",
+ "com.tt",
+ "org.tt",
+ "net.tt",
+ "biz.tt",
+ "info.tt",
+ "pro.tt",
+ "int.tt",
+ "coop.tt",
+ "jobs.tt",
+ "mobi.tt",
+ "travel.tt",
+ "museum.tt",
+ "aero.tt",
+ "name.tt",
+ "gov.tt",
+ "edu.tt",
+ "tv",
+ "tw",
+ "edu.tw",
+ "gov.tw",
+ "mil.tw",
+ "com.tw",
+ "net.tw",
+ "org.tw",
+ "idv.tw",
+ "game.tw",
+ "ebiz.tw",
+ "club.tw",
+ "xn--zf0ao64a.tw",
+ "xn--uc0atv.tw",
+ "xn--czrw28b.tw",
+ "tz",
+ "ac.tz",
+ "co.tz",
+ "go.tz",
+ "hotel.tz",
+ "info.tz",
+ "me.tz",
+ "mil.tz",
+ "mobi.tz",
+ "ne.tz",
+ "or.tz",
+ "sc.tz",
+ "tv.tz",
+ "ua",
+ "com.ua",
+ "edu.ua",
+ "gov.ua",
+ "in.ua",
+ "net.ua",
+ "org.ua",
+ "cherkassy.ua",
+ "cherkasy.ua",
+ "chernigov.ua",
+ "chernihiv.ua",
+ "chernivtsi.ua",
+ "chernovtsy.ua",
+ "ck.ua",
+ "cn.ua",
+ "cr.ua",
+ "crimea.ua",
+ "cv.ua",
+ "dn.ua",
+ "dnepropetrovsk.ua",
+ "dnipropetrovsk.ua",
+ "dominic.ua",
+ "donetsk.ua",
+ "dp.ua",
+ "if.ua",
+ "ivano-frankivsk.ua",
+ "kh.ua",
+ "kharkiv.ua",
+ "kharkov.ua",
+ "kherson.ua",
+ "khmelnitskiy.ua",
+ "khmelnytskyi.ua",
+ "kiev.ua",
+ "kirovograd.ua",
+ "km.ua",
+ "kr.ua",
+ "krym.ua",
+ "ks.ua",
+ "kv.ua",
+ "kyiv.ua",
+ "lg.ua",
+ "lt.ua",
+ "lugansk.ua",
+ "lutsk.ua",
+ "lv.ua",
+ "lviv.ua",
+ "mk.ua",
+ "mykolaiv.ua",
+ "nikolaev.ua",
+ "od.ua",
+ "odesa.ua",
+ "odessa.ua",
+ "pl.ua",
+ "poltava.ua",
+ "rivne.ua",
+ "rovno.ua",
+ "rv.ua",
+ "sb.ua",
+ "sebastopol.ua",
+ "sevastopol.ua",
+ "sm.ua",
+ "sumy.ua",
+ "te.ua",
+ "ternopil.ua",
+ "uz.ua",
+ "uzhgorod.ua",
+ "vinnica.ua",
+ "vinnytsia.ua",
+ "vn.ua",
+ "volyn.ua",
+ "yalta.ua",
+ "zaporizhzhe.ua",
+ "zaporizhzhia.ua",
+ "zhitomir.ua",
+ "zhytomyr.ua",
+ "zp.ua",
+ "zt.ua",
+ "ug",
+ "co.ug",
+ "or.ug",
+ "ac.ug",
+ "sc.ug",
+ "go.ug",
+ "ne.ug",
+ "com.ug",
+ "org.ug",
+ "uk",
+ "ac.uk",
+ "co.uk",
+ "gov.uk",
+ "ltd.uk",
+ "me.uk",
+ "net.uk",
+ "nhs.uk",
+ "org.uk",
+ "plc.uk",
+ "police.uk",
+ "*.sch.uk",
+ "us",
+ "dni.us",
+ "fed.us",
+ "isa.us",
+ "kids.us",
+ "nsn.us",
+ "ak.us",
+ "al.us",
+ "ar.us",
+ "as.us",
+ "az.us",
+ "ca.us",
+ "co.us",
+ "ct.us",
+ "dc.us",
+ "de.us",
+ "fl.us",
+ "ga.us",
+ "gu.us",
+ "hi.us",
+ "ia.us",
+ "id.us",
+ "il.us",
+ "in.us",
+ "ks.us",
+ "ky.us",
+ "la.us",
+ "ma.us",
+ "md.us",
+ "me.us",
+ "mi.us",
+ "mn.us",
+ "mo.us",
+ "ms.us",
+ "mt.us",
+ "nc.us",
+ "nd.us",
+ "ne.us",
+ "nh.us",
+ "nj.us",
+ "nm.us",
+ "nv.us",
+ "ny.us",
+ "oh.us",
+ "ok.us",
+ "or.us",
+ "pa.us",
+ "pr.us",
+ "ri.us",
+ "sc.us",
+ "sd.us",
+ "tn.us",
+ "tx.us",
+ "ut.us",
+ "vi.us",
+ "vt.us",
+ "va.us",
+ "wa.us",
+ "wi.us",
+ "wv.us",
+ "wy.us",
+ "k12.ak.us",
+ "k12.al.us",
+ "k12.ar.us",
+ "k12.as.us",
+ "k12.az.us",
+ "k12.ca.us",
+ "k12.co.us",
+ "k12.ct.us",
+ "k12.dc.us",
+ "k12.de.us",
+ "k12.fl.us",
+ "k12.ga.us",
+ "k12.gu.us",
+ "k12.ia.us",
+ "k12.id.us",
+ "k12.il.us",
+ "k12.in.us",
+ "k12.ks.us",
+ "k12.ky.us",
+ "k12.la.us",
+ "k12.ma.us",
+ "k12.md.us",
+ "k12.me.us",
+ "k12.mi.us",
+ "k12.mn.us",
+ "k12.mo.us",
+ "k12.ms.us",
+ "k12.mt.us",
+ "k12.nc.us",
+ "k12.ne.us",
+ "k12.nh.us",
+ "k12.nj.us",
+ "k12.nm.us",
+ "k12.nv.us",
+ "k12.ny.us",
+ "k12.oh.us",
+ "k12.ok.us",
+ "k12.or.us",
+ "k12.pa.us",
+ "k12.pr.us",
+ "k12.ri.us",
+ "k12.sc.us",
+ "k12.tn.us",
+ "k12.tx.us",
+ "k12.ut.us",
+ "k12.vi.us",
+ "k12.vt.us",
+ "k12.va.us",
+ "k12.wa.us",
+ "k12.wi.us",
+ "k12.wy.us",
+ "cc.ak.us",
+ "cc.al.us",
+ "cc.ar.us",
+ "cc.as.us",
+ "cc.az.us",
+ "cc.ca.us",
+ "cc.co.us",
+ "cc.ct.us",
+ "cc.dc.us",
+ "cc.de.us",
+ "cc.fl.us",
+ "cc.ga.us",
+ "cc.gu.us",
+ "cc.hi.us",
+ "cc.ia.us",
+ "cc.id.us",
+ "cc.il.us",
+ "cc.in.us",
+ "cc.ks.us",
+ "cc.ky.us",
+ "cc.la.us",
+ "cc.ma.us",
+ "cc.md.us",
+ "cc.me.us",
+ "cc.mi.us",
+ "cc.mn.us",
+ "cc.mo.us",
+ "cc.ms.us",
+ "cc.mt.us",
+ "cc.nc.us",
+ "cc.nd.us",
+ "cc.ne.us",
+ "cc.nh.us",
+ "cc.nj.us",
+ "cc.nm.us",
+ "cc.nv.us",
+ "cc.ny.us",
+ "cc.oh.us",
+ "cc.ok.us",
+ "cc.or.us",
+ "cc.pa.us",
+ "cc.pr.us",
+ "cc.ri.us",
+ "cc.sc.us",
+ "cc.sd.us",
+ "cc.tn.us",
+ "cc.tx.us",
+ "cc.ut.us",
+ "cc.vi.us",
+ "cc.vt.us",
+ "cc.va.us",
+ "cc.wa.us",
+ "cc.wi.us",
+ "cc.wv.us",
+ "cc.wy.us",
+ "lib.ak.us",
+ "lib.al.us",
+ "lib.ar.us",
+ "lib.as.us",
+ "lib.az.us",
+ "lib.ca.us",
+ "lib.co.us",
+ "lib.ct.us",
+ "lib.dc.us",
+ "lib.fl.us",
+ "lib.ga.us",
+ "lib.gu.us",
+ "lib.hi.us",
+ "lib.ia.us",
+ "lib.id.us",
+ "lib.il.us",
+ "lib.in.us",
+ "lib.ks.us",
+ "lib.ky.us",
+ "lib.la.us",
+ "lib.ma.us",
+ "lib.md.us",
+ "lib.me.us",
+ "lib.mi.us",
+ "lib.mn.us",
+ "lib.mo.us",
+ "lib.ms.us",
+ "lib.mt.us",
+ "lib.nc.us",
+ "lib.nd.us",
+ "lib.ne.us",
+ "lib.nh.us",
+ "lib.nj.us",
+ "lib.nm.us",
+ "lib.nv.us",
+ "lib.ny.us",
+ "lib.oh.us",
+ "lib.ok.us",
+ "lib.or.us",
+ "lib.pa.us",
+ "lib.pr.us",
+ "lib.ri.us",
+ "lib.sc.us",
+ "lib.sd.us",
+ "lib.tn.us",
+ "lib.tx.us",
+ "lib.ut.us",
+ "lib.vi.us",
+ "lib.vt.us",
+ "lib.va.us",
+ "lib.wa.us",
+ "lib.wi.us",
+ "lib.wy.us",
+ "pvt.k12.ma.us",
+ "chtr.k12.ma.us",
+ "paroch.k12.ma.us",
+ "ann-arbor.mi.us",
+ "cog.mi.us",
+ "dst.mi.us",
+ "eaton.mi.us",
+ "gen.mi.us",
+ "mus.mi.us",
+ "tec.mi.us",
+ "washtenaw.mi.us",
+ "uy",
+ "com.uy",
+ "edu.uy",
+ "gub.uy",
+ "mil.uy",
+ "net.uy",
+ "org.uy",
+ "uz",
+ "co.uz",
+ "com.uz",
+ "net.uz",
+ "org.uz",
+ "va",
+ "vc",
+ "com.vc",
+ "net.vc",
+ "org.vc",
+ "gov.vc",
+ "mil.vc",
+ "edu.vc",
+ "ve",
+ "arts.ve",
+ "co.ve",
+ "com.ve",
+ "e12.ve",
+ "edu.ve",
+ "firm.ve",
+ "gob.ve",
+ "gov.ve",
+ "info.ve",
+ "int.ve",
+ "mil.ve",
+ "net.ve",
+ "org.ve",
+ "rec.ve",
+ "store.ve",
+ "tec.ve",
+ "web.ve",
+ "vg",
+ "vi",
+ "co.vi",
+ "com.vi",
+ "k12.vi",
+ "net.vi",
+ "org.vi",
+ "vn",
+ "com.vn",
+ "net.vn",
+ "org.vn",
+ "edu.vn",
+ "gov.vn",
+ "int.vn",
+ "ac.vn",
+ "biz.vn",
+ "info.vn",
+ "name.vn",
+ "pro.vn",
+ "health.vn",
+ "vu",
+ "com.vu",
+ "edu.vu",
+ "net.vu",
+ "org.vu",
+ "wf",
+ "ws",
+ "com.ws",
+ "net.ws",
+ "org.ws",
+ "gov.ws",
+ "edu.ws",
+ "yt",
+ "xn--mgbaam7a8h",
+ "xn--y9a3aq",
+ "xn--54b7fta0cc",
+ "xn--90ae",
+ "xn--90ais",
+ "xn--fiqs8s",
+ "xn--fiqz9s",
+ "xn--lgbbat1ad8j",
+ "xn--wgbh1c",
+ "xn--e1a4c",
+ "xn--node",
+ "xn--qxam",
+ "xn--j6w193g",
+ "xn--2scrj9c",
+ "xn--3hcrj9c",
+ "xn--45br5cyl",
+ "xn--h2breg3eve",
+ "xn--h2brj9c8c",
+ "xn--mgbgu82a",
+ "xn--rvc1e0am3e",
+ "xn--h2brj9c",
+ "xn--mgbbh1a71e",
+ "xn--fpcrj9c3d",
+ "xn--gecrj9c",
+ "xn--s9brj9c",
+ "xn--45brj9c",
+ "xn--xkc2dl3a5ee0h",
+ "xn--mgba3a4f16a",
+ "xn--mgba3a4fra",
+ "xn--mgbtx2b",
+ "xn--mgbayh7gpa",
+ "xn--3e0b707e",
+ "xn--80ao21a",
+ "xn--fzc2c9e2c",
+ "xn--xkc2al3hye2a",
+ "xn--mgbc0a9azcg",
+ "xn--d1alf",
+ "xn--l1acc",
+ "xn--mix891f",
+ "xn--mix082f",
+ "xn--mgbx4cd0ab",
+ "xn--mgb9awbf",
+ "xn--mgbai9azgqp6j",
+ "xn--mgbai9a5eva00b",
+ "xn--ygbi2ammx",
+ "xn--90a3ac",
+ "xn--o1ac.xn--90a3ac",
+ "xn--c1avg.xn--90a3ac",
+ "xn--90azh.xn--90a3ac",
+ "xn--d1at.xn--90a3ac",
+ "xn--o1ach.xn--90a3ac",
+ "xn--80au.xn--90a3ac",
+ "xn--p1ai",
+ "xn--wgbl6a",
+ "xn--mgberp4a5d4ar",
+ "xn--mgberp4a5d4a87g",
+ "xn--mgbqly7c0a67fbc",
+ "xn--mgbqly7cvafr",
+ "xn--mgbpl2fh",
+ "xn--yfro4i67o",
+ "xn--clchc0ea0b2g2a9gcd",
+ "xn--ogbpf8fl",
+ "xn--mgbtf8fl",
+ "xn--o3cw4h",
+ "xn--12c1fe0br.xn--o3cw4h",
+ "xn--12co0c3b4eva.xn--o3cw4h",
+ "xn--h3cuzk1di.xn--o3cw4h",
+ "xn--o3cyx2a.xn--o3cw4h",
+ "xn--m3ch0j3a.xn--o3cw4h",
+ "xn--12cfi8ixb8l.xn--o3cw4h",
+ "xn--pgbs0dh",
+ "xn--kpry57d",
+ "xn--kprw13d",
+ "xn--nnx388a",
+ "xn--j1amh",
+ "xn--mgb2ddes",
+ "xxx",
+ "*.ye",
+ "ac.za",
+ "agric.za",
+ "alt.za",
+ "co.za",
+ "edu.za",
+ "gov.za",
+ "grondar.za",
+ "law.za",
+ "mil.za",
+ "net.za",
+ "ngo.za",
+ "nis.za",
+ "nom.za",
+ "org.za",
+ "school.za",
+ "tm.za",
+ "web.za",
+ "zm",
+ "ac.zm",
+ "biz.zm",
+ "co.zm",
+ "com.zm",
+ "edu.zm",
+ "gov.zm",
+ "info.zm",
+ "mil.zm",
+ "net.zm",
+ "org.zm",
+ "sch.zm",
+ "zw",
+ "ac.zw",
+ "co.zw",
+ "gov.zw",
+ "mil.zw",
+ "org.zw",
+ "aaa",
+ "aarp",
+ "abarth",
+ "abb",
+ "abbott",
+ "abbvie",
+ "abc",
+ "able",
+ "abogado",
+ "abudhabi",
+ "academy",
+ "accenture",
+ "accountant",
+ "accountants",
+ "aco",
+ "active",
+ "actor",
+ "adac",
+ "ads",
+ "adult",
+ "aeg",
+ "aetna",
+ "afamilycompany",
+ "afl",
+ "africa",
+ "agakhan",
+ "agency",
+ "aig",
+ "aigo",
+ "airbus",
+ "airforce",
+ "airtel",
+ "akdn",
+ "alfaromeo",
+ "alibaba",
+ "alipay",
+ "allfinanz",
+ "allstate",
+ "ally",
+ "alsace",
+ "alstom",
+ "americanexpress",
+ "americanfamily",
+ "amex",
+ "amfam",
+ "amica",
+ "amsterdam",
+ "analytics",
+ "android",
+ "anquan",
+ "anz",
+ "aol",
+ "apartments",
+ "app",
+ "apple",
+ "aquarelle",
+ "arab",
+ "aramco",
+ "archi",
+ "army",
+ "art",
+ "arte",
+ "asda",
+ "associates",
+ "athleta",
+ "attorney",
+ "auction",
+ "audi",
+ "audible",
+ "audio",
+ "auspost",
+ "author",
+ "auto",
+ "autos",
+ "avianca",
+ "aws",
+ "axa",
+ "azure",
+ "baby",
+ "baidu",
+ "banamex",
+ "bananarepublic",
+ "band",
+ "bank",
+ "bar",
+ "barcelona",
+ "barclaycard",
+ "barclays",
+ "barefoot",
+ "bargains",
+ "baseball",
+ "basketball",
+ "bauhaus",
+ "bayern",
+ "bbc",
+ "bbt",
+ "bbva",
+ "bcg",
+ "bcn",
+ "beats",
+ "beauty",
+ "beer",
+ "bentley",
+ "berlin",
+ "best",
+ "bestbuy",
+ "bet",
+ "bharti",
+ "bible",
+ "bid",
+ "bike",
+ "bing",
+ "bingo",
+ "bio",
+ "black",
+ "blackfriday",
+ "blanco",
+ "blockbuster",
+ "blog",
+ "bloomberg",
+ "blue",
+ "bms",
+ "bmw",
+ "bnl",
+ "bnpparibas",
+ "boats",
+ "boehringer",
+ "bofa",
+ "bom",
+ "bond",
+ "boo",
+ "book",
+ "booking",
+ "boots",
+ "bosch",
+ "bostik",
+ "boston",
+ "bot",
+ "boutique",
+ "box",
+ "bradesco",
+ "bridgestone",
+ "broadway",
+ "broker",
+ "brother",
+ "brussels",
+ "budapest",
+ "bugatti",
+ "build",
+ "builders",
+ "business",
+ "buy",
+ "buzz",
+ "bzh",
+ "cab",
+ "cafe",
+ "cal",
+ "call",
+ "calvinklein",
+ "cam",
+ "camera",
+ "camp",
+ "cancerresearch",
+ "canon",
+ "capetown",
+ "capital",
+ "capitalone",
+ "car",
+ "caravan",
+ "cards",
+ "care",
+ "career",
+ "careers",
+ "cars",
+ "cartier",
+ "casa",
+ "case",
+ "caseih",
+ "cash",
+ "casino",
+ "catering",
+ "catholic",
+ "cba",
+ "cbn",
+ "cbre",
+ "cbs",
+ "ceb",
+ "center",
+ "ceo",
+ "cern",
+ "cfa",
+ "cfd",
+ "chanel",
+ "channel",
+ "chase",
+ "chat",
+ "cheap",
+ "chintai",
+ "chloe",
+ "christmas",
+ "chrome",
+ "chrysler",
+ "church",
+ "cipriani",
+ "circle",
+ "cisco",
+ "citadel",
+ "citi",
+ "citic",
+ "city",
+ "cityeats",
+ "claims",
+ "cleaning",
+ "click",
+ "clinic",
+ "clinique",
+ "clothing",
+ "cloud",
+ "club",
+ "clubmed",
+ "coach",
+ "codes",
+ "coffee",
+ "college",
+ "cologne",
+ "comcast",
+ "commbank",
+ "community",
+ "company",
+ "compare",
+ "computer",
+ "comsec",
+ "condos",
+ "construction",
+ "consulting",
+ "contact",
+ "contractors",
+ "cooking",
+ "cookingchannel",
+ "cool",
+ "corsica",
+ "country",
+ "coupon",
+ "coupons",
+ "courses",
+ "credit",
+ "creditcard",
+ "creditunion",
+ "cricket",
+ "crown",
+ "crs",
+ "cruise",
+ "cruises",
+ "csc",
+ "cuisinella",
+ "cymru",
+ "cyou",
+ "dabur",
+ "dad",
+ "dance",
+ "data",
+ "date",
+ "dating",
+ "datsun",
+ "day",
+ "dclk",
+ "dds",
+ "deal",
+ "dealer",
+ "deals",
+ "degree",
+ "delivery",
+ "dell",
+ "deloitte",
+ "delta",
+ "democrat",
+ "dental",
+ "dentist",
+ "desi",
+ "design",
+ "dev",
+ "dhl",
+ "diamonds",
+ "diet",
+ "digital",
+ "direct",
+ "directory",
+ "discount",
+ "discover",
+ "dish",
+ "diy",
+ "dnp",
+ "docs",
+ "doctor",
+ "dodge",
+ "dog",
+ "doha",
+ "domains",
+ "dot",
+ "download",
+ "drive",
+ "dtv",
+ "dubai",
+ "duck",
+ "dunlop",
+ "duns",
+ "dupont",
+ "durban",
+ "dvag",
+ "dvr",
+ "earth",
+ "eat",
+ "eco",
+ "edeka",
+ "education",
+ "email",
+ "emerck",
+ "energy",
+ "engineer",
+ "engineering",
+ "enterprises",
+ "epost",
+ "epson",
+ "equipment",
+ "ericsson",
+ "erni",
+ "esq",
+ "estate",
+ "esurance",
+ "etisalat",
+ "eurovision",
+ "eus",
+ "events",
+ "everbank",
+ "exchange",
+ "expert",
+ "exposed",
+ "express",
+ "extraspace",
+ "fage",
+ "fail",
+ "fairwinds",
+ "faith",
+ "family",
+ "fan",
+ "fans",
+ "farm",
+ "farmers",
+ "fashion",
+ "fast",
+ "fedex",
+ "feedback",
+ "ferrari",
+ "ferrero",
+ "fiat",
+ "fidelity",
+ "fido",
+ "film",
+ "final",
+ "finance",
+ "financial",
+ "fire",
+ "firestone",
+ "firmdale",
+ "fish",
+ "fishing",
+ "fit",
+ "fitness",
+ "flickr",
+ "flights",
+ "flir",
+ "florist",
+ "flowers",
+ "fly",
+ "foo",
+ "food",
+ "foodnetwork",
+ "football",
+ "ford",
+ "forex",
+ "forsale",
+ "forum",
+ "foundation",
+ "fox",
+ "free",
+ "fresenius",
+ "frl",
+ "frogans",
+ "frontdoor",
+ "frontier",
+ "ftr",
+ "fujitsu",
+ "fujixerox",
+ "fun",
+ "fund",
+ "furniture",
+ "futbol",
+ "fyi",
+ "gal",
+ "gallery",
+ "gallo",
+ "gallup",
+ "game",
+ "games",
+ "gap",
+ "garden",
+ "gbiz",
+ "gdn",
+ "gea",
+ "gent",
+ "genting",
+ "george",
+ "ggee",
+ "gift",
+ "gifts",
+ "gives",
+ "giving",
+ "glade",
+ "glass",
+ "gle",
+ "global",
+ "globo",
+ "gmail",
+ "gmbh",
+ "gmo",
+ "gmx",
+ "godaddy",
+ "gold",
+ "goldpoint",
+ "golf",
+ "goo",
+ "goodhands",
+ "goodyear",
+ "goog",
+ "google",
+ "gop",
+ "got",
+ "grainger",
+ "graphics",
+ "gratis",
+ "green",
+ "gripe",
+ "grocery",
+ "group",
+ "guardian",
+ "gucci",
+ "guge",
+ "guide",
+ "guitars",
+ "guru",
+ "hair",
+ "hamburg",
+ "hangout",
+ "haus",
+ "hbo",
+ "hdfc",
+ "hdfcbank",
+ "health",
+ "healthcare",
+ "help",
+ "helsinki",
+ "here",
+ "hermes",
+ "hgtv",
+ "hiphop",
+ "hisamitsu",
+ "hitachi",
+ "hiv",
+ "hkt",
+ "hockey",
+ "holdings",
+ "holiday",
+ "homedepot",
+ "homegoods",
+ "homes",
+ "homesense",
+ "honda",
+ "honeywell",
+ "horse",
+ "hospital",
+ "host",
+ "hosting",
+ "hot",
+ "hoteles",
+ "hotels",
+ "hotmail",
+ "house",
+ "how",
+ "hsbc",
+ "htc",
+ "hughes",
+ "hyatt",
+ "hyundai",
+ "ibm",
+ "icbc",
+ "ice",
+ "icu",
+ "ieee",
+ "ifm",
+ "ikano",
+ "imamat",
+ "imdb",
+ "immo",
+ "immobilien",
+ "industries",
+ "infiniti",
+ "ing",
+ "ink",
+ "institute",
+ "insurance",
+ "insure",
+ "intel",
+ "international",
+ "intuit",
+ "investments",
+ "ipiranga",
+ "irish",
+ "iselect",
+ "ismaili",
+ "ist",
+ "istanbul",
+ "itau",
+ "itv",
+ "iveco",
+ "iwc",
+ "jaguar",
+ "java",
+ "jcb",
+ "jcp",
+ "jeep",
+ "jetzt",
+ "jewelry",
+ "jio",
+ "jlc",
+ "jll",
+ "jmp",
+ "jnj",
+ "joburg",
+ "jot",
+ "joy",
+ "jpmorgan",
+ "jprs",
+ "juegos",
+ "juniper",
+ "kaufen",
+ "kddi",
+ "kerryhotels",
+ "kerrylogistics",
+ "kerryproperties",
+ "kfh",
+ "kia",
+ "kim",
+ "kinder",
+ "kindle",
+ "kitchen",
+ "kiwi",
+ "koeln",
+ "komatsu",
+ "kosher",
+ "kpmg",
+ "kpn",
+ "krd",
+ "kred",
+ "kuokgroup",
+ "kyoto",
+ "lacaixa",
+ "ladbrokes",
+ "lamborghini",
+ "lamer",
+ "lancaster",
+ "lancia",
+ "lancome",
+ "land",
+ "landrover",
+ "lanxess",
+ "lasalle",
+ "lat",
+ "latino",
+ "latrobe",
+ "law",
+ "lawyer",
+ "lds",
+ "lease",
+ "leclerc",
+ "lefrak",
+ "legal",
+ "lego",
+ "lexus",
+ "lgbt",
+ "liaison",
+ "lidl",
+ "life",
+ "lifeinsurance",
+ "lifestyle",
+ "lighting",
+ "like",
+ "lilly",
+ "limited",
+ "limo",
+ "lincoln",
+ "linde",
+ "link",
+ "lipsy",
+ "live",
+ "living",
+ "lixil",
+ "loan",
+ "loans",
+ "locker",
+ "locus",
+ "loft",
+ "lol",
+ "london",
+ "lotte",
+ "lotto",
+ "love",
+ "lpl",
+ "lplfinancial",
+ "ltd",
+ "ltda",
+ "lundbeck",
+ "lupin",
+ "luxe",
+ "luxury",
+ "macys",
+ "madrid",
+ "maif",
+ "maison",
+ "makeup",
+ "man",
+ "management",
+ "mango",
+ "map",
+ "market",
+ "marketing",
+ "markets",
+ "marriott",
+ "marshalls",
+ "maserati",
+ "mattel",
+ "mba",
+ "mcd",
+ "mcdonalds",
+ "mckinsey",
+ "med",
+ "media",
+ "meet",
+ "melbourne",
+ "meme",
+ "memorial",
+ "men",
+ "menu",
+ "meo",
+ "merckmsd",
+ "metlife",
+ "miami",
+ "microsoft",
+ "mini",
+ "mint",
+ "mit",
+ "mitsubishi",
+ "mlb",
+ "mls",
+ "mma",
+ "mobile",
+ "mobily",
+ "moda",
+ "moe",
+ "moi",
+ "mom",
+ "monash",
+ "money",
+ "monster",
+ "montblanc",
+ "mopar",
+ "mormon",
+ "mortgage",
+ "moscow",
+ "moto",
+ "motorcycles",
+ "mov",
+ "movie",
+ "movistar",
+ "msd",
+ "mtn",
+ "mtpc",
+ "mtr",
+ "mutual",
+ "nab",
+ "nadex",
+ "nagoya",
+ "nationwide",
+ "natura",
+ "navy",
+ "nba",
+ "nec",
+ "netbank",
+ "netflix",
+ "network",
+ "neustar",
+ "new",
+ "newholland",
+ "news",
+ "next",
+ "nextdirect",
+ "nexus",
+ "nfl",
+ "ngo",
+ "nhk",
+ "nico",
+ "nike",
+ "nikon",
+ "ninja",
+ "nissan",
+ "nissay",
+ "nokia",
+ "northwesternmutual",
+ "norton",
+ "now",
+ "nowruz",
+ "nowtv",
+ "nra",
+ "nrw",
+ "ntt",
+ "nyc",
+ "obi",
+ "observer",
+ "off",
+ "office",
+ "okinawa",
+ "olayan",
+ "olayangroup",
+ "oldnavy",
+ "ollo",
+ "omega",
+ "one",
+ "ong",
+ "onl",
+ "online",
+ "onyourside",
+ "ooo",
+ "open",
+ "oracle",
+ "orange",
+ "organic",
+ "origins",
+ "osaka",
+ "otsuka",
+ "ott",
+ "ovh",
+ "page",
+ "pamperedchef",
+ "panasonic",
+ "panerai",
+ "paris",
+ "pars",
+ "partners",
+ "parts",
+ "party",
+ "passagens",
+ "pay",
+ "pccw",
+ "pet",
+ "pfizer",
+ "pharmacy",
+ "phd",
+ "philips",
+ "phone",
+ "photo",
+ "photography",
+ "photos",
+ "physio",
+ "piaget",
+ "pics",
+ "pictet",
+ "pictures",
+ "pid",
+ "pin",
+ "ping",
+ "pink",
+ "pioneer",
+ "pizza",
+ "place",
+ "play",
+ "playstation",
+ "plumbing",
+ "plus",
+ "pnc",
+ "pohl",
+ "poker",
+ "politie",
+ "porn",
+ "pramerica",
+ "praxi",
+ "press",
+ "prime",
+ "prod",
+ "productions",
+ "prof",
+ "progressive",
+ "promo",
+ "properties",
+ "property",
+ "protection",
+ "pru",
+ "prudential",
+ "pub",
+ "pwc",
+ "qpon",
+ "quebec",
+ "quest",
+ "qvc",
+ "racing",
+ "radio",
+ "raid",
+ "read",
+ "realestate",
+ "realtor",
+ "realty",
+ "recipes",
+ "red",
+ "redstone",
+ "redumbrella",
+ "rehab",
+ "reise",
+ "reisen",
+ "reit",
+ "reliance",
+ "ren",
+ "rent",
+ "rentals",
+ "repair",
+ "report",
+ "republican",
+ "rest",
+ "restaurant",
+ "review",
+ "reviews",
+ "rexroth",
+ "rich",
+ "richardli",
+ "ricoh",
+ "rightathome",
+ "ril",
+ "rio",
+ "rip",
+ "rmit",
+ "rocher",
+ "rocks",
+ "rodeo",
+ "rogers",
+ "room",
+ "rsvp",
+ "rugby",
+ "ruhr",
+ "run",
+ "rwe",
+ "ryukyu",
+ "saarland",
+ "safe",
+ "safety",
+ "sakura",
+ "sale",
+ "salon",
+ "samsclub",
+ "samsung",
+ "sandvik",
+ "sandvikcoromant",
+ "sanofi",
+ "sap",
+ "sapo",
+ "sarl",
+ "sas",
+ "save",
+ "saxo",
+ "sbi",
+ "sbs",
+ "sca",
+ "scb",
+ "schaeffler",
+ "schmidt",
+ "scholarships",
+ "school",
+ "schule",
+ "schwarz",
+ "science",
+ "scjohnson",
+ "scor",
+ "scot",
+ "search",
+ "seat",
+ "secure",
+ "security",
+ "seek",
+ "select",
+ "sener",
+ "services",
+ "ses",
+ "seven",
+ "sew",
+ "sex",
+ "sexy",
+ "sfr",
+ "shangrila",
+ "sharp",
+ "shaw",
+ "shell",
+ "shia",
+ "shiksha",
+ "shoes",
+ "shop",
+ "shopping",
+ "shouji",
+ "show",
+ "showtime",
+ "shriram",
+ "silk",
+ "sina",
+ "singles",
+ "site",
+ "ski",
+ "skin",
+ "sky",
+ "skype",
+ "sling",
+ "smart",
+ "smile",
+ "sncf",
+ "soccer",
+ "social",
+ "softbank",
+ "software",
+ "sohu",
+ "solar",
+ "solutions",
+ "song",
+ "sony",
+ "soy",
+ "space",
+ "spiegel",
+ "spot",
+ "spreadbetting",
+ "srl",
+ "srt",
+ "stada",
+ "staples",
+ "star",
+ "starhub",
+ "statebank",
+ "statefarm",
+ "statoil",
+ "stc",
+ "stcgroup",
+ "stockholm",
+ "storage",
+ "store",
+ "stream",
+ "studio",
+ "study",
+ "style",
+ "sucks",
+ "supplies",
+ "supply",
+ "support",
+ "surf",
+ "surgery",
+ "suzuki",
+ "swatch",
+ "swiftcover",
+ "swiss",
+ "sydney",
+ "symantec",
+ "systems",
+ "tab",
+ "taipei",
+ "talk",
+ "taobao",
+ "target",
+ "tatamotors",
+ "tatar",
+ "tattoo",
+ "tax",
+ "taxi",
+ "tci",
+ "tdk",
+ "team",
+ "tech",
+ "technology",
+ "telecity",
+ "telefonica",
+ "temasek",
+ "tennis",
+ "teva",
+ "thd",
+ "theater",
+ "theatre",
+ "tiaa",
+ "tickets",
+ "tienda",
+ "tiffany",
+ "tips",
+ "tires",
+ "tirol",
+ "tjmaxx",
+ "tjx",
+ "tkmaxx",
+ "tmall",
+ "today",
+ "tokyo",
+ "tools",
+ "top",
+ "toray",
+ "toshiba",
+ "total",
+ "tours",
+ "town",
+ "toyota",
+ "toys",
+ "trade",
+ "trading",
+ "training",
+ "travelchannel",
+ "travelers",
+ "travelersinsurance",
+ "trust",
+ "trv",
+ "tube",
+ "tui",
+ "tunes",
+ "tushu",
+ "tvs",
+ "ubank",
+ "ubs",
+ "uconnect",
+ "unicom",
+ "university",
+ "uno",
+ "uol",
+ "ups",
+ "vacations",
+ "vana",
+ "vanguard",
+ "vegas",
+ "ventures",
+ "verisign",
+ "versicherung",
+ "vet",
+ "viajes",
+ "video",
+ "vig",
+ "viking",
+ "villas",
+ "vin",
+ "vip",
+ "virgin",
+ "visa",
+ "vision",
+ "vista",
+ "vistaprint",
+ "viva",
+ "vivo",
+ "vlaanderen",
+ "vodka",
+ "volkswagen",
+ "volvo",
+ "vote",
+ "voting",
+ "voto",
+ "voyage",
+ "vuelos",
+ "wales",
+ "walmart",
+ "walter",
+ "wang",
+ "wanggou",
+ "warman",
+ "watch",
+ "watches",
+ "weather",
+ "weatherchannel",
+ "webcam",
+ "weber",
+ "website",
+ "wed",
+ "wedding",
+ "weibo",
+ "weir",
+ "whoswho",
+ "wien",
+ "wiki",
+ "williamhill",
+ "win",
+ "windows",
+ "wine",
+ "winners",
+ "wme",
+ "wolterskluwer",
+ "woodside",
+ "work",
+ "works",
+ "world",
+ "wow",
+ "wtc",
+ "wtf",
+ "xbox",
+ "xerox",
+ "xfinity",
+ "xihuan",
+ "xin",
+ "xn--11b4c3d",
+ "xn--1ck2e1b",
+ "xn--1qqw23a",
+ "xn--30rr7y",
+ "xn--3bst00m",
+ "xn--3ds443g",
+ "xn--3oq18vl8pn36a",
+ "xn--3pxu8k",
+ "xn--42c2d9a",
+ "xn--45q11c",
+ "xn--4gbrim",
+ "xn--55qw42g",
+ "xn--55qx5d",
+ "xn--5su34j936bgsg",
+ "xn--5tzm5g",
+ "xn--6frz82g",
+ "xn--6qq986b3xl",
+ "xn--80adxhks",
+ "xn--80aqecdr1a",
+ "xn--80asehdb",
+ "xn--80aswg",
+ "xn--8y0a063a",
+ "xn--9dbq2a",
+ "xn--9et52u",
+ "xn--9krt00a",
+ "xn--b4w605ferd",
+ "xn--bck1b9a5dre4c",
+ "xn--c1avg",
+ "xn--c2br7g",
+ "xn--cck2b3b",
+ "xn--cg4bki",
+ "xn--czr694b",
+ "xn--czrs0t",
+ "xn--czru2d",
+ "xn--d1acj3b",
+ "xn--eckvdtc9d",
+ "xn--efvy88h",
+ "xn--estv75g",
+ "xn--fct429k",
+ "xn--fhbei",
+ "xn--fiq228c5hs",
+ "xn--fiq64b",
+ "xn--fjq720a",
+ "xn--flw351e",
+ "xn--fzys8d69uvgm",
+ "xn--g2xx48c",
+ "xn--gckr3f0f",
+ "xn--gk3at1e",
+ "xn--hxt814e",
+ "xn--i1b6b1a6a2e",
+ "xn--imr513n",
+ "xn--io0a7i",
+ "xn--j1aef",
+ "xn--jlq61u9w7b",
+ "xn--jvr189m",
+ "xn--kcrx77d1x4a",
+ "xn--kpu716f",
+ "xn--kput3i",
+ "xn--mgba3a3ejt",
+ "xn--mgba7c0bbn0a",
+ "xn--mgbaakc7dvf",
+ "xn--mgbab2bd",
+ "xn--mgbb9fbpob",
+ "xn--mgbca7dzdo",
+ "xn--mgbi4ecexp",
+ "xn--mgbt3dhd",
+ "xn--mk1bu44c",
+ "xn--mxtq1m",
+ "xn--ngbc5azd",
+ "xn--ngbe9e0a",
+ "xn--ngbrx",
+ "xn--nqv7f",
+ "xn--nqv7fs00ema",
+ "xn--nyqy26a",
+ "xn--p1acf",
+ "xn--pbt977c",
+ "xn--pssy2u",
+ "xn--q9jyb4c",
+ "xn--qcka1pmc",
+ "xn--rhqv96g",
+ "xn--rovu88b",
+ "xn--ses554g",
+ "xn--t60b56a",
+ "xn--tckwe",
+ "xn--tiq49xqyj",
+ "xn--unup4y",
+ "xn--vermgensberater-ctb",
+ "xn--vermgensberatung-pwb",
+ "xn--vhquv",
+ "xn--vuq861b",
+ "xn--w4r85el8fhu5dnra",
+ "xn--w4rs40l",
+ "xn--xhq521b",
+ "xn--zfr164b",
+ "xperia",
+ "xyz",
+ "yachts",
+ "yahoo",
+ "yamaxun",
+ "yandex",
+ "yodobashi",
+ "yoga",
+ "yokohama",
+ "you",
+ "youtube",
+ "yun",
+ "zappos",
+ "zara",
+ "zero",
+ "zip",
+ "zippo",
+ "zone",
+ "zuerich",
+ "cc.ua",
+ "inf.ua",
+ "ltd.ua",
+ "beep.pl",
+ "*.compute.estate",
+ "*.alces.network",
+ "*.alwaysdata.net",
+ "cloudfront.net",
+ "*.compute.amazonaws.com",
+ "*.compute-1.amazonaws.com",
+ "*.compute.amazonaws.com.cn",
+ "us-east-1.amazonaws.com",
+ "cn-north-1.eb.amazonaws.com.cn",
+ "elasticbeanstalk.com",
+ "ap-northeast-1.elasticbeanstalk.com",
+ "ap-northeast-2.elasticbeanstalk.com",
+ "ap-south-1.elasticbeanstalk.com",
+ "ap-southeast-1.elasticbeanstalk.com",
+ "ap-southeast-2.elasticbeanstalk.com",
+ "ca-central-1.elasticbeanstalk.com",
+ "eu-central-1.elasticbeanstalk.com",
+ "eu-west-1.elasticbeanstalk.com",
+ "eu-west-2.elasticbeanstalk.com",
+ "sa-east-1.elasticbeanstalk.com",
+ "us-east-1.elasticbeanstalk.com",
+ "us-east-2.elasticbeanstalk.com",
+ "us-gov-west-1.elasticbeanstalk.com",
+ "us-west-1.elasticbeanstalk.com",
+ "us-west-2.elasticbeanstalk.com",
+ "*.elb.amazonaws.com",
+ "*.elb.amazonaws.com.cn",
+ "s3.amazonaws.com",
+ "s3-ap-northeast-1.amazonaws.com",
+ "s3-ap-northeast-2.amazonaws.com",
+ "s3-ap-south-1.amazonaws.com",
+ "s3-ap-southeast-1.amazonaws.com",
+ "s3-ap-southeast-2.amazonaws.com",
+ "s3-ca-central-1.amazonaws.com",
+ "s3-eu-central-1.amazonaws.com",
+ "s3-eu-west-1.amazonaws.com",
+ "s3-eu-west-2.amazonaws.com",
+ "s3-external-1.amazonaws.com",
+ "s3-fips-us-gov-west-1.amazonaws.com",
+ "s3-sa-east-1.amazonaws.com",
+ "s3-us-gov-west-1.amazonaws.com",
+ "s3-us-east-2.amazonaws.com",
+ "s3-us-west-1.amazonaws.com",
+ "s3-us-west-2.amazonaws.com",
+ "s3.ap-northeast-2.amazonaws.com",
+ "s3.ap-south-1.amazonaws.com",
+ "s3.cn-north-1.amazonaws.com.cn",
+ "s3.ca-central-1.amazonaws.com",
+ "s3.eu-central-1.amazonaws.com",
+ "s3.eu-west-2.amazonaws.com",
+ "s3.us-east-2.amazonaws.com",
+ "s3.dualstack.ap-northeast-1.amazonaws.com",
+ "s3.dualstack.ap-northeast-2.amazonaws.com",
+ "s3.dualstack.ap-south-1.amazonaws.com",
+ "s3.dualstack.ap-southeast-1.amazonaws.com",
+ "s3.dualstack.ap-southeast-2.amazonaws.com",
+ "s3.dualstack.ca-central-1.amazonaws.com",
+ "s3.dualstack.eu-central-1.amazonaws.com",
+ "s3.dualstack.eu-west-1.amazonaws.com",
+ "s3.dualstack.eu-west-2.amazonaws.com",
+ "s3.dualstack.sa-east-1.amazonaws.com",
+ "s3.dualstack.us-east-1.amazonaws.com",
+ "s3.dualstack.us-east-2.amazonaws.com",
+ "s3-website-us-east-1.amazonaws.com",
+ "s3-website-us-west-1.amazonaws.com",
+ "s3-website-us-west-2.amazonaws.com",
+ "s3-website-ap-northeast-1.amazonaws.com",
+ "s3-website-ap-southeast-1.amazonaws.com",
+ "s3-website-ap-southeast-2.amazonaws.com",
+ "s3-website-eu-west-1.amazonaws.com",
+ "s3-website-sa-east-1.amazonaws.com",
+ "s3-website.ap-northeast-2.amazonaws.com",
+ "s3-website.ap-south-1.amazonaws.com",
+ "s3-website.ca-central-1.amazonaws.com",
+ "s3-website.eu-central-1.amazonaws.com",
+ "s3-website.eu-west-2.amazonaws.com",
+ "s3-website.us-east-2.amazonaws.com",
+ "t3l3p0rt.net",
+ "tele.amune.org",
+ "on-aptible.com",
+ "user.party.eus",
+ "pimienta.org",
+ "poivron.org",
+ "potager.org",
+ "sweetpepper.org",
+ "myasustor.com",
+ "myfritz.net",
+ "*.awdev.ca",
+ "*.advisor.ws",
+ "backplaneapp.io",
+ "betainabox.com",
+ "bnr.la",
+ "boomla.net",
+ "boxfuse.io",
+ "square7.ch",
+ "bplaced.com",
+ "bplaced.de",
+ "square7.de",
+ "bplaced.net",
+ "square7.net",
+ "browsersafetymark.io",
+ "mycd.eu",
+ "ae.org",
+ "ar.com",
+ "br.com",
+ "cn.com",
+ "com.de",
+ "com.se",
+ "de.com",
+ "eu.com",
+ "gb.com",
+ "gb.net",
+ "hu.com",
+ "hu.net",
+ "jp.net",
+ "jpn.com",
+ "kr.com",
+ "mex.com",
+ "no.com",
+ "qc.com",
+ "ru.com",
+ "sa.com",
+ "se.com",
+ "se.net",
+ "uk.com",
+ "uk.net",
+ "us.com",
+ "uy.com",
+ "za.bz",
+ "za.com",
+ "africa.com",
+ "gr.com",
+ "in.net",
+ "us.org",
+ "co.com",
+ "c.la",
+ "certmgr.org",
+ "xenapponazure.com",
+ "virtueeldomein.nl",
+ "c66.me",
+ "jdevcloud.com",
+ "wpdevcloud.com",
+ "cloudaccess.host",
+ "freesite.host",
+ "cloudaccess.net",
+ "cloudcontrolled.com",
+ "cloudcontrolapp.com",
+ "co.ca",
+ "co.cz",
+ "c.cdn77.org",
+ "cdn77-ssl.net",
+ "r.cdn77.net",
+ "rsc.cdn77.org",
+ "ssl.origin.cdn77-secure.org",
+ "cloudns.asia",
+ "cloudns.biz",
+ "cloudns.club",
+ "cloudns.cc",
+ "cloudns.eu",
+ "cloudns.in",
+ "cloudns.info",
+ "cloudns.org",
+ "cloudns.pro",
+ "cloudns.pw",
+ "cloudns.us",
+ "co.nl",
+ "co.no",
+ "dyn.cosidns.de",
+ "dynamisches-dns.de",
+ "dnsupdater.de",
+ "internet-dns.de",
+ "l-o-g-i-n.de",
+ "dynamic-dns.info",
+ "feste-ip.net",
+ "knx-server.net",
+ "static-access.net",
+ "realm.cz",
+ "*.cryptonomic.net",
+ "cupcake.is",
+ "cyon.link",
+ "cyon.site",
+ "daplie.me",
+ "localhost.daplie.me",
+ "biz.dk",
+ "co.dk",
+ "firm.dk",
+ "reg.dk",
+ "store.dk",
+ "debian.net",
+ "dedyn.io",
+ "dnshome.de",
+ "drayddns.com",
+ "dreamhosters.com",
+ "mydrobo.com",
+ "drud.io",
+ "drud.us",
+ "duckdns.org",
+ "dy.fi",
+ "tunk.org",
+ "dyndns-at-home.com",
+ "dyndns-at-work.com",
+ "dyndns-blog.com",
+ "dyndns-free.com",
+ "dyndns-home.com",
+ "dyndns-ip.com",
+ "dyndns-mail.com",
+ "dyndns-office.com",
+ "dyndns-pics.com",
+ "dyndns-remote.com",
+ "dyndns-server.com",
+ "dyndns-web.com",
+ "dyndns-wiki.com",
+ "dyndns-work.com",
+ "dyndns.biz",
+ "dyndns.info",
+ "dyndns.org",
+ "dyndns.tv",
+ "at-band-camp.net",
+ "ath.cx",
+ "barrel-of-knowledge.info",
+ "barrell-of-knowledge.info",
+ "better-than.tv",
+ "blogdns.com",
+ "blogdns.net",
+ "blogdns.org",
+ "blogsite.org",
+ "boldlygoingnowhere.org",
+ "broke-it.net",
+ "buyshouses.net",
+ "cechire.com",
+ "dnsalias.com",
+ "dnsalias.net",
+ "dnsalias.org",
+ "dnsdojo.com",
+ "dnsdojo.net",
+ "dnsdojo.org",
+ "does-it.net",
+ "doesntexist.com",
+ "doesntexist.org",
+ "dontexist.com",
+ "dontexist.net",
+ "dontexist.org",
+ "doomdns.com",
+ "doomdns.org",
+ "dvrdns.org",
+ "dyn-o-saur.com",
+ "dynalias.com",
+ "dynalias.net",
+ "dynalias.org",
+ "dynathome.net",
+ "dyndns.ws",
+ "endofinternet.net",
+ "endofinternet.org",
+ "endoftheinternet.org",
+ "est-a-la-maison.com",
+ "est-a-la-masion.com",
+ "est-le-patron.com",
+ "est-mon-blogueur.com",
+ "for-better.biz",
+ "for-more.biz",
+ "for-our.info",
+ "for-some.biz",
+ "for-the.biz",
+ "forgot.her.name",
+ "forgot.his.name",
+ "from-ak.com",
+ "from-al.com",
+ "from-ar.com",
+ "from-az.net",
+ "from-ca.com",
+ "from-co.net",
+ "from-ct.com",
+ "from-dc.com",
+ "from-de.com",
+ "from-fl.com",
+ "from-ga.com",
+ "from-hi.com",
+ "from-ia.com",
+ "from-id.com",
+ "from-il.com",
+ "from-in.com",
+ "from-ks.com",
+ "from-ky.com",
+ "from-la.net",
+ "from-ma.com",
+ "from-md.com",
+ "from-me.org",
+ "from-mi.com",
+ "from-mn.com",
+ "from-mo.com",
+ "from-ms.com",
+ "from-mt.com",
+ "from-nc.com",
+ "from-nd.com",
+ "from-ne.com",
+ "from-nh.com",
+ "from-nj.com",
+ "from-nm.com",
+ "from-nv.com",
+ "from-ny.net",
+ "from-oh.com",
+ "from-ok.com",
+ "from-or.com",
+ "from-pa.com",
+ "from-pr.com",
+ "from-ri.com",
+ "from-sc.com",
+ "from-sd.com",
+ "from-tn.com",
+ "from-tx.com",
+ "from-ut.com",
+ "from-va.com",
+ "from-vt.com",
+ "from-wa.com",
+ "from-wi.com",
+ "from-wv.com",
+ "from-wy.com",
+ "ftpaccess.cc",
+ "fuettertdasnetz.de",
+ "game-host.org",
+ "game-server.cc",
+ "getmyip.com",
+ "gets-it.net",
+ "go.dyndns.org",
+ "gotdns.com",
+ "gotdns.org",
+ "groks-the.info",
+ "groks-this.info",
+ "ham-radio-op.net",
+ "here-for-more.info",
+ "hobby-site.com",
+ "hobby-site.org",
+ "home.dyndns.org",
+ "homedns.org",
+ "homeftp.net",
+ "homeftp.org",
+ "homeip.net",
+ "homelinux.com",
+ "homelinux.net",
+ "homelinux.org",
+ "homeunix.com",
+ "homeunix.net",
+ "homeunix.org",
+ "iamallama.com",
+ "in-the-band.net",
+ "is-a-anarchist.com",
+ "is-a-blogger.com",
+ "is-a-bookkeeper.com",
+ "is-a-bruinsfan.org",
+ "is-a-bulls-fan.com",
+ "is-a-candidate.org",
+ "is-a-caterer.com",
+ "is-a-celticsfan.org",
+ "is-a-chef.com",
+ "is-a-chef.net",
+ "is-a-chef.org",
+ "is-a-conservative.com",
+ "is-a-cpa.com",
+ "is-a-cubicle-slave.com",
+ "is-a-democrat.com",
+ "is-a-designer.com",
+ "is-a-doctor.com",
+ "is-a-financialadvisor.com",
+ "is-a-geek.com",
+ "is-a-geek.net",
+ "is-a-geek.org",
+ "is-a-green.com",
+ "is-a-guru.com",
+ "is-a-hard-worker.com",
+ "is-a-hunter.com",
+ "is-a-knight.org",
+ "is-a-landscaper.com",
+ "is-a-lawyer.com",
+ "is-a-liberal.com",
+ "is-a-libertarian.com",
+ "is-a-linux-user.org",
+ "is-a-llama.com",
+ "is-a-musician.com",
+ "is-a-nascarfan.com",
+ "is-a-nurse.com",
+ "is-a-painter.com",
+ "is-a-patsfan.org",
+ "is-a-personaltrainer.com",
+ "is-a-photographer.com",
+ "is-a-player.com",
+ "is-a-republican.com",
+ "is-a-rockstar.com",
+ "is-a-socialist.com",
+ "is-a-soxfan.org",
+ "is-a-student.com",
+ "is-a-teacher.com",
+ "is-a-techie.com",
+ "is-a-therapist.com",
+ "is-an-accountant.com",
+ "is-an-actor.com",
+ "is-an-actress.com",
+ "is-an-anarchist.com",
+ "is-an-artist.com",
+ "is-an-engineer.com",
+ "is-an-entertainer.com",
+ "is-by.us",
+ "is-certified.com",
+ "is-found.org",
+ "is-gone.com",
+ "is-into-anime.com",
+ "is-into-cars.com",
+ "is-into-cartoons.com",
+ "is-into-games.com",
+ "is-leet.com",
+ "is-lost.org",
+ "is-not-certified.com",
+ "is-saved.org",
+ "is-slick.com",
+ "is-uberleet.com",
+ "is-very-bad.org",
+ "is-very-evil.org",
+ "is-very-good.org",
+ "is-very-nice.org",
+ "is-very-sweet.org",
+ "is-with-theband.com",
+ "isa-geek.com",
+ "isa-geek.net",
+ "isa-geek.org",
+ "isa-hockeynut.com",
+ "issmarterthanyou.com",
+ "isteingeek.de",
+ "istmein.de",
+ "kicks-ass.net",
+ "kicks-ass.org",
+ "knowsitall.info",
+ "land-4-sale.us",
+ "lebtimnetz.de",
+ "leitungsen.de",
+ "likes-pie.com",
+ "likescandy.com",
+ "merseine.nu",
+ "mine.nu",
+ "misconfused.org",
+ "mypets.ws",
+ "myphotos.cc",
+ "neat-url.com",
+ "office-on-the.net",
+ "on-the-web.tv",
+ "podzone.net",
+ "podzone.org",
+ "readmyblog.org",
+ "saves-the-whales.com",
+ "scrapper-site.net",
+ "scrapping.cc",
+ "selfip.biz",
+ "selfip.com",
+ "selfip.info",
+ "selfip.net",
+ "selfip.org",
+ "sells-for-less.com",
+ "sells-for-u.com",
+ "sells-it.net",
+ "sellsyourhome.org",
+ "servebbs.com",
+ "servebbs.net",
+ "servebbs.org",
+ "serveftp.net",
+ "serveftp.org",
+ "servegame.org",
+ "shacknet.nu",
+ "simple-url.com",
+ "space-to-rent.com",
+ "stuff-4-sale.org",
+ "stuff-4-sale.us",
+ "teaches-yoga.com",
+ "thruhere.net",
+ "traeumtgerade.de",
+ "webhop.biz",
+ "webhop.info",
+ "webhop.net",
+ "webhop.org",
+ "worse-than.tv",
+ "writesthisblog.com",
+ "ddnss.de",
+ "dyn.ddnss.de",
+ "dyndns.ddnss.de",
+ "dyndns1.de",
+ "dyn-ip24.de",
+ "home-webserver.de",
+ "dyn.home-webserver.de",
+ "myhome-server.de",
+ "ddnss.org",
+ "definima.net",
+ "definima.io",
+ "ddnsfree.com",
+ "ddnsgeek.com",
+ "giize.com",
+ "gleeze.com",
+ "kozow.com",
+ "loseyourip.com",
+ "ooguy.com",
+ "theworkpc.com",
+ "casacam.net",
+ "dynu.net",
+ "accesscam.org",
+ "camdvr.org",
+ "freeddns.org",
+ "mywire.org",
+ "webredirect.org",
+ "myddns.rocks",
+ "blogsite.xyz",
+ "dynv6.net",
+ "e4.cz",
+ "mytuleap.com",
+ "enonic.io",
+ "customer.enonic.io",
+ "eu.org",
+ "al.eu.org",
+ "asso.eu.org",
+ "at.eu.org",
+ "au.eu.org",
+ "be.eu.org",
+ "bg.eu.org",
+ "ca.eu.org",
+ "cd.eu.org",
+ "ch.eu.org",
+ "cn.eu.org",
+ "cy.eu.org",
+ "cz.eu.org",
+ "de.eu.org",
+ "dk.eu.org",
+ "edu.eu.org",
+ "ee.eu.org",
+ "es.eu.org",
+ "fi.eu.org",
+ "fr.eu.org",
+ "gr.eu.org",
+ "hr.eu.org",
+ "hu.eu.org",
+ "ie.eu.org",
+ "il.eu.org",
+ "in.eu.org",
+ "int.eu.org",
+ "is.eu.org",
+ "it.eu.org",
+ "jp.eu.org",
+ "kr.eu.org",
+ "lt.eu.org",
+ "lu.eu.org",
+ "lv.eu.org",
+ "mc.eu.org",
+ "me.eu.org",
+ "mk.eu.org",
+ "mt.eu.org",
+ "my.eu.org",
+ "net.eu.org",
+ "ng.eu.org",
+ "nl.eu.org",
+ "no.eu.org",
+ "nz.eu.org",
+ "paris.eu.org",
+ "pl.eu.org",
+ "pt.eu.org",
+ "q-a.eu.org",
+ "ro.eu.org",
+ "ru.eu.org",
+ "se.eu.org",
+ "si.eu.org",
+ "sk.eu.org",
+ "tr.eu.org",
+ "uk.eu.org",
+ "us.eu.org",
+ "eu-1.evennode.com",
+ "eu-2.evennode.com",
+ "eu-3.evennode.com",
+ "eu-4.evennode.com",
+ "us-1.evennode.com",
+ "us-2.evennode.com",
+ "us-3.evennode.com",
+ "us-4.evennode.com",
+ "twmail.cc",
+ "twmail.net",
+ "twmail.org",
+ "mymailer.com.tw",
+ "url.tw",
+ "apps.fbsbx.com",
+ "ru.net",
+ "adygeya.ru",
+ "bashkiria.ru",
+ "bir.ru",
+ "cbg.ru",
+ "com.ru",
+ "dagestan.ru",
+ "grozny.ru",
+ "kalmykia.ru",
+ "kustanai.ru",
+ "marine.ru",
+ "mordovia.ru",
+ "msk.ru",
+ "mytis.ru",
+ "nalchik.ru",
+ "nov.ru",
+ "pyatigorsk.ru",
+ "spb.ru",
+ "vladikavkaz.ru",
+ "vladimir.ru",
+ "abkhazia.su",
+ "adygeya.su",
+ "aktyubinsk.su",
+ "arkhangelsk.su",
+ "armenia.su",
+ "ashgabad.su",
+ "azerbaijan.su",
+ "balashov.su",
+ "bashkiria.su",
+ "bryansk.su",
+ "bukhara.su",
+ "chimkent.su",
+ "dagestan.su",
+ "east-kazakhstan.su",
+ "exnet.su",
+ "georgia.su",
+ "grozny.su",
+ "ivanovo.su",
+ "jambyl.su",
+ "kalmykia.su",
+ "kaluga.su",
+ "karacol.su",
+ "karaganda.su",
+ "karelia.su",
+ "khakassia.su",
+ "krasnodar.su",
+ "kurgan.su",
+ "kustanai.su",
+ "lenug.su",
+ "mangyshlak.su",
+ "mordovia.su",
+ "msk.su",
+ "murmansk.su",
+ "nalchik.su",
+ "navoi.su",
+ "north-kazakhstan.su",
+ "nov.su",
+ "obninsk.su",
+ "penza.su",
+ "pokrovsk.su",
+ "sochi.su",
+ "spb.su",
+ "tashkent.su",
+ "termez.su",
+ "togliatti.su",
+ "troitsk.su",
+ "tselinograd.su",
+ "tula.su",
+ "tuva.su",
+ "vladikavkaz.su",
+ "vladimir.su",
+ "vologda.su",
+ "channelsdvr.net",
+ "fastlylb.net",
+ "map.fastlylb.net",
+ "freetls.fastly.net",
+ "map.fastly.net",
+ "a.prod.fastly.net",
+ "global.prod.fastly.net",
+ "a.ssl.fastly.net",
+ "b.ssl.fastly.net",
+ "global.ssl.fastly.net",
+ "fhapp.xyz",
+ "fedorainfracloud.org",
+ "fedorapeople.org",
+ "cloud.fedoraproject.org",
+ "filegear.me",
+ "firebaseapp.com",
+ "flynnhub.com",
+ "flynnhosting.net",
+ "freebox-os.com",
+ "freeboxos.com",
+ "fbx-os.fr",
+ "fbxos.fr",
+ "freebox-os.fr",
+ "freeboxos.fr",
+ "myfusion.cloud",
+ "*.futurecms.at",
+ "futurehosting.at",
+ "futuremailing.at",
+ "*.ex.ortsinfo.at",
+ "*.kunden.ortsinfo.at",
+ "*.statics.cloud",
+ "service.gov.uk",
+ "github.io",
+ "githubusercontent.com",
+ "gitlab.io",
+ "homeoffice.gov.uk",
+ "ro.im",
+ "shop.ro",
+ "goip.de",
+ "*.0emm.com",
+ "appspot.com",
+ "blogspot.ae",
+ "blogspot.al",
+ "blogspot.am",
+ "blogspot.ba",
+ "blogspot.be",
+ "blogspot.bg",
+ "blogspot.bj",
+ "blogspot.ca",
+ "blogspot.cf",
+ "blogspot.ch",
+ "blogspot.cl",
+ "blogspot.co.at",
+ "blogspot.co.id",
+ "blogspot.co.il",
+ "blogspot.co.ke",
+ "blogspot.co.nz",
+ "blogspot.co.uk",
+ "blogspot.co.za",
+ "blogspot.com",
+ "blogspot.com.ar",
+ "blogspot.com.au",
+ "blogspot.com.br",
+ "blogspot.com.by",
+ "blogspot.com.co",
+ "blogspot.com.cy",
+ "blogspot.com.ee",
+ "blogspot.com.eg",
+ "blogspot.com.es",
+ "blogspot.com.mt",
+ "blogspot.com.ng",
+ "blogspot.com.tr",
+ "blogspot.com.uy",
+ "blogspot.cv",
+ "blogspot.cz",
+ "blogspot.de",
+ "blogspot.dk",
+ "blogspot.fi",
+ "blogspot.fr",
+ "blogspot.gr",
+ "blogspot.hk",
+ "blogspot.hr",
+ "blogspot.hu",
+ "blogspot.ie",
+ "blogspot.in",
+ "blogspot.is",
+ "blogspot.it",
+ "blogspot.jp",
+ "blogspot.kr",
+ "blogspot.li",
+ "blogspot.lt",
+ "blogspot.lu",
+ "blogspot.md",
+ "blogspot.mk",
+ "blogspot.mr",
+ "blogspot.mx",
+ "blogspot.my",
+ "blogspot.nl",
+ "blogspot.no",
+ "blogspot.pe",
+ "blogspot.pt",
+ "blogspot.qa",
+ "blogspot.re",
+ "blogspot.ro",
+ "blogspot.rs",
+ "blogspot.ru",
+ "blogspot.se",
+ "blogspot.sg",
+ "blogspot.si",
+ "blogspot.sk",
+ "blogspot.sn",
+ "blogspot.td",
+ "blogspot.tw",
+ "blogspot.ug",
+ "blogspot.vn",
+ "cloudfunctions.net",
+ "cloud.goog",
+ "codespot.com",
+ "googleapis.com",
+ "googlecode.com",
+ "pagespeedmobilizer.com",
+ "publishproxy.com",
+ "withgoogle.com",
+ "withyoutube.com",
+ "hashbang.sh",
+ "hasura-app.io",
+ "hepforge.org",
+ "herokuapp.com",
+ "herokussl.com",
+ "moonscale.net",
+ "iki.fi",
+ "biz.at",
+ "info.at",
+ "info.cx",
+ "ac.leg.br",
+ "al.leg.br",
+ "am.leg.br",
+ "ap.leg.br",
+ "ba.leg.br",
+ "ce.leg.br",
+ "df.leg.br",
+ "es.leg.br",
+ "go.leg.br",
+ "ma.leg.br",
+ "mg.leg.br",
+ "ms.leg.br",
+ "mt.leg.br",
+ "pa.leg.br",
+ "pb.leg.br",
+ "pe.leg.br",
+ "pi.leg.br",
+ "pr.leg.br",
+ "rj.leg.br",
+ "rn.leg.br",
+ "ro.leg.br",
+ "rr.leg.br",
+ "rs.leg.br",
+ "sc.leg.br",
+ "se.leg.br",
+ "sp.leg.br",
+ "to.leg.br",
+ "pixolino.com",
+ "ipifony.net",
+ "*.triton.zone",
+ "*.cns.joyent.com",
+ "js.org",
+ "keymachine.de",
+ "knightpoint.systems",
+ "co.krd",
+ "edu.krd",
+ "git-repos.de",
+ "lcube-server.de",
+ "svn-repos.de",
+ "we.bs",
+ "barsy.bg",
+ "barsyonline.com",
+ "barsy.de",
+ "barsy.eu",
+ "barsy.in",
+ "barsy.net",
+ "barsy.online",
+ "barsy.support",
+ "*.magentosite.cloud",
+ "hb.cldmail.ru",
+ "cloud.metacentrum.cz",
+ "custom.metacentrum.cz",
+ "meteorapp.com",
+ "eu.meteorapp.com",
+ "co.pl",
+ "azurewebsites.net",
+ "azure-mobile.net",
+ "cloudapp.net",
+ "bmoattachments.org",
+ "net.ru",
+ "org.ru",
+ "pp.ru",
+ "bitballoon.com",
+ "netlify.com",
+ "4u.com",
+ "ngrok.io",
+ "nfshost.com",
+ "nsupdate.info",
+ "nerdpol.ovh",
+ "blogsyte.com",
+ "brasilia.me",
+ "cable-modem.org",
+ "ciscofreak.com",
+ "collegefan.org",
+ "couchpotatofries.org",
+ "damnserver.com",
+ "ddns.me",
+ "ditchyourip.com",
+ "dnsfor.me",
+ "dnsiskinky.com",
+ "dvrcam.info",
+ "dynns.com",
+ "eating-organic.net",
+ "fantasyleague.cc",
+ "geekgalaxy.com",
+ "golffan.us",
+ "health-carereform.com",
+ "homesecuritymac.com",
+ "homesecuritypc.com",
+ "hopto.me",
+ "ilovecollege.info",
+ "loginto.me",
+ "mlbfan.org",
+ "mmafan.biz",
+ "myactivedirectory.com",
+ "mydissent.net",
+ "myeffect.net",
+ "mymediapc.net",
+ "mypsx.net",
+ "mysecuritycamera.com",
+ "mysecuritycamera.net",
+ "mysecuritycamera.org",
+ "net-freaks.com",
+ "nflfan.org",
+ "nhlfan.net",
+ "no-ip.ca",
+ "no-ip.co.uk",
+ "no-ip.net",
+ "noip.us",
+ "onthewifi.com",
+ "pgafan.net",
+ "point2this.com",
+ "pointto.us",
+ "privatizehealthinsurance.net",
+ "quicksytes.com",
+ "read-books.org",
+ "securitytactics.com",
+ "serveexchange.com",
+ "servehumour.com",
+ "servep2p.com",
+ "servesarcasm.com",
+ "stufftoread.com",
+ "ufcfan.org",
+ "unusualperson.com",
+ "workisboring.com",
+ "3utilities.com",
+ "bounceme.net",
+ "ddns.net",
+ "ddnsking.com",
+ "gotdns.ch",
+ "hopto.org",
+ "myftp.biz",
+ "myftp.org",
+ "myvnc.com",
+ "no-ip.biz",
+ "no-ip.info",
+ "no-ip.org",
+ "noip.me",
+ "redirectme.net",
+ "servebeer.com",
+ "serveblog.net",
+ "servecounterstrike.com",
+ "serveftp.com",
+ "servegame.com",
+ "servehalflife.com",
+ "servehttp.com",
+ "serveirc.com",
+ "serveminecraft.net",
+ "servemp3.com",
+ "servepics.com",
+ "servequake.com",
+ "sytes.net",
+ "webhop.me",
+ "zapto.org",
+ "stage.nodeart.io",
+ "nodum.co",
+ "nodum.io",
+ "nyc.mn",
+ "nom.ae",
+ "nom.ai",
+ "nom.al",
+ "nym.by",
+ "nym.bz",
+ "nom.cl",
+ "nom.gd",
+ "nom.gl",
+ "nym.gr",
+ "nom.gt",
+ "nom.hn",
+ "nom.im",
+ "nym.kz",
+ "nym.la",
+ "nom.li",
+ "nym.li",
+ "nym.lt",
+ "nym.lu",
+ "nym.me",
+ "nom.mk",
+ "nym.mx",
+ "nom.nu",
+ "nym.nz",
+ "nym.pe",
+ "nym.pt",
+ "nom.pw",
+ "nom.qa",
+ "nom.rs",
+ "nom.si",
+ "nym.sk",
+ "nym.su",
+ "nym.sx",
+ "nym.tw",
+ "nom.ug",
+ "nom.uy",
+ "nom.vc",
+ "nom.vg",
+ "cya.gg",
+ "nid.io",
+ "opencraft.hosting",
+ "operaunite.com",
+ "outsystemscloud.com",
+ "ownprovider.com",
+ "oy.lc",
+ "pgfog.com",
+ "pagefrontapp.com",
+ "art.pl",
+ "gliwice.pl",
+ "krakow.pl",
+ "poznan.pl",
+ "wroc.pl",
+ "zakopane.pl",
+ "pantheonsite.io",
+ "gotpantheon.com",
+ "mypep.link",
+ "on-web.fr",
+ "*.platform.sh",
+ "*.platformsh.site",
+ "xen.prgmr.com",
+ "priv.at",
+ "protonet.io",
+ "chirurgiens-dentistes-en-france.fr",
+ "byen.site",
+ "qa2.com",
+ "dev-myqnapcloud.com",
+ "alpha-myqnapcloud.com",
+ "myqnapcloud.com",
+ "*.quipelements.com",
+ "vapor.cloud",
+ "vaporcloud.io",
+ "rackmaze.com",
+ "rackmaze.net",
+ "rhcloud.com",
+ "hzc.io",
+ "wellbeingzone.eu",
+ "ptplus.fit",
+ "wellbeingzone.co.uk",
+ "sandcats.io",
+ "logoip.de",
+ "logoip.com",
+ "firewall-gateway.com",
+ "firewall-gateway.de",
+ "my-gateway.de",
+ "my-router.de",
+ "spdns.de",
+ "spdns.eu",
+ "firewall-gateway.net",
+ "my-firewall.org",
+ "myfirewall.org",
+ "spdns.org",
+ "*.sensiosite.cloud",
+ "biz.ua",
+ "co.ua",
+ "pp.ua",
+ "shiftedit.io",
+ "myshopblocks.com",
+ "1kapp.com",
+ "appchizi.com",
+ "applinzi.com",
+ "sinaapp.com",
+ "vipsinaapp.com",
+ "bounty-full.com",
+ "alpha.bounty-full.com",
+ "beta.bounty-full.com",
+ "static.land",
+ "dev.static.land",
+ "sites.static.land",
+ "apps.lair.io",
+ "*.stolos.io",
+ "spacekit.io",
+ "stackspace.space",
+ "storj.farm",
+ "temp-dns.com",
+ "diskstation.me",
+ "dscloud.biz",
+ "dscloud.me",
+ "dscloud.mobi",
+ "dsmynas.com",
+ "dsmynas.net",
+ "dsmynas.org",
+ "familyds.com",
+ "familyds.net",
+ "familyds.org",
+ "i234.me",
+ "myds.me",
+ "synology.me",
+ "vpnplus.to",
+ "taifun-dns.de",
+ "gda.pl",
+ "gdansk.pl",
+ "gdynia.pl",
+ "med.pl",
+ "sopot.pl",
+ "cust.dev.thingdust.io",
+ "cust.disrec.thingdust.io",
+ "cust.prod.thingdust.io",
+ "cust.testing.thingdust.io",
+ "bloxcms.com",
+ "townnews-staging.com",
+ "12hp.at",
+ "2ix.at",
+ "4lima.at",
+ "lima-city.at",
+ "12hp.ch",
+ "2ix.ch",
+ "4lima.ch",
+ "lima-city.ch",
+ "trafficplex.cloud",
+ "de.cool",
+ "12hp.de",
+ "2ix.de",
+ "4lima.de",
+ "lima-city.de",
+ "1337.pictures",
+ "clan.rip",
+ "lima-city.rocks",
+ "webspace.rocks",
+ "lima.zone",
+ "*.transurl.be",
+ "*.transurl.eu",
+ "*.transurl.nl",
+ "tuxfamily.org",
+ "dd-dns.de",
+ "diskstation.eu",
+ "diskstation.org",
+ "dray-dns.de",
+ "draydns.de",
+ "dyn-vpn.de",
+ "dynvpn.de",
+ "mein-vigor.de",
+ "my-vigor.de",
+ "my-wan.de",
+ "syno-ds.de",
+ "synology-diskstation.de",
+ "synology-ds.de",
+ "uber.space",
+ "hk.com",
+ "hk.org",
+ "ltd.hk",
+ "inc.hk",
+ "lib.de.us",
+ "router.management",
+ "v-info.info",
+ "wedeploy.io",
+ "wedeploy.me",
+ "wedeploy.sh",
+ "remotewd.com",
+ "wmflabs.org",
+ "cistron.nl",
+ "demon.nl",
+ "xs4all.space",
+ "yolasite.com",
+ "ybo.faith",
+ "yombo.me",
+ "homelink.one",
+ "ybo.party",
+ "ybo.review",
+ "ybo.science",
+ "ybo.trade",
+ "za.net",
+ "za.org",
+ "now.sh",
+}
+
+var nodeLabels = [...]string{
+ "aaa",
+ "aarp",
+ "abarth",
+ "abb",
+ "abbott",
+ "abbvie",
+ "abc",
+ "able",
+ "abogado",
+ "abudhabi",
+ "ac",
+ "academy",
+ "accenture",
+ "accountant",
+ "accountants",
+ "aco",
+ "active",
+ "actor",
+ "ad",
+ "adac",
+ "ads",
+ "adult",
+ "ae",
+ "aeg",
+ "aero",
+ "aetna",
+ "af",
+ "afamilycompany",
+ "afl",
+ "africa",
+ "ag",
+ "agakhan",
+ "agency",
+ "ai",
+ "aig",
+ "aigo",
+ "airbus",
+ "airforce",
+ "airtel",
+ "akdn",
+ "al",
+ "alfaromeo",
+ "alibaba",
+ "alipay",
+ "allfinanz",
+ "allstate",
+ "ally",
+ "alsace",
+ "alstom",
+ "am",
+ "americanexpress",
+ "americanfamily",
+ "amex",
+ "amfam",
+ "amica",
+ "amsterdam",
+ "analytics",
+ "android",
+ "anquan",
+ "anz",
+ "ao",
+ "aol",
+ "apartments",
+ "app",
+ "apple",
+ "aq",
+ "aquarelle",
+ "ar",
+ "arab",
+ "aramco",
+ "archi",
+ "army",
+ "arpa",
+ "art",
+ "arte",
+ "as",
+ "asda",
+ "asia",
+ "associates",
+ "at",
+ "athleta",
+ "attorney",
+ "au",
+ "auction",
+ "audi",
+ "audible",
+ "audio",
+ "auspost",
+ "author",
+ "auto",
+ "autos",
+ "avianca",
+ "aw",
+ "aws",
+ "ax",
+ "axa",
+ "az",
+ "azure",
+ "ba",
+ "baby",
+ "baidu",
+ "banamex",
+ "bananarepublic",
+ "band",
+ "bank",
+ "bar",
+ "barcelona",
+ "barclaycard",
+ "barclays",
+ "barefoot",
+ "bargains",
+ "baseball",
+ "basketball",
+ "bauhaus",
+ "bayern",
+ "bb",
+ "bbc",
+ "bbt",
+ "bbva",
+ "bcg",
+ "bcn",
+ "bd",
+ "be",
+ "beats",
+ "beauty",
+ "beer",
+ "bentley",
+ "berlin",
+ "best",
+ "bestbuy",
+ "bet",
+ "bf",
+ "bg",
+ "bh",
+ "bharti",
+ "bi",
+ "bible",
+ "bid",
+ "bike",
+ "bing",
+ "bingo",
+ "bio",
+ "biz",
+ "bj",
+ "black",
+ "blackfriday",
+ "blanco",
+ "blockbuster",
+ "blog",
+ "bloomberg",
+ "blue",
+ "bm",
+ "bms",
+ "bmw",
+ "bn",
+ "bnl",
+ "bnpparibas",
+ "bo",
+ "boats",
+ "boehringer",
+ "bofa",
+ "bom",
+ "bond",
+ "boo",
+ "book",
+ "booking",
+ "boots",
+ "bosch",
+ "bostik",
+ "boston",
+ "bot",
+ "boutique",
+ "box",
+ "br",
+ "bradesco",
+ "bridgestone",
+ "broadway",
+ "broker",
+ "brother",
+ "brussels",
+ "bs",
+ "bt",
+ "budapest",
+ "bugatti",
+ "build",
+ "builders",
+ "business",
+ "buy",
+ "buzz",
+ "bv",
+ "bw",
+ "by",
+ "bz",
+ "bzh",
+ "ca",
+ "cab",
+ "cafe",
+ "cal",
+ "call",
+ "calvinklein",
+ "cam",
+ "camera",
+ "camp",
+ "cancerresearch",
+ "canon",
+ "capetown",
+ "capital",
+ "capitalone",
+ "car",
+ "caravan",
+ "cards",
+ "care",
+ "career",
+ "careers",
+ "cars",
+ "cartier",
+ "casa",
+ "case",
+ "caseih",
+ "cash",
+ "casino",
+ "cat",
+ "catering",
+ "catholic",
+ "cba",
+ "cbn",
+ "cbre",
+ "cbs",
+ "cc",
+ "cd",
+ "ceb",
+ "center",
+ "ceo",
+ "cern",
+ "cf",
+ "cfa",
+ "cfd",
+ "cg",
+ "ch",
+ "chanel",
+ "channel",
+ "chase",
+ "chat",
+ "cheap",
+ "chintai",
+ "chloe",
+ "christmas",
+ "chrome",
+ "chrysler",
+ "church",
+ "ci",
+ "cipriani",
+ "circle",
+ "cisco",
+ "citadel",
+ "citi",
+ "citic",
+ "city",
+ "cityeats",
+ "ck",
+ "cl",
+ "claims",
+ "cleaning",
+ "click",
+ "clinic",
+ "clinique",
+ "clothing",
+ "cloud",
+ "club",
+ "clubmed",
+ "cm",
+ "cn",
+ "co",
+ "coach",
+ "codes",
+ "coffee",
+ "college",
+ "cologne",
+ "com",
+ "comcast",
+ "commbank",
+ "community",
+ "company",
+ "compare",
+ "computer",
+ "comsec",
+ "condos",
+ "construction",
+ "consulting",
+ "contact",
+ "contractors",
+ "cooking",
+ "cookingchannel",
+ "cool",
+ "coop",
+ "corsica",
+ "country",
+ "coupon",
+ "coupons",
+ "courses",
+ "cr",
+ "credit",
+ "creditcard",
+ "creditunion",
+ "cricket",
+ "crown",
+ "crs",
+ "cruise",
+ "cruises",
+ "csc",
+ "cu",
+ "cuisinella",
+ "cv",
+ "cw",
+ "cx",
+ "cy",
+ "cymru",
+ "cyou",
+ "cz",
+ "dabur",
+ "dad",
+ "dance",
+ "data",
+ "date",
+ "dating",
+ "datsun",
+ "day",
+ "dclk",
+ "dds",
+ "de",
+ "deal",
+ "dealer",
+ "deals",
+ "degree",
+ "delivery",
+ "dell",
+ "deloitte",
+ "delta",
+ "democrat",
+ "dental",
+ "dentist",
+ "desi",
+ "design",
+ "dev",
+ "dhl",
+ "diamonds",
+ "diet",
+ "digital",
+ "direct",
+ "directory",
+ "discount",
+ "discover",
+ "dish",
+ "diy",
+ "dj",
+ "dk",
+ "dm",
+ "dnp",
+ "do",
+ "docs",
+ "doctor",
+ "dodge",
+ "dog",
+ "doha",
+ "domains",
+ "dot",
+ "download",
+ "drive",
+ "dtv",
+ "dubai",
+ "duck",
+ "dunlop",
+ "duns",
+ "dupont",
+ "durban",
+ "dvag",
+ "dvr",
+ "dz",
+ "earth",
+ "eat",
+ "ec",
+ "eco",
+ "edeka",
+ "edu",
+ "education",
+ "ee",
+ "eg",
+ "email",
+ "emerck",
+ "energy",
+ "engineer",
+ "engineering",
+ "enterprises",
+ "epost",
+ "epson",
+ "equipment",
+ "er",
+ "ericsson",
+ "erni",
+ "es",
+ "esq",
+ "estate",
+ "esurance",
+ "et",
+ "etisalat",
+ "eu",
+ "eurovision",
+ "eus",
+ "events",
+ "everbank",
+ "exchange",
+ "expert",
+ "exposed",
+ "express",
+ "extraspace",
+ "fage",
+ "fail",
+ "fairwinds",
+ "faith",
+ "family",
+ "fan",
+ "fans",
+ "farm",
+ "farmers",
+ "fashion",
+ "fast",
+ "fedex",
+ "feedback",
+ "ferrari",
+ "ferrero",
+ "fi",
+ "fiat",
+ "fidelity",
+ "fido",
+ "film",
+ "final",
+ "finance",
+ "financial",
+ "fire",
+ "firestone",
+ "firmdale",
+ "fish",
+ "fishing",
+ "fit",
+ "fitness",
+ "fj",
+ "fk",
+ "flickr",
+ "flights",
+ "flir",
+ "florist",
+ "flowers",
+ "fly",
+ "fm",
+ "fo",
+ "foo",
+ "food",
+ "foodnetwork",
+ "football",
+ "ford",
+ "forex",
+ "forsale",
+ "forum",
+ "foundation",
+ "fox",
+ "fr",
+ "free",
+ "fresenius",
+ "frl",
+ "frogans",
+ "frontdoor",
+ "frontier",
+ "ftr",
+ "fujitsu",
+ "fujixerox",
+ "fun",
+ "fund",
+ "furniture",
+ "futbol",
+ "fyi",
+ "ga",
+ "gal",
+ "gallery",
+ "gallo",
+ "gallup",
+ "game",
+ "games",
+ "gap",
+ "garden",
+ "gb",
+ "gbiz",
+ "gd",
+ "gdn",
+ "ge",
+ "gea",
+ "gent",
+ "genting",
+ "george",
+ "gf",
+ "gg",
+ "ggee",
+ "gh",
+ "gi",
+ "gift",
+ "gifts",
+ "gives",
+ "giving",
+ "gl",
+ "glade",
+ "glass",
+ "gle",
+ "global",
+ "globo",
+ "gm",
+ "gmail",
+ "gmbh",
+ "gmo",
+ "gmx",
+ "gn",
+ "godaddy",
+ "gold",
+ "goldpoint",
+ "golf",
+ "goo",
+ "goodhands",
+ "goodyear",
+ "goog",
+ "google",
+ "gop",
+ "got",
+ "gov",
+ "gp",
+ "gq",
+ "gr",
+ "grainger",
+ "graphics",
+ "gratis",
+ "green",
+ "gripe",
+ "grocery",
+ "group",
+ "gs",
+ "gt",
+ "gu",
+ "guardian",
+ "gucci",
+ "guge",
+ "guide",
+ "guitars",
+ "guru",
+ "gw",
+ "gy",
+ "hair",
+ "hamburg",
+ "hangout",
+ "haus",
+ "hbo",
+ "hdfc",
+ "hdfcbank",
+ "health",
+ "healthcare",
+ "help",
+ "helsinki",
+ "here",
+ "hermes",
+ "hgtv",
+ "hiphop",
+ "hisamitsu",
+ "hitachi",
+ "hiv",
+ "hk",
+ "hkt",
+ "hm",
+ "hn",
+ "hockey",
+ "holdings",
+ "holiday",
+ "homedepot",
+ "homegoods",
+ "homes",
+ "homesense",
+ "honda",
+ "honeywell",
+ "horse",
+ "hospital",
+ "host",
+ "hosting",
+ "hot",
+ "hoteles",
+ "hotels",
+ "hotmail",
+ "house",
+ "how",
+ "hr",
+ "hsbc",
+ "ht",
+ "htc",
+ "hu",
+ "hughes",
+ "hyatt",
+ "hyundai",
+ "ibm",
+ "icbc",
+ "ice",
+ "icu",
+ "id",
+ "ie",
+ "ieee",
+ "ifm",
+ "ikano",
+ "il",
+ "im",
+ "imamat",
+ "imdb",
+ "immo",
+ "immobilien",
+ "in",
+ "industries",
+ "infiniti",
+ "info",
+ "ing",
+ "ink",
+ "institute",
+ "insurance",
+ "insure",
+ "int",
+ "intel",
+ "international",
+ "intuit",
+ "investments",
+ "io",
+ "ipiranga",
+ "iq",
+ "ir",
+ "irish",
+ "is",
+ "iselect",
+ "ismaili",
+ "ist",
+ "istanbul",
+ "it",
+ "itau",
+ "itv",
+ "iveco",
+ "iwc",
+ "jaguar",
+ "java",
+ "jcb",
+ "jcp",
+ "je",
+ "jeep",
+ "jetzt",
+ "jewelry",
+ "jio",
+ "jlc",
+ "jll",
+ "jm",
+ "jmp",
+ "jnj",
+ "jo",
+ "jobs",
+ "joburg",
+ "jot",
+ "joy",
+ "jp",
+ "jpmorgan",
+ "jprs",
+ "juegos",
+ "juniper",
+ "kaufen",
+ "kddi",
+ "ke",
+ "kerryhotels",
+ "kerrylogistics",
+ "kerryproperties",
+ "kfh",
+ "kg",
+ "kh",
+ "ki",
+ "kia",
+ "kim",
+ "kinder",
+ "kindle",
+ "kitchen",
+ "kiwi",
+ "km",
+ "kn",
+ "koeln",
+ "komatsu",
+ "kosher",
+ "kp",
+ "kpmg",
+ "kpn",
+ "kr",
+ "krd",
+ "kred",
+ "kuokgroup",
+ "kw",
+ "ky",
+ "kyoto",
+ "kz",
+ "la",
+ "lacaixa",
+ "ladbrokes",
+ "lamborghini",
+ "lamer",
+ "lancaster",
+ "lancia",
+ "lancome",
+ "land",
+ "landrover",
+ "lanxess",
+ "lasalle",
+ "lat",
+ "latino",
+ "latrobe",
+ "law",
+ "lawyer",
+ "lb",
+ "lc",
+ "lds",
+ "lease",
+ "leclerc",
+ "lefrak",
+ "legal",
+ "lego",
+ "lexus",
+ "lgbt",
+ "li",
+ "liaison",
+ "lidl",
+ "life",
+ "lifeinsurance",
+ "lifestyle",
+ "lighting",
+ "like",
+ "lilly",
+ "limited",
+ "limo",
+ "lincoln",
+ "linde",
+ "link",
+ "lipsy",
+ "live",
+ "living",
+ "lixil",
+ "lk",
+ "loan",
+ "loans",
+ "locker",
+ "locus",
+ "loft",
+ "lol",
+ "london",
+ "lotte",
+ "lotto",
+ "love",
+ "lpl",
+ "lplfinancial",
+ "lr",
+ "ls",
+ "lt",
+ "ltd",
+ "ltda",
+ "lu",
+ "lundbeck",
+ "lupin",
+ "luxe",
+ "luxury",
+ "lv",
+ "ly",
+ "ma",
+ "macys",
+ "madrid",
+ "maif",
+ "maison",
+ "makeup",
+ "man",
+ "management",
+ "mango",
+ "map",
+ "market",
+ "marketing",
+ "markets",
+ "marriott",
+ "marshalls",
+ "maserati",
+ "mattel",
+ "mba",
+ "mc",
+ "mcd",
+ "mcdonalds",
+ "mckinsey",
+ "md",
+ "me",
+ "med",
+ "media",
+ "meet",
+ "melbourne",
+ "meme",
+ "memorial",
+ "men",
+ "menu",
+ "meo",
+ "merckmsd",
+ "metlife",
+ "mg",
+ "mh",
+ "miami",
+ "microsoft",
+ "mil",
+ "mini",
+ "mint",
+ "mit",
+ "mitsubishi",
+ "mk",
+ "ml",
+ "mlb",
+ "mls",
+ "mm",
+ "mma",
+ "mn",
+ "mo",
+ "mobi",
+ "mobile",
+ "mobily",
+ "moda",
+ "moe",
+ "moi",
+ "mom",
+ "monash",
+ "money",
+ "monster",
+ "montblanc",
+ "mopar",
+ "mormon",
+ "mortgage",
+ "moscow",
+ "moto",
+ "motorcycles",
+ "mov",
+ "movie",
+ "movistar",
+ "mp",
+ "mq",
+ "mr",
+ "ms",
+ "msd",
+ "mt",
+ "mtn",
+ "mtpc",
+ "mtr",
+ "mu",
+ "museum",
+ "mutual",
+ "mv",
+ "mw",
+ "mx",
+ "my",
+ "mz",
+ "na",
+ "nab",
+ "nadex",
+ "nagoya",
+ "name",
+ "nationwide",
+ "natura",
+ "navy",
+ "nba",
+ "nc",
+ "ne",
+ "nec",
+ "net",
+ "netbank",
+ "netflix",
+ "network",
+ "neustar",
+ "new",
+ "newholland",
+ "news",
+ "next",
+ "nextdirect",
+ "nexus",
+ "nf",
+ "nfl",
+ "ng",
+ "ngo",
+ "nhk",
+ "ni",
+ "nico",
+ "nike",
+ "nikon",
+ "ninja",
+ "nissan",
+ "nissay",
+ "nl",
+ "no",
+ "nokia",
+ "northwesternmutual",
+ "norton",
+ "now",
+ "nowruz",
+ "nowtv",
+ "np",
+ "nr",
+ "nra",
+ "nrw",
+ "ntt",
+ "nu",
+ "nyc",
+ "nz",
+ "obi",
+ "observer",
+ "off",
+ "office",
+ "okinawa",
+ "olayan",
+ "olayangroup",
+ "oldnavy",
+ "ollo",
+ "om",
+ "omega",
+ "one",
+ "ong",
+ "onion",
+ "onl",
+ "online",
+ "onyourside",
+ "ooo",
+ "open",
+ "oracle",
+ "orange",
+ "org",
+ "organic",
+ "origins",
+ "osaka",
+ "otsuka",
+ "ott",
+ "ovh",
+ "pa",
+ "page",
+ "pamperedchef",
+ "panasonic",
+ "panerai",
+ "paris",
+ "pars",
+ "partners",
+ "parts",
+ "party",
+ "passagens",
+ "pay",
+ "pccw",
+ "pe",
+ "pet",
+ "pf",
+ "pfizer",
+ "pg",
+ "ph",
+ "pharmacy",
+ "phd",
+ "philips",
+ "phone",
+ "photo",
+ "photography",
+ "photos",
+ "physio",
+ "piaget",
+ "pics",
+ "pictet",
+ "pictures",
+ "pid",
+ "pin",
+ "ping",
+ "pink",
+ "pioneer",
+ "pizza",
+ "pk",
+ "pl",
+ "place",
+ "play",
+ "playstation",
+ "plumbing",
+ "plus",
+ "pm",
+ "pn",
+ "pnc",
+ "pohl",
+ "poker",
+ "politie",
+ "porn",
+ "post",
+ "pr",
+ "pramerica",
+ "praxi",
+ "press",
+ "prime",
+ "pro",
+ "prod",
+ "productions",
+ "prof",
+ "progressive",
+ "promo",
+ "properties",
+ "property",
+ "protection",
+ "pru",
+ "prudential",
+ "ps",
+ "pt",
+ "pub",
+ "pw",
+ "pwc",
+ "py",
+ "qa",
+ "qpon",
+ "quebec",
+ "quest",
+ "qvc",
+ "racing",
+ "radio",
+ "raid",
+ "re",
+ "read",
+ "realestate",
+ "realtor",
+ "realty",
+ "recipes",
+ "red",
+ "redstone",
+ "redumbrella",
+ "rehab",
+ "reise",
+ "reisen",
+ "reit",
+ "reliance",
+ "ren",
+ "rent",
+ "rentals",
+ "repair",
+ "report",
+ "republican",
+ "rest",
+ "restaurant",
+ "review",
+ "reviews",
+ "rexroth",
+ "rich",
+ "richardli",
+ "ricoh",
+ "rightathome",
+ "ril",
+ "rio",
+ "rip",
+ "rmit",
+ "ro",
+ "rocher",
+ "rocks",
+ "rodeo",
+ "rogers",
+ "room",
+ "rs",
+ "rsvp",
+ "ru",
+ "rugby",
+ "ruhr",
+ "run",
+ "rw",
+ "rwe",
+ "ryukyu",
+ "sa",
+ "saarland",
+ "safe",
+ "safety",
+ "sakura",
+ "sale",
+ "salon",
+ "samsclub",
+ "samsung",
+ "sandvik",
+ "sandvikcoromant",
+ "sanofi",
+ "sap",
+ "sapo",
+ "sarl",
+ "sas",
+ "save",
+ "saxo",
+ "sb",
+ "sbi",
+ "sbs",
+ "sc",
+ "sca",
+ "scb",
+ "schaeffler",
+ "schmidt",
+ "scholarships",
+ "school",
+ "schule",
+ "schwarz",
+ "science",
+ "scjohnson",
+ "scor",
+ "scot",
+ "sd",
+ "se",
+ "search",
+ "seat",
+ "secure",
+ "security",
+ "seek",
+ "select",
+ "sener",
+ "services",
+ "ses",
+ "seven",
+ "sew",
+ "sex",
+ "sexy",
+ "sfr",
+ "sg",
+ "sh",
+ "shangrila",
+ "sharp",
+ "shaw",
+ "shell",
+ "shia",
+ "shiksha",
+ "shoes",
+ "shop",
+ "shopping",
+ "shouji",
+ "show",
+ "showtime",
+ "shriram",
+ "si",
+ "silk",
+ "sina",
+ "singles",
+ "site",
+ "sj",
+ "sk",
+ "ski",
+ "skin",
+ "sky",
+ "skype",
+ "sl",
+ "sling",
+ "sm",
+ "smart",
+ "smile",
+ "sn",
+ "sncf",
+ "so",
+ "soccer",
+ "social",
+ "softbank",
+ "software",
+ "sohu",
+ "solar",
+ "solutions",
+ "song",
+ "sony",
+ "soy",
+ "space",
+ "spiegel",
+ "spot",
+ "spreadbetting",
+ "sr",
+ "srl",
+ "srt",
+ "st",
+ "stada",
+ "staples",
+ "star",
+ "starhub",
+ "statebank",
+ "statefarm",
+ "statoil",
+ "stc",
+ "stcgroup",
+ "stockholm",
+ "storage",
+ "store",
+ "stream",
+ "studio",
+ "study",
+ "style",
+ "su",
+ "sucks",
+ "supplies",
+ "supply",
+ "support",
+ "surf",
+ "surgery",
+ "suzuki",
+ "sv",
+ "swatch",
+ "swiftcover",
+ "swiss",
+ "sx",
+ "sy",
+ "sydney",
+ "symantec",
+ "systems",
+ "sz",
+ "tab",
+ "taipei",
+ "talk",
+ "taobao",
+ "target",
+ "tatamotors",
+ "tatar",
+ "tattoo",
+ "tax",
+ "taxi",
+ "tc",
+ "tci",
+ "td",
+ "tdk",
+ "team",
+ "tech",
+ "technology",
+ "tel",
+ "telecity",
+ "telefonica",
+ "temasek",
+ "tennis",
+ "teva",
+ "tf",
+ "tg",
+ "th",
+ "thd",
+ "theater",
+ "theatre",
+ "tiaa",
+ "tickets",
+ "tienda",
+ "tiffany",
+ "tips",
+ "tires",
+ "tirol",
+ "tj",
+ "tjmaxx",
+ "tjx",
+ "tk",
+ "tkmaxx",
+ "tl",
+ "tm",
+ "tmall",
+ "tn",
+ "to",
+ "today",
+ "tokyo",
+ "tools",
+ "top",
+ "toray",
+ "toshiba",
+ "total",
+ "tours",
+ "town",
+ "toyota",
+ "toys",
+ "tr",
+ "trade",
+ "trading",
+ "training",
+ "travel",
+ "travelchannel",
+ "travelers",
+ "travelersinsurance",
+ "trust",
+ "trv",
+ "tt",
+ "tube",
+ "tui",
+ "tunes",
+ "tushu",
+ "tv",
+ "tvs",
+ "tw",
+ "tz",
+ "ua",
+ "ubank",
+ "ubs",
+ "uconnect",
+ "ug",
+ "uk",
+ "unicom",
+ "university",
+ "uno",
+ "uol",
+ "ups",
+ "us",
+ "uy",
+ "uz",
+ "va",
+ "vacations",
+ "vana",
+ "vanguard",
+ "vc",
+ "ve",
+ "vegas",
+ "ventures",
+ "verisign",
+ "versicherung",
+ "vet",
+ "vg",
+ "vi",
+ "viajes",
+ "video",
+ "vig",
+ "viking",
+ "villas",
+ "vin",
+ "vip",
+ "virgin",
+ "visa",
+ "vision",
+ "vista",
+ "vistaprint",
+ "viva",
+ "vivo",
+ "vlaanderen",
+ "vn",
+ "vodka",
+ "volkswagen",
+ "volvo",
+ "vote",
+ "voting",
+ "voto",
+ "voyage",
+ "vu",
+ "vuelos",
+ "wales",
+ "walmart",
+ "walter",
+ "wang",
+ "wanggou",
+ "warman",
+ "watch",
+ "watches",
+ "weather",
+ "weatherchannel",
+ "webcam",
+ "weber",
+ "website",
+ "wed",
+ "wedding",
+ "weibo",
+ "weir",
+ "wf",
+ "whoswho",
+ "wien",
+ "wiki",
+ "williamhill",
+ "win",
+ "windows",
+ "wine",
+ "winners",
+ "wme",
+ "wolterskluwer",
+ "woodside",
+ "work",
+ "works",
+ "world",
+ "wow",
+ "ws",
+ "wtc",
+ "wtf",
+ "xbox",
+ "xerox",
+ "xfinity",
+ "xihuan",
+ "xin",
+ "xn--11b4c3d",
+ "xn--1ck2e1b",
+ "xn--1qqw23a",
+ "xn--2scrj9c",
+ "xn--30rr7y",
+ "xn--3bst00m",
+ "xn--3ds443g",
+ "xn--3e0b707e",
+ "xn--3hcrj9c",
+ "xn--3oq18vl8pn36a",
+ "xn--3pxu8k",
+ "xn--42c2d9a",
+ "xn--45br5cyl",
+ "xn--45brj9c",
+ "xn--45q11c",
+ "xn--4gbrim",
+ "xn--54b7fta0cc",
+ "xn--55qw42g",
+ "xn--55qx5d",
+ "xn--5su34j936bgsg",
+ "xn--5tzm5g",
+ "xn--6frz82g",
+ "xn--6qq986b3xl",
+ "xn--80adxhks",
+ "xn--80ao21a",
+ "xn--80aqecdr1a",
+ "xn--80asehdb",
+ "xn--80aswg",
+ "xn--8y0a063a",
+ "xn--90a3ac",
+ "xn--90ae",
+ "xn--90ais",
+ "xn--9dbq2a",
+ "xn--9et52u",
+ "xn--9krt00a",
+ "xn--b4w605ferd",
+ "xn--bck1b9a5dre4c",
+ "xn--c1avg",
+ "xn--c2br7g",
+ "xn--cck2b3b",
+ "xn--cg4bki",
+ "xn--clchc0ea0b2g2a9gcd",
+ "xn--czr694b",
+ "xn--czrs0t",
+ "xn--czru2d",
+ "xn--d1acj3b",
+ "xn--d1alf",
+ "xn--e1a4c",
+ "xn--eckvdtc9d",
+ "xn--efvy88h",
+ "xn--estv75g",
+ "xn--fct429k",
+ "xn--fhbei",
+ "xn--fiq228c5hs",
+ "xn--fiq64b",
+ "xn--fiqs8s",
+ "xn--fiqz9s",
+ "xn--fjq720a",
+ "xn--flw351e",
+ "xn--fpcrj9c3d",
+ "xn--fzc2c9e2c",
+ "xn--fzys8d69uvgm",
+ "xn--g2xx48c",
+ "xn--gckr3f0f",
+ "xn--gecrj9c",
+ "xn--gk3at1e",
+ "xn--h2breg3eve",
+ "xn--h2brj9c",
+ "xn--h2brj9c8c",
+ "xn--hxt814e",
+ "xn--i1b6b1a6a2e",
+ "xn--imr513n",
+ "xn--io0a7i",
+ "xn--j1aef",
+ "xn--j1amh",
+ "xn--j6w193g",
+ "xn--jlq61u9w7b",
+ "xn--jvr189m",
+ "xn--kcrx77d1x4a",
+ "xn--kprw13d",
+ "xn--kpry57d",
+ "xn--kpu716f",
+ "xn--kput3i",
+ "xn--l1acc",
+ "xn--lgbbat1ad8j",
+ "xn--mgb2ddes",
+ "xn--mgb9awbf",
+ "xn--mgba3a3ejt",
+ "xn--mgba3a4f16a",
+ "xn--mgba3a4fra",
+ "xn--mgba7c0bbn0a",
+ "xn--mgbaakc7dvf",
+ "xn--mgbaam7a8h",
+ "xn--mgbab2bd",
+ "xn--mgbai9a5eva00b",
+ "xn--mgbai9azgqp6j",
+ "xn--mgbayh7gpa",
+ "xn--mgbb9fbpob",
+ "xn--mgbbh1a71e",
+ "xn--mgbc0a9azcg",
+ "xn--mgbca7dzdo",
+ "xn--mgberp4a5d4a87g",
+ "xn--mgberp4a5d4ar",
+ "xn--mgbgu82a",
+ "xn--mgbi4ecexp",
+ "xn--mgbpl2fh",
+ "xn--mgbqly7c0a67fbc",
+ "xn--mgbqly7cvafr",
+ "xn--mgbt3dhd",
+ "xn--mgbtf8fl",
+ "xn--mgbtx2b",
+ "xn--mgbx4cd0ab",
+ "xn--mix082f",
+ "xn--mix891f",
+ "xn--mk1bu44c",
+ "xn--mxtq1m",
+ "xn--ngbc5azd",
+ "xn--ngbe9e0a",
+ "xn--ngbrx",
+ "xn--nnx388a",
+ "xn--node",
+ "xn--nqv7f",
+ "xn--nqv7fs00ema",
+ "xn--nyqy26a",
+ "xn--o3cw4h",
+ "xn--ogbpf8fl",
+ "xn--p1acf",
+ "xn--p1ai",
+ "xn--pbt977c",
+ "xn--pgbs0dh",
+ "xn--pssy2u",
+ "xn--q9jyb4c",
+ "xn--qcka1pmc",
+ "xn--qxam",
+ "xn--rhqv96g",
+ "xn--rovu88b",
+ "xn--rvc1e0am3e",
+ "xn--s9brj9c",
+ "xn--ses554g",
+ "xn--t60b56a",
+ "xn--tckwe",
+ "xn--tiq49xqyj",
+ "xn--unup4y",
+ "xn--vermgensberater-ctb",
+ "xn--vermgensberatung-pwb",
+ "xn--vhquv",
+ "xn--vuq861b",
+ "xn--w4r85el8fhu5dnra",
+ "xn--w4rs40l",
+ "xn--wgbh1c",
+ "xn--wgbl6a",
+ "xn--xhq521b",
+ "xn--xkc2al3hye2a",
+ "xn--xkc2dl3a5ee0h",
+ "xn--y9a3aq",
+ "xn--yfro4i67o",
+ "xn--ygbi2ammx",
+ "xn--zfr164b",
+ "xperia",
+ "xxx",
+ "xyz",
+ "yachts",
+ "yahoo",
+ "yamaxun",
+ "yandex",
+ "ye",
+ "yodobashi",
+ "yoga",
+ "yokohama",
+ "you",
+ "youtube",
+ "yt",
+ "yun",
+ "za",
+ "zappos",
+ "zara",
+ "zero",
+ "zip",
+ "zippo",
+ "zm",
+ "zone",
+ "zuerich",
+ "zw",
+ "com",
+ "edu",
+ "gov",
+ "mil",
+ "net",
+ "org",
+ "nom",
+ "ac",
+ "blogspot",
+ "co",
+ "gov",
+ "mil",
+ "net",
+ "nom",
+ "org",
+ "sch",
+ "accident-investigation",
+ "accident-prevention",
+ "aerobatic",
+ "aeroclub",
+ "aerodrome",
+ "agents",
+ "air-surveillance",
+ "air-traffic-control",
+ "aircraft",
+ "airline",
+ "airport",
+ "airtraffic",
+ "ambulance",
+ "amusement",
+ "association",
+ "author",
+ "ballooning",
+ "broker",
+ "caa",
+ "cargo",
+ "catering",
+ "certification",
+ "championship",
+ "charter",
+ "civilaviation",
+ "club",
+ "conference",
+ "consultant",
+ "consulting",
+ "control",
+ "council",
+ "crew",
+ "design",
+ "dgca",
+ "educator",
+ "emergency",
+ "engine",
+ "engineer",
+ "entertainment",
+ "equipment",
+ "exchange",
+ "express",
+ "federation",
+ "flight",
+ "freight",
+ "fuel",
+ "gliding",
+ "government",
+ "groundhandling",
+ "group",
+ "hanggliding",
+ "homebuilt",
+ "insurance",
+ "journal",
+ "journalist",
+ "leasing",
+ "logistics",
+ "magazine",
+ "maintenance",
+ "media",
+ "microlight",
+ "modelling",
+ "navigation",
+ "parachuting",
+ "paragliding",
+ "passenger-association",
+ "pilot",
+ "press",
+ "production",
+ "recreation",
+ "repbody",
+ "res",
+ "research",
+ "rotorcraft",
+ "safety",
+ "scientist",
+ "services",
+ "show",
+ "skydiving",
+ "software",
+ "student",
+ "trader",
+ "trading",
+ "trainer",
+ "union",
+ "workinggroup",
+ "works",
+ "com",
+ "edu",
+ "gov",
+ "net",
+ "org",
+ "co",
+ "com",
+ "net",
+ "nom",
+ "org",
+ "com",
+ "net",
+ "nom",
+ "off",
+ "org",
+ "blogspot",
+ "com",
+ "edu",
+ "gov",
+ "mil",
+ "net",
+ "nom",
+ "org",
+ "blogspot",
+ "co",
+ "ed",
+ "gv",
+ "it",
+ "og",
+ "pb",
+ "com",
+ "edu",
+ "gob",
+ "gov",
+ "int",
+ "mil",
+ "musica",
+ "net",
+ "org",
+ "tur",
+ "blogspot",
+ "e164",
+ "in-addr",
+ "ip6",
+ "iris",
+ "uri",
+ "urn",
+ "gov",
+ "cloudns",
+ "12hp",
+ "2ix",
+ "4lima",
+ "ac",
+ "biz",
+ "co",
+ "futurecms",
+ "futurehosting",
+ "futuremailing",
+ "gv",
+ "info",
+ "lima-city",
+ "or",
+ "ortsinfo",
+ "priv",
+ "blogspot",
+ "ex",
+ "kunden",
+ "act",
+ "asn",
+ "com",
+ "conf",
+ "edu",
+ "gov",
+ "id",
+ "info",
+ "net",
+ "nsw",
+ "nt",
+ "org",
+ "oz",
+ "qld",
+ "sa",
+ "tas",
+ "vic",
+ "wa",
+ "blogspot",
+ "act",
+ "nsw",
+ "nt",
+ "qld",
+ "sa",
+ "tas",
+ "vic",
+ "wa",
+ "qld",
+ "sa",
+ "tas",
+ "vic",
+ "wa",
+ "com",
+ "biz",
+ "com",
+ "edu",
+ "gov",
+ "info",
+ "int",
+ "mil",
+ "name",
+ "net",
+ "org",
+ "pp",
+ "pro",
+ "blogspot",
+ "com",
+ "edu",
+ "gov",
+ "mil",
+ "net",
+ "org",
+ "biz",
+ "co",
+ "com",
+ "edu",
+ "gov",
+ "info",
+ "net",
+ "org",
+ "store",
+ "tv",
+ "ac",
+ "blogspot",
+ "transurl",
+ "gov",
+ "0",
+ "1",
+ "2",
+ "3",
+ "4",
+ "5",
+ "6",
+ "7",
+ "8",
+ "9",
+ "a",
+ "b",
+ "barsy",
+ "blogspot",
+ "c",
+ "d",
+ "e",
+ "f",
+ "g",
+ "h",
+ "i",
+ "j",
+ "k",
+ "l",
+ "m",
+ "n",
+ "o",
+ "p",
+ "q",
+ "r",
+ "s",
+ "t",
+ "u",
+ "v",
+ "w",
+ "x",
+ "y",
+ "z",
+ "com",
+ "edu",
+ "gov",
+ "net",
+ "org",
+ "co",
+ "com",
+ "edu",
+ "or",
+ "org",
+ "cloudns",
+ "dscloud",
+ "dyndns",
+ "for-better",
+ "for-more",
+ "for-some",
+ "for-the",
+ "mmafan",
+ "myftp",
+ "no-ip",
+ "selfip",
+ "webhop",
+ "asso",
+ "barreau",
+ "blogspot",
+ "gouv",
+ "com",
+ "edu",
+ "gov",
+ "net",
+ "org",
+ "com",
+ "edu",
+ "gob",
+ "gov",
+ "int",
+ "mil",
+ "net",
+ "org",
+ "tv",
+ "adm",
+ "adv",
+ "agr",
+ "am",
+ "arq",
+ "art",
+ "ato",
+ "b",
+ "belem",
+ "bio",
+ "blog",
+ "bmd",
+ "cim",
+ "cng",
+ "cnt",
+ "com",
+ "coop",
+ "cri",
+ "def",
+ "ecn",
+ "eco",
+ "edu",
+ "emp",
+ "eng",
+ "esp",
+ "etc",
+ "eti",
+ "far",
+ "flog",
+ "floripa",
+ "fm",
+ "fnd",
+ "fot",
+ "fst",
+ "g12",
+ "ggf",
+ "gov",
+ "imb",
+ "ind",
+ "inf",
+ "jampa",
+ "jor",
+ "jus",
+ "leg",
+ "lel",
+ "mat",
+ "med",
+ "mil",
+ "mp",
+ "mus",
+ "net",
+ "nom",
+ "not",
+ "ntr",
+ "odo",
+ "org",
+ "poa",
+ "ppg",
+ "pro",
+ "psc",
+ "psi",
+ "qsl",
+ "radio",
+ "rec",
+ "recife",
+ "slg",
+ "srv",
+ "taxi",
+ "teo",
+ "tmp",
+ "trd",
+ "tur",
+ "tv",
+ "vet",
+ "vix",
+ "vlog",
+ "wiki",
+ "zlg",
+ "blogspot",
+ "ac",
+ "al",
+ "am",
+ "ap",
+ "ba",
+ "ce",
+ "df",
+ "es",
+ "go",
+ "ma",
+ "mg",
+ "ms",
+ "mt",
+ "pa",
+ "pb",
+ "pe",
+ "pi",
+ "pr",
+ "rj",
+ "rn",
+ "ro",
+ "rr",
+ "rs",
+ "sc",
+ "se",
+ "sp",
+ "to",
+ "ac",
+ "al",
+ "am",
+ "ap",
+ "ba",
+ "ce",
+ "df",
+ "es",
+ "go",
+ "ma",
+ "mg",
+ "ms",
+ "mt",
+ "pa",
+ "pb",
+ "pe",
+ "pi",
+ "pr",
+ "rj",
+ "rn",
+ "ro",
+ "rr",
+ "rs",
+ "sc",
+ "se",
+ "sp",
+ "to",
+ "com",
+ "edu",
+ "gov",
+ "net",
+ "org",
+ "we",
+ "com",
+ "edu",
+ "gov",
+ "net",
+ "org",
+ "co",
+ "org",
+ "com",
+ "gov",
+ "mil",
+ "nym",
+ "of",
+ "blogspot",
+ "com",
+ "edu",
+ "gov",
+ "net",
+ "nym",
+ "org",
+ "za",
+ "ab",
+ "awdev",
+ "bc",
+ "blogspot",
+ "co",
+ "gc",
+ "mb",
+ "nb",
+ "nf",
+ "nl",
+ "no-ip",
+ "ns",
+ "nt",
+ "nu",
+ "on",
+ "pe",
+ "qc",
+ "sk",
+ "yk",
+ "cloudns",
+ "fantasyleague",
+ "ftpaccess",
+ "game-server",
+ "myphotos",
+ "scrapping",
+ "twmail",
+ "gov",
+ "blogspot",
+ "12hp",
+ "2ix",
+ "4lima",
+ "blogspot",
+ "gotdns",
+ "lima-city",
+ "square7",
+ "ac",
+ "asso",
+ "co",
+ "com",
+ "ed",
+ "edu",
+ "go",
+ "gouv",
+ "int",
+ "md",
+ "net",
+ "or",
+ "org",
+ "presse",
+ "xn--aroport-bya",
+ "www",
+ "blogspot",
+ "co",
+ "gob",
+ "gov",
+ "mil",
+ "nom",
+ "magentosite",
+ "myfusion",
+ "sensiosite",
+ "statics",
+ "trafficplex",
+ "vapor",
+ "cloudns",
+ "co",
+ "com",
+ "gov",
+ "net",
+ "ac",
+ "ah",
+ "bj",
+ "com",
+ "cq",
+ "edu",
+ "fj",
+ "gd",
+ "gov",
+ "gs",
+ "gx",
+ "gz",
+ "ha",
+ "hb",
+ "he",
+ "hi",
+ "hk",
+ "hl",
+ "hn",
+ "jl",
+ "js",
+ "jx",
+ "ln",
+ "mil",
+ "mo",
+ "net",
+ "nm",
+ "nx",
+ "org",
+ "qh",
+ "sc",
+ "sd",
+ "sh",
+ "sn",
+ "sx",
+ "tj",
+ "tw",
+ "xj",
+ "xn--55qx5d",
+ "xn--io0a7i",
+ "xn--od0alg",
+ "xz",
+ "yn",
+ "zj",
+ "amazonaws",
+ "cn-north-1",
+ "compute",
+ "eb",
+ "elb",
+ "s3",
+ "cn-north-1",
+ "arts",
+ "com",
+ "edu",
+ "firm",
+ "gov",
+ "info",
+ "int",
+ "mil",
+ "net",
+ "nodum",
+ "nom",
+ "org",
+ "rec",
+ "web",
+ "blogspot",
+ "0emm",
+ "1kapp",
+ "3utilities",
+ "4u",
+ "africa",
+ "alpha-myqnapcloud",
+ "amazonaws",
+ "appchizi",
+ "applinzi",
+ "appspot",
+ "ar",
+ "barsyonline",
+ "betainabox",
+ "bitballoon",
+ "blogdns",
+ "blogspot",
+ "blogsyte",
+ "bloxcms",
+ "bounty-full",
+ "bplaced",
+ "br",
+ "cechire",
+ "ciscofreak",
+ "cloudcontrolapp",
+ "cloudcontrolled",
+ "cn",
+ "co",
+ "codespot",
+ "damnserver",
+ "ddnsfree",
+ "ddnsgeek",
+ "ddnsking",
+ "de",
+ "dev-myqnapcloud",
+ "ditchyourip",
+ "dnsalias",
+ "dnsdojo",
+ "dnsiskinky",
+ "doesntexist",
+ "dontexist",
+ "doomdns",
+ "drayddns",
+ "dreamhosters",
+ "dsmynas",
+ "dyn-o-saur",
+ "dynalias",
+ "dyndns-at-home",
+ "dyndns-at-work",
+ "dyndns-blog",
+ "dyndns-free",
+ "dyndns-home",
+ "dyndns-ip",
+ "dyndns-mail",
+ "dyndns-office",
+ "dyndns-pics",
+ "dyndns-remote",
+ "dyndns-server",
+ "dyndns-web",
+ "dyndns-wiki",
+ "dyndns-work",
+ "dynns",
+ "elasticbeanstalk",
+ "est-a-la-maison",
+ "est-a-la-masion",
+ "est-le-patron",
+ "est-mon-blogueur",
+ "eu",
+ "evennode",
+ "familyds",
+ "fbsbx",
+ "firebaseapp",
+ "firewall-gateway",
+ "flynnhub",
+ "freebox-os",
+ "freeboxos",
+ "from-ak",
+ "from-al",
+ "from-ar",
+ "from-ca",
+ "from-ct",
+ "from-dc",
+ "from-de",
+ "from-fl",
+ "from-ga",
+ "from-hi",
+ "from-ia",
+ "from-id",
+ "from-il",
+ "from-in",
+ "from-ks",
+ "from-ky",
+ "from-ma",
+ "from-md",
+ "from-mi",
+ "from-mn",
+ "from-mo",
+ "from-ms",
+ "from-mt",
+ "from-nc",
+ "from-nd",
+ "from-ne",
+ "from-nh",
+ "from-nj",
+ "from-nm",
+ "from-nv",
+ "from-oh",
+ "from-ok",
+ "from-or",
+ "from-pa",
+ "from-pr",
+ "from-ri",
+ "from-sc",
+ "from-sd",
+ "from-tn",
+ "from-tx",
+ "from-ut",
+ "from-va",
+ "from-vt",
+ "from-wa",
+ "from-wi",
+ "from-wv",
+ "from-wy",
+ "gb",
+ "geekgalaxy",
+ "getmyip",
+ "giize",
+ "githubusercontent",
+ "gleeze",
+ "googleapis",
+ "googlecode",
+ "gotdns",
+ "gotpantheon",
+ "gr",
+ "health-carereform",
+ "herokuapp",
+ "herokussl",
+ "hk",
+ "hobby-site",
+ "homelinux",
+ "homesecuritymac",
+ "homesecuritypc",
+ "homeunix",
+ "hu",
+ "iamallama",
+ "is-a-anarchist",
+ "is-a-blogger",
+ "is-a-bookkeeper",
+ "is-a-bulls-fan",
+ "is-a-caterer",
+ "is-a-chef",
+ "is-a-conservative",
+ "is-a-cpa",
+ "is-a-cubicle-slave",
+ "is-a-democrat",
+ "is-a-designer",
+ "is-a-doctor",
+ "is-a-financialadvisor",
+ "is-a-geek",
+ "is-a-green",
+ "is-a-guru",
+ "is-a-hard-worker",
+ "is-a-hunter",
+ "is-a-landscaper",
+ "is-a-lawyer",
+ "is-a-liberal",
+ "is-a-libertarian",
+ "is-a-llama",
+ "is-a-musician",
+ "is-a-nascarfan",
+ "is-a-nurse",
+ "is-a-painter",
+ "is-a-personaltrainer",
+ "is-a-photographer",
+ "is-a-player",
+ "is-a-republican",
+ "is-a-rockstar",
+ "is-a-socialist",
+ "is-a-student",
+ "is-a-teacher",
+ "is-a-techie",
+ "is-a-therapist",
+ "is-an-accountant",
+ "is-an-actor",
+ "is-an-actress",
+ "is-an-anarchist",
+ "is-an-artist",
+ "is-an-engineer",
+ "is-an-entertainer",
+ "is-certified",
+ "is-gone",
+ "is-into-anime",
+ "is-into-cars",
+ "is-into-cartoons",
+ "is-into-games",
+ "is-leet",
+ "is-not-certified",
+ "is-slick",
+ "is-uberleet",
+ "is-with-theband",
+ "isa-geek",
+ "isa-hockeynut",
+ "issmarterthanyou",
+ "jdevcloud",
+ "joyent",
+ "jpn",
+ "kozow",
+ "kr",
+ "likes-pie",
+ "likescandy",
+ "logoip",
+ "loseyourip",
+ "meteorapp",
+ "mex",
+ "myactivedirectory",
+ "myasustor",
+ "mydrobo",
+ "myqnapcloud",
+ "mysecuritycamera",
+ "myshopblocks",
+ "mytuleap",
+ "myvnc",
+ "neat-url",
+ "net-freaks",
+ "netlify",
+ "nfshost",
+ "no",
+ "on-aptible",
+ "onthewifi",
+ "ooguy",
+ "operaunite",
+ "outsystemscloud",
+ "ownprovider",
+ "pagefrontapp",
+ "pagespeedmobilizer",
+ "pgfog",
+ "pixolino",
+ "point2this",
+ "prgmr",
+ "publishproxy",
+ "qa2",
+ "qc",
+ "quicksytes",
+ "quipelements",
+ "rackmaze",
+ "remotewd",
+ "rhcloud",
+ "ru",
+ "sa",
+ "saves-the-whales",
+ "se",
+ "securitytactics",
+ "selfip",
+ "sells-for-less",
+ "sells-for-u",
+ "servebbs",
+ "servebeer",
+ "servecounterstrike",
+ "serveexchange",
+ "serveftp",
+ "servegame",
+ "servehalflife",
+ "servehttp",
+ "servehumour",
+ "serveirc",
+ "servemp3",
+ "servep2p",
+ "servepics",
+ "servequake",
+ "servesarcasm",
+ "simple-url",
+ "sinaapp",
+ "space-to-rent",
+ "stufftoread",
+ "teaches-yoga",
+ "temp-dns",
+ "theworkpc",
+ "townnews-staging",
+ "uk",
+ "unusualperson",
+ "us",
+ "uy",
+ "vipsinaapp",
+ "withgoogle",
+ "withyoutube",
+ "workisboring",
+ "wpdevcloud",
+ "writesthisblog",
+ "xenapponazure",
+ "yolasite",
+ "za",
+ "ap-northeast-1",
+ "ap-northeast-2",
+ "ap-south-1",
+ "ap-southeast-1",
+ "ap-southeast-2",
+ "ca-central-1",
+ "compute",
+ "compute-1",
+ "elb",
+ "eu-central-1",
+ "eu-west-1",
+ "eu-west-2",
+ "s3",
+ "s3-ap-northeast-1",
+ "s3-ap-northeast-2",
+ "s3-ap-south-1",
+ "s3-ap-southeast-1",
+ "s3-ap-southeast-2",
+ "s3-ca-central-1",
+ "s3-eu-central-1",
+ "s3-eu-west-1",
+ "s3-eu-west-2",
+ "s3-external-1",
+ "s3-fips-us-gov-west-1",
+ "s3-sa-east-1",
+ "s3-us-east-2",
+ "s3-us-gov-west-1",
+ "s3-us-west-1",
+ "s3-us-west-2",
+ "s3-website-ap-northeast-1",
+ "s3-website-ap-southeast-1",
+ "s3-website-ap-southeast-2",
+ "s3-website-eu-west-1",
+ "s3-website-sa-east-1",
+ "s3-website-us-east-1",
+ "s3-website-us-west-1",
+ "s3-website-us-west-2",
+ "sa-east-1",
+ "us-east-1",
+ "us-east-2",
+ "dualstack",
+ "s3",
+ "dualstack",
+ "s3",
+ "s3-website",
+ "s3",
+ "dualstack",
+ "s3",
+ "s3-website",
+ "s3",
+ "dualstack",
+ "s3",
+ "dualstack",
+ "s3",
+ "dualstack",
+ "s3",
+ "s3-website",
+ "s3",
+ "dualstack",
+ "s3",
+ "s3-website",
+ "s3",
+ "dualstack",
+ "s3",
+ "dualstack",
+ "s3",
+ "s3-website",
+ "s3",
+ "dualstack",
+ "s3",
+ "dualstack",
+ "s3",
+ "dualstack",
+ "s3",
+ "s3-website",
+ "s3",
+ "alpha",
+ "beta",
+ "ap-northeast-1",
+ "ap-northeast-2",
+ "ap-south-1",
+ "ap-southeast-1",
+ "ap-southeast-2",
+ "ca-central-1",
+ "eu-central-1",
+ "eu-west-1",
+ "eu-west-2",
+ "sa-east-1",
+ "us-east-1",
+ "us-east-2",
+ "us-gov-west-1",
+ "us-west-1",
+ "us-west-2",
+ "eu-1",
+ "eu-2",
+ "eu-3",
+ "eu-4",
+ "us-1",
+ "us-2",
+ "us-3",
+ "us-4",
+ "apps",
+ "cns",
+ "eu",
+ "xen",
+ "de",
+ "ac",
+ "co",
+ "ed",
+ "fi",
+ "go",
+ "or",
+ "sa",
+ "com",
+ "edu",
+ "gov",
+ "inf",
+ "net",
+ "org",
+ "blogspot",
+ "com",
+ "edu",
+ "net",
+ "org",
+ "ath",
+ "gov",
+ "info",
+ "ac",
+ "biz",
+ "com",
+ "ekloges",
+ "gov",
+ "ltd",
+ "name",
+ "net",
+ "org",
+ "parliament",
+ "press",
+ "pro",
+ "tm",
+ "blogspot",
+ "blogspot",
+ "co",
+ "e4",
+ "metacentrum",
+ "realm",
+ "cloud",
+ "custom",
+ "12hp",
+ "2ix",
+ "4lima",
+ "barsy",
+ "blogspot",
+ "bplaced",
+ "com",
+ "cosidns",
+ "dd-dns",
+ "ddnss",
+ "dnshome",
+ "dnsupdater",
+ "dray-dns",
+ "draydns",
+ "dyn-ip24",
+ "dyn-vpn",
+ "dynamisches-dns",
+ "dyndns1",
+ "dynvpn",
+ "firewall-gateway",
+ "fuettertdasnetz",
+ "git-repos",
+ "goip",
+ "home-webserver",
+ "internet-dns",
+ "isteingeek",
+ "istmein",
+ "keymachine",
+ "l-o-g-i-n",
+ "lcube-server",
+ "lebtimnetz",
+ "leitungsen",
+ "lima-city",
+ "logoip",
+ "mein-vigor",
+ "my-gateway",
+ "my-router",
+ "my-vigor",
+ "my-wan",
+ "myhome-server",
+ "spdns",
+ "square7",
+ "svn-repos",
+ "syno-ds",
+ "synology-diskstation",
+ "synology-ds",
+ "taifun-dns",
+ "traeumtgerade",
+ "dyn",
+ "dyn",
+ "dyndns",
+ "dyn",
+ "biz",
+ "blogspot",
+ "co",
+ "firm",
+ "reg",
+ "store",
+ "com",
+ "edu",
+ "gov",
+ "net",
+ "org",
+ "art",
+ "com",
+ "edu",
+ "gob",
+ "gov",
+ "mil",
+ "net",
+ "org",
+ "sld",
+ "web",
+ "art",
+ "asso",
+ "com",
+ "edu",
+ "gov",
+ "net",
+ "org",
+ "pol",
+ "com",
+ "edu",
+ "fin",
+ "gob",
+ "gov",
+ "info",
+ "k12",
+ "med",
+ "mil",
+ "net",
+ "org",
+ "pro",
+ "aip",
+ "com",
+ "edu",
+ "fie",
+ "gov",
+ "lib",
+ "med",
+ "org",
+ "pri",
+ "riik",
+ "blogspot",
+ "com",
+ "edu",
+ "eun",
+ "gov",
+ "mil",
+ "name",
+ "net",
+ "org",
+ "sci",
+ "blogspot",
+ "com",
+ "edu",
+ "gob",
+ "nom",
+ "org",
+ "blogspot",
+ "compute",
+ "biz",
+ "com",
+ "edu",
+ "gov",
+ "info",
+ "name",
+ "net",
+ "org",
+ "barsy",
+ "cloudns",
+ "diskstation",
+ "mycd",
+ "spdns",
+ "transurl",
+ "wellbeingzone",
+ "party",
+ "user",
+ "ybo",
+ "storj",
+ "aland",
+ "blogspot",
+ "dy",
+ "iki",
+ "ptplus",
+ "aeroport",
+ "assedic",
+ "asso",
+ "avocat",
+ "avoues",
+ "blogspot",
+ "cci",
+ "chambagri",
+ "chirurgiens-dentistes",
+ "chirurgiens-dentistes-en-france",
+ "com",
+ "experts-comptables",
+ "fbx-os",
+ "fbxos",
+ "freebox-os",
+ "freeboxos",
+ "geometre-expert",
+ "gouv",
+ "greta",
+ "huissier-justice",
+ "medecin",
+ "nom",
+ "notaires",
+ "on-web",
+ "pharmacien",
+ "port",
+ "prd",
+ "presse",
+ "tm",
+ "veterinaire",
+ "nom",
+ "com",
+ "edu",
+ "gov",
+ "mil",
+ "net",
+ "org",
+ "pvt",
+ "co",
+ "cya",
+ "net",
+ "org",
+ "com",
+ "edu",
+ "gov",
+ "mil",
+ "org",
+ "com",
+ "edu",
+ "gov",
+ "ltd",
+ "mod",
+ "org",
+ "co",
+ "com",
+ "edu",
+ "net",
+ "nom",
+ "org",
+ "ac",
+ "com",
+ "edu",
+ "gov",
+ "net",
+ "org",
+ "cloud",
+ "asso",
+ "com",
+ "edu",
+ "mobi",
+ "net",
+ "org",
+ "blogspot",
+ "com",
+ "edu",
+ "gov",
+ "net",
+ "nym",
+ "org",
+ "com",
+ "edu",
+ "gob",
+ "ind",
+ "mil",
+ "net",
+ "nom",
+ "org",
+ "co",
+ "com",
+ "edu",
+ "gov",
+ "net",
+ "org",
+ "blogspot",
+ "com",
+ "edu",
+ "gov",
+ "idv",
+ "inc",
+ "ltd",
+ "net",
+ "org",
+ "xn--55qx5d",
+ "xn--ciqpn",
+ "xn--gmq050i",
+ "xn--gmqw5a",
+ "xn--io0a7i",
+ "xn--lcvr32d",
+ "xn--mk0axi",
+ "xn--mxtq1m",
+ "xn--od0alg",
+ "xn--od0aq3b",
+ "xn--tn0ag",
+ "xn--uc0atv",
+ "xn--uc0ay4a",
+ "xn--wcvs22d",
+ "xn--zf0avx",
+ "com",
+ "edu",
+ "gob",
+ "mil",
+ "net",
+ "nom",
+ "org",
+ "cloudaccess",
+ "freesite",
+ "opencraft",
+ "blogspot",
+ "com",
+ "from",
+ "iz",
+ "name",
+ "adult",
+ "art",
+ "asso",
+ "com",
+ "coop",
+ "edu",
+ "firm",
+ "gouv",
+ "info",
+ "med",
+ "net",
+ "org",
+ "perso",
+ "pol",
+ "pro",
+ "rel",
+ "shop",
+ "2000",
+ "agrar",
+ "blogspot",
+ "bolt",
+ "casino",
+ "city",
+ "co",
+ "erotica",
+ "erotika",
+ "film",
+ "forum",
+ "games",
+ "hotel",
+ "info",
+ "ingatlan",
+ "jogasz",
+ "konyvelo",
+ "lakas",
+ "media",
+ "news",
+ "org",
+ "priv",
+ "reklam",
+ "sex",
+ "shop",
+ "sport",
+ "suli",
+ "szex",
+ "tm",
+ "tozsde",
+ "utazas",
+ "video",
+ "ac",
+ "biz",
+ "co",
+ "desa",
+ "go",
+ "mil",
+ "my",
+ "net",
+ "or",
+ "sch",
+ "web",
+ "blogspot",
+ "blogspot",
+ "gov",
+ "ac",
+ "co",
+ "gov",
+ "idf",
+ "k12",
+ "muni",
+ "net",
+ "org",
+ "blogspot",
+ "ac",
+ "co",
+ "com",
+ "net",
+ "nom",
+ "org",
+ "ro",
+ "tt",
+ "tv",
+ "ltd",
+ "plc",
+ "ac",
+ "barsy",
+ "blogspot",
+ "cloudns",
+ "co",
+ "edu",
+ "firm",
+ "gen",
+ "gov",
+ "ind",
+ "mil",
+ "net",
+ "nic",
+ "org",
+ "res",
+ "barrel-of-knowledge",
+ "barrell-of-knowledge",
+ "cloudns",
+ "dvrcam",
+ "dynamic-dns",
+ "dyndns",
+ "for-our",
+ "groks-the",
+ "groks-this",
+ "here-for-more",
+ "ilovecollege",
+ "knowsitall",
+ "no-ip",
+ "nsupdate",
+ "selfip",
+ "v-info",
+ "webhop",
+ "eu",
+ "backplaneapp",
+ "boxfuse",
+ "browsersafetymark",
+ "com",
+ "dedyn",
+ "definima",
+ "drud",
+ "enonic",
+ "github",
+ "gitlab",
+ "hasura-app",
+ "hzc",
+ "lair",
+ "ngrok",
+ "nid",
+ "nodeart",
+ "nodum",
+ "pantheonsite",
+ "protonet",
+ "sandcats",
+ "shiftedit",
+ "spacekit",
+ "stolos",
+ "thingdust",
+ "vaporcloud",
+ "wedeploy",
+ "customer",
+ "apps",
+ "stage",
+ "dev",
+ "disrec",
+ "prod",
+ "testing",
+ "cust",
+ "cust",
+ "cust",
+ "cust",
+ "com",
+ "edu",
+ "gov",
+ "mil",
+ "net",
+ "org",
+ "ac",
+ "co",
+ "gov",
+ "id",
+ "net",
+ "org",
+ "sch",
+ "xn--mgba3a4f16a",
+ "xn--mgba3a4fra",
+ "blogspot",
+ "com",
+ "cupcake",
+ "edu",
+ "gov",
+ "int",
+ "net",
+ "org",
+ "abr",
+ "abruzzo",
+ "ag",
+ "agrigento",
+ "al",
+ "alessandria",
+ "alto-adige",
+ "altoadige",
+ "an",
+ "ancona",
+ "andria-barletta-trani",
+ "andria-trani-barletta",
+ "andriabarlettatrani",
+ "andriatranibarletta",
+ "ao",
+ "aosta",
+ "aosta-valley",
+ "aostavalley",
+ "aoste",
+ "ap",
+ "aq",
+ "aquila",
+ "ar",
+ "arezzo",
+ "ascoli-piceno",
+ "ascolipiceno",
+ "asti",
+ "at",
+ "av",
+ "avellino",
+ "ba",
+ "balsan",
+ "bari",
+ "barletta-trani-andria",
+ "barlettatraniandria",
+ "bas",
+ "basilicata",
+ "belluno",
+ "benevento",
+ "bergamo",
+ "bg",
+ "bi",
+ "biella",
+ "bl",
+ "blogspot",
+ "bn",
+ "bo",
+ "bologna",
+ "bolzano",
+ "bozen",
+ "br",
+ "brescia",
+ "brindisi",
+ "bs",
+ "bt",
+ "bz",
+ "ca",
+ "cagliari",
+ "cal",
+ "calabria",
+ "caltanissetta",
+ "cam",
+ "campania",
+ "campidano-medio",
+ "campidanomedio",
+ "campobasso",
+ "carbonia-iglesias",
+ "carboniaiglesias",
+ "carrara-massa",
+ "carraramassa",
+ "caserta",
+ "catania",
+ "catanzaro",
+ "cb",
+ "ce",
+ "cesena-forli",
+ "cesenaforli",
+ "ch",
+ "chieti",
+ "ci",
+ "cl",
+ "cn",
+ "co",
+ "como",
+ "cosenza",
+ "cr",
+ "cremona",
+ "crotone",
+ "cs",
+ "ct",
+ "cuneo",
+ "cz",
+ "dell-ogliastra",
+ "dellogliastra",
+ "edu",
+ "emilia-romagna",
+ "emiliaromagna",
+ "emr",
+ "en",
+ "enna",
+ "fc",
+ "fe",
+ "fermo",
+ "ferrara",
+ "fg",
+ "fi",
+ "firenze",
+ "florence",
+ "fm",
+ "foggia",
+ "forli-cesena",
+ "forlicesena",
+ "fr",
+ "friuli-v-giulia",
+ "friuli-ve-giulia",
+ "friuli-vegiulia",
+ "friuli-venezia-giulia",
+ "friuli-veneziagiulia",
+ "friuli-vgiulia",
+ "friuliv-giulia",
+ "friulive-giulia",
+ "friulivegiulia",
+ "friulivenezia-giulia",
+ "friuliveneziagiulia",
+ "friulivgiulia",
+ "frosinone",
+ "fvg",
+ "ge",
+ "genoa",
+ "genova",
+ "go",
+ "gorizia",
+ "gov",
+ "gr",
+ "grosseto",
+ "iglesias-carbonia",
+ "iglesiascarbonia",
+ "im",
+ "imperia",
+ "is",
+ "isernia",
+ "kr",
+ "la-spezia",
+ "laquila",
+ "laspezia",
+ "latina",
+ "laz",
+ "lazio",
+ "lc",
+ "le",
+ "lecce",
+ "lecco",
+ "li",
+ "lig",
+ "liguria",
+ "livorno",
+ "lo",
+ "lodi",
+ "lom",
+ "lombardia",
+ "lombardy",
+ "lt",
+ "lu",
+ "lucania",
+ "lucca",
+ "macerata",
+ "mantova",
+ "mar",
+ "marche",
+ "massa-carrara",
+ "massacarrara",
+ "matera",
+ "mb",
+ "mc",
+ "me",
+ "medio-campidano",
+ "mediocampidano",
+ "messina",
+ "mi",
+ "milan",
+ "milano",
+ "mn",
+ "mo",
+ "modena",
+ "mol",
+ "molise",
+ "monza",
+ "monza-brianza",
+ "monza-e-della-brianza",
+ "monzabrianza",
+ "monzaebrianza",
+ "monzaedellabrianza",
+ "ms",
+ "mt",
+ "na",
+ "naples",
+ "napoli",
+ "no",
+ "novara",
+ "nu",
+ "nuoro",
+ "og",
+ "ogliastra",
+ "olbia-tempio",
+ "olbiatempio",
+ "or",
+ "oristano",
+ "ot",
+ "pa",
+ "padova",
+ "padua",
+ "palermo",
+ "parma",
+ "pavia",
+ "pc",
+ "pd",
+ "pe",
+ "perugia",
+ "pesaro-urbino",
+ "pesarourbino",
+ "pescara",
+ "pg",
+ "pi",
+ "piacenza",
+ "piedmont",
+ "piemonte",
+ "pisa",
+ "pistoia",
+ "pmn",
+ "pn",
+ "po",
+ "pordenone",
+ "potenza",
+ "pr",
+ "prato",
+ "pt",
+ "pu",
+ "pug",
+ "puglia",
+ "pv",
+ "pz",
+ "ra",
+ "ragusa",
+ "ravenna",
+ "rc",
+ "re",
+ "reggio-calabria",
+ "reggio-emilia",
+ "reggiocalabria",
+ "reggioemilia",
+ "rg",
+ "ri",
+ "rieti",
+ "rimini",
+ "rm",
+ "rn",
+ "ro",
+ "roma",
+ "rome",
+ "rovigo",
+ "sa",
+ "salerno",
+ "sar",
+ "sardegna",
+ "sardinia",
+ "sassari",
+ "savona",
+ "si",
+ "sic",
+ "sicilia",
+ "sicily",
+ "siena",
+ "siracusa",
+ "so",
+ "sondrio",
+ "sp",
+ "sr",
+ "ss",
+ "suedtirol",
+ "sv",
+ "ta",
+ "taa",
+ "taranto",
+ "te",
+ "tempio-olbia",
+ "tempioolbia",
+ "teramo",
+ "terni",
+ "tn",
+ "to",
+ "torino",
+ "tos",
+ "toscana",
+ "tp",
+ "tr",
+ "trani-andria-barletta",
+ "trani-barletta-andria",
+ "traniandriabarletta",
+ "tranibarlettaandria",
+ "trapani",
+ "trentino",
+ "trentino-a-adige",
+ "trentino-aadige",
+ "trentino-alto-adige",
+ "trentino-altoadige",
+ "trentino-s-tirol",
+ "trentino-stirol",
+ "trentino-sud-tirol",
+ "trentino-sudtirol",
+ "trentino-sued-tirol",
+ "trentino-suedtirol",
+ "trentinoa-adige",
+ "trentinoaadige",
+ "trentinoalto-adige",
+ "trentinoaltoadige",
+ "trentinos-tirol",
+ "trentinostirol",
+ "trentinosud-tirol",
+ "trentinosudtirol",
+ "trentinosued-tirol",
+ "trentinosuedtirol",
+ "trento",
+ "treviso",
+ "trieste",
+ "ts",
+ "turin",
+ "tuscany",
+ "tv",
+ "ud",
+ "udine",
+ "umb",
+ "umbria",
+ "urbino-pesaro",
+ "urbinopesaro",
+ "va",
+ "val-d-aosta",
+ "val-daosta",
+ "vald-aosta",
+ "valdaosta",
+ "valle-aosta",
+ "valle-d-aosta",
+ "valle-daosta",
+ "valleaosta",
+ "valled-aosta",
+ "valledaosta",
+ "vallee-aoste",
+ "valleeaoste",
+ "vao",
+ "varese",
+ "vb",
+ "vc",
+ "vda",
+ "ve",
+ "ven",
+ "veneto",
+ "venezia",
+ "venice",
+ "verbania",
+ "vercelli",
+ "verona",
+ "vi",
+ "vibo-valentia",
+ "vibovalentia",
+ "vicenza",
+ "viterbo",
+ "vr",
+ "vs",
+ "vt",
+ "vv",
+ "co",
+ "net",
+ "org",
+ "com",
+ "edu",
+ "gov",
+ "mil",
+ "name",
+ "net",
+ "org",
+ "sch",
+ "ac",
+ "ad",
+ "aichi",
+ "akita",
+ "aomori",
+ "blogspot",
+ "chiba",
+ "co",
+ "ed",
+ "ehime",
+ "fukui",
+ "fukuoka",
+ "fukushima",
+ "gifu",
+ "go",
+ "gr",
+ "gunma",
+ "hiroshima",
+ "hokkaido",
+ "hyogo",
+ "ibaraki",
+ "ishikawa",
+ "iwate",
+ "kagawa",
+ "kagoshima",
+ "kanagawa",
+ "kawasaki",
+ "kitakyushu",
+ "kobe",
+ "kochi",
+ "kumamoto",
+ "kyoto",
+ "lg",
+ "mie",
+ "miyagi",
+ "miyazaki",
+ "nagano",
+ "nagasaki",
+ "nagoya",
+ "nara",
+ "ne",
+ "niigata",
+ "oita",
+ "okayama",
+ "okinawa",
+ "or",
+ "osaka",
+ "saga",
+ "saitama",
+ "sapporo",
+ "sendai",
+ "shiga",
+ "shimane",
+ "shizuoka",
+ "tochigi",
+ "tokushima",
+ "tokyo",
+ "tottori",
+ "toyama",
+ "wakayama",
+ "xn--0trq7p7nn",
+ "xn--1ctwo",
+ "xn--1lqs03n",
+ "xn--1lqs71d",
+ "xn--2m4a15e",
+ "xn--32vp30h",
+ "xn--4it168d",
+ "xn--4it797k",
+ "xn--4pvxs",
+ "xn--5js045d",
+ "xn--5rtp49c",
+ "xn--5rtq34k",
+ "xn--6btw5a",
+ "xn--6orx2r",
+ "xn--7t0a264c",
+ "xn--8ltr62k",
+ "xn--8pvr4u",
+ "xn--c3s14m",
+ "xn--d5qv7z876c",
+ "xn--djrs72d6uy",
+ "xn--djty4k",
+ "xn--efvn9s",
+ "xn--ehqz56n",
+ "xn--elqq16h",
+ "xn--f6qx53a",
+ "xn--k7yn95e",
+ "xn--kbrq7o",
+ "xn--klt787d",
+ "xn--kltp7d",
+ "xn--kltx9a",
+ "xn--klty5x",
+ "xn--mkru45i",
+ "xn--nit225k",
+ "xn--ntso0iqx3a",
+ "xn--ntsq17g",
+ "xn--pssu33l",
+ "xn--qqqt11m",
+ "xn--rht27z",
+ "xn--rht3d",
+ "xn--rht61e",
+ "xn--rny31h",
+ "xn--tor131o",
+ "xn--uist22h",
+ "xn--uisz3g",
+ "xn--uuwu58a",
+ "xn--vgu402c",
+ "xn--zbx025d",
+ "yamagata",
+ "yamaguchi",
+ "yamanashi",
+ "yokohama",
+ "aisai",
+ "ama",
+ "anjo",
+ "asuke",
+ "chiryu",
+ "chita",
+ "fuso",
+ "gamagori",
+ "handa",
+ "hazu",
+ "hekinan",
+ "higashiura",
+ "ichinomiya",
+ "inazawa",
+ "inuyama",
+ "isshiki",
+ "iwakura",
+ "kanie",
+ "kariya",
+ "kasugai",
+ "kira",
+ "kiyosu",
+ "komaki",
+ "konan",
+ "kota",
+ "mihama",
+ "miyoshi",
+ "nishio",
+ "nisshin",
+ "obu",
+ "oguchi",
+ "oharu",
+ "okazaki",
+ "owariasahi",
+ "seto",
+ "shikatsu",
+ "shinshiro",
+ "shitara",
+ "tahara",
+ "takahama",
+ "tobishima",
+ "toei",
+ "togo",
+ "tokai",
+ "tokoname",
+ "toyoake",
+ "toyohashi",
+ "toyokawa",
+ "toyone",
+ "toyota",
+ "tsushima",
+ "yatomi",
+ "akita",
+ "daisen",
+ "fujisato",
+ "gojome",
+ "hachirogata",
+ "happou",
+ "higashinaruse",
+ "honjo",
+ "honjyo",
+ "ikawa",
+ "kamikoani",
+ "kamioka",
+ "katagami",
+ "kazuno",
+ "kitaakita",
+ "kosaka",
+ "kyowa",
+ "misato",
+ "mitane",
+ "moriyoshi",
+ "nikaho",
+ "noshiro",
+ "odate",
+ "oga",
+ "ogata",
+ "semboku",
+ "yokote",
+ "yurihonjo",
+ "aomori",
+ "gonohe",
+ "hachinohe",
+ "hashikami",
+ "hiranai",
+ "hirosaki",
+ "itayanagi",
+ "kuroishi",
+ "misawa",
+ "mutsu",
+ "nakadomari",
+ "noheji",
+ "oirase",
+ "owani",
+ "rokunohe",
+ "sannohe",
+ "shichinohe",
+ "shingo",
+ "takko",
+ "towada",
+ "tsugaru",
+ "tsuruta",
+ "abiko",
+ "asahi",
+ "chonan",
+ "chosei",
+ "choshi",
+ "chuo",
+ "funabashi",
+ "futtsu",
+ "hanamigawa",
+ "ichihara",
+ "ichikawa",
+ "ichinomiya",
+ "inzai",
+ "isumi",
+ "kamagaya",
+ "kamogawa",
+ "kashiwa",
+ "katori",
+ "katsuura",
+ "kimitsu",
+ "kisarazu",
+ "kozaki",
+ "kujukuri",
+ "kyonan",
+ "matsudo",
+ "midori",
+ "mihama",
+ "minamiboso",
+ "mobara",
+ "mutsuzawa",
+ "nagara",
+ "nagareyama",
+ "narashino",
+ "narita",
+ "noda",
+ "oamishirasato",
+ "omigawa",
+ "onjuku",
+ "otaki",
+ "sakae",
+ "sakura",
+ "shimofusa",
+ "shirako",
+ "shiroi",
+ "shisui",
+ "sodegaura",
+ "sosa",
+ "tako",
+ "tateyama",
+ "togane",
+ "tohnosho",
+ "tomisato",
+ "urayasu",
+ "yachimata",
+ "yachiyo",
+ "yokaichiba",
+ "yokoshibahikari",
+ "yotsukaido",
+ "ainan",
+ "honai",
+ "ikata",
+ "imabari",
+ "iyo",
+ "kamijima",
+ "kihoku",
+ "kumakogen",
+ "masaki",
+ "matsuno",
+ "matsuyama",
+ "namikata",
+ "niihama",
+ "ozu",
+ "saijo",
+ "seiyo",
+ "shikokuchuo",
+ "tobe",
+ "toon",
+ "uchiko",
+ "uwajima",
+ "yawatahama",
+ "echizen",
+ "eiheiji",
+ "fukui",
+ "ikeda",
+ "katsuyama",
+ "mihama",
+ "minamiechizen",
+ "obama",
+ "ohi",
+ "ono",
+ "sabae",
+ "sakai",
+ "takahama",
+ "tsuruga",
+ "wakasa",
+ "ashiya",
+ "buzen",
+ "chikugo",
+ "chikuho",
+ "chikujo",
+ "chikushino",
+ "chikuzen",
+ "chuo",
+ "dazaifu",
+ "fukuchi",
+ "hakata",
+ "higashi",
+ "hirokawa",
+ "hisayama",
+ "iizuka",
+ "inatsuki",
+ "kaho",
+ "kasuga",
+ "kasuya",
+ "kawara",
+ "keisen",
+ "koga",
+ "kurate",
+ "kurogi",
+ "kurume",
+ "minami",
+ "miyako",
+ "miyama",
+ "miyawaka",
+ "mizumaki",
+ "munakata",
+ "nakagawa",
+ "nakama",
+ "nishi",
+ "nogata",
+ "ogori",
+ "okagaki",
+ "okawa",
+ "oki",
+ "omuta",
+ "onga",
+ "onojo",
+ "oto",
+ "saigawa",
+ "sasaguri",
+ "shingu",
+ "shinyoshitomi",
+ "shonai",
+ "soeda",
+ "sue",
+ "tachiarai",
+ "tagawa",
+ "takata",
+ "toho",
+ "toyotsu",
+ "tsuiki",
+ "ukiha",
+ "umi",
+ "usui",
+ "yamada",
+ "yame",
+ "yanagawa",
+ "yukuhashi",
+ "aizubange",
+ "aizumisato",
+ "aizuwakamatsu",
+ "asakawa",
+ "bandai",
+ "date",
+ "fukushima",
+ "furudono",
+ "futaba",
+ "hanawa",
+ "higashi",
+ "hirata",
+ "hirono",
+ "iitate",
+ "inawashiro",
+ "ishikawa",
+ "iwaki",
+ "izumizaki",
+ "kagamiishi",
+ "kaneyama",
+ "kawamata",
+ "kitakata",
+ "kitashiobara",
+ "koori",
+ "koriyama",
+ "kunimi",
+ "miharu",
+ "mishima",
+ "namie",
+ "nango",
+ "nishiaizu",
+ "nishigo",
+ "okuma",
+ "omotego",
+ "ono",
+ "otama",
+ "samegawa",
+ "shimogo",
+ "shirakawa",
+ "showa",
+ "soma",
+ "sukagawa",
+ "taishin",
+ "tamakawa",
+ "tanagura",
+ "tenei",
+ "yabuki",
+ "yamato",
+ "yamatsuri",
+ "yanaizu",
+ "yugawa",
+ "anpachi",
+ "ena",
+ "gifu",
+ "ginan",
+ "godo",
+ "gujo",
+ "hashima",
+ "hichiso",
+ "hida",
+ "higashishirakawa",
+ "ibigawa",
+ "ikeda",
+ "kakamigahara",
+ "kani",
+ "kasahara",
+ "kasamatsu",
+ "kawaue",
+ "kitagata",
+ "mino",
+ "minokamo",
+ "mitake",
+ "mizunami",
+ "motosu",
+ "nakatsugawa",
+ "ogaki",
+ "sakahogi",
+ "seki",
+ "sekigahara",
+ "shirakawa",
+ "tajimi",
+ "takayama",
+ "tarui",
+ "toki",
+ "tomika",
+ "wanouchi",
+ "yamagata",
+ "yaotsu",
+ "yoro",
+ "annaka",
+ "chiyoda",
+ "fujioka",
+ "higashiagatsuma",
+ "isesaki",
+ "itakura",
+ "kanna",
+ "kanra",
+ "katashina",
+ "kawaba",
+ "kiryu",
+ "kusatsu",
+ "maebashi",
+ "meiwa",
+ "midori",
+ "minakami",
+ "naganohara",
+ "nakanojo",
+ "nanmoku",
+ "numata",
+ "oizumi",
+ "ora",
+ "ota",
+ "shibukawa",
+ "shimonita",
+ "shinto",
+ "showa",
+ "takasaki",
+ "takayama",
+ "tamamura",
+ "tatebayashi",
+ "tomioka",
+ "tsukiyono",
+ "tsumagoi",
+ "ueno",
+ "yoshioka",
+ "asaminami",
+ "daiwa",
+ "etajima",
+ "fuchu",
+ "fukuyama",
+ "hatsukaichi",
+ "higashihiroshima",
+ "hongo",
+ "jinsekikogen",
+ "kaita",
+ "kui",
+ "kumano",
+ "kure",
+ "mihara",
+ "miyoshi",
+ "naka",
+ "onomichi",
+ "osakikamijima",
+ "otake",
+ "saka",
+ "sera",
+ "seranishi",
+ "shinichi",
+ "shobara",
+ "takehara",
+ "abashiri",
+ "abira",
+ "aibetsu",
+ "akabira",
+ "akkeshi",
+ "asahikawa",
+ "ashibetsu",
+ "ashoro",
+ "assabu",
+ "atsuma",
+ "bibai",
+ "biei",
+ "bifuka",
+ "bihoro",
+ "biratori",
+ "chippubetsu",
+ "chitose",
+ "date",
+ "ebetsu",
+ "embetsu",
+ "eniwa",
+ "erimo",
+ "esan",
+ "esashi",
+ "fukagawa",
+ "fukushima",
+ "furano",
+ "furubira",
+ "haboro",
+ "hakodate",
+ "hamatonbetsu",
+ "hidaka",
+ "higashikagura",
+ "higashikawa",
+ "hiroo",
+ "hokuryu",
+ "hokuto",
+ "honbetsu",
+ "horokanai",
+ "horonobe",
+ "ikeda",
+ "imakane",
+ "ishikari",
+ "iwamizawa",
+ "iwanai",
+ "kamifurano",
+ "kamikawa",
+ "kamishihoro",
+ "kamisunagawa",
+ "kamoenai",
+ "kayabe",
+ "kembuchi",
+ "kikonai",
+ "kimobetsu",
+ "kitahiroshima",
+ "kitami",
+ "kiyosato",
+ "koshimizu",
+ "kunneppu",
+ "kuriyama",
+ "kuromatsunai",
+ "kushiro",
+ "kutchan",
+ "kyowa",
+ "mashike",
+ "matsumae",
+ "mikasa",
+ "minamifurano",
+ "mombetsu",
+ "moseushi",
+ "mukawa",
+ "muroran",
+ "naie",
+ "nakagawa",
+ "nakasatsunai",
+ "nakatombetsu",
+ "nanae",
+ "nanporo",
+ "nayoro",
+ "nemuro",
+ "niikappu",
+ "niki",
+ "nishiokoppe",
+ "noboribetsu",
+ "numata",
+ "obihiro",
+ "obira",
+ "oketo",
+ "okoppe",
+ "otaru",
+ "otobe",
+ "otofuke",
+ "otoineppu",
+ "oumu",
+ "ozora",
+ "pippu",
+ "rankoshi",
+ "rebun",
+ "rikubetsu",
+ "rishiri",
+ "rishirifuji",
+ "saroma",
+ "sarufutsu",
+ "shakotan",
+ "shari",
+ "shibecha",
+ "shibetsu",
+ "shikabe",
+ "shikaoi",
+ "shimamaki",
+ "shimizu",
+ "shimokawa",
+ "shinshinotsu",
+ "shintoku",
+ "shiranuka",
+ "shiraoi",
+ "shiriuchi",
+ "sobetsu",
+ "sunagawa",
+ "taiki",
+ "takasu",
+ "takikawa",
+ "takinoue",
+ "teshikaga",
+ "tobetsu",
+ "tohma",
+ "tomakomai",
+ "tomari",
+ "toya",
+ "toyako",
+ "toyotomi",
+ "toyoura",
+ "tsubetsu",
+ "tsukigata",
+ "urakawa",
+ "urausu",
+ "uryu",
+ "utashinai",
+ "wakkanai",
+ "wassamu",
+ "yakumo",
+ "yoichi",
+ "aioi",
+ "akashi",
+ "ako",
+ "amagasaki",
+ "aogaki",
+ "asago",
+ "ashiya",
+ "awaji",
+ "fukusaki",
+ "goshiki",
+ "harima",
+ "himeji",
+ "ichikawa",
+ "inagawa",
+ "itami",
+ "kakogawa",
+ "kamigori",
+ "kamikawa",
+ "kasai",
+ "kasuga",
+ "kawanishi",
+ "miki",
+ "minamiawaji",
+ "nishinomiya",
+ "nishiwaki",
+ "ono",
+ "sanda",
+ "sannan",
+ "sasayama",
+ "sayo",
+ "shingu",
+ "shinonsen",
+ "shiso",
+ "sumoto",
+ "taishi",
+ "taka",
+ "takarazuka",
+ "takasago",
+ "takino",
+ "tamba",
+ "tatsuno",
+ "toyooka",
+ "yabu",
+ "yashiro",
+ "yoka",
+ "yokawa",
+ "ami",
+ "asahi",
+ "bando",
+ "chikusei",
+ "daigo",
+ "fujishiro",
+ "hitachi",
+ "hitachinaka",
+ "hitachiomiya",
+ "hitachiota",
+ "ibaraki",
+ "ina",
+ "inashiki",
+ "itako",
+ "iwama",
+ "joso",
+ "kamisu",
+ "kasama",
+ "kashima",
+ "kasumigaura",
+ "koga",
+ "miho",
+ "mito",
+ "moriya",
+ "naka",
+ "namegata",
+ "oarai",
+ "ogawa",
+ "omitama",
+ "ryugasaki",
+ "sakai",
+ "sakuragawa",
+ "shimodate",
+ "shimotsuma",
+ "shirosato",
+ "sowa",
+ "suifu",
+ "takahagi",
+ "tamatsukuri",
+ "tokai",
+ "tomobe",
+ "tone",
+ "toride",
+ "tsuchiura",
+ "tsukuba",
+ "uchihara",
+ "ushiku",
+ "yachiyo",
+ "yamagata",
+ "yawara",
+ "yuki",
+ "anamizu",
+ "hakui",
+ "hakusan",
+ "kaga",
+ "kahoku",
+ "kanazawa",
+ "kawakita",
+ "komatsu",
+ "nakanoto",
+ "nanao",
+ "nomi",
+ "nonoichi",
+ "noto",
+ "shika",
+ "suzu",
+ "tsubata",
+ "tsurugi",
+ "uchinada",
+ "wajima",
+ "fudai",
+ "fujisawa",
+ "hanamaki",
+ "hiraizumi",
+ "hirono",
+ "ichinohe",
+ "ichinoseki",
+ "iwaizumi",
+ "iwate",
+ "joboji",
+ "kamaishi",
+ "kanegasaki",
+ "karumai",
+ "kawai",
+ "kitakami",
+ "kuji",
+ "kunohe",
+ "kuzumaki",
+ "miyako",
+ "mizusawa",
+ "morioka",
+ "ninohe",
+ "noda",
+ "ofunato",
+ "oshu",
+ "otsuchi",
+ "rikuzentakata",
+ "shiwa",
+ "shizukuishi",
+ "sumita",
+ "tanohata",
+ "tono",
+ "yahaba",
+ "yamada",
+ "ayagawa",
+ "higashikagawa",
+ "kanonji",
+ "kotohira",
+ "manno",
+ "marugame",
+ "mitoyo",
+ "naoshima",
+ "sanuki",
+ "tadotsu",
+ "takamatsu",
+ "tonosho",
+ "uchinomi",
+ "utazu",
+ "zentsuji",
+ "akune",
+ "amami",
+ "hioki",
+ "isa",
+ "isen",
+ "izumi",
+ "kagoshima",
+ "kanoya",
+ "kawanabe",
+ "kinko",
+ "kouyama",
+ "makurazaki",
+ "matsumoto",
+ "minamitane",
+ "nakatane",
+ "nishinoomote",
+ "satsumasendai",
+ "soo",
+ "tarumizu",
+ "yusui",
+ "aikawa",
+ "atsugi",
+ "ayase",
+ "chigasaki",
+ "ebina",
+ "fujisawa",
+ "hadano",
+ "hakone",
+ "hiratsuka",
+ "isehara",
+ "kaisei",
+ "kamakura",
+ "kiyokawa",
+ "matsuda",
+ "minamiashigara",
+ "miura",
+ "nakai",
+ "ninomiya",
+ "odawara",
+ "oi",
+ "oiso",
+ "sagamihara",
+ "samukawa",
+ "tsukui",
+ "yamakita",
+ "yamato",
+ "yokosuka",
+ "yugawara",
+ "zama",
+ "zushi",
+ "city",
+ "city",
+ "city",
+ "aki",
+ "geisei",
+ "hidaka",
+ "higashitsuno",
+ "ino",
+ "kagami",
+ "kami",
+ "kitagawa",
+ "kochi",
+ "mihara",
+ "motoyama",
+ "muroto",
+ "nahari",
+ "nakamura",
+ "nankoku",
+ "nishitosa",
+ "niyodogawa",
+ "ochi",
+ "okawa",
+ "otoyo",
+ "otsuki",
+ "sakawa",
+ "sukumo",
+ "susaki",
+ "tosa",
+ "tosashimizu",
+ "toyo",
+ "tsuno",
+ "umaji",
+ "yasuda",
+ "yusuhara",
+ "amakusa",
+ "arao",
+ "aso",
+ "choyo",
+ "gyokuto",
+ "kamiamakusa",
+ "kikuchi",
+ "kumamoto",
+ "mashiki",
+ "mifune",
+ "minamata",
+ "minamioguni",
+ "nagasu",
+ "nishihara",
+ "oguni",
+ "ozu",
+ "sumoto",
+ "takamori",
+ "uki",
+ "uto",
+ "yamaga",
+ "yamato",
+ "yatsushiro",
+ "ayabe",
+ "fukuchiyama",
+ "higashiyama",
+ "ide",
+ "ine",
+ "joyo",
+ "kameoka",
+ "kamo",
+ "kita",
+ "kizu",
+ "kumiyama",
+ "kyotamba",
+ "kyotanabe",
+ "kyotango",
+ "maizuru",
+ "minami",
+ "minamiyamashiro",
+ "miyazu",
+ "muko",
+ "nagaokakyo",
+ "nakagyo",
+ "nantan",
+ "oyamazaki",
+ "sakyo",
+ "seika",
+ "tanabe",
+ "uji",
+ "ujitawara",
+ "wazuka",
+ "yamashina",
+ "yawata",
+ "asahi",
+ "inabe",
+ "ise",
+ "kameyama",
+ "kawagoe",
+ "kiho",
+ "kisosaki",
+ "kiwa",
+ "komono",
+ "kumano",
+ "kuwana",
+ "matsusaka",
+ "meiwa",
+ "mihama",
+ "minamiise",
+ "misugi",
+ "miyama",
+ "nabari",
+ "shima",
+ "suzuka",
+ "tado",
+ "taiki",
+ "taki",
+ "tamaki",
+ "toba",
+ "tsu",
+ "udono",
+ "ureshino",
+ "watarai",
+ "yokkaichi",
+ "furukawa",
+ "higashimatsushima",
+ "ishinomaki",
+ "iwanuma",
+ "kakuda",
+ "kami",
+ "kawasaki",
+ "marumori",
+ "matsushima",
+ "minamisanriku",
+ "misato",
+ "murata",
+ "natori",
+ "ogawara",
+ "ohira",
+ "onagawa",
+ "osaki",
+ "rifu",
+ "semine",
+ "shibata",
+ "shichikashuku",
+ "shikama",
+ "shiogama",
+ "shiroishi",
+ "tagajo",
+ "taiwa",
+ "tome",
+ "tomiya",
+ "wakuya",
+ "watari",
+ "yamamoto",
+ "zao",
+ "aya",
+ "ebino",
+ "gokase",
+ "hyuga",
+ "kadogawa",
+ "kawaminami",
+ "kijo",
+ "kitagawa",
+ "kitakata",
+ "kitaura",
+ "kobayashi",
+ "kunitomi",
+ "kushima",
+ "mimata",
+ "miyakonojo",
+ "miyazaki",
+ "morotsuka",
+ "nichinan",
+ "nishimera",
+ "nobeoka",
+ "saito",
+ "shiiba",
+ "shintomi",
+ "takaharu",
+ "takanabe",
+ "takazaki",
+ "tsuno",
+ "achi",
+ "agematsu",
+ "anan",
+ "aoki",
+ "asahi",
+ "azumino",
+ "chikuhoku",
+ "chikuma",
+ "chino",
+ "fujimi",
+ "hakuba",
+ "hara",
+ "hiraya",
+ "iida",
+ "iijima",
+ "iiyama",
+ "iizuna",
+ "ikeda",
+ "ikusaka",
+ "ina",
+ "karuizawa",
+ "kawakami",
+ "kiso",
+ "kisofukushima",
+ "kitaaiki",
+ "komagane",
+ "komoro",
+ "matsukawa",
+ "matsumoto",
+ "miasa",
+ "minamiaiki",
+ "minamimaki",
+ "minamiminowa",
+ "minowa",
+ "miyada",
+ "miyota",
+ "mochizuki",
+ "nagano",
+ "nagawa",
+ "nagiso",
+ "nakagawa",
+ "nakano",
+ "nozawaonsen",
+ "obuse",
+ "ogawa",
+ "okaya",
+ "omachi",
+ "omi",
+ "ookuwa",
+ "ooshika",
+ "otaki",
+ "otari",
+ "sakae",
+ "sakaki",
+ "saku",
+ "sakuho",
+ "shimosuwa",
+ "shinanomachi",
+ "shiojiri",
+ "suwa",
+ "suzaka",
+ "takagi",
+ "takamori",
+ "takayama",
+ "tateshina",
+ "tatsuno",
+ "togakushi",
+ "togura",
+ "tomi",
+ "ueda",
+ "wada",
+ "yamagata",
+ "yamanouchi",
+ "yasaka",
+ "yasuoka",
+ "chijiwa",
+ "futsu",
+ "goto",
+ "hasami",
+ "hirado",
+ "iki",
+ "isahaya",
+ "kawatana",
+ "kuchinotsu",
+ "matsuura",
+ "nagasaki",
+ "obama",
+ "omura",
+ "oseto",
+ "saikai",
+ "sasebo",
+ "seihi",
+ "shimabara",
+ "shinkamigoto",
+ "togitsu",
+ "tsushima",
+ "unzen",
+ "city",
+ "ando",
+ "gose",
+ "heguri",
+ "higashiyoshino",
+ "ikaruga",
+ "ikoma",
+ "kamikitayama",
+ "kanmaki",
+ "kashiba",
+ "kashihara",
+ "katsuragi",
+ "kawai",
+ "kawakami",
+ "kawanishi",
+ "koryo",
+ "kurotaki",
+ "mitsue",
+ "miyake",
+ "nara",
+ "nosegawa",
+ "oji",
+ "ouda",
+ "oyodo",
+ "sakurai",
+ "sango",
+ "shimoichi",
+ "shimokitayama",
+ "shinjo",
+ "soni",
+ "takatori",
+ "tawaramoto",
+ "tenkawa",
+ "tenri",
+ "uda",
+ "yamatokoriyama",
+ "yamatotakada",
+ "yamazoe",
+ "yoshino",
+ "aga",
+ "agano",
+ "gosen",
+ "itoigawa",
+ "izumozaki",
+ "joetsu",
+ "kamo",
+ "kariwa",
+ "kashiwazaki",
+ "minamiuonuma",
+ "mitsuke",
+ "muika",
+ "murakami",
+ "myoko",
+ "nagaoka",
+ "niigata",
+ "ojiya",
+ "omi",
+ "sado",
+ "sanjo",
+ "seiro",
+ "seirou",
+ "sekikawa",
+ "shibata",
+ "tagami",
+ "tainai",
+ "tochio",
+ "tokamachi",
+ "tsubame",
+ "tsunan",
+ "uonuma",
+ "yahiko",
+ "yoita",
+ "yuzawa",
+ "beppu",
+ "bungoono",
+ "bungotakada",
+ "hasama",
+ "hiji",
+ "himeshima",
+ "hita",
+ "kamitsue",
+ "kokonoe",
+ "kuju",
+ "kunisaki",
+ "kusu",
+ "oita",
+ "saiki",
+ "taketa",
+ "tsukumi",
+ "usa",
+ "usuki",
+ "yufu",
+ "akaiwa",
+ "asakuchi",
+ "bizen",
+ "hayashima",
+ "ibara",
+ "kagamino",
+ "kasaoka",
+ "kibichuo",
+ "kumenan",
+ "kurashiki",
+ "maniwa",
+ "misaki",
+ "nagi",
+ "niimi",
+ "nishiawakura",
+ "okayama",
+ "satosho",
+ "setouchi",
+ "shinjo",
+ "shoo",
+ "soja",
+ "takahashi",
+ "tamano",
+ "tsuyama",
+ "wake",
+ "yakage",
+ "aguni",
+ "ginowan",
+ "ginoza",
+ "gushikami",
+ "haebaru",
+ "higashi",
+ "hirara",
+ "iheya",
+ "ishigaki",
+ "ishikawa",
+ "itoman",
+ "izena",
+ "kadena",
+ "kin",
+ "kitadaito",
+ "kitanakagusuku",
+ "kumejima",
+ "kunigami",
+ "minamidaito",
+ "motobu",
+ "nago",
+ "naha",
+ "nakagusuku",
+ "nakijin",
+ "nanjo",
+ "nishihara",
+ "ogimi",
+ "okinawa",
+ "onna",
+ "shimoji",
+ "taketomi",
+ "tarama",
+ "tokashiki",
+ "tomigusuku",
+ "tonaki",
+ "urasoe",
+ "uruma",
+ "yaese",
+ "yomitan",
+ "yonabaru",
+ "yonaguni",
+ "zamami",
+ "abeno",
+ "chihayaakasaka",
+ "chuo",
+ "daito",
+ "fujiidera",
+ "habikino",
+ "hannan",
+ "higashiosaka",
+ "higashisumiyoshi",
+ "higashiyodogawa",
+ "hirakata",
+ "ibaraki",
+ "ikeda",
+ "izumi",
+ "izumiotsu",
+ "izumisano",
+ "kadoma",
+ "kaizuka",
+ "kanan",
+ "kashiwara",
+ "katano",
+ "kawachinagano",
+ "kishiwada",
+ "kita",
+ "kumatori",
+ "matsubara",
+ "minato",
+ "minoh",
+ "misaki",
+ "moriguchi",
+ "neyagawa",
+ "nishi",
+ "nose",
+ "osakasayama",
+ "sakai",
+ "sayama",
+ "sennan",
+ "settsu",
+ "shijonawate",
+ "shimamoto",
+ "suita",
+ "tadaoka",
+ "taishi",
+ "tajiri",
+ "takaishi",
+ "takatsuki",
+ "tondabayashi",
+ "toyonaka",
+ "toyono",
+ "yao",
+ "ariake",
+ "arita",
+ "fukudomi",
+ "genkai",
+ "hamatama",
+ "hizen",
+ "imari",
+ "kamimine",
+ "kanzaki",
+ "karatsu",
+ "kashima",
+ "kitagata",
+ "kitahata",
+ "kiyama",
+ "kouhoku",
+ "kyuragi",
+ "nishiarita",
+ "ogi",
+ "omachi",
+ "ouchi",
+ "saga",
+ "shiroishi",
+ "taku",
+ "tara",
+ "tosu",
+ "yoshinogari",
+ "arakawa",
+ "asaka",
+ "chichibu",
+ "fujimi",
+ "fujimino",
+ "fukaya",
+ "hanno",
+ "hanyu",
+ "hasuda",
+ "hatogaya",
+ "hatoyama",
+ "hidaka",
+ "higashichichibu",
+ "higashimatsuyama",
+ "honjo",
+ "ina",
+ "iruma",
+ "iwatsuki",
+ "kamiizumi",
+ "kamikawa",
+ "kamisato",
+ "kasukabe",
+ "kawagoe",
+ "kawaguchi",
+ "kawajima",
+ "kazo",
+ "kitamoto",
+ "koshigaya",
+ "kounosu",
+ "kuki",
+ "kumagaya",
+ "matsubushi",
+ "minano",
+ "misato",
+ "miyashiro",
+ "miyoshi",
+ "moroyama",
+ "nagatoro",
+ "namegawa",
+ "niiza",
+ "ogano",
+ "ogawa",
+ "ogose",
+ "okegawa",
+ "omiya",
+ "otaki",
+ "ranzan",
+ "ryokami",
+ "saitama",
+ "sakado",
+ "satte",
+ "sayama",
+ "shiki",
+ "shiraoka",
+ "soka",
+ "sugito",
+ "toda",
+ "tokigawa",
+ "tokorozawa",
+ "tsurugashima",
+ "urawa",
+ "warabi",
+ "yashio",
+ "yokoze",
+ "yono",
+ "yorii",
+ "yoshida",
+ "yoshikawa",
+ "yoshimi",
+ "city",
+ "city",
+ "aisho",
+ "gamo",
+ "higashiomi",
+ "hikone",
+ "koka",
+ "konan",
+ "kosei",
+ "koto",
+ "kusatsu",
+ "maibara",
+ "moriyama",
+ "nagahama",
+ "nishiazai",
+ "notogawa",
+ "omihachiman",
+ "otsu",
+ "ritto",
+ "ryuoh",
+ "takashima",
+ "takatsuki",
+ "torahime",
+ "toyosato",
+ "yasu",
+ "akagi",
+ "ama",
+ "gotsu",
+ "hamada",
+ "higashiizumo",
+ "hikawa",
+ "hikimi",
+ "izumo",
+ "kakinoki",
+ "masuda",
+ "matsue",
+ "misato",
+ "nishinoshima",
+ "ohda",
+ "okinoshima",
+ "okuizumo",
+ "shimane",
+ "tamayu",
+ "tsuwano",
+ "unnan",
+ "yakumo",
+ "yasugi",
+ "yatsuka",
+ "arai",
+ "atami",
+ "fuji",
+ "fujieda",
+ "fujikawa",
+ "fujinomiya",
+ "fukuroi",
+ "gotemba",
+ "haibara",
+ "hamamatsu",
+ "higashiizu",
+ "ito",
+ "iwata",
+ "izu",
+ "izunokuni",
+ "kakegawa",
+ "kannami",
+ "kawanehon",
+ "kawazu",
+ "kikugawa",
+ "kosai",
+ "makinohara",
+ "matsuzaki",
+ "minamiizu",
+ "mishima",
+ "morimachi",
+ "nishiizu",
+ "numazu",
+ "omaezaki",
+ "shimada",
+ "shimizu",
+ "shimoda",
+ "shizuoka",
+ "susono",
+ "yaizu",
+ "yoshida",
+ "ashikaga",
+ "bato",
+ "haga",
+ "ichikai",
+ "iwafune",
+ "kaminokawa",
+ "kanuma",
+ "karasuyama",
+ "kuroiso",
+ "mashiko",
+ "mibu",
+ "moka",
+ "motegi",
+ "nasu",
+ "nasushiobara",
+ "nikko",
+ "nishikata",
+ "nogi",
+ "ohira",
+ "ohtawara",
+ "oyama",
+ "sakura",
+ "sano",
+ "shimotsuke",
+ "shioya",
+ "takanezawa",
+ "tochigi",
+ "tsuga",
+ "ujiie",
+ "utsunomiya",
+ "yaita",
+ "aizumi",
+ "anan",
+ "ichiba",
+ "itano",
+ "kainan",
+ "komatsushima",
+ "matsushige",
+ "mima",
+ "minami",
+ "miyoshi",
+ "mugi",
+ "nakagawa",
+ "naruto",
+ "sanagochi",
+ "shishikui",
+ "tokushima",
+ "wajiki",
+ "adachi",
+ "akiruno",
+ "akishima",
+ "aogashima",
+ "arakawa",
+ "bunkyo",
+ "chiyoda",
+ "chofu",
+ "chuo",
+ "edogawa",
+ "fuchu",
+ "fussa",
+ "hachijo",
+ "hachioji",
+ "hamura",
+ "higashikurume",
+ "higashimurayama",
+ "higashiyamato",
+ "hino",
+ "hinode",
+ "hinohara",
+ "inagi",
+ "itabashi",
+ "katsushika",
+ "kita",
+ "kiyose",
+ "kodaira",
+ "koganei",
+ "kokubunji",
+ "komae",
+ "koto",
+ "kouzushima",
+ "kunitachi",
+ "machida",
+ "meguro",
+ "minato",
+ "mitaka",
+ "mizuho",
+ "musashimurayama",
+ "musashino",
+ "nakano",
+ "nerima",
+ "ogasawara",
+ "okutama",
+ "ome",
+ "oshima",
+ "ota",
+ "setagaya",
+ "shibuya",
+ "shinagawa",
+ "shinjuku",
+ "suginami",
+ "sumida",
+ "tachikawa",
+ "taito",
+ "tama",
+ "toshima",
+ "chizu",
+ "hino",
+ "kawahara",
+ "koge",
+ "kotoura",
+ "misasa",
+ "nanbu",
+ "nichinan",
+ "sakaiminato",
+ "tottori",
+ "wakasa",
+ "yazu",
+ "yonago",
+ "asahi",
+ "fuchu",
+ "fukumitsu",
+ "funahashi",
+ "himi",
+ "imizu",
+ "inami",
+ "johana",
+ "kamiichi",
+ "kurobe",
+ "nakaniikawa",
+ "namerikawa",
+ "nanto",
+ "nyuzen",
+ "oyabe",
+ "taira",
+ "takaoka",
+ "tateyama",
+ "toga",
+ "tonami",
+ "toyama",
+ "unazuki",
+ "uozu",
+ "yamada",
+ "arida",
+ "aridagawa",
+ "gobo",
+ "hashimoto",
+ "hidaka",
+ "hirogawa",
+ "inami",
+ "iwade",
+ "kainan",
+ "kamitonda",
+ "katsuragi",
+ "kimino",
+ "kinokawa",
+ "kitayama",
+ "koya",
+ "koza",
+ "kozagawa",
+ "kudoyama",
+ "kushimoto",
+ "mihama",
+ "misato",
+ "nachikatsuura",
+ "shingu",
+ "shirahama",
+ "taiji",
+ "tanabe",
+ "wakayama",
+ "yuasa",
+ "yura",
+ "asahi",
+ "funagata",
+ "higashine",
+ "iide",
+ "kahoku",
+ "kaminoyama",
+ "kaneyama",
+ "kawanishi",
+ "mamurogawa",
+ "mikawa",
+ "murayama",
+ "nagai",
+ "nakayama",
+ "nanyo",
+ "nishikawa",
+ "obanazawa",
+ "oe",
+ "oguni",
+ "ohkura",
+ "oishida",
+ "sagae",
+ "sakata",
+ "sakegawa",
+ "shinjo",
+ "shirataka",
+ "shonai",
+ "takahata",
+ "tendo",
+ "tozawa",
+ "tsuruoka",
+ "yamagata",
+ "yamanobe",
+ "yonezawa",
+ "yuza",
+ "abu",
+ "hagi",
+ "hikari",
+ "hofu",
+ "iwakuni",
+ "kudamatsu",
+ "mitou",
+ "nagato",
+ "oshima",
+ "shimonoseki",
+ "shunan",
+ "tabuse",
+ "tokuyama",
+ "toyota",
+ "ube",
+ "yuu",
+ "chuo",
+ "doshi",
+ "fuefuki",
+ "fujikawa",
+ "fujikawaguchiko",
+ "fujiyoshida",
+ "hayakawa",
+ "hokuto",
+ "ichikawamisato",
+ "kai",
+ "kofu",
+ "koshu",
+ "kosuge",
+ "minami-alps",
+ "minobu",
+ "nakamichi",
+ "nanbu",
+ "narusawa",
+ "nirasaki",
+ "nishikatsura",
+ "oshino",
+ "otsuki",
+ "showa",
+ "tabayama",
+ "tsuru",
+ "uenohara",
+ "yamanakako",
+ "yamanashi",
+ "city",
+ "co",
+ "blogspot",
+ "com",
+ "edu",
+ "gov",
+ "mil",
+ "net",
+ "org",
+ "biz",
+ "com",
+ "edu",
+ "gov",
+ "info",
+ "net",
+ "org",
+ "ass",
+ "asso",
+ "com",
+ "coop",
+ "edu",
+ "gouv",
+ "gov",
+ "medecin",
+ "mil",
+ "nom",
+ "notaires",
+ "org",
+ "pharmaciens",
+ "prd",
+ "presse",
+ "tm",
+ "veterinaire",
+ "edu",
+ "gov",
+ "net",
+ "org",
+ "com",
+ "edu",
+ "gov",
+ "org",
+ "rep",
+ "tra",
+ "ac",
+ "blogspot",
+ "busan",
+ "chungbuk",
+ "chungnam",
+ "co",
+ "daegu",
+ "daejeon",
+ "es",
+ "gangwon",
+ "go",
+ "gwangju",
+ "gyeongbuk",
+ "gyeonggi",
+ "gyeongnam",
+ "hs",
+ "incheon",
+ "jeju",
+ "jeonbuk",
+ "jeonnam",
+ "kg",
+ "mil",
+ "ms",
+ "ne",
+ "or",
+ "pe",
+ "re",
+ "sc",
+ "seoul",
+ "ulsan",
+ "co",
+ "edu",
+ "com",
+ "edu",
+ "gov",
+ "net",
+ "org",
+ "com",
+ "edu",
+ "gov",
+ "mil",
+ "net",
+ "nym",
+ "org",
+ "bnr",
+ "c",
+ "com",
+ "edu",
+ "gov",
+ "info",
+ "int",
+ "net",
+ "nym",
+ "org",
+ "per",
+ "static",
+ "dev",
+ "sites",
+ "com",
+ "edu",
+ "gov",
+ "net",
+ "org",
+ "co",
+ "com",
+ "edu",
+ "gov",
+ "net",
+ "org",
+ "oy",
+ "blogspot",
+ "nom",
+ "nym",
+ "cyon",
+ "mypep",
+ "ac",
+ "assn",
+ "com",
+ "edu",
+ "gov",
+ "grp",
+ "hotel",
+ "int",
+ "ltd",
+ "net",
+ "ngo",
+ "org",
+ "sch",
+ "soc",
+ "web",
+ "com",
+ "edu",
+ "gov",
+ "net",
+ "org",
+ "co",
+ "org",
+ "blogspot",
+ "gov",
+ "nym",
+ "blogspot",
+ "nym",
+ "asn",
+ "com",
+ "conf",
+ "edu",
+ "gov",
+ "id",
+ "mil",
+ "net",
+ "org",
+ "com",
+ "edu",
+ "gov",
+ "id",
+ "med",
+ "net",
+ "org",
+ "plc",
+ "sch",
+ "ac",
+ "co",
+ "gov",
+ "net",
+ "org",
+ "press",
+ "router",
+ "asso",
+ "tm",
+ "blogspot",
+ "ac",
+ "brasilia",
+ "c66",
+ "co",
+ "daplie",
+ "ddns",
+ "diskstation",
+ "dnsfor",
+ "dscloud",
+ "edu",
+ "filegear",
+ "gov",
+ "hopto",
+ "i234",
+ "its",
+ "loginto",
+ "myds",
+ "net",
+ "noip",
+ "nym",
+ "org",
+ "priv",
+ "synology",
+ "webhop",
+ "wedeploy",
+ "yombo",
+ "localhost",
+ "co",
+ "com",
+ "edu",
+ "gov",
+ "mil",
+ "nom",
+ "org",
+ "prd",
+ "tm",
+ "blogspot",
+ "com",
+ "edu",
+ "gov",
+ "inf",
+ "name",
+ "net",
+ "nom",
+ "org",
+ "com",
+ "edu",
+ "gouv",
+ "gov",
+ "net",
+ "org",
+ "presse",
+ "edu",
+ "gov",
+ "nyc",
+ "org",
+ "com",
+ "edu",
+ "gov",
+ "net",
+ "org",
+ "dscloud",
+ "blogspot",
+ "gov",
+ "com",
+ "edu",
+ "gov",
+ "net",
+ "org",
+ "com",
+ "edu",
+ "net",
+ "org",
+ "blogspot",
+ "ac",
+ "co",
+ "com",
+ "gov",
+ "net",
+ "or",
+ "org",
+ "academy",
+ "agriculture",
+ "air",
+ "airguard",
+ "alabama",
+ "alaska",
+ "amber",
+ "ambulance",
+ "american",
+ "americana",
+ "americanantiques",
+ "americanart",
+ "amsterdam",
+ "and",
+ "annefrank",
+ "anthro",
+ "anthropology",
+ "antiques",
+ "aquarium",
+ "arboretum",
+ "archaeological",
+ "archaeology",
+ "architecture",
+ "art",
+ "artanddesign",
+ "artcenter",
+ "artdeco",
+ "arteducation",
+ "artgallery",
+ "arts",
+ "artsandcrafts",
+ "asmatart",
+ "assassination",
+ "assisi",
+ "association",
+ "astronomy",
+ "atlanta",
+ "austin",
+ "australia",
+ "automotive",
+ "aviation",
+ "axis",
+ "badajoz",
+ "baghdad",
+ "bahn",
+ "bale",
+ "baltimore",
+ "barcelona",
+ "baseball",
+ "basel",
+ "baths",
+ "bauern",
+ "beauxarts",
+ "beeldengeluid",
+ "bellevue",
+ "bergbau",
+ "berkeley",
+ "berlin",
+ "bern",
+ "bible",
+ "bilbao",
+ "bill",
+ "birdart",
+ "birthplace",
+ "bonn",
+ "boston",
+ "botanical",
+ "botanicalgarden",
+ "botanicgarden",
+ "botany",
+ "brandywinevalley",
+ "brasil",
+ "bristol",
+ "british",
+ "britishcolumbia",
+ "broadcast",
+ "brunel",
+ "brussel",
+ "brussels",
+ "bruxelles",
+ "building",
+ "burghof",
+ "bus",
+ "bushey",
+ "cadaques",
+ "california",
+ "cambridge",
+ "can",
+ "canada",
+ "capebreton",
+ "carrier",
+ "cartoonart",
+ "casadelamoneda",
+ "castle",
+ "castres",
+ "celtic",
+ "center",
+ "chattanooga",
+ "cheltenham",
+ "chesapeakebay",
+ "chicago",
+ "children",
+ "childrens",
+ "childrensgarden",
+ "chiropractic",
+ "chocolate",
+ "christiansburg",
+ "cincinnati",
+ "cinema",
+ "circus",
+ "civilisation",
+ "civilization",
+ "civilwar",
+ "clinton",
+ "clock",
+ "coal",
+ "coastaldefence",
+ "cody",
+ "coldwar",
+ "collection",
+ "colonialwilliamsburg",
+ "coloradoplateau",
+ "columbia",
+ "columbus",
+ "communication",
+ "communications",
+ "community",
+ "computer",
+ "computerhistory",
+ "contemporary",
+ "contemporaryart",
+ "convent",
+ "copenhagen",
+ "corporation",
+ "corvette",
+ "costume",
+ "countryestate",
+ "county",
+ "crafts",
+ "cranbrook",
+ "creation",
+ "cultural",
+ "culturalcenter",
+ "culture",
+ "cyber",
+ "cymru",
+ "dali",
+ "dallas",
+ "database",
+ "ddr",
+ "decorativearts",
+ "delaware",
+ "delmenhorst",
+ "denmark",
+ "depot",
+ "design",
+ "detroit",
+ "dinosaur",
+ "discovery",
+ "dolls",
+ "donostia",
+ "durham",
+ "eastafrica",
+ "eastcoast",
+ "education",
+ "educational",
+ "egyptian",
+ "eisenbahn",
+ "elburg",
+ "elvendrell",
+ "embroidery",
+ "encyclopedic",
+ "england",
+ "entomology",
+ "environment",
+ "environmentalconservation",
+ "epilepsy",
+ "essex",
+ "estate",
+ "ethnology",
+ "exeter",
+ "exhibition",
+ "family",
+ "farm",
+ "farmequipment",
+ "farmers",
+ "farmstead",
+ "field",
+ "figueres",
+ "filatelia",
+ "film",
+ "fineart",
+ "finearts",
+ "finland",
+ "flanders",
+ "florida",
+ "force",
+ "fortmissoula",
+ "fortworth",
+ "foundation",
+ "francaise",
+ "frankfurt",
+ "franziskaner",
+ "freemasonry",
+ "freiburg",
+ "fribourg",
+ "frog",
+ "fundacio",
+ "furniture",
+ "gallery",
+ "garden",
+ "gateway",
+ "geelvinck",
+ "gemological",
+ "geology",
+ "georgia",
+ "giessen",
+ "glas",
+ "glass",
+ "gorge",
+ "grandrapids",
+ "graz",
+ "guernsey",
+ "halloffame",
+ "hamburg",
+ "handson",
+ "harvestcelebration",
+ "hawaii",
+ "health",
+ "heimatunduhren",
+ "hellas",
+ "helsinki",
+ "hembygdsforbund",
+ "heritage",
+ "histoire",
+ "historical",
+ "historicalsociety",
+ "historichouses",
+ "historisch",
+ "historisches",
+ "history",
+ "historyofscience",
+ "horology",
+ "house",
+ "humanities",
+ "illustration",
+ "imageandsound",
+ "indian",
+ "indiana",
+ "indianapolis",
+ "indianmarket",
+ "intelligence",
+ "interactive",
+ "iraq",
+ "iron",
+ "isleofman",
+ "jamison",
+ "jefferson",
+ "jerusalem",
+ "jewelry",
+ "jewish",
+ "jewishart",
+ "jfk",
+ "journalism",
+ "judaica",
+ "judygarland",
+ "juedisches",
+ "juif",
+ "karate",
+ "karikatur",
+ "kids",
+ "koebenhavn",
+ "koeln",
+ "kunst",
+ "kunstsammlung",
+ "kunstunddesign",
+ "labor",
+ "labour",
+ "lajolla",
+ "lancashire",
+ "landes",
+ "lans",
+ "larsson",
+ "lewismiller",
+ "lincoln",
+ "linz",
+ "living",
+ "livinghistory",
+ "localhistory",
+ "london",
+ "losangeles",
+ "louvre",
+ "loyalist",
+ "lucerne",
+ "luxembourg",
+ "luzern",
+ "mad",
+ "madrid",
+ "mallorca",
+ "manchester",
+ "mansion",
+ "mansions",
+ "manx",
+ "marburg",
+ "maritime",
+ "maritimo",
+ "maryland",
+ "marylhurst",
+ "media",
+ "medical",
+ "medizinhistorisches",
+ "meeres",
+ "memorial",
+ "mesaverde",
+ "michigan",
+ "midatlantic",
+ "military",
+ "mill",
+ "miners",
+ "mining",
+ "minnesota",
+ "missile",
+ "missoula",
+ "modern",
+ "moma",
+ "money",
+ "monmouth",
+ "monticello",
+ "montreal",
+ "moscow",
+ "motorcycle",
+ "muenchen",
+ "muenster",
+ "mulhouse",
+ "muncie",
+ "museet",
+ "museumcenter",
+ "museumvereniging",
+ "music",
+ "national",
+ "nationalfirearms",
+ "nationalheritage",
+ "nativeamerican",
+ "naturalhistory",
+ "naturalhistorymuseum",
+ "naturalsciences",
+ "nature",
+ "naturhistorisches",
+ "natuurwetenschappen",
+ "naumburg",
+ "naval",
+ "nebraska",
+ "neues",
+ "newhampshire",
+ "newjersey",
+ "newmexico",
+ "newport",
+ "newspaper",
+ "newyork",
+ "niepce",
+ "norfolk",
+ "north",
+ "nrw",
+ "nuernberg",
+ "nuremberg",
+ "nyc",
+ "nyny",
+ "oceanographic",
+ "oceanographique",
+ "omaha",
+ "online",
+ "ontario",
+ "openair",
+ "oregon",
+ "oregontrail",
+ "otago",
+ "oxford",
+ "pacific",
+ "paderborn",
+ "palace",
+ "paleo",
+ "palmsprings",
+ "panama",
+ "paris",
+ "pasadena",
+ "pharmacy",
+ "philadelphia",
+ "philadelphiaarea",
+ "philately",
+ "phoenix",
+ "photography",
+ "pilots",
+ "pittsburgh",
+ "planetarium",
+ "plantation",
+ "plants",
+ "plaza",
+ "portal",
+ "portland",
+ "portlligat",
+ "posts-and-telecommunications",
+ "preservation",
+ "presidio",
+ "press",
+ "project",
+ "public",
+ "pubol",
+ "quebec",
+ "railroad",
+ "railway",
+ "research",
+ "resistance",
+ "riodejaneiro",
+ "rochester",
+ "rockart",
+ "roma",
+ "russia",
+ "saintlouis",
+ "salem",
+ "salvadordali",
+ "salzburg",
+ "sandiego",
+ "sanfrancisco",
+ "santabarbara",
+ "santacruz",
+ "santafe",
+ "saskatchewan",
+ "satx",
+ "savannahga",
+ "schlesisches",
+ "schoenbrunn",
+ "schokoladen",
+ "school",
+ "schweiz",
+ "science",
+ "science-fiction",
+ "scienceandhistory",
+ "scienceandindustry",
+ "sciencecenter",
+ "sciencecenters",
+ "sciencehistory",
+ "sciences",
+ "sciencesnaturelles",
+ "scotland",
+ "seaport",
+ "settlement",
+ "settlers",
+ "shell",
+ "sherbrooke",
+ "sibenik",
+ "silk",
+ "ski",
+ "skole",
+ "society",
+ "sologne",
+ "soundandvision",
+ "southcarolina",
+ "southwest",
+ "space",
+ "spy",
+ "square",
+ "stadt",
+ "stalbans",
+ "starnberg",
+ "state",
+ "stateofdelaware",
+ "station",
+ "steam",
+ "steiermark",
+ "stjohn",
+ "stockholm",
+ "stpetersburg",
+ "stuttgart",
+ "suisse",
+ "surgeonshall",
+ "surrey",
+ "svizzera",
+ "sweden",
+ "sydney",
+ "tank",
+ "tcm",
+ "technology",
+ "telekommunikation",
+ "television",
+ "texas",
+ "textile",
+ "theater",
+ "time",
+ "timekeeping",
+ "topology",
+ "torino",
+ "touch",
+ "town",
+ "transport",
+ "tree",
+ "trolley",
+ "trust",
+ "trustee",
+ "uhren",
+ "ulm",
+ "undersea",
+ "university",
+ "usa",
+ "usantiques",
+ "usarts",
+ "uscountryestate",
+ "usculture",
+ "usdecorativearts",
+ "usgarden",
+ "ushistory",
+ "ushuaia",
+ "uslivinghistory",
+ "utah",
+ "uvic",
+ "valley",
+ "vantaa",
+ "versailles",
+ "viking",
+ "village",
+ "virginia",
+ "virtual",
+ "virtuel",
+ "vlaanderen",
+ "volkenkunde",
+ "wales",
+ "wallonie",
+ "war",
+ "washingtondc",
+ "watch-and-clock",
+ "watchandclock",
+ "western",
+ "westfalen",
+ "whaling",
+ "wildlife",
+ "williamsburg",
+ "windmill",
+ "workshop",
+ "xn--9dbhblg6di",
+ "xn--comunicaes-v6a2o",
+ "xn--correios-e-telecomunicaes-ghc29a",
+ "xn--h1aegh",
+ "xn--lns-qla",
+ "york",
+ "yorkshire",
+ "yosemite",
+ "youth",
+ "zoological",
+ "zoology",
+ "aero",
+ "biz",
+ "com",
+ "coop",
+ "edu",
+ "gov",
+ "info",
+ "int",
+ "mil",
+ "museum",
+ "name",
+ "net",
+ "org",
+ "pro",
+ "ac",
+ "biz",
+ "co",
+ "com",
+ "coop",
+ "edu",
+ "gov",
+ "int",
+ "museum",
+ "net",
+ "org",
+ "blogspot",
+ "com",
+ "edu",
+ "gob",
+ "net",
+ "nym",
+ "org",
+ "blogspot",
+ "com",
+ "edu",
+ "gov",
+ "mil",
+ "name",
+ "net",
+ "org",
+ "ac",
+ "adv",
+ "co",
+ "edu",
+ "gov",
+ "mil",
+ "net",
+ "org",
+ "ca",
+ "cc",
+ "co",
+ "com",
+ "dr",
+ "in",
+ "info",
+ "mobi",
+ "mx",
+ "name",
+ "or",
+ "org",
+ "pro",
+ "school",
+ "tv",
+ "us",
+ "ws",
+ "her",
+ "his",
+ "forgot",
+ "forgot",
+ "asso",
+ "nom",
+ "alwaysdata",
+ "at-band-camp",
+ "azure-mobile",
+ "azurewebsites",
+ "barsy",
+ "blogdns",
+ "boomla",
+ "bounceme",
+ "bplaced",
+ "broke-it",
+ "buyshouses",
+ "casacam",
+ "cdn77",
+ "cdn77-ssl",
+ "channelsdvr",
+ "cloudaccess",
+ "cloudapp",
+ "cloudfront",
+ "cloudfunctions",
+ "cryptonomic",
+ "ddns",
+ "debian",
+ "definima",
+ "dnsalias",
+ "dnsdojo",
+ "does-it",
+ "dontexist",
+ "dsmynas",
+ "dynalias",
+ "dynathome",
+ "dynu",
+ "dynv6",
+ "eating-organic",
+ "endofinternet",
+ "familyds",
+ "fastly",
+ "fastlylb",
+ "feste-ip",
+ "firewall-gateway",
+ "flynnhosting",
+ "from-az",
+ "from-co",
+ "from-la",
+ "from-ny",
+ "gb",
+ "gets-it",
+ "ham-radio-op",
+ "homeftp",
+ "homeip",
+ "homelinux",
+ "homeunix",
+ "hu",
+ "in",
+ "in-the-band",
+ "ipifony",
+ "is-a-chef",
+ "is-a-geek",
+ "isa-geek",
+ "jp",
+ "kicks-ass",
+ "knx-server",
+ "moonscale",
+ "mydissent",
+ "myeffect",
+ "myfritz",
+ "mymediapc",
+ "mypsx",
+ "mysecuritycamera",
+ "nhlfan",
+ "no-ip",
+ "office-on-the",
+ "pgafan",
+ "podzone",
+ "privatizehealthinsurance",
+ "rackmaze",
+ "redirectme",
+ "ru",
+ "scrapper-site",
+ "se",
+ "selfip",
+ "sells-it",
+ "servebbs",
+ "serveblog",
+ "serveftp",
+ "serveminecraft",
+ "square7",
+ "static-access",
+ "sytes",
+ "t3l3p0rt",
+ "thruhere",
+ "twmail",
+ "uk",
+ "webhop",
+ "za",
+ "r",
+ "freetls",
+ "map",
+ "prod",
+ "ssl",
+ "a",
+ "global",
+ "a",
+ "b",
+ "global",
+ "map",
+ "alces",
+ "arts",
+ "com",
+ "firm",
+ "info",
+ "net",
+ "other",
+ "per",
+ "rec",
+ "store",
+ "web",
+ "com",
+ "edu",
+ "gov",
+ "i",
+ "mil",
+ "mobi",
+ "name",
+ "net",
+ "org",
+ "sch",
+ "blogspot",
+ "ac",
+ "biz",
+ "co",
+ "com",
+ "edu",
+ "gob",
+ "in",
+ "info",
+ "int",
+ "mil",
+ "net",
+ "nom",
+ "org",
+ "web",
+ "blogspot",
+ "bv",
+ "cistron",
+ "co",
+ "demon",
+ "transurl",
+ "virtueeldomein",
+ "aa",
+ "aarborte",
+ "aejrie",
+ "afjord",
+ "agdenes",
+ "ah",
+ "akershus",
+ "aknoluokta",
+ "akrehamn",
+ "al",
+ "alaheadju",
+ "alesund",
+ "algard",
+ "alstahaug",
+ "alta",
+ "alvdal",
+ "amli",
+ "amot",
+ "andasuolo",
+ "andebu",
+ "andoy",
+ "ardal",
+ "aremark",
+ "arendal",
+ "arna",
+ "aseral",
+ "asker",
+ "askim",
+ "askoy",
+ "askvoll",
+ "asnes",
+ "audnedaln",
+ "aukra",
+ "aure",
+ "aurland",
+ "aurskog-holand",
+ "austevoll",
+ "austrheim",
+ "averoy",
+ "badaddja",
+ "bahcavuotna",
+ "bahccavuotna",
+ "baidar",
+ "bajddar",
+ "balat",
+ "balestrand",
+ "ballangen",
+ "balsfjord",
+ "bamble",
+ "bardu",
+ "barum",
+ "batsfjord",
+ "bearalvahki",
+ "beardu",
+ "beiarn",
+ "berg",
+ "bergen",
+ "berlevag",
+ "bievat",
+ "bindal",
+ "birkenes",
+ "bjarkoy",
+ "bjerkreim",
+ "bjugn",
+ "blogspot",
+ "bodo",
+ "bokn",
+ "bomlo",
+ "bremanger",
+ "bronnoy",
+ "bronnoysund",
+ "brumunddal",
+ "bryne",
+ "bu",
+ "budejju",
+ "buskerud",
+ "bygland",
+ "bykle",
+ "cahcesuolo",
+ "co",
+ "davvenjarga",
+ "davvesiida",
+ "deatnu",
+ "dep",
+ "dielddanuorri",
+ "divtasvuodna",
+ "divttasvuotna",
+ "donna",
+ "dovre",
+ "drammen",
+ "drangedal",
+ "drobak",
+ "dyroy",
+ "egersund",
+ "eid",
+ "eidfjord",
+ "eidsberg",
+ "eidskog",
+ "eidsvoll",
+ "eigersund",
+ "elverum",
+ "enebakk",
+ "engerdal",
+ "etne",
+ "etnedal",
+ "evenassi",
+ "evenes",
+ "evje-og-hornnes",
+ "farsund",
+ "fauske",
+ "fedje",
+ "fet",
+ "fetsund",
+ "fhs",
+ "finnoy",
+ "fitjar",
+ "fjaler",
+ "fjell",
+ "fla",
+ "flakstad",
+ "flatanger",
+ "flekkefjord",
+ "flesberg",
+ "flora",
+ "floro",
+ "fm",
+ "folkebibl",
+ "folldal",
+ "forde",
+ "forsand",
+ "fosnes",
+ "frana",
+ "fredrikstad",
+ "frei",
+ "frogn",
+ "froland",
+ "frosta",
+ "froya",
+ "fuoisku",
+ "fuossko",
+ "fusa",
+ "fylkesbibl",
+ "fyresdal",
+ "gaivuotna",
+ "galsa",
+ "gamvik",
+ "gangaviika",
+ "gaular",
+ "gausdal",
+ "giehtavuoatna",
+ "gildeskal",
+ "giske",
+ "gjemnes",
+ "gjerdrum",
+ "gjerstad",
+ "gjesdal",
+ "gjovik",
+ "gloppen",
+ "gol",
+ "gran",
+ "grane",
+ "granvin",
+ "gratangen",
+ "grimstad",
+ "grong",
+ "grue",
+ "gulen",
+ "guovdageaidnu",
+ "ha",
+ "habmer",
+ "hadsel",
+ "hagebostad",
+ "halden",
+ "halsa",
+ "hamar",
+ "hamaroy",
+ "hammarfeasta",
+ "hammerfest",
+ "hapmir",
+ "haram",
+ "hareid",
+ "harstad",
+ "hasvik",
+ "hattfjelldal",
+ "haugesund",
+ "hedmark",
+ "hemne",
+ "hemnes",
+ "hemsedal",
+ "herad",
+ "hitra",
+ "hjartdal",
+ "hjelmeland",
+ "hl",
+ "hm",
+ "hobol",
+ "hof",
+ "hokksund",
+ "hol",
+ "hole",
+ "holmestrand",
+ "holtalen",
+ "honefoss",
+ "hordaland",
+ "hornindal",
+ "horten",
+ "hoyanger",
+ "hoylandet",
+ "hurdal",
+ "hurum",
+ "hvaler",
+ "hyllestad",
+ "ibestad",
+ "idrett",
+ "inderoy",
+ "iveland",
+ "ivgu",
+ "jan-mayen",
+ "jessheim",
+ "jevnaker",
+ "jolster",
+ "jondal",
+ "jorpeland",
+ "kafjord",
+ "karasjohka",
+ "karasjok",
+ "karlsoy",
+ "karmoy",
+ "kautokeino",
+ "kirkenes",
+ "klabu",
+ "klepp",
+ "kommune",
+ "kongsberg",
+ "kongsvinger",
+ "kopervik",
+ "kraanghke",
+ "kragero",
+ "kristiansand",
+ "kristiansund",
+ "krodsherad",
+ "krokstadelva",
+ "kvafjord",
+ "kvalsund",
+ "kvam",
+ "kvanangen",
+ "kvinesdal",
+ "kvinnherad",
+ "kviteseid",
+ "kvitsoy",
+ "laakesvuemie",
+ "lahppi",
+ "langevag",
+ "lardal",
+ "larvik",
+ "lavagis",
+ "lavangen",
+ "leangaviika",
+ "lebesby",
+ "leikanger",
+ "leirfjord",
+ "leirvik",
+ "leka",
+ "leksvik",
+ "lenvik",
+ "lerdal",
+ "lesja",
+ "levanger",
+ "lier",
+ "lierne",
+ "lillehammer",
+ "lillesand",
+ "lindas",
+ "lindesnes",
+ "loabat",
+ "lodingen",
+ "lom",
+ "loppa",
+ "lorenskog",
+ "loten",
+ "lund",
+ "lunner",
+ "luroy",
+ "luster",
+ "lyngdal",
+ "lyngen",
+ "malatvuopmi",
+ "malselv",
+ "malvik",
+ "mandal",
+ "marker",
+ "marnardal",
+ "masfjorden",
+ "masoy",
+ "matta-varjjat",
+ "meland",
+ "meldal",
+ "melhus",
+ "meloy",
+ "meraker",
+ "midsund",
+ "midtre-gauldal",
+ "mil",
+ "mjondalen",
+ "mo-i-rana",
+ "moareke",
+ "modalen",
+ "modum",
+ "molde",
+ "more-og-romsdal",
+ "mosjoen",
+ "moskenes",
+ "moss",
+ "mosvik",
+ "mr",
+ "muosat",
+ "museum",
+ "naamesjevuemie",
+ "namdalseid",
+ "namsos",
+ "namsskogan",
+ "nannestad",
+ "naroy",
+ "narviika",
+ "narvik",
+ "naustdal",
+ "navuotna",
+ "nedre-eiker",
+ "nesna",
+ "nesodden",
+ "nesoddtangen",
+ "nesseby",
+ "nesset",
+ "nissedal",
+ "nittedal",
+ "nl",
+ "nord-aurdal",
+ "nord-fron",
+ "nord-odal",
+ "norddal",
+ "nordkapp",
+ "nordland",
+ "nordre-land",
+ "nordreisa",
+ "nore-og-uvdal",
+ "notodden",
+ "notteroy",
+ "nt",
+ "odda",
+ "of",
+ "oksnes",
+ "ol",
+ "omasvuotna",
+ "oppdal",
+ "oppegard",
+ "orkanger",
+ "orkdal",
+ "orland",
+ "orskog",
+ "orsta",
+ "osen",
+ "oslo",
+ "osoyro",
+ "osteroy",
+ "ostfold",
+ "ostre-toten",
+ "overhalla",
+ "ovre-eiker",
+ "oyer",
+ "oygarden",
+ "oystre-slidre",
+ "porsanger",
+ "porsangu",
+ "porsgrunn",
+ "priv",
+ "rade",
+ "radoy",
+ "rahkkeravju",
+ "raholt",
+ "raisa",
+ "rakkestad",
+ "ralingen",
+ "rana",
+ "randaberg",
+ "rauma",
+ "rendalen",
+ "rennebu",
+ "rennesoy",
+ "rindal",
+ "ringebu",
+ "ringerike",
+ "ringsaker",
+ "risor",
+ "rissa",
+ "rl",
+ "roan",
+ "rodoy",
+ "rollag",
+ "romsa",
+ "romskog",
+ "roros",
+ "rost",
+ "royken",
+ "royrvik",
+ "ruovat",
+ "rygge",
+ "salangen",
+ "salat",
+ "saltdal",
+ "samnanger",
+ "sandefjord",
+ "sandnes",
+ "sandnessjoen",
+ "sandoy",
+ "sarpsborg",
+ "sauda",
+ "sauherad",
+ "sel",
+ "selbu",
+ "selje",
+ "seljord",
+ "sf",
+ "siellak",
+ "sigdal",
+ "siljan",
+ "sirdal",
+ "skanit",
+ "skanland",
+ "skaun",
+ "skedsmo",
+ "skedsmokorset",
+ "ski",
+ "skien",
+ "skierva",
+ "skiptvet",
+ "skjak",
+ "skjervoy",
+ "skodje",
+ "slattum",
+ "smola",
+ "snaase",
+ "snasa",
+ "snillfjord",
+ "snoasa",
+ "sogndal",
+ "sogne",
+ "sokndal",
+ "sola",
+ "solund",
+ "somna",
+ "sondre-land",
+ "songdalen",
+ "sor-aurdal",
+ "sor-fron",
+ "sor-odal",
+ "sor-varanger",
+ "sorfold",
+ "sorreisa",
+ "sortland",
+ "sorum",
+ "spjelkavik",
+ "spydeberg",
+ "st",
+ "stange",
+ "stat",
+ "stathelle",
+ "stavanger",
+ "stavern",
+ "steigen",
+ "steinkjer",
+ "stjordal",
+ "stjordalshalsen",
+ "stokke",
+ "stor-elvdal",
+ "stord",
+ "stordal",
+ "storfjord",
+ "strand",
+ "stranda",
+ "stryn",
+ "sula",
+ "suldal",
+ "sund",
+ "sunndal",
+ "surnadal",
+ "svalbard",
+ "sveio",
+ "svelvik",
+ "sykkylven",
+ "tana",
+ "tananger",
+ "telemark",
+ "time",
+ "tingvoll",
+ "tinn",
+ "tjeldsund",
+ "tjome",
+ "tm",
+ "tokke",
+ "tolga",
+ "tonsberg",
+ "torsken",
+ "tr",
+ "trana",
+ "tranby",
+ "tranoy",
+ "troandin",
+ "trogstad",
+ "tromsa",
+ "tromso",
+ "trondheim",
+ "trysil",
+ "tvedestrand",
+ "tydal",
+ "tynset",
+ "tysfjord",
+ "tysnes",
+ "tysvar",
+ "ullensaker",
+ "ullensvang",
+ "ulvik",
+ "unjarga",
+ "utsira",
+ "va",
+ "vaapste",
+ "vadso",
+ "vaga",
+ "vagan",
+ "vagsoy",
+ "vaksdal",
+ "valle",
+ "vang",
+ "vanylven",
+ "vardo",
+ "varggat",
+ "varoy",
+ "vefsn",
+ "vega",
+ "vegarshei",
+ "vennesla",
+ "verdal",
+ "verran",
+ "vestby",
+ "vestfold",
+ "vestnes",
+ "vestre-slidre",
+ "vestre-toten",
+ "vestvagoy",
+ "vevelstad",
+ "vf",
+ "vgs",
+ "vik",
+ "vikna",
+ "vindafjord",
+ "voagat",
+ "volda",
+ "voss",
+ "vossevangen",
+ "xn--andy-ira",
+ "xn--asky-ira",
+ "xn--aurskog-hland-jnb",
+ "xn--avery-yua",
+ "xn--bdddj-mrabd",
+ "xn--bearalvhki-y4a",
+ "xn--berlevg-jxa",
+ "xn--bhcavuotna-s4a",
+ "xn--bhccavuotna-k7a",
+ "xn--bidr-5nac",
+ "xn--bievt-0qa",
+ "xn--bjarky-fya",
+ "xn--bjddar-pta",
+ "xn--blt-elab",
+ "xn--bmlo-gra",
+ "xn--bod-2na",
+ "xn--brnny-wuac",
+ "xn--brnnysund-m8ac",
+ "xn--brum-voa",
+ "xn--btsfjord-9za",
+ "xn--davvenjrga-y4a",
+ "xn--dnna-gra",
+ "xn--drbak-wua",
+ "xn--dyry-ira",
+ "xn--eveni-0qa01ga",
+ "xn--finny-yua",
+ "xn--fjord-lra",
+ "xn--fl-zia",
+ "xn--flor-jra",
+ "xn--frde-gra",
+ "xn--frna-woa",
+ "xn--frya-hra",
+ "xn--ggaviika-8ya47h",
+ "xn--gildeskl-g0a",
+ "xn--givuotna-8ya",
+ "xn--gjvik-wua",
+ "xn--gls-elac",
+ "xn--h-2fa",
+ "xn--hbmer-xqa",
+ "xn--hcesuolo-7ya35b",
+ "xn--hgebostad-g3a",
+ "xn--hmmrfeasta-s4ac",
+ "xn--hnefoss-q1a",
+ "xn--hobl-ira",
+ "xn--holtlen-hxa",
+ "xn--hpmir-xqa",
+ "xn--hyanger-q1a",
+ "xn--hylandet-54a",
+ "xn--indery-fya",
+ "xn--jlster-bya",
+ "xn--jrpeland-54a",
+ "xn--karmy-yua",
+ "xn--kfjord-iua",
+ "xn--klbu-woa",
+ "xn--koluokta-7ya57h",
+ "xn--krager-gya",
+ "xn--kranghke-b0a",
+ "xn--krdsherad-m8a",
+ "xn--krehamn-dxa",
+ "xn--krjohka-hwab49j",
+ "xn--ksnes-uua",
+ "xn--kvfjord-nxa",
+ "xn--kvitsy-fya",
+ "xn--kvnangen-k0a",
+ "xn--l-1fa",
+ "xn--laheadju-7ya",
+ "xn--langevg-jxa",
+ "xn--ldingen-q1a",
+ "xn--leagaviika-52b",
+ "xn--lesund-hua",
+ "xn--lgrd-poac",
+ "xn--lhppi-xqa",
+ "xn--linds-pra",
+ "xn--loabt-0qa",
+ "xn--lrdal-sra",
+ "xn--lrenskog-54a",
+ "xn--lt-liac",
+ "xn--lten-gra",
+ "xn--lury-ira",
+ "xn--mely-ira",
+ "xn--merker-kua",
+ "xn--mjndalen-64a",
+ "xn--mlatvuopmi-s4a",
+ "xn--mli-tla",
+ "xn--mlselv-iua",
+ "xn--moreke-jua",
+ "xn--mosjen-eya",
+ "xn--mot-tla",
+ "xn--mre-og-romsdal-qqb",
+ "xn--msy-ula0h",
+ "xn--mtta-vrjjat-k7af",
+ "xn--muost-0qa",
+ "xn--nmesjevuemie-tcba",
+ "xn--nry-yla5g",
+ "xn--nttery-byae",
+ "xn--nvuotna-hwa",
+ "xn--oppegrd-ixa",
+ "xn--ostery-fya",
+ "xn--osyro-wua",
+ "xn--porsgu-sta26f",
+ "xn--rady-ira",
+ "xn--rdal-poa",
+ "xn--rde-ula",
+ "xn--rdy-0nab",
+ "xn--rennesy-v1a",
+ "xn--rhkkervju-01af",
+ "xn--rholt-mra",
+ "xn--risa-5na",
+ "xn--risr-ira",
+ "xn--rland-uua",
+ "xn--rlingen-mxa",
+ "xn--rmskog-bya",
+ "xn--rros-gra",
+ "xn--rskog-uua",
+ "xn--rst-0na",
+ "xn--rsta-fra",
+ "xn--ryken-vua",
+ "xn--ryrvik-bya",
+ "xn--s-1fa",
+ "xn--sandnessjen-ogb",
+ "xn--sandy-yua",
+ "xn--seral-lra",
+ "xn--sgne-gra",
+ "xn--skierv-uta",
+ "xn--skjervy-v1a",
+ "xn--skjk-soa",
+ "xn--sknit-yqa",
+ "xn--sknland-fxa",
+ "xn--slat-5na",
+ "xn--slt-elab",
+ "xn--smla-hra",
+ "xn--smna-gra",
+ "xn--snase-nra",
+ "xn--sndre-land-0cb",
+ "xn--snes-poa",
+ "xn--snsa-roa",
+ "xn--sr-aurdal-l8a",
+ "xn--sr-fron-q1a",
+ "xn--sr-odal-q1a",
+ "xn--sr-varanger-ggb",
+ "xn--srfold-bya",
+ "xn--srreisa-q1a",
+ "xn--srum-gra",
+ "xn--stfold-9xa",
+ "xn--stjrdal-s1a",
+ "xn--stjrdalshalsen-sqb",
+ "xn--stre-toten-zcb",
+ "xn--tjme-hra",
+ "xn--tnsberg-q1a",
+ "xn--trany-yua",
+ "xn--trgstad-r1a",
+ "xn--trna-woa",
+ "xn--troms-zua",
+ "xn--tysvr-vra",
+ "xn--unjrga-rta",
+ "xn--vads-jra",
+ "xn--vard-jra",
+ "xn--vegrshei-c0a",
+ "xn--vestvgy-ixa6o",
+ "xn--vg-yiab",
+ "xn--vgan-qoa",
+ "xn--vgsy-qoa0j",
+ "xn--vre-eiker-k8a",
+ "xn--vrggt-xqad",
+ "xn--vry-yla5g",
+ "xn--yer-zna",
+ "xn--ygarden-p1a",
+ "xn--ystre-slidre-ujb",
+ "gs",
+ "gs",
+ "nes",
+ "gs",
+ "nes",
+ "gs",
+ "os",
+ "valer",
+ "xn--vler-qoa",
+ "gs",
+ "gs",
+ "os",
+ "gs",
+ "heroy",
+ "sande",
+ "gs",
+ "gs",
+ "bo",
+ "heroy",
+ "xn--b-5ga",
+ "xn--hery-ira",
+ "gs",
+ "gs",
+ "gs",
+ "gs",
+ "valer",
+ "gs",
+ "gs",
+ "gs",
+ "gs",
+ "bo",
+ "xn--b-5ga",
+ "gs",
+ "gs",
+ "gs",
+ "sande",
+ "gs",
+ "sande",
+ "xn--hery-ira",
+ "xn--vler-qoa",
+ "biz",
+ "com",
+ "edu",
+ "gov",
+ "info",
+ "net",
+ "org",
+ "merseine",
+ "mine",
+ "nom",
+ "shacknet",
+ "ac",
+ "co",
+ "cri",
+ "geek",
+ "gen",
+ "govt",
+ "health",
+ "iwi",
+ "kiwi",
+ "maori",
+ "mil",
+ "net",
+ "nym",
+ "org",
+ "parliament",
+ "school",
+ "xn--mori-qsa",
+ "blogspot",
+ "co",
+ "com",
+ "edu",
+ "gov",
+ "med",
+ "museum",
+ "net",
+ "org",
+ "pro",
+ "homelink",
+ "barsy",
+ "accesscam",
+ "ae",
+ "amune",
+ "blogdns",
+ "blogsite",
+ "bmoattachments",
+ "boldlygoingnowhere",
+ "cable-modem",
+ "camdvr",
+ "cdn77",
+ "cdn77-secure",
+ "certmgr",
+ "cloudns",
+ "collegefan",
+ "couchpotatofries",
+ "ddnss",
+ "diskstation",
+ "dnsalias",
+ "dnsdojo",
+ "doesntexist",
+ "dontexist",
+ "doomdns",
+ "dsmynas",
+ "duckdns",
+ "dvrdns",
+ "dynalias",
+ "dyndns",
+ "endofinternet",
+ "endoftheinternet",
+ "eu",
+ "familyds",
+ "fedorainfracloud",
+ "fedorapeople",
+ "fedoraproject",
+ "freeddns",
+ "from-me",
+ "game-host",
+ "gotdns",
+ "hepforge",
+ "hk",
+ "hobby-site",
+ "homedns",
+ "homeftp",
+ "homelinux",
+ "homeunix",
+ "hopto",
+ "is-a-bruinsfan",
+ "is-a-candidate",
+ "is-a-celticsfan",
+ "is-a-chef",
+ "is-a-geek",
+ "is-a-knight",
+ "is-a-linux-user",
+ "is-a-patsfan",
+ "is-a-soxfan",
+ "is-found",
+ "is-lost",
+ "is-saved",
+ "is-very-bad",
+ "is-very-evil",
+ "is-very-good",
+ "is-very-nice",
+ "is-very-sweet",
+ "isa-geek",
+ "js",
+ "kicks-ass",
+ "misconfused",
+ "mlbfan",
+ "my-firewall",
+ "myfirewall",
+ "myftp",
+ "mysecuritycamera",
+ "mywire",
+ "nflfan",
+ "no-ip",
+ "pimienta",
+ "podzone",
+ "poivron",
+ "potager",
+ "read-books",
+ "readmyblog",
+ "selfip",
+ "sellsyourhome",
+ "servebbs",
+ "serveftp",
+ "servegame",
+ "spdns",
+ "stuff-4-sale",
+ "sweetpepper",
+ "tunk",
+ "tuxfamily",
+ "twmail",
+ "ufcfan",
+ "us",
+ "webhop",
+ "webredirect",
+ "wmflabs",
+ "za",
+ "zapto",
+ "tele",
+ "c",
+ "rsc",
+ "origin",
+ "ssl",
+ "go",
+ "home",
+ "al",
+ "asso",
+ "at",
+ "au",
+ "be",
+ "bg",
+ "ca",
+ "cd",
+ "ch",
+ "cn",
+ "cy",
+ "cz",
+ "de",
+ "dk",
+ "edu",
+ "ee",
+ "es",
+ "fi",
+ "fr",
+ "gr",
+ "hr",
+ "hu",
+ "ie",
+ "il",
+ "in",
+ "int",
+ "is",
+ "it",
+ "jp",
+ "kr",
+ "lt",
+ "lu",
+ "lv",
+ "mc",
+ "me",
+ "mk",
+ "mt",
+ "my",
+ "net",
+ "ng",
+ "nl",
+ "no",
+ "nz",
+ "paris",
+ "pl",
+ "pt",
+ "q-a",
+ "ro",
+ "ru",
+ "se",
+ "si",
+ "sk",
+ "tr",
+ "uk",
+ "us",
+ "cloud",
+ "nerdpol",
+ "abo",
+ "ac",
+ "com",
+ "edu",
+ "gob",
+ "ing",
+ "med",
+ "net",
+ "nom",
+ "org",
+ "sld",
+ "ybo",
+ "blogspot",
+ "com",
+ "edu",
+ "gob",
+ "mil",
+ "net",
+ "nom",
+ "nym",
+ "org",
+ "com",
+ "edu",
+ "org",
+ "com",
+ "edu",
+ "gov",
+ "i",
+ "mil",
+ "net",
+ "ngo",
+ "org",
+ "1337",
+ "biz",
+ "com",
+ "edu",
+ "fam",
+ "gob",
+ "gok",
+ "gon",
+ "gop",
+ "gos",
+ "gov",
+ "info",
+ "net",
+ "org",
+ "web",
+ "agro",
+ "aid",
+ "art",
+ "atm",
+ "augustow",
+ "auto",
+ "babia-gora",
+ "bedzin",
+ "beep",
+ "beskidy",
+ "bialowieza",
+ "bialystok",
+ "bielawa",
+ "bieszczady",
+ "biz",
+ "boleslawiec",
+ "bydgoszcz",
+ "bytom",
+ "cieszyn",
+ "co",
+ "com",
+ "czeladz",
+ "czest",
+ "dlugoleka",
+ "edu",
+ "elblag",
+ "elk",
+ "gda",
+ "gdansk",
+ "gdynia",
+ "gliwice",
+ "glogow",
+ "gmina",
+ "gniezno",
+ "gorlice",
+ "gov",
+ "grajewo",
+ "gsm",
+ "ilawa",
+ "info",
+ "jaworzno",
+ "jelenia-gora",
+ "jgora",
+ "kalisz",
+ "karpacz",
+ "kartuzy",
+ "kaszuby",
+ "katowice",
+ "kazimierz-dolny",
+ "kepno",
+ "ketrzyn",
+ "klodzko",
+ "kobierzyce",
+ "kolobrzeg",
+ "konin",
+ "konskowola",
+ "krakow",
+ "kutno",
+ "lapy",
+ "lebork",
+ "legnica",
+ "lezajsk",
+ "limanowa",
+ "lomza",
+ "lowicz",
+ "lubin",
+ "lukow",
+ "mail",
+ "malbork",
+ "malopolska",
+ "mazowsze",
+ "mazury",
+ "med",
+ "media",
+ "miasta",
+ "mielec",
+ "mielno",
+ "mil",
+ "mragowo",
+ "naklo",
+ "net",
+ "nieruchomosci",
+ "nom",
+ "nowaruda",
+ "nysa",
+ "olawa",
+ "olecko",
+ "olkusz",
+ "olsztyn",
+ "opoczno",
+ "opole",
+ "org",
+ "ostroda",
+ "ostroleka",
+ "ostrowiec",
+ "ostrowwlkp",
+ "pc",
+ "pila",
+ "pisz",
+ "podhale",
+ "podlasie",
+ "polkowice",
+ "pomorskie",
+ "pomorze",
+ "powiat",
+ "poznan",
+ "priv",
+ "prochowice",
+ "pruszkow",
+ "przeworsk",
+ "pulawy",
+ "radom",
+ "rawa-maz",
+ "realestate",
+ "rel",
+ "rybnik",
+ "rzeszow",
+ "sanok",
+ "sejny",
+ "sex",
+ "shop",
+ "sklep",
+ "skoczow",
+ "slask",
+ "slupsk",
+ "sopot",
+ "sos",
+ "sosnowiec",
+ "stalowa-wola",
+ "starachowice",
+ "stargard",
+ "suwalki",
+ "swidnica",
+ "swiebodzin",
+ "swinoujscie",
+ "szczecin",
+ "szczytno",
+ "szkola",
+ "targi",
+ "tarnobrzeg",
+ "tgory",
+ "tm",
+ "tourism",
+ "travel",
+ "turek",
+ "turystyka",
+ "tychy",
+ "ustka",
+ "walbrzych",
+ "warmia",
+ "warszawa",
+ "waw",
+ "wegrow",
+ "wielun",
+ "wlocl",
+ "wloclawek",
+ "wodzislaw",
+ "wolomin",
+ "wroc",
+ "wroclaw",
+ "zachpomor",
+ "zagan",
+ "zakopane",
+ "zarow",
+ "zgora",
+ "zgorzelec",
+ "ap",
+ "griw",
+ "ic",
+ "is",
+ "kmpsp",
+ "konsulat",
+ "kppsp",
+ "kwp",
+ "kwpsp",
+ "mup",
+ "mw",
+ "oirm",
+ "oum",
+ "pa",
+ "pinb",
+ "piw",
+ "po",
+ "psp",
+ "psse",
+ "pup",
+ "rzgw",
+ "sa",
+ "sdn",
+ "sko",
+ "so",
+ "sr",
+ "starostwo",
+ "ug",
+ "ugim",
+ "um",
+ "umig",
+ "upow",
+ "uppo",
+ "us",
+ "uw",
+ "uzs",
+ "wif",
+ "wiih",
+ "winb",
+ "wios",
+ "witd",
+ "wiw",
+ "wsa",
+ "wskr",
+ "wuoz",
+ "wzmiuw",
+ "zp",
+ "co",
+ "edu",
+ "gov",
+ "net",
+ "org",
+ "ac",
+ "biz",
+ "com",
+ "edu",
+ "est",
+ "gov",
+ "info",
+ "isla",
+ "name",
+ "net",
+ "org",
+ "pro",
+ "prof",
+ "aaa",
+ "aca",
+ "acct",
+ "avocat",
+ "bar",
+ "cloudns",
+ "cpa",
+ "eng",
+ "jur",
+ "law",
+ "med",
+ "recht",
+ "com",
+ "edu",
+ "gov",
+ "net",
+ "org",
+ "plo",
+ "sec",
+ "blogspot",
+ "com",
+ "edu",
+ "gov",
+ "int",
+ "net",
+ "nome",
+ "nym",
+ "org",
+ "publ",
+ "belau",
+ "cloudns",
+ "co",
+ "ed",
+ "go",
+ "ne",
+ "nom",
+ "or",
+ "com",
+ "coop",
+ "edu",
+ "gov",
+ "mil",
+ "net",
+ "org",
+ "blogspot",
+ "com",
+ "edu",
+ "gov",
+ "mil",
+ "name",
+ "net",
+ "nom",
+ "org",
+ "sch",
+ "asso",
+ "blogspot",
+ "com",
+ "nom",
+ "ybo",
+ "clan",
+ "arts",
+ "blogspot",
+ "com",
+ "firm",
+ "info",
+ "nom",
+ "nt",
+ "org",
+ "rec",
+ "shop",
+ "store",
+ "tm",
+ "www",
+ "lima-city",
+ "myddns",
+ "webspace",
+ "ac",
+ "blogspot",
+ "co",
+ "edu",
+ "gov",
+ "in",
+ "nom",
+ "org",
+ "ac",
+ "adygeya",
+ "bashkiria",
+ "bir",
+ "blogspot",
+ "cbg",
+ "cldmail",
+ "com",
+ "dagestan",
+ "edu",
+ "gov",
+ "grozny",
+ "int",
+ "kalmykia",
+ "kustanai",
+ "marine",
+ "mil",
+ "mordovia",
+ "msk",
+ "mytis",
+ "nalchik",
+ "net",
+ "nov",
+ "org",
+ "pp",
+ "pyatigorsk",
+ "spb",
+ "test",
+ "vladikavkaz",
+ "vladimir",
+ "hb",
+ "ac",
+ "co",
+ "com",
+ "edu",
+ "gouv",
+ "gov",
+ "int",
+ "mil",
+ "net",
+ "com",
+ "edu",
+ "gov",
+ "med",
+ "net",
+ "org",
+ "pub",
+ "sch",
+ "com",
+ "edu",
+ "gov",
+ "net",
+ "org",
+ "com",
+ "edu",
+ "gov",
+ "net",
+ "org",
+ "ybo",
+ "com",
+ "edu",
+ "gov",
+ "info",
+ "med",
+ "net",
+ "org",
+ "tv",
+ "a",
+ "ac",
+ "b",
+ "bd",
+ "blogspot",
+ "brand",
+ "c",
+ "com",
+ "d",
+ "e",
+ "f",
+ "fh",
+ "fhsk",
+ "fhv",
+ "g",
+ "h",
+ "i",
+ "k",
+ "komforb",
+ "kommunalforbund",
+ "komvux",
+ "l",
+ "lanbib",
+ "m",
+ "n",
+ "naturbruksgymn",
+ "o",
+ "org",
+ "p",
+ "parti",
+ "pp",
+ "press",
+ "r",
+ "s",
+ "t",
+ "tm",
+ "u",
+ "w",
+ "x",
+ "y",
+ "z",
+ "blogspot",
+ "com",
+ "edu",
+ "gov",
+ "net",
+ "org",
+ "per",
+ "com",
+ "gov",
+ "hashbang",
+ "mil",
+ "net",
+ "now",
+ "org",
+ "platform",
+ "wedeploy",
+ "blogspot",
+ "nom",
+ "byen",
+ "cyon",
+ "platformsh",
+ "blogspot",
+ "nym",
+ "com",
+ "edu",
+ "gov",
+ "net",
+ "org",
+ "art",
+ "blogspot",
+ "com",
+ "edu",
+ "gouv",
+ "org",
+ "perso",
+ "univ",
+ "com",
+ "net",
+ "org",
+ "stackspace",
+ "uber",
+ "xs4all",
+ "co",
+ "com",
+ "consulado",
+ "edu",
+ "embaixada",
+ "gov",
+ "mil",
+ "net",
+ "org",
+ "principe",
+ "saotome",
+ "store",
+ "abkhazia",
+ "adygeya",
+ "aktyubinsk",
+ "arkhangelsk",
+ "armenia",
+ "ashgabad",
+ "azerbaijan",
+ "balashov",
+ "bashkiria",
+ "bryansk",
+ "bukhara",
+ "chimkent",
+ "dagestan",
+ "east-kazakhstan",
+ "exnet",
+ "georgia",
+ "grozny",
+ "ivanovo",
+ "jambyl",
+ "kalmykia",
+ "kaluga",
+ "karacol",
+ "karaganda",
+ "karelia",
+ "khakassia",
+ "krasnodar",
+ "kurgan",
+ "kustanai",
+ "lenug",
+ "mangyshlak",
+ "mordovia",
+ "msk",
+ "murmansk",
+ "nalchik",
+ "navoi",
+ "north-kazakhstan",
+ "nov",
+ "nym",
+ "obninsk",
+ "penza",
+ "pokrovsk",
+ "sochi",
+ "spb",
+ "tashkent",
+ "termez",
+ "togliatti",
+ "troitsk",
+ "tselinograd",
+ "tula",
+ "tuva",
+ "vladikavkaz",
+ "vladimir",
+ "vologda",
+ "barsy",
+ "com",
+ "edu",
+ "gob",
+ "org",
+ "red",
+ "gov",
+ "nym",
+ "com",
+ "edu",
+ "gov",
+ "mil",
+ "net",
+ "org",
+ "knightpoint",
+ "ac",
+ "co",
+ "org",
+ "blogspot",
+ "ac",
+ "co",
+ "go",
+ "in",
+ "mi",
+ "net",
+ "or",
+ "ac",
+ "biz",
+ "co",
+ "com",
+ "edu",
+ "go",
+ "gov",
+ "int",
+ "mil",
+ "name",
+ "net",
+ "nic",
+ "org",
+ "test",
+ "web",
+ "gov",
+ "co",
+ "com",
+ "edu",
+ "gov",
+ "mil",
+ "net",
+ "nom",
+ "org",
+ "agrinet",
+ "com",
+ "defense",
+ "edunet",
+ "ens",
+ "fin",
+ "gov",
+ "ind",
+ "info",
+ "intl",
+ "mincom",
+ "nat",
+ "net",
+ "org",
+ "perso",
+ "rnrt",
+ "rns",
+ "rnu",
+ "tourism",
+ "turen",
+ "com",
+ "edu",
+ "gov",
+ "mil",
+ "net",
+ "org",
+ "vpnplus",
+ "av",
+ "bbs",
+ "bel",
+ "biz",
+ "com",
+ "dr",
+ "edu",
+ "gen",
+ "gov",
+ "info",
+ "k12",
+ "kep",
+ "mil",
+ "name",
+ "nc",
+ "net",
+ "org",
+ "pol",
+ "tel",
+ "tv",
+ "web",
+ "blogspot",
+ "gov",
+ "ybo",
+ "aero",
+ "biz",
+ "co",
+ "com",
+ "coop",
+ "edu",
+ "gov",
+ "info",
+ "int",
+ "jobs",
+ "mobi",
+ "museum",
+ "name",
+ "net",
+ "org",
+ "pro",
+ "travel",
+ "better-than",
+ "dyndns",
+ "on-the-web",
+ "worse-than",
+ "blogspot",
+ "club",
+ "com",
+ "ebiz",
+ "edu",
+ "game",
+ "gov",
+ "idv",
+ "mil",
+ "net",
+ "nym",
+ "org",
+ "url",
+ "xn--czrw28b",
+ "xn--uc0atv",
+ "xn--zf0ao64a",
+ "mymailer",
+ "ac",
+ "co",
+ "go",
+ "hotel",
+ "info",
+ "me",
+ "mil",
+ "mobi",
+ "ne",
+ "or",
+ "sc",
+ "tv",
+ "biz",
+ "cc",
+ "cherkassy",
+ "cherkasy",
+ "chernigov",
+ "chernihiv",
+ "chernivtsi",
+ "chernovtsy",
+ "ck",
+ "cn",
+ "co",
+ "com",
+ "cr",
+ "crimea",
+ "cv",
+ "dn",
+ "dnepropetrovsk",
+ "dnipropetrovsk",
+ "dominic",
+ "donetsk",
+ "dp",
+ "edu",
+ "gov",
+ "if",
+ "in",
+ "inf",
+ "ivano-frankivsk",
+ "kh",
+ "kharkiv",
+ "kharkov",
+ "kherson",
+ "khmelnitskiy",
+ "khmelnytskyi",
+ "kiev",
+ "kirovograd",
+ "km",
+ "kr",
+ "krym",
+ "ks",
+ "kv",
+ "kyiv",
+ "lg",
+ "lt",
+ "ltd",
+ "lugansk",
+ "lutsk",
+ "lv",
+ "lviv",
+ "mk",
+ "mykolaiv",
+ "net",
+ "nikolaev",
+ "od",
+ "odesa",
+ "odessa",
+ "org",
+ "pl",
+ "poltava",
+ "pp",
+ "rivne",
+ "rovno",
+ "rv",
+ "sb",
+ "sebastopol",
+ "sevastopol",
+ "sm",
+ "sumy",
+ "te",
+ "ternopil",
+ "uz",
+ "uzhgorod",
+ "vinnica",
+ "vinnytsia",
+ "vn",
+ "volyn",
+ "yalta",
+ "zaporizhzhe",
+ "zaporizhzhia",
+ "zhitomir",
+ "zhytomyr",
+ "zp",
+ "zt",
+ "ac",
+ "blogspot",
+ "co",
+ "com",
+ "go",
+ "ne",
+ "nom",
+ "or",
+ "org",
+ "sc",
+ "ac",
+ "co",
+ "gov",
+ "ltd",
+ "me",
+ "net",
+ "nhs",
+ "org",
+ "plc",
+ "police",
+ "sch",
+ "blogspot",
+ "no-ip",
+ "wellbeingzone",
+ "homeoffice",
+ "service",
+ "ak",
+ "al",
+ "ar",
+ "as",
+ "az",
+ "ca",
+ "cloudns",
+ "co",
+ "ct",
+ "dc",
+ "de",
+ "dni",
+ "drud",
+ "fed",
+ "fl",
+ "ga",
+ "golffan",
+ "gu",
+ "hi",
+ "ia",
+ "id",
+ "il",
+ "in",
+ "is-by",
+ "isa",
+ "kids",
+ "ks",
+ "ky",
+ "la",
+ "land-4-sale",
+ "ma",
+ "md",
+ "me",
+ "mi",
+ "mn",
+ "mo",
+ "ms",
+ "mt",
+ "nc",
+ "nd",
+ "ne",
+ "nh",
+ "nj",
+ "nm",
+ "noip",
+ "nsn",
+ "nv",
+ "ny",
+ "oh",
+ "ok",
+ "or",
+ "pa",
+ "pointto",
+ "pr",
+ "ri",
+ "sc",
+ "sd",
+ "stuff-4-sale",
+ "tn",
+ "tx",
+ "ut",
+ "va",
+ "vi",
+ "vt",
+ "wa",
+ "wi",
+ "wv",
+ "wy",
+ "cc",
+ "k12",
+ "lib",
+ "cc",
+ "k12",
+ "lib",
+ "cc",
+ "k12",
+ "lib",
+ "cc",
+ "k12",
+ "lib",
+ "cc",
+ "k12",
+ "lib",
+ "cc",
+ "k12",
+ "lib",
+ "cc",
+ "k12",
+ "lib",
+ "cc",
+ "k12",
+ "lib",
+ "cc",
+ "k12",
+ "lib",
+ "cc",
+ "k12",
+ "lib",
+ "cc",
+ "k12",
+ "lib",
+ "cc",
+ "k12",
+ "lib",
+ "cc",
+ "k12",
+ "lib",
+ "cc",
+ "lib",
+ "cc",
+ "k12",
+ "lib",
+ "cc",
+ "k12",
+ "lib",
+ "cc",
+ "k12",
+ "lib",
+ "cc",
+ "k12",
+ "lib",
+ "cc",
+ "k12",
+ "lib",
+ "cc",
+ "k12",
+ "lib",
+ "cc",
+ "k12",
+ "lib",
+ "cc",
+ "k12",
+ "lib",
+ "chtr",
+ "paroch",
+ "pvt",
+ "cc",
+ "k12",
+ "lib",
+ "cc",
+ "k12",
+ "lib",
+ "ann-arbor",
+ "cc",
+ "cog",
+ "dst",
+ "eaton",
+ "gen",
+ "k12",
+ "lib",
+ "mus",
+ "tec",
+ "washtenaw",
+ "cc",
+ "k12",
+ "lib",
+ "cc",
+ "k12",
+ "lib",
+ "cc",
+ "k12",
+ "lib",
+ "cc",
+ "k12",
+ "lib",
+ "cc",
+ "k12",
+ "lib",
+ "cc",
+ "lib",
+ "cc",
+ "k12",
+ "lib",
+ "cc",
+ "k12",
+ "lib",
+ "cc",
+ "k12",
+ "lib",
+ "cc",
+ "k12",
+ "lib",
+ "cc",
+ "k12",
+ "lib",
+ "cc",
+ "k12",
+ "lib",
+ "cc",
+ "k12",
+ "lib",
+ "cc",
+ "k12",
+ "lib",
+ "cc",
+ "k12",
+ "lib",
+ "cc",
+ "k12",
+ "lib",
+ "cc",
+ "k12",
+ "lib",
+ "cc",
+ "k12",
+ "lib",
+ "cc",
+ "k12",
+ "lib",
+ "cc",
+ "lib",
+ "cc",
+ "k12",
+ "lib",
+ "cc",
+ "k12",
+ "lib",
+ "cc",
+ "k12",
+ "lib",
+ "cc",
+ "k12",
+ "lib",
+ "cc",
+ "k12",
+ "lib",
+ "cc",
+ "k12",
+ "lib",
+ "cc",
+ "k12",
+ "lib",
+ "cc",
+ "k12",
+ "lib",
+ "cc",
+ "cc",
+ "k12",
+ "lib",
+ "com",
+ "edu",
+ "gub",
+ "mil",
+ "net",
+ "nom",
+ "org",
+ "blogspot",
+ "co",
+ "com",
+ "net",
+ "org",
+ "com",
+ "edu",
+ "gov",
+ "mil",
+ "net",
+ "nom",
+ "org",
+ "arts",
+ "co",
+ "com",
+ "e12",
+ "edu",
+ "firm",
+ "gob",
+ "gov",
+ "info",
+ "int",
+ "mil",
+ "net",
+ "org",
+ "rec",
+ "store",
+ "tec",
+ "web",
+ "nom",
+ "co",
+ "com",
+ "k12",
+ "net",
+ "org",
+ "ac",
+ "biz",
+ "blogspot",
+ "com",
+ "edu",
+ "gov",
+ "health",
+ "info",
+ "int",
+ "name",
+ "net",
+ "org",
+ "pro",
+ "com",
+ "edu",
+ "net",
+ "org",
+ "advisor",
+ "com",
+ "dyndns",
+ "edu",
+ "gov",
+ "mypets",
+ "net",
+ "org",
+ "xn--80au",
+ "xn--90azh",
+ "xn--c1avg",
+ "xn--d1at",
+ "xn--o1ac",
+ "xn--o1ach",
+ "xn--12c1fe0br",
+ "xn--12cfi8ixb8l",
+ "xn--12co0c3b4eva",
+ "xn--h3cuzk1di",
+ "xn--m3ch0j3a",
+ "xn--o3cyx2a",
+ "blogsite",
+ "fhapp",
+ "ac",
+ "agric",
+ "alt",
+ "co",
+ "edu",
+ "gov",
+ "grondar",
+ "law",
+ "mil",
+ "net",
+ "ngo",
+ "nis",
+ "nom",
+ "org",
+ "school",
+ "tm",
+ "web",
+ "blogspot",
+ "ac",
+ "biz",
+ "co",
+ "com",
+ "edu",
+ "gov",
+ "info",
+ "mil",
+ "net",
+ "org",
+ "sch",
+ "lima",
+ "triton",
+ "ac",
+ "co",
+ "gov",
+ "mil",
+ "org",
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/address.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/address.go
new file mode 100644
index 000000000..e6bfa39e9
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/address.go
@@ -0,0 +1,425 @@
+// 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.
+
+// +build darwin dragonfly freebsd netbsd openbsd
+
+package route
+
+import "runtime"
+
+// An Addr represents an address associated with packet routing.
+type Addr interface {
+ // Family returns an address family.
+ Family() int
+}
+
+// A LinkAddr represents a link-layer address.
+type LinkAddr struct {
+ Index int // interface index when attached
+ Name string // interface name when attached
+ Addr []byte // link-layer address when attached
+}
+
+// Family implements the Family method of Addr interface.
+func (a *LinkAddr) Family() int { return sysAF_LINK }
+
+func (a *LinkAddr) lenAndSpace() (int, int) {
+ l := 8 + len(a.Name) + len(a.Addr)
+ return l, roundup(l)
+}
+
+func (a *LinkAddr) marshal(b []byte) (int, error) {
+ l, ll := a.lenAndSpace()
+ if len(b) < ll {
+ return 0, errShortBuffer
+ }
+ nlen, alen := len(a.Name), len(a.Addr)
+ if nlen > 255 || alen > 255 {
+ return 0, errInvalidAddr
+ }
+ b[0] = byte(l)
+ b[1] = sysAF_LINK
+ if a.Index > 0 {
+ nativeEndian.PutUint16(b[2:4], uint16(a.Index))
+ }
+ data := b[8:]
+ if nlen > 0 {
+ b[5] = byte(nlen)
+ copy(data[:nlen], a.Addr)
+ data = data[nlen:]
+ }
+ if alen > 0 {
+ b[6] = byte(alen)
+ copy(data[:alen], a.Name)
+ data = data[alen:]
+ }
+ return ll, nil
+}
+
+func parseLinkAddr(b []byte) (Addr, error) {
+ if len(b) < 8 {
+ return nil, errInvalidAddr
+ }
+ _, a, err := parseKernelLinkAddr(sysAF_LINK, b[4:])
+ if err != nil {
+ return nil, err
+ }
+ a.(*LinkAddr).Index = int(nativeEndian.Uint16(b[2:4]))
+ return a, nil
+}
+
+// parseKernelLinkAddr parses b as a link-layer address in
+// conventional BSD kernel form.
+func parseKernelLinkAddr(_ int, b []byte) (int, Addr, error) {
+ // The encoding looks like the following:
+ // +----------------------------+
+ // | Type (1 octet) |
+ // +----------------------------+
+ // | Name length (1 octet) |
+ // +----------------------------+
+ // | Address length (1 octet) |
+ // +----------------------------+
+ // | Selector length (1 octet) |
+ // +----------------------------+
+ // | Data (variable) |
+ // +----------------------------+
+ //
+ // On some platforms, all-bit-one of length field means "don't
+ // care".
+ nlen, alen, slen := int(b[1]), int(b[2]), int(b[3])
+ if nlen == 0xff {
+ nlen = 0
+ }
+ if alen == 0xff {
+ alen = 0
+ }
+ if slen == 0xff {
+ slen = 0
+ }
+ l := 4 + nlen + alen + slen
+ if len(b) < l {
+ return 0, nil, errInvalidAddr
+ }
+ data := b[4:]
+ var name string
+ var addr []byte
+ if nlen > 0 {
+ name = string(data[:nlen])
+ data = data[nlen:]
+ }
+ if alen > 0 {
+ addr = data[:alen]
+ data = data[alen:]
+ }
+ return l, &LinkAddr{Name: name, Addr: addr}, nil
+}
+
+// An Inet4Addr represents an internet address for IPv4.
+type Inet4Addr struct {
+ IP [4]byte // IP address
+}
+
+// Family implements the Family method of Addr interface.
+func (a *Inet4Addr) Family() int { return sysAF_INET }
+
+func (a *Inet4Addr) lenAndSpace() (int, int) {
+ return sizeofSockaddrInet, roundup(sizeofSockaddrInet)
+}
+
+func (a *Inet4Addr) marshal(b []byte) (int, error) {
+ l, ll := a.lenAndSpace()
+ if len(b) < ll {
+ return 0, errShortBuffer
+ }
+ b[0] = byte(l)
+ b[1] = sysAF_INET
+ copy(b[4:8], a.IP[:])
+ return ll, nil
+}
+
+// An Inet6Addr represents an internet address for IPv6.
+type Inet6Addr struct {
+ IP [16]byte // IP address
+ ZoneID int // zone identifier
+}
+
+// Family implements the Family method of Addr interface.
+func (a *Inet6Addr) Family() int { return sysAF_INET6 }
+
+func (a *Inet6Addr) lenAndSpace() (int, int) {
+ return sizeofSockaddrInet6, roundup(sizeofSockaddrInet6)
+}
+
+func (a *Inet6Addr) marshal(b []byte) (int, error) {
+ l, ll := a.lenAndSpace()
+ if len(b) < ll {
+ return 0, errShortBuffer
+ }
+ b[0] = byte(l)
+ b[1] = sysAF_INET6
+ copy(b[8:24], a.IP[:])
+ if a.ZoneID > 0 {
+ nativeEndian.PutUint32(b[24:28], uint32(a.ZoneID))
+ }
+ return ll, nil
+}
+
+// parseInetAddr parses b as an internet address for IPv4 or IPv6.
+func parseInetAddr(af int, b []byte) (Addr, error) {
+ switch af {
+ case sysAF_INET:
+ if len(b) < sizeofSockaddrInet {
+ return nil, errInvalidAddr
+ }
+ a := &Inet4Addr{}
+ copy(a.IP[:], b[4:8])
+ return a, nil
+ case sysAF_INET6:
+ if len(b) < sizeofSockaddrInet6 {
+ return nil, errInvalidAddr
+ }
+ a := &Inet6Addr{ZoneID: int(nativeEndian.Uint32(b[24:28]))}
+ copy(a.IP[:], b[8:24])
+ if a.IP[0] == 0xfe && a.IP[1]&0xc0 == 0x80 || a.IP[0] == 0xff && (a.IP[1]&0x0f == 0x01 || a.IP[1]&0x0f == 0x02) {
+ // KAME based IPv6 protocol stack usually
+ // embeds the interface index in the
+ // interface-local or link-local address as
+ // the kernel-internal form.
+ id := int(bigEndian.Uint16(a.IP[2:4]))
+ if id != 0 {
+ a.ZoneID = id
+ a.IP[2], a.IP[3] = 0, 0
+ }
+ }
+ return a, nil
+ default:
+ return nil, errInvalidAddr
+ }
+}
+
+// parseKernelInetAddr parses b as an internet address in conventional
+// BSD kernel form.
+func parseKernelInetAddr(af int, b []byte) (int, Addr, error) {
+ // The encoding looks similar to the NLRI encoding.
+ // +----------------------------+
+ // | Length (1 octet) |
+ // +----------------------------+
+ // | Address prefix (variable) |
+ // +----------------------------+
+ //
+ // The differences between the kernel form and the NLRI
+ // encoding are:
+ //
+ // - The length field of the kernel form indicates the prefix
+ // length in bytes, not in bits
+ //
+ // - In the kernel form, zero value of the length field
+ // 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
+ // the routing message boundary
+ l := int(b[0])
+ if runtime.GOOS == "darwin" {
+ // On Darwn, an address in the kernel form is also
+ // used as a message filler.
+ if l == 0 || len(b) > roundup(l) {
+ l = roundup(l)
+ }
+ } else {
+ l = roundup(l)
+ }
+ if len(b) < l {
+ return 0, nil, errInvalidAddr
+ }
+ // Don't reorder case expressions.
+ // The case expressions for IPv6 must come first.
+ const (
+ off4 = 4 // offset of in_addr
+ off6 = 8 // offset of in6_addr
+ )
+ switch {
+ case b[0] == sizeofSockaddrInet6:
+ a := &Inet6Addr{}
+ copy(a.IP[:], b[off6:off6+16])
+ return int(b[0]), a, nil
+ case af == sysAF_INET6:
+ a := &Inet6Addr{}
+ if l-1 < off6 {
+ copy(a.IP[:], b[1:l])
+ } else {
+ copy(a.IP[:], b[l-off6:l])
+ }
+ return int(b[0]), a, nil
+ case b[0] == sizeofSockaddrInet:
+ a := &Inet4Addr{}
+ copy(a.IP[:], b[off4:off4+4])
+ return int(b[0]), a, nil
+ default: // an old fashion, AF_UNSPEC or unknown means AF_INET
+ a := &Inet4Addr{}
+ if l-1 < off4 {
+ copy(a.IP[:], b[1:l])
+ } else {
+ copy(a.IP[:], b[l-off4:l])
+ }
+ return int(b[0]), a, nil
+ }
+}
+
+// A DefaultAddr represents an address of various operating
+// system-specific features.
+type DefaultAddr struct {
+ af int
+ Raw []byte // raw format of address
+}
+
+// Family implements the Family method of Addr interface.
+func (a *DefaultAddr) Family() int { return a.af }
+
+func (a *DefaultAddr) lenAndSpace() (int, int) {
+ l := len(a.Raw)
+ return l, roundup(l)
+}
+
+func (a *DefaultAddr) marshal(b []byte) (int, error) {
+ l, ll := a.lenAndSpace()
+ if len(b) < ll {
+ return 0, errShortBuffer
+ }
+ if l > 255 {
+ return 0, errInvalidAddr
+ }
+ b[1] = byte(l)
+ copy(b[:l], a.Raw)
+ return ll, nil
+}
+
+func parseDefaultAddr(b []byte) (Addr, error) {
+ if len(b) < 2 || len(b) < int(b[0]) {
+ return nil, errInvalidAddr
+ }
+ a := &DefaultAddr{af: int(b[1]), Raw: b[:b[0]]}
+ return a, nil
+}
+
+func addrsSpace(as []Addr) int {
+ var l int
+ for _, a := range as {
+ switch a := a.(type) {
+ case *LinkAddr:
+ _, ll := a.lenAndSpace()
+ l += ll
+ case *Inet4Addr:
+ _, ll := a.lenAndSpace()
+ l += ll
+ case *Inet6Addr:
+ _, ll := a.lenAndSpace()
+ l += ll
+ case *DefaultAddr:
+ _, ll := a.lenAndSpace()
+ l += ll
+ }
+ }
+ return l
+}
+
+// marshalAddrs marshals as and returns a bitmap indicating which
+// address is stored in b.
+func marshalAddrs(b []byte, as []Addr) (uint, error) {
+ var attrs uint
+ for i, a := range as {
+ switch a := a.(type) {
+ case *LinkAddr:
+ l, err := a.marshal(b)
+ if err != nil {
+ return 0, err
+ }
+ b = b[l:]
+ attrs |= 1 << uint(i)
+ case *Inet4Addr:
+ l, err := a.marshal(b)
+ if err != nil {
+ return 0, err
+ }
+ b = b[l:]
+ attrs |= 1 << uint(i)
+ case *Inet6Addr:
+ l, err := a.marshal(b)
+ if err != nil {
+ return 0, err
+ }
+ b = b[l:]
+ attrs |= 1 << uint(i)
+ case *DefaultAddr:
+ l, err := a.marshal(b)
+ if err != nil {
+ return 0, err
+ }
+ b = b[l:]
+ attrs |= 1 << uint(i)
+ }
+ }
+ return attrs, nil
+}
+
+func parseAddrs(attrs uint, fn func(int, []byte) (int, Addr, error), b []byte) ([]Addr, error) {
+ var as [sysRTAX_MAX]Addr
+ af := int(sysAF_UNSPEC)
+ for i := uint(0); i < sysRTAX_MAX && len(b) >= roundup(0); i++ {
+ if attrs&(1<<i) == 0 {
+ continue
+ }
+ if i <= sysRTAX_BRD {
+ switch b[1] {
+ case sysAF_LINK:
+ a, err := parseLinkAddr(b)
+ if err != nil {
+ return nil, err
+ }
+ as[i] = a
+ l := roundup(int(b[0]))
+ if len(b) < l {
+ return nil, errMessageTooShort
+ }
+ b = b[l:]
+ case sysAF_INET, sysAF_INET6:
+ af = int(b[1])
+ a, err := parseInetAddr(af, b)
+ if err != nil {
+ return nil, err
+ }
+ as[i] = a
+ l := roundup(int(b[0]))
+ if len(b) < l {
+ return nil, errMessageTooShort
+ }
+ b = b[l:]
+ default:
+ l, a, err := fn(af, b)
+ if err != nil {
+ return nil, err
+ }
+ as[i] = a
+ ll := roundup(l)
+ if len(b) < ll {
+ b = b[l:]
+ } else {
+ b = b[ll:]
+ }
+ }
+ } else {
+ a, err := parseDefaultAddr(b)
+ if err != nil {
+ return nil, err
+ }
+ as[i] = a
+ l := roundup(int(b[0]))
+ if len(b) < l {
+ return nil, errMessageTooShort
+ }
+ b = b[l:]
+ }
+ }
+ return as[:], nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/address_darwin_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/address_darwin_test.go
new file mode 100644
index 000000000..b86bd3df1
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/address_darwin_test.go
@@ -0,0 +1,63 @@
+// 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.
+
+package route
+
+import (
+ "reflect"
+ "testing"
+)
+
+type parseAddrsOnDarwinTest struct {
+ attrs uint
+ fn func(int, []byte) (int, Addr, error)
+ b []byte
+ as []Addr
+}
+
+var parseAddrsOnDarwinLittleEndianTests = []parseAddrsOnDarwinTest{
+ {
+ sysRTA_DST | sysRTA_GATEWAY | sysRTA_NETMASK,
+ parseKernelInetAddr,
+ []byte{
+ 0x10, 0x2, 0x0, 0x0, 0xc0, 0xa8, 0x56, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+
+ 0x14, 0x12, 0x4, 0x0, 0x6, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0,
+
+ 0x7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ },
+ []Addr{
+ &Inet4Addr{IP: [4]byte{192, 168, 86, 0}},
+ &LinkAddr{Index: 4},
+ &Inet4Addr{IP: [4]byte{255, 255, 255, 255}},
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ },
+ },
+}
+
+func TestParseAddrsOnDarwin(t *testing.T) {
+ tests := parseAddrsOnDarwinLittleEndianTests
+ if nativeEndian != littleEndian {
+ t.Skip("no test for non-little endian machine yet")
+ }
+
+ for i, tt := range tests {
+ as, err := parseAddrs(tt.attrs, tt.fn, tt.b)
+ if err != nil {
+ t.Error(i, err)
+ continue
+ }
+ if !reflect.DeepEqual(as, tt.as) {
+ t.Errorf("#%d: got %+v; want %+v", i, as, tt.as)
+ continue
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/address_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/address_test.go
new file mode 100644
index 000000000..2005ef7c2
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/address_test.go
@@ -0,0 +1,103 @@
+// 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.
+
+// +build darwin dragonfly freebsd netbsd openbsd
+
+package route
+
+import (
+ "reflect"
+ "testing"
+)
+
+type parseAddrsTest struct {
+ attrs uint
+ fn func(int, []byte) (int, Addr, error)
+ b []byte
+ as []Addr
+}
+
+var parseAddrsLittleEndianTests = []parseAddrsTest{
+ {
+ sysRTA_DST | sysRTA_GATEWAY | sysRTA_NETMASK | sysRTA_BRD,
+ parseKernelInetAddr,
+ []byte{
+ 0x38, 0x12, 0x0, 0x0, 0xff, 0xff, 0xff, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+
+ 0x38, 0x12, 0x2, 0x0, 0x6, 0x3, 0x6, 0x0,
+ 0x65, 0x6d, 0x31, 0x0, 0xc, 0x29, 0x66, 0x2c,
+ 0xdc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+
+ 0x10, 0x2, 0x0, 0x0, 0xac, 0x10, 0xdc, 0xb4,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+
+ 0x10, 0x2, 0x0, 0x0, 0xac, 0x10, 0xdc, 0xff,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ },
+ []Addr{
+ &LinkAddr{Index: 0},
+ &LinkAddr{Index: 2, Name: "em1", Addr: []byte{0x00, 0x0c, 0x29, 0x66, 0x2c, 0xdc}},
+ &Inet4Addr{IP: [4]byte{172, 16, 220, 180}},
+ nil,
+ nil,
+ nil,
+ nil,
+ &Inet4Addr{IP: [4]byte{172, 16, 220, 255}},
+ },
+ },
+ {
+ sysRTA_NETMASK | sysRTA_IFP | sysRTA_IFA,
+ parseKernelInetAddr,
+ []byte{
+ 0x7, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0x0,
+
+ 0x18, 0x12, 0xa, 0x0, 0x87, 0x8, 0x0, 0x0,
+ 0x76, 0x6c, 0x61, 0x6e, 0x35, 0x36, 0x38, 0x32,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+
+ 0x10, 0x2, 0x0, 0x0, 0xa9, 0xfe, 0x0, 0x1,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ },
+ []Addr{
+ nil,
+ nil,
+ &Inet4Addr{IP: [4]byte{255, 255, 255, 0}},
+ nil,
+ &LinkAddr{Index: 10, Name: "vlan5682"},
+ &Inet4Addr{IP: [4]byte{169, 254, 0, 1}},
+ nil,
+ nil,
+ },
+ },
+}
+
+func TestParseAddrs(t *testing.T) {
+ tests := parseAddrsLittleEndianTests
+ if nativeEndian != littleEndian {
+ t.Skip("no test for non-little endian machine yet")
+ }
+
+ for i, tt := range tests {
+ as, err := parseAddrs(tt.attrs, tt.fn, tt.b)
+ if err != nil {
+ t.Error(i, err)
+ continue
+ }
+ as = as[:8] // the list varies between operating systems
+ if !reflect.DeepEqual(as, tt.as) {
+ t.Errorf("#%d: got %+v; want %+v", i, as, tt.as)
+ continue
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/binary.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/binary.go
new file mode 100644
index 000000000..6910520ec
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/binary.go
@@ -0,0 +1,90 @@
+// 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.
+
+// +build darwin dragonfly freebsd netbsd openbsd
+
+package route
+
+// This file contains duplicates of encoding/binary package.
+//
+// This package is supposed to be used by the net package of standard
+// library. Therefore the package set used in the package must be the
+// same as net package.
+
+var (
+ littleEndian binaryLittleEndian
+ bigEndian binaryBigEndian
+)
+
+type binaryByteOrder interface {
+ Uint16([]byte) uint16
+ Uint32([]byte) uint32
+ PutUint16([]byte, uint16)
+ PutUint32([]byte, uint32)
+ Uint64([]byte) uint64
+}
+
+type binaryLittleEndian struct{}
+
+func (binaryLittleEndian) Uint16(b []byte) uint16 {
+ _ = b[1] // bounds check hint to compiler; see golang.org/issue/14808
+ return uint16(b[0]) | uint16(b[1])<<8
+}
+
+func (binaryLittleEndian) PutUint16(b []byte, v uint16) {
+ _ = b[1] // early bounds check to guarantee safety of writes below
+ b[0] = byte(v)
+ b[1] = byte(v >> 8)
+}
+
+func (binaryLittleEndian) Uint32(b []byte) uint32 {
+ _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
+ return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
+}
+
+func (binaryLittleEndian) PutUint32(b []byte, v uint32) {
+ _ = b[3] // early bounds check to guarantee safety of writes below
+ b[0] = byte(v)
+ b[1] = byte(v >> 8)
+ b[2] = byte(v >> 16)
+ b[3] = byte(v >> 24)
+}
+
+func (binaryLittleEndian) Uint64(b []byte) uint64 {
+ _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
+ return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
+ uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
+}
+
+type binaryBigEndian struct{}
+
+func (binaryBigEndian) Uint16(b []byte) uint16 {
+ _ = b[1] // bounds check hint to compiler; see golang.org/issue/14808
+ return uint16(b[1]) | uint16(b[0])<<8
+}
+
+func (binaryBigEndian) PutUint16(b []byte, v uint16) {
+ _ = b[1] // early bounds check to guarantee safety of writes below
+ b[0] = byte(v >> 8)
+ b[1] = byte(v)
+}
+
+func (binaryBigEndian) Uint32(b []byte) uint32 {
+ _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
+ return uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24
+}
+
+func (binaryBigEndian) PutUint32(b []byte, v uint32) {
+ _ = b[3] // early bounds check to guarantee safety of writes below
+ b[0] = byte(v >> 24)
+ b[1] = byte(v >> 16)
+ b[2] = byte(v >> 8)
+ b[3] = byte(v)
+}
+
+func (binaryBigEndian) Uint64(b []byte) uint64 {
+ _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
+ return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
+ uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/defs_darwin.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/defs_darwin.go
new file mode 100644
index 000000000..e7716442d
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/defs_darwin.go
@@ -0,0 +1,114 @@
+// 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.
+
+// +build ignore
+
+package route
+
+/*
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/route.h>
+
+#include <netinet/in.h>
+*/
+import "C"
+
+const (
+ sysAF_UNSPEC = C.AF_UNSPEC
+ sysAF_INET = C.AF_INET
+ sysAF_ROUTE = C.AF_ROUTE
+ sysAF_LINK = C.AF_LINK
+ sysAF_INET6 = C.AF_INET6
+
+ sysSOCK_RAW = C.SOCK_RAW
+
+ sysNET_RT_DUMP = C.NET_RT_DUMP
+ sysNET_RT_FLAGS = C.NET_RT_FLAGS
+ sysNET_RT_IFLIST = C.NET_RT_IFLIST
+ sysNET_RT_STAT = C.NET_RT_STAT
+ sysNET_RT_TRASH = C.NET_RT_TRASH
+ sysNET_RT_IFLIST2 = C.NET_RT_IFLIST2
+ sysNET_RT_DUMP2 = C.NET_RT_DUMP2
+ sysNET_RT_MAXID = C.NET_RT_MAXID
+)
+
+const (
+ sysCTL_MAXNAME = C.CTL_MAXNAME
+
+ sysCTL_UNSPEC = C.CTL_UNSPEC
+ sysCTL_KERN = C.CTL_KERN
+ sysCTL_VM = C.CTL_VM
+ sysCTL_VFS = C.CTL_VFS
+ sysCTL_NET = C.CTL_NET
+ sysCTL_DEBUG = C.CTL_DEBUG
+ sysCTL_HW = C.CTL_HW
+ sysCTL_MACHDEP = C.CTL_MACHDEP
+ sysCTL_USER = C.CTL_USER
+ sysCTL_MAXID = C.CTL_MAXID
+)
+
+const (
+ sysRTM_VERSION = C.RTM_VERSION
+
+ sysRTM_ADD = C.RTM_ADD
+ sysRTM_DELETE = C.RTM_DELETE
+ sysRTM_CHANGE = C.RTM_CHANGE
+ sysRTM_GET = C.RTM_GET
+ sysRTM_LOSING = C.RTM_LOSING
+ sysRTM_REDIRECT = C.RTM_REDIRECT
+ sysRTM_MISS = C.RTM_MISS
+ sysRTM_LOCK = C.RTM_LOCK
+ sysRTM_OLDADD = C.RTM_OLDADD
+ sysRTM_OLDDEL = C.RTM_OLDDEL
+ sysRTM_RESOLVE = C.RTM_RESOLVE
+ sysRTM_NEWADDR = C.RTM_NEWADDR
+ sysRTM_DELADDR = C.RTM_DELADDR
+ sysRTM_IFINFO = C.RTM_IFINFO
+ sysRTM_NEWMADDR = C.RTM_NEWMADDR
+ sysRTM_DELMADDR = C.RTM_DELMADDR
+ sysRTM_IFINFO2 = C.RTM_IFINFO2
+ sysRTM_NEWMADDR2 = C.RTM_NEWMADDR2
+ sysRTM_GET2 = C.RTM_GET2
+
+ sysRTA_DST = C.RTA_DST
+ sysRTA_GATEWAY = C.RTA_GATEWAY
+ sysRTA_NETMASK = C.RTA_NETMASK
+ sysRTA_GENMASK = C.RTA_GENMASK
+ sysRTA_IFP = C.RTA_IFP
+ sysRTA_IFA = C.RTA_IFA
+ sysRTA_AUTHOR = C.RTA_AUTHOR
+ sysRTA_BRD = C.RTA_BRD
+
+ sysRTAX_DST = C.RTAX_DST
+ sysRTAX_GATEWAY = C.RTAX_GATEWAY
+ sysRTAX_NETMASK = C.RTAX_NETMASK
+ sysRTAX_GENMASK = C.RTAX_GENMASK
+ sysRTAX_IFP = C.RTAX_IFP
+ sysRTAX_IFA = C.RTAX_IFA
+ sysRTAX_AUTHOR = C.RTAX_AUTHOR
+ sysRTAX_BRD = C.RTAX_BRD
+ sysRTAX_MAX = C.RTAX_MAX
+)
+
+const (
+ sizeofIfMsghdrDarwin15 = C.sizeof_struct_if_msghdr
+ sizeofIfaMsghdrDarwin15 = C.sizeof_struct_ifa_msghdr
+ sizeofIfmaMsghdrDarwin15 = C.sizeof_struct_ifma_msghdr
+ sizeofIfMsghdr2Darwin15 = C.sizeof_struct_if_msghdr2
+ sizeofIfmaMsghdr2Darwin15 = C.sizeof_struct_ifma_msghdr2
+ sizeofIfDataDarwin15 = C.sizeof_struct_if_data
+ sizeofIfData64Darwin15 = C.sizeof_struct_if_data64
+
+ sizeofRtMsghdrDarwin15 = C.sizeof_struct_rt_msghdr
+ sizeofRtMsghdr2Darwin15 = C.sizeof_struct_rt_msghdr2
+ sizeofRtMetricsDarwin15 = C.sizeof_struct_rt_metrics
+
+ sizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage
+ sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
+ sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/defs_dragonfly.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/defs_dragonfly.go
new file mode 100644
index 000000000..dd31de269
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/defs_dragonfly.go
@@ -0,0 +1,113 @@
+// 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.
+
+// +build ignore
+
+package route
+
+/*
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/route.h>
+
+#include <netinet/in.h>
+*/
+import "C"
+
+const (
+ sysAF_UNSPEC = C.AF_UNSPEC
+ sysAF_INET = C.AF_INET
+ sysAF_ROUTE = C.AF_ROUTE
+ sysAF_LINK = C.AF_LINK
+ sysAF_INET6 = C.AF_INET6
+
+ sysSOCK_RAW = C.SOCK_RAW
+
+ sysNET_RT_DUMP = C.NET_RT_DUMP
+ sysNET_RT_FLAGS = C.NET_RT_FLAGS
+ sysNET_RT_IFLIST = C.NET_RT_IFLIST
+ sysNET_RT_MAXID = C.NET_RT_MAXID
+)
+
+const (
+ sysCTL_MAXNAME = C.CTL_MAXNAME
+
+ sysCTL_UNSPEC = C.CTL_UNSPEC
+ sysCTL_KERN = C.CTL_KERN
+ sysCTL_VM = C.CTL_VM
+ sysCTL_VFS = C.CTL_VFS
+ sysCTL_NET = C.CTL_NET
+ sysCTL_DEBUG = C.CTL_DEBUG
+ sysCTL_HW = C.CTL_HW
+ sysCTL_MACHDEP = C.CTL_MACHDEP
+ sysCTL_USER = C.CTL_USER
+ sysCTL_P1003_1B = C.CTL_P1003_1B
+ sysCTL_LWKT = C.CTL_LWKT
+ sysCTL_MAXID = C.CTL_MAXID
+)
+
+const (
+ sysRTM_VERSION = C.RTM_VERSION
+
+ sysRTM_ADD = C.RTM_ADD
+ sysRTM_DELETE = C.RTM_DELETE
+ sysRTM_CHANGE = C.RTM_CHANGE
+ sysRTM_GET = C.RTM_GET
+ sysRTM_LOSING = C.RTM_LOSING
+ sysRTM_REDIRECT = C.RTM_REDIRECT
+ sysRTM_MISS = C.RTM_MISS
+ sysRTM_LOCK = C.RTM_LOCK
+ sysRTM_OLDADD = C.RTM_OLDADD
+ sysRTM_OLDDEL = C.RTM_OLDDEL
+ sysRTM_RESOLVE = C.RTM_RESOLVE
+ sysRTM_NEWADDR = C.RTM_NEWADDR
+ sysRTM_DELADDR = C.RTM_DELADDR
+ sysRTM_IFINFO = C.RTM_IFINFO
+ sysRTM_NEWMADDR = C.RTM_NEWMADDR
+ sysRTM_DELMADDR = C.RTM_DELMADDR
+ sysRTM_IFANNOUNCE = C.RTM_IFANNOUNCE
+ sysRTM_IEEE80211 = C.RTM_IEEE80211
+
+ sysRTA_DST = C.RTA_DST
+ sysRTA_GATEWAY = C.RTA_GATEWAY
+ sysRTA_NETMASK = C.RTA_NETMASK
+ sysRTA_GENMASK = C.RTA_GENMASK
+ sysRTA_IFP = C.RTA_IFP
+ sysRTA_IFA = C.RTA_IFA
+ sysRTA_AUTHOR = C.RTA_AUTHOR
+ sysRTA_BRD = C.RTA_BRD
+ sysRTA_MPLS1 = C.RTA_MPLS1
+ sysRTA_MPLS2 = C.RTA_MPLS2
+ sysRTA_MPLS3 = C.RTA_MPLS3
+
+ sysRTAX_DST = C.RTAX_DST
+ sysRTAX_GATEWAY = C.RTAX_GATEWAY
+ sysRTAX_NETMASK = C.RTAX_NETMASK
+ sysRTAX_GENMASK = C.RTAX_GENMASK
+ sysRTAX_IFP = C.RTAX_IFP
+ sysRTAX_IFA = C.RTAX_IFA
+ sysRTAX_AUTHOR = C.RTAX_AUTHOR
+ sysRTAX_BRD = C.RTAX_BRD
+ sysRTAX_MPLS1 = C.RTAX_MPLS1
+ sysRTAX_MPLS2 = C.RTAX_MPLS2
+ sysRTAX_MPLS3 = C.RTAX_MPLS3
+ sysRTAX_MAX = C.RTAX_MAX
+)
+
+const (
+ sizeofIfMsghdrDragonFlyBSD4 = C.sizeof_struct_if_msghdr
+ sizeofIfaMsghdrDragonFlyBSD4 = C.sizeof_struct_ifa_msghdr
+ sizeofIfmaMsghdrDragonFlyBSD4 = C.sizeof_struct_ifma_msghdr
+ sizeofIfAnnouncemsghdrDragonFlyBSD4 = C.sizeof_struct_if_announcemsghdr
+
+ sizeofRtMsghdrDragonFlyBSD4 = C.sizeof_struct_rt_msghdr
+ sizeofRtMetricsDragonFlyBSD4 = C.sizeof_struct_rt_metrics
+
+ sizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage
+ sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
+ sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/defs_freebsd.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/defs_freebsd.go
new file mode 100644
index 000000000..d95594d8e
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/defs_freebsd.go
@@ -0,0 +1,337 @@
+// 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.
+
+// +build ignore
+
+package route
+
+/*
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/route.h>
+
+#include <netinet/in.h>
+
+struct if_data_freebsd7 {
+ u_char ifi_type;
+ u_char ifi_physical;
+ u_char ifi_addrlen;
+ u_char ifi_hdrlen;
+ u_char ifi_link_state;
+ u_char ifi_spare_char1;
+ u_char ifi_spare_char2;
+ u_char ifi_datalen;
+ u_long ifi_mtu;
+ u_long ifi_metric;
+ u_long ifi_baudrate;
+ u_long ifi_ipackets;
+ u_long ifi_ierrors;
+ u_long ifi_opackets;
+ u_long ifi_oerrors;
+ u_long ifi_collisions;
+ u_long ifi_ibytes;
+ u_long ifi_obytes;
+ u_long ifi_imcasts;
+ u_long ifi_omcasts;
+ u_long ifi_iqdrops;
+ u_long ifi_noproto;
+ u_long ifi_hwassist;
+ time_t __ifi_epoch;
+ struct timeval __ifi_lastchange;
+};
+
+struct if_data_freebsd8 {
+ u_char ifi_type;
+ u_char ifi_physical;
+ u_char ifi_addrlen;
+ u_char ifi_hdrlen;
+ u_char ifi_link_state;
+ u_char ifi_spare_char1;
+ u_char ifi_spare_char2;
+ u_char ifi_datalen;
+ u_long ifi_mtu;
+ u_long ifi_metric;
+ u_long ifi_baudrate;
+ u_long ifi_ipackets;
+ u_long ifi_ierrors;
+ u_long ifi_opackets;
+ u_long ifi_oerrors;
+ u_long ifi_collisions;
+ u_long ifi_ibytes;
+ u_long ifi_obytes;
+ u_long ifi_imcasts;
+ u_long ifi_omcasts;
+ u_long ifi_iqdrops;
+ u_long ifi_noproto;
+ u_long ifi_hwassist;
+ time_t __ifi_epoch;
+ struct timeval __ifi_lastchange;
+};
+
+struct if_data_freebsd9 {
+ u_char ifi_type;
+ u_char ifi_physical;
+ u_char ifi_addrlen;
+ u_char ifi_hdrlen;
+ u_char ifi_link_state;
+ u_char ifi_spare_char1;
+ u_char ifi_spare_char2;
+ u_char ifi_datalen;
+ u_long ifi_mtu;
+ u_long ifi_metric;
+ u_long ifi_baudrate;
+ u_long ifi_ipackets;
+ u_long ifi_ierrors;
+ u_long ifi_opackets;
+ u_long ifi_oerrors;
+ u_long ifi_collisions;
+ u_long ifi_ibytes;
+ u_long ifi_obytes;
+ u_long ifi_imcasts;
+ u_long ifi_omcasts;
+ u_long ifi_iqdrops;
+ u_long ifi_noproto;
+ u_long ifi_hwassist;
+ time_t __ifi_epoch;
+ struct timeval __ifi_lastchange;
+};
+
+struct if_data_freebsd10 {
+ u_char ifi_type;
+ u_char ifi_physical;
+ u_char ifi_addrlen;
+ u_char ifi_hdrlen;
+ u_char ifi_link_state;
+ u_char ifi_vhid;
+ u_char ifi_baudrate_pf;
+ u_char ifi_datalen;
+ u_long ifi_mtu;
+ u_long ifi_metric;
+ u_long ifi_baudrate;
+ u_long ifi_ipackets;
+ u_long ifi_ierrors;
+ u_long ifi_opackets;
+ u_long ifi_oerrors;
+ u_long ifi_collisions;
+ u_long ifi_ibytes;
+ u_long ifi_obytes;
+ u_long ifi_imcasts;
+ u_long ifi_omcasts;
+ u_long ifi_iqdrops;
+ u_long ifi_noproto;
+ uint64_t ifi_hwassist;
+ time_t __ifi_epoch;
+ struct timeval __ifi_lastchange;
+};
+
+struct if_data_freebsd11 {
+ uint8_t ifi_type;
+ uint8_t ifi_physical;
+ uint8_t ifi_addrlen;
+ uint8_t ifi_hdrlen;
+ uint8_t ifi_link_state;
+ uint8_t ifi_vhid;
+ uint16_t ifi_datalen;
+ uint32_t ifi_mtu;
+ uint32_t ifi_metric;
+ uint64_t ifi_baudrate;
+ uint64_t ifi_ipackets;
+ uint64_t ifi_ierrors;
+ uint64_t ifi_opackets;
+ uint64_t ifi_oerrors;
+ uint64_t ifi_collisions;
+ uint64_t ifi_ibytes;
+ uint64_t ifi_obytes;
+ uint64_t ifi_imcasts;
+ uint64_t ifi_omcasts;
+ uint64_t ifi_iqdrops;
+ uint64_t ifi_oqdrops;
+ uint64_t ifi_noproto;
+ uint64_t ifi_hwassist;
+ union {
+ time_t tt;
+ uint64_t ph;
+ } __ifi_epoch;
+ union {
+ struct timeval tv;
+ struct {
+ uint64_t ph1;
+ uint64_t ph2;
+ } ph;
+ } __ifi_lastchange;
+};
+
+struct if_msghdr_freebsd7 {
+ u_short ifm_msglen;
+ u_char ifm_version;
+ u_char ifm_type;
+ int ifm_addrs;
+ int ifm_flags;
+ u_short ifm_index;
+ struct if_data_freebsd7 ifm_data;
+};
+
+struct if_msghdr_freebsd8 {
+ u_short ifm_msglen;
+ u_char ifm_version;
+ u_char ifm_type;
+ int ifm_addrs;
+ int ifm_flags;
+ u_short ifm_index;
+ struct if_data_freebsd8 ifm_data;
+};
+
+struct if_msghdr_freebsd9 {
+ u_short ifm_msglen;
+ u_char ifm_version;
+ u_char ifm_type;
+ int ifm_addrs;
+ int ifm_flags;
+ u_short ifm_index;
+ struct if_data_freebsd9 ifm_data;
+};
+
+struct if_msghdr_freebsd10 {
+ u_short ifm_msglen;
+ u_char ifm_version;
+ u_char ifm_type;
+ int ifm_addrs;
+ int ifm_flags;
+ u_short ifm_index;
+ struct if_data_freebsd10 ifm_data;
+};
+
+struct if_msghdr_freebsd11 {
+ u_short ifm_msglen;
+ u_char ifm_version;
+ u_char ifm_type;
+ int ifm_addrs;
+ int ifm_flags;
+ u_short ifm_index;
+ struct if_data_freebsd11 ifm_data;
+};
+*/
+import "C"
+
+const (
+ sysAF_UNSPEC = C.AF_UNSPEC
+ sysAF_INET = C.AF_INET
+ sysAF_ROUTE = C.AF_ROUTE
+ sysAF_LINK = C.AF_LINK
+ sysAF_INET6 = C.AF_INET6
+
+ sysSOCK_RAW = C.SOCK_RAW
+
+ sysNET_RT_DUMP = C.NET_RT_DUMP
+ sysNET_RT_FLAGS = C.NET_RT_FLAGS
+ sysNET_RT_IFLIST = C.NET_RT_IFLIST
+ sysNET_RT_IFMALIST = C.NET_RT_IFMALIST
+ sysNET_RT_IFLISTL = C.NET_RT_IFLISTL
+)
+
+const (
+ sysCTL_MAXNAME = C.CTL_MAXNAME
+
+ sysCTL_UNSPEC = C.CTL_UNSPEC
+ sysCTL_KERN = C.CTL_KERN
+ sysCTL_VM = C.CTL_VM
+ sysCTL_VFS = C.CTL_VFS
+ sysCTL_NET = C.CTL_NET
+ sysCTL_DEBUG = C.CTL_DEBUG
+ sysCTL_HW = C.CTL_HW
+ sysCTL_MACHDEP = C.CTL_MACHDEP
+ sysCTL_USER = C.CTL_USER
+ sysCTL_P1003_1B = C.CTL_P1003_1B
+)
+
+const (
+ sysRTM_VERSION = C.RTM_VERSION
+
+ sysRTM_ADD = C.RTM_ADD
+ sysRTM_DELETE = C.RTM_DELETE
+ sysRTM_CHANGE = C.RTM_CHANGE
+ sysRTM_GET = C.RTM_GET
+ sysRTM_LOSING = C.RTM_LOSING
+ sysRTM_REDIRECT = C.RTM_REDIRECT
+ sysRTM_MISS = C.RTM_MISS
+ sysRTM_LOCK = C.RTM_LOCK
+ sysRTM_RESOLVE = C.RTM_RESOLVE
+ sysRTM_NEWADDR = C.RTM_NEWADDR
+ sysRTM_DELADDR = C.RTM_DELADDR
+ sysRTM_IFINFO = C.RTM_IFINFO
+ sysRTM_NEWMADDR = C.RTM_NEWMADDR
+ sysRTM_DELMADDR = C.RTM_DELMADDR
+ sysRTM_IFANNOUNCE = C.RTM_IFANNOUNCE
+ sysRTM_IEEE80211 = C.RTM_IEEE80211
+
+ sysRTA_DST = C.RTA_DST
+ sysRTA_GATEWAY = C.RTA_GATEWAY
+ sysRTA_NETMASK = C.RTA_NETMASK
+ sysRTA_GENMASK = C.RTA_GENMASK
+ sysRTA_IFP = C.RTA_IFP
+ sysRTA_IFA = C.RTA_IFA
+ sysRTA_AUTHOR = C.RTA_AUTHOR
+ sysRTA_BRD = C.RTA_BRD
+
+ sysRTAX_DST = C.RTAX_DST
+ sysRTAX_GATEWAY = C.RTAX_GATEWAY
+ sysRTAX_NETMASK = C.RTAX_NETMASK
+ sysRTAX_GENMASK = C.RTAX_GENMASK
+ sysRTAX_IFP = C.RTAX_IFP
+ sysRTAX_IFA = C.RTAX_IFA
+ sysRTAX_AUTHOR = C.RTAX_AUTHOR
+ sysRTAX_BRD = C.RTAX_BRD
+ sysRTAX_MAX = C.RTAX_MAX
+)
+
+const (
+ sizeofIfMsghdrlFreeBSD10 = C.sizeof_struct_if_msghdrl
+ sizeofIfaMsghdrFreeBSD10 = C.sizeof_struct_ifa_msghdr
+ sizeofIfaMsghdrlFreeBSD10 = C.sizeof_struct_ifa_msghdrl
+ sizeofIfmaMsghdrFreeBSD10 = C.sizeof_struct_ifma_msghdr
+ sizeofIfAnnouncemsghdrFreeBSD10 = C.sizeof_struct_if_announcemsghdr
+
+ sizeofRtMsghdrFreeBSD10 = C.sizeof_struct_rt_msghdr
+ sizeofRtMetricsFreeBSD10 = C.sizeof_struct_rt_metrics
+
+ sizeofIfMsghdrFreeBSD7 = C.sizeof_struct_if_msghdr_freebsd7
+ sizeofIfMsghdrFreeBSD8 = C.sizeof_struct_if_msghdr_freebsd8
+ sizeofIfMsghdrFreeBSD9 = C.sizeof_struct_if_msghdr_freebsd9
+ sizeofIfMsghdrFreeBSD10 = C.sizeof_struct_if_msghdr_freebsd10
+ sizeofIfMsghdrFreeBSD11 = C.sizeof_struct_if_msghdr_freebsd11
+
+ sizeofIfDataFreeBSD7 = C.sizeof_struct_if_data_freebsd7
+ sizeofIfDataFreeBSD8 = C.sizeof_struct_if_data_freebsd8
+ sizeofIfDataFreeBSD9 = C.sizeof_struct_if_data_freebsd9
+ sizeofIfDataFreeBSD10 = C.sizeof_struct_if_data_freebsd10
+ sizeofIfDataFreeBSD11 = C.sizeof_struct_if_data_freebsd11
+
+ sizeofIfMsghdrlFreeBSD10Emu = C.sizeof_struct_if_msghdrl
+ sizeofIfaMsghdrFreeBSD10Emu = C.sizeof_struct_ifa_msghdr
+ sizeofIfaMsghdrlFreeBSD10Emu = C.sizeof_struct_ifa_msghdrl
+ sizeofIfmaMsghdrFreeBSD10Emu = C.sizeof_struct_ifma_msghdr
+ sizeofIfAnnouncemsghdrFreeBSD10Emu = C.sizeof_struct_if_announcemsghdr
+
+ sizeofRtMsghdrFreeBSD10Emu = C.sizeof_struct_rt_msghdr
+ sizeofRtMetricsFreeBSD10Emu = C.sizeof_struct_rt_metrics
+
+ sizeofIfMsghdrFreeBSD7Emu = C.sizeof_struct_if_msghdr_freebsd7
+ sizeofIfMsghdrFreeBSD8Emu = C.sizeof_struct_if_msghdr_freebsd8
+ sizeofIfMsghdrFreeBSD9Emu = C.sizeof_struct_if_msghdr_freebsd9
+ sizeofIfMsghdrFreeBSD10Emu = C.sizeof_struct_if_msghdr_freebsd10
+ sizeofIfMsghdrFreeBSD11Emu = C.sizeof_struct_if_msghdr_freebsd11
+
+ sizeofIfDataFreeBSD7Emu = C.sizeof_struct_if_data_freebsd7
+ sizeofIfDataFreeBSD8Emu = C.sizeof_struct_if_data_freebsd8
+ sizeofIfDataFreeBSD9Emu = C.sizeof_struct_if_data_freebsd9
+ sizeofIfDataFreeBSD10Emu = C.sizeof_struct_if_data_freebsd10
+ sizeofIfDataFreeBSD11Emu = C.sizeof_struct_if_data_freebsd11
+
+ sizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage
+ sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
+ sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/defs_netbsd.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/defs_netbsd.go
new file mode 100644
index 000000000..b0abd549a
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/defs_netbsd.go
@@ -0,0 +1,112 @@
+// 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.
+
+// +build ignore
+
+package route
+
+/*
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/route.h>
+
+#include <netinet/in.h>
+*/
+import "C"
+
+const (
+ sysAF_UNSPEC = C.AF_UNSPEC
+ sysAF_INET = C.AF_INET
+ sysAF_ROUTE = C.AF_ROUTE
+ sysAF_LINK = C.AF_LINK
+ sysAF_INET6 = C.AF_INET6
+
+ sysSOCK_RAW = C.SOCK_RAW
+
+ sysNET_RT_DUMP = C.NET_RT_DUMP
+ sysNET_RT_FLAGS = C.NET_RT_FLAGS
+ sysNET_RT_IFLIST = C.NET_RT_IFLIST
+ sysNET_RT_MAXID = C.NET_RT_MAXID
+)
+
+const (
+ sysCTL_MAXNAME = C.CTL_MAXNAME
+
+ sysCTL_UNSPEC = C.CTL_UNSPEC
+ sysCTL_KERN = C.CTL_KERN
+ sysCTL_VM = C.CTL_VM
+ sysCTL_VFS = C.CTL_VFS
+ sysCTL_NET = C.CTL_NET
+ sysCTL_DEBUG = C.CTL_DEBUG
+ sysCTL_HW = C.CTL_HW
+ sysCTL_MACHDEP = C.CTL_MACHDEP
+ sysCTL_USER = C.CTL_USER
+ sysCTL_DDB = C.CTL_DDB
+ sysCTL_PROC = C.CTL_PROC
+ sysCTL_VENDOR = C.CTL_VENDOR
+ sysCTL_EMUL = C.CTL_EMUL
+ sysCTL_SECURITY = C.CTL_SECURITY
+ sysCTL_MAXID = C.CTL_MAXID
+)
+
+const (
+ sysRTM_VERSION = C.RTM_VERSION
+
+ sysRTM_ADD = C.RTM_ADD
+ sysRTM_DELETE = C.RTM_DELETE
+ sysRTM_CHANGE = C.RTM_CHANGE
+ sysRTM_GET = C.RTM_GET
+ sysRTM_LOSING = C.RTM_LOSING
+ sysRTM_REDIRECT = C.RTM_REDIRECT
+ sysRTM_MISS = C.RTM_MISS
+ sysRTM_LOCK = C.RTM_LOCK
+ sysRTM_OLDADD = C.RTM_OLDADD
+ sysRTM_OLDDEL = C.RTM_OLDDEL
+ sysRTM_RESOLVE = C.RTM_RESOLVE
+ sysRTM_NEWADDR = C.RTM_NEWADDR
+ sysRTM_DELADDR = C.RTM_DELADDR
+ sysRTM_IFANNOUNCE = C.RTM_IFANNOUNCE
+ sysRTM_IEEE80211 = C.RTM_IEEE80211
+ sysRTM_SETGATE = C.RTM_SETGATE
+ sysRTM_LLINFO_UPD = C.RTM_LLINFO_UPD
+ sysRTM_IFINFO = C.RTM_IFINFO
+ sysRTM_CHGADDR = C.RTM_CHGADDR
+
+ sysRTA_DST = C.RTA_DST
+ sysRTA_GATEWAY = C.RTA_GATEWAY
+ sysRTA_NETMASK = C.RTA_NETMASK
+ sysRTA_GENMASK = C.RTA_GENMASK
+ sysRTA_IFP = C.RTA_IFP
+ sysRTA_IFA = C.RTA_IFA
+ sysRTA_AUTHOR = C.RTA_AUTHOR
+ sysRTA_BRD = C.RTA_BRD
+ sysRTA_TAG = C.RTA_TAG
+
+ sysRTAX_DST = C.RTAX_DST
+ sysRTAX_GATEWAY = C.RTAX_GATEWAY
+ sysRTAX_NETMASK = C.RTAX_NETMASK
+ sysRTAX_GENMASK = C.RTAX_GENMASK
+ sysRTAX_IFP = C.RTAX_IFP
+ sysRTAX_IFA = C.RTAX_IFA
+ sysRTAX_AUTHOR = C.RTAX_AUTHOR
+ sysRTAX_BRD = C.RTAX_BRD
+ sysRTAX_TAG = C.RTAX_TAG
+ sysRTAX_MAX = C.RTAX_MAX
+)
+
+const (
+ sizeofIfMsghdrNetBSD7 = C.sizeof_struct_if_msghdr
+ sizeofIfaMsghdrNetBSD7 = C.sizeof_struct_ifa_msghdr
+ sizeofIfAnnouncemsghdrNetBSD7 = C.sizeof_struct_if_announcemsghdr
+
+ sizeofRtMsghdrNetBSD7 = C.sizeof_struct_rt_msghdr
+ sizeofRtMetricsNetBSD7 = C.sizeof_struct_rt_metrics
+
+ sizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage
+ sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
+ sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/defs_openbsd.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/defs_openbsd.go
new file mode 100644
index 000000000..173bb5d51
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/defs_openbsd.go
@@ -0,0 +1,116 @@
+// 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.
+
+// +build ignore
+
+package route
+
+/*
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/route.h>
+
+#include <netinet/in.h>
+*/
+import "C"
+
+const (
+ sysAF_UNSPEC = C.AF_UNSPEC
+ sysAF_INET = C.AF_INET
+ sysAF_ROUTE = C.AF_ROUTE
+ sysAF_LINK = C.AF_LINK
+ sysAF_INET6 = C.AF_INET6
+
+ sysSOCK_RAW = C.SOCK_RAW
+
+ sysNET_RT_DUMP = C.NET_RT_DUMP
+ sysNET_RT_FLAGS = C.NET_RT_FLAGS
+ sysNET_RT_IFLIST = C.NET_RT_IFLIST
+ sysNET_RT_STATS = C.NET_RT_STATS
+ sysNET_RT_TABLE = C.NET_RT_TABLE
+ sysNET_RT_IFNAMES = C.NET_RT_IFNAMES
+ sysNET_RT_MAXID = C.NET_RT_MAXID
+)
+
+const (
+ sysCTL_MAXNAME = C.CTL_MAXNAME
+
+ sysCTL_UNSPEC = C.CTL_UNSPEC
+ sysCTL_KERN = C.CTL_KERN
+ sysCTL_VM = C.CTL_VM
+ sysCTL_FS = C.CTL_FS
+ sysCTL_NET = C.CTL_NET
+ sysCTL_DEBUG = C.CTL_DEBUG
+ sysCTL_HW = C.CTL_HW
+ sysCTL_MACHDEP = C.CTL_MACHDEP
+ sysCTL_DDB = C.CTL_DDB
+ sysCTL_VFS = C.CTL_VFS
+ sysCTL_MAXID = C.CTL_MAXID
+)
+
+const (
+ sysRTM_VERSION = C.RTM_VERSION
+
+ sysRTM_ADD = C.RTM_ADD
+ sysRTM_DELETE = C.RTM_DELETE
+ sysRTM_CHANGE = C.RTM_CHANGE
+ sysRTM_GET = C.RTM_GET
+ sysRTM_LOSING = C.RTM_LOSING
+ sysRTM_REDIRECT = C.RTM_REDIRECT
+ sysRTM_MISS = C.RTM_MISS
+ sysRTM_LOCK = C.RTM_LOCK
+ sysRTM_RESOLVE = C.RTM_RESOLVE
+ sysRTM_NEWADDR = C.RTM_NEWADDR
+ sysRTM_DELADDR = C.RTM_DELADDR
+ sysRTM_IFINFO = C.RTM_IFINFO
+ sysRTM_IFANNOUNCE = C.RTM_IFANNOUNCE
+ sysRTM_DESYNC = C.RTM_DESYNC
+ sysRTM_INVALIDATE = C.RTM_INVALIDATE
+ sysRTM_BFD = C.RTM_BFD
+ sysRTM_PROPOSAL = C.RTM_PROPOSAL
+
+ sysRTA_DST = C.RTA_DST
+ sysRTA_GATEWAY = C.RTA_GATEWAY
+ sysRTA_NETMASK = C.RTA_NETMASK
+ sysRTA_GENMASK = C.RTA_GENMASK
+ sysRTA_IFP = C.RTA_IFP
+ sysRTA_IFA = C.RTA_IFA
+ sysRTA_AUTHOR = C.RTA_AUTHOR
+ sysRTA_BRD = C.RTA_BRD
+ sysRTA_SRC = C.RTA_SRC
+ sysRTA_SRCMASK = C.RTA_SRCMASK
+ sysRTA_LABEL = C.RTA_LABEL
+ sysRTA_BFD = C.RTA_BFD
+ sysRTA_DNS = C.RTA_DNS
+ sysRTA_STATIC = C.RTA_STATIC
+ sysRTA_SEARCH = C.RTA_SEARCH
+
+ sysRTAX_DST = C.RTAX_DST
+ sysRTAX_GATEWAY = C.RTAX_GATEWAY
+ sysRTAX_NETMASK = C.RTAX_NETMASK
+ sysRTAX_GENMASK = C.RTAX_GENMASK
+ sysRTAX_IFP = C.RTAX_IFP
+ sysRTAX_IFA = C.RTAX_IFA
+ sysRTAX_AUTHOR = C.RTAX_AUTHOR
+ sysRTAX_BRD = C.RTAX_BRD
+ sysRTAX_SRC = C.RTAX_SRC
+ sysRTAX_SRCMASK = C.RTAX_SRCMASK
+ sysRTAX_LABEL = C.RTAX_LABEL
+ sysRTAX_BFD = C.RTAX_BFD
+ sysRTAX_DNS = C.RTAX_DNS
+ sysRTAX_STATIC = C.RTAX_STATIC
+ sysRTAX_SEARCH = C.RTAX_SEARCH
+ sysRTAX_MAX = C.RTAX_MAX
+)
+
+const (
+ sizeofRtMsghdr = C.sizeof_struct_rt_msghdr
+
+ sizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage
+ sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
+ sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/interface.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/interface.go
new file mode 100644
index 000000000..854906d9c
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/interface.go
@@ -0,0 +1,64 @@
+// 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.
+
+// +build darwin dragonfly freebsd netbsd openbsd
+
+package route
+
+// An InterfaceMessage represents an interface message.
+type InterfaceMessage struct {
+ Version int // message version
+ Type int // message type
+ Flags int // interface flags
+ Index int // interface index
+ Name string // interface name
+ Addrs []Addr // addresses
+
+ extOff int // offset of header extension
+ raw []byte // raw message
+}
+
+// An InterfaceAddrMessage represents an interface address message.
+type InterfaceAddrMessage struct {
+ Version int // message version
+ Type int // message type
+ Flags int // interface flags
+ Index int // interface index
+ Addrs []Addr // addresses
+
+ raw []byte // raw message
+}
+
+// Sys implements the Sys method of Message interface.
+func (m *InterfaceAddrMessage) Sys() []Sys { return nil }
+
+// An InterfaceMulticastAddrMessage represents an interface multicast
+// address message.
+type InterfaceMulticastAddrMessage struct {
+ Version int // message version
+ Type int // messsage type
+ Flags int // interface flags
+ Index int // interface index
+ Addrs []Addr // addresses
+
+ raw []byte // raw message
+}
+
+// Sys implements the Sys method of Message interface.
+func (m *InterfaceMulticastAddrMessage) Sys() []Sys { return nil }
+
+// An InterfaceAnnounceMessage represents an interface announcement
+// message.
+type InterfaceAnnounceMessage struct {
+ Version int // message version
+ Type int // message type
+ Index int // interface index
+ Name string // interface name
+ What int // what type of announcement
+
+ raw []byte // raw message
+}
+
+// Sys implements the Sys method of Message interface.
+func (m *InterfaceAnnounceMessage) Sys() []Sys { return nil }
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/interface_announce.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/interface_announce.go
new file mode 100644
index 000000000..520d657b5
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/interface_announce.go
@@ -0,0 +1,32 @@
+// 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.
+
+// +build dragonfly freebsd netbsd
+
+package route
+
+func (w *wireFormat) parseInterfaceAnnounceMessage(_ RIBType, b []byte) (Message, error) {
+ if len(b) < w.bodyOff {
+ return nil, errMessageTooShort
+ }
+ l := int(nativeEndian.Uint16(b[:2]))
+ if len(b) < l {
+ return nil, errInvalidMessage
+ }
+ m := &InterfaceAnnounceMessage{
+ Version: int(b[2]),
+ Type: int(b[3]),
+ Index: int(nativeEndian.Uint16(b[4:6])),
+ What: int(nativeEndian.Uint16(b[22:24])),
+ raw: b[:l],
+ }
+ for i := 0; i < 16; i++ {
+ if b[6+i] != 0 {
+ continue
+ }
+ m.Name = string(b[6 : 6+i])
+ break
+ }
+ return m, nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/interface_classic.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/interface_classic.go
new file mode 100644
index 000000000..ac4e7a680
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/interface_classic.go
@@ -0,0 +1,66 @@
+// 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.
+
+// +build darwin dragonfly netbsd
+
+package route
+
+import "runtime"
+
+func (w *wireFormat) parseInterfaceMessage(_ RIBType, b []byte) (Message, error) {
+ if len(b) < w.bodyOff {
+ return nil, errMessageTooShort
+ }
+ l := int(nativeEndian.Uint16(b[:2]))
+ if len(b) < l {
+ return nil, errInvalidMessage
+ }
+ attrs := uint(nativeEndian.Uint32(b[4:8]))
+ if attrs&sysRTA_IFP == 0 {
+ return nil, nil
+ }
+ m := &InterfaceMessage{
+ Version: int(b[2]),
+ Type: int(b[3]),
+ Addrs: make([]Addr, sysRTAX_MAX),
+ Flags: int(nativeEndian.Uint32(b[8:12])),
+ Index: int(nativeEndian.Uint16(b[12:14])),
+ extOff: w.extOff,
+ raw: b[:l],
+ }
+ a, err := parseLinkAddr(b[w.bodyOff:])
+ if err != nil {
+ return nil, err
+ }
+ m.Addrs[sysRTAX_IFP] = a
+ m.Name = a.(*LinkAddr).Name
+ return m, nil
+}
+
+func (w *wireFormat) parseInterfaceAddrMessage(_ RIBType, b []byte) (Message, error) {
+ if len(b) < w.bodyOff {
+ return nil, errMessageTooShort
+ }
+ l := int(nativeEndian.Uint16(b[:2]))
+ if len(b) < l {
+ return nil, errInvalidMessage
+ }
+ m := &InterfaceAddrMessage{
+ Version: int(b[2]),
+ Type: int(b[3]),
+ Flags: int(nativeEndian.Uint32(b[8:12])),
+ raw: b[:l],
+ }
+ if runtime.GOOS == "netbsd" {
+ m.Index = int(nativeEndian.Uint16(b[16:18]))
+ } else {
+ m.Index = int(nativeEndian.Uint16(b[12:14]))
+ }
+ var err error
+ m.Addrs, err = parseAddrs(uint(nativeEndian.Uint32(b[4:8])), parseKernelInetAddr, b[w.bodyOff:])
+ if err != nil {
+ return nil, err
+ }
+ return m, nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/interface_freebsd.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/interface_freebsd.go
new file mode 100644
index 000000000..9f6f50c00
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/interface_freebsd.go
@@ -0,0 +1,78 @@
+// 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.
+
+package route
+
+func (w *wireFormat) parseInterfaceMessage(typ RIBType, b []byte) (Message, error) {
+ var extOff, bodyOff int
+ if typ == sysNET_RT_IFLISTL {
+ if len(b) < 20 {
+ return nil, errMessageTooShort
+ }
+ extOff = int(nativeEndian.Uint16(b[18:20]))
+ bodyOff = int(nativeEndian.Uint16(b[16:18]))
+ } else {
+ extOff = w.extOff
+ bodyOff = w.bodyOff
+ }
+ if len(b) < extOff || len(b) < bodyOff {
+ return nil, errInvalidMessage
+ }
+ l := int(nativeEndian.Uint16(b[:2]))
+ if len(b) < l {
+ return nil, errInvalidMessage
+ }
+ attrs := uint(nativeEndian.Uint32(b[4:8]))
+ if attrs&sysRTA_IFP == 0 {
+ return nil, nil
+ }
+ m := &InterfaceMessage{
+ Version: int(b[2]),
+ Type: int(b[3]),
+ Flags: int(nativeEndian.Uint32(b[8:12])),
+ Index: int(nativeEndian.Uint16(b[12:14])),
+ Addrs: make([]Addr, sysRTAX_MAX),
+ extOff: extOff,
+ raw: b[:l],
+ }
+ a, err := parseLinkAddr(b[bodyOff:])
+ if err != nil {
+ return nil, err
+ }
+ m.Addrs[sysRTAX_IFP] = a
+ m.Name = a.(*LinkAddr).Name
+ return m, nil
+}
+
+func (w *wireFormat) parseInterfaceAddrMessage(typ RIBType, b []byte) (Message, error) {
+ var bodyOff int
+ if typ == sysNET_RT_IFLISTL {
+ if len(b) < 24 {
+ return nil, errMessageTooShort
+ }
+ bodyOff = int(nativeEndian.Uint16(b[16:18]))
+ } else {
+ bodyOff = w.bodyOff
+ }
+ if len(b) < bodyOff {
+ return nil, errInvalidMessage
+ }
+ l := int(nativeEndian.Uint16(b[:2]))
+ if len(b) < l {
+ return nil, errInvalidMessage
+ }
+ m := &InterfaceAddrMessage{
+ Version: int(b[2]),
+ Type: int(b[3]),
+ Flags: int(nativeEndian.Uint32(b[8:12])),
+ Index: int(nativeEndian.Uint16(b[12:14])),
+ raw: b[:l],
+ }
+ var err error
+ m.Addrs, err = parseAddrs(uint(nativeEndian.Uint32(b[4:8])), parseKernelInetAddr, b[bodyOff:])
+ if err != nil {
+ return nil, err
+ }
+ return m, nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/interface_multicast.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/interface_multicast.go
new file mode 100644
index 000000000..1e99a9cc6
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/interface_multicast.go
@@ -0,0 +1,30 @@
+// 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.
+
+// +build darwin dragonfly freebsd
+
+package route
+
+func (w *wireFormat) parseInterfaceMulticastAddrMessage(_ RIBType, b []byte) (Message, error) {
+ if len(b) < w.bodyOff {
+ return nil, errMessageTooShort
+ }
+ l := int(nativeEndian.Uint16(b[:2]))
+ if len(b) < l {
+ return nil, errInvalidMessage
+ }
+ m := &InterfaceMulticastAddrMessage{
+ Version: int(b[2]),
+ Type: int(b[3]),
+ Flags: int(nativeEndian.Uint32(b[8:12])),
+ Index: int(nativeEndian.Uint16(b[12:14])),
+ raw: b[:l],
+ }
+ var err error
+ m.Addrs, err = parseAddrs(uint(nativeEndian.Uint32(b[4:8])), parseKernelInetAddr, b[w.bodyOff:])
+ if err != nil {
+ return nil, err
+ }
+ return m, nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/interface_openbsd.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/interface_openbsd.go
new file mode 100644
index 000000000..e4a143c1c
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/interface_openbsd.go
@@ -0,0 +1,90 @@
+// 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.
+
+package route
+
+func (*wireFormat) parseInterfaceMessage(_ RIBType, b []byte) (Message, error) {
+ if len(b) < 32 {
+ return nil, errMessageTooShort
+ }
+ l := int(nativeEndian.Uint16(b[:2]))
+ if len(b) < l {
+ return nil, errInvalidMessage
+ }
+ attrs := uint(nativeEndian.Uint32(b[12:16]))
+ if attrs&sysRTA_IFP == 0 {
+ return nil, nil
+ }
+ m := &InterfaceMessage{
+ Version: int(b[2]),
+ Type: int(b[3]),
+ Flags: int(nativeEndian.Uint32(b[16:20])),
+ Index: int(nativeEndian.Uint16(b[6:8])),
+ Addrs: make([]Addr, sysRTAX_MAX),
+ raw: b[:l],
+ }
+ ll := int(nativeEndian.Uint16(b[4:6]))
+ if len(b) < ll {
+ return nil, errInvalidMessage
+ }
+ a, err := parseLinkAddr(b[ll:])
+ if err != nil {
+ return nil, err
+ }
+ m.Addrs[sysRTAX_IFP] = a
+ m.Name = a.(*LinkAddr).Name
+ return m, nil
+}
+
+func (*wireFormat) parseInterfaceAddrMessage(_ RIBType, b []byte) (Message, error) {
+ if len(b) < 24 {
+ return nil, errMessageTooShort
+ }
+ l := int(nativeEndian.Uint16(b[:2]))
+ if len(b) < l {
+ return nil, errInvalidMessage
+ }
+ bodyOff := int(nativeEndian.Uint16(b[4:6]))
+ if len(b) < bodyOff {
+ return nil, errInvalidMessage
+ }
+ m := &InterfaceAddrMessage{
+ Version: int(b[2]),
+ Type: int(b[3]),
+ Flags: int(nativeEndian.Uint32(b[12:16])),
+ Index: int(nativeEndian.Uint16(b[6:8])),
+ raw: b[:l],
+ }
+ var err error
+ m.Addrs, err = parseAddrs(uint(nativeEndian.Uint32(b[12:16])), parseKernelInetAddr, b[bodyOff:])
+ if err != nil {
+ return nil, err
+ }
+ return m, nil
+}
+
+func (*wireFormat) parseInterfaceAnnounceMessage(_ RIBType, b []byte) (Message, error) {
+ if len(b) < 26 {
+ return nil, errMessageTooShort
+ }
+ l := int(nativeEndian.Uint16(b[:2]))
+ if len(b) < l {
+ return nil, errInvalidMessage
+ }
+ m := &InterfaceAnnounceMessage{
+ Version: int(b[2]),
+ Type: int(b[3]),
+ Index: int(nativeEndian.Uint16(b[6:8])),
+ What: int(nativeEndian.Uint16(b[8:10])),
+ raw: b[:l],
+ }
+ for i := 0; i < 16; i++ {
+ if b[10+i] != 0 {
+ continue
+ }
+ m.Name = string(b[10 : 10+i])
+ break
+ }
+ return m, nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/message.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/message.go
new file mode 100644
index 000000000..0fa7e09f4
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/message.go
@@ -0,0 +1,72 @@
+// 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.
+
+// +build darwin dragonfly freebsd netbsd openbsd
+
+package route
+
+// A Message represents a routing message.
+type Message interface {
+ // Sys returns operating system-specific information.
+ Sys() []Sys
+}
+
+// A Sys reprensents operating system-specific information.
+type Sys interface {
+ // SysType returns a type of operating system-specific
+ // information.
+ SysType() SysType
+}
+
+// A SysType represents a type of operating system-specific
+// information.
+type SysType int
+
+const (
+ SysMetrics SysType = iota
+ SysStats
+)
+
+// ParseRIB parses b as a routing information base and returns a list
+// of routing messages.
+func ParseRIB(typ RIBType, b []byte) ([]Message, error) {
+ if !typ.parseable() {
+ return nil, errUnsupportedMessage
+ }
+ var msgs []Message
+ nmsgs, nskips := 0, 0
+ for len(b) > 4 {
+ nmsgs++
+ l := int(nativeEndian.Uint16(b[:2]))
+ if l == 0 {
+ return nil, errInvalidMessage
+ }
+ if len(b) < l {
+ return nil, errMessageTooShort
+ }
+ if b[2] != sysRTM_VERSION {
+ b = b[l:]
+ continue
+ }
+ if w, ok := wireFormats[int(b[3])]; !ok {
+ nskips++
+ } else {
+ m, err := w.parse(typ, b)
+ if err != nil {
+ return nil, err
+ }
+ if m == nil {
+ nskips++
+ } else {
+ msgs = append(msgs, m)
+ }
+ }
+ b = b[l:]
+ }
+ // We failed to parse any of the messages - version mismatch?
+ if nmsgs != len(msgs)+nskips {
+ return nil, errMessageMismatch
+ }
+ return msgs, nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/message_darwin_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/message_darwin_test.go
new file mode 100644
index 000000000..316aa7507
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/message_darwin_test.go
@@ -0,0 +1,34 @@
+// 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.
+
+package route
+
+import "testing"
+
+func TestFetchAndParseRIBOnDarwin(t *testing.T) {
+ for _, typ := range []RIBType{sysNET_RT_FLAGS, sysNET_RT_DUMP2, sysNET_RT_IFLIST2} {
+ var lastErr error
+ var ms []Message
+ for _, af := range []int{sysAF_UNSPEC, sysAF_INET, sysAF_INET6} {
+ rs, err := fetchAndParseRIB(af, typ)
+ if err != nil {
+ lastErr = err
+ continue
+ }
+ ms = append(ms, rs...)
+ }
+ if len(ms) == 0 && lastErr != nil {
+ t.Error(typ, lastErr)
+ continue
+ }
+ ss, err := msgs(ms).validate()
+ if err != nil {
+ t.Error(typ, err)
+ continue
+ }
+ for _, s := range ss {
+ t.Log(s)
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/message_freebsd_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/message_freebsd_test.go
new file mode 100644
index 000000000..db4b56752
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/message_freebsd_test.go
@@ -0,0 +1,92 @@
+// 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.
+
+package route
+
+import (
+ "testing"
+ "unsafe"
+)
+
+func TestFetchAndParseRIBOnFreeBSD(t *testing.T) {
+ for _, typ := range []RIBType{sysNET_RT_IFMALIST} {
+ var lastErr error
+ var ms []Message
+ for _, af := range []int{sysAF_UNSPEC, sysAF_INET, sysAF_INET6} {
+ rs, err := fetchAndParseRIB(af, typ)
+ if err != nil {
+ lastErr = err
+ continue
+ }
+ ms = append(ms, rs...)
+ }
+ if len(ms) == 0 && lastErr != nil {
+ t.Error(typ, lastErr)
+ continue
+ }
+ ss, err := msgs(ms).validate()
+ if err != nil {
+ t.Error(typ, err)
+ continue
+ }
+ for _, s := range ss {
+ t.Log(s)
+ }
+ }
+}
+
+func TestFetchAndParseRIBOnFreeBSD10AndAbove(t *testing.T) {
+ if _, err := FetchRIB(sysAF_UNSPEC, sysNET_RT_IFLISTL, 0); err != nil {
+ t.Skip("NET_RT_IFLISTL not supported")
+ }
+ var p uintptr
+ if kernelAlign != int(unsafe.Sizeof(p)) {
+ t.Skip("NET_RT_IFLIST vs. NET_RT_IFLISTL doesn't work for 386 emulation on amd64")
+ }
+
+ var tests = [2]struct {
+ typ RIBType
+ b []byte
+ msgs []Message
+ ss []string
+ }{
+ {typ: sysNET_RT_IFLIST},
+ {typ: sysNET_RT_IFLISTL},
+ }
+ for i := range tests {
+ var lastErr error
+ for _, af := range []int{sysAF_UNSPEC, sysAF_INET, sysAF_INET6} {
+ rs, err := fetchAndParseRIB(af, tests[i].typ)
+ if err != nil {
+ lastErr = err
+ continue
+ }
+ tests[i].msgs = append(tests[i].msgs, rs...)
+ }
+ if len(tests[i].msgs) == 0 && lastErr != nil {
+ t.Error(tests[i].typ, lastErr)
+ continue
+ }
+ tests[i].ss, lastErr = msgs(tests[i].msgs).validate()
+ if lastErr != nil {
+ t.Error(tests[i].typ, lastErr)
+ continue
+ }
+ for _, s := range tests[i].ss {
+ t.Log(s)
+ }
+ }
+ for i := len(tests) - 1; i > 0; i-- {
+ if len(tests[i].ss) != len(tests[i-1].ss) {
+ t.Errorf("got %v; want %v", tests[i].ss, tests[i-1].ss)
+ continue
+ }
+ for j, s1 := range tests[i].ss {
+ s0 := tests[i-1].ss[j]
+ if s1 != s0 {
+ t.Errorf("got %s; want %s", s1, s0)
+ }
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/message_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/message_test.go
new file mode 100644
index 000000000..e848dabf4
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/message_test.go
@@ -0,0 +1,239 @@
+// 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.
+
+// +build darwin dragonfly freebsd netbsd openbsd
+
+package route
+
+import (
+ "os"
+ "syscall"
+ "testing"
+ "time"
+)
+
+func TestFetchAndParseRIB(t *testing.T) {
+ for _, typ := range []RIBType{sysNET_RT_DUMP, sysNET_RT_IFLIST} {
+ var lastErr error
+ var ms []Message
+ for _, af := range []int{sysAF_UNSPEC, sysAF_INET, sysAF_INET6} {
+ rs, err := fetchAndParseRIB(af, typ)
+ if err != nil {
+ lastErr = err
+ continue
+ }
+ ms = append(ms, rs...)
+ }
+ if len(ms) == 0 && lastErr != nil {
+ t.Error(typ, lastErr)
+ continue
+ }
+ ss, err := msgs(ms).validate()
+ if err != nil {
+ t.Error(typ, err)
+ continue
+ }
+ for _, s := range ss {
+ t.Log(typ, s)
+ }
+ }
+}
+
+var (
+ rtmonSock int
+ rtmonErr error
+)
+
+func init() {
+ // We need to keep rtmonSock alive to avoid treading on
+ // recycled socket descriptors.
+ rtmonSock, rtmonErr = syscall.Socket(sysAF_ROUTE, sysSOCK_RAW, sysAF_UNSPEC)
+}
+
+// TestMonitorAndParseRIB leaks a worker goroutine and a socket
+// descriptor but that's intentional.
+func TestMonitorAndParseRIB(t *testing.T) {
+ if testing.Short() || os.Getuid() != 0 {
+ t.Skip("must be root")
+ }
+
+ if rtmonErr != nil {
+ t.Fatal(rtmonErr)
+ }
+
+ // We suppose that using an IPv4 link-local address and the
+ // dot1Q ID for Token Ring and FDDI doesn't harm anyone.
+ pv := &propVirtual{addr: "169.254.0.1", mask: "255.255.255.0"}
+ if err := pv.configure(1002); err != nil {
+ t.Skip(err)
+ }
+ if err := pv.setup(); err != nil {
+ t.Skip(err)
+ }
+ pv.teardown()
+
+ go func() {
+ b := make([]byte, os.Getpagesize())
+ for {
+ // There's no easy way to unblock this read
+ // call because the routing message exchange
+ // over routing socket is a connectionless
+ // message-oriented protocol, no control plane
+ // for signaling connectivity, and we cannot
+ // use the net package of standard library due
+ // to the lack of support for routing socket
+ // and circular dependency.
+ n, err := syscall.Read(rtmonSock, b)
+ if err != nil {
+ return
+ }
+ ms, err := ParseRIB(0, b[:n])
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ ss, err := msgs(ms).validate()
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ for _, s := range ss {
+ t.Log(s)
+ }
+ }
+ }()
+
+ for _, vid := range []int{1002, 1003, 1004, 1005} {
+ pv := &propVirtual{addr: "169.254.0.1", mask: "255.255.255.0"}
+ if err := pv.configure(vid); err != nil {
+ t.Fatal(err)
+ }
+ if err := pv.setup(); err != nil {
+ t.Fatal(err)
+ }
+ time.Sleep(200 * time.Millisecond)
+ if err := pv.teardown(); err != nil {
+ t.Fatal(err)
+ }
+ time.Sleep(200 * time.Millisecond)
+ }
+}
+
+func TestParseRIBWithFuzz(t *testing.T) {
+ for _, fuzz := range []string{
+ "0\x00\x05\x050000000000000000" +
+ "00000000000000000000" +
+ "00000000000000000000" +
+ "00000000000000000000" +
+ "0000000000000\x02000000" +
+ "00000000",
+ "\x02\x00\x05\f0000000000000000" +
+ "0\x0200000000000000",
+ "\x02\x00\x05\x100000000000000\x1200" +
+ "0\x00\xff\x00",
+ "\x02\x00\x05\f0000000000000000" +
+ "0\x12000\x00\x02\x0000",
+ "\x00\x00\x00\x01\x00",
+ "00000",
+ } {
+ for typ := RIBType(0); typ < 256; typ++ {
+ ParseRIB(typ, []byte(fuzz))
+ }
+ }
+}
+
+func TestRouteMessage(t *testing.T) {
+ s, err := syscall.Socket(sysAF_ROUTE, sysSOCK_RAW, sysAF_UNSPEC)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer syscall.Close(s)
+
+ var ms []RouteMessage
+ for _, af := range []int{sysAF_INET, sysAF_INET6} {
+ if _, err := fetchAndParseRIB(af, sysNET_RT_DUMP); err != nil {
+ t.Log(err)
+ continue
+ }
+ switch af {
+ case sysAF_INET:
+ ms = append(ms, []RouteMessage{
+ {
+ Type: sysRTM_GET,
+ Addrs: []Addr{
+ &Inet4Addr{IP: [4]byte{127, 0, 0, 1}},
+ nil,
+ nil,
+ nil,
+ &LinkAddr{},
+ &Inet4Addr{},
+ nil,
+ &Inet4Addr{},
+ },
+ },
+ {
+ Type: sysRTM_GET,
+ Addrs: []Addr{
+ &Inet4Addr{IP: [4]byte{127, 0, 0, 1}},
+ },
+ },
+ }...)
+ case sysAF_INET6:
+ ms = append(ms, []RouteMessage{
+ {
+ Type: sysRTM_GET,
+ Addrs: []Addr{
+ &Inet6Addr{IP: [16]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}},
+ nil,
+ nil,
+ nil,
+ &LinkAddr{},
+ &Inet6Addr{},
+ nil,
+ &Inet6Addr{},
+ },
+ },
+ {
+ Type: sysRTM_GET,
+ Addrs: []Addr{
+ &Inet6Addr{IP: [16]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}},
+ },
+ },
+ }...)
+ }
+ }
+ for i, m := range ms {
+ m.ID = uintptr(os.Getpid())
+ m.Seq = i + 1
+ wb, err := m.Marshal()
+ if err != nil {
+ t.Fatalf("%v: %v", m, err)
+ }
+ if _, err := syscall.Write(s, wb); err != nil {
+ t.Fatalf("%v: %v", m, err)
+ }
+ rb := make([]byte, os.Getpagesize())
+ n, err := syscall.Read(s, rb)
+ if err != nil {
+ t.Fatalf("%v: %v", m, err)
+ }
+ rms, err := ParseRIB(0, rb[:n])
+ if err != nil {
+ t.Fatalf("%v: %v", m, err)
+ }
+ for _, rm := range rms {
+ err := rm.(*RouteMessage).Err
+ if err != nil {
+ t.Errorf("%v: %v", m, err)
+ }
+ }
+ ss, err := msgs(rms).validate()
+ if err != nil {
+ t.Fatalf("%v: %v", m, err)
+ }
+ for _, s := range ss {
+ t.Log(s)
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/route.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/route.go
new file mode 100644
index 000000000..081da0d5c
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/route.go
@@ -0,0 +1,123 @@
+// 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.
+
+// +build darwin dragonfly freebsd netbsd openbsd
+
+// Package route provides basic functions for the manipulation of
+// packet routing facilities on BSD variants.
+//
+// The package supports any version of Darwin, any version of
+// DragonFly BSD, FreeBSD 7 through 11, NetBSD 6 and above, and
+// OpenBSD 5.6 and above.
+package route
+
+import (
+ "errors"
+ "os"
+ "syscall"
+)
+
+var (
+ errUnsupportedMessage = errors.New("unsupported message")
+ errMessageMismatch = errors.New("message mismatch")
+ errMessageTooShort = errors.New("message too short")
+ errInvalidMessage = errors.New("invalid message")
+ errInvalidAddr = errors.New("invalid address")
+ errShortBuffer = errors.New("short buffer")
+)
+
+// A RouteMessage represents a message conveying an address prefix, a
+// nexthop address and an output interface.
+//
+// Unlike other messages, this message can be used to query adjacency
+// information for the given address prefix, to add a new route, and
+// to delete or modify the existing route from the routing information
+// base inside the kernel by writing and reading route messages on a
+// routing socket.
+//
+// For the manipulation of routing information, the route message must
+// contain appropriate fields that include:
+//
+// Version = <must be specified>
+// Type = <must be specified>
+// Flags = <must be specified>
+// Index = <must be specified if necessary>
+// ID = <must be specified>
+// Seq = <must be specified>
+// Addrs = <must be specified>
+//
+// The Type field specifies a type of manipulation, the Flags field
+// specifies a class of target information and the Addrs field
+// specifies target information like the following:
+//
+// route.RouteMessage{
+// Version: RTM_VERSION,
+// Type: RTM_GET,
+// Flags: RTF_UP | RTF_HOST,
+// ID: uintptr(os.Getpid()),
+// Seq: 1,
+// Addrs: []route.Addrs{
+// RTAX_DST: &route.Inet4Addr{ ... },
+// RTAX_IFP: &route.LinkAddr{ ... },
+// RTAX_BRD: &route.Inet4Addr{ ... },
+// },
+// }
+//
+// The values for the above fields depend on the implementation of
+// each operating system.
+//
+// The Err field on a response message contains an error value on the
+// requested operation. If non-nil, the requested operation is failed.
+type RouteMessage struct {
+ Version int // message version
+ Type int // message type
+ Flags int // route flags
+ Index int // interface index when atatched
+ ID uintptr // sender's identifier; usually process ID
+ Seq int // sequence number
+ Err error // error on requested operation
+ Addrs []Addr // addresses
+
+ extOff int // offset of header extension
+ raw []byte // raw message
+}
+
+// Marshal returns the binary encoding of m.
+func (m *RouteMessage) Marshal() ([]byte, error) {
+ return m.marshal()
+}
+
+// A RIBType reprensents a type of routing information base.
+type RIBType int
+
+const (
+ RIBTypeRoute RIBType = syscall.NET_RT_DUMP
+ RIBTypeInterface RIBType = syscall.NET_RT_IFLIST
+)
+
+// FetchRIB fetches a routing information base from the operating
+// system.
+//
+// The provided af must be an address family.
+//
+// The provided arg must be a RIBType-specific argument.
+// When RIBType is related to routes, arg might be a set of route
+// flags. When RIBType is related to network interfaces, arg might be
+// an interface index or a set of interface flags. In most cases, zero
+// means a wildcard.
+func FetchRIB(af int, typ RIBType, arg int) ([]byte, error) {
+ mib := [6]int32{sysCTL_NET, sysAF_ROUTE, 0, int32(af), int32(typ), int32(arg)}
+ n := uintptr(0)
+ if err := sysctl(mib[:], nil, &n, nil, 0); err != nil {
+ return nil, os.NewSyscallError("sysctl", err)
+ }
+ if n == 0 {
+ return nil, nil
+ }
+ b := make([]byte, n)
+ if err := sysctl(mib[:], &b[0], &n, nil, 0); err != nil {
+ return nil, os.NewSyscallError("sysctl", err)
+ }
+ return b[:n], nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/route_classic.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/route_classic.go
new file mode 100644
index 000000000..02fa68830
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/route_classic.go
@@ -0,0 +1,75 @@
+// 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.
+
+// +build darwin dragonfly freebsd netbsd
+
+package route
+
+import (
+ "runtime"
+ "syscall"
+)
+
+func (m *RouteMessage) marshal() ([]byte, error) {
+ w, ok := wireFormats[m.Type]
+ if !ok {
+ return nil, errUnsupportedMessage
+ }
+ l := w.bodyOff + addrsSpace(m.Addrs)
+ if runtime.GOOS == "darwin" {
+ // Fix stray pointer writes on macOS.
+ // See golang.org/issue/22456.
+ l += 1024
+ }
+ b := make([]byte, l)
+ nativeEndian.PutUint16(b[:2], uint16(l))
+ if m.Version == 0 {
+ b[2] = sysRTM_VERSION
+ } else {
+ b[2] = byte(m.Version)
+ }
+ b[3] = byte(m.Type)
+ nativeEndian.PutUint32(b[8:12], uint32(m.Flags))
+ nativeEndian.PutUint16(b[4:6], uint16(m.Index))
+ nativeEndian.PutUint32(b[16:20], uint32(m.ID))
+ nativeEndian.PutUint32(b[20:24], uint32(m.Seq))
+ attrs, err := marshalAddrs(b[w.bodyOff:], m.Addrs)
+ if err != nil {
+ return nil, err
+ }
+ if attrs > 0 {
+ nativeEndian.PutUint32(b[12:16], uint32(attrs))
+ }
+ return b, nil
+}
+
+func (w *wireFormat) parseRouteMessage(typ RIBType, b []byte) (Message, error) {
+ if len(b) < w.bodyOff {
+ return nil, errMessageTooShort
+ }
+ l := int(nativeEndian.Uint16(b[:2]))
+ if len(b) < l {
+ return nil, errInvalidMessage
+ }
+ m := &RouteMessage{
+ Version: int(b[2]),
+ Type: int(b[3]),
+ Flags: int(nativeEndian.Uint32(b[8:12])),
+ Index: int(nativeEndian.Uint16(b[4:6])),
+ ID: uintptr(nativeEndian.Uint32(b[16:20])),
+ Seq: int(nativeEndian.Uint32(b[20:24])),
+ extOff: w.extOff,
+ raw: b[:l],
+ }
+ errno := syscall.Errno(nativeEndian.Uint32(b[28:32]))
+ if errno != 0 {
+ m.Err = errno
+ }
+ var err error
+ m.Addrs, err = parseAddrs(uint(nativeEndian.Uint32(b[12:16])), parseKernelInetAddr, b[w.bodyOff:])
+ if err != nil {
+ return nil, err
+ }
+ return m, nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/route_openbsd.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/route_openbsd.go
new file mode 100644
index 000000000..daf2e90c4
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/route_openbsd.go
@@ -0,0 +1,65 @@
+// 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.
+
+package route
+
+import "syscall"
+
+func (m *RouteMessage) marshal() ([]byte, error) {
+ l := sizeofRtMsghdr + addrsSpace(m.Addrs)
+ b := make([]byte, l)
+ nativeEndian.PutUint16(b[:2], uint16(l))
+ if m.Version == 0 {
+ b[2] = sysRTM_VERSION
+ } else {
+ b[2] = byte(m.Version)
+ }
+ b[3] = byte(m.Type)
+ nativeEndian.PutUint16(b[4:6], uint16(sizeofRtMsghdr))
+ nativeEndian.PutUint32(b[16:20], uint32(m.Flags))
+ nativeEndian.PutUint16(b[6:8], uint16(m.Index))
+ nativeEndian.PutUint32(b[24:28], uint32(m.ID))
+ nativeEndian.PutUint32(b[28:32], uint32(m.Seq))
+ attrs, err := marshalAddrs(b[sizeofRtMsghdr:], m.Addrs)
+ if err != nil {
+ return nil, err
+ }
+ if attrs > 0 {
+ nativeEndian.PutUint32(b[12:16], uint32(attrs))
+ }
+ return b, nil
+}
+
+func (*wireFormat) parseRouteMessage(_ RIBType, b []byte) (Message, error) {
+ if len(b) < sizeofRtMsghdr {
+ return nil, errMessageTooShort
+ }
+ l := int(nativeEndian.Uint16(b[:2]))
+ if len(b) < l {
+ return nil, errInvalidMessage
+ }
+ m := &RouteMessage{
+ Version: int(b[2]),
+ Type: int(b[3]),
+ Flags: int(nativeEndian.Uint32(b[16:20])),
+ Index: int(nativeEndian.Uint16(b[6:8])),
+ ID: uintptr(nativeEndian.Uint32(b[24:28])),
+ Seq: int(nativeEndian.Uint32(b[28:32])),
+ raw: b[:l],
+ }
+ ll := int(nativeEndian.Uint16(b[4:6]))
+ if len(b) < ll {
+ return nil, errInvalidMessage
+ }
+ errno := syscall.Errno(nativeEndian.Uint32(b[32:36]))
+ if errno != 0 {
+ m.Err = errno
+ }
+ as, err := parseAddrs(uint(nativeEndian.Uint32(b[12:16])), parseKernelInetAddr, b[ll:])
+ if err != nil {
+ return nil, err
+ }
+ m.Addrs = as
+ return m, nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/route_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/route_test.go
new file mode 100644
index 000000000..61bd17454
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/route_test.go
@@ -0,0 +1,390 @@
+// 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.
+
+// +build darwin dragonfly freebsd netbsd openbsd
+
+package route
+
+import (
+ "fmt"
+ "os/exec"
+ "runtime"
+ "time"
+)
+
+func (m *RouteMessage) String() string {
+ return fmt.Sprintf("%s", addrAttrs(nativeEndian.Uint32(m.raw[12:16])))
+}
+
+func (m *InterfaceMessage) String() string {
+ var attrs addrAttrs
+ if runtime.GOOS == "openbsd" {
+ attrs = addrAttrs(nativeEndian.Uint32(m.raw[12:16]))
+ } else {
+ attrs = addrAttrs(nativeEndian.Uint32(m.raw[4:8]))
+ }
+ return fmt.Sprintf("%s", attrs)
+}
+
+func (m *InterfaceAddrMessage) String() string {
+ var attrs addrAttrs
+ if runtime.GOOS == "openbsd" {
+ attrs = addrAttrs(nativeEndian.Uint32(m.raw[12:16]))
+ } else {
+ attrs = addrAttrs(nativeEndian.Uint32(m.raw[4:8]))
+ }
+ return fmt.Sprintf("%s", attrs)
+}
+
+func (m *InterfaceMulticastAddrMessage) String() string {
+ return fmt.Sprintf("%s", addrAttrs(nativeEndian.Uint32(m.raw[4:8])))
+}
+
+func (m *InterfaceAnnounceMessage) String() string {
+ what := "<nil>"
+ switch m.What {
+ case 0:
+ what = "arrival"
+ case 1:
+ what = "departure"
+ }
+ return fmt.Sprintf("(%d %s %s)", m.Index, m.Name, what)
+}
+
+func (m *InterfaceMetrics) String() string {
+ return fmt.Sprintf("(type=%d mtu=%d)", m.Type, m.MTU)
+}
+
+func (m *RouteMetrics) String() string {
+ return fmt.Sprintf("(pmtu=%d)", m.PathMTU)
+}
+
+type addrAttrs uint
+
+var addrAttrNames = [...]string{
+ "dst",
+ "gateway",
+ "netmask",
+ "genmask",
+ "ifp",
+ "ifa",
+ "author",
+ "brd",
+ "df:mpls1-n:tag-o:src", // mpls1 for dragonfly, tag for netbsd, src for openbsd
+ "df:mpls2-o:srcmask", // mpls2 for dragonfly, srcmask for openbsd
+ "df:mpls3-o:label", // mpls3 for dragonfly, label for openbsd
+ "o:bfd", // bfd for openbsd
+ "o:dns", // dns for openbsd
+ "o:static", // static for openbsd
+ "o:search", // search for openbsd
+}
+
+func (attrs addrAttrs) String() string {
+ var s string
+ for i, name := range addrAttrNames {
+ if attrs&(1<<uint(i)) != 0 {
+ if s != "" {
+ s += "|"
+ }
+ s += name
+ }
+ }
+ if s == "" {
+ return "<nil>"
+ }
+ return s
+}
+
+type msgs []Message
+
+func (ms msgs) validate() ([]string, error) {
+ var ss []string
+ for _, m := range ms {
+ switch m := m.(type) {
+ case *RouteMessage:
+ if err := addrs(m.Addrs).match(addrAttrs(nativeEndian.Uint32(m.raw[12:16]))); err != nil {
+ return nil, err
+ }
+ sys := m.Sys()
+ if sys == nil {
+ return nil, fmt.Errorf("no sys for %s", m.String())
+ }
+ ss = append(ss, m.String()+" "+syss(sys).String()+" "+addrs(m.Addrs).String())
+ case *InterfaceMessage:
+ var attrs addrAttrs
+ if runtime.GOOS == "openbsd" {
+ attrs = addrAttrs(nativeEndian.Uint32(m.raw[12:16]))
+ } else {
+ attrs = addrAttrs(nativeEndian.Uint32(m.raw[4:8]))
+ }
+ if err := addrs(m.Addrs).match(attrs); err != nil {
+ return nil, err
+ }
+ sys := m.Sys()
+ if sys == nil {
+ return nil, fmt.Errorf("no sys for %s", m.String())
+ }
+ ss = append(ss, m.String()+" "+syss(sys).String()+" "+addrs(m.Addrs).String())
+ case *InterfaceAddrMessage:
+ var attrs addrAttrs
+ if runtime.GOOS == "openbsd" {
+ attrs = addrAttrs(nativeEndian.Uint32(m.raw[12:16]))
+ } else {
+ attrs = addrAttrs(nativeEndian.Uint32(m.raw[4:8]))
+ }
+ if err := addrs(m.Addrs).match(attrs); err != nil {
+ return nil, err
+ }
+ ss = append(ss, m.String()+" "+addrs(m.Addrs).String())
+ case *InterfaceMulticastAddrMessage:
+ if err := addrs(m.Addrs).match(addrAttrs(nativeEndian.Uint32(m.raw[4:8]))); err != nil {
+ return nil, err
+ }
+ ss = append(ss, m.String()+" "+addrs(m.Addrs).String())
+ case *InterfaceAnnounceMessage:
+ ss = append(ss, m.String())
+ default:
+ ss = append(ss, fmt.Sprintf("%+v", m))
+ }
+ }
+ return ss, nil
+}
+
+type syss []Sys
+
+func (sys syss) String() string {
+ var s string
+ for _, sy := range sys {
+ switch sy := sy.(type) {
+ case *InterfaceMetrics:
+ if len(s) > 0 {
+ s += " "
+ }
+ s += sy.String()
+ case *RouteMetrics:
+ if len(s) > 0 {
+ s += " "
+ }
+ s += sy.String()
+ }
+ }
+ return s
+}
+
+type addrFamily int
+
+func (af addrFamily) String() string {
+ switch af {
+ case sysAF_UNSPEC:
+ return "unspec"
+ case sysAF_LINK:
+ return "link"
+ case sysAF_INET:
+ return "inet4"
+ case sysAF_INET6:
+ return "inet6"
+ default:
+ return fmt.Sprintf("%d", af)
+ }
+}
+
+const hexDigit = "0123456789abcdef"
+
+type llAddr []byte
+
+func (a llAddr) String() string {
+ if len(a) == 0 {
+ return ""
+ }
+ buf := make([]byte, 0, len(a)*3-1)
+ for i, b := range a {
+ if i > 0 {
+ buf = append(buf, ':')
+ }
+ buf = append(buf, hexDigit[b>>4])
+ buf = append(buf, hexDigit[b&0xF])
+ }
+ return string(buf)
+}
+
+type ipAddr []byte
+
+func (a ipAddr) String() string {
+ if len(a) == 0 {
+ return "<nil>"
+ }
+ if len(a) == 4 {
+ return fmt.Sprintf("%d.%d.%d.%d", a[0], a[1], a[2], a[3])
+ }
+ if len(a) == 16 {
+ return fmt.Sprintf("%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15])
+ }
+ s := make([]byte, len(a)*2)
+ for i, tn := range a {
+ s[i*2], s[i*2+1] = hexDigit[tn>>4], hexDigit[tn&0xf]
+ }
+ return string(s)
+}
+
+func (a *LinkAddr) String() string {
+ name := a.Name
+ if name == "" {
+ name = "<nil>"
+ }
+ lla := llAddr(a.Addr).String()
+ if lla == "" {
+ lla = "<nil>"
+ }
+ return fmt.Sprintf("(%v %d %s %s)", addrFamily(a.Family()), a.Index, name, lla)
+}
+
+func (a *Inet4Addr) String() string {
+ return fmt.Sprintf("(%v %v)", addrFamily(a.Family()), ipAddr(a.IP[:]))
+}
+
+func (a *Inet6Addr) String() string {
+ return fmt.Sprintf("(%v %v %d)", addrFamily(a.Family()), ipAddr(a.IP[:]), a.ZoneID)
+}
+
+func (a *DefaultAddr) String() string {
+ return fmt.Sprintf("(%v %s)", addrFamily(a.Family()), ipAddr(a.Raw[2:]).String())
+}
+
+type addrs []Addr
+
+func (as addrs) String() string {
+ var s string
+ for _, a := range as {
+ if a == nil {
+ continue
+ }
+ if len(s) > 0 {
+ s += " "
+ }
+ switch a := a.(type) {
+ case *LinkAddr:
+ s += a.String()
+ case *Inet4Addr:
+ s += a.String()
+ case *Inet6Addr:
+ s += a.String()
+ case *DefaultAddr:
+ s += a.String()
+ }
+ }
+ if s == "" {
+ return "<nil>"
+ }
+ return s
+}
+
+func (as addrs) match(attrs addrAttrs) error {
+ var ts addrAttrs
+ af := sysAF_UNSPEC
+ for i := range as {
+ if as[i] != nil {
+ ts |= 1 << uint(i)
+ }
+ switch as[i].(type) {
+ case *Inet4Addr:
+ if af == sysAF_UNSPEC {
+ af = sysAF_INET
+ }
+ if af != sysAF_INET {
+ return fmt.Errorf("got %v; want %v", addrs(as), addrFamily(af))
+ }
+ case *Inet6Addr:
+ if af == sysAF_UNSPEC {
+ af = sysAF_INET6
+ }
+ if af != sysAF_INET6 {
+ return fmt.Errorf("got %v; want %v", addrs(as), addrFamily(af))
+ }
+ }
+ }
+ if ts != attrs && ts > attrs {
+ return fmt.Errorf("%v not included in %v", ts, attrs)
+ }
+ return nil
+}
+
+func fetchAndParseRIB(af int, typ RIBType) ([]Message, error) {
+ var err error
+ var b []byte
+ for i := 0; i < 3; i++ {
+ if b, err = FetchRIB(af, typ, 0); err != nil {
+ time.Sleep(10 * time.Millisecond)
+ continue
+ }
+ break
+ }
+ if err != nil {
+ return nil, fmt.Errorf("%v %d %v", addrFamily(af), typ, err)
+ }
+ ms, err := ParseRIB(typ, b)
+ if err != nil {
+ return nil, fmt.Errorf("%v %d %v", addrFamily(af), typ, err)
+ }
+ return ms, nil
+}
+
+// propVirtual is a proprietary virtual network interface.
+type propVirtual struct {
+ name string
+ addr, mask string
+ setupCmds []*exec.Cmd
+ teardownCmds []*exec.Cmd
+}
+
+func (pv *propVirtual) setup() error {
+ for _, cmd := range pv.setupCmds {
+ if err := cmd.Run(); err != nil {
+ pv.teardown()
+ return err
+ }
+ }
+ return nil
+}
+
+func (pv *propVirtual) teardown() error {
+ for _, cmd := range pv.teardownCmds {
+ if err := cmd.Run(); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (pv *propVirtual) configure(suffix int) error {
+ if runtime.GOOS == "openbsd" {
+ pv.name = fmt.Sprintf("vether%d", suffix)
+ } else {
+ pv.name = fmt.Sprintf("vlan%d", suffix)
+ }
+ xname, err := exec.LookPath("ifconfig")
+ if err != nil {
+ return err
+ }
+ pv.setupCmds = append(pv.setupCmds, &exec.Cmd{
+ Path: xname,
+ Args: []string{"ifconfig", pv.name, "create"},
+ })
+ if runtime.GOOS == "netbsd" {
+ // NetBSD requires an underlying dot1Q-capable network
+ // interface.
+ pv.setupCmds = append(pv.setupCmds, &exec.Cmd{
+ Path: xname,
+ Args: []string{"ifconfig", pv.name, "vlan", fmt.Sprintf("%d", suffix&0xfff), "vlanif", "wm0"},
+ })
+ }
+ pv.setupCmds = append(pv.setupCmds, &exec.Cmd{
+ Path: xname,
+ Args: []string{"ifconfig", pv.name, "inet", pv.addr, "netmask", pv.mask},
+ })
+ pv.teardownCmds = append(pv.teardownCmds, &exec.Cmd{
+ Path: xname,
+ Args: []string{"ifconfig", pv.name, "destroy"},
+ })
+ return nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/sys.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/sys.go
new file mode 100644
index 000000000..3d0ee9b14
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/sys.go
@@ -0,0 +1,39 @@
+// 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.
+
+// +build darwin dragonfly freebsd netbsd openbsd
+
+package route
+
+import "unsafe"
+
+var (
+ nativeEndian binaryByteOrder
+ kernelAlign int
+ wireFormats map[int]*wireFormat
+)
+
+func init() {
+ i := uint32(1)
+ b := (*[4]byte)(unsafe.Pointer(&i))
+ if b[0] == 1 {
+ nativeEndian = littleEndian
+ } else {
+ nativeEndian = bigEndian
+ }
+ kernelAlign, wireFormats = probeRoutingStack()
+}
+
+func roundup(l int) int {
+ if l == 0 {
+ return kernelAlign
+ }
+ return (l + kernelAlign - 1) & ^(kernelAlign - 1)
+}
+
+type wireFormat struct {
+ extOff int // offset of header extension
+ bodyOff int // offset of message body
+ parse func(RIBType, []byte) (Message, error)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/sys_darwin.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/sys_darwin.go
new file mode 100644
index 000000000..d2daf5c05
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/sys_darwin.go
@@ -0,0 +1,87 @@
+// 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.
+
+package route
+
+func (typ RIBType) parseable() bool {
+ switch typ {
+ case sysNET_RT_STAT, sysNET_RT_TRASH:
+ return false
+ default:
+ return true
+ }
+}
+
+// RouteMetrics represents route metrics.
+type RouteMetrics struct {
+ PathMTU int // path maximum transmission unit
+}
+
+// SysType implements the SysType method of Sys interface.
+func (rmx *RouteMetrics) SysType() SysType { return SysMetrics }
+
+// Sys implements the Sys method of Message interface.
+func (m *RouteMessage) Sys() []Sys {
+ return []Sys{
+ &RouteMetrics{
+ PathMTU: int(nativeEndian.Uint32(m.raw[m.extOff+4 : m.extOff+8])),
+ },
+ }
+}
+
+// InterfaceMetrics represents interface metrics.
+type InterfaceMetrics struct {
+ Type int // interface type
+ MTU int // maximum transmission unit
+}
+
+// SysType implements the SysType method of Sys interface.
+func (imx *InterfaceMetrics) SysType() SysType { return SysMetrics }
+
+// Sys implements the Sys method of Message interface.
+func (m *InterfaceMessage) Sys() []Sys {
+ return []Sys{
+ &InterfaceMetrics{
+ Type: int(m.raw[m.extOff]),
+ MTU: int(nativeEndian.Uint32(m.raw[m.extOff+8 : m.extOff+12])),
+ },
+ }
+}
+
+func probeRoutingStack() (int, map[int]*wireFormat) {
+ rtm := &wireFormat{extOff: 36, bodyOff: sizeofRtMsghdrDarwin15}
+ rtm.parse = rtm.parseRouteMessage
+ rtm2 := &wireFormat{extOff: 36, bodyOff: sizeofRtMsghdr2Darwin15}
+ rtm2.parse = rtm2.parseRouteMessage
+ ifm := &wireFormat{extOff: 16, bodyOff: sizeofIfMsghdrDarwin15}
+ ifm.parse = ifm.parseInterfaceMessage
+ ifm2 := &wireFormat{extOff: 32, bodyOff: sizeofIfMsghdr2Darwin15}
+ ifm2.parse = ifm2.parseInterfaceMessage
+ ifam := &wireFormat{extOff: sizeofIfaMsghdrDarwin15, bodyOff: sizeofIfaMsghdrDarwin15}
+ ifam.parse = ifam.parseInterfaceAddrMessage
+ ifmam := &wireFormat{extOff: sizeofIfmaMsghdrDarwin15, bodyOff: sizeofIfmaMsghdrDarwin15}
+ ifmam.parse = ifmam.parseInterfaceMulticastAddrMessage
+ ifmam2 := &wireFormat{extOff: sizeofIfmaMsghdr2Darwin15, bodyOff: sizeofIfmaMsghdr2Darwin15}
+ ifmam2.parse = ifmam2.parseInterfaceMulticastAddrMessage
+ // Darwin kernels require 32-bit aligned access to routing facilities.
+ return 4, map[int]*wireFormat{
+ sysRTM_ADD: rtm,
+ sysRTM_DELETE: rtm,
+ sysRTM_CHANGE: rtm,
+ sysRTM_GET: rtm,
+ sysRTM_LOSING: rtm,
+ sysRTM_REDIRECT: rtm,
+ sysRTM_MISS: rtm,
+ sysRTM_LOCK: rtm,
+ sysRTM_RESOLVE: rtm,
+ sysRTM_NEWADDR: ifam,
+ sysRTM_DELADDR: ifam,
+ sysRTM_IFINFO: ifm,
+ sysRTM_NEWMADDR: ifmam,
+ sysRTM_DELMADDR: ifmam,
+ sysRTM_IFINFO2: ifm2,
+ sysRTM_NEWMADDR2: ifmam2,
+ sysRTM_GET2: rtm2,
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/sys_dragonfly.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/sys_dragonfly.go
new file mode 100644
index 000000000..0c14bc2b4
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/sys_dragonfly.go
@@ -0,0 +1,76 @@
+// 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.
+
+package route
+
+import "unsafe"
+
+func (typ RIBType) parseable() bool { return true }
+
+// RouteMetrics represents route metrics.
+type RouteMetrics struct {
+ PathMTU int // path maximum transmission unit
+}
+
+// SysType implements the SysType method of Sys interface.
+func (rmx *RouteMetrics) SysType() SysType { return SysMetrics }
+
+// Sys implements the Sys method of Message interface.
+func (m *RouteMessage) Sys() []Sys {
+ return []Sys{
+ &RouteMetrics{
+ PathMTU: int(nativeEndian.Uint64(m.raw[m.extOff+8 : m.extOff+16])),
+ },
+ }
+}
+
+// InterfaceMetrics represents interface metrics.
+type InterfaceMetrics struct {
+ Type int // interface type
+ MTU int // maximum transmission unit
+}
+
+// SysType implements the SysType method of Sys interface.
+func (imx *InterfaceMetrics) SysType() SysType { return SysMetrics }
+
+// Sys implements the Sys method of Message interface.
+func (m *InterfaceMessage) Sys() []Sys {
+ return []Sys{
+ &InterfaceMetrics{
+ Type: int(m.raw[m.extOff]),
+ MTU: int(nativeEndian.Uint32(m.raw[m.extOff+8 : m.extOff+12])),
+ },
+ }
+}
+
+func probeRoutingStack() (int, map[int]*wireFormat) {
+ var p uintptr
+ rtm := &wireFormat{extOff: 40, bodyOff: sizeofRtMsghdrDragonFlyBSD4}
+ rtm.parse = rtm.parseRouteMessage
+ ifm := &wireFormat{extOff: 16, bodyOff: sizeofIfMsghdrDragonFlyBSD4}
+ ifm.parse = ifm.parseInterfaceMessage
+ ifam := &wireFormat{extOff: sizeofIfaMsghdrDragonFlyBSD4, bodyOff: sizeofIfaMsghdrDragonFlyBSD4}
+ ifam.parse = ifam.parseInterfaceAddrMessage
+ ifmam := &wireFormat{extOff: sizeofIfmaMsghdrDragonFlyBSD4, bodyOff: sizeofIfmaMsghdrDragonFlyBSD4}
+ ifmam.parse = ifmam.parseInterfaceMulticastAddrMessage
+ ifanm := &wireFormat{extOff: sizeofIfAnnouncemsghdrDragonFlyBSD4, bodyOff: sizeofIfAnnouncemsghdrDragonFlyBSD4}
+ ifanm.parse = ifanm.parseInterfaceAnnounceMessage
+ return int(unsafe.Sizeof(p)), map[int]*wireFormat{
+ sysRTM_ADD: rtm,
+ sysRTM_DELETE: rtm,
+ sysRTM_CHANGE: rtm,
+ sysRTM_GET: rtm,
+ sysRTM_LOSING: rtm,
+ sysRTM_REDIRECT: rtm,
+ sysRTM_MISS: rtm,
+ sysRTM_LOCK: rtm,
+ sysRTM_RESOLVE: rtm,
+ sysRTM_NEWADDR: ifam,
+ sysRTM_DELADDR: ifam,
+ sysRTM_IFINFO: ifm,
+ sysRTM_NEWMADDR: ifmam,
+ sysRTM_DELMADDR: ifmam,
+ sysRTM_IFANNOUNCE: ifanm,
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/sys_freebsd.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/sys_freebsd.go
new file mode 100644
index 000000000..89ba1c4e2
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/sys_freebsd.go
@@ -0,0 +1,155 @@
+// 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.
+
+package route
+
+import (
+ "syscall"
+ "unsafe"
+)
+
+func (typ RIBType) parseable() bool { return true }
+
+// RouteMetrics represents route metrics.
+type RouteMetrics struct {
+ PathMTU int // path maximum transmission unit
+}
+
+// SysType implements the SysType method of Sys interface.
+func (rmx *RouteMetrics) SysType() SysType { return SysMetrics }
+
+// Sys implements the Sys method of Message interface.
+func (m *RouteMessage) Sys() []Sys {
+ if kernelAlign == 8 {
+ return []Sys{
+ &RouteMetrics{
+ PathMTU: int(nativeEndian.Uint64(m.raw[m.extOff+8 : m.extOff+16])),
+ },
+ }
+ }
+ return []Sys{
+ &RouteMetrics{
+ PathMTU: int(nativeEndian.Uint32(m.raw[m.extOff+4 : m.extOff+8])),
+ },
+ }
+}
+
+// InterfaceMetrics represents interface metrics.
+type InterfaceMetrics struct {
+ Type int // interface type
+ MTU int // maximum transmission unit
+}
+
+// SysType implements the SysType method of Sys interface.
+func (imx *InterfaceMetrics) SysType() SysType { return SysMetrics }
+
+// Sys implements the Sys method of Message interface.
+func (m *InterfaceMessage) Sys() []Sys {
+ return []Sys{
+ &InterfaceMetrics{
+ Type: int(m.raw[m.extOff]),
+ MTU: int(nativeEndian.Uint32(m.raw[m.extOff+8 : m.extOff+12])),
+ },
+ }
+}
+
+func probeRoutingStack() (int, map[int]*wireFormat) {
+ var p uintptr
+ wordSize := int(unsafe.Sizeof(p))
+ align := int(unsafe.Sizeof(p))
+ // In the case of kern.supported_archs="amd64 i386", we need
+ // to know the underlying kernel's architecture because the
+ // alignment for routing facilities are set at the build time
+ // of the kernel.
+ conf, _ := syscall.Sysctl("kern.conftxt")
+ for i, j := 0, 0; j < len(conf); j++ {
+ if conf[j] != '\n' {
+ continue
+ }
+ s := conf[i:j]
+ i = j + 1
+ if len(s) > len("machine") && s[:len("machine")] == "machine" {
+ s = s[len("machine"):]
+ for k := 0; k < len(s); k++ {
+ if s[k] == ' ' || s[k] == '\t' {
+ s = s[1:]
+ }
+ break
+ }
+ if s == "amd64" {
+ align = 8
+ }
+ break
+ }
+ }
+ var rtm, ifm, ifam, ifmam, ifanm *wireFormat
+ if align != wordSize { // 386 emulation on amd64
+ rtm = &wireFormat{extOff: sizeofRtMsghdrFreeBSD10Emu - sizeofRtMetricsFreeBSD10Emu, bodyOff: sizeofRtMsghdrFreeBSD10Emu}
+ ifm = &wireFormat{extOff: 16}
+ ifam = &wireFormat{extOff: sizeofIfaMsghdrFreeBSD10Emu, bodyOff: sizeofIfaMsghdrFreeBSD10Emu}
+ ifmam = &wireFormat{extOff: sizeofIfmaMsghdrFreeBSD10Emu, bodyOff: sizeofIfmaMsghdrFreeBSD10Emu}
+ ifanm = &wireFormat{extOff: sizeofIfAnnouncemsghdrFreeBSD10Emu, bodyOff: sizeofIfAnnouncemsghdrFreeBSD10Emu}
+ } else {
+ rtm = &wireFormat{extOff: sizeofRtMsghdrFreeBSD10 - sizeofRtMetricsFreeBSD10, bodyOff: sizeofRtMsghdrFreeBSD10}
+ ifm = &wireFormat{extOff: 16}
+ ifam = &wireFormat{extOff: sizeofIfaMsghdrFreeBSD10, bodyOff: sizeofIfaMsghdrFreeBSD10}
+ ifmam = &wireFormat{extOff: sizeofIfmaMsghdrFreeBSD10, bodyOff: sizeofIfmaMsghdrFreeBSD10}
+ ifanm = &wireFormat{extOff: sizeofIfAnnouncemsghdrFreeBSD10, bodyOff: sizeofIfAnnouncemsghdrFreeBSD10}
+ }
+ rel, _ := syscall.SysctlUint32("kern.osreldate")
+ switch {
+ case rel < 800000:
+ if align != wordSize { // 386 emulation on amd64
+ ifm.bodyOff = sizeofIfMsghdrFreeBSD7Emu
+ } else {
+ ifm.bodyOff = sizeofIfMsghdrFreeBSD7
+ }
+ case 800000 <= rel && rel < 900000:
+ if align != wordSize { // 386 emulation on amd64
+ ifm.bodyOff = sizeofIfMsghdrFreeBSD8Emu
+ } else {
+ ifm.bodyOff = sizeofIfMsghdrFreeBSD8
+ }
+ case 900000 <= rel && rel < 1000000:
+ if align != wordSize { // 386 emulation on amd64
+ ifm.bodyOff = sizeofIfMsghdrFreeBSD9Emu
+ } else {
+ ifm.bodyOff = sizeofIfMsghdrFreeBSD9
+ }
+ case 1000000 <= rel && rel < 1100000:
+ if align != wordSize { // 386 emulation on amd64
+ ifm.bodyOff = sizeofIfMsghdrFreeBSD10Emu
+ } else {
+ ifm.bodyOff = sizeofIfMsghdrFreeBSD10
+ }
+ default:
+ if align != wordSize { // 386 emulation on amd64
+ ifm.bodyOff = sizeofIfMsghdrFreeBSD11Emu
+ } else {
+ ifm.bodyOff = sizeofIfMsghdrFreeBSD11
+ }
+ }
+ rtm.parse = rtm.parseRouteMessage
+ ifm.parse = ifm.parseInterfaceMessage
+ ifam.parse = ifam.parseInterfaceAddrMessage
+ ifmam.parse = ifmam.parseInterfaceMulticastAddrMessage
+ ifanm.parse = ifanm.parseInterfaceAnnounceMessage
+ return align, map[int]*wireFormat{
+ sysRTM_ADD: rtm,
+ sysRTM_DELETE: rtm,
+ sysRTM_CHANGE: rtm,
+ sysRTM_GET: rtm,
+ sysRTM_LOSING: rtm,
+ sysRTM_REDIRECT: rtm,
+ sysRTM_MISS: rtm,
+ sysRTM_LOCK: rtm,
+ sysRTM_RESOLVE: rtm,
+ sysRTM_NEWADDR: ifam,
+ sysRTM_DELADDR: ifam,
+ sysRTM_IFINFO: ifm,
+ sysRTM_NEWMADDR: ifmam,
+ sysRTM_DELMADDR: ifmam,
+ sysRTM_IFANNOUNCE: ifanm,
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/sys_netbsd.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/sys_netbsd.go
new file mode 100644
index 000000000..02f71d54b
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/sys_netbsd.go
@@ -0,0 +1,71 @@
+// 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.
+
+package route
+
+func (typ RIBType) parseable() bool { return true }
+
+// RouteMetrics represents route metrics.
+type RouteMetrics struct {
+ PathMTU int // path maximum transmission unit
+}
+
+// SysType implements the SysType method of Sys interface.
+func (rmx *RouteMetrics) SysType() SysType { return SysMetrics }
+
+// Sys implements the Sys method of Message interface.
+func (m *RouteMessage) Sys() []Sys {
+ return []Sys{
+ &RouteMetrics{
+ PathMTU: int(nativeEndian.Uint64(m.raw[m.extOff+8 : m.extOff+16])),
+ },
+ }
+}
+
+// RouteMetrics represents route metrics.
+type InterfaceMetrics struct {
+ Type int // interface type
+ MTU int // maximum transmission unit
+}
+
+// SysType implements the SysType method of Sys interface.
+func (imx *InterfaceMetrics) SysType() SysType { return SysMetrics }
+
+// Sys implements the Sys method of Message interface.
+func (m *InterfaceMessage) Sys() []Sys {
+ return []Sys{
+ &InterfaceMetrics{
+ Type: int(m.raw[m.extOff]),
+ MTU: int(nativeEndian.Uint32(m.raw[m.extOff+8 : m.extOff+12])),
+ },
+ }
+}
+
+func probeRoutingStack() (int, map[int]*wireFormat) {
+ rtm := &wireFormat{extOff: 40, bodyOff: sizeofRtMsghdrNetBSD7}
+ rtm.parse = rtm.parseRouteMessage
+ ifm := &wireFormat{extOff: 16, bodyOff: sizeofIfMsghdrNetBSD7}
+ ifm.parse = ifm.parseInterfaceMessage
+ ifam := &wireFormat{extOff: sizeofIfaMsghdrNetBSD7, bodyOff: sizeofIfaMsghdrNetBSD7}
+ ifam.parse = ifam.parseInterfaceAddrMessage
+ ifanm := &wireFormat{extOff: sizeofIfAnnouncemsghdrNetBSD7, bodyOff: sizeofIfAnnouncemsghdrNetBSD7}
+ ifanm.parse = ifanm.parseInterfaceAnnounceMessage
+ // NetBSD 6 and above kernels require 64-bit aligned access to
+ // routing facilities.
+ return 8, map[int]*wireFormat{
+ sysRTM_ADD: rtm,
+ sysRTM_DELETE: rtm,
+ sysRTM_CHANGE: rtm,
+ sysRTM_GET: rtm,
+ sysRTM_LOSING: rtm,
+ sysRTM_REDIRECT: rtm,
+ sysRTM_MISS: rtm,
+ sysRTM_LOCK: rtm,
+ sysRTM_RESOLVE: rtm,
+ sysRTM_NEWADDR: ifam,
+ sysRTM_DELADDR: ifam,
+ sysRTM_IFANNOUNCE: ifanm,
+ sysRTM_IFINFO: ifm,
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/sys_openbsd.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/sys_openbsd.go
new file mode 100644
index 000000000..c5674e83d
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/sys_openbsd.go
@@ -0,0 +1,80 @@
+// 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.
+
+package route
+
+import "unsafe"
+
+func (typ RIBType) parseable() bool {
+ switch typ {
+ case sysNET_RT_STATS, sysNET_RT_TABLE:
+ return false
+ default:
+ return true
+ }
+}
+
+// RouteMetrics represents route metrics.
+type RouteMetrics struct {
+ PathMTU int // path maximum transmission unit
+}
+
+// SysType implements the SysType method of Sys interface.
+func (rmx *RouteMetrics) SysType() SysType { return SysMetrics }
+
+// Sys implements the Sys method of Message interface.
+func (m *RouteMessage) Sys() []Sys {
+ return []Sys{
+ &RouteMetrics{
+ PathMTU: int(nativeEndian.Uint32(m.raw[60:64])),
+ },
+ }
+}
+
+// InterfaceMetrics represents interface metrics.
+type InterfaceMetrics struct {
+ Type int // interface type
+ MTU int // maximum transmission unit
+}
+
+// SysType implements the SysType method of Sys interface.
+func (imx *InterfaceMetrics) SysType() SysType { return SysMetrics }
+
+// Sys implements the Sys method of Message interface.
+func (m *InterfaceMessage) Sys() []Sys {
+ return []Sys{
+ &InterfaceMetrics{
+ Type: int(m.raw[24]),
+ MTU: int(nativeEndian.Uint32(m.raw[28:32])),
+ },
+ }
+}
+
+func probeRoutingStack() (int, map[int]*wireFormat) {
+ var p uintptr
+ rtm := &wireFormat{extOff: -1, bodyOff: -1}
+ rtm.parse = rtm.parseRouteMessage
+ ifm := &wireFormat{extOff: -1, bodyOff: -1}
+ ifm.parse = ifm.parseInterfaceMessage
+ ifam := &wireFormat{extOff: -1, bodyOff: -1}
+ ifam.parse = ifam.parseInterfaceAddrMessage
+ ifanm := &wireFormat{extOff: -1, bodyOff: -1}
+ ifanm.parse = ifanm.parseInterfaceAnnounceMessage
+ return int(unsafe.Sizeof(p)), map[int]*wireFormat{
+ sysRTM_ADD: rtm,
+ sysRTM_DELETE: rtm,
+ sysRTM_CHANGE: rtm,
+ sysRTM_GET: rtm,
+ sysRTM_LOSING: rtm,
+ sysRTM_REDIRECT: rtm,
+ sysRTM_MISS: rtm,
+ sysRTM_LOCK: rtm,
+ sysRTM_RESOLVE: rtm,
+ sysRTM_NEWADDR: ifam,
+ sysRTM_DELADDR: ifam,
+ sysRTM_IFINFO: ifm,
+ sysRTM_IFANNOUNCE: ifanm,
+ sysRTM_DESYNC: rtm,
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/syscall.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/syscall.go
new file mode 100644
index 000000000..c211188b1
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/syscall.go
@@ -0,0 +1,28 @@
+// 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.
+
+// +build darwin dragonfly freebsd netbsd openbsd
+
+package route
+
+import (
+ "syscall"
+ "unsafe"
+)
+
+var zero uintptr
+
+func sysctl(mib []int32, old *byte, oldlen *uintptr, new *byte, newlen uintptr) error {
+ var p unsafe.Pointer
+ if len(mib) > 0 {
+ p = unsafe.Pointer(&mib[0])
+ } else {
+ p = unsafe.Pointer(&zero)
+ }
+ _, _, errno := syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(p), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen))
+ if errno != 0 {
+ return error(errno)
+ }
+ return nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/zsys_darwin.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/zsys_darwin.go
new file mode 100644
index 000000000..4e2e1ab09
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/zsys_darwin.go
@@ -0,0 +1,99 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_darwin.go
+
+package route
+
+const (
+ sysAF_UNSPEC = 0x0
+ sysAF_INET = 0x2
+ sysAF_ROUTE = 0x11
+ sysAF_LINK = 0x12
+ sysAF_INET6 = 0x1e
+
+ sysSOCK_RAW = 0x3
+
+ sysNET_RT_DUMP = 0x1
+ sysNET_RT_FLAGS = 0x2
+ sysNET_RT_IFLIST = 0x3
+ sysNET_RT_STAT = 0x4
+ sysNET_RT_TRASH = 0x5
+ sysNET_RT_IFLIST2 = 0x6
+ sysNET_RT_DUMP2 = 0x7
+ sysNET_RT_MAXID = 0xa
+)
+
+const (
+ sysCTL_MAXNAME = 0xc
+
+ sysCTL_UNSPEC = 0x0
+ sysCTL_KERN = 0x1
+ sysCTL_VM = 0x2
+ sysCTL_VFS = 0x3
+ sysCTL_NET = 0x4
+ sysCTL_DEBUG = 0x5
+ sysCTL_HW = 0x6
+ sysCTL_MACHDEP = 0x7
+ sysCTL_USER = 0x8
+ sysCTL_MAXID = 0x9
+)
+
+const (
+ sysRTM_VERSION = 0x5
+
+ sysRTM_ADD = 0x1
+ sysRTM_DELETE = 0x2
+ sysRTM_CHANGE = 0x3
+ sysRTM_GET = 0x4
+ sysRTM_LOSING = 0x5
+ sysRTM_REDIRECT = 0x6
+ sysRTM_MISS = 0x7
+ sysRTM_LOCK = 0x8
+ sysRTM_OLDADD = 0x9
+ sysRTM_OLDDEL = 0xa
+ sysRTM_RESOLVE = 0xb
+ sysRTM_NEWADDR = 0xc
+ sysRTM_DELADDR = 0xd
+ sysRTM_IFINFO = 0xe
+ sysRTM_NEWMADDR = 0xf
+ sysRTM_DELMADDR = 0x10
+ sysRTM_IFINFO2 = 0x12
+ sysRTM_NEWMADDR2 = 0x13
+ sysRTM_GET2 = 0x14
+
+ sysRTA_DST = 0x1
+ sysRTA_GATEWAY = 0x2
+ sysRTA_NETMASK = 0x4
+ sysRTA_GENMASK = 0x8
+ sysRTA_IFP = 0x10
+ sysRTA_IFA = 0x20
+ sysRTA_AUTHOR = 0x40
+ sysRTA_BRD = 0x80
+
+ sysRTAX_DST = 0x0
+ sysRTAX_GATEWAY = 0x1
+ sysRTAX_NETMASK = 0x2
+ sysRTAX_GENMASK = 0x3
+ sysRTAX_IFP = 0x4
+ sysRTAX_IFA = 0x5
+ sysRTAX_AUTHOR = 0x6
+ sysRTAX_BRD = 0x7
+ sysRTAX_MAX = 0x8
+)
+
+const (
+ sizeofIfMsghdrDarwin15 = 0x70
+ sizeofIfaMsghdrDarwin15 = 0x14
+ sizeofIfmaMsghdrDarwin15 = 0x10
+ sizeofIfMsghdr2Darwin15 = 0xa0
+ sizeofIfmaMsghdr2Darwin15 = 0x14
+ sizeofIfDataDarwin15 = 0x60
+ sizeofIfData64Darwin15 = 0x80
+
+ sizeofRtMsghdrDarwin15 = 0x5c
+ sizeofRtMsghdr2Darwin15 = 0x5c
+ sizeofRtMetricsDarwin15 = 0x38
+
+ sizeofSockaddrStorage = 0x80
+ sizeofSockaddrInet = 0x10
+ sizeofSockaddrInet6 = 0x1c
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/zsys_dragonfly.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/zsys_dragonfly.go
new file mode 100644
index 000000000..719c88d11
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/zsys_dragonfly.go
@@ -0,0 +1,98 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_dragonfly.go
+
+package route
+
+const (
+ sysAF_UNSPEC = 0x0
+ sysAF_INET = 0x2
+ sysAF_ROUTE = 0x11
+ sysAF_LINK = 0x12
+ sysAF_INET6 = 0x1c
+
+ sysSOCK_RAW = 0x3
+
+ sysNET_RT_DUMP = 0x1
+ sysNET_RT_FLAGS = 0x2
+ sysNET_RT_IFLIST = 0x3
+ sysNET_RT_MAXID = 0x4
+)
+
+const (
+ sysCTL_MAXNAME = 0xc
+
+ sysCTL_UNSPEC = 0x0
+ sysCTL_KERN = 0x1
+ sysCTL_VM = 0x2
+ sysCTL_VFS = 0x3
+ sysCTL_NET = 0x4
+ sysCTL_DEBUG = 0x5
+ sysCTL_HW = 0x6
+ sysCTL_MACHDEP = 0x7
+ sysCTL_USER = 0x8
+ sysCTL_P1003_1B = 0x9
+ sysCTL_LWKT = 0xa
+ sysCTL_MAXID = 0xb
+)
+
+const (
+ sysRTM_VERSION = 0x6
+
+ sysRTM_ADD = 0x1
+ sysRTM_DELETE = 0x2
+ sysRTM_CHANGE = 0x3
+ sysRTM_GET = 0x4
+ sysRTM_LOSING = 0x5
+ sysRTM_REDIRECT = 0x6
+ sysRTM_MISS = 0x7
+ sysRTM_LOCK = 0x8
+ sysRTM_OLDADD = 0x9
+ sysRTM_OLDDEL = 0xa
+ sysRTM_RESOLVE = 0xb
+ sysRTM_NEWADDR = 0xc
+ sysRTM_DELADDR = 0xd
+ sysRTM_IFINFO = 0xe
+ sysRTM_NEWMADDR = 0xf
+ sysRTM_DELMADDR = 0x10
+ sysRTM_IFANNOUNCE = 0x11
+ sysRTM_IEEE80211 = 0x12
+
+ sysRTA_DST = 0x1
+ sysRTA_GATEWAY = 0x2
+ sysRTA_NETMASK = 0x4
+ sysRTA_GENMASK = 0x8
+ sysRTA_IFP = 0x10
+ sysRTA_IFA = 0x20
+ sysRTA_AUTHOR = 0x40
+ sysRTA_BRD = 0x80
+ sysRTA_MPLS1 = 0x100
+ sysRTA_MPLS2 = 0x200
+ sysRTA_MPLS3 = 0x400
+
+ sysRTAX_DST = 0x0
+ sysRTAX_GATEWAY = 0x1
+ sysRTAX_NETMASK = 0x2
+ sysRTAX_GENMASK = 0x3
+ sysRTAX_IFP = 0x4
+ sysRTAX_IFA = 0x5
+ sysRTAX_AUTHOR = 0x6
+ sysRTAX_BRD = 0x7
+ sysRTAX_MPLS1 = 0x8
+ sysRTAX_MPLS2 = 0x9
+ sysRTAX_MPLS3 = 0xa
+ sysRTAX_MAX = 0xb
+)
+
+const (
+ sizeofIfMsghdrDragonFlyBSD4 = 0xb0
+ sizeofIfaMsghdrDragonFlyBSD4 = 0x14
+ sizeofIfmaMsghdrDragonFlyBSD4 = 0x10
+ sizeofIfAnnouncemsghdrDragonFlyBSD4 = 0x18
+
+ sizeofRtMsghdrDragonFlyBSD4 = 0x98
+ sizeofRtMetricsDragonFlyBSD4 = 0x70
+
+ sizeofSockaddrStorage = 0x80
+ sizeofSockaddrInet = 0x10
+ sizeofSockaddrInet6 = 0x1c
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/zsys_freebsd_386.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/zsys_freebsd_386.go
new file mode 100644
index 000000000..b03bc01f6
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/zsys_freebsd_386.go
@@ -0,0 +1,126 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_freebsd.go
+
+package route
+
+const (
+ sysAF_UNSPEC = 0x0
+ sysAF_INET = 0x2
+ sysAF_ROUTE = 0x11
+ sysAF_LINK = 0x12
+ sysAF_INET6 = 0x1c
+
+ sysSOCK_RAW = 0x3
+
+ sysNET_RT_DUMP = 0x1
+ sysNET_RT_FLAGS = 0x2
+ sysNET_RT_IFLIST = 0x3
+ sysNET_RT_IFMALIST = 0x4
+ sysNET_RT_IFLISTL = 0x5
+)
+
+const (
+ sysCTL_MAXNAME = 0x18
+
+ sysCTL_UNSPEC = 0x0
+ sysCTL_KERN = 0x1
+ sysCTL_VM = 0x2
+ sysCTL_VFS = 0x3
+ sysCTL_NET = 0x4
+ sysCTL_DEBUG = 0x5
+ sysCTL_HW = 0x6
+ sysCTL_MACHDEP = 0x7
+ sysCTL_USER = 0x8
+ sysCTL_P1003_1B = 0x9
+)
+
+const (
+ sysRTM_VERSION = 0x5
+
+ sysRTM_ADD = 0x1
+ sysRTM_DELETE = 0x2
+ sysRTM_CHANGE = 0x3
+ sysRTM_GET = 0x4
+ sysRTM_LOSING = 0x5
+ sysRTM_REDIRECT = 0x6
+ sysRTM_MISS = 0x7
+ sysRTM_LOCK = 0x8
+ sysRTM_RESOLVE = 0xb
+ sysRTM_NEWADDR = 0xc
+ sysRTM_DELADDR = 0xd
+ sysRTM_IFINFO = 0xe
+ sysRTM_NEWMADDR = 0xf
+ sysRTM_DELMADDR = 0x10
+ sysRTM_IFANNOUNCE = 0x11
+ sysRTM_IEEE80211 = 0x12
+
+ sysRTA_DST = 0x1
+ sysRTA_GATEWAY = 0x2
+ sysRTA_NETMASK = 0x4
+ sysRTA_GENMASK = 0x8
+ sysRTA_IFP = 0x10
+ sysRTA_IFA = 0x20
+ sysRTA_AUTHOR = 0x40
+ sysRTA_BRD = 0x80
+
+ sysRTAX_DST = 0x0
+ sysRTAX_GATEWAY = 0x1
+ sysRTAX_NETMASK = 0x2
+ sysRTAX_GENMASK = 0x3
+ sysRTAX_IFP = 0x4
+ sysRTAX_IFA = 0x5
+ sysRTAX_AUTHOR = 0x6
+ sysRTAX_BRD = 0x7
+ sysRTAX_MAX = 0x8
+)
+
+const (
+ sizeofIfMsghdrlFreeBSD10 = 0x68
+ sizeofIfaMsghdrFreeBSD10 = 0x14
+ sizeofIfaMsghdrlFreeBSD10 = 0x6c
+ sizeofIfmaMsghdrFreeBSD10 = 0x10
+ sizeofIfAnnouncemsghdrFreeBSD10 = 0x18
+
+ sizeofRtMsghdrFreeBSD10 = 0x5c
+ sizeofRtMetricsFreeBSD10 = 0x38
+
+ sizeofIfMsghdrFreeBSD7 = 0x60
+ sizeofIfMsghdrFreeBSD8 = 0x60
+ sizeofIfMsghdrFreeBSD9 = 0x60
+ sizeofIfMsghdrFreeBSD10 = 0x64
+ sizeofIfMsghdrFreeBSD11 = 0xa8
+
+ sizeofIfDataFreeBSD7 = 0x50
+ sizeofIfDataFreeBSD8 = 0x50
+ sizeofIfDataFreeBSD9 = 0x50
+ sizeofIfDataFreeBSD10 = 0x54
+ sizeofIfDataFreeBSD11 = 0x98
+
+ // MODIFIED BY HAND FOR 386 EMULATION ON AMD64
+ // 386 EMULATION USES THE UNDERLYING RAW DATA LAYOUT
+
+ sizeofIfMsghdrlFreeBSD10Emu = 0xb0
+ sizeofIfaMsghdrFreeBSD10Emu = 0x14
+ sizeofIfaMsghdrlFreeBSD10Emu = 0xb0
+ sizeofIfmaMsghdrFreeBSD10Emu = 0x10
+ sizeofIfAnnouncemsghdrFreeBSD10Emu = 0x18
+
+ sizeofRtMsghdrFreeBSD10Emu = 0x98
+ sizeofRtMetricsFreeBSD10Emu = 0x70
+
+ sizeofIfMsghdrFreeBSD7Emu = 0xa8
+ sizeofIfMsghdrFreeBSD8Emu = 0xa8
+ sizeofIfMsghdrFreeBSD9Emu = 0xa8
+ sizeofIfMsghdrFreeBSD10Emu = 0xa8
+ sizeofIfMsghdrFreeBSD11Emu = 0xa8
+
+ sizeofIfDataFreeBSD7Emu = 0x98
+ sizeofIfDataFreeBSD8Emu = 0x98
+ sizeofIfDataFreeBSD9Emu = 0x98
+ sizeofIfDataFreeBSD10Emu = 0x98
+ sizeofIfDataFreeBSD11Emu = 0x98
+
+ sizeofSockaddrStorage = 0x80
+ sizeofSockaddrInet = 0x10
+ sizeofSockaddrInet6 = 0x1c
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/zsys_freebsd_amd64.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/zsys_freebsd_amd64.go
new file mode 100644
index 000000000..0b675b3d3
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/zsys_freebsd_amd64.go
@@ -0,0 +1,123 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_freebsd.go
+
+package route
+
+const (
+ sysAF_UNSPEC = 0x0
+ sysAF_INET = 0x2
+ sysAF_ROUTE = 0x11
+ sysAF_LINK = 0x12
+ sysAF_INET6 = 0x1c
+
+ sysSOCK_RAW = 0x3
+
+ sysNET_RT_DUMP = 0x1
+ sysNET_RT_FLAGS = 0x2
+ sysNET_RT_IFLIST = 0x3
+ sysNET_RT_IFMALIST = 0x4
+ sysNET_RT_IFLISTL = 0x5
+)
+
+const (
+ sysCTL_MAXNAME = 0x18
+
+ sysCTL_UNSPEC = 0x0
+ sysCTL_KERN = 0x1
+ sysCTL_VM = 0x2
+ sysCTL_VFS = 0x3
+ sysCTL_NET = 0x4
+ sysCTL_DEBUG = 0x5
+ sysCTL_HW = 0x6
+ sysCTL_MACHDEP = 0x7
+ sysCTL_USER = 0x8
+ sysCTL_P1003_1B = 0x9
+)
+
+const (
+ sysRTM_VERSION = 0x5
+
+ sysRTM_ADD = 0x1
+ sysRTM_DELETE = 0x2
+ sysRTM_CHANGE = 0x3
+ sysRTM_GET = 0x4
+ sysRTM_LOSING = 0x5
+ sysRTM_REDIRECT = 0x6
+ sysRTM_MISS = 0x7
+ sysRTM_LOCK = 0x8
+ sysRTM_RESOLVE = 0xb
+ sysRTM_NEWADDR = 0xc
+ sysRTM_DELADDR = 0xd
+ sysRTM_IFINFO = 0xe
+ sysRTM_NEWMADDR = 0xf
+ sysRTM_DELMADDR = 0x10
+ sysRTM_IFANNOUNCE = 0x11
+ sysRTM_IEEE80211 = 0x12
+
+ sysRTA_DST = 0x1
+ sysRTA_GATEWAY = 0x2
+ sysRTA_NETMASK = 0x4
+ sysRTA_GENMASK = 0x8
+ sysRTA_IFP = 0x10
+ sysRTA_IFA = 0x20
+ sysRTA_AUTHOR = 0x40
+ sysRTA_BRD = 0x80
+
+ sysRTAX_DST = 0x0
+ sysRTAX_GATEWAY = 0x1
+ sysRTAX_NETMASK = 0x2
+ sysRTAX_GENMASK = 0x3
+ sysRTAX_IFP = 0x4
+ sysRTAX_IFA = 0x5
+ sysRTAX_AUTHOR = 0x6
+ sysRTAX_BRD = 0x7
+ sysRTAX_MAX = 0x8
+)
+
+const (
+ sizeofIfMsghdrlFreeBSD10 = 0xb0
+ sizeofIfaMsghdrFreeBSD10 = 0x14
+ sizeofIfaMsghdrlFreeBSD10 = 0xb0
+ sizeofIfmaMsghdrFreeBSD10 = 0x10
+ sizeofIfAnnouncemsghdrFreeBSD10 = 0x18
+
+ sizeofRtMsghdrFreeBSD10 = 0x98
+ sizeofRtMetricsFreeBSD10 = 0x70
+
+ sizeofIfMsghdrFreeBSD7 = 0xa8
+ sizeofIfMsghdrFreeBSD8 = 0xa8
+ sizeofIfMsghdrFreeBSD9 = 0xa8
+ sizeofIfMsghdrFreeBSD10 = 0xa8
+ sizeofIfMsghdrFreeBSD11 = 0xa8
+
+ sizeofIfDataFreeBSD7 = 0x98
+ sizeofIfDataFreeBSD8 = 0x98
+ sizeofIfDataFreeBSD9 = 0x98
+ sizeofIfDataFreeBSD10 = 0x98
+ sizeofIfDataFreeBSD11 = 0x98
+
+ sizeofIfMsghdrlFreeBSD10Emu = 0xb0
+ sizeofIfaMsghdrFreeBSD10Emu = 0x14
+ sizeofIfaMsghdrlFreeBSD10Emu = 0xb0
+ sizeofIfmaMsghdrFreeBSD10Emu = 0x10
+ sizeofIfAnnouncemsghdrFreeBSD10Emu = 0x18
+
+ sizeofRtMsghdrFreeBSD10Emu = 0x98
+ sizeofRtMetricsFreeBSD10Emu = 0x70
+
+ sizeofIfMsghdrFreeBSD7Emu = 0xa8
+ sizeofIfMsghdrFreeBSD8Emu = 0xa8
+ sizeofIfMsghdrFreeBSD9Emu = 0xa8
+ sizeofIfMsghdrFreeBSD10Emu = 0xa8
+ sizeofIfMsghdrFreeBSD11Emu = 0xa8
+
+ sizeofIfDataFreeBSD7Emu = 0x98
+ sizeofIfDataFreeBSD8Emu = 0x98
+ sizeofIfDataFreeBSD9Emu = 0x98
+ sizeofIfDataFreeBSD10Emu = 0x98
+ sizeofIfDataFreeBSD11Emu = 0x98
+
+ sizeofSockaddrStorage = 0x80
+ sizeofSockaddrInet = 0x10
+ sizeofSockaddrInet6 = 0x1c
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/zsys_freebsd_arm.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/zsys_freebsd_arm.go
new file mode 100644
index 000000000..58f8ea16f
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/zsys_freebsd_arm.go
@@ -0,0 +1,123 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_freebsd.go
+
+package route
+
+const (
+ sysAF_UNSPEC = 0x0
+ sysAF_INET = 0x2
+ sysAF_ROUTE = 0x11
+ sysAF_LINK = 0x12
+ sysAF_INET6 = 0x1c
+
+ sysSOCK_RAW = 0x3
+
+ sysNET_RT_DUMP = 0x1
+ sysNET_RT_FLAGS = 0x2
+ sysNET_RT_IFLIST = 0x3
+ sysNET_RT_IFMALIST = 0x4
+ sysNET_RT_IFLISTL = 0x5
+)
+
+const (
+ sysCTL_MAXNAME = 0x18
+
+ sysCTL_UNSPEC = 0x0
+ sysCTL_KERN = 0x1
+ sysCTL_VM = 0x2
+ sysCTL_VFS = 0x3
+ sysCTL_NET = 0x4
+ sysCTL_DEBUG = 0x5
+ sysCTL_HW = 0x6
+ sysCTL_MACHDEP = 0x7
+ sysCTL_USER = 0x8
+ sysCTL_P1003_1B = 0x9
+)
+
+const (
+ sysRTM_VERSION = 0x5
+
+ sysRTM_ADD = 0x1
+ sysRTM_DELETE = 0x2
+ sysRTM_CHANGE = 0x3
+ sysRTM_GET = 0x4
+ sysRTM_LOSING = 0x5
+ sysRTM_REDIRECT = 0x6
+ sysRTM_MISS = 0x7
+ sysRTM_LOCK = 0x8
+ sysRTM_RESOLVE = 0xb
+ sysRTM_NEWADDR = 0xc
+ sysRTM_DELADDR = 0xd
+ sysRTM_IFINFO = 0xe
+ sysRTM_NEWMADDR = 0xf
+ sysRTM_DELMADDR = 0x10
+ sysRTM_IFANNOUNCE = 0x11
+ sysRTM_IEEE80211 = 0x12
+
+ sysRTA_DST = 0x1
+ sysRTA_GATEWAY = 0x2
+ sysRTA_NETMASK = 0x4
+ sysRTA_GENMASK = 0x8
+ sysRTA_IFP = 0x10
+ sysRTA_IFA = 0x20
+ sysRTA_AUTHOR = 0x40
+ sysRTA_BRD = 0x80
+
+ sysRTAX_DST = 0x0
+ sysRTAX_GATEWAY = 0x1
+ sysRTAX_NETMASK = 0x2
+ sysRTAX_GENMASK = 0x3
+ sysRTAX_IFP = 0x4
+ sysRTAX_IFA = 0x5
+ sysRTAX_AUTHOR = 0x6
+ sysRTAX_BRD = 0x7
+ sysRTAX_MAX = 0x8
+)
+
+const (
+ sizeofIfMsghdrlFreeBSD10 = 0x68
+ sizeofIfaMsghdrFreeBSD10 = 0x14
+ sizeofIfaMsghdrlFreeBSD10 = 0x6c
+ sizeofIfmaMsghdrFreeBSD10 = 0x10
+ sizeofIfAnnouncemsghdrFreeBSD10 = 0x18
+
+ sizeofRtMsghdrFreeBSD10 = 0x5c
+ sizeofRtMetricsFreeBSD10 = 0x38
+
+ sizeofIfMsghdrFreeBSD7 = 0x70
+ sizeofIfMsghdrFreeBSD8 = 0x70
+ sizeofIfMsghdrFreeBSD9 = 0x70
+ sizeofIfMsghdrFreeBSD10 = 0x70
+ sizeofIfMsghdrFreeBSD11 = 0xa8
+
+ sizeofIfDataFreeBSD7 = 0x60
+ sizeofIfDataFreeBSD8 = 0x60
+ sizeofIfDataFreeBSD9 = 0x60
+ sizeofIfDataFreeBSD10 = 0x60
+ sizeofIfDataFreeBSD11 = 0x98
+
+ sizeofIfMsghdrlFreeBSD10Emu = 0x68
+ sizeofIfaMsghdrFreeBSD10Emu = 0x14
+ sizeofIfaMsghdrlFreeBSD10Emu = 0x6c
+ sizeofIfmaMsghdrFreeBSD10Emu = 0x10
+ sizeofIfAnnouncemsghdrFreeBSD10Emu = 0x18
+
+ sizeofRtMsghdrFreeBSD10Emu = 0x5c
+ sizeofRtMetricsFreeBSD10Emu = 0x38
+
+ sizeofIfMsghdrFreeBSD7Emu = 0x70
+ sizeofIfMsghdrFreeBSD8Emu = 0x70
+ sizeofIfMsghdrFreeBSD9Emu = 0x70
+ sizeofIfMsghdrFreeBSD10Emu = 0x70
+ sizeofIfMsghdrFreeBSD11Emu = 0xa8
+
+ sizeofIfDataFreeBSD7Emu = 0x60
+ sizeofIfDataFreeBSD8Emu = 0x60
+ sizeofIfDataFreeBSD9Emu = 0x60
+ sizeofIfDataFreeBSD10Emu = 0x60
+ sizeofIfDataFreeBSD11Emu = 0x98
+
+ sizeofSockaddrStorage = 0x80
+ sizeofSockaddrInet = 0x10
+ sizeofSockaddrInet6 = 0x1c
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/zsys_netbsd.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/zsys_netbsd.go
new file mode 100644
index 000000000..e0df45e8b
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/zsys_netbsd.go
@@ -0,0 +1,97 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_netbsd.go
+
+package route
+
+const (
+ sysAF_UNSPEC = 0x0
+ sysAF_INET = 0x2
+ sysAF_ROUTE = 0x22
+ sysAF_LINK = 0x12
+ sysAF_INET6 = 0x18
+
+ sysSOCK_RAW = 0x3
+
+ sysNET_RT_DUMP = 0x1
+ sysNET_RT_FLAGS = 0x2
+ sysNET_RT_IFLIST = 0x5
+ sysNET_RT_MAXID = 0x6
+)
+
+const (
+ sysCTL_MAXNAME = 0xc
+
+ sysCTL_UNSPEC = 0x0
+ sysCTL_KERN = 0x1
+ sysCTL_VM = 0x2
+ sysCTL_VFS = 0x3
+ sysCTL_NET = 0x4
+ sysCTL_DEBUG = 0x5
+ sysCTL_HW = 0x6
+ sysCTL_MACHDEP = 0x7
+ sysCTL_USER = 0x8
+ sysCTL_DDB = 0x9
+ sysCTL_PROC = 0xa
+ sysCTL_VENDOR = 0xb
+ sysCTL_EMUL = 0xc
+ sysCTL_SECURITY = 0xd
+ sysCTL_MAXID = 0xe
+)
+
+const (
+ sysRTM_VERSION = 0x4
+
+ sysRTM_ADD = 0x1
+ sysRTM_DELETE = 0x2
+ sysRTM_CHANGE = 0x3
+ sysRTM_GET = 0x4
+ sysRTM_LOSING = 0x5
+ sysRTM_REDIRECT = 0x6
+ sysRTM_MISS = 0x7
+ sysRTM_LOCK = 0x8
+ sysRTM_OLDADD = 0x9
+ sysRTM_OLDDEL = 0xa
+ sysRTM_RESOLVE = 0xb
+ sysRTM_NEWADDR = 0xc
+ sysRTM_DELADDR = 0xd
+ sysRTM_IFANNOUNCE = 0x10
+ sysRTM_IEEE80211 = 0x11
+ sysRTM_SETGATE = 0x12
+ sysRTM_LLINFO_UPD = 0x13
+ sysRTM_IFINFO = 0x14
+ sysRTM_CHGADDR = 0x15
+
+ sysRTA_DST = 0x1
+ sysRTA_GATEWAY = 0x2
+ sysRTA_NETMASK = 0x4
+ sysRTA_GENMASK = 0x8
+ sysRTA_IFP = 0x10
+ sysRTA_IFA = 0x20
+ sysRTA_AUTHOR = 0x40
+ sysRTA_BRD = 0x80
+ sysRTA_TAG = 0x100
+
+ sysRTAX_DST = 0x0
+ sysRTAX_GATEWAY = 0x1
+ sysRTAX_NETMASK = 0x2
+ sysRTAX_GENMASK = 0x3
+ sysRTAX_IFP = 0x4
+ sysRTAX_IFA = 0x5
+ sysRTAX_AUTHOR = 0x6
+ sysRTAX_BRD = 0x7
+ sysRTAX_TAG = 0x8
+ sysRTAX_MAX = 0x9
+)
+
+const (
+ sizeofIfMsghdrNetBSD7 = 0x98
+ sizeofIfaMsghdrNetBSD7 = 0x18
+ sizeofIfAnnouncemsghdrNetBSD7 = 0x18
+
+ sizeofRtMsghdrNetBSD7 = 0x78
+ sizeofRtMetricsNetBSD7 = 0x50
+
+ sizeofSockaddrStorage = 0x80
+ sizeofSockaddrInet = 0x10
+ sizeofSockaddrInet6 = 0x1c
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/zsys_openbsd.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/zsys_openbsd.go
new file mode 100644
index 000000000..db8c8efb4
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/route/zsys_openbsd.go
@@ -0,0 +1,101 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_openbsd.go
+
+package route
+
+const (
+ sysAF_UNSPEC = 0x0
+ sysAF_INET = 0x2
+ sysAF_ROUTE = 0x11
+ sysAF_LINK = 0x12
+ sysAF_INET6 = 0x18
+
+ sysSOCK_RAW = 0x3
+
+ sysNET_RT_DUMP = 0x1
+ sysNET_RT_FLAGS = 0x2
+ sysNET_RT_IFLIST = 0x3
+ sysNET_RT_STATS = 0x4
+ sysNET_RT_TABLE = 0x5
+ sysNET_RT_IFNAMES = 0x6
+ sysNET_RT_MAXID = 0x7
+)
+
+const (
+ sysCTL_MAXNAME = 0xc
+
+ sysCTL_UNSPEC = 0x0
+ sysCTL_KERN = 0x1
+ sysCTL_VM = 0x2
+ sysCTL_FS = 0x3
+ sysCTL_NET = 0x4
+ sysCTL_DEBUG = 0x5
+ sysCTL_HW = 0x6
+ sysCTL_MACHDEP = 0x7
+ sysCTL_DDB = 0x9
+ sysCTL_VFS = 0xa
+ sysCTL_MAXID = 0xb
+)
+
+const (
+ sysRTM_VERSION = 0x5
+
+ sysRTM_ADD = 0x1
+ sysRTM_DELETE = 0x2
+ sysRTM_CHANGE = 0x3
+ sysRTM_GET = 0x4
+ sysRTM_LOSING = 0x5
+ sysRTM_REDIRECT = 0x6
+ sysRTM_MISS = 0x7
+ sysRTM_LOCK = 0x8
+ sysRTM_RESOLVE = 0xb
+ sysRTM_NEWADDR = 0xc
+ sysRTM_DELADDR = 0xd
+ sysRTM_IFINFO = 0xe
+ sysRTM_IFANNOUNCE = 0xf
+ sysRTM_DESYNC = 0x10
+ sysRTM_INVALIDATE = 0x11
+ sysRTM_BFD = 0x12
+ sysRTM_PROPOSAL = 0x13
+
+ sysRTA_DST = 0x1
+ sysRTA_GATEWAY = 0x2
+ sysRTA_NETMASK = 0x4
+ sysRTA_GENMASK = 0x8
+ sysRTA_IFP = 0x10
+ sysRTA_IFA = 0x20
+ sysRTA_AUTHOR = 0x40
+ sysRTA_BRD = 0x80
+ sysRTA_SRC = 0x100
+ sysRTA_SRCMASK = 0x200
+ sysRTA_LABEL = 0x400
+ sysRTA_BFD = 0x800
+ sysRTA_DNS = 0x1000
+ sysRTA_STATIC = 0x2000
+ sysRTA_SEARCH = 0x4000
+
+ sysRTAX_DST = 0x0
+ sysRTAX_GATEWAY = 0x1
+ sysRTAX_NETMASK = 0x2
+ sysRTAX_GENMASK = 0x3
+ sysRTAX_IFP = 0x4
+ sysRTAX_IFA = 0x5
+ sysRTAX_AUTHOR = 0x6
+ sysRTAX_BRD = 0x7
+ sysRTAX_SRC = 0x8
+ sysRTAX_SRCMASK = 0x9
+ sysRTAX_LABEL = 0xa
+ sysRTAX_BFD = 0xb
+ sysRTAX_DNS = 0xc
+ sysRTAX_STATIC = 0xd
+ sysRTAX_SEARCH = 0xe
+ sysRTAX_MAX = 0xf
+)
+
+const (
+ sizeofRtMsghdr = 0x60
+
+ sizeofSockaddrStorage = 0x100
+ sizeofSockaddrInet = 0x10
+ sizeofSockaddrInet6 = 0x1c
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/trace/events.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/trace/events.go
new file mode 100644
index 000000000..c646a6952
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/trace/events.go
@@ -0,0 +1,532 @@
+// Copyright 2015 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 trace
+
+import (
+ "bytes"
+ "fmt"
+ "html/template"
+ "io"
+ "log"
+ "net/http"
+ "runtime"
+ "sort"
+ "strconv"
+ "strings"
+ "sync"
+ "sync/atomic"
+ "text/tabwriter"
+ "time"
+)
+
+const maxEventsPerLog = 100
+
+type bucket struct {
+ MaxErrAge time.Duration
+ String string
+}
+
+var buckets = []bucket{
+ {0, "total"},
+ {10 * time.Second, "errs<10s"},
+ {1 * time.Minute, "errs<1m"},
+ {10 * time.Minute, "errs<10m"},
+ {1 * time.Hour, "errs<1h"},
+ {10 * time.Hour, "errs<10h"},
+ {24000 * time.Hour, "errors"},
+}
+
+// RenderEvents renders the HTML page typically served at /debug/events.
+// It does not do any auth checking. The request may be nil.
+//
+// Most users will use the Events handler.
+func RenderEvents(w http.ResponseWriter, req *http.Request, sensitive bool) {
+ now := time.Now()
+ data := &struct {
+ Families []string // family names
+ Buckets []bucket
+ Counts [][]int // eventLog count per family/bucket
+
+ // Set when a bucket has been selected.
+ Family string
+ Bucket int
+ EventLogs eventLogs
+ Expanded bool
+ }{
+ Buckets: buckets,
+ }
+
+ data.Families = make([]string, 0, len(families))
+ famMu.RLock()
+ for name := range families {
+ data.Families = append(data.Families, name)
+ }
+ famMu.RUnlock()
+ sort.Strings(data.Families)
+
+ // Count the number of eventLogs in each family for each error age.
+ data.Counts = make([][]int, len(data.Families))
+ for i, name := range data.Families {
+ // TODO(sameer): move this loop under the family lock.
+ f := getEventFamily(name)
+ data.Counts[i] = make([]int, len(data.Buckets))
+ for j, b := range data.Buckets {
+ data.Counts[i][j] = f.Count(now, b.MaxErrAge)
+ }
+ }
+
+ if req != nil {
+ var ok bool
+ data.Family, data.Bucket, ok = parseEventsArgs(req)
+ if !ok {
+ // No-op
+ } else {
+ data.EventLogs = getEventFamily(data.Family).Copy(now, buckets[data.Bucket].MaxErrAge)
+ }
+ if data.EventLogs != nil {
+ defer data.EventLogs.Free()
+ sort.Sort(data.EventLogs)
+ }
+ if exp, err := strconv.ParseBool(req.FormValue("exp")); err == nil {
+ data.Expanded = exp
+ }
+ }
+
+ famMu.RLock()
+ defer famMu.RUnlock()
+ if err := eventsTmpl().Execute(w, data); err != nil {
+ log.Printf("net/trace: Failed executing template: %v", err)
+ }
+}
+
+func parseEventsArgs(req *http.Request) (fam string, b int, ok bool) {
+ fam, bStr := req.FormValue("fam"), req.FormValue("b")
+ if fam == "" || bStr == "" {
+ return "", 0, false
+ }
+ b, err := strconv.Atoi(bStr)
+ if err != nil || b < 0 || b >= len(buckets) {
+ return "", 0, false
+ }
+ return fam, b, true
+}
+
+// An EventLog provides a log of events associated with a specific object.
+type EventLog interface {
+ // Printf formats its arguments with fmt.Sprintf and adds the
+ // result to the event log.
+ Printf(format string, a ...interface{})
+
+ // Errorf is like Printf, but it marks this event as an error.
+ Errorf(format string, a ...interface{})
+
+ // Finish declares that this event log is complete.
+ // The event log should not be used after calling this method.
+ Finish()
+}
+
+// NewEventLog returns a new EventLog with the specified family name
+// and title.
+func NewEventLog(family, title string) EventLog {
+ el := newEventLog()
+ el.ref()
+ el.Family, el.Title = family, title
+ el.Start = time.Now()
+ el.events = make([]logEntry, 0, maxEventsPerLog)
+ el.stack = make([]uintptr, 32)
+ n := runtime.Callers(2, el.stack)
+ el.stack = el.stack[:n]
+
+ getEventFamily(family).add(el)
+ return el
+}
+
+func (el *eventLog) Finish() {
+ getEventFamily(el.Family).remove(el)
+ el.unref() // matches ref in New
+}
+
+var (
+ famMu sync.RWMutex
+ families = make(map[string]*eventFamily) // family name => family
+)
+
+func getEventFamily(fam string) *eventFamily {
+ famMu.Lock()
+ defer famMu.Unlock()
+ f := families[fam]
+ if f == nil {
+ f = &eventFamily{}
+ families[fam] = f
+ }
+ return f
+}
+
+type eventFamily struct {
+ mu sync.RWMutex
+ eventLogs eventLogs
+}
+
+func (f *eventFamily) add(el *eventLog) {
+ f.mu.Lock()
+ f.eventLogs = append(f.eventLogs, el)
+ f.mu.Unlock()
+}
+
+func (f *eventFamily) remove(el *eventLog) {
+ f.mu.Lock()
+ defer f.mu.Unlock()
+ for i, el0 := range f.eventLogs {
+ if el == el0 {
+ copy(f.eventLogs[i:], f.eventLogs[i+1:])
+ f.eventLogs = f.eventLogs[:len(f.eventLogs)-1]
+ return
+ }
+ }
+}
+
+func (f *eventFamily) Count(now time.Time, maxErrAge time.Duration) (n int) {
+ f.mu.RLock()
+ defer f.mu.RUnlock()
+ for _, el := range f.eventLogs {
+ if el.hasRecentError(now, maxErrAge) {
+ n++
+ }
+ }
+ return
+}
+
+func (f *eventFamily) Copy(now time.Time, maxErrAge time.Duration) (els eventLogs) {
+ f.mu.RLock()
+ defer f.mu.RUnlock()
+ els = make(eventLogs, 0, len(f.eventLogs))
+ for _, el := range f.eventLogs {
+ if el.hasRecentError(now, maxErrAge) {
+ el.ref()
+ els = append(els, el)
+ }
+ }
+ return
+}
+
+type eventLogs []*eventLog
+
+// Free calls unref on each element of the list.
+func (els eventLogs) Free() {
+ for _, el := range els {
+ el.unref()
+ }
+}
+
+// eventLogs may be sorted in reverse chronological order.
+func (els eventLogs) Len() int { return len(els) }
+func (els eventLogs) Less(i, j int) bool { return els[i].Start.After(els[j].Start) }
+func (els eventLogs) Swap(i, j int) { els[i], els[j] = els[j], els[i] }
+
+// A logEntry is a timestamped log entry in an event log.
+type logEntry struct {
+ When time.Time
+ Elapsed time.Duration // since previous event in log
+ NewDay bool // whether this event is on a different day to the previous event
+ What string
+ IsErr bool
+}
+
+// WhenString returns a string representation of the elapsed time of the event.
+// It will include the date if midnight was crossed.
+func (e logEntry) WhenString() string {
+ if e.NewDay {
+ return e.When.Format("2006/01/02 15:04:05.000000")
+ }
+ return e.When.Format("15:04:05.000000")
+}
+
+// An eventLog represents an active event log.
+type eventLog struct {
+ // Family is the top-level grouping of event logs to which this belongs.
+ Family string
+
+ // Title is the title of this event log.
+ Title string
+
+ // Timing information.
+ Start time.Time
+
+ // Call stack where this event log was created.
+ stack []uintptr
+
+ // Append-only sequence of events.
+ //
+ // TODO(sameer): change this to a ring buffer to avoid the array copy
+ // when we hit maxEventsPerLog.
+ mu sync.RWMutex
+ events []logEntry
+ LastErrorTime time.Time
+ discarded int
+
+ refs int32 // how many buckets this is in
+}
+
+func (el *eventLog) reset() {
+ // Clear all but the mutex. Mutexes may not be copied, even when unlocked.
+ el.Family = ""
+ el.Title = ""
+ el.Start = time.Time{}
+ el.stack = nil
+ el.events = nil
+ el.LastErrorTime = time.Time{}
+ el.discarded = 0
+ el.refs = 0
+}
+
+func (el *eventLog) hasRecentError(now time.Time, maxErrAge time.Duration) bool {
+ if maxErrAge == 0 {
+ return true
+ }
+ el.mu.RLock()
+ defer el.mu.RUnlock()
+ return now.Sub(el.LastErrorTime) < maxErrAge
+}
+
+// delta returns the elapsed time since the last event or the log start,
+// and whether it spans midnight.
+// L >= el.mu
+func (el *eventLog) delta(t time.Time) (time.Duration, bool) {
+ if len(el.events) == 0 {
+ return t.Sub(el.Start), false
+ }
+ prev := el.events[len(el.events)-1].When
+ return t.Sub(prev), prev.Day() != t.Day()
+
+}
+
+func (el *eventLog) Printf(format string, a ...interface{}) {
+ el.printf(false, format, a...)
+}
+
+func (el *eventLog) Errorf(format string, a ...interface{}) {
+ el.printf(true, format, a...)
+}
+
+func (el *eventLog) printf(isErr bool, format string, a ...interface{}) {
+ e := logEntry{When: time.Now(), IsErr: isErr, What: fmt.Sprintf(format, a...)}
+ el.mu.Lock()
+ e.Elapsed, e.NewDay = el.delta(e.When)
+ if len(el.events) < maxEventsPerLog {
+ el.events = append(el.events, e)
+ } else {
+ // Discard the oldest event.
+ if el.discarded == 0 {
+ // el.discarded starts at two to count for the event it
+ // is replacing, plus the next one that we are about to
+ // drop.
+ el.discarded = 2
+ } else {
+ el.discarded++
+ }
+ // TODO(sameer): if this causes allocations on a critical path,
+ // change eventLog.What to be a fmt.Stringer, as in trace.go.
+ el.events[0].What = fmt.Sprintf("(%d events discarded)", el.discarded)
+ // The timestamp of the discarded meta-event should be
+ // the time of the last event it is representing.
+ el.events[0].When = el.events[1].When
+ copy(el.events[1:], el.events[2:])
+ el.events[maxEventsPerLog-1] = e
+ }
+ if e.IsErr {
+ el.LastErrorTime = e.When
+ }
+ el.mu.Unlock()
+}
+
+func (el *eventLog) ref() {
+ atomic.AddInt32(&el.refs, 1)
+}
+
+func (el *eventLog) unref() {
+ if atomic.AddInt32(&el.refs, -1) == 0 {
+ freeEventLog(el)
+ }
+}
+
+func (el *eventLog) When() string {
+ return el.Start.Format("2006/01/02 15:04:05.000000")
+}
+
+func (el *eventLog) ElapsedTime() string {
+ elapsed := time.Since(el.Start)
+ return fmt.Sprintf("%.6f", elapsed.Seconds())
+}
+
+func (el *eventLog) Stack() string {
+ buf := new(bytes.Buffer)
+ tw := tabwriter.NewWriter(buf, 1, 8, 1, '\t', 0)
+ printStackRecord(tw, el.stack)
+ tw.Flush()
+ return buf.String()
+}
+
+// printStackRecord prints the function + source line information
+// for a single stack trace.
+// Adapted from runtime/pprof/pprof.go.
+func printStackRecord(w io.Writer, stk []uintptr) {
+ for _, pc := range stk {
+ f := runtime.FuncForPC(pc)
+ if f == nil {
+ continue
+ }
+ file, line := f.FileLine(pc)
+ name := f.Name()
+ // Hide runtime.goexit and any runtime functions at the beginning.
+ if strings.HasPrefix(name, "runtime.") {
+ continue
+ }
+ fmt.Fprintf(w, "# %s\t%s:%d\n", name, file, line)
+ }
+}
+
+func (el *eventLog) Events() []logEntry {
+ el.mu.RLock()
+ defer el.mu.RUnlock()
+ return el.events
+}
+
+// freeEventLogs is a freelist of *eventLog
+var freeEventLogs = make(chan *eventLog, 1000)
+
+// newEventLog returns a event log ready to use.
+func newEventLog() *eventLog {
+ select {
+ case el := <-freeEventLogs:
+ return el
+ default:
+ return new(eventLog)
+ }
+}
+
+// freeEventLog adds el to freeEventLogs if there's room.
+// This is non-blocking.
+func freeEventLog(el *eventLog) {
+ el.reset()
+ select {
+ case freeEventLogs <- el:
+ default:
+ }
+}
+
+var eventsTmplCache *template.Template
+var eventsTmplOnce sync.Once
+
+func eventsTmpl() *template.Template {
+ eventsTmplOnce.Do(func() {
+ eventsTmplCache = template.Must(template.New("events").Funcs(template.FuncMap{
+ "elapsed": elapsed,
+ "trimSpace": strings.TrimSpace,
+ }).Parse(eventsHTML))
+ })
+ return eventsTmplCache
+}
+
+const eventsHTML = `
+<html>
+ <head>
+ <title>events</title>
+ </head>
+ <style type="text/css">
+ body {
+ font-family: sans-serif;
+ }
+ table#req-status td.family {
+ padding-right: 2em;
+ }
+ table#req-status td.active {
+ padding-right: 1em;
+ }
+ table#req-status td.empty {
+ color: #aaa;
+ }
+ table#reqs {
+ margin-top: 1em;
+ }
+ table#reqs tr.first {
+ {{if $.Expanded}}font-weight: bold;{{end}}
+ }
+ table#reqs td {
+ font-family: monospace;
+ }
+ table#reqs td.when {
+ text-align: right;
+ white-space: nowrap;
+ }
+ table#reqs td.elapsed {
+ padding: 0 0.5em;
+ text-align: right;
+ white-space: pre;
+ width: 10em;
+ }
+ address {
+ font-size: smaller;
+ margin-top: 5em;
+ }
+ </style>
+ <body>
+
+<h1>/debug/events</h1>
+
+<table id="req-status">
+ {{range $i, $fam := .Families}}
+ <tr>
+ <td class="family">{{$fam}}</td>
+
+ {{range $j, $bucket := $.Buckets}}
+ {{$n := index $.Counts $i $j}}
+ <td class="{{if not $bucket.MaxErrAge}}active{{end}}{{if not $n}}empty{{end}}">
+ {{if $n}}<a href="?fam={{$fam}}&b={{$j}}{{if $.Expanded}}&exp=1{{end}}">{{end}}
+ [{{$n}} {{$bucket.String}}]
+ {{if $n}}</a>{{end}}
+ </td>
+ {{end}}
+
+ </tr>{{end}}
+</table>
+
+{{if $.EventLogs}}
+<hr />
+<h3>Family: {{$.Family}}</h3>
+
+{{if $.Expanded}}<a href="?fam={{$.Family}}&b={{$.Bucket}}">{{end}}
+[Summary]{{if $.Expanded}}</a>{{end}}
+
+{{if not $.Expanded}}<a href="?fam={{$.Family}}&b={{$.Bucket}}&exp=1">{{end}}
+[Expanded]{{if not $.Expanded}}</a>{{end}}
+
+<table id="reqs">
+ <tr><th>When</th><th>Elapsed</th></tr>
+ {{range $el := $.EventLogs}}
+ <tr class="first">
+ <td class="when">{{$el.When}}</td>
+ <td class="elapsed">{{$el.ElapsedTime}}</td>
+ <td>{{$el.Title}}
+ </tr>
+ {{if $.Expanded}}
+ <tr>
+ <td class="when"></td>
+ <td class="elapsed"></td>
+ <td><pre>{{$el.Stack|trimSpace}}</pre></td>
+ </tr>
+ {{range $el.Events}}
+ <tr>
+ <td class="when">{{.WhenString}}</td>
+ <td class="elapsed">{{elapsed .Elapsed}}</td>
+ <td>.{{if .IsErr}}E{{else}}.{{end}}. {{.What}}</td>
+ </tr>
+ {{end}}
+ {{end}}
+ {{end}}
+</table>
+{{end}}
+ </body>
+</html>
+`
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/trace/histogram.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/trace/histogram.go
new file mode 100644
index 000000000..9bf4286c7
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/trace/histogram.go
@@ -0,0 +1,365 @@
+// Copyright 2015 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 trace
+
+// This file implements histogramming for RPC statistics collection.
+
+import (
+ "bytes"
+ "fmt"
+ "html/template"
+ "log"
+ "math"
+ "sync"
+
+ "golang.org/x/net/internal/timeseries"
+)
+
+const (
+ bucketCount = 38
+)
+
+// histogram keeps counts of values in buckets that are spaced
+// out in powers of 2: 0-1, 2-3, 4-7...
+// histogram implements timeseries.Observable
+type histogram struct {
+ sum int64 // running total of measurements
+ sumOfSquares float64 // square of running total
+ buckets []int64 // bucketed values for histogram
+ value int // holds a single value as an optimization
+ valueCount int64 // number of values recorded for single value
+}
+
+// AddMeasurement records a value measurement observation to the histogram.
+func (h *histogram) addMeasurement(value int64) {
+ // TODO: assert invariant
+ h.sum += value
+ h.sumOfSquares += float64(value) * float64(value)
+
+ bucketIndex := getBucket(value)
+
+ if h.valueCount == 0 || (h.valueCount > 0 && h.value == bucketIndex) {
+ h.value = bucketIndex
+ h.valueCount++
+ } else {
+ h.allocateBuckets()
+ h.buckets[bucketIndex]++
+ }
+}
+
+func (h *histogram) allocateBuckets() {
+ if h.buckets == nil {
+ h.buckets = make([]int64, bucketCount)
+ h.buckets[h.value] = h.valueCount
+ h.value = 0
+ h.valueCount = -1
+ }
+}
+
+func log2(i int64) int {
+ n := 0
+ for ; i >= 0x100; i >>= 8 {
+ n += 8
+ }
+ for ; i > 0; i >>= 1 {
+ n += 1
+ }
+ return n
+}
+
+func getBucket(i int64) (index int) {
+ index = log2(i) - 1
+ if index < 0 {
+ index = 0
+ }
+ if index >= bucketCount {
+ index = bucketCount - 1
+ }
+ return
+}
+
+// Total returns the number of recorded observations.
+func (h *histogram) total() (total int64) {
+ if h.valueCount >= 0 {
+ total = h.valueCount
+ }
+ for _, val := range h.buckets {
+ total += int64(val)
+ }
+ return
+}
+
+// Average returns the average value of recorded observations.
+func (h *histogram) average() float64 {
+ t := h.total()
+ if t == 0 {
+ return 0
+ }
+ return float64(h.sum) / float64(t)
+}
+
+// Variance returns the variance of recorded observations.
+func (h *histogram) variance() float64 {
+ t := float64(h.total())
+ if t == 0 {
+ return 0
+ }
+ s := float64(h.sum) / t
+ return h.sumOfSquares/t - s*s
+}
+
+// StandardDeviation returns the standard deviation of recorded observations.
+func (h *histogram) standardDeviation() float64 {
+ return math.Sqrt(h.variance())
+}
+
+// PercentileBoundary estimates the value that the given fraction of recorded
+// observations are less than.
+func (h *histogram) percentileBoundary(percentile float64) int64 {
+ total := h.total()
+
+ // Corner cases (make sure result is strictly less than Total())
+ if total == 0 {
+ return 0
+ } else if total == 1 {
+ return int64(h.average())
+ }
+
+ percentOfTotal := round(float64(total) * percentile)
+ var runningTotal int64
+
+ for i := range h.buckets {
+ value := h.buckets[i]
+ runningTotal += value
+ if runningTotal == percentOfTotal {
+ // We hit an exact bucket boundary. If the next bucket has data, it is a
+ // good estimate of the value. If the bucket is empty, we interpolate the
+ // midpoint between the next bucket's boundary and the next non-zero
+ // bucket. If the remaining buckets are all empty, then we use the
+ // boundary for the next bucket as the estimate.
+ j := uint8(i + 1)
+ min := bucketBoundary(j)
+ if runningTotal < total {
+ for h.buckets[j] == 0 {
+ j++
+ }
+ }
+ max := bucketBoundary(j)
+ return min + round(float64(max-min)/2)
+ } else if runningTotal > percentOfTotal {
+ // The value is in this bucket. Interpolate the value.
+ delta := runningTotal - percentOfTotal
+ percentBucket := float64(value-delta) / float64(value)
+ bucketMin := bucketBoundary(uint8(i))
+ nextBucketMin := bucketBoundary(uint8(i + 1))
+ bucketSize := nextBucketMin - bucketMin
+ return bucketMin + round(percentBucket*float64(bucketSize))
+ }
+ }
+ return bucketBoundary(bucketCount - 1)
+}
+
+// Median returns the estimated median of the observed values.
+func (h *histogram) median() int64 {
+ return h.percentileBoundary(0.5)
+}
+
+// Add adds other to h.
+func (h *histogram) Add(other timeseries.Observable) {
+ o := other.(*histogram)
+ if o.valueCount == 0 {
+ // Other histogram is empty
+ } else if h.valueCount >= 0 && o.valueCount > 0 && h.value == o.value {
+ // Both have a single bucketed value, aggregate them
+ h.valueCount += o.valueCount
+ } else {
+ // Two different values necessitate buckets in this histogram
+ h.allocateBuckets()
+ if o.valueCount >= 0 {
+ h.buckets[o.value] += o.valueCount
+ } else {
+ for i := range h.buckets {
+ h.buckets[i] += o.buckets[i]
+ }
+ }
+ }
+ h.sumOfSquares += o.sumOfSquares
+ h.sum += o.sum
+}
+
+// Clear resets the histogram to an empty state, removing all observed values.
+func (h *histogram) Clear() {
+ h.buckets = nil
+ h.value = 0
+ h.valueCount = 0
+ h.sum = 0
+ h.sumOfSquares = 0
+}
+
+// CopyFrom copies from other, which must be a *histogram, into h.
+func (h *histogram) CopyFrom(other timeseries.Observable) {
+ o := other.(*histogram)
+ if o.valueCount == -1 {
+ h.allocateBuckets()
+ copy(h.buckets, o.buckets)
+ }
+ h.sum = o.sum
+ h.sumOfSquares = o.sumOfSquares
+ h.value = o.value
+ h.valueCount = o.valueCount
+}
+
+// Multiply scales the histogram by the specified ratio.
+func (h *histogram) Multiply(ratio float64) {
+ if h.valueCount == -1 {
+ for i := range h.buckets {
+ h.buckets[i] = int64(float64(h.buckets[i]) * ratio)
+ }
+ } else {
+ h.valueCount = int64(float64(h.valueCount) * ratio)
+ }
+ h.sum = int64(float64(h.sum) * ratio)
+ h.sumOfSquares = h.sumOfSquares * ratio
+}
+
+// New creates a new histogram.
+func (h *histogram) New() timeseries.Observable {
+ r := new(histogram)
+ r.Clear()
+ return r
+}
+
+func (h *histogram) String() string {
+ return fmt.Sprintf("%d, %f, %d, %d, %v",
+ h.sum, h.sumOfSquares, h.value, h.valueCount, h.buckets)
+}
+
+// round returns the closest int64 to the argument
+func round(in float64) int64 {
+ return int64(math.Floor(in + 0.5))
+}
+
+// bucketBoundary returns the first value in the bucket.
+func bucketBoundary(bucket uint8) int64 {
+ if bucket == 0 {
+ return 0
+ }
+ return 1 << bucket
+}
+
+// bucketData holds data about a specific bucket for use in distTmpl.
+type bucketData struct {
+ Lower, Upper int64
+ N int64
+ Pct, CumulativePct float64
+ GraphWidth int
+}
+
+// data holds data about a Distribution for use in distTmpl.
+type data struct {
+ Buckets []*bucketData
+ Count, Median int64
+ Mean, StandardDeviation float64
+}
+
+// maxHTMLBarWidth is the maximum width of the HTML bar for visualizing buckets.
+const maxHTMLBarWidth = 350.0
+
+// newData returns data representing h for use in distTmpl.
+func (h *histogram) newData() *data {
+ // Force the allocation of buckets to simplify the rendering implementation
+ h.allocateBuckets()
+ // We scale the bars on the right so that the largest bar is
+ // maxHTMLBarWidth pixels in width.
+ maxBucket := int64(0)
+ for _, n := range h.buckets {
+ if n > maxBucket {
+ maxBucket = n
+ }
+ }
+ total := h.total()
+ barsizeMult := maxHTMLBarWidth / float64(maxBucket)
+ var pctMult float64
+ if total == 0 {
+ pctMult = 1.0
+ } else {
+ pctMult = 100.0 / float64(total)
+ }
+
+ buckets := make([]*bucketData, len(h.buckets))
+ runningTotal := int64(0)
+ for i, n := range h.buckets {
+ if n == 0 {
+ continue
+ }
+ runningTotal += n
+ var upperBound int64
+ if i < bucketCount-1 {
+ upperBound = bucketBoundary(uint8(i + 1))
+ } else {
+ upperBound = math.MaxInt64
+ }
+ buckets[i] = &bucketData{
+ Lower: bucketBoundary(uint8(i)),
+ Upper: upperBound,
+ N: n,
+ Pct: float64(n) * pctMult,
+ CumulativePct: float64(runningTotal) * pctMult,
+ GraphWidth: int(float64(n) * barsizeMult),
+ }
+ }
+ return &data{
+ Buckets: buckets,
+ Count: total,
+ Median: h.median(),
+ Mean: h.average(),
+ StandardDeviation: h.standardDeviation(),
+ }
+}
+
+func (h *histogram) html() template.HTML {
+ buf := new(bytes.Buffer)
+ if err := distTmpl().Execute(buf, h.newData()); err != nil {
+ buf.Reset()
+ log.Printf("net/trace: couldn't execute template: %v", err)
+ }
+ return template.HTML(buf.String())
+}
+
+var distTmplCache *template.Template
+var distTmplOnce sync.Once
+
+func distTmpl() *template.Template {
+ distTmplOnce.Do(func() {
+ // Input: data
+ distTmplCache = template.Must(template.New("distTmpl").Parse(`
+<table>
+<tr>
+ <td style="padding:0.25em">Count: {{.Count}}</td>
+ <td style="padding:0.25em">Mean: {{printf "%.0f" .Mean}}</td>
+ <td style="padding:0.25em">StdDev: {{printf "%.0f" .StandardDeviation}}</td>
+ <td style="padding:0.25em">Median: {{.Median}}</td>
+</tr>
+</table>
+<hr>
+<table>
+{{range $b := .Buckets}}
+{{if $b}}
+ <tr>
+ <td style="padding:0 0 0 0.25em">[</td>
+ <td style="text-align:right;padding:0 0.25em">{{.Lower}},</td>
+ <td style="text-align:right;padding:0 0.25em">{{.Upper}})</td>
+ <td style="text-align:right;padding:0 0.25em">{{.N}}</td>
+ <td style="text-align:right;padding:0 0.25em">{{printf "%#.3f" .Pct}}%</td>
+ <td style="text-align:right;padding:0 0.25em">{{printf "%#.3f" .CumulativePct}}%</td>
+ <td><div style="background-color: blue; height: 1em; width: {{.GraphWidth}};"></div></td>
+ </tr>
+{{end}}
+{{end}}
+</table>
+`))
+ })
+ return distTmplCache
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/trace/histogram_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/trace/histogram_test.go
new file mode 100644
index 000000000..d384b9332
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/trace/histogram_test.go
@@ -0,0 +1,325 @@
+// Copyright 2015 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 trace
+
+import (
+ "math"
+ "testing"
+)
+
+type sumTest struct {
+ value int64
+ sum int64
+ sumOfSquares float64
+ total int64
+}
+
+var sumTests = []sumTest{
+ {100, 100, 10000, 1},
+ {50, 150, 12500, 2},
+ {50, 200, 15000, 3},
+ {50, 250, 17500, 4},
+}
+
+type bucketingTest struct {
+ in int64
+ log int
+ bucket int
+}
+
+var bucketingTests = []bucketingTest{
+ {0, 0, 0},
+ {1, 1, 0},
+ {2, 2, 1},
+ {3, 2, 1},
+ {4, 3, 2},
+ {1000, 10, 9},
+ {1023, 10, 9},
+ {1024, 11, 10},
+ {1000000, 20, 19},
+}
+
+type multiplyTest struct {
+ in int64
+ ratio float64
+ expectedSum int64
+ expectedTotal int64
+ expectedSumOfSquares float64
+}
+
+var multiplyTests = []multiplyTest{
+ {15, 2.5, 37, 2, 562.5},
+ {128, 4.6, 758, 13, 77953.9},
+}
+
+type percentileTest struct {
+ fraction float64
+ expected int64
+}
+
+var percentileTests = []percentileTest{
+ {0.25, 48},
+ {0.5, 96},
+ {0.6, 109},
+ {0.75, 128},
+ {0.90, 205},
+ {0.95, 230},
+ {0.99, 256},
+}
+
+func TestSum(t *testing.T) {
+ var h histogram
+
+ for _, test := range sumTests {
+ h.addMeasurement(test.value)
+ sum := h.sum
+ if sum != test.sum {
+ t.Errorf("h.Sum = %v WANT: %v", sum, test.sum)
+ }
+
+ sumOfSquares := h.sumOfSquares
+ if sumOfSquares != test.sumOfSquares {
+ t.Errorf("h.SumOfSquares = %v WANT: %v", sumOfSquares, test.sumOfSquares)
+ }
+
+ total := h.total()
+ if total != test.total {
+ t.Errorf("h.Total = %v WANT: %v", total, test.total)
+ }
+ }
+}
+
+func TestMultiply(t *testing.T) {
+ var h histogram
+ for i, test := range multiplyTests {
+ h.addMeasurement(test.in)
+ h.Multiply(test.ratio)
+ if h.sum != test.expectedSum {
+ t.Errorf("#%v: h.sum = %v WANT: %v", i, h.sum, test.expectedSum)
+ }
+ if h.total() != test.expectedTotal {
+ t.Errorf("#%v: h.total = %v WANT: %v", i, h.total(), test.expectedTotal)
+ }
+ if h.sumOfSquares != test.expectedSumOfSquares {
+ t.Errorf("#%v: h.SumOfSquares = %v WANT: %v", i, test.expectedSumOfSquares, h.sumOfSquares)
+ }
+ }
+}
+
+func TestBucketingFunctions(t *testing.T) {
+ for _, test := range bucketingTests {
+ log := log2(test.in)
+ if log != test.log {
+ t.Errorf("log2 = %v WANT: %v", log, test.log)
+ }
+
+ bucket := getBucket(test.in)
+ if bucket != test.bucket {
+ t.Errorf("getBucket = %v WANT: %v", bucket, test.bucket)
+ }
+ }
+}
+
+func TestAverage(t *testing.T) {
+ a := new(histogram)
+ average := a.average()
+ if average != 0 {
+ t.Errorf("Average of empty histogram was %v WANT: 0", average)
+ }
+
+ a.addMeasurement(1)
+ a.addMeasurement(1)
+ a.addMeasurement(3)
+ const expected = float64(5) / float64(3)
+ average = a.average()
+
+ if !isApproximate(average, expected) {
+ t.Errorf("Average = %g WANT: %v", average, expected)
+ }
+}
+
+func TestStandardDeviation(t *testing.T) {
+ a := new(histogram)
+ add(a, 10, 1<<4)
+ add(a, 10, 1<<5)
+ add(a, 10, 1<<6)
+ stdDev := a.standardDeviation()
+ const expected = 19.95
+
+ if !isApproximate(stdDev, expected) {
+ t.Errorf("StandardDeviation = %v WANT: %v", stdDev, expected)
+ }
+
+ // No values
+ a = new(histogram)
+ stdDev = a.standardDeviation()
+
+ if !isApproximate(stdDev, 0) {
+ t.Errorf("StandardDeviation = %v WANT: 0", stdDev)
+ }
+
+ add(a, 1, 1<<4)
+ if !isApproximate(stdDev, 0) {
+ t.Errorf("StandardDeviation = %v WANT: 0", stdDev)
+ }
+
+ add(a, 10, 1<<4)
+ if !isApproximate(stdDev, 0) {
+ t.Errorf("StandardDeviation = %v WANT: 0", stdDev)
+ }
+}
+
+func TestPercentileBoundary(t *testing.T) {
+ a := new(histogram)
+ add(a, 5, 1<<4)
+ add(a, 10, 1<<6)
+ add(a, 5, 1<<7)
+
+ for _, test := range percentileTests {
+ percentile := a.percentileBoundary(test.fraction)
+ if percentile != test.expected {
+ t.Errorf("h.PercentileBoundary (fraction=%v) = %v WANT: %v", test.fraction, percentile, test.expected)
+ }
+ }
+}
+
+func TestCopyFrom(t *testing.T) {
+ a := histogram{5, 25, []int64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38}, 4, -1}
+ b := histogram{6, 36, []int64{2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39}, 5, -1}
+
+ a.CopyFrom(&b)
+
+ if a.String() != b.String() {
+ t.Errorf("a.String = %s WANT: %s", a.String(), b.String())
+ }
+}
+
+func TestClear(t *testing.T) {
+ a := histogram{5, 25, []int64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38}, 4, -1}
+
+ a.Clear()
+
+ expected := "0, 0.000000, 0, 0, []"
+ if a.String() != expected {
+ t.Errorf("a.String = %s WANT %s", a.String(), expected)
+ }
+}
+
+func TestNew(t *testing.T) {
+ a := histogram{5, 25, []int64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38}, 4, -1}
+ b := a.New()
+
+ expected := "0, 0.000000, 0, 0, []"
+ if b.(*histogram).String() != expected {
+ t.Errorf("b.(*histogram).String = %s WANT: %s", b.(*histogram).String(), expected)
+ }
+}
+
+func TestAdd(t *testing.T) {
+ // The tests here depend on the associativity of addMeasurement and Add.
+ // Add empty observation
+ a := histogram{5, 25, []int64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38}, 4, -1}
+ b := a.New()
+
+ expected := a.String()
+ a.Add(b)
+ if a.String() != expected {
+ t.Errorf("a.String = %s WANT: %s", a.String(), expected)
+ }
+
+ // Add same bucketed value, no new buckets
+ c := new(histogram)
+ d := new(histogram)
+ e := new(histogram)
+ c.addMeasurement(12)
+ d.addMeasurement(11)
+ e.addMeasurement(12)
+ e.addMeasurement(11)
+ c.Add(d)
+ if c.String() != e.String() {
+ t.Errorf("c.String = %s WANT: %s", c.String(), e.String())
+ }
+
+ // Add bucketed values
+ f := new(histogram)
+ g := new(histogram)
+ h := new(histogram)
+ f.addMeasurement(4)
+ f.addMeasurement(12)
+ f.addMeasurement(100)
+ g.addMeasurement(18)
+ g.addMeasurement(36)
+ g.addMeasurement(255)
+ h.addMeasurement(4)
+ h.addMeasurement(12)
+ h.addMeasurement(100)
+ h.addMeasurement(18)
+ h.addMeasurement(36)
+ h.addMeasurement(255)
+ f.Add(g)
+ if f.String() != h.String() {
+ t.Errorf("f.String = %q WANT: %q", f.String(), h.String())
+ }
+
+ // add buckets to no buckets
+ i := new(histogram)
+ j := new(histogram)
+ k := new(histogram)
+ j.addMeasurement(18)
+ j.addMeasurement(36)
+ j.addMeasurement(255)
+ k.addMeasurement(18)
+ k.addMeasurement(36)
+ k.addMeasurement(255)
+ i.Add(j)
+ if i.String() != k.String() {
+ t.Errorf("i.String = %q WANT: %q", i.String(), k.String())
+ }
+
+ // add buckets to single value (no overlap)
+ l := new(histogram)
+ m := new(histogram)
+ n := new(histogram)
+ l.addMeasurement(0)
+ m.addMeasurement(18)
+ m.addMeasurement(36)
+ m.addMeasurement(255)
+ n.addMeasurement(0)
+ n.addMeasurement(18)
+ n.addMeasurement(36)
+ n.addMeasurement(255)
+ l.Add(m)
+ if l.String() != n.String() {
+ t.Errorf("l.String = %q WANT: %q", l.String(), n.String())
+ }
+
+ // mixed order
+ o := new(histogram)
+ p := new(histogram)
+ o.addMeasurement(0)
+ o.addMeasurement(2)
+ o.addMeasurement(0)
+ p.addMeasurement(0)
+ p.addMeasurement(0)
+ p.addMeasurement(2)
+ if o.String() != p.String() {
+ t.Errorf("o.String = %q WANT: %q", o.String(), p.String())
+ }
+}
+
+func add(h *histogram, times int, val int64) {
+ for i := 0; i < times; i++ {
+ h.addMeasurement(val)
+ }
+}
+
+func isApproximate(x, y float64) bool {
+ return math.Abs(x-y) < 1e-2
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/trace/trace.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/trace/trace.go
new file mode 100644
index 000000000..bb72a527e
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/trace/trace.go
@@ -0,0 +1,1082 @@
+// Copyright 2015 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 trace implements tracing of requests and long-lived objects.
+It exports HTTP interfaces on /debug/requests and /debug/events.
+
+A trace.Trace provides tracing for short-lived objects, usually requests.
+A request handler might be implemented like this:
+
+ func fooHandler(w http.ResponseWriter, req *http.Request) {
+ tr := trace.New("mypkg.Foo", req.URL.Path)
+ defer tr.Finish()
+ ...
+ tr.LazyPrintf("some event %q happened", str)
+ ...
+ if err := somethingImportant(); err != nil {
+ tr.LazyPrintf("somethingImportant failed: %v", err)
+ tr.SetError()
+ }
+ }
+
+The /debug/requests HTTP endpoint organizes the traces by family,
+errors, and duration. It also provides histogram of request duration
+for each family.
+
+A trace.EventLog provides tracing for long-lived objects, such as RPC
+connections.
+
+ // A Fetcher fetches URL paths for a single domain.
+ type Fetcher struct {
+ domain string
+ events trace.EventLog
+ }
+
+ func NewFetcher(domain string) *Fetcher {
+ return &Fetcher{
+ domain,
+ trace.NewEventLog("mypkg.Fetcher", domain),
+ }
+ }
+
+ func (f *Fetcher) Fetch(path string) (string, error) {
+ resp, err := http.Get("http://" + f.domain + "/" + path)
+ if err != nil {
+ f.events.Errorf("Get(%q) = %v", path, err)
+ return "", err
+ }
+ f.events.Printf("Get(%q) = %s", path, resp.Status)
+ ...
+ }
+
+ func (f *Fetcher) Close() error {
+ f.events.Finish()
+ return nil
+ }
+
+The /debug/events HTTP endpoint organizes the event logs by family and
+by time since the last error. The expanded view displays recent log
+entries and the log's call stack.
+*/
+package trace // import "golang.org/x/net/trace"
+
+import (
+ "bytes"
+ "fmt"
+ "html/template"
+ "io"
+ "log"
+ "net"
+ "net/http"
+ "runtime"
+ "sort"
+ "strconv"
+ "sync"
+ "sync/atomic"
+ "time"
+
+ "golang.org/x/net/internal/timeseries"
+)
+
+// DebugUseAfterFinish controls whether to debug uses of Trace values after finishing.
+// FOR DEBUGGING ONLY. This will slow down the program.
+var DebugUseAfterFinish = false
+
+// AuthRequest determines whether a specific request is permitted to load the
+// /debug/requests or /debug/events pages.
+//
+// It returns two bools; the first indicates whether the page may be viewed at all,
+// and the second indicates whether sensitive events will be shown.
+//
+// AuthRequest may be replaced by a program to customize its authorization requirements.
+//
+// The default AuthRequest function returns (true, true) if and only if the request
+// comes from localhost/127.0.0.1/[::1].
+var AuthRequest = func(req *http.Request) (any, sensitive bool) {
+ // RemoteAddr is commonly in the form "IP" or "IP:port".
+ // If it is in the form "IP:port", split off the port.
+ host, _, err := net.SplitHostPort(req.RemoteAddr)
+ if err != nil {
+ host = req.RemoteAddr
+ }
+ switch host {
+ case "localhost", "127.0.0.1", "::1":
+ return true, true
+ default:
+ return false, false
+ }
+}
+
+func init() {
+ // TODO(jbd): Serve Traces from /debug/traces in the future?
+ // There is no requirement for a request to be present to have traces.
+ http.HandleFunc("/debug/requests", Traces)
+ http.HandleFunc("/debug/events", Events)
+}
+
+// Traces responds with traces from the program.
+// The package initialization registers it in http.DefaultServeMux
+// at /debug/requests.
+//
+// It performs authorization by running AuthRequest.
+func Traces(w http.ResponseWriter, req *http.Request) {
+ any, sensitive := AuthRequest(req)
+ if !any {
+ http.Error(w, "not allowed", http.StatusUnauthorized)
+ return
+ }
+ w.Header().Set("Content-Type", "text/html; charset=utf-8")
+ Render(w, req, sensitive)
+}
+
+// Events responds with a page of events collected by EventLogs.
+// The package initialization registers it in http.DefaultServeMux
+// at /debug/events.
+//
+// It performs authorization by running AuthRequest.
+func Events(w http.ResponseWriter, req *http.Request) {
+ any, sensitive := AuthRequest(req)
+ if !any {
+ http.Error(w, "not allowed", http.StatusUnauthorized)
+ return
+ }
+ w.Header().Set("Content-Type", "text/html; charset=utf-8")
+ RenderEvents(w, req, sensitive)
+}
+
+// Render renders the HTML page typically served at /debug/requests.
+// It does not do any auth checking. The request may be nil.
+//
+// Most users will use the Traces handler.
+func Render(w io.Writer, req *http.Request, sensitive bool) {
+ data := &struct {
+ Families []string
+ ActiveTraceCount map[string]int
+ CompletedTraces map[string]*family
+
+ // Set when a bucket has been selected.
+ Traces traceList
+ Family string
+ Bucket int
+ Expanded bool
+ Traced bool
+ Active bool
+ ShowSensitive bool // whether to show sensitive events
+
+ Histogram template.HTML
+ HistogramWindow string // e.g. "last minute", "last hour", "all time"
+
+ // If non-zero, the set of traces is a partial set,
+ // and this is the total number.
+ Total int
+ }{
+ CompletedTraces: completedTraces,
+ }
+
+ data.ShowSensitive = sensitive
+ if req != nil {
+ // Allow show_sensitive=0 to force hiding of sensitive data for testing.
+ // This only goes one way; you can't use show_sensitive=1 to see things.
+ if req.FormValue("show_sensitive") == "0" {
+ data.ShowSensitive = false
+ }
+
+ if exp, err := strconv.ParseBool(req.FormValue("exp")); err == nil {
+ data.Expanded = exp
+ }
+ if exp, err := strconv.ParseBool(req.FormValue("rtraced")); err == nil {
+ data.Traced = exp
+ }
+ }
+
+ completedMu.RLock()
+ data.Families = make([]string, 0, len(completedTraces))
+ for fam := range completedTraces {
+ data.Families = append(data.Families, fam)
+ }
+ completedMu.RUnlock()
+ sort.Strings(data.Families)
+
+ // We are careful here to minimize the time spent locking activeMu,
+ // since that lock is required every time an RPC starts and finishes.
+ data.ActiveTraceCount = make(map[string]int, len(data.Families))
+ activeMu.RLock()
+ for fam, s := range activeTraces {
+ data.ActiveTraceCount[fam] = s.Len()
+ }
+ activeMu.RUnlock()
+
+ var ok bool
+ data.Family, data.Bucket, ok = parseArgs(req)
+ switch {
+ case !ok:
+ // No-op
+ case data.Bucket == -1:
+ data.Active = true
+ n := data.ActiveTraceCount[data.Family]
+ data.Traces = getActiveTraces(data.Family)
+ if len(data.Traces) < n {
+ data.Total = n
+ }
+ case data.Bucket < bucketsPerFamily:
+ if b := lookupBucket(data.Family, data.Bucket); b != nil {
+ data.Traces = b.Copy(data.Traced)
+ }
+ default:
+ if f := getFamily(data.Family, false); f != nil {
+ var obs timeseries.Observable
+ f.LatencyMu.RLock()
+ switch o := data.Bucket - bucketsPerFamily; o {
+ case 0:
+ obs = f.Latency.Minute()
+ data.HistogramWindow = "last minute"
+ case 1:
+ obs = f.Latency.Hour()
+ data.HistogramWindow = "last hour"
+ case 2:
+ obs = f.Latency.Total()
+ data.HistogramWindow = "all time"
+ }
+ f.LatencyMu.RUnlock()
+ if obs != nil {
+ data.Histogram = obs.(*histogram).html()
+ }
+ }
+ }
+
+ if data.Traces != nil {
+ defer data.Traces.Free()
+ sort.Sort(data.Traces)
+ }
+
+ completedMu.RLock()
+ defer completedMu.RUnlock()
+ if err := pageTmpl().ExecuteTemplate(w, "Page", data); err != nil {
+ log.Printf("net/trace: Failed executing template: %v", err)
+ }
+}
+
+func parseArgs(req *http.Request) (fam string, b int, ok bool) {
+ if req == nil {
+ return "", 0, false
+ }
+ fam, bStr := req.FormValue("fam"), req.FormValue("b")
+ if fam == "" || bStr == "" {
+ return "", 0, false
+ }
+ b, err := strconv.Atoi(bStr)
+ if err != nil || b < -1 {
+ return "", 0, false
+ }
+
+ return fam, b, true
+}
+
+func lookupBucket(fam string, b int) *traceBucket {
+ f := getFamily(fam, false)
+ if f == nil || b < 0 || b >= len(f.Buckets) {
+ return nil
+ }
+ return f.Buckets[b]
+}
+
+type contextKeyT string
+
+var contextKey = contextKeyT("golang.org/x/net/trace.Trace")
+
+// Trace represents an active request.
+type Trace interface {
+ // LazyLog adds x to the event log. It will be evaluated each time the
+ // /debug/requests page is rendered. Any memory referenced by x will be
+ // pinned until the trace is finished and later discarded.
+ LazyLog(x fmt.Stringer, sensitive bool)
+
+ // LazyPrintf evaluates its arguments with fmt.Sprintf each time the
+ // /debug/requests page is rendered. Any memory referenced by a will be
+ // pinned until the trace is finished and later discarded.
+ LazyPrintf(format string, a ...interface{})
+
+ // SetError declares that this trace resulted in an error.
+ SetError()
+
+ // SetRecycler sets a recycler for the trace.
+ // f will be called for each event passed to LazyLog at a time when
+ // it is no longer required, whether while the trace is still active
+ // and the event is discarded, or when a completed trace is discarded.
+ SetRecycler(f func(interface{}))
+
+ // SetTraceInfo sets the trace info for the trace.
+ // This is currently unused.
+ SetTraceInfo(traceID, spanID uint64)
+
+ // SetMaxEvents sets the maximum number of events that will be stored
+ // in the trace. This has no effect if any events have already been
+ // added to the trace.
+ SetMaxEvents(m int)
+
+ // Finish declares that this trace is complete.
+ // The trace should not be used after calling this method.
+ Finish()
+}
+
+type lazySprintf struct {
+ format string
+ a []interface{}
+}
+
+func (l *lazySprintf) String() string {
+ return fmt.Sprintf(l.format, l.a...)
+}
+
+// New returns a new Trace with the specified family and title.
+func New(family, title string) Trace {
+ tr := newTrace()
+ tr.ref()
+ tr.Family, tr.Title = family, title
+ tr.Start = time.Now()
+ tr.maxEvents = maxEventsPerTrace
+ tr.events = tr.eventsBuf[:0]
+
+ activeMu.RLock()
+ s := activeTraces[tr.Family]
+ activeMu.RUnlock()
+ if s == nil {
+ activeMu.Lock()
+ s = activeTraces[tr.Family] // check again
+ if s == nil {
+ s = new(traceSet)
+ activeTraces[tr.Family] = s
+ }
+ activeMu.Unlock()
+ }
+ s.Add(tr)
+
+ // Trigger allocation of the completed trace structure for this family.
+ // This will cause the family to be present in the request page during
+ // the first trace of this family. We don't care about the return value,
+ // nor is there any need for this to run inline, so we execute it in its
+ // own goroutine, but only if the family isn't allocated yet.
+ completedMu.RLock()
+ if _, ok := completedTraces[tr.Family]; !ok {
+ go allocFamily(tr.Family)
+ }
+ completedMu.RUnlock()
+
+ return tr
+}
+
+func (tr *trace) Finish() {
+ tr.Elapsed = time.Now().Sub(tr.Start)
+ if DebugUseAfterFinish {
+ buf := make([]byte, 4<<10) // 4 KB should be enough
+ n := runtime.Stack(buf, false)
+ tr.finishStack = buf[:n]
+ }
+
+ activeMu.RLock()
+ m := activeTraces[tr.Family]
+ activeMu.RUnlock()
+ m.Remove(tr)
+
+ f := getFamily(tr.Family, true)
+ for _, b := range f.Buckets {
+ if b.Cond.match(tr) {
+ b.Add(tr)
+ }
+ }
+ // Add a sample of elapsed time as microseconds to the family's timeseries
+ h := new(histogram)
+ h.addMeasurement(tr.Elapsed.Nanoseconds() / 1e3)
+ f.LatencyMu.Lock()
+ f.Latency.Add(h)
+ f.LatencyMu.Unlock()
+
+ tr.unref() // matches ref in New
+}
+
+const (
+ bucketsPerFamily = 9
+ tracesPerBucket = 10
+ maxActiveTraces = 20 // Maximum number of active traces to show.
+ maxEventsPerTrace = 10
+ numHistogramBuckets = 38
+)
+
+var (
+ // The active traces.
+ activeMu sync.RWMutex
+ activeTraces = make(map[string]*traceSet) // family -> traces
+
+ // Families of completed traces.
+ completedMu sync.RWMutex
+ completedTraces = make(map[string]*family) // family -> traces
+)
+
+type traceSet struct {
+ mu sync.RWMutex
+ m map[*trace]bool
+
+ // We could avoid the entire map scan in FirstN by having a slice of all the traces
+ // ordered by start time, and an index into that from the trace struct, with a periodic
+ // repack of the slice after enough traces finish; we could also use a skip list or similar.
+ // However, that would shift some of the expense from /debug/requests time to RPC time,
+ // which is probably the wrong trade-off.
+}
+
+func (ts *traceSet) Len() int {
+ ts.mu.RLock()
+ defer ts.mu.RUnlock()
+ return len(ts.m)
+}
+
+func (ts *traceSet) Add(tr *trace) {
+ ts.mu.Lock()
+ if ts.m == nil {
+ ts.m = make(map[*trace]bool)
+ }
+ ts.m[tr] = true
+ ts.mu.Unlock()
+}
+
+func (ts *traceSet) Remove(tr *trace) {
+ ts.mu.Lock()
+ delete(ts.m, tr)
+ ts.mu.Unlock()
+}
+
+// FirstN returns the first n traces ordered by time.
+func (ts *traceSet) FirstN(n int) traceList {
+ ts.mu.RLock()
+ defer ts.mu.RUnlock()
+
+ if n > len(ts.m) {
+ n = len(ts.m)
+ }
+ trl := make(traceList, 0, n)
+
+ // Fast path for when no selectivity is needed.
+ if n == len(ts.m) {
+ for tr := range ts.m {
+ tr.ref()
+ trl = append(trl, tr)
+ }
+ sort.Sort(trl)
+ return trl
+ }
+
+ // Pick the oldest n traces.
+ // This is inefficient. See the comment in the traceSet struct.
+ for tr := range ts.m {
+ // Put the first n traces into trl in the order they occur.
+ // When we have n, sort trl, and thereafter maintain its order.
+ if len(trl) < n {
+ tr.ref()
+ trl = append(trl, tr)
+ if len(trl) == n {
+ // This is guaranteed to happen exactly once during this loop.
+ sort.Sort(trl)
+ }
+ continue
+ }
+ if tr.Start.After(trl[n-1].Start) {
+ continue
+ }
+
+ // Find where to insert this one.
+ tr.ref()
+ i := sort.Search(n, func(i int) bool { return trl[i].Start.After(tr.Start) })
+ trl[n-1].unref()
+ copy(trl[i+1:], trl[i:])
+ trl[i] = tr
+ }
+
+ return trl
+}
+
+func getActiveTraces(fam string) traceList {
+ activeMu.RLock()
+ s := activeTraces[fam]
+ activeMu.RUnlock()
+ if s == nil {
+ return nil
+ }
+ return s.FirstN(maxActiveTraces)
+}
+
+func getFamily(fam string, allocNew bool) *family {
+ completedMu.RLock()
+ f := completedTraces[fam]
+ completedMu.RUnlock()
+ if f == nil && allocNew {
+ f = allocFamily(fam)
+ }
+ return f
+}
+
+func allocFamily(fam string) *family {
+ completedMu.Lock()
+ defer completedMu.Unlock()
+ f := completedTraces[fam]
+ if f == nil {
+ f = newFamily()
+ completedTraces[fam] = f
+ }
+ return f
+}
+
+// family represents a set of trace buckets and associated latency information.
+type family struct {
+ // traces may occur in multiple buckets.
+ Buckets [bucketsPerFamily]*traceBucket
+
+ // latency time series
+ LatencyMu sync.RWMutex
+ Latency *timeseries.MinuteHourSeries
+}
+
+func newFamily() *family {
+ return &family{
+ Buckets: [bucketsPerFamily]*traceBucket{
+ {Cond: minCond(0)},
+ {Cond: minCond(50 * time.Millisecond)},
+ {Cond: minCond(100 * time.Millisecond)},
+ {Cond: minCond(200 * time.Millisecond)},
+ {Cond: minCond(500 * time.Millisecond)},
+ {Cond: minCond(1 * time.Second)},
+ {Cond: minCond(10 * time.Second)},
+ {Cond: minCond(100 * time.Second)},
+ {Cond: errorCond{}},
+ },
+ Latency: timeseries.NewMinuteHourSeries(func() timeseries.Observable { return new(histogram) }),
+ }
+}
+
+// traceBucket represents a size-capped bucket of historic traces,
+// along with a condition for a trace to belong to the bucket.
+type traceBucket struct {
+ Cond cond
+
+ // Ring buffer implementation of a fixed-size FIFO queue.
+ mu sync.RWMutex
+ buf [tracesPerBucket]*trace
+ start int // < tracesPerBucket
+ length int // <= tracesPerBucket
+}
+
+func (b *traceBucket) Add(tr *trace) {
+ b.mu.Lock()
+ defer b.mu.Unlock()
+
+ i := b.start + b.length
+ if i >= tracesPerBucket {
+ i -= tracesPerBucket
+ }
+ if b.length == tracesPerBucket {
+ // "Remove" an element from the bucket.
+ b.buf[i].unref()
+ b.start++
+ if b.start == tracesPerBucket {
+ b.start = 0
+ }
+ }
+ b.buf[i] = tr
+ if b.length < tracesPerBucket {
+ b.length++
+ }
+ tr.ref()
+}
+
+// Copy returns a copy of the traces in the bucket.
+// If tracedOnly is true, only the traces with trace information will be returned.
+// The logs will be ref'd before returning; the caller should call
+// the Free method when it is done with them.
+// TODO(dsymonds): keep track of traced requests in separate buckets.
+func (b *traceBucket) Copy(tracedOnly bool) traceList {
+ b.mu.RLock()
+ defer b.mu.RUnlock()
+
+ trl := make(traceList, 0, b.length)
+ for i, x := 0, b.start; i < b.length; i++ {
+ tr := b.buf[x]
+ if !tracedOnly || tr.spanID != 0 {
+ tr.ref()
+ trl = append(trl, tr)
+ }
+ x++
+ if x == b.length {
+ x = 0
+ }
+ }
+ return trl
+}
+
+func (b *traceBucket) Empty() bool {
+ b.mu.RLock()
+ defer b.mu.RUnlock()
+ return b.length == 0
+}
+
+// cond represents a condition on a trace.
+type cond interface {
+ match(t *trace) bool
+ String() string
+}
+
+type minCond time.Duration
+
+func (m minCond) match(t *trace) bool { return t.Elapsed >= time.Duration(m) }
+func (m minCond) String() string { return fmt.Sprintf("≥%gs", time.Duration(m).Seconds()) }
+
+type errorCond struct{}
+
+func (e errorCond) match(t *trace) bool { return t.IsError }
+func (e errorCond) String() string { return "errors" }
+
+type traceList []*trace
+
+// Free calls unref on each element of the list.
+func (trl traceList) Free() {
+ for _, t := range trl {
+ t.unref()
+ }
+}
+
+// traceList may be sorted in reverse chronological order.
+func (trl traceList) Len() int { return len(trl) }
+func (trl traceList) Less(i, j int) bool { return trl[i].Start.After(trl[j].Start) }
+func (trl traceList) Swap(i, j int) { trl[i], trl[j] = trl[j], trl[i] }
+
+// An event is a timestamped log entry in a trace.
+type event struct {
+ When time.Time
+ Elapsed time.Duration // since previous event in trace
+ NewDay bool // whether this event is on a different day to the previous event
+ Recyclable bool // whether this event was passed via LazyLog
+ Sensitive bool // whether this event contains sensitive information
+ What interface{} // string or fmt.Stringer
+}
+
+// WhenString returns a string representation of the elapsed time of the event.
+// It will include the date if midnight was crossed.
+func (e event) WhenString() string {
+ if e.NewDay {
+ return e.When.Format("2006/01/02 15:04:05.000000")
+ }
+ return e.When.Format("15:04:05.000000")
+}
+
+// discarded represents a number of discarded events.
+// It is stored as *discarded to make it easier to update in-place.
+type discarded int
+
+func (d *discarded) String() string {
+ return fmt.Sprintf("(%d events discarded)", int(*d))
+}
+
+// trace represents an active or complete request,
+// either sent or received by this program.
+type trace struct {
+ // Family is the top-level grouping of traces to which this belongs.
+ Family string
+
+ // Title is the title of this trace.
+ Title string
+
+ // Timing information.
+ Start time.Time
+ Elapsed time.Duration // zero while active
+
+ // Trace information if non-zero.
+ traceID uint64
+ spanID uint64
+
+ // Whether this trace resulted in an error.
+ IsError bool
+
+ // Append-only sequence of events (modulo discards).
+ mu sync.RWMutex
+ events []event
+ maxEvents int
+
+ refs int32 // how many buckets this is in
+ recycler func(interface{})
+ disc discarded // scratch space to avoid allocation
+
+ finishStack []byte // where finish was called, if DebugUseAfterFinish is set
+
+ eventsBuf [4]event // preallocated buffer in case we only log a few events
+}
+
+func (tr *trace) reset() {
+ // Clear all but the mutex. Mutexes may not be copied, even when unlocked.
+ tr.Family = ""
+ tr.Title = ""
+ tr.Start = time.Time{}
+ tr.Elapsed = 0
+ tr.traceID = 0
+ tr.spanID = 0
+ tr.IsError = false
+ tr.maxEvents = 0
+ tr.events = nil
+ tr.refs = 0
+ tr.recycler = nil
+ tr.disc = 0
+ tr.finishStack = nil
+ for i := range tr.eventsBuf {
+ tr.eventsBuf[i] = event{}
+ }
+}
+
+// delta returns the elapsed time since the last event or the trace start,
+// and whether it spans midnight.
+// L >= tr.mu
+func (tr *trace) delta(t time.Time) (time.Duration, bool) {
+ if len(tr.events) == 0 {
+ return t.Sub(tr.Start), false
+ }
+ prev := tr.events[len(tr.events)-1].When
+ return t.Sub(prev), prev.Day() != t.Day()
+}
+
+func (tr *trace) addEvent(x interface{}, recyclable, sensitive bool) {
+ if DebugUseAfterFinish && tr.finishStack != nil {
+ buf := make([]byte, 4<<10) // 4 KB should be enough
+ n := runtime.Stack(buf, false)
+ log.Printf("net/trace: trace used after finish:\nFinished at:\n%s\nUsed at:\n%s", tr.finishStack, buf[:n])
+ }
+
+ /*
+ NOTE TO DEBUGGERS
+
+ If you are here because your program panicked in this code,
+ it is almost definitely the fault of code using this package,
+ and very unlikely to be the fault of this code.
+
+ The most likely scenario is that some code elsewhere is using
+ a trace.Trace after its Finish method is called.
+ You can temporarily set the DebugUseAfterFinish var
+ to help discover where that is; do not leave that var set,
+ since it makes this package much less efficient.
+ */
+
+ e := event{When: time.Now(), What: x, Recyclable: recyclable, Sensitive: sensitive}
+ tr.mu.Lock()
+ e.Elapsed, e.NewDay = tr.delta(e.When)
+ if len(tr.events) < tr.maxEvents {
+ tr.events = append(tr.events, e)
+ } else {
+ // Discard the middle events.
+ di := int((tr.maxEvents - 1) / 2)
+ if d, ok := tr.events[di].What.(*discarded); ok {
+ (*d)++
+ } else {
+ // disc starts at two to count for the event it is replacing,
+ // plus the next one that we are about to drop.
+ tr.disc = 2
+ if tr.recycler != nil && tr.events[di].Recyclable {
+ go tr.recycler(tr.events[di].What)
+ }
+ tr.events[di].What = &tr.disc
+ }
+ // The timestamp of the discarded meta-event should be
+ // the time of the last event it is representing.
+ tr.events[di].When = tr.events[di+1].When
+
+ if tr.recycler != nil && tr.events[di+1].Recyclable {
+ go tr.recycler(tr.events[di+1].What)
+ }
+ copy(tr.events[di+1:], tr.events[di+2:])
+ tr.events[tr.maxEvents-1] = e
+ }
+ tr.mu.Unlock()
+}
+
+func (tr *trace) LazyLog(x fmt.Stringer, sensitive bool) {
+ tr.addEvent(x, true, sensitive)
+}
+
+func (tr *trace) LazyPrintf(format string, a ...interface{}) {
+ tr.addEvent(&lazySprintf{format, a}, false, false)
+}
+
+func (tr *trace) SetError() { tr.IsError = true }
+
+func (tr *trace) SetRecycler(f func(interface{})) {
+ tr.recycler = f
+}
+
+func (tr *trace) SetTraceInfo(traceID, spanID uint64) {
+ tr.traceID, tr.spanID = traceID, spanID
+}
+
+func (tr *trace) SetMaxEvents(m int) {
+ // Always keep at least three events: first, discarded count, last.
+ if len(tr.events) == 0 && m > 3 {
+ tr.maxEvents = m
+ }
+}
+
+func (tr *trace) ref() {
+ atomic.AddInt32(&tr.refs, 1)
+}
+
+func (tr *trace) unref() {
+ if atomic.AddInt32(&tr.refs, -1) == 0 {
+ if tr.recycler != nil {
+ // freeTrace clears tr, so we hold tr.recycler and tr.events here.
+ go func(f func(interface{}), es []event) {
+ for _, e := range es {
+ if e.Recyclable {
+ f(e.What)
+ }
+ }
+ }(tr.recycler, tr.events)
+ }
+
+ freeTrace(tr)
+ }
+}
+
+func (tr *trace) When() string {
+ return tr.Start.Format("2006/01/02 15:04:05.000000")
+}
+
+func (tr *trace) ElapsedTime() string {
+ t := tr.Elapsed
+ if t == 0 {
+ // Active trace.
+ t = time.Since(tr.Start)
+ }
+ return fmt.Sprintf("%.6f", t.Seconds())
+}
+
+func (tr *trace) Events() []event {
+ tr.mu.RLock()
+ defer tr.mu.RUnlock()
+ return tr.events
+}
+
+var traceFreeList = make(chan *trace, 1000) // TODO(dsymonds): Use sync.Pool?
+
+// newTrace returns a trace ready to use.
+func newTrace() *trace {
+ select {
+ case tr := <-traceFreeList:
+ return tr
+ default:
+ return new(trace)
+ }
+}
+
+// freeTrace adds tr to traceFreeList if there's room.
+// This is non-blocking.
+func freeTrace(tr *trace) {
+ if DebugUseAfterFinish {
+ return // never reuse
+ }
+ tr.reset()
+ select {
+ case traceFreeList <- tr:
+ default:
+ }
+}
+
+func elapsed(d time.Duration) string {
+ b := []byte(fmt.Sprintf("%.6f", d.Seconds()))
+
+ // For subsecond durations, blank all zeros before decimal point,
+ // and all zeros between the decimal point and the first non-zero digit.
+ if d < time.Second {
+ dot := bytes.IndexByte(b, '.')
+ for i := 0; i < dot; i++ {
+ b[i] = ' '
+ }
+ for i := dot + 1; i < len(b); i++ {
+ if b[i] == '0' {
+ b[i] = ' '
+ } else {
+ break
+ }
+ }
+ }
+
+ return string(b)
+}
+
+var pageTmplCache *template.Template
+var pageTmplOnce sync.Once
+
+func pageTmpl() *template.Template {
+ pageTmplOnce.Do(func() {
+ pageTmplCache = template.Must(template.New("Page").Funcs(template.FuncMap{
+ "elapsed": elapsed,
+ "add": func(a, b int) int { return a + b },
+ }).Parse(pageHTML))
+ })
+ return pageTmplCache
+}
+
+const pageHTML = `
+{{template "Prolog" .}}
+{{template "StatusTable" .}}
+{{template "Epilog" .}}
+
+{{define "Prolog"}}
+<html>
+ <head>
+ <title>/debug/requests</title>
+ <style type="text/css">
+ body {
+ font-family: sans-serif;
+ }
+ table#tr-status td.family {
+ padding-right: 2em;
+ }
+ table#tr-status td.active {
+ padding-right: 1em;
+ }
+ table#tr-status td.latency-first {
+ padding-left: 1em;
+ }
+ table#tr-status td.empty {
+ color: #aaa;
+ }
+ table#reqs {
+ margin-top: 1em;
+ }
+ table#reqs tr.first {
+ {{if $.Expanded}}font-weight: bold;{{end}}
+ }
+ table#reqs td {
+ font-family: monospace;
+ }
+ table#reqs td.when {
+ text-align: right;
+ white-space: nowrap;
+ }
+ table#reqs td.elapsed {
+ padding: 0 0.5em;
+ text-align: right;
+ white-space: pre;
+ width: 10em;
+ }
+ address {
+ font-size: smaller;
+ margin-top: 5em;
+ }
+ </style>
+ </head>
+ <body>
+
+<h1>/debug/requests</h1>
+{{end}} {{/* end of Prolog */}}
+
+{{define "StatusTable"}}
+<table id="tr-status">
+ {{range $fam := .Families}}
+ <tr>
+ <td class="family">{{$fam}}</td>
+
+ {{$n := index $.ActiveTraceCount $fam}}
+ <td class="active {{if not $n}}empty{{end}}">
+ {{if $n}}<a href="?fam={{$fam}}&b=-1{{if $.Expanded}}&exp=1{{end}}">{{end}}
+ [{{$n}} active]
+ {{if $n}}</a>{{end}}
+ </td>
+
+ {{$f := index $.CompletedTraces $fam}}
+ {{range $i, $b := $f.Buckets}}
+ {{$empty := $b.Empty}}
+ <td {{if $empty}}class="empty"{{end}}>
+ {{if not $empty}}<a href="?fam={{$fam}}&b={{$i}}{{if $.Expanded}}&exp=1{{end}}">{{end}}
+ [{{.Cond}}]
+ {{if not $empty}}</a>{{end}}
+ </td>
+ {{end}}
+
+ {{$nb := len $f.Buckets}}
+ <td class="latency-first">
+ <a href="?fam={{$fam}}&b={{$nb}}">[minute]</a>
+ </td>
+ <td>
+ <a href="?fam={{$fam}}&b={{add $nb 1}}">[hour]</a>
+ </td>
+ <td>
+ <a href="?fam={{$fam}}&b={{add $nb 2}}">[total]</a>
+ </td>
+
+ </tr>
+ {{end}}
+</table>
+{{end}} {{/* end of StatusTable */}}
+
+{{define "Epilog"}}
+{{if $.Traces}}
+<hr />
+<h3>Family: {{$.Family}}</h3>
+
+{{if or $.Expanded $.Traced}}
+ <a href="?fam={{$.Family}}&b={{$.Bucket}}">[Normal/Summary]</a>
+{{else}}
+ [Normal/Summary]
+{{end}}
+
+{{if or (not $.Expanded) $.Traced}}
+ <a href="?fam={{$.Family}}&b={{$.Bucket}}&exp=1">[Normal/Expanded]</a>
+{{else}}
+ [Normal/Expanded]
+{{end}}
+
+{{if not $.Active}}
+ {{if or $.Expanded (not $.Traced)}}
+ <a href="?fam={{$.Family}}&b={{$.Bucket}}&rtraced=1">[Traced/Summary]</a>
+ {{else}}
+ [Traced/Summary]
+ {{end}}
+ {{if or (not $.Expanded) (not $.Traced)}}
+ <a href="?fam={{$.Family}}&b={{$.Bucket}}&exp=1&rtraced=1">[Traced/Expanded]</a>
+ {{else}}
+ [Traced/Expanded]
+ {{end}}
+{{end}}
+
+{{if $.Total}}
+<p><em>Showing <b>{{len $.Traces}}</b> of <b>{{$.Total}}</b> traces.</em></p>
+{{end}}
+
+<table id="reqs">
+ <caption>
+ {{if $.Active}}Active{{else}}Completed{{end}} Requests
+ </caption>
+ <tr><th>When</th><th>Elapsed&nbsp;(s)</th></tr>
+ {{range $tr := $.Traces}}
+ <tr class="first">
+ <td class="when">{{$tr.When}}</td>
+ <td class="elapsed">{{$tr.ElapsedTime}}</td>
+ <td>{{$tr.Title}}</td>
+ {{/* TODO: include traceID/spanID */}}
+ </tr>
+ {{if $.Expanded}}
+ {{range $tr.Events}}
+ <tr>
+ <td class="when">{{.WhenString}}</td>
+ <td class="elapsed">{{elapsed .Elapsed}}</td>
+ <td>{{if or $.ShowSensitive (not .Sensitive)}}... {{.What}}{{else}}<em>[redacted]</em>{{end}}</td>
+ </tr>
+ {{end}}
+ {{end}}
+ {{end}}
+</table>
+{{end}} {{/* if $.Traces */}}
+
+{{if $.Histogram}}
+<h4>Latency (&micro;s) of {{$.Family}} over {{$.HistogramWindow}}</h4>
+{{$.Histogram}}
+{{end}} {{/* if $.Histogram */}}
+
+ </body>
+</html>
+{{end}} {{/* end of Epilog */}}
+`
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/trace/trace_go16.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/trace/trace_go16.go
new file mode 100644
index 000000000..d60819118
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/trace/trace_go16.go
@@ -0,0 +1,21 @@
+// 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.
+
+// +build !go1.7
+
+package trace
+
+import "golang.org/x/net/context"
+
+// NewContext returns a copy of the parent context
+// and associates it with a Trace.
+func NewContext(ctx context.Context, tr Trace) context.Context {
+ return context.WithValue(ctx, contextKey, tr)
+}
+
+// FromContext returns the Trace bound to the context, if any.
+func FromContext(ctx context.Context) (tr Trace, ok bool) {
+ tr, ok = ctx.Value(contextKey).(Trace)
+ return
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/trace/trace_go17.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/trace/trace_go17.go
new file mode 100644
index 000000000..df6e1fba7
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/trace/trace_go17.go
@@ -0,0 +1,21 @@
+// 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.
+
+// +build go1.7
+
+package trace
+
+import "context"
+
+// NewContext returns a copy of the parent context
+// and associates it with a Trace.
+func NewContext(ctx context.Context, tr Trace) context.Context {
+ return context.WithValue(ctx, contextKey, tr)
+}
+
+// FromContext returns the Trace bound to the context, if any.
+func FromContext(ctx context.Context) (tr Trace, ok bool) {
+ tr, ok = ctx.Value(contextKey).(Trace)
+ return
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/trace/trace_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/trace/trace_test.go
new file mode 100644
index 000000000..bfd9dfe94
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/trace/trace_test.go
@@ -0,0 +1,178 @@
+// Copyright 2015 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 trace
+
+import (
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+type s struct{}
+
+func (s) String() string { return "lazy string" }
+
+// TestReset checks whether all the fields are zeroed after reset.
+func TestReset(t *testing.T) {
+ tr := New("foo", "bar")
+ tr.LazyLog(s{}, false)
+ tr.LazyPrintf("%d", 1)
+ tr.SetRecycler(func(_ interface{}) {})
+ tr.SetTraceInfo(3, 4)
+ tr.SetMaxEvents(100)
+ tr.SetError()
+ tr.Finish()
+
+ tr.(*trace).reset()
+
+ if !reflect.DeepEqual(tr, new(trace)) {
+ t.Errorf("reset didn't clear all fields: %+v", tr)
+ }
+}
+
+// TestResetLog checks whether all the fields are zeroed after reset.
+func TestResetLog(t *testing.T) {
+ el := NewEventLog("foo", "bar")
+ el.Printf("message")
+ el.Errorf("error")
+ el.Finish()
+
+ el.(*eventLog).reset()
+
+ if !reflect.DeepEqual(el, new(eventLog)) {
+ t.Errorf("reset didn't clear all fields: %+v", el)
+ }
+}
+
+func TestAuthRequest(t *testing.T) {
+ testCases := []struct {
+ host string
+ want bool
+ }{
+ {host: "192.168.23.1", want: false},
+ {host: "192.168.23.1:8080", want: false},
+ {host: "malformed remote addr", want: false},
+ {host: "localhost", want: true},
+ {host: "localhost:8080", want: true},
+ {host: "127.0.0.1", want: true},
+ {host: "127.0.0.1:8080", want: true},
+ {host: "::1", want: true},
+ {host: "[::1]:8080", want: true},
+ }
+ for _, tt := range testCases {
+ req := &http.Request{RemoteAddr: tt.host}
+ any, sensitive := AuthRequest(req)
+ if any != tt.want || sensitive != tt.want {
+ t.Errorf("AuthRequest(%q) = %t, %t; want %t, %t", tt.host, any, sensitive, tt.want, tt.want)
+ }
+ }
+}
+
+// TestParseTemplate checks that all templates used by this package are valid
+// as they are parsed on first usage
+func TestParseTemplate(t *testing.T) {
+ if tmpl := distTmpl(); tmpl == nil {
+ t.Error("invalid template returned from distTmpl()")
+ }
+ if tmpl := pageTmpl(); tmpl == nil {
+ t.Error("invalid template returned from pageTmpl()")
+ }
+ if tmpl := eventsTmpl(); tmpl == nil {
+ t.Error("invalid template returned from eventsTmpl()")
+ }
+}
+
+func benchmarkTrace(b *testing.B, maxEvents, numEvents int) {
+ numSpans := (b.N + numEvents + 1) / numEvents
+
+ for i := 0; i < numSpans; i++ {
+ tr := New("test", "test")
+ tr.SetMaxEvents(maxEvents)
+ for j := 0; j < numEvents; j++ {
+ tr.LazyPrintf("%d", j)
+ }
+ tr.Finish()
+ }
+}
+
+func BenchmarkTrace_Default_2(b *testing.B) {
+ benchmarkTrace(b, 0, 2)
+}
+
+func BenchmarkTrace_Default_10(b *testing.B) {
+ benchmarkTrace(b, 0, 10)
+}
+
+func BenchmarkTrace_Default_100(b *testing.B) {
+ benchmarkTrace(b, 0, 100)
+}
+
+func BenchmarkTrace_Default_1000(b *testing.B) {
+ benchmarkTrace(b, 0, 1000)
+}
+
+func BenchmarkTrace_Default_10000(b *testing.B) {
+ benchmarkTrace(b, 0, 10000)
+}
+
+func BenchmarkTrace_10_2(b *testing.B) {
+ benchmarkTrace(b, 10, 2)
+}
+
+func BenchmarkTrace_10_10(b *testing.B) {
+ benchmarkTrace(b, 10, 10)
+}
+
+func BenchmarkTrace_10_100(b *testing.B) {
+ benchmarkTrace(b, 10, 100)
+}
+
+func BenchmarkTrace_10_1000(b *testing.B) {
+ benchmarkTrace(b, 10, 1000)
+}
+
+func BenchmarkTrace_10_10000(b *testing.B) {
+ benchmarkTrace(b, 10, 10000)
+}
+
+func BenchmarkTrace_100_2(b *testing.B) {
+ benchmarkTrace(b, 100, 2)
+}
+
+func BenchmarkTrace_100_10(b *testing.B) {
+ benchmarkTrace(b, 100, 10)
+}
+
+func BenchmarkTrace_100_100(b *testing.B) {
+ benchmarkTrace(b, 100, 100)
+}
+
+func BenchmarkTrace_100_1000(b *testing.B) {
+ benchmarkTrace(b, 100, 1000)
+}
+
+func BenchmarkTrace_100_10000(b *testing.B) {
+ benchmarkTrace(b, 100, 10000)
+}
+
+func BenchmarkTrace_1000_2(b *testing.B) {
+ benchmarkTrace(b, 1000, 2)
+}
+
+func BenchmarkTrace_1000_10(b *testing.B) {
+ benchmarkTrace(b, 1000, 10)
+}
+
+func BenchmarkTrace_1000_100(b *testing.B) {
+ benchmarkTrace(b, 1000, 100)
+}
+
+func BenchmarkTrace_1000_1000(b *testing.B) {
+ benchmarkTrace(b, 1000, 1000)
+}
+
+func BenchmarkTrace_1000_10000(b *testing.B) {
+ benchmarkTrace(b, 1000, 10000)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/file.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/file.go
new file mode 100644
index 000000000..748118dd3
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/file.go
@@ -0,0 +1,796 @@
+// Copyright 2014 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 webdav
+
+import (
+ "encoding/xml"
+ "io"
+ "net/http"
+ "os"
+ "path"
+ "path/filepath"
+ "strings"
+ "sync"
+ "time"
+
+ "golang.org/x/net/context"
+)
+
+// slashClean is equivalent to but slightly more efficient than
+// path.Clean("/" + name).
+func slashClean(name string) string {
+ if name == "" || name[0] != '/' {
+ name = "/" + name
+ }
+ return path.Clean(name)
+}
+
+// A FileSystem implements access to a collection of named files. The elements
+// in a file path are separated by slash ('/', U+002F) characters, regardless
+// of host operating system convention.
+//
+// Each method has the same semantics as the os package's function of the same
+// name.
+//
+// Note that the os.Rename documentation says that "OS-specific restrictions
+// might apply". In particular, whether or not renaming a file or directory
+// overwriting another existing file or directory is an error is OS-dependent.
+type FileSystem interface {
+ Mkdir(ctx context.Context, name string, perm os.FileMode) error
+ OpenFile(ctx context.Context, name string, flag int, perm os.FileMode) (File, error)
+ RemoveAll(ctx context.Context, name string) error
+ Rename(ctx context.Context, oldName, newName string) error
+ Stat(ctx context.Context, name string) (os.FileInfo, error)
+}
+
+// A File is returned by a FileSystem's OpenFile method and can be served by a
+// Handler.
+//
+// A File may optionally implement the DeadPropsHolder interface, if it can
+// load and save dead properties.
+type File interface {
+ http.File
+ io.Writer
+}
+
+// A Dir implements FileSystem using the native file system restricted to a
+// specific directory tree.
+//
+// While the FileSystem.OpenFile method takes '/'-separated paths, a Dir's
+// string value is a filename on the native file system, not a URL, so it is
+// separated by filepath.Separator, which isn't necessarily '/'.
+//
+// An empty Dir is treated as ".".
+type Dir string
+
+func (d Dir) resolve(name string) string {
+ // This implementation is based on Dir.Open's code in the standard net/http package.
+ if filepath.Separator != '/' && strings.IndexRune(name, filepath.Separator) >= 0 ||
+ strings.Contains(name, "\x00") {
+ return ""
+ }
+ dir := string(d)
+ if dir == "" {
+ dir = "."
+ }
+ return filepath.Join(dir, filepath.FromSlash(slashClean(name)))
+}
+
+func (d Dir) Mkdir(ctx context.Context, name string, perm os.FileMode) error {
+ if name = d.resolve(name); name == "" {
+ return os.ErrNotExist
+ }
+ return os.Mkdir(name, perm)
+}
+
+func (d Dir) OpenFile(ctx context.Context, name string, flag int, perm os.FileMode) (File, error) {
+ if name = d.resolve(name); name == "" {
+ return nil, os.ErrNotExist
+ }
+ f, err := os.OpenFile(name, flag, perm)
+ if err != nil {
+ return nil, err
+ }
+ return f, nil
+}
+
+func (d Dir) RemoveAll(ctx context.Context, name string) error {
+ if name = d.resolve(name); name == "" {
+ return os.ErrNotExist
+ }
+ if name == filepath.Clean(string(d)) {
+ // Prohibit removing the virtual root directory.
+ return os.ErrInvalid
+ }
+ return os.RemoveAll(name)
+}
+
+func (d Dir) Rename(ctx context.Context, oldName, newName string) error {
+ if oldName = d.resolve(oldName); oldName == "" {
+ return os.ErrNotExist
+ }
+ if newName = d.resolve(newName); newName == "" {
+ return os.ErrNotExist
+ }
+ if root := filepath.Clean(string(d)); root == oldName || root == newName {
+ // Prohibit renaming from or to the virtual root directory.
+ return os.ErrInvalid
+ }
+ return os.Rename(oldName, newName)
+}
+
+func (d Dir) Stat(ctx context.Context, name string) (os.FileInfo, error) {
+ if name = d.resolve(name); name == "" {
+ return nil, os.ErrNotExist
+ }
+ return os.Stat(name)
+}
+
+// NewMemFS returns a new in-memory FileSystem implementation.
+func NewMemFS() FileSystem {
+ return &memFS{
+ root: memFSNode{
+ children: make(map[string]*memFSNode),
+ mode: 0660 | os.ModeDir,
+ modTime: time.Now(),
+ },
+ }
+}
+
+// A memFS implements FileSystem, storing all metadata and actual file data
+// in-memory. No limits on filesystem size are used, so it is not recommended
+// this be used where the clients are untrusted.
+//
+// Concurrent access is permitted. The tree structure is protected by a mutex,
+// and each node's contents and metadata are protected by a per-node mutex.
+//
+// TODO: Enforce file permissions.
+type memFS struct {
+ mu sync.Mutex
+ root memFSNode
+}
+
+// TODO: clean up and rationalize the walk/find code.
+
+// walk walks the directory tree for the fullname, calling f at each step. If f
+// returns an error, the walk will be aborted and return that same error.
+//
+// dir is the directory at that step, frag is the name fragment, and final is
+// whether it is the final step. For example, walking "/foo/bar/x" will result
+// in 3 calls to f:
+// - "/", "foo", false
+// - "/foo/", "bar", false
+// - "/foo/bar/", "x", true
+// The frag argument will be empty only if dir is the root node and the walk
+// ends at that root node.
+func (fs *memFS) walk(op, fullname string, f func(dir *memFSNode, frag string, final bool) error) error {
+ original := fullname
+ fullname = slashClean(fullname)
+
+ // Strip any leading "/"s to make fullname a relative path, as the walk
+ // starts at fs.root.
+ if fullname[0] == '/' {
+ fullname = fullname[1:]
+ }
+ dir := &fs.root
+
+ for {
+ frag, remaining := fullname, ""
+ i := strings.IndexRune(fullname, '/')
+ final := i < 0
+ if !final {
+ frag, remaining = fullname[:i], fullname[i+1:]
+ }
+ if frag == "" && dir != &fs.root {
+ panic("webdav: empty path fragment for a clean path")
+ }
+ if err := f(dir, frag, final); err != nil {
+ return &os.PathError{
+ Op: op,
+ Path: original,
+ Err: err,
+ }
+ }
+ if final {
+ break
+ }
+ child := dir.children[frag]
+ if child == nil {
+ return &os.PathError{
+ Op: op,
+ Path: original,
+ Err: os.ErrNotExist,
+ }
+ }
+ if !child.mode.IsDir() {
+ return &os.PathError{
+ Op: op,
+ Path: original,
+ Err: os.ErrInvalid,
+ }
+ }
+ dir, fullname = child, remaining
+ }
+ return nil
+}
+
+// find returns the parent of the named node and the relative name fragment
+// from the parent to the child. For example, if finding "/foo/bar/baz" then
+// parent will be the node for "/foo/bar" and frag will be "baz".
+//
+// If the fullname names the root node, then parent, frag and err will be zero.
+//
+// find returns an error if the parent does not already exist or the parent
+// isn't a directory, but it will not return an error per se if the child does
+// not already exist. The error returned is either nil or an *os.PathError
+// whose Op is op.
+func (fs *memFS) find(op, fullname string) (parent *memFSNode, frag string, err error) {
+ err = fs.walk(op, fullname, func(parent0 *memFSNode, frag0 string, final bool) error {
+ if !final {
+ return nil
+ }
+ if frag0 != "" {
+ parent, frag = parent0, frag0
+ }
+ return nil
+ })
+ return parent, frag, err
+}
+
+func (fs *memFS) Mkdir(ctx context.Context, name string, perm os.FileMode) error {
+ fs.mu.Lock()
+ defer fs.mu.Unlock()
+
+ dir, frag, err := fs.find("mkdir", name)
+ if err != nil {
+ return err
+ }
+ if dir == nil {
+ // We can't create the root.
+ return os.ErrInvalid
+ }
+ if _, ok := dir.children[frag]; ok {
+ return os.ErrExist
+ }
+ dir.children[frag] = &memFSNode{
+ children: make(map[string]*memFSNode),
+ mode: perm.Perm() | os.ModeDir,
+ modTime: time.Now(),
+ }
+ return nil
+}
+
+func (fs *memFS) OpenFile(ctx context.Context, name string, flag int, perm os.FileMode) (File, error) {
+ fs.mu.Lock()
+ defer fs.mu.Unlock()
+
+ dir, frag, err := fs.find("open", name)
+ if err != nil {
+ return nil, err
+ }
+ var n *memFSNode
+ if dir == nil {
+ // We're opening the root.
+ if flag&(os.O_WRONLY|os.O_RDWR) != 0 {
+ return nil, os.ErrPermission
+ }
+ n, frag = &fs.root, "/"
+
+ } else {
+ n = dir.children[frag]
+ if flag&(os.O_SYNC|os.O_APPEND) != 0 {
+ // memFile doesn't support these flags yet.
+ return nil, os.ErrInvalid
+ }
+ if flag&os.O_CREATE != 0 {
+ if flag&os.O_EXCL != 0 && n != nil {
+ return nil, os.ErrExist
+ }
+ if n == nil {
+ n = &memFSNode{
+ mode: perm.Perm(),
+ }
+ dir.children[frag] = n
+ }
+ }
+ if n == nil {
+ return nil, os.ErrNotExist
+ }
+ if flag&(os.O_WRONLY|os.O_RDWR) != 0 && flag&os.O_TRUNC != 0 {
+ n.mu.Lock()
+ n.data = nil
+ n.mu.Unlock()
+ }
+ }
+
+ children := make([]os.FileInfo, 0, len(n.children))
+ for cName, c := range n.children {
+ children = append(children, c.stat(cName))
+ }
+ return &memFile{
+ n: n,
+ nameSnapshot: frag,
+ childrenSnapshot: children,
+ }, nil
+}
+
+func (fs *memFS) RemoveAll(ctx context.Context, name string) error {
+ fs.mu.Lock()
+ defer fs.mu.Unlock()
+
+ dir, frag, err := fs.find("remove", name)
+ if err != nil {
+ return err
+ }
+ if dir == nil {
+ // We can't remove the root.
+ return os.ErrInvalid
+ }
+ delete(dir.children, frag)
+ return nil
+}
+
+func (fs *memFS) Rename(ctx context.Context, oldName, newName string) error {
+ fs.mu.Lock()
+ defer fs.mu.Unlock()
+
+ oldName = slashClean(oldName)
+ newName = slashClean(newName)
+ if oldName == newName {
+ return nil
+ }
+ if strings.HasPrefix(newName, oldName+"/") {
+ // We can't rename oldName to be a sub-directory of itself.
+ return os.ErrInvalid
+ }
+
+ oDir, oFrag, err := fs.find("rename", oldName)
+ if err != nil {
+ return err
+ }
+ if oDir == nil {
+ // We can't rename from the root.
+ return os.ErrInvalid
+ }
+
+ nDir, nFrag, err := fs.find("rename", newName)
+ if err != nil {
+ return err
+ }
+ if nDir == nil {
+ // We can't rename to the root.
+ return os.ErrInvalid
+ }
+
+ oNode, ok := oDir.children[oFrag]
+ if !ok {
+ return os.ErrNotExist
+ }
+ if oNode.children != nil {
+ if nNode, ok := nDir.children[nFrag]; ok {
+ if nNode.children == nil {
+ return errNotADirectory
+ }
+ if len(nNode.children) != 0 {
+ return errDirectoryNotEmpty
+ }
+ }
+ }
+ delete(oDir.children, oFrag)
+ nDir.children[nFrag] = oNode
+ return nil
+}
+
+func (fs *memFS) Stat(ctx context.Context, name string) (os.FileInfo, error) {
+ fs.mu.Lock()
+ defer fs.mu.Unlock()
+
+ dir, frag, err := fs.find("stat", name)
+ if err != nil {
+ return nil, err
+ }
+ if dir == nil {
+ // We're stat'ting the root.
+ return fs.root.stat("/"), nil
+ }
+ if n, ok := dir.children[frag]; ok {
+ return n.stat(path.Base(name)), nil
+ }
+ return nil, os.ErrNotExist
+}
+
+// A memFSNode represents a single entry in the in-memory filesystem and also
+// implements os.FileInfo.
+type memFSNode struct {
+ // children is protected by memFS.mu.
+ children map[string]*memFSNode
+
+ mu sync.Mutex
+ data []byte
+ mode os.FileMode
+ modTime time.Time
+ deadProps map[xml.Name]Property
+}
+
+func (n *memFSNode) stat(name string) *memFileInfo {
+ n.mu.Lock()
+ defer n.mu.Unlock()
+ return &memFileInfo{
+ name: name,
+ size: int64(len(n.data)),
+ mode: n.mode,
+ modTime: n.modTime,
+ }
+}
+
+func (n *memFSNode) DeadProps() (map[xml.Name]Property, error) {
+ n.mu.Lock()
+ defer n.mu.Unlock()
+ if len(n.deadProps) == 0 {
+ return nil, nil
+ }
+ ret := make(map[xml.Name]Property, len(n.deadProps))
+ for k, v := range n.deadProps {
+ ret[k] = v
+ }
+ return ret, nil
+}
+
+func (n *memFSNode) Patch(patches []Proppatch) ([]Propstat, error) {
+ n.mu.Lock()
+ defer n.mu.Unlock()
+ pstat := Propstat{Status: http.StatusOK}
+ for _, patch := range patches {
+ for _, p := range patch.Props {
+ pstat.Props = append(pstat.Props, Property{XMLName: p.XMLName})
+ if patch.Remove {
+ delete(n.deadProps, p.XMLName)
+ continue
+ }
+ if n.deadProps == nil {
+ n.deadProps = map[xml.Name]Property{}
+ }
+ n.deadProps[p.XMLName] = p
+ }
+ }
+ return []Propstat{pstat}, nil
+}
+
+type memFileInfo struct {
+ name string
+ size int64
+ mode os.FileMode
+ modTime time.Time
+}
+
+func (f *memFileInfo) Name() string { return f.name }
+func (f *memFileInfo) Size() int64 { return f.size }
+func (f *memFileInfo) Mode() os.FileMode { return f.mode }
+func (f *memFileInfo) ModTime() time.Time { return f.modTime }
+func (f *memFileInfo) IsDir() bool { return f.mode.IsDir() }
+func (f *memFileInfo) Sys() interface{} { return nil }
+
+// A memFile is a File implementation for a memFSNode. It is a per-file (not
+// per-node) read/write position, and a snapshot of the memFS' tree structure
+// (a node's name and children) for that node.
+type memFile struct {
+ n *memFSNode
+ nameSnapshot string
+ childrenSnapshot []os.FileInfo
+ // pos is protected by n.mu.
+ pos int
+}
+
+// A *memFile implements the optional DeadPropsHolder interface.
+var _ DeadPropsHolder = (*memFile)(nil)
+
+func (f *memFile) DeadProps() (map[xml.Name]Property, error) { return f.n.DeadProps() }
+func (f *memFile) Patch(patches []Proppatch) ([]Propstat, error) { return f.n.Patch(patches) }
+
+func (f *memFile) Close() error {
+ return nil
+}
+
+func (f *memFile) Read(p []byte) (int, error) {
+ f.n.mu.Lock()
+ defer f.n.mu.Unlock()
+ if f.n.mode.IsDir() {
+ return 0, os.ErrInvalid
+ }
+ if f.pos >= len(f.n.data) {
+ return 0, io.EOF
+ }
+ n := copy(p, f.n.data[f.pos:])
+ f.pos += n
+ return n, nil
+}
+
+func (f *memFile) Readdir(count int) ([]os.FileInfo, error) {
+ f.n.mu.Lock()
+ defer f.n.mu.Unlock()
+ if !f.n.mode.IsDir() {
+ return nil, os.ErrInvalid
+ }
+ old := f.pos
+ if old >= len(f.childrenSnapshot) {
+ // The os.File Readdir docs say that at the end of a directory,
+ // the error is io.EOF if count > 0 and nil if count <= 0.
+ if count > 0 {
+ return nil, io.EOF
+ }
+ return nil, nil
+ }
+ if count > 0 {
+ f.pos += count
+ if f.pos > len(f.childrenSnapshot) {
+ f.pos = len(f.childrenSnapshot)
+ }
+ } else {
+ f.pos = len(f.childrenSnapshot)
+ old = 0
+ }
+ return f.childrenSnapshot[old:f.pos], nil
+}
+
+func (f *memFile) Seek(offset int64, whence int) (int64, error) {
+ f.n.mu.Lock()
+ defer f.n.mu.Unlock()
+ npos := f.pos
+ // TODO: How to handle offsets greater than the size of system int?
+ switch whence {
+ case os.SEEK_SET:
+ npos = int(offset)
+ case os.SEEK_CUR:
+ npos += int(offset)
+ case os.SEEK_END:
+ npos = len(f.n.data) + int(offset)
+ default:
+ npos = -1
+ }
+ if npos < 0 {
+ return 0, os.ErrInvalid
+ }
+ f.pos = npos
+ return int64(f.pos), nil
+}
+
+func (f *memFile) Stat() (os.FileInfo, error) {
+ return f.n.stat(f.nameSnapshot), nil
+}
+
+func (f *memFile) Write(p []byte) (int, error) {
+ lenp := len(p)
+ f.n.mu.Lock()
+ defer f.n.mu.Unlock()
+
+ if f.n.mode.IsDir() {
+ return 0, os.ErrInvalid
+ }
+ if f.pos < len(f.n.data) {
+ n := copy(f.n.data[f.pos:], p)
+ f.pos += n
+ p = p[n:]
+ } else if f.pos > len(f.n.data) {
+ // Write permits the creation of holes, if we've seek'ed past the
+ // existing end of file.
+ if f.pos <= cap(f.n.data) {
+ oldLen := len(f.n.data)
+ f.n.data = f.n.data[:f.pos]
+ hole := f.n.data[oldLen:]
+ for i := range hole {
+ hole[i] = 0
+ }
+ } else {
+ d := make([]byte, f.pos, f.pos+len(p))
+ copy(d, f.n.data)
+ f.n.data = d
+ }
+ }
+
+ if len(p) > 0 {
+ // We should only get here if f.pos == len(f.n.data).
+ f.n.data = append(f.n.data, p...)
+ f.pos = len(f.n.data)
+ }
+ f.n.modTime = time.Now()
+ return lenp, nil
+}
+
+// moveFiles moves files and/or directories from src to dst.
+//
+// See section 9.9.4 for when various HTTP status codes apply.
+func moveFiles(ctx context.Context, fs FileSystem, src, dst string, overwrite bool) (status int, err error) {
+ created := false
+ if _, err := fs.Stat(ctx, dst); err != nil {
+ if !os.IsNotExist(err) {
+ return http.StatusForbidden, err
+ }
+ created = true
+ } else if overwrite {
+ // Section 9.9.3 says that "If a resource exists at the destination
+ // and the Overwrite header is "T", then prior to performing the move,
+ // the server must perform a DELETE with "Depth: infinity" on the
+ // destination resource.
+ if err := fs.RemoveAll(ctx, dst); err != nil {
+ return http.StatusForbidden, err
+ }
+ } else {
+ return http.StatusPreconditionFailed, os.ErrExist
+ }
+ if err := fs.Rename(ctx, src, dst); err != nil {
+ return http.StatusForbidden, err
+ }
+ if created {
+ return http.StatusCreated, nil
+ }
+ return http.StatusNoContent, nil
+}
+
+func copyProps(dst, src File) error {
+ d, ok := dst.(DeadPropsHolder)
+ if !ok {
+ return nil
+ }
+ s, ok := src.(DeadPropsHolder)
+ if !ok {
+ return nil
+ }
+ m, err := s.DeadProps()
+ if err != nil {
+ return err
+ }
+ props := make([]Property, 0, len(m))
+ for _, prop := range m {
+ props = append(props, prop)
+ }
+ _, err = d.Patch([]Proppatch{{Props: props}})
+ return err
+}
+
+// copyFiles copies files and/or directories from src to dst.
+//
+// See section 9.8.5 for when various HTTP status codes apply.
+func copyFiles(ctx context.Context, fs FileSystem, src, dst string, overwrite bool, depth int, recursion int) (status int, err error) {
+ if recursion == 1000 {
+ return http.StatusInternalServerError, errRecursionTooDeep
+ }
+ recursion++
+
+ // TODO: section 9.8.3 says that "Note that an infinite-depth COPY of /A/
+ // into /A/B/ could lead to infinite recursion if not handled correctly."
+
+ srcFile, err := fs.OpenFile(ctx, src, os.O_RDONLY, 0)
+ if err != nil {
+ if os.IsNotExist(err) {
+ return http.StatusNotFound, err
+ }
+ return http.StatusInternalServerError, err
+ }
+ defer srcFile.Close()
+ srcStat, err := srcFile.Stat()
+ if err != nil {
+ if os.IsNotExist(err) {
+ return http.StatusNotFound, err
+ }
+ return http.StatusInternalServerError, err
+ }
+ srcPerm := srcStat.Mode() & os.ModePerm
+
+ created := false
+ if _, err := fs.Stat(ctx, dst); err != nil {
+ if os.IsNotExist(err) {
+ created = true
+ } else {
+ return http.StatusForbidden, err
+ }
+ } else {
+ if !overwrite {
+ return http.StatusPreconditionFailed, os.ErrExist
+ }
+ if err := fs.RemoveAll(ctx, dst); err != nil && !os.IsNotExist(err) {
+ return http.StatusForbidden, err
+ }
+ }
+
+ if srcStat.IsDir() {
+ if err := fs.Mkdir(ctx, dst, srcPerm); err != nil {
+ return http.StatusForbidden, err
+ }
+ if depth == infiniteDepth {
+ children, err := srcFile.Readdir(-1)
+ if err != nil {
+ return http.StatusForbidden, err
+ }
+ for _, c := range children {
+ name := c.Name()
+ s := path.Join(src, name)
+ d := path.Join(dst, name)
+ cStatus, cErr := copyFiles(ctx, fs, s, d, overwrite, depth, recursion)
+ if cErr != nil {
+ // TODO: MultiStatus.
+ return cStatus, cErr
+ }
+ }
+ }
+
+ } else {
+ dstFile, err := fs.OpenFile(ctx, dst, os.O_RDWR|os.O_CREATE|os.O_TRUNC, srcPerm)
+ if err != nil {
+ if os.IsNotExist(err) {
+ return http.StatusConflict, err
+ }
+ return http.StatusForbidden, err
+
+ }
+ _, copyErr := io.Copy(dstFile, srcFile)
+ propsErr := copyProps(dstFile, srcFile)
+ closeErr := dstFile.Close()
+ if copyErr != nil {
+ return http.StatusInternalServerError, copyErr
+ }
+ if propsErr != nil {
+ return http.StatusInternalServerError, propsErr
+ }
+ if closeErr != nil {
+ return http.StatusInternalServerError, closeErr
+ }
+ }
+
+ if created {
+ return http.StatusCreated, nil
+ }
+ return http.StatusNoContent, nil
+}
+
+// walkFS traverses filesystem fs starting at name up to depth levels.
+//
+// Allowed values for depth are 0, 1 or infiniteDepth. For each visited node,
+// walkFS calls walkFn. If a visited file system node is a directory and
+// walkFn returns filepath.SkipDir, walkFS will skip traversal of this node.
+func walkFS(ctx context.Context, fs FileSystem, depth int, name string, info os.FileInfo, walkFn filepath.WalkFunc) error {
+ // This implementation is based on Walk's code in the standard path/filepath package.
+ err := walkFn(name, info, nil)
+ if err != nil {
+ if info.IsDir() && err == filepath.SkipDir {
+ return nil
+ }
+ return err
+ }
+ if !info.IsDir() || depth == 0 {
+ return nil
+ }
+ if depth == 1 {
+ depth = 0
+ }
+
+ // Read directory names.
+ f, err := fs.OpenFile(ctx, name, os.O_RDONLY, 0)
+ if err != nil {
+ return walkFn(name, info, err)
+ }
+ fileInfos, err := f.Readdir(0)
+ f.Close()
+ if err != nil {
+ return walkFn(name, info, err)
+ }
+
+ for _, fileInfo := range fileInfos {
+ filename := path.Join(name, fileInfo.Name())
+ fileInfo, err := fs.Stat(ctx, filename)
+ if err != nil {
+ if err := walkFn(filename, fileInfo, err); err != nil && err != filepath.SkipDir {
+ return err
+ }
+ } else {
+ err = walkFS(ctx, fs, depth, filename, fileInfo, walkFn)
+ if err != nil {
+ if !fileInfo.IsDir() || err != filepath.SkipDir {
+ return err
+ }
+ }
+ }
+ }
+ return nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/file_go1.6.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/file_go1.6.go
new file mode 100644
index 000000000..fa387700d
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/file_go1.6.go
@@ -0,0 +1,17 @@
+// 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.
+
+// +build !go1.7
+
+package webdav
+
+import (
+ "net/http"
+
+ "golang.org/x/net/context"
+)
+
+func getContext(r *http.Request) context.Context {
+ return context.Background()
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/file_go1.7.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/file_go1.7.go
new file mode 100644
index 000000000..d1c3de832
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/file_go1.7.go
@@ -0,0 +1,16 @@
+// 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.
+
+// +build go1.7
+
+package webdav
+
+import (
+ "context"
+ "net/http"
+)
+
+func getContext(r *http.Request) context.Context {
+ return r.Context()
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/file_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/file_test.go
new file mode 100644
index 000000000..bfd96e193
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/file_test.go
@@ -0,0 +1,1184 @@
+// Copyright 2014 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 webdav
+
+import (
+ "encoding/xml"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "os"
+ "path"
+ "path/filepath"
+ "reflect"
+ "runtime"
+ "sort"
+ "strconv"
+ "strings"
+ "testing"
+
+ "golang.org/x/net/context"
+)
+
+func TestSlashClean(t *testing.T) {
+ testCases := []string{
+ "",
+ ".",
+ "/",
+ "/./",
+ "//",
+ "//.",
+ "//a",
+ "/a",
+ "/a/b/c",
+ "/a//b/./../c/d/",
+ "a",
+ "a/b/c",
+ }
+ for _, tc := range testCases {
+ got := slashClean(tc)
+ want := path.Clean("/" + tc)
+ if got != want {
+ t.Errorf("tc=%q: got %q, want %q", tc, got, want)
+ }
+ }
+}
+
+func TestDirResolve(t *testing.T) {
+ testCases := []struct {
+ dir, name, want string
+ }{
+ {"/", "", "/"},
+ {"/", "/", "/"},
+ {"/", ".", "/"},
+ {"/", "./a", "/a"},
+ {"/", "..", "/"},
+ {"/", "..", "/"},
+ {"/", "../", "/"},
+ {"/", "../.", "/"},
+ {"/", "../a", "/a"},
+ {"/", "../..", "/"},
+ {"/", "../bar/a", "/bar/a"},
+ {"/", "../baz/a", "/baz/a"},
+ {"/", "...", "/..."},
+ {"/", ".../a", "/.../a"},
+ {"/", ".../..", "/"},
+ {"/", "a", "/a"},
+ {"/", "a/./b", "/a/b"},
+ {"/", "a/../../b", "/b"},
+ {"/", "a/../b", "/b"},
+ {"/", "a/b", "/a/b"},
+ {"/", "a/b/c/../../d", "/a/d"},
+ {"/", "a/b/c/../../../d", "/d"},
+ {"/", "a/b/c/../../../../d", "/d"},
+ {"/", "a/b/c/d", "/a/b/c/d"},
+
+ {"/foo/bar", "", "/foo/bar"},
+ {"/foo/bar", "/", "/foo/bar"},
+ {"/foo/bar", ".", "/foo/bar"},
+ {"/foo/bar", "./a", "/foo/bar/a"},
+ {"/foo/bar", "..", "/foo/bar"},
+ {"/foo/bar", "../", "/foo/bar"},
+ {"/foo/bar", "../.", "/foo/bar"},
+ {"/foo/bar", "../a", "/foo/bar/a"},
+ {"/foo/bar", "../..", "/foo/bar"},
+ {"/foo/bar", "../bar/a", "/foo/bar/bar/a"},
+ {"/foo/bar", "../baz/a", "/foo/bar/baz/a"},
+ {"/foo/bar", "...", "/foo/bar/..."},
+ {"/foo/bar", ".../a", "/foo/bar/.../a"},
+ {"/foo/bar", ".../..", "/foo/bar"},
+ {"/foo/bar", "a", "/foo/bar/a"},
+ {"/foo/bar", "a/./b", "/foo/bar/a/b"},
+ {"/foo/bar", "a/../../b", "/foo/bar/b"},
+ {"/foo/bar", "a/../b", "/foo/bar/b"},
+ {"/foo/bar", "a/b", "/foo/bar/a/b"},
+ {"/foo/bar", "a/b/c/../../d", "/foo/bar/a/d"},
+ {"/foo/bar", "a/b/c/../../../d", "/foo/bar/d"},
+ {"/foo/bar", "a/b/c/../../../../d", "/foo/bar/d"},
+ {"/foo/bar", "a/b/c/d", "/foo/bar/a/b/c/d"},
+
+ {"/foo/bar/", "", "/foo/bar"},
+ {"/foo/bar/", "/", "/foo/bar"},
+ {"/foo/bar/", ".", "/foo/bar"},
+ {"/foo/bar/", "./a", "/foo/bar/a"},
+ {"/foo/bar/", "..", "/foo/bar"},
+
+ {"/foo//bar///", "", "/foo/bar"},
+ {"/foo//bar///", "/", "/foo/bar"},
+ {"/foo//bar///", ".", "/foo/bar"},
+ {"/foo//bar///", "./a", "/foo/bar/a"},
+ {"/foo//bar///", "..", "/foo/bar"},
+
+ {"/x/y/z", "ab/c\x00d/ef", ""},
+
+ {".", "", "."},
+ {".", "/", "."},
+ {".", ".", "."},
+ {".", "./a", "a"},
+ {".", "..", "."},
+ {".", "..", "."},
+ {".", "../", "."},
+ {".", "../.", "."},
+ {".", "../a", "a"},
+ {".", "../..", "."},
+ {".", "../bar/a", "bar/a"},
+ {".", "../baz/a", "baz/a"},
+ {".", "...", "..."},
+ {".", ".../a", ".../a"},
+ {".", ".../..", "."},
+ {".", "a", "a"},
+ {".", "a/./b", "a/b"},
+ {".", "a/../../b", "b"},
+ {".", "a/../b", "b"},
+ {".", "a/b", "a/b"},
+ {".", "a/b/c/../../d", "a/d"},
+ {".", "a/b/c/../../../d", "d"},
+ {".", "a/b/c/../../../../d", "d"},
+ {".", "a/b/c/d", "a/b/c/d"},
+
+ {"", "", "."},
+ {"", "/", "."},
+ {"", ".", "."},
+ {"", "./a", "a"},
+ {"", "..", "."},
+ }
+
+ for _, tc := range testCases {
+ d := Dir(filepath.FromSlash(tc.dir))
+ if got := filepath.ToSlash(d.resolve(tc.name)); got != tc.want {
+ t.Errorf("dir=%q, name=%q: got %q, want %q", tc.dir, tc.name, got, tc.want)
+ }
+ }
+}
+
+func TestWalk(t *testing.T) {
+ type walkStep struct {
+ name, frag string
+ final bool
+ }
+
+ testCases := []struct {
+ dir string
+ want []walkStep
+ }{
+ {"", []walkStep{
+ {"", "", true},
+ }},
+ {"/", []walkStep{
+ {"", "", true},
+ }},
+ {"/a", []walkStep{
+ {"", "a", true},
+ }},
+ {"/a/", []walkStep{
+ {"", "a", true},
+ }},
+ {"/a/b", []walkStep{
+ {"", "a", false},
+ {"a", "b", true},
+ }},
+ {"/a/b/", []walkStep{
+ {"", "a", false},
+ {"a", "b", true},
+ }},
+ {"/a/b/c", []walkStep{
+ {"", "a", false},
+ {"a", "b", false},
+ {"b", "c", true},
+ }},
+ // The following test case is the one mentioned explicitly
+ // in the method description.
+ {"/foo/bar/x", []walkStep{
+ {"", "foo", false},
+ {"foo", "bar", false},
+ {"bar", "x", true},
+ }},
+ }
+
+ ctx := context.Background()
+
+ for _, tc := range testCases {
+ fs := NewMemFS().(*memFS)
+
+ parts := strings.Split(tc.dir, "/")
+ for p := 2; p < len(parts); p++ {
+ d := strings.Join(parts[:p], "/")
+ if err := fs.Mkdir(ctx, d, 0666); err != nil {
+ t.Errorf("tc.dir=%q: mkdir: %q: %v", tc.dir, d, err)
+ }
+ }
+
+ i, prevFrag := 0, ""
+ err := fs.walk("test", tc.dir, func(dir *memFSNode, frag string, final bool) error {
+ got := walkStep{
+ name: prevFrag,
+ frag: frag,
+ final: final,
+ }
+ want := tc.want[i]
+
+ if got != want {
+ return fmt.Errorf("got %+v, want %+v", got, want)
+ }
+ i, prevFrag = i+1, frag
+ return nil
+ })
+ if err != nil {
+ t.Errorf("tc.dir=%q: %v", tc.dir, err)
+ }
+ }
+}
+
+// find appends to ss the names of the named file and its children. It is
+// analogous to the Unix find command.
+//
+// The returned strings are not guaranteed to be in any particular order.
+func find(ctx context.Context, ss []string, fs FileSystem, name string) ([]string, error) {
+ stat, err := fs.Stat(ctx, name)
+ if err != nil {
+ return nil, err
+ }
+ ss = append(ss, name)
+ if stat.IsDir() {
+ f, err := fs.OpenFile(ctx, name, os.O_RDONLY, 0)
+ if err != nil {
+ return nil, err
+ }
+ defer f.Close()
+ children, err := f.Readdir(-1)
+ if err != nil {
+ return nil, err
+ }
+ for _, c := range children {
+ ss, err = find(ctx, ss, fs, path.Join(name, c.Name()))
+ if err != nil {
+ return nil, err
+ }
+ }
+ }
+ return ss, nil
+}
+
+func testFS(t *testing.T, fs FileSystem) {
+ errStr := func(err error) string {
+ switch {
+ case os.IsExist(err):
+ return "errExist"
+ case os.IsNotExist(err):
+ return "errNotExist"
+ case err != nil:
+ return "err"
+ }
+ return "ok"
+ }
+
+ // The non-"find" non-"stat" test cases should change the file system state. The
+ // indentation of the "find"s and "stat"s helps distinguish such test cases.
+ testCases := []string{
+ " stat / want dir",
+ " stat /a want errNotExist",
+ " stat /d want errNotExist",
+ " stat /d/e want errNotExist",
+ "create /a A want ok",
+ " stat /a want 1",
+ "create /d/e EEE want errNotExist",
+ "mk-dir /a want errExist",
+ "mk-dir /d/m want errNotExist",
+ "mk-dir /d want ok",
+ " stat /d want dir",
+ "create /d/e EEE want ok",
+ " stat /d/e want 3",
+ " find / /a /d /d/e",
+ "create /d/f FFFF want ok",
+ "create /d/g GGGGGGG want ok",
+ "mk-dir /d/m want ok",
+ "mk-dir /d/m want errExist",
+ "create /d/m/p PPPPP want ok",
+ " stat /d/e want 3",
+ " stat /d/f want 4",
+ " stat /d/g want 7",
+ " stat /d/h want errNotExist",
+ " stat /d/m want dir",
+ " stat /d/m/p want 5",
+ " find / /a /d /d/e /d/f /d/g /d/m /d/m/p",
+ "rm-all /d want ok",
+ " stat /a want 1",
+ " stat /d want errNotExist",
+ " stat /d/e want errNotExist",
+ " stat /d/f want errNotExist",
+ " stat /d/g want errNotExist",
+ " stat /d/m want errNotExist",
+ " stat /d/m/p want errNotExist",
+ " find / /a",
+ "mk-dir /d/m want errNotExist",
+ "mk-dir /d want ok",
+ "create /d/f FFFF want ok",
+ "rm-all /d/f want ok",
+ "mk-dir /d/m want ok",
+ "rm-all /z want ok",
+ "rm-all / want err",
+ "create /b BB want ok",
+ " stat / want dir",
+ " stat /a want 1",
+ " stat /b want 2",
+ " stat /c want errNotExist",
+ " stat /d want dir",
+ " stat /d/m want dir",
+ " find / /a /b /d /d/m",
+ "move__ o=F /b /c want ok",
+ " stat /b want errNotExist",
+ " stat /c want 2",
+ " stat /d/m want dir",
+ " stat /d/n want errNotExist",
+ " find / /a /c /d /d/m",
+ "move__ o=F /d/m /d/n want ok",
+ "create /d/n/q QQQQ want ok",
+ " stat /d/m want errNotExist",
+ " stat /d/n want dir",
+ " stat /d/n/q want 4",
+ "move__ o=F /d /d/n/z want err",
+ "move__ o=T /c /d/n/q want ok",
+ " stat /c want errNotExist",
+ " stat /d/n/q want 2",
+ " find / /a /d /d/n /d/n/q",
+ "create /d/n/r RRRRR want ok",
+ "mk-dir /u want ok",
+ "mk-dir /u/v want ok",
+ "move__ o=F /d/n /u want errExist",
+ "create /t TTTTTT want ok",
+ "move__ o=F /d/n /t want errExist",
+ "rm-all /t want ok",
+ "move__ o=F /d/n /t want ok",
+ " stat /d want dir",
+ " stat /d/n want errNotExist",
+ " stat /d/n/r want errNotExist",
+ " stat /t want dir",
+ " stat /t/q want 2",
+ " stat /t/r want 5",
+ " find / /a /d /t /t/q /t/r /u /u/v",
+ "move__ o=F /t / want errExist",
+ "move__ o=T /t /u/v want ok",
+ " stat /u/v/r want 5",
+ "move__ o=F / /z want err",
+ " find / /a /d /u /u/v /u/v/q /u/v/r",
+ " stat /a want 1",
+ " stat /b want errNotExist",
+ " stat /c want errNotExist",
+ " stat /u/v/r want 5",
+ "copy__ o=F d=0 /a /b want ok",
+ "copy__ o=T d=0 /a /c want ok",
+ " stat /a want 1",
+ " stat /b want 1",
+ " stat /c want 1",
+ " stat /u/v/r want 5",
+ "copy__ o=F d=0 /u/v/r /b want errExist",
+ " stat /b want 1",
+ "copy__ o=T d=0 /u/v/r /b want ok",
+ " stat /a want 1",
+ " stat /b want 5",
+ " stat /u/v/r want 5",
+ "rm-all /a want ok",
+ "rm-all /b want ok",
+ "mk-dir /u/v/w want ok",
+ "create /u/v/w/s SSSSSSSS want ok",
+ " stat /d want dir",
+ " stat /d/x want errNotExist",
+ " stat /d/y want errNotExist",
+ " stat /u/v/r want 5",
+ " stat /u/v/w/s want 8",
+ " find / /c /d /u /u/v /u/v/q /u/v/r /u/v/w /u/v/w/s",
+ "copy__ o=T d=0 /u/v /d/x want ok",
+ "copy__ o=T d=∞ /u/v /d/y want ok",
+ "rm-all /u want ok",
+ " stat /d/x want dir",
+ " stat /d/x/q want errNotExist",
+ " stat /d/x/r want errNotExist",
+ " stat /d/x/w want errNotExist",
+ " stat /d/x/w/s want errNotExist",
+ " stat /d/y want dir",
+ " stat /d/y/q want 2",
+ " stat /d/y/r want 5",
+ " stat /d/y/w want dir",
+ " stat /d/y/w/s want 8",
+ " stat /u want errNotExist",
+ " find / /c /d /d/x /d/y /d/y/q /d/y/r /d/y/w /d/y/w/s",
+ "copy__ o=F d=∞ /d/y /d/x want errExist",
+ }
+
+ ctx := context.Background()
+
+ for i, tc := range testCases {
+ tc = strings.TrimSpace(tc)
+ j := strings.IndexByte(tc, ' ')
+ if j < 0 {
+ t.Fatalf("test case #%d %q: invalid command", i, tc)
+ }
+ op, arg := tc[:j], tc[j+1:]
+
+ switch op {
+ default:
+ t.Fatalf("test case #%d %q: invalid operation %q", i, tc, op)
+
+ case "create":
+ parts := strings.Split(arg, " ")
+ if len(parts) != 4 || parts[2] != "want" {
+ t.Fatalf("test case #%d %q: invalid write", i, tc)
+ }
+ f, opErr := fs.OpenFile(ctx, parts[0], os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666)
+ if got := errStr(opErr); got != parts[3] {
+ t.Fatalf("test case #%d %q: OpenFile: got %q (%v), want %q", i, tc, got, opErr, parts[3])
+ }
+ if f != nil {
+ if _, err := f.Write([]byte(parts[1])); err != nil {
+ t.Fatalf("test case #%d %q: Write: %v", i, tc, err)
+ }
+ if err := f.Close(); err != nil {
+ t.Fatalf("test case #%d %q: Close: %v", i, tc, err)
+ }
+ }
+
+ case "find":
+ got, err := find(ctx, nil, fs, "/")
+ if err != nil {
+ t.Fatalf("test case #%d %q: find: %v", i, tc, err)
+ }
+ sort.Strings(got)
+ want := strings.Split(arg, " ")
+ if !reflect.DeepEqual(got, want) {
+ t.Fatalf("test case #%d %q:\ngot %s\nwant %s", i, tc, got, want)
+ }
+
+ case "copy__", "mk-dir", "move__", "rm-all", "stat":
+ nParts := 3
+ switch op {
+ case "copy__":
+ nParts = 6
+ case "move__":
+ nParts = 5
+ }
+ parts := strings.Split(arg, " ")
+ if len(parts) != nParts {
+ t.Fatalf("test case #%d %q: invalid %s", i, tc, op)
+ }
+
+ got, opErr := "", error(nil)
+ switch op {
+ case "copy__":
+ depth := 0
+ if parts[1] == "d=∞" {
+ depth = infiniteDepth
+ }
+ _, opErr = copyFiles(ctx, fs, parts[2], parts[3], parts[0] == "o=T", depth, 0)
+ case "mk-dir":
+ opErr = fs.Mkdir(ctx, parts[0], 0777)
+ case "move__":
+ _, opErr = moveFiles(ctx, fs, parts[1], parts[2], parts[0] == "o=T")
+ case "rm-all":
+ opErr = fs.RemoveAll(ctx, parts[0])
+ case "stat":
+ var stat os.FileInfo
+ fileName := parts[0]
+ if stat, opErr = fs.Stat(ctx, fileName); opErr == nil {
+ if stat.IsDir() {
+ got = "dir"
+ } else {
+ got = strconv.Itoa(int(stat.Size()))
+ }
+
+ if fileName == "/" {
+ // For a Dir FileSystem, the virtual file system root maps to a
+ // real file system name like "/tmp/webdav-test012345", which does
+ // not end with "/". We skip such cases.
+ } else if statName := stat.Name(); path.Base(fileName) != statName {
+ t.Fatalf("test case #%d %q: file name %q inconsistent with stat name %q",
+ i, tc, fileName, statName)
+ }
+ }
+ }
+ if got == "" {
+ got = errStr(opErr)
+ }
+
+ if parts[len(parts)-2] != "want" {
+ t.Fatalf("test case #%d %q: invalid %s", i, tc, op)
+ }
+ if want := parts[len(parts)-1]; got != want {
+ t.Fatalf("test case #%d %q: got %q (%v), want %q", i, tc, got, opErr, want)
+ }
+ }
+ }
+}
+
+func TestDir(t *testing.T) {
+ switch runtime.GOOS {
+ case "nacl":
+ t.Skip("see golang.org/issue/12004")
+ case "plan9":
+ t.Skip("see golang.org/issue/11453")
+ }
+
+ td, err := ioutil.TempDir("", "webdav-test")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.RemoveAll(td)
+ testFS(t, Dir(td))
+}
+
+func TestMemFS(t *testing.T) {
+ testFS(t, NewMemFS())
+}
+
+func TestMemFSRoot(t *testing.T) {
+ ctx := context.Background()
+ fs := NewMemFS()
+ for i := 0; i < 5; i++ {
+ stat, err := fs.Stat(ctx, "/")
+ if err != nil {
+ t.Fatalf("i=%d: Stat: %v", i, err)
+ }
+ if !stat.IsDir() {
+ t.Fatalf("i=%d: Stat.IsDir is false, want true", i)
+ }
+
+ f, err := fs.OpenFile(ctx, "/", os.O_RDONLY, 0)
+ if err != nil {
+ t.Fatalf("i=%d: OpenFile: %v", i, err)
+ }
+ defer f.Close()
+ children, err := f.Readdir(-1)
+ if err != nil {
+ t.Fatalf("i=%d: Readdir: %v", i, err)
+ }
+ if len(children) != i {
+ t.Fatalf("i=%d: got %d children, want %d", i, len(children), i)
+ }
+
+ if _, err := f.Write(make([]byte, 1)); err == nil {
+ t.Fatalf("i=%d: Write: got nil error, want non-nil", i)
+ }
+
+ if err := fs.Mkdir(ctx, fmt.Sprintf("/dir%d", i), 0777); err != nil {
+ t.Fatalf("i=%d: Mkdir: %v", i, err)
+ }
+ }
+}
+
+func TestMemFileReaddir(t *testing.T) {
+ ctx := context.Background()
+ fs := NewMemFS()
+ if err := fs.Mkdir(ctx, "/foo", 0777); err != nil {
+ t.Fatalf("Mkdir: %v", err)
+ }
+ readdir := func(count int) ([]os.FileInfo, error) {
+ f, err := fs.OpenFile(ctx, "/foo", os.O_RDONLY, 0)
+ if err != nil {
+ t.Fatalf("OpenFile: %v", err)
+ }
+ defer f.Close()
+ return f.Readdir(count)
+ }
+ if got, err := readdir(-1); len(got) != 0 || err != nil {
+ t.Fatalf("readdir(-1): got %d fileInfos with err=%v, want 0, <nil>", len(got), err)
+ }
+ if got, err := readdir(+1); len(got) != 0 || err != io.EOF {
+ t.Fatalf("readdir(+1): got %d fileInfos with err=%v, want 0, EOF", len(got), err)
+ }
+}
+
+func TestMemFile(t *testing.T) {
+ testCases := []string{
+ "wantData ",
+ "wantSize 0",
+ "write abc",
+ "wantData abc",
+ "write de",
+ "wantData abcde",
+ "wantSize 5",
+ "write 5*x",
+ "write 4*y+2*z",
+ "write 3*st",
+ "wantData abcdexxxxxyyyyzzststst",
+ "wantSize 22",
+ "seek set 4 want 4",
+ "write EFG",
+ "wantData abcdEFGxxxyyyyzzststst",
+ "wantSize 22",
+ "seek set 2 want 2",
+ "read cdEF",
+ "read Gx",
+ "seek cur 0 want 8",
+ "seek cur 2 want 10",
+ "seek cur -1 want 9",
+ "write J",
+ "wantData abcdEFGxxJyyyyzzststst",
+ "wantSize 22",
+ "seek cur -4 want 6",
+ "write ghijk",
+ "wantData abcdEFghijkyyyzzststst",
+ "wantSize 22",
+ "read yyyz",
+ "seek cur 0 want 15",
+ "write ",
+ "seek cur 0 want 15",
+ "read ",
+ "seek cur 0 want 15",
+ "seek end -3 want 19",
+ "write ZZ",
+ "wantData abcdEFghijkyyyzzstsZZt",
+ "wantSize 22",
+ "write 4*A",
+ "wantData abcdEFghijkyyyzzstsZZAAAA",
+ "wantSize 25",
+ "seek end 0 want 25",
+ "seek end -5 want 20",
+ "read Z+4*A",
+ "write 5*B",
+ "wantData abcdEFghijkyyyzzstsZZAAAABBBBB",
+ "wantSize 30",
+ "seek end 10 want 40",
+ "write C",
+ "wantData abcdEFghijkyyyzzstsZZAAAABBBBB..........C",
+ "wantSize 41",
+ "write D",
+ "wantData abcdEFghijkyyyzzstsZZAAAABBBBB..........CD",
+ "wantSize 42",
+ "seek set 43 want 43",
+ "write E",
+ "wantData abcdEFghijkyyyzzstsZZAAAABBBBB..........CD.E",
+ "wantSize 44",
+ "seek set 0 want 0",
+ "write 5*123456789_",
+ "wantData 123456789_123456789_123456789_123456789_123456789_",
+ "wantSize 50",
+ "seek cur 0 want 50",
+ "seek cur -99 want err",
+ }
+
+ ctx := context.Background()
+
+ const filename = "/foo"
+ fs := NewMemFS()
+ f, err := fs.OpenFile(ctx, filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666)
+ if err != nil {
+ t.Fatalf("OpenFile: %v", err)
+ }
+ defer f.Close()
+
+ for i, tc := range testCases {
+ j := strings.IndexByte(tc, ' ')
+ if j < 0 {
+ t.Fatalf("test case #%d %q: invalid command", i, tc)
+ }
+ op, arg := tc[:j], tc[j+1:]
+
+ // Expand an arg like "3*a+2*b" to "aaabb".
+ parts := strings.Split(arg, "+")
+ for j, part := range parts {
+ if k := strings.IndexByte(part, '*'); k >= 0 {
+ repeatCount, repeatStr := part[:k], part[k+1:]
+ n, err := strconv.Atoi(repeatCount)
+ if err != nil {
+ t.Fatalf("test case #%d %q: invalid repeat count %q", i, tc, repeatCount)
+ }
+ parts[j] = strings.Repeat(repeatStr, n)
+ }
+ }
+ arg = strings.Join(parts, "")
+
+ switch op {
+ default:
+ t.Fatalf("test case #%d %q: invalid operation %q", i, tc, op)
+
+ case "read":
+ buf := make([]byte, len(arg))
+ if _, err := io.ReadFull(f, buf); err != nil {
+ t.Fatalf("test case #%d %q: ReadFull: %v", i, tc, err)
+ }
+ if got := string(buf); got != arg {
+ t.Fatalf("test case #%d %q:\ngot %q\nwant %q", i, tc, got, arg)
+ }
+
+ case "seek":
+ parts := strings.Split(arg, " ")
+ if len(parts) != 4 {
+ t.Fatalf("test case #%d %q: invalid seek", i, tc)
+ }
+
+ whence := 0
+ switch parts[0] {
+ default:
+ t.Fatalf("test case #%d %q: invalid seek whence", i, tc)
+ case "set":
+ whence = os.SEEK_SET
+ case "cur":
+ whence = os.SEEK_CUR
+ case "end":
+ whence = os.SEEK_END
+ }
+ offset, err := strconv.Atoi(parts[1])
+ if err != nil {
+ t.Fatalf("test case #%d %q: invalid offset %q", i, tc, parts[1])
+ }
+
+ if parts[2] != "want" {
+ t.Fatalf("test case #%d %q: invalid seek", i, tc)
+ }
+ if parts[3] == "err" {
+ _, err := f.Seek(int64(offset), whence)
+ if err == nil {
+ t.Fatalf("test case #%d %q: Seek returned nil error, want non-nil", i, tc)
+ }
+ } else {
+ got, err := f.Seek(int64(offset), whence)
+ if err != nil {
+ t.Fatalf("test case #%d %q: Seek: %v", i, tc, err)
+ }
+ want, err := strconv.Atoi(parts[3])
+ if err != nil {
+ t.Fatalf("test case #%d %q: invalid want %q", i, tc, parts[3])
+ }
+ if got != int64(want) {
+ t.Fatalf("test case #%d %q: got %d, want %d", i, tc, got, want)
+ }
+ }
+
+ case "write":
+ n, err := f.Write([]byte(arg))
+ if err != nil {
+ t.Fatalf("test case #%d %q: write: %v", i, tc, err)
+ }
+ if n != len(arg) {
+ t.Fatalf("test case #%d %q: write returned %d bytes, want %d", i, tc, n, len(arg))
+ }
+
+ case "wantData":
+ g, err := fs.OpenFile(ctx, filename, os.O_RDONLY, 0666)
+ if err != nil {
+ t.Fatalf("test case #%d %q: OpenFile: %v", i, tc, err)
+ }
+ gotBytes, err := ioutil.ReadAll(g)
+ if err != nil {
+ t.Fatalf("test case #%d %q: ReadAll: %v", i, tc, err)
+ }
+ for i, c := range gotBytes {
+ if c == '\x00' {
+ gotBytes[i] = '.'
+ }
+ }
+ got := string(gotBytes)
+ if got != arg {
+ t.Fatalf("test case #%d %q:\ngot %q\nwant %q", i, tc, got, arg)
+ }
+ if err := g.Close(); err != nil {
+ t.Fatalf("test case #%d %q: Close: %v", i, tc, err)
+ }
+
+ case "wantSize":
+ n, err := strconv.Atoi(arg)
+ if err != nil {
+ t.Fatalf("test case #%d %q: invalid size %q", i, tc, arg)
+ }
+ fi, err := fs.Stat(ctx, filename)
+ if err != nil {
+ t.Fatalf("test case #%d %q: Stat: %v", i, tc, err)
+ }
+ if got, want := fi.Size(), int64(n); got != want {
+ t.Fatalf("test case #%d %q: got %d, want %d", i, tc, got, want)
+ }
+ }
+ }
+}
+
+// TestMemFileWriteAllocs tests that writing N consecutive 1KiB chunks to a
+// memFile doesn't allocate a new buffer for each of those N times. Otherwise,
+// calling io.Copy(aMemFile, src) is likely to have quadratic complexity.
+func TestMemFileWriteAllocs(t *testing.T) {
+ if runtime.Compiler == "gccgo" {
+ t.Skip("gccgo allocates here")
+ }
+ ctx := context.Background()
+ fs := NewMemFS()
+ f, err := fs.OpenFile(ctx, "/xxx", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666)
+ if err != nil {
+ t.Fatalf("OpenFile: %v", err)
+ }
+ defer f.Close()
+
+ xxx := make([]byte, 1024)
+ for i := range xxx {
+ xxx[i] = 'x'
+ }
+
+ a := testing.AllocsPerRun(100, func() {
+ f.Write(xxx)
+ })
+ // AllocsPerRun returns an integral value, so we compare the rounded-down
+ // number to zero.
+ if a > 0 {
+ t.Fatalf("%v allocs per run, want 0", a)
+ }
+}
+
+func BenchmarkMemFileWrite(b *testing.B) {
+ ctx := context.Background()
+ fs := NewMemFS()
+ xxx := make([]byte, 1024)
+ for i := range xxx {
+ xxx[i] = 'x'
+ }
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ f, err := fs.OpenFile(ctx, "/xxx", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666)
+ if err != nil {
+ b.Fatalf("OpenFile: %v", err)
+ }
+ for j := 0; j < 100; j++ {
+ f.Write(xxx)
+ }
+ if err := f.Close(); err != nil {
+ b.Fatalf("Close: %v", err)
+ }
+ if err := fs.RemoveAll(ctx, "/xxx"); err != nil {
+ b.Fatalf("RemoveAll: %v", err)
+ }
+ }
+}
+
+func TestCopyMoveProps(t *testing.T) {
+ ctx := context.Background()
+ fs := NewMemFS()
+ create := func(name string) error {
+ f, err := fs.OpenFile(ctx, name, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666)
+ if err != nil {
+ return err
+ }
+ _, wErr := f.Write([]byte("contents"))
+ cErr := f.Close()
+ if wErr != nil {
+ return wErr
+ }
+ return cErr
+ }
+ patch := func(name string, patches ...Proppatch) error {
+ f, err := fs.OpenFile(ctx, name, os.O_RDWR, 0666)
+ if err != nil {
+ return err
+ }
+ _, pErr := f.(DeadPropsHolder).Patch(patches)
+ cErr := f.Close()
+ if pErr != nil {
+ return pErr
+ }
+ return cErr
+ }
+ props := func(name string) (map[xml.Name]Property, error) {
+ f, err := fs.OpenFile(ctx, name, os.O_RDWR, 0666)
+ if err != nil {
+ return nil, err
+ }
+ m, pErr := f.(DeadPropsHolder).DeadProps()
+ cErr := f.Close()
+ if pErr != nil {
+ return nil, pErr
+ }
+ if cErr != nil {
+ return nil, cErr
+ }
+ return m, nil
+ }
+
+ p0 := Property{
+ XMLName: xml.Name{Space: "x:", Local: "boat"},
+ InnerXML: []byte("pea-green"),
+ }
+ p1 := Property{
+ XMLName: xml.Name{Space: "x:", Local: "ring"},
+ InnerXML: []byte("1 shilling"),
+ }
+ p2 := Property{
+ XMLName: xml.Name{Space: "x:", Local: "spoon"},
+ InnerXML: []byte("runcible"),
+ }
+ p3 := Property{
+ XMLName: xml.Name{Space: "x:", Local: "moon"},
+ InnerXML: []byte("light"),
+ }
+
+ if err := create("/src"); err != nil {
+ t.Fatalf("create /src: %v", err)
+ }
+ if err := patch("/src", Proppatch{Props: []Property{p0, p1}}); err != nil {
+ t.Fatalf("patch /src +p0 +p1: %v", err)
+ }
+ if _, err := copyFiles(ctx, fs, "/src", "/tmp", true, infiniteDepth, 0); err != nil {
+ t.Fatalf("copyFiles /src /tmp: %v", err)
+ }
+ if _, err := moveFiles(ctx, fs, "/tmp", "/dst", true); err != nil {
+ t.Fatalf("moveFiles /tmp /dst: %v", err)
+ }
+ if err := patch("/src", Proppatch{Props: []Property{p0}, Remove: true}); err != nil {
+ t.Fatalf("patch /src -p0: %v", err)
+ }
+ if err := patch("/src", Proppatch{Props: []Property{p2}}); err != nil {
+ t.Fatalf("patch /src +p2: %v", err)
+ }
+ if err := patch("/dst", Proppatch{Props: []Property{p1}, Remove: true}); err != nil {
+ t.Fatalf("patch /dst -p1: %v", err)
+ }
+ if err := patch("/dst", Proppatch{Props: []Property{p3}}); err != nil {
+ t.Fatalf("patch /dst +p3: %v", err)
+ }
+
+ gotSrc, err := props("/src")
+ if err != nil {
+ t.Fatalf("props /src: %v", err)
+ }
+ wantSrc := map[xml.Name]Property{
+ p1.XMLName: p1,
+ p2.XMLName: p2,
+ }
+ if !reflect.DeepEqual(gotSrc, wantSrc) {
+ t.Fatalf("props /src:\ngot %v\nwant %v", gotSrc, wantSrc)
+ }
+
+ gotDst, err := props("/dst")
+ if err != nil {
+ t.Fatalf("props /dst: %v", err)
+ }
+ wantDst := map[xml.Name]Property{
+ p0.XMLName: p0,
+ p3.XMLName: p3,
+ }
+ if !reflect.DeepEqual(gotDst, wantDst) {
+ t.Fatalf("props /dst:\ngot %v\nwant %v", gotDst, wantDst)
+ }
+}
+
+func TestWalkFS(t *testing.T) {
+ testCases := []struct {
+ desc string
+ buildfs []string
+ startAt string
+ depth int
+ walkFn filepath.WalkFunc
+ want []string
+ }{{
+ "just root",
+ []string{},
+ "/",
+ infiniteDepth,
+ nil,
+ []string{
+ "/",
+ },
+ }, {
+ "infinite walk from root",
+ []string{
+ "mkdir /a",
+ "mkdir /a/b",
+ "touch /a/b/c",
+ "mkdir /a/d",
+ "mkdir /e",
+ "touch /f",
+ },
+ "/",
+ infiniteDepth,
+ nil,
+ []string{
+ "/",
+ "/a",
+ "/a/b",
+ "/a/b/c",
+ "/a/d",
+ "/e",
+ "/f",
+ },
+ }, {
+ "infinite walk from subdir",
+ []string{
+ "mkdir /a",
+ "mkdir /a/b",
+ "touch /a/b/c",
+ "mkdir /a/d",
+ "mkdir /e",
+ "touch /f",
+ },
+ "/a",
+ infiniteDepth,
+ nil,
+ []string{
+ "/a",
+ "/a/b",
+ "/a/b/c",
+ "/a/d",
+ },
+ }, {
+ "depth 1 walk from root",
+ []string{
+ "mkdir /a",
+ "mkdir /a/b",
+ "touch /a/b/c",
+ "mkdir /a/d",
+ "mkdir /e",
+ "touch /f",
+ },
+ "/",
+ 1,
+ nil,
+ []string{
+ "/",
+ "/a",
+ "/e",
+ "/f",
+ },
+ }, {
+ "depth 1 walk from subdir",
+ []string{
+ "mkdir /a",
+ "mkdir /a/b",
+ "touch /a/b/c",
+ "mkdir /a/b/g",
+ "mkdir /a/b/g/h",
+ "touch /a/b/g/i",
+ "touch /a/b/g/h/j",
+ },
+ "/a/b",
+ 1,
+ nil,
+ []string{
+ "/a/b",
+ "/a/b/c",
+ "/a/b/g",
+ },
+ }, {
+ "depth 0 walk from subdir",
+ []string{
+ "mkdir /a",
+ "mkdir /a/b",
+ "touch /a/b/c",
+ "mkdir /a/b/g",
+ "mkdir /a/b/g/h",
+ "touch /a/b/g/i",
+ "touch /a/b/g/h/j",
+ },
+ "/a/b",
+ 0,
+ nil,
+ []string{
+ "/a/b",
+ },
+ }, {
+ "infinite walk from file",
+ []string{
+ "mkdir /a",
+ "touch /a/b",
+ "touch /a/c",
+ },
+ "/a/b",
+ 0,
+ nil,
+ []string{
+ "/a/b",
+ },
+ }, {
+ "infinite walk with skipped subdir",
+ []string{
+ "mkdir /a",
+ "mkdir /a/b",
+ "touch /a/b/c",
+ "mkdir /a/b/g",
+ "mkdir /a/b/g/h",
+ "touch /a/b/g/i",
+ "touch /a/b/g/h/j",
+ "touch /a/b/z",
+ },
+ "/",
+ infiniteDepth,
+ func(path string, info os.FileInfo, err error) error {
+ if path == "/a/b/g" {
+ return filepath.SkipDir
+ }
+ return nil
+ },
+ []string{
+ "/",
+ "/a",
+ "/a/b",
+ "/a/b/c",
+ "/a/b/z",
+ },
+ }}
+ ctx := context.Background()
+ for _, tc := range testCases {
+ fs, err := buildTestFS(tc.buildfs)
+ if err != nil {
+ t.Fatalf("%s: cannot create test filesystem: %v", tc.desc, err)
+ }
+ var got []string
+ traceFn := func(path string, info os.FileInfo, err error) error {
+ if tc.walkFn != nil {
+ err = tc.walkFn(path, info, err)
+ if err != nil {
+ return err
+ }
+ }
+ got = append(got, path)
+ return nil
+ }
+ fi, err := fs.Stat(ctx, tc.startAt)
+ if err != nil {
+ t.Fatalf("%s: cannot stat: %v", tc.desc, err)
+ }
+ err = walkFS(ctx, fs, tc.depth, tc.startAt, fi, traceFn)
+ if err != nil {
+ t.Errorf("%s:\ngot error %v, want nil", tc.desc, err)
+ continue
+ }
+ sort.Strings(got)
+ sort.Strings(tc.want)
+ if !reflect.DeepEqual(got, tc.want) {
+ t.Errorf("%s:\ngot %q\nwant %q", tc.desc, got, tc.want)
+ continue
+ }
+ }
+}
+
+func buildTestFS(buildfs []string) (FileSystem, error) {
+ // TODO: Could this be merged with the build logic in TestFS?
+
+ ctx := context.Background()
+ fs := NewMemFS()
+ for _, b := range buildfs {
+ op := strings.Split(b, " ")
+ switch op[0] {
+ case "mkdir":
+ err := fs.Mkdir(ctx, op[1], os.ModeDir|0777)
+ if err != nil {
+ return nil, err
+ }
+ case "touch":
+ f, err := fs.OpenFile(ctx, op[1], os.O_RDWR|os.O_CREATE, 0666)
+ if err != nil {
+ return nil, err
+ }
+ f.Close()
+ case "write":
+ f, err := fs.OpenFile(ctx, op[1], os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666)
+ if err != nil {
+ return nil, err
+ }
+ _, err = f.Write([]byte(op[2]))
+ f.Close()
+ if err != nil {
+ return nil, err
+ }
+ default:
+ return nil, fmt.Errorf("unknown file operation %q", op[0])
+ }
+ }
+ return fs, nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/if.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/if.go
new file mode 100644
index 000000000..416e81cdf
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/if.go
@@ -0,0 +1,173 @@
+// Copyright 2014 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 webdav
+
+// The If header is covered by Section 10.4.
+// http://www.webdav.org/specs/rfc4918.html#HEADER_If
+
+import (
+ "strings"
+)
+
+// ifHeader is a disjunction (OR) of ifLists.
+type ifHeader struct {
+ lists []ifList
+}
+
+// ifList is a conjunction (AND) of Conditions, and an optional resource tag.
+type ifList struct {
+ resourceTag string
+ conditions []Condition
+}
+
+// parseIfHeader parses the "If: foo bar" HTTP header. The httpHeader string
+// should omit the "If:" prefix and have any "\r\n"s collapsed to a " ", as is
+// returned by req.Header.Get("If") for a http.Request req.
+func parseIfHeader(httpHeader string) (h ifHeader, ok bool) {
+ s := strings.TrimSpace(httpHeader)
+ switch tokenType, _, _ := lex(s); tokenType {
+ case '(':
+ return parseNoTagLists(s)
+ case angleTokenType:
+ return parseTaggedLists(s)
+ default:
+ return ifHeader{}, false
+ }
+}
+
+func parseNoTagLists(s string) (h ifHeader, ok bool) {
+ for {
+ l, remaining, ok := parseList(s)
+ if !ok {
+ return ifHeader{}, false
+ }
+ h.lists = append(h.lists, l)
+ if remaining == "" {
+ return h, true
+ }
+ s = remaining
+ }
+}
+
+func parseTaggedLists(s string) (h ifHeader, ok bool) {
+ resourceTag, n := "", 0
+ for first := true; ; first = false {
+ tokenType, tokenStr, remaining := lex(s)
+ switch tokenType {
+ case angleTokenType:
+ if !first && n == 0 {
+ return ifHeader{}, false
+ }
+ resourceTag, n = tokenStr, 0
+ s = remaining
+ case '(':
+ n++
+ l, remaining, ok := parseList(s)
+ if !ok {
+ return ifHeader{}, false
+ }
+ l.resourceTag = resourceTag
+ h.lists = append(h.lists, l)
+ if remaining == "" {
+ return h, true
+ }
+ s = remaining
+ default:
+ return ifHeader{}, false
+ }
+ }
+}
+
+func parseList(s string) (l ifList, remaining string, ok bool) {
+ tokenType, _, s := lex(s)
+ if tokenType != '(' {
+ return ifList{}, "", false
+ }
+ for {
+ tokenType, _, remaining = lex(s)
+ if tokenType == ')' {
+ if len(l.conditions) == 0 {
+ return ifList{}, "", false
+ }
+ return l, remaining, true
+ }
+ c, remaining, ok := parseCondition(s)
+ if !ok {
+ return ifList{}, "", false
+ }
+ l.conditions = append(l.conditions, c)
+ s = remaining
+ }
+}
+
+func parseCondition(s string) (c Condition, remaining string, ok bool) {
+ tokenType, tokenStr, s := lex(s)
+ if tokenType == notTokenType {
+ c.Not = true
+ tokenType, tokenStr, s = lex(s)
+ }
+ switch tokenType {
+ case strTokenType, angleTokenType:
+ c.Token = tokenStr
+ case squareTokenType:
+ c.ETag = tokenStr
+ default:
+ return Condition{}, "", false
+ }
+ return c, s, true
+}
+
+// Single-rune tokens like '(' or ')' have a token type equal to their rune.
+// All other tokens have a negative token type.
+const (
+ errTokenType = rune(-1)
+ eofTokenType = rune(-2)
+ strTokenType = rune(-3)
+ notTokenType = rune(-4)
+ angleTokenType = rune(-5)
+ squareTokenType = rune(-6)
+)
+
+func lex(s string) (tokenType rune, tokenStr string, remaining string) {
+ // The net/textproto Reader that parses the HTTP header will collapse
+ // Linear White Space that spans multiple "\r\n" lines to a single " ",
+ // so we don't need to look for '\r' or '\n'.
+ for len(s) > 0 && (s[0] == '\t' || s[0] == ' ') {
+ s = s[1:]
+ }
+ if len(s) == 0 {
+ return eofTokenType, "", ""
+ }
+ i := 0
+loop:
+ for ; i < len(s); i++ {
+ switch s[i] {
+ case '\t', ' ', '(', ')', '<', '>', '[', ']':
+ break loop
+ }
+ }
+
+ if i != 0 {
+ tokenStr, remaining = s[:i], s[i:]
+ if tokenStr == "Not" {
+ return notTokenType, "", remaining
+ }
+ return strTokenType, tokenStr, remaining
+ }
+
+ j := 0
+ switch s[0] {
+ case '<':
+ j, tokenType = strings.IndexByte(s, '>'), angleTokenType
+ case '[':
+ j, tokenType = strings.IndexByte(s, ']'), squareTokenType
+ default:
+ return rune(s[0]), "", s[1:]
+ }
+ if j < 0 {
+ return errTokenType, "", ""
+ }
+ return tokenType, s[1:j], s[j+1:]
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/if_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/if_test.go
new file mode 100644
index 000000000..aad61a401
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/if_test.go
@@ -0,0 +1,322 @@
+// Copyright 2014 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 webdav
+
+import (
+ "reflect"
+ "strings"
+ "testing"
+)
+
+func TestParseIfHeader(t *testing.T) {
+ // The "section x.y.z" test cases come from section x.y.z of the spec at
+ // http://www.webdav.org/specs/rfc4918.html
+ testCases := []struct {
+ desc string
+ input string
+ want ifHeader
+ }{{
+ "bad: empty",
+ ``,
+ ifHeader{},
+ }, {
+ "bad: no parens",
+ `foobar`,
+ ifHeader{},
+ }, {
+ "bad: empty list #1",
+ `()`,
+ ifHeader{},
+ }, {
+ "bad: empty list #2",
+ `(a) (b c) () (d)`,
+ ifHeader{},
+ }, {
+ "bad: no list after resource #1",
+ `<foo>`,
+ ifHeader{},
+ }, {
+ "bad: no list after resource #2",
+ `<foo> <bar> (a)`,
+ ifHeader{},
+ }, {
+ "bad: no list after resource #3",
+ `<foo> (a) (b) <bar>`,
+ ifHeader{},
+ }, {
+ "bad: no-tag-list followed by tagged-list",
+ `(a) (b) <foo> (c)`,
+ ifHeader{},
+ }, {
+ "bad: unfinished list",
+ `(a`,
+ ifHeader{},
+ }, {
+ "bad: unfinished ETag",
+ `([b`,
+ ifHeader{},
+ }, {
+ "bad: unfinished Notted list",
+ `(Not a`,
+ ifHeader{},
+ }, {
+ "bad: double Not",
+ `(Not Not a)`,
+ ifHeader{},
+ }, {
+ "good: one list with a Token",
+ `(a)`,
+ ifHeader{
+ lists: []ifList{{
+ conditions: []Condition{{
+ Token: `a`,
+ }},
+ }},
+ },
+ }, {
+ "good: one list with an ETag",
+ `([a])`,
+ ifHeader{
+ lists: []ifList{{
+ conditions: []Condition{{
+ ETag: `a`,
+ }},
+ }},
+ },
+ }, {
+ "good: one list with three Nots",
+ `(Not a Not b Not [d])`,
+ ifHeader{
+ lists: []ifList{{
+ conditions: []Condition{{
+ Not: true,
+ Token: `a`,
+ }, {
+ Not: true,
+ Token: `b`,
+ }, {
+ Not: true,
+ ETag: `d`,
+ }},
+ }},
+ },
+ }, {
+ "good: two lists",
+ `(a) (b)`,
+ ifHeader{
+ lists: []ifList{{
+ conditions: []Condition{{
+ Token: `a`,
+ }},
+ }, {
+ conditions: []Condition{{
+ Token: `b`,
+ }},
+ }},
+ },
+ }, {
+ "good: two Notted lists",
+ `(Not a) (Not b)`,
+ ifHeader{
+ lists: []ifList{{
+ conditions: []Condition{{
+ Not: true,
+ Token: `a`,
+ }},
+ }, {
+ conditions: []Condition{{
+ Not: true,
+ Token: `b`,
+ }},
+ }},
+ },
+ }, {
+ "section 7.5.1",
+ `<http://www.example.com/users/f/fielding/index.html>
+ (<urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6>)`,
+ ifHeader{
+ lists: []ifList{{
+ resourceTag: `http://www.example.com/users/f/fielding/index.html`,
+ conditions: []Condition{{
+ Token: `urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6`,
+ }},
+ }},
+ },
+ }, {
+ "section 7.5.2 #1",
+ `(<urn:uuid:150852e2-3847-42d5-8cbe-0f4f296f26cf>)`,
+ ifHeader{
+ lists: []ifList{{
+ conditions: []Condition{{
+ Token: `urn:uuid:150852e2-3847-42d5-8cbe-0f4f296f26cf`,
+ }},
+ }},
+ },
+ }, {
+ "section 7.5.2 #2",
+ `<http://example.com/locked/>
+ (<urn:uuid:150852e2-3847-42d5-8cbe-0f4f296f26cf>)`,
+ ifHeader{
+ lists: []ifList{{
+ resourceTag: `http://example.com/locked/`,
+ conditions: []Condition{{
+ Token: `urn:uuid:150852e2-3847-42d5-8cbe-0f4f296f26cf`,
+ }},
+ }},
+ },
+ }, {
+ "section 7.5.2 #3",
+ `<http://example.com/locked/member>
+ (<urn:uuid:150852e2-3847-42d5-8cbe-0f4f296f26cf>)`,
+ ifHeader{
+ lists: []ifList{{
+ resourceTag: `http://example.com/locked/member`,
+ conditions: []Condition{{
+ Token: `urn:uuid:150852e2-3847-42d5-8cbe-0f4f296f26cf`,
+ }},
+ }},
+ },
+ }, {
+ "section 9.9.6",
+ `(<urn:uuid:fe184f2e-6eec-41d0-c765-01adc56e6bb4>)
+ (<urn:uuid:e454f3f3-acdc-452a-56c7-00a5c91e4b77>)`,
+ ifHeader{
+ lists: []ifList{{
+ conditions: []Condition{{
+ Token: `urn:uuid:fe184f2e-6eec-41d0-c765-01adc56e6bb4`,
+ }},
+ }, {
+ conditions: []Condition{{
+ Token: `urn:uuid:e454f3f3-acdc-452a-56c7-00a5c91e4b77`,
+ }},
+ }},
+ },
+ }, {
+ "section 9.10.8",
+ `(<urn:uuid:e71d4fae-5dec-22d6-fea5-00a0c91e6be4>)`,
+ ifHeader{
+ lists: []ifList{{
+ conditions: []Condition{{
+ Token: `urn:uuid:e71d4fae-5dec-22d6-fea5-00a0c91e6be4`,
+ }},
+ }},
+ },
+ }, {
+ "section 10.4.6",
+ `(<urn:uuid:181d4fae-7d8c-11d0-a765-00a0c91e6bf2>
+ ["I am an ETag"])
+ (["I am another ETag"])`,
+ ifHeader{
+ lists: []ifList{{
+ conditions: []Condition{{
+ Token: `urn:uuid:181d4fae-7d8c-11d0-a765-00a0c91e6bf2`,
+ }, {
+ ETag: `"I am an ETag"`,
+ }},
+ }, {
+ conditions: []Condition{{
+ ETag: `"I am another ETag"`,
+ }},
+ }},
+ },
+ }, {
+ "section 10.4.7",
+ `(Not <urn:uuid:181d4fae-7d8c-11d0-a765-00a0c91e6bf2>
+ <urn:uuid:58f202ac-22cf-11d1-b12d-002035b29092>)`,
+ ifHeader{
+ lists: []ifList{{
+ conditions: []Condition{{
+ Not: true,
+ Token: `urn:uuid:181d4fae-7d8c-11d0-a765-00a0c91e6bf2`,
+ }, {
+ Token: `urn:uuid:58f202ac-22cf-11d1-b12d-002035b29092`,
+ }},
+ }},
+ },
+ }, {
+ "section 10.4.8",
+ `(<urn:uuid:181d4fae-7d8c-11d0-a765-00a0c91e6bf2>)
+ (Not <DAV:no-lock>)`,
+ ifHeader{
+ lists: []ifList{{
+ conditions: []Condition{{
+ Token: `urn:uuid:181d4fae-7d8c-11d0-a765-00a0c91e6bf2`,
+ }},
+ }, {
+ conditions: []Condition{{
+ Not: true,
+ Token: `DAV:no-lock`,
+ }},
+ }},
+ },
+ }, {
+ "section 10.4.9",
+ `</resource1>
+ (<urn:uuid:181d4fae-7d8c-11d0-a765-00a0c91e6bf2>
+ [W/"A weak ETag"]) (["strong ETag"])`,
+ ifHeader{
+ lists: []ifList{{
+ resourceTag: `/resource1`,
+ conditions: []Condition{{
+ Token: `urn:uuid:181d4fae-7d8c-11d0-a765-00a0c91e6bf2`,
+ }, {
+ ETag: `W/"A weak ETag"`,
+ }},
+ }, {
+ resourceTag: `/resource1`,
+ conditions: []Condition{{
+ ETag: `"strong ETag"`,
+ }},
+ }},
+ },
+ }, {
+ "section 10.4.10",
+ `<http://www.example.com/specs/>
+ (<urn:uuid:181d4fae-7d8c-11d0-a765-00a0c91e6bf2>)`,
+ ifHeader{
+ lists: []ifList{{
+ resourceTag: `http://www.example.com/specs/`,
+ conditions: []Condition{{
+ Token: `urn:uuid:181d4fae-7d8c-11d0-a765-00a0c91e6bf2`,
+ }},
+ }},
+ },
+ }, {
+ "section 10.4.11 #1",
+ `</specs/rfc2518.doc> (["4217"])`,
+ ifHeader{
+ lists: []ifList{{
+ resourceTag: `/specs/rfc2518.doc`,
+ conditions: []Condition{{
+ ETag: `"4217"`,
+ }},
+ }},
+ },
+ }, {
+ "section 10.4.11 #2",
+ `</specs/rfc2518.doc> (Not ["4217"])`,
+ ifHeader{
+ lists: []ifList{{
+ resourceTag: `/specs/rfc2518.doc`,
+ conditions: []Condition{{
+ Not: true,
+ ETag: `"4217"`,
+ }},
+ }},
+ },
+ }}
+
+ for _, tc := range testCases {
+ got, ok := parseIfHeader(strings.Replace(tc.input, "\n", "", -1))
+ if gotEmpty := reflect.DeepEqual(got, ifHeader{}); gotEmpty == ok {
+ t.Errorf("%s: should be different: empty header == %t, ok == %t", tc.desc, gotEmpty, ok)
+ continue
+ }
+ if !reflect.DeepEqual(got, tc.want) {
+ t.Errorf("%s:\ngot %v\nwant %v", tc.desc, got, tc.want)
+ continue
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/internal/xml/README b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/internal/xml/README
new file mode 100644
index 000000000..89656f489
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/internal/xml/README
@@ -0,0 +1,11 @@
+This is a fork of the encoding/xml package at ca1d6c4, the last commit before
+https://go.googlesource.com/go/+/c0d6d33 "encoding/xml: restore Go 1.4 name
+space behavior" made late in the lead-up to the Go 1.5 release.
+
+The list of encoding/xml changes is at
+https://go.googlesource.com/go/+log/master/src/encoding/xml
+
+This fork is temporary, and I (nigeltao) expect to revert it after Go 1.6 is
+released.
+
+See http://golang.org/issue/11841
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/internal/xml/atom_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/internal/xml/atom_test.go
new file mode 100644
index 000000000..a71284312
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/internal/xml/atom_test.go
@@ -0,0 +1,56 @@
+// Copyright 2011 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 xml
+
+import "time"
+
+var atomValue = &Feed{
+ XMLName: Name{"http://www.w3.org/2005/Atom", "feed"},
+ Title: "Example Feed",
+ Link: []Link{{Href: "http://example.org/"}},
+ Updated: ParseTime("2003-12-13T18:30:02Z"),
+ Author: Person{Name: "John Doe"},
+ Id: "urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6",
+
+ Entry: []Entry{
+ {
+ Title: "Atom-Powered Robots Run Amok",
+ Link: []Link{{Href: "http://example.org/2003/12/13/atom03"}},
+ Id: "urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a",
+ Updated: ParseTime("2003-12-13T18:30:02Z"),
+ Summary: NewText("Some text."),
+ },
+ },
+}
+
+var atomXml = `` +
+ `<feed xmlns="http://www.w3.org/2005/Atom" updated="2003-12-13T18:30:02Z">` +
+ `<title>Example Feed</title>` +
+ `<id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>` +
+ `<link href="http://example.org/"></link>` +
+ `<author><name>John Doe</name><uri></uri><email></email></author>` +
+ `<entry>` +
+ `<title>Atom-Powered Robots Run Amok</title>` +
+ `<id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>` +
+ `<link href="http://example.org/2003/12/13/atom03"></link>` +
+ `<updated>2003-12-13T18:30:02Z</updated>` +
+ `<author><name></name><uri></uri><email></email></author>` +
+ `<summary>Some text.</summary>` +
+ `</entry>` +
+ `</feed>`
+
+func ParseTime(str string) time.Time {
+ t, err := time.Parse(time.RFC3339, str)
+ if err != nil {
+ panic(err)
+ }
+ return t
+}
+
+func NewText(text string) Text {
+ return Text{
+ Body: text,
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/internal/xml/example_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/internal/xml/example_test.go
new file mode 100644
index 000000000..21b48dea5
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/internal/xml/example_test.go
@@ -0,0 +1,151 @@
+// Copyright 2012 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 xml_test
+
+import (
+ "encoding/xml"
+ "fmt"
+ "os"
+)
+
+func ExampleMarshalIndent() {
+ type Address struct {
+ City, State string
+ }
+ type Person struct {
+ XMLName xml.Name `xml:"person"`
+ Id int `xml:"id,attr"`
+ FirstName string `xml:"name>first"`
+ LastName string `xml:"name>last"`
+ Age int `xml:"age"`
+ Height float32 `xml:"height,omitempty"`
+ Married bool
+ Address
+ Comment string `xml:",comment"`
+ }
+
+ v := &Person{Id: 13, FirstName: "John", LastName: "Doe", Age: 42}
+ v.Comment = " Need more details. "
+ v.Address = Address{"Hanga Roa", "Easter Island"}
+
+ output, err := xml.MarshalIndent(v, " ", " ")
+ if err != nil {
+ fmt.Printf("error: %v\n", err)
+ }
+
+ os.Stdout.Write(output)
+ // Output:
+ // <person id="13">
+ // <name>
+ // <first>John</first>
+ // <last>Doe</last>
+ // </name>
+ // <age>42</age>
+ // <Married>false</Married>
+ // <City>Hanga Roa</City>
+ // <State>Easter Island</State>
+ // <!-- Need more details. -->
+ // </person>
+}
+
+func ExampleEncoder() {
+ type Address struct {
+ City, State string
+ }
+ type Person struct {
+ XMLName xml.Name `xml:"person"`
+ Id int `xml:"id,attr"`
+ FirstName string `xml:"name>first"`
+ LastName string `xml:"name>last"`
+ Age int `xml:"age"`
+ Height float32 `xml:"height,omitempty"`
+ Married bool
+ Address
+ Comment string `xml:",comment"`
+ }
+
+ v := &Person{Id: 13, FirstName: "John", LastName: "Doe", Age: 42}
+ v.Comment = " Need more details. "
+ v.Address = Address{"Hanga Roa", "Easter Island"}
+
+ enc := xml.NewEncoder(os.Stdout)
+ enc.Indent(" ", " ")
+ if err := enc.Encode(v); err != nil {
+ fmt.Printf("error: %v\n", err)
+ }
+
+ // Output:
+ // <person id="13">
+ // <name>
+ // <first>John</first>
+ // <last>Doe</last>
+ // </name>
+ // <age>42</age>
+ // <Married>false</Married>
+ // <City>Hanga Roa</City>
+ // <State>Easter Island</State>
+ // <!-- Need more details. -->
+ // </person>
+}
+
+// This example demonstrates unmarshaling an XML excerpt into a value with
+// some preset fields. Note that the Phone field isn't modified and that
+// the XML <Company> element is ignored. Also, the Groups field is assigned
+// considering the element path provided in its tag.
+func ExampleUnmarshal() {
+ type Email struct {
+ Where string `xml:"where,attr"`
+ Addr string
+ }
+ type Address struct {
+ City, State string
+ }
+ type Result struct {
+ XMLName xml.Name `xml:"Person"`
+ Name string `xml:"FullName"`
+ Phone string
+ Email []Email
+ Groups []string `xml:"Group>Value"`
+ Address
+ }
+ v := Result{Name: "none", Phone: "none"}
+
+ data := `
+ <Person>
+ <FullName>Grace R. Emlin</FullName>
+ <Company>Example Inc.</Company>
+ <Email where="home">
+ <Addr>gre@example.com</Addr>
+ </Email>
+ <Email where='work'>
+ <Addr>gre@work.com</Addr>
+ </Email>
+ <Group>
+ <Value>Friends</Value>
+ <Value>Squash</Value>
+ </Group>
+ <City>Hanga Roa</City>
+ <State>Easter Island</State>
+ </Person>
+ `
+ err := xml.Unmarshal([]byte(data), &v)
+ if err != nil {
+ fmt.Printf("error: %v", err)
+ return
+ }
+ fmt.Printf("XMLName: %#v\n", v.XMLName)
+ fmt.Printf("Name: %q\n", v.Name)
+ fmt.Printf("Phone: %q\n", v.Phone)
+ fmt.Printf("Email: %v\n", v.Email)
+ fmt.Printf("Groups: %v\n", v.Groups)
+ fmt.Printf("Address: %v\n", v.Address)
+ // Output:
+ // XMLName: xml.Name{Space:"", Local:"Person"}
+ // Name: "Grace R. Emlin"
+ // Phone: "none"
+ // Email: [{home gre@example.com} {work gre@work.com}]
+ // Groups: [Friends Squash]
+ // Address: {Hanga Roa Easter Island}
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/internal/xml/marshal.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/internal/xml/marshal.go
new file mode 100644
index 000000000..cb82ec214
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/internal/xml/marshal.go
@@ -0,0 +1,1223 @@
+// Copyright 2011 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 xml
+
+import (
+ "bufio"
+ "bytes"
+ "encoding"
+ "fmt"
+ "io"
+ "reflect"
+ "strconv"
+ "strings"
+)
+
+const (
+ // A generic XML header suitable for use with the output of Marshal.
+ // This is not automatically added to any output of this package,
+ // it is provided as a convenience.
+ Header = `<?xml version="1.0" encoding="UTF-8"?>` + "\n"
+)
+
+// Marshal returns the XML encoding of v.
+//
+// Marshal handles an array or slice by marshalling each of the elements.
+// Marshal handles a pointer by marshalling the value it points at or, if the
+// pointer is nil, by writing nothing. Marshal handles an interface value by
+// marshalling the value it contains or, if the interface value is nil, by
+// writing nothing. Marshal handles all other data by writing one or more XML
+// elements containing the data.
+//
+// The name for the XML elements is taken from, in order of preference:
+// - the tag on the XMLName field, if the data is a struct
+// - the value of the XMLName field of type xml.Name
+// - the tag of the struct field used to obtain the data
+// - the name of the struct field used to obtain the data
+// - the name of the marshalled type
+//
+// The XML element for a struct contains marshalled elements for each of the
+// exported fields of the struct, with these exceptions:
+// - the XMLName field, described above, is omitted.
+// - a field with tag "-" is omitted.
+// - a field with tag "name,attr" becomes an attribute with
+// the given name in the XML element.
+// - a field with tag ",attr" becomes an attribute with the
+// field name in the XML element.
+// - a field with tag ",chardata" is written as character data,
+// not as an XML element.
+// - a field with tag ",innerxml" is written verbatim, not subject
+// to the usual marshalling procedure.
+// - a field with tag ",comment" is written as an XML comment, not
+// subject to the usual marshalling procedure. It must not contain
+// the "--" string within it.
+// - a field with a tag including the "omitempty" option is omitted
+// if the field value is empty. The empty values are false, 0, any
+// nil pointer or interface value, and any array, slice, map, or
+// string of length zero.
+// - an anonymous struct field is handled as if the fields of its
+// value were part of the outer struct.
+//
+// If a field uses a tag "a>b>c", then the element c will be nested inside
+// parent elements a and b. Fields that appear next to each other that name
+// the same parent will be enclosed in one XML element.
+//
+// See MarshalIndent for an example.
+//
+// Marshal will return an error if asked to marshal a channel, function, or map.
+func Marshal(v interface{}) ([]byte, error) {
+ var b bytes.Buffer
+ if err := NewEncoder(&b).Encode(v); err != nil {
+ return nil, err
+ }
+ return b.Bytes(), nil
+}
+
+// Marshaler is the interface implemented by objects that can marshal
+// themselves into valid XML elements.
+//
+// MarshalXML encodes the receiver as zero or more XML elements.
+// By convention, arrays or slices are typically encoded as a sequence
+// of elements, one per entry.
+// Using start as the element tag is not required, but doing so
+// will enable Unmarshal to match the XML elements to the correct
+// struct field.
+// One common implementation strategy is to construct a separate
+// value with a layout corresponding to the desired XML and then
+// to encode it using e.EncodeElement.
+// Another common strategy is to use repeated calls to e.EncodeToken
+// to generate the XML output one token at a time.
+// The sequence of encoded tokens must make up zero or more valid
+// XML elements.
+type Marshaler interface {
+ MarshalXML(e *Encoder, start StartElement) error
+}
+
+// MarshalerAttr is the interface implemented by objects that can marshal
+// themselves into valid XML attributes.
+//
+// MarshalXMLAttr returns an XML attribute with the encoded value of the receiver.
+// Using name as the attribute name is not required, but doing so
+// will enable Unmarshal to match the attribute to the correct
+// struct field.
+// If MarshalXMLAttr returns the zero attribute Attr{}, no attribute
+// will be generated in the output.
+// MarshalXMLAttr is used only for struct fields with the
+// "attr" option in the field tag.
+type MarshalerAttr interface {
+ MarshalXMLAttr(name Name) (Attr, error)
+}
+
+// MarshalIndent works like Marshal, but each XML element begins on a new
+// indented line that starts with prefix and is followed by one or more
+// copies of indent according to the nesting depth.
+func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) {
+ var b bytes.Buffer
+ enc := NewEncoder(&b)
+ enc.Indent(prefix, indent)
+ if err := enc.Encode(v); err != nil {
+ return nil, err
+ }
+ return b.Bytes(), nil
+}
+
+// An Encoder writes XML data to an output stream.
+type Encoder struct {
+ p printer
+}
+
+// NewEncoder returns a new encoder that writes to w.
+func NewEncoder(w io.Writer) *Encoder {
+ e := &Encoder{printer{Writer: bufio.NewWriter(w)}}
+ e.p.encoder = e
+ return e
+}
+
+// Indent sets the encoder to generate XML in which each element
+// begins on a new indented line that starts with prefix and is followed by
+// one or more copies of indent according to the nesting depth.
+func (enc *Encoder) Indent(prefix, indent string) {
+ enc.p.prefix = prefix
+ enc.p.indent = indent
+}
+
+// Encode writes the XML encoding of v to the stream.
+//
+// See the documentation for Marshal for details about the conversion
+// of Go values to XML.
+//
+// Encode calls Flush before returning.
+func (enc *Encoder) Encode(v interface{}) error {
+ err := enc.p.marshalValue(reflect.ValueOf(v), nil, nil)
+ if err != nil {
+ return err
+ }
+ return enc.p.Flush()
+}
+
+// EncodeElement writes the XML encoding of v to the stream,
+// using start as the outermost tag in the encoding.
+//
+// See the documentation for Marshal for details about the conversion
+// of Go values to XML.
+//
+// EncodeElement calls Flush before returning.
+func (enc *Encoder) EncodeElement(v interface{}, start StartElement) error {
+ err := enc.p.marshalValue(reflect.ValueOf(v), nil, &start)
+ if err != nil {
+ return err
+ }
+ return enc.p.Flush()
+}
+
+var (
+ begComment = []byte("<!--")
+ endComment = []byte("-->")
+ endProcInst = []byte("?>")
+ endDirective = []byte(">")
+)
+
+// EncodeToken writes the given XML token to the stream.
+// It returns an error if StartElement and EndElement tokens are not
+// properly matched.
+//
+// EncodeToken does not call Flush, because usually it is part of a
+// larger operation such as Encode or EncodeElement (or a custom
+// Marshaler's MarshalXML invoked during those), and those will call
+// Flush when finished. Callers that create an Encoder and then invoke
+// EncodeToken directly, without using Encode or EncodeElement, need to
+// call Flush when finished to ensure that the XML is written to the
+// underlying writer.
+//
+// EncodeToken allows writing a ProcInst with Target set to "xml" only
+// as the first token in the stream.
+//
+// When encoding a StartElement holding an XML namespace prefix
+// declaration for a prefix that is not already declared, contained
+// elements (including the StartElement itself) will use the declared
+// prefix when encoding names with matching namespace URIs.
+func (enc *Encoder) EncodeToken(t Token) error {
+
+ p := &enc.p
+ switch t := t.(type) {
+ case StartElement:
+ if err := p.writeStart(&t); err != nil {
+ return err
+ }
+ case EndElement:
+ if err := p.writeEnd(t.Name); err != nil {
+ return err
+ }
+ case CharData:
+ escapeText(p, t, false)
+ case Comment:
+ if bytes.Contains(t, endComment) {
+ return fmt.Errorf("xml: EncodeToken of Comment containing --> marker")
+ }
+ p.WriteString("<!--")
+ p.Write(t)
+ p.WriteString("-->")
+ return p.cachedWriteError()
+ case ProcInst:
+ // First token to be encoded which is also a ProcInst with target of xml
+ // is the xml declaration. The only ProcInst where target of xml is allowed.
+ if t.Target == "xml" && p.Buffered() != 0 {
+ return fmt.Errorf("xml: EncodeToken of ProcInst xml target only valid for xml declaration, first token encoded")
+ }
+ if !isNameString(t.Target) {
+ return fmt.Errorf("xml: EncodeToken of ProcInst with invalid Target")
+ }
+ if bytes.Contains(t.Inst, endProcInst) {
+ return fmt.Errorf("xml: EncodeToken of ProcInst containing ?> marker")
+ }
+ p.WriteString("<?")
+ p.WriteString(t.Target)
+ if len(t.Inst) > 0 {
+ p.WriteByte(' ')
+ p.Write(t.Inst)
+ }
+ p.WriteString("?>")
+ case Directive:
+ if !isValidDirective(t) {
+ return fmt.Errorf("xml: EncodeToken of Directive containing wrong < or > markers")
+ }
+ p.WriteString("<!")
+ p.Write(t)
+ p.WriteString(">")
+ default:
+ return fmt.Errorf("xml: EncodeToken of invalid token type")
+
+ }
+ return p.cachedWriteError()
+}
+
+// isValidDirective reports whether dir is a valid directive text,
+// meaning angle brackets are matched, ignoring comments and strings.
+func isValidDirective(dir Directive) bool {
+ var (
+ depth int
+ inquote uint8
+ incomment bool
+ )
+ for i, c := range dir {
+ switch {
+ case incomment:
+ if c == '>' {
+ if n := 1 + i - len(endComment); n >= 0 && bytes.Equal(dir[n:i+1], endComment) {
+ incomment = false
+ }
+ }
+ // Just ignore anything in comment
+ case inquote != 0:
+ if c == inquote {
+ inquote = 0
+ }
+ // Just ignore anything within quotes
+ case c == '\'' || c == '"':
+ inquote = c
+ case c == '<':
+ if i+len(begComment) < len(dir) && bytes.Equal(dir[i:i+len(begComment)], begComment) {
+ incomment = true
+ } else {
+ depth++
+ }
+ case c == '>':
+ if depth == 0 {
+ return false
+ }
+ depth--
+ }
+ }
+ return depth == 0 && inquote == 0 && !incomment
+}
+
+// Flush flushes any buffered XML to the underlying writer.
+// See the EncodeToken documentation for details about when it is necessary.
+func (enc *Encoder) Flush() error {
+ return enc.p.Flush()
+}
+
+type printer struct {
+ *bufio.Writer
+ encoder *Encoder
+ seq int
+ indent string
+ prefix string
+ depth int
+ indentedIn bool
+ putNewline bool
+ defaultNS string
+ attrNS map[string]string // map prefix -> name space
+ attrPrefix map[string]string // map name space -> prefix
+ prefixes []printerPrefix
+ tags []Name
+}
+
+// printerPrefix holds a namespace undo record.
+// When an element is popped, the prefix record
+// is set back to the recorded URL. The empty
+// prefix records the URL for the default name space.
+//
+// The start of an element is recorded with an element
+// that has mark=true.
+type printerPrefix struct {
+ prefix string
+ url string
+ mark bool
+}
+
+func (p *printer) prefixForNS(url string, isAttr bool) string {
+ // The "http://www.w3.org/XML/1998/namespace" name space is predefined as "xml"
+ // and must be referred to that way.
+ // (The "http://www.w3.org/2000/xmlns/" name space is also predefined as "xmlns",
+ // but users should not be trying to use that one directly - that's our job.)
+ if url == xmlURL {
+ return "xml"
+ }
+ if !isAttr && url == p.defaultNS {
+ // We can use the default name space.
+ return ""
+ }
+ return p.attrPrefix[url]
+}
+
+// defineNS pushes any namespace definition found in the given attribute.
+// If ignoreNonEmptyDefault is true, an xmlns="nonempty"
+// attribute will be ignored.
+func (p *printer) defineNS(attr Attr, ignoreNonEmptyDefault bool) error {
+ var prefix string
+ if attr.Name.Local == "xmlns" {
+ if attr.Name.Space != "" && attr.Name.Space != "xml" && attr.Name.Space != xmlURL {
+ return fmt.Errorf("xml: cannot redefine xmlns attribute prefix")
+ }
+ } else if attr.Name.Space == "xmlns" && attr.Name.Local != "" {
+ prefix = attr.Name.Local
+ if attr.Value == "" {
+ // Technically, an empty XML namespace is allowed for an attribute.
+ // From http://www.w3.org/TR/xml-names11/#scoping-defaulting:
+ //
+ // The attribute value in a namespace declaration for a prefix may be
+ // empty. This has the effect, within the scope of the declaration, of removing
+ // any association of the prefix with a namespace name.
+ //
+ // However our namespace prefixes here are used only as hints. There's
+ // no need to respect the removal of a namespace prefix, so we ignore it.
+ return nil
+ }
+ } else {
+ // Ignore: it's not a namespace definition
+ return nil
+ }
+ if prefix == "" {
+ if attr.Value == p.defaultNS {
+ // No need for redefinition.
+ return nil
+ }
+ if attr.Value != "" && ignoreNonEmptyDefault {
+ // We have an xmlns="..." value but
+ // it can't define a name space in this context,
+ // probably because the element has an empty
+ // name space. In this case, we just ignore
+ // the name space declaration.
+ return nil
+ }
+ } else if _, ok := p.attrPrefix[attr.Value]; ok {
+ // There's already a prefix for the given name space,
+ // so use that. This prevents us from
+ // having two prefixes for the same name space
+ // so attrNS and attrPrefix can remain bijective.
+ return nil
+ }
+ p.pushPrefix(prefix, attr.Value)
+ return nil
+}
+
+// createNSPrefix creates a name space prefix attribute
+// to use for the given name space, defining a new prefix
+// if necessary.
+// If isAttr is true, the prefix is to be created for an attribute
+// prefix, which means that the default name space cannot
+// be used.
+func (p *printer) createNSPrefix(url string, isAttr bool) {
+ if _, ok := p.attrPrefix[url]; ok {
+ // We already have a prefix for the given URL.
+ return
+ }
+ switch {
+ case !isAttr && url == p.defaultNS:
+ // We can use the default name space.
+ return
+ case url == "":
+ // The only way we can encode names in the empty
+ // name space is by using the default name space,
+ // so we must use that.
+ if p.defaultNS != "" {
+ // The default namespace is non-empty, so we
+ // need to set it to empty.
+ p.pushPrefix("", "")
+ }
+ return
+ case url == xmlURL:
+ return
+ }
+ // TODO If the URL is an existing prefix, we could
+ // use it as is. That would enable the
+ // marshaling of elements that had been unmarshaled
+ // and with a name space prefix that was not found.
+ // although technically it would be incorrect.
+
+ // Pick a name. We try to use the final element of the path
+ // but fall back to _.
+ prefix := strings.TrimRight(url, "/")
+ if i := strings.LastIndex(prefix, "/"); i >= 0 {
+ prefix = prefix[i+1:]
+ }
+ if prefix == "" || !isName([]byte(prefix)) || strings.Contains(prefix, ":") {
+ prefix = "_"
+ }
+ if strings.HasPrefix(prefix, "xml") {
+ // xmlanything is reserved.
+ prefix = "_" + prefix
+ }
+ if p.attrNS[prefix] != "" {
+ // Name is taken. Find a better one.
+ for p.seq++; ; p.seq++ {
+ if id := prefix + "_" + strconv.Itoa(p.seq); p.attrNS[id] == "" {
+ prefix = id
+ break
+ }
+ }
+ }
+
+ p.pushPrefix(prefix, url)
+}
+
+// writeNamespaces writes xmlns attributes for all the
+// namespace prefixes that have been defined in
+// the current element.
+func (p *printer) writeNamespaces() {
+ for i := len(p.prefixes) - 1; i >= 0; i-- {
+ prefix := p.prefixes[i]
+ if prefix.mark {
+ return
+ }
+ p.WriteString(" ")
+ if prefix.prefix == "" {
+ // Default name space.
+ p.WriteString(`xmlns="`)
+ } else {
+ p.WriteString("xmlns:")
+ p.WriteString(prefix.prefix)
+ p.WriteString(`="`)
+ }
+ EscapeText(p, []byte(p.nsForPrefix(prefix.prefix)))
+ p.WriteString(`"`)
+ }
+}
+
+// pushPrefix pushes a new prefix on the prefix stack
+// without checking to see if it is already defined.
+func (p *printer) pushPrefix(prefix, url string) {
+ p.prefixes = append(p.prefixes, printerPrefix{
+ prefix: prefix,
+ url: p.nsForPrefix(prefix),
+ })
+ p.setAttrPrefix(prefix, url)
+}
+
+// nsForPrefix returns the name space for the given
+// prefix. Note that this is not valid for the
+// empty attribute prefix, which always has an empty
+// name space.
+func (p *printer) nsForPrefix(prefix string) string {
+ if prefix == "" {
+ return p.defaultNS
+ }
+ return p.attrNS[prefix]
+}
+
+// markPrefix marks the start of an element on the prefix
+// stack.
+func (p *printer) markPrefix() {
+ p.prefixes = append(p.prefixes, printerPrefix{
+ mark: true,
+ })
+}
+
+// popPrefix pops all defined prefixes for the current
+// element.
+func (p *printer) popPrefix() {
+ for len(p.prefixes) > 0 {
+ prefix := p.prefixes[len(p.prefixes)-1]
+ p.prefixes = p.prefixes[:len(p.prefixes)-1]
+ if prefix.mark {
+ break
+ }
+ p.setAttrPrefix(prefix.prefix, prefix.url)
+ }
+}
+
+// setAttrPrefix sets an attribute name space prefix.
+// If url is empty, the attribute is removed.
+// If prefix is empty, the default name space is set.
+func (p *printer) setAttrPrefix(prefix, url string) {
+ if prefix == "" {
+ p.defaultNS = url
+ return
+ }
+ if url == "" {
+ delete(p.attrPrefix, p.attrNS[prefix])
+ delete(p.attrNS, prefix)
+ return
+ }
+ if p.attrPrefix == nil {
+ // Need to define a new name space.
+ p.attrPrefix = make(map[string]string)
+ p.attrNS = make(map[string]string)
+ }
+ // Remove any old prefix value. This is OK because we maintain a
+ // strict one-to-one mapping between prefix and URL (see
+ // defineNS)
+ delete(p.attrPrefix, p.attrNS[prefix])
+ p.attrPrefix[url] = prefix
+ p.attrNS[prefix] = url
+}
+
+var (
+ marshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem()
+ marshalerAttrType = reflect.TypeOf((*MarshalerAttr)(nil)).Elem()
+ textMarshalerType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
+)
+
+// marshalValue writes one or more XML elements representing val.
+// If val was obtained from a struct field, finfo must have its details.
+func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo, startTemplate *StartElement) error {
+ if startTemplate != nil && startTemplate.Name.Local == "" {
+ return fmt.Errorf("xml: EncodeElement of StartElement with missing name")
+ }
+
+ if !val.IsValid() {
+ return nil
+ }
+ if finfo != nil && finfo.flags&fOmitEmpty != 0 && isEmptyValue(val) {
+ return nil
+ }
+
+ // Drill into interfaces and pointers.
+ // This can turn into an infinite loop given a cyclic chain,
+ // but it matches the Go 1 behavior.
+ for val.Kind() == reflect.Interface || val.Kind() == reflect.Ptr {
+ if val.IsNil() {
+ return nil
+ }
+ val = val.Elem()
+ }
+
+ kind := val.Kind()
+ typ := val.Type()
+
+ // Check for marshaler.
+ if val.CanInterface() && typ.Implements(marshalerType) {
+ return p.marshalInterface(val.Interface().(Marshaler), p.defaultStart(typ, finfo, startTemplate))
+ }
+ if val.CanAddr() {
+ pv := val.Addr()
+ if pv.CanInterface() && pv.Type().Implements(marshalerType) {
+ return p.marshalInterface(pv.Interface().(Marshaler), p.defaultStart(pv.Type(), finfo, startTemplate))
+ }
+ }
+
+ // Check for text marshaler.
+ if val.CanInterface() && typ.Implements(textMarshalerType) {
+ return p.marshalTextInterface(val.Interface().(encoding.TextMarshaler), p.defaultStart(typ, finfo, startTemplate))
+ }
+ if val.CanAddr() {
+ pv := val.Addr()
+ if pv.CanInterface() && pv.Type().Implements(textMarshalerType) {
+ return p.marshalTextInterface(pv.Interface().(encoding.TextMarshaler), p.defaultStart(pv.Type(), finfo, startTemplate))
+ }
+ }
+
+ // Slices and arrays iterate over the elements. They do not have an enclosing tag.
+ if (kind == reflect.Slice || kind == reflect.Array) && typ.Elem().Kind() != reflect.Uint8 {
+ for i, n := 0, val.Len(); i < n; i++ {
+ if err := p.marshalValue(val.Index(i), finfo, startTemplate); err != nil {
+ return err
+ }
+ }
+ return nil
+ }
+
+ tinfo, err := getTypeInfo(typ)
+ if err != nil {
+ return err
+ }
+
+ // Create start element.
+ // Precedence for the XML element name is:
+ // 0. startTemplate
+ // 1. XMLName field in underlying struct;
+ // 2. field name/tag in the struct field; and
+ // 3. type name
+ var start StartElement
+
+ // explicitNS records whether the element's name space has been
+ // explicitly set (for example an XMLName field).
+ explicitNS := false
+
+ if startTemplate != nil {
+ start.Name = startTemplate.Name
+ explicitNS = true
+ start.Attr = append(start.Attr, startTemplate.Attr...)
+ } else if tinfo.xmlname != nil {
+ xmlname := tinfo.xmlname
+ if xmlname.name != "" {
+ start.Name.Space, start.Name.Local = xmlname.xmlns, xmlname.name
+ } else if v, ok := xmlname.value(val).Interface().(Name); ok && v.Local != "" {
+ start.Name = v
+ }
+ explicitNS = true
+ }
+ if start.Name.Local == "" && finfo != nil {
+ start.Name.Local = finfo.name
+ if finfo.xmlns != "" {
+ start.Name.Space = finfo.xmlns
+ explicitNS = true
+ }
+ }
+ if start.Name.Local == "" {
+ name := typ.Name()
+ if name == "" {
+ return &UnsupportedTypeError{typ}
+ }
+ start.Name.Local = name
+ }
+
+ // defaultNS records the default name space as set by a xmlns="..."
+ // attribute. We don't set p.defaultNS because we want to let
+ // the attribute writing code (in p.defineNS) be solely responsible
+ // for maintaining that.
+ defaultNS := p.defaultNS
+
+ // Attributes
+ for i := range tinfo.fields {
+ finfo := &tinfo.fields[i]
+ if finfo.flags&fAttr == 0 {
+ continue
+ }
+ attr, err := p.fieldAttr(finfo, val)
+ if err != nil {
+ return err
+ }
+ if attr.Name.Local == "" {
+ continue
+ }
+ start.Attr = append(start.Attr, attr)
+ if attr.Name.Space == "" && attr.Name.Local == "xmlns" {
+ defaultNS = attr.Value
+ }
+ }
+ if !explicitNS {
+ // Historic behavior: elements use the default name space
+ // they are contained in by default.
+ start.Name.Space = defaultNS
+ }
+ // Historic behaviour: an element that's in a namespace sets
+ // the default namespace for all elements contained within it.
+ start.setDefaultNamespace()
+
+ if err := p.writeStart(&start); err != nil {
+ return err
+ }
+
+ if val.Kind() == reflect.Struct {
+ err = p.marshalStruct(tinfo, val)
+ } else {
+ s, b, err1 := p.marshalSimple(typ, val)
+ if err1 != nil {
+ err = err1
+ } else if b != nil {
+ EscapeText(p, b)
+ } else {
+ p.EscapeString(s)
+ }
+ }
+ if err != nil {
+ return err
+ }
+
+ if err := p.writeEnd(start.Name); err != nil {
+ return err
+ }
+
+ return p.cachedWriteError()
+}
+
+// fieldAttr returns the attribute of the given field.
+// If the returned attribute has an empty Name.Local,
+// it should not be used.
+// The given value holds the value containing the field.
+func (p *printer) fieldAttr(finfo *fieldInfo, val reflect.Value) (Attr, error) {
+ fv := finfo.value(val)
+ name := Name{Space: finfo.xmlns, Local: finfo.name}
+ if finfo.flags&fOmitEmpty != 0 && isEmptyValue(fv) {
+ return Attr{}, nil
+ }
+ if fv.Kind() == reflect.Interface && fv.IsNil() {
+ return Attr{}, nil
+ }
+ if fv.CanInterface() && fv.Type().Implements(marshalerAttrType) {
+ attr, err := fv.Interface().(MarshalerAttr).MarshalXMLAttr(name)
+ return attr, err
+ }
+ if fv.CanAddr() {
+ pv := fv.Addr()
+ if pv.CanInterface() && pv.Type().Implements(marshalerAttrType) {
+ attr, err := pv.Interface().(MarshalerAttr).MarshalXMLAttr(name)
+ return attr, err
+ }
+ }
+ if fv.CanInterface() && fv.Type().Implements(textMarshalerType) {
+ text, err := fv.Interface().(encoding.TextMarshaler).MarshalText()
+ if err != nil {
+ return Attr{}, err
+ }
+ return Attr{name, string(text)}, nil
+ }
+ if fv.CanAddr() {
+ pv := fv.Addr()
+ if pv.CanInterface() && pv.Type().Implements(textMarshalerType) {
+ text, err := pv.Interface().(encoding.TextMarshaler).MarshalText()
+ if err != nil {
+ return Attr{}, err
+ }
+ return Attr{name, string(text)}, nil
+ }
+ }
+ // Dereference or skip nil pointer, interface values.
+ switch fv.Kind() {
+ case reflect.Ptr, reflect.Interface:
+ if fv.IsNil() {
+ return Attr{}, nil
+ }
+ fv = fv.Elem()
+ }
+ s, b, err := p.marshalSimple(fv.Type(), fv)
+ if err != nil {
+ return Attr{}, err
+ }
+ if b != nil {
+ s = string(b)
+ }
+ return Attr{name, s}, nil
+}
+
+// defaultStart returns the default start element to use,
+// given the reflect type, field info, and start template.
+func (p *printer) defaultStart(typ reflect.Type, finfo *fieldInfo, startTemplate *StartElement) StartElement {
+ var start StartElement
+ // Precedence for the XML element name is as above,
+ // except that we do not look inside structs for the first field.
+ if startTemplate != nil {
+ start.Name = startTemplate.Name
+ start.Attr = append(start.Attr, startTemplate.Attr...)
+ } else if finfo != nil && finfo.name != "" {
+ start.Name.Local = finfo.name
+ start.Name.Space = finfo.xmlns
+ } else if typ.Name() != "" {
+ start.Name.Local = typ.Name()
+ } else {
+ // Must be a pointer to a named type,
+ // since it has the Marshaler methods.
+ start.Name.Local = typ.Elem().Name()
+ }
+ // Historic behaviour: elements use the name space of
+ // the element they are contained in by default.
+ if start.Name.Space == "" {
+ start.Name.Space = p.defaultNS
+ }
+ start.setDefaultNamespace()
+ return start
+}
+
+// marshalInterface marshals a Marshaler interface value.
+func (p *printer) marshalInterface(val Marshaler, start StartElement) error {
+ // Push a marker onto the tag stack so that MarshalXML
+ // cannot close the XML tags that it did not open.
+ p.tags = append(p.tags, Name{})
+ n := len(p.tags)
+
+ err := val.MarshalXML(p.encoder, start)
+ if err != nil {
+ return err
+ }
+
+ // Make sure MarshalXML closed all its tags. p.tags[n-1] is the mark.
+ if len(p.tags) > n {
+ return fmt.Errorf("xml: %s.MarshalXML wrote invalid XML: <%s> not closed", receiverType(val), p.tags[len(p.tags)-1].Local)
+ }
+ p.tags = p.tags[:n-1]
+ return nil
+}
+
+// marshalTextInterface marshals a TextMarshaler interface value.
+func (p *printer) marshalTextInterface(val encoding.TextMarshaler, start StartElement) error {
+ if err := p.writeStart(&start); err != nil {
+ return err
+ }
+ text, err := val.MarshalText()
+ if err != nil {
+ return err
+ }
+ EscapeText(p, text)
+ return p.writeEnd(start.Name)
+}
+
+// writeStart writes the given start element.
+func (p *printer) writeStart(start *StartElement) error {
+ if start.Name.Local == "" {
+ return fmt.Errorf("xml: start tag with no name")
+ }
+
+ p.tags = append(p.tags, start.Name)
+ p.markPrefix()
+ // Define any name spaces explicitly declared in the attributes.
+ // We do this as a separate pass so that explicitly declared prefixes
+ // will take precedence over implicitly declared prefixes
+ // regardless of the order of the attributes.
+ ignoreNonEmptyDefault := start.Name.Space == ""
+ for _, attr := range start.Attr {
+ if err := p.defineNS(attr, ignoreNonEmptyDefault); err != nil {
+ return err
+ }
+ }
+ // Define any new name spaces implied by the attributes.
+ for _, attr := range start.Attr {
+ name := attr.Name
+ // From http://www.w3.org/TR/xml-names11/#defaulting
+ // "Default namespace declarations do not apply directly
+ // to attribute names; the interpretation of unprefixed
+ // attributes is determined by the element on which they
+ // appear."
+ // This means we don't need to create a new namespace
+ // when an attribute name space is empty.
+ if name.Space != "" && !name.isNamespace() {
+ p.createNSPrefix(name.Space, true)
+ }
+ }
+ p.createNSPrefix(start.Name.Space, false)
+
+ p.writeIndent(1)
+ p.WriteByte('<')
+ p.writeName(start.Name, false)
+ p.writeNamespaces()
+ for _, attr := range start.Attr {
+ name := attr.Name
+ if name.Local == "" || name.isNamespace() {
+ // Namespaces have already been written by writeNamespaces above.
+ continue
+ }
+ p.WriteByte(' ')
+ p.writeName(name, true)
+ p.WriteString(`="`)
+ p.EscapeString(attr.Value)
+ p.WriteByte('"')
+ }
+ p.WriteByte('>')
+ return nil
+}
+
+// writeName writes the given name. It assumes
+// that p.createNSPrefix(name) has already been called.
+func (p *printer) writeName(name Name, isAttr bool) {
+ if prefix := p.prefixForNS(name.Space, isAttr); prefix != "" {
+ p.WriteString(prefix)
+ p.WriteByte(':')
+ }
+ p.WriteString(name.Local)
+}
+
+func (p *printer) writeEnd(name Name) error {
+ if name.Local == "" {
+ return fmt.Errorf("xml: end tag with no name")
+ }
+ if len(p.tags) == 0 || p.tags[len(p.tags)-1].Local == "" {
+ return fmt.Errorf("xml: end tag </%s> without start tag", name.Local)
+ }
+ if top := p.tags[len(p.tags)-1]; top != name {
+ if top.Local != name.Local {
+ return fmt.Errorf("xml: end tag </%s> does not match start tag <%s>", name.Local, top.Local)
+ }
+ return fmt.Errorf("xml: end tag </%s> in namespace %s does not match start tag <%s> in namespace %s", name.Local, name.Space, top.Local, top.Space)
+ }
+ p.tags = p.tags[:len(p.tags)-1]
+
+ p.writeIndent(-1)
+ p.WriteByte('<')
+ p.WriteByte('/')
+ p.writeName(name, false)
+ p.WriteByte('>')
+ p.popPrefix()
+ return nil
+}
+
+func (p *printer) marshalSimple(typ reflect.Type, val reflect.Value) (string, []byte, error) {
+ switch val.Kind() {
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return strconv.FormatInt(val.Int(), 10), nil, nil
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ return strconv.FormatUint(val.Uint(), 10), nil, nil
+ case reflect.Float32, reflect.Float64:
+ return strconv.FormatFloat(val.Float(), 'g', -1, val.Type().Bits()), nil, nil
+ case reflect.String:
+ return val.String(), nil, nil
+ case reflect.Bool:
+ return strconv.FormatBool(val.Bool()), nil, nil
+ case reflect.Array:
+ if typ.Elem().Kind() != reflect.Uint8 {
+ break
+ }
+ // [...]byte
+ var bytes []byte
+ if val.CanAddr() {
+ bytes = val.Slice(0, val.Len()).Bytes()
+ } else {
+ bytes = make([]byte, val.Len())
+ reflect.Copy(reflect.ValueOf(bytes), val)
+ }
+ return "", bytes, nil
+ case reflect.Slice:
+ if typ.Elem().Kind() != reflect.Uint8 {
+ break
+ }
+ // []byte
+ return "", val.Bytes(), nil
+ }
+ return "", nil, &UnsupportedTypeError{typ}
+}
+
+var ddBytes = []byte("--")
+
+func (p *printer) marshalStruct(tinfo *typeInfo, val reflect.Value) error {
+ s := parentStack{p: p}
+ for i := range tinfo.fields {
+ finfo := &tinfo.fields[i]
+ if finfo.flags&fAttr != 0 {
+ continue
+ }
+ vf := finfo.value(val)
+
+ // Dereference or skip nil pointer, interface values.
+ switch vf.Kind() {
+ case reflect.Ptr, reflect.Interface:
+ if !vf.IsNil() {
+ vf = vf.Elem()
+ }
+ }
+
+ switch finfo.flags & fMode {
+ case fCharData:
+ if err := s.setParents(&noField, reflect.Value{}); err != nil {
+ return err
+ }
+ if vf.CanInterface() && vf.Type().Implements(textMarshalerType) {
+ data, err := vf.Interface().(encoding.TextMarshaler).MarshalText()
+ if err != nil {
+ return err
+ }
+ Escape(p, data)
+ continue
+ }
+ if vf.CanAddr() {
+ pv := vf.Addr()
+ if pv.CanInterface() && pv.Type().Implements(textMarshalerType) {
+ data, err := pv.Interface().(encoding.TextMarshaler).MarshalText()
+ if err != nil {
+ return err
+ }
+ Escape(p, data)
+ continue
+ }
+ }
+ var scratch [64]byte
+ switch vf.Kind() {
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ Escape(p, strconv.AppendInt(scratch[:0], vf.Int(), 10))
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ Escape(p, strconv.AppendUint(scratch[:0], vf.Uint(), 10))
+ case reflect.Float32, reflect.Float64:
+ Escape(p, strconv.AppendFloat(scratch[:0], vf.Float(), 'g', -1, vf.Type().Bits()))
+ case reflect.Bool:
+ Escape(p, strconv.AppendBool(scratch[:0], vf.Bool()))
+ case reflect.String:
+ if err := EscapeText(p, []byte(vf.String())); err != nil {
+ return err
+ }
+ case reflect.Slice:
+ if elem, ok := vf.Interface().([]byte); ok {
+ if err := EscapeText(p, elem); err != nil {
+ return err
+ }
+ }
+ }
+ continue
+
+ case fComment:
+ if err := s.setParents(&noField, reflect.Value{}); err != nil {
+ return err
+ }
+ k := vf.Kind()
+ if !(k == reflect.String || k == reflect.Slice && vf.Type().Elem().Kind() == reflect.Uint8) {
+ return fmt.Errorf("xml: bad type for comment field of %s", val.Type())
+ }
+ if vf.Len() == 0 {
+ continue
+ }
+ p.writeIndent(0)
+ p.WriteString("<!--")
+ dashDash := false
+ dashLast := false
+ switch k {
+ case reflect.String:
+ s := vf.String()
+ dashDash = strings.Index(s, "--") >= 0
+ dashLast = s[len(s)-1] == '-'
+ if !dashDash {
+ p.WriteString(s)
+ }
+ case reflect.Slice:
+ b := vf.Bytes()
+ dashDash = bytes.Index(b, ddBytes) >= 0
+ dashLast = b[len(b)-1] == '-'
+ if !dashDash {
+ p.Write(b)
+ }
+ default:
+ panic("can't happen")
+ }
+ if dashDash {
+ return fmt.Errorf(`xml: comments must not contain "--"`)
+ }
+ if dashLast {
+ // "--->" is invalid grammar. Make it "- -->"
+ p.WriteByte(' ')
+ }
+ p.WriteString("-->")
+ continue
+
+ case fInnerXml:
+ iface := vf.Interface()
+ switch raw := iface.(type) {
+ case []byte:
+ p.Write(raw)
+ continue
+ case string:
+ p.WriteString(raw)
+ continue
+ }
+
+ case fElement, fElement | fAny:
+ if err := s.setParents(finfo, vf); err != nil {
+ return err
+ }
+ }
+ if err := p.marshalValue(vf, finfo, nil); err != nil {
+ return err
+ }
+ }
+ if err := s.setParents(&noField, reflect.Value{}); err != nil {
+ return err
+ }
+ return p.cachedWriteError()
+}
+
+var noField fieldInfo
+
+// return the bufio Writer's cached write error
+func (p *printer) cachedWriteError() error {
+ _, err := p.Write(nil)
+ return err
+}
+
+func (p *printer) writeIndent(depthDelta int) {
+ if len(p.prefix) == 0 && len(p.indent) == 0 {
+ return
+ }
+ if depthDelta < 0 {
+ p.depth--
+ if p.indentedIn {
+ p.indentedIn = false
+ return
+ }
+ p.indentedIn = false
+ }
+ if p.putNewline {
+ p.WriteByte('\n')
+ } else {
+ p.putNewline = true
+ }
+ if len(p.prefix) > 0 {
+ p.WriteString(p.prefix)
+ }
+ if len(p.indent) > 0 {
+ for i := 0; i < p.depth; i++ {
+ p.WriteString(p.indent)
+ }
+ }
+ if depthDelta > 0 {
+ p.depth++
+ p.indentedIn = true
+ }
+}
+
+type parentStack struct {
+ p *printer
+ xmlns string
+ parents []string
+}
+
+// setParents sets the stack of current parents to those found in finfo.
+// It only writes the start elements if vf holds a non-nil value.
+// If finfo is &noField, it pops all elements.
+func (s *parentStack) setParents(finfo *fieldInfo, vf reflect.Value) error {
+ xmlns := s.p.defaultNS
+ if finfo.xmlns != "" {
+ xmlns = finfo.xmlns
+ }
+ commonParents := 0
+ if xmlns == s.xmlns {
+ for ; commonParents < len(finfo.parents) && commonParents < len(s.parents); commonParents++ {
+ if finfo.parents[commonParents] != s.parents[commonParents] {
+ break
+ }
+ }
+ }
+ // Pop off any parents that aren't in common with the previous field.
+ for i := len(s.parents) - 1; i >= commonParents; i-- {
+ if err := s.p.writeEnd(Name{
+ Space: s.xmlns,
+ Local: s.parents[i],
+ }); err != nil {
+ return err
+ }
+ }
+ s.parents = finfo.parents
+ s.xmlns = xmlns
+ if commonParents >= len(s.parents) {
+ // No new elements to push.
+ return nil
+ }
+ if (vf.Kind() == reflect.Ptr || vf.Kind() == reflect.Interface) && vf.IsNil() {
+ // The element is nil, so no need for the start elements.
+ s.parents = s.parents[:commonParents]
+ return nil
+ }
+ // Push any new parents required.
+ for _, name := range s.parents[commonParents:] {
+ start := &StartElement{
+ Name: Name{
+ Space: s.xmlns,
+ Local: name,
+ },
+ }
+ // Set the default name space for parent elements
+ // to match what we do with other elements.
+ if s.xmlns != s.p.defaultNS {
+ start.setDefaultNamespace()
+ }
+ if err := s.p.writeStart(start); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// A MarshalXMLError is returned when Marshal encounters a type
+// that cannot be converted into XML.
+type UnsupportedTypeError struct {
+ Type reflect.Type
+}
+
+func (e *UnsupportedTypeError) Error() string {
+ return "xml: unsupported type: " + e.Type.String()
+}
+
+func isEmptyValue(v reflect.Value) bool {
+ switch v.Kind() {
+ case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
+ return v.Len() == 0
+ case reflect.Bool:
+ return !v.Bool()
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return v.Int() == 0
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ return v.Uint() == 0
+ case reflect.Float32, reflect.Float64:
+ return v.Float() == 0
+ case reflect.Interface, reflect.Ptr:
+ return v.IsNil()
+ }
+ return false
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/internal/xml/marshal_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/internal/xml/marshal_test.go
new file mode 100644
index 000000000..226cfd013
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/internal/xml/marshal_test.go
@@ -0,0 +1,1939 @@
+// Copyright 2011 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 xml
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "io"
+ "reflect"
+ "strconv"
+ "strings"
+ "sync"
+ "testing"
+ "time"
+)
+
+type DriveType int
+
+const (
+ HyperDrive DriveType = iota
+ ImprobabilityDrive
+)
+
+type Passenger struct {
+ Name []string `xml:"name"`
+ Weight float32 `xml:"weight"`
+}
+
+type Ship struct {
+ XMLName struct{} `xml:"spaceship"`
+
+ Name string `xml:"name,attr"`
+ Pilot string `xml:"pilot,attr"`
+ Drive DriveType `xml:"drive"`
+ Age uint `xml:"age"`
+ Passenger []*Passenger `xml:"passenger"`
+ secret string
+}
+
+type NamedType string
+
+type Port struct {
+ XMLName struct{} `xml:"port"`
+ Type string `xml:"type,attr,omitempty"`
+ Comment string `xml:",comment"`
+ Number string `xml:",chardata"`
+}
+
+type Domain struct {
+ XMLName struct{} `xml:"domain"`
+ Country string `xml:",attr,omitempty"`
+ Name []byte `xml:",chardata"`
+ Comment []byte `xml:",comment"`
+}
+
+type Book struct {
+ XMLName struct{} `xml:"book"`
+ Title string `xml:",chardata"`
+}
+
+type Event struct {
+ XMLName struct{} `xml:"event"`
+ Year int `xml:",chardata"`
+}
+
+type Movie struct {
+ XMLName struct{} `xml:"movie"`
+ Length uint `xml:",chardata"`
+}
+
+type Pi struct {
+ XMLName struct{} `xml:"pi"`
+ Approximation float32 `xml:",chardata"`
+}
+
+type Universe struct {
+ XMLName struct{} `xml:"universe"`
+ Visible float64 `xml:",chardata"`
+}
+
+type Particle struct {
+ XMLName struct{} `xml:"particle"`
+ HasMass bool `xml:",chardata"`
+}
+
+type Departure struct {
+ XMLName struct{} `xml:"departure"`
+ When time.Time `xml:",chardata"`
+}
+
+type SecretAgent struct {
+ XMLName struct{} `xml:"agent"`
+ Handle string `xml:"handle,attr"`
+ Identity string
+ Obfuscate string `xml:",innerxml"`
+}
+
+type NestedItems struct {
+ XMLName struct{} `xml:"result"`
+ Items []string `xml:">item"`
+ Item1 []string `xml:"Items>item1"`
+}
+
+type NestedOrder struct {
+ XMLName struct{} `xml:"result"`
+ Field1 string `xml:"parent>c"`
+ Field2 string `xml:"parent>b"`
+ Field3 string `xml:"parent>a"`
+}
+
+type MixedNested struct {
+ XMLName struct{} `xml:"result"`
+ A string `xml:"parent1>a"`
+ B string `xml:"b"`
+ C string `xml:"parent1>parent2>c"`
+ D string `xml:"parent1>d"`
+}
+
+type NilTest struct {
+ A interface{} `xml:"parent1>parent2>a"`
+ B interface{} `xml:"parent1>b"`
+ C interface{} `xml:"parent1>parent2>c"`
+}
+
+type Service struct {
+ XMLName struct{} `xml:"service"`
+ Domain *Domain `xml:"host>domain"`
+ Port *Port `xml:"host>port"`
+ Extra1 interface{}
+ Extra2 interface{} `xml:"host>extra2"`
+}
+
+var nilStruct *Ship
+
+type EmbedA struct {
+ EmbedC
+ EmbedB EmbedB
+ FieldA string
+}
+
+type EmbedB struct {
+ FieldB string
+ *EmbedC
+}
+
+type EmbedC struct {
+ FieldA1 string `xml:"FieldA>A1"`
+ FieldA2 string `xml:"FieldA>A2"`
+ FieldB string
+ FieldC string
+}
+
+type NameCasing struct {
+ XMLName struct{} `xml:"casing"`
+ Xy string
+ XY string
+ XyA string `xml:"Xy,attr"`
+ XYA string `xml:"XY,attr"`
+}
+
+type NamePrecedence struct {
+ XMLName Name `xml:"Parent"`
+ FromTag XMLNameWithoutTag `xml:"InTag"`
+ FromNameVal XMLNameWithoutTag
+ FromNameTag XMLNameWithTag
+ InFieldName string
+}
+
+type XMLNameWithTag struct {
+ XMLName Name `xml:"InXMLNameTag"`
+ Value string `xml:",chardata"`
+}
+
+type XMLNameWithNSTag struct {
+ XMLName Name `xml:"ns InXMLNameWithNSTag"`
+ Value string `xml:",chardata"`
+}
+
+type XMLNameWithoutTag struct {
+ XMLName Name
+ Value string `xml:",chardata"`
+}
+
+type NameInField struct {
+ Foo Name `xml:"ns foo"`
+}
+
+type AttrTest struct {
+ Int int `xml:",attr"`
+ Named int `xml:"int,attr"`
+ Float float64 `xml:",attr"`
+ Uint8 uint8 `xml:",attr"`
+ Bool bool `xml:",attr"`
+ Str string `xml:",attr"`
+ Bytes []byte `xml:",attr"`
+}
+
+type OmitAttrTest struct {
+ Int int `xml:",attr,omitempty"`
+ Named int `xml:"int,attr,omitempty"`
+ Float float64 `xml:",attr,omitempty"`
+ Uint8 uint8 `xml:",attr,omitempty"`
+ Bool bool `xml:",attr,omitempty"`
+ Str string `xml:",attr,omitempty"`
+ Bytes []byte `xml:",attr,omitempty"`
+}
+
+type OmitFieldTest struct {
+ Int int `xml:",omitempty"`
+ Named int `xml:"int,omitempty"`
+ Float float64 `xml:",omitempty"`
+ Uint8 uint8 `xml:",omitempty"`
+ Bool bool `xml:",omitempty"`
+ Str string `xml:",omitempty"`
+ Bytes []byte `xml:",omitempty"`
+ Ptr *PresenceTest `xml:",omitempty"`
+}
+
+type AnyTest struct {
+ XMLName struct{} `xml:"a"`
+ Nested string `xml:"nested>value"`
+ AnyField AnyHolder `xml:",any"`
+}
+
+type AnyOmitTest struct {
+ XMLName struct{} `xml:"a"`
+ Nested string `xml:"nested>value"`
+ AnyField *AnyHolder `xml:",any,omitempty"`
+}
+
+type AnySliceTest struct {
+ XMLName struct{} `xml:"a"`
+ Nested string `xml:"nested>value"`
+ AnyField []AnyHolder `xml:",any"`
+}
+
+type AnyHolder struct {
+ XMLName Name
+ XML string `xml:",innerxml"`
+}
+
+type RecurseA struct {
+ A string
+ B *RecurseB
+}
+
+type RecurseB struct {
+ A *RecurseA
+ B string
+}
+
+type PresenceTest struct {
+ Exists *struct{}
+}
+
+type IgnoreTest struct {
+ PublicSecret string `xml:"-"`
+}
+
+type MyBytes []byte
+
+type Data struct {
+ Bytes []byte
+ Attr []byte `xml:",attr"`
+ Custom MyBytes
+}
+
+type Plain struct {
+ V interface{}
+}
+
+type MyInt int
+
+type EmbedInt struct {
+ MyInt
+}
+
+type Strings struct {
+ X []string `xml:"A>B,omitempty"`
+}
+
+type PointerFieldsTest struct {
+ XMLName Name `xml:"dummy"`
+ Name *string `xml:"name,attr"`
+ Age *uint `xml:"age,attr"`
+ Empty *string `xml:"empty,attr"`
+ Contents *string `xml:",chardata"`
+}
+
+type ChardataEmptyTest struct {
+ XMLName Name `xml:"test"`
+ Contents *string `xml:",chardata"`
+}
+
+type MyMarshalerTest struct {
+}
+
+var _ Marshaler = (*MyMarshalerTest)(nil)
+
+func (m *MyMarshalerTest) MarshalXML(e *Encoder, start StartElement) error {
+ e.EncodeToken(start)
+ e.EncodeToken(CharData([]byte("hello world")))
+ e.EncodeToken(EndElement{start.Name})
+ return nil
+}
+
+type MyMarshalerAttrTest struct{}
+
+var _ MarshalerAttr = (*MyMarshalerAttrTest)(nil)
+
+func (m *MyMarshalerAttrTest) MarshalXMLAttr(name Name) (Attr, error) {
+ return Attr{name, "hello world"}, nil
+}
+
+type MyMarshalerValueAttrTest struct{}
+
+var _ MarshalerAttr = MyMarshalerValueAttrTest{}
+
+func (m MyMarshalerValueAttrTest) MarshalXMLAttr(name Name) (Attr, error) {
+ return Attr{name, "hello world"}, nil
+}
+
+type MarshalerStruct struct {
+ Foo MyMarshalerAttrTest `xml:",attr"`
+}
+
+type MarshalerValueStruct struct {
+ Foo MyMarshalerValueAttrTest `xml:",attr"`
+}
+
+type InnerStruct struct {
+ XMLName Name `xml:"testns outer"`
+}
+
+type OuterStruct struct {
+ InnerStruct
+ IntAttr int `xml:"int,attr"`
+}
+
+type OuterNamedStruct struct {
+ InnerStruct
+ XMLName Name `xml:"outerns test"`
+ IntAttr int `xml:"int,attr"`
+}
+
+type OuterNamedOrderedStruct struct {
+ XMLName Name `xml:"outerns test"`
+ InnerStruct
+ IntAttr int `xml:"int,attr"`
+}
+
+type OuterOuterStruct struct {
+ OuterStruct
+}
+
+type NestedAndChardata struct {
+ AB []string `xml:"A>B"`
+ Chardata string `xml:",chardata"`
+}
+
+type NestedAndComment struct {
+ AB []string `xml:"A>B"`
+ Comment string `xml:",comment"`
+}
+
+type XMLNSFieldStruct struct {
+ Ns string `xml:"xmlns,attr"`
+ Body string
+}
+
+type NamedXMLNSFieldStruct struct {
+ XMLName struct{} `xml:"testns test"`
+ Ns string `xml:"xmlns,attr"`
+ Body string
+}
+
+type XMLNSFieldStructWithOmitEmpty struct {
+ Ns string `xml:"xmlns,attr,omitempty"`
+ Body string
+}
+
+type NamedXMLNSFieldStructWithEmptyNamespace struct {
+ XMLName struct{} `xml:"test"`
+ Ns string `xml:"xmlns,attr"`
+ Body string
+}
+
+type RecursiveXMLNSFieldStruct struct {
+ Ns string `xml:"xmlns,attr"`
+ Body *RecursiveXMLNSFieldStruct `xml:",omitempty"`
+ Text string `xml:",omitempty"`
+}
+
+func ifaceptr(x interface{}) interface{} {
+ return &x
+}
+
+var (
+ nameAttr = "Sarah"
+ ageAttr = uint(12)
+ contentsAttr = "lorem ipsum"
+)
+
+// Unless explicitly stated as such (or *Plain), all of the
+// tests below are two-way tests. When introducing new tests,
+// please try to make them two-way as well to ensure that
+// marshalling and unmarshalling are as symmetrical as feasible.
+var marshalTests = []struct {
+ Value interface{}
+ ExpectXML string
+ MarshalOnly bool
+ UnmarshalOnly bool
+}{
+ // Test nil marshals to nothing
+ {Value: nil, ExpectXML: ``, MarshalOnly: true},
+ {Value: nilStruct, ExpectXML: ``, MarshalOnly: true},
+
+ // Test value types
+ {Value: &Plain{true}, ExpectXML: `<Plain><V>true</V></Plain>`},
+ {Value: &Plain{false}, ExpectXML: `<Plain><V>false</V></Plain>`},
+ {Value: &Plain{int(42)}, ExpectXML: `<Plain><V>42</V></Plain>`},
+ {Value: &Plain{int8(42)}, ExpectXML: `<Plain><V>42</V></Plain>`},
+ {Value: &Plain{int16(42)}, ExpectXML: `<Plain><V>42</V></Plain>`},
+ {Value: &Plain{int32(42)}, ExpectXML: `<Plain><V>42</V></Plain>`},
+ {Value: &Plain{uint(42)}, ExpectXML: `<Plain><V>42</V></Plain>`},
+ {Value: &Plain{uint8(42)}, ExpectXML: `<Plain><V>42</V></Plain>`},
+ {Value: &Plain{uint16(42)}, ExpectXML: `<Plain><V>42</V></Plain>`},
+ {Value: &Plain{uint32(42)}, ExpectXML: `<Plain><V>42</V></Plain>`},
+ {Value: &Plain{float32(1.25)}, ExpectXML: `<Plain><V>1.25</V></Plain>`},
+ {Value: &Plain{float64(1.25)}, ExpectXML: `<Plain><V>1.25</V></Plain>`},
+ {Value: &Plain{uintptr(0xFFDD)}, ExpectXML: `<Plain><V>65501</V></Plain>`},
+ {Value: &Plain{"gopher"}, ExpectXML: `<Plain><V>gopher</V></Plain>`},
+ {Value: &Plain{[]byte("gopher")}, ExpectXML: `<Plain><V>gopher</V></Plain>`},
+ {Value: &Plain{"</>"}, ExpectXML: `<Plain><V>&lt;/&gt;</V></Plain>`},
+ {Value: &Plain{[]byte("</>")}, ExpectXML: `<Plain><V>&lt;/&gt;</V></Plain>`},
+ {Value: &Plain{[3]byte{'<', '/', '>'}}, ExpectXML: `<Plain><V>&lt;/&gt;</V></Plain>`},
+ {Value: &Plain{NamedType("potato")}, ExpectXML: `<Plain><V>potato</V></Plain>`},
+ {Value: &Plain{[]int{1, 2, 3}}, ExpectXML: `<Plain><V>1</V><V>2</V><V>3</V></Plain>`},
+ {Value: &Plain{[3]int{1, 2, 3}}, ExpectXML: `<Plain><V>1</V><V>2</V><V>3</V></Plain>`},
+ {Value: ifaceptr(true), MarshalOnly: true, ExpectXML: `<bool>true</bool>`},
+
+ // Test time.
+ {
+ Value: &Plain{time.Unix(1e9, 123456789).UTC()},
+ ExpectXML: `<Plain><V>2001-09-09T01:46:40.123456789Z</V></Plain>`,
+ },
+
+ // A pointer to struct{} may be used to test for an element's presence.
+ {
+ Value: &PresenceTest{new(struct{})},
+ ExpectXML: `<PresenceTest><Exists></Exists></PresenceTest>`,
+ },
+ {
+ Value: &PresenceTest{},
+ ExpectXML: `<PresenceTest></PresenceTest>`,
+ },
+
+ // A pointer to struct{} may be used to test for an element's presence.
+ {
+ Value: &PresenceTest{new(struct{})},
+ ExpectXML: `<PresenceTest><Exists></Exists></PresenceTest>`,
+ },
+ {
+ Value: &PresenceTest{},
+ ExpectXML: `<PresenceTest></PresenceTest>`,
+ },
+
+ // A []byte field is only nil if the element was not found.
+ {
+ Value: &Data{},
+ ExpectXML: `<Data></Data>`,
+ UnmarshalOnly: true,
+ },
+ {
+ Value: &Data{Bytes: []byte{}, Custom: MyBytes{}, Attr: []byte{}},
+ ExpectXML: `<Data Attr=""><Bytes></Bytes><Custom></Custom></Data>`,
+ UnmarshalOnly: true,
+ },
+
+ // Check that []byte works, including named []byte types.
+ {
+ Value: &Data{Bytes: []byte("ab"), Custom: MyBytes("cd"), Attr: []byte{'v'}},
+ ExpectXML: `<Data Attr="v"><Bytes>ab</Bytes><Custom>cd</Custom></Data>`,
+ },
+
+ // Test innerxml
+ {
+ Value: &SecretAgent{
+ Handle: "007",
+ Identity: "James Bond",
+ Obfuscate: "<redacted/>",
+ },
+ ExpectXML: `<agent handle="007"><Identity>James Bond</Identity><redacted/></agent>`,
+ MarshalOnly: true,
+ },
+ {
+ Value: &SecretAgent{
+ Handle: "007",
+ Identity: "James Bond",
+ Obfuscate: "<Identity>James Bond</Identity><redacted/>",
+ },
+ ExpectXML: `<agent handle="007"><Identity>James Bond</Identity><redacted/></agent>`,
+ UnmarshalOnly: true,
+ },
+
+ // Test structs
+ {Value: &Port{Type: "ssl", Number: "443"}, ExpectXML: `<port type="ssl">443</port>`},
+ {Value: &Port{Number: "443"}, ExpectXML: `<port>443</port>`},
+ {Value: &Port{Type: "<unix>"}, ExpectXML: `<port type="&lt;unix&gt;"></port>`},
+ {Value: &Port{Number: "443", Comment: "https"}, ExpectXML: `<port><!--https-->443</port>`},
+ {Value: &Port{Number: "443", Comment: "add space-"}, ExpectXML: `<port><!--add space- -->443</port>`, MarshalOnly: true},
+ {Value: &Domain{Name: []byte("google.com&friends")}, ExpectXML: `<domain>google.com&amp;friends</domain>`},
+ {Value: &Domain{Name: []byte("google.com"), Comment: []byte(" &friends ")}, ExpectXML: `<domain>google.com<!-- &friends --></domain>`},
+ {Value: &Book{Title: "Pride & Prejudice"}, ExpectXML: `<book>Pride &amp; Prejudice</book>`},
+ {Value: &Event{Year: -3114}, ExpectXML: `<event>-3114</event>`},
+ {Value: &Movie{Length: 13440}, ExpectXML: `<movie>13440</movie>`},
+ {Value: &Pi{Approximation: 3.14159265}, ExpectXML: `<pi>3.1415927</pi>`},
+ {Value: &Universe{Visible: 9.3e13}, ExpectXML: `<universe>9.3e+13</universe>`},
+ {Value: &Particle{HasMass: true}, ExpectXML: `<particle>true</particle>`},
+ {Value: &Departure{When: ParseTime("2013-01-09T00:15:00-09:00")}, ExpectXML: `<departure>2013-01-09T00:15:00-09:00</departure>`},
+ {Value: atomValue, ExpectXML: atomXml},
+ {
+ Value: &Ship{
+ Name: "Heart of Gold",
+ Pilot: "Computer",
+ Age: 1,
+ Drive: ImprobabilityDrive,
+ Passenger: []*Passenger{
+ {
+ Name: []string{"Zaphod", "Beeblebrox"},
+ Weight: 7.25,
+ },
+ {
+ Name: []string{"Trisha", "McMillen"},
+ Weight: 5.5,
+ },
+ {
+ Name: []string{"Ford", "Prefect"},
+ Weight: 7,
+ },
+ {
+ Name: []string{"Arthur", "Dent"},
+ Weight: 6.75,
+ },
+ },
+ },
+ ExpectXML: `<spaceship name="Heart of Gold" pilot="Computer">` +
+ `<drive>` + strconv.Itoa(int(ImprobabilityDrive)) + `</drive>` +
+ `<age>1</age>` +
+ `<passenger>` +
+ `<name>Zaphod</name>` +
+ `<name>Beeblebrox</name>` +
+ `<weight>7.25</weight>` +
+ `</passenger>` +
+ `<passenger>` +
+ `<name>Trisha</name>` +
+ `<name>McMillen</name>` +
+ `<weight>5.5</weight>` +
+ `</passenger>` +
+ `<passenger>` +
+ `<name>Ford</name>` +
+ `<name>Prefect</name>` +
+ `<weight>7</weight>` +
+ `</passenger>` +
+ `<passenger>` +
+ `<name>Arthur</name>` +
+ `<name>Dent</name>` +
+ `<weight>6.75</weight>` +
+ `</passenger>` +
+ `</spaceship>`,
+ },
+
+ // Test a>b
+ {
+ Value: &NestedItems{Items: nil, Item1: nil},
+ ExpectXML: `<result>` +
+ `<Items>` +
+ `</Items>` +
+ `</result>`,
+ },
+ {
+ Value: &NestedItems{Items: []string{}, Item1: []string{}},
+ ExpectXML: `<result>` +
+ `<Items>` +
+ `</Items>` +
+ `</result>`,
+ MarshalOnly: true,
+ },
+ {
+ Value: &NestedItems{Items: nil, Item1: []string{"A"}},
+ ExpectXML: `<result>` +
+ `<Items>` +
+ `<item1>A</item1>` +
+ `</Items>` +
+ `</result>`,
+ },
+ {
+ Value: &NestedItems{Items: []string{"A", "B"}, Item1: nil},
+ ExpectXML: `<result>` +
+ `<Items>` +
+ `<item>A</item>` +
+ `<item>B</item>` +
+ `</Items>` +
+ `</result>`,
+ },
+ {
+ Value: &NestedItems{Items: []string{"A", "B"}, Item1: []string{"C"}},
+ ExpectXML: `<result>` +
+ `<Items>` +
+ `<item>A</item>` +
+ `<item>B</item>` +
+ `<item1>C</item1>` +
+ `</Items>` +
+ `</result>`,
+ },
+ {
+ Value: &NestedOrder{Field1: "C", Field2: "B", Field3: "A"},
+ ExpectXML: `<result>` +
+ `<parent>` +
+ `<c>C</c>` +
+ `<b>B</b>` +
+ `<a>A</a>` +
+ `</parent>` +
+ `</result>`,
+ },
+ {
+ Value: &NilTest{A: "A", B: nil, C: "C"},
+ ExpectXML: `<NilTest>` +
+ `<parent1>` +
+ `<parent2><a>A</a></parent2>` +
+ `<parent2><c>C</c></parent2>` +
+ `</parent1>` +
+ `</NilTest>`,
+ MarshalOnly: true, // Uses interface{}
+ },
+ {
+ Value: &MixedNested{A: "A", B: "B", C: "C", D: "D"},
+ ExpectXML: `<result>` +
+ `<parent1><a>A</a></parent1>` +
+ `<b>B</b>` +
+ `<parent1>` +
+ `<parent2><c>C</c></parent2>` +
+ `<d>D</d>` +
+ `</parent1>` +
+ `</result>`,
+ },
+ {
+ Value: &Service{Port: &Port{Number: "80"}},
+ ExpectXML: `<service><host><port>80</port></host></service>`,
+ },
+ {
+ Value: &Service{},
+ ExpectXML: `<service></service>`,
+ },
+ {
+ Value: &Service{Port: &Port{Number: "80"}, Extra1: "A", Extra2: "B"},
+ ExpectXML: `<service>` +
+ `<host><port>80</port></host>` +
+ `<Extra1>A</Extra1>` +
+ `<host><extra2>B</extra2></host>` +
+ `</service>`,
+ MarshalOnly: true,
+ },
+ {
+ Value: &Service{Port: &Port{Number: "80"}, Extra2: "example"},
+ ExpectXML: `<service>` +
+ `<host><port>80</port></host>` +
+ `<host><extra2>example</extra2></host>` +
+ `</service>`,
+ MarshalOnly: true,
+ },
+ {
+ Value: &struct {
+ XMLName struct{} `xml:"space top"`
+ A string `xml:"x>a"`
+ B string `xml:"x>b"`
+ C string `xml:"space x>c"`
+ C1 string `xml:"space1 x>c"`
+ D1 string `xml:"space1 x>d"`
+ E1 string `xml:"x>e"`
+ }{
+ A: "a",
+ B: "b",
+ C: "c",
+ C1: "c1",
+ D1: "d1",
+ E1: "e1",
+ },
+ ExpectXML: `<top xmlns="space">` +
+ `<x><a>a</a><b>b</b><c>c</c></x>` +
+ `<x xmlns="space1">` +
+ `<c>c1</c>` +
+ `<d>d1</d>` +
+ `</x>` +
+ `<x>` +
+ `<e>e1</e>` +
+ `</x>` +
+ `</top>`,
+ },
+ {
+ Value: &struct {
+ XMLName Name
+ A string `xml:"x>a"`
+ B string `xml:"x>b"`
+ C string `xml:"space x>c"`
+ C1 string `xml:"space1 x>c"`
+ D1 string `xml:"space1 x>d"`
+ }{
+ XMLName: Name{
+ Space: "space0",
+ Local: "top",
+ },
+ A: "a",
+ B: "b",
+ C: "c",
+ C1: "c1",
+ D1: "d1",
+ },
+ ExpectXML: `<top xmlns="space0">` +
+ `<x><a>a</a><b>b</b></x>` +
+ `<x xmlns="space"><c>c</c></x>` +
+ `<x xmlns="space1">` +
+ `<c>c1</c>` +
+ `<d>d1</d>` +
+ `</x>` +
+ `</top>`,
+ },
+ {
+ Value: &struct {
+ XMLName struct{} `xml:"top"`
+ B string `xml:"space x>b"`
+ B1 string `xml:"space1 x>b"`
+ }{
+ B: "b",
+ B1: "b1",
+ },
+ ExpectXML: `<top>` +
+ `<x xmlns="space"><b>b</b></x>` +
+ `<x xmlns="space1"><b>b1</b></x>` +
+ `</top>`,
+ },
+
+ // Test struct embedding
+ {
+ Value: &EmbedA{
+ EmbedC: EmbedC{
+ FieldA1: "", // Shadowed by A.A
+ FieldA2: "", // Shadowed by A.A
+ FieldB: "A.C.B",
+ FieldC: "A.C.C",
+ },
+ EmbedB: EmbedB{
+ FieldB: "A.B.B",
+ EmbedC: &EmbedC{
+ FieldA1: "A.B.C.A1",
+ FieldA2: "A.B.C.A2",
+ FieldB: "", // Shadowed by A.B.B
+ FieldC: "A.B.C.C",
+ },
+ },
+ FieldA: "A.A",
+ },
+ ExpectXML: `<EmbedA>` +
+ `<FieldB>A.C.B</FieldB>` +
+ `<FieldC>A.C.C</FieldC>` +
+ `<EmbedB>` +
+ `<FieldB>A.B.B</FieldB>` +
+ `<FieldA>` +
+ `<A1>A.B.C.A1</A1>` +
+ `<A2>A.B.C.A2</A2>` +
+ `</FieldA>` +
+ `<FieldC>A.B.C.C</FieldC>` +
+ `</EmbedB>` +
+ `<FieldA>A.A</FieldA>` +
+ `</EmbedA>`,
+ },
+
+ // Test that name casing matters
+ {
+ Value: &NameCasing{Xy: "mixed", XY: "upper", XyA: "mixedA", XYA: "upperA"},
+ ExpectXML: `<casing Xy="mixedA" XY="upperA"><Xy>mixed</Xy><XY>upper</XY></casing>`,
+ },
+
+ // Test the order in which the XML element name is chosen
+ {
+ Value: &NamePrecedence{
+ FromTag: XMLNameWithoutTag{Value: "A"},
+ FromNameVal: XMLNameWithoutTag{XMLName: Name{Local: "InXMLName"}, Value: "B"},
+ FromNameTag: XMLNameWithTag{Value: "C"},
+ InFieldName: "D",
+ },
+ ExpectXML: `<Parent>` +
+ `<InTag>A</InTag>` +
+ `<InXMLName>B</InXMLName>` +
+ `<InXMLNameTag>C</InXMLNameTag>` +
+ `<InFieldName>D</InFieldName>` +
+ `</Parent>`,
+ MarshalOnly: true,
+ },
+ {
+ Value: &NamePrecedence{
+ XMLName: Name{Local: "Parent"},
+ FromTag: XMLNameWithoutTag{XMLName: Name{Local: "InTag"}, Value: "A"},
+ FromNameVal: XMLNameWithoutTag{XMLName: Name{Local: "FromNameVal"}, Value: "B"},
+ FromNameTag: XMLNameWithTag{XMLName: Name{Local: "InXMLNameTag"}, Value: "C"},
+ InFieldName: "D",
+ },
+ ExpectXML: `<Parent>` +
+ `<InTag>A</InTag>` +
+ `<FromNameVal>B</FromNameVal>` +
+ `<InXMLNameTag>C</InXMLNameTag>` +
+ `<InFieldName>D</InFieldName>` +
+ `</Parent>`,
+ UnmarshalOnly: true,
+ },
+
+ // xml.Name works in a plain field as well.
+ {
+ Value: &NameInField{Name{Space: "ns", Local: "foo"}},
+ ExpectXML: `<NameInField><foo xmlns="ns"></foo></NameInField>`,
+ },
+ {
+ Value: &NameInField{Name{Space: "ns", Local: "foo"}},
+ ExpectXML: `<NameInField><foo xmlns="ns"><ignore></ignore></foo></NameInField>`,
+ UnmarshalOnly: true,
+ },
+
+ // Marshaling zero xml.Name uses the tag or field name.
+ {
+ Value: &NameInField{},
+ ExpectXML: `<NameInField><foo xmlns="ns"></foo></NameInField>`,
+ MarshalOnly: true,
+ },
+
+ // Test attributes
+ {
+ Value: &AttrTest{
+ Int: 8,
+ Named: 9,
+ Float: 23.5,
+ Uint8: 255,
+ Bool: true,
+ Str: "str",
+ Bytes: []byte("byt"),
+ },
+ ExpectXML: `<AttrTest Int="8" int="9" Float="23.5" Uint8="255"` +
+ ` Bool="true" Str="str" Bytes="byt"></AttrTest>`,
+ },
+ {
+ Value: &AttrTest{Bytes: []byte{}},
+ ExpectXML: `<AttrTest Int="0" int="0" Float="0" Uint8="0"` +
+ ` Bool="false" Str="" Bytes=""></AttrTest>`,
+ },
+ {
+ Value: &OmitAttrTest{
+ Int: 8,
+ Named: 9,
+ Float: 23.5,
+ Uint8: 255,
+ Bool: true,
+ Str: "str",
+ Bytes: []byte("byt"),
+ },
+ ExpectXML: `<OmitAttrTest Int="8" int="9" Float="23.5" Uint8="255"` +
+ ` Bool="true" Str="str" Bytes="byt"></OmitAttrTest>`,
+ },
+ {
+ Value: &OmitAttrTest{},
+ ExpectXML: `<OmitAttrTest></OmitAttrTest>`,
+ },
+
+ // pointer fields
+ {
+ Value: &PointerFieldsTest{Name: &nameAttr, Age: &ageAttr, Contents: &contentsAttr},
+ ExpectXML: `<dummy name="Sarah" age="12">lorem ipsum</dummy>`,
+ MarshalOnly: true,
+ },
+
+ // empty chardata pointer field
+ {
+ Value: &ChardataEmptyTest{},
+ ExpectXML: `<test></test>`,
+ MarshalOnly: true,
+ },
+
+ // omitempty on fields
+ {
+ Value: &OmitFieldTest{
+ Int: 8,
+ Named: 9,
+ Float: 23.5,
+ Uint8: 255,
+ Bool: true,
+ Str: "str",
+ Bytes: []byte("byt"),
+ Ptr: &PresenceTest{},
+ },
+ ExpectXML: `<OmitFieldTest>` +
+ `<Int>8</Int>` +
+ `<int>9</int>` +
+ `<Float>23.5</Float>` +
+ `<Uint8>255</Uint8>` +
+ `<Bool>true</Bool>` +
+ `<Str>str</Str>` +
+ `<Bytes>byt</Bytes>` +
+ `<Ptr></Ptr>` +
+ `</OmitFieldTest>`,
+ },
+ {
+ Value: &OmitFieldTest{},
+ ExpectXML: `<OmitFieldTest></OmitFieldTest>`,
+ },
+
+ // Test ",any"
+ {
+ ExpectXML: `<a><nested><value>known</value></nested><other><sub>unknown</sub></other></a>`,
+ Value: &AnyTest{
+ Nested: "known",
+ AnyField: AnyHolder{
+ XMLName: Name{Local: "other"},
+ XML: "<sub>unknown</sub>",
+ },
+ },
+ },
+ {
+ Value: &AnyTest{Nested: "known",
+ AnyField: AnyHolder{
+ XML: "<unknown/>",
+ XMLName: Name{Local: "AnyField"},
+ },
+ },
+ ExpectXML: `<a><nested><value>known</value></nested><AnyField><unknown/></AnyField></a>`,
+ },
+ {
+ ExpectXML: `<a><nested><value>b</value></nested></a>`,
+ Value: &AnyOmitTest{
+ Nested: "b",
+ },
+ },
+ {
+ ExpectXML: `<a><nested><value>b</value></nested><c><d>e</d></c><g xmlns="f"><h>i</h></g></a>`,
+ Value: &AnySliceTest{
+ Nested: "b",
+ AnyField: []AnyHolder{
+ {
+ XMLName: Name{Local: "c"},
+ XML: "<d>e</d>",
+ },
+ {
+ XMLName: Name{Space: "f", Local: "g"},
+ XML: "<h>i</h>",
+ },
+ },
+ },
+ },
+ {
+ ExpectXML: `<a><nested><value>b</value></nested></a>`,
+ Value: &AnySliceTest{
+ Nested: "b",
+ },
+ },
+
+ // Test recursive types.
+ {
+ Value: &RecurseA{
+ A: "a1",
+ B: &RecurseB{
+ A: &RecurseA{"a2", nil},
+ B: "b1",
+ },
+ },
+ ExpectXML: `<RecurseA><A>a1</A><B><A><A>a2</A></A><B>b1</B></B></RecurseA>`,
+ },
+
+ // Test ignoring fields via "-" tag
+ {
+ ExpectXML: `<IgnoreTest></IgnoreTest>`,
+ Value: &IgnoreTest{},
+ },
+ {
+ ExpectXML: `<IgnoreTest></IgnoreTest>`,
+ Value: &IgnoreTest{PublicSecret: "can't tell"},
+ MarshalOnly: true,
+ },
+ {
+ ExpectXML: `<IgnoreTest><PublicSecret>ignore me</PublicSecret></IgnoreTest>`,
+ Value: &IgnoreTest{},
+ UnmarshalOnly: true,
+ },
+
+ // Test escaping.
+ {
+ ExpectXML: `<a><nested><value>dquote: &#34;; squote: &#39;; ampersand: &amp;; less: &lt;; greater: &gt;;</value></nested><empty></empty></a>`,
+ Value: &AnyTest{
+ Nested: `dquote: "; squote: '; ampersand: &; less: <; greater: >;`,
+ AnyField: AnyHolder{XMLName: Name{Local: "empty"}},
+ },
+ },
+ {
+ ExpectXML: `<a><nested><value>newline: &#xA;; cr: &#xD;; tab: &#x9;;</value></nested><AnyField></AnyField></a>`,
+ Value: &AnyTest{
+ Nested: "newline: \n; cr: \r; tab: \t;",
+ AnyField: AnyHolder{XMLName: Name{Local: "AnyField"}},
+ },
+ },
+ {
+ ExpectXML: "<a><nested><value>1\r2\r\n3\n\r4\n5</value></nested></a>",
+ Value: &AnyTest{
+ Nested: "1\n2\n3\n\n4\n5",
+ },
+ UnmarshalOnly: true,
+ },
+ {
+ ExpectXML: `<EmbedInt><MyInt>42</MyInt></EmbedInt>`,
+ Value: &EmbedInt{
+ MyInt: 42,
+ },
+ },
+ // Test omitempty with parent chain; see golang.org/issue/4168.
+ {
+ ExpectXML: `<Strings><A></A></Strings>`,
+ Value: &Strings{},
+ },
+ // Custom marshalers.
+ {
+ ExpectXML: `<MyMarshalerTest>hello world</MyMarshalerTest>`,
+ Value: &MyMarshalerTest{},
+ },
+ {
+ ExpectXML: `<MarshalerStruct Foo="hello world"></MarshalerStruct>`,
+ Value: &MarshalerStruct{},
+ },
+ {
+ ExpectXML: `<MarshalerValueStruct Foo="hello world"></MarshalerValueStruct>`,
+ Value: &MarshalerValueStruct{},
+ },
+ {
+ ExpectXML: `<outer xmlns="testns" int="10"></outer>`,
+ Value: &OuterStruct{IntAttr: 10},
+ },
+ {
+ ExpectXML: `<test xmlns="outerns" int="10"></test>`,
+ Value: &OuterNamedStruct{XMLName: Name{Space: "outerns", Local: "test"}, IntAttr: 10},
+ },
+ {
+ ExpectXML: `<test xmlns="outerns" int="10"></test>`,
+ Value: &OuterNamedOrderedStruct{XMLName: Name{Space: "outerns", Local: "test"}, IntAttr: 10},
+ },
+ {
+ ExpectXML: `<outer xmlns="testns" int="10"></outer>`,
+ Value: &OuterOuterStruct{OuterStruct{IntAttr: 10}},
+ },
+ {
+ ExpectXML: `<NestedAndChardata><A><B></B><B></B></A>test</NestedAndChardata>`,
+ Value: &NestedAndChardata{AB: make([]string, 2), Chardata: "test"},
+ },
+ {
+ ExpectXML: `<NestedAndComment><A><B></B><B></B></A><!--test--></NestedAndComment>`,
+ Value: &NestedAndComment{AB: make([]string, 2), Comment: "test"},
+ },
+ {
+ ExpectXML: `<XMLNSFieldStruct xmlns="http://example.com/ns"><Body>hello world</Body></XMLNSFieldStruct>`,
+ Value: &XMLNSFieldStruct{Ns: "http://example.com/ns", Body: "hello world"},
+ },
+ {
+ ExpectXML: `<testns:test xmlns:testns="testns" xmlns="http://example.com/ns"><Body>hello world</Body></testns:test>`,
+ Value: &NamedXMLNSFieldStruct{Ns: "http://example.com/ns", Body: "hello world"},
+ },
+ {
+ ExpectXML: `<testns:test xmlns:testns="testns"><Body>hello world</Body></testns:test>`,
+ Value: &NamedXMLNSFieldStruct{Ns: "", Body: "hello world"},
+ },
+ {
+ ExpectXML: `<XMLNSFieldStructWithOmitEmpty><Body>hello world</Body></XMLNSFieldStructWithOmitEmpty>`,
+ Value: &XMLNSFieldStructWithOmitEmpty{Body: "hello world"},
+ },
+ {
+ // The xmlns attribute must be ignored because the <test>
+ // element is in the empty namespace, so it's not possible
+ // to set the default namespace to something non-empty.
+ ExpectXML: `<test><Body>hello world</Body></test>`,
+ Value: &NamedXMLNSFieldStructWithEmptyNamespace{Ns: "foo", Body: "hello world"},
+ MarshalOnly: true,
+ },
+ {
+ ExpectXML: `<RecursiveXMLNSFieldStruct xmlns="foo"><Body xmlns=""><Text>hello world</Text></Body></RecursiveXMLNSFieldStruct>`,
+ Value: &RecursiveXMLNSFieldStruct{
+ Ns: "foo",
+ Body: &RecursiveXMLNSFieldStruct{
+ Text: "hello world",
+ },
+ },
+ },
+}
+
+func TestMarshal(t *testing.T) {
+ for idx, test := range marshalTests {
+ if test.UnmarshalOnly {
+ continue
+ }
+ data, err := Marshal(test.Value)
+ if err != nil {
+ t.Errorf("#%d: marshal(%#v): %s", idx, test.Value, err)
+ continue
+ }
+ if got, want := string(data), test.ExpectXML; got != want {
+ if strings.Contains(want, "\n") {
+ t.Errorf("#%d: marshal(%#v):\nHAVE:\n%s\nWANT:\n%s", idx, test.Value, got, want)
+ } else {
+ t.Errorf("#%d: marshal(%#v):\nhave %#q\nwant %#q", idx, test.Value, got, want)
+ }
+ }
+ }
+}
+
+type AttrParent struct {
+ X string `xml:"X>Y,attr"`
+}
+
+type BadAttr struct {
+ Name []string `xml:"name,attr"`
+}
+
+var marshalErrorTests = []struct {
+ Value interface{}
+ Err string
+ Kind reflect.Kind
+}{
+ {
+ Value: make(chan bool),
+ Err: "xml: unsupported type: chan bool",
+ Kind: reflect.Chan,
+ },
+ {
+ Value: map[string]string{
+ "question": "What do you get when you multiply six by nine?",
+ "answer": "42",
+ },
+ Err: "xml: unsupported type: map[string]string",
+ Kind: reflect.Map,
+ },
+ {
+ Value: map[*Ship]bool{nil: false},
+ Err: "xml: unsupported type: map[*xml.Ship]bool",
+ Kind: reflect.Map,
+ },
+ {
+ Value: &Domain{Comment: []byte("f--bar")},
+ Err: `xml: comments must not contain "--"`,
+ },
+ // Reject parent chain with attr, never worked; see golang.org/issue/5033.
+ {
+ Value: &AttrParent{},
+ Err: `xml: X>Y chain not valid with attr flag`,
+ },
+ {
+ Value: BadAttr{[]string{"X", "Y"}},
+ Err: `xml: unsupported type: []string`,
+ },
+}
+
+var marshalIndentTests = []struct {
+ Value interface{}
+ Prefix string
+ Indent string
+ ExpectXML string
+}{
+ {
+ Value: &SecretAgent{
+ Handle: "007",
+ Identity: "James Bond",
+ Obfuscate: "<redacted/>",
+ },
+ Prefix: "",
+ Indent: "\t",
+ ExpectXML: fmt.Sprintf("<agent handle=\"007\">\n\t<Identity>James Bond</Identity><redacted/>\n</agent>"),
+ },
+}
+
+func TestMarshalErrors(t *testing.T) {
+ for idx, test := range marshalErrorTests {
+ data, err := Marshal(test.Value)
+ if err == nil {
+ t.Errorf("#%d: marshal(%#v) = [success] %q, want error %v", idx, test.Value, data, test.Err)
+ continue
+ }
+ if err.Error() != test.Err {
+ t.Errorf("#%d: marshal(%#v) = [error] %v, want %v", idx, test.Value, err, test.Err)
+ }
+ if test.Kind != reflect.Invalid {
+ if kind := err.(*UnsupportedTypeError).Type.Kind(); kind != test.Kind {
+ t.Errorf("#%d: marshal(%#v) = [error kind] %s, want %s", idx, test.Value, kind, test.Kind)
+ }
+ }
+ }
+}
+
+// Do invertibility testing on the various structures that we test
+func TestUnmarshal(t *testing.T) {
+ for i, test := range marshalTests {
+ if test.MarshalOnly {
+ continue
+ }
+ if _, ok := test.Value.(*Plain); ok {
+ continue
+ }
+ vt := reflect.TypeOf(test.Value)
+ dest := reflect.New(vt.Elem()).Interface()
+ err := Unmarshal([]byte(test.ExpectXML), dest)
+
+ switch fix := dest.(type) {
+ case *Feed:
+ fix.Author.InnerXML = ""
+ for i := range fix.Entry {
+ fix.Entry[i].Author.InnerXML = ""
+ }
+ }
+
+ if err != nil {
+ t.Errorf("#%d: unexpected error: %#v", i, err)
+ } else if got, want := dest, test.Value; !reflect.DeepEqual(got, want) {
+ t.Errorf("#%d: unmarshal(%q):\nhave %#v\nwant %#v", i, test.ExpectXML, got, want)
+ }
+ }
+}
+
+func TestMarshalIndent(t *testing.T) {
+ for i, test := range marshalIndentTests {
+ data, err := MarshalIndent(test.Value, test.Prefix, test.Indent)
+ if err != nil {
+ t.Errorf("#%d: Error: %s", i, err)
+ continue
+ }
+ if got, want := string(data), test.ExpectXML; got != want {
+ t.Errorf("#%d: MarshalIndent:\nGot:%s\nWant:\n%s", i, got, want)
+ }
+ }
+}
+
+type limitedBytesWriter struct {
+ w io.Writer
+ remain int // until writes fail
+}
+
+func (lw *limitedBytesWriter) Write(p []byte) (n int, err error) {
+ if lw.remain <= 0 {
+ println("error")
+ return 0, errors.New("write limit hit")
+ }
+ if len(p) > lw.remain {
+ p = p[:lw.remain]
+ n, _ = lw.w.Write(p)
+ lw.remain = 0
+ return n, errors.New("write limit hit")
+ }
+ n, err = lw.w.Write(p)
+ lw.remain -= n
+ return n, err
+}
+
+func TestMarshalWriteErrors(t *testing.T) {
+ var buf bytes.Buffer
+ const writeCap = 1024
+ w := &limitedBytesWriter{&buf, writeCap}
+ enc := NewEncoder(w)
+ var err error
+ var i int
+ const n = 4000
+ for i = 1; i <= n; i++ {
+ err = enc.Encode(&Passenger{
+ Name: []string{"Alice", "Bob"},
+ Weight: 5,
+ })
+ if err != nil {
+ break
+ }
+ }
+ if err == nil {
+ t.Error("expected an error")
+ }
+ if i == n {
+ t.Errorf("expected to fail before the end")
+ }
+ if buf.Len() != writeCap {
+ t.Errorf("buf.Len() = %d; want %d", buf.Len(), writeCap)
+ }
+}
+
+func TestMarshalWriteIOErrors(t *testing.T) {
+ enc := NewEncoder(errWriter{})
+
+ expectErr := "unwritable"
+ err := enc.Encode(&Passenger{})
+ if err == nil || err.Error() != expectErr {
+ t.Errorf("EscapeTest = [error] %v, want %v", err, expectErr)
+ }
+}
+
+func TestMarshalFlush(t *testing.T) {
+ var buf bytes.Buffer
+ enc := NewEncoder(&buf)
+ if err := enc.EncodeToken(CharData("hello world")); err != nil {
+ t.Fatalf("enc.EncodeToken: %v", err)
+ }
+ if buf.Len() > 0 {
+ t.Fatalf("enc.EncodeToken caused actual write: %q", buf.Bytes())
+ }
+ if err := enc.Flush(); err != nil {
+ t.Fatalf("enc.Flush: %v", err)
+ }
+ if buf.String() != "hello world" {
+ t.Fatalf("after enc.Flush, buf.String() = %q, want %q", buf.String(), "hello world")
+ }
+}
+
+var encodeElementTests = []struct {
+ desc string
+ value interface{}
+ start StartElement
+ expectXML string
+}{{
+ desc: "simple string",
+ value: "hello",
+ start: StartElement{
+ Name: Name{Local: "a"},
+ },
+ expectXML: `<a>hello</a>`,
+}, {
+ desc: "string with added attributes",
+ value: "hello",
+ start: StartElement{
+ Name: Name{Local: "a"},
+ Attr: []Attr{{
+ Name: Name{Local: "x"},
+ Value: "y",
+ }, {
+ Name: Name{Local: "foo"},
+ Value: "bar",
+ }},
+ },
+ expectXML: `<a x="y" foo="bar">hello</a>`,
+}, {
+ desc: "start element with default name space",
+ value: struct {
+ Foo XMLNameWithNSTag
+ }{
+ Foo: XMLNameWithNSTag{
+ Value: "hello",
+ },
+ },
+ start: StartElement{
+ Name: Name{Space: "ns", Local: "a"},
+ Attr: []Attr{{
+ Name: Name{Local: "xmlns"},
+ // "ns" is the name space defined in XMLNameWithNSTag
+ Value: "ns",
+ }},
+ },
+ expectXML: `<a xmlns="ns"><InXMLNameWithNSTag>hello</InXMLNameWithNSTag></a>`,
+}, {
+ desc: "start element in name space with different default name space",
+ value: struct {
+ Foo XMLNameWithNSTag
+ }{
+ Foo: XMLNameWithNSTag{
+ Value: "hello",
+ },
+ },
+ start: StartElement{
+ Name: Name{Space: "ns2", Local: "a"},
+ Attr: []Attr{{
+ Name: Name{Local: "xmlns"},
+ // "ns" is the name space defined in XMLNameWithNSTag
+ Value: "ns",
+ }},
+ },
+ expectXML: `<ns2:a xmlns:ns2="ns2" xmlns="ns"><InXMLNameWithNSTag>hello</InXMLNameWithNSTag></ns2:a>`,
+}, {
+ desc: "XMLMarshaler with start element with default name space",
+ value: &MyMarshalerTest{},
+ start: StartElement{
+ Name: Name{Space: "ns2", Local: "a"},
+ Attr: []Attr{{
+ Name: Name{Local: "xmlns"},
+ // "ns" is the name space defined in XMLNameWithNSTag
+ Value: "ns",
+ }},
+ },
+ expectXML: `<ns2:a xmlns:ns2="ns2" xmlns="ns">hello world</ns2:a>`,
+}}
+
+func TestEncodeElement(t *testing.T) {
+ for idx, test := range encodeElementTests {
+ var buf bytes.Buffer
+ enc := NewEncoder(&buf)
+ err := enc.EncodeElement(test.value, test.start)
+ if err != nil {
+ t.Fatalf("enc.EncodeElement: %v", err)
+ }
+ err = enc.Flush()
+ if err != nil {
+ t.Fatalf("enc.Flush: %v", err)
+ }
+ if got, want := buf.String(), test.expectXML; got != want {
+ t.Errorf("#%d(%s): EncodeElement(%#v, %#v):\nhave %#q\nwant %#q", idx, test.desc, test.value, test.start, got, want)
+ }
+ }
+}
+
+func BenchmarkMarshal(b *testing.B) {
+ b.ReportAllocs()
+ for i := 0; i < b.N; i++ {
+ Marshal(atomValue)
+ }
+}
+
+func BenchmarkUnmarshal(b *testing.B) {
+ b.ReportAllocs()
+ xml := []byte(atomXml)
+ for i := 0; i < b.N; i++ {
+ Unmarshal(xml, &Feed{})
+ }
+}
+
+// golang.org/issue/6556
+func TestStructPointerMarshal(t *testing.T) {
+ type A struct {
+ XMLName string `xml:"a"`
+ B []interface{}
+ }
+ type C struct {
+ XMLName Name
+ Value string `xml:"value"`
+ }
+
+ a := new(A)
+ a.B = append(a.B, &C{
+ XMLName: Name{Local: "c"},
+ Value: "x",
+ })
+
+ b, err := Marshal(a)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if x := string(b); x != "<a><c><value>x</value></c></a>" {
+ t.Fatal(x)
+ }
+ var v A
+ err = Unmarshal(b, &v)
+ if err != nil {
+ t.Fatal(err)
+ }
+}
+
+var encodeTokenTests = []struct {
+ desc string
+ toks []Token
+ want string
+ err string
+}{{
+ desc: "start element with name space",
+ toks: []Token{
+ StartElement{Name{"space", "local"}, nil},
+ },
+ want: `<space:local xmlns:space="space">`,
+}, {
+ desc: "start element with no name",
+ toks: []Token{
+ StartElement{Name{"space", ""}, nil},
+ },
+ err: "xml: start tag with no name",
+}, {
+ desc: "end element with no name",
+ toks: []Token{
+ EndElement{Name{"space", ""}},
+ },
+ err: "xml: end tag with no name",
+}, {
+ desc: "char data",
+ toks: []Token{
+ CharData("foo"),
+ },
+ want: `foo`,
+}, {
+ desc: "char data with escaped chars",
+ toks: []Token{
+ CharData(" \t\n"),
+ },
+ want: " &#x9;\n",
+}, {
+ desc: "comment",
+ toks: []Token{
+ Comment("foo"),
+ },
+ want: `<!--foo-->`,
+}, {
+ desc: "comment with invalid content",
+ toks: []Token{
+ Comment("foo-->"),
+ },
+ err: "xml: EncodeToken of Comment containing --> marker",
+}, {
+ desc: "proc instruction",
+ toks: []Token{
+ ProcInst{"Target", []byte("Instruction")},
+ },
+ want: `<?Target Instruction?>`,
+}, {
+ desc: "proc instruction with empty target",
+ toks: []Token{
+ ProcInst{"", []byte("Instruction")},
+ },
+ err: "xml: EncodeToken of ProcInst with invalid Target",
+}, {
+ desc: "proc instruction with bad content",
+ toks: []Token{
+ ProcInst{"", []byte("Instruction?>")},
+ },
+ err: "xml: EncodeToken of ProcInst with invalid Target",
+}, {
+ desc: "directive",
+ toks: []Token{
+ Directive("foo"),
+ },
+ want: `<!foo>`,
+}, {
+ desc: "more complex directive",
+ toks: []Token{
+ Directive("DOCTYPE doc [ <!ELEMENT doc '>'> <!-- com>ment --> ]"),
+ },
+ want: `<!DOCTYPE doc [ <!ELEMENT doc '>'> <!-- com>ment --> ]>`,
+}, {
+ desc: "directive instruction with bad name",
+ toks: []Token{
+ Directive("foo>"),
+ },
+ err: "xml: EncodeToken of Directive containing wrong < or > markers",
+}, {
+ desc: "end tag without start tag",
+ toks: []Token{
+ EndElement{Name{"foo", "bar"}},
+ },
+ err: "xml: end tag </bar> without start tag",
+}, {
+ desc: "mismatching end tag local name",
+ toks: []Token{
+ StartElement{Name{"", "foo"}, nil},
+ EndElement{Name{"", "bar"}},
+ },
+ err: "xml: end tag </bar> does not match start tag <foo>",
+ want: `<foo>`,
+}, {
+ desc: "mismatching end tag namespace",
+ toks: []Token{
+ StartElement{Name{"space", "foo"}, nil},
+ EndElement{Name{"another", "foo"}},
+ },
+ err: "xml: end tag </foo> in namespace another does not match start tag <foo> in namespace space",
+ want: `<space:foo xmlns:space="space">`,
+}, {
+ desc: "start element with explicit namespace",
+ toks: []Token{
+ StartElement{Name{"space", "local"}, []Attr{
+ {Name{"xmlns", "x"}, "space"},
+ {Name{"space", "foo"}, "value"},
+ }},
+ },
+ want: `<x:local xmlns:x="space" x:foo="value">`,
+}, {
+ desc: "start element with explicit namespace and colliding prefix",
+ toks: []Token{
+ StartElement{Name{"space", "local"}, []Attr{
+ {Name{"xmlns", "x"}, "space"},
+ {Name{"space", "foo"}, "value"},
+ {Name{"x", "bar"}, "other"},
+ }},
+ },
+ want: `<x:local xmlns:x_1="x" xmlns:x="space" x:foo="value" x_1:bar="other">`,
+}, {
+ desc: "start element using previously defined namespace",
+ toks: []Token{
+ StartElement{Name{"", "local"}, []Attr{
+ {Name{"xmlns", "x"}, "space"},
+ }},
+ StartElement{Name{"space", "foo"}, []Attr{
+ {Name{"space", "x"}, "y"},
+ }},
+ },
+ want: `<local xmlns:x="space"><x:foo x:x="y">`,
+}, {
+ desc: "nested name space with same prefix",
+ toks: []Token{
+ StartElement{Name{"", "foo"}, []Attr{
+ {Name{"xmlns", "x"}, "space1"},
+ }},
+ StartElement{Name{"", "foo"}, []Attr{
+ {Name{"xmlns", "x"}, "space2"},
+ }},
+ StartElement{Name{"", "foo"}, []Attr{
+ {Name{"space1", "a"}, "space1 value"},
+ {Name{"space2", "b"}, "space2 value"},
+ }},
+ EndElement{Name{"", "foo"}},
+ EndElement{Name{"", "foo"}},
+ StartElement{Name{"", "foo"}, []Attr{
+ {Name{"space1", "a"}, "space1 value"},
+ {Name{"space2", "b"}, "space2 value"},
+ }},
+ },
+ want: `<foo xmlns:x="space1"><foo xmlns:x="space2"><foo xmlns:space1="space1" space1:a="space1 value" x:b="space2 value"></foo></foo><foo xmlns:space2="space2" x:a="space1 value" space2:b="space2 value">`,
+}, {
+ desc: "start element defining several prefixes for the same name space",
+ toks: []Token{
+ StartElement{Name{"space", "foo"}, []Attr{
+ {Name{"xmlns", "a"}, "space"},
+ {Name{"xmlns", "b"}, "space"},
+ {Name{"space", "x"}, "value"},
+ }},
+ },
+ want: `<a:foo xmlns:a="space" a:x="value">`,
+}, {
+ desc: "nested element redefines name space",
+ toks: []Token{
+ StartElement{Name{"", "foo"}, []Attr{
+ {Name{"xmlns", "x"}, "space"},
+ }},
+ StartElement{Name{"space", "foo"}, []Attr{
+ {Name{"xmlns", "y"}, "space"},
+ {Name{"space", "a"}, "value"},
+ }},
+ },
+ want: `<foo xmlns:x="space"><x:foo x:a="value">`,
+}, {
+ desc: "nested element creates alias for default name space",
+ toks: []Token{
+ StartElement{Name{"space", "foo"}, []Attr{
+ {Name{"", "xmlns"}, "space"},
+ }},
+ StartElement{Name{"space", "foo"}, []Attr{
+ {Name{"xmlns", "y"}, "space"},
+ {Name{"space", "a"}, "value"},
+ }},
+ },
+ want: `<foo xmlns="space"><foo xmlns:y="space" y:a="value">`,
+}, {
+ desc: "nested element defines default name space with existing prefix",
+ toks: []Token{
+ StartElement{Name{"", "foo"}, []Attr{
+ {Name{"xmlns", "x"}, "space"},
+ }},
+ StartElement{Name{"space", "foo"}, []Attr{
+ {Name{"", "xmlns"}, "space"},
+ {Name{"space", "a"}, "value"},
+ }},
+ },
+ want: `<foo xmlns:x="space"><foo xmlns="space" x:a="value">`,
+}, {
+ desc: "nested element uses empty attribute name space when default ns defined",
+ toks: []Token{
+ StartElement{Name{"space", "foo"}, []Attr{
+ {Name{"", "xmlns"}, "space"},
+ }},
+ StartElement{Name{"space", "foo"}, []Attr{
+ {Name{"", "attr"}, "value"},
+ }},
+ },
+ want: `<foo xmlns="space"><foo attr="value">`,
+}, {
+ desc: "redefine xmlns",
+ toks: []Token{
+ StartElement{Name{"", "foo"}, []Attr{
+ {Name{"foo", "xmlns"}, "space"},
+ }},
+ },
+ err: `xml: cannot redefine xmlns attribute prefix`,
+}, {
+ desc: "xmlns with explicit name space #1",
+ toks: []Token{
+ StartElement{Name{"space", "foo"}, []Attr{
+ {Name{"xml", "xmlns"}, "space"},
+ }},
+ },
+ want: `<foo xmlns="space">`,
+}, {
+ desc: "xmlns with explicit name space #2",
+ toks: []Token{
+ StartElement{Name{"space", "foo"}, []Attr{
+ {Name{xmlURL, "xmlns"}, "space"},
+ }},
+ },
+ want: `<foo xmlns="space">`,
+}, {
+ desc: "empty name space declaration is ignored",
+ toks: []Token{
+ StartElement{Name{"", "foo"}, []Attr{
+ {Name{"xmlns", "foo"}, ""},
+ }},
+ },
+ want: `<foo>`,
+}, {
+ desc: "attribute with no name is ignored",
+ toks: []Token{
+ StartElement{Name{"", "foo"}, []Attr{
+ {Name{"", ""}, "value"},
+ }},
+ },
+ want: `<foo>`,
+}, {
+ desc: "namespace URL with non-valid name",
+ toks: []Token{
+ StartElement{Name{"/34", "foo"}, []Attr{
+ {Name{"/34", "x"}, "value"},
+ }},
+ },
+ want: `<_:foo xmlns:_="/34" _:x="value">`,
+}, {
+ desc: "nested element resets default namespace to empty",
+ toks: []Token{
+ StartElement{Name{"space", "foo"}, []Attr{
+ {Name{"", "xmlns"}, "space"},
+ }},
+ StartElement{Name{"", "foo"}, []Attr{
+ {Name{"", "xmlns"}, ""},
+ {Name{"", "x"}, "value"},
+ {Name{"space", "x"}, "value"},
+ }},
+ },
+ want: `<foo xmlns="space"><foo xmlns:space="space" xmlns="" x="value" space:x="value">`,
+}, {
+ desc: "nested element requires empty default name space",
+ toks: []Token{
+ StartElement{Name{"space", "foo"}, []Attr{
+ {Name{"", "xmlns"}, "space"},
+ }},
+ StartElement{Name{"", "foo"}, nil},
+ },
+ want: `<foo xmlns="space"><foo xmlns="">`,
+}, {
+ desc: "attribute uses name space from xmlns",
+ toks: []Token{
+ StartElement{Name{"some/space", "foo"}, []Attr{
+ {Name{"", "attr"}, "value"},
+ {Name{"some/space", "other"}, "other value"},
+ }},
+ },
+ want: `<space:foo xmlns:space="some/space" attr="value" space:other="other value">`,
+}, {
+ desc: "default name space should not be used by attributes",
+ toks: []Token{
+ StartElement{Name{"space", "foo"}, []Attr{
+ {Name{"", "xmlns"}, "space"},
+ {Name{"xmlns", "bar"}, "space"},
+ {Name{"space", "baz"}, "foo"},
+ }},
+ StartElement{Name{"space", "baz"}, nil},
+ EndElement{Name{"space", "baz"}},
+ EndElement{Name{"space", "foo"}},
+ },
+ want: `<foo xmlns:bar="space" xmlns="space" bar:baz="foo"><baz></baz></foo>`,
+}, {
+ desc: "default name space not used by attributes, not explicitly defined",
+ toks: []Token{
+ StartElement{Name{"space", "foo"}, []Attr{
+ {Name{"", "xmlns"}, "space"},
+ {Name{"space", "baz"}, "foo"},
+ }},
+ StartElement{Name{"space", "baz"}, nil},
+ EndElement{Name{"space", "baz"}},
+ EndElement{Name{"space", "foo"}},
+ },
+ want: `<foo xmlns:space="space" xmlns="space" space:baz="foo"><baz></baz></foo>`,
+}, {
+ desc: "impossible xmlns declaration",
+ toks: []Token{
+ StartElement{Name{"", "foo"}, []Attr{
+ {Name{"", "xmlns"}, "space"},
+ }},
+ StartElement{Name{"space", "bar"}, []Attr{
+ {Name{"space", "attr"}, "value"},
+ }},
+ },
+ want: `<foo><space:bar xmlns:space="space" space:attr="value">`,
+}}
+
+func TestEncodeToken(t *testing.T) {
+loop:
+ for i, tt := range encodeTokenTests {
+ var buf bytes.Buffer
+ enc := NewEncoder(&buf)
+ var err error
+ for j, tok := range tt.toks {
+ err = enc.EncodeToken(tok)
+ if err != nil && j < len(tt.toks)-1 {
+ t.Errorf("#%d %s token #%d: %v", i, tt.desc, j, err)
+ continue loop
+ }
+ }
+ errorf := func(f string, a ...interface{}) {
+ t.Errorf("#%d %s token #%d:%s", i, tt.desc, len(tt.toks)-1, fmt.Sprintf(f, a...))
+ }
+ switch {
+ case tt.err != "" && err == nil:
+ errorf(" expected error; got none")
+ continue
+ case tt.err == "" && err != nil:
+ errorf(" got error: %v", err)
+ continue
+ case tt.err != "" && err != nil && tt.err != err.Error():
+ errorf(" error mismatch; got %v, want %v", err, tt.err)
+ continue
+ }
+ if err := enc.Flush(); err != nil {
+ errorf(" %v", err)
+ continue
+ }
+ if got := buf.String(); got != tt.want {
+ errorf("\ngot %v\nwant %v", got, tt.want)
+ continue
+ }
+ }
+}
+
+func TestProcInstEncodeToken(t *testing.T) {
+ var buf bytes.Buffer
+ enc := NewEncoder(&buf)
+
+ if err := enc.EncodeToken(ProcInst{"xml", []byte("Instruction")}); err != nil {
+ t.Fatalf("enc.EncodeToken: expected to be able to encode xml target ProcInst as first token, %s", err)
+ }
+
+ if err := enc.EncodeToken(ProcInst{"Target", []byte("Instruction")}); err != nil {
+ t.Fatalf("enc.EncodeToken: expected to be able to add non-xml target ProcInst")
+ }
+
+ if err := enc.EncodeToken(ProcInst{"xml", []byte("Instruction")}); err == nil {
+ t.Fatalf("enc.EncodeToken: expected to not be allowed to encode xml target ProcInst when not first token")
+ }
+}
+
+func TestDecodeEncode(t *testing.T) {
+ var in, out bytes.Buffer
+ in.WriteString(`<?xml version="1.0" encoding="UTF-8"?>
+<?Target Instruction?>
+<root>
+</root>
+`)
+ dec := NewDecoder(&in)
+ enc := NewEncoder(&out)
+ for tok, err := dec.Token(); err == nil; tok, err = dec.Token() {
+ err = enc.EncodeToken(tok)
+ if err != nil {
+ t.Fatalf("enc.EncodeToken: Unable to encode token (%#v), %v", tok, err)
+ }
+ }
+}
+
+// Issue 9796. Used to fail with GORACE="halt_on_error=1" -race.
+func TestRace9796(t *testing.T) {
+ type A struct{}
+ type B struct {
+ C []A `xml:"X>Y"`
+ }
+ var wg sync.WaitGroup
+ for i := 0; i < 2; i++ {
+ wg.Add(1)
+ go func() {
+ Marshal(B{[]A{{}}})
+ wg.Done()
+ }()
+ }
+ wg.Wait()
+}
+
+func TestIsValidDirective(t *testing.T) {
+ testOK := []string{
+ "<>",
+ "< < > >",
+ "<!DOCTYPE '<' '>' '>' <!--nothing-->>",
+ "<!DOCTYPE doc [ <!ELEMENT doc ANY> <!ELEMENT doc ANY> ]>",
+ "<!DOCTYPE doc [ <!ELEMENT doc \"ANY> '<' <!E\" LEMENT '>' doc ANY> ]>",
+ "<!DOCTYPE doc <!-- just>>>> a < comment --> [ <!ITEM anything> ] >",
+ }
+ testKO := []string{
+ "<",
+ ">",
+ "<!--",
+ "-->",
+ "< > > < < >",
+ "<!dummy <!-- > -->",
+ "<!DOCTYPE doc '>",
+ "<!DOCTYPE doc '>'",
+ "<!DOCTYPE doc <!--comment>",
+ }
+ for _, s := range testOK {
+ if !isValidDirective(Directive(s)) {
+ t.Errorf("Directive %q is expected to be valid", s)
+ }
+ }
+ for _, s := range testKO {
+ if isValidDirective(Directive(s)) {
+ t.Errorf("Directive %q is expected to be invalid", s)
+ }
+ }
+}
+
+// Issue 11719. EncodeToken used to silently eat tokens with an invalid type.
+func TestSimpleUseOfEncodeToken(t *testing.T) {
+ var buf bytes.Buffer
+ enc := NewEncoder(&buf)
+ if err := enc.EncodeToken(&StartElement{Name: Name{"", "object1"}}); err == nil {
+ t.Errorf("enc.EncodeToken: pointer type should be rejected")
+ }
+ if err := enc.EncodeToken(&EndElement{Name: Name{"", "object1"}}); err == nil {
+ t.Errorf("enc.EncodeToken: pointer type should be rejected")
+ }
+ if err := enc.EncodeToken(StartElement{Name: Name{"", "object2"}}); err != nil {
+ t.Errorf("enc.EncodeToken: StartElement %s", err)
+ }
+ if err := enc.EncodeToken(EndElement{Name: Name{"", "object2"}}); err != nil {
+ t.Errorf("enc.EncodeToken: EndElement %s", err)
+ }
+ if err := enc.EncodeToken(Universe{}); err == nil {
+ t.Errorf("enc.EncodeToken: invalid type not caught")
+ }
+ if err := enc.Flush(); err != nil {
+ t.Errorf("enc.Flush: %s", err)
+ }
+ if buf.Len() == 0 {
+ t.Errorf("enc.EncodeToken: empty buffer")
+ }
+ want := "<object2></object2>"
+ if buf.String() != want {
+ t.Errorf("enc.EncodeToken: expected %q; got %q", want, buf.String())
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/internal/xml/read.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/internal/xml/read.go
new file mode 100644
index 000000000..4089056a1
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/internal/xml/read.go
@@ -0,0 +1,692 @@
+// Copyright 2009 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 xml
+
+import (
+ "bytes"
+ "encoding"
+ "errors"
+ "fmt"
+ "reflect"
+ "strconv"
+ "strings"
+)
+
+// BUG(rsc): Mapping between XML elements and data structures is inherently flawed:
+// an XML element is an order-dependent collection of anonymous
+// values, while a data structure is an order-independent collection
+// of named values.
+// See package json for a textual representation more suitable
+// to data structures.
+
+// Unmarshal parses the XML-encoded data and stores the result in
+// the value pointed to by v, which must be an arbitrary struct,
+// slice, or string. Well-formed data that does not fit into v is
+// discarded.
+//
+// Because Unmarshal uses the reflect package, it can only assign
+// to exported (upper case) fields. Unmarshal uses a case-sensitive
+// comparison to match XML element names to tag values and struct
+// field names.
+//
+// Unmarshal maps an XML element to a struct using the following rules.
+// In the rules, the tag of a field refers to the value associated with the
+// key 'xml' in the struct field's tag (see the example above).
+//
+// * If the struct has a field of type []byte or string with tag
+// ",innerxml", Unmarshal accumulates the raw XML nested inside the
+// element in that field. The rest of the rules still apply.
+//
+// * If the struct has a field named XMLName of type xml.Name,
+// Unmarshal records the element name in that field.
+//
+// * If the XMLName field has an associated tag of the form
+// "name" or "namespace-URL name", the XML element must have
+// the given name (and, optionally, name space) or else Unmarshal
+// returns an error.
+//
+// * If the XML element has an attribute whose name matches a
+// struct field name with an associated tag containing ",attr" or
+// the explicit name in a struct field tag of the form "name,attr",
+// Unmarshal records the attribute value in that field.
+//
+// * If the XML element contains character data, that data is
+// accumulated in the first struct field that has tag ",chardata".
+// The struct field may have type []byte or string.
+// If there is no such field, the character data is discarded.
+//
+// * If the XML element contains comments, they are accumulated in
+// the first struct field that has tag ",comment". The struct
+// field may have type []byte or string. If there is no such
+// field, the comments are discarded.
+//
+// * If the XML element contains a sub-element whose name matches
+// the prefix of a tag formatted as "a" or "a>b>c", unmarshal
+// will descend into the XML structure looking for elements with the
+// given names, and will map the innermost elements to that struct
+// field. A tag starting with ">" is equivalent to one starting
+// with the field name followed by ">".
+//
+// * If the XML element contains a sub-element whose name matches
+// a struct field's XMLName tag and the struct field has no
+// explicit name tag as per the previous rule, unmarshal maps
+// the sub-element to that struct field.
+//
+// * If the XML element contains a sub-element whose name matches a
+// field without any mode flags (",attr", ",chardata", etc), Unmarshal
+// maps the sub-element to that struct field.
+//
+// * If the XML element contains a sub-element that hasn't matched any
+// of the above rules and the struct has a field with tag ",any",
+// unmarshal maps the sub-element to that struct field.
+//
+// * An anonymous struct field is handled as if the fields of its
+// value were part of the outer struct.
+//
+// * A struct field with tag "-" is never unmarshalled into.
+//
+// Unmarshal maps an XML element to a string or []byte by saving the
+// concatenation of that element's character data in the string or
+// []byte. The saved []byte is never nil.
+//
+// Unmarshal maps an attribute value to a string or []byte by saving
+// the value in the string or slice.
+//
+// Unmarshal maps an XML element to a slice by extending the length of
+// the slice and mapping the element to the newly created value.
+//
+// Unmarshal maps an XML element or attribute value to a bool by
+// setting it to the boolean value represented by the string.
+//
+// Unmarshal maps an XML element or attribute value to an integer or
+// floating-point field by setting the field to the result of
+// interpreting the string value in decimal. There is no check for
+// overflow.
+//
+// Unmarshal maps an XML element to an xml.Name by recording the
+// element name.
+//
+// Unmarshal maps an XML element to a pointer by setting the pointer
+// to a freshly allocated value and then mapping the element to that value.
+//
+func Unmarshal(data []byte, v interface{}) error {
+ return NewDecoder(bytes.NewReader(data)).Decode(v)
+}
+
+// Decode works like xml.Unmarshal, except it reads the decoder
+// stream to find the start element.
+func (d *Decoder) Decode(v interface{}) error {
+ return d.DecodeElement(v, nil)
+}
+
+// DecodeElement works like xml.Unmarshal except that it takes
+// a pointer to the start XML element to decode into v.
+// It is useful when a client reads some raw XML tokens itself
+// but also wants to defer to Unmarshal for some elements.
+func (d *Decoder) DecodeElement(v interface{}, start *StartElement) error {
+ val := reflect.ValueOf(v)
+ if val.Kind() != reflect.Ptr {
+ return errors.New("non-pointer passed to Unmarshal")
+ }
+ return d.unmarshal(val.Elem(), start)
+}
+
+// An UnmarshalError represents an error in the unmarshalling process.
+type UnmarshalError string
+
+func (e UnmarshalError) Error() string { return string(e) }
+
+// Unmarshaler is the interface implemented by objects that can unmarshal
+// an XML element description of themselves.
+//
+// UnmarshalXML decodes a single XML element
+// beginning with the given start element.
+// If it returns an error, the outer call to Unmarshal stops and
+// returns that error.
+// UnmarshalXML must consume exactly one XML element.
+// One common implementation strategy is to unmarshal into
+// a separate value with a layout matching the expected XML
+// using d.DecodeElement, and then to copy the data from
+// that value into the receiver.
+// Another common strategy is to use d.Token to process the
+// XML object one token at a time.
+// UnmarshalXML may not use d.RawToken.
+type Unmarshaler interface {
+ UnmarshalXML(d *Decoder, start StartElement) error
+}
+
+// UnmarshalerAttr is the interface implemented by objects that can unmarshal
+// an XML attribute description of themselves.
+//
+// UnmarshalXMLAttr decodes a single XML attribute.
+// If it returns an error, the outer call to Unmarshal stops and
+// returns that error.
+// UnmarshalXMLAttr is used only for struct fields with the
+// "attr" option in the field tag.
+type UnmarshalerAttr interface {
+ UnmarshalXMLAttr(attr Attr) error
+}
+
+// receiverType returns the receiver type to use in an expression like "%s.MethodName".
+func receiverType(val interface{}) string {
+ t := reflect.TypeOf(val)
+ if t.Name() != "" {
+ return t.String()
+ }
+ return "(" + t.String() + ")"
+}
+
+// unmarshalInterface unmarshals a single XML element into val.
+// start is the opening tag of the element.
+func (p *Decoder) unmarshalInterface(val Unmarshaler, start *StartElement) error {
+ // Record that decoder must stop at end tag corresponding to start.
+ p.pushEOF()
+
+ p.unmarshalDepth++
+ err := val.UnmarshalXML(p, *start)
+ p.unmarshalDepth--
+ if err != nil {
+ p.popEOF()
+ return err
+ }
+
+ if !p.popEOF() {
+ return fmt.Errorf("xml: %s.UnmarshalXML did not consume entire <%s> element", receiverType(val), start.Name.Local)
+ }
+
+ return nil
+}
+
+// unmarshalTextInterface unmarshals a single XML element into val.
+// The chardata contained in the element (but not its children)
+// is passed to the text unmarshaler.
+func (p *Decoder) unmarshalTextInterface(val encoding.TextUnmarshaler, start *StartElement) error {
+ var buf []byte
+ depth := 1
+ for depth > 0 {
+ t, err := p.Token()
+ if err != nil {
+ return err
+ }
+ switch t := t.(type) {
+ case CharData:
+ if depth == 1 {
+ buf = append(buf, t...)
+ }
+ case StartElement:
+ depth++
+ case EndElement:
+ depth--
+ }
+ }
+ return val.UnmarshalText(buf)
+}
+
+// unmarshalAttr unmarshals a single XML attribute into val.
+func (p *Decoder) unmarshalAttr(val reflect.Value, attr Attr) error {
+ if val.Kind() == reflect.Ptr {
+ if val.IsNil() {
+ val.Set(reflect.New(val.Type().Elem()))
+ }
+ val = val.Elem()
+ }
+
+ if val.CanInterface() && val.Type().Implements(unmarshalerAttrType) {
+ // This is an unmarshaler with a non-pointer receiver,
+ // so it's likely to be incorrect, but we do what we're told.
+ return val.Interface().(UnmarshalerAttr).UnmarshalXMLAttr(attr)
+ }
+ if val.CanAddr() {
+ pv := val.Addr()
+ if pv.CanInterface() && pv.Type().Implements(unmarshalerAttrType) {
+ return pv.Interface().(UnmarshalerAttr).UnmarshalXMLAttr(attr)
+ }
+ }
+
+ // Not an UnmarshalerAttr; try encoding.TextUnmarshaler.
+ if val.CanInterface() && val.Type().Implements(textUnmarshalerType) {
+ // This is an unmarshaler with a non-pointer receiver,
+ // so it's likely to be incorrect, but we do what we're told.
+ return val.Interface().(encoding.TextUnmarshaler).UnmarshalText([]byte(attr.Value))
+ }
+ if val.CanAddr() {
+ pv := val.Addr()
+ if pv.CanInterface() && pv.Type().Implements(textUnmarshalerType) {
+ return pv.Interface().(encoding.TextUnmarshaler).UnmarshalText([]byte(attr.Value))
+ }
+ }
+
+ copyValue(val, []byte(attr.Value))
+ return nil
+}
+
+var (
+ unmarshalerType = reflect.TypeOf((*Unmarshaler)(nil)).Elem()
+ unmarshalerAttrType = reflect.TypeOf((*UnmarshalerAttr)(nil)).Elem()
+ textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
+)
+
+// Unmarshal a single XML element into val.
+func (p *Decoder) unmarshal(val reflect.Value, start *StartElement) error {
+ // Find start element if we need it.
+ if start == nil {
+ for {
+ tok, err := p.Token()
+ if err != nil {
+ return err
+ }
+ if t, ok := tok.(StartElement); ok {
+ start = &t
+ break
+ }
+ }
+ }
+
+ // Load value from interface, but only if the result will be
+ // usefully addressable.
+ if val.Kind() == reflect.Interface && !val.IsNil() {
+ e := val.Elem()
+ if e.Kind() == reflect.Ptr && !e.IsNil() {
+ val = e
+ }
+ }
+
+ if val.Kind() == reflect.Ptr {
+ if val.IsNil() {
+ val.Set(reflect.New(val.Type().Elem()))
+ }
+ val = val.Elem()
+ }
+
+ if val.CanInterface() && val.Type().Implements(unmarshalerType) {
+ // This is an unmarshaler with a non-pointer receiver,
+ // so it's likely to be incorrect, but we do what we're told.
+ return p.unmarshalInterface(val.Interface().(Unmarshaler), start)
+ }
+
+ if val.CanAddr() {
+ pv := val.Addr()
+ if pv.CanInterface() && pv.Type().Implements(unmarshalerType) {
+ return p.unmarshalInterface(pv.Interface().(Unmarshaler), start)
+ }
+ }
+
+ if val.CanInterface() && val.Type().Implements(textUnmarshalerType) {
+ return p.unmarshalTextInterface(val.Interface().(encoding.TextUnmarshaler), start)
+ }
+
+ if val.CanAddr() {
+ pv := val.Addr()
+ if pv.CanInterface() && pv.Type().Implements(textUnmarshalerType) {
+ return p.unmarshalTextInterface(pv.Interface().(encoding.TextUnmarshaler), start)
+ }
+ }
+
+ var (
+ data []byte
+ saveData reflect.Value
+ comment []byte
+ saveComment reflect.Value
+ saveXML reflect.Value
+ saveXMLIndex int
+ saveXMLData []byte
+ saveAny reflect.Value
+ sv reflect.Value
+ tinfo *typeInfo
+ err error
+ )
+
+ switch v := val; v.Kind() {
+ default:
+ return errors.New("unknown type " + v.Type().String())
+
+ case reflect.Interface:
+ // TODO: For now, simply ignore the field. In the near
+ // future we may choose to unmarshal the start
+ // element on it, if not nil.
+ return p.Skip()
+
+ case reflect.Slice:
+ typ := v.Type()
+ if typ.Elem().Kind() == reflect.Uint8 {
+ // []byte
+ saveData = v
+ break
+ }
+
+ // Slice of element values.
+ // Grow slice.
+ n := v.Len()
+ if n >= v.Cap() {
+ ncap := 2 * n
+ if ncap < 4 {
+ ncap = 4
+ }
+ new := reflect.MakeSlice(typ, n, ncap)
+ reflect.Copy(new, v)
+ v.Set(new)
+ }
+ v.SetLen(n + 1)
+
+ // Recur to read element into slice.
+ if err := p.unmarshal(v.Index(n), start); err != nil {
+ v.SetLen(n)
+ return err
+ }
+ return nil
+
+ case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr, reflect.String:
+ saveData = v
+
+ case reflect.Struct:
+ typ := v.Type()
+ if typ == nameType {
+ v.Set(reflect.ValueOf(start.Name))
+ break
+ }
+
+ sv = v
+ tinfo, err = getTypeInfo(typ)
+ if err != nil {
+ return err
+ }
+
+ // Validate and assign element name.
+ if tinfo.xmlname != nil {
+ finfo := tinfo.xmlname
+ if finfo.name != "" && finfo.name != start.Name.Local {
+ return UnmarshalError("expected element type <" + finfo.name + "> but have <" + start.Name.Local + ">")
+ }
+ if finfo.xmlns != "" && finfo.xmlns != start.Name.Space {
+ e := "expected element <" + finfo.name + "> in name space " + finfo.xmlns + " but have "
+ if start.Name.Space == "" {
+ e += "no name space"
+ } else {
+ e += start.Name.Space
+ }
+ return UnmarshalError(e)
+ }
+ fv := finfo.value(sv)
+ if _, ok := fv.Interface().(Name); ok {
+ fv.Set(reflect.ValueOf(start.Name))
+ }
+ }
+
+ // Assign attributes.
+ // Also, determine whether we need to save character data or comments.
+ for i := range tinfo.fields {
+ finfo := &tinfo.fields[i]
+ switch finfo.flags & fMode {
+ case fAttr:
+ strv := finfo.value(sv)
+ // Look for attribute.
+ for _, a := range start.Attr {
+ if a.Name.Local == finfo.name && (finfo.xmlns == "" || finfo.xmlns == a.Name.Space) {
+ if err := p.unmarshalAttr(strv, a); err != nil {
+ return err
+ }
+ break
+ }
+ }
+
+ case fCharData:
+ if !saveData.IsValid() {
+ saveData = finfo.value(sv)
+ }
+
+ case fComment:
+ if !saveComment.IsValid() {
+ saveComment = finfo.value(sv)
+ }
+
+ case fAny, fAny | fElement:
+ if !saveAny.IsValid() {
+ saveAny = finfo.value(sv)
+ }
+
+ case fInnerXml:
+ if !saveXML.IsValid() {
+ saveXML = finfo.value(sv)
+ if p.saved == nil {
+ saveXMLIndex = 0
+ p.saved = new(bytes.Buffer)
+ } else {
+ saveXMLIndex = p.savedOffset()
+ }
+ }
+ }
+ }
+ }
+
+ // Find end element.
+ // Process sub-elements along the way.
+Loop:
+ for {
+ var savedOffset int
+ if saveXML.IsValid() {
+ savedOffset = p.savedOffset()
+ }
+ tok, err := p.Token()
+ if err != nil {
+ return err
+ }
+ switch t := tok.(type) {
+ case StartElement:
+ consumed := false
+ if sv.IsValid() {
+ consumed, err = p.unmarshalPath(tinfo, sv, nil, &t)
+ if err != nil {
+ return err
+ }
+ if !consumed && saveAny.IsValid() {
+ consumed = true
+ if err := p.unmarshal(saveAny, &t); err != nil {
+ return err
+ }
+ }
+ }
+ if !consumed {
+ if err := p.Skip(); err != nil {
+ return err
+ }
+ }
+
+ case EndElement:
+ if saveXML.IsValid() {
+ saveXMLData = p.saved.Bytes()[saveXMLIndex:savedOffset]
+ if saveXMLIndex == 0 {
+ p.saved = nil
+ }
+ }
+ break Loop
+
+ case CharData:
+ if saveData.IsValid() {
+ data = append(data, t...)
+ }
+
+ case Comment:
+ if saveComment.IsValid() {
+ comment = append(comment, t...)
+ }
+ }
+ }
+
+ if saveData.IsValid() && saveData.CanInterface() && saveData.Type().Implements(textUnmarshalerType) {
+ if err := saveData.Interface().(encoding.TextUnmarshaler).UnmarshalText(data); err != nil {
+ return err
+ }
+ saveData = reflect.Value{}
+ }
+
+ if saveData.IsValid() && saveData.CanAddr() {
+ pv := saveData.Addr()
+ if pv.CanInterface() && pv.Type().Implements(textUnmarshalerType) {
+ if err := pv.Interface().(encoding.TextUnmarshaler).UnmarshalText(data); err != nil {
+ return err
+ }
+ saveData = reflect.Value{}
+ }
+ }
+
+ if err := copyValue(saveData, data); err != nil {
+ return err
+ }
+
+ switch t := saveComment; t.Kind() {
+ case reflect.String:
+ t.SetString(string(comment))
+ case reflect.Slice:
+ t.Set(reflect.ValueOf(comment))
+ }
+
+ switch t := saveXML; t.Kind() {
+ case reflect.String:
+ t.SetString(string(saveXMLData))
+ case reflect.Slice:
+ t.Set(reflect.ValueOf(saveXMLData))
+ }
+
+ return nil
+}
+
+func copyValue(dst reflect.Value, src []byte) (err error) {
+ dst0 := dst
+
+ if dst.Kind() == reflect.Ptr {
+ if dst.IsNil() {
+ dst.Set(reflect.New(dst.Type().Elem()))
+ }
+ dst = dst.Elem()
+ }
+
+ // Save accumulated data.
+ switch dst.Kind() {
+ case reflect.Invalid:
+ // Probably a comment.
+ default:
+ return errors.New("cannot unmarshal into " + dst0.Type().String())
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ itmp, err := strconv.ParseInt(string(src), 10, dst.Type().Bits())
+ if err != nil {
+ return err
+ }
+ dst.SetInt(itmp)
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ utmp, err := strconv.ParseUint(string(src), 10, dst.Type().Bits())
+ if err != nil {
+ return err
+ }
+ dst.SetUint(utmp)
+ case reflect.Float32, reflect.Float64:
+ ftmp, err := strconv.ParseFloat(string(src), dst.Type().Bits())
+ if err != nil {
+ return err
+ }
+ dst.SetFloat(ftmp)
+ case reflect.Bool:
+ value, err := strconv.ParseBool(strings.TrimSpace(string(src)))
+ if err != nil {
+ return err
+ }
+ dst.SetBool(value)
+ case reflect.String:
+ dst.SetString(string(src))
+ case reflect.Slice:
+ if len(src) == 0 {
+ // non-nil to flag presence
+ src = []byte{}
+ }
+ dst.SetBytes(src)
+ }
+ return nil
+}
+
+// unmarshalPath walks down an XML structure looking for wanted
+// paths, and calls unmarshal on them.
+// The consumed result tells whether XML elements have been consumed
+// from the Decoder until start's matching end element, or if it's
+// still untouched because start is uninteresting for sv's fields.
+func (p *Decoder) unmarshalPath(tinfo *typeInfo, sv reflect.Value, parents []string, start *StartElement) (consumed bool, err error) {
+ recurse := false
+Loop:
+ for i := range tinfo.fields {
+ finfo := &tinfo.fields[i]
+ if finfo.flags&fElement == 0 || len(finfo.parents) < len(parents) || finfo.xmlns != "" && finfo.xmlns != start.Name.Space {
+ continue
+ }
+ for j := range parents {
+ if parents[j] != finfo.parents[j] {
+ continue Loop
+ }
+ }
+ if len(finfo.parents) == len(parents) && finfo.name == start.Name.Local {
+ // It's a perfect match, unmarshal the field.
+ return true, p.unmarshal(finfo.value(sv), start)
+ }
+ if len(finfo.parents) > len(parents) && finfo.parents[len(parents)] == start.Name.Local {
+ // It's a prefix for the field. Break and recurse
+ // since it's not ok for one field path to be itself
+ // the prefix for another field path.
+ recurse = true
+
+ // We can reuse the same slice as long as we
+ // don't try to append to it.
+ parents = finfo.parents[:len(parents)+1]
+ break
+ }
+ }
+ if !recurse {
+ // We have no business with this element.
+ return false, nil
+ }
+ // The element is not a perfect match for any field, but one
+ // or more fields have the path to this element as a parent
+ // prefix. Recurse and attempt to match these.
+ for {
+ var tok Token
+ tok, err = p.Token()
+ if err != nil {
+ return true, err
+ }
+ switch t := tok.(type) {
+ case StartElement:
+ consumed2, err := p.unmarshalPath(tinfo, sv, parents, &t)
+ if err != nil {
+ return true, err
+ }
+ if !consumed2 {
+ if err := p.Skip(); err != nil {
+ return true, err
+ }
+ }
+ case EndElement:
+ return true, nil
+ }
+ }
+}
+
+// Skip reads tokens until it has consumed the end element
+// matching the most recent start element already consumed.
+// It recurs if it encounters a start element, so it can be used to
+// skip nested structures.
+// It returns nil if it finds an end element matching the start
+// element; otherwise it returns an error describing the problem.
+func (d *Decoder) Skip() error {
+ for {
+ tok, err := d.Token()
+ if err != nil {
+ return err
+ }
+ switch tok.(type) {
+ case StartElement:
+ if err := d.Skip(); err != nil {
+ return err
+ }
+ case EndElement:
+ return nil
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/internal/xml/read_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/internal/xml/read_test.go
new file mode 100644
index 000000000..02f1e10c3
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/internal/xml/read_test.go
@@ -0,0 +1,744 @@
+// Copyright 2009 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 xml
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "reflect"
+ "strings"
+ "testing"
+ "time"
+)
+
+// Stripped down Atom feed data structures.
+
+func TestUnmarshalFeed(t *testing.T) {
+ var f Feed
+ if err := Unmarshal([]byte(atomFeedString), &f); err != nil {
+ t.Fatalf("Unmarshal: %s", err)
+ }
+ if !reflect.DeepEqual(f, atomFeed) {
+ t.Fatalf("have %#v\nwant %#v", f, atomFeed)
+ }
+}
+
+// hget http://codereview.appspot.com/rss/mine/rsc
+const atomFeedString = `
+<?xml version="1.0" encoding="utf-8"?>
+<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-us" updated="2009-10-04T01:35:58+00:00"><title>Code Review - My issues</title><link href="http://codereview.appspot.com/" rel="alternate"></link><link href="http://codereview.appspot.com/rss/mine/rsc" rel="self"></link><id>http://codereview.appspot.com/</id><author><name>rietveld&lt;&gt;</name></author><entry><title>rietveld: an attempt at pubsubhubbub
+</title><link href="http://codereview.appspot.com/126085" rel="alternate"></link><updated>2009-10-04T01:35:58+00:00</updated><author><name>email-address-removed</name></author><id>urn:md5:134d9179c41f806be79b3a5f7877d19a</id><summary type="html">
+ An attempt at adding pubsubhubbub support to Rietveld.
+http://code.google.com/p/pubsubhubbub
+http://code.google.com/p/rietveld/issues/detail?id=155
+
+The server side of the protocol is trivial:
+ 1. add a &amp;lt;link rel=&amp;quot;hub&amp;quot; href=&amp;quot;hub-server&amp;quot;&amp;gt; tag to all
+ feeds that will be pubsubhubbubbed.
+ 2. every time one of those feeds changes, tell the hub
+ with a simple POST request.
+
+I have tested this by adding debug prints to a local hub
+server and checking that the server got the right publish
+requests.
+
+I can&amp;#39;t quite get the server to work, but I think the bug
+is not in my code. I think that the server expects to be
+able to grab the feed and see the feed&amp;#39;s actual URL in
+the link rel=&amp;quot;self&amp;quot;, but the default value for that drops
+the :port from the URL, and I cannot for the life of me
+figure out how to get the Atom generator deep inside
+django not to do that, or even where it is doing that,
+or even what code is running to generate the Atom feed.
+(I thought I knew but I added some assert False statements
+and it kept running!)
+
+Ignoring that particular problem, I would appreciate
+feedback on the right way to get the two values at
+the top of feeds.py marked NOTE(rsc).
+
+
+</summary></entry><entry><title>rietveld: correct tab handling
+</title><link href="http://codereview.appspot.com/124106" rel="alternate"></link><updated>2009-10-03T23:02:17+00:00</updated><author><name>email-address-removed</name></author><id>urn:md5:0a2a4f19bb815101f0ba2904aed7c35a</id><summary type="html">
+ This fixes the buggy tab rendering that can be seen at
+http://codereview.appspot.com/116075/diff/1/2
+
+The fundamental problem was that the tab code was
+not being told what column the text began in, so it
+didn&amp;#39;t know where to put the tab stops. Another problem
+was that some of the code assumed that string byte
+offsets were the same as column offsets, which is only
+true if there are no tabs.
+
+In the process of fixing this, I cleaned up the arguments
+to Fold and ExpandTabs and renamed them Break and
+_ExpandTabs so that I could be sure that I found all the
+call sites. I also wanted to verify that ExpandTabs was
+not being used from outside intra_region_diff.py.
+
+
+</summary></entry></feed> `
+
+type Feed struct {
+ XMLName Name `xml:"http://www.w3.org/2005/Atom feed"`
+ Title string `xml:"title"`
+ Id string `xml:"id"`
+ Link []Link `xml:"link"`
+ Updated time.Time `xml:"updated,attr"`
+ Author Person `xml:"author"`
+ Entry []Entry `xml:"entry"`
+}
+
+type Entry struct {
+ Title string `xml:"title"`
+ Id string `xml:"id"`
+ Link []Link `xml:"link"`
+ Updated time.Time `xml:"updated"`
+ Author Person `xml:"author"`
+ Summary Text `xml:"summary"`
+}
+
+type Link struct {
+ Rel string `xml:"rel,attr,omitempty"`
+ Href string `xml:"href,attr"`
+}
+
+type Person struct {
+ Name string `xml:"name"`
+ URI string `xml:"uri"`
+ Email string `xml:"email"`
+ InnerXML string `xml:",innerxml"`
+}
+
+type Text struct {
+ Type string `xml:"type,attr,omitempty"`
+ Body string `xml:",chardata"`
+}
+
+var atomFeed = Feed{
+ XMLName: Name{"http://www.w3.org/2005/Atom", "feed"},
+ Title: "Code Review - My issues",
+ Link: []Link{
+ {Rel: "alternate", Href: "http://codereview.appspot.com/"},
+ {Rel: "self", Href: "http://codereview.appspot.com/rss/mine/rsc"},
+ },
+ Id: "http://codereview.appspot.com/",
+ Updated: ParseTime("2009-10-04T01:35:58+00:00"),
+ Author: Person{
+ Name: "rietveld<>",
+ InnerXML: "<name>rietveld&lt;&gt;</name>",
+ },
+ Entry: []Entry{
+ {
+ Title: "rietveld: an attempt at pubsubhubbub\n",
+ Link: []Link{
+ {Rel: "alternate", Href: "http://codereview.appspot.com/126085"},
+ },
+ Updated: ParseTime("2009-10-04T01:35:58+00:00"),
+ Author: Person{
+ Name: "email-address-removed",
+ InnerXML: "<name>email-address-removed</name>",
+ },
+ Id: "urn:md5:134d9179c41f806be79b3a5f7877d19a",
+ Summary: Text{
+ Type: "html",
+ Body: `
+ An attempt at adding pubsubhubbub support to Rietveld.
+http://code.google.com/p/pubsubhubbub
+http://code.google.com/p/rietveld/issues/detail?id=155
+
+The server side of the protocol is trivial:
+ 1. add a &lt;link rel=&quot;hub&quot; href=&quot;hub-server&quot;&gt; tag to all
+ feeds that will be pubsubhubbubbed.
+ 2. every time one of those feeds changes, tell the hub
+ with a simple POST request.
+
+I have tested this by adding debug prints to a local hub
+server and checking that the server got the right publish
+requests.
+
+I can&#39;t quite get the server to work, but I think the bug
+is not in my code. I think that the server expects to be
+able to grab the feed and see the feed&#39;s actual URL in
+the link rel=&quot;self&quot;, but the default value for that drops
+the :port from the URL, and I cannot for the life of me
+figure out how to get the Atom generator deep inside
+django not to do that, or even where it is doing that,
+or even what code is running to generate the Atom feed.
+(I thought I knew but I added some assert False statements
+and it kept running!)
+
+Ignoring that particular problem, I would appreciate
+feedback on the right way to get the two values at
+the top of feeds.py marked NOTE(rsc).
+
+
+`,
+ },
+ },
+ {
+ Title: "rietveld: correct tab handling\n",
+ Link: []Link{
+ {Rel: "alternate", Href: "http://codereview.appspot.com/124106"},
+ },
+ Updated: ParseTime("2009-10-03T23:02:17+00:00"),
+ Author: Person{
+ Name: "email-address-removed",
+ InnerXML: "<name>email-address-removed</name>",
+ },
+ Id: "urn:md5:0a2a4f19bb815101f0ba2904aed7c35a",
+ Summary: Text{
+ Type: "html",
+ Body: `
+ This fixes the buggy tab rendering that can be seen at
+http://codereview.appspot.com/116075/diff/1/2
+
+The fundamental problem was that the tab code was
+not being told what column the text began in, so it
+didn&#39;t know where to put the tab stops. Another problem
+was that some of the code assumed that string byte
+offsets were the same as column offsets, which is only
+true if there are no tabs.
+
+In the process of fixing this, I cleaned up the arguments
+to Fold and ExpandTabs and renamed them Break and
+_ExpandTabs so that I could be sure that I found all the
+call sites. I also wanted to verify that ExpandTabs was
+not being used from outside intra_region_diff.py.
+
+
+`,
+ },
+ },
+ },
+}
+
+const pathTestString = `
+<Result>
+ <Before>1</Before>
+ <Items>
+ <Item1>
+ <Value>A</Value>
+ </Item1>
+ <Item2>
+ <Value>B</Value>
+ </Item2>
+ <Item1>
+ <Value>C</Value>
+ <Value>D</Value>
+ </Item1>
+ <_>
+ <Value>E</Value>
+ </_>
+ </Items>
+ <After>2</After>
+</Result>
+`
+
+type PathTestItem struct {
+ Value string
+}
+
+type PathTestA struct {
+ Items []PathTestItem `xml:">Item1"`
+ Before, After string
+}
+
+type PathTestB struct {
+ Other []PathTestItem `xml:"Items>Item1"`
+ Before, After string
+}
+
+type PathTestC struct {
+ Values1 []string `xml:"Items>Item1>Value"`
+ Values2 []string `xml:"Items>Item2>Value"`
+ Before, After string
+}
+
+type PathTestSet struct {
+ Item1 []PathTestItem
+}
+
+type PathTestD struct {
+ Other PathTestSet `xml:"Items"`
+ Before, After string
+}
+
+type PathTestE struct {
+ Underline string `xml:"Items>_>Value"`
+ Before, After string
+}
+
+var pathTests = []interface{}{
+ &PathTestA{Items: []PathTestItem{{"A"}, {"D"}}, Before: "1", After: "2"},
+ &PathTestB{Other: []PathTestItem{{"A"}, {"D"}}, Before: "1", After: "2"},
+ &PathTestC{Values1: []string{"A", "C", "D"}, Values2: []string{"B"}, Before: "1", After: "2"},
+ &PathTestD{Other: PathTestSet{Item1: []PathTestItem{{"A"}, {"D"}}}, Before: "1", After: "2"},
+ &PathTestE{Underline: "E", Before: "1", After: "2"},
+}
+
+func TestUnmarshalPaths(t *testing.T) {
+ for _, pt := range pathTests {
+ v := reflect.New(reflect.TypeOf(pt).Elem()).Interface()
+ if err := Unmarshal([]byte(pathTestString), v); err != nil {
+ t.Fatalf("Unmarshal: %s", err)
+ }
+ if !reflect.DeepEqual(v, pt) {
+ t.Fatalf("have %#v\nwant %#v", v, pt)
+ }
+ }
+}
+
+type BadPathTestA struct {
+ First string `xml:"items>item1"`
+ Other string `xml:"items>item2"`
+ Second string `xml:"items"`
+}
+
+type BadPathTestB struct {
+ Other string `xml:"items>item2>value"`
+ First string `xml:"items>item1"`
+ Second string `xml:"items>item1>value"`
+}
+
+type BadPathTestC struct {
+ First string
+ Second string `xml:"First"`
+}
+
+type BadPathTestD struct {
+ BadPathEmbeddedA
+ BadPathEmbeddedB
+}
+
+type BadPathEmbeddedA struct {
+ First string
+}
+
+type BadPathEmbeddedB struct {
+ Second string `xml:"First"`
+}
+
+var badPathTests = []struct {
+ v, e interface{}
+}{
+ {&BadPathTestA{}, &TagPathError{reflect.TypeOf(BadPathTestA{}), "First", "items>item1", "Second", "items"}},
+ {&BadPathTestB{}, &TagPathError{reflect.TypeOf(BadPathTestB{}), "First", "items>item1", "Second", "items>item1>value"}},
+ {&BadPathTestC{}, &TagPathError{reflect.TypeOf(BadPathTestC{}), "First", "", "Second", "First"}},
+ {&BadPathTestD{}, &TagPathError{reflect.TypeOf(BadPathTestD{}), "First", "", "Second", "First"}},
+}
+
+func TestUnmarshalBadPaths(t *testing.T) {
+ for _, tt := range badPathTests {
+ err := Unmarshal([]byte(pathTestString), tt.v)
+ if !reflect.DeepEqual(err, tt.e) {
+ t.Fatalf("Unmarshal with %#v didn't fail properly:\nhave %#v,\nwant %#v", tt.v, err, tt.e)
+ }
+ }
+}
+
+const OK = "OK"
+const withoutNameTypeData = `
+<?xml version="1.0" charset="utf-8"?>
+<Test3 Attr="OK" />`
+
+type TestThree struct {
+ XMLName Name `xml:"Test3"`
+ Attr string `xml:",attr"`
+}
+
+func TestUnmarshalWithoutNameType(t *testing.T) {
+ var x TestThree
+ if err := Unmarshal([]byte(withoutNameTypeData), &x); err != nil {
+ t.Fatalf("Unmarshal: %s", err)
+ }
+ if x.Attr != OK {
+ t.Fatalf("have %v\nwant %v", x.Attr, OK)
+ }
+}
+
+func TestUnmarshalAttr(t *testing.T) {
+ type ParamVal struct {
+ Int int `xml:"int,attr"`
+ }
+
+ type ParamPtr struct {
+ Int *int `xml:"int,attr"`
+ }
+
+ type ParamStringPtr struct {
+ Int *string `xml:"int,attr"`
+ }
+
+ x := []byte(`<Param int="1" />`)
+
+ p1 := &ParamPtr{}
+ if err := Unmarshal(x, p1); err != nil {
+ t.Fatalf("Unmarshal: %s", err)
+ }
+ if p1.Int == nil {
+ t.Fatalf("Unmarshal failed in to *int field")
+ } else if *p1.Int != 1 {
+ t.Fatalf("Unmarshal with %s failed:\nhave %#v,\n want %#v", x, p1.Int, 1)
+ }
+
+ p2 := &ParamVal{}
+ if err := Unmarshal(x, p2); err != nil {
+ t.Fatalf("Unmarshal: %s", err)
+ }
+ if p2.Int != 1 {
+ t.Fatalf("Unmarshal with %s failed:\nhave %#v,\n want %#v", x, p2.Int, 1)
+ }
+
+ p3 := &ParamStringPtr{}
+ if err := Unmarshal(x, p3); err != nil {
+ t.Fatalf("Unmarshal: %s", err)
+ }
+ if p3.Int == nil {
+ t.Fatalf("Unmarshal failed in to *string field")
+ } else if *p3.Int != "1" {
+ t.Fatalf("Unmarshal with %s failed:\nhave %#v,\n want %#v", x, p3.Int, 1)
+ }
+}
+
+type Tables struct {
+ HTable string `xml:"http://www.w3.org/TR/html4/ table"`
+ FTable string `xml:"http://www.w3schools.com/furniture table"`
+}
+
+var tables = []struct {
+ xml string
+ tab Tables
+ ns string
+}{
+ {
+ xml: `<Tables>` +
+ `<table xmlns="http://www.w3.org/TR/html4/">hello</table>` +
+ `<table xmlns="http://www.w3schools.com/furniture">world</table>` +
+ `</Tables>`,
+ tab: Tables{"hello", "world"},
+ },
+ {
+ xml: `<Tables>` +
+ `<table xmlns="http://www.w3schools.com/furniture">world</table>` +
+ `<table xmlns="http://www.w3.org/TR/html4/">hello</table>` +
+ `</Tables>`,
+ tab: Tables{"hello", "world"},
+ },
+ {
+ xml: `<Tables xmlns:f="http://www.w3schools.com/furniture" xmlns:h="http://www.w3.org/TR/html4/">` +
+ `<f:table>world</f:table>` +
+ `<h:table>hello</h:table>` +
+ `</Tables>`,
+ tab: Tables{"hello", "world"},
+ },
+ {
+ xml: `<Tables>` +
+ `<table>bogus</table>` +
+ `</Tables>`,
+ tab: Tables{},
+ },
+ {
+ xml: `<Tables>` +
+ `<table>only</table>` +
+ `</Tables>`,
+ tab: Tables{HTable: "only"},
+ ns: "http://www.w3.org/TR/html4/",
+ },
+ {
+ xml: `<Tables>` +
+ `<table>only</table>` +
+ `</Tables>`,
+ tab: Tables{FTable: "only"},
+ ns: "http://www.w3schools.com/furniture",
+ },
+ {
+ xml: `<Tables>` +
+ `<table>only</table>` +
+ `</Tables>`,
+ tab: Tables{},
+ ns: "something else entirely",
+ },
+}
+
+func TestUnmarshalNS(t *testing.T) {
+ for i, tt := range tables {
+ var dst Tables
+ var err error
+ if tt.ns != "" {
+ d := NewDecoder(strings.NewReader(tt.xml))
+ d.DefaultSpace = tt.ns
+ err = d.Decode(&dst)
+ } else {
+ err = Unmarshal([]byte(tt.xml), &dst)
+ }
+ if err != nil {
+ t.Errorf("#%d: Unmarshal: %v", i, err)
+ continue
+ }
+ want := tt.tab
+ if dst != want {
+ t.Errorf("#%d: dst=%+v, want %+v", i, dst, want)
+ }
+ }
+}
+
+func TestRoundTrip(t *testing.T) {
+ // From issue 7535
+ const s = `<ex:element xmlns:ex="http://example.com/schema"></ex:element>`
+ in := bytes.NewBufferString(s)
+ for i := 0; i < 10; i++ {
+ out := &bytes.Buffer{}
+ d := NewDecoder(in)
+ e := NewEncoder(out)
+
+ for {
+ t, err := d.Token()
+ if err == io.EOF {
+ break
+ }
+ if err != nil {
+ fmt.Println("failed:", err)
+ return
+ }
+ e.EncodeToken(t)
+ }
+ e.Flush()
+ in = out
+ }
+ if got := in.String(); got != s {
+ t.Errorf("have: %q\nwant: %q\n", got, s)
+ }
+}
+
+func TestMarshalNS(t *testing.T) {
+ dst := Tables{"hello", "world"}
+ data, err := Marshal(&dst)
+ if err != nil {
+ t.Fatalf("Marshal: %v", err)
+ }
+ want := `<Tables><table xmlns="http://www.w3.org/TR/html4/">hello</table><table xmlns="http://www.w3schools.com/furniture">world</table></Tables>`
+ str := string(data)
+ if str != want {
+ t.Errorf("have: %q\nwant: %q\n", str, want)
+ }
+}
+
+type TableAttrs struct {
+ TAttr TAttr
+}
+
+type TAttr struct {
+ HTable string `xml:"http://www.w3.org/TR/html4/ table,attr"`
+ FTable string `xml:"http://www.w3schools.com/furniture table,attr"`
+ Lang string `xml:"http://www.w3.org/XML/1998/namespace lang,attr,omitempty"`
+ Other1 string `xml:"http://golang.org/xml/ other,attr,omitempty"`
+ Other2 string `xml:"http://golang.org/xmlfoo/ other,attr,omitempty"`
+ Other3 string `xml:"http://golang.org/json/ other,attr,omitempty"`
+ Other4 string `xml:"http://golang.org/2/json/ other,attr,omitempty"`
+}
+
+var tableAttrs = []struct {
+ xml string
+ tab TableAttrs
+ ns string
+}{
+ {
+ xml: `<TableAttrs xmlns:f="http://www.w3schools.com/furniture" xmlns:h="http://www.w3.org/TR/html4/"><TAttr ` +
+ `h:table="hello" f:table="world" ` +
+ `/></TableAttrs>`,
+ tab: TableAttrs{TAttr{HTable: "hello", FTable: "world"}},
+ },
+ {
+ xml: `<TableAttrs><TAttr xmlns:f="http://www.w3schools.com/furniture" xmlns:h="http://www.w3.org/TR/html4/" ` +
+ `h:table="hello" f:table="world" ` +
+ `/></TableAttrs>`,
+ tab: TableAttrs{TAttr{HTable: "hello", FTable: "world"}},
+ },
+ {
+ xml: `<TableAttrs><TAttr ` +
+ `h:table="hello" f:table="world" xmlns:f="http://www.w3schools.com/furniture" xmlns:h="http://www.w3.org/TR/html4/" ` +
+ `/></TableAttrs>`,
+ tab: TableAttrs{TAttr{HTable: "hello", FTable: "world"}},
+ },
+ {
+ // Default space does not apply to attribute names.
+ xml: `<TableAttrs xmlns="http://www.w3schools.com/furniture" xmlns:h="http://www.w3.org/TR/html4/"><TAttr ` +
+ `h:table="hello" table="world" ` +
+ `/></TableAttrs>`,
+ tab: TableAttrs{TAttr{HTable: "hello", FTable: ""}},
+ },
+ {
+ // Default space does not apply to attribute names.
+ xml: `<TableAttrs xmlns:f="http://www.w3schools.com/furniture"><TAttr xmlns="http://www.w3.org/TR/html4/" ` +
+ `table="hello" f:table="world" ` +
+ `/></TableAttrs>`,
+ tab: TableAttrs{TAttr{HTable: "", FTable: "world"}},
+ },
+ {
+ xml: `<TableAttrs><TAttr ` +
+ `table="bogus" ` +
+ `/></TableAttrs>`,
+ tab: TableAttrs{},
+ },
+ {
+ // Default space does not apply to attribute names.
+ xml: `<TableAttrs xmlns:h="http://www.w3.org/TR/html4/"><TAttr ` +
+ `h:table="hello" table="world" ` +
+ `/></TableAttrs>`,
+ tab: TableAttrs{TAttr{HTable: "hello", FTable: ""}},
+ ns: "http://www.w3schools.com/furniture",
+ },
+ {
+ // Default space does not apply to attribute names.
+ xml: `<TableAttrs xmlns:f="http://www.w3schools.com/furniture"><TAttr ` +
+ `table="hello" f:table="world" ` +
+ `/></TableAttrs>`,
+ tab: TableAttrs{TAttr{HTable: "", FTable: "world"}},
+ ns: "http://www.w3.org/TR/html4/",
+ },
+ {
+ xml: `<TableAttrs><TAttr ` +
+ `table="bogus" ` +
+ `/></TableAttrs>`,
+ tab: TableAttrs{},
+ ns: "something else entirely",
+ },
+}
+
+func TestUnmarshalNSAttr(t *testing.T) {
+ for i, tt := range tableAttrs {
+ var dst TableAttrs
+ var err error
+ if tt.ns != "" {
+ d := NewDecoder(strings.NewReader(tt.xml))
+ d.DefaultSpace = tt.ns
+ err = d.Decode(&dst)
+ } else {
+ err = Unmarshal([]byte(tt.xml), &dst)
+ }
+ if err != nil {
+ t.Errorf("#%d: Unmarshal: %v", i, err)
+ continue
+ }
+ want := tt.tab
+ if dst != want {
+ t.Errorf("#%d: dst=%+v, want %+v", i, dst, want)
+ }
+ }
+}
+
+func TestMarshalNSAttr(t *testing.T) {
+ src := TableAttrs{TAttr{"hello", "world", "en_US", "other1", "other2", "other3", "other4"}}
+ data, err := Marshal(&src)
+ if err != nil {
+ t.Fatalf("Marshal: %v", err)
+ }
+ want := `<TableAttrs><TAttr xmlns:json_1="http://golang.org/2/json/" xmlns:json="http://golang.org/json/" xmlns:_xmlfoo="http://golang.org/xmlfoo/" xmlns:_xml="http://golang.org/xml/" xmlns:furniture="http://www.w3schools.com/furniture" xmlns:html4="http://www.w3.org/TR/html4/" html4:table="hello" furniture:table="world" xml:lang="en_US" _xml:other="other1" _xmlfoo:other="other2" json:other="other3" json_1:other="other4"></TAttr></TableAttrs>`
+ str := string(data)
+ if str != want {
+ t.Errorf("Marshal:\nhave: %#q\nwant: %#q\n", str, want)
+ }
+
+ var dst TableAttrs
+ if err := Unmarshal(data, &dst); err != nil {
+ t.Errorf("Unmarshal: %v", err)
+ }
+
+ if dst != src {
+ t.Errorf("Unmarshal = %q, want %q", dst, src)
+ }
+}
+
+type MyCharData struct {
+ body string
+}
+
+func (m *MyCharData) UnmarshalXML(d *Decoder, start StartElement) error {
+ for {
+ t, err := d.Token()
+ if err == io.EOF { // found end of element
+ break
+ }
+ if err != nil {
+ return err
+ }
+ if char, ok := t.(CharData); ok {
+ m.body += string(char)
+ }
+ }
+ return nil
+}
+
+var _ Unmarshaler = (*MyCharData)(nil)
+
+func (m *MyCharData) UnmarshalXMLAttr(attr Attr) error {
+ panic("must not call")
+}
+
+type MyAttr struct {
+ attr string
+}
+
+func (m *MyAttr) UnmarshalXMLAttr(attr Attr) error {
+ m.attr = attr.Value
+ return nil
+}
+
+var _ UnmarshalerAttr = (*MyAttr)(nil)
+
+type MyStruct struct {
+ Data *MyCharData
+ Attr *MyAttr `xml:",attr"`
+
+ Data2 MyCharData
+ Attr2 MyAttr `xml:",attr"`
+}
+
+func TestUnmarshaler(t *testing.T) {
+ xml := `<?xml version="1.0" encoding="utf-8"?>
+ <MyStruct Attr="attr1" Attr2="attr2">
+ <Data>hello <!-- comment -->world</Data>
+ <Data2>howdy <!-- comment -->world</Data2>
+ </MyStruct>
+ `
+
+ var m MyStruct
+ if err := Unmarshal([]byte(xml), &m); err != nil {
+ t.Fatal(err)
+ }
+
+ if m.Data == nil || m.Attr == nil || m.Data.body != "hello world" || m.Attr.attr != "attr1" || m.Data2.body != "howdy world" || m.Attr2.attr != "attr2" {
+ t.Errorf("m=%#+v\n", m)
+ }
+}
+
+type Pea struct {
+ Cotelydon string
+}
+
+type Pod struct {
+ Pea interface{} `xml:"Pea"`
+}
+
+// https://golang.org/issue/6836
+func TestUnmarshalIntoInterface(t *testing.T) {
+ pod := new(Pod)
+ pod.Pea = new(Pea)
+ xml := `<Pod><Pea><Cotelydon>Green stuff</Cotelydon></Pea></Pod>`
+ err := Unmarshal([]byte(xml), pod)
+ if err != nil {
+ t.Fatalf("failed to unmarshal %q: %v", xml, err)
+ }
+ pea, ok := pod.Pea.(*Pea)
+ if !ok {
+ t.Fatalf("unmarshalled into wrong type: have %T want *Pea", pod.Pea)
+ }
+ have, want := pea.Cotelydon, "Green stuff"
+ if have != want {
+ t.Errorf("failed to unmarshal into interface, have %q want %q", have, want)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/internal/xml/typeinfo.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/internal/xml/typeinfo.go
new file mode 100644
index 000000000..fdde288bc
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/internal/xml/typeinfo.go
@@ -0,0 +1,371 @@
+// Copyright 2011 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 xml
+
+import (
+ "fmt"
+ "reflect"
+ "strings"
+ "sync"
+)
+
+// typeInfo holds details for the xml representation of a type.
+type typeInfo struct {
+ xmlname *fieldInfo
+ fields []fieldInfo
+}
+
+// fieldInfo holds details for the xml representation of a single field.
+type fieldInfo struct {
+ idx []int
+ name string
+ xmlns string
+ flags fieldFlags
+ parents []string
+}
+
+type fieldFlags int
+
+const (
+ fElement fieldFlags = 1 << iota
+ fAttr
+ fCharData
+ fInnerXml
+ fComment
+ fAny
+
+ fOmitEmpty
+
+ fMode = fElement | fAttr | fCharData | fInnerXml | fComment | fAny
+)
+
+var tinfoMap = make(map[reflect.Type]*typeInfo)
+var tinfoLock sync.RWMutex
+
+var nameType = reflect.TypeOf(Name{})
+
+// getTypeInfo returns the typeInfo structure with details necessary
+// for marshalling and unmarshalling typ.
+func getTypeInfo(typ reflect.Type) (*typeInfo, error) {
+ tinfoLock.RLock()
+ tinfo, ok := tinfoMap[typ]
+ tinfoLock.RUnlock()
+ if ok {
+ return tinfo, nil
+ }
+ tinfo = &typeInfo{}
+ if typ.Kind() == reflect.Struct && typ != nameType {
+ n := typ.NumField()
+ for i := 0; i < n; i++ {
+ f := typ.Field(i)
+ if f.PkgPath != "" || f.Tag.Get("xml") == "-" {
+ continue // Private field
+ }
+
+ // For embedded structs, embed its fields.
+ if f.Anonymous {
+ t := f.Type
+ if t.Kind() == reflect.Ptr {
+ t = t.Elem()
+ }
+ if t.Kind() == reflect.Struct {
+ inner, err := getTypeInfo(t)
+ if err != nil {
+ return nil, err
+ }
+ if tinfo.xmlname == nil {
+ tinfo.xmlname = inner.xmlname
+ }
+ for _, finfo := range inner.fields {
+ finfo.idx = append([]int{i}, finfo.idx...)
+ if err := addFieldInfo(typ, tinfo, &finfo); err != nil {
+ return nil, err
+ }
+ }
+ continue
+ }
+ }
+
+ finfo, err := structFieldInfo(typ, &f)
+ if err != nil {
+ return nil, err
+ }
+
+ if f.Name == "XMLName" {
+ tinfo.xmlname = finfo
+ continue
+ }
+
+ // Add the field if it doesn't conflict with other fields.
+ if err := addFieldInfo(typ, tinfo, finfo); err != nil {
+ return nil, err
+ }
+ }
+ }
+ tinfoLock.Lock()
+ tinfoMap[typ] = tinfo
+ tinfoLock.Unlock()
+ return tinfo, nil
+}
+
+// structFieldInfo builds and returns a fieldInfo for f.
+func structFieldInfo(typ reflect.Type, f *reflect.StructField) (*fieldInfo, error) {
+ finfo := &fieldInfo{idx: f.Index}
+
+ // Split the tag from the xml namespace if necessary.
+ tag := f.Tag.Get("xml")
+ if i := strings.Index(tag, " "); i >= 0 {
+ finfo.xmlns, tag = tag[:i], tag[i+1:]
+ }
+
+ // Parse flags.
+ tokens := strings.Split(tag, ",")
+ if len(tokens) == 1 {
+ finfo.flags = fElement
+ } else {
+ tag = tokens[0]
+ for _, flag := range tokens[1:] {
+ switch flag {
+ case "attr":
+ finfo.flags |= fAttr
+ case "chardata":
+ finfo.flags |= fCharData
+ case "innerxml":
+ finfo.flags |= fInnerXml
+ case "comment":
+ finfo.flags |= fComment
+ case "any":
+ finfo.flags |= fAny
+ case "omitempty":
+ finfo.flags |= fOmitEmpty
+ }
+ }
+
+ // Validate the flags used.
+ valid := true
+ switch mode := finfo.flags & fMode; mode {
+ case 0:
+ finfo.flags |= fElement
+ case fAttr, fCharData, fInnerXml, fComment, fAny:
+ if f.Name == "XMLName" || tag != "" && mode != fAttr {
+ valid = false
+ }
+ default:
+ // This will also catch multiple modes in a single field.
+ valid = false
+ }
+ if finfo.flags&fMode == fAny {
+ finfo.flags |= fElement
+ }
+ if finfo.flags&fOmitEmpty != 0 && finfo.flags&(fElement|fAttr) == 0 {
+ valid = false
+ }
+ if !valid {
+ return nil, fmt.Errorf("xml: invalid tag in field %s of type %s: %q",
+ f.Name, typ, f.Tag.Get("xml"))
+ }
+ }
+
+ // Use of xmlns without a name is not allowed.
+ if finfo.xmlns != "" && tag == "" {
+ return nil, fmt.Errorf("xml: namespace without name in field %s of type %s: %q",
+ f.Name, typ, f.Tag.Get("xml"))
+ }
+
+ if f.Name == "XMLName" {
+ // The XMLName field records the XML element name. Don't
+ // process it as usual because its name should default to
+ // empty rather than to the field name.
+ finfo.name = tag
+ return finfo, nil
+ }
+
+ if tag == "" {
+ // If the name part of the tag is completely empty, get
+ // default from XMLName of underlying struct if feasible,
+ // or field name otherwise.
+ if xmlname := lookupXMLName(f.Type); xmlname != nil {
+ finfo.xmlns, finfo.name = xmlname.xmlns, xmlname.name
+ } else {
+ finfo.name = f.Name
+ }
+ return finfo, nil
+ }
+
+ if finfo.xmlns == "" && finfo.flags&fAttr == 0 {
+ // If it's an element no namespace specified, get the default
+ // from the XMLName of enclosing struct if possible.
+ if xmlname := lookupXMLName(typ); xmlname != nil {
+ finfo.xmlns = xmlname.xmlns
+ }
+ }
+
+ // Prepare field name and parents.
+ parents := strings.Split(tag, ">")
+ if parents[0] == "" {
+ parents[0] = f.Name
+ }
+ if parents[len(parents)-1] == "" {
+ return nil, fmt.Errorf("xml: trailing '>' in field %s of type %s", f.Name, typ)
+ }
+ finfo.name = parents[len(parents)-1]
+ if len(parents) > 1 {
+ if (finfo.flags & fElement) == 0 {
+ return nil, fmt.Errorf("xml: %s chain not valid with %s flag", tag, strings.Join(tokens[1:], ","))
+ }
+ finfo.parents = parents[:len(parents)-1]
+ }
+
+ // If the field type has an XMLName field, the names must match
+ // so that the behavior of both marshalling and unmarshalling
+ // is straightforward and unambiguous.
+ if finfo.flags&fElement != 0 {
+ ftyp := f.Type
+ xmlname := lookupXMLName(ftyp)
+ if xmlname != nil && xmlname.name != finfo.name {
+ return nil, fmt.Errorf("xml: name %q in tag of %s.%s conflicts with name %q in %s.XMLName",
+ finfo.name, typ, f.Name, xmlname.name, ftyp)
+ }
+ }
+ return finfo, nil
+}
+
+// lookupXMLName returns the fieldInfo for typ's XMLName field
+// in case it exists and has a valid xml field tag, otherwise
+// it returns nil.
+func lookupXMLName(typ reflect.Type) (xmlname *fieldInfo) {
+ for typ.Kind() == reflect.Ptr {
+ typ = typ.Elem()
+ }
+ if typ.Kind() != reflect.Struct {
+ return nil
+ }
+ for i, n := 0, typ.NumField(); i < n; i++ {
+ f := typ.Field(i)
+ if f.Name != "XMLName" {
+ continue
+ }
+ finfo, err := structFieldInfo(typ, &f)
+ if finfo.name != "" && err == nil {
+ return finfo
+ }
+ // Also consider errors as a non-existent field tag
+ // and let getTypeInfo itself report the error.
+ break
+ }
+ return nil
+}
+
+func min(a, b int) int {
+ if a <= b {
+ return a
+ }
+ return b
+}
+
+// addFieldInfo adds finfo to tinfo.fields if there are no
+// conflicts, or if conflicts arise from previous fields that were
+// obtained from deeper embedded structures than finfo. In the latter
+// case, the conflicting entries are dropped.
+// A conflict occurs when the path (parent + name) to a field is
+// itself a prefix of another path, or when two paths match exactly.
+// It is okay for field paths to share a common, shorter prefix.
+func addFieldInfo(typ reflect.Type, tinfo *typeInfo, newf *fieldInfo) error {
+ var conflicts []int
+Loop:
+ // First, figure all conflicts. Most working code will have none.
+ for i := range tinfo.fields {
+ oldf := &tinfo.fields[i]
+ if oldf.flags&fMode != newf.flags&fMode {
+ continue
+ }
+ if oldf.xmlns != "" && newf.xmlns != "" && oldf.xmlns != newf.xmlns {
+ continue
+ }
+ minl := min(len(newf.parents), len(oldf.parents))
+ for p := 0; p < minl; p++ {
+ if oldf.parents[p] != newf.parents[p] {
+ continue Loop
+ }
+ }
+ if len(oldf.parents) > len(newf.parents) {
+ if oldf.parents[len(newf.parents)] == newf.name {
+ conflicts = append(conflicts, i)
+ }
+ } else if len(oldf.parents) < len(newf.parents) {
+ if newf.parents[len(oldf.parents)] == oldf.name {
+ conflicts = append(conflicts, i)
+ }
+ } else {
+ if newf.name == oldf.name {
+ conflicts = append(conflicts, i)
+ }
+ }
+ }
+ // Without conflicts, add the new field and return.
+ if conflicts == nil {
+ tinfo.fields = append(tinfo.fields, *newf)
+ return nil
+ }
+
+ // If any conflict is shallower, ignore the new field.
+ // This matches the Go field resolution on embedding.
+ for _, i := range conflicts {
+ if len(tinfo.fields[i].idx) < len(newf.idx) {
+ return nil
+ }
+ }
+
+ // Otherwise, if any of them is at the same depth level, it's an error.
+ for _, i := range conflicts {
+ oldf := &tinfo.fields[i]
+ if len(oldf.idx) == len(newf.idx) {
+ f1 := typ.FieldByIndex(oldf.idx)
+ f2 := typ.FieldByIndex(newf.idx)
+ return &TagPathError{typ, f1.Name, f1.Tag.Get("xml"), f2.Name, f2.Tag.Get("xml")}
+ }
+ }
+
+ // Otherwise, the new field is shallower, and thus takes precedence,
+ // so drop the conflicting fields from tinfo and append the new one.
+ for c := len(conflicts) - 1; c >= 0; c-- {
+ i := conflicts[c]
+ copy(tinfo.fields[i:], tinfo.fields[i+1:])
+ tinfo.fields = tinfo.fields[:len(tinfo.fields)-1]
+ }
+ tinfo.fields = append(tinfo.fields, *newf)
+ return nil
+}
+
+// A TagPathError represents an error in the unmarshalling process
+// caused by the use of field tags with conflicting paths.
+type TagPathError struct {
+ Struct reflect.Type
+ Field1, Tag1 string
+ Field2, Tag2 string
+}
+
+func (e *TagPathError) Error() string {
+ return fmt.Sprintf("%s field %q with tag %q conflicts with field %q with tag %q", e.Struct, e.Field1, e.Tag1, e.Field2, e.Tag2)
+}
+
+// value returns v's field value corresponding to finfo.
+// It's equivalent to v.FieldByIndex(finfo.idx), but initializes
+// and dereferences pointers as necessary.
+func (finfo *fieldInfo) value(v reflect.Value) reflect.Value {
+ for i, x := range finfo.idx {
+ if i > 0 {
+ t := v.Type()
+ if t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Struct {
+ if v.IsNil() {
+ v.Set(reflect.New(v.Type().Elem()))
+ }
+ v = v.Elem()
+ }
+ }
+ v = v.Field(x)
+ }
+ return v
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/internal/xml/xml.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/internal/xml/xml.go
new file mode 100644
index 000000000..5b79cbecb
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/internal/xml/xml.go
@@ -0,0 +1,1998 @@
+// Copyright 2009 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 xml implements a simple XML 1.0 parser that
+// understands XML name spaces.
+package xml
+
+// References:
+// Annotated XML spec: http://www.xml.com/axml/testaxml.htm
+// XML name spaces: http://www.w3.org/TR/REC-xml-names/
+
+// TODO(rsc):
+// Test error handling.
+
+import (
+ "bufio"
+ "bytes"
+ "errors"
+ "fmt"
+ "io"
+ "strconv"
+ "strings"
+ "unicode"
+ "unicode/utf8"
+)
+
+// A SyntaxError represents a syntax error in the XML input stream.
+type SyntaxError struct {
+ Msg string
+ Line int
+}
+
+func (e *SyntaxError) Error() string {
+ return "XML syntax error on line " + strconv.Itoa(e.Line) + ": " + e.Msg
+}
+
+// A Name represents an XML name (Local) annotated with a name space
+// identifier (Space). In tokens returned by Decoder.Token, the Space
+// identifier is given as a canonical URL, not the short prefix used in
+// the document being parsed.
+//
+// As a special case, XML namespace declarations will use the literal
+// string "xmlns" for the Space field instead of the fully resolved URL.
+// See Encoder.EncodeToken for more information on namespace encoding
+// behaviour.
+type Name struct {
+ Space, Local string
+}
+
+// isNamespace reports whether the name is a namespace-defining name.
+func (name Name) isNamespace() bool {
+ return name.Local == "xmlns" || name.Space == "xmlns"
+}
+
+// An Attr represents an attribute in an XML element (Name=Value).
+type Attr struct {
+ Name Name
+ Value string
+}
+
+// A Token is an interface holding one of the token types:
+// StartElement, EndElement, CharData, Comment, ProcInst, or Directive.
+type Token interface{}
+
+// A StartElement represents an XML start element.
+type StartElement struct {
+ Name Name
+ Attr []Attr
+}
+
+func (e StartElement) Copy() StartElement {
+ attrs := make([]Attr, len(e.Attr))
+ copy(attrs, e.Attr)
+ e.Attr = attrs
+ return e
+}
+
+// End returns the corresponding XML end element.
+func (e StartElement) End() EndElement {
+ return EndElement{e.Name}
+}
+
+// setDefaultNamespace sets the namespace of the element
+// as the default for all elements contained within it.
+func (e *StartElement) setDefaultNamespace() {
+ if e.Name.Space == "" {
+ // If there's no namespace on the element, don't
+ // set the default. Strictly speaking this might be wrong, as
+ // we can't tell if the element had no namespace set
+ // or was just using the default namespace.
+ return
+ }
+ // Don't add a default name space if there's already one set.
+ for _, attr := range e.Attr {
+ if attr.Name.Space == "" && attr.Name.Local == "xmlns" {
+ return
+ }
+ }
+ e.Attr = append(e.Attr, Attr{
+ Name: Name{
+ Local: "xmlns",
+ },
+ Value: e.Name.Space,
+ })
+}
+
+// An EndElement represents an XML end element.
+type EndElement struct {
+ Name Name
+}
+
+// A CharData represents XML character data (raw text),
+// in which XML escape sequences have been replaced by
+// the characters they represent.
+type CharData []byte
+
+func makeCopy(b []byte) []byte {
+ b1 := make([]byte, len(b))
+ copy(b1, b)
+ return b1
+}
+
+func (c CharData) Copy() CharData { return CharData(makeCopy(c)) }
+
+// A Comment represents an XML comment of the form <!--comment-->.
+// The bytes do not include the <!-- and --> comment markers.
+type Comment []byte
+
+func (c Comment) Copy() Comment { return Comment(makeCopy(c)) }
+
+// A ProcInst represents an XML processing instruction of the form <?target inst?>
+type ProcInst struct {
+ Target string
+ Inst []byte
+}
+
+func (p ProcInst) Copy() ProcInst {
+ p.Inst = makeCopy(p.Inst)
+ return p
+}
+
+// A Directive represents an XML directive of the form <!text>.
+// The bytes do not include the <! and > markers.
+type Directive []byte
+
+func (d Directive) Copy() Directive { return Directive(makeCopy(d)) }
+
+// CopyToken returns a copy of a Token.
+func CopyToken(t Token) Token {
+ switch v := t.(type) {
+ case CharData:
+ return v.Copy()
+ case Comment:
+ return v.Copy()
+ case Directive:
+ return v.Copy()
+ case ProcInst:
+ return v.Copy()
+ case StartElement:
+ return v.Copy()
+ }
+ return t
+}
+
+// A Decoder represents an XML parser reading a particular input stream.
+// The parser assumes that its input is encoded in UTF-8.
+type Decoder struct {
+ // Strict defaults to true, enforcing the requirements
+ // of the XML specification.
+ // If set to false, the parser allows input containing common
+ // mistakes:
+ // * If an element is missing an end tag, the parser invents
+ // end tags as necessary to keep the return values from Token
+ // properly balanced.
+ // * In attribute values and character data, unknown or malformed
+ // character entities (sequences beginning with &) are left alone.
+ //
+ // Setting:
+ //
+ // d.Strict = false;
+ // d.AutoClose = HTMLAutoClose;
+ // d.Entity = HTMLEntity
+ //
+ // creates a parser that can handle typical HTML.
+ //
+ // Strict mode does not enforce the requirements of the XML name spaces TR.
+ // In particular it does not reject name space tags using undefined prefixes.
+ // Such tags are recorded with the unknown prefix as the name space URL.
+ Strict bool
+
+ // When Strict == false, AutoClose indicates a set of elements to
+ // consider closed immediately after they are opened, regardless
+ // of whether an end element is present.
+ AutoClose []string
+
+ // Entity can be used to map non-standard entity names to string replacements.
+ // The parser behaves as if these standard mappings are present in the map,
+ // regardless of the actual map content:
+ //
+ // "lt": "<",
+ // "gt": ">",
+ // "amp": "&",
+ // "apos": "'",
+ // "quot": `"`,
+ Entity map[string]string
+
+ // CharsetReader, if non-nil, defines a function to generate
+ // charset-conversion readers, converting from the provided
+ // non-UTF-8 charset into UTF-8. If CharsetReader is nil or
+ // returns an error, parsing stops with an error. One of the
+ // the CharsetReader's result values must be non-nil.
+ CharsetReader func(charset string, input io.Reader) (io.Reader, error)
+
+ // DefaultSpace sets the default name space used for unadorned tags,
+ // as if the entire XML stream were wrapped in an element containing
+ // the attribute xmlns="DefaultSpace".
+ DefaultSpace string
+
+ r io.ByteReader
+ buf bytes.Buffer
+ saved *bytes.Buffer
+ stk *stack
+ free *stack
+ needClose bool
+ toClose Name
+ nextToken Token
+ nextByte int
+ ns map[string]string
+ err error
+ line int
+ offset int64
+ unmarshalDepth int
+}
+
+// NewDecoder creates a new XML parser reading from r.
+// If r does not implement io.ByteReader, NewDecoder will
+// do its own buffering.
+func NewDecoder(r io.Reader) *Decoder {
+ d := &Decoder{
+ ns: make(map[string]string),
+ nextByte: -1,
+ line: 1,
+ Strict: true,
+ }
+ d.switchToReader(r)
+ return d
+}
+
+// Token returns the next XML token in the input stream.
+// At the end of the input stream, Token returns nil, io.EOF.
+//
+// Slices of bytes in the returned token data refer to the
+// parser's internal buffer and remain valid only until the next
+// call to Token. To acquire a copy of the bytes, call CopyToken
+// or the token's Copy method.
+//
+// Token expands self-closing elements such as <br/>
+// into separate start and end elements returned by successive calls.
+//
+// Token guarantees that the StartElement and EndElement
+// tokens it returns are properly nested and matched:
+// if Token encounters an unexpected end element,
+// it will return an error.
+//
+// Token implements XML name spaces as described by
+// http://www.w3.org/TR/REC-xml-names/. Each of the
+// Name structures contained in the Token has the Space
+// set to the URL identifying its name space when known.
+// If Token encounters an unrecognized name space prefix,
+// it uses the prefix as the Space rather than report an error.
+func (d *Decoder) Token() (t Token, err error) {
+ if d.stk != nil && d.stk.kind == stkEOF {
+ err = io.EOF
+ return
+ }
+ if d.nextToken != nil {
+ t = d.nextToken
+ d.nextToken = nil
+ } else if t, err = d.rawToken(); err != nil {
+ return
+ }
+
+ if !d.Strict {
+ if t1, ok := d.autoClose(t); ok {
+ d.nextToken = t
+ t = t1
+ }
+ }
+ switch t1 := t.(type) {
+ case StartElement:
+ // In XML name spaces, the translations listed in the
+ // attributes apply to the element name and
+ // to the other attribute names, so process
+ // the translations first.
+ for _, a := range t1.Attr {
+ if a.Name.Space == "xmlns" {
+ v, ok := d.ns[a.Name.Local]
+ d.pushNs(a.Name.Local, v, ok)
+ d.ns[a.Name.Local] = a.Value
+ }
+ if a.Name.Space == "" && a.Name.Local == "xmlns" {
+ // Default space for untagged names
+ v, ok := d.ns[""]
+ d.pushNs("", v, ok)
+ d.ns[""] = a.Value
+ }
+ }
+
+ d.translate(&t1.Name, true)
+ for i := range t1.Attr {
+ d.translate(&t1.Attr[i].Name, false)
+ }
+ d.pushElement(t1.Name)
+ t = t1
+
+ case EndElement:
+ d.translate(&t1.Name, true)
+ if !d.popElement(&t1) {
+ return nil, d.err
+ }
+ t = t1
+ }
+ return
+}
+
+const xmlURL = "http://www.w3.org/XML/1998/namespace"
+
+// Apply name space translation to name n.
+// The default name space (for Space=="")
+// applies only to element names, not to attribute names.
+func (d *Decoder) translate(n *Name, isElementName bool) {
+ switch {
+ case n.Space == "xmlns":
+ return
+ case n.Space == "" && !isElementName:
+ return
+ case n.Space == "xml":
+ n.Space = xmlURL
+ case n.Space == "" && n.Local == "xmlns":
+ return
+ }
+ if v, ok := d.ns[n.Space]; ok {
+ n.Space = v
+ } else if n.Space == "" {
+ n.Space = d.DefaultSpace
+ }
+}
+
+func (d *Decoder) switchToReader(r io.Reader) {
+ // Get efficient byte at a time reader.
+ // Assume that if reader has its own
+ // ReadByte, it's efficient enough.
+ // Otherwise, use bufio.
+ if rb, ok := r.(io.ByteReader); ok {
+ d.r = rb
+ } else {
+ d.r = bufio.NewReader(r)
+ }
+}
+
+// Parsing state - stack holds old name space translations
+// and the current set of open elements. The translations to pop when
+// ending a given tag are *below* it on the stack, which is
+// more work but forced on us by XML.
+type stack struct {
+ next *stack
+ kind int
+ name Name
+ ok bool
+}
+
+const (
+ stkStart = iota
+ stkNs
+ stkEOF
+)
+
+func (d *Decoder) push(kind int) *stack {
+ s := d.free
+ if s != nil {
+ d.free = s.next
+ } else {
+ s = new(stack)
+ }
+ s.next = d.stk
+ s.kind = kind
+ d.stk = s
+ return s
+}
+
+func (d *Decoder) pop() *stack {
+ s := d.stk
+ if s != nil {
+ d.stk = s.next
+ s.next = d.free
+ d.free = s
+ }
+ return s
+}
+
+// Record that after the current element is finished
+// (that element is already pushed on the stack)
+// Token should return EOF until popEOF is called.
+func (d *Decoder) pushEOF() {
+ // Walk down stack to find Start.
+ // It might not be the top, because there might be stkNs
+ // entries above it.
+ start := d.stk
+ for start.kind != stkStart {
+ start = start.next
+ }
+ // The stkNs entries below a start are associated with that
+ // element too; skip over them.
+ for start.next != nil && start.next.kind == stkNs {
+ start = start.next
+ }
+ s := d.free
+ if s != nil {
+ d.free = s.next
+ } else {
+ s = new(stack)
+ }
+ s.kind = stkEOF
+ s.next = start.next
+ start.next = s
+}
+
+// Undo a pushEOF.
+// The element must have been finished, so the EOF should be at the top of the stack.
+func (d *Decoder) popEOF() bool {
+ if d.stk == nil || d.stk.kind != stkEOF {
+ return false
+ }
+ d.pop()
+ return true
+}
+
+// Record that we are starting an element with the given name.
+func (d *Decoder) pushElement(name Name) {
+ s := d.push(stkStart)
+ s.name = name
+}
+
+// Record that we are changing the value of ns[local].
+// The old value is url, ok.
+func (d *Decoder) pushNs(local string, url string, ok bool) {
+ s := d.push(stkNs)
+ s.name.Local = local
+ s.name.Space = url
+ s.ok = ok
+}
+
+// Creates a SyntaxError with the current line number.
+func (d *Decoder) syntaxError(msg string) error {
+ return &SyntaxError{Msg: msg, Line: d.line}
+}
+
+// Record that we are ending an element with the given name.
+// The name must match the record at the top of the stack,
+// which must be a pushElement record.
+// After popping the element, apply any undo records from
+// the stack to restore the name translations that existed
+// before we saw this element.
+func (d *Decoder) popElement(t *EndElement) bool {
+ s := d.pop()
+ name := t.Name
+ switch {
+ case s == nil || s.kind != stkStart:
+ d.err = d.syntaxError("unexpected end element </" + name.Local + ">")
+ return false
+ case s.name.Local != name.Local:
+ if !d.Strict {
+ d.needClose = true
+ d.toClose = t.Name
+ t.Name = s.name
+ return true
+ }
+ d.err = d.syntaxError("element <" + s.name.Local + "> closed by </" + name.Local + ">")
+ return false
+ case s.name.Space != name.Space:
+ d.err = d.syntaxError("element <" + s.name.Local + "> in space " + s.name.Space +
+ "closed by </" + name.Local + "> in space " + name.Space)
+ return false
+ }
+
+ // Pop stack until a Start or EOF is on the top, undoing the
+ // translations that were associated with the element we just closed.
+ for d.stk != nil && d.stk.kind != stkStart && d.stk.kind != stkEOF {
+ s := d.pop()
+ if s.ok {
+ d.ns[s.name.Local] = s.name.Space
+ } else {
+ delete(d.ns, s.name.Local)
+ }
+ }
+
+ return true
+}
+
+// If the top element on the stack is autoclosing and
+// t is not the end tag, invent the end tag.
+func (d *Decoder) autoClose(t Token) (Token, bool) {
+ if d.stk == nil || d.stk.kind != stkStart {
+ return nil, false
+ }
+ name := strings.ToLower(d.stk.name.Local)
+ for _, s := range d.AutoClose {
+ if strings.ToLower(s) == name {
+ // This one should be auto closed if t doesn't close it.
+ et, ok := t.(EndElement)
+ if !ok || et.Name.Local != name {
+ return EndElement{d.stk.name}, true
+ }
+ break
+ }
+ }
+ return nil, false
+}
+
+var errRawToken = errors.New("xml: cannot use RawToken from UnmarshalXML method")
+
+// RawToken is like Token but does not verify that
+// start and end elements match and does not translate
+// name space prefixes to their corresponding URLs.
+func (d *Decoder) RawToken() (Token, error) {
+ if d.unmarshalDepth > 0 {
+ return nil, errRawToken
+ }
+ return d.rawToken()
+}
+
+func (d *Decoder) rawToken() (Token, error) {
+ if d.err != nil {
+ return nil, d.err
+ }
+ if d.needClose {
+ // The last element we read was self-closing and
+ // we returned just the StartElement half.
+ // Return the EndElement half now.
+ d.needClose = false
+ return EndElement{d.toClose}, nil
+ }
+
+ b, ok := d.getc()
+ if !ok {
+ return nil, d.err
+ }
+
+ if b != '<' {
+ // Text section.
+ d.ungetc(b)
+ data := d.text(-1, false)
+ if data == nil {
+ return nil, d.err
+ }
+ return CharData(data), nil
+ }
+
+ if b, ok = d.mustgetc(); !ok {
+ return nil, d.err
+ }
+ switch b {
+ case '/':
+ // </: End element
+ var name Name
+ if name, ok = d.nsname(); !ok {
+ if d.err == nil {
+ d.err = d.syntaxError("expected element name after </")
+ }
+ return nil, d.err
+ }
+ d.space()
+ if b, ok = d.mustgetc(); !ok {
+ return nil, d.err
+ }
+ if b != '>' {
+ d.err = d.syntaxError("invalid characters between </" + name.Local + " and >")
+ return nil, d.err
+ }
+ return EndElement{name}, nil
+
+ case '?':
+ // <?: Processing instruction.
+ var target string
+ if target, ok = d.name(); !ok {
+ if d.err == nil {
+ d.err = d.syntaxError("expected target name after <?")
+ }
+ return nil, d.err
+ }
+ d.space()
+ d.buf.Reset()
+ var b0 byte
+ for {
+ if b, ok = d.mustgetc(); !ok {
+ return nil, d.err
+ }
+ d.buf.WriteByte(b)
+ if b0 == '?' && b == '>' {
+ break
+ }
+ b0 = b
+ }
+ data := d.buf.Bytes()
+ data = data[0 : len(data)-2] // chop ?>
+
+ if target == "xml" {
+ content := string(data)
+ ver := procInst("version", content)
+ if ver != "" && ver != "1.0" {
+ d.err = fmt.Errorf("xml: unsupported version %q; only version 1.0 is supported", ver)
+ return nil, d.err
+ }
+ enc := procInst("encoding", content)
+ if enc != "" && enc != "utf-8" && enc != "UTF-8" {
+ if d.CharsetReader == nil {
+ d.err = fmt.Errorf("xml: encoding %q declared but Decoder.CharsetReader is nil", enc)
+ return nil, d.err
+ }
+ newr, err := d.CharsetReader(enc, d.r.(io.Reader))
+ if err != nil {
+ d.err = fmt.Errorf("xml: opening charset %q: %v", enc, err)
+ return nil, d.err
+ }
+ if newr == nil {
+ panic("CharsetReader returned a nil Reader for charset " + enc)
+ }
+ d.switchToReader(newr)
+ }
+ }
+ return ProcInst{target, data}, nil
+
+ case '!':
+ // <!: Maybe comment, maybe CDATA.
+ if b, ok = d.mustgetc(); !ok {
+ return nil, d.err
+ }
+ switch b {
+ case '-': // <!-
+ // Probably <!-- for a comment.
+ if b, ok = d.mustgetc(); !ok {
+ return nil, d.err
+ }
+ if b != '-' {
+ d.err = d.syntaxError("invalid sequence <!- not part of <!--")
+ return nil, d.err
+ }
+ // Look for terminator.
+ d.buf.Reset()
+ var b0, b1 byte
+ for {
+ if b, ok = d.mustgetc(); !ok {
+ return nil, d.err
+ }
+ d.buf.WriteByte(b)
+ if b0 == '-' && b1 == '-' && b == '>' {
+ break
+ }
+ b0, b1 = b1, b
+ }
+ data := d.buf.Bytes()
+ data = data[0 : len(data)-3] // chop -->
+ return Comment(data), nil
+
+ case '[': // <![
+ // Probably <![CDATA[.
+ for i := 0; i < 6; i++ {
+ if b, ok = d.mustgetc(); !ok {
+ return nil, d.err
+ }
+ if b != "CDATA["[i] {
+ d.err = d.syntaxError("invalid <![ sequence")
+ return nil, d.err
+ }
+ }
+ // Have <![CDATA[. Read text until ]]>.
+ data := d.text(-1, true)
+ if data == nil {
+ return nil, d.err
+ }
+ return CharData(data), nil
+ }
+
+ // Probably a directive: <!DOCTYPE ...>, <!ENTITY ...>, etc.
+ // We don't care, but accumulate for caller. Quoted angle
+ // brackets do not count for nesting.
+ d.buf.Reset()
+ d.buf.WriteByte(b)
+ inquote := uint8(0)
+ depth := 0
+ for {
+ if b, ok = d.mustgetc(); !ok {
+ return nil, d.err
+ }
+ if inquote == 0 && b == '>' && depth == 0 {
+ break
+ }
+ HandleB:
+ d.buf.WriteByte(b)
+ switch {
+ case b == inquote:
+ inquote = 0
+
+ case inquote != 0:
+ // in quotes, no special action
+
+ case b == '\'' || b == '"':
+ inquote = b
+
+ case b == '>' && inquote == 0:
+ depth--
+
+ case b == '<' && inquote == 0:
+ // Look for <!-- to begin comment.
+ s := "!--"
+ for i := 0; i < len(s); i++ {
+ if b, ok = d.mustgetc(); !ok {
+ return nil, d.err
+ }
+ if b != s[i] {
+ for j := 0; j < i; j++ {
+ d.buf.WriteByte(s[j])
+ }
+ depth++
+ goto HandleB
+ }
+ }
+
+ // Remove < that was written above.
+ d.buf.Truncate(d.buf.Len() - 1)
+
+ // Look for terminator.
+ var b0, b1 byte
+ for {
+ if b, ok = d.mustgetc(); !ok {
+ return nil, d.err
+ }
+ if b0 == '-' && b1 == '-' && b == '>' {
+ break
+ }
+ b0, b1 = b1, b
+ }
+ }
+ }
+ return Directive(d.buf.Bytes()), nil
+ }
+
+ // Must be an open element like <a href="foo">
+ d.ungetc(b)
+
+ var (
+ name Name
+ empty bool
+ attr []Attr
+ )
+ if name, ok = d.nsname(); !ok {
+ if d.err == nil {
+ d.err = d.syntaxError("expected element name after <")
+ }
+ return nil, d.err
+ }
+
+ attr = []Attr{}
+ for {
+ d.space()
+ if b, ok = d.mustgetc(); !ok {
+ return nil, d.err
+ }
+ if b == '/' {
+ empty = true
+ if b, ok = d.mustgetc(); !ok {
+ return nil, d.err
+ }
+ if b != '>' {
+ d.err = d.syntaxError("expected /> in element")
+ return nil, d.err
+ }
+ break
+ }
+ if b == '>' {
+ break
+ }
+ d.ungetc(b)
+
+ n := len(attr)
+ if n >= cap(attr) {
+ nCap := 2 * cap(attr)
+ if nCap == 0 {
+ nCap = 4
+ }
+ nattr := make([]Attr, n, nCap)
+ copy(nattr, attr)
+ attr = nattr
+ }
+ attr = attr[0 : n+1]
+ a := &attr[n]
+ if a.Name, ok = d.nsname(); !ok {
+ if d.err == nil {
+ d.err = d.syntaxError("expected attribute name in element")
+ }
+ return nil, d.err
+ }
+ d.space()
+ if b, ok = d.mustgetc(); !ok {
+ return nil, d.err
+ }
+ if b != '=' {
+ if d.Strict {
+ d.err = d.syntaxError("attribute name without = in element")
+ return nil, d.err
+ } else {
+ d.ungetc(b)
+ a.Value = a.Name.Local
+ }
+ } else {
+ d.space()
+ data := d.attrval()
+ if data == nil {
+ return nil, d.err
+ }
+ a.Value = string(data)
+ }
+ }
+ if empty {
+ d.needClose = true
+ d.toClose = name
+ }
+ return StartElement{name, attr}, nil
+}
+
+func (d *Decoder) attrval() []byte {
+ b, ok := d.mustgetc()
+ if !ok {
+ return nil
+ }
+ // Handle quoted attribute values
+ if b == '"' || b == '\'' {
+ return d.text(int(b), false)
+ }
+ // Handle unquoted attribute values for strict parsers
+ if d.Strict {
+ d.err = d.syntaxError("unquoted or missing attribute value in element")
+ return nil
+ }
+ // Handle unquoted attribute values for unstrict parsers
+ d.ungetc(b)
+ d.buf.Reset()
+ for {
+ b, ok = d.mustgetc()
+ if !ok {
+ return nil
+ }
+ // http://www.w3.org/TR/REC-html40/intro/sgmltut.html#h-3.2.2
+ if 'a' <= b && b <= 'z' || 'A' <= b && b <= 'Z' ||
+ '0' <= b && b <= '9' || b == '_' || b == ':' || b == '-' {
+ d.buf.WriteByte(b)
+ } else {
+ d.ungetc(b)
+ break
+ }
+ }
+ return d.buf.Bytes()
+}
+
+// Skip spaces if any
+func (d *Decoder) space() {
+ for {
+ b, ok := d.getc()
+ if !ok {
+ return
+ }
+ switch b {
+ case ' ', '\r', '\n', '\t':
+ default:
+ d.ungetc(b)
+ return
+ }
+ }
+}
+
+// Read a single byte.
+// If there is no byte to read, return ok==false
+// and leave the error in d.err.
+// Maintain line number.
+func (d *Decoder) getc() (b byte, ok bool) {
+ if d.err != nil {
+ return 0, false
+ }
+ if d.nextByte >= 0 {
+ b = byte(d.nextByte)
+ d.nextByte = -1
+ } else {
+ b, d.err = d.r.ReadByte()
+ if d.err != nil {
+ return 0, false
+ }
+ if d.saved != nil {
+ d.saved.WriteByte(b)
+ }
+ }
+ if b == '\n' {
+ d.line++
+ }
+ d.offset++
+ return b, true
+}
+
+// InputOffset returns the input stream byte offset of the current decoder position.
+// The offset gives the location of the end of the most recently returned token
+// and the beginning of the next token.
+func (d *Decoder) InputOffset() int64 {
+ return d.offset
+}
+
+// Return saved offset.
+// If we did ungetc (nextByte >= 0), have to back up one.
+func (d *Decoder) savedOffset() int {
+ n := d.saved.Len()
+ if d.nextByte >= 0 {
+ n--
+ }
+ return n
+}
+
+// Must read a single byte.
+// If there is no byte to read,
+// set d.err to SyntaxError("unexpected EOF")
+// and return ok==false
+func (d *Decoder) mustgetc() (b byte, ok bool) {
+ if b, ok = d.getc(); !ok {
+ if d.err == io.EOF {
+ d.err = d.syntaxError("unexpected EOF")
+ }
+ }
+ return
+}
+
+// Unread a single byte.
+func (d *Decoder) ungetc(b byte) {
+ if b == '\n' {
+ d.line--
+ }
+ d.nextByte = int(b)
+ d.offset--
+}
+
+var entity = map[string]int{
+ "lt": '<',
+ "gt": '>',
+ "amp": '&',
+ "apos": '\'',
+ "quot": '"',
+}
+
+// Read plain text section (XML calls it character data).
+// If quote >= 0, we are in a quoted string and need to find the matching quote.
+// If cdata == true, we are in a <![CDATA[ section and need to find ]]>.
+// On failure return nil and leave the error in d.err.
+func (d *Decoder) text(quote int, cdata bool) []byte {
+ var b0, b1 byte
+ var trunc int
+ d.buf.Reset()
+Input:
+ for {
+ b, ok := d.getc()
+ if !ok {
+ if cdata {
+ if d.err == io.EOF {
+ d.err = d.syntaxError("unexpected EOF in CDATA section")
+ }
+ return nil
+ }
+ break Input
+ }
+
+ // <![CDATA[ section ends with ]]>.
+ // It is an error for ]]> to appear in ordinary text.
+ if b0 == ']' && b1 == ']' && b == '>' {
+ if cdata {
+ trunc = 2
+ break Input
+ }
+ d.err = d.syntaxError("unescaped ]]> not in CDATA section")
+ return nil
+ }
+
+ // Stop reading text if we see a <.
+ if b == '<' && !cdata {
+ if quote >= 0 {
+ d.err = d.syntaxError("unescaped < inside quoted string")
+ return nil
+ }
+ d.ungetc('<')
+ break Input
+ }
+ if quote >= 0 && b == byte(quote) {
+ break Input
+ }
+ if b == '&' && !cdata {
+ // Read escaped character expression up to semicolon.
+ // XML in all its glory allows a document to define and use
+ // its own character names with <!ENTITY ...> directives.
+ // Parsers are required to recognize lt, gt, amp, apos, and quot
+ // even if they have not been declared.
+ before := d.buf.Len()
+ d.buf.WriteByte('&')
+ var ok bool
+ var text string
+ var haveText bool
+ if b, ok = d.mustgetc(); !ok {
+ return nil
+ }
+ if b == '#' {
+ d.buf.WriteByte(b)
+ if b, ok = d.mustgetc(); !ok {
+ return nil
+ }
+ base := 10
+ if b == 'x' {
+ base = 16
+ d.buf.WriteByte(b)
+ if b, ok = d.mustgetc(); !ok {
+ return nil
+ }
+ }
+ start := d.buf.Len()
+ for '0' <= b && b <= '9' ||
+ base == 16 && 'a' <= b && b <= 'f' ||
+ base == 16 && 'A' <= b && b <= 'F' {
+ d.buf.WriteByte(b)
+ if b, ok = d.mustgetc(); !ok {
+ return nil
+ }
+ }
+ if b != ';' {
+ d.ungetc(b)
+ } else {
+ s := string(d.buf.Bytes()[start:])
+ d.buf.WriteByte(';')
+ n, err := strconv.ParseUint(s, base, 64)
+ if err == nil && n <= unicode.MaxRune {
+ text = string(n)
+ haveText = true
+ }
+ }
+ } else {
+ d.ungetc(b)
+ if !d.readName() {
+ if d.err != nil {
+ return nil
+ }
+ ok = false
+ }
+ if b, ok = d.mustgetc(); !ok {
+ return nil
+ }
+ if b != ';' {
+ d.ungetc(b)
+ } else {
+ name := d.buf.Bytes()[before+1:]
+ d.buf.WriteByte(';')
+ if isName(name) {
+ s := string(name)
+ if r, ok := entity[s]; ok {
+ text = string(r)
+ haveText = true
+ } else if d.Entity != nil {
+ text, haveText = d.Entity[s]
+ }
+ }
+ }
+ }
+
+ if haveText {
+ d.buf.Truncate(before)
+ d.buf.Write([]byte(text))
+ b0, b1 = 0, 0
+ continue Input
+ }
+ if !d.Strict {
+ b0, b1 = 0, 0
+ continue Input
+ }
+ ent := string(d.buf.Bytes()[before:])
+ if ent[len(ent)-1] != ';' {
+ ent += " (no semicolon)"
+ }
+ d.err = d.syntaxError("invalid character entity " + ent)
+ return nil
+ }
+
+ // We must rewrite unescaped \r and \r\n into \n.
+ if b == '\r' {
+ d.buf.WriteByte('\n')
+ } else if b1 == '\r' && b == '\n' {
+ // Skip \r\n--we already wrote \n.
+ } else {
+ d.buf.WriteByte(b)
+ }
+
+ b0, b1 = b1, b
+ }
+ data := d.buf.Bytes()
+ data = data[0 : len(data)-trunc]
+
+ // Inspect each rune for being a disallowed character.
+ buf := data
+ for len(buf) > 0 {
+ r, size := utf8.DecodeRune(buf)
+ if r == utf8.RuneError && size == 1 {
+ d.err = d.syntaxError("invalid UTF-8")
+ return nil
+ }
+ buf = buf[size:]
+ if !isInCharacterRange(r) {
+ d.err = d.syntaxError(fmt.Sprintf("illegal character code %U", r))
+ return nil
+ }
+ }
+
+ return data
+}
+
+// Decide whether the given rune is in the XML Character Range, per
+// the Char production of http://www.xml.com/axml/testaxml.htm,
+// Section 2.2 Characters.
+func isInCharacterRange(r rune) (inrange bool) {
+ return r == 0x09 ||
+ r == 0x0A ||
+ r == 0x0D ||
+ r >= 0x20 && r <= 0xDF77 ||
+ r >= 0xE000 && r <= 0xFFFD ||
+ r >= 0x10000 && r <= 0x10FFFF
+}
+
+// Get name space name: name with a : stuck in the middle.
+// The part before the : is the name space identifier.
+func (d *Decoder) nsname() (name Name, ok bool) {
+ s, ok := d.name()
+ if !ok {
+ return
+ }
+ i := strings.Index(s, ":")
+ if i < 0 {
+ name.Local = s
+ } else {
+ name.Space = s[0:i]
+ name.Local = s[i+1:]
+ }
+ return name, true
+}
+
+// Get name: /first(first|second)*/
+// Do not set d.err if the name is missing (unless unexpected EOF is received):
+// let the caller provide better context.
+func (d *Decoder) name() (s string, ok bool) {
+ d.buf.Reset()
+ if !d.readName() {
+ return "", false
+ }
+
+ // Now we check the characters.
+ b := d.buf.Bytes()
+ if !isName(b) {
+ d.err = d.syntaxError("invalid XML name: " + string(b))
+ return "", false
+ }
+ return string(b), true
+}
+
+// Read a name and append its bytes to d.buf.
+// The name is delimited by any single-byte character not valid in names.
+// All multi-byte characters are accepted; the caller must check their validity.
+func (d *Decoder) readName() (ok bool) {
+ var b byte
+ if b, ok = d.mustgetc(); !ok {
+ return
+ }
+ if b < utf8.RuneSelf && !isNameByte(b) {
+ d.ungetc(b)
+ return false
+ }
+ d.buf.WriteByte(b)
+
+ for {
+ if b, ok = d.mustgetc(); !ok {
+ return
+ }
+ if b < utf8.RuneSelf && !isNameByte(b) {
+ d.ungetc(b)
+ break
+ }
+ d.buf.WriteByte(b)
+ }
+ return true
+}
+
+func isNameByte(c byte) bool {
+ return 'A' <= c && c <= 'Z' ||
+ 'a' <= c && c <= 'z' ||
+ '0' <= c && c <= '9' ||
+ c == '_' || c == ':' || c == '.' || c == '-'
+}
+
+func isName(s []byte) bool {
+ if len(s) == 0 {
+ return false
+ }
+ c, n := utf8.DecodeRune(s)
+ if c == utf8.RuneError && n == 1 {
+ return false
+ }
+ if !unicode.Is(first, c) {
+ return false
+ }
+ for n < len(s) {
+ s = s[n:]
+ c, n = utf8.DecodeRune(s)
+ if c == utf8.RuneError && n == 1 {
+ return false
+ }
+ if !unicode.Is(first, c) && !unicode.Is(second, c) {
+ return false
+ }
+ }
+ return true
+}
+
+func isNameString(s string) bool {
+ if len(s) == 0 {
+ return false
+ }
+ c, n := utf8.DecodeRuneInString(s)
+ if c == utf8.RuneError && n == 1 {
+ return false
+ }
+ if !unicode.Is(first, c) {
+ return false
+ }
+ for n < len(s) {
+ s = s[n:]
+ c, n = utf8.DecodeRuneInString(s)
+ if c == utf8.RuneError && n == 1 {
+ return false
+ }
+ if !unicode.Is(first, c) && !unicode.Is(second, c) {
+ return false
+ }
+ }
+ return true
+}
+
+// These tables were generated by cut and paste from Appendix B of
+// the XML spec at http://www.xml.com/axml/testaxml.htm
+// and then reformatting. First corresponds to (Letter | '_' | ':')
+// and second corresponds to NameChar.
+
+var first = &unicode.RangeTable{
+ R16: []unicode.Range16{
+ {0x003A, 0x003A, 1},
+ {0x0041, 0x005A, 1},
+ {0x005F, 0x005F, 1},
+ {0x0061, 0x007A, 1},
+ {0x00C0, 0x00D6, 1},
+ {0x00D8, 0x00F6, 1},
+ {0x00F8, 0x00FF, 1},
+ {0x0100, 0x0131, 1},
+ {0x0134, 0x013E, 1},
+ {0x0141, 0x0148, 1},
+ {0x014A, 0x017E, 1},
+ {0x0180, 0x01C3, 1},
+ {0x01CD, 0x01F0, 1},
+ {0x01F4, 0x01F5, 1},
+ {0x01FA, 0x0217, 1},
+ {0x0250, 0x02A8, 1},
+ {0x02BB, 0x02C1, 1},
+ {0x0386, 0x0386, 1},
+ {0x0388, 0x038A, 1},
+ {0x038C, 0x038C, 1},
+ {0x038E, 0x03A1, 1},
+ {0x03A3, 0x03CE, 1},
+ {0x03D0, 0x03D6, 1},
+ {0x03DA, 0x03E0, 2},
+ {0x03E2, 0x03F3, 1},
+ {0x0401, 0x040C, 1},
+ {0x040E, 0x044F, 1},
+ {0x0451, 0x045C, 1},
+ {0x045E, 0x0481, 1},
+ {0x0490, 0x04C4, 1},
+ {0x04C7, 0x04C8, 1},
+ {0x04CB, 0x04CC, 1},
+ {0x04D0, 0x04EB, 1},
+ {0x04EE, 0x04F5, 1},
+ {0x04F8, 0x04F9, 1},
+ {0x0531, 0x0556, 1},
+ {0x0559, 0x0559, 1},
+ {0x0561, 0x0586, 1},
+ {0x05D0, 0x05EA, 1},
+ {0x05F0, 0x05F2, 1},
+ {0x0621, 0x063A, 1},
+ {0x0641, 0x064A, 1},
+ {0x0671, 0x06B7, 1},
+ {0x06BA, 0x06BE, 1},
+ {0x06C0, 0x06CE, 1},
+ {0x06D0, 0x06D3, 1},
+ {0x06D5, 0x06D5, 1},
+ {0x06E5, 0x06E6, 1},
+ {0x0905, 0x0939, 1},
+ {0x093D, 0x093D, 1},
+ {0x0958, 0x0961, 1},
+ {0x0985, 0x098C, 1},
+ {0x098F, 0x0990, 1},
+ {0x0993, 0x09A8, 1},
+ {0x09AA, 0x09B0, 1},
+ {0x09B2, 0x09B2, 1},
+ {0x09B6, 0x09B9, 1},
+ {0x09DC, 0x09DD, 1},
+ {0x09DF, 0x09E1, 1},
+ {0x09F0, 0x09F1, 1},
+ {0x0A05, 0x0A0A, 1},
+ {0x0A0F, 0x0A10, 1},
+ {0x0A13, 0x0A28, 1},
+ {0x0A2A, 0x0A30, 1},
+ {0x0A32, 0x0A33, 1},
+ {0x0A35, 0x0A36, 1},
+ {0x0A38, 0x0A39, 1},
+ {0x0A59, 0x0A5C, 1},
+ {0x0A5E, 0x0A5E, 1},
+ {0x0A72, 0x0A74, 1},
+ {0x0A85, 0x0A8B, 1},
+ {0x0A8D, 0x0A8D, 1},
+ {0x0A8F, 0x0A91, 1},
+ {0x0A93, 0x0AA8, 1},
+ {0x0AAA, 0x0AB0, 1},
+ {0x0AB2, 0x0AB3, 1},
+ {0x0AB5, 0x0AB9, 1},
+ {0x0ABD, 0x0AE0, 0x23},
+ {0x0B05, 0x0B0C, 1},
+ {0x0B0F, 0x0B10, 1},
+ {0x0B13, 0x0B28, 1},
+ {0x0B2A, 0x0B30, 1},
+ {0x0B32, 0x0B33, 1},
+ {0x0B36, 0x0B39, 1},
+ {0x0B3D, 0x0B3D, 1},
+ {0x0B5C, 0x0B5D, 1},
+ {0x0B5F, 0x0B61, 1},
+ {0x0B85, 0x0B8A, 1},
+ {0x0B8E, 0x0B90, 1},
+ {0x0B92, 0x0B95, 1},
+ {0x0B99, 0x0B9A, 1},
+ {0x0B9C, 0x0B9C, 1},
+ {0x0B9E, 0x0B9F, 1},
+ {0x0BA3, 0x0BA4, 1},
+ {0x0BA8, 0x0BAA, 1},
+ {0x0BAE, 0x0BB5, 1},
+ {0x0BB7, 0x0BB9, 1},
+ {0x0C05, 0x0C0C, 1},
+ {0x0C0E, 0x0C10, 1},
+ {0x0C12, 0x0C28, 1},
+ {0x0C2A, 0x0C33, 1},
+ {0x0C35, 0x0C39, 1},
+ {0x0C60, 0x0C61, 1},
+ {0x0C85, 0x0C8C, 1},
+ {0x0C8E, 0x0C90, 1},
+ {0x0C92, 0x0CA8, 1},
+ {0x0CAA, 0x0CB3, 1},
+ {0x0CB5, 0x0CB9, 1},
+ {0x0CDE, 0x0CDE, 1},
+ {0x0CE0, 0x0CE1, 1},
+ {0x0D05, 0x0D0C, 1},
+ {0x0D0E, 0x0D10, 1},
+ {0x0D12, 0x0D28, 1},
+ {0x0D2A, 0x0D39, 1},
+ {0x0D60, 0x0D61, 1},
+ {0x0E01, 0x0E2E, 1},
+ {0x0E30, 0x0E30, 1},
+ {0x0E32, 0x0E33, 1},
+ {0x0E40, 0x0E45, 1},
+ {0x0E81, 0x0E82, 1},
+ {0x0E84, 0x0E84, 1},
+ {0x0E87, 0x0E88, 1},
+ {0x0E8A, 0x0E8D, 3},
+ {0x0E94, 0x0E97, 1},
+ {0x0E99, 0x0E9F, 1},
+ {0x0EA1, 0x0EA3, 1},
+ {0x0EA5, 0x0EA7, 2},
+ {0x0EAA, 0x0EAB, 1},
+ {0x0EAD, 0x0EAE, 1},
+ {0x0EB0, 0x0EB0, 1},
+ {0x0EB2, 0x0EB3, 1},
+ {0x0EBD, 0x0EBD, 1},
+ {0x0EC0, 0x0EC4, 1},
+ {0x0F40, 0x0F47, 1},
+ {0x0F49, 0x0F69, 1},
+ {0x10A0, 0x10C5, 1},
+ {0x10D0, 0x10F6, 1},
+ {0x1100, 0x1100, 1},
+ {0x1102, 0x1103, 1},
+ {0x1105, 0x1107, 1},
+ {0x1109, 0x1109, 1},
+ {0x110B, 0x110C, 1},
+ {0x110E, 0x1112, 1},
+ {0x113C, 0x1140, 2},
+ {0x114C, 0x1150, 2},
+ {0x1154, 0x1155, 1},
+ {0x1159, 0x1159, 1},
+ {0x115F, 0x1161, 1},
+ {0x1163, 0x1169, 2},
+ {0x116D, 0x116E, 1},
+ {0x1172, 0x1173, 1},
+ {0x1175, 0x119E, 0x119E - 0x1175},
+ {0x11A8, 0x11AB, 0x11AB - 0x11A8},
+ {0x11AE, 0x11AF, 1},
+ {0x11B7, 0x11B8, 1},
+ {0x11BA, 0x11BA, 1},
+ {0x11BC, 0x11C2, 1},
+ {0x11EB, 0x11F0, 0x11F0 - 0x11EB},
+ {0x11F9, 0x11F9, 1},
+ {0x1E00, 0x1E9B, 1},
+ {0x1EA0, 0x1EF9, 1},
+ {0x1F00, 0x1F15, 1},
+ {0x1F18, 0x1F1D, 1},
+ {0x1F20, 0x1F45, 1},
+ {0x1F48, 0x1F4D, 1},
+ {0x1F50, 0x1F57, 1},
+ {0x1F59, 0x1F5B, 0x1F5B - 0x1F59},
+ {0x1F5D, 0x1F5D, 1},
+ {0x1F5F, 0x1F7D, 1},
+ {0x1F80, 0x1FB4, 1},
+ {0x1FB6, 0x1FBC, 1},
+ {0x1FBE, 0x1FBE, 1},
+ {0x1FC2, 0x1FC4, 1},
+ {0x1FC6, 0x1FCC, 1},
+ {0x1FD0, 0x1FD3, 1},
+ {0x1FD6, 0x1FDB, 1},
+ {0x1FE0, 0x1FEC, 1},
+ {0x1FF2, 0x1FF4, 1},
+ {0x1FF6, 0x1FFC, 1},
+ {0x2126, 0x2126, 1},
+ {0x212A, 0x212B, 1},
+ {0x212E, 0x212E, 1},
+ {0x2180, 0x2182, 1},
+ {0x3007, 0x3007, 1},
+ {0x3021, 0x3029, 1},
+ {0x3041, 0x3094, 1},
+ {0x30A1, 0x30FA, 1},
+ {0x3105, 0x312C, 1},
+ {0x4E00, 0x9FA5, 1},
+ {0xAC00, 0xD7A3, 1},
+ },
+}
+
+var second = &unicode.RangeTable{
+ R16: []unicode.Range16{
+ {0x002D, 0x002E, 1},
+ {0x0030, 0x0039, 1},
+ {0x00B7, 0x00B7, 1},
+ {0x02D0, 0x02D1, 1},
+ {0x0300, 0x0345, 1},
+ {0x0360, 0x0361, 1},
+ {0x0387, 0x0387, 1},
+ {0x0483, 0x0486, 1},
+ {0x0591, 0x05A1, 1},
+ {0x05A3, 0x05B9, 1},
+ {0x05BB, 0x05BD, 1},
+ {0x05BF, 0x05BF, 1},
+ {0x05C1, 0x05C2, 1},
+ {0x05C4, 0x0640, 0x0640 - 0x05C4},
+ {0x064B, 0x0652, 1},
+ {0x0660, 0x0669, 1},
+ {0x0670, 0x0670, 1},
+ {0x06D6, 0x06DC, 1},
+ {0x06DD, 0x06DF, 1},
+ {0x06E0, 0x06E4, 1},
+ {0x06E7, 0x06E8, 1},
+ {0x06EA, 0x06ED, 1},
+ {0x06F0, 0x06F9, 1},
+ {0x0901, 0x0903, 1},
+ {0x093C, 0x093C, 1},
+ {0x093E, 0x094C, 1},
+ {0x094D, 0x094D, 1},
+ {0x0951, 0x0954, 1},
+ {0x0962, 0x0963, 1},
+ {0x0966, 0x096F, 1},
+ {0x0981, 0x0983, 1},
+ {0x09BC, 0x09BC, 1},
+ {0x09BE, 0x09BF, 1},
+ {0x09C0, 0x09C4, 1},
+ {0x09C7, 0x09C8, 1},
+ {0x09CB, 0x09CD, 1},
+ {0x09D7, 0x09D7, 1},
+ {0x09E2, 0x09E3, 1},
+ {0x09E6, 0x09EF, 1},
+ {0x0A02, 0x0A3C, 0x3A},
+ {0x0A3E, 0x0A3F, 1},
+ {0x0A40, 0x0A42, 1},
+ {0x0A47, 0x0A48, 1},
+ {0x0A4B, 0x0A4D, 1},
+ {0x0A66, 0x0A6F, 1},
+ {0x0A70, 0x0A71, 1},
+ {0x0A81, 0x0A83, 1},
+ {0x0ABC, 0x0ABC, 1},
+ {0x0ABE, 0x0AC5, 1},
+ {0x0AC7, 0x0AC9, 1},
+ {0x0ACB, 0x0ACD, 1},
+ {0x0AE6, 0x0AEF, 1},
+ {0x0B01, 0x0B03, 1},
+ {0x0B3C, 0x0B3C, 1},
+ {0x0B3E, 0x0B43, 1},
+ {0x0B47, 0x0B48, 1},
+ {0x0B4B, 0x0B4D, 1},
+ {0x0B56, 0x0B57, 1},
+ {0x0B66, 0x0B6F, 1},
+ {0x0B82, 0x0B83, 1},
+ {0x0BBE, 0x0BC2, 1},
+ {0x0BC6, 0x0BC8, 1},
+ {0x0BCA, 0x0BCD, 1},
+ {0x0BD7, 0x0BD7, 1},
+ {0x0BE7, 0x0BEF, 1},
+ {0x0C01, 0x0C03, 1},
+ {0x0C3E, 0x0C44, 1},
+ {0x0C46, 0x0C48, 1},
+ {0x0C4A, 0x0C4D, 1},
+ {0x0C55, 0x0C56, 1},
+ {0x0C66, 0x0C6F, 1},
+ {0x0C82, 0x0C83, 1},
+ {0x0CBE, 0x0CC4, 1},
+ {0x0CC6, 0x0CC8, 1},
+ {0x0CCA, 0x0CCD, 1},
+ {0x0CD5, 0x0CD6, 1},
+ {0x0CE6, 0x0CEF, 1},
+ {0x0D02, 0x0D03, 1},
+ {0x0D3E, 0x0D43, 1},
+ {0x0D46, 0x0D48, 1},
+ {0x0D4A, 0x0D4D, 1},
+ {0x0D57, 0x0D57, 1},
+ {0x0D66, 0x0D6F, 1},
+ {0x0E31, 0x0E31, 1},
+ {0x0E34, 0x0E3A, 1},
+ {0x0E46, 0x0E46, 1},
+ {0x0E47, 0x0E4E, 1},
+ {0x0E50, 0x0E59, 1},
+ {0x0EB1, 0x0EB1, 1},
+ {0x0EB4, 0x0EB9, 1},
+ {0x0EBB, 0x0EBC, 1},
+ {0x0EC6, 0x0EC6, 1},
+ {0x0EC8, 0x0ECD, 1},
+ {0x0ED0, 0x0ED9, 1},
+ {0x0F18, 0x0F19, 1},
+ {0x0F20, 0x0F29, 1},
+ {0x0F35, 0x0F39, 2},
+ {0x0F3E, 0x0F3F, 1},
+ {0x0F71, 0x0F84, 1},
+ {0x0F86, 0x0F8B, 1},
+ {0x0F90, 0x0F95, 1},
+ {0x0F97, 0x0F97, 1},
+ {0x0F99, 0x0FAD, 1},
+ {0x0FB1, 0x0FB7, 1},
+ {0x0FB9, 0x0FB9, 1},
+ {0x20D0, 0x20DC, 1},
+ {0x20E1, 0x3005, 0x3005 - 0x20E1},
+ {0x302A, 0x302F, 1},
+ {0x3031, 0x3035, 1},
+ {0x3099, 0x309A, 1},
+ {0x309D, 0x309E, 1},
+ {0x30FC, 0x30FE, 1},
+ },
+}
+
+// HTMLEntity is an entity map containing translations for the
+// standard HTML entity characters.
+var HTMLEntity = htmlEntity
+
+var htmlEntity = map[string]string{
+ /*
+ hget http://www.w3.org/TR/html4/sgml/entities.html |
+ ssam '
+ ,y /\&gt;/ x/\&lt;(.|\n)+/ s/\n/ /g
+ ,x v/^\&lt;!ENTITY/d
+ ,s/\&lt;!ENTITY ([^ ]+) .*U\+([0-9A-F][0-9A-F][0-9A-F][0-9A-F]) .+/ "\1": "\\u\2",/g
+ '
+ */
+ "nbsp": "\u00A0",
+ "iexcl": "\u00A1",
+ "cent": "\u00A2",
+ "pound": "\u00A3",
+ "curren": "\u00A4",
+ "yen": "\u00A5",
+ "brvbar": "\u00A6",
+ "sect": "\u00A7",
+ "uml": "\u00A8",
+ "copy": "\u00A9",
+ "ordf": "\u00AA",
+ "laquo": "\u00AB",
+ "not": "\u00AC",
+ "shy": "\u00AD",
+ "reg": "\u00AE",
+ "macr": "\u00AF",
+ "deg": "\u00B0",
+ "plusmn": "\u00B1",
+ "sup2": "\u00B2",
+ "sup3": "\u00B3",
+ "acute": "\u00B4",
+ "micro": "\u00B5",
+ "para": "\u00B6",
+ "middot": "\u00B7",
+ "cedil": "\u00B8",
+ "sup1": "\u00B9",
+ "ordm": "\u00BA",
+ "raquo": "\u00BB",
+ "frac14": "\u00BC",
+ "frac12": "\u00BD",
+ "frac34": "\u00BE",
+ "iquest": "\u00BF",
+ "Agrave": "\u00C0",
+ "Aacute": "\u00C1",
+ "Acirc": "\u00C2",
+ "Atilde": "\u00C3",
+ "Auml": "\u00C4",
+ "Aring": "\u00C5",
+ "AElig": "\u00C6",
+ "Ccedil": "\u00C7",
+ "Egrave": "\u00C8",
+ "Eacute": "\u00C9",
+ "Ecirc": "\u00CA",
+ "Euml": "\u00CB",
+ "Igrave": "\u00CC",
+ "Iacute": "\u00CD",
+ "Icirc": "\u00CE",
+ "Iuml": "\u00CF",
+ "ETH": "\u00D0",
+ "Ntilde": "\u00D1",
+ "Ograve": "\u00D2",
+ "Oacute": "\u00D3",
+ "Ocirc": "\u00D4",
+ "Otilde": "\u00D5",
+ "Ouml": "\u00D6",
+ "times": "\u00D7",
+ "Oslash": "\u00D8",
+ "Ugrave": "\u00D9",
+ "Uacute": "\u00DA",
+ "Ucirc": "\u00DB",
+ "Uuml": "\u00DC",
+ "Yacute": "\u00DD",
+ "THORN": "\u00DE",
+ "szlig": "\u00DF",
+ "agrave": "\u00E0",
+ "aacute": "\u00E1",
+ "acirc": "\u00E2",
+ "atilde": "\u00E3",
+ "auml": "\u00E4",
+ "aring": "\u00E5",
+ "aelig": "\u00E6",
+ "ccedil": "\u00E7",
+ "egrave": "\u00E8",
+ "eacute": "\u00E9",
+ "ecirc": "\u00EA",
+ "euml": "\u00EB",
+ "igrave": "\u00EC",
+ "iacute": "\u00ED",
+ "icirc": "\u00EE",
+ "iuml": "\u00EF",
+ "eth": "\u00F0",
+ "ntilde": "\u00F1",
+ "ograve": "\u00F2",
+ "oacute": "\u00F3",
+ "ocirc": "\u00F4",
+ "otilde": "\u00F5",
+ "ouml": "\u00F6",
+ "divide": "\u00F7",
+ "oslash": "\u00F8",
+ "ugrave": "\u00F9",
+ "uacute": "\u00FA",
+ "ucirc": "\u00FB",
+ "uuml": "\u00FC",
+ "yacute": "\u00FD",
+ "thorn": "\u00FE",
+ "yuml": "\u00FF",
+ "fnof": "\u0192",
+ "Alpha": "\u0391",
+ "Beta": "\u0392",
+ "Gamma": "\u0393",
+ "Delta": "\u0394",
+ "Epsilon": "\u0395",
+ "Zeta": "\u0396",
+ "Eta": "\u0397",
+ "Theta": "\u0398",
+ "Iota": "\u0399",
+ "Kappa": "\u039A",
+ "Lambda": "\u039B",
+ "Mu": "\u039C",
+ "Nu": "\u039D",
+ "Xi": "\u039E",
+ "Omicron": "\u039F",
+ "Pi": "\u03A0",
+ "Rho": "\u03A1",
+ "Sigma": "\u03A3",
+ "Tau": "\u03A4",
+ "Upsilon": "\u03A5",
+ "Phi": "\u03A6",
+ "Chi": "\u03A7",
+ "Psi": "\u03A8",
+ "Omega": "\u03A9",
+ "alpha": "\u03B1",
+ "beta": "\u03B2",
+ "gamma": "\u03B3",
+ "delta": "\u03B4",
+ "epsilon": "\u03B5",
+ "zeta": "\u03B6",
+ "eta": "\u03B7",
+ "theta": "\u03B8",
+ "iota": "\u03B9",
+ "kappa": "\u03BA",
+ "lambda": "\u03BB",
+ "mu": "\u03BC",
+ "nu": "\u03BD",
+ "xi": "\u03BE",
+ "omicron": "\u03BF",
+ "pi": "\u03C0",
+ "rho": "\u03C1",
+ "sigmaf": "\u03C2",
+ "sigma": "\u03C3",
+ "tau": "\u03C4",
+ "upsilon": "\u03C5",
+ "phi": "\u03C6",
+ "chi": "\u03C7",
+ "psi": "\u03C8",
+ "omega": "\u03C9",
+ "thetasym": "\u03D1",
+ "upsih": "\u03D2",
+ "piv": "\u03D6",
+ "bull": "\u2022",
+ "hellip": "\u2026",
+ "prime": "\u2032",
+ "Prime": "\u2033",
+ "oline": "\u203E",
+ "frasl": "\u2044",
+ "weierp": "\u2118",
+ "image": "\u2111",
+ "real": "\u211C",
+ "trade": "\u2122",
+ "alefsym": "\u2135",
+ "larr": "\u2190",
+ "uarr": "\u2191",
+ "rarr": "\u2192",
+ "darr": "\u2193",
+ "harr": "\u2194",
+ "crarr": "\u21B5",
+ "lArr": "\u21D0",
+ "uArr": "\u21D1",
+ "rArr": "\u21D2",
+ "dArr": "\u21D3",
+ "hArr": "\u21D4",
+ "forall": "\u2200",
+ "part": "\u2202",
+ "exist": "\u2203",
+ "empty": "\u2205",
+ "nabla": "\u2207",
+ "isin": "\u2208",
+ "notin": "\u2209",
+ "ni": "\u220B",
+ "prod": "\u220F",
+ "sum": "\u2211",
+ "minus": "\u2212",
+ "lowast": "\u2217",
+ "radic": "\u221A",
+ "prop": "\u221D",
+ "infin": "\u221E",
+ "ang": "\u2220",
+ "and": "\u2227",
+ "or": "\u2228",
+ "cap": "\u2229",
+ "cup": "\u222A",
+ "int": "\u222B",
+ "there4": "\u2234",
+ "sim": "\u223C",
+ "cong": "\u2245",
+ "asymp": "\u2248",
+ "ne": "\u2260",
+ "equiv": "\u2261",
+ "le": "\u2264",
+ "ge": "\u2265",
+ "sub": "\u2282",
+ "sup": "\u2283",
+ "nsub": "\u2284",
+ "sube": "\u2286",
+ "supe": "\u2287",
+ "oplus": "\u2295",
+ "otimes": "\u2297",
+ "perp": "\u22A5",
+ "sdot": "\u22C5",
+ "lceil": "\u2308",
+ "rceil": "\u2309",
+ "lfloor": "\u230A",
+ "rfloor": "\u230B",
+ "lang": "\u2329",
+ "rang": "\u232A",
+ "loz": "\u25CA",
+ "spades": "\u2660",
+ "clubs": "\u2663",
+ "hearts": "\u2665",
+ "diams": "\u2666",
+ "quot": "\u0022",
+ "amp": "\u0026",
+ "lt": "\u003C",
+ "gt": "\u003E",
+ "OElig": "\u0152",
+ "oelig": "\u0153",
+ "Scaron": "\u0160",
+ "scaron": "\u0161",
+ "Yuml": "\u0178",
+ "circ": "\u02C6",
+ "tilde": "\u02DC",
+ "ensp": "\u2002",
+ "emsp": "\u2003",
+ "thinsp": "\u2009",
+ "zwnj": "\u200C",
+ "zwj": "\u200D",
+ "lrm": "\u200E",
+ "rlm": "\u200F",
+ "ndash": "\u2013",
+ "mdash": "\u2014",
+ "lsquo": "\u2018",
+ "rsquo": "\u2019",
+ "sbquo": "\u201A",
+ "ldquo": "\u201C",
+ "rdquo": "\u201D",
+ "bdquo": "\u201E",
+ "dagger": "\u2020",
+ "Dagger": "\u2021",
+ "permil": "\u2030",
+ "lsaquo": "\u2039",
+ "rsaquo": "\u203A",
+ "euro": "\u20AC",
+}
+
+// HTMLAutoClose is the set of HTML elements that
+// should be considered to close automatically.
+var HTMLAutoClose = htmlAutoClose
+
+var htmlAutoClose = []string{
+ /*
+ hget http://www.w3.org/TR/html4/loose.dtd |
+ 9 sed -n 's/<!ELEMENT ([^ ]*) +- O EMPTY.+/ "\1",/p' | tr A-Z a-z
+ */
+ "basefont",
+ "br",
+ "area",
+ "link",
+ "img",
+ "param",
+ "hr",
+ "input",
+ "col",
+ "frame",
+ "isindex",
+ "base",
+ "meta",
+}
+
+var (
+ esc_quot = []byte("&#34;") // shorter than "&quot;"
+ esc_apos = []byte("&#39;") // shorter than "&apos;"
+ esc_amp = []byte("&amp;")
+ esc_lt = []byte("&lt;")
+ esc_gt = []byte("&gt;")
+ esc_tab = []byte("&#x9;")
+ esc_nl = []byte("&#xA;")
+ esc_cr = []byte("&#xD;")
+ esc_fffd = []byte("\uFFFD") // Unicode replacement character
+)
+
+// EscapeText writes to w the properly escaped XML equivalent
+// of the plain text data s.
+func EscapeText(w io.Writer, s []byte) error {
+ return escapeText(w, s, true)
+}
+
+// escapeText writes to w the properly escaped XML equivalent
+// of the plain text data s. If escapeNewline is true, newline
+// characters will be escaped.
+func escapeText(w io.Writer, s []byte, escapeNewline bool) error {
+ var esc []byte
+ last := 0
+ for i := 0; i < len(s); {
+ r, width := utf8.DecodeRune(s[i:])
+ i += width
+ switch r {
+ case '"':
+ esc = esc_quot
+ case '\'':
+ esc = esc_apos
+ case '&':
+ esc = esc_amp
+ case '<':
+ esc = esc_lt
+ case '>':
+ esc = esc_gt
+ case '\t':
+ esc = esc_tab
+ case '\n':
+ if !escapeNewline {
+ continue
+ }
+ esc = esc_nl
+ case '\r':
+ esc = esc_cr
+ default:
+ if !isInCharacterRange(r) || (r == 0xFFFD && width == 1) {
+ esc = esc_fffd
+ break
+ }
+ continue
+ }
+ if _, err := w.Write(s[last : i-width]); err != nil {
+ return err
+ }
+ if _, err := w.Write(esc); err != nil {
+ return err
+ }
+ last = i
+ }
+ if _, err := w.Write(s[last:]); err != nil {
+ return err
+ }
+ return nil
+}
+
+// EscapeString writes to p the properly escaped XML equivalent
+// of the plain text data s.
+func (p *printer) EscapeString(s string) {
+ var esc []byte
+ last := 0
+ for i := 0; i < len(s); {
+ r, width := utf8.DecodeRuneInString(s[i:])
+ i += width
+ switch r {
+ case '"':
+ esc = esc_quot
+ case '\'':
+ esc = esc_apos
+ case '&':
+ esc = esc_amp
+ case '<':
+ esc = esc_lt
+ case '>':
+ esc = esc_gt
+ case '\t':
+ esc = esc_tab
+ case '\n':
+ esc = esc_nl
+ case '\r':
+ esc = esc_cr
+ default:
+ if !isInCharacterRange(r) || (r == 0xFFFD && width == 1) {
+ esc = esc_fffd
+ break
+ }
+ continue
+ }
+ p.WriteString(s[last : i-width])
+ p.Write(esc)
+ last = i
+ }
+ p.WriteString(s[last:])
+}
+
+// Escape is like EscapeText but omits the error return value.
+// It is provided for backwards compatibility with Go 1.0.
+// Code targeting Go 1.1 or later should use EscapeText.
+func Escape(w io.Writer, s []byte) {
+ EscapeText(w, s)
+}
+
+// procInst parses the `param="..."` or `param='...'`
+// value out of the provided string, returning "" if not found.
+func procInst(param, s string) string {
+ // TODO: this parsing is somewhat lame and not exact.
+ // It works for all actual cases, though.
+ param = param + "="
+ idx := strings.Index(s, param)
+ if idx == -1 {
+ return ""
+ }
+ v := s[idx+len(param):]
+ if v == "" {
+ return ""
+ }
+ if v[0] != '\'' && v[0] != '"' {
+ return ""
+ }
+ idx = strings.IndexRune(v[1:], rune(v[0]))
+ if idx == -1 {
+ return ""
+ }
+ return v[1 : idx+1]
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/internal/xml/xml_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/internal/xml/xml_test.go
new file mode 100644
index 000000000..af4cf8ea8
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/internal/xml/xml_test.go
@@ -0,0 +1,752 @@
+// Copyright 2009 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 xml
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "reflect"
+ "strings"
+ "testing"
+ "unicode/utf8"
+)
+
+const testInput = `
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<body xmlns:foo="ns1" xmlns="ns2" xmlns:tag="ns3" ` +
+ "\r\n\t" + ` >
+ <hello lang="en">World &lt;&gt;&apos;&quot; &#x767d;&#40300;翔</hello>
+ <query>&何; &is-it;</query>
+ <goodbye />
+ <outer foo:attr="value" xmlns:tag="ns4">
+ <inner/>
+ </outer>
+ <tag:name>
+ <![CDATA[Some text here.]]>
+ </tag:name>
+</body><!-- missing final newline -->`
+
+var testEntity = map[string]string{"何": "What", "is-it": "is it?"}
+
+var rawTokens = []Token{
+ CharData("\n"),
+ ProcInst{"xml", []byte(`version="1.0" encoding="UTF-8"`)},
+ CharData("\n"),
+ Directive(`DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"`),
+ CharData("\n"),
+ StartElement{Name{"", "body"}, []Attr{{Name{"xmlns", "foo"}, "ns1"}, {Name{"", "xmlns"}, "ns2"}, {Name{"xmlns", "tag"}, "ns3"}}},
+ CharData("\n "),
+ StartElement{Name{"", "hello"}, []Attr{{Name{"", "lang"}, "en"}}},
+ CharData("World <>'\" 白鵬翔"),
+ EndElement{Name{"", "hello"}},
+ CharData("\n "),
+ StartElement{Name{"", "query"}, []Attr{}},
+ CharData("What is it?"),
+ EndElement{Name{"", "query"}},
+ CharData("\n "),
+ StartElement{Name{"", "goodbye"}, []Attr{}},
+ EndElement{Name{"", "goodbye"}},
+ CharData("\n "),
+ StartElement{Name{"", "outer"}, []Attr{{Name{"foo", "attr"}, "value"}, {Name{"xmlns", "tag"}, "ns4"}}},
+ CharData("\n "),
+ StartElement{Name{"", "inner"}, []Attr{}},
+ EndElement{Name{"", "inner"}},
+ CharData("\n "),
+ EndElement{Name{"", "outer"}},
+ CharData("\n "),
+ StartElement{Name{"tag", "name"}, []Attr{}},
+ CharData("\n "),
+ CharData("Some text here."),
+ CharData("\n "),
+ EndElement{Name{"tag", "name"}},
+ CharData("\n"),
+ EndElement{Name{"", "body"}},
+ Comment(" missing final newline "),
+}
+
+var cookedTokens = []Token{
+ CharData("\n"),
+ ProcInst{"xml", []byte(`version="1.0" encoding="UTF-8"`)},
+ CharData("\n"),
+ Directive(`DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"`),
+ CharData("\n"),
+ StartElement{Name{"ns2", "body"}, []Attr{{Name{"xmlns", "foo"}, "ns1"}, {Name{"", "xmlns"}, "ns2"}, {Name{"xmlns", "tag"}, "ns3"}}},
+ CharData("\n "),
+ StartElement{Name{"ns2", "hello"}, []Attr{{Name{"", "lang"}, "en"}}},
+ CharData("World <>'\" 白鵬翔"),
+ EndElement{Name{"ns2", "hello"}},
+ CharData("\n "),
+ StartElement{Name{"ns2", "query"}, []Attr{}},
+ CharData("What is it?"),
+ EndElement{Name{"ns2", "query"}},
+ CharData("\n "),
+ StartElement{Name{"ns2", "goodbye"}, []Attr{}},
+ EndElement{Name{"ns2", "goodbye"}},
+ CharData("\n "),
+ StartElement{Name{"ns2", "outer"}, []Attr{{Name{"ns1", "attr"}, "value"}, {Name{"xmlns", "tag"}, "ns4"}}},
+ CharData("\n "),
+ StartElement{Name{"ns2", "inner"}, []Attr{}},
+ EndElement{Name{"ns2", "inner"}},
+ CharData("\n "),
+ EndElement{Name{"ns2", "outer"}},
+ CharData("\n "),
+ StartElement{Name{"ns3", "name"}, []Attr{}},
+ CharData("\n "),
+ CharData("Some text here."),
+ CharData("\n "),
+ EndElement{Name{"ns3", "name"}},
+ CharData("\n"),
+ EndElement{Name{"ns2", "body"}},
+ Comment(" missing final newline "),
+}
+
+const testInputAltEncoding = `
+<?xml version="1.0" encoding="x-testing-uppercase"?>
+<TAG>VALUE</TAG>`
+
+var rawTokensAltEncoding = []Token{
+ CharData("\n"),
+ ProcInst{"xml", []byte(`version="1.0" encoding="x-testing-uppercase"`)},
+ CharData("\n"),
+ StartElement{Name{"", "tag"}, []Attr{}},
+ CharData("value"),
+ EndElement{Name{"", "tag"}},
+}
+
+var xmlInput = []string{
+ // unexpected EOF cases
+ "<",
+ "<t",
+ "<t ",
+ "<t/",
+ "<!",
+ "<!-",
+ "<!--",
+ "<!--c-",
+ "<!--c--",
+ "<!d",
+ "<t></",
+ "<t></t",
+ "<?",
+ "<?p",
+ "<t a",
+ "<t a=",
+ "<t a='",
+ "<t a=''",
+ "<t/><![",
+ "<t/><![C",
+ "<t/><![CDATA[d",
+ "<t/><![CDATA[d]",
+ "<t/><![CDATA[d]]",
+
+ // other Syntax errors
+ "<>",
+ "<t/a",
+ "<0 />",
+ "<?0 >",
+ // "<!0 >", // let the Token() caller handle
+ "</0>",
+ "<t 0=''>",
+ "<t a='&'>",
+ "<t a='<'>",
+ "<t>&nbspc;</t>",
+ "<t a>",
+ "<t a=>",
+ "<t a=v>",
+ // "<![CDATA[d]]>", // let the Token() caller handle
+ "<t></e>",
+ "<t></>",
+ "<t></t!",
+ "<t>cdata]]></t>",
+}
+
+func TestRawToken(t *testing.T) {
+ d := NewDecoder(strings.NewReader(testInput))
+ d.Entity = testEntity
+ testRawToken(t, d, testInput, rawTokens)
+}
+
+const nonStrictInput = `
+<tag>non&entity</tag>
+<tag>&unknown;entity</tag>
+<tag>&#123</tag>
+<tag>&#zzz;</tag>
+<tag>&なまえ3;</tag>
+<tag>&lt-gt;</tag>
+<tag>&;</tag>
+<tag>&0a;</tag>
+`
+
+var nonStringEntity = map[string]string{"": "oops!", "0a": "oops!"}
+
+var nonStrictTokens = []Token{
+ CharData("\n"),
+ StartElement{Name{"", "tag"}, []Attr{}},
+ CharData("non&entity"),
+ EndElement{Name{"", "tag"}},
+ CharData("\n"),
+ StartElement{Name{"", "tag"}, []Attr{}},
+ CharData("&unknown;entity"),
+ EndElement{Name{"", "tag"}},
+ CharData("\n"),
+ StartElement{Name{"", "tag"}, []Attr{}},
+ CharData("&#123"),
+ EndElement{Name{"", "tag"}},
+ CharData("\n"),
+ StartElement{Name{"", "tag"}, []Attr{}},
+ CharData("&#zzz;"),
+ EndElement{Name{"", "tag"}},
+ CharData("\n"),
+ StartElement{Name{"", "tag"}, []Attr{}},
+ CharData("&なまえ3;"),
+ EndElement{Name{"", "tag"}},
+ CharData("\n"),
+ StartElement{Name{"", "tag"}, []Attr{}},
+ CharData("&lt-gt;"),
+ EndElement{Name{"", "tag"}},
+ CharData("\n"),
+ StartElement{Name{"", "tag"}, []Attr{}},
+ CharData("&;"),
+ EndElement{Name{"", "tag"}},
+ CharData("\n"),
+ StartElement{Name{"", "tag"}, []Attr{}},
+ CharData("&0a;"),
+ EndElement{Name{"", "tag"}},
+ CharData("\n"),
+}
+
+func TestNonStrictRawToken(t *testing.T) {
+ d := NewDecoder(strings.NewReader(nonStrictInput))
+ d.Strict = false
+ testRawToken(t, d, nonStrictInput, nonStrictTokens)
+}
+
+type downCaser struct {
+ t *testing.T
+ r io.ByteReader
+}
+
+func (d *downCaser) ReadByte() (c byte, err error) {
+ c, err = d.r.ReadByte()
+ if c >= 'A' && c <= 'Z' {
+ c += 'a' - 'A'
+ }
+ return
+}
+
+func (d *downCaser) Read(p []byte) (int, error) {
+ d.t.Fatalf("unexpected Read call on downCaser reader")
+ panic("unreachable")
+}
+
+func TestRawTokenAltEncoding(t *testing.T) {
+ d := NewDecoder(strings.NewReader(testInputAltEncoding))
+ d.CharsetReader = func(charset string, input io.Reader) (io.Reader, error) {
+ if charset != "x-testing-uppercase" {
+ t.Fatalf("unexpected charset %q", charset)
+ }
+ return &downCaser{t, input.(io.ByteReader)}, nil
+ }
+ testRawToken(t, d, testInputAltEncoding, rawTokensAltEncoding)
+}
+
+func TestRawTokenAltEncodingNoConverter(t *testing.T) {
+ d := NewDecoder(strings.NewReader(testInputAltEncoding))
+ token, err := d.RawToken()
+ if token == nil {
+ t.Fatalf("expected a token on first RawToken call")
+ }
+ if err != nil {
+ t.Fatal(err)
+ }
+ token, err = d.RawToken()
+ if token != nil {
+ t.Errorf("expected a nil token; got %#v", token)
+ }
+ if err == nil {
+ t.Fatalf("expected an error on second RawToken call")
+ }
+ const encoding = "x-testing-uppercase"
+ if !strings.Contains(err.Error(), encoding) {
+ t.Errorf("expected error to contain %q; got error: %v",
+ encoding, err)
+ }
+}
+
+func testRawToken(t *testing.T, d *Decoder, raw string, rawTokens []Token) {
+ lastEnd := int64(0)
+ for i, want := range rawTokens {
+ start := d.InputOffset()
+ have, err := d.RawToken()
+ end := d.InputOffset()
+ if err != nil {
+ t.Fatalf("token %d: unexpected error: %s", i, err)
+ }
+ if !reflect.DeepEqual(have, want) {
+ var shave, swant string
+ if _, ok := have.(CharData); ok {
+ shave = fmt.Sprintf("CharData(%q)", have)
+ } else {
+ shave = fmt.Sprintf("%#v", have)
+ }
+ if _, ok := want.(CharData); ok {
+ swant = fmt.Sprintf("CharData(%q)", want)
+ } else {
+ swant = fmt.Sprintf("%#v", want)
+ }
+ t.Errorf("token %d = %s, want %s", i, shave, swant)
+ }
+
+ // Check that InputOffset returned actual token.
+ switch {
+ case start < lastEnd:
+ t.Errorf("token %d: position [%d,%d) for %T is before previous token", i, start, end, have)
+ case start >= end:
+ // Special case: EndElement can be synthesized.
+ if start == end && end == lastEnd {
+ break
+ }
+ t.Errorf("token %d: position [%d,%d) for %T is empty", i, start, end, have)
+ case end > int64(len(raw)):
+ t.Errorf("token %d: position [%d,%d) for %T extends beyond input", i, start, end, have)
+ default:
+ text := raw[start:end]
+ if strings.ContainsAny(text, "<>") && (!strings.HasPrefix(text, "<") || !strings.HasSuffix(text, ">")) {
+ t.Errorf("token %d: misaligned raw token %#q for %T", i, text, have)
+ }
+ }
+ lastEnd = end
+ }
+}
+
+// Ensure that directives (specifically !DOCTYPE) include the complete
+// text of any nested directives, noting that < and > do not change
+// nesting depth if they are in single or double quotes.
+
+var nestedDirectivesInput = `
+<!DOCTYPE [<!ENTITY rdf "http://www.w3.org/1999/02/22-rdf-syntax-ns#">]>
+<!DOCTYPE [<!ENTITY xlt ">">]>
+<!DOCTYPE [<!ENTITY xlt "<">]>
+<!DOCTYPE [<!ENTITY xlt '>'>]>
+<!DOCTYPE [<!ENTITY xlt '<'>]>
+<!DOCTYPE [<!ENTITY xlt '">'>]>
+<!DOCTYPE [<!ENTITY xlt "'<">]>
+`
+
+var nestedDirectivesTokens = []Token{
+ CharData("\n"),
+ Directive(`DOCTYPE [<!ENTITY rdf "http://www.w3.org/1999/02/22-rdf-syntax-ns#">]`),
+ CharData("\n"),
+ Directive(`DOCTYPE [<!ENTITY xlt ">">]`),
+ CharData("\n"),
+ Directive(`DOCTYPE [<!ENTITY xlt "<">]`),
+ CharData("\n"),
+ Directive(`DOCTYPE [<!ENTITY xlt '>'>]`),
+ CharData("\n"),
+ Directive(`DOCTYPE [<!ENTITY xlt '<'>]`),
+ CharData("\n"),
+ Directive(`DOCTYPE [<!ENTITY xlt '">'>]`),
+ CharData("\n"),
+ Directive(`DOCTYPE [<!ENTITY xlt "'<">]`),
+ CharData("\n"),
+}
+
+func TestNestedDirectives(t *testing.T) {
+ d := NewDecoder(strings.NewReader(nestedDirectivesInput))
+
+ for i, want := range nestedDirectivesTokens {
+ have, err := d.Token()
+ if err != nil {
+ t.Fatalf("token %d: unexpected error: %s", i, err)
+ }
+ if !reflect.DeepEqual(have, want) {
+ t.Errorf("token %d = %#v want %#v", i, have, want)
+ }
+ }
+}
+
+func TestToken(t *testing.T) {
+ d := NewDecoder(strings.NewReader(testInput))
+ d.Entity = testEntity
+
+ for i, want := range cookedTokens {
+ have, err := d.Token()
+ if err != nil {
+ t.Fatalf("token %d: unexpected error: %s", i, err)
+ }
+ if !reflect.DeepEqual(have, want) {
+ t.Errorf("token %d = %#v want %#v", i, have, want)
+ }
+ }
+}
+
+func TestSyntax(t *testing.T) {
+ for i := range xmlInput {
+ d := NewDecoder(strings.NewReader(xmlInput[i]))
+ var err error
+ for _, err = d.Token(); err == nil; _, err = d.Token() {
+ }
+ if _, ok := err.(*SyntaxError); !ok {
+ t.Fatalf(`xmlInput "%s": expected SyntaxError not received`, xmlInput[i])
+ }
+ }
+}
+
+type allScalars struct {
+ True1 bool
+ True2 bool
+ False1 bool
+ False2 bool
+ Int int
+ Int8 int8
+ Int16 int16
+ Int32 int32
+ Int64 int64
+ Uint int
+ Uint8 uint8
+ Uint16 uint16
+ Uint32 uint32
+ Uint64 uint64
+ Uintptr uintptr
+ Float32 float32
+ Float64 float64
+ String string
+ PtrString *string
+}
+
+var all = allScalars{
+ True1: true,
+ True2: true,
+ False1: false,
+ False2: false,
+ Int: 1,
+ Int8: -2,
+ Int16: 3,
+ Int32: -4,
+ Int64: 5,
+ Uint: 6,
+ Uint8: 7,
+ Uint16: 8,
+ Uint32: 9,
+ Uint64: 10,
+ Uintptr: 11,
+ Float32: 13.0,
+ Float64: 14.0,
+ String: "15",
+ PtrString: &sixteen,
+}
+
+var sixteen = "16"
+
+const testScalarsInput = `<allscalars>
+ <True1>true</True1>
+ <True2>1</True2>
+ <False1>false</False1>
+ <False2>0</False2>
+ <Int>1</Int>
+ <Int8>-2</Int8>
+ <Int16>3</Int16>
+ <Int32>-4</Int32>
+ <Int64>5</Int64>
+ <Uint>6</Uint>
+ <Uint8>7</Uint8>
+ <Uint16>8</Uint16>
+ <Uint32>9</Uint32>
+ <Uint64>10</Uint64>
+ <Uintptr>11</Uintptr>
+ <Float>12.0</Float>
+ <Float32>13.0</Float32>
+ <Float64>14.0</Float64>
+ <String>15</String>
+ <PtrString>16</PtrString>
+</allscalars>`
+
+func TestAllScalars(t *testing.T) {
+ var a allScalars
+ err := Unmarshal([]byte(testScalarsInput), &a)
+
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !reflect.DeepEqual(a, all) {
+ t.Errorf("have %+v want %+v", a, all)
+ }
+}
+
+type item struct {
+ Field_a string
+}
+
+func TestIssue569(t *testing.T) {
+ data := `<item><Field_a>abcd</Field_a></item>`
+ var i item
+ err := Unmarshal([]byte(data), &i)
+
+ if err != nil || i.Field_a != "abcd" {
+ t.Fatal("Expecting abcd")
+ }
+}
+
+func TestUnquotedAttrs(t *testing.T) {
+ data := "<tag attr=azAZ09:-_\t>"
+ d := NewDecoder(strings.NewReader(data))
+ d.Strict = false
+ token, err := d.Token()
+ if _, ok := err.(*SyntaxError); ok {
+ t.Errorf("Unexpected error: %v", err)
+ }
+ if token.(StartElement).Name.Local != "tag" {
+ t.Errorf("Unexpected tag name: %v", token.(StartElement).Name.Local)
+ }
+ attr := token.(StartElement).Attr[0]
+ if attr.Value != "azAZ09:-_" {
+ t.Errorf("Unexpected attribute value: %v", attr.Value)
+ }
+ if attr.Name.Local != "attr" {
+ t.Errorf("Unexpected attribute name: %v", attr.Name.Local)
+ }
+}
+
+func TestValuelessAttrs(t *testing.T) {
+ tests := [][3]string{
+ {"<p nowrap>", "p", "nowrap"},
+ {"<p nowrap >", "p", "nowrap"},
+ {"<input checked/>", "input", "checked"},
+ {"<input checked />", "input", "checked"},
+ }
+ for _, test := range tests {
+ d := NewDecoder(strings.NewReader(test[0]))
+ d.Strict = false
+ token, err := d.Token()
+ if _, ok := err.(*SyntaxError); ok {
+ t.Errorf("Unexpected error: %v", err)
+ }
+ if token.(StartElement).Name.Local != test[1] {
+ t.Errorf("Unexpected tag name: %v", token.(StartElement).Name.Local)
+ }
+ attr := token.(StartElement).Attr[0]
+ if attr.Value != test[2] {
+ t.Errorf("Unexpected attribute value: %v", attr.Value)
+ }
+ if attr.Name.Local != test[2] {
+ t.Errorf("Unexpected attribute name: %v", attr.Name.Local)
+ }
+ }
+}
+
+func TestCopyTokenCharData(t *testing.T) {
+ data := []byte("same data")
+ var tok1 Token = CharData(data)
+ tok2 := CopyToken(tok1)
+ if !reflect.DeepEqual(tok1, tok2) {
+ t.Error("CopyToken(CharData) != CharData")
+ }
+ data[1] = 'o'
+ if reflect.DeepEqual(tok1, tok2) {
+ t.Error("CopyToken(CharData) uses same buffer.")
+ }
+}
+
+func TestCopyTokenStartElement(t *testing.T) {
+ elt := StartElement{Name{"", "hello"}, []Attr{{Name{"", "lang"}, "en"}}}
+ var tok1 Token = elt
+ tok2 := CopyToken(tok1)
+ if tok1.(StartElement).Attr[0].Value != "en" {
+ t.Error("CopyToken overwrote Attr[0]")
+ }
+ if !reflect.DeepEqual(tok1, tok2) {
+ t.Error("CopyToken(StartElement) != StartElement")
+ }
+ tok1.(StartElement).Attr[0] = Attr{Name{"", "lang"}, "de"}
+ if reflect.DeepEqual(tok1, tok2) {
+ t.Error("CopyToken(CharData) uses same buffer.")
+ }
+}
+
+func TestSyntaxErrorLineNum(t *testing.T) {
+ testInput := "<P>Foo<P>\n\n<P>Bar</>\n"
+ d := NewDecoder(strings.NewReader(testInput))
+ var err error
+ for _, err = d.Token(); err == nil; _, err = d.Token() {
+ }
+ synerr, ok := err.(*SyntaxError)
+ if !ok {
+ t.Error("Expected SyntaxError.")
+ }
+ if synerr.Line != 3 {
+ t.Error("SyntaxError didn't have correct line number.")
+ }
+}
+
+func TestTrailingRawToken(t *testing.T) {
+ input := `<FOO></FOO> `
+ d := NewDecoder(strings.NewReader(input))
+ var err error
+ for _, err = d.RawToken(); err == nil; _, err = d.RawToken() {
+ }
+ if err != io.EOF {
+ t.Fatalf("d.RawToken() = _, %v, want _, io.EOF", err)
+ }
+}
+
+func TestTrailingToken(t *testing.T) {
+ input := `<FOO></FOO> `
+ d := NewDecoder(strings.NewReader(input))
+ var err error
+ for _, err = d.Token(); err == nil; _, err = d.Token() {
+ }
+ if err != io.EOF {
+ t.Fatalf("d.Token() = _, %v, want _, io.EOF", err)
+ }
+}
+
+func TestEntityInsideCDATA(t *testing.T) {
+ input := `<test><![CDATA[ &val=foo ]]></test>`
+ d := NewDecoder(strings.NewReader(input))
+ var err error
+ for _, err = d.Token(); err == nil; _, err = d.Token() {
+ }
+ if err != io.EOF {
+ t.Fatalf("d.Token() = _, %v, want _, io.EOF", err)
+ }
+}
+
+var characterTests = []struct {
+ in string
+ err string
+}{
+ {"\x12<doc/>", "illegal character code U+0012"},
+ {"<?xml version=\"1.0\"?>\x0b<doc/>", "illegal character code U+000B"},
+ {"\xef\xbf\xbe<doc/>", "illegal character code U+FFFE"},
+ {"<?xml version=\"1.0\"?><doc>\r\n<hiya/>\x07<toots/></doc>", "illegal character code U+0007"},
+ {"<?xml version=\"1.0\"?><doc \x12='value'>what's up</doc>", "expected attribute name in element"},
+ {"<doc>&abc\x01;</doc>", "invalid character entity &abc (no semicolon)"},
+ {"<doc>&\x01;</doc>", "invalid character entity & (no semicolon)"},
+ {"<doc>&\xef\xbf\xbe;</doc>", "invalid character entity &\uFFFE;"},
+ {"<doc>&hello;</doc>", "invalid character entity &hello;"},
+}
+
+func TestDisallowedCharacters(t *testing.T) {
+
+ for i, tt := range characterTests {
+ d := NewDecoder(strings.NewReader(tt.in))
+ var err error
+
+ for err == nil {
+ _, err = d.Token()
+ }
+ synerr, ok := err.(*SyntaxError)
+ if !ok {
+ t.Fatalf("input %d d.Token() = _, %v, want _, *SyntaxError", i, err)
+ }
+ if synerr.Msg != tt.err {
+ t.Fatalf("input %d synerr.Msg wrong: want %q, got %q", i, tt.err, synerr.Msg)
+ }
+ }
+}
+
+type procInstEncodingTest struct {
+ expect, got string
+}
+
+var procInstTests = []struct {
+ input string
+ expect [2]string
+}{
+ {`version="1.0" encoding="utf-8"`, [2]string{"1.0", "utf-8"}},
+ {`version="1.0" encoding='utf-8'`, [2]string{"1.0", "utf-8"}},
+ {`version="1.0" encoding='utf-8' `, [2]string{"1.0", "utf-8"}},
+ {`version="1.0" encoding=utf-8`, [2]string{"1.0", ""}},
+ {`encoding="FOO" `, [2]string{"", "FOO"}},
+}
+
+func TestProcInstEncoding(t *testing.T) {
+ for _, test := range procInstTests {
+ if got := procInst("version", test.input); got != test.expect[0] {
+ t.Errorf("procInst(version, %q) = %q; want %q", test.input, got, test.expect[0])
+ }
+ if got := procInst("encoding", test.input); got != test.expect[1] {
+ t.Errorf("procInst(encoding, %q) = %q; want %q", test.input, got, test.expect[1])
+ }
+ }
+}
+
+// Ensure that directives with comments include the complete
+// text of any nested directives.
+
+var directivesWithCommentsInput = `
+<!DOCTYPE [<!-- a comment --><!ENTITY rdf "http://www.w3.org/1999/02/22-rdf-syntax-ns#">]>
+<!DOCTYPE [<!ENTITY go "Golang"><!-- a comment-->]>
+<!DOCTYPE <!-> <!> <!----> <!-->--> <!--->--> [<!ENTITY go "Golang"><!-- a comment-->]>
+`
+
+var directivesWithCommentsTokens = []Token{
+ CharData("\n"),
+ Directive(`DOCTYPE [<!ENTITY rdf "http://www.w3.org/1999/02/22-rdf-syntax-ns#">]`),
+ CharData("\n"),
+ Directive(`DOCTYPE [<!ENTITY go "Golang">]`),
+ CharData("\n"),
+ Directive(`DOCTYPE <!-> <!> [<!ENTITY go "Golang">]`),
+ CharData("\n"),
+}
+
+func TestDirectivesWithComments(t *testing.T) {
+ d := NewDecoder(strings.NewReader(directivesWithCommentsInput))
+
+ for i, want := range directivesWithCommentsTokens {
+ have, err := d.Token()
+ if err != nil {
+ t.Fatalf("token %d: unexpected error: %s", i, err)
+ }
+ if !reflect.DeepEqual(have, want) {
+ t.Errorf("token %d = %#v want %#v", i, have, want)
+ }
+ }
+}
+
+// Writer whose Write method always returns an error.
+type errWriter struct{}
+
+func (errWriter) Write(p []byte) (n int, err error) { return 0, fmt.Errorf("unwritable") }
+
+func TestEscapeTextIOErrors(t *testing.T) {
+ expectErr := "unwritable"
+ err := EscapeText(errWriter{}, []byte{'A'})
+
+ if err == nil || err.Error() != expectErr {
+ t.Errorf("have %v, want %v", err, expectErr)
+ }
+}
+
+func TestEscapeTextInvalidChar(t *testing.T) {
+ input := []byte("A \x00 terminated string.")
+ expected := "A \uFFFD terminated string."
+
+ buff := new(bytes.Buffer)
+ if err := EscapeText(buff, input); err != nil {
+ t.Fatalf("have %v, want nil", err)
+ }
+ text := buff.String()
+
+ if text != expected {
+ t.Errorf("have %v, want %v", text, expected)
+ }
+}
+
+func TestIssue5880(t *testing.T) {
+ type T []byte
+ data, err := Marshal(T{192, 168, 0, 1})
+ if err != nil {
+ t.Errorf("Marshal error: %v", err)
+ }
+ if !utf8.Valid(data) {
+ t.Errorf("Marshal generated invalid UTF-8: %x", data)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/litmus_test_server.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/litmus_test_server.go
new file mode 100644
index 000000000..514db5dd1
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/litmus_test_server.go
@@ -0,0 +1,94 @@
+// Copyright 2015 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.
+
+// +build ignore
+
+/*
+This program is a server for the WebDAV 'litmus' compliance test at
+http://www.webdav.org/neon/litmus/
+To run the test:
+
+go run litmus_test_server.go
+
+and separately, from the downloaded litmus-xxx directory:
+
+make URL=http://localhost:9999/ check
+*/
+package main
+
+import (
+ "flag"
+ "fmt"
+ "log"
+ "net/http"
+ "net/url"
+
+ "golang.org/x/net/webdav"
+)
+
+var port = flag.Int("port", 9999, "server port")
+
+func main() {
+ flag.Parse()
+ log.SetFlags(0)
+ h := &webdav.Handler{
+ FileSystem: webdav.NewMemFS(),
+ LockSystem: webdav.NewMemLS(),
+ Logger: func(r *http.Request, err error) {
+ litmus := r.Header.Get("X-Litmus")
+ if len(litmus) > 19 {
+ litmus = litmus[:16] + "..."
+ }
+
+ switch r.Method {
+ case "COPY", "MOVE":
+ dst := ""
+ if u, err := url.Parse(r.Header.Get("Destination")); err == nil {
+ dst = u.Path
+ }
+ o := r.Header.Get("Overwrite")
+ log.Printf("%-20s%-10s%-30s%-30so=%-2s%v", litmus, r.Method, r.URL.Path, dst, o, err)
+ default:
+ log.Printf("%-20s%-10s%-30s%v", litmus, r.Method, r.URL.Path, err)
+ }
+ },
+ }
+
+ // The next line would normally be:
+ // http.Handle("/", h)
+ // but we wrap that HTTP handler h to cater for a special case.
+ //
+ // The propfind_invalid2 litmus test case expects an empty namespace prefix
+ // declaration to be an error. The FAQ in the webdav litmus test says:
+ //
+ // "What does the "propfind_invalid2" test check for?...
+ //
+ // If a request was sent with an XML body which included an empty namespace
+ // prefix declaration (xmlns:ns1=""), then the server must reject that with
+ // a "400 Bad Request" response, as it is invalid according to the XML
+ // Namespace specification."
+ //
+ // On the other hand, the Go standard library's encoding/xml package
+ // accepts an empty xmlns namespace, as per the discussion at
+ // https://github.com/golang/go/issues/8068
+ //
+ // Empty namespaces seem disallowed in the second (2006) edition of the XML
+ // standard, but allowed in a later edition. The grammar differs between
+ // http://www.w3.org/TR/2006/REC-xml-names-20060816/#ns-decl and
+ // http://www.w3.org/TR/REC-xml-names/#dt-prefix
+ //
+ // Thus, we assume that the propfind_invalid2 test is obsolete, and
+ // hard-code the 400 Bad Request response that the test expects.
+ http.Handle("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if r.Header.Get("X-Litmus") == "props: 3 (propfind_invalid2)" {
+ http.Error(w, "400 Bad Request", http.StatusBadRequest)
+ return
+ }
+ h.ServeHTTP(w, r)
+ }))
+
+ addr := fmt.Sprintf(":%d", *port)
+ log.Printf("Serving %v", addr)
+ log.Fatal(http.ListenAndServe(addr, nil))
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/lock.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/lock.go
new file mode 100644
index 000000000..344ac5cea
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/lock.go
@@ -0,0 +1,445 @@
+// Copyright 2014 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 webdav
+
+import (
+ "container/heap"
+ "errors"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+)
+
+var (
+ // ErrConfirmationFailed is returned by a LockSystem's Confirm method.
+ ErrConfirmationFailed = errors.New("webdav: confirmation failed")
+ // ErrForbidden is returned by a LockSystem's Unlock method.
+ ErrForbidden = errors.New("webdav: forbidden")
+ // ErrLocked is returned by a LockSystem's Create, Refresh and Unlock methods.
+ ErrLocked = errors.New("webdav: locked")
+ // ErrNoSuchLock is returned by a LockSystem's Refresh and Unlock methods.
+ ErrNoSuchLock = errors.New("webdav: no such lock")
+)
+
+// Condition can match a WebDAV resource, based on a token or ETag.
+// Exactly one of Token and ETag should be non-empty.
+type Condition struct {
+ Not bool
+ Token string
+ ETag string
+}
+
+// LockSystem manages access to a collection of named resources. The elements
+// in a lock name are separated by slash ('/', U+002F) characters, regardless
+// of host operating system convention.
+type LockSystem interface {
+ // Confirm confirms that the caller can claim all of the locks specified by
+ // the given conditions, and that holding the union of all of those locks
+ // gives exclusive access to all of the named resources. Up to two resources
+ // can be named. Empty names are ignored.
+ //
+ // Exactly one of release and err will be non-nil. If release is non-nil,
+ // all of the requested locks are held until release is called. Calling
+ // release does not unlock the lock, in the WebDAV UNLOCK sense, but once
+ // Confirm has confirmed that a lock claim is valid, that lock cannot be
+ // Confirmed again until it has been released.
+ //
+ // If Confirm returns ErrConfirmationFailed then the Handler will continue
+ // to try any other set of locks presented (a WebDAV HTTP request can
+ // present more than one set of locks). If it returns any other non-nil
+ // error, the Handler will write a "500 Internal Server Error" HTTP status.
+ Confirm(now time.Time, name0, name1 string, conditions ...Condition) (release func(), err error)
+
+ // Create creates a lock with the given depth, duration, owner and root
+ // (name). The depth will either be negative (meaning infinite) or zero.
+ //
+ // If Create returns ErrLocked then the Handler will write a "423 Locked"
+ // HTTP status. If it returns any other non-nil error, the Handler will
+ // write a "500 Internal Server Error" HTTP status.
+ //
+ // See http://www.webdav.org/specs/rfc4918.html#rfc.section.9.10.6 for
+ // when to use each error.
+ //
+ // The token returned identifies the created lock. It should be an absolute
+ // URI as defined by RFC 3986, Section 4.3. In particular, it should not
+ // contain whitespace.
+ Create(now time.Time, details LockDetails) (token string, err error)
+
+ // Refresh refreshes the lock with the given token.
+ //
+ // If Refresh returns ErrLocked then the Handler will write a "423 Locked"
+ // HTTP Status. If Refresh returns ErrNoSuchLock then the Handler will write
+ // a "412 Precondition Failed" HTTP Status. If it returns any other non-nil
+ // error, the Handler will write a "500 Internal Server Error" HTTP status.
+ //
+ // See http://www.webdav.org/specs/rfc4918.html#rfc.section.9.10.6 for
+ // when to use each error.
+ Refresh(now time.Time, token string, duration time.Duration) (LockDetails, error)
+
+ // Unlock unlocks the lock with the given token.
+ //
+ // If Unlock returns ErrForbidden then the Handler will write a "403
+ // Forbidden" HTTP Status. If Unlock returns ErrLocked then the Handler
+ // will write a "423 Locked" HTTP status. If Unlock returns ErrNoSuchLock
+ // then the Handler will write a "409 Conflict" HTTP Status. If it returns
+ // any other non-nil error, the Handler will write a "500 Internal Server
+ // Error" HTTP status.
+ //
+ // See http://www.webdav.org/specs/rfc4918.html#rfc.section.9.11.1 for
+ // when to use each error.
+ Unlock(now time.Time, token string) error
+}
+
+// LockDetails are a lock's metadata.
+type LockDetails struct {
+ // Root is the root resource name being locked. For a zero-depth lock, the
+ // root is the only resource being locked.
+ Root string
+ // Duration is the lock timeout. A negative duration means infinite.
+ Duration time.Duration
+ // OwnerXML is the verbatim <owner> XML given in a LOCK HTTP request.
+ //
+ // TODO: does the "verbatim" nature play well with XML namespaces?
+ // Does the OwnerXML field need to have more structure? See
+ // https://codereview.appspot.com/175140043/#msg2
+ OwnerXML string
+ // ZeroDepth is whether the lock has zero depth. If it does not have zero
+ // depth, it has infinite depth.
+ ZeroDepth bool
+}
+
+// NewMemLS returns a new in-memory LockSystem.
+func NewMemLS() LockSystem {
+ return &memLS{
+ byName: make(map[string]*memLSNode),
+ byToken: make(map[string]*memLSNode),
+ gen: uint64(time.Now().Unix()),
+ }
+}
+
+type memLS struct {
+ mu sync.Mutex
+ byName map[string]*memLSNode
+ byToken map[string]*memLSNode
+ gen uint64
+ // byExpiry only contains those nodes whose LockDetails have a finite
+ // Duration and are yet to expire.
+ byExpiry byExpiry
+}
+
+func (m *memLS) nextToken() string {
+ m.gen++
+ return strconv.FormatUint(m.gen, 10)
+}
+
+func (m *memLS) collectExpiredNodes(now time.Time) {
+ for len(m.byExpiry) > 0 {
+ if now.Before(m.byExpiry[0].expiry) {
+ break
+ }
+ m.remove(m.byExpiry[0])
+ }
+}
+
+func (m *memLS) Confirm(now time.Time, name0, name1 string, conditions ...Condition) (func(), error) {
+ m.mu.Lock()
+ defer m.mu.Unlock()
+ m.collectExpiredNodes(now)
+
+ var n0, n1 *memLSNode
+ if name0 != "" {
+ if n0 = m.lookup(slashClean(name0), conditions...); n0 == nil {
+ return nil, ErrConfirmationFailed
+ }
+ }
+ if name1 != "" {
+ if n1 = m.lookup(slashClean(name1), conditions...); n1 == nil {
+ return nil, ErrConfirmationFailed
+ }
+ }
+
+ // Don't hold the same node twice.
+ if n1 == n0 {
+ n1 = nil
+ }
+
+ if n0 != nil {
+ m.hold(n0)
+ }
+ if n1 != nil {
+ m.hold(n1)
+ }
+ return func() {
+ m.mu.Lock()
+ defer m.mu.Unlock()
+ if n1 != nil {
+ m.unhold(n1)
+ }
+ if n0 != nil {
+ m.unhold(n0)
+ }
+ }, nil
+}
+
+// lookup returns the node n that locks the named resource, provided that n
+// matches at least one of the given conditions and that lock isn't held by
+// another party. Otherwise, it returns nil.
+//
+// n may be a parent of the named resource, if n is an infinite depth lock.
+func (m *memLS) lookup(name string, conditions ...Condition) (n *memLSNode) {
+ // TODO: support Condition.Not and Condition.ETag.
+ for _, c := range conditions {
+ n = m.byToken[c.Token]
+ if n == nil || n.held {
+ continue
+ }
+ if name == n.details.Root {
+ return n
+ }
+ if n.details.ZeroDepth {
+ continue
+ }
+ if n.details.Root == "/" || strings.HasPrefix(name, n.details.Root+"/") {
+ return n
+ }
+ }
+ return nil
+}
+
+func (m *memLS) hold(n *memLSNode) {
+ if n.held {
+ panic("webdav: memLS inconsistent held state")
+ }
+ n.held = true
+ if n.details.Duration >= 0 && n.byExpiryIndex >= 0 {
+ heap.Remove(&m.byExpiry, n.byExpiryIndex)
+ }
+}
+
+func (m *memLS) unhold(n *memLSNode) {
+ if !n.held {
+ panic("webdav: memLS inconsistent held state")
+ }
+ n.held = false
+ if n.details.Duration >= 0 {
+ heap.Push(&m.byExpiry, n)
+ }
+}
+
+func (m *memLS) Create(now time.Time, details LockDetails) (string, error) {
+ m.mu.Lock()
+ defer m.mu.Unlock()
+ m.collectExpiredNodes(now)
+ details.Root = slashClean(details.Root)
+
+ if !m.canCreate(details.Root, details.ZeroDepth) {
+ return "", ErrLocked
+ }
+ n := m.create(details.Root)
+ n.token = m.nextToken()
+ m.byToken[n.token] = n
+ n.details = details
+ if n.details.Duration >= 0 {
+ n.expiry = now.Add(n.details.Duration)
+ heap.Push(&m.byExpiry, n)
+ }
+ return n.token, nil
+}
+
+func (m *memLS) Refresh(now time.Time, token string, duration time.Duration) (LockDetails, error) {
+ m.mu.Lock()
+ defer m.mu.Unlock()
+ m.collectExpiredNodes(now)
+
+ n := m.byToken[token]
+ if n == nil {
+ return LockDetails{}, ErrNoSuchLock
+ }
+ if n.held {
+ return LockDetails{}, ErrLocked
+ }
+ if n.byExpiryIndex >= 0 {
+ heap.Remove(&m.byExpiry, n.byExpiryIndex)
+ }
+ n.details.Duration = duration
+ if n.details.Duration >= 0 {
+ n.expiry = now.Add(n.details.Duration)
+ heap.Push(&m.byExpiry, n)
+ }
+ return n.details, nil
+}
+
+func (m *memLS) Unlock(now time.Time, token string) error {
+ m.mu.Lock()
+ defer m.mu.Unlock()
+ m.collectExpiredNodes(now)
+
+ n := m.byToken[token]
+ if n == nil {
+ return ErrNoSuchLock
+ }
+ if n.held {
+ return ErrLocked
+ }
+ m.remove(n)
+ return nil
+}
+
+func (m *memLS) canCreate(name string, zeroDepth bool) bool {
+ return walkToRoot(name, func(name0 string, first bool) bool {
+ n := m.byName[name0]
+ if n == nil {
+ return true
+ }
+ if first {
+ if n.token != "" {
+ // The target node is already locked.
+ return false
+ }
+ if !zeroDepth {
+ // The requested lock depth is infinite, and the fact that n exists
+ // (n != nil) means that a descendent of the target node is locked.
+ return false
+ }
+ } else if n.token != "" && !n.details.ZeroDepth {
+ // An ancestor of the target node is locked with infinite depth.
+ return false
+ }
+ return true
+ })
+}
+
+func (m *memLS) create(name string) (ret *memLSNode) {
+ walkToRoot(name, func(name0 string, first bool) bool {
+ n := m.byName[name0]
+ if n == nil {
+ n = &memLSNode{
+ details: LockDetails{
+ Root: name0,
+ },
+ byExpiryIndex: -1,
+ }
+ m.byName[name0] = n
+ }
+ n.refCount++
+ if first {
+ ret = n
+ }
+ return true
+ })
+ return ret
+}
+
+func (m *memLS) remove(n *memLSNode) {
+ delete(m.byToken, n.token)
+ n.token = ""
+ walkToRoot(n.details.Root, func(name0 string, first bool) bool {
+ x := m.byName[name0]
+ x.refCount--
+ if x.refCount == 0 {
+ delete(m.byName, name0)
+ }
+ return true
+ })
+ if n.byExpiryIndex >= 0 {
+ heap.Remove(&m.byExpiry, n.byExpiryIndex)
+ }
+}
+
+func walkToRoot(name string, f func(name0 string, first bool) bool) bool {
+ for first := true; ; first = false {
+ if !f(name, first) {
+ return false
+ }
+ if name == "/" {
+ break
+ }
+ name = name[:strings.LastIndex(name, "/")]
+ if name == "" {
+ name = "/"
+ }
+ }
+ return true
+}
+
+type memLSNode struct {
+ // details are the lock metadata. Even if this node's name is not explicitly locked,
+ // details.Root will still equal the node's name.
+ details LockDetails
+ // token is the unique identifier for this node's lock. An empty token means that
+ // this node is not explicitly locked.
+ token string
+ // refCount is the number of self-or-descendent nodes that are explicitly locked.
+ refCount int
+ // expiry is when this node's lock expires.
+ expiry time.Time
+ // byExpiryIndex is the index of this node in memLS.byExpiry. It is -1
+ // if this node does not expire, or has expired.
+ byExpiryIndex int
+ // held is whether this node's lock is actively held by a Confirm call.
+ held bool
+}
+
+type byExpiry []*memLSNode
+
+func (b *byExpiry) Len() int {
+ return len(*b)
+}
+
+func (b *byExpiry) Less(i, j int) bool {
+ return (*b)[i].expiry.Before((*b)[j].expiry)
+}
+
+func (b *byExpiry) Swap(i, j int) {
+ (*b)[i], (*b)[j] = (*b)[j], (*b)[i]
+ (*b)[i].byExpiryIndex = i
+ (*b)[j].byExpiryIndex = j
+}
+
+func (b *byExpiry) Push(x interface{}) {
+ n := x.(*memLSNode)
+ n.byExpiryIndex = len(*b)
+ *b = append(*b, n)
+}
+
+func (b *byExpiry) Pop() interface{} {
+ i := len(*b) - 1
+ n := (*b)[i]
+ (*b)[i] = nil
+ n.byExpiryIndex = -1
+ *b = (*b)[:i]
+ return n
+}
+
+const infiniteTimeout = -1
+
+// parseTimeout parses the Timeout HTTP header, as per section 10.7. If s is
+// empty, an infiniteTimeout is returned.
+func parseTimeout(s string) (time.Duration, error) {
+ if s == "" {
+ return infiniteTimeout, nil
+ }
+ if i := strings.IndexByte(s, ','); i >= 0 {
+ s = s[:i]
+ }
+ s = strings.TrimSpace(s)
+ if s == "Infinite" {
+ return infiniteTimeout, nil
+ }
+ const pre = "Second-"
+ if !strings.HasPrefix(s, pre) {
+ return 0, errInvalidTimeout
+ }
+ s = s[len(pre):]
+ if s == "" || s[0] < '0' || '9' < s[0] {
+ return 0, errInvalidTimeout
+ }
+ n, err := strconv.ParseInt(s, 10, 64)
+ if err != nil || 1<<32-1 < n {
+ return 0, errInvalidTimeout
+ }
+ return time.Duration(n) * time.Second, nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/lock_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/lock_test.go
new file mode 100644
index 000000000..5cf14cda4
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/lock_test.go
@@ -0,0 +1,731 @@
+// Copyright 2014 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 webdav
+
+import (
+ "fmt"
+ "math/rand"
+ "path"
+ "reflect"
+ "sort"
+ "strconv"
+ "strings"
+ "testing"
+ "time"
+)
+
+func TestWalkToRoot(t *testing.T) {
+ testCases := []struct {
+ name string
+ want []string
+ }{{
+ "/a/b/c/d",
+ []string{
+ "/a/b/c/d",
+ "/a/b/c",
+ "/a/b",
+ "/a",
+ "/",
+ },
+ }, {
+ "/a",
+ []string{
+ "/a",
+ "/",
+ },
+ }, {
+ "/",
+ []string{
+ "/",
+ },
+ }}
+
+ for _, tc := range testCases {
+ var got []string
+ if !walkToRoot(tc.name, func(name0 string, first bool) bool {
+ if first != (len(got) == 0) {
+ t.Errorf("name=%q: first=%t but len(got)==%d", tc.name, first, len(got))
+ return false
+ }
+ got = append(got, name0)
+ return true
+ }) {
+ continue
+ }
+ if !reflect.DeepEqual(got, tc.want) {
+ t.Errorf("name=%q:\ngot %q\nwant %q", tc.name, got, tc.want)
+ }
+ }
+}
+
+var lockTestDurations = []time.Duration{
+ infiniteTimeout, // infiniteTimeout means to never expire.
+ 0, // A zero duration means to expire immediately.
+ 100 * time.Hour, // A very large duration will not expire in these tests.
+}
+
+// lockTestNames are the names of a set of mutually compatible locks. For each
+// name fragment:
+// - _ means no explicit lock.
+// - i means an infinite-depth lock,
+// - z means a zero-depth lock,
+var lockTestNames = []string{
+ "/_/_/_/_/z",
+ "/_/_/i",
+ "/_/z",
+ "/_/z/i",
+ "/_/z/z",
+ "/_/z/_/i",
+ "/_/z/_/z",
+ "/i",
+ "/z",
+ "/z/_/i",
+ "/z/_/z",
+}
+
+func lockTestZeroDepth(name string) bool {
+ switch name[len(name)-1] {
+ case 'i':
+ return false
+ case 'z':
+ return true
+ }
+ panic(fmt.Sprintf("lock name %q did not end with 'i' or 'z'", name))
+}
+
+func TestMemLSCanCreate(t *testing.T) {
+ now := time.Unix(0, 0)
+ m := NewMemLS().(*memLS)
+
+ for _, name := range lockTestNames {
+ _, err := m.Create(now, LockDetails{
+ Root: name,
+ Duration: infiniteTimeout,
+ ZeroDepth: lockTestZeroDepth(name),
+ })
+ if err != nil {
+ t.Fatalf("creating lock for %q: %v", name, err)
+ }
+ }
+
+ wantCanCreate := func(name string, zeroDepth bool) bool {
+ for _, n := range lockTestNames {
+ switch {
+ case n == name:
+ // An existing lock has the same name as the proposed lock.
+ return false
+ case strings.HasPrefix(n, name):
+ // An existing lock would be a child of the proposed lock,
+ // which conflicts if the proposed lock has infinite depth.
+ if !zeroDepth {
+ return false
+ }
+ case strings.HasPrefix(name, n):
+ // An existing lock would be an ancestor of the proposed lock,
+ // which conflicts if the ancestor has infinite depth.
+ if n[len(n)-1] == 'i' {
+ return false
+ }
+ }
+ }
+ return true
+ }
+
+ var check func(int, string)
+ check = func(recursion int, name string) {
+ for _, zeroDepth := range []bool{false, true} {
+ got := m.canCreate(name, zeroDepth)
+ want := wantCanCreate(name, zeroDepth)
+ if got != want {
+ t.Errorf("canCreate name=%q zeroDepth=%t: got %t, want %t", name, zeroDepth, got, want)
+ }
+ }
+ if recursion == 6 {
+ return
+ }
+ if name != "/" {
+ name += "/"
+ }
+ for _, c := range "_iz" {
+ check(recursion+1, name+string(c))
+ }
+ }
+ check(0, "/")
+}
+
+func TestMemLSLookup(t *testing.T) {
+ now := time.Unix(0, 0)
+ m := NewMemLS().(*memLS)
+
+ badToken := m.nextToken()
+ t.Logf("badToken=%q", badToken)
+
+ for _, name := range lockTestNames {
+ token, err := m.Create(now, LockDetails{
+ Root: name,
+ Duration: infiniteTimeout,
+ ZeroDepth: lockTestZeroDepth(name),
+ })
+ if err != nil {
+ t.Fatalf("creating lock for %q: %v", name, err)
+ }
+ t.Logf("%-15q -> node=%p token=%q", name, m.byName[name], token)
+ }
+
+ baseNames := append([]string{"/a", "/b/c"}, lockTestNames...)
+ for _, baseName := range baseNames {
+ for _, suffix := range []string{"", "/0", "/1/2/3"} {
+ name := baseName + suffix
+
+ goodToken := ""
+ base := m.byName[baseName]
+ if base != nil && (suffix == "" || !lockTestZeroDepth(baseName)) {
+ goodToken = base.token
+ }
+
+ for _, token := range []string{badToken, goodToken} {
+ if token == "" {
+ continue
+ }
+
+ got := m.lookup(name, Condition{Token: token})
+ want := base
+ if token == badToken {
+ want = nil
+ }
+ if got != want {
+ t.Errorf("name=%-20qtoken=%q (bad=%t): got %p, want %p",
+ name, token, token == badToken, got, want)
+ }
+ }
+ }
+ }
+}
+
+func TestMemLSConfirm(t *testing.T) {
+ now := time.Unix(0, 0)
+ m := NewMemLS().(*memLS)
+ alice, err := m.Create(now, LockDetails{
+ Root: "/alice",
+ Duration: infiniteTimeout,
+ ZeroDepth: false,
+ })
+ tweedle, err := m.Create(now, LockDetails{
+ Root: "/tweedle",
+ Duration: infiniteTimeout,
+ ZeroDepth: false,
+ })
+ if err != nil {
+ t.Fatalf("Create: %v", err)
+ }
+ if err := m.consistent(); err != nil {
+ t.Fatalf("Create: inconsistent state: %v", err)
+ }
+
+ // Test a mismatch between name and condition.
+ _, err = m.Confirm(now, "/tweedle/dee", "", Condition{Token: alice})
+ if err != ErrConfirmationFailed {
+ t.Fatalf("Confirm (mismatch): got %v, want ErrConfirmationFailed", err)
+ }
+ if err := m.consistent(); err != nil {
+ t.Fatalf("Confirm (mismatch): inconsistent state: %v", err)
+ }
+
+ // Test two names (that fall under the same lock) in the one Confirm call.
+ release, err := m.Confirm(now, "/tweedle/dee", "/tweedle/dum", Condition{Token: tweedle})
+ if err != nil {
+ t.Fatalf("Confirm (twins): %v", err)
+ }
+ if err := m.consistent(); err != nil {
+ t.Fatalf("Confirm (twins): inconsistent state: %v", err)
+ }
+ release()
+ if err := m.consistent(); err != nil {
+ t.Fatalf("release (twins): inconsistent state: %v", err)
+ }
+
+ // Test the same two names in overlapping Confirm / release calls.
+ releaseDee, err := m.Confirm(now, "/tweedle/dee", "", Condition{Token: tweedle})
+ if err != nil {
+ t.Fatalf("Confirm (sequence #0): %v", err)
+ }
+ if err := m.consistent(); err != nil {
+ t.Fatalf("Confirm (sequence #0): inconsistent state: %v", err)
+ }
+
+ _, err = m.Confirm(now, "/tweedle/dum", "", Condition{Token: tweedle})
+ if err != ErrConfirmationFailed {
+ t.Fatalf("Confirm (sequence #1): got %v, want ErrConfirmationFailed", err)
+ }
+ if err := m.consistent(); err != nil {
+ t.Fatalf("Confirm (sequence #1): inconsistent state: %v", err)
+ }
+
+ releaseDee()
+ if err := m.consistent(); err != nil {
+ t.Fatalf("release (sequence #2): inconsistent state: %v", err)
+ }
+
+ releaseDum, err := m.Confirm(now, "/tweedle/dum", "", Condition{Token: tweedle})
+ if err != nil {
+ t.Fatalf("Confirm (sequence #3): %v", err)
+ }
+ if err := m.consistent(); err != nil {
+ t.Fatalf("Confirm (sequence #3): inconsistent state: %v", err)
+ }
+
+ // Test that you can't unlock a held lock.
+ err = m.Unlock(now, tweedle)
+ if err != ErrLocked {
+ t.Fatalf("Unlock (sequence #4): got %v, want ErrLocked", err)
+ }
+
+ releaseDum()
+ if err := m.consistent(); err != nil {
+ t.Fatalf("release (sequence #5): inconsistent state: %v", err)
+ }
+
+ err = m.Unlock(now, tweedle)
+ if err != nil {
+ t.Fatalf("Unlock (sequence #6): %v", err)
+ }
+ if err := m.consistent(); err != nil {
+ t.Fatalf("Unlock (sequence #6): inconsistent state: %v", err)
+ }
+}
+
+func TestMemLSNonCanonicalRoot(t *testing.T) {
+ now := time.Unix(0, 0)
+ m := NewMemLS().(*memLS)
+ token, err := m.Create(now, LockDetails{
+ Root: "/foo/./bar//",
+ Duration: 1 * time.Second,
+ })
+ if err != nil {
+ t.Fatalf("Create: %v", err)
+ }
+ if err := m.consistent(); err != nil {
+ t.Fatalf("Create: inconsistent state: %v", err)
+ }
+ if err := m.Unlock(now, token); err != nil {
+ t.Fatalf("Unlock: %v", err)
+ }
+ if err := m.consistent(); err != nil {
+ t.Fatalf("Unlock: inconsistent state: %v", err)
+ }
+}
+
+func TestMemLSExpiry(t *testing.T) {
+ m := NewMemLS().(*memLS)
+ testCases := []string{
+ "setNow 0",
+ "create /a.5",
+ "want /a.5",
+ "create /c.6",
+ "want /a.5 /c.6",
+ "create /a/b.7",
+ "want /a.5 /a/b.7 /c.6",
+ "setNow 4",
+ "want /a.5 /a/b.7 /c.6",
+ "setNow 5",
+ "want /a/b.7 /c.6",
+ "setNow 6",
+ "want /a/b.7",
+ "setNow 7",
+ "want ",
+ "setNow 8",
+ "want ",
+ "create /a.12",
+ "create /b.13",
+ "create /c.15",
+ "create /a/d.16",
+ "want /a.12 /a/d.16 /b.13 /c.15",
+ "refresh /a.14",
+ "want /a.14 /a/d.16 /b.13 /c.15",
+ "setNow 12",
+ "want /a.14 /a/d.16 /b.13 /c.15",
+ "setNow 13",
+ "want /a.14 /a/d.16 /c.15",
+ "setNow 14",
+ "want /a/d.16 /c.15",
+ "refresh /a/d.20",
+ "refresh /c.20",
+ "want /a/d.20 /c.20",
+ "setNow 20",
+ "want ",
+ }
+
+ tokens := map[string]string{}
+ zTime := time.Unix(0, 0)
+ now := zTime
+ for i, tc := range testCases {
+ j := strings.IndexByte(tc, ' ')
+ if j < 0 {
+ t.Fatalf("test case #%d %q: invalid command", i, tc)
+ }
+ op, arg := tc[:j], tc[j+1:]
+ switch op {
+ default:
+ t.Fatalf("test case #%d %q: invalid operation %q", i, tc, op)
+
+ case "create", "refresh":
+ parts := strings.Split(arg, ".")
+ if len(parts) != 2 {
+ t.Fatalf("test case #%d %q: invalid create", i, tc)
+ }
+ root := parts[0]
+ d, err := strconv.Atoi(parts[1])
+ if err != nil {
+ t.Fatalf("test case #%d %q: invalid duration", i, tc)
+ }
+ dur := time.Unix(0, 0).Add(time.Duration(d) * time.Second).Sub(now)
+
+ switch op {
+ case "create":
+ token, err := m.Create(now, LockDetails{
+ Root: root,
+ Duration: dur,
+ ZeroDepth: true,
+ })
+ if err != nil {
+ t.Fatalf("test case #%d %q: Create: %v", i, tc, err)
+ }
+ tokens[root] = token
+
+ case "refresh":
+ token := tokens[root]
+ if token == "" {
+ t.Fatalf("test case #%d %q: no token for %q", i, tc, root)
+ }
+ got, err := m.Refresh(now, token, dur)
+ if err != nil {
+ t.Fatalf("test case #%d %q: Refresh: %v", i, tc, err)
+ }
+ want := LockDetails{
+ Root: root,
+ Duration: dur,
+ ZeroDepth: true,
+ }
+ if got != want {
+ t.Fatalf("test case #%d %q:\ngot %v\nwant %v", i, tc, got, want)
+ }
+ }
+
+ case "setNow":
+ d, err := strconv.Atoi(arg)
+ if err != nil {
+ t.Fatalf("test case #%d %q: invalid duration", i, tc)
+ }
+ now = time.Unix(0, 0).Add(time.Duration(d) * time.Second)
+
+ case "want":
+ m.mu.Lock()
+ m.collectExpiredNodes(now)
+ got := make([]string, 0, len(m.byToken))
+ for _, n := range m.byToken {
+ got = append(got, fmt.Sprintf("%s.%d",
+ n.details.Root, n.expiry.Sub(zTime)/time.Second))
+ }
+ m.mu.Unlock()
+ sort.Strings(got)
+ want := []string{}
+ if arg != "" {
+ want = strings.Split(arg, " ")
+ }
+ if !reflect.DeepEqual(got, want) {
+ t.Fatalf("test case #%d %q:\ngot %q\nwant %q", i, tc, got, want)
+ }
+ }
+
+ if err := m.consistent(); err != nil {
+ t.Fatalf("test case #%d %q: inconsistent state: %v", i, tc, err)
+ }
+ }
+}
+
+func TestMemLS(t *testing.T) {
+ now := time.Unix(0, 0)
+ m := NewMemLS().(*memLS)
+ rng := rand.New(rand.NewSource(0))
+ tokens := map[string]string{}
+ nConfirm, nCreate, nRefresh, nUnlock := 0, 0, 0, 0
+ const N = 2000
+
+ for i := 0; i < N; i++ {
+ name := lockTestNames[rng.Intn(len(lockTestNames))]
+ duration := lockTestDurations[rng.Intn(len(lockTestDurations))]
+ confirmed, unlocked := false, false
+
+ // If the name was already locked, we randomly confirm/release, refresh
+ // or unlock it. Otherwise, we create a lock.
+ token := tokens[name]
+ if token != "" {
+ switch rng.Intn(3) {
+ case 0:
+ confirmed = true
+ nConfirm++
+ release, err := m.Confirm(now, name, "", Condition{Token: token})
+ if err != nil {
+ t.Fatalf("iteration #%d: Confirm %q: %v", i, name, err)
+ }
+ if err := m.consistent(); err != nil {
+ t.Fatalf("iteration #%d: inconsistent state: %v", i, err)
+ }
+ release()
+
+ case 1:
+ nRefresh++
+ if _, err := m.Refresh(now, token, duration); err != nil {
+ t.Fatalf("iteration #%d: Refresh %q: %v", i, name, err)
+ }
+
+ case 2:
+ unlocked = true
+ nUnlock++
+ if err := m.Unlock(now, token); err != nil {
+ t.Fatalf("iteration #%d: Unlock %q: %v", i, name, err)
+ }
+ }
+
+ } else {
+ nCreate++
+ var err error
+ token, err = m.Create(now, LockDetails{
+ Root: name,
+ Duration: duration,
+ ZeroDepth: lockTestZeroDepth(name),
+ })
+ if err != nil {
+ t.Fatalf("iteration #%d: Create %q: %v", i, name, err)
+ }
+ }
+
+ if !confirmed {
+ if duration == 0 || unlocked {
+ // A zero-duration lock should expire immediately and is
+ // effectively equivalent to being unlocked.
+ tokens[name] = ""
+ } else {
+ tokens[name] = token
+ }
+ }
+
+ if err := m.consistent(); err != nil {
+ t.Fatalf("iteration #%d: inconsistent state: %v", i, err)
+ }
+ }
+
+ if nConfirm < N/10 {
+ t.Fatalf("too few Confirm calls: got %d, want >= %d", nConfirm, N/10)
+ }
+ if nCreate < N/10 {
+ t.Fatalf("too few Create calls: got %d, want >= %d", nCreate, N/10)
+ }
+ if nRefresh < N/10 {
+ t.Fatalf("too few Refresh calls: got %d, want >= %d", nRefresh, N/10)
+ }
+ if nUnlock < N/10 {
+ t.Fatalf("too few Unlock calls: got %d, want >= %d", nUnlock, N/10)
+ }
+}
+
+func (m *memLS) consistent() error {
+ m.mu.Lock()
+ defer m.mu.Unlock()
+
+ // If m.byName is non-empty, then it must contain an entry for the root "/",
+ // and its refCount should equal the number of locked nodes.
+ if len(m.byName) > 0 {
+ n := m.byName["/"]
+ if n == nil {
+ return fmt.Errorf(`non-empty m.byName does not contain the root "/"`)
+ }
+ if n.refCount != len(m.byToken) {
+ return fmt.Errorf("root node refCount=%d, differs from len(m.byToken)=%d", n.refCount, len(m.byToken))
+ }
+ }
+
+ for name, n := range m.byName {
+ // The map keys should be consistent with the node's copy of the key.
+ if n.details.Root != name {
+ return fmt.Errorf("node name %q != byName map key %q", n.details.Root, name)
+ }
+
+ // A name must be clean, and start with a "/".
+ if len(name) == 0 || name[0] != '/' {
+ return fmt.Errorf(`node name %q does not start with "/"`, name)
+ }
+ if name != path.Clean(name) {
+ return fmt.Errorf(`node name %q is not clean`, name)
+ }
+
+ // A node's refCount should be positive.
+ if n.refCount <= 0 {
+ return fmt.Errorf("non-positive refCount for node at name %q", name)
+ }
+
+ // A node's refCount should be the number of self-or-descendents that
+ // are locked (i.e. have a non-empty token).
+ var list []string
+ for name0, n0 := range m.byName {
+ // All of lockTestNames' name fragments are one byte long: '_', 'i' or 'z',
+ // so strings.HasPrefix is equivalent to self-or-descendent name match.
+ // We don't have to worry about "/foo/bar" being a false positive match
+ // for "/foo/b".
+ if strings.HasPrefix(name0, name) && n0.token != "" {
+ list = append(list, name0)
+ }
+ }
+ if n.refCount != len(list) {
+ sort.Strings(list)
+ return fmt.Errorf("node at name %q has refCount %d but locked self-or-descendents are %q (len=%d)",
+ name, n.refCount, list, len(list))
+ }
+
+ // A node n is in m.byToken if it has a non-empty token.
+ if n.token != "" {
+ if _, ok := m.byToken[n.token]; !ok {
+ return fmt.Errorf("node at name %q has token %q but not in m.byToken", name, n.token)
+ }
+ }
+
+ // A node n is in m.byExpiry if it has a non-negative byExpiryIndex.
+ if n.byExpiryIndex >= 0 {
+ if n.byExpiryIndex >= len(m.byExpiry) {
+ return fmt.Errorf("node at name %q has byExpiryIndex %d but m.byExpiry has length %d", name, n.byExpiryIndex, len(m.byExpiry))
+ }
+ if n != m.byExpiry[n.byExpiryIndex] {
+ return fmt.Errorf("node at name %q has byExpiryIndex %d but that indexes a different node", name, n.byExpiryIndex)
+ }
+ }
+ }
+
+ for token, n := range m.byToken {
+ // The map keys should be consistent with the node's copy of the key.
+ if n.token != token {
+ return fmt.Errorf("node token %q != byToken map key %q", n.token, token)
+ }
+
+ // Every node in m.byToken is in m.byName.
+ if _, ok := m.byName[n.details.Root]; !ok {
+ return fmt.Errorf("node at name %q in m.byToken but not in m.byName", n.details.Root)
+ }
+ }
+
+ for i, n := range m.byExpiry {
+ // The slice indices should be consistent with the node's copy of the index.
+ if n.byExpiryIndex != i {
+ return fmt.Errorf("node byExpiryIndex %d != byExpiry slice index %d", n.byExpiryIndex, i)
+ }
+
+ // Every node in m.byExpiry is in m.byName.
+ if _, ok := m.byName[n.details.Root]; !ok {
+ return fmt.Errorf("node at name %q in m.byExpiry but not in m.byName", n.details.Root)
+ }
+
+ // No node in m.byExpiry should be held.
+ if n.held {
+ return fmt.Errorf("node at name %q in m.byExpiry is held", n.details.Root)
+ }
+ }
+ return nil
+}
+
+func TestParseTimeout(t *testing.T) {
+ testCases := []struct {
+ s string
+ want time.Duration
+ wantErr error
+ }{{
+ "",
+ infiniteTimeout,
+ nil,
+ }, {
+ "Infinite",
+ infiniteTimeout,
+ nil,
+ }, {
+ "Infinitesimal",
+ 0,
+ errInvalidTimeout,
+ }, {
+ "infinite",
+ 0,
+ errInvalidTimeout,
+ }, {
+ "Second-0",
+ 0 * time.Second,
+ nil,
+ }, {
+ "Second-123",
+ 123 * time.Second,
+ nil,
+ }, {
+ " Second-456 ",
+ 456 * time.Second,
+ nil,
+ }, {
+ "Second-4100000000",
+ 4100000000 * time.Second,
+ nil,
+ }, {
+ "junk",
+ 0,
+ errInvalidTimeout,
+ }, {
+ "Second-",
+ 0,
+ errInvalidTimeout,
+ }, {
+ "Second--1",
+ 0,
+ errInvalidTimeout,
+ }, {
+ "Second--123",
+ 0,
+ errInvalidTimeout,
+ }, {
+ "Second-+123",
+ 0,
+ errInvalidTimeout,
+ }, {
+ "Second-0x123",
+ 0,
+ errInvalidTimeout,
+ }, {
+ "second-123",
+ 0,
+ errInvalidTimeout,
+ }, {
+ "Second-4294967295",
+ 4294967295 * time.Second,
+ nil,
+ }, {
+ // Section 10.7 says that "The timeout value for TimeType "Second"
+ // must not be greater than 2^32-1."
+ "Second-4294967296",
+ 0,
+ errInvalidTimeout,
+ }, {
+ // This test case comes from section 9.10.9 of the spec. It says,
+ //
+ // "In this request, the client has specified that it desires an
+ // infinite-length lock, if available, otherwise a timeout of 4.1
+ // billion seconds, if available."
+ //
+ // The Go WebDAV package always supports infinite length locks,
+ // and ignores the fallback after the comma.
+ "Infinite, Second-4100000000",
+ infiniteTimeout,
+ nil,
+ }}
+
+ for _, tc := range testCases {
+ got, gotErr := parseTimeout(tc.s)
+ if got != tc.want || gotErr != tc.wantErr {
+ t.Errorf("parsing %q:\ngot %v, %v\nwant %v, %v", tc.s, got, gotErr, tc.want, tc.wantErr)
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/prop.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/prop.go
new file mode 100644
index 000000000..e36a3b31d
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/prop.go
@@ -0,0 +1,418 @@
+// Copyright 2015 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 webdav
+
+import (
+ "bytes"
+ "encoding/xml"
+ "fmt"
+ "io"
+ "mime"
+ "net/http"
+ "os"
+ "path/filepath"
+ "strconv"
+
+ "golang.org/x/net/context"
+)
+
+// Proppatch describes a property update instruction as defined in RFC 4918.
+// See http://www.webdav.org/specs/rfc4918.html#METHOD_PROPPATCH
+type Proppatch struct {
+ // Remove specifies whether this patch removes properties. If it does not
+ // remove them, it sets them.
+ Remove bool
+ // Props contains the properties to be set or removed.
+ Props []Property
+}
+
+// Propstat describes a XML propstat element as defined in RFC 4918.
+// See http://www.webdav.org/specs/rfc4918.html#ELEMENT_propstat
+type Propstat struct {
+ // Props contains the properties for which Status applies.
+ Props []Property
+
+ // Status defines the HTTP status code of the properties in Prop.
+ // Allowed values include, but are not limited to the WebDAV status
+ // code extensions for HTTP/1.1.
+ // http://www.webdav.org/specs/rfc4918.html#status.code.extensions.to.http11
+ Status int
+
+ // XMLError contains the XML representation of the optional error element.
+ // XML content within this field must not rely on any predefined
+ // namespace declarations or prefixes. If empty, the XML error element
+ // is omitted.
+ XMLError string
+
+ // ResponseDescription contains the contents of the optional
+ // responsedescription field. If empty, the XML element is omitted.
+ ResponseDescription string
+}
+
+// makePropstats returns a slice containing those of x and y whose Props slice
+// is non-empty. If both are empty, it returns a slice containing an otherwise
+// zero Propstat whose HTTP status code is 200 OK.
+func makePropstats(x, y Propstat) []Propstat {
+ pstats := make([]Propstat, 0, 2)
+ if len(x.Props) != 0 {
+ pstats = append(pstats, x)
+ }
+ if len(y.Props) != 0 {
+ pstats = append(pstats, y)
+ }
+ if len(pstats) == 0 {
+ pstats = append(pstats, Propstat{
+ Status: http.StatusOK,
+ })
+ }
+ return pstats
+}
+
+// DeadPropsHolder holds the dead properties of a resource.
+//
+// Dead properties are those properties that are explicitly defined. In
+// comparison, live properties, such as DAV:getcontentlength, are implicitly
+// defined by the underlying resource, and cannot be explicitly overridden or
+// removed. See the Terminology section of
+// http://www.webdav.org/specs/rfc4918.html#rfc.section.3
+//
+// There is a whitelist of the names of live properties. This package handles
+// all live properties, and will only pass non-whitelisted names to the Patch
+// method of DeadPropsHolder implementations.
+type DeadPropsHolder interface {
+ // DeadProps returns a copy of the dead properties held.
+ DeadProps() (map[xml.Name]Property, error)
+
+ // Patch patches the dead properties held.
+ //
+ // Patching is atomic; either all or no patches succeed. It returns (nil,
+ // non-nil) if an internal server error occurred, otherwise the Propstats
+ // collectively contain one Property for each proposed patch Property. If
+ // all patches succeed, Patch returns a slice of length one and a Propstat
+ // element with a 200 OK HTTP status code. If none succeed, for reasons
+ // other than an internal server error, no Propstat has status 200 OK.
+ //
+ // For more details on when various HTTP status codes apply, see
+ // http://www.webdav.org/specs/rfc4918.html#PROPPATCH-status
+ Patch([]Proppatch) ([]Propstat, error)
+}
+
+// liveProps contains all supported, protected DAV: properties.
+var liveProps = map[xml.Name]struct {
+ // findFn implements the propfind function of this property. If nil,
+ // it indicates a hidden property.
+ findFn func(context.Context, FileSystem, LockSystem, string, os.FileInfo) (string, error)
+ // dir is true if the property applies to directories.
+ dir bool
+}{
+ {Space: "DAV:", Local: "resourcetype"}: {
+ findFn: findResourceType,
+ dir: true,
+ },
+ {Space: "DAV:", Local: "displayname"}: {
+ findFn: findDisplayName,
+ dir: true,
+ },
+ {Space: "DAV:", Local: "getcontentlength"}: {
+ findFn: findContentLength,
+ dir: false,
+ },
+ {Space: "DAV:", Local: "getlastmodified"}: {
+ findFn: findLastModified,
+ // http://webdav.org/specs/rfc4918.html#PROPERTY_getlastmodified
+ // suggests that getlastmodified should only apply to GETable
+ // resources, and this package does not support GET on directories.
+ //
+ // Nonetheless, some WebDAV clients expect child directories to be
+ // sortable by getlastmodified date, so this value is true, not false.
+ // See golang.org/issue/15334.
+ dir: true,
+ },
+ {Space: "DAV:", Local: "creationdate"}: {
+ findFn: nil,
+ dir: false,
+ },
+ {Space: "DAV:", Local: "getcontentlanguage"}: {
+ findFn: nil,
+ dir: false,
+ },
+ {Space: "DAV:", Local: "getcontenttype"}: {
+ findFn: findContentType,
+ dir: false,
+ },
+ {Space: "DAV:", Local: "getetag"}: {
+ findFn: findETag,
+ // findETag implements ETag as the concatenated hex values of a file's
+ // modification time and size. This is not a reliable synchronization
+ // mechanism for directories, so we do not advertise getetag for DAV
+ // collections.
+ dir: false,
+ },
+
+ // TODO: The lockdiscovery property requires LockSystem to list the
+ // active locks on a resource.
+ {Space: "DAV:", Local: "lockdiscovery"}: {},
+ {Space: "DAV:", Local: "supportedlock"}: {
+ findFn: findSupportedLock,
+ dir: true,
+ },
+}
+
+// TODO(nigeltao) merge props and allprop?
+
+// Props returns the status of the properties named pnames for resource name.
+//
+// Each Propstat has a unique status and each property name will only be part
+// of one Propstat element.
+func props(ctx context.Context, fs FileSystem, ls LockSystem, name string, pnames []xml.Name) ([]Propstat, error) {
+ f, err := fs.OpenFile(ctx, name, os.O_RDONLY, 0)
+ if err != nil {
+ return nil, err
+ }
+ defer f.Close()
+ fi, err := f.Stat()
+ if err != nil {
+ return nil, err
+ }
+ isDir := fi.IsDir()
+
+ var deadProps map[xml.Name]Property
+ if dph, ok := f.(DeadPropsHolder); ok {
+ deadProps, err = dph.DeadProps()
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ pstatOK := Propstat{Status: http.StatusOK}
+ pstatNotFound := Propstat{Status: http.StatusNotFound}
+ for _, pn := range pnames {
+ // If this file has dead properties, check if they contain pn.
+ if dp, ok := deadProps[pn]; ok {
+ pstatOK.Props = append(pstatOK.Props, dp)
+ continue
+ }
+ // Otherwise, it must either be a live property or we don't know it.
+ if prop := liveProps[pn]; prop.findFn != nil && (prop.dir || !isDir) {
+ innerXML, err := prop.findFn(ctx, fs, ls, name, fi)
+ if err != nil {
+ return nil, err
+ }
+ pstatOK.Props = append(pstatOK.Props, Property{
+ XMLName: pn,
+ InnerXML: []byte(innerXML),
+ })
+ } else {
+ pstatNotFound.Props = append(pstatNotFound.Props, Property{
+ XMLName: pn,
+ })
+ }
+ }
+ return makePropstats(pstatOK, pstatNotFound), nil
+}
+
+// Propnames returns the property names defined for resource name.
+func propnames(ctx context.Context, fs FileSystem, ls LockSystem, name string) ([]xml.Name, error) {
+ f, err := fs.OpenFile(ctx, name, os.O_RDONLY, 0)
+ if err != nil {
+ return nil, err
+ }
+ defer f.Close()
+ fi, err := f.Stat()
+ if err != nil {
+ return nil, err
+ }
+ isDir := fi.IsDir()
+
+ var deadProps map[xml.Name]Property
+ if dph, ok := f.(DeadPropsHolder); ok {
+ deadProps, err = dph.DeadProps()
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ pnames := make([]xml.Name, 0, len(liveProps)+len(deadProps))
+ for pn, prop := range liveProps {
+ if prop.findFn != nil && (prop.dir || !isDir) {
+ pnames = append(pnames, pn)
+ }
+ }
+ for pn := range deadProps {
+ pnames = append(pnames, pn)
+ }
+ return pnames, nil
+}
+
+// Allprop returns the properties defined for resource name and the properties
+// named in include.
+//
+// Note that RFC 4918 defines 'allprop' to return the DAV: properties defined
+// within the RFC plus dead properties. Other live properties should only be
+// returned if they are named in 'include'.
+//
+// See http://www.webdav.org/specs/rfc4918.html#METHOD_PROPFIND
+func allprop(ctx context.Context, fs FileSystem, ls LockSystem, name string, include []xml.Name) ([]Propstat, error) {
+ pnames, err := propnames(ctx, fs, ls, name)
+ if err != nil {
+ return nil, err
+ }
+ // Add names from include if they are not already covered in pnames.
+ nameset := make(map[xml.Name]bool)
+ for _, pn := range pnames {
+ nameset[pn] = true
+ }
+ for _, pn := range include {
+ if !nameset[pn] {
+ pnames = append(pnames, pn)
+ }
+ }
+ return props(ctx, fs, ls, name, pnames)
+}
+
+// Patch patches the properties of resource name. The return values are
+// constrained in the same manner as DeadPropsHolder.Patch.
+func patch(ctx context.Context, fs FileSystem, ls LockSystem, name string, patches []Proppatch) ([]Propstat, error) {
+ conflict := false
+loop:
+ for _, patch := range patches {
+ for _, p := range patch.Props {
+ if _, ok := liveProps[p.XMLName]; ok {
+ conflict = true
+ break loop
+ }
+ }
+ }
+ if conflict {
+ pstatForbidden := Propstat{
+ Status: http.StatusForbidden,
+ XMLError: `<D:cannot-modify-protected-property xmlns:D="DAV:"/>`,
+ }
+ pstatFailedDep := Propstat{
+ Status: StatusFailedDependency,
+ }
+ for _, patch := range patches {
+ for _, p := range patch.Props {
+ if _, ok := liveProps[p.XMLName]; ok {
+ pstatForbidden.Props = append(pstatForbidden.Props, Property{XMLName: p.XMLName})
+ } else {
+ pstatFailedDep.Props = append(pstatFailedDep.Props, Property{XMLName: p.XMLName})
+ }
+ }
+ }
+ return makePropstats(pstatForbidden, pstatFailedDep), nil
+ }
+
+ f, err := fs.OpenFile(ctx, name, os.O_RDWR, 0)
+ if err != nil {
+ return nil, err
+ }
+ defer f.Close()
+ if dph, ok := f.(DeadPropsHolder); ok {
+ ret, err := dph.Patch(patches)
+ if err != nil {
+ return nil, err
+ }
+ // http://www.webdav.org/specs/rfc4918.html#ELEMENT_propstat says that
+ // "The contents of the prop XML element must only list the names of
+ // properties to which the result in the status element applies."
+ for _, pstat := range ret {
+ for i, p := range pstat.Props {
+ pstat.Props[i] = Property{XMLName: p.XMLName}
+ }
+ }
+ return ret, nil
+ }
+ // The file doesn't implement the optional DeadPropsHolder interface, so
+ // all patches are forbidden.
+ pstat := Propstat{Status: http.StatusForbidden}
+ for _, patch := range patches {
+ for _, p := range patch.Props {
+ pstat.Props = append(pstat.Props, Property{XMLName: p.XMLName})
+ }
+ }
+ return []Propstat{pstat}, nil
+}
+
+func escapeXML(s string) string {
+ for i := 0; i < len(s); i++ {
+ // As an optimization, if s contains only ASCII letters, digits or a
+ // few special characters, the escaped value is s itself and we don't
+ // need to allocate a buffer and convert between string and []byte.
+ switch c := s[i]; {
+ case c == ' ' || c == '_' ||
+ ('+' <= c && c <= '9') || // Digits as well as + , - . and /
+ ('A' <= c && c <= 'Z') ||
+ ('a' <= c && c <= 'z'):
+ continue
+ }
+ // Otherwise, go through the full escaping process.
+ var buf bytes.Buffer
+ xml.EscapeText(&buf, []byte(s))
+ return buf.String()
+ }
+ return s
+}
+
+func findResourceType(ctx context.Context, fs FileSystem, ls LockSystem, name string, fi os.FileInfo) (string, error) {
+ if fi.IsDir() {
+ return `<D:collection xmlns:D="DAV:"/>`, nil
+ }
+ return "", nil
+}
+
+func findDisplayName(ctx context.Context, fs FileSystem, ls LockSystem, name string, fi os.FileInfo) (string, error) {
+ if slashClean(name) == "/" {
+ // Hide the real name of a possibly prefixed root directory.
+ return "", nil
+ }
+ return escapeXML(fi.Name()), nil
+}
+
+func findContentLength(ctx context.Context, fs FileSystem, ls LockSystem, name string, fi os.FileInfo) (string, error) {
+ return strconv.FormatInt(fi.Size(), 10), nil
+}
+
+func findLastModified(ctx context.Context, fs FileSystem, ls LockSystem, name string, fi os.FileInfo) (string, error) {
+ return fi.ModTime().Format(http.TimeFormat), nil
+}
+
+func findContentType(ctx context.Context, fs FileSystem, ls LockSystem, name string, fi os.FileInfo) (string, error) {
+ f, err := fs.OpenFile(ctx, name, os.O_RDONLY, 0)
+ if err != nil {
+ return "", err
+ }
+ defer f.Close()
+ // This implementation is based on serveContent's code in the standard net/http package.
+ ctype := mime.TypeByExtension(filepath.Ext(name))
+ if ctype != "" {
+ return ctype, nil
+ }
+ // Read a chunk to decide between utf-8 text and binary.
+ var buf [512]byte
+ n, err := io.ReadFull(f, buf[:])
+ if err != nil && err != io.EOF && err != io.ErrUnexpectedEOF {
+ return "", err
+ }
+ ctype = http.DetectContentType(buf[:n])
+ // Rewind file.
+ _, err = f.Seek(0, os.SEEK_SET)
+ return ctype, err
+}
+
+func findETag(ctx context.Context, fs FileSystem, ls LockSystem, name string, fi os.FileInfo) (string, error) {
+ // The Apache http 2.4 web server by default concatenates the
+ // modification time and size of a file. We replicate the heuristic
+ // with nanosecond granularity.
+ return fmt.Sprintf(`"%x%x"`, fi.ModTime().UnixNano(), fi.Size()), nil
+}
+
+func findSupportedLock(ctx context.Context, fs FileSystem, ls LockSystem, name string, fi os.FileInfo) (string, error) {
+ return `` +
+ `<D:lockentry xmlns:D="DAV:">` +
+ `<D:lockscope><D:exclusive/></D:lockscope>` +
+ `<D:locktype><D:write/></D:locktype>` +
+ `</D:lockentry>`, nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/prop_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/prop_test.go
new file mode 100644
index 000000000..57d0e826f
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/prop_test.go
@@ -0,0 +1,613 @@
+// Copyright 2015 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 webdav
+
+import (
+ "encoding/xml"
+ "fmt"
+ "net/http"
+ "os"
+ "reflect"
+ "sort"
+ "testing"
+
+ "golang.org/x/net/context"
+)
+
+func TestMemPS(t *testing.T) {
+ ctx := context.Background()
+ // calcProps calculates the getlastmodified and getetag DAV: property
+ // values in pstats for resource name in file-system fs.
+ calcProps := func(name string, fs FileSystem, ls LockSystem, pstats []Propstat) error {
+ fi, err := fs.Stat(ctx, name)
+ if err != nil {
+ return err
+ }
+ for _, pst := range pstats {
+ for i, p := range pst.Props {
+ switch p.XMLName {
+ case xml.Name{Space: "DAV:", Local: "getlastmodified"}:
+ p.InnerXML = []byte(fi.ModTime().Format(http.TimeFormat))
+ pst.Props[i] = p
+ case xml.Name{Space: "DAV:", Local: "getetag"}:
+ if fi.IsDir() {
+ continue
+ }
+ etag, err := findETag(ctx, fs, ls, name, fi)
+ if err != nil {
+ return err
+ }
+ p.InnerXML = []byte(etag)
+ pst.Props[i] = p
+ }
+ }
+ }
+ return nil
+ }
+
+ const (
+ lockEntry = `` +
+ `<D:lockentry xmlns:D="DAV:">` +
+ `<D:lockscope><D:exclusive/></D:lockscope>` +
+ `<D:locktype><D:write/></D:locktype>` +
+ `</D:lockentry>`
+ statForbiddenError = `<D:cannot-modify-protected-property xmlns:D="DAV:"/>`
+ )
+
+ type propOp struct {
+ op string
+ name string
+ pnames []xml.Name
+ patches []Proppatch
+ wantPnames []xml.Name
+ wantPropstats []Propstat
+ }
+
+ testCases := []struct {
+ desc string
+ noDeadProps bool
+ buildfs []string
+ propOp []propOp
+ }{{
+ desc: "propname",
+ buildfs: []string{"mkdir /dir", "touch /file"},
+ propOp: []propOp{{
+ op: "propname",
+ name: "/dir",
+ wantPnames: []xml.Name{
+ {Space: "DAV:", Local: "resourcetype"},
+ {Space: "DAV:", Local: "displayname"},
+ {Space: "DAV:", Local: "supportedlock"},
+ {Space: "DAV:", Local: "getlastmodified"},
+ },
+ }, {
+ op: "propname",
+ name: "/file",
+ wantPnames: []xml.Name{
+ {Space: "DAV:", Local: "resourcetype"},
+ {Space: "DAV:", Local: "displayname"},
+ {Space: "DAV:", Local: "getcontentlength"},
+ {Space: "DAV:", Local: "getlastmodified"},
+ {Space: "DAV:", Local: "getcontenttype"},
+ {Space: "DAV:", Local: "getetag"},
+ {Space: "DAV:", Local: "supportedlock"},
+ },
+ }},
+ }, {
+ desc: "allprop dir and file",
+ buildfs: []string{"mkdir /dir", "write /file foobarbaz"},
+ propOp: []propOp{{
+ op: "allprop",
+ name: "/dir",
+ wantPropstats: []Propstat{{
+ Status: http.StatusOK,
+ Props: []Property{{
+ XMLName: xml.Name{Space: "DAV:", Local: "resourcetype"},
+ InnerXML: []byte(`<D:collection xmlns:D="DAV:"/>`),
+ }, {
+ XMLName: xml.Name{Space: "DAV:", Local: "displayname"},
+ InnerXML: []byte("dir"),
+ }, {
+ XMLName: xml.Name{Space: "DAV:", Local: "getlastmodified"},
+ InnerXML: nil, // Calculated during test.
+ }, {
+ XMLName: xml.Name{Space: "DAV:", Local: "supportedlock"},
+ InnerXML: []byte(lockEntry),
+ }},
+ }},
+ }, {
+ op: "allprop",
+ name: "/file",
+ wantPropstats: []Propstat{{
+ Status: http.StatusOK,
+ Props: []Property{{
+ XMLName: xml.Name{Space: "DAV:", Local: "resourcetype"},
+ InnerXML: []byte(""),
+ }, {
+ XMLName: xml.Name{Space: "DAV:", Local: "displayname"},
+ InnerXML: []byte("file"),
+ }, {
+ XMLName: xml.Name{Space: "DAV:", Local: "getcontentlength"},
+ InnerXML: []byte("9"),
+ }, {
+ XMLName: xml.Name{Space: "DAV:", Local: "getlastmodified"},
+ InnerXML: nil, // Calculated during test.
+ }, {
+ XMLName: xml.Name{Space: "DAV:", Local: "getcontenttype"},
+ InnerXML: []byte("text/plain; charset=utf-8"),
+ }, {
+ XMLName: xml.Name{Space: "DAV:", Local: "getetag"},
+ InnerXML: nil, // Calculated during test.
+ }, {
+ XMLName: xml.Name{Space: "DAV:", Local: "supportedlock"},
+ InnerXML: []byte(lockEntry),
+ }},
+ }},
+ }, {
+ op: "allprop",
+ name: "/file",
+ pnames: []xml.Name{
+ {"DAV:", "resourcetype"},
+ {"foo", "bar"},
+ },
+ wantPropstats: []Propstat{{
+ Status: http.StatusOK,
+ Props: []Property{{
+ XMLName: xml.Name{Space: "DAV:", Local: "resourcetype"},
+ InnerXML: []byte(""),
+ }, {
+ XMLName: xml.Name{Space: "DAV:", Local: "displayname"},
+ InnerXML: []byte("file"),
+ }, {
+ XMLName: xml.Name{Space: "DAV:", Local: "getcontentlength"},
+ InnerXML: []byte("9"),
+ }, {
+ XMLName: xml.Name{Space: "DAV:", Local: "getlastmodified"},
+ InnerXML: nil, // Calculated during test.
+ }, {
+ XMLName: xml.Name{Space: "DAV:", Local: "getcontenttype"},
+ InnerXML: []byte("text/plain; charset=utf-8"),
+ }, {
+ XMLName: xml.Name{Space: "DAV:", Local: "getetag"},
+ InnerXML: nil, // Calculated during test.
+ }, {
+ XMLName: xml.Name{Space: "DAV:", Local: "supportedlock"},
+ InnerXML: []byte(lockEntry),
+ }}}, {
+ Status: http.StatusNotFound,
+ Props: []Property{{
+ XMLName: xml.Name{Space: "foo", Local: "bar"},
+ }}},
+ },
+ }},
+ }, {
+ desc: "propfind DAV:resourcetype",
+ buildfs: []string{"mkdir /dir", "touch /file"},
+ propOp: []propOp{{
+ op: "propfind",
+ name: "/dir",
+ pnames: []xml.Name{{"DAV:", "resourcetype"}},
+ wantPropstats: []Propstat{{
+ Status: http.StatusOK,
+ Props: []Property{{
+ XMLName: xml.Name{Space: "DAV:", Local: "resourcetype"},
+ InnerXML: []byte(`<D:collection xmlns:D="DAV:"/>`),
+ }},
+ }},
+ }, {
+ op: "propfind",
+ name: "/file",
+ pnames: []xml.Name{{"DAV:", "resourcetype"}},
+ wantPropstats: []Propstat{{
+ Status: http.StatusOK,
+ Props: []Property{{
+ XMLName: xml.Name{Space: "DAV:", Local: "resourcetype"},
+ InnerXML: []byte(""),
+ }},
+ }},
+ }},
+ }, {
+ desc: "propfind unsupported DAV properties",
+ buildfs: []string{"mkdir /dir"},
+ propOp: []propOp{{
+ op: "propfind",
+ name: "/dir",
+ pnames: []xml.Name{{"DAV:", "getcontentlanguage"}},
+ wantPropstats: []Propstat{{
+ Status: http.StatusNotFound,
+ Props: []Property{{
+ XMLName: xml.Name{Space: "DAV:", Local: "getcontentlanguage"},
+ }},
+ }},
+ }, {
+ op: "propfind",
+ name: "/dir",
+ pnames: []xml.Name{{"DAV:", "creationdate"}},
+ wantPropstats: []Propstat{{
+ Status: http.StatusNotFound,
+ Props: []Property{{
+ XMLName: xml.Name{Space: "DAV:", Local: "creationdate"},
+ }},
+ }},
+ }},
+ }, {
+ desc: "propfind getetag for files but not for directories",
+ buildfs: []string{"mkdir /dir", "touch /file"},
+ propOp: []propOp{{
+ op: "propfind",
+ name: "/dir",
+ pnames: []xml.Name{{"DAV:", "getetag"}},
+ wantPropstats: []Propstat{{
+ Status: http.StatusNotFound,
+ Props: []Property{{
+ XMLName: xml.Name{Space: "DAV:", Local: "getetag"},
+ }},
+ }},
+ }, {
+ op: "propfind",
+ name: "/file",
+ pnames: []xml.Name{{"DAV:", "getetag"}},
+ wantPropstats: []Propstat{{
+ Status: http.StatusOK,
+ Props: []Property{{
+ XMLName: xml.Name{Space: "DAV:", Local: "getetag"},
+ InnerXML: nil, // Calculated during test.
+ }},
+ }},
+ }},
+ }, {
+ desc: "proppatch property on no-dead-properties file system",
+ buildfs: []string{"mkdir /dir"},
+ noDeadProps: true,
+ propOp: []propOp{{
+ op: "proppatch",
+ name: "/dir",
+ patches: []Proppatch{{
+ Props: []Property{{
+ XMLName: xml.Name{Space: "foo", Local: "bar"},
+ }},
+ }},
+ wantPropstats: []Propstat{{
+ Status: http.StatusForbidden,
+ Props: []Property{{
+ XMLName: xml.Name{Space: "foo", Local: "bar"},
+ }},
+ }},
+ }, {
+ op: "proppatch",
+ name: "/dir",
+ patches: []Proppatch{{
+ Props: []Property{{
+ XMLName: xml.Name{Space: "DAV:", Local: "getetag"},
+ }},
+ }},
+ wantPropstats: []Propstat{{
+ Status: http.StatusForbidden,
+ XMLError: statForbiddenError,
+ Props: []Property{{
+ XMLName: xml.Name{Space: "DAV:", Local: "getetag"},
+ }},
+ }},
+ }},
+ }, {
+ desc: "proppatch dead property",
+ buildfs: []string{"mkdir /dir"},
+ propOp: []propOp{{
+ op: "proppatch",
+ name: "/dir",
+ patches: []Proppatch{{
+ Props: []Property{{
+ XMLName: xml.Name{Space: "foo", Local: "bar"},
+ InnerXML: []byte("baz"),
+ }},
+ }},
+ wantPropstats: []Propstat{{
+ Status: http.StatusOK,
+ Props: []Property{{
+ XMLName: xml.Name{Space: "foo", Local: "bar"},
+ }},
+ }},
+ }, {
+ op: "propfind",
+ name: "/dir",
+ pnames: []xml.Name{{Space: "foo", Local: "bar"}},
+ wantPropstats: []Propstat{{
+ Status: http.StatusOK,
+ Props: []Property{{
+ XMLName: xml.Name{Space: "foo", Local: "bar"},
+ InnerXML: []byte("baz"),
+ }},
+ }},
+ }},
+ }, {
+ desc: "proppatch dead property with failed dependency",
+ buildfs: []string{"mkdir /dir"},
+ propOp: []propOp{{
+ op: "proppatch",
+ name: "/dir",
+ patches: []Proppatch{{
+ Props: []Property{{
+ XMLName: xml.Name{Space: "foo", Local: "bar"},
+ InnerXML: []byte("baz"),
+ }},
+ }, {
+ Props: []Property{{
+ XMLName: xml.Name{Space: "DAV:", Local: "displayname"},
+ InnerXML: []byte("xxx"),
+ }},
+ }},
+ wantPropstats: []Propstat{{
+ Status: http.StatusForbidden,
+ XMLError: statForbiddenError,
+ Props: []Property{{
+ XMLName: xml.Name{Space: "DAV:", Local: "displayname"},
+ }},
+ }, {
+ Status: StatusFailedDependency,
+ Props: []Property{{
+ XMLName: xml.Name{Space: "foo", Local: "bar"},
+ }},
+ }},
+ }, {
+ op: "propfind",
+ name: "/dir",
+ pnames: []xml.Name{{Space: "foo", Local: "bar"}},
+ wantPropstats: []Propstat{{
+ Status: http.StatusNotFound,
+ Props: []Property{{
+ XMLName: xml.Name{Space: "foo", Local: "bar"},
+ }},
+ }},
+ }},
+ }, {
+ desc: "proppatch remove dead property",
+ buildfs: []string{"mkdir /dir"},
+ propOp: []propOp{{
+ op: "proppatch",
+ name: "/dir",
+ patches: []Proppatch{{
+ Props: []Property{{
+ XMLName: xml.Name{Space: "foo", Local: "bar"},
+ InnerXML: []byte("baz"),
+ }, {
+ XMLName: xml.Name{Space: "spam", Local: "ham"},
+ InnerXML: []byte("eggs"),
+ }},
+ }},
+ wantPropstats: []Propstat{{
+ Status: http.StatusOK,
+ Props: []Property{{
+ XMLName: xml.Name{Space: "foo", Local: "bar"},
+ }, {
+ XMLName: xml.Name{Space: "spam", Local: "ham"},
+ }},
+ }},
+ }, {
+ op: "propfind",
+ name: "/dir",
+ pnames: []xml.Name{
+ {Space: "foo", Local: "bar"},
+ {Space: "spam", Local: "ham"},
+ },
+ wantPropstats: []Propstat{{
+ Status: http.StatusOK,
+ Props: []Property{{
+ XMLName: xml.Name{Space: "foo", Local: "bar"},
+ InnerXML: []byte("baz"),
+ }, {
+ XMLName: xml.Name{Space: "spam", Local: "ham"},
+ InnerXML: []byte("eggs"),
+ }},
+ }},
+ }, {
+ op: "proppatch",
+ name: "/dir",
+ patches: []Proppatch{{
+ Remove: true,
+ Props: []Property{{
+ XMLName: xml.Name{Space: "foo", Local: "bar"},
+ }},
+ }},
+ wantPropstats: []Propstat{{
+ Status: http.StatusOK,
+ Props: []Property{{
+ XMLName: xml.Name{Space: "foo", Local: "bar"},
+ }},
+ }},
+ }, {
+ op: "propfind",
+ name: "/dir",
+ pnames: []xml.Name{
+ {Space: "foo", Local: "bar"},
+ {Space: "spam", Local: "ham"},
+ },
+ wantPropstats: []Propstat{{
+ Status: http.StatusNotFound,
+ Props: []Property{{
+ XMLName: xml.Name{Space: "foo", Local: "bar"},
+ }},
+ }, {
+ Status: http.StatusOK,
+ Props: []Property{{
+ XMLName: xml.Name{Space: "spam", Local: "ham"},
+ InnerXML: []byte("eggs"),
+ }},
+ }},
+ }},
+ }, {
+ desc: "propname with dead property",
+ buildfs: []string{"touch /file"},
+ propOp: []propOp{{
+ op: "proppatch",
+ name: "/file",
+ patches: []Proppatch{{
+ Props: []Property{{
+ XMLName: xml.Name{Space: "foo", Local: "bar"},
+ InnerXML: []byte("baz"),
+ }},
+ }},
+ wantPropstats: []Propstat{{
+ Status: http.StatusOK,
+ Props: []Property{{
+ XMLName: xml.Name{Space: "foo", Local: "bar"},
+ }},
+ }},
+ }, {
+ op: "propname",
+ name: "/file",
+ wantPnames: []xml.Name{
+ {Space: "DAV:", Local: "resourcetype"},
+ {Space: "DAV:", Local: "displayname"},
+ {Space: "DAV:", Local: "getcontentlength"},
+ {Space: "DAV:", Local: "getlastmodified"},
+ {Space: "DAV:", Local: "getcontenttype"},
+ {Space: "DAV:", Local: "getetag"},
+ {Space: "DAV:", Local: "supportedlock"},
+ {Space: "foo", Local: "bar"},
+ },
+ }},
+ }, {
+ desc: "proppatch remove unknown dead property",
+ buildfs: []string{"mkdir /dir"},
+ propOp: []propOp{{
+ op: "proppatch",
+ name: "/dir",
+ patches: []Proppatch{{
+ Remove: true,
+ Props: []Property{{
+ XMLName: xml.Name{Space: "foo", Local: "bar"},
+ }},
+ }},
+ wantPropstats: []Propstat{{
+ Status: http.StatusOK,
+ Props: []Property{{
+ XMLName: xml.Name{Space: "foo", Local: "bar"},
+ }},
+ }},
+ }},
+ }, {
+ desc: "bad: propfind unknown property",
+ buildfs: []string{"mkdir /dir"},
+ propOp: []propOp{{
+ op: "propfind",
+ name: "/dir",
+ pnames: []xml.Name{{"foo:", "bar"}},
+ wantPropstats: []Propstat{{
+ Status: http.StatusNotFound,
+ Props: []Property{{
+ XMLName: xml.Name{Space: "foo:", Local: "bar"},
+ }},
+ }},
+ }},
+ }}
+
+ for _, tc := range testCases {
+ fs, err := buildTestFS(tc.buildfs)
+ if err != nil {
+ t.Fatalf("%s: cannot create test filesystem: %v", tc.desc, err)
+ }
+ if tc.noDeadProps {
+ fs = noDeadPropsFS{fs}
+ }
+ ls := NewMemLS()
+ for _, op := range tc.propOp {
+ desc := fmt.Sprintf("%s: %s %s", tc.desc, op.op, op.name)
+ if err = calcProps(op.name, fs, ls, op.wantPropstats); err != nil {
+ t.Fatalf("%s: calcProps: %v", desc, err)
+ }
+
+ // Call property system.
+ var propstats []Propstat
+ switch op.op {
+ case "propname":
+ pnames, err := propnames(ctx, fs, ls, op.name)
+ if err != nil {
+ t.Errorf("%s: got error %v, want nil", desc, err)
+ continue
+ }
+ sort.Sort(byXMLName(pnames))
+ sort.Sort(byXMLName(op.wantPnames))
+ if !reflect.DeepEqual(pnames, op.wantPnames) {
+ t.Errorf("%s: pnames\ngot %q\nwant %q", desc, pnames, op.wantPnames)
+ }
+ continue
+ case "allprop":
+ propstats, err = allprop(ctx, fs, ls, op.name, op.pnames)
+ case "propfind":
+ propstats, err = props(ctx, fs, ls, op.name, op.pnames)
+ case "proppatch":
+ propstats, err = patch(ctx, fs, ls, op.name, op.patches)
+ default:
+ t.Fatalf("%s: %s not implemented", desc, op.op)
+ }
+ if err != nil {
+ t.Errorf("%s: got error %v, want nil", desc, err)
+ continue
+ }
+ // Compare return values from allprop, propfind or proppatch.
+ for _, pst := range propstats {
+ sort.Sort(byPropname(pst.Props))
+ }
+ for _, pst := range op.wantPropstats {
+ sort.Sort(byPropname(pst.Props))
+ }
+ sort.Sort(byStatus(propstats))
+ sort.Sort(byStatus(op.wantPropstats))
+ if !reflect.DeepEqual(propstats, op.wantPropstats) {
+ t.Errorf("%s: propstat\ngot %q\nwant %q", desc, propstats, op.wantPropstats)
+ }
+ }
+ }
+}
+
+func cmpXMLName(a, b xml.Name) bool {
+ if a.Space != b.Space {
+ return a.Space < b.Space
+ }
+ return a.Local < b.Local
+}
+
+type byXMLName []xml.Name
+
+func (b byXMLName) Len() int { return len(b) }
+func (b byXMLName) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
+func (b byXMLName) Less(i, j int) bool { return cmpXMLName(b[i], b[j]) }
+
+type byPropname []Property
+
+func (b byPropname) Len() int { return len(b) }
+func (b byPropname) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
+func (b byPropname) Less(i, j int) bool { return cmpXMLName(b[i].XMLName, b[j].XMLName) }
+
+type byStatus []Propstat
+
+func (b byStatus) Len() int { return len(b) }
+func (b byStatus) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
+func (b byStatus) Less(i, j int) bool { return b[i].Status < b[j].Status }
+
+type noDeadPropsFS struct {
+ FileSystem
+}
+
+func (fs noDeadPropsFS) OpenFile(ctx context.Context, name string, flag int, perm os.FileMode) (File, error) {
+ f, err := fs.FileSystem.OpenFile(ctx, name, flag, perm)
+ if err != nil {
+ return nil, err
+ }
+ return noDeadPropsFile{f}, nil
+}
+
+// noDeadPropsFile wraps a File but strips any optional DeadPropsHolder methods
+// provided by the underlying File implementation.
+type noDeadPropsFile struct {
+ f File
+}
+
+func (f noDeadPropsFile) Close() error { return f.f.Close() }
+func (f noDeadPropsFile) Read(p []byte) (int, error) { return f.f.Read(p) }
+func (f noDeadPropsFile) Readdir(count int) ([]os.FileInfo, error) { return f.f.Readdir(count) }
+func (f noDeadPropsFile) Seek(off int64, whence int) (int64, error) { return f.f.Seek(off, whence) }
+func (f noDeadPropsFile) Stat() (os.FileInfo, error) { return f.f.Stat() }
+func (f noDeadPropsFile) Write(p []byte) (int, error) { return f.f.Write(p) }
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/webdav.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/webdav.go
new file mode 100644
index 000000000..7b56687fc
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/webdav.go
@@ -0,0 +1,702 @@
+// Copyright 2014 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 webdav provides a WebDAV server implementation.
+package webdav // import "golang.org/x/net/webdav"
+
+import (
+ "errors"
+ "fmt"
+ "io"
+ "net/http"
+ "net/url"
+ "os"
+ "path"
+ "strings"
+ "time"
+)
+
+type Handler struct {
+ // Prefix is the URL path prefix to strip from WebDAV resource paths.
+ Prefix string
+ // FileSystem is the virtual file system.
+ FileSystem FileSystem
+ // LockSystem is the lock management system.
+ LockSystem LockSystem
+ // Logger is an optional error logger. If non-nil, it will be called
+ // for all HTTP requests.
+ Logger func(*http.Request, error)
+}
+
+func (h *Handler) stripPrefix(p string) (string, int, error) {
+ if h.Prefix == "" {
+ return p, http.StatusOK, nil
+ }
+ if r := strings.TrimPrefix(p, h.Prefix); len(r) < len(p) {
+ return r, http.StatusOK, nil
+ }
+ return p, http.StatusNotFound, errPrefixMismatch
+}
+
+func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ status, err := http.StatusBadRequest, errUnsupportedMethod
+ if h.FileSystem == nil {
+ status, err = http.StatusInternalServerError, errNoFileSystem
+ } else if h.LockSystem == nil {
+ status, err = http.StatusInternalServerError, errNoLockSystem
+ } else {
+ switch r.Method {
+ case "OPTIONS":
+ status, err = h.handleOptions(w, r)
+ case "GET", "HEAD", "POST":
+ status, err = h.handleGetHeadPost(w, r)
+ case "DELETE":
+ status, err = h.handleDelete(w, r)
+ case "PUT":
+ status, err = h.handlePut(w, r)
+ case "MKCOL":
+ status, err = h.handleMkcol(w, r)
+ case "COPY", "MOVE":
+ status, err = h.handleCopyMove(w, r)
+ case "LOCK":
+ status, err = h.handleLock(w, r)
+ case "UNLOCK":
+ status, err = h.handleUnlock(w, r)
+ case "PROPFIND":
+ status, err = h.handlePropfind(w, r)
+ case "PROPPATCH":
+ status, err = h.handleProppatch(w, r)
+ }
+ }
+
+ if status != 0 {
+ w.WriteHeader(status)
+ if status != http.StatusNoContent {
+ w.Write([]byte(StatusText(status)))
+ }
+ }
+ if h.Logger != nil {
+ h.Logger(r, err)
+ }
+}
+
+func (h *Handler) lock(now time.Time, root string) (token string, status int, err error) {
+ token, err = h.LockSystem.Create(now, LockDetails{
+ Root: root,
+ Duration: infiniteTimeout,
+ ZeroDepth: true,
+ })
+ if err != nil {
+ if err == ErrLocked {
+ return "", StatusLocked, err
+ }
+ return "", http.StatusInternalServerError, err
+ }
+ return token, 0, nil
+}
+
+func (h *Handler) confirmLocks(r *http.Request, src, dst string) (release func(), status int, err error) {
+ hdr := r.Header.Get("If")
+ if hdr == "" {
+ // An empty If header means that the client hasn't previously created locks.
+ // Even if this client doesn't care about locks, we still need to check that
+ // the resources aren't locked by another client, so we create temporary
+ // locks that would conflict with another client's locks. These temporary
+ // locks are unlocked at the end of the HTTP request.
+ now, srcToken, dstToken := time.Now(), "", ""
+ if src != "" {
+ srcToken, status, err = h.lock(now, src)
+ if err != nil {
+ return nil, status, err
+ }
+ }
+ if dst != "" {
+ dstToken, status, err = h.lock(now, dst)
+ if err != nil {
+ if srcToken != "" {
+ h.LockSystem.Unlock(now, srcToken)
+ }
+ return nil, status, err
+ }
+ }
+
+ return func() {
+ if dstToken != "" {
+ h.LockSystem.Unlock(now, dstToken)
+ }
+ if srcToken != "" {
+ h.LockSystem.Unlock(now, srcToken)
+ }
+ }, 0, nil
+ }
+
+ ih, ok := parseIfHeader(hdr)
+ if !ok {
+ return nil, http.StatusBadRequest, errInvalidIfHeader
+ }
+ // ih is a disjunction (OR) of ifLists, so any ifList will do.
+ for _, l := range ih.lists {
+ lsrc := l.resourceTag
+ if lsrc == "" {
+ lsrc = src
+ } else {
+ u, err := url.Parse(lsrc)
+ if err != nil {
+ continue
+ }
+ if u.Host != r.Host {
+ continue
+ }
+ lsrc, status, err = h.stripPrefix(u.Path)
+ if err != nil {
+ return nil, status, err
+ }
+ }
+ release, err = h.LockSystem.Confirm(time.Now(), lsrc, dst, l.conditions...)
+ if err == ErrConfirmationFailed {
+ continue
+ }
+ if err != nil {
+ return nil, http.StatusInternalServerError, err
+ }
+ return release, 0, nil
+ }
+ // Section 10.4.1 says that "If this header is evaluated and all state lists
+ // fail, then the request must fail with a 412 (Precondition Failed) status."
+ // We follow the spec even though the cond_put_corrupt_token test case from
+ // the litmus test warns on seeing a 412 instead of a 423 (Locked).
+ return nil, http.StatusPreconditionFailed, ErrLocked
+}
+
+func (h *Handler) handleOptions(w http.ResponseWriter, r *http.Request) (status int, err error) {
+ reqPath, status, err := h.stripPrefix(r.URL.Path)
+ if err != nil {
+ return status, err
+ }
+ ctx := getContext(r)
+ allow := "OPTIONS, LOCK, PUT, MKCOL"
+ if fi, err := h.FileSystem.Stat(ctx, reqPath); err == nil {
+ if fi.IsDir() {
+ allow = "OPTIONS, LOCK, DELETE, PROPPATCH, COPY, MOVE, UNLOCK, PROPFIND"
+ } else {
+ allow = "OPTIONS, LOCK, GET, HEAD, POST, DELETE, PROPPATCH, COPY, MOVE, UNLOCK, PROPFIND, PUT"
+ }
+ }
+ w.Header().Set("Allow", allow)
+ // http://www.webdav.org/specs/rfc4918.html#dav.compliance.classes
+ w.Header().Set("DAV", "1, 2")
+ // http://msdn.microsoft.com/en-au/library/cc250217.aspx
+ w.Header().Set("MS-Author-Via", "DAV")
+ return 0, nil
+}
+
+func (h *Handler) handleGetHeadPost(w http.ResponseWriter, r *http.Request) (status int, err error) {
+ reqPath, status, err := h.stripPrefix(r.URL.Path)
+ if err != nil {
+ return status, err
+ }
+ // TODO: check locks for read-only access??
+ ctx := getContext(r)
+ f, err := h.FileSystem.OpenFile(ctx, reqPath, os.O_RDONLY, 0)
+ if err != nil {
+ return http.StatusNotFound, err
+ }
+ defer f.Close()
+ fi, err := f.Stat()
+ if err != nil {
+ return http.StatusNotFound, err
+ }
+ if fi.IsDir() {
+ return http.StatusMethodNotAllowed, nil
+ }
+ etag, err := findETag(ctx, h.FileSystem, h.LockSystem, reqPath, fi)
+ if err != nil {
+ return http.StatusInternalServerError, err
+ }
+ w.Header().Set("ETag", etag)
+ // Let ServeContent determine the Content-Type header.
+ http.ServeContent(w, r, reqPath, fi.ModTime(), f)
+ return 0, nil
+}
+
+func (h *Handler) handleDelete(w http.ResponseWriter, r *http.Request) (status int, err error) {
+ reqPath, status, err := h.stripPrefix(r.URL.Path)
+ if err != nil {
+ return status, err
+ }
+ release, status, err := h.confirmLocks(r, reqPath, "")
+ if err != nil {
+ return status, err
+ }
+ defer release()
+
+ ctx := getContext(r)
+
+ // TODO: return MultiStatus where appropriate.
+
+ // "godoc os RemoveAll" says that "If the path does not exist, RemoveAll
+ // returns nil (no error)." WebDAV semantics are that it should return a
+ // "404 Not Found". We therefore have to Stat before we RemoveAll.
+ if _, err := h.FileSystem.Stat(ctx, reqPath); err != nil {
+ if os.IsNotExist(err) {
+ return http.StatusNotFound, err
+ }
+ return http.StatusMethodNotAllowed, err
+ }
+ if err := h.FileSystem.RemoveAll(ctx, reqPath); err != nil {
+ return http.StatusMethodNotAllowed, err
+ }
+ return http.StatusNoContent, nil
+}
+
+func (h *Handler) handlePut(w http.ResponseWriter, r *http.Request) (status int, err error) {
+ reqPath, status, err := h.stripPrefix(r.URL.Path)
+ if err != nil {
+ return status, err
+ }
+ release, status, err := h.confirmLocks(r, reqPath, "")
+ if err != nil {
+ return status, err
+ }
+ defer release()
+ // TODO(rost): Support the If-Match, If-None-Match headers? See bradfitz'
+ // comments in http.checkEtag.
+ ctx := getContext(r)
+
+ f, err := h.FileSystem.OpenFile(ctx, reqPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666)
+ if err != nil {
+ return http.StatusNotFound, err
+ }
+ _, copyErr := io.Copy(f, r.Body)
+ fi, statErr := f.Stat()
+ closeErr := f.Close()
+ // TODO(rost): Returning 405 Method Not Allowed might not be appropriate.
+ if copyErr != nil {
+ return http.StatusMethodNotAllowed, copyErr
+ }
+ if statErr != nil {
+ return http.StatusMethodNotAllowed, statErr
+ }
+ if closeErr != nil {
+ return http.StatusMethodNotAllowed, closeErr
+ }
+ etag, err := findETag(ctx, h.FileSystem, h.LockSystem, reqPath, fi)
+ if err != nil {
+ return http.StatusInternalServerError, err
+ }
+ w.Header().Set("ETag", etag)
+ return http.StatusCreated, nil
+}
+
+func (h *Handler) handleMkcol(w http.ResponseWriter, r *http.Request) (status int, err error) {
+ reqPath, status, err := h.stripPrefix(r.URL.Path)
+ if err != nil {
+ return status, err
+ }
+ release, status, err := h.confirmLocks(r, reqPath, "")
+ if err != nil {
+ return status, err
+ }
+ defer release()
+
+ ctx := getContext(r)
+
+ if r.ContentLength > 0 {
+ return http.StatusUnsupportedMediaType, nil
+ }
+ if err := h.FileSystem.Mkdir(ctx, reqPath, 0777); err != nil {
+ if os.IsNotExist(err) {
+ return http.StatusConflict, err
+ }
+ return http.StatusMethodNotAllowed, err
+ }
+ return http.StatusCreated, nil
+}
+
+func (h *Handler) handleCopyMove(w http.ResponseWriter, r *http.Request) (status int, err error) {
+ hdr := r.Header.Get("Destination")
+ if hdr == "" {
+ return http.StatusBadRequest, errInvalidDestination
+ }
+ u, err := url.Parse(hdr)
+ if err != nil {
+ return http.StatusBadRequest, errInvalidDestination
+ }
+ if u.Host != r.Host {
+ return http.StatusBadGateway, errInvalidDestination
+ }
+
+ src, status, err := h.stripPrefix(r.URL.Path)
+ if err != nil {
+ return status, err
+ }
+
+ dst, status, err := h.stripPrefix(u.Path)
+ if err != nil {
+ return status, err
+ }
+
+ if dst == "" {
+ return http.StatusBadGateway, errInvalidDestination
+ }
+ if dst == src {
+ return http.StatusForbidden, errDestinationEqualsSource
+ }
+
+ ctx := getContext(r)
+
+ if r.Method == "COPY" {
+ // Section 7.5.1 says that a COPY only needs to lock the destination,
+ // not both destination and source. Strictly speaking, this is racy,
+ // even though a COPY doesn't modify the source, if a concurrent
+ // operation modifies the source. However, the litmus test explicitly
+ // checks that COPYing a locked-by-another source is OK.
+ release, status, err := h.confirmLocks(r, "", dst)
+ if err != nil {
+ return status, err
+ }
+ defer release()
+
+ // Section 9.8.3 says that "The COPY method on a collection without a Depth
+ // header must act as if a Depth header with value "infinity" was included".
+ depth := infiniteDepth
+ if hdr := r.Header.Get("Depth"); hdr != "" {
+ depth = parseDepth(hdr)
+ if depth != 0 && depth != infiniteDepth {
+ // Section 9.8.3 says that "A client may submit a Depth header on a
+ // COPY on a collection with a value of "0" or "infinity"."
+ return http.StatusBadRequest, errInvalidDepth
+ }
+ }
+ return copyFiles(ctx, h.FileSystem, src, dst, r.Header.Get("Overwrite") != "F", depth, 0)
+ }
+
+ release, status, err := h.confirmLocks(r, src, dst)
+ if err != nil {
+ return status, err
+ }
+ defer release()
+
+ // Section 9.9.2 says that "The MOVE method on a collection must act as if
+ // a "Depth: infinity" header was used on it. A client must not submit a
+ // Depth header on a MOVE on a collection with any value but "infinity"."
+ if hdr := r.Header.Get("Depth"); hdr != "" {
+ if parseDepth(hdr) != infiniteDepth {
+ return http.StatusBadRequest, errInvalidDepth
+ }
+ }
+ return moveFiles(ctx, h.FileSystem, src, dst, r.Header.Get("Overwrite") == "T")
+}
+
+func (h *Handler) handleLock(w http.ResponseWriter, r *http.Request) (retStatus int, retErr error) {
+ duration, err := parseTimeout(r.Header.Get("Timeout"))
+ if err != nil {
+ return http.StatusBadRequest, err
+ }
+ li, status, err := readLockInfo(r.Body)
+ if err != nil {
+ return status, err
+ }
+
+ ctx := getContext(r)
+ token, ld, now, created := "", LockDetails{}, time.Now(), false
+ if li == (lockInfo{}) {
+ // An empty lockInfo means to refresh the lock.
+ ih, ok := parseIfHeader(r.Header.Get("If"))
+ if !ok {
+ return http.StatusBadRequest, errInvalidIfHeader
+ }
+ if len(ih.lists) == 1 && len(ih.lists[0].conditions) == 1 {
+ token = ih.lists[0].conditions[0].Token
+ }
+ if token == "" {
+ return http.StatusBadRequest, errInvalidLockToken
+ }
+ ld, err = h.LockSystem.Refresh(now, token, duration)
+ if err != nil {
+ if err == ErrNoSuchLock {
+ return http.StatusPreconditionFailed, err
+ }
+ return http.StatusInternalServerError, err
+ }
+
+ } else {
+ // Section 9.10.3 says that "If no Depth header is submitted on a LOCK request,
+ // then the request MUST act as if a "Depth:infinity" had been submitted."
+ depth := infiniteDepth
+ if hdr := r.Header.Get("Depth"); hdr != "" {
+ depth = parseDepth(hdr)
+ if depth != 0 && depth != infiniteDepth {
+ // Section 9.10.3 says that "Values other than 0 or infinity must not be
+ // used with the Depth header on a LOCK method".
+ return http.StatusBadRequest, errInvalidDepth
+ }
+ }
+ reqPath, status, err := h.stripPrefix(r.URL.Path)
+ if err != nil {
+ return status, err
+ }
+ ld = LockDetails{
+ Root: reqPath,
+ Duration: duration,
+ OwnerXML: li.Owner.InnerXML,
+ ZeroDepth: depth == 0,
+ }
+ token, err = h.LockSystem.Create(now, ld)
+ if err != nil {
+ if err == ErrLocked {
+ return StatusLocked, err
+ }
+ return http.StatusInternalServerError, err
+ }
+ defer func() {
+ if retErr != nil {
+ h.LockSystem.Unlock(now, token)
+ }
+ }()
+
+ // Create the resource if it didn't previously exist.
+ if _, err := h.FileSystem.Stat(ctx, reqPath); err != nil {
+ f, err := h.FileSystem.OpenFile(ctx, reqPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666)
+ if err != nil {
+ // TODO: detect missing intermediate dirs and return http.StatusConflict?
+ return http.StatusInternalServerError, err
+ }
+ f.Close()
+ created = true
+ }
+
+ // http://www.webdav.org/specs/rfc4918.html#HEADER_Lock-Token says that the
+ // Lock-Token value is a Coded-URL. We add angle brackets.
+ w.Header().Set("Lock-Token", "<"+token+">")
+ }
+
+ w.Header().Set("Content-Type", "application/xml; charset=utf-8")
+ if created {
+ // This is "w.WriteHeader(http.StatusCreated)" and not "return
+ // http.StatusCreated, nil" because we write our own (XML) response to w
+ // and Handler.ServeHTTP would otherwise write "Created".
+ w.WriteHeader(http.StatusCreated)
+ }
+ writeLockInfo(w, token, ld)
+ return 0, nil
+}
+
+func (h *Handler) handleUnlock(w http.ResponseWriter, r *http.Request) (status int, err error) {
+ // http://www.webdav.org/specs/rfc4918.html#HEADER_Lock-Token says that the
+ // Lock-Token value is a Coded-URL. We strip its angle brackets.
+ t := r.Header.Get("Lock-Token")
+ if len(t) < 2 || t[0] != '<' || t[len(t)-1] != '>' {
+ return http.StatusBadRequest, errInvalidLockToken
+ }
+ t = t[1 : len(t)-1]
+
+ switch err = h.LockSystem.Unlock(time.Now(), t); err {
+ case nil:
+ return http.StatusNoContent, err
+ case ErrForbidden:
+ return http.StatusForbidden, err
+ case ErrLocked:
+ return StatusLocked, err
+ case ErrNoSuchLock:
+ return http.StatusConflict, err
+ default:
+ return http.StatusInternalServerError, err
+ }
+}
+
+func (h *Handler) handlePropfind(w http.ResponseWriter, r *http.Request) (status int, err error) {
+ reqPath, status, err := h.stripPrefix(r.URL.Path)
+ if err != nil {
+ return status, err
+ }
+ ctx := getContext(r)
+ fi, err := h.FileSystem.Stat(ctx, reqPath)
+ if err != nil {
+ if os.IsNotExist(err) {
+ return http.StatusNotFound, err
+ }
+ return http.StatusMethodNotAllowed, err
+ }
+ depth := infiniteDepth
+ if hdr := r.Header.Get("Depth"); hdr != "" {
+ depth = parseDepth(hdr)
+ if depth == invalidDepth {
+ return http.StatusBadRequest, errInvalidDepth
+ }
+ }
+ pf, status, err := readPropfind(r.Body)
+ if err != nil {
+ return status, err
+ }
+
+ mw := multistatusWriter{w: w}
+
+ walkFn := func(reqPath string, info os.FileInfo, err error) error {
+ if err != nil {
+ return err
+ }
+ var pstats []Propstat
+ if pf.Propname != nil {
+ pnames, err := propnames(ctx, h.FileSystem, h.LockSystem, reqPath)
+ if err != nil {
+ return err
+ }
+ pstat := Propstat{Status: http.StatusOK}
+ for _, xmlname := range pnames {
+ pstat.Props = append(pstat.Props, Property{XMLName: xmlname})
+ }
+ pstats = append(pstats, pstat)
+ } else if pf.Allprop != nil {
+ pstats, err = allprop(ctx, h.FileSystem, h.LockSystem, reqPath, pf.Prop)
+ } else {
+ pstats, err = props(ctx, h.FileSystem, h.LockSystem, reqPath, pf.Prop)
+ }
+ if err != nil {
+ return err
+ }
+ return mw.write(makePropstatResponse(path.Join(h.Prefix, reqPath), pstats))
+ }
+
+ walkErr := walkFS(ctx, h.FileSystem, depth, reqPath, fi, walkFn)
+ closeErr := mw.close()
+ if walkErr != nil {
+ return http.StatusInternalServerError, walkErr
+ }
+ if closeErr != nil {
+ return http.StatusInternalServerError, closeErr
+ }
+ return 0, nil
+}
+
+func (h *Handler) handleProppatch(w http.ResponseWriter, r *http.Request) (status int, err error) {
+ reqPath, status, err := h.stripPrefix(r.URL.Path)
+ if err != nil {
+ return status, err
+ }
+ release, status, err := h.confirmLocks(r, reqPath, "")
+ if err != nil {
+ return status, err
+ }
+ defer release()
+
+ ctx := getContext(r)
+
+ if _, err := h.FileSystem.Stat(ctx, reqPath); err != nil {
+ if os.IsNotExist(err) {
+ return http.StatusNotFound, err
+ }
+ return http.StatusMethodNotAllowed, err
+ }
+ patches, status, err := readProppatch(r.Body)
+ if err != nil {
+ return status, err
+ }
+ pstats, err := patch(ctx, h.FileSystem, h.LockSystem, reqPath, patches)
+ if err != nil {
+ return http.StatusInternalServerError, err
+ }
+ mw := multistatusWriter{w: w}
+ writeErr := mw.write(makePropstatResponse(r.URL.Path, pstats))
+ closeErr := mw.close()
+ if writeErr != nil {
+ return http.StatusInternalServerError, writeErr
+ }
+ if closeErr != nil {
+ return http.StatusInternalServerError, closeErr
+ }
+ return 0, nil
+}
+
+func makePropstatResponse(href string, pstats []Propstat) *response {
+ resp := response{
+ Href: []string{(&url.URL{Path: href}).EscapedPath()},
+ Propstat: make([]propstat, 0, len(pstats)),
+ }
+ for _, p := range pstats {
+ var xmlErr *xmlError
+ if p.XMLError != "" {
+ xmlErr = &xmlError{InnerXML: []byte(p.XMLError)}
+ }
+ resp.Propstat = append(resp.Propstat, propstat{
+ Status: fmt.Sprintf("HTTP/1.1 %d %s", p.Status, StatusText(p.Status)),
+ Prop: p.Props,
+ ResponseDescription: p.ResponseDescription,
+ Error: xmlErr,
+ })
+ }
+ return &resp
+}
+
+const (
+ infiniteDepth = -1
+ invalidDepth = -2
+)
+
+// parseDepth maps the strings "0", "1" and "infinity" to 0, 1 and
+// infiniteDepth. Parsing any other string returns invalidDepth.
+//
+// Different WebDAV methods have further constraints on valid depths:
+// - PROPFIND has no further restrictions, as per section 9.1.
+// - COPY accepts only "0" or "infinity", as per section 9.8.3.
+// - MOVE accepts only "infinity", as per section 9.9.2.
+// - LOCK accepts only "0" or "infinity", as per section 9.10.3.
+// These constraints are enforced by the handleXxx methods.
+func parseDepth(s string) int {
+ switch s {
+ case "0":
+ return 0
+ case "1":
+ return 1
+ case "infinity":
+ return infiniteDepth
+ }
+ return invalidDepth
+}
+
+// http://www.webdav.org/specs/rfc4918.html#status.code.extensions.to.http11
+const (
+ StatusMulti = 207
+ StatusUnprocessableEntity = 422
+ StatusLocked = 423
+ StatusFailedDependency = 424
+ StatusInsufficientStorage = 507
+)
+
+func StatusText(code int) string {
+ switch code {
+ case StatusMulti:
+ return "Multi-Status"
+ case StatusUnprocessableEntity:
+ return "Unprocessable Entity"
+ case StatusLocked:
+ return "Locked"
+ case StatusFailedDependency:
+ return "Failed Dependency"
+ case StatusInsufficientStorage:
+ return "Insufficient Storage"
+ }
+ return http.StatusText(code)
+}
+
+var (
+ errDestinationEqualsSource = errors.New("webdav: destination equals source")
+ errDirectoryNotEmpty = errors.New("webdav: directory not empty")
+ errInvalidDepth = errors.New("webdav: invalid depth")
+ errInvalidDestination = errors.New("webdav: invalid destination")
+ errInvalidIfHeader = errors.New("webdav: invalid If header")
+ errInvalidLockInfo = errors.New("webdav: invalid lock info")
+ errInvalidLockToken = errors.New("webdav: invalid lock token")
+ errInvalidPropfind = errors.New("webdav: invalid propfind")
+ errInvalidProppatch = errors.New("webdav: invalid proppatch")
+ errInvalidResponse = errors.New("webdav: invalid response")
+ errInvalidTimeout = errors.New("webdav: invalid timeout")
+ errNoFileSystem = errors.New("webdav: no file system")
+ errNoLockSystem = errors.New("webdav: no lock system")
+ errNotADirectory = errors.New("webdav: not a directory")
+ errPrefixMismatch = errors.New("webdav: prefix mismatch")
+ errRecursionTooDeep = errors.New("webdav: recursion too deep")
+ errUnsupportedLockInfo = errors.New("webdav: unsupported lock info")
+ errUnsupportedMethod = errors.New("webdav: unsupported method")
+)
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/webdav_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/webdav_test.go
new file mode 100644
index 000000000..25e0d5421
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/webdav_test.go
@@ -0,0 +1,344 @@
+// Copyright 2015 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 webdav
+
+import (
+ "errors"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "net/http"
+ "net/http/httptest"
+ "net/url"
+ "os"
+ "reflect"
+ "regexp"
+ "sort"
+ "strings"
+ "testing"
+
+ "golang.org/x/net/context"
+)
+
+// TODO: add tests to check XML responses with the expected prefix path
+func TestPrefix(t *testing.T) {
+ const dst, blah = "Destination", "blah blah blah"
+
+ // createLockBody comes from the example in Section 9.10.7.
+ const createLockBody = `<?xml version="1.0" encoding="utf-8" ?>
+ <D:lockinfo xmlns:D='DAV:'>
+ <D:lockscope><D:exclusive/></D:lockscope>
+ <D:locktype><D:write/></D:locktype>
+ <D:owner>
+ <D:href>http://example.org/~ejw/contact.html</D:href>
+ </D:owner>
+ </D:lockinfo>
+ `
+
+ do := func(method, urlStr string, body string, wantStatusCode int, headers ...string) (http.Header, error) {
+ var bodyReader io.Reader
+ if body != "" {
+ bodyReader = strings.NewReader(body)
+ }
+ req, err := http.NewRequest(method, urlStr, bodyReader)
+ if err != nil {
+ return nil, err
+ }
+ for len(headers) >= 2 {
+ req.Header.Add(headers[0], headers[1])
+ headers = headers[2:]
+ }
+ res, err := http.DefaultTransport.RoundTrip(req)
+ if err != nil {
+ return nil, err
+ }
+ defer res.Body.Close()
+ if res.StatusCode != wantStatusCode {
+ return nil, fmt.Errorf("got status code %d, want %d", res.StatusCode, wantStatusCode)
+ }
+ return res.Header, nil
+ }
+
+ prefixes := []string{
+ "/",
+ "/a/",
+ "/a/b/",
+ "/a/b/c/",
+ }
+ ctx := context.Background()
+ for _, prefix := range prefixes {
+ fs := NewMemFS()
+ h := &Handler{
+ FileSystem: fs,
+ LockSystem: NewMemLS(),
+ }
+ mux := http.NewServeMux()
+ if prefix != "/" {
+ h.Prefix = prefix
+ }
+ mux.Handle(prefix, h)
+ srv := httptest.NewServer(mux)
+ defer srv.Close()
+
+ // The script is:
+ // MKCOL /a
+ // MKCOL /a/b
+ // PUT /a/b/c
+ // COPY /a/b/c /a/b/d
+ // MKCOL /a/b/e
+ // MOVE /a/b/d /a/b/e/f
+ // LOCK /a/b/e/g
+ // PUT /a/b/e/g
+ // which should yield the (possibly stripped) filenames /a/b/c,
+ // /a/b/e/f and /a/b/e/g, plus their parent directories.
+
+ wantA := map[string]int{
+ "/": http.StatusCreated,
+ "/a/": http.StatusMovedPermanently,
+ "/a/b/": http.StatusNotFound,
+ "/a/b/c/": http.StatusNotFound,
+ }[prefix]
+ if _, err := do("MKCOL", srv.URL+"/a", "", wantA); err != nil {
+ t.Errorf("prefix=%-9q MKCOL /a: %v", prefix, err)
+ continue
+ }
+
+ wantB := map[string]int{
+ "/": http.StatusCreated,
+ "/a/": http.StatusCreated,
+ "/a/b/": http.StatusMovedPermanently,
+ "/a/b/c/": http.StatusNotFound,
+ }[prefix]
+ if _, err := do("MKCOL", srv.URL+"/a/b", "", wantB); err != nil {
+ t.Errorf("prefix=%-9q MKCOL /a/b: %v", prefix, err)
+ continue
+ }
+
+ wantC := map[string]int{
+ "/": http.StatusCreated,
+ "/a/": http.StatusCreated,
+ "/a/b/": http.StatusCreated,
+ "/a/b/c/": http.StatusMovedPermanently,
+ }[prefix]
+ if _, err := do("PUT", srv.URL+"/a/b/c", blah, wantC); err != nil {
+ t.Errorf("prefix=%-9q PUT /a/b/c: %v", prefix, err)
+ continue
+ }
+
+ wantD := map[string]int{
+ "/": http.StatusCreated,
+ "/a/": http.StatusCreated,
+ "/a/b/": http.StatusCreated,
+ "/a/b/c/": http.StatusMovedPermanently,
+ }[prefix]
+ if _, err := do("COPY", srv.URL+"/a/b/c", "", wantD, dst, srv.URL+"/a/b/d"); err != nil {
+ t.Errorf("prefix=%-9q COPY /a/b/c /a/b/d: %v", prefix, err)
+ continue
+ }
+
+ wantE := map[string]int{
+ "/": http.StatusCreated,
+ "/a/": http.StatusCreated,
+ "/a/b/": http.StatusCreated,
+ "/a/b/c/": http.StatusNotFound,
+ }[prefix]
+ if _, err := do("MKCOL", srv.URL+"/a/b/e", "", wantE); err != nil {
+ t.Errorf("prefix=%-9q MKCOL /a/b/e: %v", prefix, err)
+ continue
+ }
+
+ wantF := map[string]int{
+ "/": http.StatusCreated,
+ "/a/": http.StatusCreated,
+ "/a/b/": http.StatusCreated,
+ "/a/b/c/": http.StatusNotFound,
+ }[prefix]
+ if _, err := do("MOVE", srv.URL+"/a/b/d", "", wantF, dst, srv.URL+"/a/b/e/f"); err != nil {
+ t.Errorf("prefix=%-9q MOVE /a/b/d /a/b/e/f: %v", prefix, err)
+ continue
+ }
+
+ var lockToken string
+ wantG := map[string]int{
+ "/": http.StatusCreated,
+ "/a/": http.StatusCreated,
+ "/a/b/": http.StatusCreated,
+ "/a/b/c/": http.StatusNotFound,
+ }[prefix]
+ if h, err := do("LOCK", srv.URL+"/a/b/e/g", createLockBody, wantG); err != nil {
+ t.Errorf("prefix=%-9q LOCK /a/b/e/g: %v", prefix, err)
+ continue
+ } else {
+ lockToken = h.Get("Lock-Token")
+ }
+
+ ifHeader := fmt.Sprintf("<%s/a/b/e/g> (%s)", srv.URL, lockToken)
+ wantH := map[string]int{
+ "/": http.StatusCreated,
+ "/a/": http.StatusCreated,
+ "/a/b/": http.StatusCreated,
+ "/a/b/c/": http.StatusNotFound,
+ }[prefix]
+ if _, err := do("PUT", srv.URL+"/a/b/e/g", blah, wantH, "If", ifHeader); err != nil {
+ t.Errorf("prefix=%-9q PUT /a/b/e/g: %v", prefix, err)
+ continue
+ }
+
+ got, err := find(ctx, nil, fs, "/")
+ if err != nil {
+ t.Errorf("prefix=%-9q find: %v", prefix, err)
+ continue
+ }
+ sort.Strings(got)
+ want := map[string][]string{
+ "/": {"/", "/a", "/a/b", "/a/b/c", "/a/b/e", "/a/b/e/f", "/a/b/e/g"},
+ "/a/": {"/", "/b", "/b/c", "/b/e", "/b/e/f", "/b/e/g"},
+ "/a/b/": {"/", "/c", "/e", "/e/f", "/e/g"},
+ "/a/b/c/": {"/"},
+ }[prefix]
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("prefix=%-9q find:\ngot %v\nwant %v", prefix, got, want)
+ continue
+ }
+ }
+}
+
+func TestEscapeXML(t *testing.T) {
+ // These test cases aren't exhaustive, and there is more than one way to
+ // escape e.g. a quot (as "&#34;" or "&quot;") or an apos. We presume that
+ // the encoding/xml package tests xml.EscapeText more thoroughly. This test
+ // here is just a sanity check for this package's escapeXML function, and
+ // its attempt to provide a fast path (and avoid a bytes.Buffer allocation)
+ // when escaping filenames is obviously a no-op.
+ testCases := map[string]string{
+ "": "",
+ " ": " ",
+ "&": "&amp;",
+ "*": "*",
+ "+": "+",
+ ",": ",",
+ "-": "-",
+ ".": ".",
+ "/": "/",
+ "0": "0",
+ "9": "9",
+ ":": ":",
+ "<": "&lt;",
+ ">": "&gt;",
+ "A": "A",
+ "_": "_",
+ "a": "a",
+ "~": "~",
+ "\u0201": "\u0201",
+ "&amp;": "&amp;amp;",
+ "foo&<b/ar>baz": "foo&amp;&lt;b/ar&gt;baz",
+ }
+
+ for in, want := range testCases {
+ if got := escapeXML(in); got != want {
+ t.Errorf("in=%q: got %q, want %q", in, got, want)
+ }
+ }
+}
+
+func TestFilenameEscape(t *testing.T) {
+ hrefRe := regexp.MustCompile(`<D:href>([^<]*)</D:href>`)
+ displayNameRe := regexp.MustCompile(`<D:displayname>([^<]*)</D:displayname>`)
+ do := func(method, urlStr string) (string, string, error) {
+ req, err := http.NewRequest(method, urlStr, nil)
+ if err != nil {
+ return "", "", err
+ }
+ res, err := http.DefaultClient.Do(req)
+ if err != nil {
+ return "", "", err
+ }
+ defer res.Body.Close()
+
+ b, err := ioutil.ReadAll(res.Body)
+ if err != nil {
+ return "", "", err
+ }
+ hrefMatch := hrefRe.FindStringSubmatch(string(b))
+ if len(hrefMatch) != 2 {
+ return "", "", errors.New("D:href not found")
+ }
+ displayNameMatch := displayNameRe.FindStringSubmatch(string(b))
+ if len(displayNameMatch) != 2 {
+ return "", "", errors.New("D:displayname not found")
+ }
+
+ return hrefMatch[1], displayNameMatch[1], nil
+ }
+
+ testCases := []struct {
+ name, wantHref, wantDisplayName string
+ }{{
+ name: `/foo%bar`,
+ wantHref: `/foo%25bar`,
+ wantDisplayName: `foo%bar`,
+ }, {
+ name: `/こんにちわ世界`,
+ wantHref: `/%E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%82%8F%E4%B8%96%E7%95%8C`,
+ wantDisplayName: `こんにちわ世界`,
+ }, {
+ name: `/Program Files/`,
+ wantHref: `/Program%20Files`,
+ wantDisplayName: `Program Files`,
+ }, {
+ name: `/go+lang`,
+ wantHref: `/go+lang`,
+ wantDisplayName: `go+lang`,
+ }, {
+ name: `/go&lang`,
+ wantHref: `/go&amp;lang`,
+ wantDisplayName: `go&amp;lang`,
+ }, {
+ name: `/go<lang`,
+ wantHref: `/go%3Clang`,
+ wantDisplayName: `go&lt;lang`,
+ }}
+ ctx := context.Background()
+ fs := NewMemFS()
+ for _, tc := range testCases {
+ if strings.HasSuffix(tc.name, "/") {
+ if err := fs.Mkdir(ctx, tc.name, 0755); err != nil {
+ t.Fatalf("name=%q: Mkdir: %v", tc.name, err)
+ }
+ } else {
+ f, err := fs.OpenFile(ctx, tc.name, os.O_CREATE, 0644)
+ if err != nil {
+ t.Fatalf("name=%q: OpenFile: %v", tc.name, err)
+ }
+ f.Close()
+ }
+ }
+
+ srv := httptest.NewServer(&Handler{
+ FileSystem: fs,
+ LockSystem: NewMemLS(),
+ })
+ defer srv.Close()
+
+ u, err := url.Parse(srv.URL)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ for _, tc := range testCases {
+ u.Path = tc.name
+ gotHref, gotDisplayName, err := do("PROPFIND", u.String())
+ if err != nil {
+ t.Errorf("name=%q: PROPFIND: %v", tc.name, err)
+ continue
+ }
+ if gotHref != tc.wantHref {
+ t.Errorf("name=%q: got href %q, want %q", tc.name, gotHref, tc.wantHref)
+ }
+ if gotDisplayName != tc.wantDisplayName {
+ t.Errorf("name=%q: got dispayname %q, want %q", tc.name, gotDisplayName, tc.wantDisplayName)
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/xml.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/xml.go
new file mode 100644
index 000000000..790dc8169
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/xml.go
@@ -0,0 +1,519 @@
+// Copyright 2014 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 webdav
+
+// The XML encoding is covered by Section 14.
+// http://www.webdav.org/specs/rfc4918.html#xml.element.definitions
+
+import (
+ "bytes"
+ "encoding/xml"
+ "fmt"
+ "io"
+ "net/http"
+ "time"
+
+ // As of https://go-review.googlesource.com/#/c/12772/ which was submitted
+ // in July 2015, this package uses an internal fork of the standard
+ // library's encoding/xml package, due to changes in the way namespaces
+ // were encoded. Such changes were introduced in the Go 1.5 cycle, but were
+ // rolled back in response to https://github.com/golang/go/issues/11841
+ //
+ // However, this package's exported API, specifically the Property and
+ // DeadPropsHolder types, need to refer to the standard library's version
+ // of the xml.Name type, as code that imports this package cannot refer to
+ // the internal version.
+ //
+ // This file therefore imports both the internal and external versions, as
+ // ixml and xml, and converts between them.
+ //
+ // In the long term, this package should use the standard library's version
+ // only, and the internal fork deleted, once
+ // https://github.com/golang/go/issues/13400 is resolved.
+ ixml "golang.org/x/net/webdav/internal/xml"
+)
+
+// http://www.webdav.org/specs/rfc4918.html#ELEMENT_lockinfo
+type lockInfo struct {
+ XMLName ixml.Name `xml:"lockinfo"`
+ Exclusive *struct{} `xml:"lockscope>exclusive"`
+ Shared *struct{} `xml:"lockscope>shared"`
+ Write *struct{} `xml:"locktype>write"`
+ Owner owner `xml:"owner"`
+}
+
+// http://www.webdav.org/specs/rfc4918.html#ELEMENT_owner
+type owner struct {
+ InnerXML string `xml:",innerxml"`
+}
+
+func readLockInfo(r io.Reader) (li lockInfo, status int, err error) {
+ c := &countingReader{r: r}
+ if err = ixml.NewDecoder(c).Decode(&li); err != nil {
+ if err == io.EOF {
+ if c.n == 0 {
+ // An empty body means to refresh the lock.
+ // http://www.webdav.org/specs/rfc4918.html#refreshing-locks
+ return lockInfo{}, 0, nil
+ }
+ err = errInvalidLockInfo
+ }
+ return lockInfo{}, http.StatusBadRequest, err
+ }
+ // We only support exclusive (non-shared) write locks. In practice, these are
+ // the only types of locks that seem to matter.
+ if li.Exclusive == nil || li.Shared != nil || li.Write == nil {
+ return lockInfo{}, http.StatusNotImplemented, errUnsupportedLockInfo
+ }
+ return li, 0, nil
+}
+
+type countingReader struct {
+ n int
+ r io.Reader
+}
+
+func (c *countingReader) Read(p []byte) (int, error) {
+ n, err := c.r.Read(p)
+ c.n += n
+ return n, err
+}
+
+func writeLockInfo(w io.Writer, token string, ld LockDetails) (int, error) {
+ depth := "infinity"
+ if ld.ZeroDepth {
+ depth = "0"
+ }
+ timeout := ld.Duration / time.Second
+ return fmt.Fprintf(w, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"+
+ "<D:prop xmlns:D=\"DAV:\"><D:lockdiscovery><D:activelock>\n"+
+ " <D:locktype><D:write/></D:locktype>\n"+
+ " <D:lockscope><D:exclusive/></D:lockscope>\n"+
+ " <D:depth>%s</D:depth>\n"+
+ " <D:owner>%s</D:owner>\n"+
+ " <D:timeout>Second-%d</D:timeout>\n"+
+ " <D:locktoken><D:href>%s</D:href></D:locktoken>\n"+
+ " <D:lockroot><D:href>%s</D:href></D:lockroot>\n"+
+ "</D:activelock></D:lockdiscovery></D:prop>",
+ depth, ld.OwnerXML, timeout, escape(token), escape(ld.Root),
+ )
+}
+
+func escape(s string) string {
+ for i := 0; i < len(s); i++ {
+ switch s[i] {
+ case '"', '&', '\'', '<', '>':
+ b := bytes.NewBuffer(nil)
+ ixml.EscapeText(b, []byte(s))
+ return b.String()
+ }
+ }
+ return s
+}
+
+// Next returns the next token, if any, in the XML stream of d.
+// RFC 4918 requires to ignore comments, processing instructions
+// and directives.
+// http://www.webdav.org/specs/rfc4918.html#property_values
+// http://www.webdav.org/specs/rfc4918.html#xml-extensibility
+func next(d *ixml.Decoder) (ixml.Token, error) {
+ for {
+ t, err := d.Token()
+ if err != nil {
+ return t, err
+ }
+ switch t.(type) {
+ case ixml.Comment, ixml.Directive, ixml.ProcInst:
+ continue
+ default:
+ return t, nil
+ }
+ }
+}
+
+// http://www.webdav.org/specs/rfc4918.html#ELEMENT_prop (for propfind)
+type propfindProps []xml.Name
+
+// UnmarshalXML appends the property names enclosed within start to pn.
+//
+// It returns an error if start does not contain any properties or if
+// properties contain values. Character data between properties is ignored.
+func (pn *propfindProps) UnmarshalXML(d *ixml.Decoder, start ixml.StartElement) error {
+ for {
+ t, err := next(d)
+ if err != nil {
+ return err
+ }
+ switch t.(type) {
+ case ixml.EndElement:
+ if len(*pn) == 0 {
+ return fmt.Errorf("%s must not be empty", start.Name.Local)
+ }
+ return nil
+ case ixml.StartElement:
+ name := t.(ixml.StartElement).Name
+ t, err = next(d)
+ if err != nil {
+ return err
+ }
+ if _, ok := t.(ixml.EndElement); !ok {
+ return fmt.Errorf("unexpected token %T", t)
+ }
+ *pn = append(*pn, xml.Name(name))
+ }
+ }
+}
+
+// http://www.webdav.org/specs/rfc4918.html#ELEMENT_propfind
+type propfind struct {
+ XMLName ixml.Name `xml:"DAV: propfind"`
+ Allprop *struct{} `xml:"DAV: allprop"`
+ Propname *struct{} `xml:"DAV: propname"`
+ Prop propfindProps `xml:"DAV: prop"`
+ Include propfindProps `xml:"DAV: include"`
+}
+
+func readPropfind(r io.Reader) (pf propfind, status int, err error) {
+ c := countingReader{r: r}
+ if err = ixml.NewDecoder(&c).Decode(&pf); err != nil {
+ if err == io.EOF {
+ if c.n == 0 {
+ // An empty body means to propfind allprop.
+ // http://www.webdav.org/specs/rfc4918.html#METHOD_PROPFIND
+ return propfind{Allprop: new(struct{})}, 0, nil
+ }
+ err = errInvalidPropfind
+ }
+ return propfind{}, http.StatusBadRequest, err
+ }
+
+ if pf.Allprop == nil && pf.Include != nil {
+ return propfind{}, http.StatusBadRequest, errInvalidPropfind
+ }
+ if pf.Allprop != nil && (pf.Prop != nil || pf.Propname != nil) {
+ return propfind{}, http.StatusBadRequest, errInvalidPropfind
+ }
+ if pf.Prop != nil && pf.Propname != nil {
+ return propfind{}, http.StatusBadRequest, errInvalidPropfind
+ }
+ if pf.Propname == nil && pf.Allprop == nil && pf.Prop == nil {
+ return propfind{}, http.StatusBadRequest, errInvalidPropfind
+ }
+ return pf, 0, nil
+}
+
+// Property represents a single DAV resource property as defined in RFC 4918.
+// See http://www.webdav.org/specs/rfc4918.html#data.model.for.resource.properties
+type Property struct {
+ // XMLName is the fully qualified name that identifies this property.
+ XMLName xml.Name
+
+ // Lang is an optional xml:lang attribute.
+ Lang string `xml:"xml:lang,attr,omitempty"`
+
+ // InnerXML contains the XML representation of the property value.
+ // See http://www.webdav.org/specs/rfc4918.html#property_values
+ //
+ // Property values of complex type or mixed-content must have fully
+ // expanded XML namespaces or be self-contained with according
+ // XML namespace declarations. They must not rely on any XML
+ // namespace declarations within the scope of the XML document,
+ // even including the DAV: namespace.
+ InnerXML []byte `xml:",innerxml"`
+}
+
+// ixmlProperty is the same as the Property type except it holds an ixml.Name
+// instead of an xml.Name.
+type ixmlProperty struct {
+ XMLName ixml.Name
+ Lang string `xml:"xml:lang,attr,omitempty"`
+ InnerXML []byte `xml:",innerxml"`
+}
+
+// http://www.webdav.org/specs/rfc4918.html#ELEMENT_error
+// See multistatusWriter for the "D:" namespace prefix.
+type xmlError struct {
+ XMLName ixml.Name `xml:"D:error"`
+ InnerXML []byte `xml:",innerxml"`
+}
+
+// http://www.webdav.org/specs/rfc4918.html#ELEMENT_propstat
+// See multistatusWriter for the "D:" namespace prefix.
+type propstat struct {
+ Prop []Property `xml:"D:prop>_ignored_"`
+ Status string `xml:"D:status"`
+ Error *xmlError `xml:"D:error"`
+ ResponseDescription string `xml:"D:responsedescription,omitempty"`
+}
+
+// ixmlPropstat is the same as the propstat type except it holds an ixml.Name
+// instead of an xml.Name.
+type ixmlPropstat struct {
+ Prop []ixmlProperty `xml:"D:prop>_ignored_"`
+ Status string `xml:"D:status"`
+ Error *xmlError `xml:"D:error"`
+ ResponseDescription string `xml:"D:responsedescription,omitempty"`
+}
+
+// MarshalXML prepends the "D:" namespace prefix on properties in the DAV: namespace
+// before encoding. See multistatusWriter.
+func (ps propstat) MarshalXML(e *ixml.Encoder, start ixml.StartElement) error {
+ // Convert from a propstat to an ixmlPropstat.
+ ixmlPs := ixmlPropstat{
+ Prop: make([]ixmlProperty, len(ps.Prop)),
+ Status: ps.Status,
+ Error: ps.Error,
+ ResponseDescription: ps.ResponseDescription,
+ }
+ for k, prop := range ps.Prop {
+ ixmlPs.Prop[k] = ixmlProperty{
+ XMLName: ixml.Name(prop.XMLName),
+ Lang: prop.Lang,
+ InnerXML: prop.InnerXML,
+ }
+ }
+
+ for k, prop := range ixmlPs.Prop {
+ if prop.XMLName.Space == "DAV:" {
+ prop.XMLName = ixml.Name{Space: "", Local: "D:" + prop.XMLName.Local}
+ ixmlPs.Prop[k] = prop
+ }
+ }
+ // Distinct type to avoid infinite recursion of MarshalXML.
+ type newpropstat ixmlPropstat
+ return e.EncodeElement(newpropstat(ixmlPs), start)
+}
+
+// http://www.webdav.org/specs/rfc4918.html#ELEMENT_response
+// See multistatusWriter for the "D:" namespace prefix.
+type response struct {
+ XMLName ixml.Name `xml:"D:response"`
+ Href []string `xml:"D:href"`
+ Propstat []propstat `xml:"D:propstat"`
+ Status string `xml:"D:status,omitempty"`
+ Error *xmlError `xml:"D:error"`
+ ResponseDescription string `xml:"D:responsedescription,omitempty"`
+}
+
+// MultistatusWriter marshals one or more Responses into a XML
+// multistatus response.
+// See http://www.webdav.org/specs/rfc4918.html#ELEMENT_multistatus
+// TODO(rsto, mpl): As a workaround, the "D:" namespace prefix, defined as
+// "DAV:" on this element, is prepended on the nested response, as well as on all
+// its nested elements. All property names in the DAV: namespace are prefixed as
+// well. This is because some versions of Mini-Redirector (on windows 7) ignore
+// elements with a default namespace (no prefixed namespace). A less intrusive fix
+// should be possible after golang.org/cl/11074. See https://golang.org/issue/11177
+type multistatusWriter struct {
+ // ResponseDescription contains the optional responsedescription
+ // of the multistatus XML element. Only the latest content before
+ // close will be emitted. Empty response descriptions are not
+ // written.
+ responseDescription string
+
+ w http.ResponseWriter
+ enc *ixml.Encoder
+}
+
+// Write validates and emits a DAV response as part of a multistatus response
+// element.
+//
+// It sets the HTTP status code of its underlying http.ResponseWriter to 207
+// (Multi-Status) and populates the Content-Type header. If r is the
+// first, valid response to be written, Write prepends the XML representation
+// of r with a multistatus tag. Callers must call close after the last response
+// has been written.
+func (w *multistatusWriter) write(r *response) error {
+ switch len(r.Href) {
+ case 0:
+ return errInvalidResponse
+ case 1:
+ if len(r.Propstat) > 0 != (r.Status == "") {
+ return errInvalidResponse
+ }
+ default:
+ if len(r.Propstat) > 0 || r.Status == "" {
+ return errInvalidResponse
+ }
+ }
+ err := w.writeHeader()
+ if err != nil {
+ return err
+ }
+ return w.enc.Encode(r)
+}
+
+// writeHeader writes a XML multistatus start element on w's underlying
+// http.ResponseWriter and returns the result of the write operation.
+// After the first write attempt, writeHeader becomes a no-op.
+func (w *multistatusWriter) writeHeader() error {
+ if w.enc != nil {
+ return nil
+ }
+ w.w.Header().Add("Content-Type", "text/xml; charset=utf-8")
+ w.w.WriteHeader(StatusMulti)
+ _, err := fmt.Fprintf(w.w, `<?xml version="1.0" encoding="UTF-8"?>`)
+ if err != nil {
+ return err
+ }
+ w.enc = ixml.NewEncoder(w.w)
+ return w.enc.EncodeToken(ixml.StartElement{
+ Name: ixml.Name{
+ Space: "DAV:",
+ Local: "multistatus",
+ },
+ Attr: []ixml.Attr{{
+ Name: ixml.Name{Space: "xmlns", Local: "D"},
+ Value: "DAV:",
+ }},
+ })
+}
+
+// Close completes the marshalling of the multistatus response. It returns
+// an error if the multistatus response could not be completed. If both the
+// return value and field enc of w are nil, then no multistatus response has
+// been written.
+func (w *multistatusWriter) close() error {
+ if w.enc == nil {
+ return nil
+ }
+ var end []ixml.Token
+ if w.responseDescription != "" {
+ name := ixml.Name{Space: "DAV:", Local: "responsedescription"}
+ end = append(end,
+ ixml.StartElement{Name: name},
+ ixml.CharData(w.responseDescription),
+ ixml.EndElement{Name: name},
+ )
+ }
+ end = append(end, ixml.EndElement{
+ Name: ixml.Name{Space: "DAV:", Local: "multistatus"},
+ })
+ for _, t := range end {
+ err := w.enc.EncodeToken(t)
+ if err != nil {
+ return err
+ }
+ }
+ return w.enc.Flush()
+}
+
+var xmlLangName = ixml.Name{Space: "http://www.w3.org/XML/1998/namespace", Local: "lang"}
+
+func xmlLang(s ixml.StartElement, d string) string {
+ for _, attr := range s.Attr {
+ if attr.Name == xmlLangName {
+ return attr.Value
+ }
+ }
+ return d
+}
+
+type xmlValue []byte
+
+func (v *xmlValue) UnmarshalXML(d *ixml.Decoder, start ixml.StartElement) error {
+ // The XML value of a property can be arbitrary, mixed-content XML.
+ // To make sure that the unmarshalled value contains all required
+ // namespaces, we encode all the property value XML tokens into a
+ // buffer. This forces the encoder to redeclare any used namespaces.
+ var b bytes.Buffer
+ e := ixml.NewEncoder(&b)
+ for {
+ t, err := next(d)
+ if err != nil {
+ return err
+ }
+ if e, ok := t.(ixml.EndElement); ok && e.Name == start.Name {
+ break
+ }
+ if err = e.EncodeToken(t); err != nil {
+ return err
+ }
+ }
+ err := e.Flush()
+ if err != nil {
+ return err
+ }
+ *v = b.Bytes()
+ return nil
+}
+
+// http://www.webdav.org/specs/rfc4918.html#ELEMENT_prop (for proppatch)
+type proppatchProps []Property
+
+// UnmarshalXML appends the property names and values enclosed within start
+// to ps.
+//
+// An xml:lang attribute that is defined either on the DAV:prop or property
+// name XML element is propagated to the property's Lang field.
+//
+// UnmarshalXML returns an error if start does not contain any properties or if
+// property values contain syntactically incorrect XML.
+func (ps *proppatchProps) UnmarshalXML(d *ixml.Decoder, start ixml.StartElement) error {
+ lang := xmlLang(start, "")
+ for {
+ t, err := next(d)
+ if err != nil {
+ return err
+ }
+ switch elem := t.(type) {
+ case ixml.EndElement:
+ if len(*ps) == 0 {
+ return fmt.Errorf("%s must not be empty", start.Name.Local)
+ }
+ return nil
+ case ixml.StartElement:
+ p := Property{
+ XMLName: xml.Name(t.(ixml.StartElement).Name),
+ Lang: xmlLang(t.(ixml.StartElement), lang),
+ }
+ err = d.DecodeElement(((*xmlValue)(&p.InnerXML)), &elem)
+ if err != nil {
+ return err
+ }
+ *ps = append(*ps, p)
+ }
+ }
+}
+
+// http://www.webdav.org/specs/rfc4918.html#ELEMENT_set
+// http://www.webdav.org/specs/rfc4918.html#ELEMENT_remove
+type setRemove struct {
+ XMLName ixml.Name
+ Lang string `xml:"xml:lang,attr,omitempty"`
+ Prop proppatchProps `xml:"DAV: prop"`
+}
+
+// http://www.webdav.org/specs/rfc4918.html#ELEMENT_propertyupdate
+type propertyupdate struct {
+ XMLName ixml.Name `xml:"DAV: propertyupdate"`
+ Lang string `xml:"xml:lang,attr,omitempty"`
+ SetRemove []setRemove `xml:",any"`
+}
+
+func readProppatch(r io.Reader) (patches []Proppatch, status int, err error) {
+ var pu propertyupdate
+ if err = ixml.NewDecoder(r).Decode(&pu); err != nil {
+ return nil, http.StatusBadRequest, err
+ }
+ for _, op := range pu.SetRemove {
+ remove := false
+ switch op.XMLName {
+ case ixml.Name{Space: "DAV:", Local: "set"}:
+ // No-op.
+ case ixml.Name{Space: "DAV:", Local: "remove"}:
+ for _, p := range op.Prop {
+ if len(p.InnerXML) > 0 {
+ return nil, http.StatusBadRequest, errInvalidProppatch
+ }
+ }
+ remove = true
+ default:
+ return nil, http.StatusBadRequest, errInvalidProppatch
+ }
+ patches = append(patches, Proppatch{Remove: remove, Props: op.Prop})
+ }
+ return patches, 0, nil
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/xml_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/xml_test.go
new file mode 100644
index 000000000..a3d9e1ed8
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/webdav/xml_test.go
@@ -0,0 +1,906 @@
+// Copyright 2014 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 webdav
+
+import (
+ "bytes"
+ "encoding/xml"
+ "fmt"
+ "io"
+ "net/http"
+ "net/http/httptest"
+ "reflect"
+ "sort"
+ "strings"
+ "testing"
+
+ ixml "golang.org/x/net/webdav/internal/xml"
+)
+
+func TestReadLockInfo(t *testing.T) {
+ // The "section x.y.z" test cases come from section x.y.z of the spec at
+ // http://www.webdav.org/specs/rfc4918.html
+ testCases := []struct {
+ desc string
+ input string
+ wantLI lockInfo
+ wantStatus int
+ }{{
+ "bad: junk",
+ "xxx",
+ lockInfo{},
+ http.StatusBadRequest,
+ }, {
+ "bad: invalid owner XML",
+ "" +
+ "<D:lockinfo xmlns:D='DAV:'>\n" +
+ " <D:lockscope><D:exclusive/></D:lockscope>\n" +
+ " <D:locktype><D:write/></D:locktype>\n" +
+ " <D:owner>\n" +
+ " <D:href> no end tag \n" +
+ " </D:owner>\n" +
+ "</D:lockinfo>",
+ lockInfo{},
+ http.StatusBadRequest,
+ }, {
+ "bad: invalid UTF-8",
+ "" +
+ "<D:lockinfo xmlns:D='DAV:'>\n" +
+ " <D:lockscope><D:exclusive/></D:lockscope>\n" +
+ " <D:locktype><D:write/></D:locktype>\n" +
+ " <D:owner>\n" +
+ " <D:href> \xff </D:href>\n" +
+ " </D:owner>\n" +
+ "</D:lockinfo>",
+ lockInfo{},
+ http.StatusBadRequest,
+ }, {
+ "bad: unfinished XML #1",
+ "" +
+ "<D:lockinfo xmlns:D='DAV:'>\n" +
+ " <D:lockscope><D:exclusive/></D:lockscope>\n" +
+ " <D:locktype><D:write/></D:locktype>\n",
+ lockInfo{},
+ http.StatusBadRequest,
+ }, {
+ "bad: unfinished XML #2",
+ "" +
+ "<D:lockinfo xmlns:D='DAV:'>\n" +
+ " <D:lockscope><D:exclusive/></D:lockscope>\n" +
+ " <D:locktype><D:write/></D:locktype>\n" +
+ " <D:owner>\n",
+ lockInfo{},
+ http.StatusBadRequest,
+ }, {
+ "good: empty",
+ "",
+ lockInfo{},
+ 0,
+ }, {
+ "good: plain-text owner",
+ "" +
+ "<D:lockinfo xmlns:D='DAV:'>\n" +
+ " <D:lockscope><D:exclusive/></D:lockscope>\n" +
+ " <D:locktype><D:write/></D:locktype>\n" +
+ " <D:owner>gopher</D:owner>\n" +
+ "</D:lockinfo>",
+ lockInfo{
+ XMLName: ixml.Name{Space: "DAV:", Local: "lockinfo"},
+ Exclusive: new(struct{}),
+ Write: new(struct{}),
+ Owner: owner{
+ InnerXML: "gopher",
+ },
+ },
+ 0,
+ }, {
+ "section 9.10.7",
+ "" +
+ "<D:lockinfo xmlns:D='DAV:'>\n" +
+ " <D:lockscope><D:exclusive/></D:lockscope>\n" +
+ " <D:locktype><D:write/></D:locktype>\n" +
+ " <D:owner>\n" +
+ " <D:href>http://example.org/~ejw/contact.html</D:href>\n" +
+ " </D:owner>\n" +
+ "</D:lockinfo>",
+ lockInfo{
+ XMLName: ixml.Name{Space: "DAV:", Local: "lockinfo"},
+ Exclusive: new(struct{}),
+ Write: new(struct{}),
+ Owner: owner{
+ InnerXML: "\n <D:href>http://example.org/~ejw/contact.html</D:href>\n ",
+ },
+ },
+ 0,
+ }}
+
+ for _, tc := range testCases {
+ li, status, err := readLockInfo(strings.NewReader(tc.input))
+ if tc.wantStatus != 0 {
+ if err == nil {
+ t.Errorf("%s: got nil error, want non-nil", tc.desc)
+ continue
+ }
+ } else if err != nil {
+ t.Errorf("%s: %v", tc.desc, err)
+ continue
+ }
+ if !reflect.DeepEqual(li, tc.wantLI) || status != tc.wantStatus {
+ t.Errorf("%s:\ngot lockInfo=%v, status=%v\nwant lockInfo=%v, status=%v",
+ tc.desc, li, status, tc.wantLI, tc.wantStatus)
+ continue
+ }
+ }
+}
+
+func TestReadPropfind(t *testing.T) {
+ testCases := []struct {
+ desc string
+ input string
+ wantPF propfind
+ wantStatus int
+ }{{
+ desc: "propfind: propname",
+ input: "" +
+ "<A:propfind xmlns:A='DAV:'>\n" +
+ " <A:propname/>\n" +
+ "</A:propfind>",
+ wantPF: propfind{
+ XMLName: ixml.Name{Space: "DAV:", Local: "propfind"},
+ Propname: new(struct{}),
+ },
+ }, {
+ desc: "propfind: empty body means allprop",
+ input: "",
+ wantPF: propfind{
+ Allprop: new(struct{}),
+ },
+ }, {
+ desc: "propfind: allprop",
+ input: "" +
+ "<A:propfind xmlns:A='DAV:'>\n" +
+ " <A:allprop/>\n" +
+ "</A:propfind>",
+ wantPF: propfind{
+ XMLName: ixml.Name{Space: "DAV:", Local: "propfind"},
+ Allprop: new(struct{}),
+ },
+ }, {
+ desc: "propfind: allprop followed by include",
+ input: "" +
+ "<A:propfind xmlns:A='DAV:'>\n" +
+ " <A:allprop/>\n" +
+ " <A:include><A:displayname/></A:include>\n" +
+ "</A:propfind>",
+ wantPF: propfind{
+ XMLName: ixml.Name{Space: "DAV:", Local: "propfind"},
+ Allprop: new(struct{}),
+ Include: propfindProps{xml.Name{Space: "DAV:", Local: "displayname"}},
+ },
+ }, {
+ desc: "propfind: include followed by allprop",
+ input: "" +
+ "<A:propfind xmlns:A='DAV:'>\n" +
+ " <A:include><A:displayname/></A:include>\n" +
+ " <A:allprop/>\n" +
+ "</A:propfind>",
+ wantPF: propfind{
+ XMLName: ixml.Name{Space: "DAV:", Local: "propfind"},
+ Allprop: new(struct{}),
+ Include: propfindProps{xml.Name{Space: "DAV:", Local: "displayname"}},
+ },
+ }, {
+ desc: "propfind: propfind",
+ input: "" +
+ "<A:propfind xmlns:A='DAV:'>\n" +
+ " <A:prop><A:displayname/></A:prop>\n" +
+ "</A:propfind>",
+ wantPF: propfind{
+ XMLName: ixml.Name{Space: "DAV:", Local: "propfind"},
+ Prop: propfindProps{xml.Name{Space: "DAV:", Local: "displayname"}},
+ },
+ }, {
+ desc: "propfind: prop with ignored comments",
+ input: "" +
+ "<A:propfind xmlns:A='DAV:'>\n" +
+ " <A:prop>\n" +
+ " <!-- ignore -->\n" +
+ " <A:displayname><!-- ignore --></A:displayname>\n" +
+ " </A:prop>\n" +
+ "</A:propfind>",
+ wantPF: propfind{
+ XMLName: ixml.Name{Space: "DAV:", Local: "propfind"},
+ Prop: propfindProps{xml.Name{Space: "DAV:", Local: "displayname"}},
+ },
+ }, {
+ desc: "propfind: propfind with ignored whitespace",
+ input: "" +
+ "<A:propfind xmlns:A='DAV:'>\n" +
+ " <A:prop> <A:displayname/></A:prop>\n" +
+ "</A:propfind>",
+ wantPF: propfind{
+ XMLName: ixml.Name{Space: "DAV:", Local: "propfind"},
+ Prop: propfindProps{xml.Name{Space: "DAV:", Local: "displayname"}},
+ },
+ }, {
+ desc: "propfind: propfind with ignored mixed-content",
+ input: "" +
+ "<A:propfind xmlns:A='DAV:'>\n" +
+ " <A:prop>foo<A:displayname/>bar</A:prop>\n" +
+ "</A:propfind>",
+ wantPF: propfind{
+ XMLName: ixml.Name{Space: "DAV:", Local: "propfind"},
+ Prop: propfindProps{xml.Name{Space: "DAV:", Local: "displayname"}},
+ },
+ }, {
+ desc: "propfind: propname with ignored element (section A.4)",
+ input: "" +
+ "<A:propfind xmlns:A='DAV:'>\n" +
+ " <A:propname/>\n" +
+ " <E:leave-out xmlns:E='E:'>*boss*</E:leave-out>\n" +
+ "</A:propfind>",
+ wantPF: propfind{
+ XMLName: ixml.Name{Space: "DAV:", Local: "propfind"},
+ Propname: new(struct{}),
+ },
+ }, {
+ desc: "propfind: bad: junk",
+ input: "xxx",
+ wantStatus: http.StatusBadRequest,
+ }, {
+ desc: "propfind: bad: propname and allprop (section A.3)",
+ input: "" +
+ "<A:propfind xmlns:A='DAV:'>\n" +
+ " <A:propname/>" +
+ " <A:allprop/>" +
+ "</A:propfind>",
+ wantStatus: http.StatusBadRequest,
+ }, {
+ desc: "propfind: bad: propname and prop",
+ input: "" +
+ "<A:propfind xmlns:A='DAV:'>\n" +
+ " <A:prop><A:displayname/></A:prop>\n" +
+ " <A:propname/>\n" +
+ "</A:propfind>",
+ wantStatus: http.StatusBadRequest,
+ }, {
+ desc: "propfind: bad: allprop and prop",
+ input: "" +
+ "<A:propfind xmlns:A='DAV:'>\n" +
+ " <A:allprop/>\n" +
+ " <A:prop><A:foo/><A:/prop>\n" +
+ "</A:propfind>",
+ wantStatus: http.StatusBadRequest,
+ }, {
+ desc: "propfind: bad: empty propfind with ignored element (section A.4)",
+ input: "" +
+ "<A:propfind xmlns:A='DAV:'>\n" +
+ " <E:expired-props/>\n" +
+ "</A:propfind>",
+ wantStatus: http.StatusBadRequest,
+ }, {
+ desc: "propfind: bad: empty prop",
+ input: "" +
+ "<A:propfind xmlns:A='DAV:'>\n" +
+ " <A:prop/>\n" +
+ "</A:propfind>",
+ wantStatus: http.StatusBadRequest,
+ }, {
+ desc: "propfind: bad: prop with just chardata",
+ input: "" +
+ "<A:propfind xmlns:A='DAV:'>\n" +
+ " <A:prop>foo</A:prop>\n" +
+ "</A:propfind>",
+ wantStatus: http.StatusBadRequest,
+ }, {
+ desc: "bad: interrupted prop",
+ input: "" +
+ "<A:propfind xmlns:A='DAV:'>\n" +
+ " <A:prop><A:foo></A:prop>\n",
+ wantStatus: http.StatusBadRequest,
+ }, {
+ desc: "bad: malformed end element prop",
+ input: "" +
+ "<A:propfind xmlns:A='DAV:'>\n" +
+ " <A:prop><A:foo/></A:bar></A:prop>\n",
+ wantStatus: http.StatusBadRequest,
+ }, {
+ desc: "propfind: bad: property with chardata value",
+ input: "" +
+ "<A:propfind xmlns:A='DAV:'>\n" +
+ " <A:prop><A:foo>bar</A:foo></A:prop>\n" +
+ "</A:propfind>",
+ wantStatus: http.StatusBadRequest,
+ }, {
+ desc: "propfind: bad: property with whitespace value",
+ input: "" +
+ "<A:propfind xmlns:A='DAV:'>\n" +
+ " <A:prop><A:foo> </A:foo></A:prop>\n" +
+ "</A:propfind>",
+ wantStatus: http.StatusBadRequest,
+ }, {
+ desc: "propfind: bad: include without allprop",
+ input: "" +
+ "<A:propfind xmlns:A='DAV:'>\n" +
+ " <A:include><A:foo/></A:include>\n" +
+ "</A:propfind>",
+ wantStatus: http.StatusBadRequest,
+ }}
+
+ for _, tc := range testCases {
+ pf, status, err := readPropfind(strings.NewReader(tc.input))
+ if tc.wantStatus != 0 {
+ if err == nil {
+ t.Errorf("%s: got nil error, want non-nil", tc.desc)
+ continue
+ }
+ } else if err != nil {
+ t.Errorf("%s: %v", tc.desc, err)
+ continue
+ }
+ if !reflect.DeepEqual(pf, tc.wantPF) || status != tc.wantStatus {
+ t.Errorf("%s:\ngot propfind=%v, status=%v\nwant propfind=%v, status=%v",
+ tc.desc, pf, status, tc.wantPF, tc.wantStatus)
+ continue
+ }
+ }
+}
+
+func TestMultistatusWriter(t *testing.T) {
+ ///The "section x.y.z" test cases come from section x.y.z of the spec at
+ // http://www.webdav.org/specs/rfc4918.html
+ testCases := []struct {
+ desc string
+ responses []response
+ respdesc string
+ writeHeader bool
+ wantXML string
+ wantCode int
+ wantErr error
+ }{{
+ desc: "section 9.2.2 (failed dependency)",
+ responses: []response{{
+ Href: []string{"http://example.com/foo"},
+ Propstat: []propstat{{
+ Prop: []Property{{
+ XMLName: xml.Name{
+ Space: "http://ns.example.com/",
+ Local: "Authors",
+ },
+ }},
+ Status: "HTTP/1.1 424 Failed Dependency",
+ }, {
+ Prop: []Property{{
+ XMLName: xml.Name{
+ Space: "http://ns.example.com/",
+ Local: "Copyright-Owner",
+ },
+ }},
+ Status: "HTTP/1.1 409 Conflict",
+ }},
+ ResponseDescription: "Copyright Owner cannot be deleted or altered.",
+ }},
+ wantXML: `` +
+ `<?xml version="1.0" encoding="UTF-8"?>` +
+ `<multistatus xmlns="DAV:">` +
+ ` <response>` +
+ ` <href>http://example.com/foo</href>` +
+ ` <propstat>` +
+ ` <prop>` +
+ ` <Authors xmlns="http://ns.example.com/"></Authors>` +
+ ` </prop>` +
+ ` <status>HTTP/1.1 424 Failed Dependency</status>` +
+ ` </propstat>` +
+ ` <propstat xmlns="DAV:">` +
+ ` <prop>` +
+ ` <Copyright-Owner xmlns="http://ns.example.com/"></Copyright-Owner>` +
+ ` </prop>` +
+ ` <status>HTTP/1.1 409 Conflict</status>` +
+ ` </propstat>` +
+ ` <responsedescription>Copyright Owner cannot be deleted or altered.</responsedescription>` +
+ `</response>` +
+ `</multistatus>`,
+ wantCode: StatusMulti,
+ }, {
+ desc: "section 9.6.2 (lock-token-submitted)",
+ responses: []response{{
+ Href: []string{"http://example.com/foo"},
+ Status: "HTTP/1.1 423 Locked",
+ Error: &xmlError{
+ InnerXML: []byte(`<lock-token-submitted xmlns="DAV:"/>`),
+ },
+ }},
+ wantXML: `` +
+ `<?xml version="1.0" encoding="UTF-8"?>` +
+ `<multistatus xmlns="DAV:">` +
+ ` <response>` +
+ ` <href>http://example.com/foo</href>` +
+ ` <status>HTTP/1.1 423 Locked</status>` +
+ ` <error><lock-token-submitted xmlns="DAV:"/></error>` +
+ ` </response>` +
+ `</multistatus>`,
+ wantCode: StatusMulti,
+ }, {
+ desc: "section 9.1.3",
+ responses: []response{{
+ Href: []string{"http://example.com/foo"},
+ Propstat: []propstat{{
+ Prop: []Property{{
+ XMLName: xml.Name{Space: "http://ns.example.com/boxschema/", Local: "bigbox"},
+ InnerXML: []byte(`` +
+ `<BoxType xmlns="http://ns.example.com/boxschema/">` +
+ `Box type A` +
+ `</BoxType>`),
+ }, {
+ XMLName: xml.Name{Space: "http://ns.example.com/boxschema/", Local: "author"},
+ InnerXML: []byte(`` +
+ `<Name xmlns="http://ns.example.com/boxschema/">` +
+ `J.J. Johnson` +
+ `</Name>`),
+ }},
+ Status: "HTTP/1.1 200 OK",
+ }, {
+ Prop: []Property{{
+ XMLName: xml.Name{Space: "http://ns.example.com/boxschema/", Local: "DingALing"},
+ }, {
+ XMLName: xml.Name{Space: "http://ns.example.com/boxschema/", Local: "Random"},
+ }},
+ Status: "HTTP/1.1 403 Forbidden",
+ ResponseDescription: "The user does not have access to the DingALing property.",
+ }},
+ }},
+ respdesc: "There has been an access violation error.",
+ wantXML: `` +
+ `<?xml version="1.0" encoding="UTF-8"?>` +
+ `<multistatus xmlns="DAV:" xmlns:B="http://ns.example.com/boxschema/">` +
+ ` <response>` +
+ ` <href>http://example.com/foo</href>` +
+ ` <propstat>` +
+ ` <prop>` +
+ ` <B:bigbox><B:BoxType>Box type A</B:BoxType></B:bigbox>` +
+ ` <B:author><B:Name>J.J. Johnson</B:Name></B:author>` +
+ ` </prop>` +
+ ` <status>HTTP/1.1 200 OK</status>` +
+ ` </propstat>` +
+ ` <propstat>` +
+ ` <prop>` +
+ ` <B:DingALing/>` +
+ ` <B:Random/>` +
+ ` </prop>` +
+ ` <status>HTTP/1.1 403 Forbidden</status>` +
+ ` <responsedescription>The user does not have access to the DingALing property.</responsedescription>` +
+ ` </propstat>` +
+ ` </response>` +
+ ` <responsedescription>There has been an access violation error.</responsedescription>` +
+ `</multistatus>`,
+ wantCode: StatusMulti,
+ }, {
+ desc: "no response written",
+ // default of http.responseWriter
+ wantCode: http.StatusOK,
+ }, {
+ desc: "no response written (with description)",
+ respdesc: "too bad",
+ // default of http.responseWriter
+ wantCode: http.StatusOK,
+ }, {
+ desc: "empty multistatus with header",
+ writeHeader: true,
+ wantXML: `<multistatus xmlns="DAV:"></multistatus>`,
+ wantCode: StatusMulti,
+ }, {
+ desc: "bad: no href",
+ responses: []response{{
+ Propstat: []propstat{{
+ Prop: []Property{{
+ XMLName: xml.Name{
+ Space: "http://example.com/",
+ Local: "foo",
+ },
+ }},
+ Status: "HTTP/1.1 200 OK",
+ }},
+ }},
+ wantErr: errInvalidResponse,
+ // default of http.responseWriter
+ wantCode: http.StatusOK,
+ }, {
+ desc: "bad: multiple hrefs and no status",
+ responses: []response{{
+ Href: []string{"http://example.com/foo", "http://example.com/bar"},
+ }},
+ wantErr: errInvalidResponse,
+ // default of http.responseWriter
+ wantCode: http.StatusOK,
+ }, {
+ desc: "bad: one href and no propstat",
+ responses: []response{{
+ Href: []string{"http://example.com/foo"},
+ }},
+ wantErr: errInvalidResponse,
+ // default of http.responseWriter
+ wantCode: http.StatusOK,
+ }, {
+ desc: "bad: status with one href and propstat",
+ responses: []response{{
+ Href: []string{"http://example.com/foo"},
+ Propstat: []propstat{{
+ Prop: []Property{{
+ XMLName: xml.Name{
+ Space: "http://example.com/",
+ Local: "foo",
+ },
+ }},
+ Status: "HTTP/1.1 200 OK",
+ }},
+ Status: "HTTP/1.1 200 OK",
+ }},
+ wantErr: errInvalidResponse,
+ // default of http.responseWriter
+ wantCode: http.StatusOK,
+ }, {
+ desc: "bad: multiple hrefs and propstat",
+ responses: []response{{
+ Href: []string{
+ "http://example.com/foo",
+ "http://example.com/bar",
+ },
+ Propstat: []propstat{{
+ Prop: []Property{{
+ XMLName: xml.Name{
+ Space: "http://example.com/",
+ Local: "foo",
+ },
+ }},
+ Status: "HTTP/1.1 200 OK",
+ }},
+ }},
+ wantErr: errInvalidResponse,
+ // default of http.responseWriter
+ wantCode: http.StatusOK,
+ }}
+
+ n := xmlNormalizer{omitWhitespace: true}
+loop:
+ for _, tc := range testCases {
+ rec := httptest.NewRecorder()
+ w := multistatusWriter{w: rec, responseDescription: tc.respdesc}
+ if tc.writeHeader {
+ if err := w.writeHeader(); err != nil {
+ t.Errorf("%s: got writeHeader error %v, want nil", tc.desc, err)
+ continue
+ }
+ }
+ for _, r := range tc.responses {
+ if err := w.write(&r); err != nil {
+ if err != tc.wantErr {
+ t.Errorf("%s: got write error %v, want %v",
+ tc.desc, err, tc.wantErr)
+ }
+ continue loop
+ }
+ }
+ if err := w.close(); err != tc.wantErr {
+ t.Errorf("%s: got close error %v, want %v",
+ tc.desc, err, tc.wantErr)
+ continue
+ }
+ if rec.Code != tc.wantCode {
+ t.Errorf("%s: got HTTP status code %d, want %d\n",
+ tc.desc, rec.Code, tc.wantCode)
+ continue
+ }
+ gotXML := rec.Body.String()
+ eq, err := n.equalXML(strings.NewReader(gotXML), strings.NewReader(tc.wantXML))
+ if err != nil {
+ t.Errorf("%s: equalXML: %v", tc.desc, err)
+ continue
+ }
+ if !eq {
+ t.Errorf("%s: XML body\ngot %s\nwant %s", tc.desc, gotXML, tc.wantXML)
+ }
+ }
+}
+
+func TestReadProppatch(t *testing.T) {
+ ppStr := func(pps []Proppatch) string {
+ var outer []string
+ for _, pp := range pps {
+ var inner []string
+ for _, p := range pp.Props {
+ inner = append(inner, fmt.Sprintf("{XMLName: %q, Lang: %q, InnerXML: %q}",
+ p.XMLName, p.Lang, p.InnerXML))
+ }
+ outer = append(outer, fmt.Sprintf("{Remove: %t, Props: [%s]}",
+ pp.Remove, strings.Join(inner, ", ")))
+ }
+ return "[" + strings.Join(outer, ", ") + "]"
+ }
+
+ testCases := []struct {
+ desc string
+ input string
+ wantPP []Proppatch
+ wantStatus int
+ }{{
+ desc: "proppatch: section 9.2 (with simple property value)",
+ input: `` +
+ `<?xml version="1.0" encoding="utf-8" ?>` +
+ `<D:propertyupdate xmlns:D="DAV:"` +
+ ` xmlns:Z="http://ns.example.com/z/">` +
+ ` <D:set>` +
+ ` <D:prop><Z:Authors>somevalue</Z:Authors></D:prop>` +
+ ` </D:set>` +
+ ` <D:remove>` +
+ ` <D:prop><Z:Copyright-Owner/></D:prop>` +
+ ` </D:remove>` +
+ `</D:propertyupdate>`,
+ wantPP: []Proppatch{{
+ Props: []Property{{
+ xml.Name{Space: "http://ns.example.com/z/", Local: "Authors"},
+ "",
+ []byte(`somevalue`),
+ }},
+ }, {
+ Remove: true,
+ Props: []Property{{
+ xml.Name{Space: "http://ns.example.com/z/", Local: "Copyright-Owner"},
+ "",
+ nil,
+ }},
+ }},
+ }, {
+ desc: "proppatch: lang attribute on prop",
+ input: `` +
+ `<?xml version="1.0" encoding="utf-8" ?>` +
+ `<D:propertyupdate xmlns:D="DAV:">` +
+ ` <D:set>` +
+ ` <D:prop xml:lang="en">` +
+ ` <foo xmlns="http://example.com/ns"/>` +
+ ` </D:prop>` +
+ ` </D:set>` +
+ `</D:propertyupdate>`,
+ wantPP: []Proppatch{{
+ Props: []Property{{
+ xml.Name{Space: "http://example.com/ns", Local: "foo"},
+ "en",
+ nil,
+ }},
+ }},
+ }, {
+ desc: "bad: remove with value",
+ input: `` +
+ `<?xml version="1.0" encoding="utf-8" ?>` +
+ `<D:propertyupdate xmlns:D="DAV:"` +
+ ` xmlns:Z="http://ns.example.com/z/">` +
+ ` <D:remove>` +
+ ` <D:prop>` +
+ ` <Z:Authors>` +
+ ` <Z:Author>Jim Whitehead</Z:Author>` +
+ ` </Z:Authors>` +
+ ` </D:prop>` +
+ ` </D:remove>` +
+ `</D:propertyupdate>`,
+ wantStatus: http.StatusBadRequest,
+ }, {
+ desc: "bad: empty propertyupdate",
+ input: `` +
+ `<?xml version="1.0" encoding="utf-8" ?>` +
+ `<D:propertyupdate xmlns:D="DAV:"` +
+ `</D:propertyupdate>`,
+ wantStatus: http.StatusBadRequest,
+ }, {
+ desc: "bad: empty prop",
+ input: `` +
+ `<?xml version="1.0" encoding="utf-8" ?>` +
+ `<D:propertyupdate xmlns:D="DAV:"` +
+ ` xmlns:Z="http://ns.example.com/z/">` +
+ ` <D:remove>` +
+ ` <D:prop/>` +
+ ` </D:remove>` +
+ `</D:propertyupdate>`,
+ wantStatus: http.StatusBadRequest,
+ }}
+
+ for _, tc := range testCases {
+ pp, status, err := readProppatch(strings.NewReader(tc.input))
+ if tc.wantStatus != 0 {
+ if err == nil {
+ t.Errorf("%s: got nil error, want non-nil", tc.desc)
+ continue
+ }
+ } else if err != nil {
+ t.Errorf("%s: %v", tc.desc, err)
+ continue
+ }
+ if status != tc.wantStatus {
+ t.Errorf("%s: got status %d, want %d", tc.desc, status, tc.wantStatus)
+ continue
+ }
+ if !reflect.DeepEqual(pp, tc.wantPP) || status != tc.wantStatus {
+ t.Errorf("%s: proppatch\ngot %v\nwant %v", tc.desc, ppStr(pp), ppStr(tc.wantPP))
+ }
+ }
+}
+
+func TestUnmarshalXMLValue(t *testing.T) {
+ testCases := []struct {
+ desc string
+ input string
+ wantVal string
+ }{{
+ desc: "simple char data",
+ input: "<root>foo</root>",
+ wantVal: "foo",
+ }, {
+ desc: "empty element",
+ input: "<root><foo/></root>",
+ wantVal: "<foo/>",
+ }, {
+ desc: "preserve namespace",
+ input: `<root><foo xmlns="bar"/></root>`,
+ wantVal: `<foo xmlns="bar"/>`,
+ }, {
+ desc: "preserve root element namespace",
+ input: `<root xmlns:bar="bar"><bar:foo/></root>`,
+ wantVal: `<foo xmlns="bar"/>`,
+ }, {
+ desc: "preserve whitespace",
+ input: "<root> \t </root>",
+ wantVal: " \t ",
+ }, {
+ desc: "preserve mixed content",
+ input: `<root xmlns="bar"> <foo>a<bam xmlns="baz"/> </foo> </root>`,
+ wantVal: ` <foo xmlns="bar">a<bam xmlns="baz"/> </foo> `,
+ }, {
+ desc: "section 9.2",
+ input: `` +
+ `<Z:Authors xmlns:Z="http://ns.example.com/z/">` +
+ ` <Z:Author>Jim Whitehead</Z:Author>` +
+ ` <Z:Author>Roy Fielding</Z:Author>` +
+ `</Z:Authors>`,
+ wantVal: `` +
+ ` <Author xmlns="http://ns.example.com/z/">Jim Whitehead</Author>` +
+ ` <Author xmlns="http://ns.example.com/z/">Roy Fielding</Author>`,
+ }, {
+ desc: "section 4.3.1 (mixed content)",
+ input: `` +
+ `<x:author ` +
+ ` xmlns:x='http://example.com/ns' ` +
+ ` xmlns:D="DAV:">` +
+ ` <x:name>Jane Doe</x:name>` +
+ ` <!-- Jane's contact info -->` +
+ ` <x:uri type='email'` +
+ ` added='2005-11-26'>mailto:jane.doe@example.com</x:uri>` +
+ ` <x:uri type='web'` +
+ ` added='2005-11-27'>http://www.example.com</x:uri>` +
+ ` <x:notes xmlns:h='http://www.w3.org/1999/xhtml'>` +
+ ` Jane has been working way <h:em>too</h:em> long on the` +
+ ` long-awaited revision of <![CDATA[<RFC2518>]]>.` +
+ ` </x:notes>` +
+ `</x:author>`,
+ wantVal: `` +
+ ` <name xmlns="http://example.com/ns">Jane Doe</name>` +
+ ` ` +
+ ` <uri type='email'` +
+ ` xmlns="http://example.com/ns" ` +
+ ` added='2005-11-26'>mailto:jane.doe@example.com</uri>` +
+ ` <uri added='2005-11-27'` +
+ ` type='web'` +
+ ` xmlns="http://example.com/ns">http://www.example.com</uri>` +
+ ` <notes xmlns="http://example.com/ns" ` +
+ ` xmlns:h="http://www.w3.org/1999/xhtml">` +
+ ` Jane has been working way <h:em>too</h:em> long on the` +
+ ` long-awaited revision of &lt;RFC2518&gt;.` +
+ ` </notes>`,
+ }}
+
+ var n xmlNormalizer
+ for _, tc := range testCases {
+ d := ixml.NewDecoder(strings.NewReader(tc.input))
+ var v xmlValue
+ if err := d.Decode(&v); err != nil {
+ t.Errorf("%s: got error %v, want nil", tc.desc, err)
+ continue
+ }
+ eq, err := n.equalXML(bytes.NewReader(v), strings.NewReader(tc.wantVal))
+ if err != nil {
+ t.Errorf("%s: equalXML: %v", tc.desc, err)
+ continue
+ }
+ if !eq {
+ t.Errorf("%s:\ngot %s\nwant %s", tc.desc, string(v), tc.wantVal)
+ }
+ }
+}
+
+// xmlNormalizer normalizes XML.
+type xmlNormalizer struct {
+ // omitWhitespace instructs to ignore whitespace between element tags.
+ omitWhitespace bool
+ // omitComments instructs to ignore XML comments.
+ omitComments bool
+}
+
+// normalize writes the normalized XML content of r to w. It applies the
+// following rules
+//
+// * Rename namespace prefixes according to an internal heuristic.
+// * Remove unnecessary namespace declarations.
+// * Sort attributes in XML start elements in lexical order of their
+// fully qualified name.
+// * Remove XML directives and processing instructions.
+// * Remove CDATA between XML tags that only contains whitespace, if
+// instructed to do so.
+// * Remove comments, if instructed to do so.
+//
+func (n *xmlNormalizer) normalize(w io.Writer, r io.Reader) error {
+ d := ixml.NewDecoder(r)
+ e := ixml.NewEncoder(w)
+ for {
+ t, err := d.Token()
+ if err != nil {
+ if t == nil && err == io.EOF {
+ break
+ }
+ return err
+ }
+ switch val := t.(type) {
+ case ixml.Directive, ixml.ProcInst:
+ continue
+ case ixml.Comment:
+ if n.omitComments {
+ continue
+ }
+ case ixml.CharData:
+ if n.omitWhitespace && len(bytes.TrimSpace(val)) == 0 {
+ continue
+ }
+ case ixml.StartElement:
+ start, _ := ixml.CopyToken(val).(ixml.StartElement)
+ attr := start.Attr[:0]
+ for _, a := range start.Attr {
+ if a.Name.Space == "xmlns" || a.Name.Local == "xmlns" {
+ continue
+ }
+ attr = append(attr, a)
+ }
+ sort.Sort(byName(attr))
+ start.Attr = attr
+ t = start
+ }
+ err = e.EncodeToken(t)
+ if err != nil {
+ return err
+ }
+ }
+ return e.Flush()
+}
+
+// equalXML tests for equality of the normalized XML contents of a and b.
+func (n *xmlNormalizer) equalXML(a, b io.Reader) (bool, error) {
+ var buf bytes.Buffer
+ if err := n.normalize(&buf, a); err != nil {
+ return false, err
+ }
+ normA := buf.String()
+ buf.Reset()
+ if err := n.normalize(&buf, b); err != nil {
+ return false, err
+ }
+ normB := buf.String()
+ return normA == normB, nil
+}
+
+type byName []ixml.Attr
+
+func (a byName) Len() int { return len(a) }
+func (a byName) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+func (a byName) Less(i, j int) bool {
+ if a[i].Name.Space != a[j].Name.Space {
+ return a[i].Name.Space < a[j].Name.Space
+ }
+ return a[i].Name.Local < a[j].Name.Local
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/websocket/client.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/websocket/client.go
new file mode 100644
index 000000000..69a4ac7ee
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/websocket/client.go
@@ -0,0 +1,106 @@
+// Copyright 2009 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 websocket
+
+import (
+ "bufio"
+ "io"
+ "net"
+ "net/http"
+ "net/url"
+)
+
+// DialError is an error that occurs while dialling a websocket server.
+type DialError struct {
+ *Config
+ Err error
+}
+
+func (e *DialError) Error() string {
+ return "websocket.Dial " + e.Config.Location.String() + ": " + e.Err.Error()
+}
+
+// NewConfig creates a new WebSocket config for client connection.
+func NewConfig(server, origin string) (config *Config, err error) {
+ config = new(Config)
+ config.Version = ProtocolVersionHybi13
+ config.Location, err = url.ParseRequestURI(server)
+ if err != nil {
+ return
+ }
+ config.Origin, err = url.ParseRequestURI(origin)
+ if err != nil {
+ return
+ }
+ config.Header = http.Header(make(map[string][]string))
+ return
+}
+
+// NewClient creates a new WebSocket client connection over rwc.
+func NewClient(config *Config, rwc io.ReadWriteCloser) (ws *Conn, err error) {
+ br := bufio.NewReader(rwc)
+ bw := bufio.NewWriter(rwc)
+ err = hybiClientHandshake(config, br, bw)
+ if err != nil {
+ return
+ }
+ buf := bufio.NewReadWriter(br, bw)
+ ws = newHybiClientConn(config, buf, rwc)
+ return
+}
+
+// Dial opens a new client connection to a WebSocket.
+func Dial(url_, protocol, origin string) (ws *Conn, err error) {
+ config, err := NewConfig(url_, origin)
+ if err != nil {
+ return nil, err
+ }
+ if protocol != "" {
+ config.Protocol = []string{protocol}
+ }
+ return DialConfig(config)
+}
+
+var portMap = map[string]string{
+ "ws": "80",
+ "wss": "443",
+}
+
+func parseAuthority(location *url.URL) string {
+ if _, ok := portMap[location.Scheme]; ok {
+ if _, _, err := net.SplitHostPort(location.Host); err != nil {
+ return net.JoinHostPort(location.Host, portMap[location.Scheme])
+ }
+ }
+ return location.Host
+}
+
+// DialConfig opens a new client connection to a WebSocket with a config.
+func DialConfig(config *Config) (ws *Conn, err error) {
+ var client net.Conn
+ if config.Location == nil {
+ return nil, &DialError{config, ErrBadWebSocketLocation}
+ }
+ if config.Origin == nil {
+ return nil, &DialError{config, ErrBadWebSocketOrigin}
+ }
+ dialer := config.Dialer
+ if dialer == nil {
+ dialer = &net.Dialer{}
+ }
+ client, err = dialWithDialer(dialer, config)
+ if err != nil {
+ goto Error
+ }
+ ws, err = NewClient(config, client)
+ if err != nil {
+ client.Close()
+ goto Error
+ }
+ return
+
+Error:
+ return nil, &DialError{config, err}
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/websocket/dial.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/websocket/dial.go
new file mode 100644
index 000000000..2dab943a4
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/websocket/dial.go
@@ -0,0 +1,24 @@
+// Copyright 2015 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 websocket
+
+import (
+ "crypto/tls"
+ "net"
+)
+
+func dialWithDialer(dialer *net.Dialer, config *Config) (conn net.Conn, err error) {
+ switch config.Location.Scheme {
+ case "ws":
+ conn, err = dialer.Dial("tcp", parseAuthority(config.Location))
+
+ case "wss":
+ conn, err = tls.DialWithDialer(dialer, "tcp", parseAuthority(config.Location), config.TlsConfig)
+
+ default:
+ err = ErrBadScheme
+ }
+ return
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/websocket/dial_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/websocket/dial_test.go
new file mode 100644
index 000000000..aa03e30dd
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/websocket/dial_test.go
@@ -0,0 +1,43 @@
+// Copyright 2015 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 websocket
+
+import (
+ "crypto/tls"
+ "fmt"
+ "log"
+ "net"
+ "net/http/httptest"
+ "testing"
+ "time"
+)
+
+// This test depend on Go 1.3+ because in earlier versions the Dialer won't be
+// used in TLS connections and a timeout won't be triggered.
+func TestDialConfigTLSWithDialer(t *testing.T) {
+ tlsServer := httptest.NewTLSServer(nil)
+ tlsServerAddr := tlsServer.Listener.Addr().String()
+ log.Print("Test TLS WebSocket server listening on ", tlsServerAddr)
+ defer tlsServer.Close()
+ config, _ := NewConfig(fmt.Sprintf("wss://%s/echo", tlsServerAddr), "http://localhost")
+ config.Dialer = &net.Dialer{
+ Deadline: time.Now().Add(-time.Minute),
+ }
+ config.TlsConfig = &tls.Config{
+ InsecureSkipVerify: true,
+ }
+ _, err := DialConfig(config)
+ dialerr, ok := err.(*DialError)
+ if !ok {
+ t.Fatalf("DialError expected, got %#v", err)
+ }
+ neterr, ok := dialerr.Err.(*net.OpError)
+ if !ok {
+ t.Fatalf("net.OpError error expected, got %#v", dialerr.Err)
+ }
+ if !neterr.Timeout() {
+ t.Fatalf("expected timeout error, got %#v", neterr)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/websocket/exampledial_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/websocket/exampledial_test.go
new file mode 100644
index 000000000..72bb9d48e
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/websocket/exampledial_test.go
@@ -0,0 +1,31 @@
+// Copyright 2012 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 websocket_test
+
+import (
+ "fmt"
+ "log"
+
+ "golang.org/x/net/websocket"
+)
+
+// This example demonstrates a trivial client.
+func ExampleDial() {
+ origin := "http://localhost/"
+ url := "ws://localhost:12345/ws"
+ ws, err := websocket.Dial(url, "", origin)
+ if err != nil {
+ log.Fatal(err)
+ }
+ if _, err := ws.Write([]byte("hello, world!\n")); err != nil {
+ log.Fatal(err)
+ }
+ var msg = make([]byte, 512)
+ var n int
+ if n, err = ws.Read(msg); err != nil {
+ log.Fatal(err)
+ }
+ fmt.Printf("Received: %s.\n", msg[:n])
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/websocket/examplehandler_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/websocket/examplehandler_test.go
new file mode 100644
index 000000000..f22a98fcd
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/websocket/examplehandler_test.go
@@ -0,0 +1,26 @@
+// Copyright 2012 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 websocket_test
+
+import (
+ "io"
+ "net/http"
+
+ "golang.org/x/net/websocket"
+)
+
+// Echo the data received on the WebSocket.
+func EchoServer(ws *websocket.Conn) {
+ io.Copy(ws, ws)
+}
+
+// This example demonstrates a trivial echo server.
+func ExampleHandler() {
+ http.Handle("/echo", websocket.Handler(EchoServer))
+ err := http.ListenAndServe(":12345", nil)
+ if err != nil {
+ panic("ListenAndServe: " + err.Error())
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/websocket/hybi.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/websocket/hybi.go
new file mode 100644
index 000000000..8cffdd16c
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/websocket/hybi.go
@@ -0,0 +1,583 @@
+// Copyright 2011 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 websocket
+
+// This file implements a protocol of hybi draft.
+// http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17
+
+import (
+ "bufio"
+ "bytes"
+ "crypto/rand"
+ "crypto/sha1"
+ "encoding/base64"
+ "encoding/binary"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "net/http"
+ "net/url"
+ "strings"
+)
+
+const (
+ websocketGUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
+
+ closeStatusNormal = 1000
+ closeStatusGoingAway = 1001
+ closeStatusProtocolError = 1002
+ closeStatusUnsupportedData = 1003
+ closeStatusFrameTooLarge = 1004
+ closeStatusNoStatusRcvd = 1005
+ closeStatusAbnormalClosure = 1006
+ closeStatusBadMessageData = 1007
+ closeStatusPolicyViolation = 1008
+ closeStatusTooBigData = 1009
+ closeStatusExtensionMismatch = 1010
+
+ maxControlFramePayloadLength = 125
+)
+
+var (
+ ErrBadMaskingKey = &ProtocolError{"bad masking key"}
+ ErrBadPongMessage = &ProtocolError{"bad pong message"}
+ ErrBadClosingStatus = &ProtocolError{"bad closing status"}
+ ErrUnsupportedExtensions = &ProtocolError{"unsupported extensions"}
+ ErrNotImplemented = &ProtocolError{"not implemented"}
+
+ handshakeHeader = map[string]bool{
+ "Host": true,
+ "Upgrade": true,
+ "Connection": true,
+ "Sec-Websocket-Key": true,
+ "Sec-Websocket-Origin": true,
+ "Sec-Websocket-Version": true,
+ "Sec-Websocket-Protocol": true,
+ "Sec-Websocket-Accept": true,
+ }
+)
+
+// A hybiFrameHeader is a frame header as defined in hybi draft.
+type hybiFrameHeader struct {
+ Fin bool
+ Rsv [3]bool
+ OpCode byte
+ Length int64
+ MaskingKey []byte
+
+ data *bytes.Buffer
+}
+
+// A hybiFrameReader is a reader for hybi frame.
+type hybiFrameReader struct {
+ reader io.Reader
+
+ header hybiFrameHeader
+ pos int64
+ length int
+}
+
+func (frame *hybiFrameReader) Read(msg []byte) (n int, err error) {
+ n, err = frame.reader.Read(msg)
+ if frame.header.MaskingKey != nil {
+ for i := 0; i < n; i++ {
+ msg[i] = msg[i] ^ frame.header.MaskingKey[frame.pos%4]
+ frame.pos++
+ }
+ }
+ return n, err
+}
+
+func (frame *hybiFrameReader) PayloadType() byte { return frame.header.OpCode }
+
+func (frame *hybiFrameReader) HeaderReader() io.Reader {
+ if frame.header.data == nil {
+ return nil
+ }
+ if frame.header.data.Len() == 0 {
+ return nil
+ }
+ return frame.header.data
+}
+
+func (frame *hybiFrameReader) TrailerReader() io.Reader { return nil }
+
+func (frame *hybiFrameReader) Len() (n int) { return frame.length }
+
+// A hybiFrameReaderFactory creates new frame reader based on its frame type.
+type hybiFrameReaderFactory struct {
+ *bufio.Reader
+}
+
+// NewFrameReader reads a frame header from the connection, and creates new reader for the frame.
+// See Section 5.2 Base Framing protocol for detail.
+// http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17#section-5.2
+func (buf hybiFrameReaderFactory) NewFrameReader() (frame frameReader, err error) {
+ hybiFrame := new(hybiFrameReader)
+ frame = hybiFrame
+ var header []byte
+ var b byte
+ // First byte. FIN/RSV1/RSV2/RSV3/OpCode(4bits)
+ b, err = buf.ReadByte()
+ if err != nil {
+ return
+ }
+ header = append(header, b)
+ hybiFrame.header.Fin = ((header[0] >> 7) & 1) != 0
+ for i := 0; i < 3; i++ {
+ j := uint(6 - i)
+ hybiFrame.header.Rsv[i] = ((header[0] >> j) & 1) != 0
+ }
+ hybiFrame.header.OpCode = header[0] & 0x0f
+
+ // Second byte. Mask/Payload len(7bits)
+ b, err = buf.ReadByte()
+ if err != nil {
+ return
+ }
+ header = append(header, b)
+ mask := (b & 0x80) != 0
+ b &= 0x7f
+ lengthFields := 0
+ switch {
+ case b <= 125: // Payload length 7bits.
+ hybiFrame.header.Length = int64(b)
+ case b == 126: // Payload length 7+16bits
+ lengthFields = 2
+ case b == 127: // Payload length 7+64bits
+ lengthFields = 8
+ }
+ for i := 0; i < lengthFields; i++ {
+ b, err = buf.ReadByte()
+ if err != nil {
+ return
+ }
+ if lengthFields == 8 && i == 0 { // MSB must be zero when 7+64 bits
+ b &= 0x7f
+ }
+ header = append(header, b)
+ hybiFrame.header.Length = hybiFrame.header.Length*256 + int64(b)
+ }
+ if mask {
+ // Masking key. 4 bytes.
+ for i := 0; i < 4; i++ {
+ b, err = buf.ReadByte()
+ if err != nil {
+ return
+ }
+ header = append(header, b)
+ hybiFrame.header.MaskingKey = append(hybiFrame.header.MaskingKey, b)
+ }
+ }
+ hybiFrame.reader = io.LimitReader(buf.Reader, hybiFrame.header.Length)
+ hybiFrame.header.data = bytes.NewBuffer(header)
+ hybiFrame.length = len(header) + int(hybiFrame.header.Length)
+ return
+}
+
+// A HybiFrameWriter is a writer for hybi frame.
+type hybiFrameWriter struct {
+ writer *bufio.Writer
+
+ header *hybiFrameHeader
+}
+
+func (frame *hybiFrameWriter) Write(msg []byte) (n int, err error) {
+ var header []byte
+ var b byte
+ if frame.header.Fin {
+ b |= 0x80
+ }
+ for i := 0; i < 3; i++ {
+ if frame.header.Rsv[i] {
+ j := uint(6 - i)
+ b |= 1 << j
+ }
+ }
+ b |= frame.header.OpCode
+ header = append(header, b)
+ if frame.header.MaskingKey != nil {
+ b = 0x80
+ } else {
+ b = 0
+ }
+ lengthFields := 0
+ length := len(msg)
+ switch {
+ case length <= 125:
+ b |= byte(length)
+ case length < 65536:
+ b |= 126
+ lengthFields = 2
+ default:
+ b |= 127
+ lengthFields = 8
+ }
+ header = append(header, b)
+ for i := 0; i < lengthFields; i++ {
+ j := uint((lengthFields - i - 1) * 8)
+ b = byte((length >> j) & 0xff)
+ header = append(header, b)
+ }
+ if frame.header.MaskingKey != nil {
+ if len(frame.header.MaskingKey) != 4 {
+ return 0, ErrBadMaskingKey
+ }
+ header = append(header, frame.header.MaskingKey...)
+ frame.writer.Write(header)
+ data := make([]byte, length)
+ for i := range data {
+ data[i] = msg[i] ^ frame.header.MaskingKey[i%4]
+ }
+ frame.writer.Write(data)
+ err = frame.writer.Flush()
+ return length, err
+ }
+ frame.writer.Write(header)
+ frame.writer.Write(msg)
+ err = frame.writer.Flush()
+ return length, err
+}
+
+func (frame *hybiFrameWriter) Close() error { return nil }
+
+type hybiFrameWriterFactory struct {
+ *bufio.Writer
+ needMaskingKey bool
+}
+
+func (buf hybiFrameWriterFactory) NewFrameWriter(payloadType byte) (frame frameWriter, err error) {
+ frameHeader := &hybiFrameHeader{Fin: true, OpCode: payloadType}
+ if buf.needMaskingKey {
+ frameHeader.MaskingKey, err = generateMaskingKey()
+ if err != nil {
+ return nil, err
+ }
+ }
+ return &hybiFrameWriter{writer: buf.Writer, header: frameHeader}, nil
+}
+
+type hybiFrameHandler struct {
+ conn *Conn
+ payloadType byte
+}
+
+func (handler *hybiFrameHandler) HandleFrame(frame frameReader) (frameReader, error) {
+ if handler.conn.IsServerConn() {
+ // The client MUST mask all frames sent to the server.
+ if frame.(*hybiFrameReader).header.MaskingKey == nil {
+ handler.WriteClose(closeStatusProtocolError)
+ return nil, io.EOF
+ }
+ } else {
+ // The server MUST NOT mask all frames.
+ if frame.(*hybiFrameReader).header.MaskingKey != nil {
+ handler.WriteClose(closeStatusProtocolError)
+ return nil, io.EOF
+ }
+ }
+ if header := frame.HeaderReader(); header != nil {
+ io.Copy(ioutil.Discard, header)
+ }
+ switch frame.PayloadType() {
+ case ContinuationFrame:
+ frame.(*hybiFrameReader).header.OpCode = handler.payloadType
+ case TextFrame, BinaryFrame:
+ handler.payloadType = frame.PayloadType()
+ case CloseFrame:
+ return nil, io.EOF
+ case PingFrame, PongFrame:
+ b := make([]byte, maxControlFramePayloadLength)
+ n, err := io.ReadFull(frame, b)
+ if err != nil && err != io.EOF && err != io.ErrUnexpectedEOF {
+ return nil, err
+ }
+ io.Copy(ioutil.Discard, frame)
+ if frame.PayloadType() == PingFrame {
+ if _, err := handler.WritePong(b[:n]); err != nil {
+ return nil, err
+ }
+ }
+ return nil, nil
+ }
+ return frame, nil
+}
+
+func (handler *hybiFrameHandler) WriteClose(status int) (err error) {
+ handler.conn.wio.Lock()
+ defer handler.conn.wio.Unlock()
+ w, err := handler.conn.frameWriterFactory.NewFrameWriter(CloseFrame)
+ if err != nil {
+ return err
+ }
+ msg := make([]byte, 2)
+ binary.BigEndian.PutUint16(msg, uint16(status))
+ _, err = w.Write(msg)
+ w.Close()
+ return err
+}
+
+func (handler *hybiFrameHandler) WritePong(msg []byte) (n int, err error) {
+ handler.conn.wio.Lock()
+ defer handler.conn.wio.Unlock()
+ w, err := handler.conn.frameWriterFactory.NewFrameWriter(PongFrame)
+ if err != nil {
+ return 0, err
+ }
+ n, err = w.Write(msg)
+ w.Close()
+ return n, err
+}
+
+// newHybiConn creates a new WebSocket connection speaking hybi draft protocol.
+func newHybiConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
+ if buf == nil {
+ br := bufio.NewReader(rwc)
+ bw := bufio.NewWriter(rwc)
+ buf = bufio.NewReadWriter(br, bw)
+ }
+ ws := &Conn{config: config, request: request, buf: buf, rwc: rwc,
+ frameReaderFactory: hybiFrameReaderFactory{buf.Reader},
+ frameWriterFactory: hybiFrameWriterFactory{
+ buf.Writer, request == nil},
+ PayloadType: TextFrame,
+ defaultCloseStatus: closeStatusNormal}
+ ws.frameHandler = &hybiFrameHandler{conn: ws}
+ return ws
+}
+
+// generateMaskingKey generates a masking key for a frame.
+func generateMaskingKey() (maskingKey []byte, err error) {
+ maskingKey = make([]byte, 4)
+ if _, err = io.ReadFull(rand.Reader, maskingKey); err != nil {
+ return
+ }
+ return
+}
+
+// generateNonce generates a nonce consisting of a randomly selected 16-byte
+// value that has been base64-encoded.
+func generateNonce() (nonce []byte) {
+ key := make([]byte, 16)
+ if _, err := io.ReadFull(rand.Reader, key); err != nil {
+ panic(err)
+ }
+ nonce = make([]byte, 24)
+ base64.StdEncoding.Encode(nonce, key)
+ return
+}
+
+// removeZone removes IPv6 zone identifer from host.
+// E.g., "[fe80::1%en0]:8080" to "[fe80::1]:8080"
+func removeZone(host string) string {
+ if !strings.HasPrefix(host, "[") {
+ return host
+ }
+ i := strings.LastIndex(host, "]")
+ if i < 0 {
+ return host
+ }
+ j := strings.LastIndex(host[:i], "%")
+ if j < 0 {
+ return host
+ }
+ return host[:j] + host[i:]
+}
+
+// getNonceAccept computes the base64-encoded SHA-1 of the concatenation of
+// the nonce ("Sec-WebSocket-Key" value) with the websocket GUID string.
+func getNonceAccept(nonce []byte) (expected []byte, err error) {
+ h := sha1.New()
+ if _, err = h.Write(nonce); err != nil {
+ return
+ }
+ if _, err = h.Write([]byte(websocketGUID)); err != nil {
+ return
+ }
+ expected = make([]byte, 28)
+ base64.StdEncoding.Encode(expected, h.Sum(nil))
+ return
+}
+
+// Client handshake described in draft-ietf-hybi-thewebsocket-protocol-17
+func hybiClientHandshake(config *Config, br *bufio.Reader, bw *bufio.Writer) (err error) {
+ bw.WriteString("GET " + config.Location.RequestURI() + " HTTP/1.1\r\n")
+
+ // According to RFC 6874, an HTTP client, proxy, or other
+ // intermediary must remove any IPv6 zone identifier attached
+ // to an outgoing URI.
+ bw.WriteString("Host: " + removeZone(config.Location.Host) + "\r\n")
+ bw.WriteString("Upgrade: websocket\r\n")
+ bw.WriteString("Connection: Upgrade\r\n")
+ nonce := generateNonce()
+ if config.handshakeData != nil {
+ nonce = []byte(config.handshakeData["key"])
+ }
+ bw.WriteString("Sec-WebSocket-Key: " + string(nonce) + "\r\n")
+ bw.WriteString("Origin: " + strings.ToLower(config.Origin.String()) + "\r\n")
+
+ if config.Version != ProtocolVersionHybi13 {
+ return ErrBadProtocolVersion
+ }
+
+ bw.WriteString("Sec-WebSocket-Version: " + fmt.Sprintf("%d", config.Version) + "\r\n")
+ if len(config.Protocol) > 0 {
+ bw.WriteString("Sec-WebSocket-Protocol: " + strings.Join(config.Protocol, ", ") + "\r\n")
+ }
+ // TODO(ukai): send Sec-WebSocket-Extensions.
+ err = config.Header.WriteSubset(bw, handshakeHeader)
+ if err != nil {
+ return err
+ }
+
+ bw.WriteString("\r\n")
+ if err = bw.Flush(); err != nil {
+ return err
+ }
+
+ resp, err := http.ReadResponse(br, &http.Request{Method: "GET"})
+ if err != nil {
+ return err
+ }
+ if resp.StatusCode != 101 {
+ return ErrBadStatus
+ }
+ if strings.ToLower(resp.Header.Get("Upgrade")) != "websocket" ||
+ strings.ToLower(resp.Header.Get("Connection")) != "upgrade" {
+ return ErrBadUpgrade
+ }
+ expectedAccept, err := getNonceAccept(nonce)
+ if err != nil {
+ return err
+ }
+ if resp.Header.Get("Sec-WebSocket-Accept") != string(expectedAccept) {
+ return ErrChallengeResponse
+ }
+ if resp.Header.Get("Sec-WebSocket-Extensions") != "" {
+ return ErrUnsupportedExtensions
+ }
+ offeredProtocol := resp.Header.Get("Sec-WebSocket-Protocol")
+ if offeredProtocol != "" {
+ protocolMatched := false
+ for i := 0; i < len(config.Protocol); i++ {
+ if config.Protocol[i] == offeredProtocol {
+ protocolMatched = true
+ break
+ }
+ }
+ if !protocolMatched {
+ return ErrBadWebSocketProtocol
+ }
+ config.Protocol = []string{offeredProtocol}
+ }
+
+ return nil
+}
+
+// newHybiClientConn creates a client WebSocket connection after handshake.
+func newHybiClientConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser) *Conn {
+ return newHybiConn(config, buf, rwc, nil)
+}
+
+// A HybiServerHandshaker performs a server handshake using hybi draft protocol.
+type hybiServerHandshaker struct {
+ *Config
+ accept []byte
+}
+
+func (c *hybiServerHandshaker) ReadHandshake(buf *bufio.Reader, req *http.Request) (code int, err error) {
+ c.Version = ProtocolVersionHybi13
+ if req.Method != "GET" {
+ return http.StatusMethodNotAllowed, ErrBadRequestMethod
+ }
+ // HTTP version can be safely ignored.
+
+ if strings.ToLower(req.Header.Get("Upgrade")) != "websocket" ||
+ !strings.Contains(strings.ToLower(req.Header.Get("Connection")), "upgrade") {
+ return http.StatusBadRequest, ErrNotWebSocket
+ }
+
+ key := req.Header.Get("Sec-Websocket-Key")
+ if key == "" {
+ return http.StatusBadRequest, ErrChallengeResponse
+ }
+ version := req.Header.Get("Sec-Websocket-Version")
+ switch version {
+ case "13":
+ c.Version = ProtocolVersionHybi13
+ default:
+ return http.StatusBadRequest, ErrBadWebSocketVersion
+ }
+ var scheme string
+ if req.TLS != nil {
+ scheme = "wss"
+ } else {
+ scheme = "ws"
+ }
+ c.Location, err = url.ParseRequestURI(scheme + "://" + req.Host + req.URL.RequestURI())
+ if err != nil {
+ return http.StatusBadRequest, err
+ }
+ protocol := strings.TrimSpace(req.Header.Get("Sec-Websocket-Protocol"))
+ if protocol != "" {
+ protocols := strings.Split(protocol, ",")
+ for i := 0; i < len(protocols); i++ {
+ c.Protocol = append(c.Protocol, strings.TrimSpace(protocols[i]))
+ }
+ }
+ c.accept, err = getNonceAccept([]byte(key))
+ if err != nil {
+ return http.StatusInternalServerError, err
+ }
+ return http.StatusSwitchingProtocols, nil
+}
+
+// Origin parses the Origin header in req.
+// If the Origin header is not set, it returns nil and nil.
+func Origin(config *Config, req *http.Request) (*url.URL, error) {
+ var origin string
+ switch config.Version {
+ case ProtocolVersionHybi13:
+ origin = req.Header.Get("Origin")
+ }
+ if origin == "" {
+ return nil, nil
+ }
+ return url.ParseRequestURI(origin)
+}
+
+func (c *hybiServerHandshaker) AcceptHandshake(buf *bufio.Writer) (err error) {
+ if len(c.Protocol) > 0 {
+ if len(c.Protocol) != 1 {
+ // You need choose a Protocol in Handshake func in Server.
+ return ErrBadWebSocketProtocol
+ }
+ }
+ buf.WriteString("HTTP/1.1 101 Switching Protocols\r\n")
+ buf.WriteString("Upgrade: websocket\r\n")
+ buf.WriteString("Connection: Upgrade\r\n")
+ buf.WriteString("Sec-WebSocket-Accept: " + string(c.accept) + "\r\n")
+ if len(c.Protocol) > 0 {
+ buf.WriteString("Sec-WebSocket-Protocol: " + c.Protocol[0] + "\r\n")
+ }
+ // TODO(ukai): send Sec-WebSocket-Extensions.
+ if c.Header != nil {
+ err := c.Header.WriteSubset(buf, handshakeHeader)
+ if err != nil {
+ return err
+ }
+ }
+ buf.WriteString("\r\n")
+ return buf.Flush()
+}
+
+func (c *hybiServerHandshaker) NewServerConn(buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
+ return newHybiServerConn(c.Config, buf, rwc, request)
+}
+
+// newHybiServerConn returns a new WebSocket connection speaking hybi draft protocol.
+func newHybiServerConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
+ return newHybiConn(config, buf, rwc, request)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/websocket/hybi_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/websocket/hybi_test.go
new file mode 100644
index 000000000..9504aa2d3
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/websocket/hybi_test.go
@@ -0,0 +1,608 @@
+// Copyright 2011 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 websocket
+
+import (
+ "bufio"
+ "bytes"
+ "fmt"
+ "io"
+ "net/http"
+ "net/url"
+ "strings"
+ "testing"
+)
+
+// Test the getNonceAccept function with values in
+// http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17
+func TestSecWebSocketAccept(t *testing.T) {
+ nonce := []byte("dGhlIHNhbXBsZSBub25jZQ==")
+ expected := []byte("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=")
+ accept, err := getNonceAccept(nonce)
+ if err != nil {
+ t.Errorf("getNonceAccept: returned error %v", err)
+ return
+ }
+ if !bytes.Equal(expected, accept) {
+ t.Errorf("getNonceAccept: expected %q got %q", expected, accept)
+ }
+}
+
+func TestHybiClientHandshake(t *testing.T) {
+ type test struct {
+ url, host string
+ }
+ tests := []test{
+ {"ws://server.example.com/chat", "server.example.com"},
+ {"ws://127.0.0.1/chat", "127.0.0.1"},
+ }
+ if _, err := url.ParseRequestURI("http://[fe80::1%25lo0]"); err == nil {
+ tests = append(tests, test{"ws://[fe80::1%25lo0]/chat", "[fe80::1]"})
+ }
+
+ for _, tt := range tests {
+ var b bytes.Buffer
+ bw := bufio.NewWriter(&b)
+ br := bufio.NewReader(strings.NewReader(`HTTP/1.1 101 Switching Protocols
+Upgrade: websocket
+Connection: Upgrade
+Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
+Sec-WebSocket-Protocol: chat
+
+`))
+ var err error
+ var config Config
+ config.Location, err = url.ParseRequestURI(tt.url)
+ if err != nil {
+ t.Fatal("location url", err)
+ }
+ config.Origin, err = url.ParseRequestURI("http://example.com")
+ if err != nil {
+ t.Fatal("origin url", err)
+ }
+ config.Protocol = append(config.Protocol, "chat")
+ config.Protocol = append(config.Protocol, "superchat")
+ config.Version = ProtocolVersionHybi13
+ config.handshakeData = map[string]string{
+ "key": "dGhlIHNhbXBsZSBub25jZQ==",
+ }
+ if err := hybiClientHandshake(&config, br, bw); err != nil {
+ t.Fatal("handshake", err)
+ }
+ req, err := http.ReadRequest(bufio.NewReader(&b))
+ if err != nil {
+ t.Fatal("read request", err)
+ }
+ if req.Method != "GET" {
+ t.Errorf("request method expected GET, but got %s", req.Method)
+ }
+ if req.URL.Path != "/chat" {
+ t.Errorf("request path expected /chat, but got %s", req.URL.Path)
+ }
+ if req.Proto != "HTTP/1.1" {
+ t.Errorf("request proto expected HTTP/1.1, but got %s", req.Proto)
+ }
+ if req.Host != tt.host {
+ t.Errorf("request host expected %s, but got %s", tt.host, req.Host)
+ }
+ var expectedHeader = map[string]string{
+ "Connection": "Upgrade",
+ "Upgrade": "websocket",
+ "Sec-Websocket-Key": config.handshakeData["key"],
+ "Origin": config.Origin.String(),
+ "Sec-Websocket-Protocol": "chat, superchat",
+ "Sec-Websocket-Version": fmt.Sprintf("%d", ProtocolVersionHybi13),
+ }
+ for k, v := range expectedHeader {
+ if req.Header.Get(k) != v {
+ t.Errorf("%s expected %s, but got %v", k, v, req.Header.Get(k))
+ }
+ }
+ }
+}
+
+func TestHybiClientHandshakeWithHeader(t *testing.T) {
+ b := bytes.NewBuffer([]byte{})
+ bw := bufio.NewWriter(b)
+ br := bufio.NewReader(strings.NewReader(`HTTP/1.1 101 Switching Protocols
+Upgrade: websocket
+Connection: Upgrade
+Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
+Sec-WebSocket-Protocol: chat
+
+`))
+ var err error
+ config := new(Config)
+ config.Location, err = url.ParseRequestURI("ws://server.example.com/chat")
+ if err != nil {
+ t.Fatal("location url", err)
+ }
+ config.Origin, err = url.ParseRequestURI("http://example.com")
+ if err != nil {
+ t.Fatal("origin url", err)
+ }
+ config.Protocol = append(config.Protocol, "chat")
+ config.Protocol = append(config.Protocol, "superchat")
+ config.Version = ProtocolVersionHybi13
+ config.Header = http.Header(make(map[string][]string))
+ config.Header.Add("User-Agent", "test")
+
+ config.handshakeData = map[string]string{
+ "key": "dGhlIHNhbXBsZSBub25jZQ==",
+ }
+ err = hybiClientHandshake(config, br, bw)
+ if err != nil {
+ t.Errorf("handshake failed: %v", err)
+ }
+ req, err := http.ReadRequest(bufio.NewReader(b))
+ if err != nil {
+ t.Fatalf("read request: %v", err)
+ }
+ if req.Method != "GET" {
+ t.Errorf("request method expected GET, but got %q", req.Method)
+ }
+ if req.URL.Path != "/chat" {
+ t.Errorf("request path expected /chat, but got %q", req.URL.Path)
+ }
+ if req.Proto != "HTTP/1.1" {
+ t.Errorf("request proto expected HTTP/1.1, but got %q", req.Proto)
+ }
+ if req.Host != "server.example.com" {
+ t.Errorf("request Host expected server.example.com, but got %v", req.Host)
+ }
+ var expectedHeader = map[string]string{
+ "Connection": "Upgrade",
+ "Upgrade": "websocket",
+ "Sec-Websocket-Key": config.handshakeData["key"],
+ "Origin": config.Origin.String(),
+ "Sec-Websocket-Protocol": "chat, superchat",
+ "Sec-Websocket-Version": fmt.Sprintf("%d", ProtocolVersionHybi13),
+ "User-Agent": "test",
+ }
+ for k, v := range expectedHeader {
+ if req.Header.Get(k) != v {
+ t.Errorf(fmt.Sprintf("%s expected %q but got %q", k, v, req.Header.Get(k)))
+ }
+ }
+}
+
+func TestHybiServerHandshake(t *testing.T) {
+ config := new(Config)
+ handshaker := &hybiServerHandshaker{Config: config}
+ br := bufio.NewReader(strings.NewReader(`GET /chat HTTP/1.1
+Host: server.example.com
+Upgrade: websocket
+Connection: Upgrade
+Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
+Origin: http://example.com
+Sec-WebSocket-Protocol: chat, superchat
+Sec-WebSocket-Version: 13
+
+`))
+ req, err := http.ReadRequest(br)
+ if err != nil {
+ t.Fatal("request", err)
+ }
+ code, err := handshaker.ReadHandshake(br, req)
+ if err != nil {
+ t.Errorf("handshake failed: %v", err)
+ }
+ if code != http.StatusSwitchingProtocols {
+ t.Errorf("status expected %q but got %q", http.StatusSwitchingProtocols, code)
+ }
+ expectedProtocols := []string{"chat", "superchat"}
+ if fmt.Sprintf("%v", config.Protocol) != fmt.Sprintf("%v", expectedProtocols) {
+ t.Errorf("protocol expected %q but got %q", expectedProtocols, config.Protocol)
+ }
+ b := bytes.NewBuffer([]byte{})
+ bw := bufio.NewWriter(b)
+
+ config.Protocol = config.Protocol[:1]
+
+ err = handshaker.AcceptHandshake(bw)
+ if err != nil {
+ t.Errorf("handshake response failed: %v", err)
+ }
+ expectedResponse := strings.Join([]string{
+ "HTTP/1.1 101 Switching Protocols",
+ "Upgrade: websocket",
+ "Connection: Upgrade",
+ "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",
+ "Sec-WebSocket-Protocol: chat",
+ "", ""}, "\r\n")
+
+ if b.String() != expectedResponse {
+ t.Errorf("handshake expected %q but got %q", expectedResponse, b.String())
+ }
+}
+
+func TestHybiServerHandshakeNoSubProtocol(t *testing.T) {
+ config := new(Config)
+ handshaker := &hybiServerHandshaker{Config: config}
+ br := bufio.NewReader(strings.NewReader(`GET /chat HTTP/1.1
+Host: server.example.com
+Upgrade: websocket
+Connection: Upgrade
+Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
+Origin: http://example.com
+Sec-WebSocket-Version: 13
+
+`))
+ req, err := http.ReadRequest(br)
+ if err != nil {
+ t.Fatal("request", err)
+ }
+ code, err := handshaker.ReadHandshake(br, req)
+ if err != nil {
+ t.Errorf("handshake failed: %v", err)
+ }
+ if code != http.StatusSwitchingProtocols {
+ t.Errorf("status expected %q but got %q", http.StatusSwitchingProtocols, code)
+ }
+ if len(config.Protocol) != 0 {
+ t.Errorf("len(config.Protocol) expected 0, but got %q", len(config.Protocol))
+ }
+ b := bytes.NewBuffer([]byte{})
+ bw := bufio.NewWriter(b)
+
+ err = handshaker.AcceptHandshake(bw)
+ if err != nil {
+ t.Errorf("handshake response failed: %v", err)
+ }
+ expectedResponse := strings.Join([]string{
+ "HTTP/1.1 101 Switching Protocols",
+ "Upgrade: websocket",
+ "Connection: Upgrade",
+ "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",
+ "", ""}, "\r\n")
+
+ if b.String() != expectedResponse {
+ t.Errorf("handshake expected %q but got %q", expectedResponse, b.String())
+ }
+}
+
+func TestHybiServerHandshakeHybiBadVersion(t *testing.T) {
+ config := new(Config)
+ handshaker := &hybiServerHandshaker{Config: config}
+ br := bufio.NewReader(strings.NewReader(`GET /chat HTTP/1.1
+Host: server.example.com
+Upgrade: websocket
+Connection: Upgrade
+Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
+Sec-WebSocket-Origin: http://example.com
+Sec-WebSocket-Protocol: chat, superchat
+Sec-WebSocket-Version: 9
+
+`))
+ req, err := http.ReadRequest(br)
+ if err != nil {
+ t.Fatal("request", err)
+ }
+ code, err := handshaker.ReadHandshake(br, req)
+ if err != ErrBadWebSocketVersion {
+ t.Errorf("handshake expected err %q but got %q", ErrBadWebSocketVersion, err)
+ }
+ if code != http.StatusBadRequest {
+ t.Errorf("status expected %q but got %q", http.StatusBadRequest, code)
+ }
+}
+
+func testHybiFrame(t *testing.T, testHeader, testPayload, testMaskedPayload []byte, frameHeader *hybiFrameHeader) {
+ b := bytes.NewBuffer([]byte{})
+ frameWriterFactory := &hybiFrameWriterFactory{bufio.NewWriter(b), false}
+ w, _ := frameWriterFactory.NewFrameWriter(TextFrame)
+ w.(*hybiFrameWriter).header = frameHeader
+ _, err := w.Write(testPayload)
+ w.Close()
+ if err != nil {
+ t.Errorf("Write error %q", err)
+ }
+ var expectedFrame []byte
+ expectedFrame = append(expectedFrame, testHeader...)
+ expectedFrame = append(expectedFrame, testMaskedPayload...)
+ if !bytes.Equal(expectedFrame, b.Bytes()) {
+ t.Errorf("frame expected %q got %q", expectedFrame, b.Bytes())
+ }
+ frameReaderFactory := &hybiFrameReaderFactory{bufio.NewReader(b)}
+ r, err := frameReaderFactory.NewFrameReader()
+ if err != nil {
+ t.Errorf("Read error %q", err)
+ }
+ if header := r.HeaderReader(); header == nil {
+ t.Errorf("no header")
+ } else {
+ actualHeader := make([]byte, r.Len())
+ n, err := header.Read(actualHeader)
+ if err != nil {
+ t.Errorf("Read header error %q", err)
+ } else {
+ if n < len(testHeader) {
+ t.Errorf("header too short %q got %q", testHeader, actualHeader[:n])
+ }
+ if !bytes.Equal(testHeader, actualHeader[:n]) {
+ t.Errorf("header expected %q got %q", testHeader, actualHeader[:n])
+ }
+ }
+ }
+ if trailer := r.TrailerReader(); trailer != nil {
+ t.Errorf("unexpected trailer %q", trailer)
+ }
+ frame := r.(*hybiFrameReader)
+ if frameHeader.Fin != frame.header.Fin ||
+ frameHeader.OpCode != frame.header.OpCode ||
+ len(testPayload) != int(frame.header.Length) {
+ t.Errorf("mismatch %v (%d) vs %v", frameHeader, len(testPayload), frame)
+ }
+ payload := make([]byte, len(testPayload))
+ _, err = r.Read(payload)
+ if err != nil && err != io.EOF {
+ t.Errorf("read %v", err)
+ }
+ if !bytes.Equal(testPayload, payload) {
+ t.Errorf("payload %q vs %q", testPayload, payload)
+ }
+}
+
+func TestHybiShortTextFrame(t *testing.T) {
+ frameHeader := &hybiFrameHeader{Fin: true, OpCode: TextFrame}
+ payload := []byte("hello")
+ testHybiFrame(t, []byte{0x81, 0x05}, payload, payload, frameHeader)
+
+ payload = make([]byte, 125)
+ testHybiFrame(t, []byte{0x81, 125}, payload, payload, frameHeader)
+}
+
+func TestHybiShortMaskedTextFrame(t *testing.T) {
+ frameHeader := &hybiFrameHeader{Fin: true, OpCode: TextFrame,
+ MaskingKey: []byte{0xcc, 0x55, 0x80, 0x20}}
+ payload := []byte("hello")
+ maskedPayload := []byte{0xa4, 0x30, 0xec, 0x4c, 0xa3}
+ header := []byte{0x81, 0x85}
+ header = append(header, frameHeader.MaskingKey...)
+ testHybiFrame(t, header, payload, maskedPayload, frameHeader)
+}
+
+func TestHybiShortBinaryFrame(t *testing.T) {
+ frameHeader := &hybiFrameHeader{Fin: true, OpCode: BinaryFrame}
+ payload := []byte("hello")
+ testHybiFrame(t, []byte{0x82, 0x05}, payload, payload, frameHeader)
+
+ payload = make([]byte, 125)
+ testHybiFrame(t, []byte{0x82, 125}, payload, payload, frameHeader)
+}
+
+func TestHybiControlFrame(t *testing.T) {
+ payload := []byte("hello")
+
+ frameHeader := &hybiFrameHeader{Fin: true, OpCode: PingFrame}
+ testHybiFrame(t, []byte{0x89, 0x05}, payload, payload, frameHeader)
+
+ frameHeader = &hybiFrameHeader{Fin: true, OpCode: PingFrame}
+ testHybiFrame(t, []byte{0x89, 0x00}, nil, nil, frameHeader)
+
+ frameHeader = &hybiFrameHeader{Fin: true, OpCode: PongFrame}
+ testHybiFrame(t, []byte{0x8A, 0x05}, payload, payload, frameHeader)
+
+ frameHeader = &hybiFrameHeader{Fin: true, OpCode: PongFrame}
+ testHybiFrame(t, []byte{0x8A, 0x00}, nil, nil, frameHeader)
+
+ frameHeader = &hybiFrameHeader{Fin: true, OpCode: CloseFrame}
+ payload = []byte{0x03, 0xe8} // 1000
+ testHybiFrame(t, []byte{0x88, 0x02}, payload, payload, frameHeader)
+}
+
+func TestHybiLongFrame(t *testing.T) {
+ frameHeader := &hybiFrameHeader{Fin: true, OpCode: TextFrame}
+ payload := make([]byte, 126)
+ testHybiFrame(t, []byte{0x81, 126, 0x00, 126}, payload, payload, frameHeader)
+
+ payload = make([]byte, 65535)
+ testHybiFrame(t, []byte{0x81, 126, 0xff, 0xff}, payload, payload, frameHeader)
+
+ payload = make([]byte, 65536)
+ testHybiFrame(t, []byte{0x81, 127, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00}, payload, payload, frameHeader)
+}
+
+func TestHybiClientRead(t *testing.T) {
+ wireData := []byte{0x81, 0x05, 'h', 'e', 'l', 'l', 'o',
+ 0x89, 0x05, 'h', 'e', 'l', 'l', 'o', // ping
+ 0x81, 0x05, 'w', 'o', 'r', 'l', 'd'}
+ br := bufio.NewReader(bytes.NewBuffer(wireData))
+ bw := bufio.NewWriter(bytes.NewBuffer([]byte{}))
+ conn := newHybiConn(newConfig(t, "/"), bufio.NewReadWriter(br, bw), nil, nil)
+
+ msg := make([]byte, 512)
+ n, err := conn.Read(msg)
+ if err != nil {
+ t.Errorf("read 1st frame, error %q", err)
+ }
+ if n != 5 {
+ t.Errorf("read 1st frame, expect 5, got %d", n)
+ }
+ if !bytes.Equal(wireData[2:7], msg[:n]) {
+ t.Errorf("read 1st frame %v, got %v", wireData[2:7], msg[:n])
+ }
+ n, err = conn.Read(msg)
+ if err != nil {
+ t.Errorf("read 2nd frame, error %q", err)
+ }
+ if n != 5 {
+ t.Errorf("read 2nd frame, expect 5, got %d", n)
+ }
+ if !bytes.Equal(wireData[16:21], msg[:n]) {
+ t.Errorf("read 2nd frame %v, got %v", wireData[16:21], msg[:n])
+ }
+ n, err = conn.Read(msg)
+ if err == nil {
+ t.Errorf("read not EOF")
+ }
+ if n != 0 {
+ t.Errorf("expect read 0, got %d", n)
+ }
+}
+
+func TestHybiShortRead(t *testing.T) {
+ wireData := []byte{0x81, 0x05, 'h', 'e', 'l', 'l', 'o',
+ 0x89, 0x05, 'h', 'e', 'l', 'l', 'o', // ping
+ 0x81, 0x05, 'w', 'o', 'r', 'l', 'd'}
+ br := bufio.NewReader(bytes.NewBuffer(wireData))
+ bw := bufio.NewWriter(bytes.NewBuffer([]byte{}))
+ conn := newHybiConn(newConfig(t, "/"), bufio.NewReadWriter(br, bw), nil, nil)
+
+ step := 0
+ pos := 0
+ expectedPos := []int{2, 5, 16, 19}
+ expectedLen := []int{3, 2, 3, 2}
+ for {
+ msg := make([]byte, 3)
+ n, err := conn.Read(msg)
+ if step >= len(expectedPos) {
+ if err == nil {
+ t.Errorf("read not EOF")
+ }
+ if n != 0 {
+ t.Errorf("expect read 0, got %d", n)
+ }
+ return
+ }
+ pos = expectedPos[step]
+ endPos := pos + expectedLen[step]
+ if err != nil {
+ t.Errorf("read from %d, got error %q", pos, err)
+ return
+ }
+ if n != endPos-pos {
+ t.Errorf("read from %d, expect %d, got %d", pos, endPos-pos, n)
+ }
+ if !bytes.Equal(wireData[pos:endPos], msg[:n]) {
+ t.Errorf("read from %d, frame %v, got %v", pos, wireData[pos:endPos], msg[:n])
+ }
+ step++
+ }
+}
+
+func TestHybiServerRead(t *testing.T) {
+ wireData := []byte{0x81, 0x85, 0xcc, 0x55, 0x80, 0x20,
+ 0xa4, 0x30, 0xec, 0x4c, 0xa3, // hello
+ 0x89, 0x85, 0xcc, 0x55, 0x80, 0x20,
+ 0xa4, 0x30, 0xec, 0x4c, 0xa3, // ping: hello
+ 0x81, 0x85, 0xed, 0x83, 0xb4, 0x24,
+ 0x9a, 0xec, 0xc6, 0x48, 0x89, // world
+ }
+ br := bufio.NewReader(bytes.NewBuffer(wireData))
+ bw := bufio.NewWriter(bytes.NewBuffer([]byte{}))
+ conn := newHybiConn(newConfig(t, "/"), bufio.NewReadWriter(br, bw), nil, new(http.Request))
+
+ expected := [][]byte{[]byte("hello"), []byte("world")}
+
+ msg := make([]byte, 512)
+ n, err := conn.Read(msg)
+ if err != nil {
+ t.Errorf("read 1st frame, error %q", err)
+ }
+ if n != 5 {
+ t.Errorf("read 1st frame, expect 5, got %d", n)
+ }
+ if !bytes.Equal(expected[0], msg[:n]) {
+ t.Errorf("read 1st frame %q, got %q", expected[0], msg[:n])
+ }
+
+ n, err = conn.Read(msg)
+ if err != nil {
+ t.Errorf("read 2nd frame, error %q", err)
+ }
+ if n != 5 {
+ t.Errorf("read 2nd frame, expect 5, got %d", n)
+ }
+ if !bytes.Equal(expected[1], msg[:n]) {
+ t.Errorf("read 2nd frame %q, got %q", expected[1], msg[:n])
+ }
+
+ n, err = conn.Read(msg)
+ if err == nil {
+ t.Errorf("read not EOF")
+ }
+ if n != 0 {
+ t.Errorf("expect read 0, got %d", n)
+ }
+}
+
+func TestHybiServerReadWithoutMasking(t *testing.T) {
+ wireData := []byte{0x81, 0x05, 'h', 'e', 'l', 'l', 'o'}
+ br := bufio.NewReader(bytes.NewBuffer(wireData))
+ bw := bufio.NewWriter(bytes.NewBuffer([]byte{}))
+ conn := newHybiConn(newConfig(t, "/"), bufio.NewReadWriter(br, bw), nil, new(http.Request))
+ // server MUST close the connection upon receiving a non-masked frame.
+ msg := make([]byte, 512)
+ _, err := conn.Read(msg)
+ if err != io.EOF {
+ t.Errorf("read 1st frame, expect %q, but got %q", io.EOF, err)
+ }
+}
+
+func TestHybiClientReadWithMasking(t *testing.T) {
+ wireData := []byte{0x81, 0x85, 0xcc, 0x55, 0x80, 0x20,
+ 0xa4, 0x30, 0xec, 0x4c, 0xa3, // hello
+ }
+ br := bufio.NewReader(bytes.NewBuffer(wireData))
+ bw := bufio.NewWriter(bytes.NewBuffer([]byte{}))
+ conn := newHybiConn(newConfig(t, "/"), bufio.NewReadWriter(br, bw), nil, nil)
+
+ // client MUST close the connection upon receiving a masked frame.
+ msg := make([]byte, 512)
+ _, err := conn.Read(msg)
+ if err != io.EOF {
+ t.Errorf("read 1st frame, expect %q, but got %q", io.EOF, err)
+ }
+}
+
+// Test the hybiServerHandshaker supports firefox implementation and
+// checks Connection request header include (but it's not necessary
+// equal to) "upgrade"
+func TestHybiServerFirefoxHandshake(t *testing.T) {
+ config := new(Config)
+ handshaker := &hybiServerHandshaker{Config: config}
+ br := bufio.NewReader(strings.NewReader(`GET /chat HTTP/1.1
+Host: server.example.com
+Upgrade: websocket
+Connection: keep-alive, upgrade
+Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
+Origin: http://example.com
+Sec-WebSocket-Protocol: chat, superchat
+Sec-WebSocket-Version: 13
+
+`))
+ req, err := http.ReadRequest(br)
+ if err != nil {
+ t.Fatal("request", err)
+ }
+ code, err := handshaker.ReadHandshake(br, req)
+ if err != nil {
+ t.Errorf("handshake failed: %v", err)
+ }
+ if code != http.StatusSwitchingProtocols {
+ t.Errorf("status expected %q but got %q", http.StatusSwitchingProtocols, code)
+ }
+ b := bytes.NewBuffer([]byte{})
+ bw := bufio.NewWriter(b)
+
+ config.Protocol = []string{"chat"}
+
+ err = handshaker.AcceptHandshake(bw)
+ if err != nil {
+ t.Errorf("handshake response failed: %v", err)
+ }
+ expectedResponse := strings.Join([]string{
+ "HTTP/1.1 101 Switching Protocols",
+ "Upgrade: websocket",
+ "Connection: Upgrade",
+ "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",
+ "Sec-WebSocket-Protocol: chat",
+ "", ""}, "\r\n")
+
+ if b.String() != expectedResponse {
+ t.Errorf("handshake expected %q but got %q", expectedResponse, b.String())
+ }
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/websocket/server.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/websocket/server.go
new file mode 100644
index 000000000..0895dea19
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/websocket/server.go
@@ -0,0 +1,113 @@
+// Copyright 2009 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 websocket
+
+import (
+ "bufio"
+ "fmt"
+ "io"
+ "net/http"
+)
+
+func newServerConn(rwc io.ReadWriteCloser, buf *bufio.ReadWriter, req *http.Request, config *Config, handshake func(*Config, *http.Request) error) (conn *Conn, err error) {
+ var hs serverHandshaker = &hybiServerHandshaker{Config: config}
+ code, err := hs.ReadHandshake(buf.Reader, req)
+ if err == ErrBadWebSocketVersion {
+ fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code))
+ fmt.Fprintf(buf, "Sec-WebSocket-Version: %s\r\n", SupportedProtocolVersion)
+ buf.WriteString("\r\n")
+ buf.WriteString(err.Error())
+ buf.Flush()
+ return
+ }
+ if err != nil {
+ fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code))
+ buf.WriteString("\r\n")
+ buf.WriteString(err.Error())
+ buf.Flush()
+ return
+ }
+ if handshake != nil {
+ err = handshake(config, req)
+ if err != nil {
+ code = http.StatusForbidden
+ fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code))
+ buf.WriteString("\r\n")
+ buf.Flush()
+ return
+ }
+ }
+ err = hs.AcceptHandshake(buf.Writer)
+ if err != nil {
+ code = http.StatusBadRequest
+ fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code))
+ buf.WriteString("\r\n")
+ buf.Flush()
+ return
+ }
+ conn = hs.NewServerConn(buf, rwc, req)
+ return
+}
+
+// Server represents a server of a WebSocket.
+type Server struct {
+ // Config is a WebSocket configuration for new WebSocket connection.
+ Config
+
+ // Handshake is an optional function in WebSocket handshake.
+ // For example, you can check, or don't check Origin header.
+ // Another example, you can select config.Protocol.
+ Handshake func(*Config, *http.Request) error
+
+ // Handler handles a WebSocket connection.
+ Handler
+}
+
+// ServeHTTP implements the http.Handler interface for a WebSocket
+func (s Server) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+ s.serveWebSocket(w, req)
+}
+
+func (s Server) serveWebSocket(w http.ResponseWriter, req *http.Request) {
+ rwc, buf, err := w.(http.Hijacker).Hijack()
+ if err != nil {
+ panic("Hijack failed: " + err.Error())
+ }
+ // The server should abort the WebSocket connection if it finds
+ // the client did not send a handshake that matches with protocol
+ // specification.
+ defer rwc.Close()
+ conn, err := newServerConn(rwc, buf, req, &s.Config, s.Handshake)
+ if err != nil {
+ return
+ }
+ if conn == nil {
+ panic("unexpected nil conn")
+ }
+ s.Handler(conn)
+}
+
+// Handler is a simple interface to a WebSocket browser client.
+// It checks if Origin header is valid URL by default.
+// You might want to verify websocket.Conn.Config().Origin in the func.
+// If you use Server instead of Handler, you could call websocket.Origin and
+// check the origin in your Handshake func. So, if you want to accept
+// non-browser clients, which do not send an Origin header, set a
+// Server.Handshake that does not check the origin.
+type Handler func(*Conn)
+
+func checkOrigin(config *Config, req *http.Request) (err error) {
+ config.Origin, err = Origin(config, req)
+ if err == nil && config.Origin == nil {
+ return fmt.Errorf("null origin")
+ }
+ return err
+}
+
+// ServeHTTP implements the http.Handler interface for a WebSocket
+func (h Handler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+ s := Server{Handler: h, Handshake: checkOrigin}
+ s.serveWebSocket(w, req)
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/websocket/websocket.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/websocket/websocket.go
new file mode 100644
index 000000000..e242c89a7
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/websocket/websocket.go
@@ -0,0 +1,448 @@
+// Copyright 2009 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 websocket implements a client and server for the WebSocket protocol
+// as specified in RFC 6455.
+//
+// This package currently lacks some features found in an alternative
+// and more actively maintained WebSocket package:
+//
+// https://godoc.org/github.com/gorilla/websocket
+//
+package websocket // import "golang.org/x/net/websocket"
+
+import (
+ "bufio"
+ "crypto/tls"
+ "encoding/json"
+ "errors"
+ "io"
+ "io/ioutil"
+ "net"
+ "net/http"
+ "net/url"
+ "sync"
+ "time"
+)
+
+const (
+ ProtocolVersionHybi13 = 13
+ ProtocolVersionHybi = ProtocolVersionHybi13
+ SupportedProtocolVersion = "13"
+
+ ContinuationFrame = 0
+ TextFrame = 1
+ BinaryFrame = 2
+ CloseFrame = 8
+ PingFrame = 9
+ PongFrame = 10
+ UnknownFrame = 255
+
+ DefaultMaxPayloadBytes = 32 << 20 // 32MB
+)
+
+// ProtocolError represents WebSocket protocol errors.
+type ProtocolError struct {
+ ErrorString string
+}
+
+func (err *ProtocolError) Error() string { return err.ErrorString }
+
+var (
+ ErrBadProtocolVersion = &ProtocolError{"bad protocol version"}
+ ErrBadScheme = &ProtocolError{"bad scheme"}
+ ErrBadStatus = &ProtocolError{"bad status"}
+ ErrBadUpgrade = &ProtocolError{"missing or bad upgrade"}
+ ErrBadWebSocketOrigin = &ProtocolError{"missing or bad WebSocket-Origin"}
+ ErrBadWebSocketLocation = &ProtocolError{"missing or bad WebSocket-Location"}
+ ErrBadWebSocketProtocol = &ProtocolError{"missing or bad WebSocket-Protocol"}
+ ErrBadWebSocketVersion = &ProtocolError{"missing or bad WebSocket Version"}
+ ErrChallengeResponse = &ProtocolError{"mismatch challenge/response"}
+ ErrBadFrame = &ProtocolError{"bad frame"}
+ ErrBadFrameBoundary = &ProtocolError{"not on frame boundary"}
+ ErrNotWebSocket = &ProtocolError{"not websocket protocol"}
+ ErrBadRequestMethod = &ProtocolError{"bad method"}
+ ErrNotSupported = &ProtocolError{"not supported"}
+)
+
+// ErrFrameTooLarge is returned by Codec's Receive method if payload size
+// exceeds limit set by Conn.MaxPayloadBytes
+var ErrFrameTooLarge = errors.New("websocket: frame payload size exceeds limit")
+
+// Addr is an implementation of net.Addr for WebSocket.
+type Addr struct {
+ *url.URL
+}
+
+// Network returns the network type for a WebSocket, "websocket".
+func (addr *Addr) Network() string { return "websocket" }
+
+// Config is a WebSocket configuration
+type Config struct {
+ // A WebSocket server address.
+ Location *url.URL
+
+ // A Websocket client origin.
+ Origin *url.URL
+
+ // WebSocket subprotocols.
+ Protocol []string
+
+ // WebSocket protocol version.
+ Version int
+
+ // TLS config for secure WebSocket (wss).
+ TlsConfig *tls.Config
+
+ // Additional header fields to be sent in WebSocket opening handshake.
+ Header http.Header
+
+ // Dialer used when opening websocket connections.
+ Dialer *net.Dialer
+
+ handshakeData map[string]string
+}
+
+// serverHandshaker is an interface to handle WebSocket server side handshake.
+type serverHandshaker interface {
+ // ReadHandshake reads handshake request message from client.
+ // Returns http response code and error if any.
+ ReadHandshake(buf *bufio.Reader, req *http.Request) (code int, err error)
+
+ // AcceptHandshake accepts the client handshake request and sends
+ // handshake response back to client.
+ AcceptHandshake(buf *bufio.Writer) (err error)
+
+ // NewServerConn creates a new WebSocket connection.
+ NewServerConn(buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) (conn *Conn)
+}
+
+// frameReader is an interface to read a WebSocket frame.
+type frameReader interface {
+ // Reader is to read payload of the frame.
+ io.Reader
+
+ // PayloadType returns payload type.
+ PayloadType() byte
+
+ // HeaderReader returns a reader to read header of the frame.
+ HeaderReader() io.Reader
+
+ // TrailerReader returns a reader to read trailer of the frame.
+ // If it returns nil, there is no trailer in the frame.
+ TrailerReader() io.Reader
+
+ // Len returns total length of the frame, including header and trailer.
+ Len() int
+}
+
+// frameReaderFactory is an interface to creates new frame reader.
+type frameReaderFactory interface {
+ NewFrameReader() (r frameReader, err error)
+}
+
+// frameWriter is an interface to write a WebSocket frame.
+type frameWriter interface {
+ // Writer is to write payload of the frame.
+ io.WriteCloser
+}
+
+// frameWriterFactory is an interface to create new frame writer.
+type frameWriterFactory interface {
+ NewFrameWriter(payloadType byte) (w frameWriter, err error)
+}
+
+type frameHandler interface {
+ HandleFrame(frame frameReader) (r frameReader, err error)
+ WriteClose(status int) (err error)
+}
+
+// Conn represents a WebSocket connection.
+//
+// Multiple goroutines may invoke methods on a Conn simultaneously.
+type Conn struct {
+ config *Config
+ request *http.Request
+
+ buf *bufio.ReadWriter
+ rwc io.ReadWriteCloser
+
+ rio sync.Mutex
+ frameReaderFactory
+ frameReader
+
+ wio sync.Mutex
+ frameWriterFactory
+
+ frameHandler
+ PayloadType byte
+ defaultCloseStatus int
+
+ // MaxPayloadBytes limits the size of frame payload received over Conn
+ // by Codec's Receive method. If zero, DefaultMaxPayloadBytes is used.
+ MaxPayloadBytes int
+}
+
+// Read implements the io.Reader interface:
+// it reads data of a frame from the WebSocket connection.
+// if msg is not large enough for the frame data, it fills the msg and next Read
+// will read the rest of the frame data.
+// it reads Text frame or Binary frame.
+func (ws *Conn) Read(msg []byte) (n int, err error) {
+ ws.rio.Lock()
+ defer ws.rio.Unlock()
+again:
+ if ws.frameReader == nil {
+ frame, err := ws.frameReaderFactory.NewFrameReader()
+ if err != nil {
+ return 0, err
+ }
+ ws.frameReader, err = ws.frameHandler.HandleFrame(frame)
+ if err != nil {
+ return 0, err
+ }
+ if ws.frameReader == nil {
+ goto again
+ }
+ }
+ n, err = ws.frameReader.Read(msg)
+ if err == io.EOF {
+ if trailer := ws.frameReader.TrailerReader(); trailer != nil {
+ io.Copy(ioutil.Discard, trailer)
+ }
+ ws.frameReader = nil
+ goto again
+ }
+ return n, err
+}
+
+// Write implements the io.Writer interface:
+// it writes data as a frame to the WebSocket connection.
+func (ws *Conn) Write(msg []byte) (n int, err error) {
+ ws.wio.Lock()
+ defer ws.wio.Unlock()
+ w, err := ws.frameWriterFactory.NewFrameWriter(ws.PayloadType)
+ if err != nil {
+ return 0, err
+ }
+ n, err = w.Write(msg)
+ w.Close()
+ return n, err
+}
+
+// Close implements the io.Closer interface.
+func (ws *Conn) Close() error {
+ err := ws.frameHandler.WriteClose(ws.defaultCloseStatus)
+ err1 := ws.rwc.Close()
+ if err != nil {
+ return err
+ }
+ return err1
+}
+
+func (ws *Conn) IsClientConn() bool { return ws.request == nil }
+func (ws *Conn) IsServerConn() bool { return ws.request != nil }
+
+// LocalAddr returns the WebSocket Origin for the connection for client, or
+// the WebSocket location for server.
+func (ws *Conn) LocalAddr() net.Addr {
+ if ws.IsClientConn() {
+ return &Addr{ws.config.Origin}
+ }
+ return &Addr{ws.config.Location}
+}
+
+// RemoteAddr returns the WebSocket location for the connection for client, or
+// the Websocket Origin for server.
+func (ws *Conn) RemoteAddr() net.Addr {
+ if ws.IsClientConn() {
+ return &Addr{ws.config.Location}
+ }
+ return &Addr{ws.config.Origin}
+}
+
+var errSetDeadline = errors.New("websocket: cannot set deadline: not using a net.Conn")
+
+// SetDeadline sets the connection's network read & write deadlines.
+func (ws *Conn) SetDeadline(t time.Time) error {
+ if conn, ok := ws.rwc.(net.Conn); ok {
+ return conn.SetDeadline(t)
+ }
+ return errSetDeadline
+}
+
+// SetReadDeadline sets the connection's network read deadline.
+func (ws *Conn) SetReadDeadline(t time.Time) error {
+ if conn, ok := ws.rwc.(net.Conn); ok {
+ return conn.SetReadDeadline(t)
+ }
+ return errSetDeadline
+}
+
+// SetWriteDeadline sets the connection's network write deadline.
+func (ws *Conn) SetWriteDeadline(t time.Time) error {
+ if conn, ok := ws.rwc.(net.Conn); ok {
+ return conn.SetWriteDeadline(t)
+ }
+ return errSetDeadline
+}
+
+// Config returns the WebSocket config.
+func (ws *Conn) Config() *Config { return ws.config }
+
+// Request returns the http request upgraded to the WebSocket.
+// It is nil for client side.
+func (ws *Conn) Request() *http.Request { return ws.request }
+
+// Codec represents a symmetric pair of functions that implement a codec.
+type Codec struct {
+ Marshal func(v interface{}) (data []byte, payloadType byte, err error)
+ Unmarshal func(data []byte, payloadType byte, v interface{}) (err error)
+}
+
+// Send sends v marshaled by cd.Marshal as single frame to ws.
+func (cd Codec) Send(ws *Conn, v interface{}) (err error) {
+ data, payloadType, err := cd.Marshal(v)
+ if err != nil {
+ return err
+ }
+ ws.wio.Lock()
+ defer ws.wio.Unlock()
+ w, err := ws.frameWriterFactory.NewFrameWriter(payloadType)
+ if err != nil {
+ return err
+ }
+ _, err = w.Write(data)
+ w.Close()
+ return err
+}
+
+// Receive receives single frame from ws, unmarshaled by cd.Unmarshal and stores
+// in v. The whole frame payload is read to an in-memory buffer; max size of
+// payload is defined by ws.MaxPayloadBytes. If frame payload size exceeds
+// limit, ErrFrameTooLarge is returned; in this case frame is not read off wire
+// completely. The next call to Receive would read and discard leftover data of
+// previous oversized frame before processing next frame.
+func (cd Codec) Receive(ws *Conn, v interface{}) (err error) {
+ ws.rio.Lock()
+ defer ws.rio.Unlock()
+ if ws.frameReader != nil {
+ _, err = io.Copy(ioutil.Discard, ws.frameReader)
+ if err != nil {
+ return err
+ }
+ ws.frameReader = nil
+ }
+again:
+ frame, err := ws.frameReaderFactory.NewFrameReader()
+ if err != nil {
+ return err
+ }
+ frame, err = ws.frameHandler.HandleFrame(frame)
+ if err != nil {
+ return err
+ }
+ if frame == nil {
+ goto again
+ }
+ maxPayloadBytes := ws.MaxPayloadBytes
+ if maxPayloadBytes == 0 {
+ maxPayloadBytes = DefaultMaxPayloadBytes
+ }
+ if hf, ok := frame.(*hybiFrameReader); ok && hf.header.Length > int64(maxPayloadBytes) {
+ // payload size exceeds limit, no need to call Unmarshal
+ //
+ // set frameReader to current oversized frame so that
+ // the next call to this function can drain leftover
+ // data before processing the next frame
+ ws.frameReader = frame
+ return ErrFrameTooLarge
+ }
+ payloadType := frame.PayloadType()
+ data, err := ioutil.ReadAll(frame)
+ if err != nil {
+ return err
+ }
+ return cd.Unmarshal(data, payloadType, v)
+}
+
+func marshal(v interface{}) (msg []byte, payloadType byte, err error) {
+ switch data := v.(type) {
+ case string:
+ return []byte(data), TextFrame, nil
+ case []byte:
+ return data, BinaryFrame, nil
+ }
+ return nil, UnknownFrame, ErrNotSupported
+}
+
+func unmarshal(msg []byte, payloadType byte, v interface{}) (err error) {
+ switch data := v.(type) {
+ case *string:
+ *data = string(msg)
+ return nil
+ case *[]byte:
+ *data = msg
+ return nil
+ }
+ return ErrNotSupported
+}
+
+/*
+Message is a codec to send/receive text/binary data in a frame on WebSocket connection.
+To send/receive text frame, use string type.
+To send/receive binary frame, use []byte type.
+
+Trivial usage:
+
+ import "websocket"
+
+ // receive text frame
+ var message string
+ websocket.Message.Receive(ws, &message)
+
+ // send text frame
+ message = "hello"
+ websocket.Message.Send(ws, message)
+
+ // receive binary frame
+ var data []byte
+ websocket.Message.Receive(ws, &data)
+
+ // send binary frame
+ data = []byte{0, 1, 2}
+ websocket.Message.Send(ws, data)
+
+*/
+var Message = Codec{marshal, unmarshal}
+
+func jsonMarshal(v interface{}) (msg []byte, payloadType byte, err error) {
+ msg, err = json.Marshal(v)
+ return msg, TextFrame, err
+}
+
+func jsonUnmarshal(msg []byte, payloadType byte, v interface{}) (err error) {
+ return json.Unmarshal(msg, v)
+}
+
+/*
+JSON is a codec to send/receive JSON data in a frame from a WebSocket connection.
+
+Trivial usage:
+
+ import "websocket"
+
+ type T struct {
+ Msg string
+ Count int
+ }
+
+ // receive JSON type T
+ var data T
+ websocket.JSON.Receive(ws, &data)
+
+ // send JSON type T
+ websocket.JSON.Send(ws, data)
+*/
+var JSON = Codec{jsonMarshal, jsonUnmarshal}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/websocket/websocket_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/websocket/websocket_test.go
new file mode 100644
index 000000000..2054ce85a
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/websocket/websocket_test.go
@@ -0,0 +1,665 @@
+// Copyright 2009 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 websocket
+
+import (
+ "bytes"
+ "crypto/rand"
+ "fmt"
+ "io"
+ "log"
+ "net"
+ "net/http"
+ "net/http/httptest"
+ "net/url"
+ "reflect"
+ "runtime"
+ "strings"
+ "sync"
+ "testing"
+ "time"
+)
+
+var serverAddr string
+var once sync.Once
+
+func echoServer(ws *Conn) {
+ defer ws.Close()
+ io.Copy(ws, ws)
+}
+
+type Count struct {
+ S string
+ N int
+}
+
+func countServer(ws *Conn) {
+ defer ws.Close()
+ for {
+ var count Count
+ err := JSON.Receive(ws, &count)
+ if err != nil {
+ return
+ }
+ count.N++
+ count.S = strings.Repeat(count.S, count.N)
+ err = JSON.Send(ws, count)
+ if err != nil {
+ return
+ }
+ }
+}
+
+type testCtrlAndDataHandler struct {
+ hybiFrameHandler
+}
+
+func (h *testCtrlAndDataHandler) WritePing(b []byte) (int, error) {
+ h.hybiFrameHandler.conn.wio.Lock()
+ defer h.hybiFrameHandler.conn.wio.Unlock()
+ w, err := h.hybiFrameHandler.conn.frameWriterFactory.NewFrameWriter(PingFrame)
+ if err != nil {
+ return 0, err
+ }
+ n, err := w.Write(b)
+ w.Close()
+ return n, err
+}
+
+func ctrlAndDataServer(ws *Conn) {
+ defer ws.Close()
+ h := &testCtrlAndDataHandler{hybiFrameHandler: hybiFrameHandler{conn: ws}}
+ ws.frameHandler = h
+
+ go func() {
+ for i := 0; ; i++ {
+ var b []byte
+ if i%2 != 0 { // with or without payload
+ b = []byte(fmt.Sprintf("#%d-CONTROL-FRAME-FROM-SERVER", i))
+ }
+ if _, err := h.WritePing(b); err != nil {
+ break
+ }
+ if _, err := h.WritePong(b); err != nil { // unsolicited pong
+ break
+ }
+ time.Sleep(10 * time.Millisecond)
+ }
+ }()
+
+ b := make([]byte, 128)
+ for {
+ n, err := ws.Read(b)
+ if err != nil {
+ break
+ }
+ if _, err := ws.Write(b[:n]); err != nil {
+ break
+ }
+ }
+}
+
+func subProtocolHandshake(config *Config, req *http.Request) error {
+ for _, proto := range config.Protocol {
+ if proto == "chat" {
+ config.Protocol = []string{proto}
+ return nil
+ }
+ }
+ return ErrBadWebSocketProtocol
+}
+
+func subProtoServer(ws *Conn) {
+ for _, proto := range ws.Config().Protocol {
+ io.WriteString(ws, proto)
+ }
+}
+
+func startServer() {
+ http.Handle("/echo", Handler(echoServer))
+ http.Handle("/count", Handler(countServer))
+ http.Handle("/ctrldata", Handler(ctrlAndDataServer))
+ subproto := Server{
+ Handshake: subProtocolHandshake,
+ Handler: Handler(subProtoServer),
+ }
+ http.Handle("/subproto", subproto)
+ server := httptest.NewServer(nil)
+ serverAddr = server.Listener.Addr().String()
+ log.Print("Test WebSocket server listening on ", serverAddr)
+}
+
+func newConfig(t *testing.T, path string) *Config {
+ config, _ := NewConfig(fmt.Sprintf("ws://%s%s", serverAddr, path), "http://localhost")
+ return config
+}
+
+func TestEcho(t *testing.T) {
+ once.Do(startServer)
+
+ // websocket.Dial()
+ client, err := net.Dial("tcp", serverAddr)
+ if err != nil {
+ t.Fatal("dialing", err)
+ }
+ conn, err := NewClient(newConfig(t, "/echo"), client)
+ if err != nil {
+ t.Errorf("WebSocket handshake error: %v", err)
+ return
+ }
+
+ msg := []byte("hello, world\n")
+ if _, err := conn.Write(msg); err != nil {
+ t.Errorf("Write: %v", err)
+ }
+ var actual_msg = make([]byte, 512)
+ n, err := conn.Read(actual_msg)
+ if err != nil {
+ t.Errorf("Read: %v", err)
+ }
+ actual_msg = actual_msg[0:n]
+ if !bytes.Equal(msg, actual_msg) {
+ t.Errorf("Echo: expected %q got %q", msg, actual_msg)
+ }
+ conn.Close()
+}
+
+func TestAddr(t *testing.T) {
+ once.Do(startServer)
+
+ // websocket.Dial()
+ client, err := net.Dial("tcp", serverAddr)
+ if err != nil {
+ t.Fatal("dialing", err)
+ }
+ conn, err := NewClient(newConfig(t, "/echo"), client)
+ if err != nil {
+ t.Errorf("WebSocket handshake error: %v", err)
+ return
+ }
+
+ ra := conn.RemoteAddr().String()
+ if !strings.HasPrefix(ra, "ws://") || !strings.HasSuffix(ra, "/echo") {
+ t.Errorf("Bad remote addr: %v", ra)
+ }
+ la := conn.LocalAddr().String()
+ if !strings.HasPrefix(la, "http://") {
+ t.Errorf("Bad local addr: %v", la)
+ }
+ conn.Close()
+}
+
+func TestCount(t *testing.T) {
+ once.Do(startServer)
+
+ // websocket.Dial()
+ client, err := net.Dial("tcp", serverAddr)
+ if err != nil {
+ t.Fatal("dialing", err)
+ }
+ conn, err := NewClient(newConfig(t, "/count"), client)
+ if err != nil {
+ t.Errorf("WebSocket handshake error: %v", err)
+ return
+ }
+
+ var count Count
+ count.S = "hello"
+ if err := JSON.Send(conn, count); err != nil {
+ t.Errorf("Write: %v", err)
+ }
+ if err := JSON.Receive(conn, &count); err != nil {
+ t.Errorf("Read: %v", err)
+ }
+ if count.N != 1 {
+ t.Errorf("count: expected %d got %d", 1, count.N)
+ }
+ if count.S != "hello" {
+ t.Errorf("count: expected %q got %q", "hello", count.S)
+ }
+ if err := JSON.Send(conn, count); err != nil {
+ t.Errorf("Write: %v", err)
+ }
+ if err := JSON.Receive(conn, &count); err != nil {
+ t.Errorf("Read: %v", err)
+ }
+ if count.N != 2 {
+ t.Errorf("count: expected %d got %d", 2, count.N)
+ }
+ if count.S != "hellohello" {
+ t.Errorf("count: expected %q got %q", "hellohello", count.S)
+ }
+ conn.Close()
+}
+
+func TestWithQuery(t *testing.T) {
+ once.Do(startServer)
+
+ client, err := net.Dial("tcp", serverAddr)
+ if err != nil {
+ t.Fatal("dialing", err)
+ }
+
+ config := newConfig(t, "/echo")
+ config.Location, err = url.ParseRequestURI(fmt.Sprintf("ws://%s/echo?q=v", serverAddr))
+ if err != nil {
+ t.Fatal("location url", err)
+ }
+
+ ws, err := NewClient(config, client)
+ if err != nil {
+ t.Errorf("WebSocket handshake: %v", err)
+ return
+ }
+ ws.Close()
+}
+
+func testWithProtocol(t *testing.T, subproto []string) (string, error) {
+ once.Do(startServer)
+
+ client, err := net.Dial("tcp", serverAddr)
+ if err != nil {
+ t.Fatal("dialing", err)
+ }
+
+ config := newConfig(t, "/subproto")
+ config.Protocol = subproto
+
+ ws, err := NewClient(config, client)
+ if err != nil {
+ return "", err
+ }
+ msg := make([]byte, 16)
+ n, err := ws.Read(msg)
+ if err != nil {
+ return "", err
+ }
+ ws.Close()
+ return string(msg[:n]), nil
+}
+
+func TestWithProtocol(t *testing.T) {
+ proto, err := testWithProtocol(t, []string{"chat"})
+ if err != nil {
+ t.Errorf("SubProto: unexpected error: %v", err)
+ }
+ if proto != "chat" {
+ t.Errorf("SubProto: expected %q, got %q", "chat", proto)
+ }
+}
+
+func TestWithTwoProtocol(t *testing.T) {
+ proto, err := testWithProtocol(t, []string{"test", "chat"})
+ if err != nil {
+ t.Errorf("SubProto: unexpected error: %v", err)
+ }
+ if proto != "chat" {
+ t.Errorf("SubProto: expected %q, got %q", "chat", proto)
+ }
+}
+
+func TestWithBadProtocol(t *testing.T) {
+ _, err := testWithProtocol(t, []string{"test"})
+ if err != ErrBadStatus {
+ t.Errorf("SubProto: expected %v, got %v", ErrBadStatus, err)
+ }
+}
+
+func TestHTTP(t *testing.T) {
+ once.Do(startServer)
+
+ // If the client did not send a handshake that matches the protocol
+ // specification, the server MUST return an HTTP response with an
+ // appropriate error code (such as 400 Bad Request)
+ resp, err := http.Get(fmt.Sprintf("http://%s/echo", serverAddr))
+ if err != nil {
+ t.Errorf("Get: error %#v", err)
+ return
+ }
+ if resp == nil {
+ t.Error("Get: resp is null")
+ return
+ }
+ if resp.StatusCode != http.StatusBadRequest {
+ t.Errorf("Get: expected %q got %q", http.StatusBadRequest, resp.StatusCode)
+ }
+}
+
+func TestTrailingSpaces(t *testing.T) {
+ // http://code.google.com/p/go/issues/detail?id=955
+ // The last runs of this create keys with trailing spaces that should not be
+ // generated by the client.
+ once.Do(startServer)
+ config := newConfig(t, "/echo")
+ for i := 0; i < 30; i++ {
+ // body
+ ws, err := DialConfig(config)
+ if err != nil {
+ t.Errorf("Dial #%d failed: %v", i, err)
+ break
+ }
+ ws.Close()
+ }
+}
+
+func TestDialConfigBadVersion(t *testing.T) {
+ once.Do(startServer)
+ config := newConfig(t, "/echo")
+ config.Version = 1234
+
+ _, err := DialConfig(config)
+
+ if dialerr, ok := err.(*DialError); ok {
+ if dialerr.Err != ErrBadProtocolVersion {
+ t.Errorf("dial expected err %q but got %q", ErrBadProtocolVersion, dialerr.Err)
+ }
+ }
+}
+
+func TestDialConfigWithDialer(t *testing.T) {
+ once.Do(startServer)
+ config := newConfig(t, "/echo")
+ config.Dialer = &net.Dialer{
+ Deadline: time.Now().Add(-time.Minute),
+ }
+ _, err := DialConfig(config)
+ dialerr, ok := err.(*DialError)
+ if !ok {
+ t.Fatalf("DialError expected, got %#v", err)
+ }
+ neterr, ok := dialerr.Err.(*net.OpError)
+ if !ok {
+ t.Fatalf("net.OpError error expected, got %#v", dialerr.Err)
+ }
+ if !neterr.Timeout() {
+ t.Fatalf("expected timeout error, got %#v", neterr)
+ }
+}
+
+func TestSmallBuffer(t *testing.T) {
+ // http://code.google.com/p/go/issues/detail?id=1145
+ // Read should be able to handle reading a fragment of a frame.
+ once.Do(startServer)
+
+ // websocket.Dial()
+ client, err := net.Dial("tcp", serverAddr)
+ if err != nil {
+ t.Fatal("dialing", err)
+ }
+ conn, err := NewClient(newConfig(t, "/echo"), client)
+ if err != nil {
+ t.Errorf("WebSocket handshake error: %v", err)
+ return
+ }
+
+ msg := []byte("hello, world\n")
+ if _, err := conn.Write(msg); err != nil {
+ t.Errorf("Write: %v", err)
+ }
+ var small_msg = make([]byte, 8)
+ n, err := conn.Read(small_msg)
+ if err != nil {
+ t.Errorf("Read: %v", err)
+ }
+ if !bytes.Equal(msg[:len(small_msg)], small_msg) {
+ t.Errorf("Echo: expected %q got %q", msg[:len(small_msg)], small_msg)
+ }
+ var second_msg = make([]byte, len(msg))
+ n, err = conn.Read(second_msg)
+ if err != nil {
+ t.Errorf("Read: %v", err)
+ }
+ second_msg = second_msg[0:n]
+ if !bytes.Equal(msg[len(small_msg):], second_msg) {
+ t.Errorf("Echo: expected %q got %q", msg[len(small_msg):], second_msg)
+ }
+ conn.Close()
+}
+
+var parseAuthorityTests = []struct {
+ in *url.URL
+ out string
+}{
+ {
+ &url.URL{
+ Scheme: "ws",
+ Host: "www.google.com",
+ },
+ "www.google.com:80",
+ },
+ {
+ &url.URL{
+ Scheme: "wss",
+ Host: "www.google.com",
+ },
+ "www.google.com:443",
+ },
+ {
+ &url.URL{
+ Scheme: "ws",
+ Host: "www.google.com:80",
+ },
+ "www.google.com:80",
+ },
+ {
+ &url.URL{
+ Scheme: "wss",
+ Host: "www.google.com:443",
+ },
+ "www.google.com:443",
+ },
+ // some invalid ones for parseAuthority. parseAuthority doesn't
+ // concern itself with the scheme unless it actually knows about it
+ {
+ &url.URL{
+ Scheme: "http",
+ Host: "www.google.com",
+ },
+ "www.google.com",
+ },
+ {
+ &url.URL{
+ Scheme: "http",
+ Host: "www.google.com:80",
+ },
+ "www.google.com:80",
+ },
+ {
+ &url.URL{
+ Scheme: "asdf",
+ Host: "127.0.0.1",
+ },
+ "127.0.0.1",
+ },
+ {
+ &url.URL{
+ Scheme: "asdf",
+ Host: "www.google.com",
+ },
+ "www.google.com",
+ },
+}
+
+func TestParseAuthority(t *testing.T) {
+ for _, tt := range parseAuthorityTests {
+ out := parseAuthority(tt.in)
+ if out != tt.out {
+ t.Errorf("got %v; want %v", out, tt.out)
+ }
+ }
+}
+
+type closerConn struct {
+ net.Conn
+ closed int // count of the number of times Close was called
+}
+
+func (c *closerConn) Close() error {
+ c.closed++
+ return c.Conn.Close()
+}
+
+func TestClose(t *testing.T) {
+ if runtime.GOOS == "plan9" {
+ t.Skip("see golang.org/issue/11454")
+ }
+
+ once.Do(startServer)
+
+ conn, err := net.Dial("tcp", serverAddr)
+ if err != nil {
+ t.Fatal("dialing", err)
+ }
+
+ cc := closerConn{Conn: conn}
+
+ client, err := NewClient(newConfig(t, "/echo"), &cc)
+ if err != nil {
+ t.Fatalf("WebSocket handshake: %v", err)
+ }
+
+ // set the deadline to ten minutes ago, which will have expired by the time
+ // client.Close sends the close status frame.
+ conn.SetDeadline(time.Now().Add(-10 * time.Minute))
+
+ if err := client.Close(); err == nil {
+ t.Errorf("ws.Close(): expected error, got %v", err)
+ }
+ if cc.closed < 1 {
+ t.Fatalf("ws.Close(): expected underlying ws.rwc.Close to be called > 0 times, got: %v", cc.closed)
+ }
+}
+
+var originTests = []struct {
+ req *http.Request
+ origin *url.URL
+}{
+ {
+ req: &http.Request{
+ Header: http.Header{
+ "Origin": []string{"http://www.example.com"},
+ },
+ },
+ origin: &url.URL{
+ Scheme: "http",
+ Host: "www.example.com",
+ },
+ },
+ {
+ req: &http.Request{},
+ },
+}
+
+func TestOrigin(t *testing.T) {
+ conf := newConfig(t, "/echo")
+ conf.Version = ProtocolVersionHybi13
+ for i, tt := range originTests {
+ origin, err := Origin(conf, tt.req)
+ if err != nil {
+ t.Error(err)
+ continue
+ }
+ if !reflect.DeepEqual(origin, tt.origin) {
+ t.Errorf("#%d: got origin %v; want %v", i, origin, tt.origin)
+ continue
+ }
+ }
+}
+
+func TestCtrlAndData(t *testing.T) {
+ once.Do(startServer)
+
+ c, err := net.Dial("tcp", serverAddr)
+ if err != nil {
+ t.Fatal(err)
+ }
+ ws, err := NewClient(newConfig(t, "/ctrldata"), c)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer ws.Close()
+
+ h := &testCtrlAndDataHandler{hybiFrameHandler: hybiFrameHandler{conn: ws}}
+ ws.frameHandler = h
+
+ b := make([]byte, 128)
+ for i := 0; i < 2; i++ {
+ data := []byte(fmt.Sprintf("#%d-DATA-FRAME-FROM-CLIENT", i))
+ if _, err := ws.Write(data); err != nil {
+ t.Fatalf("#%d: %v", i, err)
+ }
+ var ctrl []byte
+ if i%2 != 0 { // with or without payload
+ ctrl = []byte(fmt.Sprintf("#%d-CONTROL-FRAME-FROM-CLIENT", i))
+ }
+ if _, err := h.WritePing(ctrl); err != nil {
+ t.Fatalf("#%d: %v", i, err)
+ }
+ n, err := ws.Read(b)
+ if err != nil {
+ t.Fatalf("#%d: %v", i, err)
+ }
+ if !bytes.Equal(b[:n], data) {
+ t.Fatalf("#%d: got %v; want %v", i, b[:n], data)
+ }
+ }
+}
+
+func TestCodec_ReceiveLimited(t *testing.T) {
+ const limit = 2048
+ var payloads [][]byte
+ for _, size := range []int{
+ 1024,
+ 2048,
+ 4096, // receive of this message would be interrupted due to limit
+ 2048, // this one is to make sure next receive recovers discarding leftovers
+ } {
+ b := make([]byte, size)
+ rand.Read(b)
+ payloads = append(payloads, b)
+ }
+ handlerDone := make(chan struct{})
+ limitedHandler := func(ws *Conn) {
+ defer close(handlerDone)
+ ws.MaxPayloadBytes = limit
+ defer ws.Close()
+ for i, p := range payloads {
+ t.Logf("payload #%d (size %d, exceeds limit: %v)", i, len(p), len(p) > limit)
+ var recv []byte
+ err := Message.Receive(ws, &recv)
+ switch err {
+ case nil:
+ case ErrFrameTooLarge:
+ if len(p) <= limit {
+ t.Fatalf("unexpected frame size limit: expected %d bytes of payload having limit at %d", len(p), limit)
+ }
+ continue
+ default:
+ t.Fatalf("unexpected error: %v (want either nil or ErrFrameTooLarge)", err)
+ }
+ if len(recv) > limit {
+ t.Fatalf("received %d bytes of payload having limit at %d", len(recv), limit)
+ }
+ if !bytes.Equal(p, recv) {
+ t.Fatalf("received payload differs:\ngot:\t%v\nwant:\t%v", recv, p)
+ }
+ }
+ }
+ server := httptest.NewServer(Handler(limitedHandler))
+ defer server.CloseClientConnections()
+ defer server.Close()
+ addr := server.Listener.Addr().String()
+ ws, err := Dial("ws://"+addr+"/", "", "http://localhost/")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer ws.Close()
+ for i, p := range payloads {
+ if err := Message.Send(ws, p); err != nil {
+ t.Fatalf("payload #%d (size %d): %v", i, len(p), err)
+ }
+ }
+ <-handlerDone
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/xsrftoken/xsrf.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/xsrftoken/xsrf.go
new file mode 100644
index 000000000..bc861e1f3
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/xsrftoken/xsrf.go
@@ -0,0 +1,94 @@
+// Copyright 2012 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 xsrftoken provides methods for generating and validating secure XSRF tokens.
+package xsrftoken // import "golang.org/x/net/xsrftoken"
+
+import (
+ "crypto/hmac"
+ "crypto/sha1"
+ "crypto/subtle"
+ "encoding/base64"
+ "fmt"
+ "strconv"
+ "strings"
+ "time"
+)
+
+// Timeout is the duration for which XSRF tokens are valid.
+// It is exported so clients may set cookie timeouts that match generated tokens.
+const Timeout = 24 * time.Hour
+
+// clean sanitizes a string for inclusion in a token by replacing all ":"s.
+func clean(s string) string {
+ return strings.Replace(s, ":", "_", -1)
+}
+
+// Generate returns a URL-safe secure XSRF token that expires in 24 hours.
+//
+// key is a secret key for your application; it must be non-empty.
+// userID is an optional unique identifier for the user.
+// actionID is an optional action the user is taking (e.g. POSTing to a particular path).
+func Generate(key, userID, actionID string) string {
+ return generateTokenAtTime(key, userID, actionID, time.Now())
+}
+
+// generateTokenAtTime is like Generate, but returns a token that expires 24 hours from now.
+func generateTokenAtTime(key, userID, actionID string, now time.Time) string {
+ if len(key) == 0 {
+ panic("zero length xsrf secret key")
+ }
+ // Round time up and convert to milliseconds.
+ milliTime := (now.UnixNano() + 1e6 - 1) / 1e6
+
+ h := hmac.New(sha1.New, []byte(key))
+ fmt.Fprintf(h, "%s:%s:%d", clean(userID), clean(actionID), milliTime)
+
+ // Get the padded base64 string then removing the padding.
+ tok := string(h.Sum(nil))
+ tok = base64.URLEncoding.EncodeToString([]byte(tok))
+ tok = strings.TrimRight(tok, "=")
+
+ return fmt.Sprintf("%s:%d", tok, milliTime)
+}
+
+// Valid reports whether a token is a valid, unexpired token returned by Generate.
+func Valid(token, key, userID, actionID string) bool {
+ return validTokenAtTime(token, key, userID, actionID, time.Now())
+}
+
+// validTokenAtTime reports whether a token is valid at the given time.
+func validTokenAtTime(token, key, userID, actionID string, now time.Time) bool {
+ if len(key) == 0 {
+ panic("zero length xsrf secret key")
+ }
+ // Extract the issue time of the token.
+ sep := strings.LastIndex(token, ":")
+ if sep < 0 {
+ return false
+ }
+ millis, err := strconv.ParseInt(token[sep+1:], 10, 64)
+ if err != nil {
+ return false
+ }
+ issueTime := time.Unix(0, millis*1e6)
+
+ // Check that the token is not expired.
+ if now.Sub(issueTime) >= Timeout {
+ return false
+ }
+
+ // Check that the token is not from the future.
+ // Allow 1 minute grace period in case the token is being verified on a
+ // machine whose clock is behind the machine that issued the token.
+ if issueTime.After(now.Add(1 * time.Minute)) {
+ return false
+ }
+
+ expected := generateTokenAtTime(key, userID, actionID, issueTime)
+
+ // Check that the token matches the expected value.
+ // Use constant time comparison to avoid timing attacks.
+ return subtle.ConstantTimeCompare([]byte(token), []byte(expected)) == 1
+}
diff --git a/vendor/github.com/miekg/dns/vendor/golang.org/x/net/xsrftoken/xsrf_test.go b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/xsrftoken/xsrf_test.go
new file mode 100644
index 000000000..6c8e7d9b5
--- /dev/null
+++ b/vendor/github.com/miekg/dns/vendor/golang.org/x/net/xsrftoken/xsrf_test.go
@@ -0,0 +1,83 @@
+// Copyright 2012 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 xsrftoken
+
+import (
+ "encoding/base64"
+ "testing"
+ "time"
+)
+
+const (
+ key = "quay"
+ userID = "12345678"
+ actionID = "POST /form"
+)
+
+var (
+ now = time.Now()
+ oneMinuteFromNow = now.Add(1 * time.Minute)
+)
+
+func TestValidToken(t *testing.T) {
+ tok := generateTokenAtTime(key, userID, actionID, now)
+ if !validTokenAtTime(tok, key, userID, actionID, oneMinuteFromNow) {
+ t.Error("One second later: Expected token to be valid")
+ }
+ if !validTokenAtTime(tok, key, userID, actionID, now.Add(Timeout-1*time.Nanosecond)) {
+ t.Error("Just before timeout: Expected token to be valid")
+ }
+ if !validTokenAtTime(tok, key, userID, actionID, now.Add(-1*time.Minute+1*time.Millisecond)) {
+ t.Error("One minute in the past: Expected token to be valid")
+ }
+}
+
+// TestSeparatorReplacement tests that separators are being correctly substituted
+func TestSeparatorReplacement(t *testing.T) {
+ tok := generateTokenAtTime("foo:bar", "baz", "wah", now)
+ tok2 := generateTokenAtTime("foo", "bar:baz", "wah", now)
+ if tok == tok2 {
+ t.Errorf("Expected generated tokens to be different")
+ }
+}
+
+func TestInvalidToken(t *testing.T) {
+ invalidTokenTests := []struct {
+ name, key, userID, actionID string
+ t time.Time
+ }{
+ {"Bad key", "foobar", userID, actionID, oneMinuteFromNow},
+ {"Bad userID", key, "foobar", actionID, oneMinuteFromNow},
+ {"Bad actionID", key, userID, "foobar", oneMinuteFromNow},
+ {"Expired", key, userID, actionID, now.Add(Timeout + 1*time.Millisecond)},
+ {"More than 1 minute from the future", key, userID, actionID, now.Add(-1*time.Nanosecond - 1*time.Minute)},
+ }
+
+ tok := generateTokenAtTime(key, userID, actionID, now)
+ for _, itt := range invalidTokenTests {
+ if validTokenAtTime(tok, itt.key, itt.userID, itt.actionID, itt.t) {
+ t.Errorf("%v: Expected token to be invalid", itt.name)
+ }
+ }
+}
+
+// TestValidateBadData primarily tests that no unexpected panics are triggered
+// during parsing
+func TestValidateBadData(t *testing.T) {
+ badDataTests := []struct {
+ name, tok string
+ }{
+ {"Invalid Base64", "ASDab24(@)$*=="},
+ {"No delimiter", base64.URLEncoding.EncodeToString([]byte("foobar12345678"))},
+ {"Invalid time", base64.URLEncoding.EncodeToString([]byte("foobar:foobar"))},
+ {"Wrong length", "1234" + generateTokenAtTime(key, userID, actionID, now)},
+ }
+
+ for _, bdt := range badDataTests {
+ if validTokenAtTime(bdt.tok, key, userID, actionID, oneMinuteFromNow) {
+ t.Errorf("%v: Expected token to be invalid", bdt.name)
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/version.go b/vendor/github.com/miekg/dns/version.go
new file mode 100644
index 000000000..0e23cc3e1
--- /dev/null
+++ b/vendor/github.com/miekg/dns/version.go
@@ -0,0 +1,15 @@
+package dns
+
+import "fmt"
+
+// Version is current version of this library.
+var Version = V{1, 0, 3}
+
+// V holds the version of this library.
+type V struct {
+ Major, Minor, Patch int
+}
+
+func (v V) String() string {
+ return fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch)
+}
diff --git a/vendor/github.com/miekg/dns/version_test.go b/vendor/github.com/miekg/dns/version_test.go
new file mode 100644
index 000000000..61c404848
--- /dev/null
+++ b/vendor/github.com/miekg/dns/version_test.go
@@ -0,0 +1,10 @@
+package dns
+
+import "testing"
+
+func TestVersion(t *testing.T) {
+ v := V{1, 0, 0}
+ if x := v.String(); x != "1.0.0" {
+ t.Fatalf("Failed to convert version %v, got: %s", v, x)
+ }
+}
diff --git a/vendor/github.com/miekg/dns/xfr.go b/vendor/github.com/miekg/dns/xfr.go
index 2e892ea38..5d0ff5c8a 100644
--- a/vendor/github.com/miekg/dns/xfr.go
+++ b/vendor/github.com/miekg/dns/xfr.go
@@ -17,7 +17,7 @@ type Transfer struct {
DialTimeout time.Duration // net.DialTimeout, defaults to 2 seconds
ReadTimeout time.Duration // net.Conn.SetReadTimeout value for connections, defaults to 2 seconds
WriteTimeout time.Duration // net.Conn.SetWriteTimeout value for connections, defaults to 2 seconds
- TsigSecret map[string]string // Secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be fully qualified
+ TsigSecret map[string]string // Secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2)
tsigTimersOnly bool
}
diff --git a/vendor/github.com/miekg/dns/xfr_test.go b/vendor/github.com/miekg/dns/xfr_test.go
deleted file mode 100644
index e7cc6b2fa..000000000
--- a/vendor/github.com/miekg/dns/xfr_test.go
+++ /dev/null
@@ -1,184 +0,0 @@
-// +build net
-
-package dns
-
-import (
- "net"
- "strings"
- "testing"
- "time"
-)
-
-func getIP(s string) string {
- a, err := net.LookupAddr(s)
- if err != nil {
- return ""
- }
- return a[0]
-}
-
-// flaky, need to setup local server and test from that.
-func TestAXFR_Miek(t *testing.T) {
- // This test runs against a server maintained by Miek
- if testing.Short() {
- return
- }
- m := new(Msg)
- m.SetAxfr("miek.nl.")
-
- server := getIP("linode.atoom.net")
-
- tr := new(Transfer)
-
- if a, err := tr.In(m, net.JoinHostPort(server, "53")); err != nil {
- t.Fatal("failed to setup axfr: ", err)
- } else {
- for ex := range a {
- if ex.Error != nil {
- t.Errorf("error %v", ex.Error)
- break
- }
- for _, rr := range ex.RR {
- // Nothing
- }
- }
- }
-}
-
-// fails.
-func TestAXFR_NLNL_MultipleEnvelopes(t *testing.T) {
- // This test runs against a server maintained by NLnet Labs
- if testing.Short() {
- return
- }
- m := new(Msg)
- m.SetAxfr("nlnetlabs.nl.")
-
- server := getIP("open.nlnetlabs.nl.")
-
- tr := new(Transfer)
- if a, err := tr.In(m, net.JoinHostPort(server, "53")); err != nil {
- t.Fatalf("failed to setup axfr %v for server: %v", err, server)
- } else {
- for ex := range a {
- if ex.Error != nil {
- t.Errorf("error %v", ex.Error)
- break
- }
- }
- }
-}
-
-func TestAXFR_Miek_Tsig(t *testing.T) {
- // This test runs against a server maintained by Miek
- if testing.Short() {
- return
- }
- m := new(Msg)
- m.SetAxfr("example.nl.")
- m.SetTsig("axfr.", HmacMD5, 300, time.Now().Unix())
-
- tr := new(Transfer)
- tr.TsigSecret = map[string]string{"axfr.": "so6ZGir4GPAqINNh9U5c3A=="}
-
- if a, err := tr.In(m, "176.58.119.54:53"); err != nil {
- t.Fatal("failed to setup axfr: ", err)
- } else {
- for ex := range a {
- if ex.Error != nil {
- t.Errorf("error %v", ex.Error)
- break
- }
- for _, rr := range ex.RR {
- // Nothing
- }
- }
- }
-}
-
-func TestAXFR_SIDN_NSD3_NONE(t *testing.T) { testAXFRSIDN(t, "nsd", "") }
-func TestAXFR_SIDN_NSD3_MD5(t *testing.T) { testAXFRSIDN(t, "nsd", HmacMD5) }
-func TestAXFR_SIDN_NSD3_SHA1(t *testing.T) { testAXFRSIDN(t, "nsd", HmacSHA1) }
-func TestAXFR_SIDN_NSD3_SHA256(t *testing.T) { testAXFRSIDN(t, "nsd", HmacSHA256) }
-
-func TestAXFR_SIDN_NSD4_NONE(t *testing.T) { testAXFRSIDN(t, "nsd4", "") }
-func TestAXFR_SIDN_NSD4_MD5(t *testing.T) { testAXFRSIDN(t, "nsd4", HmacMD5) }
-func TestAXFR_SIDN_NSD4_SHA1(t *testing.T) { testAXFRSIDN(t, "nsd4", HmacSHA1) }
-func TestAXFR_SIDN_NSD4_SHA256(t *testing.T) { testAXFRSIDN(t, "nsd4", HmacSHA256) }
-
-func TestAXFR_SIDN_BIND9_NONE(t *testing.T) { testAXFRSIDN(t, "bind9", "") }
-func TestAXFR_SIDN_BIND9_MD5(t *testing.T) { testAXFRSIDN(t, "bind9", HmacMD5) }
-func TestAXFR_SIDN_BIND9_SHA1(t *testing.T) { testAXFRSIDN(t, "bind9", HmacSHA1) }
-func TestAXFR_SIDN_BIND9_SHA256(t *testing.T) { testAXFRSIDN(t, "bind9", HmacSHA256) }
-
-func TestAXFR_SIDN_KNOT_NONE(t *testing.T) { testAXFRSIDN(t, "knot", "") }
-func TestAXFR_SIDN_KNOT_MD5(t *testing.T) { testAXFRSIDN(t, "knot", HmacMD5) }
-func TestAXFR_SIDN_KNOT_SHA1(t *testing.T) { testAXFRSIDN(t, "knot", HmacSHA1) }
-func TestAXFR_SIDN_KNOT_SHA256(t *testing.T) { testAXFRSIDN(t, "knot", HmacSHA256) }
-
-func TestAXFR_SIDN_POWERDNS_NONE(t *testing.T) { testAXFRSIDN(t, "powerdns", "") }
-func TestAXFR_SIDN_POWERDNS_MD5(t *testing.T) { testAXFRSIDN(t, "powerdns", HmacMD5) }
-func TestAXFR_SIDN_POWERDNS_SHA1(t *testing.T) { testAXFRSIDN(t, "powerdns", HmacSHA1) }
-func TestAXFR_SIDN_POWERDNS_SHA256(t *testing.T) { testAXFRSIDN(t, "powerdns", HmacSHA256) }
-
-func TestAXFR_SIDN_YADIFA_NONE(t *testing.T) { testAXFRSIDN(t, "yadifa", "") }
-func TestAXFR_SIDN_YADIFA_MD5(t *testing.T) { testAXFRSIDN(t, "yadifa", HmacMD5) }
-func TestAXFR_SIDN_YADIFA_SHA1(t *testing.T) { testAXFRSIDN(t, "yadifa", HmacSHA1) }
-func TestAXFR_SIDN_YADIFA_SHA256(t *testing.T) { testAXFRSIDN(t, "yadifa", HmacSHA256) }
-
-func testAXFRSIDN(t *testing.T, host, alg string) {
- // This tests run against a server maintained by SIDN labs, see:
- // https://workbench.sidnlabs.nl/
- if testing.Short() {
- return
- }
- x := new(Transfer)
- x.TsigSecret = map[string]string{
- "wb_md5.": "Wu/utSasZUkoeCNku152Zw==",
- "wb_sha1_longkey.": "uhMpEhPq/RAD9Bt4mqhfmi+7ZdKmjLQb/lcrqYPXR4s/nnbsqw==",
- "wb_sha256.": "npfrIJjt/MJOjGJoBNZtsjftKMhkSpIYMv2RzRZt1f8=",
- }
- keyname := map[string]string{
- HmacMD5: "wb_md5.",
- HmacSHA1: "wb_sha1_longkey.",
- HmacSHA256: "wb_sha256.",
- }[alg]
-
- m := new(Msg)
- m.SetAxfr("types.wb.sidnlabs.nl.")
- if keyname != "" {
- m.SetTsig(keyname, alg, 300, time.Now().Unix())
- }
- c, err := x.In(m, host+".sidnlabs.nl:53")
- if err != nil {
- t.Fatal(err)
- }
- for e := range c {
- if e.Error != nil {
- t.Fatal(e.Error)
- }
- }
-}
-
-func TestAXFRFailNotAuth(t *testing.T) {
- // This tests run against a server maintained by SIDN labs, see:
- // https://workbench.sidnlabs.nl/
- if testing.Short() {
- return
- }
- x := new(Transfer)
-
- m := new(Msg)
- m.SetAxfr("sidnlabs.nl.")
- c, err := x.In(m, "yadifa.sidnlabs.nl:53")
- if err != nil {
- t.Fatal(err)
- }
- for e := range c {
- if e.Error != nil {
- if !strings.HasPrefix(e.Error.Error(), "dns: bad xfr rcode:") {
- t.Fatal(e.Error)
- }
- }
- }
-}
diff --git a/vendor/github.com/miekg/dns/zcompress.go b/vendor/github.com/miekg/dns/zcompress.go
index ee9841ed5..c2503204d 100644
--- a/vendor/github.com/miekg/dns/zcompress.go
+++ b/vendor/github.com/miekg/dns/zcompress.go
@@ -1,5 +1,4 @@
-// *** DO NOT MODIFY ***
-// AUTOGENERATED BY go generate from compress_generate.go
+// Code generated by "go run compress_generate.go"; DO NOT EDIT.
package dns
diff --git a/vendor/github.com/miekg/dns/zmsg.go b/vendor/github.com/miekg/dns/zmsg.go
index 418fb1fe3..0d1f6f4da 100644
--- a/vendor/github.com/miekg/dns/zmsg.go
+++ b/vendor/github.com/miekg/dns/zmsg.go
@@ -1,5 +1,4 @@
-// *** DO NOT MODIFY ***
-// AUTOGENERATED BY go generate from msg_generate.go
+// Code generated by "go run msg_generate.go"; DO NOT EDIT.
package dns
@@ -189,6 +188,28 @@ func (rr *CNAME) pack(msg []byte, off int, compression map[string]int, compress
return off, nil
}
+func (rr *CSYNC) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packUint32(rr.Serial, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint16(rr.Flags, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packDataNsec(rr.TypeBitMap, msg, off)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
func (rr *DHCID) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
off, err := rr.Hdr.pack(msg, off, compression, compress)
if err != nil {
@@ -1303,7 +1324,7 @@ func (rr *TKEY) pack(msg []byte, off int, compression map[string]int, compress b
if err != nil {
return off, err
}
- off, err = packString(rr.Key, msg, off)
+ off, err = packStringHex(rr.Key, msg, off)
if err != nil {
return off, err
}
@@ -1311,7 +1332,7 @@ func (rr *TKEY) pack(msg []byte, off int, compression map[string]int, compress b
if err != nil {
return off, err
}
- off, err = packString(rr.OtherData, msg, off)
+ off, err = packStringHex(rr.OtherData, msg, off)
if err != nil {
return off, err
}
@@ -1721,6 +1742,37 @@ func unpackCNAME(h RR_Header, msg []byte, off int) (RR, int, error) {
return rr, off, err
}
+func unpackCSYNC(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(CSYNC)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Serial, off, err = unpackUint32(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Flags, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.TypeBitMap, off, err = unpackDataNsec(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
func unpackDHCID(h RR_Header, msg []byte, off int) (RR, int, error) {
rr := new(DHCID)
rr.Hdr = h
@@ -3265,13 +3317,10 @@ func unpackTKEY(h RR_Header, msg []byte, off int) (RR, int, error) {
if off == len(msg) {
return rr, off, nil
}
- rr.Key, off, err = unpackString(msg, off)
+ rr.Key, off, err = unpackStringHex(msg, off, off+int(rr.KeySize))
if err != nil {
return rr, off, err
}
- if off == len(msg) {
- return rr, off, nil
- }
rr.OtherLen, off, err = unpackUint16(msg, off)
if err != nil {
return rr, off, err
@@ -3279,7 +3328,7 @@ func unpackTKEY(h RR_Header, msg []byte, off int) (RR, int, error) {
if off == len(msg) {
return rr, off, nil
}
- rr.OtherData, off, err = unpackString(msg, off)
+ rr.OtherData, off, err = unpackStringHex(msg, off, off+int(rr.OtherLen))
if err != nil {
return rr, off, err
}
@@ -3504,6 +3553,7 @@ var typeToUnpack = map[uint16]func(RR_Header, []byte, int) (RR, int, error){
TypeCDS: unpackCDS,
TypeCERT: unpackCERT,
TypeCNAME: unpackCNAME,
+ TypeCSYNC: unpackCSYNC,
TypeDHCID: unpackDHCID,
TypeDLV: unpackDLV,
TypeDNAME: unpackDNAME,
diff --git a/vendor/github.com/miekg/dns/ztypes.go b/vendor/github.com/miekg/dns/ztypes.go
index 0613ba09d..abd75dd91 100644
--- a/vendor/github.com/miekg/dns/ztypes.go
+++ b/vendor/github.com/miekg/dns/ztypes.go
@@ -1,5 +1,4 @@
-// *** DO NOT MODIFY ***
-// AUTOGENERATED BY go generate from types_generate.go
+// Code generated by "go run types_generate.go"; DO NOT EDIT.
package dns
@@ -20,6 +19,7 @@ var TypeToRR = map[uint16]func() RR{
TypeCDS: func() RR { return new(CDS) },
TypeCERT: func() RR { return new(CERT) },
TypeCNAME: func() RR { return new(CNAME) },
+ TypeCSYNC: func() RR { return new(CSYNC) },
TypeDHCID: func() RR { return new(DHCID) },
TypeDLV: func() RR { return new(DLV) },
TypeDNAME: func() RR { return new(DNAME) },
@@ -94,6 +94,7 @@ var TypeToString = map[uint16]string{
TypeCDS: "CDS",
TypeCERT: "CERT",
TypeCNAME: "CNAME",
+ TypeCSYNC: "CSYNC",
TypeDHCID: "DHCID",
TypeDLV: "DLV",
TypeDNAME: "DNAME",
@@ -173,6 +174,7 @@ func (rr *CDNSKEY) Header() *RR_Header { return &rr.Hdr }
func (rr *CDS) Header() *RR_Header { return &rr.Hdr }
func (rr *CERT) Header() *RR_Header { return &rr.Hdr }
func (rr *CNAME) Header() *RR_Header { return &rr.Hdr }
+func (rr *CSYNC) Header() *RR_Header { return &rr.Hdr }
func (rr *DHCID) Header() *RR_Header { return &rr.Hdr }
func (rr *DLV) Header() *RR_Header { return &rr.Hdr }
func (rr *DNAME) Header() *RR_Header { return &rr.Hdr }
@@ -345,7 +347,7 @@ func (rr *HIP) len() int {
l++ // HitLength
l++ // PublicKeyAlgorithm
l += 2 // PublicKeyLength
- l += len(rr.Hit)/2 + 1
+ l += len(rr.Hit) / 2
l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
for _, x := range rr.RendezvousServers {
l += len(x) + 1
@@ -468,7 +470,7 @@ func (rr *NSEC3PARAM) len() int {
l++ // Flags
l += 2 // Iterations
l++ // SaltLength
- l += len(rr.Salt)/2 + 1
+ l += len(rr.Salt) / 2
return l
}
func (rr *OPENPGPKEY) len() int {
@@ -589,9 +591,9 @@ func (rr *TKEY) len() int {
l += 2 // Mode
l += 2 // Error
l += 2 // KeySize
- l += len(rr.Key) + 1
+ l += len(rr.Key) / 2
l += 2 // OtherLen
- l += len(rr.OtherData) + 1
+ l += len(rr.OtherData) / 2
return l
}
func (rr *TLSA) len() int {
@@ -608,11 +610,11 @@ func (rr *TSIG) len() int {
l += 6 // TimeSigned
l += 2 // Fudge
l += 2 // MACSize
- l += len(rr.MAC)/2 + 1
+ l += len(rr.MAC) / 2
l += 2 // OrigId
l += 2 // Error
l += 2 // OtherLen
- l += len(rr.OtherData)/2 + 1
+ l += len(rr.OtherData) / 2
return l
}
func (rr *TXT) len() int {
@@ -672,6 +674,11 @@ func (rr *CERT) copy() RR {
func (rr *CNAME) copy() RR {
return &CNAME{*rr.Hdr.copyHeader(), rr.Target}
}
+func (rr *CSYNC) copy() RR {
+ TypeBitMap := make([]uint16, len(rr.TypeBitMap))
+ copy(TypeBitMap, rr.TypeBitMap)
+ return &CSYNC{*rr.Hdr.copyHeader(), rr.Serial, rr.Flags, TypeBitMap}
+}
func (rr *DHCID) copy() RR {
return &DHCID{*rr.Hdr.copyHeader(), rr.Digest}
}
diff --git a/vendor/github.com/mssola/user_agent/LICENSE b/vendor/github.com/mssola/user_agent/LICENSE
index ede19fbfb..1c42691ce 100644
--- a/vendor/github.com/mssola/user_agent/LICENSE
+++ b/vendor/github.com/mssola/user_agent/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2012-2017 Miquel Sabaté Solà
+Copyright (c) 2012-2018 Miquel Sabaté Solà
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
diff --git a/vendor/github.com/mssola/user_agent/README.md b/vendor/github.com/mssola/user_agent/README.md
index 575977df2..60427ec53 100644
--- a/vendor/github.com/mssola/user_agent/README.md
+++ b/vendor/github.com/mssola/user_agent/README.md
@@ -48,4 +48,4 @@ func main() {
}
~~~
-Copyright &copy; 2012-2017 Miquel Sabaté Solà, released under the MIT License.
+Copyright &copy; 2012-2018 Miquel Sabaté Solà, released under the MIT License.
diff --git a/vendor/github.com/mssola/user_agent/all_test.go b/vendor/github.com/mssola/user_agent/all_test.go
index fb0cf054e..a5d5ee648 100644
--- a/vendor/github.com/mssola/user_agent/all_test.go
+++ b/vendor/github.com/mssola/user_agent/all_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2012-2017 Miquel Sabaté Solà <mikisabate@gmail.com>
+// Copyright (C) 2012-2018 Miquel Sabaté Solà <mikisabate@gmail.com>
// This file is licensed under the MIT license.
// See the LICENSE file.
@@ -25,11 +25,16 @@ var uastrings = []struct {
expected: "Mozilla:5.0 Browser:Googlebot-2.1 Bot:true Mobile:false",
},
{
- title: "GoogleBotSmartphone",
+ title: "GoogleBotSmartphone (iPhone)",
ua: "Mozilla/5.0 (iPhone; CPU iPhone OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)",
expected: "Mozilla:5.0 Browser:Googlebot-2.1 Bot:true Mobile:true",
},
{
+ title: "GoogleBotSmartphone (Android)",
+ ua: "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5X Build/MMB29P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.96 Mobile Safari/537.36 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)",
+ expected: "Mozilla:5.0 Browser:Googlebot-2.1 Bot:true Mobile:true",
+ },
+ {
title: "BingBot",
ua: "Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)",
expected: "Mozilla:5.0 Browser:bingbot-2.0 Bot:true Mobile:false",
diff --git a/vendor/github.com/mssola/user_agent/bot.go b/vendor/github.com/mssola/user_agent/bot.go
index a6222d17f..acccd51d6 100644
--- a/vendor/github.com/mssola/user_agent/bot.go
+++ b/vendor/github.com/mssola/user_agent/bot.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2017 Miquel Sabaté Solà <mikisabate@gmail.com>
+// Copyright (C) 2014-2018 Miquel Sabaté Solà <mikisabate@gmail.com>
// This file is licensed under the MIT license.
// See the LICENSE file.
diff --git a/vendor/github.com/mssola/user_agent/browser.go b/vendor/github.com/mssola/user_agent/browser.go
index fbed92176..c6a1d2469 100644
--- a/vendor/github.com/mssola/user_agent/browser.go
+++ b/vendor/github.com/mssola/user_agent/browser.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2012-2017 Miquel Sabaté Solà <mikisabate@gmail.com>
+// Copyright (C) 2012-2018 Miquel Sabaté Solà <mikisabate@gmail.com>
// This file is licensed under the MIT license.
// See the LICENSE file.
diff --git a/vendor/github.com/mssola/user_agent/operating_systems.go b/vendor/github.com/mssola/user_agent/operating_systems.go
index aebd8b394..ad4d56680 100644
--- a/vendor/github.com/mssola/user_agent/operating_systems.go
+++ b/vendor/github.com/mssola/user_agent/operating_systems.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2012-2017 Miquel Sabaté Solà <mikisabate@gmail.com>
+// Copyright (C) 2012-2018 Miquel Sabaté Solà <mikisabate@gmail.com>
// This file is licensed under the MIT license.
// See the LICENSE file.
@@ -88,6 +88,8 @@ func webkit(p *UserAgent, comment []string) {
}
if len(comment) > 3 {
p.localization = comment[3]
+ } else if len(comment) == 3 {
+ _ = p.googleBot()
}
} else if len(comment) > 0 {
if len(comment) > 3 {
diff --git a/vendor/github.com/mssola/user_agent/user_agent.go b/vendor/github.com/mssola/user_agent/user_agent.go
index 36e8d1bfa..436e94980 100644
--- a/vendor/github.com/mssola/user_agent/user_agent.go
+++ b/vendor/github.com/mssola/user_agent/user_agent.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2012-2017 Miquel Sabaté Solà <mikisabate@gmail.com>
+// Copyright (C) 2012-2018 Miquel Sabaté Solà <mikisabate@gmail.com>
// This file is licensed under the MIT license.
// See the LICENSE file.
diff --git a/vendor/github.com/pelletier/go-toml/keysparsing.go b/vendor/github.com/pelletier/go-toml/keysparsing.go
index 9707c6884..0da938b03 100644
--- a/vendor/github.com/pelletier/go-toml/keysparsing.go
+++ b/vendor/github.com/pelletier/go-toml/keysparsing.go
@@ -23,19 +23,19 @@ var escapeSequenceMap = map[rune]rune{
type parseKeyState int
const (
- BARE parseKeyState = iota
- BASIC
- LITERAL
- ESC
- UNICODE_4
- UNICODE_8
+ bare parseKeyState = iota
+ basic
+ literal
+ esc
+ unicode4
+ unicode8
)
func parseKey(key string) ([]string, error) {
groups := []string{}
var buffer bytes.Buffer
var hex bytes.Buffer
- state := BARE
+ state := bare
wasInQuotes := false
ignoreSpace := true
expectDot := false
@@ -48,66 +48,66 @@ func parseKey(key string) ([]string, error) {
ignoreSpace = false
}
- if state == ESC {
+ if state == esc {
if char == 'u' {
- state = UNICODE_4
+ state = unicode4
hex.Reset()
} else if char == 'U' {
- state = UNICODE_8
+ state = unicode8
hex.Reset()
} else if newChar, ok := escapeSequenceMap[char]; ok {
buffer.WriteRune(newChar)
- state = BASIC
+ state = basic
} else {
return nil, fmt.Errorf(`invalid escape sequence \%c`, char)
}
continue
}
- if state == UNICODE_4 || state == UNICODE_8 {
+ if state == unicode4 || state == unicode8 {
if isHexDigit(char) {
hex.WriteRune(char)
}
- if (state == UNICODE_4 && hex.Len() == 4) || (state == UNICODE_8 && hex.Len() == 8) {
+ if (state == unicode4 && hex.Len() == 4) || (state == unicode8 && hex.Len() == 8) {
if value, err := strconv.ParseInt(hex.String(), 16, 32); err == nil {
buffer.WriteRune(rune(value))
} else {
return nil, err
}
- state = BASIC
+ state = basic
}
continue
}
switch char {
case '\\':
- if state == BASIC {
- state = ESC
- } else if state == LITERAL {
+ if state == basic {
+ state = esc
+ } else if state == literal {
buffer.WriteRune(char)
}
case '\'':
- if state == BARE {
- state = LITERAL
- } else if state == LITERAL {
+ if state == bare {
+ state = literal
+ } else if state == literal {
groups = append(groups, buffer.String())
buffer.Reset()
wasInQuotes = true
- state = BARE
+ state = bare
}
expectDot = false
case '"':
- if state == BARE {
- state = BASIC
- } else if state == BASIC {
+ if state == bare {
+ state = basic
+ } else if state == basic {
groups = append(groups, buffer.String())
buffer.Reset()
- state = BARE
+ state = bare
wasInQuotes = true
}
expectDot = false
case '.':
- if state != BARE {
+ if state != bare {
buffer.WriteRune(char)
} else {
if !wasInQuotes {
@@ -122,13 +122,13 @@ func parseKey(key string) ([]string, error) {
wasInQuotes = false
}
case ' ':
- if state == BASIC {
+ if state == basic {
buffer.WriteRune(char)
} else {
expectDot = true
}
default:
- if state == BARE {
+ if state == bare {
if !isValidBareChar(char) {
return nil, fmt.Errorf("invalid bare character: %c", char)
} else if expectDot {
@@ -140,10 +140,10 @@ func parseKey(key string) ([]string, error) {
}
}
- // state must be BARE at the end
- if state == ESC {
+ // state must be bare at the end
+ if state == esc {
return nil, errors.New("unfinished escape sequence")
- } else if state != BARE {
+ } else if state != bare {
return nil, errors.New("mismatched quotes")
}
diff --git a/vendor/github.com/pelletier/go-toml/lexer.go b/vendor/github.com/pelletier/go-toml/lexer.go
index 1b6647d66..209665676 100644
--- a/vendor/github.com/pelletier/go-toml/lexer.go
+++ b/vendor/github.com/pelletier/go-toml/lexer.go
@@ -575,8 +575,67 @@ func (l *tomlLexer) lexRightBracket() tomlLexStateFn {
return l.lexRvalue
}
+type validRuneFn func(r rune) bool
+
+func isValidHexRune(r rune) bool {
+ return r >= 'a' && r <= 'f' ||
+ r >= 'A' && r <= 'F' ||
+ r >= '0' && r <= '9' ||
+ r == '_'
+}
+
+func isValidOctalRune(r rune) bool {
+ return r >= '0' && r <= '7' || r == '_'
+}
+
+func isValidBinaryRune(r rune) bool {
+ return r == '0' || r == '1' || r == '_'
+}
+
func (l *tomlLexer) lexNumber() tomlLexStateFn {
r := l.peek()
+
+ if r == '0' {
+ follow := l.peekString(2)
+ if len(follow) == 2 {
+ var isValidRune validRuneFn
+ switch follow[1] {
+ case 'x':
+ isValidRune = isValidHexRune
+ case 'o':
+ isValidRune = isValidOctalRune
+ case 'b':
+ isValidRune = isValidBinaryRune
+ default:
+ if follow[1] >= 'a' && follow[1] <= 'z' || follow[1] >= 'A' && follow[1] <= 'Z' {
+ return l.errorf("unknown number base: %s. possible options are x (hex) o (octal) b (binary)", string(follow[1]))
+ }
+ }
+
+ if isValidRune != nil {
+ l.next()
+ l.next()
+ digitSeen := false
+ for {
+ next := l.peek()
+ if !isValidRune(next) {
+ break
+ }
+ digitSeen = true
+ l.next()
+ }
+
+ if !digitSeen {
+ return l.errorf("number needs at least one digit")
+ }
+
+ l.emit(tokenInteger)
+
+ return l.lexRvalue
+ }
+ }
+ }
+
if r == '+' || r == '-' {
l.next()
}
diff --git a/vendor/github.com/pelletier/go-toml/marshal.go b/vendor/github.com/pelletier/go-toml/marshal.go
index 1bbdfa1d8..6280225e9 100644
--- a/vendor/github.com/pelletier/go-toml/marshal.go
+++ b/vendor/github.com/pelletier/go-toml/marshal.go
@@ -20,7 +20,8 @@ type tomlOpts struct {
}
type encOpts struct {
- quoteMapKeys bool
+ quoteMapKeys bool
+ arraysOneElementPerLine bool
}
var encOptsDefaults = encOpts{
@@ -174,6 +175,25 @@ func (e *Encoder) QuoteMapKeys(v bool) *Encoder {
return e
}
+// ArraysWithOneElementPerLine sets up the encoder to encode arrays
+// with more than one element on multiple lines instead of one.
+//
+// For example:
+//
+// A = [1,2,3]
+//
+// Becomes
+//
+// A = [
+// 1,
+// 2,
+// 3
+// ]
+func (e *Encoder) ArraysWithOneElementPerLine(v bool) *Encoder {
+ e.arraysOneElementPerLine = v
+ return e
+}
+
func (e *Encoder) marshal(v interface{}) ([]byte, error) {
mtype := reflect.TypeOf(v)
if mtype.Kind() != reflect.Struct {
@@ -187,8 +207,11 @@ func (e *Encoder) marshal(v interface{}) ([]byte, error) {
if err != nil {
return []byte{}, err
}
- s, err := t.ToTomlString()
- return []byte(s), err
+
+ var buf bytes.Buffer
+ _, err = t.writeTo(&buf, "", "", 0, e.arraysOneElementPerLine)
+
+ return buf.Bytes(), err
}
// Convert given marshal struct or map value to toml tree
@@ -218,7 +241,7 @@ func (e *Encoder) valueToTree(mtype reflect.Type, mval reflect.Value) (*Tree, er
return nil, err
}
if e.quoteMapKeys {
- keyStr, err := tomlValueStringRepresentation(key.String())
+ keyStr, err := tomlValueStringRepresentation(key.String(), "", e.arraysOneElementPerLine)
if err != nil {
return nil, err
}
@@ -449,21 +472,18 @@ func (d *Decoder) valueFromToml(mtype reflect.Type, tval interface{}) (reflect.V
case *Tree:
if isTree(mtype) {
return d.valueFromTree(mtype, tval.(*Tree))
- } else {
- return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to a tree", tval, tval)
}
+ return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to a tree", tval, tval)
case []*Tree:
if isTreeSlice(mtype) {
return d.valueFromTreeSlice(mtype, tval.([]*Tree))
- } else {
- return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to trees", tval, tval)
}
+ return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to trees", tval, tval)
case []interface{}:
if isOtherSlice(mtype) {
return d.valueFromOtherSlice(mtype, tval.([]interface{}))
- } else {
- return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to a slice", tval, tval)
}
+ return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to a slice", tval, tval)
default:
switch mtype.Kind() {
case reflect.Bool:
diff --git a/vendor/github.com/pelletier/go-toml/marshal_test.go b/vendor/github.com/pelletier/go-toml/marshal_test.go
index e7d1d6e4d..291a80d2a 100644
--- a/vendor/github.com/pelletier/go-toml/marshal_test.go
+++ b/vendor/github.com/pelletier/go-toml/marshal_test.go
@@ -146,8 +146,8 @@ var docData = testDoc{
Second: &subdoc,
},
SubDocList: []testSubDoc{
- testSubDoc{"List.First", 0},
- testSubDoc{"List.Second", 0},
+ {"List.First", 0},
+ {"List.Second", 0},
},
SubDocPtrs: []*testSubDoc{&subdoc},
}
@@ -530,7 +530,7 @@ var strPtr = []*string{&str1, &str2}
var strPtr2 = []*[]*string{&strPtr}
var nestedTestData = nestedMarshalTestStruct{
- String: [][]string{[]string{"Five", "Six"}, []string{"One", "Two"}},
+ String: [][]string{{"Five", "Six"}, {"One", "Two"}},
StringPtr: &strPtr2,
}
@@ -721,6 +721,7 @@ func TestEncodeQuotedMapKeys(t *testing.T) {
t.Errorf("Bad maps marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
}
}
+
func TestDecodeQuotedMapKeys(t *testing.T) {
result := mapsTestStruct{}
err := NewDecoder(bytes.NewBuffer(mapsTestToml)).Decode(&result)
@@ -732,3 +733,74 @@ func TestDecodeQuotedMapKeys(t *testing.T) {
t.Errorf("Bad maps unmarshal: expected %v, got %v", expected, result)
}
}
+
+type structArrayNoTag struct {
+ A struct {
+ B []int64
+ C []int64
+ }
+}
+
+func TestMarshalArray(t *testing.T) {
+ expected := []byte(`
+[A]
+ B = [1,2,3]
+ C = [1]
+`)
+
+ m := structArrayNoTag{
+ A: struct {
+ B []int64
+ C []int64
+ }{
+ B: []int64{1, 2, 3},
+ C: []int64{1},
+ },
+ }
+
+ b, err := Marshal(m)
+
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if !bytes.Equal(b, expected) {
+ t.Errorf("Bad arrays marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, b)
+ }
+}
+
+func TestMarshalArrayOnePerLine(t *testing.T) {
+ expected := []byte(`
+[A]
+ B = [
+ 1,
+ 2,
+ 3
+ ]
+ C = [1]
+`)
+
+ m := structArrayNoTag{
+ A: struct {
+ B []int64
+ C []int64
+ }{
+ B: []int64{1, 2, 3},
+ C: []int64{1},
+ },
+ }
+
+ var buf bytes.Buffer
+ encoder := NewEncoder(&buf).ArraysWithOneElementPerLine(true)
+ err := encoder.Encode(m)
+
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ b := buf.Bytes()
+
+ if !bytes.Equal(b, expected) {
+ t.Errorf("Bad arrays marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, b)
+ }
+}
diff --git a/vendor/github.com/pelletier/go-toml/parser.go b/vendor/github.com/pelletier/go-toml/parser.go
index d492a1e6f..0f2ab7a33 100644
--- a/vendor/github.com/pelletier/go-toml/parser.go
+++ b/vendor/github.com/pelletier/go-toml/parser.go
@@ -212,13 +212,25 @@ func (p *tomlParser) parseAssign() tomlParserStateFn {
}
var numberUnderscoreInvalidRegexp *regexp.Regexp
+var hexNumberUnderscoreInvalidRegexp *regexp.Regexp
-func cleanupNumberToken(value string) (string, error) {
+func numberContainsInvalidUnderscore(value string) error {
if numberUnderscoreInvalidRegexp.MatchString(value) {
- return "", errors.New("invalid use of _ in number")
+ return errors.New("invalid use of _ in number")
}
+ return nil
+}
+
+func hexNumberContainsInvalidUnderscore(value string) error {
+ if hexNumberUnderscoreInvalidRegexp.MatchString(value) {
+ return errors.New("invalid use of _ in hex number")
+ }
+ return nil
+}
+
+func cleanupNumberToken(value string) string {
cleanedVal := strings.Replace(value, "_", "", -1)
- return cleanedVal, nil
+ return cleanedVal
}
func (p *tomlParser) parseRvalue() interface{} {
@@ -235,20 +247,49 @@ func (p *tomlParser) parseRvalue() interface{} {
case tokenFalse:
return false
case tokenInteger:
- cleanedVal, err := cleanupNumberToken(tok.val)
- if err != nil {
- p.raiseError(tok, "%s", err)
+ cleanedVal := cleanupNumberToken(tok.val)
+ var err error
+ var val int64
+ if len(cleanedVal) >= 3 && cleanedVal[0] == '0' {
+ switch cleanedVal[1] {
+ case 'x':
+ err = hexNumberContainsInvalidUnderscore(tok.val)
+ if err != nil {
+ p.raiseError(tok, "%s", err)
+ }
+ val, err = strconv.ParseInt(cleanedVal[2:], 16, 64)
+ case 'o':
+ err = numberContainsInvalidUnderscore(tok.val)
+ if err != nil {
+ p.raiseError(tok, "%s", err)
+ }
+ val, err = strconv.ParseInt(cleanedVal[2:], 8, 64)
+ case 'b':
+ err = numberContainsInvalidUnderscore(tok.val)
+ if err != nil {
+ p.raiseError(tok, "%s", err)
+ }
+ val, err = strconv.ParseInt(cleanedVal[2:], 2, 64)
+ default:
+ panic("invalid base") // the lexer should catch this first
+ }
+ } else {
+ err = numberContainsInvalidUnderscore(tok.val)
+ if err != nil {
+ p.raiseError(tok, "%s", err)
+ }
+ val, err = strconv.ParseInt(cleanedVal, 10, 64)
}
- val, err := strconv.ParseInt(cleanedVal, 10, 64)
if err != nil {
p.raiseError(tok, "%s", err)
}
return val
case tokenFloat:
- cleanedVal, err := cleanupNumberToken(tok.val)
+ err := numberContainsInvalidUnderscore(tok.val)
if err != nil {
p.raiseError(tok, "%s", err)
}
+ cleanedVal := cleanupNumberToken(tok.val)
val, err := strconv.ParseFloat(cleanedVal, 64)
if err != nil {
p.raiseError(tok, "%s", err)
@@ -379,5 +420,6 @@ func parseToml(flow []token) *Tree {
}
func init() {
- numberUnderscoreInvalidRegexp = regexp.MustCompile(`([^\d]_|_[^\d]|_$|^_)`)
+ numberUnderscoreInvalidRegexp = regexp.MustCompile(`([^\d]_|_[^\d])|_$|^_`)
+ hexNumberUnderscoreInvalidRegexp = regexp.MustCompile(`(^0x_)|([^\da-f]_|_[^\da-f])|_$|^_`)
}
diff --git a/vendor/github.com/pelletier/go-toml/parser_test.go b/vendor/github.com/pelletier/go-toml/parser_test.go
index 029bc52c3..6c8eec6a3 100644
--- a/vendor/github.com/pelletier/go-toml/parser_test.go
+++ b/vendor/github.com/pelletier/go-toml/parser_test.go
@@ -82,6 +82,59 @@ func TestSimpleNumbers(t *testing.T) {
})
}
+func TestHexIntegers(t *testing.T) {
+ tree, err := Load(`a = 0xDEADBEEF`)
+ assertTree(t, tree, err, map[string]interface{}{"a": int64(3735928559)})
+
+ tree, err = Load(`a = 0xdeadbeef`)
+ assertTree(t, tree, err, map[string]interface{}{"a": int64(3735928559)})
+
+ tree, err = Load(`a = 0xdead_beef`)
+ assertTree(t, tree, err, map[string]interface{}{"a": int64(3735928559)})
+
+ _, err = Load(`a = 0x_1`)
+ if err.Error() != "(1, 5): invalid use of _ in hex number" {
+ t.Error("Bad error message:", err.Error())
+ }
+}
+
+func TestOctIntegers(t *testing.T) {
+ tree, err := Load(`a = 0o01234567`)
+ assertTree(t, tree, err, map[string]interface{}{"a": int64(342391)})
+
+ tree, err = Load(`a = 0o755`)
+ assertTree(t, tree, err, map[string]interface{}{"a": int64(493)})
+
+ _, err = Load(`a = 0o_1`)
+ if err.Error() != "(1, 5): invalid use of _ in number" {
+ t.Error("Bad error message:", err.Error())
+ }
+}
+
+func TestBinIntegers(t *testing.T) {
+ tree, err := Load(`a = 0b11010110`)
+ assertTree(t, tree, err, map[string]interface{}{"a": int64(214)})
+
+ _, err = Load(`a = 0b_1`)
+ if err.Error() != "(1, 5): invalid use of _ in number" {
+ t.Error("Bad error message:", err.Error())
+ }
+}
+
+func TestBadIntegerBase(t *testing.T) {
+ _, err := Load(`a = 0k1`)
+ if err.Error() != "(1, 5): unknown number base: k. possible options are x (hex) o (octal) b (binary)" {
+ t.Error("Error should have been returned.")
+ }
+}
+
+func TestIntegerNoDigit(t *testing.T) {
+ _, err := Load(`a = 0b`)
+ if err.Error() != "(1, 5): number needs at least one digit" {
+ t.Error("Bad error message:", err.Error())
+ }
+}
+
func TestNumbersWithUnderscores(t *testing.T) {
tree, err := Load("a = 1_000")
assertTree(t, tree, err, map[string]interface{}{
@@ -642,7 +695,7 @@ func TestTomlValueStringRepresentation(t *testing.T) {
{int64(12345), "12345"},
{uint64(50), "50"},
{float64(123.45), "123.45"},
- {bool(true), "true"},
+ {true, "true"},
{"hello world", "\"hello world\""},
{"\b\t\n\f\r\"\\", "\"\\b\\t\\n\\f\\r\\\"\\\\\""},
{"\x05", "\"\\u0005\""},
@@ -652,7 +705,7 @@ func TestTomlValueStringRepresentation(t *testing.T) {
"[\"gamma\",\"delta\"]"},
{nil, ""},
} {
- result, err := tomlValueStringRepresentation(item.Value)
+ result, err := tomlValueStringRepresentation(item.Value, "", false)
if err != nil {
t.Errorf("Test %d - unexpected error: %s", idx, err)
}
diff --git a/vendor/github.com/pelletier/go-toml/tomltree_create_test.go b/vendor/github.com/pelletier/go-toml/tomltree_create_test.go
index 1ca108a52..3465a1066 100644
--- a/vendor/github.com/pelletier/go-toml/tomltree_create_test.go
+++ b/vendor/github.com/pelletier/go-toml/tomltree_create_test.go
@@ -60,7 +60,7 @@ func TestTreeCreateToTree(t *testing.T) {
},
"array": []string{"a", "b", "c"},
"array_uint": []uint{uint(1), uint(2)},
- "array_table": []map[string]interface{}{map[string]interface{}{"sub_map": 52}},
+ "array_table": []map[string]interface{}{{"sub_map": 52}},
"array_times": []time.Time{time.Now(), time.Now()},
"map_times": map[string]time.Time{"now": time.Now()},
"custom_string_map_key": map[customString]interface{}{customString("custom"): "custom"},
@@ -97,7 +97,7 @@ func TestTreeCreateToTreeInvalidArrayMemberType(t *testing.T) {
}
func TestTreeCreateToTreeInvalidTableGroupType(t *testing.T) {
- _, err := TreeFromMap(map[string]interface{}{"foo": []map[string]interface{}{map[string]interface{}{"hello": t}}})
+ _, err := TreeFromMap(map[string]interface{}{"foo": []map[string]interface{}{{"hello": t}}})
expected := "cannot convert type *testing.T to Tree"
if err.Error() != expected {
t.Fatalf("expected error %s, got %s", expected, err.Error())
diff --git a/vendor/github.com/pelletier/go-toml/tomltree_write.go b/vendor/github.com/pelletier/go-toml/tomltree_write.go
index 449f35a44..f5ef124f0 100644
--- a/vendor/github.com/pelletier/go-toml/tomltree_write.go
+++ b/vendor/github.com/pelletier/go-toml/tomltree_write.go
@@ -44,7 +44,7 @@ func encodeTomlString(value string) string {
return b.String()
}
-func tomlValueStringRepresentation(v interface{}) (string, error) {
+func tomlValueStringRepresentation(v interface{}, indent string, arraysOneElementPerLine bool) (string, error) {
switch value := v.(type) {
case uint64:
return strconv.FormatUint(value, 10), nil
@@ -61,7 +61,7 @@ func tomlValueStringRepresentation(v interface{}) (string, error) {
return "\"" + encodeTomlString(value) + "\"", nil
case []byte:
b, _ := v.([]byte)
- return tomlValueStringRepresentation(string(b))
+ return tomlValueStringRepresentation(string(b), indent, arraysOneElementPerLine)
case bool:
if value {
return "true", nil
@@ -76,21 +76,40 @@ func tomlValueStringRepresentation(v interface{}) (string, error) {
rv := reflect.ValueOf(v)
if rv.Kind() == reflect.Slice {
- values := []string{}
+ var values []string
for i := 0; i < rv.Len(); i++ {
item := rv.Index(i).Interface()
- itemRepr, err := tomlValueStringRepresentation(item)
+ itemRepr, err := tomlValueStringRepresentation(item, indent, arraysOneElementPerLine)
if err != nil {
return "", err
}
values = append(values, itemRepr)
}
+ if arraysOneElementPerLine && len(values) > 1 {
+ stringBuffer := bytes.Buffer{}
+ valueIndent := indent + ` ` // TODO: move that to a shared encoder state
+
+ stringBuffer.WriteString("[\n")
+
+ for i, value := range values {
+ stringBuffer.WriteString(valueIndent)
+ stringBuffer.WriteString(value)
+ if i != len(values)-1 {
+ stringBuffer.WriteString(`,`)
+ }
+ stringBuffer.WriteString("\n")
+ }
+
+ stringBuffer.WriteString(indent + "]")
+
+ return stringBuffer.String(), nil
+ }
return "[" + strings.Join(values, ",") + "]", nil
}
return "", fmt.Errorf("unsupported value type %T: %v", v, v)
}
-func (t *Tree) writeTo(w io.Writer, indent, keyspace string, bytesCount int64) (int64, error) {
+func (t *Tree) writeTo(w io.Writer, indent, keyspace string, bytesCount int64, arraysOneElementPerLine bool) (int64, error) {
simpleValuesKeys := make([]string, 0)
complexValuesKeys := make([]string, 0)
@@ -113,7 +132,7 @@ func (t *Tree) writeTo(w io.Writer, indent, keyspace string, bytesCount int64) (
return bytesCount, fmt.Errorf("invalid value type at %s: %T", k, t.values[k])
}
- repr, err := tomlValueStringRepresentation(v.value)
+ repr, err := tomlValueStringRepresentation(v.value, indent, arraysOneElementPerLine)
if err != nil {
return bytesCount, err
}
@@ -178,7 +197,7 @@ func (t *Tree) writeTo(w io.Writer, indent, keyspace string, bytesCount int64) (
if err != nil {
return bytesCount, err
}
- bytesCount, err = node.writeTo(w, indent+" ", combinedKey, bytesCount)
+ bytesCount, err = node.writeTo(w, indent+" ", combinedKey, bytesCount, arraysOneElementPerLine)
if err != nil {
return bytesCount, err
}
@@ -190,7 +209,7 @@ func (t *Tree) writeTo(w io.Writer, indent, keyspace string, bytesCount int64) (
return bytesCount, err
}
- bytesCount, err = subTree.writeTo(w, indent+" ", combinedKey, bytesCount)
+ bytesCount, err = subTree.writeTo(w, indent+" ", combinedKey, bytesCount, arraysOneElementPerLine)
if err != nil {
return bytesCount, err
}
@@ -216,7 +235,7 @@ func writeStrings(w io.Writer, s ...string) (int, error) {
// WriteTo encode the Tree as Toml and writes it to the writer w.
// Returns the number of bytes written in case of success, or an error if anything happened.
func (t *Tree) WriteTo(w io.Writer) (int64, error) {
- return t.writeTo(w, "", "", 0)
+ return t.writeTo(w, "", "", 0, false)
}
// ToTomlString generates a human-readable representation of the current tree.
diff --git a/vendor/github.com/pkg/errors/README.md b/vendor/github.com/pkg/errors/README.md
index 273db3c98..6483ba2af 100644
--- a/vendor/github.com/pkg/errors/README.md
+++ b/vendor/github.com/pkg/errors/README.md
@@ -1,4 +1,4 @@
-# errors [![Travis-CI](https://travis-ci.org/pkg/errors.svg)](https://travis-ci.org/pkg/errors) [![AppVeyor](https://ci.appveyor.com/api/projects/status/b98mptawhudj53ep/branch/master?svg=true)](https://ci.appveyor.com/project/davecheney/errors/branch/master) [![GoDoc](https://godoc.org/github.com/pkg/errors?status.svg)](http://godoc.org/github.com/pkg/errors) [![Report card](https://goreportcard.com/badge/github.com/pkg/errors)](https://goreportcard.com/report/github.com/pkg/errors)
+# errors [![Travis-CI](https://travis-ci.org/pkg/errors.svg)](https://travis-ci.org/pkg/errors) [![AppVeyor](https://ci.appveyor.com/api/projects/status/b98mptawhudj53ep/branch/master?svg=true)](https://ci.appveyor.com/project/davecheney/errors/branch/master) [![GoDoc](https://godoc.org/github.com/pkg/errors?status.svg)](http://godoc.org/github.com/pkg/errors) [![Report card](https://goreportcard.com/badge/github.com/pkg/errors)](https://goreportcard.com/report/github.com/pkg/errors) [![Sourcegraph](https://sourcegraph.com/github.com/pkg/errors/-/badge.svg)](https://sourcegraph.com/github.com/pkg/errors?badge)
Package errors provides simple error handling primitives.
@@ -47,6 +47,6 @@ We welcome pull requests, bug fixes and issue reports. With that said, the bar f
Before proposing a change, please discuss your change by raising an issue.
-## Licence
+## License
BSD-2-Clause
diff --git a/vendor/github.com/pkg/errors/stack.go b/vendor/github.com/pkg/errors/stack.go
index cbe3f3e38..b485761a7 100644
--- a/vendor/github.com/pkg/errors/stack.go
+++ b/vendor/github.com/pkg/errors/stack.go
@@ -46,7 +46,8 @@ func (f Frame) line() int {
//
// Format accepts flags that alter the printing of some verbs, as follows:
//
-// %+s path of source file relative to the compile time GOPATH
+// %+s function name and path of source file relative to the compile time
+// GOPATH separated by \n\t (<funcname>\n\t<path>)
// %+v equivalent to %+s:%d
func (f Frame) Format(s fmt.State, verb rune) {
switch verb {
diff --git a/vendor/github.com/prometheus/client_model/Makefile b/vendor/github.com/prometheus/client_model/Makefile
index 9cc23b340..e147c69da 100644
--- a/vendor/github.com/prometheus/client_model/Makefile
+++ b/vendor/github.com/prometheus/client_model/Makefile
@@ -39,6 +39,7 @@ src/main/java/io/prometheus/client/Metrics.java: metrics.proto
python: python/prometheus/client/model/metrics_pb2.py
python/prometheus/client/model/metrics_pb2.py: metrics.proto
+ mkdir -p python/prometheus/client/model
protoc $< --python_out=python/prometheus/client/model
ruby:
diff --git a/vendor/github.com/prometheus/common/config/http_config.go b/vendor/github.com/prometheus/common/config/http_config.go
index ff5837fa5..ea231bf8d 100644
--- a/vendor/github.com/prometheus/common/config/http_config.go
+++ b/vendor/github.com/prometheus/common/config/http_config.go
@@ -22,7 +22,7 @@ import (
"net/url"
"strings"
- yaml "gopkg.in/yaml.v2"
+ "gopkg.in/yaml.v2"
)
// BasicAuth contains basic HTTP authentication credentials.
@@ -79,7 +79,9 @@ type HTTPClientConfig struct {
XXX map[string]interface{} `yaml:",inline"`
}
-func (c *HTTPClientConfig) validate() error {
+// Validate validates the HTTPClientConfig to check only one of BearerToken,
+// BasicAuth and BearerTokenFile is configured.
+func (c *HTTPClientConfig) Validate() error {
if len(c.BearerToken) > 0 && len(c.BearerTokenFile) > 0 {
return fmt.Errorf("at most one of bearer_token & bearer_token_file must be configured")
}
@@ -96,9 +98,9 @@ func (c *HTTPClientConfig) UnmarshalYAML(unmarshal func(interface{}) error) erro
if err != nil {
return err
}
- err = c.validate()
+ err = c.Validate()
if err != nil {
- return c.validate()
+ return c.Validate()
}
return checkOverflow(c.XXX, "http_client_config")
}
diff --git a/vendor/github.com/prometheus/common/config/http_config_test.go b/vendor/github.com/prometheus/common/config/http_config_test.go
index 1e2490bbb..4b13e101b 100644
--- a/vendor/github.com/prometheus/common/config/http_config_test.go
+++ b/vendor/github.com/prometheus/common/config/http_config_test.go
@@ -114,7 +114,7 @@ func TestValidateHTTPConfig(t *testing.T) {
if err != nil {
t.Errorf("Error loading HTTP client config: %v", err)
}
- err = cfg.validate()
+ err = cfg.Validate()
if err != nil {
t.Fatalf("Error validating %s: %s", "testdata/http.conf.good.yml", err)
}
diff --git a/vendor/github.com/prometheus/common/model/time.go b/vendor/github.com/prometheus/common/model/time.go
index 7e87f1ac6..74ed5a9f7 100644
--- a/vendor/github.com/prometheus/common/model/time.go
+++ b/vendor/github.com/prometheus/common/model/time.go
@@ -214,6 +214,9 @@ func (d Duration) String() string {
ms = int64(time.Duration(d) / time.Millisecond)
unit = "ms"
)
+ if ms == 0 {
+ return "0s"
+ }
factors := map[string]int64{
"y": 1000 * 60 * 60 * 24 * 365,
"w": 1000 * 60 * 60 * 24 * 7,
diff --git a/vendor/github.com/prometheus/common/model/time_test.go b/vendor/github.com/prometheus/common/model/time_test.go
index 45ffd872d..3efdd65ff 100644
--- a/vendor/github.com/prometheus/common/model/time_test.go
+++ b/vendor/github.com/prometheus/common/model/time_test.go
@@ -91,6 +91,9 @@ func TestParseDuration(t *testing.T) {
out time.Duration
}{
{
+ in: "0s",
+ out: 0,
+ }, {
in: "324ms",
out: 324 * time.Millisecond,
}, {
diff --git a/vendor/github.com/prometheus/procfs/.travis.yml b/vendor/github.com/prometheus/procfs/.travis.yml
index ee09bb733..0dc42122b 100644
--- a/vendor/github.com/prometheus/procfs/.travis.yml
+++ b/vendor/github.com/prometheus/procfs/.travis.yml
@@ -1,5 +1,9 @@
sudo: false
+
language: go
+
go:
- - 1.7.6
- - 1.8.3
+- 1.9.x
+- 1.x
+
+go_import_path: github.com/prometheus/procfs
diff --git a/vendor/github.com/prometheus/procfs/bcache/get.go b/vendor/github.com/prometheus/procfs/bcache/get.go
index 4d56f3d98..b6d97de15 100644
--- a/vendor/github.com/prometheus/procfs/bcache/get.go
+++ b/vendor/github.com/prometheus/procfs/bcache/get.go
@@ -61,7 +61,7 @@ func dehumanize(hbytes []byte) (uint64, error) {
mul := float64(1)
var (
mant float64
- err error
+ err error
)
// If lastByte is beyond the range of ASCII digits, it must be a
// multiplier.
@@ -93,7 +93,7 @@ func dehumanize(hbytes []byte) (uint64, error) {
'Z': ZiB,
'Y': YiB,
}
- mul = float64(multipliers[rune(lastByte)])
+ mul = multipliers[rune(lastByte)]
mant, err = parsePseudoFloat(string(hbytes))
if err != nil {
return 0, err
@@ -139,10 +139,10 @@ func (p *parser) readValue(fileName string) uint64 {
}
// ParsePriorityStats parses lines from the priority_stats file.
-func parsePriorityStats(line string, ps *PriorityStats) (error) {
+func parsePriorityStats(line string, ps *PriorityStats) error {
var (
value uint64
- err error
+ err error
)
switch {
case strings.HasPrefix(line, "Unused:"):
diff --git a/vendor/github.com/prometheus/procfs/bcache/get_test.go b/vendor/github.com/prometheus/procfs/bcache/get_test.go
index 38c3df573..1d41a5ad3 100644
--- a/vendor/github.com/prometheus/procfs/bcache/get_test.go
+++ b/vendor/github.com/prometheus/procfs/bcache/get_test.go
@@ -14,8 +14,8 @@
package bcache
import (
- "testing"
"math"
+ "testing"
)
func TestDehumanizeTests(t *testing.T) {
@@ -45,8 +45,8 @@ func TestDehumanizeTests(t *testing.T) {
out: 2024,
},
{
- in: []byte(""),
- out: 0,
+ in: []byte(""),
+ out: 0,
invalid: true,
},
}
@@ -59,7 +59,7 @@ func TestDehumanizeTests(t *testing.T) {
t.Errorf("unexpected error: %v", err)
}
if got != tst.out {
- t.Errorf("dehumanize: '%s', want %f, got %f", tst.in, tst.out, got)
+ t.Errorf("dehumanize: '%s', want %d, got %d", tst.in, tst.out, got)
}
}
}
@@ -84,7 +84,7 @@ func TestParsePseudoFloatTests(t *testing.T) {
}
for _, tst := range parsePseudoFloatTests {
got, err := parsePseudoFloat(tst.in)
- if err != nil || math.Abs(got - tst.out) > 0.0001 {
+ if err != nil || math.Abs(got-tst.out) > 0.0001 {
t.Errorf("parsePseudoFloat: %s, want %f, got %f", tst.in, tst.out, got)
}
}
@@ -92,23 +92,23 @@ func TestParsePseudoFloatTests(t *testing.T) {
func TestPriorityStats(t *testing.T) {
var want = PriorityStats{
- UnusedPercent: 99,
+ UnusedPercent: 99,
MetadataPercent: 5,
}
var (
- in string
+ in string
gotErr error
- got PriorityStats
+ got PriorityStats
)
in = "Metadata: 5%"
gotErr = parsePriorityStats(in, &got)
if gotErr != nil || got.MetadataPercent != want.MetadataPercent {
- t.Errorf("parsePriorityStats: '%s', want %f, got %f", in, want.MetadataPercent, got.MetadataPercent)
+ t.Errorf("parsePriorityStats: '%s', want %d, got %d", in, want.MetadataPercent, got.MetadataPercent)
}
in = "Unused: 99%"
gotErr = parsePriorityStats(in, &got)
if gotErr != nil || got.UnusedPercent != want.UnusedPercent {
- t.Errorf("parsePriorityStats: '%s', want %f, got %f", in, want.UnusedPercent, got.UnusedPercent)
+ t.Errorf("parsePriorityStats: '%s', want %d, got %d", in, want.UnusedPercent, got.UnusedPercent)
}
}
diff --git a/vendor/github.com/prometheus/procfs/buddyinfo.go b/vendor/github.com/prometheus/procfs/buddyinfo.go
index 680a9842a..d3a826807 100644
--- a/vendor/github.com/prometheus/procfs/buddyinfo.go
+++ b/vendor/github.com/prometheus/procfs/buddyinfo.go
@@ -62,7 +62,7 @@ func parseBuddyInfo(r io.Reader) ([]BuddyInfo, error) {
for scanner.Scan() {
var err error
line := scanner.Text()
- parts := strings.Fields(string(line))
+ parts := strings.Fields(line)
if len(parts) < 4 {
return nil, fmt.Errorf("invalid number of fields when parsing buddyinfo")
diff --git a/vendor/github.com/prometheus/procfs/fixtures/26231/net/dev b/vendor/github.com/prometheus/procfs/fixtures/26231/net/dev
new file mode 100644
index 000000000..f10895560
--- /dev/null
+++ b/vendor/github.com/prometheus/procfs/fixtures/26231/net/dev
@@ -0,0 +1,4 @@
+Inter-| Receive | Transmit
+ face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
+ lo: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ eth0: 438 5 0 0 0 0 0 0 648 8 0 0 0 0 0 0
diff --git a/vendor/github.com/prometheus/procfs/fixtures/26231/ns/mnt b/vendor/github.com/prometheus/procfs/fixtures/26231/ns/mnt
new file mode 120000
index 000000000..9c52ca211
--- /dev/null
+++ b/vendor/github.com/prometheus/procfs/fixtures/26231/ns/mnt
@@ -0,0 +1 @@
+mnt:[4026531840] \ No newline at end of file
diff --git a/vendor/github.com/prometheus/procfs/fixtures/26231/ns/net b/vendor/github.com/prometheus/procfs/fixtures/26231/ns/net
new file mode 120000
index 000000000..1f0f79594
--- /dev/null
+++ b/vendor/github.com/prometheus/procfs/fixtures/26231/ns/net
@@ -0,0 +1 @@
+net:[4026531993] \ No newline at end of file
diff --git a/vendor/github.com/prometheus/procfs/fixtures/net/dev b/vendor/github.com/prometheus/procfs/fixtures/net/dev
new file mode 100644
index 000000000..2df786fa5
--- /dev/null
+++ b/vendor/github.com/prometheus/procfs/fixtures/net/dev
@@ -0,0 +1,6 @@
+Inter-| Receive | Transmit
+ face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
+vethf345468: 648 8 0 0 0 0 0 0 438 5 0 0 0 0 0 0
+ lo: 1664039048 1566805 0 0 0 0 0 0 1664039048 1566805 0 0 0 0 0 0
+docker0: 2568 38 0 0 0 0 0 0 438 5 0 0 0 0 0 0
+ eth0: 874354587 1036395 0 0 0 0 0 0 563352563 732147 0 0 0 0 0 0
diff --git a/vendor/github.com/prometheus/procfs/ipvs.go b/vendor/github.com/prometheus/procfs/ipvs.go
index 696d114e7..5761b4570 100644
--- a/vendor/github.com/prometheus/procfs/ipvs.go
+++ b/vendor/github.com/prometheus/procfs/ipvs.go
@@ -31,16 +31,16 @@ type IPVSStats struct {
type IPVSBackendStatus struct {
// The local (virtual) IP address.
LocalAddress net.IP
+ // The remote (real) IP address.
+ RemoteAddress net.IP
// The local (virtual) port.
LocalPort uint16
+ // The remote (real) port.
+ RemotePort uint16
// The local firewall mark
LocalMark string
// The transport protocol (TCP, UDP).
Proto string
- // The remote (real) IP address.
- RemoteAddress net.IP
- // The remote (real) port.
- RemotePort uint16
// The current number of active connections for this virtual/real address pair.
ActiveConn uint64
// The current number of inactive connections for this virtual/real address pair.
@@ -151,7 +151,7 @@ func parseIPVSBackendStatus(file io.Reader) ([]IPVSBackendStatus, error) {
)
for scanner.Scan() {
- fields := strings.Fields(string(scanner.Text()))
+ fields := strings.Fields(scanner.Text())
if len(fields) == 0 {
continue
}
diff --git a/vendor/github.com/prometheus/procfs/net_dev.go b/vendor/github.com/prometheus/procfs/net_dev.go
new file mode 100644
index 000000000..f8c184efe
--- /dev/null
+++ b/vendor/github.com/prometheus/procfs/net_dev.go
@@ -0,0 +1,203 @@
+package procfs
+
+import (
+ "bufio"
+ "errors"
+ "os"
+ "sort"
+ "strconv"
+ "strings"
+)
+
+// NetDevLine is single line parsed from /proc/net/dev or /proc/[pid]/net/dev.
+type NetDevLine struct {
+ Name string `json:"name"` // The name of the interface.
+ RxBytes uint64 `json:"rx_bytes"` // Cumulative count of bytes received.
+ RxPackets uint64 `json:"rx_packets"` // Cumulative count of packets received.
+ RxErrors uint64 `json:"rx_errors"` // Cumulative count of receive errors encountered.
+ RxDropped uint64 `json:"rx_dropped"` // Cumulative count of packets dropped while receiving.
+ RxFIFO uint64 `json:"rx_fifo"` // Cumulative count of FIFO buffer errors.
+ RxFrame uint64 `json:"rx_frame"` // Cumulative count of packet framing errors.
+ RxCompressed uint64 `json:"rx_compressed"` // Cumulative count of compressed packets received by the device driver.
+ RxMulticast uint64 `json:"rx_multicast"` // Cumulative count of multicast frames received by the device driver.
+ TxBytes uint64 `json:"tx_bytes"` // Cumulative count of bytes transmitted.
+ TxPackets uint64 `json:"tx_packets"` // Cumulative count of packets transmitted.
+ TxErrors uint64 `json:"tx_errors"` // Cumulative count of transmit errors encountered.
+ TxDropped uint64 `json:"tx_dropped"` // Cumulative count of packets dropped while transmitting.
+ TxFIFO uint64 `json:"tx_fifo"` // Cumulative count of FIFO buffer errors.
+ TxCollisions uint64 `json:"tx_collisions"` // Cumulative count of collisions detected on the interface.
+ TxCarrier uint64 `json:"tx_carrier"` // Cumulative count of carrier losses detected by the device driver.
+ TxCompressed uint64 `json:"tx_compressed"` // Cumulative count of compressed packets transmitted by the device driver.
+}
+
+// NetDev is parsed from /proc/net/dev or /proc/[pid]/net/dev. The map keys
+// are interface names.
+type NetDev map[string]NetDevLine
+
+// NewNetDev returns kernel/system statistics read from /proc/net/dev.
+func NewNetDev() (NetDev, error) {
+ fs, err := NewFS(DefaultMountPoint)
+ if err != nil {
+ return nil, err
+ }
+
+ return fs.NewNetDev()
+}
+
+// NewNetDev returns kernel/system statistics read from /proc/net/dev.
+func (fs FS) NewNetDev() (NetDev, error) {
+ return newNetDev(fs.Path("net/dev"))
+}
+
+// NewNetDev returns kernel/system statistics read from /proc/[pid]/net/dev.
+func (p Proc) NewNetDev() (NetDev, error) {
+ return newNetDev(p.path("net/dev"))
+}
+
+// newNetDev creates a new NetDev from the contents of the given file.
+func newNetDev(file string) (NetDev, error) {
+ f, err := os.Open(file)
+ if err != nil {
+ return NetDev{}, err
+ }
+ defer f.Close()
+
+ nd := NetDev{}
+ s := bufio.NewScanner(f)
+ for n := 0; s.Scan(); n++ {
+ // Skip the 2 header lines.
+ if n < 2 {
+ continue
+ }
+
+ line, err := nd.parseLine(s.Text())
+ if err != nil {
+ return nd, err
+ }
+
+ nd[line.Name] = *line
+ }
+
+ return nd, s.Err()
+}
+
+// parseLine parses a single line from the /proc/net/dev file. Header lines
+// must be filtered prior to calling this method.
+func (nd NetDev) parseLine(rawLine string) (*NetDevLine, error) {
+ parts := strings.SplitN(rawLine, ":", 2)
+ if len(parts) != 2 {
+ return nil, errors.New("invalid net/dev line, missing colon")
+ }
+ fields := strings.Fields(strings.TrimSpace(parts[1]))
+
+ var err error
+ line := &NetDevLine{}
+
+ // Interface Name
+ line.Name = strings.TrimSpace(parts[0])
+ if line.Name == "" {
+ return nil, errors.New("invalid net/dev line, empty interface name")
+ }
+
+ // RX
+ line.RxBytes, err = strconv.ParseUint(fields[0], 10, 64)
+ if err != nil {
+ return nil, err
+ }
+ line.RxPackets, err = strconv.ParseUint(fields[1], 10, 64)
+ if err != nil {
+ return nil, err
+ }
+ line.RxErrors, err = strconv.ParseUint(fields[2], 10, 64)
+ if err != nil {
+ return nil, err
+ }
+ line.RxDropped, err = strconv.ParseUint(fields[3], 10, 64)
+ if err != nil {
+ return nil, err
+ }
+ line.RxFIFO, err = strconv.ParseUint(fields[4], 10, 64)
+ if err != nil {
+ return nil, err
+ }
+ line.RxFrame, err = strconv.ParseUint(fields[5], 10, 64)
+ if err != nil {
+ return nil, err
+ }
+ line.RxCompressed, err = strconv.ParseUint(fields[6], 10, 64)
+ if err != nil {
+ return nil, err
+ }
+ line.RxMulticast, err = strconv.ParseUint(fields[7], 10, 64)
+ if err != nil {
+ return nil, err
+ }
+
+ // TX
+ line.TxBytes, err = strconv.ParseUint(fields[8], 10, 64)
+ if err != nil {
+ return nil, err
+ }
+ line.TxPackets, err = strconv.ParseUint(fields[9], 10, 64)
+ if err != nil {
+ return nil, err
+ }
+ line.TxErrors, err = strconv.ParseUint(fields[10], 10, 64)
+ if err != nil {
+ return nil, err
+ }
+ line.TxDropped, err = strconv.ParseUint(fields[11], 10, 64)
+ if err != nil {
+ return nil, err
+ }
+ line.TxFIFO, err = strconv.ParseUint(fields[12], 10, 64)
+ if err != nil {
+ return nil, err
+ }
+ line.TxCollisions, err = strconv.ParseUint(fields[13], 10, 64)
+ if err != nil {
+ return nil, err
+ }
+ line.TxCarrier, err = strconv.ParseUint(fields[14], 10, 64)
+ if err != nil {
+ return nil, err
+ }
+ line.TxCompressed, err = strconv.ParseUint(fields[15], 10, 64)
+ if err != nil {
+ return nil, err
+ }
+
+ return line, nil
+}
+
+// Total aggregates the values across interfaces and returns a new NetDevLine.
+// The Name field will be a sorted comma seperated list of interface names.
+func (nd NetDev) Total() NetDevLine {
+ total := NetDevLine{}
+
+ names := make([]string, 0, len(nd))
+ for _, ifc := range nd {
+ names = append(names, ifc.Name)
+ total.RxBytes += ifc.RxBytes
+ total.RxPackets += ifc.RxPackets
+ total.RxPackets += ifc.RxPackets
+ total.RxErrors += ifc.RxErrors
+ total.RxDropped += ifc.RxDropped
+ total.RxFIFO += ifc.RxFIFO
+ total.RxFrame += ifc.RxFrame
+ total.RxCompressed += ifc.RxCompressed
+ total.RxMulticast += ifc.RxMulticast
+ total.TxBytes += ifc.TxBytes
+ total.TxPackets += ifc.TxPackets
+ total.TxErrors += ifc.TxErrors
+ total.TxDropped += ifc.TxDropped
+ total.TxFIFO += ifc.TxFIFO
+ total.TxCollisions += ifc.TxCollisions
+ total.TxCarrier += ifc.TxCarrier
+ total.TxCompressed += ifc.TxCompressed
+ }
+ sort.Strings(names)
+ total.Name = strings.Join(names, ", ")
+
+ return total
+}
diff --git a/vendor/github.com/prometheus/procfs/net_dev_test.go b/vendor/github.com/prometheus/procfs/net_dev_test.go
new file mode 100644
index 000000000..a69d8b9b8
--- /dev/null
+++ b/vendor/github.com/prometheus/procfs/net_dev_test.go
@@ -0,0 +1,73 @@
+package procfs
+
+import (
+ "testing"
+)
+
+func TestNetDevParseLine(t *testing.T) {
+ const rawLine = ` eth0: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16`
+
+ have, err := NetDev{}.parseLine(rawLine)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ want := NetDevLine{"eth0", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}
+ if want != *have {
+ t.Errorf("want %v, have %v", want, have)
+ }
+}
+
+func TestNewNetDev(t *testing.T) {
+ fs, err := NewFS("fixtures")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ nd, err := fs.NewNetDev()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ lines := map[string]NetDevLine{
+ "vethf345468": {Name: "vethf345468", RxBytes: 648, RxPackets: 8, TxBytes: 438, TxPackets: 5},
+ "lo": {Name: "lo", RxBytes: 1664039048, RxPackets: 1566805, TxBytes: 1664039048, TxPackets: 1566805},
+ "docker0": {Name: "docker0", RxBytes: 2568, RxPackets: 38, TxBytes: 438, TxPackets: 5},
+ "eth0": {Name: "eth0", RxBytes: 874354587, RxPackets: 1036395, TxBytes: 563352563, TxPackets: 732147},
+ }
+
+ if want, have := len(lines), len(nd); want != have {
+ t.Errorf("want %d parsed net/dev lines, have %d", want, have)
+ }
+ for _, line := range nd {
+ if want, have := lines[line.Name], line; want != have {
+ t.Errorf("%s: want %v, have %v", line.Name, want, have)
+ }
+ }
+}
+
+func TestProcNewNetDev(t *testing.T) {
+ p, err := FS("fixtures").NewProc(26231)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ nd, err := p.NewNetDev()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ lines := map[string]NetDevLine{
+ "lo": {Name: "lo"},
+ "eth0": {Name: "eth0", RxBytes: 438, RxPackets: 5, TxBytes: 648, TxPackets: 8},
+ }
+
+ if want, have := len(lines), len(nd); want != have {
+ t.Errorf("want %d parsed net/dev lines, have %d", want, have)
+ }
+ for _, line := range nd {
+ if want, have := lines[line.Name], line; want != have {
+ t.Errorf("%s: want %v, have %v", line.Name, want, have)
+ }
+ }
+}
diff --git a/vendor/github.com/prometheus/procfs/proc_io.go b/vendor/github.com/prometheus/procfs/proc_io.go
index b4e31d7ba..e7f6674d0 100644
--- a/vendor/github.com/prometheus/procfs/proc_io.go
+++ b/vendor/github.com/prometheus/procfs/proc_io.go
@@ -47,9 +47,6 @@ func (p Proc) NewIO() (ProcIO, error) {
_, err = fmt.Sscanf(string(data), ioFormat, &pio.RChar, &pio.WChar, &pio.SyscR,
&pio.SyscW, &pio.ReadBytes, &pio.WriteBytes, &pio.CancelledWriteBytes)
- if err != nil {
- return pio, err
- }
- return pio, nil
+ return pio, err
}
diff --git a/vendor/github.com/prometheus/procfs/proc_ns.go b/vendor/github.com/prometheus/procfs/proc_ns.go
new file mode 100644
index 000000000..befdd2690
--- /dev/null
+++ b/vendor/github.com/prometheus/procfs/proc_ns.go
@@ -0,0 +1,55 @@
+package procfs
+
+import (
+ "fmt"
+ "os"
+ "strconv"
+ "strings"
+)
+
+// Namespace represents a single namespace of a process.
+type Namespace struct {
+ Type string // Namespace type.
+ Inode uint32 // Inode number of the namespace. If two processes are in the same namespace their inodes will match.
+}
+
+// Namespaces contains all of the namespaces that the process is contained in.
+type Namespaces map[string]Namespace
+
+// NewNamespaces reads from /proc/[pid/ns/* to get the namespaces of which the
+// process is a member.
+func (p Proc) NewNamespaces() (Namespaces, error) {
+ d, err := os.Open(p.path("ns"))
+ if err != nil {
+ return nil, err
+ }
+ defer d.Close()
+
+ names, err := d.Readdirnames(-1)
+ if err != nil {
+ return nil, fmt.Errorf("failed to read contents of ns dir: %v", err)
+ }
+
+ ns := make(Namespaces, len(names))
+ for _, name := range names {
+ target, err := os.Readlink(p.path("ns", name))
+ if err != nil {
+ return nil, err
+ }
+
+ fields := strings.SplitN(target, ":", 2)
+ if len(fields) != 2 {
+ return nil, fmt.Errorf("failed to parse namespace type and inode from '%v'", target)
+ }
+
+ typ := fields[0]
+ inode, err := strconv.ParseUint(strings.Trim(fields[1], "[]"), 10, 32)
+ if err != nil {
+ return nil, fmt.Errorf("failed to parse inode from '%v': %v", fields[1], err)
+ }
+
+ ns[name] = Namespace{typ, uint32(inode)}
+ }
+
+ return ns, nil
+}
diff --git a/vendor/github.com/prometheus/procfs/proc_ns_test.go b/vendor/github.com/prometheus/procfs/proc_ns_test.go
new file mode 100644
index 000000000..aea3f6a6c
--- /dev/null
+++ b/vendor/github.com/prometheus/procfs/proc_ns_test.go
@@ -0,0 +1,31 @@
+package procfs
+
+import (
+ "testing"
+)
+
+func TestNewNamespaces(t *testing.T) {
+ p, err := FS("fixtures").NewProc(26231)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ namespaces, err := p.NewNamespaces()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ expectedNamespaces := map[string]Namespace{
+ "mnt": {"mnt", 4026531840},
+ "net": {"net", 4026531993},
+ }
+
+ if want, have := len(expectedNamespaces), len(namespaces); want != have {
+ t.Errorf("want %d parsed namespaces, have %d", want, have)
+ }
+ for _, ns := range namespaces {
+ if want, have := expectedNamespaces[ns.Type], ns; want != have {
+ t.Errorf("%s: want %v, have %v", ns.Type, want, have)
+ }
+ }
+}
diff --git a/vendor/github.com/rwcarlsen/goexif/README.md b/vendor/github.com/rwcarlsen/goexif/README.md
index 8b815a0fd..b57ef20fc 100644
--- a/vendor/github.com/rwcarlsen/goexif/README.md
+++ b/vendor/github.com/rwcarlsen/goexif/README.md
@@ -6,7 +6,7 @@ Suggestions and pull requests are welcome. Functionality is split into two pack
The exif package depends on the tiff package.
Documentation can be found at http://godoc.org/github.com/rwcarlsen/goexif
-Like goexif? - Bitcoin tips welcome: 17M7LFh3ETz4bz83VikB7xuGQskt8K5Lj4
+Like goexif? - Bitcoin Cash tips welcome: 1DrU5V37nTXuv4vnRLVpahJEjhdATNgoBh
To install, in a terminal type:
diff --git a/vendor/github.com/spf13/afero/copyOnWriteFs.go b/vendor/github.com/spf13/afero/copyOnWriteFs.go
index ed692ae95..f2ebcd226 100644
--- a/vendor/github.com/spf13/afero/copyOnWriteFs.go
+++ b/vendor/github.com/spf13/afero/copyOnWriteFs.go
@@ -80,7 +80,7 @@ func (u *CopyOnWriteFs) Stat(name string) (os.FileInfo, error) {
if e, ok := err.(*os.PathError); ok {
err = e.Err
}
- if err == syscall.ENOENT || err == syscall.ENOTDIR {
+ if err == os.ErrNotExist || err == syscall.ENOENT || err == syscall.ENOTDIR {
return u.base.Stat(name)
}
return nil, origErr
diff --git a/vendor/github.com/spf13/afero/copyOnWriteFs_test.go b/vendor/github.com/spf13/afero/copyOnWriteFs_test.go
index 2a00fab72..c6f2c6d62 100644
--- a/vendor/github.com/spf13/afero/copyOnWriteFs_test.go
+++ b/vendor/github.com/spf13/afero/copyOnWriteFs_test.go
@@ -21,3 +21,19 @@ func TestCopyOnWrite(t *testing.T) {
}
}
+
+func TestCopyOnWriteFileInMemMapBase(t *testing.T) {
+ base := &MemMapFs{}
+ layer := &MemMapFs{}
+
+ if err := WriteFile(base, "base.txt", []byte("base"), 0755); err != nil {
+ t.Fatalf("Failed to write file: %s", err)
+ }
+
+ ufs := NewCopyOnWriteFs(base, layer)
+
+ _, err := ufs.Stat("base.txt")
+ if err != nil {
+ t.Fatal(err)
+ }
+}
diff --git a/vendor/github.com/spf13/afero/mem/file.go b/vendor/github.com/spf13/afero/mem/file.go
index 5401a3b7c..885e55429 100644
--- a/vendor/github.com/spf13/afero/mem/file.go
+++ b/vendor/github.com/spf13/afero/mem/file.go
@@ -176,6 +176,9 @@ func (f *File) Read(b []byte) (n int, err error) {
if len(b) > 0 && int(f.at) == len(f.fileData.data) {
return 0, io.EOF
}
+ if int(f.at) > len(f.fileData.data) {
+ return 0, io.ErrUnexpectedEOF
+ }
if len(f.fileData.data)-int(f.at) >= len(b) {
n = len(b)
} else {
diff --git a/vendor/github.com/spf13/afero/memmap_test.go b/vendor/github.com/spf13/afero/memmap_test.go
index 09d8680f6..47414ab14 100644
--- a/vendor/github.com/spf13/afero/memmap_test.go
+++ b/vendor/github.com/spf13/afero/memmap_test.go
@@ -2,6 +2,7 @@ package afero
import (
"fmt"
+ "io"
"os"
"path/filepath"
"runtime"
@@ -419,3 +420,32 @@ func TestMemFsDirMode(t *testing.T) {
t.Error("FileMode is not directory")
}
}
+
+func TestMemFsUnexpectedEOF(t *testing.T) {
+ t.Parallel()
+
+ fs := NewMemMapFs()
+
+ if err := WriteFile(fs, "file.txt", []byte("abc"), 0777); err != nil {
+ t.Fatal(err)
+ }
+
+ f, err := fs.Open("file.txt")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer f.Close()
+
+ // Seek beyond the end.
+ _, err = f.Seek(512, 0)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ buff := make([]byte, 256)
+ _, err = io.ReadAtLeast(f, buff, 256)
+
+ if err != io.ErrUnexpectedEOF {
+ t.Fatal("Expected ErrUnexpectedEOF")
+ }
+}
diff --git a/vendor/github.com/spf13/cobra/README.md b/vendor/github.com/spf13/cobra/README.md
index d8b5c96c8..f887d603c 100644
--- a/vendor/github.com/spf13/cobra/README.md
+++ b/vendor/github.com/spf13/cobra/README.md
@@ -20,6 +20,7 @@ Many of the most widely used Go projects are built using Cobra including:
* [Nanobox](https://github.com/nanobox-io/nanobox)/[Nanopack](https://github.com/nanopack)
* [rclone](http://rclone.org/)
* [nehm](https://github.com/bogem/nehm)
+* [Pouch](https://github.com/alibaba/pouch)
[![Build Status](https://travis-ci.org/spf13/cobra.svg "Travis CI status")](https://travis-ci.org/spf13/cobra)
[![CircleCI status](https://circleci.com/gh/spf13/cobra.png?circle-token=:circle-token "CircleCI status")](https://circleci.com/gh/spf13/cobra)
@@ -158,10 +159,7 @@ import (
)
func main() {
- if err := cmd.RootCmd.Execute(); err != nil {
- fmt.Println(err)
- os.Exit(1)
- }
+ cmd.Execute()
}
```
@@ -174,7 +172,7 @@ commands you want. It's the easiest way to incorporate Cobra into your applicati
## Using the Cobra Library
-To manually implement Cobra you need to create a bare main.go file and a RootCmd file.
+To manually implement Cobra you need to create a bare main.go file and a rootCmd file.
You will optionally provide additional commands as you see fit.
### Create rootCmd
@@ -184,7 +182,7 @@ Cobra doesn't require any special constructors. Simply create your commands.
Ideally you place this in app/cmd/root.go:
```go
-var RootCmd = &cobra.Command{
+var rootCmd = &cobra.Command{
Use: "hugo",
Short: "Hugo is a very fast static site generator",
Long: `A Fast and Flexible Static Site Generator built with
@@ -212,14 +210,14 @@ import (
func init() {
cobra.OnInitialize(initConfig)
- RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)")
- RootCmd.PersistentFlags().StringVarP(&projectBase, "projectbase", "b", "", "base project directory eg. github.com/spf13/")
- RootCmd.PersistentFlags().StringP("author", "a", "YOUR NAME", "Author name for copyright attribution")
- RootCmd.PersistentFlags().StringVarP(&userLicense, "license", "l", "", "Name of license for the project (can provide `licensetext` in config)")
- RootCmd.PersistentFlags().Bool("viper", true, "Use Viper for configuration")
- viper.BindPFlag("author", RootCmd.PersistentFlags().Lookup("author"))
- viper.BindPFlag("projectbase", RootCmd.PersistentFlags().Lookup("projectbase"))
- viper.BindPFlag("useViper", RootCmd.PersistentFlags().Lookup("viper"))
+ rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)")
+ rootCmd.PersistentFlags().StringVarP(&projectBase, "projectbase", "b", "", "base project directory eg. github.com/spf13/")
+ rootCmd.PersistentFlags().StringP("author", "a", "YOUR NAME", "Author name for copyright attribution")
+ rootCmd.PersistentFlags().StringVarP(&userLicense, "license", "l", "", "Name of license for the project (can provide `licensetext` in config)")
+ rootCmd.PersistentFlags().Bool("viper", true, "Use Viper for configuration")
+ viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author"))
+ viper.BindPFlag("projectbase", rootCmd.PersistentFlags().Lookup("projectbase"))
+ viper.BindPFlag("useViper", rootCmd.PersistentFlags().Lookup("viper"))
viper.SetDefault("author", "NAME HERE <EMAIL ADDRESS>")
viper.SetDefault("license", "apache")
}
@@ -267,10 +265,7 @@ import (
)
func main() {
- if err := cmd.RootCmd.Execute(); err != nil {
- fmt.Println(err)
- os.Exit(1)
- }
+ cmd.Execute()
}
```
@@ -286,12 +281,13 @@ populate it with the following:
package cmd
import (
- "github.com/spf13/cobra"
"fmt"
+
+ "github.com/spf13/cobra"
)
func init() {
- RootCmd.AddCommand(versionCmd)
+ rootCmd.AddCommand(versionCmd)
}
var versionCmd = &cobra.Command{
@@ -328,7 +324,7 @@ command it's assigned to as well as every command under that command. For
global flags, assign a flag as a persistent flag on the root.
```go
-RootCmd.PersistentFlags().BoolVarP(&Verbose, "verbose", "v", false, "verbose output")
+rootCmd.PersistentFlags().BoolVarP(&Verbose, "verbose", "v", false, "verbose output")
```
### Local Flags
@@ -336,7 +332,7 @@ RootCmd.PersistentFlags().BoolVarP(&Verbose, "verbose", "v", false, "verbose out
A flag can also be assigned locally which will only apply to that specific command.
```go
-RootCmd.Flags().StringVarP(&Source, "source", "s", "", "Source directory to read from")
+rootCmd.Flags().StringVarP(&Source, "source", "s", "", "Source directory to read from")
```
### Local Flag on Parent Commands
@@ -359,8 +355,8 @@ You can also bind your flags with [viper](https://github.com/spf13/viper):
var author string
func init() {
- RootCmd.PersistentFlags().StringVar(&author, "author", "YOUR NAME", "Author name for copyright attribution")
- viper.BindPFlag("author", RootCmd.PersistentFlags().Lookup("author"))
+ rootCmd.PersistentFlags().StringVar(&author, "author", "YOUR NAME", "Author name for copyright attribution")
+ viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author"))
}
```
@@ -518,7 +514,7 @@ around it. In fact, you can provide your own if you want.
### Defining your own help
You can provide your own Help command or your own template for the default command to use
-with followind functions:
+with following functions:
```go
cmd.SetHelpCommand(cmd *Command)
@@ -565,6 +561,13 @@ cmd.SetUsageFunc(f func(*Command) error)
cmd.SetUsageTemplate(s string)
```
+## Version Flag
+
+Cobra adds a top-level '--version' flag if the Version field is set on the root command.
+Running an application with the '--version' flag will print the version to stdout using
+the version template. The template can be customized using the
+`cmd.SetVersionTemplate(s string)` function.
+
## PreRun and PostRun Hooks
It is possible to run functions before or after the main `Run` function of your command. The `PersistentPreRun` and `PreRun` functions will be executed before `Run`. `PersistentPostRun` and `PostRun` will be executed after `Run`. The `Persistent*Run` functions will be inherited by children if they do not declare their own. These functions are run in the following order:
diff --git a/vendor/github.com/spf13/cobra/cobra.go b/vendor/github.com/spf13/cobra/cobra.go
index e4b910c5d..7010fd15b 100644
--- a/vendor/github.com/spf13/cobra/cobra.go
+++ b/vendor/github.com/spf13/cobra/cobra.go
@@ -70,7 +70,8 @@ func AddTemplateFuncs(tmplFuncs template.FuncMap) {
}
}
-// OnInitialize takes a series of func() arguments and appends them to a slice of func().
+// OnInitialize sets the passed functions to be run when each command's
+// Execute method is called.
func OnInitialize(y ...func()) {
initializers = append(initializers, y...)
}
diff --git a/vendor/github.com/spf13/cobra/cobra/cmd/add.go b/vendor/github.com/spf13/cobra/cobra/cmd/add.go
index 993ae16f0..fb22096a3 100644
--- a/vendor/github.com/spf13/cobra/cobra/cmd/add.go
+++ b/vendor/github.com/spf13/cobra/cobra/cmd/add.go
@@ -24,7 +24,7 @@ import (
func init() {
addCmd.Flags().StringVarP(&packageName, "package", "t", "", "target package name (e.g. github.com/spf13/hugo)")
- addCmd.Flags().StringVarP(&parentName, "parent", "p", "RootCmd", "variable name of parent command for this command")
+ addCmd.Flags().StringVarP(&parentName, "parent", "p", "rootCmd", "variable name of parent command for this command")
}
var packageName, parentName string
@@ -35,7 +35,7 @@ var addCmd = &cobra.Command{
Short: "Add a command to a Cobra Application",
Long: `Add (cobra add) will create a new command, with a license and
the appropriate structure for a Cobra-based CLI application,
-and register it to its parent (default RootCmd).
+and register it to its parent (default rootCmd).
If you want your command to be public, pass in the command name
with an initial uppercase letter.
diff --git a/vendor/github.com/spf13/cobra/cobra/cmd/init.go b/vendor/github.com/spf13/cobra/cobra/cmd/init.go
index 149aabe1f..244137015 100644
--- a/vendor/github.com/spf13/cobra/cobra/cmd/init.go
+++ b/vendor/github.com/spf13/cobra/cobra/cmd/init.go
@@ -150,8 +150,8 @@ import (
var cfgFile string{{end}}
-// RootCmd represents the base command when called without any subcommands
-var RootCmd = &cobra.Command{
+// rootCmd represents the base command when called without any subcommands
+var rootCmd = &cobra.Command{
Use: "{{.appName}}",
Short: "A brief description of your application",
Long: ` + "`" + `A longer description that spans multiple lines and likely contains
@@ -168,24 +168,24 @@ to quickly create a Cobra application.` + "`" + `,
// Execute adds all child commands to the root command and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
- if err := RootCmd.Execute(); err != nil {
+ if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}
-func init() { {{if .viper}}
+func init() { {{- if .viper}}
cobra.OnInitialize(initConfig)
{{end}}
// Here you will define your flags and configuration settings.
// Cobra supports persistent flags, which, if defined here,
// will be global for your application.{{ if .viper }}
- RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.{{ .appName }}.yaml)"){{ else }}
- // RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.{{ .appName }}.yaml)"){{ end }}
+ rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.{{ .appName }}.yaml)"){{ else }}
+ // rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.{{ .appName }}.yaml)"){{ end }}
// Cobra also supports local flags, which will only run
// when this action is called directly.
- RootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+ rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}{{ if .viper }}
// initConfig reads in config file and ENV variables if set.
diff --git a/vendor/github.com/spf13/cobra/cobra/cmd/testdata/root.go.golden b/vendor/github.com/spf13/cobra/cobra/cmd/testdata/root.go.golden
index 8eeeae89e..d74f4cd45 100644
--- a/vendor/github.com/spf13/cobra/cobra/cmd/testdata/root.go.golden
+++ b/vendor/github.com/spf13/cobra/cobra/cmd/testdata/root.go.golden
@@ -25,8 +25,8 @@ import (
var cfgFile string
-// RootCmd represents the base command when called without any subcommands
-var RootCmd = &cobra.Command{
+// rootCmd represents the base command when called without any subcommands
+var rootCmd = &cobra.Command{
Use: "testproject",
Short: "A brief description of your application",
Long: `A longer description that spans multiple lines and likely contains
@@ -43,23 +43,23 @@ to quickly create a Cobra application.`,
// Execute adds all child commands to the root command and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
- if err := RootCmd.Execute(); err != nil {
+ if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}
-func init() {
+func init() {
cobra.OnInitialize(initConfig)
// Here you will define your flags and configuration settings.
// Cobra supports persistent flags, which, if defined here,
// will be global for your application.
- RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.testproject.yaml)")
+ rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.testproject.yaml)")
// Cobra also supports local flags, which will only run
// when this action is called directly.
- RootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+ rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}
// initConfig reads in config file and ENV variables if set.
diff --git a/vendor/github.com/spf13/cobra/cobra/cmd/testdata/test.go.golden b/vendor/github.com/spf13/cobra/cobra/cmd/testdata/test.go.golden
index 584056802..ed6442755 100644
--- a/vendor/github.com/spf13/cobra/cobra/cmd/testdata/test.go.golden
+++ b/vendor/github.com/spf13/cobra/cobra/cmd/testdata/test.go.golden
@@ -36,7 +36,7 @@ to quickly create a Cobra application.`,
}
func init() {
- RootCmd.AddCommand(testCmd)
+ rootCmd.AddCommand(testCmd)
// Here you will define your flags and configuration settings.
diff --git a/vendor/github.com/spf13/cobra/command.go b/vendor/github.com/spf13/cobra/command.go
index 6cb642647..5fefb58da 100644
--- a/vendor/github.com/spf13/cobra/command.go
+++ b/vendor/github.com/spf13/cobra/command.go
@@ -75,6 +75,11 @@ type Command struct {
// group commands.
Annotations map[string]string
+ // Version defines the version for this command. If this value is non-empty and the command does not
+ // define a "version" flag, a "version" boolean flag will be added to the command and, if specified,
+ // will print content of the "Version" variable.
+ Version string
+
// The *Run functions are executed in the following order:
// * PersistentPreRun()
// * PreRun()
@@ -118,6 +123,10 @@ type Command struct {
// will be printed by generating docs for this command.
DisableAutoGenTag bool
+ // DisableFlagsInUseLine will disable the addition of [flags] to the usage
+ // line of a command when printing help or generating docs
+ DisableFlagsInUseLine bool
+
// DisableSuggestions disables the suggestions based on Levenshtein distance
// that go along with 'unknown command' messages.
DisableSuggestions bool
@@ -173,6 +182,8 @@ type Command struct {
// helpCommand is command with usage 'help'. If it's not defined by user,
// cobra uses default help command.
helpCommand *Command
+ // versionTemplate is the version template defined by user.
+ versionTemplate string
}
// SetArgs sets arguments for the command. It is set to os.Args[1:] by default, if desired, can be overridden
@@ -218,6 +229,11 @@ func (c *Command) SetHelpTemplate(s string) {
c.helpTemplate = s
}
+// SetVersionTemplate sets version template to be used. Application can use it to set custom template.
+func (c *Command) SetVersionTemplate(s string) {
+ c.versionTemplate = s
+}
+
// SetGlobalNormalizationFunc sets a normalization function to all flag sets and also to child commands.
// The user should not have a cyclic dependency on commands.
func (c *Command) SetGlobalNormalizationFunc(n func(f *flag.FlagSet, name string) flag.NormalizedName) {
@@ -407,6 +423,19 @@ func (c *Command) HelpTemplate() string {
{{end}}{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}`
}
+// VersionTemplate return version template for the command.
+func (c *Command) VersionTemplate() string {
+ if c.versionTemplate != "" {
+ return c.versionTemplate
+ }
+
+ if c.HasParent() {
+ return c.parent.VersionTemplate()
+ }
+ return `{{with .Name}}{{printf "%s " .}}{{end}}{{printf "version %s" .Version}}
+`
+}
+
func hasNoOptDefVal(name string, fs *flag.FlagSet) bool {
flag := fs.Lookup(name)
if flag == nil {
@@ -636,9 +665,10 @@ func (c *Command) execute(a []string) (err error) {
c.Printf("Command %q is deprecated, %s\n", c.Name(), c.Deprecated)
}
- // initialize help flag as the last point possible to allow for user
+ // initialize help and version flag at the last point possible to allow for user
// overriding
c.InitDefaultHelpFlag()
+ c.InitDefaultVersionFlag()
err = c.ParseFlags(a)
if err != nil {
@@ -655,7 +685,27 @@ func (c *Command) execute(a []string) (err error) {
return err
}
- if helpVal || !c.Runnable() {
+ if helpVal {
+ return flag.ErrHelp
+ }
+
+ // for back-compat, only add version flag behavior if version is defined
+ if c.Version != "" {
+ versionVal, err := c.Flags().GetBool("version")
+ if err != nil {
+ c.Println("\"version\" flag declared as non-bool. Please correct your code")
+ return err
+ }
+ if versionVal {
+ err := tmpl(c.OutOrStdout(), c.VersionTemplate(), c)
+ if err != nil {
+ c.Println(err)
+ }
+ return err
+ }
+ }
+
+ if !c.Runnable() {
return flag.ErrHelp
}
@@ -823,7 +873,7 @@ func (c *Command) validateRequiredFlags() error {
})
if len(missingFlagNames) > 0 {
- return fmt.Errorf(`Required flag(s) "%s" have/has not been set`, strings.Join(missingFlagNames, `", "`))
+ return fmt.Errorf(`required flag(s) "%s" not set`, strings.Join(missingFlagNames, `", "`))
}
return nil
}
@@ -844,6 +894,27 @@ func (c *Command) InitDefaultHelpFlag() {
}
}
+// InitDefaultVersionFlag adds default version flag to c.
+// It is called automatically by executing the c.
+// If c already has a version flag, it will do nothing.
+// If c.Version is empty, it will do nothing.
+func (c *Command) InitDefaultVersionFlag() {
+ if c.Version == "" {
+ return
+ }
+
+ c.mergePersistentFlags()
+ if c.Flags().Lookup("version") == nil {
+ usage := "version for "
+ if c.Name() == "" {
+ usage += "this command"
+ } else {
+ usage += c.Name()
+ }
+ c.Flags().Bool("version", false, usage)
+ }
+}
+
// InitDefaultHelpCmd adds default help command to c.
// It is called automatically by executing the c or by calling help and usage.
// If c already has help command or c has no subcommands, it will do nothing.
@@ -994,6 +1065,9 @@ func (c *Command) UseLine() string {
} else {
useline = c.Use
}
+ if c.DisableFlagsInUseLine {
+ return useline
+ }
if c.HasAvailableFlags() && !strings.Contains(useline, "[flags]") {
useline += " [flags]"
}
diff --git a/vendor/github.com/spf13/cobra/command_test.go b/vendor/github.com/spf13/cobra/command_test.go
index edffc1501..d3dde1525 100644
--- a/vendor/github.com/spf13/cobra/command_test.go
+++ b/vendor/github.com/spf13/cobra/command_test.go
@@ -681,7 +681,7 @@ func TestRequiredFlags(t *testing.T) {
c.MarkFlagRequired("foo2")
c.Flags().String("bar", "", "")
- expected := fmt.Sprintf("Required flag(s) %q, %q have/has not been set", "foo1", "foo2")
+ expected := fmt.Sprintf("required flag(s) %q, %q not set", "foo1", "foo2")
_, err := executeCommand(c)
got := err.Error()
@@ -708,7 +708,7 @@ func TestPersistentRequiredFlags(t *testing.T) {
parent.AddCommand(child)
- expected := fmt.Sprintf("Required flag(s) %q, %q, %q, %q have/has not been set", "bar1", "bar2", "foo1", "foo2")
+ expected := fmt.Sprintf("required flag(s) %q, %q, %q, %q not set", "bar1", "bar2", "foo1", "foo2")
_, err := executeCommand(parent, "child")
if err.Error() != expected {
@@ -843,6 +843,63 @@ func TestHelpExecutedOnNonRunnableChild(t *testing.T) {
checkStringContains(t, output, childCmd.Long)
}
+func TestVersionFlagExecuted(t *testing.T) {
+ rootCmd := &Command{Use: "root", Version: "1.0.0", Run: emptyRun}
+
+ output, err := executeCommand(rootCmd, "--version", "arg1")
+ if err != nil {
+ t.Errorf("Unexpected error: %v", err)
+ }
+
+ checkStringContains(t, output, "root version 1.0.0")
+}
+
+func TestVersionTemplate(t *testing.T) {
+ rootCmd := &Command{Use: "root", Version: "1.0.0", Run: emptyRun}
+ rootCmd.SetVersionTemplate(`customized version: {{.Version}}`)
+
+ output, err := executeCommand(rootCmd, "--version", "arg1")
+ if err != nil {
+ t.Errorf("Unexpected error: %v", err)
+ }
+
+ checkStringContains(t, output, "customized version: 1.0.0")
+}
+
+func TestVersionFlagExecutedOnSubcommand(t *testing.T) {
+ rootCmd := &Command{Use: "root", Version: "1.0.0"}
+ rootCmd.AddCommand(&Command{Use: "sub", Run: emptyRun})
+
+ output, err := executeCommand(rootCmd, "--version", "sub")
+ if err != nil {
+ t.Errorf("Unexpected error: %v", err)
+ }
+
+ checkStringContains(t, output, "root version 1.0.0")
+}
+
+func TestVersionFlagOnlyAddedToRoot(t *testing.T) {
+ rootCmd := &Command{Use: "root", Version: "1.0.0", Run: emptyRun}
+ rootCmd.AddCommand(&Command{Use: "sub", Run: emptyRun})
+
+ _, err := executeCommand(rootCmd, "sub", "--version")
+ if err == nil {
+ t.Errorf("Expected error")
+ }
+
+ checkStringContains(t, err.Error(), "unknown flag: --version")
+}
+
+func TestVersionFlagOnlyExistsIfVersionNonEmpty(t *testing.T) {
+ rootCmd := &Command{Use: "root", Run: emptyRun}
+
+ _, err := executeCommand(rootCmd, "--version")
+ if err == nil {
+ t.Errorf("Expected error")
+ }
+ checkStringContains(t, err.Error(), "unknown flag: --version")
+}
+
func TestUsageIsNotPrintedTwice(t *testing.T) {
var cmd = &Command{Use: "root"}
var sub = &Command{Use: "sub"}
diff --git a/vendor/github.com/spf13/cobra/doc/md_docs.go b/vendor/github.com/spf13/cobra/doc/md_docs.go
index 68cf5bf64..d7a2c2b62 100644
--- a/vendor/github.com/spf13/cobra/doc/md_docs.go
+++ b/vendor/github.com/spf13/cobra/doc/md_docs.go
@@ -67,7 +67,7 @@ func GenMarkdownCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string)
buf.WriteString("## " + name + "\n\n")
buf.WriteString(short + "\n\n")
buf.WriteString("### Synopsis\n\n")
- buf.WriteString("\n" + long + "\n\n")
+ buf.WriteString(long + "\n\n")
if cmd.Runnable() {
buf.WriteString(fmt.Sprintf("```\n%s\n```\n\n", cmd.UseLine()))
@@ -82,7 +82,7 @@ func GenMarkdownCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string)
return err
}
if hasSeeAlso(cmd) {
- buf.WriteString("### SEE ALSO\n")
+ buf.WriteString("### SEE ALSO\n\n")
if cmd.HasParent() {
parent := cmd.Parent()
pname := parent.CommandPath()
diff --git a/vendor/github.com/spf13/jwalterweatherman/README.md b/vendor/github.com/spf13/jwalterweatherman/README.md
index 350a9683d..d8cfd27ab 100644
--- a/vendor/github.com/spf13/jwalterweatherman/README.md
+++ b/vendor/github.com/spf13/jwalterweatherman/README.md
@@ -144,5 +144,5 @@ This is an early release. I’ve been using it for a while and this is the
third interface I’ve tried. I like this one pretty well, but no guarantees
that it won’t change a bit.
-I wrote this for use in [hugo](http://hugo.spf13.com). If you are looking
+I wrote this for use in [hugo](https://gohugo.io). If you are looking
for a static website engine that’s super fast please checkout Hugo.
diff --git a/vendor/github.com/spf13/viper/.travis.yml b/vendor/github.com/spf13/viper/.travis.yml
index f1deac3d7..55960d11b 100644
--- a/vendor/github.com/spf13/viper/.travis.yml
+++ b/vendor/github.com/spf13/viper/.travis.yml
@@ -2,8 +2,9 @@ go_import_path: github.com/spf13/viper
language: go
go:
- - 1.7.5
- - 1.8
+ - 1.7.x
+ - 1.8.x
+ - 1.9.x
- tip
os:
diff --git a/vendor/github.com/spf13/viper/remote/remote.go b/vendor/github.com/spf13/viper/remote/remote.go
index 68a35d692..810d0702e 100644
--- a/vendor/github.com/spf13/viper/remote/remote.go
+++ b/vendor/github.com/spf13/viper/remote/remote.go
@@ -8,10 +8,11 @@ package remote
import (
"bytes"
- "github.com/spf13/viper"
- crypt "github.com/xordataexchange/crypt/config"
"io"
"os"
+
+ "github.com/spf13/viper"
+ crypt "github.com/xordataexchange/crypt/config"
)
type remoteConfigProvider struct{}
diff --git a/vendor/github.com/spf13/viper/util.go b/vendor/github.com/spf13/viper/util.go
index c784dad40..952cad44c 100644
--- a/vendor/github.com/spf13/viper/util.go
+++ b/vendor/github.com/spf13/viper/util.go
@@ -11,23 +11,16 @@
package viper
import (
- "bytes"
- "encoding/json"
"fmt"
- "io"
"os"
"path/filepath"
"runtime"
"strings"
"unicode"
- "github.com/hashicorp/hcl"
- "github.com/magiconair/properties"
- toml "github.com/pelletier/go-toml"
"github.com/spf13/afero"
"github.com/spf13/cast"
jww "github.com/spf13/jwalterweatherman"
- "gopkg.in/yaml.v2"
)
// ConfigParseError denotes failing to parse configuration file.
@@ -153,61 +146,6 @@ func userHomeDir() string {
return os.Getenv("HOME")
}
-func unmarshallConfigReader(in io.Reader, c map[string]interface{}, configType string) error {
- buf := new(bytes.Buffer)
- buf.ReadFrom(in)
-
- switch strings.ToLower(configType) {
- case "yaml", "yml":
- if err := yaml.Unmarshal(buf.Bytes(), &c); err != nil {
- return ConfigParseError{err}
- }
-
- case "json":
- if err := json.Unmarshal(buf.Bytes(), &c); err != nil {
- return ConfigParseError{err}
- }
-
- case "hcl":
- obj, err := hcl.Parse(string(buf.Bytes()))
- if err != nil {
- return ConfigParseError{err}
- }
- if err = hcl.DecodeObject(&c, obj); err != nil {
- return ConfigParseError{err}
- }
-
- case "toml":
- tree, err := toml.LoadReader(buf)
- if err != nil {
- return ConfigParseError{err}
- }
- tmap := tree.ToMap()
- for k, v := range tmap {
- c[k] = v
- }
-
- case "properties", "props", "prop":
- var p *properties.Properties
- var err error
- if p, err = properties.Load(buf.Bytes(), properties.UTF8); err != nil {
- return ConfigParseError{err}
- }
- for _, key := range p.Keys() {
- value, _ := p.Get(key)
- // recursively build nested maps
- path := strings.Split(key, ".")
- lastKey := strings.ToLower(path[len(path)-1])
- deepestMap := deepSearch(c, path[0:len(path)-1])
- // set innermost value
- deepestMap[lastKey] = value
- }
- }
-
- insensitiviseMap(c)
- return nil
-}
-
func safeMul(a, b uint) uint {
c := a * b
if a > 1 && b > 1 && c/b != a {
diff --git a/vendor/github.com/spf13/viper/viper.go b/vendor/github.com/spf13/viper/viper.go
index 64f006a39..ad8a03729 100644
--- a/vendor/github.com/spf13/viper/viper.go
+++ b/vendor/github.com/spf13/viper/viper.go
@@ -22,6 +22,7 @@ package viper
import (
"bytes"
"encoding/csv"
+ "encoding/json"
"fmt"
"io"
"log"
@@ -31,14 +32,30 @@ import (
"strings"
"time"
+ yaml "gopkg.in/yaml.v2"
+
"github.com/fsnotify/fsnotify"
+ "github.com/hashicorp/hcl"
+ "github.com/hashicorp/hcl/hcl/printer"
+ "github.com/magiconair/properties"
"github.com/mitchellh/mapstructure"
+ toml "github.com/pelletier/go-toml"
"github.com/spf13/afero"
"github.com/spf13/cast"
jww "github.com/spf13/jwalterweatherman"
"github.com/spf13/pflag"
)
+// ConfigMarshalError happens when failing to marshal the configuration.
+type ConfigMarshalError struct {
+ err error
+}
+
+// Error returns the formatted configuration error.
+func (e ConfigMarshalError) Error() string {
+ return fmt.Sprintf("While marshaling config: %s", e.err.Error())
+}
+
var v *Viper
type RemoteResponse struct {
@@ -162,6 +179,10 @@ type Viper struct {
aliases map[string]string
typeByDefValue bool
+ // Store read properties on the object so that we can write back in order with comments.
+ // This will only be used if the configuration read is a properties file.
+ properties *properties.Properties
+
onConfigChange func(fsnotify.Event)
}
@@ -188,7 +209,7 @@ func New() *Viper {
// can use it in their testing as well.
func Reset() {
v = New()
- SupportedExts = []string{"json", "toml", "yaml", "yml", "hcl"}
+ SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl"}
SupportedRemoteProviders = []string{"etcd", "consul"}
}
@@ -1119,6 +1140,7 @@ func (v *Viper) ReadInConfig() error {
return UnsupportedConfigError(v.getConfigType())
}
+ jww.DEBUG.Println("Reading file: ", filename)
file, err := afero.ReadFile(v.fs, filename)
if err != nil {
return err
@@ -1178,6 +1200,195 @@ func (v *Viper) MergeConfig(in io.Reader) error {
return nil
}
+// WriteConfig writes the current configuration to a file.
+func WriteConfig() error { return v.WriteConfig() }
+func (v *Viper) WriteConfig() error {
+ filename, err := v.getConfigFile()
+ if err != nil {
+ return err
+ }
+ return v.writeConfig(filename, true)
+}
+
+// SafeWriteConfig writes current configuration to file only if the file does not exist.
+func SafeWriteConfig() error { return v.SafeWriteConfig() }
+func (v *Viper) SafeWriteConfig() error {
+ filename, err := v.getConfigFile()
+ if err != nil {
+ return err
+ }
+ return v.writeConfig(filename, false)
+}
+
+// WriteConfigAs writes current configuration to a given filename.
+func WriteConfigAs(filename string) error { return v.WriteConfigAs(filename) }
+func (v *Viper) WriteConfigAs(filename string) error {
+ return v.writeConfig(filename, true)
+}
+
+// SafeWriteConfigAs writes current configuration to a given filename if it does not exist.
+func SafeWriteConfigAs(filename string) error { return v.SafeWriteConfigAs(filename) }
+func (v *Viper) SafeWriteConfigAs(filename string) error {
+ return v.writeConfig(filename, false)
+}
+
+func writeConfig(filename string, force bool) error { return v.writeConfig(filename, force) }
+func (v *Viper) writeConfig(filename string, force bool) error {
+ jww.INFO.Println("Attempting to write configuration to file.")
+ ext := filepath.Ext(filename)
+ if len(ext) <= 1 {
+ return fmt.Errorf("Filename: %s requires valid extension.", filename)
+ }
+ configType := ext[1:]
+ if !stringInSlice(configType, SupportedExts) {
+ return UnsupportedConfigError(configType)
+ }
+ if v.config == nil {
+ v.config = make(map[string]interface{})
+ }
+ var flags int
+ if force == true {
+ flags = os.O_CREATE | os.O_TRUNC | os.O_WRONLY
+ } else {
+ if _, err := os.Stat(filename); os.IsNotExist(err) {
+ flags = os.O_WRONLY
+ } else {
+ return fmt.Errorf("File: %s exists. Use WriteConfig to overwrite.", filename)
+ }
+ }
+ f, err := v.fs.OpenFile(filename, flags, os.FileMode(0644))
+ if err != nil {
+ return err
+ }
+ return v.marshalWriter(f, configType)
+}
+
+// Unmarshal a Reader into a map.
+// Should probably be an unexported function.
+func unmarshalReader(in io.Reader, c map[string]interface{}) error {
+ return v.unmarshalReader(in, c)
+}
+func (v *Viper) unmarshalReader(in io.Reader, c map[string]interface{}) error {
+ buf := new(bytes.Buffer)
+ buf.ReadFrom(in)
+
+ switch strings.ToLower(v.getConfigType()) {
+ case "yaml", "yml":
+ if err := yaml.Unmarshal(buf.Bytes(), &c); err != nil {
+ return ConfigParseError{err}
+ }
+
+ case "json":
+ if err := json.Unmarshal(buf.Bytes(), &c); err != nil {
+ return ConfigParseError{err}
+ }
+
+ case "hcl":
+ obj, err := hcl.Parse(string(buf.Bytes()))
+ if err != nil {
+ return ConfigParseError{err}
+ }
+ if err = hcl.DecodeObject(&c, obj); err != nil {
+ return ConfigParseError{err}
+ }
+
+ case "toml":
+ tree, err := toml.LoadReader(buf)
+ if err != nil {
+ return ConfigParseError{err}
+ }
+ tmap := tree.ToMap()
+ for k, v := range tmap {
+ c[k] = v
+ }
+
+ case "properties", "props", "prop":
+ v.properties = properties.NewProperties()
+ var err error
+ if v.properties, err = properties.Load(buf.Bytes(), properties.UTF8); err != nil {
+ return ConfigParseError{err}
+ }
+ for _, key := range v.properties.Keys() {
+ value, _ := v.properties.Get(key)
+ // recursively build nested maps
+ path := strings.Split(key, ".")
+ lastKey := strings.ToLower(path[len(path)-1])
+ deepestMap := deepSearch(c, path[0:len(path)-1])
+ // set innermost value
+ deepestMap[lastKey] = value
+ }
+ }
+
+ insensitiviseMap(c)
+ return nil
+}
+
+// Marshal a map into Writer.
+func marshalWriter(f afero.File, configType string) error {
+ return v.marshalWriter(f, configType)
+}
+func (v *Viper) marshalWriter(f afero.File, configType string) error {
+ c := v.AllSettings()
+ switch configType {
+ case "json":
+ b, err := json.MarshalIndent(c, "", " ")
+ if err != nil {
+ return ConfigMarshalError{err}
+ }
+ _, err = f.WriteString(string(b))
+ if err != nil {
+ return ConfigMarshalError{err}
+ }
+
+ case "hcl":
+ b, err := json.Marshal(c)
+ ast, err := hcl.Parse(string(b))
+ if err != nil {
+ return ConfigMarshalError{err}
+ }
+ err = printer.Fprint(f, ast.Node)
+ if err != nil {
+ return ConfigMarshalError{err}
+ }
+
+ case "prop", "props", "properties":
+ if v.properties == nil {
+ v.properties = properties.NewProperties()
+ }
+ p := v.properties
+ for _, key := range v.AllKeys() {
+ _, _, err := p.Set(key, v.GetString(key))
+ if err != nil {
+ return ConfigMarshalError{err}
+ }
+ }
+ _, err := p.WriteComment(f, "#", properties.UTF8)
+ if err != nil {
+ return ConfigMarshalError{err}
+ }
+
+ case "toml":
+ t, err := toml.TreeFromMap(c)
+ if err != nil {
+ return ConfigMarshalError{err}
+ }
+ s := t.String()
+ if _, err := f.WriteString(s); err != nil {
+ return ConfigMarshalError{err}
+ }
+
+ case "yaml", "yml":
+ b, err := yaml.Marshal(c)
+ if err != nil {
+ return ConfigMarshalError{err}
+ }
+ if _, err = f.WriteString(string(b)); err != nil {
+ return ConfigMarshalError{err}
+ }
+ }
+ return nil
+}
+
func keyExists(k string, m map[string]interface{}) string {
lk := strings.ToLower(k)
for mk := range m {
@@ -1290,16 +1501,6 @@ func (v *Viper) WatchRemoteConfigOnChannel() error {
return v.watchKeyValueConfigOnChannel()
}
-// Unmarshal a Reader into a map.
-// Should probably be an unexported function.
-func unmarshalReader(in io.Reader, c map[string]interface{}) error {
- return v.unmarshalReader(in, c)
-}
-
-func (v *Viper) unmarshalReader(in io.Reader, c map[string]interface{}) error {
- return unmarshallConfigReader(in, c, v.getConfigType())
-}
-
func (v *Viper) insensitiviseMaps() {
insensitiviseMap(v.config)
insensitiviseMap(v.defaults)
diff --git a/vendor/github.com/spf13/viper/viper_test.go b/vendor/github.com/spf13/viper/viper_test.go
index 7050d5abd..c93480eab 100644
--- a/vendor/github.com/spf13/viper/viper_test.go
+++ b/vendor/github.com/spf13/viper/viper_test.go
@@ -18,6 +18,7 @@ import (
"testing"
"time"
+ "github.com/spf13/afero"
"github.com/spf13/cast"
"github.com/spf13/pflag"
@@ -262,7 +263,7 @@ func TestDefault(t *testing.T) {
assert.Equal(t, "leather", Get("clothing.jacket"))
}
-func TestUnmarshalling(t *testing.T) {
+func TestUnmarshaling(t *testing.T) {
SetConfigType("yaml")
r := bytes.NewReader(yamlExample)
@@ -847,6 +848,190 @@ func TestSub(t *testing.T) {
assert.Equal(t, (*Viper)(nil), subv)
}
+var hclWriteExpected = []byte(`"foos" = {
+ "foo" = {
+ "key" = 1
+ }
+
+ "foo" = {
+ "key" = 2
+ }
+
+ "foo" = {
+ "key" = 3
+ }
+
+ "foo" = {
+ "key" = 4
+ }
+}
+
+"id" = "0001"
+
+"name" = "Cake"
+
+"ppu" = 0.55
+
+"type" = "donut"`)
+
+func TestWriteConfigHCL(t *testing.T) {
+ v := New()
+ fs := afero.NewMemMapFs()
+ v.SetFs(fs)
+ v.SetConfigName("c")
+ v.SetConfigType("hcl")
+ err := v.ReadConfig(bytes.NewBuffer(hclExample))
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := v.WriteConfigAs("c.hcl"); err != nil {
+ t.Fatal(err)
+ }
+ read, err := afero.ReadFile(fs, "c.hcl")
+ if err != nil {
+ t.Fatal(err)
+ }
+ assert.Equal(t, hclWriteExpected, read)
+}
+
+var jsonWriteExpected = []byte(`{
+ "batters": {
+ "batter": [
+ {
+ "type": "Regular"
+ },
+ {
+ "type": "Chocolate"
+ },
+ {
+ "type": "Blueberry"
+ },
+ {
+ "type": "Devil's Food"
+ }
+ ]
+ },
+ "id": "0001",
+ "name": "Cake",
+ "ppu": 0.55,
+ "type": "donut"
+}`)
+
+func TestWriteConfigJson(t *testing.T) {
+ v := New()
+ fs := afero.NewMemMapFs()
+ v.SetFs(fs)
+ v.SetConfigName("c")
+ v.SetConfigType("json")
+ err := v.ReadConfig(bytes.NewBuffer(jsonExample))
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := v.WriteConfigAs("c.json"); err != nil {
+ t.Fatal(err)
+ }
+ read, err := afero.ReadFile(fs, "c.json")
+ if err != nil {
+ t.Fatal(err)
+ }
+ assert.Equal(t, jsonWriteExpected, read)
+}
+
+var propertiesWriteExpected = []byte(`p_id = 0001
+p_type = donut
+p_name = Cake
+p_ppu = 0.55
+p_batters.batter.type = Regular
+`)
+
+func TestWriteConfigProperties(t *testing.T) {
+ v := New()
+ fs := afero.NewMemMapFs()
+ v.SetFs(fs)
+ v.SetConfigName("c")
+ v.SetConfigType("properties")
+ err := v.ReadConfig(bytes.NewBuffer(propertiesExample))
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := v.WriteConfigAs("c.properties"); err != nil {
+ t.Fatal(err)
+ }
+ read, err := afero.ReadFile(fs, "c.properties")
+ if err != nil {
+ t.Fatal(err)
+ }
+ assert.Equal(t, propertiesWriteExpected, read)
+}
+
+func TestWriteConfigTOML(t *testing.T) {
+ fs := afero.NewMemMapFs()
+ v := New()
+ v.SetFs(fs)
+ v.SetConfigName("c")
+ v.SetConfigType("toml")
+ err := v.ReadConfig(bytes.NewBuffer(tomlExample))
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := v.WriteConfigAs("c.toml"); err != nil {
+ t.Fatal(err)
+ }
+
+ // The TOML String method does not order the contents.
+ // Therefore, we must read the generated file and compare the data.
+ v2 := New()
+ v2.SetFs(fs)
+ v2.SetConfigName("c")
+ v2.SetConfigType("toml")
+ v2.SetConfigFile("c.toml")
+ err = v2.ReadInConfig()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ assert.Equal(t, v.GetString("title"), v2.GetString("title"))
+ assert.Equal(t, v.GetString("owner.bio"), v2.GetString("owner.bio"))
+ assert.Equal(t, v.GetString("owner.dob"), v2.GetString("owner.dob"))
+ assert.Equal(t, v.GetString("owner.organization"), v2.GetString("owner.organization"))
+}
+
+var yamlWriteExpected = []byte(`age: 35
+beard: true
+clothing:
+ jacket: leather
+ pants:
+ size: large
+ trousers: denim
+eyes: brown
+hacker: true
+hobbies:
+- skateboarding
+- snowboarding
+- go
+name: steve
+`)
+
+func TestWriteConfigYAML(t *testing.T) {
+ v := New()
+ fs := afero.NewMemMapFs()
+ v.SetFs(fs)
+ v.SetConfigName("c")
+ v.SetConfigType("yaml")
+ err := v.ReadConfig(bytes.NewBuffer(yamlExample))
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := v.WriteConfigAs("c.yaml"); err != nil {
+ t.Fatal(err)
+ }
+ read, err := afero.ReadFile(fs, "c.yaml")
+ if err != nil {
+ t.Fatal(err)
+ }
+ assert.Equal(t, yamlWriteExpected, read)
+}
+
var yamlMergeExampleTgt = []byte(`
hello:
pop: 37890
diff --git a/vendor/github.com/xenolf/lego/.travis.yml b/vendor/github.com/xenolf/lego/.travis.yml
index 8cf9aed1b..d7a626e23 100644
--- a/vendor/github.com/xenolf/lego/.travis.yml
+++ b/vendor/github.com/xenolf/lego/.travis.yml
@@ -1,7 +1,7 @@
language: go
go:
-- 1.8
-- 1.9
+- 1.8.x
+- 1.9.x
- tip
services:
- memcached
diff --git a/vendor/github.com/xenolf/lego/acme/dns_challenge.go b/vendor/github.com/xenolf/lego/acme/dns_challenge.go
index 133739748..d6844dcd4 100644
--- a/vendor/github.com/xenolf/lego/acme/dns_challenge.go
+++ b/vendor/github.com/xenolf/lego/acme/dns_challenge.go
@@ -255,6 +255,13 @@ func FindZoneByFqdn(fqdn string, nameservers []string) (string, error) {
// Check if we got a SOA RR in the answer section
if in.Rcode == dns.RcodeSuccess {
+
+ // CNAME records cannot/should not exist at the root of a zone.
+ // So we skip a domain when a CNAME is found.
+ if dnsMsgContainsCNAME(in) {
+ continue
+ }
+
for _, ans := range in.Answer {
if soa, ok := ans.(*dns.SOA); ok {
zone := soa.Hdr.Name
@@ -268,6 +275,16 @@ func FindZoneByFqdn(fqdn string, nameservers []string) (string, error) {
return "", fmt.Errorf("Could not find the start of authority")
}
+// dnsMsgContainsCNAME checks for a CNAME answer in msg
+func dnsMsgContainsCNAME(msg *dns.Msg) bool {
+ for _, ans := range msg.Answer {
+ if _, ok := ans.(*dns.CNAME); ok {
+ return true
+ }
+ }
+ return false
+}
+
// ClearFqdnCache clears the cache of fqdn to zone mappings. Primarily used in testing.
func ClearFqdnCache() {
fqdnToZone = map[string]string{}
diff --git a/vendor/github.com/xenolf/lego/acme/dns_challenge_test.go b/vendor/github.com/xenolf/lego/acme/dns_challenge_test.go
index 4a2a7feac..117ac3038 100644
--- a/vendor/github.com/xenolf/lego/acme/dns_challenge_test.go
+++ b/vendor/github.com/xenolf/lego/acme/dns_challenge_test.go
@@ -43,9 +43,10 @@ var findZoneByFqdnTests = []struct {
fqdn string
zone string
}{
- {"mail.google.com.", "google.com."}, // domain is a CNAME
- {"foo.google.com.", "google.com."}, // domain is a non-existent subdomain
- {"example.com.ac.", "ac."}, // domain is a eTLD
+ {"mail.google.com.", "google.com."}, // domain is a CNAME
+ {"foo.google.com.", "google.com."}, // domain is a non-existent subdomain
+ {"example.com.ac.", "ac."}, // domain is a eTLD
+ {"cross-zone-example.assets.sh.", "assets.sh."}, // domain is a cross-zone CNAME
}
var checkAuthoritativeNssTests = []struct {
diff --git a/vendor/github.com/xenolf/lego/providers/dns/azure/azure.go b/vendor/github.com/xenolf/lego/providers/dns/azure/azure.go
index 04897aa18..6a30b318a 100644
--- a/vendor/github.com/xenolf/lego/providers/dns/azure/azure.go
+++ b/vendor/github.com/xenolf/lego/providers/dns/azure/azure.go
@@ -30,7 +30,7 @@ type DNSProvider struct {
// NewDNSProvider returns a DNSProvider instance configured for azure.
// Credentials must be passed in the environment variables: AZURE_CLIENT_ID,
-// AZURE_CLIENT_SECRET, AZURE_SUBSCRIPTION_ID, AZURE_TENANT_ID
+// AZURE_CLIENT_SECRET, AZURE_SUBSCRIPTION_ID, AZURE_TENANT_ID, AZURE_RESOURCE_GROUP
func NewDNSProvider() (*DNSProvider, error) {
clientId := os.Getenv("AZURE_CLIENT_ID")
clientSecret := os.Getenv("AZURE_CLIENT_SECRET")